Changed a lot of non-const pointers to const.
[pspp-builds.git] / src / language / expressions / parse.c
index 7c5ea4cfda7acd08316caef515fd8a216cf1831c..329a740960217979ec1310be133b71c6b34fdd39 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
-   Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -62,7 +61,7 @@ static struct expression *finish_expression (union any_node *,
 static bool type_check (struct expression *, union any_node **,
                         enum expr_type expected_type);
 static union any_node *allocate_unary_variable (struct expression *,
-                                                struct variable *); 
+                                                const struct variable *); 
 \f
 /* Public functions. */
 
@@ -400,6 +399,15 @@ type_coercion_core (struct expression *e,
         }
       break;
 
+    case OP_var:
+      if ((*node)->type == OP_NUM_VAR || (*node)->type == OP_STR_VAR)
+        {
+          if (do_coercion)
+            *node = (*node)->composite.args[0];
+          return true;
+        }
+      break;
+
     case OP_pos_int:
       if ((*node)->type == OP_number
           && floor ((*node)->number.n) == (*node)->number.n
@@ -456,6 +464,16 @@ is_coercible (atom_type required_type, union any_node *const *node)
                              (union any_node **) node, NULL, false);
 }
 
+/* Returns true if ACTUAL_TYPE is a kind of REQUIRED_TYPE, false
+   otherwise. */
+static bool
+is_compatible (atom_type required_type, atom_type actual_type) 
+{
+  return (required_type == actual_type
+          || (required_type == OP_var
+              && (actual_type == OP_num_var || actual_type == OP_str_var)));
+}
+
 /* How to parse an operator. */
 struct operator
   {
@@ -502,7 +520,7 @@ check_operator (const struct operator *op, int arg_cnt, atom_type arg_type)
   assert (o->arg_cnt == arg_cnt);
   assert ((o->flags & OPF_ARRAY_OPERAND) == 0);
   for (i = 0; i < arg_cnt; i++) 
-    assert (o->args[i] == arg_type);
+    assert (is_compatible (arg_type, o->args[i]));
   return true;
 }
 
@@ -944,8 +962,11 @@ word_matches (const char **test, const char **name)
 }
 
 static int
-compare_names (const char *test, const char *name) 
+compare_names (const char *test, const char *name, bool abbrev_ok
 {
+  if (!abbrev_ok)
+    return true;
+  
   for (;;) 
     {
       if (!word_matches (&test, &name))
@@ -956,14 +977,15 @@ compare_names (const char *test, const char *name)
 }
 
 static int
-compare_strings (const char *test, const char *name
+compare_strings (const char *test, const char *name, bool abbrev_ok UNUSED)
 {
   return strcasecmp (test, name);
 }
 
 static bool
 lookup_function_helper (const char *name,
-                        int (*compare) (const char *test, const char *name),
+                        int (*compare) (const char *test, const char *name,
+                                        bool abbrev_ok),
                         const struct operation **first,
                         const struct operation **last)
 {
@@ -971,11 +993,12 @@ lookup_function_helper (const char *name,
   
   for (f = operations + OP_function_first;
        f <= operations + OP_function_last; f++) 
-    if (!compare (name, f->name)) 
+    if (!compare (name, f->name, !(f->flags & OPF_NO_ABBREV))) 
       {
         *first = f;
 
-        while (f <= operations + OP_function_last && !compare (name, f->name))
+        while (f <= operations + OP_function_last
+               && !compare (name, f->name, !(f->flags & OPF_NO_ABBREV)))
           f++;
         *last = f;
 
@@ -1193,13 +1216,14 @@ parse_function (struct lexer *lexer, struct expression *e)
   if (lex_token (lexer) != ')')
     for (;;)
       {
-        if (lex_token (lexer) == T_ID && lex_look_ahead (lexer) == 'T')
+        if (lex_token (lexer) == T_ID
+            && toupper (lex_look_ahead (lexer)) == 'T')
           {
-            struct variable **vars;
+            const struct variable **vars;
             size_t var_cnt;
             size_t i;
 
-            if (!parse_variables (lexer, dataset_dict (e->ds), &vars, &var_cnt, PV_SINGLE))
+            if (!parse_variables_const (lexer, dataset_dict (e->ds), &vars, &var_cnt, PV_SINGLE))
               goto fail;
             for (i = 0; i < var_cnt; i++)
               add_arg (&args, &arg_cnt, &arg_cap,
@@ -1255,18 +1279,14 @@ parse_function (struct lexer *lexer, struct expression *e)
   n->composite.min_valid = min_valid != -1 ? min_valid : f->array_min_elems; 
 
   if (n->type == OP_LAG_Vn || n->type == OP_LAG_Vs) 
-    {
-      if (dataset_n_lag (e->ds) < 1)
-        dataset_set_n_lag (e->ds, 1);
-    }
+    dataset_need_lag (e->ds, 1);
   else if (n->type == OP_LAG_Vnn || n->type == OP_LAG_Vsn)
     {
       int n_before;
       assert (n->composite.arg_cnt == 2);
       assert (n->composite.args[1]->type == OP_pos_int);
       n_before = n->composite.args[1]->integer.i;
-      if ( dataset_n_lag (e->ds) < n_before)
-        dataset_set_n_lag (e->ds, n_before);
+      dataset_need_lag (e->ds, n_before);
     }
   
   free (args);
@@ -1355,13 +1375,13 @@ is_valid_node (union any_node *n)
       assert (is_composite (n->type));
       assert (c->arg_cnt >= op->arg_cnt);
       for (i = 0; i < op->arg_cnt; i++) 
-        assert (expr_node_returns (c->args[i]) == op->args[i]);
+        assert (is_compatible (op->args[i], expr_node_returns (c->args[i])));
       if (c->arg_cnt > op->arg_cnt && !is_operator (n->type)) 
         {
           assert (op->flags & OPF_ARRAY_OPERAND);
           for (i = 0; i < c->arg_cnt; i++)
-            assert (operations[c->args[i]->type].returns
-                    == op->args[op->arg_cnt - 1]);
+            assert (is_compatible (op->args[op->arg_cnt - 1],
+                                   expr_node_returns (c->args[i])));
         }
     }
 
@@ -1461,7 +1481,7 @@ expr_allocate_string (struct expression *e, struct substring s)
 }
 
 union any_node *
-expr_allocate_variable (struct expression *e, struct variable *v)
+expr_allocate_variable (struct expression *e, const struct variable *v)
 {
   union any_node *n = pool_alloc (e->expr_pool, sizeof n->variable);
   n->type = var_is_numeric (v) ? OP_num_var : OP_str_var;
@@ -1481,7 +1501,7 @@ expr_allocate_format (struct expression *e, const struct fmt_spec *format)
 /* Allocates a unary composite node that represents the value of
    variable V in expression E. */
 static union any_node *
-allocate_unary_variable (struct expression *e, struct variable *v) 
+allocate_unary_variable (struct expression *e, const struct variable *v) 
 {
   assert (v != NULL);
   return expr_allocate_unary (e, var_is_numeric (v) ? OP_NUM_VAR : OP_STR_VAR,