Actually implement the new procedure code and adapt all of its clients
[pspp] / src / language / dictionary / modify-variables.c
index 1632f6ea0db7aecda785b929f72fd544af469b30..41709416ae669e349a6fa6263322cae3bed0d2d1 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
    Copyright (C) 1997-9, 2000 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
@@ -41,7 +40,6 @@
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
-/* FIXME: should change weighting variable, etc. */
 /* These control the ordering produced by
    compare_variables_given_ordering(). */
 struct ordering
@@ -54,7 +52,7 @@ struct ordering
 static struct ordering forward_positional_ordering = {1, 1};
 
 static int compare_variables_given_ordering (const void *, const void *,
-                                             void *ordering);
+                                             const void *ordering);
 
 /* Explains how to modify the variables in a dictionary. */
 struct var_modification
@@ -73,12 +71,12 @@ struct var_modification
     size_t rename_cnt;
   };
 
-static int rearrange_dict (struct dictionary *d,
+static bool rearrange_dict (struct dictionary *d,
                            const struct var_modification *vm);
 
 /* Performs MODIFY VARS command. */
 int
-cmd_modify_vars (void)
+cmd_modify_vars (struct lexer *lexer, struct dataset *ds)
 {
   /* Bits indicated whether we've already encountered a subcommand of
      this type. */
@@ -92,7 +90,7 @@ cmd_modify_vars (void)
 
   size_t i;
 
-  if (proc_make_temporary_transformations_permanent ())
+  if (proc_make_temporary_transformations_permanent (ds))
     msg (SE, _("MODIFY VARS may not be used after TEMPORARY.  "
                "Temporary transformations will be made permanent."));
 
@@ -105,10 +103,10 @@ cmd_modify_vars (void)
   vm.drop_cnt = 0;
 
   /* Parse each subcommand. */
-  lex_match ('/');
+  lex_match (lexer, '/');
   for (;;)
     {
-      if (lex_match_id ("REORDER"))
+      if (lex_match_id (lexer, "REORDER"))
        {
          struct variable **v = NULL;
          size_t nv = 0;
@@ -120,21 +118,21 @@ cmd_modify_vars (void)
            }
          already_encountered |= 1;
 
-         lex_match ('=');
+         lex_match (lexer, '=');
          do
            {
               struct ordering ordering;
              size_t prev_nv = nv;
 
              ordering.forward = ordering.positional = 1;
-             if (lex_match_id ("FORWARD"));
-             else if (lex_match_id ("BACKWARD"))
+             if (lex_match_id (lexer, "FORWARD"));
+             else if (lex_match_id (lexer, "BACKWARD"))
                ordering.forward = 0;
-             if (lex_match_id ("POSITIONAL"));
-             else if (lex_match_id ("ALPHA"))
+             if (lex_match_id (lexer, "POSITIONAL"));
+             else if (lex_match_id (lexer, "ALPHA"))
                ordering.positional = 0;
 
-             if (lex_match (T_ALL) || token == '/' || token == '.')
+             if (lex_match (lexer, T_ALL) || lex_token (lexer) == '/' || lex_token (lexer) == '.')
                {
                  if (prev_nv != 0)
                    {
@@ -142,23 +140,23 @@ cmd_modify_vars (void)
                           "of variables."));
                      goto done;
                    }
-                 dict_get_vars (default_dict, &v, &nv, 1u << DC_SYSTEM);
+                 dict_get_vars_mutable (dataset_dict (ds), &v, &nv, 1u << DC_SYSTEM);
                }
              else
                {
-                 if (!lex_match ('('))
+                 if (!lex_match (lexer, '('))
                    {
                      msg (SE, _("`(' expected on REORDER subcommand."));
                      free (v);
                      goto done;
                    }
-                 if (!parse_variables (default_dict, &v, &nv,
+                 if (!parse_variables (lexer, dataset_dict (ds), &v, &nv,
                                        PV_APPEND | PV_NO_DUPLICATE))
                    {
                      free (v);
                      goto done;
                    }
-                 if (!lex_match (')'))
+                 if (!lex_match (lexer, ')'))
                    {
                      msg (SE, _("`)' expected following variable names on "
                           "REORDER subcommand."));
@@ -169,12 +167,12 @@ cmd_modify_vars (void)
              sort (&v[prev_nv], nv - prev_nv, sizeof *v,
                     compare_variables_given_ordering, &ordering);
            }
-         while (token != '/' && token != '.');
+         while (lex_token (lexer) != '/' && lex_token (lexer) != '.');
 
          vm.reorder_vars = v;
           vm.reorder_cnt = nv;
        }
-      else if (lex_match_id ("RENAME"))
+      else if (lex_match_id (lexer, "RENAME"))
        {
          if (already_encountered & 2)
            {
@@ -183,49 +181,52 @@ cmd_modify_vars (void)
            }
          already_encountered |= 2;
 
-         lex_match ('=');
+         lex_match (lexer, '=');
          do
            {
              size_t prev_nv_1 = vm.rename_cnt;
              size_t prev_nv_2 = vm.rename_cnt;
 
-             if (!lex_match ('('))
+             if (!lex_match (lexer, '('))
                {
                  msg (SE, _("`(' expected on RENAME subcommand."));
                  goto done;
                }
-             if (!parse_variables (default_dict, &vm.rename_vars, &vm.rename_cnt,
+             if (!parse_variables (lexer, dataset_dict (ds), 
+                                   &vm.rename_vars, &vm.rename_cnt,
                                    PV_APPEND | PV_NO_DUPLICATE))
                goto done;
-             if (!lex_match ('='))
+             if (!lex_match (lexer, '='))
                {
                  msg (SE, _("`=' expected between lists of new and old variable "
                       "names on RENAME subcommand."));
                  goto done;
                }
-             if (!parse_DATA_LIST_vars (&vm.new_names, &prev_nv_1, PV_APPEND))
+             if (!parse_DATA_LIST_vars (lexer, &vm.new_names, 
+                                        &prev_nv_1, PV_APPEND))
                goto done;
              if (prev_nv_1 != vm.rename_cnt)
                {
                  msg (SE, _("Differing number of variables in old name list "
                       "(%d) and in new name list (%d)."),
-                      vm.rename_cnt - prev_nv_2, prev_nv_1 - prev_nv_2);
+                      (int) (vm.rename_cnt - prev_nv_2),
+                       (int) (prev_nv_1 - prev_nv_2));
                  for (i = 0; i < prev_nv_1; i++)
                    free (vm.new_names[i]);
                  free (vm.new_names);
                  vm.new_names = NULL;
                  goto done;
                }
-             if (!lex_match (')'))
+             if (!lex_match (lexer, ')'))
                {
                  msg (SE, _("`)' expected after variable lists on RENAME "
                       "subcommand."));
                  goto done;
                }
            }
-         while (token != '.' && token != '/');
+         while (lex_token (lexer) != '.' && lex_token (lexer) != '/');
        }
-      else if (lex_match_id ("KEEP"))
+      else if (lex_match_id (lexer, "KEEP"))
        {
          struct variable **keep_vars, **all_vars, **drop_vars;
          size_t keep_cnt, all_cnt, drop_cnt;
@@ -238,8 +239,8 @@ cmd_modify_vars (void)
            }
          already_encountered |= 4;
 
-         lex_match ('=');
-         if (!parse_variables (default_dict, &keep_vars, &keep_cnt, PV_NONE))
+         lex_match (lexer, '=');
+         if (!parse_variables (lexer, dataset_dict (ds), &keep_vars, &keep_cnt, PV_NONE))
            goto done;
 
          /* Transform the list of variables to keep into a list of
@@ -248,7 +249,7 @@ cmd_modify_vars (void)
          sort (keep_vars, keep_cnt, sizeof *keep_vars,
                 compare_variables_given_ordering, &forward_positional_ordering);
 
-          dict_get_vars (default_dict, &all_vars, &all_cnt, 0);
+          dict_get_vars_mutable (dataset_dict (ds), &all_vars, &all_cnt, 0);
           assert (all_cnt >= keep_cnt);
 
           drop_cnt = all_cnt - keep_cnt;
@@ -268,7 +269,7 @@ cmd_modify_vars (void)
           vm.drop_vars = drop_vars;
           vm.drop_cnt = drop_cnt;
        }
-      else if (lex_match_id ("DROP"))
+      else if (lex_match_id (lexer, "DROP"))
        {
          struct variable **drop_vars;
          size_t drop_cnt;
@@ -282,15 +283,15 @@ cmd_modify_vars (void)
            }
          already_encountered |= 4;
 
-         lex_match ('=');
-         if (!parse_variables (default_dict, &drop_vars, &drop_cnt, PV_NONE))
+         lex_match (lexer, '=');
+         if (!parse_variables (lexer, dataset_dict (ds), &drop_vars, &drop_cnt, PV_NONE))
            goto done;
           vm.drop_vars = drop_vars;
           vm.drop_cnt = drop_cnt;
        }
-      else if (lex_match_id ("MAP"))
+      else if (lex_match_id (lexer, "MAP"))
        {
-          struct dictionary *temp = dict_clone (default_dict);
+          struct dictionary *temp = dict_clone (dataset_dict (ds));
           int success = rearrange_dict (temp, &vm);
           if (success) 
             {
@@ -300,31 +301,31 @@ cmd_modify_vars (void)
        }
       else
        {
-         if (token == T_ID)
-           msg (SE, _("Unrecognized subcommand name `%s'."), tokid);
+         if (lex_token (lexer) == T_ID)
+           msg (SE, _("Unrecognized subcommand name `%s'."), lex_tokid (lexer));
          else
            msg (SE, _("Subcommand name expected."));
          goto done;
        }
 
-      if (token == '.')
+      if (lex_token (lexer) == '.')
        break;
-      if (token != '/')
+      if (lex_token (lexer) != '/')
        {
          msg (SE, _("`/' or `.' expected."));
          goto done;
        }
-      lex_get ();
+      lex_get (lexer);
     }
 
   if (already_encountered & (1 | 4))
     {
       /* Read the data. */
-      if (!procedure (NULL, NULL)) 
+      if (!proc_execute (ds)) 
         goto done; 
     }
 
-  if (!rearrange_dict (default_dict, &vm))
+  if (!rearrange_dict (dataset_dict (ds), &vm))
     goto done; 
 
   ret_code = CMD_SUCCESS;
@@ -343,7 +344,7 @@ done:
    ORDERING, returning a strcmp()-type result. */
 static int
 compare_variables_given_ordering (const void *a_, const void *b_,
-                                  void *ordering_)
+                                  const void *ordering_)
 {
   struct variable *const *pa = a_;
   struct variable *const *pb = b_;
@@ -352,10 +353,14 @@ compare_variables_given_ordering (const void *a_, const void *b_,
   const struct ordering *ordering = ordering_;
 
   int result;
-  if (ordering->positional)
-    result = a->index < b->index ? -1 : a->index > b->index;
+  if (ordering->positional) 
+    {
+      size_t a_index = var_get_dict_index (a);
+      size_t b_index = var_get_dict_index (b);
+      result = a_index < b_index ? -1 : a_index > b_index; 
+    }
   else
-    result = strcasecmp (a->name, b->name);
+    result = strcasecmp (var_get_name (a), var_get_name (b));
   if (!ordering->forward)
     result = -result;
   return result;
@@ -372,7 +377,7 @@ struct var_renaming
    var_renaming structures A and B. */
 static int
 compare_var_renaming_by_new_name (const void *a_, const void *b_,
-                                  void *foo UNUSED) 
+                                  const void *aux UNUSED) 
 {
   const struct var_renaming *a = a_;
   const struct var_renaming *b = b_;
@@ -402,7 +407,7 @@ validate_var_modification (const struct dictionary *d,
   size_t i;
 
   /* All variables, in index order. */
-  dict_get_vars (d, &all_vars, &all_cnt, 0);
+  dict_get_vars_mutable (d, &all_vars, &all_cnt, 0);
 
   /* Drop variables, in index order. */
   drop_cnt = vm->drop_cnt;
@@ -428,7 +433,7 @@ validate_var_modification (const struct dictionary *d,
   for (i = 0; i < keep_cnt; i++) 
     {
       var_renaming[i].var = keep_vars[i];
-      strcpy (var_renaming[i].new_name, keep_vars[i]->name);
+      strcpy (var_renaming[i].new_name, var_get_name (keep_vars[i]));
     }
   
   /* Rename variables in var_renaming array. */
@@ -466,11 +471,11 @@ validate_var_modification (const struct dictionary *d,
 }
 
 /* Reoders, removes, and renames variables in dictionary D
-   according to VM.  Returns nonzero if successful, zero if there
+   according to VM.  Returns true if successful, false if there
    would have been duplicate variable names if the modifications
    had been carried out.  In the latter case, the dictionary is
    not modified. */
-static int
+static bool
 rearrange_dict (struct dictionary *d, const struct var_modification *vm)
 {
   char **rename_old_names;
@@ -484,14 +489,14 @@ rearrange_dict (struct dictionary *d, const struct var_modification *vm)
   /* Check whether the modifications will cause duplicate
      names. */
   if (!validate_var_modification (d, vm))
-    return 0;
+    return false;
 
   /* Record the old names of variables to rename.  After
      variables are deleted, we can't depend on the variables to
      still exist, but we can still look them up by name. */
   rename_old_names = xnmalloc (vm->rename_cnt, sizeof *rename_old_names);
   for (i = 0; i < vm->rename_cnt; i++)
-    rename_old_names[i] = xstrdup (vm->rename_vars[i]->name);
+    rename_old_names[i] = xstrdup (var_get_name (vm->rename_vars[i]));
 
   /* Reorder and delete variables. */
   dict_reorder_vars (d, vm->reorder_vars, vm->reorder_cnt);
@@ -524,5 +529,5 @@ rearrange_dict (struct dictionary *d, const struct var_modification *vm)
   free (rename_vars);
   free (rename_new_names);
 
-  return 1;
+  return true;
 }