Cite tokens when reporting invalid identifiers.
[pspp] / src / language / stats / aggregate.c
index 9f0b271533888cc195c68637b9f569451d56e490..944ba7b92278173633df300f0e22f3f96401d85c 100644 (file)
@@ -129,13 +129,13 @@ struct agr_proc
     /* Break variables. */
     struct subcase sort;                /* Sort criteria (break variables). */
     const struct variable **break_vars;       /* Break variables. */
-    size_t break_var_cnt;               /* Number of break variables. */
+    size_t break_n_vars;                /* Number of break variables. */
 
     enum missing_treatment missing;     /* How to treat missing values. */
     struct agr_var *agr_vars;           /* First aggregate variable. */
     struct dictionary *dict;            /* Aggregate dictionary. */
     const struct dictionary *src_dict;  /* Dict of the source */
-    int case_cnt;                       /* Counts aggregated cases. */
+    int n_cases;                        /* Counts aggregated cases. */
 
     bool add_variables;                 /* True iff the aggregated variables should
                                           be appended to the existing dictionary */
@@ -241,10 +241,10 @@ cmd_aggregate (struct lexer *lexer, struct dataset *ds)
           if (!parse_sort_criteria (lexer, dict, &agr.sort, &agr.break_vars,
                                     &saw_direction))
             goto error;
-          agr.break_var_cnt = subcase_get_n_fields (&agr.sort);
+          agr.break_n_vars = subcase_get_n_fields (&agr.sort);
 
          if  (! agr.add_variables)
-           for (i = 0; i < agr.break_var_cnt; i++)
+           for (i = 0; i < agr.break_n_vars; i++)
              dict_clone_var_assert (agr.dict, agr.break_vars[i]);
 
           /* BREAK must follow the options. */
@@ -269,10 +269,10 @@ cmd_aggregate (struct lexer *lexer, struct dataset *ds)
     dict_clear_documents (agr.dict);
 
   /* Cancel SPLIT FILE. */
-  dict_set_split_vars (agr.dict, NULL, 0);
+  dict_clear_split_vars (agr.dict);
 
   /* Initialize. */
-  agr.case_cnt = 0;
+  agr.n_cases = 0;
 
   if (out_file == NULL)
     {
@@ -297,7 +297,7 @@ cmd_aggregate (struct lexer *lexer, struct dataset *ds)
     }
 
   for (grouper = casegrouper_create_vars (input, agr.break_vars,
-                                          agr.break_var_cnt);
+                                          agr.break_n_vars);
        casegrouper_get_next_group (grouper, &group);
        casereader_destroy (group))
     {
@@ -445,7 +445,7 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
       /* Get the name of the aggregation function. */
       if (lex_token (lexer) != T_ID)
        {
-         lex_error (lexer, _("expecting aggregation function"));
+         lex_error (lexer, _("Syntax error expecting aggregation function."));
          goto error;
        }
 
@@ -457,8 +457,8 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
          break;
       if (NULL == function->name)
        {
-         msg (SE, _("Unknown aggregation function %s."),
-              ds_cstr (&function_name));
+         lex_error (lexer, _("Unknown aggregation function %s."),
+                     ds_cstr (&function_name));
          goto error;
        }
       ds_destroy (&function_name);
@@ -476,26 +476,28 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
       else
         {
          /* Parse list of source variables. */
-         {
-           int pv_opts = PV_NO_SCRATCH;
-
-           if (func_index == SUM || func_index == MEAN || func_index == SD)
-             pv_opts |= PV_NUMERIC;
-           else if (function->n_args)
-             pv_opts |= PV_SAME_TYPE;
-
-           if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
-             goto error;
-         }
+          int pv_opts = PV_NO_SCRATCH;
+          if (func_index == SUM || func_index == MEAN || func_index == SD)
+            pv_opts |= PV_NUMERIC;
+          else if (function->n_args)
+            pv_opts |= PV_SAME_TYPE;
+
+          int vars_start_ofs = lex_ofs (lexer);
+          if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
+            goto error;
+          int vars_end_ofs = lex_ofs (lexer) - 1;
 
          /* Parse function arguments, for those functions that
             require arguments. */
+          int args_start_ofs = 0;
          if (function->n_args != 0)
            for (i = 0; i < function->n_args; i++)
              {
                int type;
 
                lex_match (lexer, T_COMMA);
+                if (i == 0)
+                  args_start_ofs = lex_ofs (lexer);
                if (lex_is_string (lexer))
                  {
                    arg[i].c = recode_string (dict_get_encoding (agr->dict),
@@ -510,21 +512,35 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
                  }
                 else
                   {
-                   msg (SE, _("Missing argument %zu to %s."),
-                         i + 1, function->name);
+                   lex_error (lexer, _("Missing argument %zu to %s."),
+                               i + 1, function->name);
                    goto error;
                  }
-
-               lex_get (lexer);
-
                if (type != var_get_type (src[0]))
                  {
                    msg (SE, _("Arguments to %s must be of same type as "
                               "source variables."),
                         function->name);
+                    if (type == VAL_NUMERIC)
+                      {
+                        lex_next_msg (lexer, SN, 0, 0,
+                                      _("The argument is numeric."));
+                        lex_ofs_msg (lexer, SN, vars_start_ofs, vars_end_ofs,
+                                     _("The variables have string type."));
+                      }
+                    else
+                      {
+                        lex_next_msg (lexer, SN, 0, 0,
+                                      _("The argument is a string."));
+                        lex_ofs_msg (lexer, SN, vars_start_ofs, vars_end_ofs,
+                                     _("The variables are numeric."));
+                      }
                    goto error;
                  }
+
+               lex_get (lexer);
              }
+          int args_end_ofs = lex_ofs (lexer) - 1;
 
          /* Trailing rparen. */
          if (!lex_force_match (lexer, T_RPAREN))
@@ -554,10 +570,11 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
               arg[0] = arg[1];
               arg[1] = t;
 
-              msg (SW, _("The value arguments passed to the %s function "
-                         "are out-of-order.  They will be treated as if "
-                         "they had been specified in the correct order."),
-                   function->name);
+              lex_ofs_msg (lexer, SW, args_start_ofs, args_end_ofs,
+                           _("The value arguments passed to the %s function "
+                             "are out of order.  They will be treated as if "
+                             "they had been specified in the correct order."),
+                           function->name);
             }
        }
 
@@ -565,7 +582,7 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
          variables. */
       for (i = 0; i < n_dest; i++)
        {
-         struct agr_var *v = xzalloc (sizeof *v);
+         struct agr_var *v = XZALLOC (struct agr_var);
 
          /* Add variable to chain. */
          if (agr->agr_vars != NULL)
@@ -674,7 +691,7 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
          if (lex_token (lexer) == T_ENDCMD)
            return true;
 
-         lex_error (lexer, "expecting end of command");
+         lex_error (lexer, "Syntax error expecting end of command.");
          return false;
        }
       continue;
@@ -708,7 +725,7 @@ agr_destroy (struct agr_proc *agr)
 {
   struct agr_var *iter, *next;
 
-  subcase_destroy (&agr->sort);
+  subcase_uninit (&agr->sort);
   free (agr->break_vars);
   for (iter = agr->agr_vars; iter; iter = next)
     {
@@ -754,7 +771,7 @@ accumulate_aggregate_info (struct agr_proc *agr, const struct ccase *input)
        const union value *v = case_data (input, iter->src);
         int src_width = var_get_width (iter->src);
 
-        if (var_is_value_missing (iter->src, v, iter->exclude))
+        if (var_is_value_missing (iter->src, v) & iter->exclude)
          {
            switch (iter->function)
              {
@@ -789,12 +806,11 @@ accumulate_aggregate_info (struct agr_proc *agr, const struct ccase *input)
 
               cout = case_create (casewriter_get_proto (iter->writer));
 
-             case_data_rw (cout, iter->subject)->f
-                = case_data (input, iter->src)->f;
+             *case_num_rw (cout, iter->subject) = case_num (input, iter->src);
 
              wv = dict_get_case_weight (agr->src_dict, input, NULL);
 
-             case_data_rw (cout, iter->weight)->f = wv;
+             *case_num_rw (cout, iter->weight) = wv;
 
              iter->cc += wv;
 
@@ -936,14 +952,14 @@ dump_aggregate_info (const struct agr_proc *agr, struct casewriter *output, cons
 
   if (agr->add_variables)
     {
-      case_copy (c, 0, break_case, 0, dict_get_var_cnt (agr->src_dict));
+      case_copy (c, 0, break_case, 0, dict_get_n_vars (agr->src_dict));
     }
   else
     {
       int value_idx = 0;
       int i;
 
-      for (i = 0; i < agr->break_var_cnt; i++)
+      for (i = 0; i < agr->break_n_vars; i++)
        {
          const struct variable *v = agr->break_vars[i];
          value_copy (case_data_rw_idx (c, value_idx),
@@ -1120,7 +1136,7 @@ initialize_aggregate_info (struct agr_proc *agr)
 
             subcase_init_var (&ordering, iter->subject, SC_ASCEND);
            iter->writer = sort_create_writer (&ordering, proto);
-            subcase_destroy (&ordering);
+            subcase_uninit (&ordering);
             caseproto_unref (proto);
 
            iter->cc = 0;