Adopt use of gnulib for portability.
[pspp-builds.git] / src / apply-dict.c
index 082a8bd89735aa119bdf3cc25b67f0d32b8843aa..74c1642b96df8f466a978d27abd2ef6134936e62 100644 (file)
 
    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 <stdlib.h>
-#include "avl.h"
 #include "command.h"
+#include "dictionary.h"
 #include "error.h"
 #include "file-handle.h"
+#include "hash.h"
 #include "lexer.h"
-#include "sfm.h"
+#include "sfm-read.h"
 #include "str.h"
+#include "value-labels.h"
 #include "var.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 #include "debug-print.h"
 
 /* Parses and executes APPLY DICTIONARY. */
@@ -35,29 +40,28 @@ int
 cmd_apply_dictionary (void)
 {
   struct file_handle *handle;
+  struct sfm_reader *reader;
   struct dictionary *dict;
 
   int n_matched = 0;
 
   int i;
   
-  lex_match_id ("APPLY");
-  lex_match_id ("DICTIONARY");
-  
   lex_match_id ("FROM");
   lex_match ('=');
-  handle = fh_parse_file_handle ();
+  handle = fh_parse ();
   if (!handle)
     return CMD_FAILURE;
 
-  dict = sfm_read_dictionary (handle, NULL);
+  reader = sfm_open_reader (handle, &dict, NULL);
   if (dict == NULL)
     return CMD_FAILURE;
+  sfm_close_reader (reader);
 
-  for (i = 0; i < dict->nvar; i++)
+  for (i = 0; i < dict_get_var_cnt (dict); i++)
     {
-      struct variable *s = dict->var[i];
-      struct variable *t = find_variable (s->name);
+      struct variable *s = dict_get_var (dict, i);
+      struct variable *t = dict_lookup_var (default_dict, s->name);
       if (t == NULL)
        continue;
 
@@ -79,27 +83,34 @@ cmd_apply_dictionary (void)
          s->label = NULL;
        }
 
-      if (s->val_lab && t->width > MAX_SHORT_STRING)
+      if (val_labs_count (s->val_labs) && t->width > MAX_SHORT_STRING)
        msg (SW, _("Cannot add value labels from source file to "
                   "long string variable %s."),
             s->name);
-      else if (s->val_lab)
+      else if (val_labs_count (s->val_labs))
        {
+          /* Whether to apply the value labels. */
+          int apply = 1;
+          
          if (t->width < s->width)
            {
-             avl_traverser iter;
-             struct value_label *lab;
+             struct val_labs_iterator *i;
+             struct val_lab *lab;
 
-             avl_traverser_init (iter);
-             while ((lab = avl_traverse (s->val_lab, &iter)) != NULL)
+              for (lab = val_labs_first (s->val_labs, &i); lab != NULL;
+                   lab = val_labs_next (s->val_labs, &i))
                {
                  int j;
 
-                 /* If the truncated characters aren't all blanks
-                    anyway, then don't apply the value labels. */
+                 /* We will apply the value labels only if all
+                     the truncated characters are blanks. */
                  for (j = t->width; j < s->width; j++)
-                   if (lab->v.s[j] != ' ')
-                     goto skip_value_labels;
+                   if (lab->value.s[j] != ' ') 
+                      {
+                        val_labs_done (&i);
+                        apply = 0;
+                        break; 
+                      }
                }
            }
          else
@@ -108,12 +119,15 @@ cmd_apply_dictionary (void)
                 label values are right-padded with spaces, so it is
                 unnecessary to bother padding values here. */
            }
-         
-         avl_destroy (t->val_lab, free_val_lab);
-         t->val_lab = s->val_lab;
-         s->val_lab = NULL;
+
+         if (apply) 
+            {
+              val_labs_destroy (t->val_labs);
+              t->val_labs = s->val_labs;
+              val_labs_set_width (t->val_labs, t->width);
+              s->val_labs = val_labs_create (s->width);
+            }
        }
-    skip_value_labels: ;
 
       if (s->miss_type != MISSING_NONE && t->width > MAX_SHORT_STRING)
        msg (SW, _("Cannot apply missing values from source file to "
@@ -139,6 +153,7 @@ cmd_apply_dictionary (void)
          t->miss_type = s->miss_type;
          memcpy (t->missing, s->missing, sizeof s->missing);
        }
+    skip_missing_values: ;
 
       if (s->type == NUMERIC)
        {
@@ -152,31 +167,16 @@ cmd_apply_dictionary (void)
               "and target files."));
       
   /* Weighting. */
-  {
-    const int tfw = find_variable (default_dict.weight_var) != 0;
-    const int sfw = dict->weight_var[0] != 0;
-    struct variable *w;
-
-    switch (10 * tfw + sfw)
-      {
-      case 10:
-       /* The working file retains its weighting variable. */
-       break;
-
-      case 00:
-      case 01:
-       /* Fall through to case 11. */
-
-      case 11:
-       w = find_variable (dict->weight_var);
-       if (w)
-         strcpy (default_dict.weight_var, dict->weight_var);
-       break;
-      }
-  }
- skip_missing_values: ;
+  if (dict_get_weight (dict) != NULL) 
+    {
+      struct variable *new_weight
+        = dict_lookup_var (default_dict, dict_get_weight (dict)->name);
+
+      if (new_weight != NULL)
+        dict_set_weight (default_dict, new_weight);
+    }
   
-  sfm_maybe_close (handle);
+  sfm_close_reader (reader);
 
   return lex_end_of_command ();
 }