Remove "Written by Ben Pfaff <blp@gnu.org>" lines everywhere.
[pspp-builds.git] / src / language / data-io / matrix-data.c
index ff008caa412c60532cae4b5e363d93f703bf616c..f958584b5403f7442984e8922e783b355ec0e851 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>.
+   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
 #include <data/case.h>
 #include <data/data-in.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/data-io/data-reader.h>
 #include <language/data-io/file-handle.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/variable-parser.h>
 #include <libpspp/alloc.h>
 #include <libpspp/array.h>
+#include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
 #include <libpspp/message.h>
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/pool.h>
 #include <libpspp/str.h>
-#include <procedure.h>
+
+#include "minmax.h"
+#include "size_max.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -111,7 +115,7 @@ static const int content_type[PROX + 1] =
   };
 
 /* Name of each content type. */
-static const char *content_names[PROX + 1] =
+static const char *const content_names[PROX + 1] =
   {
     "N", "N", "N_MATRIX", "MEAN", "STDDEV", "COUNT", "MSE",
     "DFE", "MAT", "COV", "CORR", "PROX",
@@ -148,7 +152,7 @@ struct matrix_data_pgm
 
     /* Continuous variables. */
     int n_continuous;           /* Number of continuous variables. */
-    int first_continuous;       /* Index into default_dict.var of
+    int first_continuous;       /* Index into dictionary of
                                    first continuous variable. */
   };
 
@@ -164,13 +168,13 @@ static const struct case_source_class matrix_data_without_rowtype_source_class;
 
 static int compare_variables_by_mxd_var_type (const void *pa,
                                             const void *pb);
-static bool read_matrices_without_rowtype (struct matrix_data_pgm *);
-static bool read_matrices_with_rowtype (struct matrix_data_pgm *);
-static int string_to_content_type (char *, int *);
+static bool read_matrices_without_rowtype (struct dataset *ds, struct matrix_data_pgm *);
+static bool read_matrices_with_rowtype (struct dataset *ds, struct matrix_data_pgm *);
+static int string_to_content_type (const char *, int *);
 static void attach_mxd_aux (struct variable *, int var_type, int sub_type);
 
 int
-cmd_matrix_data (void)
+cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
 {
   struct pool *pool;
   struct matrix_data_pgm *mx;
@@ -179,7 +183,7 @@ cmd_matrix_data (void)
     
   unsigned seen = 0;
   
-  discard_variables ();
+  discard_variables (ds);
 
   pool = pool_create ();
   mx = pool_alloc (pool, sizeof *mx);
@@ -200,11 +204,11 @@ cmd_matrix_data (void)
   mx->n_contents = 0;
   mx->n_continuous = 0;
   mx->first_continuous = 0;
-  while (token != '.')
+  while (lex_token (lexer) != '.')
     {
-      lex_match ('/');
+      lex_match (lexer, '/');
 
-      if (lex_match_id ("VARIABLES"))
+      if (lex_match_id (lexer, "VARIABLES"))
        {
          char **v;
          size_t nv;
@@ -216,8 +220,8 @@ cmd_matrix_data (void)
            }
          seen |= 1;
          
-         lex_match ('=');
-         if (!parse_DATA_LIST_vars (&v, &nv, PV_NO_DUPLICATE))
+         lex_match (lexer, '=');
+         if (!parse_DATA_LIST_vars (lexer, &v, &nv, PV_NO_DUPLICATE))
            goto lossage;
          
          {
@@ -244,7 +248,7 @@ cmd_matrix_data (void)
                
                if (strcasecmp (v[i], "ROWTYPE_"))
                  {
-                   new_var = dict_create_var_assert (default_dict, v[i], 0);
+                   new_var = dict_create_var_assert (dataset_dict (ds), v[i], 0);
                     attach_mxd_aux (new_var, MXD_CONTINUOUS, i);
                   }
                else
@@ -254,47 +258,47 @@ cmd_matrix_data (void)
            free (v);
          }
          
-          mx->rowtype_ = dict_create_var_assert (default_dict,
+          mx->rowtype_ = dict_create_var_assert (dataset_dict (ds),
                                                  "ROWTYPE_", 8);
           attach_mxd_aux (mx->rowtype_, MXD_ROWTYPE, 0);
        }
-      else if (lex_match_id ("FILE"))
+      else if (lex_match_id (lexer, "FILE"))
        {
-         lex_match ('=');
-         fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
+         lex_match (lexer, '=');
+         fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE);
          if (fh == NULL)
            goto lossage;
        }
-      else if (lex_match_id ("FORMAT"))
+      else if (lex_match_id (lexer, "FORMAT"))
        {
-         lex_match ('=');
+         lex_match (lexer, '=');
 
-         while (token == T_ID)
+         while (lex_token (lexer) == T_ID)
            {
-             if (lex_match_id ("LIST"))
+             if (lex_match_id (lexer, "LIST"))
                mx->fmt = LIST;
-             else if (lex_match_id ("FREE"))
+             else if (lex_match_id (lexer, "FREE"))
                mx->fmt = FREE;
-             else if (lex_match_id ("LOWER"))
+             else if (lex_match_id (lexer, "LOWER"))
                mx->section = LOWER;
-             else if (lex_match_id ("UPPER"))
+             else if (lex_match_id (lexer, "UPPER"))
                mx->section = UPPER;
-             else if (lex_match_id ("FULL"))
+             else if (lex_match_id (lexer, "FULL"))
                mx->section = FULL;
-             else if (lex_match_id ("DIAGONAL"))
+             else if (lex_match_id (lexer, "DIAGONAL"))
                mx->diag = DIAGONAL;
-             else if (lex_match_id ("NODIAGONAL"))
+             else if (lex_match_id (lexer, "NODIAGONAL"))
                mx->diag = NODIAGONAL;
              else 
                {
-                 lex_error (_("in FORMAT subcommand"));
+                 lex_error (lexer, _("in FORMAT subcommand"));
                  goto lossage;
                }
            }
        }
-      else if (lex_match_id ("SPLIT"))
+      else if (lex_match_id (lexer, "SPLIT"))
        {
-         lex_match ('=');
+         lex_match (lexer, '=');
 
          if (seen & 2)
            {
@@ -303,54 +307,54 @@ cmd_matrix_data (void)
            }
          seen |= 2;
          
-         if (token != T_ID)
+         if (lex_token (lexer) != T_ID)
            {
-             lex_error (_("in SPLIT subcommand"));
+             lex_error (lexer, _("in SPLIT subcommand"));
              goto lossage;
            }
          
-         if (dict_lookup_var (default_dict, tokid) == NULL
-             && (lex_look_ahead () == '.' || lex_look_ahead () == '/'))
+         if (dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) == NULL
+             && (lex_look_ahead (lexer) == '.' || lex_look_ahead (lexer) == '/'))
            {
-             if (!strcasecmp (tokid, "ROWTYPE_")
-                  || !strcasecmp (tokid, "VARNAME_"))
+             if (!strcasecmp (lex_tokid (lexer), "ROWTYPE_")
+                  || !strcasecmp (lex_tokid (lexer), "VARNAME_"))
                {
                  msg (SE, _("Split variable may not be named ROWTYPE_ "
                             "or VARNAME_."));
                  goto lossage;
                }
 
-             mx->single_split = dict_create_var_assert (default_dict,
-                                                         tokid, 0);
+             mx->single_split = dict_create_var_assert (dataset_dict (ds),
+                                                         lex_tokid (lexer), 0);
               attach_mxd_aux (mx->single_split, MXD_CONTINUOUS, 0);
-             lex_get ();
+             lex_get (lexer);
 
-              dict_set_split_vars (default_dict, &mx->single_split, 1);
+              dict_set_split_vars (dataset_dict (ds), &mx->single_split, 1);
            }
          else
            {
              struct variable **split;
              size_t n;
 
-             if (!parse_variables (default_dict, &split, &n, PV_NO_DUPLICATE))
+             if (!parse_variables (lexer, dataset_dict (ds), 
+                                   &split, &n, PV_NO_DUPLICATE))
                goto lossage;
 
-              dict_set_split_vars (default_dict, split, n);
+              dict_set_split_vars (dataset_dict (ds), split, n);
            }
          
          {
-            struct variable *const *split = dict_get_split_vars (default_dict);
-            size_t split_cnt = dict_get_split_cnt (default_dict);
+            struct variable *const *split = dict_get_split_vars (dataset_dict (ds));
+            size_t split_cnt = dict_get_split_cnt (dataset_dict (ds));
             int i;
 
             for (i = 0; i < split_cnt; i++)
               {
-                struct mxd_var *mv = split[i]->aux;
-                assert (mv != NULL);
+                struct mxd_var *mv = var_get_aux (split[i]);
                if (mv->var_type != MXD_CONTINUOUS)
                  {
                    msg (SE, _("Split variable %s is already another type."),
-                        tokid);
+                        lex_tokid (lexer));
                    goto lossage;
                  }
                 var_clear_aux (split[i]);
@@ -358,9 +362,9 @@ cmd_matrix_data (void)
               }
          }
        }
-      else if (lex_match_id ("FACTORS"))
+      else if (lex_match_id (lexer, "FACTORS"))
        {
-         lex_match ('=');
+         lex_match (lexer, '=');
          
          if (seen & 4)
            {
@@ -369,7 +373,7 @@ cmd_matrix_data (void)
            }
          seen |= 4;
 
-         if (!parse_variables (default_dict, &mx->factors, &mx->n_factors,
+         if (!parse_variables (lexer, dataset_dict (ds), &mx->factors, &mx->n_factors,
                                 PV_NONE))
            goto lossage;
          
@@ -379,12 +383,11 @@ cmd_matrix_data (void)
            for (i = 0; i < mx->n_factors; i++)
              {
                 struct variable *v = mx->factors[i];
-                struct mxd_var *mv = v->aux;
-                assert (mv != NULL);
+                struct mxd_var *mv = var_get_aux (v);
                if (mv->var_type != MXD_CONTINUOUS)
                  {
                    msg (SE, _("Factor variable %s is already another type."),
-                        tokid);
+                        lex_tokid (lexer));
                    goto lossage;
                  }
                 var_clear_aux (v);
@@ -392,9 +395,9 @@ cmd_matrix_data (void)
              }
          }
        }
-      else if (lex_match_id ("CELLS"))
+      else if (lex_match_id (lexer, "CELLS"))
        {
-         lex_match ('=');
+         lex_match (lexer, '=');
          
          if (mx->cells != -1)
            {
@@ -402,18 +405,18 @@ cmd_matrix_data (void)
              goto lossage;
            }
 
-         if (!lex_is_integer () || lex_integer () < 1)
+         if (!lex_is_integer (lexer) || lex_integer (lexer) < 1)
            {
-             lex_error (_("expecting positive integer"));
+             lex_error (lexer, _("expecting positive integer"));
              goto lossage;
            }
 
-         mx->cells = lex_integer ();
-         lex_get ();
+         mx->cells = lex_integer (lexer);
+         lex_get (lexer);
        }
-      else if (lex_match_id ("N"))
+      else if (lex_match_id (lexer, "N"))
        {
-         lex_match ('=');
+         lex_match (lexer, '=');
 
          if (mx->pop_n != -1)
            {
@@ -421,16 +424,16 @@ cmd_matrix_data (void)
              goto lossage;
            }
 
-         if (!lex_is_integer () || lex_integer () < 1)
+         if (!lex_is_integer (lexer) || lex_integer (lexer) < 1)
            {
-             lex_error (_("expecting positive integer"));
+             lex_error (lexer, _("expecting positive integer"));
              goto lossage;
            }
 
-         mx->pop_n = lex_integer ();
-         lex_get ();
+         mx->pop_n = lex_integer (lexer);
+         lex_get (lexer);
        }
-      else if (lex_match_id ("CONTENTS"))
+      else if (lex_match_id (lexer, "CONTENTS"))
        {
          int inside_parens = 0;
          unsigned collide = 0;
@@ -443,7 +446,7 @@ cmd_matrix_data (void)
            }
          seen |= 8;
 
-         lex_match ('=');
+         lex_match (lexer, '=');
          
          {
            int i;
@@ -454,7 +457,7 @@ cmd_matrix_data (void)
 
          for (;;)
            {
-             if (lex_match ('('))
+             if (lex_match (lexer, '('))
                {
                  if (inside_parens)
                    {
@@ -464,7 +467,7 @@ cmd_matrix_data (void)
                  inside_parens = 1;
                  item = LPAREN;
                }
-             else if (lex_match (')'))
+             else if (lex_match (lexer, ')'))
                {
                  if (!inside_parens)
                    {
@@ -484,20 +487,20 @@ cmd_matrix_data (void)
                  int content_type;
                  int collide_index;
                  
-                 if (token != T_ID)
+                 if (lex_token (lexer) != T_ID)
                    {
-                     lex_error (_("in CONTENTS subcommand"));
+                     lex_error (lexer, _("in CONTENTS subcommand"));
                      goto lossage;
                    }
 
-                 content_type = string_to_content_type (tokid,
+                 content_type = string_to_content_type (lex_tokid (lexer),
                                                         &collide_index);
                  if (content_type == -1)
                    {
-                     lex_error (_("in CONTENTS subcommand"));
+                     lex_error (lexer, _("in CONTENTS subcommand"));
                      goto lossage;
                    }
-                 lex_get ();
+                 lex_get (lexer);
 
                  if (collide & (1 << collide_index))
                    {
@@ -512,7 +515,7 @@ cmd_matrix_data (void)
                }
              mx->contents[mx->n_contents++] = item;
 
-             if (token == '/' || token == '.')
+             if (lex_token (lexer) == '/' || lex_token (lexer) == '.')
                break;
            }
 
@@ -525,14 +528,14 @@ cmd_matrix_data (void)
        }
       else 
        {
-         lex_error (NULL);
+         lex_error (lexer, NULL);
          goto lossage;
        }
     }
   
-  if (token != '.')
+  if (lex_token (lexer) != '.')
     {
-      lex_error (_("expecting end of command"));
+      lex_error (lexer, _("expecting end of command"));
       goto lossage;
     }
   
@@ -568,7 +571,7 @@ cmd_matrix_data (void)
     }
       
   /* Create VARNAME_. */
-  mx->varname_ = dict_create_var_assert (default_dict, "VARNAME_", 8);
+  mx->varname_ = dict_create_var_assert (dataset_dict (ds), "VARNAME_", 8);
   attach_mxd_aux (mx->varname_, MXD_VARNAME, 0);
   
   /* Sort the dictionary variables into the desired order for the
@@ -577,9 +580,9 @@ cmd_matrix_data (void)
     struct variable **v;
     size_t nv;
 
-    dict_get_vars (default_dict, &v, &nv, 0);
+    dict_get_vars (dataset_dict (ds), &v, &nv, 0);
     qsort (v, nv, sizeof *v, compare_variables_by_mxd_var_type);
-    dict_reorder_vars (default_dict, v, nv);
+    dict_reorder_vars (dataset_dict (ds), v, nv);
     free (v);
   }
 
@@ -597,14 +600,14 @@ cmd_matrix_data (void)
     int i;
 
     mx->first_continuous = -1;
-    for (i = 0; i < dict_get_var_cnt (default_dict); i++)
+    for (i = 0; i < dict_get_var_cnt (dataset_dict (ds)); i++)
       {
-       struct variable *v = dict_get_var (default_dict, i);
-        struct mxd_var *mv = v->aux;
+       struct variable *v = dict_get_var (dataset_dict (ds), i);
+        struct mxd_var *mv = var_get_aux (v);
        int type = mv->var_type;
        
        assert (type >= 0 && type < MXD_COUNT);
-       v->print = v->write = fmt_tab[type];
+        var_set_both_formats (v, &fmt_tab[type]);
 
        if (type == MXD_CONTINUOUS)
          mx->n_continuous++;
@@ -619,14 +622,14 @@ cmd_matrix_data (void)
       goto lossage;
     }
 
-  mx->reader = dfm_open_reader (fh);
+  mx->reader = dfm_open_reader (fh, lexer);
   if (mx->reader == NULL)
     goto lossage;
 
   if (mx->explicit_rowtype)
-    ok = read_matrices_with_rowtype (mx);
+    ok = read_matrices_with_rowtype (ds, mx);
   else
-    ok = read_matrices_without_rowtype (mx);
+    ok = read_matrices_without_rowtype (ds, mx);
 
   dfm_close_reader (mx->reader);
 
@@ -635,7 +638,7 @@ cmd_matrix_data (void)
   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
 
 lossage:
-  discard_variables ();
+  discard_variables (ds);
   free (mx->factors);
   pool_destroy (mx->container);
   return CMD_CASCADING_FAILURE;
@@ -647,7 +650,7 @@ lossage:
    as a bit-index) which can be used for determining whether a related
    statistic has already been used. */
 static int
-string_to_content_type (char *s, int *collide)
+string_to_content_type (const char *s, int *collide)
 {
   static const struct
     {
@@ -693,8 +696,8 @@ compare_variables_by_mxd_var_type (const void *a_, const void *b_)
 {
   struct variable *const *pa = a_;
   struct variable *const *pb = b_;
-  const struct mxd_var *a = (*pa)->aux;
-  const struct mxd_var *b = (*pb)->aux;
+  const struct mxd_var *a = var_get_aux (*pa);
+  const struct mxd_var *b = var_get_aux (*pb);
   
   if (a->var_type != b->var_type)
     return a->var_type > b->var_type ? 1 : -1;
@@ -709,7 +712,7 @@ attach_mxd_aux (struct variable *v, int var_type, int sub_type)
 {
   struct mxd_var *mv;
   
-  assert (v->aux == NULL);
+  assert (var_get_aux (v) == NULL);
   mv = xmalloc (sizeof *mv);
   mv->var_type = var_type;
   mv->sub_type = sub_type;
@@ -751,7 +754,7 @@ mdump_token (const struct matrix_token *token)
       printf (" '%.*s'", token->length, token->string);
       break;
     default:
-      assert (0);
+      NOT_REACHED ();
     }
   fflush (stdout);
 }
@@ -769,138 +772,107 @@ mget_token_dump (struct matrix_token *token, struct dfm_reader *reader)
 static const char *
 context (struct dfm_reader *reader)
 {
-  static char buf[32];
+  static struct string buf = DS_EMPTY_INITIALIZER;
 
+  ds_clear (&buf);
   if (dfm_eof (reader))
-    strcpy (buf, "at end of file");
+    ds_assign_cstr (&buf, "at end of file");
   else 
     {
-      struct fixed_string line;
-      const char *sp;
+      struct substring p;
       
-      dfm_get_record (reader, &line);
-      sp = ls_c_str (&line);
-      while (sp < ls_end (&line) && isspace ((unsigned char) *sp))
-        sp++;
-      if (sp >= ls_end (&line))
-        strcpy (buf, "at end of line");
+      p = dfm_get_record (reader);
+      ss_ltrim (&p, ss_cstr (CC_SPACES));
+      if (ss_is_empty (p))
+        ds_assign_cstr (&buf, "at end of line");
       else
-        {
-          char *dp;
-          size_t copy_cnt = 0;
-
-          dp = stpcpy (buf, "before `");
-          while (sp < ls_end (&line) && !isspace ((unsigned char) *sp)
-                 && copy_cnt < 10) 
-            {
-              *dp++ = *sp++;
-              copy_cnt++; 
-            }
-          strcpy (dp, "'");
-        }
+        ds_put_format (&buf, "before `%.*s'",
+                       (int) ss_cspan (p, ss_cstr (CC_SPACES)), ss_data (p));
     }
   
-  return buf;
+  return ds_cstr (&buf);
 }
 
 /* Is there at least one token left in the data file? */
-static int
+static bool
 another_token (struct dfm_reader *reader)
 {
   for (;;)
     {
-      struct fixed_string line;
-      const char *cp;
+      struct substring p;
+      size_t space_cnt;
       
       if (dfm_eof (reader))
-        return 0;
-      dfm_get_record (reader, &line);
-
-      cp = ls_c_str (&line);
-      while (isspace ((unsigned char) *cp) && cp < ls_end (&line))
-       cp++;
+        return false;
 
-      if (cp < ls_end (&line)) 
+      p = dfm_get_record (reader);
+      space_cnt = ss_span (p, ss_cstr (CC_SPACES));
+      if (space_cnt < ss_length (p)) 
         {
-          dfm_forward_columns (reader, cp - ls_c_str (&line));
-          return 1;
+          dfm_forward_columns (reader, space_cnt);
+          return true;
         }
 
       dfm_forward_record (reader);
     }
+  NOT_REACHED();
 }
 
 /* Parse a MATRIX DATA token from READER into TOKEN. */
 static int
 (mget_token) (struct matrix_token *token, struct dfm_reader *reader)
 {
-  struct fixed_string line;
-  int first_column;
-  char *cp;
+  struct substring line, p;
+  struct substring s;
+  int c;
 
   if (!another_token (reader))
     return 0;
 
-  dfm_get_record (reader, &line);
-  first_column = dfm_column_start (reader);
+  line = p = dfm_get_record (reader);
 
   /* Three types of fields: quoted with ', quoted with ", unquoted. */
-  cp = ls_c_str (&line);
-  if (*cp == '\'' || *cp == '"')
+  c = ss_first (p);
+  if (c == '\'' || c == '"')
     {
-      int quote = *cp;
-
-      token->type = MSTR;
-      token->string = ++cp;
-      while (cp < ls_end (&line) && *cp != quote)
-       cp++;
-      token->length = cp - token->string;
-      if (cp < ls_end (&line))
-       cp++;
-      else
-       msg (SW, _("Scope of string exceeds line."));
+      ss_get_char (&p);
+      if (!ss_get_until (&p, c, &s))
+        msg (SW, _("Scope of string exceeds line."));
     }
   else
     {
-      int is_num = isdigit ((unsigned char) *cp) || *cp == '.';
-
-      token->string = cp++;
-      while (cp < ls_end (&line)
-             && !isspace ((unsigned char) *cp) && *cp != ','
-            && *cp != '-' && *cp != '+')
-       {
-         if (isdigit ((unsigned char) *cp))
-           is_num = 1;
-         
-         if ((tolower ((unsigned char) *cp) == 'd'
-              || tolower ((unsigned char) *cp) == 'e')
-             && (cp[1] == '+' || cp[1] == '-'))
-           cp += 2;
-         else
-           cp++;
-       }
+      bool is_num = isdigit (c) || c == '.';
+      const char *start = ss_data (p);
       
-      token->length = cp - token->string;
-      assert (token->length);
-
-      if (is_num)
-       {
-         struct data_in di;
+      for (;;) 
+        {
+          c = ss_first (p);
+          if (strchr (CC_SPACES ",-+", c) != NULL)
+            break;
 
-         di.s = token->string;
-         di.e = token->string + token->length;
-         di.v = (union value *) &token->number;
-         di.f1 = first_column;
-         di.format = make_output_format (FMT_F, token->length, 0);
+          if (isdigit (c))
+            is_num = true;
+          if (strchr ("deDE", c) && strchr ("+-", ss_at (p, 1)))
+            {
+              is_num = true;
+              ss_advance (&p, 2);
+            }
+          else
+            ss_advance (&p, 1);
+        }
+      s = ss_buffer (start, ss_data (p) - start);
 
-         if (!data_in (&di))
-           return 0;
-       }
+      if (is_num)
+        data_in (s, FMT_F, 0,
+                 dfm_get_column (reader, ss_data (s)),
+                 (union value *) &token->number, 0);
       else
        token->type = MSTR;
     }
-
-  dfm_forward_columns (reader, cp - ls_c_str (&line));
+  token->string = ss_data (s);
+  token->length = ss_length (s);
+  
+  dfm_reread_record (reader, dfm_get_column (reader, ss_end (s)));
     
   return 1;
 }
@@ -910,18 +882,13 @@ static int
 static int
 force_eol (struct dfm_reader *reader, const char *content)
 {
-  struct fixed_string line;
-  const char *cp;
+  struct substring p;
 
   if (dfm_eof (reader))
     return 0;
-  dfm_get_record (reader, &line);
 
-  cp = ls_c_str (&line);
-  while (isspace ((unsigned char) *cp) && cp < ls_end (&line))
-    cp++;
-  
-  if (cp < ls_end (&line))
+  p = dfm_get_record (reader);
+  if (ss_span (p, ss_cstr (CC_SPACES)) != ss_length (p))
     {
       msg (SE, _("End of line expected %s while reading %s."),
           context (reader), content);
@@ -936,6 +903,7 @@ force_eol (struct dfm_reader *reader, const char *content)
 
 struct nr_aux_data 
   {
+    const struct dictionary *dict; /* The dictionary */
     struct matrix_data_pgm *mx; /* MATRIX DATA program. */
     double ***data;             /* MATRIX DATA data. */
     double *factor_values;      /* Factor values. */
@@ -944,8 +912,8 @@ struct nr_aux_data
     double *split_values;       /* SPLIT FILE variable values. */
   };
 
-static int nr_read_splits (struct nr_aux_data *, int compare);
-static int nr_read_factors (struct nr_aux_data *, int cell);
+static bool nr_read_splits (struct nr_aux_data *, int compare);
+static bool nr_read_factors (struct nr_aux_data *, int cell);
 static bool nr_output_data (struct nr_aux_data *, struct ccase *,
                             write_case_func *, write_case_data);
 static bool matrix_data_read_without_rowtype (struct case_source *source,
@@ -956,7 +924,7 @@ static bool matrix_data_read_without_rowtype (struct case_source *source,
 /* Read from the data file and write it to the active file.
    Returns true if successful, false if an I/O error occurred. */
 static bool
-read_matrices_without_rowtype (struct matrix_data_pgm *mx)
+read_matrices_without_rowtype (struct dataset *ds, struct matrix_data_pgm *mx)
 {
   struct nr_aux_data nr;
   bool ok;
@@ -965,17 +933,18 @@ read_matrices_without_rowtype (struct matrix_data_pgm *mx)
     mx->cells = 1;
 
   nr.mx = mx;
+  nr.dict = dataset_dict (ds);
   nr.data = NULL;
   nr.factor_values = xnmalloc (mx->n_factors * mx->cells,
                                sizeof *nr.factor_values);
   nr.max_cell_idx = 0;
-  nr.split_values = xnmalloc (dict_get_split_cnt (default_dict),
+  nr.split_values = xnmalloc (dict_get_split_cnt (dataset_dict (ds)),
                               sizeof *nr.split_values);
 
-  proc_set_source (create_case_source (
+  proc_set_source (ds, create_case_source (
                      &matrix_data_without_rowtype_source_class, &nr));
   
-  ok = procedure (NULL, NULL);
+  ok = procedure (ds, NULL, NULL);
 
   free (nr.split_values);
   free (nr.factor_values);
@@ -1092,16 +1061,14 @@ nr_read_data_lines (struct nr_aux_data *nr,
              n_cols = mx->n_continuous;
              break;
            default:
-             assert (0);
-              abort ();
+              NOT_REACHED ();
            }
          break;
        case 2:
          n_cols = 1;
          break;
        default:
-         assert (0);
-          abort ();
+          NOT_REACHED ();
        }
 
       {
@@ -1115,7 +1082,7 @@ nr_read_data_lines (struct nr_aux_data *nr,
            if (token.type != MNUM)
              {
                msg (SE, _("expecting value for %s %s"),
-                    dict_get_var (default_dict, j)->name,
+                    var_get_name (dict_get_var (nr->dict, j)),
                      context (mx->reader));
                return 0;
              }
@@ -1232,16 +1199,16 @@ matrix_data_read_without_rowtype (struct case_source *source,
       if (!nr_output_data (nr, c, write_case, wc_data))
         return false;
 
-      if (dict_get_split_cnt (default_dict) == 0
+      if (dict_get_split_cnt (nr->dict) == 0
           || !another_token (mx->reader))
        return true;
     }
 }
 
 /* Read the split file variables.  If COMPARE is 1, compares the
-   values read to the last values read and returns 1 if they're equal,
-   0 otherwise. */
-static int
+   values read to the last values read and returns true if they're equal,
+   false otherwise. */
+static bool
 nr_read_splits (struct nr_aux_data *nr, int compare)
 {
   struct matrix_data_pgm *mx = nr->mx;
@@ -1252,36 +1219,36 @@ nr_read_splits (struct nr_aux_data *nr, int compare)
   if (compare && just_read)
     {
       just_read = 0;
-      return 1;
+      return true;
     }
   
-  if (dict_get_split_vars (default_dict) == NULL)
-    return 1;
+  if (dict_get_split_vars (nr->dict) == NULL)
+    return true;
 
   if (mx->single_split)
     {
       if (!compare) 
         {
-          struct mxd_var *mv = dict_get_split_vars (default_dict)[0]->aux;
+          struct mxd_var *mv = var_get_aux (dict_get_split_vars (nr->dict)[0]);
           nr->split_values[0] = ++mv->sub_type; 
         }
-      return 1;
+      return true;
     }
 
   if (!compare)
     just_read = 1;
 
-  split_cnt = dict_get_split_cnt (default_dict);
+  split_cnt = dict_get_split_cnt (nr->dict);
   for (i = 0; i < split_cnt; i++) 
     {
       struct matrix_token token;
       if (!mget_token (&token, mx->reader))
-        return 0;
+        return false;
       if (token.type != MNUM)
         {
           msg (SE, _("Syntax error expecting SPLIT FILE value %s."),
                context (mx->reader));
-          return 0;
+          return false;
         }
 
       if (!compare)
@@ -1290,32 +1257,32 @@ nr_read_splits (struct nr_aux_data *nr, int compare)
         {
           msg (SE, _("Expecting value %g for %s."),
                nr->split_values[i],
-               dict_get_split_vars (default_dict)[i]->name);
-          return 0;
+               var_get_name (dict_get_split_vars (nr->dict)[i]));
+          return false;
         }
     }
 
-  return 1;
+  return true;
 }
 
 /* Read the factors for cell CELL.  If COMPARE is 1, compares the
-   values read to the last values read and returns 1 if they're equal,
-   0 otherwise. */
-static int
+   values read to the last values read and returns true if they're equal,
+   false otherwise. */
+static bool
 nr_read_factors (struct nr_aux_data *nr, int cell)
 {
   struct matrix_data_pgm *mx = nr->mx;
-  int compare;
+  bool compare;
   
   if (mx->n_factors == 0)
-    return 1;
+    return true;
 
   assert (nr->max_cell_idx >= cell);
   if (cell != nr->max_cell_idx)
-    compare = 1;
+    compare = true;
   else
     {
-      compare = 0;
+      compare = false;
       nr->max_cell_idx++;
     }
       
@@ -1326,12 +1293,12 @@ nr_read_factors (struct nr_aux_data *nr, int cell)
       {
         struct matrix_token token;
        if (!mget_token (&token, mx->reader))
-         return 0;
+         return false;
        if (token.type != MNUM)
          {
            msg (SE, _("Syntax error expecting factor value %s."),
                 context (mx->reader));
-           return 0;
+           return false;
          }
        
        if (!compare)
@@ -1340,31 +1307,32 @@ nr_read_factors (struct nr_aux_data *nr, int cell)
          {
            msg (SE, _("Syntax error expecting value %g for %s %s."),
                 nr->factor_values[i + mx->n_factors * cell],
-                mx->factors[i]->name, context (mx->reader));
-           return 0;
+                var_get_name (mx->factors[i]), context (mx->reader));
+           return false;
          }
       }
   }
 
-  return 1;
+  return true;
 }
 
 /* Write the contents of a cell having content type CONTENT and data
    CP to the active file.
    Returns true if successful, false if an I/O error occurred. */
 static bool
-dump_cell_content (struct matrix_data_pgm *mx, int content, double *cp,
+dump_cell_content (const struct dictionary *dict, 
+                  struct matrix_data_pgm *mx, int content, double *cp,
                    struct ccase *c,
                    write_case_func *write_case, write_case_data wc_data)
 {
   int type = content_type[content];
 
   {
-    buf_copy_str_rpad (case_data_rw (c, mx->rowtype_->fv)->s, 8,
+    buf_copy_str_rpad (case_data_rw (c, mx->rowtype_)->s, 8,
                        content_names[content]);
     
     if (type != 1)
-      memset (case_data_rw (c, mx->varname_->fv)->s, ' ', 8);
+      memset (case_data_rw (c, mx->varname_)->s, ' ', 8);
   }
 
   {
@@ -1377,14 +1345,14 @@ dump_cell_content (struct matrix_data_pgm *mx, int content, double *cp,
 
        for (j = 0; j < mx->n_continuous; j++)
          {
-            int fv = dict_get_var (default_dict, mx->first_continuous + j)->fv;
-            case_data_rw (c, fv)->f = *cp;
+            struct variable *v = dict_get_var (dict, mx->first_continuous + j);
+            case_data_rw (c, v)->f = *cp;
            cp++;
          }
        if (type == 1)
-         buf_copy_str_rpad (case_data_rw (c, mx->varname_->fv)->s, 8,
-                             dict_get_var (default_dict,
-                                           mx->first_continuous + i)->name);
+         buf_copy_str_rpad (case_data_rw (c, mx->varname_)->s, 8,
+                             var_get_name (
+                               dict_get_var (dict, mx->first_continuous + i)));
        if (!write_case (wc_data))
           return false;
       }
@@ -1404,10 +1372,10 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c,
     size_t split_cnt;
     size_t i;
 
-    split_cnt = dict_get_split_cnt (default_dict);
-    split = dict_get_split_vars (default_dict);
+    split_cnt = dict_get_split_cnt (nr->dict);
+    split = dict_get_split_vars (nr->dict);
     for (i = 0; i < split_cnt; i++)
-      case_data_rw (c, split[i]->fv)->f = nr->split_values[i];
+      case_data_rw (c, split[i])->f = nr->split_values[i];
   }
 
   if (mx->n_factors)
@@ -1420,7 +1388,7 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c,
            size_t factor;
 
            for (factor = 0; factor < mx->n_factors; factor++)
-              case_data_rw (c, mx->factors[factor]->fv)->f
+              case_data_rw (c, mx->factors[factor])->f
                 = nr->factor_values[factor + cell * mx->n_factors];
          }
          
@@ -1433,7 +1401,8 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c,
                  assert (nr->data[content] != NULL
                          && nr->data[content][cell] != NULL);
 
-                 if (!dump_cell_content (mx, content, nr->data[content][cell],
+                 if (!dump_cell_content (nr->dict, mx, 
+                                         content, nr->data[content][cell],
                                           c, write_case, wc_data))
                     return false;
                }
@@ -1448,13 +1417,13 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c,
       size_t factor;
 
       for (factor = 0; factor < mx->n_factors; factor++)
-       case_data_rw (c, mx->factors[factor]->fv)->f = SYSMIS;
+       case_data_rw (c, mx->factors[factor])->f = SYSMIS;
     }
     
     for (content = 0; content <= PROX; content++)
       if (!mx->is_per_factor[content] && nr->data[content] != NULL) 
         {
-          if (!dump_cell_content (mx, content, nr->data[content][0],
+          if (!dump_cell_content (nr->dict, mx, content, nr->data[content][0],
                                   c, write_case, wc_data))
             return false; 
         }
@@ -1477,6 +1446,7 @@ struct factor_data
 /* With ROWTYPE_ auxiliary data. */
 struct wr_aux_data 
   {
+    const struct dictionary *dict;            /* The dictionary */
     struct matrix_data_pgm *mx;         /* MATRIX DATA program. */
     int content;                        /* Type of current row. */
     double *split_values;               /* SPLIT FILE variable values. */
@@ -1484,14 +1454,14 @@ struct wr_aux_data
     struct factor_data *current;        /* Current factor. */
   };
 
-static int wr_read_splits (struct wr_aux_data *, struct ccase *,
+static bool wr_read_splits (struct wr_aux_data *, struct ccase *,
                            write_case_func *, write_case_data);
 static bool wr_output_data (struct wr_aux_data *, struct ccase *,
                            write_case_func *, write_case_data);
-static int wr_read_rowtype (struct wr_aux_data *, 
+static bool wr_read_rowtype (struct wr_aux_data *, 
                             const struct matrix_token *, struct dfm_reader *);
-static int wr_read_factors (struct wr_aux_data *);
-static int wr_read_indeps (struct wr_aux_data *);
+static bool wr_read_factors (struct wr_aux_data *);
+static bool wr_read_indeps (struct wr_aux_data *);
 static bool matrix_data_read_with_rowtype (struct case_source *,
                                            struct ccase *,
                                            write_case_func *,
@@ -1501,7 +1471,7 @@ static bool matrix_data_read_with_rowtype (struct case_source *,
    them to the output file.
    Returns true if successful, false if an I/O error occurred. */
 static bool
-read_matrices_with_rowtype (struct matrix_data_pgm *mx)
+read_matrices_with_rowtype (struct dataset *ds, struct matrix_data_pgm *mx)
 {
   struct wr_aux_data wr;
   bool ok;
@@ -1511,11 +1481,13 @@ read_matrices_with_rowtype (struct matrix_data_pgm *mx)
   wr.split_values = NULL;
   wr.data = NULL;
   wr.current = NULL;
+  wr.dict = dataset_dict (ds);
   mx->cells = 0;
 
-  proc_set_source (create_case_source (&matrix_data_with_rowtype_source_class,
+  proc_set_source (ds, 
+                  create_case_source (&matrix_data_with_rowtype_source_class,
                                        &wr));
-  ok = procedure (NULL, NULL);
+  ok = procedure (ds, NULL, NULL);
 
   free (wr.split_values);
   return ok;
@@ -1550,60 +1522,60 @@ matrix_data_read_with_rowtype (struct case_source *source,
 
 /* Read the split file variables.  If they differ from the previous
    set of split variables then output the data.  Returns success. */
-static int 
+static bool 
 wr_read_splits (struct wr_aux_data *wr,
                 struct ccase *c,
                 write_case_func *write_case, write_case_data wc_data)
 {
   struct matrix_data_pgm *mx = wr->mx;
-  int compare;
+  bool compare;
   size_t split_cnt;
 
-  split_cnt = dict_get_split_cnt (default_dict);
+  split_cnt = dict_get_split_cnt (wr->dict);
   if (split_cnt == 0)
-    return 1;
+    return true;
 
   if (wr->split_values)
-    compare = 1;
+    compare = true;
   else
     {
-      compare = 0;
+      compare = false;
       wr->split_values = xnmalloc (split_cnt, sizeof *wr->split_values);
     }
   
   {
-    int different = 0;
+    bool different = false;
     int i;
 
     for (i = 0; i < split_cnt; i++)
       {
         struct matrix_token token;
        if (!mget_token (&token, mx->reader))
-         return 0;
+         return false;
        if (token.type != MNUM)
          {
            msg (SE, _("Syntax error %s expecting SPLIT FILE value."),
                 context (mx->reader));
-           return 0;
+           return false;
          }
 
        if (compare && wr->split_values[i] != token.number && !different)
          {
            if (!wr_output_data (wr, c, write_case, wc_data))
              return 0;
-           different = 1;
+           different = true;
            mx->cells = 0;
          }
        wr->split_values[i] = token.number;
       }
   }
 
-  return 1;
+  return true;
 }
 
 /* Compares doubles A and B, treating SYSMIS as greatest. */
 static int
-compare_doubles (const void *a_, const void *b_, void *aux UNUSED)
+compare_doubles (const void *a_, const void *b_, const void *aux UNUSED)
 {
   const double *a = a_;
   const double *b = b_;
@@ -1623,9 +1595,9 @@ compare_doubles (const void *a_, const void *b_, void *aux UNUSED)
 /* Return strcmp()-type comparison of the MX->n_factors factors at _A and
    _B.  Sort missing values toward the end. */
 static int
-compare_factors (const void *a_, const void *b_, void *mx_)
+compare_factors (const void *a_, const void *b_, const void *mx_)
 {
-  struct matrix_data_pgm *mx = mx_;
+  const struct matrix_data_pgm *mx = mx_;
   struct factor_data *const *pa = a_;
   struct factor_data *const *pb = b_;
   const double *a = (*pa)->factors;
@@ -1653,10 +1625,10 @@ wr_output_data (struct wr_aux_data *wr,
     size_t split_cnt;
     size_t i;
 
-    split_cnt = dict_get_split_cnt (default_dict);
-    split = dict_get_split_vars (default_dict);
+    split_cnt = dict_get_split_cnt (wr->dict);
+    split = dict_get_split_vars (wr->dict);
     for (i = 0; i < split_cnt; i++)
-      case_data_rw (c, split[i]->fv)->f = wr->split_values[i];
+      case_data_rw (c, split[i])->f = wr->split_values[i];
   }
 
   /* Sort the wr->data list. */
@@ -1690,8 +1662,7 @@ wr_output_data (struct wr_aux_data *wr,
          size_t factor;
 
          for (factor = 0; factor < mx->n_factors; factor++)
-            case_data_rw (c, mx->factors[factor]->fv)->f
-              = iter->factors[factor];
+            case_data_rw (c, mx->factors[factor])->f = iter->factors[factor];
        }
        
        {
@@ -1722,7 +1693,8 @@ wr_output_data (struct wr_aux_data *wr,
 
              fill_matrix (mx, content, iter->data[content]);
 
-             ok = dump_cell_content (mx, content, iter->data[content],
+             ok = dump_cell_content (wr->dict, mx, content, 
+                                     iter->data[content],
                                       c, write_case, wc_data);
               if (!ok)
                 break;
@@ -1741,7 +1713,7 @@ wr_output_data (struct wr_aux_data *wr,
 
 /* Sets ROWTYPE_ based on the given TOKEN read from READER.
    Return success. */
-static int 
+static bool 
 wr_read_rowtype (struct wr_aux_data *wr,
                  const struct matrix_token *token,
                  struct dfm_reader *reader)
@@ -1749,21 +1721,21 @@ wr_read_rowtype (struct wr_aux_data *wr,
   if (wr->content != -1)
     {
       msg (SE, _("Multiply specified ROWTYPE_ %s."), context (reader));
-      return 0;
+      return false;
     }
   if (token->type != MSTR)
     {
       msg (SE, _("Syntax error %s expecting ROWTYPE_ string."),
            context (reader));
-      return 0;
+      return false;
     }
   
   {
     char s[16];
     char *cp;
     
-    memcpy (s, token->string, min (15, token->length));
-    s[min (15, token->length)] = 0;
+    memcpy (s, token->string, MIN (15, token->length));
+    s[MIN (15, token->length)] = 0;
 
     for (cp = s; *cp; cp++)
       *cp = toupper ((unsigned char) *cp);
@@ -1777,12 +1749,12 @@ wr_read_rowtype (struct wr_aux_data *wr,
       return 0;
     }
 
-  return 1;
+  return true;
 }
 
 /* Read the factors for the current row.  Select a set of factors and
    point wr_current to it. */
-static int 
+static bool 
 wr_read_factors (struct wr_aux_data *wr)
 {
   struct matrix_data_pgm *mx = wr->mx;
@@ -1886,15 +1858,15 @@ cache_miss:
 
 winnage:
   local_free (factor_values);
-  return 1;
+  return true;
 
 lossage:
   local_free (factor_values);
-  return 0;
+  return false;
 }
 
 /* Read the independent variables into wr->current. */
-static int 
+static bool 
 wr_read_indeps (struct wr_aux_data *wr)
 {
   struct matrix_data_pgm *mx = wr->mx;
@@ -1926,7 +1898,7 @@ wr_read_indeps (struct wr_aux_data *wr)
        {
          msg (SE, _("Duplicate specification for %s."),
               content_names[wr->content]);
-         return 0;
+         return false;
        }
       if (type == 0)
        n_cols = mx->n_continuous;
@@ -1938,7 +1910,7 @@ wr_read_indeps (struct wr_aux_data *wr)
        {
          msg (SE, _("Too many rows of matrix data for %s."),
               content_names[wr->content]);
-         return 0;
+         return false;
        }
       
       switch (mx->section)
@@ -1961,13 +1933,11 @@ wr_read_indeps (struct wr_aux_data *wr)
          n_cols = mx->n_continuous;
          break;
        default:
-         assert (0);
-          abort ();
+          NOT_REACHED ();
        }
       break;
     default:
-      assert (0);
-      abort ();
+      NOT_REACHED ();
     }
   c->n_rows[wr->content]++;
 
@@ -1979,23 +1949,24 @@ wr_read_indeps (struct wr_aux_data *wr)
       {
         struct matrix_token token;
        if (!mget_token (&token, mx->reader))
-         return 0;
+         return false;
        if (token.type != MNUM)
          {
            msg (SE, _("Syntax error expecting value for %s %s."),
-                 dict_get_var (default_dict, mx->first_continuous + j)->name,
+                 var_get_name (dict_get_var (wr->dict,
+                                             mx->first_continuous + j)),
                  context (mx->reader));
-           return 0;
+           return false;
          }
 
        *cp++ = token.number;
       }
     if (mx->fmt != FREE
         && !force_eol (mx->reader, content_names[wr->content]))
-      return 0;
+      return false;
   }
 
-  return 1;
+  return true;
 }
 \f
 /* Matrix source. */