Adopt use of gnulib for portability.
[pspp-builds.git] / src / get.c
index c4dcc820ac5d6e5d5d624849e2a7b0d2ac4748b2..a13277a6bf4676ccc0125d1bf846e5f50b9a25a4 100644 (file)
--- a/src/get.c
+++ b/src/get.c
@@ -40,6 +40,9 @@
 #include "vfm.h"
 #include "vfmP.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 #include "debug-print.h"
 
 /* Rearranging and reducing a dictionary. */
@@ -212,17 +215,13 @@ cmd_save_internal (void)
       if (lex_match_id ("VERSION"))
        {
          lex_match ('=');
-         if ( lex_force_num() 
+         if (lex_force_int ()
            {
-             lex_get();
-             version = tokval;
+             version = lex_integer ();
+              lex_get ();
              
-             if ( 0 == strncasecmp (tokid,"x", 1) ) 
-               {
-                 lex_get();
-                 no_name_table = 1;
-               }
-
+             if (lex_match_id ("X")) 
+                no_name_table = 1;
            }
        }
       else if (lex_match_id ("OUTFILE"))
@@ -450,8 +449,6 @@ rename_variables (struct dictionary *dict)
       if (!lex_force_match ('=')
          || !lex_force_id ())
        return 0;
-      if (!strncmp (tokid, v->name, SHORT_NAME_LEN))
-       return 1;
       if (dict_lookup_var (dict, tokid) != NULL)
        {
          msg (SE, _("Cannot rename %s as %s because there already exists "
@@ -686,7 +683,7 @@ struct mtf_proc
     size_t by_cnt;              /* Number of variables on BY subcommand. */
 
     /* Names of FIRST, LAST variables. */
-    char first[SHORT_NAME_LEN + 1], last[SHORT_NAME_LEN + 1];
+    char first[LONG_NAME_LEN + 1], last[LONG_NAME_LEN + 1];
     
     struct dictionary *dict;    /* Dictionary of output file. */
     struct case_sink *sink;     /* Sink to receive output. */
@@ -734,7 +731,8 @@ cmd_match_files (void)
   dict_set_case_limit (mtf.dict, dict_get_case_limit (default_dict));
 
   lex_match ('/');
-  while (lex_id_match ("FILE", tokid) || lex_id_match ("TABLE", tokid)) 
+  while (token == T_ID
+         && (lex_id_match ("FILE", tokid) || lex_id_match ("TABLE", tokid)))
     {
       struct mtf_file *file = xmalloc (sizeof *file);
 
@@ -747,6 +745,7 @@ cmd_match_files (void)
         }
       else
         assert (0);
+      lex_match ('=');
 
       file->by = NULL;
       file->handle = NULL;
@@ -780,9 +779,7 @@ cmd_match_files (void)
             mtf.head = file;
           first_table->prev = file;
         }
-         
-      lex_match ('=');
-         
+
       if (lex_match ('*'))
         {
           file->handle = NULL;
@@ -893,6 +890,7 @@ cmd_match_files (void)
                     }
                 }
             }
+          free (by);
        }
       else if (lex_match_id ("FIRST")) 
         {
@@ -963,6 +961,8 @@ cmd_match_files (void)
         }
     }
 
+  /* Set up mapping from each file's variables to master
+     variables. */
   for (iter = mtf.head; iter != NULL; iter = iter->next)
     {
       struct dictionary *d = iter->dict;
@@ -977,20 +977,20 @@ cmd_match_files (void)
         }
     }
 
+  /* Add IN variables to master dictionary. */
   for (iter = mtf.head; iter != NULL; iter = iter->next) 
     if (iter->in_name != NULL)
       {
-        static const struct fmt_spec f1_0 = {FMT_F, 1, 0};
-        
         iter->in_var = dict_create_var (mtf.dict, iter->in_name, 0);
         if (iter->in_var == NULL)
           {
             msg (SE, _("IN variable name %s duplicates an "
                        "existing variable name."),
-                 iter->in_var);
+                 iter->in_var->name);
             goto error;
           }
-        iter->in_var->print = iter->in_var->write = f1_0;
+        iter->in_var->print = iter->in_var->write
+          = make_output_format (FMT_F, 1, 0);
       }
     
   /* MATCH FILES performs an n-way merge on all its input files.
@@ -1034,7 +1034,7 @@ cmd_match_files (void)
   if (mtf.sink->class->open != NULL)
     mtf.sink->class->open (mtf.sink);
 
-  mtf.seq_nums = xcalloc (dict_get_var_cnt (mtf.dict) * sizeof *mtf.seq_nums);
+  mtf.seq_nums = xcalloc (dict_get_var_cnt (mtf.dict), sizeof *mtf.seq_nums);
   case_create (&mtf.mtf_case, dict_get_next_value_idx (mtf.dict));
 
   mtf_read_nonactive_records (&mtf);
@@ -1042,6 +1042,9 @@ cmd_match_files (void)
     procedure (mtf_processing, &mtf);
   mtf_processing_finish (&mtf);
 
+  free_case_source (vfm_source);
+  vfm_source = NULL;
+
   dict_destroy (default_dict);
   default_dict = mtf.dict;
   mtf.dict = NULL;
@@ -1205,7 +1208,9 @@ mtf_processing (struct ccase *c, void *mtf_)
   bool read_active_file;
 
   assert (mtf->head != NULL);
-  assert (mtf->head->type == MTF_FILE);
+  if (mtf->head->type == MTF_TABLE)
+    return 1;
+  
   do
     {
       struct mtf_file *min_head, *min_tail; /* Files with minimum BY values. */
@@ -1220,38 +1225,34 @@ mtf_processing (struct ccase *c, void *mtf_)
       min_head = min_tail = mtf->head;
       max_head = max_tail = NULL;
       for (iter = mtf->head->next; iter && iter->type == MTF_FILE;
-          iter = iter->next)
-       switch (mtf_compare_BY_values (mtf, min_head, iter, c))
-         {
-         case -1:
-           if (max_head)
-             max_tail = max_tail->next_min = iter;
-           else
-             max_head = max_tail = iter;
-           break;
-
-         case 0:
+          iter = iter->next) 
+        {
+          int cmp = mtf_compare_BY_values (mtf, min_head, iter, c);
+          if (cmp < 0) 
+            {
+              if (max_head)
+                max_tail = max_tail->next_min = iter;
+              else
+                max_head = max_tail = iter;
+            }
+          else if (cmp == 0) 
            min_tail = min_tail->next_min = iter;
-           break;
-
-         case 1:
-           if (max_head)
-             {
-               max_tail->next_min = min_head;
-               max_tail = min_tail;
-             }
-           else
-             {
-               max_head = min_head;
-               max_tail = min_tail;
-             }
-           min_head = min_tail = iter;
-           break;
-
-         default:
-           assert (0);
-         }
-
+          else /* cmp > 0 */
+            {
+              if (max_head)
+                {
+                  max_tail->next_min = min_head;
+                  max_tail = min_tail;
+                }
+              else
+                {
+                  max_head = min_head;
+                  max_tail = min_tail;
+                }
+              min_head = min_tail = iter;
+            }
+        }
+      
       /* 4. For every TABLE, read another record as long as the BY
         values on the TABLE's input record are less than the FILEs'
         BY values.  If an exact match is found, store all the values
@@ -1261,32 +1262,28 @@ mtf_processing (struct ccase *c, void *mtf_)
          assert (iter->type == MTF_TABLE);
       
          next = iter->next;
-
-       again:
-         switch (mtf_compare_BY_values (mtf, min_head, iter, c))
-           {
-           case -1:
-             if (max_head)
-               max_tail = max_tail->next_min = iter;
-             else
-               max_head = max_tail = iter;
-             break;
-
-           case 0:
-             min_tail = min_tail->next_min = iter;
-             break;
-
-           case 1:
-             if (iter->handle == NULL)
-               return 1;
-             if (sfm_read_case (iter->reader, &iter->input))
-               goto again;
-             mtf_delete_file_in_place (mtf, &iter);
-             break;
-
-           default:
-             assert (0);
-           }
+          for (;;) 
+            {
+              int cmp = mtf_compare_BY_values (mtf, min_head, iter, c);
+              if (cmp < 0) 
+                {
+                  if (max_head)
+                    max_tail = max_tail->next_min = iter;
+                  else
+                    max_head = max_tail = iter;
+                }
+              else if (cmp == 0)
+                min_tail = min_tail->next_min = iter;
+              else /* cmp > 0 */
+                {
+                  if (iter->handle == NULL)
+                    return 1;
+                  if (sfm_read_case (iter->reader, &iter->input))
+                    continue;
+                  mtf_delete_file_in_place (mtf, &iter);
+                }
+              break;
+            }
        }
 
       /* Next sequence number. */
@@ -1404,13 +1401,14 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f)
         }
     }
   
-  dict_compact_values (d);
-
   for (i = 0; i < dict_get_var_cnt (d); i++)
     {
       struct variable *dv = dict_get_var (d, i);
       struct variable *mv = dict_lookup_var (m, dv->name);
 
+      if (dict_class_from_id (dv->name) == DC_SCRATCH)
+        continue;
+
       if (mv != NULL)
         {
           if (mv->width != dv->width) 
@@ -1437,10 +1435,7 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f)
             mv->label = xstrdup (dv->label);
         }
       else
-        {
-          mv = dict_clone_var (m, dv, dv->name, dv->longname);
-          assert (mv != NULL);
-        }
+        mv = dict_clone_var_assert (m, dv, dv->name);
     }
 
   return 1;