Remove >>> conflict markers.
[pspp-builds.git] / src / sfm-read.c
index 40a366cf1e9cafa1cc408e0f6b2de035ea792eb6..23abde90ff1e57c0e14a04d11a5fdbc72a47e463 100644 (file)
@@ -14,8 +14,8 @@
 
    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 "sfm-read.h"
@@ -122,26 +122,16 @@ corrupt_msg (int class, const char *format,...)
 static void
 corrupt_msg (int class, const char *format,...)
 {
-  char buf[1024];
-  
-  {
-    va_list args;
-
-    va_start (args, format);
-    vsnprintf (buf, 1024, format, args);
-    va_end (args);
-  }
-  
-  {
-    struct error e;
+  struct error e;
+  va_list args;
 
-    e.class = class;
-    getl_location (&e.where.filename, &e.where.line_number);
-    e.title = _("corrupt system file: ");
-    e.text = buf;
+  e.class = class;
+  getl_location (&e.where.filename, &e.where.line_number);
+  e.title = _("corrupt system file: ");
 
-    err_vmsg (&e);
-  }
+  va_start (args, format);
+  err_vmsg (&e, format, args);
+  va_end (args);
 }
 
 /* Closes a system file after we're done with it. */
@@ -306,6 +296,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                int32 count P;
              }
            data;
+            unsigned long bytes;
 
            int skip = 0;
 
@@ -316,6 +307,10 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                bswap_int32 (&data.size);
                bswap_int32 (&data.count);
              }
+            bytes = data.size * data.count;
+            if (bytes < data.size || bytes < data.count)
+              lose ((ME, "%s: Record type %d subtype %d too large.",
+                     handle_get_filename (r->fh), rec_type, data.subtype));
 
            switch (data.subtype)
              {
@@ -330,10 +325,113 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                break;
 
              case 5:
-             case 6:
-             case 11: /* ?? Used by SPSS 8.0. */
+             case 6:  /* ?? Used by SPSS 8.0. */
                skip = 1;
                break;
+               
+             case 11: /* Variable display parameters */
+               {
+                 const int  n_vars = data.count / 3 ;
+                 int i;
+                 if ( data.count % 3 ) 
+                   {
+                     msg (MW, _("%s: Invalid subrecord length. "
+                                "Record: 7; Subrecord: 11"), 
+                          handle_get_filename (r->fh));
+                     skip = 1;
+                   }
+
+                 for ( i = 0 ; i < n_vars ; ++i ) 
+                   {
+                     struct
+                     {
+                       int32 measure P;
+                       int32 width P;
+                       int32 align P;
+                     }
+                     params;
+
+                     struct variable *v;
+
+                     assertive_buf_read (r, &params, sizeof(params), 0);
+
+                     v = dict_get_var(*dict, i);
+
+                     v->measure = params.measure;
+                     v->display_width = params.width;
+                     v->alignment = params.align;
+                   }
+               }
+               break;
+
+             case 13: /* SPSS 12.0 Long variable name map */
+               {
+                 char *buf, *short_name, *save_ptr;
+                  int idx;
+
+                  /* Read data. */
+                  buf = xmalloc (bytes + 1);
+                 if (!buf_read (r, buf, bytes, 0)) 
+                    {
+                      free (buf);
+                      goto error;
+                    }
+                 buf[bytes] = '\0';
+
+                  /* Parse data. */
+                 for (short_name = strtok_r (buf, "=", &save_ptr), idx = 0;
+                       short_name != NULL;
+                       short_name = strtok_r (NULL, "=", &save_ptr), idx++)
+                   {
+                      char *long_name = strtok_r (NULL, "\t", &save_ptr);
+                      struct variable *v;
+
+                      /* Validate long name. */
+                      if (long_name == NULL)
+                        {
+                          msg (MW, _("%s: Trailing garbage in long variable "
+                                     "name map."),
+                               handle_get_filename (r->fh));
+                          break;
+                        }
+                      if (!var_is_valid_name (long_name, false))
+                        {
+                          msg (MW, _("%s: Long variable mapping to invalid "
+                                     "variable name `%s'."),
+                               handle_get_filename (r->fh), long_name);
+                          break;
+                        }
+                      
+                      /* Find variable using short name. */
+                      v = dict_lookup_var (*dict, short_name);
+                      if (v == NULL)
+                        {
+                          msg (MW, _("%s: Long variable mapping for "
+                                     "nonexistent variable %s."),
+                               handle_get_filename (r->fh), short_name);
+                          break;
+                        }
+
+                      /* Set long name.
+                         Renaming a variable may clear the short
+                         name, but we want to retain it, so
+                         re-set it explicitly. */
+                      dict_rename_var (*dict, v, long_name);
+                      var_set_short_name (v, short_name);
+
+                      /* For compatability, make sure dictionary
+                         is in long variable name map order.  In
+                         the common case, this has no effect,
+                         because the dictionary and the long
+                         variable name map are already in the
+                         same order. */
+                      dict_reorder_var (*dict, v, idx);
+                   }
+
+                 /* Free data. */
+                 free (buf);
+               }
+               break;
 
              default:
                msg (MW, _("%s: Unrecognized record type 7, subtype %d "
@@ -638,6 +736,8 @@ read_variables (struct sfm_reader *r,
   int next_value = 0;          /* Index to next `value' structure. */
   size_t var_cap = 0;
 
+  assert(r);
+
   /* Allocate variables. */
   *var_by_idx = xmalloc (sizeof **var_by_idx * r->value_cnt);
 
@@ -716,7 +816,7 @@ read_variables (struct sfm_reader *r,
       name[0] = toupper ((unsigned char) (sv.name[0]));
 
       /* Copy remaining characters of variable name. */
-      for (j = 1; j < 8; j++)
+      for (j = 1; j < SHORT_NAME_LEN; j++)
        {
          int c = (unsigned char) sv.name[j];
 
@@ -744,6 +844,7 @@ read_variables (struct sfm_reader *r,
       if (vv == NULL) 
         lose ((ME, _("%s: Duplicate variable name `%s' within system file."),
                handle_get_filename (r->fh), name));
+      var_set_short_name (vv, vv->name);
 
       /* Case reading data. */
       nv = sv.type == 0 ? 1 : DIV_RND_UP (sv.type, sizeof (flt64));
@@ -767,11 +868,14 @@ read_variables (struct sfm_reader *r,
                          "length %d."),
                    handle_get_filename (r->fh), vv->name, len));
 
-         /* Read label into variable structure. */
-         vv->label = buf_read (r, NULL, ROUND_UP (len, sizeof (int32)), len + 1);
-         if (vv->label == NULL)
-           goto error;
-         vv->label[len] = '\0';
+         if ( len != 0 ) 
+           {
+             /* Read label into variable structure. */
+             vv->label = buf_read (r, NULL, ROUND_UP (len, sizeof (int32)), len + 1);
+             if (vv->label == NULL)
+               goto error;
+             vv->label[len] = '\0';
+           }
        }
 
       /* Set missing values. */
@@ -1089,8 +1193,15 @@ error:
 static void *
 buf_read (struct sfm_reader *r, void *buf, size_t byte_cnt, size_t min_alloc)
 {
-  if (buf == NULL)
+  assert (r);
+
+  if (buf == NULL && byte_cnt > 0 )
     buf = xmalloc (max (byte_cnt, min_alloc));
+
+  if ( byte_cnt == 0 )
+    return buf;
+
+  
   if (1 != fread (buf, byte_cnt, 1, r->file))
     {
       if (ferror (r->file))