added automake.mk files in src/language
[pspp] / src / expressions / parse.c
index b1998f63c8f89daa5ea41456ad4c0bba80659de9..fcfd8ef3fb44a7d36ccc028f381feb53766b155f 100644 (file)
@@ -14,8 +14,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
 #include "private.h"
@@ -86,6 +86,19 @@ expr_parse (struct dictionary *dict, enum expr_type type)
     }
 }
 
+/* Parses and returns an expression of the given TYPE, as
+   expr_parse(), and sets up so that destroying POOL will free
+   the expression as well. */
+struct expression *
+expr_parse_pool (struct pool *pool,
+                 struct dictionary *dict, enum expr_type type) 
+{
+  struct expression *e = expr_parse (dict, type);
+  if (e != NULL)
+    pool_add_subpool (pool, e->expr_pool);
+  return e;
+}
+
 /* Free expression E. */
 void
 expr_free (struct expression *e)
@@ -269,13 +282,12 @@ type_check (struct expression *e,
 /* Considers whether *NODE may be coerced to type REQUIRED_TYPE.
    Returns true if possible, false if disallowed.
 
-   If DO_COERCION is zero, then *NODE is not modified and there
+   If DO_COERCION is false, then *NODE is not modified and there
    are no side effects.
 
-   Otherwise, DO_COERCION is nonzero.  In this case, we perform
-   the coercion if possible, possibly modifying *NODE.  If the
-   coercion is not possible then we free *NODE and set *NODE to
-   a null pointer.
+   If DO_COERCION is true, we perform the coercion if possible,
+   modifying *NODE if necessary.  If the coercion is not possible
+   then we free *NODE and set *NODE to a null pointer.
 
    This function's interface is somewhat awkward.  Use one of the
    wrapper functions type_coercion(), type_coercion_assert(), or
@@ -337,7 +349,8 @@ type_coercion_core (struct expression *e,
 
     case OP_ni_format:
       if ((*node)->type == OP_format
-          && check_input_specifier (&(*node)->format.f, 0))
+          && check_input_specifier (&(*node)->format.f, false)
+          && check_specifier_type (&(*node)->format.f, NUMERIC, false))
         {
           if (do_coercion)
             (*node)->type = OP_ni_format;
@@ -347,7 +360,8 @@ type_coercion_core (struct expression *e,
 
     case OP_no_format:
       if ((*node)->type == OP_format
-          && check_output_specifier (&(*node)->format.f, 0))
+          && check_output_specifier (&(*node)->format.f, false)
+          && check_specifier_type (&(*node)->format.f, NUMERIC, false))
         {
           if (do_coercion)
             (*node)->type = OP_no_format;
@@ -389,10 +403,13 @@ type_coercion_core (struct expression *e,
     }
 
   if (do_coercion) 
-    msg (SE, _("Type mismatch while applying %s operator: "
-               "cannot convert %s to %s."),
-         operator_name,
-         atom_type_name (actual_type), atom_type_name (required_type));
+    {
+      msg (SE, _("Type mismatch while applying %s operator: "
+                 "cannot convert %s to %s."),
+           operator_name,
+           atom_type_name (actual_type), atom_type_name (required_type));
+      *node = NULL;
+    }
   return false;
 }
 
@@ -519,7 +536,7 @@ parse_binary_operators (struct expression *e, union any_node *node,
 
       /* Convert the left-hand side to type OPERAND_TYPE. */
       if (!type_coercion (e, operand_type, &node, operator->name))
-        return node;
+        return NULL;
 
       /* Parse the right-hand side and coerce to type
          OPERAND_TYPE. */
@@ -653,7 +670,7 @@ parse_add (struct expression *e)
   static const struct operator ops[] = 
     {
       { '+', OP_ADD, "addition (\"+\")" },
-      { '-', OP_SUB, "subtraction (\"-\")-" },
+      { '-', OP_SUB, "subtraction (\"-\")" },
     };
   
   return parse_binary_operators (e, parse_mul (e),
@@ -714,6 +731,7 @@ parse_sysvar (struct expression *e)
           "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
         };
 
+      time_t last_vfm_invocation = vfm_last_invocation ();
       struct tm *time;
       char temp_buf[10];
 
@@ -731,21 +749,23 @@ parse_sysvar (struct expression *e)
     return expr_allocate_number (e, SYSMIS);
   else if (lex_match_id ("$JDATE"))
     {
-      struct tm *time = localtime (&last_vfm_invocation);
-      return expr_allocate_number (e, expr_ymd_to_ofs (time->tm_year + 1900,
-                                                       time->tm_mon + 1,
-                                                       time->tm_mday));
+      time_t time = vfm_last_invocation ();
+      struct tm *tm = localtime (&time);
+      return expr_allocate_number (e, expr_ymd_to_ofs (tm->tm_year + 1900,
+                                                       tm->tm_mon + 1,
+                                                       tm->tm_mday));
     }
   else if (lex_match_id ("$TIME"))
     {
-      struct tm *time = localtime (&last_vfm_invocation);
+      time_t time = vfm_last_invocation ();
+      struct tm *tm = localtime (&time);
       return expr_allocate_number (e,
-                                   expr_ymd_to_date (time->tm_year + 1900,
-                                                     time->tm_mon + 1,
-                                                     time->tm_mday)
-                                   + time->tm_hour * 60 * 60.
-                                   + time->tm_min * 60.
-                                   + time->tm_sec);
+                                   expr_ymd_to_date (tm->tm_year + 1900,
+                                                     tm->tm_mon + 1,
+                                                     tm->tm_mday)
+                                   + tm->tm_hour * 60 * 60.
+                                   + tm->tm_min * 60.
+                                   + tm->tm_sec);
     }
   else if (lex_match_id ("$LENGTH"))
     return expr_allocate_number (e, get_viewlength ());
@@ -800,7 +820,8 @@ parse_primary (struct expression *e)
         }
       break;
       
-    case T_NUM: 
+    case T_POS_NUM: 
+    case T_NEG_NUM: 
       {
         union any_node *node = expr_allocate_number (e, tokval);
         lex_get ();
@@ -860,7 +881,7 @@ parse_vector_element (struct expression *e)
 
   return expr_allocate_binary (e, (vector->var[0]->type == NUMERIC
                                    ? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR),
-                               expr_allocate_vector (e, vector), element);
+                               element, expr_allocate_vector (e, vector));
 }
 \f
 /* Individual function parsing. */
@@ -876,14 +897,14 @@ word_matches (const char **test, const char **name)
   size_t name_len = strcspn (*name, ".");
   if (test_len == name_len) 
     {
-      if (memcmp (*test, *name, test_len))
+      if (buf_compare_case (*test, *name, test_len))
         return false;
     }
   else if (test_len < 3 || test_len > name_len)
     return false;
   else 
     {
-      if (memcmp (*test, *name, test_len))
+      if (buf_compare_case (*test, *name, test_len))
         return false;
     }
 
@@ -912,6 +933,12 @@ compare_names (const char *test, const char *name)
     }
 }
 
+static int
+compare_strings (const char *test, const char *name) 
+{
+  return strcasecmp (test, name);
+}
+
 static bool
 lookup_function_helper (const char *name,
                         int (*compare) (const char *test, const char *name),
@@ -942,7 +969,7 @@ lookup_function (const char *name,
                  const struct operation **last) 
 {
   *first = *last = NULL;
-  return (lookup_function_helper (name, strcmp, first, last)
+  return (lookup_function_helper (name, compare_strings, first, last)
           || lookup_function_helper (name, compare_names, first, last));
 }
 
@@ -1022,7 +1049,7 @@ validate_function_args (const struct operation *f, int arg_cnt, int min_valid)
         {
           assert ((f->flags & OPF_MIN_VALID) == 0);
           msg (SE, _("%s function does not accept a minimum valid "
-                     "argument count."));
+                     "argument count."), f->prototype);
           return false;
         }
       else 
@@ -1031,7 +1058,7 @@ validate_function_args (const struct operation *f, int arg_cnt, int min_valid)
           if (array_arg_cnt < f->array_min_elems)
             {
               msg (SE, _("%s requires at least %d valid arguments in list."),
-                   f->prototype);
+                   f->prototype, f->array_min_elems);
               return false;
             }
           else if (min_valid > array_arg_cnt) 
@@ -1095,14 +1122,12 @@ no_match (const char *func_name,
     }
   else 
     {
-      ds_create (&s, _("Function invocation "));
+      ds_puts (&s, _("Function invocation "));
       put_invocation (&s, func_name, args, arg_cnt);
       ds_puts (&s, _(" does not match any known function.  Candidates are:"));
 
       for (f = first; f < last; f++)
-        {
-          ds_printf (&s, "\n%s", f->prototype);
-        }
+        ds_printf (&s, "\n%s", f->prototype);
     }
   ds_putc (&s, '.');
 
@@ -1149,8 +1174,8 @@ parse_function (struct expression *e)
         if (token == T_ID && lex_look_ahead () == 'T')
           {
             struct variable **vars;
-            int var_cnt;
-            int i;
+            size_t var_cnt;
+            size_t i;
 
             if (!parse_variables (default_dict, &vars, &var_cnt, PV_SINGLE))
               goto fail;
@@ -1201,13 +1226,18 @@ parse_function (struct expression *e)
   n = expr_allocate_composite (e, f - operations, args, arg_cnt);
   n->composite.min_valid = min_valid != -1 ? min_valid : f->array_min_elems; 
 
-  if (n->type == OP_LAG_Vnn || n->type == OP_LAG_Vsn) 
+  if (n->type == OP_LAG_Vn || n->type == OP_LAG_Vs) 
+    {
+      if (n_lag < 1)
+        n_lag = 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 (n_before > n_lag)
+      if (n_lag < n_before)
         n_lag = n_before;
     }
   
@@ -1265,7 +1295,7 @@ expr_allocate_nullary (struct expression *e, operation_type op)
 
 union any_node *
 expr_allocate_unary (struct expression *e, operation_type op,
-union any_node *arg0)
+                     union any_node *arg0)
 {
   return expr_allocate_composite (e, op, &arg0, 1);
 }