Implemented long variable names a la spss V12.
[pspp-builds.git] / src / file-type.c
index fee98518557bb80ae0ad6021f51081b8be623054..adf81a995c8730bb6ac0d60b479ae592f3937e09 100644 (file)
    02111-1307, USA. */
 
 #include <config.h>
-#include <assert.h>
 #include <stdlib.h>
 #include "alloc.h"
+#include "case.h"
 #include "command.h"
 #include "data-in.h"
-#include "dfm.h"
+#include "dfm-read.h"
+#include "dictionary.h"
+#include "error.h"
 #include "file-handle.h"
 #include "format.h"
 #include "lexer.h"
@@ -42,7 +44,7 @@ enum
 /* Limited variable column specifications. */
 struct col_spec
   {
-   char name[9];               /* Variable name. */
+   char name[SHORT_NAME_LEN + 1];      /* Variable name. */
     int fc, nc;                        /* First column (1-based), # of columns. */
     int fmt;                   /* Format type. */
     struct variable *v;                /* Variable. */
@@ -74,7 +76,7 @@ struct record_type
 struct file_type_pgm
   {
     int type;                  /* One of the FTY_* constants. */
-    struct file_handle *handle;        /* File handle of input file. */
+    struct dfm_reader *reader;  /* Data file to read. */
     struct col_spec record;    /* RECORD subcommand. */
     struct col_spec case_sbc;  /* CASE subcommand. */
     int wild;                  /* 0=NOWARN, 1=WARN. */
@@ -86,6 +88,7 @@ struct file_type_pgm
                                   DATA LIST. */
     struct record_type *recs_head;     /* List of record types. */
     struct record_type *recs_tail;     /* Last in list of record types. */
+    size_t case_size;           /* Case size in bytes. */
   };
 
 static int parse_col_spec (struct col_spec *, const char *);
@@ -95,20 +98,20 @@ static void create_col_var (struct col_spec *c);
 int
 cmd_file_type (void)
 {
-  static struct file_type_pgm *fty;
+  static struct file_type_pgm *fty;     /* FIXME: static? WTF? */
+  struct file_handle *fh = NULL;
 
   /* Initialize. */
   discard_variables ();
 
   fty = xmalloc (sizeof *fty);
-  fty->handle = inline_file;
+  fty->reader = NULL;
   fty->record.name[0] = 0;
   fty->case_sbc.name[0] = 0;
   fty->wild = fty->duplicate = fty->missing = fty->ordered = 0;
   fty->had_rec_type = 0;
   fty->recs_head = fty->recs_tail = NULL;
 
-  lex_match_id ("TYPE");
   if (lex_match_id ("MIXED"))
     fty->type = FTY_MIXED;
   else if (lex_match_id ("GROUPED"))
@@ -132,8 +135,8 @@ cmd_file_type (void)
       if (lex_match_id ("FILE"))
        {
          lex_match ('=');
-         fty->handle = fh_parse_file_handle ();
-         if (!fty->handle)
+         fh = fh_parse ();
+         if (fh == NULL)
            goto error;
        }
       else if (lex_match_id ("RECORD"))
@@ -269,12 +272,15 @@ cmd_file_type (void)
        }
     }
 
-  default_handle = fty->handle;
+  fty->reader = dfm_open_reader (fh);
+  if (fty->reader == NULL)
+    goto error;
+  default_handle = fh;
 
-  vfm_source = create_case_source (&file_type_source_class, fty);
   create_col_var (&fty->record);
   if (fty->case_sbc.name[0])
     create_col_var (&fty->case_sbc);
+  vfm_source = create_case_source (&file_type_source_class, fty);
 
   return CMD_SUCCESS;
 
@@ -367,7 +373,7 @@ parse_col_spec (struct col_spec *c, const char *def_name)
   spec.type = c->fmt;
   spec.w = c->nc;
   spec.d = 0;
-  return check_input_specifier (&spec);
+  return check_input_specifier (&spec, 1);
 }
 \f
 /* RECORD TYPE. */
@@ -422,9 +428,6 @@ cmd_record_type (void)
        }
     }
 
-  lex_match_id ("RECORD");
-  lex_match_id ("TYPE");
-
   /* Parse record type values. */
   if (lex_match_id ("OTHER"))
     rct->flags |= RCT_OTHER;
@@ -432,7 +435,7 @@ cmd_record_type (void)
     {
       int mv = 0;
 
-      while (token == T_NUM || token == T_STRING)
+      while (lex_is_number () || token == T_STRING)
        {
          if (rct->nv >= mv)
            {
@@ -445,7 +448,7 @@ cmd_record_type (void)
              if (!lex_force_string ())
                goto error;
              rct->v[rct->nv].c = xmalloc (fty->record.nc + 1);
-             st_bare_pad_copy (rct->v[rct->nv].c, ds_value (&tokstr),
+             st_bare_pad_copy (rct->v[rct->nv].c, ds_c_str (&tokstr),
                                fty->record.nc + 1);
            }
          else
@@ -579,8 +582,7 @@ cmd_end_file_type (void)
       return CMD_FAILURE;
     }
   fty = vfm_source->aux;
-
-  lex_match_id ("TYPE");
+  fty->case_size = dict_get_case_size (default_dict);
 
   if (fty->recs_tail)
     {
@@ -616,37 +618,38 @@ cmd_end_file_type (void)
    static void read_from_file_type_grouped(void);
    static void read_from_file_type_nested(void); */
 
-/* Reads any number of cases into temp_case and calls write_case() for
-   each one.  Compare data-list.c:read_from_data_list. */
+/* Reads any number of cases into case C and calls write_case()
+   for each one.  Compare data-list.c:read_from_data_list. */
 static void
 file_type_source_read (struct case_source *source,
+                       struct ccase *c,
                        write_case_func *write_case UNUSED,
                        write_case_data wc_data UNUSED)
 {
   struct file_type_pgm *fty = source->aux;
-  char *line;
-  int len;
-
   struct fmt_spec format;
 
-  dfm_push (fty->handle);
+  dfm_push (fty->reader);
 
   format.type = fty->record.fmt;
   format.w = fty->record.nc;
   format.d = 0;
-  while (NULL != (line = dfm_get_record (fty->handle, &len)))
+  while (!dfm_eof (fty->reader))
     {
+      struct fixed_string line;
       struct record_type *iter;
       union value v;
       int i;
 
+      dfm_expand_tabs (fty->reader);
+      dfm_get_record (fty->reader, &line);
       if (formats[fty->record.fmt].cat & FCAT_STRING)
        {
          struct data_in di;
          
-         v.c = temp_case->data[fty->record.v->fv].s;
+         v.c = case_data_rw (c, fty->record.v->fv)->s;
 
-         data_in_finite_line (&di, line, len,
+         data_in_finite_line (&di, ls_c_str (&line), ls_length (&line),
                               fty->record.fc, fty->record.fc + fty->record.nc);
          di.v = (union value *) v.c;
          di.flags = 0;
@@ -669,7 +672,7 @@ file_type_source_read (struct case_source *source,
        {
          struct data_in di;
 
-         data_in_finite_line (&di, line, len,
+         data_in_finite_line (&di, ls_c_str (&line), ls_length (&line),
                               fty->record.fc, fty->record.fc + fty->record.nc);
          di.v = &v;
          di.flags = 0;
@@ -677,7 +680,7 @@ file_type_source_read (struct case_source *source,
          di.format = format;
          data_in (&di);
 
-         memcpy (&temp_case->data[fty->record.v->fv].f, &v.f, sizeof v.f);
+          case_data_rw (c, fty->record.v->fv)->f = v.f;
          for (iter = fty->recs_head; iter; iter = iter->next)
            {
              if (iter->flags & RCT_OTHER)
@@ -689,13 +692,13 @@ file_type_source_read (struct case_source *source,
          if (fty->wild)
            msg (SW, _("Unknown record type %g."), v.f);
        }
-      dfm_fwd_record (fty->handle);
+      dfm_forward_record (fty->reader);
       continue;
 
     found:
       /* Arrive here if there is a matching record_type, which is in
          iter. */
-      dfm_fwd_record (fty->handle);
+      dfm_forward_record (fty->reader);
     }
 
 /*  switch(fty->type)
@@ -706,7 +709,7 @@ file_type_source_read (struct case_source *source,
    default: assert(0);
    } */
 
-  dfm_pop (fty->handle);
+  dfm_pop (fty->reader);
 }
 
 static void
@@ -716,6 +719,7 @@ file_type_source_destroy (struct case_source *source)
   struct record_type *iter, *next;
 
   cancel_transformations ();
+  dfm_close_reader (fty->reader);
   for (iter = fty->recs_head; iter; iter = next)
     {
       next = iter->next;
@@ -726,6 +730,7 @@ file_type_source_destroy (struct case_source *source)
 const struct case_source_class file_type_source_class =
   {
     "FILE TYPE",
+    NULL,
     file_type_source_read,
     file_type_source_destroy,
   };