Implemented long variable names a la spss V12.
[pspp-builds.git] / src / flip.c
index 6bd6a243907f6632712fd64aa48419764a56e67e..d0949980472699e505018ef45ac5d1fb89a489d8 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA. */
 
-#include <config.h>
-#include <assert.h>
+#include "config.h"
+#include "error.h"
 #include <ctype.h>
 #include <errno.h>
 #include <float.h>
 #include <limits.h>
 #include <stdlib.h>
+#include "algorithm.h"
 #include "alloc.h"
+#include "case.h"
 #include "command.h"
+#include "dictionary.h"
 #include "error.h"
 #include "lexer.h"
 #include "misc.h"
 #include "settings.h"
 #include "str.h"
+#include "val.h"
 #include "var.h"
 #include "vfm.h"
 
+
 /* List of variable names. */
 struct varname
   {
     struct varname *next;
-    char name[9];
+    char name[SHORT_NAME_LEN + 1];
   };
 
 /* Represents a FLIP input program. */
 struct flip_pgm 
   {
     struct variable **var;      /* Variables to transpose. */
+    int *idx_to_fv;             /* var[]->index to compacted sink case fv. */
     int var_cnt;                /* Number of elements in `var'. */
     int case_cnt;               /* Pre-flip case count. */
     size_t case_size;           /* Post-flip bytes per case. */
@@ -80,6 +86,7 @@ cmd_flip (void)
 
   flip = xmalloc (sizeof *flip);
   flip->var = NULL;
+  flip->idx_to_fv = dict_get_compacted_idx_to_fv (default_dict);
   flip->var_cnt = 0;
   flip->case_cnt = 0;
   flip->new_names = NULL;
@@ -116,7 +123,7 @@ cmd_flip (void)
       for (i = 0; i < flip->var_cnt; i++)
        if (flip->var[i] == flip->new_names)
          {
-           memmove (&flip->var[i], &flip->var[i + 1], sizeof *flip->var * (flip->var_cnt - i - 1));
+            remove_element (flip->var, flip->var_cnt, sizeof *flip->var, i);
            flip->var_cnt--;
            break;
          }
@@ -158,6 +165,7 @@ destroy_flip_pgm (struct flip_pgm *flip)
   struct varname *iter, *next;
   
   free (flip->var);
+  free (flip->idx_to_fv);
   for (iter = flip->new_names_head; iter != NULL; iter = next) 
     {
       next = iter->next;
@@ -198,8 +206,8 @@ make_new_var (char name[])
 
   /* Add numeric extensions until acceptable. */
   {
-    int len = (int) strlen (name);
-    char n[9];
+    const int len = (int) strlen (name);
+    char n[SHORT_NAME_LEN + 1];
     int i;
 
     for (i = 1; i < 10000000; i++)
@@ -236,7 +244,7 @@ build_dictionary (struct flip_pgm *flip)
       for (i = 0; i < flip->case_cnt; i++)
        {
           struct variable *v;
-         char s[9];
+         char s[SHORT_NAME_LEN + 1];
 
          sprintf (s, "VAR%03d", i);
          v = dict_create_var_assert (default_dict, s, 0);
@@ -277,7 +285,7 @@ flip_sink_create (struct flip_pgm *flip)
 
   /* Write variable names as first case. */
   for (i = 0; i < flip->var_cnt; i++) 
-    st_bare_pad_copy (info->output_buf[i].s, flip->var[i]->name, 8);
+    st_bare_pad_copy (info->output_buf[i].s, flip->var[i]->name, MAX_SHORT_STRING);
   if (fwrite (info->output_buf, sizeof *info->output_buf,
               flip->var_cnt, flip->file) != (size_t) flip->var_cnt)
     msg (FE, _("Error writing FLIP file: %s."), strerror (errno));
@@ -303,7 +311,7 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c)
       v->next = NULL;
       if (flip->new_names->type == NUMERIC) 
         {
-          double f = c->data[sink->idx_to_fv[flip->new_names->index]].f;
+          double f = case_num (c, flip->idx_to_fv[flip->new_names->index]);
 
           if (f == SYSMIS)
             strcpy (v->name, "VSYSMIS");
@@ -315,14 +323,14 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c)
             {
               char name[INT_DIGITS + 2];
               sprintf (name, "V%d", (int) f);
-              strncpy (v->name, name, 8);
-              name[8] = 0; 
+              strncpy (v->name, name, SHORT_NAME_LEN);
+              name[SHORT_NAME_LEN] = 0; 
             }
         }
       else
        {
-         int width = min (flip->new_names->width, 8);
-         memcpy (v->name, c->data[sink->idx_to_fv[flip->new_names->index]].s,
+         int width = min (flip->new_names->width, MAX_SHORT_STRING);
+         memcpy (v->name, case_str (c, flip->idx_to_fv[flip->new_names->index]),
                   width);
          v->name[width] = 0;
        }
@@ -336,10 +344,15 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c)
 
   /* Write to external file. */
   for (i = 0; i < flip->var_cnt; i++)
-    if (flip->var[i]->type == NUMERIC)
-      info->output_buf[i].f = c->data[sink->idx_to_fv[flip->var[i]->index]].f;
-    else
-      info->output_buf[i].f = SYSMIS;
+    {
+      double out;
+      
+      if (flip->var[i]->type == NUMERIC)
+        out = case_num (c, flip->idx_to_fv[flip->var[i]->index]);
+      else
+        out = SYSMIS;
+      info->output_buf[i].f = out;
+    }
          
   if (fwrite (info->output_buf, sizeof *info->output_buf,
               flip->var_cnt, flip->file) != (size_t) flip->var_cnt)
@@ -407,9 +420,18 @@ flip_file (struct flip_pgm *flip)
          for (j = 0; j < read_cases; j++)
            output_buf[j] = input_buf[i + j * flip->var_cnt];
 
-         if (fseek (output_file,
-                     sizeof *input_buf * (case_idx + i * flip->case_cnt),
-                     SEEK_SET) != 0)
+#ifndef HAVE_FSEEKO
+#define fseeko fseek
+#endif
+
+#ifndef HAVE_OFF_T
+#define off_t long int
+#endif
+
+         if (fseeko (output_file,
+                      sizeof *input_buf * (case_idx
+                                           + (off_t) i * flip->case_cnt),
+                      SEEK_SET) != 0)
            msg (FE, _("Error seeking FLIP source file: %s."),
                       strerror (errno));
 
@@ -455,7 +477,7 @@ static const struct case_sink_class flip_sink_class =
 static struct case_source *
 flip_source_create (struct flip_pgm *pgm)
 {
-  return create_case_source (&flip_source_class, default_dict, pgm);
+  return create_case_source (&flip_source_class, pgm);
 }
 
 /* Reads the FLIP stream.  Copies each case into C and calls
@@ -466,11 +488,15 @@ flip_source_read (struct case_source *source,
                   write_case_func *write_case, write_case_data wc_data)
 {
   struct flip_pgm *flip = source->aux;
+  union value *input_buf;
   int i;
 
+  input_buf = xmalloc (sizeof *input_buf * flip->case_cnt);
   for (i = 0; i < flip->var_cnt; i++)
     {
-      if (fread (c->data, sizeof *c->data, flip->case_cnt,
+      size_t j;
+      
+      if (fread (input_buf, sizeof *input_buf, flip->case_cnt,
                  flip->file) != flip->case_cnt) 
         {
           if (ferror (flip->file))
@@ -483,9 +509,12 @@ flip_source_read (struct case_source *source,
           break;
         }
 
+      for (j = 0; j < flip->case_cnt; j++)
+        case_data_rw (c, j)->f = input_buf[j].f;
       if (!write_case (wc_data))
         break;
     }
+  free (input_buf);
 }
 
 /* Destroy internal data in SOURCE. */