Make the expression code a little nicer and fix bugs found
[pspp-builds.git] / src / sfm-write.c
index e0aeb44441abe8bea32186d6a8b97d2ea360f52a..cb6bfa54a7a37536caa94c459bac7be4ea6f2d43 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA. */
 
-/* AIX requires this to be the first thing in the file.  */
 #include <config.h>
-#if __GNUC__
-#define alloca __builtin_alloca
-#else
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else
-#ifdef _AIX
-#pragma alloca
-#else
-#ifndef alloca                 /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#endif
-#endif
-#endif
-#endif
-
-#include <assert.h>
+#include "sfm.h"
+#include "sfmP.h"
+#include "error.h"
 #include <stdlib.h>
 #include <ctype.h>
 #include <errno.h>
@@ -44,21 +29,17 @@ char *alloca ();
 #include <unistd.h>    /* Required by SunOS4. */
 #endif
 #include "alloc.h"
-#include "approx.h"
-#include "avl.h"
 #include "error.h"
 #include "file-handle.h"
 #include "getline.h"
+#include "hash.h"
 #include "magic.h"
 #include "misc.h"
-#include "sfm.h"
-#include "sfmP.h"
 #include "str.h"
+#include "value-labels.h"
 #include "var.h"
 #include "version.h"
 
-#undef DEBUGGING
-/*#define DEBUGGING 1 */
 #include "debug-print.h"
 
 /* PORTME: This file may require substantial revision for those
@@ -111,23 +92,25 @@ sfm_write_dictionary (struct sfm_write_info *inf)
 
   if (inf->h->class != NULL)
     {
-      msg (ME, _("Cannot write file %s as system file: already opened for %s."),
-          fh_handle_name (inf->h), inf->h->class->name);
+      msg (ME, _("Cannot write file %s as system file: "
+                 "already opened for %s."),
+          handle_get_name (inf->h), inf->h->class->name);
       return 0;
     }
 
   msg (VM (1), _("%s: Opening system-file handle %s for writing."),
-       fh_handle_filename (inf->h), fh_handle_name (inf->h));
+       handle_get_filename (inf->h), handle_get_name (inf->h));
   
   /* Open the physical disk file. */
   inf->h->class = &sfm_w_class;
   inf->h->ext = ext = xmalloc (sizeof (struct sfm_fhuser_ext));
-  ext->file = fopen (inf->h->norm_fn, "wb");
+  ext->file = fopen (handle_get_filename (inf->h), "wb");
   ext->elem_type = NULL;
   if (ext->file == NULL)
     {
       msg (ME, _("An error occurred while opening \"%s\" for writing "
-          "as a system file: %s."), inf->h->fn, strerror (errno));
+                 "as a system file: %s."),
+           handle_get_filename (inf->h), strerror (errno));
       err_cond_fail ();
       free (ext);
       return 0;
@@ -144,13 +127,13 @@ sfm_write_dictionary (struct sfm_write_info *inf)
     goto lossage;
 
   /* Write basic variable info. */
-  for (i = 0; i < d->nvar; i++)
-    write_variable (inf, d->var[i]);
+  for (i = 0; i < dict_get_var_cnt (d); i++)
+    write_variable (inf, dict_get_var (d, i));
 
   /* Write out value labels. */
-  for (index = i = 0; i < d->nvar; i++)
+  for (index = i = 0; i < dict_get_var_cnt (d); i++)
     {
-      struct variable *v = d->var[i];
+      struct variable *v = dict_get_var (d, i);
 
       if (!write_value_labels (inf, v, index))
        goto lossage;
@@ -158,7 +141,7 @@ sfm_write_dictionary (struct sfm_write_info *inf)
                : DIV_RND_UP (v->width, sizeof (flt64)));
     }
 
-  if (d->documents != NULL && !write_documents (inf))
+  if (dict_get_documents (d) != NULL && !write_documents (inf))
     goto lossage;
   if (!write_rec_7_34 (inf))
     goto lossage;
@@ -228,18 +211,18 @@ write_header (struct sfm_write_info *inf)
   hdr.layout_code = 2;
 
   hdr.case_size = 0;
-  for (i = 0; i < d->nvar; i++)
+  for (i = 0; i < dict_get_var_cnt (d); i++)
     {
-      struct variable *v = d->var[i];
+      struct variable *v = dict_get_var (d, i);
       hdr.case_size += (v->type == NUMERIC ? 1
                        : DIV_RND_UP (v->width, sizeof (flt64)));
     }
   inf->case_size = hdr.case_size;
 
   p = ext->elem_type = xmalloc (inf->case_size);
-  for (i = 0; i < d->nvar; i++)
+  for (i = 0; i < dict_get_var_cnt (d); i++)
     {
-      struct variable *v = d->var[i];
+      struct variable *v = dict_get_var (d, i);
       int count = (v->type == NUMERIC ? 1
                    : DIV_RND_UP (v->width, sizeof (flt64)));
       while (count--)
@@ -248,14 +231,18 @@ write_header (struct sfm_write_info *inf)
 
   hdr.compressed = inf->compress;
 
-  update_weighting (d);
-  if (d->weight_index != -1)
+  if (dict_get_weight (d) != NULL)
     {
+      struct variable *weight_var;
       int recalc_weight_index = 1;
+      int i;
 
-      for (i = 0; i < d->weight_index; i++)
-       {
-         struct variable *v = d->var[i];
+      weight_var = dict_get_weight (d);
+      for (i = 0; ; i++) 
+        {
+         struct variable *v = dict_get_var (d, i);
+          if (v == weight_var)
+            break;
          recalc_weight_index += (v->type == NUMERIC ? 1
                                  : DIV_RND_UP (v->width, sizeof (flt64)));
        }
@@ -293,9 +280,15 @@ write_header (struct sfm_write_info *inf)
       sprintf (buf, "%02d:%02d:%02d", hour - 1, min - 1, sec - 1);
       memcpy (hdr.creation_time, buf, sizeof hdr.creation_time);
     }
+  
+  {
+    const char *label = dict_get_label (d);
+    if (label == NULL)
+      label = "";
 
-  st_bare_pad_copy (hdr.file_label, d->label ? d->label : "",
-                   sizeof hdr.file_label);
+    st_bare_pad_copy (hdr.file_label, label, sizeof hdr.file_label); 
+  }
+  
   memset (hdr.padding, 0, sizeof hdr.padding);
 
   if (!bufwrite (inf->h, &hdr, sizeof hdr))
@@ -372,6 +365,7 @@ write_variable (struct sfm_write_info *inf, struct variable *v)
       break;
     default:
       assert (0);
+      abort ();
     }
 
   sv.n_missing_values = nm;
@@ -446,35 +440,36 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index)
       int32 vars[1] P;
     };
 
-  avl_traverser i;
+  struct val_labs_iterator *i;
   struct value_label_rec *vlr;
   struct variable_index_rec vir;
-  struct value_label *vl;
+  struct val_lab *vl;
   size_t vlr_size;
   flt64 *loc;
-  avl_traverser_init (i);
 
-  if (v->val_lab == NULL || avl_count (v->val_lab) == 0)
+  if (!val_labs_count (v->val_labs))
     return 1;
 
   /* Pass 1: Count bytes. */
   vlr_size = (sizeof (struct value_label_rec)
-             + sizeof (flt64) * (avl_count (v->val_lab) - 1));
-  while (NULL != (vl = avl_traverse (v->val_lab, &i)))
-    vlr_size += ROUND_UP (strlen (vl->s) + 1, sizeof (flt64));
+             + sizeof (flt64) * (val_labs_count (v->val_labs) - 1));
+  for (vl = val_labs_first (v->val_labs, &i); vl != NULL;
+       vl = val_labs_next (v->val_labs, &i))
+    vlr_size += ROUND_UP (strlen (vl->label) + 1, sizeof (flt64));
 
   /* Pass 2: Copy bytes. */
-  vlr = local_alloc (vlr_size);
+  vlr = xmalloc (vlr_size);
   vlr->rec_type = 3;
-  vlr->n_labels = avl_count (v->val_lab);
+  vlr->n_labels = val_labs_count (v->val_labs);
   loc = vlr->labels;
-  while (NULL != (vl = avl_traverse (v->val_lab, &i)))
+  for (vl = val_labs_first_sorted (v->val_labs, &i); vl != NULL;
+       vl = val_labs_next (v->val_labs, &i))
     {
-      int len = strlen (vl->s);
+      size_t len = strlen (vl->label);
 
-      *loc++ = vl->v.f;
+      *loc++ = vl->value.f;
       *(unsigned char *) loc = len;
-      memcpy (&((unsigned char *) loc)[1], vl->s, len);
+      memcpy (&((unsigned char *) loc)[1], vl->label, len);
       memset (&((unsigned char *) loc)[1 + len], ' ',
              REM_RND_UP (len + 1, sizeof (flt64)));
       loc += DIV_RND_UP (len + 1, sizeof (flt64));
@@ -482,10 +477,10 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index)
   
   if (!bufwrite (inf->h, vlr, vlr_size))
     {
-      local_free (vlr);
+      free (vlr);
       return 0;
     }
-  local_free (vlr);
+  free (vlr);
 
   vir.rec_type = 4;
   vir.n_vars = 1;
@@ -508,11 +503,17 @@ write_documents (struct sfm_write_info * inf)
   }
   rec_6;
 
+  const char *documents;
+  size_t n_lines;
+
+  documents = dict_get_documents (d);
+  n_lines = strlen (documents) / 80;
+
   rec_6.rec_type = 6;
-  rec_6.n_lines = d->n_documents;
+  rec_6.n_lines = n_lines;
   if (!bufwrite (inf->h, &rec_6, sizeof rec_6))
     return 0;
-  if (!bufwrite (inf->h, d->documents, 80 * d->n_documents))
+  if (!bufwrite (inf->h, documents, 80 * n_lines))
     return 0;
 
   return 1;
@@ -602,7 +603,8 @@ bufwrite (struct file_handle * h, const void *buf, size_t nbytes)
   assert (buf);
   if (1 != fwrite (buf, nbytes, 1, ext->file))
     {
-      msg (ME, _("%s: Writing system file: %s."), h->fn, strerror (errno));
+      msg (ME, _("%s: Writing system file: %s."),
+           handle_get_filename (h), strerror (errno));
       return 0;
     }
   return 1;
@@ -677,13 +679,13 @@ sfm_write_case (struct file_handle * h, const flt64 *elem, int n_elem)
              *ext->x++ = 255;
               continue;
             }
-         else
+         else if (*elem > INT_MIN && *elem < INT_MAX)
            {
-             int value = *elem < 0 ? *elem - EPSILON : *elem + EPSILON;
+             int value = *elem;
 
              if (value >= 1 - COMPRESSION_BIAS
                  && value <= 251 - COMPRESSION_BIAS
-                 && approx_eq (value, *elem))
+                 && value == *elem)
                 {
                  *ext->x++ = value + COMPRESSION_BIAS;
                   continue;
@@ -738,7 +740,8 @@ sfm_close (struct file_handle * h)
     }
 
   if (EOF == fclose (ext->file))
-    msg (ME, _("%s: Closing system file: %s."), h->fn, strerror (errno));
+    msg (ME, _("%s: Closing system file: %s."),
+         handle_get_filename (h), strerror (errno));
   free (ext->buf);
 
   free (ext->elem_type);