lexer: Change the functions for retrieving token strings.
[pspp] / src / language / lexer / variable-parser.c
index c6a2d5378b112ecd2210d74bc904f054df893d6e..5b698bbf4a2c6eefc063bcf431cffe6c559f61af 100644 (file)
@@ -34,6 +34,7 @@
 #include "libpspp/misc.h"
 #include "libpspp/pool.h"
 #include "libpspp/str.h"
+#include "libpspp/stringi-set.h"
 
 #include "gl/xalloc.h"
 
@@ -64,14 +65,14 @@ parse_vs_variable_idx (struct lexer *lexer, const struct var_set *vs,
       lex_error (lexer, _("expecting variable name"));
       return false;
     }
-  else if (var_set_lookup_var_idx (vs, lex_tokid (lexer), idx))
+  else if (var_set_lookup_var_idx (vs, lex_tokcstr (lexer), idx))
     {
       lex_get (lexer);
       return true;
     }
   else
     {
-      msg (SE, _("%s is not a variable name."), lex_tokid (lexer));
+      msg (SE, _("%s is not a variable name."), lex_tokcstr (lexer));
       return false;
     }
 }
@@ -335,10 +336,10 @@ parse_var_set_vars (struct lexer *lexer, const struct var_set *vs,
 
       if (pv_opts & PV_SINGLE)
         break;
-      lex_match (lexer, ',');
+      lex_match (lexer, T_COMMA);
     }
   while (lex_token (lexer) == T_ALL
-         || (lex_token (lexer) == T_ID && var_set_lookup_var (vs, lex_tokid (lexer)) != NULL));
+         || (lex_token (lexer) == T_ID && var_set_lookup_var (vs, lex_tokcstr (lexer)) != NULL));
 
   if (*nv == 0)
     goto fail;
@@ -400,7 +401,8 @@ extract_num (char *s, char *r, int *n, int *d)
 /* Parses a list of variable names according to the DATA LIST version
    of the TO convention.  */
 bool
-parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv_opts)
+parse_DATA_LIST_vars (struct lexer *lexer, char ***names,
+                      size_t *nnames, int pv_opts)
 {
   int n1, n2;
   int d1, d2;
@@ -408,16 +410,27 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
   size_t nvar, mvar;
   char name1[VAR_NAME_LEN + 1], name2[VAR_NAME_LEN + 1];
   char root1[VAR_NAME_LEN + 1], root2[VAR_NAME_LEN + 1];
+  struct stringi_set set;
   int success = 0;
 
   assert (names != NULL);
   assert (nnames != NULL);
   assert ((pv_opts & ~(PV_APPEND | PV_SINGLE
                        | PV_NO_SCRATCH | PV_NO_DUPLICATE)) == 0);
-  /* FIXME: PV_NO_DUPLICATE is not implemented. */
+  stringi_set_init (&set);
 
   if (pv_opts & PV_APPEND)
-    nvar = mvar = *nnames;
+    {
+      nvar = mvar = *nnames;
+
+      if (pv_opts & PV_NO_DUPLICATE)
+        {
+          size_t i;
+
+          for (i = 0; i < nvar; i++)
+            stringi_set_insert (&set, (*names)[i]);
+        }
+    }
   else
     {
       nvar = mvar = 0;
@@ -431,13 +444,13 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
          lex_error (lexer, "expecting variable name");
          goto fail;
        }
-      if (dict_class_from_id (lex_tokid (lexer)) == DC_SCRATCH
+      if (dict_class_from_id (lex_tokcstr (lexer)) == DC_SCRATCH
           && (pv_opts & PV_NO_SCRATCH))
        {
          msg (SE, _("Scratch variables not allowed here."));
          goto fail;
        }
-      strcpy (name1, lex_tokid (lexer));
+      strcpy (name1, lex_tokcstr (lexer));
       lex_get (lexer);
       if (lex_token (lexer) == T_TO)
        {
@@ -447,7 +460,7 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
              lex_error (lexer, "expecting variable name");
              goto fail;
            }
-         strcpy (name2, lex_tokid (lexer));
+         strcpy (name2, lex_tokcstr (lexer));
          lex_get (lexer);
 
          if (!extract_num (name1, root1, &n1, &d1)
@@ -477,6 +490,13 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
            {
               char name[VAR_NAME_LEN + 1];
              sprintf (name, "%s%0*d", root1, d1, n);
+
+              if (pv_opts & PV_NO_DUPLICATE && !stringi_set_insert (&set, name))
+                {
+                  msg (SE, _("Variable %s appears twice in variable list."),
+                       name);
+                  goto fail;
+                }
              (*names)[nvar] = xstrdup (name);
              nvar++;
            }
@@ -491,7 +511,7 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
          (*names)[nvar++] = xstrdup (name1);
        }
 
-      lex_match (lexer, ',');
+      lex_match (lexer, T_COMMA);
 
       if (pv_opts & PV_SINGLE)
        break;
@@ -501,6 +521,7 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
 
 fail:
   *nnames = nvar;
+  stringi_set_destroy (&set);
   if (!success)
     {
       int i;
@@ -567,7 +588,7 @@ parse_mixed_vars (struct lexer *lexer, const struct dictionary *dict,
     }
   while (lex_token (lexer) == T_ID || lex_token (lexer) == T_ALL)
     {
-      if (lex_token (lexer) == T_ALL || dict_lookup_var (dict, lex_tokid (lexer)) != NULL)
+      if (lex_token (lexer) == T_ALL || dict_lookup_var (dict, lex_tokcstr (lexer)) != NULL)
        {
          struct variable **v;
          size_t nv;