Add an Emacs header line to output files that makes generated .c files
authorBen Pfaff <blp@gnu.org>
Tue, 17 Feb 2004 06:19:35 +0000 (06:19 +0000)
committerBen Pfaff <blp@gnu.org>
Tue, 17 Feb 2004 06:19:35 +0000 (06:19 +0000)
read-only by default, to make it difficult to accidentally change
generated files.

FREQUENCIES: Compare by frequency, not bogus a->v.c <=> b->v.c pointer
compare.

Changed data_out() to store string data directly into a `union
value''s s member, not indirectly into c.

Renamed some confusingly named member objects in crosstabs.q.

16 files changed:
src/ChangeLog
src/crosstabs.q
src/data-in.h
src/data-list.c
src/data-out.c
src/expr-evl.c
src/expr-opt.c
src/format.h
src/frequencies.q
src/list.q
src/print.c
src/q2c.c
src/tab.c
src/var.h
src/vars-atr.c
src/vfm.c

index e7dba3586b75669f6697a49b8e5a0ba87fe16e60..3df622789a19183a84a258af6d749fb8cc332407 100644 (file)
@@ -1,3 +1,75 @@
+Mon Feb 16 22:14:36 2004  Ben Pfaff  <blp@gnu.org>
+
+       * q2c.c: (dump_header) Add an Emacs header line to output files
+       that makes generated .c files read-only by default, to make it
+       difficult to accidentally change generated files.
+
+Mon Feb 16 22:12:07 2004  Ben Pfaff  <blp@gnu.org>
+
+       * frequencies.q: (compare_freq_numeric_a) Compare by frequency,
+       not bogus a->v.c <=> b->v.c pointer compare.
+       (compare_freq_alpha_a) Ditto.
+       (compare_freq_numeric_d) Ditto.
+       (compare_freq_alpha_d) Ditto.
+       
+Mon Feb 16 22:00:53 2004  Ben Pfaff  <blp@gnu.org>
+
+       Changed data_out() to store string data directly into a `union
+       value''s s member, not indirectly into c.
+
+       * crosstabs.q: (output_pivot_table) Use format_short() instead of
+       data_out().
+       (table_value_missing) Ditto.
+       (float_M_suffix) Ditto.
+       (format_short) New function.
+
+       * data-in.h: (data_in_finite_line) Remove inline definition.
+
+       * data-list.c: (destroy_dls_var_spec) New function.
+       (destroy_dls) Rewrite in terms of destroy_dls_var_spec().
+       (data_list_source_destroy_source) Avoid cast.
+       (struct repeating_data_trns) New field `id_value'.  Update
+       comments.
+       (cmd_repeating_data) Initialize id_value.  Use new
+       repeating_data_trns_free() for freeing REPEATING DATA
+       transformations.
+       (rpd_parse_record) Rewrite support for record ID to be less bogus.
+       (repeating_data_trns_free) New function.
+
+       * data-out.c: (data_out) Change return type to `void' by replacing
+       error returns by writing a message into the output buffer.
+       (convert_A) Read from v->s instead of v->c.
+       (convert_AHEX) Ditto.
+
+       * expr-evl.c: Update comment.
+       (expr_evaluate) Add assertion in OP_STRING case.
+
+       * format.h: (macro MAX_FORMATTED_LEN) New macro.
+
+       * list.q: (list_cases) Update for new data_out() semantics.
+
+       * print.c: (print_trns_proc) Ditto.
+
+       * tab.c: (tab_value) Ditto.
+       (tab_float) Avoid stupid cast.
+
+       * var.h: Update comments.
+       (macro MAX_STRING) New macro.
+       (macro MAX_ELEMS_PER_VALUE) New macro.
+
+       * vars-atr.c: (compare_values) New function.
+
+       * vfm.c: (dump_splits) Update for new data_out() semantics.
+
+Mon Feb 16 21:45:47 2004  Ben Pfaff  <blp@gnu.org>
+
+       * crosstabs.q: (struct table_entry) Rename v[] to values[].  All
+       references updated.
+       (struct crosstab) Rename v[] to vars[].  All references updated.
+       (hash_table_entry) Replace the hash algorithm and fix a bug at the
+       same time, which caused the hash value to depend only on a single
+       value, not all of the variables' values.
+       
 Mon Feb 16 12:49:53 2004  Ben Pfaff  <blp@gnu.org>
 
        Clean up struct dictionary's value_cnt usage.
index 11f3832dd7ef2fe2c20c72271976768ff8636feb..36c388ac29fcb282706170b5043d84b0e2d65770 100644 (file)
@@ -91,7 +91,7 @@ struct table_entry
        double *data;   /* Crosstabulation table for integer mode. */
       }
     u;
-    union value v[1];          /* Values. */
+    union value values[1];     /* Values. */
   };
 
 /* A crosstabulation. */
@@ -100,7 +100,7 @@ struct crosstab
     int nvar;                  /* Number of variables. */
     double missing;            /* Missing cases count. */
     int ofs;                   /* Integer mode: Offset into sorted_tab[]. */
-    struct variable *v[2];     /* At least two variables; sorted by
+    struct variable *vars[2];  /* At least two variables; sorted by
                                   larger indices first. */
   };
 
@@ -154,6 +154,9 @@ static int calc_integer (struct ccase *, void *);
 static void postcalc (void *);
 static void submit (struct tab_table *);
 
+static void format_short (char *s, const struct fmt_spec *fp,
+                         const union value *v);
+
 #if DEBUGGING
 static void debug_print (void);
 static void print_table_entries (struct table_entry **tab);
@@ -346,7 +349,7 @@ crs_custom_tables (struct cmd_crosstabs *cmd UNUSED)
          int i;
 
           for (i = 0; i < n_by; i++)
-            x->v[i] = by[i][by_iter[i]];
+            x->vars[i] = by[i][by_iter[i]];
        }
        
        {
@@ -540,13 +543,13 @@ precalc (void *aux UNUSED)
          x->ofs = n_sorted_tab;
 
          for (j = 2; j < x->nvar; j++)
-           count *= x->v[j - 2]->p.crs.count;
+           count *= x->vars[j - 2]->p.crs.count;
 
          sorted_tab = xrealloc (sorted_tab,
                                 sizeof *sorted_tab * (n_sorted_tab + count));
          v = local_alloc (sizeof *v * x->nvar);
          for (j = 2; j < x->nvar; j++)
-           v[j] = x->v[j]->p.crs.min;
+           v[j] = x->vars[j]->p.crs.min;
          for (j = 0; j < count; j++)
            {
              struct table_entry *te;
@@ -557,8 +560,8 @@ precalc (void *aux UNUSED)
              te->table = i;
              
              {
-               const int mat_size = (x->v[0]->p.crs.count
-                                     * x->v[1]->p.crs.count);
+               const int mat_size = (x->vars[0]->p.crs.count
+                                     * x->vars[1]->p.crs.count);
                int m;
                
                te->u.data = xmalloc (sizeof *te->u.data * mat_size);
@@ -567,10 +570,10 @@ precalc (void *aux UNUSED)
              }
              
              for (k = 2; k < x->nvar; k++)
-               te->v[k].f = v[k];
+               te->values[k].f = v[k];
              for (k = 2; k < x->nvar; k++)
-               if (++v[k] >= x->v[k]->p.crs.max)
-                 v[k] = x->v[k]->p.crs.min;
+               if (++v[k] >= x->vars[k]->p.crs.max)
+                 v[k] = x->vars[k]->p.crs.min;
                else
                  break;
            }
@@ -609,23 +612,25 @@ calc_general (struct ccase *c, void *aux UNUSED)
        for (j = 0; j < x->nvar; j++)
          {
            if ((cmd.miss == CRS_TABLE
-                && is_missing (&c->data[x->v[j]->fv], x->v[j]))
+                && is_missing (&c->data[x->vars[j]->fv], x->vars[j]))
                || (cmd.miss == CRS_INCLUDE
-                   && is_system_missing (&c->data[x->v[j]->fv], x->v[j])))
+                   && is_system_missing (&c->data[x->vars[j]->fv],
+                                          x->vars[j])))
              {
                x->missing += weight;
                goto next_crosstab;
              }
              
-           if (x->v[j]->type == NUMERIC)
-             te->v[j].f = c->data[x->v[j]->fv].f;
+           if (x->vars[j]->type == NUMERIC)
+             te->values[j].f = c->data[x->vars[j]->fv].f;
            else
              {
-               memcpy (te->v[j].s, c->data[x->v[j]->fv].s, x->v[j]->width);
+               memcpy (te->values[j].s, c->data[x->vars[j]->fv].s,
+                        x->vars[j]->width);
              
                /* Necessary in order to simplify comparisons. */
-               memset (&te->v[j].s[x->v[j]->width], 0,
-                       sizeof (union value) - x->v[j]->width);
+               memset (&te->values[j].s[x->vars[j]->width], 0,
+                       sizeof (union value) - x->vars[j]->width);
              }
          }
       }
@@ -672,7 +677,7 @@ calc_integer (struct ccase *c, void *aux UNUSED)
       ofs = x->ofs;
       for (i = 0; i < x->nvar; i++)
        {
-         struct variable *const v = x->v[i];
+         struct variable *const v = x->vars[i];
          double value = c->data[v->fv].f;
          
          /* Note that the first test also rules out SYSMIS. */
@@ -691,9 +696,9 @@ calc_integer (struct ccase *c, void *aux UNUSED)
        }
       
       {
-       const int row = c->data[x->v[ROW_VAR]->fv].f - x->v[ROW_VAR]->p.crs.min;
-       const int col = c->data[x->v[COL_VAR]->fv].f - x->v[COL_VAR]->p.crs.min;
-       const int col_dim = x->v[COL_VAR]->p.crs.count;
+       const int row = c->data[x->vars[ROW_VAR]->fv].f - x->vars[ROW_VAR]->p.crs.min;
+       const int col = c->data[x->vars[COL_VAR]->fv].f - x->vars[COL_VAR]->p.crs.min;
+       const int col_dim = x->vars[COL_VAR]->p.crs.count;
 
        sorted_tab[ofs]->u.data[col + row * col_dim] += weight;
       }
@@ -752,9 +757,9 @@ compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
     int i;
 
     for (i = x->nvar - 1; i >= 0; i--)
-      if (x->v[i]->type == NUMERIC)
+      if (x->vars[i]->type == NUMERIC)
        {
-         const double diffnum = a->v[i].f - b->v[i].f;
+         const double diffnum = a->values[i].f - b->values[i].f;
          if (diffnum < 0)
            return -1;
          else if (diffnum > 0)
@@ -762,9 +767,10 @@ compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
        }
       else 
        {
-         assert (x->v[i]->type == ALPHA);
+         assert (x->vars[i]->type == ALPHA);
          {
-           const int diffstr = strncmp (a->v[i].s, b->v[i].s, x->v[i]->width);
+           const int diffstr = strncmp (a->values[i].s, b->values[i].s,
+                                         x->vars[i]->width);
            if (diffstr)
              return diffstr;
          }
@@ -774,23 +780,17 @@ compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
   return 0;
 }
 
-/* Calculate a hash value from table_entry PA. */
+/* Calculate a hash value from table_entry A. */
 static unsigned
-hash_table_entry (const void *pa, void *foo UNUSED)
+hash_table_entry (const void *a_, void *foo UNUSED)
 {
-  const struct table_entry *a = pa;
-  unsigned long hash = a->table;
+  const struct table_entry *a = a_;
+  unsigned long hash;
   int i;
 
-  /* Hash formula from _SPSS Statistical Algorithms_. */
+  hash = a->table;
   for (i = 0; i < xtab[a->table]->nvar; i++)
-    {
-      hash = (hash << 3) | (hash >> (CHAR_BIT * SIZEOF_LONG - 3));
-      hash ^= a->v[i].hash[0];
-#if SIZEOF_DOUBLE / SIZEOF_LONG > 1
-      hash ^= a->v[i].hash[1];
-#endif
-    }
+    hash ^= hsh_hash_bytes (&a->values[i], sizeof a->values[i]);
   
   return hash;
 }
@@ -900,8 +900,8 @@ make_summary_table (void)
       else
        {
          const struct crosstab *const x = xtab[(*pb)->table];
-         const int n_cols = x->v[COL_VAR]->p.crs.count;
-         const int n_rows = x->v[ROW_VAR]->p.crs.count;
+         const int n_cols = x->vars[COL_VAR]->p.crs.count;
+         const int n_rows = x->vars[ROW_VAR]->p.crs.count;
          const int count = n_cols * n_rows;
            
          for (valid = 0.; pb < pe; pb++)
@@ -944,7 +944,8 @@ insert_summary (struct tab_table *t, int tab_index, double valid)
        if (i > 0)
          cp = stpcpy (cp, " * ");
 
-       cp = stpcpy (cp, x->v[i]->label ? x->v[i]->label : x->v[i]->name);
+       cp = stpcpy (cp,
+                     x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name);
       }
     tab_text (t, 0, 0, TAB_LEFT, buf);
 
@@ -1051,7 +1052,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
 
       /* First header line. */
       tab_joint_text (table, nvar - 1, 0, (nvar - 1) + (n_cols - 1), 0,
-                     TAB_CENTER | TAT_TITLE, x->v[COL_VAR]->name);
+                     TAB_CENTER | TAT_TITLE, x->vars[COL_VAR]->name);
   
       tab_hline (table, TAL_1, nvar - 1, nvar + n_cols - 2, 1);
             
@@ -1062,12 +1063,13 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
        for (i = 2; i < nvar; i++)
          tab_joint_text (table, nvar - i - 1, 0, nvar - i - 1, 1,
                          TAB_RIGHT | TAT_TITLE,
-                         x->v[i]->label ? x->v[i]->label : x->v[i]->name);
+                         (x->vars[i]->label
+                           ? x->vars[i]->label : x->vars[i]->name));
        tab_text (table, nvar - 2, 1, TAB_RIGHT | TAT_TITLE,
-                 x->v[ROW_VAR]->name);
+                 x->vars[ROW_VAR]->name);
        for (i = 0; i < n_cols; i++)
          table_value_missing (table, nvar + i - 1, 1, TAB_RIGHT, &cols[i],
-                              x->v[COL_VAR]);
+                              x->vars[COL_VAR]);
        tab_text (table, nvar + n_cols - 1, 1, TAB_CENTER, _("Total"));
       }
 
@@ -1085,11 +1087,12 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
            {
              if (i)
                cp = stpcpy (cp, " by ");
-             cp = stpcpy (cp, x->v[i]->name);
+             cp = stpcpy (cp, x->vars[i]->name);
            }
        else
          {
-           cp = spprintf (cp, "%s by %s for", x->v[0]->name, x->v[1]->name);
+           cp = spprintf (cp, "%s by %s for",
+                           x->vars[0]->name, x->vars[1]->name);
            for (i = 2; i < nvar; i++)
              {
                char buf[64], *bufp;
@@ -1097,9 +1100,9 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
                if (i > 2)
                  *cp++ = ',';
                *cp++ = ' ';
-               cp = stpcpy (cp, x->v[i]->name);
+               cp = stpcpy (cp, x->vars[i]->name);
                *cp++ = '=';
-               data_out (buf, &x->v[i]->print, &(*pb)->v[i]);
+               format_short (buf, &x->vars[i]->print, &(*pb)->values[i]);
                for (bufp = buf; isspace ((unsigned char) *bufp); bufp++)
                  ;
                cp = stpcpy (cp, bufp);
@@ -1288,7 +1291,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
            *cp = 0.;
            for (p = &tb[0]; p < te; p++)
              {
-               for (; memcmp (cur_col, &(*p)->v[COL_VAR], sizeof *cur_col);
+               for (; memcmp (cur_col, &(*p)->values[COL_VAR], sizeof *cur_col);
                     cur_row = rows)
                  {
                    *++cp = 0.;
@@ -1301,7 +1304,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
                    mp = &mat[cur_col - cols];
                  }
 
-               for (; memcmp (cur_row, &(*p)->v[ROW_VAR], sizeof *cur_row);
+               for (; memcmp (cur_row, &(*p)->values[ROW_VAR], sizeof *cur_row);
                     cur_row++)
                  {
                    *mp = 0.;
@@ -1436,8 +1439,9 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
          for (; ; first_difference--)
            {
              assert (first_difference >= 2);
-             if (memcmp (&cmp->v[first_difference],
-                         &(*tb)->v[first_difference], sizeof *cmp->v))
+             if (memcmp (&cmp->values[first_difference],
+                         &(*tb)->values[first_difference],
+                          sizeof *cmp->values))
                break;
            }
        cmp = *tb;
@@ -1496,7 +1500,7 @@ delete_missing (void)
     int r;
 
     for (r = 0; r < n_rows; r++)
-      if (is_num_user_missing (rows[r].f, x->v[ROW_VAR]))
+      if (is_num_user_missing (rows[r].f, x->vars[ROW_VAR]))
        {
          int c;
 
@@ -1510,7 +1514,7 @@ delete_missing (void)
     int c;
 
     for (c = 0; c < n_cols; c++)
-      if (is_num_user_missing (cols[c].f, x->v[COL_VAR]))
+      if (is_num_user_missing (cols[c].f, x->vars[COL_VAR]))
        {
          int r;
 
@@ -1540,7 +1544,7 @@ submit (struct tab_table *t)
   if (t != table)
     for (i = 2; i < nvar; i++)
       tab_text (t, nvar - i - 1, 0, TAB_RIGHT | TAT_TITLE,
-               x->v[i]->label ? x->v[i]->label : x->v[i]->name);
+               x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name);
   tab_box (t, TAL_2, TAL_2, -1, -1, 0, 0, tab_nc (t) - 1, tab_nr (t) - 1);
   tab_box (t, -1, -1, -1, TAL_1, tab_l (t), tab_t (t) - 1, tab_nc (t) - 1,
           tab_nr (t) - 1);
@@ -1629,7 +1633,7 @@ find_pivot_extent_general (struct table_entry **tp, int *cnt, int pivot)
       if (pivot)
        continue;
 
-      if (memcmp (&(*tp)->v[2], &fp->v[2], sizeof (union value) * (x->nvar - 2)))
+      if (memcmp (&(*tp)->values[2], &fp->values[2], sizeof (union value) * (x->nvar - 2)))
        break;
     }
 
@@ -1663,7 +1667,8 @@ find_pivot_extent_integer (struct table_entry **tp, int *cnt, int pivot)
       if (pivot)
        continue;
       
-      if (memcmp (&(*tp)->v[2], &fp->v[2], sizeof (union value) * (x->nvar - 2)))
+      if (memcmp (&(*tp)->values[2], &fp->values[2],
+                  sizeof (union value) * (x->nvar - 2)))
        break;
     }
 
@@ -1699,18 +1704,19 @@ enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx,
 {
   if (mode == GENERAL)
     {
-      int width = xtab[(*entries)->table]->v[var_idx]->width;
+      int width = xtab[(*entries)->table]->vars[var_idx]->width;
       int i;
 
       *values = xmalloc (sizeof **values * entry_cnt);
       for (i = 0; i < entry_cnt; i++)
-        (*values)[i] = entries[i]->v[var_idx];
+        (*values)[i] = entries[i]->values[var_idx];
       *value_cnt = sort_unique (*values, entry_cnt, sizeof **values,
                                 compare_value, &width);
     }
   else
     {
-      struct crosstab_proc *crs = &xtab[(*entries)->table]->v[var_idx]->p.crs;
+      struct crosstab_proc *crs
+        = &xtab[(*entries)->table]->vars[var_idx]->p.crs;
       int i;
       
       assert (mode == INTEGER);
@@ -1737,9 +1743,9 @@ table_value_missing (struct tab_table *table, int c, int r, unsigned char opt,
       return;
     }
 
-  s.length = var->print.w;
-  s.string = tab_alloc (table, s.length + 1);
-  data_out (s.string, &var->print, v);
+  s.string = tab_alloc (table, var->print.w);
+  format_short (s.string, &var->print, v);
+  s.length = strlen (s.string);
   if (cmd.miss == CRS_REPORT && is_num_user_missing (v->f, var))
     s.string[s.length++] = 'M';
   while (s.length && *s.string == ' ')
@@ -1762,8 +1768,8 @@ display_dimensions (struct tab_table *table, int first_difference, struct table_
 
   for (; first_difference >= 2; first_difference--)
     table_value_missing (table, nvar - first_difference - 1, 0,
-                        TAB_RIGHT, &tb->v[first_difference],
-                        x->v[first_difference]);
+                        TAB_RIGHT, &tb->values[first_difference],
+                        x->vars[first_difference]);
 }
 
 /* Put value V into cell (C,R) of TABLE, suffixed with letter M. */
@@ -1776,7 +1782,7 @@ float_M_suffix (struct tab_table *table, int c, int r, double v)
   s.length = 9;
   s.string = tab_alloc (table, 9);
   s.string[8] = 'M';
-  data_out (s.string, &f, (union value *) &v);
+  format_short (s.string, &f, (union value *) &v);
   while (*s.string == ' ')
     {
       s.length--;
@@ -1794,7 +1800,7 @@ display_crosstabulation (void)
        
     for (r = 0; r < n_rows; r++)
       table_value_missing (table, nvar - 2, r * num_cells,
-                          TAB_RIGHT, &rows[r], x->v[ROW_VAR]);
+                          TAB_RIGHT, &rows[r], x->vars[ROW_VAR]);
   }
   tab_text (table, nvar - 2, n_rows * num_cells,
            TAB_LEFT, _("Total"));
@@ -1853,8 +1859,8 @@ display_crosstabulation (void)
                  }
 
                if (cmd.miss == CRS_REPORT
-                   && (is_num_user_missing (cols[c].f, x->v[COL_VAR])
-                       || is_num_user_missing (rows[r].f, x->v[ROW_VAR])))
+                   && (is_num_user_missing (cols[c].f, x->vars[COL_VAR])
+                       || is_num_user_missing (rows[r].f, x->vars[ROW_VAR])))
                  float_M_suffix (table, c, i, v);
                else if (v != 0.)
                  tab_float (table, c, i, TAB_RIGHT, v, 8, 0);
@@ -1902,7 +1908,7 @@ display_crosstabulation (void)
            }
 
          if (cmd.miss == CRS_REPORT
-             && is_num_user_missing (rows[r].f, x->v[ROW_VAR]))
+             && is_num_user_missing (rows[r].f, x->vars[ROW_VAR]))
            float_M_suffix (table, n_cols, 0, v);
          else if (v != 0.)
            tab_float (table, n_cols, 0, TAB_RIGHT, v, 8, 0);
@@ -1950,7 +1956,7 @@ display_crosstabulation (void)
              }
 
            if (cmd.miss == CRS_REPORT && c < n_cols 
-               && is_num_user_missing (cols[c].f, x->v[COL_VAR]))
+               && is_num_user_missing (cols[c].f, x->vars[COL_VAR]))
              float_M_suffix (table, c, j, v);
            else if (v != 0.)
              tab_float (table, c, j, TAB_RIGHT, v, 8, 0);
@@ -2116,24 +2122,24 @@ display_risk (void)
       switch (i)
        {
        case 0:
-         if (x->v[COL_VAR]->type == NUMERIC)
+         if (x->vars[COL_VAR]->type == NUMERIC)
            sprintf (buf, _("Odds Ratio for %s (%g / %g)"),
-                    x->v[COL_VAR]->name, c[0].f, c[1].f);
+                    x->vars[COL_VAR]->name, c[0].f, c[1].f);
          else
            sprintf (buf, _("Odds Ratio for %s (%.*s / %.*s)"),
-                    x->v[COL_VAR]->name,
-                    x->v[COL_VAR]->width, c[0].s,
-                    x->v[COL_VAR]->width, c[1].s);
+                    x->vars[COL_VAR]->name,
+                    x->vars[COL_VAR]->width, c[0].s,
+                    x->vars[COL_VAR]->width, c[1].s);
          break;
        case 1:
        case 2:
-         if (x->v[ROW_VAR]->type == NUMERIC)
+         if (x->vars[ROW_VAR]->type == NUMERIC)
            sprintf (buf, _("For cohort %s = %g"),
-                    x->v[ROW_VAR]->name, rows[i - 1].f);
+                    x->vars[ROW_VAR]->name, rows[i - 1].f);
          else
            sprintf (buf, _("For cohort %s = %.*s"),
-                    x->v[ROW_VAR]->name,
-                    x->v[ROW_VAR]->width, rows[i - 1].s);
+                    x->vars[ROW_VAR]->name,
+                    x->vars[ROW_VAR]->width, rows[i - 1].s);
          break;
        }
                   
@@ -2248,9 +2254,9 @@ display_directional (void)
                  if (k == 0)
                    string = NULL;
                  else if (k == 1)
-                   string = x->v[0]->name;
+                   string = x->vars[0]->name;
                  else
-                   string = x->v[1]->name;
+                   string = x->vars[1]->name;
                  
                  tab_text (direct, j, 0, TAB_LEFT | TAT_PRINTF,
                            gettext (stats_names[j][k]), string);
@@ -2421,7 +2427,7 @@ calc_chisq (double chisq[N_CHISQ], int df[N_CHISQ],
     }
 
   /* Calculate Mantel-Haenszel. */
-  if (x->v[ROW_VAR]->type == NUMERIC && x->v[COL_VAR]->type == NUMERIC)
+  if (x->vars[ROW_VAR]->type == NUMERIC && x->vars[COL_VAR]->type == NUMERIC)
     {
       double r, ase_0, ase_1;
       calc_r ((double *) rows, (double *) cols, &r, &ase_0, &ase_1);
@@ -3218,6 +3224,34 @@ calc_directional (double v[N_DIRECTIONAL], double ase[N_DIRECTIONAL],
   return 1;
 }
 
+/* A wrapper around data_out() that limits string output to short
+   string width and null terminates the result. */
+static void
+format_short (char *s, const struct fmt_spec *fp, const union value *v)
+{
+  struct fmt_spec fmt_subst;
+
+  /* Limit to short string width. */
+  if (formats[fp->type].cat & FCAT_STRING) 
+    {
+      fmt_subst = *fp;
+
+      assert (fmt_subst.type == FMT_A || fmt_subst.type == FMT_AHEX);
+      if (fmt_subst.type == FMT_A)
+        fmt_subst.w = min (8, fmt_subst.w);
+      else
+        fmt_subst.w = min (16, fmt_subst.w);
+
+      fp = &fmt_subst;
+    }
+
+  /* Format. */
+  data_out (s, fp, v);
+  
+  /* Null terminate. */
+  s[fp->w] = '\0';
+}
+
 /* 
    Local Variables:
    mode: c
index c569d55c990beb9d56601b5f48583ef68ef87cb5..450e10d2edb53e4a9620e2bea110d0a0364e8065 100644 (file)
@@ -47,14 +47,4 @@ int data_in (struct data_in *);
 void data_in_finite_line (struct data_in *di, const char *line, size_t len,
                          int fc, int lc);
 
-#if __GNUC__ >= 2
-extern inline void
-data_in_finite_line (struct data_in *di, const char *line, size_t len,
-                    int fc, int lc)
-{
-  di->s = line + ((size_t) fc <= len ? fc - 1 : len);
-  di->e = line + ((size_t) lc <= len ? lc : len);
-}
-#endif /* GNU C */
-
 #endif /* data-in.h */
index f4ed8d874d7c2986e530b8dec777225a09fce73f..a0036d6aa51c9b951027bb3dabf444d032898c04 100644 (file)
@@ -1186,20 +1186,26 @@ read_from_data_list_list (void)
   return -1;
 }
 
-/* Destroys DATA LIST transformation or input program PGM. */
+/* Destroys SPEC. */
 static void
-destroy_dls (struct trns_header *pgm)
+destroy_dls_var_spec (struct dls_var_spec *spec) 
 {
-  struct data_list_pgm *dls = (struct data_list_pgm *) pgm;
-  struct dls_var_spec *iter, *next;
+  struct dls_var_spec *next;
 
-  iter = dls->spec;
-  while (iter)
+  while (spec != NULL)
     {
-      next = iter->next;
-      free (iter);
-      iter = next;
+      next = spec->next;
+      free (spec);
+      spec = next;
     }
+}
+
+/* Destroys DATA LIST transformation PGM. */
+static void
+destroy_dls (struct trns_header *pgm)
+{
+  struct data_list_pgm *dls = (struct data_list_pgm *) pgm;
+  destroy_dls_var_spec (dls->spec);
   fh_close_handle (dls->handle);
 }
 
@@ -1225,7 +1231,7 @@ data_list_source_read (write_case_func *write_case, write_case_data wc_data)
 static void
 data_list_source_destroy_source (void)
 {
-  destroy_dls ((struct trns_header *) & dls);
+  destroy_dls (&dls.h);
 }
 
 struct case_stream data_list_source = 
@@ -1254,7 +1260,6 @@ struct repeating_data_trns
     struct trns_header h;
     struct dls_var_spec *spec; /* Variable parsing specifications. */
     struct file_handle *handle;        /* Input file, never NULL. */
-    /* Do not reorder preceding fields. */
 
     struct rpd_num_or_var starts_beg;  /* STARTS=, before the dash. */
     struct rpd_num_or_var starts_end;  /* STARTS=, after the dash. */
@@ -1262,9 +1267,13 @@ struct repeating_data_trns
     struct rpd_num_or_var length;      /* LENGTH= subcommand. */
     struct rpd_num_or_var cont_beg;    /* CONTINUED=, before the dash. */
     struct rpd_num_or_var cont_end;    /* CONTINUED=, after the dash. */
-    int id_beg, id_end;                        /* ID subcommand, beginning & end columns. */
-    struct variable *id_var;           /* ID subcommand, DATA LIST variable. */
-    struct fmt_spec id_spec;           /* ID subcommand, input format spec. */
+
+    /* ID subcommand. */
+    int id_beg, id_end;                        /* Beginning & end columns. */
+    struct variable *id_var;           /* DATA LIST variable. */
+    struct fmt_spec id_spec;           /* Input format spec. */
+    union value *id_value;              /* ID value. */
+
     write_case_func *write_case;
     write_case_data wc_data;
   };
@@ -1273,6 +1282,7 @@ struct repeating_data_trns
 static struct repeating_data_trns rpd;
 
 int repeating_data_trns_proc (struct trns_header *, struct ccase *);
+void repeating_data_trns_free (struct trns_header *);
 static int parse_num_or_var (struct rpd_num_or_var *, const char *);
 static int parse_repeating_data (void);
 static void find_variable_input_spec (struct variable *v,
@@ -1301,6 +1311,7 @@ cmd_repeating_data (void)
     = rpd.cont_end = rpd.starts_beg;
   rpd.id_beg = rpd.id_end = 0;
   rpd.id_var = NULL;
+  rpd.id_value = NULL;
   rpd.spec = NULL;
   first = &rpd.spec;
   next = NULL;
@@ -1469,6 +1480,7 @@ cmd_repeating_data (void)
            return CMD_FAILURE;
 
          find_variable_input_spec (rpd.id_var, &rpd.id_spec);
+          rpd.id_value = xmalloc (sizeof *rpd.id_value * rpd.id_var->nv);
        }
       else if (lex_match_id ("TABLE"))
        table = 1;
@@ -1533,7 +1545,7 @@ cmd_repeating_data (void)
     struct repeating_data_trns *new_trns;
 
     rpd.h.proc = repeating_data_trns_proc;
-    rpd.h.free = destroy_dls;
+    rpd.h.free = repeating_data_trns_free;
 
     new_trns = xmalloc (sizeof *new_trns);
     memcpy (new_trns, &rpd, sizeof *new_trns);
@@ -1709,14 +1721,14 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
   /* Handle record ID values. */
   if (t->id_beg != 0)
     {
-      static union value comparator;
-      union value v;
+      union value id_temp[MAX_ELEMS_PER_VALUE];
       
+      /* Parse record ID into V. */
       {
        struct data_in di;
 
        data_in_finite_line (&di, line, len, t->id_beg, t->id_end);
-       di.v = &v;
+       di.v = compare_id ? id_temp : t->id_value;
        di.flags = 0;
        di.f1 = t->id_beg;
        di.format = t->id_spec;
@@ -1725,25 +1737,21 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
          return 0;
       }
 
-      if (compare_id == 0)
-       comparator = v;
-      else if ((t->id_var->type == NUMERIC && comparator.f != v.f)
-              || (t->id_var->type == ALPHA
-                  && strncmp (comparator.s, v.s, t->id_var->width)))
+      if (compare_id
+          && compare_values (id_temp, t->id_value, t->id_var->width) != 0)
        {
-         char comp_str [64];
-         char v_str [64];
+         char expected_str [MAX_FORMATTED_LEN + 1];
+         char actual_str [MAX_FORMATTED_LEN + 1];
 
-         if (!data_out (comp_str, &t->id_var->print, &comparator))
-           comp_str[0] = 0;
-         if (!data_out (v_str, &t->id_var->print, &v))
-           v_str[0] = 0;
-         
-         comp_str[t->id_var->print.w] = v_str[t->id_var->print.w] = 0;
+         data_out (expected_str, &t->id_var->print, t->id_value);
+          expected_str[t->id_var->print.w] = '\0';
+
+         data_out (actual_str, &t->id_var->print, id_temp);
+          actual_str[t->id_var->print.w] = '\0';
            
          tmsg (SE, RPD_ERR, 
-               _("Mismatched case ID (%s).  Expected value was %s."),
-               v_str, comp_str);
+               _("Encountered mismatched record ID \"%s\" expecting \"%s\"."),
+               actual_str, expected_str);
 
          return 0;
        }
@@ -1942,6 +1950,16 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c)
   return -3;
 }
 
+void
+repeating_data_trns_free (struct trns_header *rpd_) 
+{
+  struct repeating_data_trns *rpd = (struct repeating_data_trns *) rpd_;
+
+  destroy_dls_var_spec (rpd->spec);
+  fh_close_handle (rpd->handle);
+  free (rpd->id_value);
+}
+
 /* This is a kluge.  It is only here until I have more time
    tocome up with something better.  It lets
    repeating_data_trns_proc() know how to write the cases that it
index be4471a047eca12f7e61073b0fcb8670b6041c09..7e3443290e85447f9e8925ee47a3c0707f73f81f 100644 (file)
@@ -54,13 +54,25 @@ static convert_func convert_RB, convert_RBHEX, convert_CCx, convert_date;
 static convert_func convert_time, convert_WKDAY, convert_MONTH;
 static convert_func try_F;
 
-/* Converts binary value V into printable form in string S according
-   to format specification FP.  The string as written has exactly
-   FP->W characters.  It is not null-terminated.  Returns 1 on
-   success, 0 on failure. */
-int
+/* Converts binary value V into printable form in the exactly
+   FP->W character in buffer S according to format specification
+   FP.  No null terminator is appended to the buffer.  */
+void
 data_out (char *s, const struct fmt_spec *fp, const union value *v)
 {
+  static convert_func *const handlers[FMT_NUMBER_OF_FORMATS] =
+    {
+      convert_F, convert_N, convert_E, convert_F_plus,
+      convert_F_plus, convert_F_plus, convert_F_plus,
+      convert_Z, convert_A, convert_AHEX, convert_IB, convert_P, convert_PIB,
+      convert_PIBHEX, convert_PK, convert_RB, convert_RBHEX,
+      convert_CCx, convert_CCx, convert_CCx, convert_CCx, convert_CCx,
+      convert_date, convert_date, convert_date, convert_date, convert_date,
+      convert_date, convert_date, convert_date, convert_date,
+      convert_time, convert_time,
+      convert_WKDAY, convert_MONTH,
+    };
+
   union value tmp_val;
   
   {
@@ -69,7 +81,7 @@ data_out (char *s, const struct fmt_spec *fp, const union value *v)
       {
        memset (s, ' ', fp->w);
        s[fp->w - fp->d - 1] = '.';
-       return 1;
+       return;
       }
     if ((cat & FCAT_SHIFT_DECIMAL) && v->f != SYSMIS && fp->d)
       {
@@ -78,22 +90,8 @@ data_out (char *s, const struct fmt_spec *fp, const union value *v)
       }
   }
   
-  {
-    static convert_func *const handlers[FMT_NUMBER_OF_FORMATS] =
-      {
-       convert_F, convert_N, convert_E, convert_F_plus,
-       convert_F_plus, convert_F_plus, convert_F_plus,
-       convert_Z, convert_A, convert_AHEX, convert_IB, convert_P, convert_PIB,
-       convert_PIBHEX, convert_PK, convert_RB, convert_RBHEX,
-       convert_CCx, convert_CCx, convert_CCx, convert_CCx, convert_CCx,
-       convert_date, convert_date, convert_date, convert_date, convert_date,
-       convert_date, convert_date, convert_date, convert_date,
-       convert_time, convert_time,
-       convert_WKDAY, convert_MONTH,
-      };
-
-    return handlers[fp->type] (s, fp, v);
-  }
+  if (!handlers[fp->type] (s, fp, v)) 
+    strncpy (s, "ERROR", fp->w);
 }
 
 /* Converts V into S in F format with width W and D decimal places,
@@ -397,7 +395,7 @@ convert_Z (char *dst, const struct fmt_spec *fp, const union value *v)
 static int
 convert_A (char *dst, const struct fmt_spec *fp, const union value *v)
 {
-  memcpy (dst, v->c, fp->w);
+  memcpy (dst, v->s, fp->w);
   return 1;
 }
 
@@ -408,8 +406,8 @@ convert_AHEX (char *dst, const struct fmt_spec *fp, const union value *v)
 
   for (i = 0; i < fp->w / 2; i++)
     {
-      ((unsigned char *) dst)[i * 2] = MAKE_HEXIT ((v->c[i]) >> 4);
-      ((unsigned char *) dst)[i * 2 + 1] = MAKE_HEXIT ((v->c[i]) & 0xf);
+      ((unsigned char *) dst)[i * 2] = MAKE_HEXIT ((v->s[i]) >> 4);
+      ((unsigned char *) dst)[i * 2 + 1] = MAKE_HEXIT ((v->s[i]) & 0xf);
     }
 
   return 1;
index 0699e86b0b4c1d03a3260f37626f72eb661296ab..3a6abca6eba41af508b1080a37c39bb05991c135 100644 (file)
 #include "vfm.h"
 #include "vfmP.h"
 
-/* FIXME: This could be even more efficient if we caught SYSMIS when
-   it first reared its ugly head, then threw it into an entirely new
-   switch that handled SYSMIS aggressively like all the code does now.
-   But I've spent a couple of weeks on the expression code, and that's
-   enough to make anyone sick.  For that matter, it could be more
-   efficient if I hand-coded it in assembly for a dozen processors,
-   but I'm not going to do that either. */
-
 double
 expr_evaluate (struct expression *e, struct ccase *c, union value *v)
 {
@@ -1061,6 +1053,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v)
            dest = pool_alloc (e->pool, f.w + 1);
            dest[0] = f.w;
 
+            assert ((formats[f.type].cat & FCAT_STRING) == 0);
            data_out (&dest[1], &f, sp);
            sp->c = dest;
          }
@@ -1292,12 +1285,6 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v)
          goto finished;
 
        default:
-#if GLOBAL_DEBUGGING
-         printf (_("evaluate_expression(): not implemented: %s\n"),
-                 ops[op[-1]].name);
-#else
-         printf (_("evaluate_expression(): not implemented: %d\n"), op[-1]);
-#endif
          assert (0);
        }
 
index e021858e966cfeab96f76511fbe9350f51a4c0c9..40358a77e76108159ef41e45467b1e4e0a5260f8 100644 (file)
@@ -835,6 +835,7 @@ evaluate_tree (struct nonterm_node * n)
        f.d = (int) n->arg[3];
        v.f = n0;
 
+        assert ((formats[f.type].cat & FCAT_STRING) == 0);
        data_out (strbuf, &f, &v);
        n = repl_str_con (n, strbuf, f.w);
       }
index ad6d2f7ba5d39caf45a6f887a8ed699f0bb15d86..a1a6e5c54ebe50931676244181376621326fba6c 100644 (file)
@@ -77,6 +77,9 @@ extern const int translate_fmt[40];
 
 union value;
 
+/* Maximum length of formatted value, in character. */
+#define MAX_FORMATTED_LEN 256
+
 int parse_format_specifier (struct fmt_spec *input, int allow_xt);
 int parse_format_specifier_name (const char **cp, int allow_xt);
 int check_input_specifier (const struct fmt_spec *spec);
@@ -85,7 +88,7 @@ int check_string_specifier (const struct fmt_spec *spec, int min_len);
 void convert_fmt_ItoO (const struct fmt_spec *input, struct fmt_spec *output);
 int parse_string_as_format (const char *s, int len, const struct fmt_spec *fp,
                            int fc, union value *v);
-int data_out (char *s, const struct fmt_spec *fp, const union value *v);
+void data_out (char *s, const struct fmt_spec *fp, const union value *v);
 char *fmt_to_string (const struct fmt_spec *);
 void num_to_string (double v, char *s, int w, int d);
 
index 850beda2bc495d22a7a29dd516e3165892359da8..44393a89bbe765ad473afaa63a1af1a4cc72a9f5 100644 (file)
@@ -889,9 +889,9 @@ compare_freq_numeric_a (const void *a_, const void *b_, void *foo UNUSED)
   const struct freq *a = a_;
   const struct freq *b = b_;
 
-  if (a->v.c > b->v.c)
+  if (a->c > b->c)
     return 1;
-  else if (a->v.c < b->v.c)
+  else if (a->c < b->c)
     return -1;
 
   if (a->v.f > b->v.f)
@@ -911,9 +911,9 @@ compare_freq_alpha_a (const void *a_, const void *b_, void *v_)
   const struct freq *b = b_;
   const struct variable *v = v_;
 
-  if (a->v.c > b->v.c)
+  if (a->c > b->c)
     return 1;
-  else if (a->v.c < b->v.c)
+  else if (a->c < b->c)
     return -1;
   else
     return memcmp (a->v.s, b->v.s, v->width);
@@ -927,9 +927,9 @@ compare_freq_numeric_d (const void *a_, const void *b_, void *foo UNUSED)
   const struct freq *a = a_;
   const struct freq *b = b_;
 
-  if (a->v.c > b->v.c)
+  if (a->c > b->c)
     return -1;
-  else if (a->v.c < b->v.c)
+  else if (a->c < b->c)
     return 1;
 
   if (a->v.f > b->v.f)
@@ -949,9 +949,9 @@ compare_freq_alpha_d (const void *a_, const void *b_, void *v_)
   const struct freq *b = b_;
   const struct variable *v = v_;
 
-  if (a->v.c > b->v.c)
+  if (a->c > b->c)
     return -1;
-  else if (a->v.c < b->v.c)
+  else if (a->c < b->c)
     return 1;
   else
     return memcmp (a->v.s, b->v.s, v->width);
index 5e312f81e9eea28e620ffc9c4b42da608534a78d..b0629e0c187f4a40a89eb2f73256fe8f3abc32e8 100644 (file)
@@ -669,19 +669,15 @@ list_cases (struct ccase *c, void *aux UNUSED)
                memset(&line_buf[x], ' ', width - v->print.w);
                x += width - v->print.w;
              }
-         
-           {
-             union value value;
-           
-             if (formats[v->print.type].cat & FCAT_STRING)
-               value.c = c->data[v->fv].s;
-             else if (v->fv == -1)
-               value.f = case_num;
-             else
-               value.f = c->data[v->fv].f;
-               
-             data_out (&line_buf[x], &v->print, &value);
-           }
+
+            if ((formats[v->print.type].cat & FCAT_STRING) || v->fv != -1)
+             data_out (&line_buf[x], &v->print, &c->data[v->fv]);
+            else 
+              {
+                union value case_num_value;
+                case_num_value.f = case_num;
+                data_out (&line_buf[x], &v->print, &case_num_value); 
+              }
            x += v->print.w;
          
            line_buf[x++] = ' ';
@@ -706,17 +702,16 @@ list_cases (struct ccase *c, void *aux UNUSED)
        for (column = 0; column < cmd.n_variables; column++)
          {
            struct variable *v = cmd.v_variables[column];
-           union value value;
            char buf[41];
            
-           if (formats[v->print.type].cat & FCAT_STRING)
-             value.c = c->data[v->fv].s;
-           else if (v->fv == -1)
-             value.f = case_num;
-           else
-             value.f = c->data[v->fv].f;
-               
-           data_out (buf, &v->print, &value);
+            if ((formats[v->print.type].cat & FCAT_STRING) || v->fv != -1)
+             data_out (buf, &v->print, &c->data[v->fv]);
+            else 
+              {
+                union value case_num_value;
+                case_num_value.f = case_num;
+                data_out (buf, &v->print, &case_num_value); 
+              }
            buf[v->print.w] = 0;
 
            fprintf (x->file.file, "    <TD ALIGN=RIGHT>%s</TD>\n",
index 7d5b73b8cc75a81fc38916b761d142d40737c16a..2fa40ae6e31a365222131f3f0d4afa11e807f1b0 100644 (file)
@@ -958,14 +958,7 @@ print_trns_proc (struct trns_header * trns, struct ccase * c)
        break;
 
       case PRT_VAR:
-       if (i->u.v.v->type == NUMERIC)
-         data_out (&buf[i->fc], &i->u.v.f, &c->data[i->u.v.v->fv]);
-       else
-         {
-           union value t;
-           t.c = c->data[i->u.v.v->fv].s;
-           data_out (&buf[i->fc], &i->u.v.f, &t);
-         }
+        data_out (&buf[i->fc], &i->u.v.f, &c->data[i->u.v.v->fv]);
        len = i->fc + i->u.v.f.w;
        break;
 
index c85ea9b37db54663f0c1556d6129983d97a8bdc2..20b245986b127b3bc8ddd703048d11def95f7682 100644 (file)
--- a/src/q2c.c
+++ b/src/q2c.c
@@ -1704,7 +1704,7 @@ dump_header (void)
   loctime = localtime (&curtime);
   timep = asctime (loctime);
   timep[strlen (timep) - 1] = 0;
-  dump (0,   "/* %s", ofn);
+  dump (0,   "/* %s\t\t-*- mode: c; buffer-read-only: t -*-", ofn);
   dump (0, nullstr);
   dump (0, "   Generated by q2c from %s on %s.", ifn, timep);
   dump (0, "   Do not modify!");
index 862028a8c5ab56959896e8b9cb8c9deb1f9c1c65..fbb292fdbb84b6639a844b26a1d689df87e1fc31 100644 (file)
--- a/src/tab.c
+++ b/src/tab.c
@@ -570,7 +570,6 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt,
           const union value *v, const struct fmt_spec *f)
 {
   char *contents;
-  union value temp_val;
 
   assert (table != NULL && v != NULL && f != NULL);
 #if GLOBAL_DEBUGGING
@@ -591,11 +590,6 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt,
   ls_init (&table->cc[c + r * table->cf], contents, f->w);
   table->ct[c + r * table->cf] = opt;
   
-  if (formats[f->type].cat & FCAT_STRING)
-    {
-      temp_val.c = (char *) v->s;
-      v = &temp_val;
-    }
   data_out (contents, f, v);
 }
 
@@ -609,6 +603,7 @@ tab_float (struct tab_table *table, int c, int r, unsigned char opt,
   char buf[40], *cp;
   
   struct fmt_spec f;
+  union value double_value;
 
   assert (table != NULL && w <= 40);
   
@@ -635,7 +630,9 @@ tab_float (struct tab_table *table, int c, int r, unsigned char opt,
     }
 #endif
 
-  data_out (buf, &f, (union value *) &val);
+  double_value.f = val;
+  data_out (buf, &f, &double_value);
+
   cp = buf;
   while (isspace ((unsigned char) *cp) && cp < &buf[w])
     cp++;
index ea7152521300534e9d0a677a0cfb6e732fbd5c9e..fc9827d93b94785661a27a2c08a57884ac2e873e 100644 (file)
--- a/src/var.h
+++ b/src/var.h
 
 /* Values. */
 
-/* Definition of the max length of a short string value, generally
-   eight characters.  */
+/* Max length of a short string value, generally 8 chars. */
 #define MAX_SHORT_STRING ((SIZEOF_DOUBLE)>=8 ? ((SIZEOF_DOUBLE)+1)/2*2 : 8)
 #define MIN_LONG_STRING (MAX_SHORT_STRING+1)
 
+/* Max string length. */
+#define MAX_STRING 255
+
 /* FYI: It is a bad situation if sizeof(flt64) < MAX_SHORT_STRING:
    then short string missing values can be truncated in system files
    because there's only room for as many characters as can fit in a
@@ -54,22 +56,20 @@ union value
     /* A short-string value. */
     unsigned char s[MAX_SHORT_STRING];
 
-    /* This member is used by data-in.c to return a string result,
-       since it may need to return a long string.  As currently
-       implemented, it's a pointer to a static internal buffer in
-       data-in.c.
-
-       Also used by evaluate_expression() to return a string result.
-       As currently implemented, it's a pointer to a dynamic buffer in
-       the appropriate expression.
+    /* Used by evaluate_expression() to return a string result.
+       As currently implemented, it's a pointer to a dynamic
+       buffer in the appropriate expression.
 
        Also used by the AGGREGATE procedure in handling string
        values. */
     unsigned char *c;
-
-    /* Sometimes we insert value's in a hash table. */
-    unsigned long hash[SIZEOF_DOUBLE / SIZEOF_LONG];
   };
+
+/* Maximum number of `union value's in a single number or string
+   value. */
+#define MAX_ELEMS_PER_VALUE (MAX_STRING / sizeof (union value) + 1)
+
+int compare_values (union value *a, union value *b, int width);
 \f
 /* Frequency tables. */
 
index 41e4a70197bccaecf6c92649d76056e7ff76a63b..f90dc1c929812e3a9fffd5466f10e514c3fbda32 100644 (file)
 
 #include "debug-print.h"
 
+/* Compares A and B, which both have the given WIDTH, and returns
+   a strcmp()-type result. */
+int
+compare_values (union value *a, union value *b, int width) 
+{
+  if (width == 0) 
+    return a->f < b->f ? -1 : a->f > b->f;
+  else
+    return memcmp (a->s, b->s, width);
+}
+
 /* Discards all the current state in preparation for a data-input
    command like DATA LIST or GET. */
 void
index 3d40f6c029a55429bebfbd3bad27b15ba4913ffa..e9c7d2048064d5abdc406fe1ddcadf83681f33dc 100644 (file)
--- a/src/vfm.c
+++ b/src/vfm.c
@@ -1091,12 +1091,7 @@ dump_splits (struct ccase *c)
       assert (v->type == NUMERIC || v->type == ALPHA);
       tab_text (t, 0, i + 1, TAB_LEFT | TAT_PRINTF, "%s", v->name);
       
-      {
-       union value val = c->data[v->fv];
-       if (v->type == ALPHA)
-         val.c = c->data[v->fv].s;
-       data_out (temp_buf, &v->print, &val);
-      }
+      data_out (temp_buf, &v->print, &c->data[v->fv]);
       
       temp_buf[v->print.w] = 0;
       tab_text (t, 1, i + 1, TAT_PRINTF, "%.*s", v->print.w, temp_buf);