/[pspp]/pspp/src/get.c
ViewVC logotype

Diff of /pspp/src/get.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.37 by blp, Sun Aug 7 04:39:28 2005 UTC revision 1.38 by blp, Sun Aug 21 07:21:06 2005 UTC
# Line 60  enum operation Line 60  enum operation
60      OP_EXPORT   /* EXPORT. */      OP_EXPORT   /* EXPORT. */
61    };    };
62    
63  static bool trim_dictionary (struct dictionary *,  static bool parse_dict_trim (struct dictionary *);
                              enum operation, int *compress);  
64    
65  /* GET input program. */  /* GET input program. */
66  struct get_pgm  struct get_pgm
# Line 101  cmd_get (void) Line 100  cmd_get (void)
100    case_create (&pgm->bounce, dict_get_next_value_idx (dict));    case_create (&pgm->bounce, dict_get_next_value_idx (dict));
101    
102    start_case_map (dict);    start_case_map (dict);
103    if (!trim_dictionary (dict, OP_READ, NULL))    while (lex_match ('/'))
104      goto error;      if (!parse_dict_trim (dict))
105          goto error;
106    
107      if (!lex_end_of_command ())
108        return false;
109    
110      dict_compact_values (dict);
111    pgm->map = finish_case_map (dict);    pgm->map = finish_case_map (dict);
112    
113    dict_destroy (default_dict);    dict_destroy (default_dict);
# Line 114  cmd_get (void) Line 119  cmd_get (void)
119    
120   error:   error:
121    get_pgm_free (pgm);    get_pgm_free (pgm);
122    if (dict != NULL)    if (dict != NULL)
123      dict_destroy (dict);      dict_destroy (dict);
124    return CMD_FAILURE;    return CMD_FAILURE;
125  }  }
# Line 175  const struct case_source_class get_sourc Line 180  const struct case_source_class get_sourc
180      get_source_destroy,      get_source_destroy,
181    };    };
182    
183  /* XSAVE transformation and SAVE procedure. */  /* Type of output file. */
184  struct save_trns  enum writer_type
185    {    {
186      struct trns_header h;      SYSFILE_WRITER,     /* System file. */
187      struct sfm_writer *writer;  /* System file writer. */      PORFILE_WRITER      /* Portable file. */
188      struct case_map *map;       /* Map from active file to system file dict. */    };
189      struct ccase bounce;        /* Bounce buffer. */  
190    /* Type of a command. */
191    enum command_type
192      {
193        XFORM_CMD,          /* Transformation. */
194        PROC_CMD            /* Procedure. */
195      };
196    
197    /* Portable or system file writer plus a case map. */
198    struct any_writer
199      {
200        enum writer_type writer_type;
201        void *writer;
202        struct case_map *map;       /* Map to output file dictionary
203                                       (null pointer for identity mapping). */
204        struct ccase bounce;        /* Bounce buffer for mapping (if needed). */
205    };    };
206    
207  static int save_write_case_func (struct ccase *, void *);  /* Destroys AW. */
208  static trns_proc_func save_trns_proc;  static void
209  static trns_free_func save_trns_free;  any_writer_destroy (struct any_writer *aw)
   
 /* Parses the SAVE or XSAVE command  
    and returns the parsed transformation. */  
 static struct save_trns *  
 cmd_save_internal (void)  
210  {  {
211    struct file_handle *fh = NULL;    if (aw != NULL)
212    struct dictionary *dict = NULL;      {
213    struct save_trns *t = NULL;        switch (aw->writer_type)
214    int compress = get_scompression ();          {
215    const int default_version = 3;          case PORFILE_WRITER:
216    int version = default_version;            pfm_close_writer (aw->writer);
217    short no_name_table = 0;            break;
218            case SYSFILE_WRITER:
219    t = xmalloc (sizeof *t);            sfm_close_writer (aw->writer);
220    t->h.proc = save_trns_proc;            break;
221    t->h.free = save_trns_free;          }
222    t->writer = NULL;        destroy_case_map (aw->map);
223    t->map = NULL;        case_destroy (&aw->bounce);
224    case_nullify (&t->bounce);        free (aw);
225          }
226    }
227    
228    /* Parses SAVE or XSAVE or EXPORT or XEXPORT command.
229       WRITER_TYPE identifies the type of file to write,
230       and COMMAND_TYPE identifies the type of command.
231    
232       On success, returns a writer.
233       For procedures only, sets *RETAIN_UNSELECTED to true if cases
234       that would otherwise be excluded by FILTER or USE should be
235       included.
236    
237       On failure, returns a null pointer. */
238    static struct any_writer *
239    parse_write_command (enum writer_type writer_type,
240                         enum command_type command_type,
241                         bool *retain_unselected)
242    {
243      /* Common data. */
244      struct file_handle *handle; /* Output file. */
245      struct dictionary *dict;    /* Dictionary for output file. */
246      struct any_writer *aw;      /* Writer. */  
247    
248      /* Common options. */
249      bool print_map;             /* Print map?  TODO. */
250      bool print_short_names;     /* Print long-to-short name map.  TODO. */
251      struct sfm_write_options sysfile_opts;
252      struct pfm_write_options porfile_opts;
253    
254      assert (writer_type == SYSFILE_WRITER || writer_type == PORFILE_WRITER);
255      assert (command_type == XFORM_CMD || command_type == PROC_CMD);
256      assert ((retain_unselected != NULL) == (command_type == PROC_CMD));
257    
258      if (command_type == PROC_CMD)
259        *retain_unselected = true;
260    
261      handle = NULL;
262      dict = dict_clone (default_dict);
263      aw = xmalloc (sizeof *aw);
264      aw->writer_type = writer_type;
265      aw->writer = NULL;
266      aw->map = NULL;
267      case_nullify (&aw->bounce);
268      print_map = false;
269      print_short_names = false;
270      sysfile_opts = sfm_writer_default_options ();
271      porfile_opts = pfm_writer_default_options ();
272    
273      start_case_map (dict);
274      dict_delete_scratch_vars (dict);
275    
276    /* Read most of the subcommands. */    lex_match ('/');
277    for (;;)    for (;;)
278      {      {
279        if (lex_match_id ("VERSION"))        if (lex_match_id ("OUTFILE"))
280          {          {
281              if (handle != NULL)
282                {
283                  lex_sbc_only_once ("OUTFILE");
284                  goto error;
285                }
286              
287            lex_match ('=');            lex_match ('=');
288            if (lex_force_int ())        
289              {            handle = fh_parse ();
290                version = lex_integer ();            if (handle == NULL)
291                lex_get ();              goto error;
                 
               if (lex_match_id ("X"))  
                 no_name_table = 1;  
             }  
292          }          }
293        else if (lex_match_id ("OUTFILE"))        else if (lex_match_id ("NAMES"))
294            print_short_names = true;
295          else if (lex_match_id ("PERMISSIONS"))
296            {
297              bool cw;
298              
299              lex_match ('=');
300              if (lex_match_id ("READONLY"))
301                cw = false;
302              else if (lex_match_id ("WRITEABLE"))
303                cw = true;
304              else
305                {
306                  lex_error (_("expecting %s or %s"), "READONLY", "WRITEABLE");
307                  goto error;
308                }
309              sysfile_opts.create_writeable = porfile_opts.create_writeable = cw;
310            }
311          else if (command_type == PROC_CMD && lex_match_id ("UNSELECTED"))
312            {
313              lex_match ('=');
314              if (lex_match_id ("RETAIN"))
315                *retain_unselected = true;
316              else if (lex_match_id ("DELETE"))
317                *retain_unselected = false;
318              else
319                {
320                  lex_error (_("expecting %s or %s"), "RETAIN", "DELETE");
321                  goto error;
322                }
323            }
324          else if (writer_type == SYSFILE_WRITER && lex_match_id ("COMPRESSED"))
325            sysfile_opts.compress = true;
326          else if (writer_type == SYSFILE_WRITER && lex_match_id ("UNCOMPRESSED"))
327            sysfile_opts.compress = false;
328          else if (writer_type == SYSFILE_WRITER && lex_match_id ("VERSION"))
329          {          {
330            lex_match ('=');            lex_match ('=');
331                    if (!lex_force_int ())
332            fh = fh_parse ();              goto error;
333            if (fh == NULL)            sysfile_opts.version = lex_integer ();
334              goto error;            lex_get ();
   
335          }          }
336        if ( ! lex_match('/')  )        else if (writer_type == PORFILE_WRITER && lex_match_id ("TYPE"))
337            {
338              lex_match ('=');
339              if (lex_match_id ("COMMUNICATIONS"))
340                porfile_opts.type = PFM_COMM;
341              else if (lex_match_id ("TAPE"))
342                porfile_opts.type = PFM_TAPE;
343              else
344                {
345                  lex_error (_("expecting %s or %s"), "COMM", "TAPE");
346                  goto error;
347                }
348            }
349          else if (writer_type == PORFILE_WRITER && lex_match_id ("DIGITS"))
350            {
351              lex_match ('=');
352              if (!lex_force_int ())
353                goto error;
354              porfile_opts.digits = lex_integer ();
355              lex_get ();
356            }
357          else if (!parse_dict_trim (dict))
358            goto error;
359          
360          if (!lex_match ('/'))
361          break;          break;
   
362      }      }
363      if (lex_end_of_command () != CMD_SUCCESS)
364        goto error;
365    
366    if (token != '.')    if (handle == NULL)
367      {      {
368        lex_error (_("expecting end of command"));        lex_sbc_missing ("OUTFILE");
369        goto error;        goto error;
370      }      }
371    
372    if ( fh == NULL )    dict_compact_values (dict);
373      {    aw->map = finish_case_map (dict);
374        msg ( ME, _("The required %s subcommand was not present"), "OUTFILE");    if (aw->map != NULL)
375        goto error;      case_create (&aw->bounce, dict_get_next_value_idx (dict));
     }  
376    
377    if ( version != default_version )    switch (writer_type)
378      {      {
379        msg (MW, _("Unsupported sysfile version: %d. Using version %d instead."),      case SYSFILE_WRITER:
380             version, default_version);        aw->writer = sfm_open_writer (handle, dict, sysfile_opts);
381          break;
382        version = default_version;      case PORFILE_WRITER:
383          aw->writer = pfm_open_writer (handle, dict, porfile_opts);
384          break;
385      }      }
386      
387    dict = dict_clone (default_dict);    return aw;
   start_case_map (dict);  
   if (!trim_dictionary (dict, OP_SAVE, &compress))  
     goto error;  
   t->map = finish_case_map (dict);  
   if (t->map != NULL)  
     case_create (&t->bounce, dict_get_next_value_idx (dict));  
   
   t->writer = sfm_open_writer (fh, dict, compress, no_name_table);  
   if (t->writer == NULL)  
     goto error;  
   
   dict_destroy (dict);  
   
   return t;  
388    
389   error:   error:
390    assert (t != NULL);    any_writer_destroy (aw);
391    dict_destroy (dict);    dict_destroy (dict);
   save_trns_free (&t->h);  
392    return NULL;    return NULL;
393  }  }
394    
395  /* Parses and performs the SAVE procedure. */  /* Writes case C to writer AW. */
396  int  static void
397  cmd_save (void)  any_writer_write_case (struct any_writer *aw, struct ccase *c)
398  {  {
399    struct save_trns *t = cmd_save_internal ();    if (aw->map != NULL)
   if (t != NULL)  
400      {      {
401        procedure (save_write_case_func, t);        map_case (aw->map, c, &aw->bounce);
402        save_trns_free (&t->h);        c = &aw->bounce;
       free(t);  
       return CMD_SUCCESS;  
403      }      }
404    else    
405      switch (aw->writer_type)
406        {
407        case SYSFILE_WRITER:
408          sfm_write_case (aw->writer, c);
409          break;
410        case PORFILE_WRITER:
411          pfm_write_case (aw->writer, c);
412          break;
413        }
414    }
415    
416    /* SAVE and EXPORT. */
417    
418    static int output_proc (struct ccase *, void *);
419    
420    /* Parses and performs the SAVE or EXPORT procedure. */
421    static int
422    parse_output_proc (enum writer_type writer_type)
423    {
424      bool retain_unselected;
425      struct variable *saved_filter_variable;
426      struct any_writer *aw;
427    
428      aw = parse_write_command (writer_type, PROC_CMD, &retain_unselected);
429      if (aw == NULL)
430      return CMD_FAILURE;      return CMD_FAILURE;
431    
432      saved_filter_variable = dict_get_filter (default_dict);
433      if (retain_unselected)
434        dict_set_filter (default_dict, NULL);
435      procedure (output_proc, aw);
436      dict_set_filter (default_dict, saved_filter_variable);
437    
438      any_writer_destroy (aw);
439      return CMD_SUCCESS;
440    }
441    
442    /* Writes case C to file. */
443    static int
444    output_proc (struct ccase *c, void *aw_)
445    {
446      struct any_writer *aw = aw_;
447      any_writer_write_case (aw, c);
448      return 0;
449  }  }
450    
 /* Parses the XSAVE transformation command. */  
451  int  int
452  cmd_xsave (void)  cmd_save (void)
453  {  {
454    struct save_trns *t = cmd_save_internal ();    return parse_output_proc (SYSFILE_WRITER);
   if (t != NULL)  
     {  
       add_transformation (&t->h);  
       return CMD_SUCCESS;  
     }  
   else  
     return CMD_FAILURE;  
455  }  }
456    
457  /* Writes the given C to the file specified by T. */  int
458  static void  cmd_export (void)
 do_write_case (struct save_trns *t, struct ccase *c)  
459  {  {
460    if (t->map == NULL)    return parse_output_proc (PORFILE_WRITER);
     sfm_write_case (t->writer, c);  
   else  
     {  
       map_case (t->map, c, &t->bounce);  
       sfm_write_case (t->writer, &t->bounce);  
     }  
461  }  }
462    
463    /* XSAVE and XEXPORT. */
464    
465    /* Transformation. */
466    struct output_trns
467      {
468        struct trns_header h;       /* Header. */
469        struct any_writer *aw;      /* Writer. */
470      };
471    
472    static trns_proc_func output_trns_proc;
473    static trns_free_func output_trns_free;
474    
475  /* Writes case C to the system file specified on SAVE. */  /* Parses the XSAVE or XEXPORT transformation command. */
476  static int  static int
477  save_write_case_func (struct ccase *c, void *aux UNUSED)  parse_output_trns (enum writer_type writer_type)
478  {  {
479    do_write_case (aux, c);    struct output_trns *t = xmalloc (sizeof *t);
480    return 1;    t->h.proc = output_trns_proc;
481      t->h.free = output_trns_free;
482      t->aw = parse_write_command (writer_type, XFORM_CMD, NULL);
483      if (t->aw == NULL)
484        {
485          free (t);
486          return CMD_FAILURE;
487        }
488    
489      add_transformation (&t->h);
490      return CMD_SUCCESS;
491  }  }
492    
493  /* Writes case C to the system file specified on XSAVE. */  /* Writes case C to the system file specified on XSAVE or XEXPORT. */
494  static int  static int
495  save_trns_proc (struct trns_header *h, struct ccase *c, int case_num UNUSED)  output_trns_proc (struct trns_header *h, struct ccase *c, int case_num UNUSED)
496  {  {
497    struct save_trns *t = (struct save_trns *) h;    struct output_trns *t = (struct output_trns *) h;
498    do_write_case (t, c);    any_writer_write_case (t->aw, c);
499    return -1;    return -1;
500  }  }
501    
502  /* Frees a SAVE transformation. */  /* Frees an XSAVE or XEXPORT transformation. */
503  static void  static void
504  save_trns_free (struct trns_header *t_)  output_trns_free (struct trns_header *h)
505  {  {
506    struct save_trns *t = (struct save_trns *) t_;    struct output_trns *t = (struct output_trns *) h;
507    
508    if (t != NULL)    if (t != NULL)
509      {      {
510        sfm_close_writer (t->writer);        any_writer_destroy (t->aw);
511        destroy_case_map (t->map);        free (t);
       case_destroy (&t->bounce);  
512      }      }
513  }  }
514    
515    /* XSAVE command. */
516    int
517    cmd_xsave (void)
518    {
519      return parse_output_trns (SYSFILE_WRITER);
520    }
521    
522    /* XEXPORT command. */
523    int
524    cmd_xexport (void)
525    {
526      return parse_output_trns (PORFILE_WRITER);
527    }
528    
529  static bool rename_variables (struct dictionary *dict);  static bool rename_variables (struct dictionary *dict);
530  static bool drop_variables (struct dictionary *dict);  static bool drop_variables (struct dictionary *dict);
531  static bool keep_variables (struct dictionary *dict);  static bool keep_variables (struct dictionary *dict);
# Line 362  static bool keep_variables (struct dicti Line 533  static bool keep_variables (struct dicti
533  /* Commands that read and write system files share a great deal  /* Commands that read and write system files share a great deal
534     of common syntactic structure for rearranging and dropping     of common syntactic structure for rearranging and dropping
535     variables.  This function parses this syntax and modifies DICT     variables.  This function parses this syntax and modifies DICT
536     appropriately.     appropriately.  Returns true on success, false on failure. */
   
    OP is the operation being performed.  For operations that  
    write a system file, *COMPRESS is set to 1 if the system file  
    should be compressed, 0 otherwise.  
     
    Returns true on success, false on failure. */  
537  static bool  static bool
538  trim_dictionary (struct dictionary *dict, enum operation op, int *compress)  parse_dict_trim (struct dictionary *dict)
539  {  {
540    assert ((compress != NULL) == (op == OP_SAVE));    if (lex_match_id ("MAP"))
541    if (get_scompression())      {
542      *compress = 1;        /* FIXME. */
543          return true;
   if (op == OP_SAVE || op == OP_EXPORT)  
     {  
       /* Delete all the scratch variables. */  
       struct variable **v;  
       size_t nv;  
       size_t i;  
   
       v = xmalloc (sizeof *v * dict_get_var_cnt (dict));  
       nv = 0;  
       for (i = 0; i < dict_get_var_cnt (dict); i++)  
         if (dict_class_from_id (dict_get_var (dict, i)->name) == DC_SCRATCH)  
           v[nv++] = dict_get_var (dict, i);  
       dict_delete_vars (dict, v, nv);  
       free (v);  
544      }      }
545        else if (lex_match_id ("DROP"))
546    while (lex_match ('/'))      return drop_variables (dict);
547      else if (lex_match_id ("KEEP"))
548        return keep_variables (dict);
549      else if (lex_match_id ("RENAME"))
550        return rename_variables (dict);
551      else
552      {      {
553        bool ok = true;        lex_error (_("expecting a valid subcommand"));
554                return false;
       if (op == OP_SAVE && lex_match_id ("COMPRESSED"))  
         *compress = 1;  
       else if (op == OP_SAVE && lex_match_id ("UNCOMPRESSED"))  
         *compress = 0;  
       else if (lex_match_id ("DROP"))  
         ok = drop_variables (dict);  
       else if (lex_match_id ("KEEP"))  
         ok = keep_variables (dict);  
       else if (lex_match_id ("RENAME"))  
         ok = rename_variables (dict);  
       else  
         {  
           lex_error (_("expecting a valid subcommand"));  
           ok = false;  
         }  
   
       if (!ok)  
         return false;  
555      }      }
   
   if (!lex_end_of_command ())  
     return false;  
   
   dict_compact_values (dict);  
   return true;  
556  }  }
557    
558  /* Parses and performs the RENAME subcommand of GET and SAVE. */  /* Parses and performs the RENAME subcommand of GET and SAVE. */
# Line 484  rename_variables (struct dictionary *dic Line 616  rename_variables (struct dictionary *dic
616        if (nn != nv)        if (nn != nv)
617          {          {
618            msg (SE, _("Number of variables on left side of `=' (%d) does not "            msg (SE, _("Number of variables on left side of `=' (%d) does not "
619                 "match number of variables on right side (%d), in "                       "match number of variables on right side (%d), in "
620                 "parenthesized group %d of RENAME subcommand."),                       "parenthesized group %d of RENAME subcommand."),
621                 nv - old_nv, nn - old_nv, group);                 nv - old_nv, nn - old_nv, group);
622            goto done;            goto done;
623          }          }
# Line 501  rename_variables (struct dictionary *dic Line 633  rename_variables (struct dictionary *dic
633      }      }
634    success = 1;    success = 1;
635    
636  done:   done:
637    for (i = 0; i < nn; i++)    for (i = 0; i < nn; i++)
638      free (new_names[i]);      free (new_names[i]);
639    free (new_names);    free (new_names);
# Line 558  keep_variables (struct dictionary *dict) Line 690  keep_variables (struct dictionary *dict)
690    return true;    return true;
691  }  }
692    
 /* EXPORT procedure. */  
 struct export_proc  
   {  
     struct pfm_writer *writer;  /* System file writer. */  
     struct case_map *map;       /* Map from active file to system file dict. */  
     struct ccase bounce;        /* Bounce buffer. */  
   };  
   
 static int export_write_case_func (struct ccase *, void *);  
 static void export_proc_free (struct export_proc *);  
       
 /* Parses the EXPORT command.  */  
 /* FIXME: same as cmd_save_internal(). */  
 int  
 cmd_export (void)  
 {  
   struct file_handle *fh;  
   struct dictionary *dict;  
   struct export_proc *proc;  
   
   proc = xmalloc (sizeof *proc);  
   proc->writer = NULL;  
   proc->map = NULL;  
   case_nullify (&proc->bounce);  
   
   lex_match ('/');  
   if (lex_match_id ("OUTFILE"))  
     lex_match ('=');  
   fh = fh_parse ();  
   if (fh == NULL)  
     return CMD_FAILURE;  
   
   dict = dict_clone (default_dict);  
   start_case_map (dict);  
   if (!trim_dictionary (dict, OP_EXPORT, NULL))  
     goto error;  
   proc->map = finish_case_map (dict);  
   if (proc->map != NULL)  
     case_create (&proc->bounce, dict_get_next_value_idx (dict));  
   
   proc->writer = pfm_open_writer (fh, dict);  
   if (proc->writer == NULL)  
     goto error;  
     
   dict_destroy (dict);  
   
   procedure (export_write_case_func, proc);  
   export_proc_free (proc);  
   free (proc);  
   
   return CMD_SUCCESS;  
   
  error:  
   dict_destroy (dict);  
   export_proc_free (proc);  
   free (proc);  
   return CMD_FAILURE;  
 }  
   
 /* Writes case C to the EXPORT file. */  
 static int  
 export_write_case_func (struct ccase *c, void *aux)  
 {  
   struct export_proc *proc = aux;  
   if (proc->map == NULL)  
     pfm_write_case (proc->writer, c);  
   else  
     {  
       map_case (proc->map, c, &proc->bounce);  
       pfm_write_case (proc->writer, &proc->bounce);  
     }  
   return 1;  
 }  
   
 static void  
 export_proc_free (struct export_proc *proc)  
 {  
   if (proc != NULL)  
     {  
       pfm_close_writer (proc->writer);  
       destroy_case_map (proc->map);  
       case_destroy (&proc->bounce);  
     }  
 }  
   
693  /* MATCH FILES. */  /* MATCH FILES. */
694    
695  #include "debug-print.h"  #include "debug-print.h"
# Line 657  enum Line 704  enum
704  /* One of the files on MATCH FILES. */  /* One of the files on MATCH FILES. */
705  struct mtf_file  struct mtf_file
706    {    {
707      struct mtf_file *next, *prev;      struct mtf_file *next, *prev; /* Next, previous in the list of files. */
                                 /* Next, previous in the list of files. */  
708      struct mtf_file *next_min;  /* Next in the chain of minimums. */      struct mtf_file *next_min;  /* Next in the chain of minimums. */
709            
710      int type;                   /* One of MTF_*. */      int type;                   /* One of MTF_*. */
# Line 680  struct mtf_proc Line 726  struct mtf_proc
726      struct mtf_file *head;      /* First file mentioned on FILE or TABLE. */      struct mtf_file *head;      /* First file mentioned on FILE or TABLE. */
727      struct mtf_file *tail;      /* Last file mentioned on FILE or TABLE. */      struct mtf_file *tail;      /* Last file mentioned on FILE or TABLE. */
728            
729      size_t by_cnt;              /* Number of variables on BY subcommand. */      int by_cnt;                 /* Number of variables on BY subcommand. */
730    
731      /* Names of FIRST, LAST variables. */      /* Names of FIRST, LAST variables. */
732      char first[LONG_NAME_LEN + 1], last[LONG_NAME_LEN + 1];      char first[LONG_NAME_LEN + 1], last[LONG_NAME_LEN + 1];
# Line 1054  cmd_match_files (void) Line 1100  cmd_match_files (void)
1100    mtf_free (&mtf);    mtf_free (&mtf);
1101    return CMD_SUCCESS;    return CMD_SUCCESS;
1102        
1103  error:   error:
1104    mtf_free (&mtf);    mtf_free (&mtf);
1105    return CMD_FAILURE;    return CMD_FAILURE;
1106  }  }
# Line 1474  cmd_import (void) Line 1520  cmd_import (void)
1520    struct import_pgm *pgm = NULL;    struct import_pgm *pgm = NULL;
1521    struct file_handle *fh = NULL;    struct file_handle *fh = NULL;
1522    struct dictionary *dict = NULL;    struct dictionary *dict = NULL;
1523    int type;    enum pfm_type type;
   
   pgm = xmalloc (sizeof *pgm);  
   pgm->reader = NULL;  
   pgm->map = NULL;  
   case_nullify (&pgm->bounce);  
1524    
1525      lex_match ('/');
1526    for (;;)    for (;;)
1527      {      {
1528        lex_match ('/');        if (pgm == NULL && (lex_match_id ("FILE") || token == T_STRING))
         
       if (lex_match_id ("FILE") || token == T_STRING)  
1529          {          {
1530            lex_match ('=');            lex_match ('=');
1531    
1532            fh = fh_parse ();            fh = fh_parse ();
1533            if (fh == NULL)            if (fh == NULL)
1534              return CMD_FAILURE;              goto error;
1535          }          }
1536        else if (lex_match_id ("TYPE"))        else if (pgm == NULL && lex_match_id ("TYPE"))
1537          {          {
1538            lex_match ('=');            lex_match ('=');
1539    
# Line 1504  cmd_import (void) Line 1544  cmd_import (void)
1544            else            else
1545              {              {
1546                lex_error (_("expecting COMM or TAPE"));                lex_error (_("expecting COMM or TAPE"));
1547                return CMD_FAILURE;                goto error;
1548              }              }
1549          }          }
1550        else break;        else
1551            {
1552              if (pgm == NULL)
1553                {
1554                  if (fh == NULL)
1555                    {
1556                      lex_sbc_missing ("FILE");
1557                      goto error;
1558                    }
1559                  
1560                  discard_variables ();
1561    
1562                  pgm = xmalloc (sizeof *pgm);
1563                  pgm->reader = pfm_open_reader (fh, &dict, NULL);
1564                  pgm->map = NULL;
1565                  case_nullify (&pgm->bounce);
1566                  if (pgm->reader == NULL)
1567                    goto error;
1568    
1569                  case_create (&pgm->bounce, dict_get_next_value_idx (dict));
1570      
1571                  start_case_map (dict);
1572                }
1573    
1574              if (token == '.')
1575                break;
1576              
1577              if (!parse_dict_trim (dict))
1578                goto error;
1579            }
1580    
1581          lex_match ('/');
1582      }      }
1583    if (!lex_match ('/') && token != '.')    if (pgm == NULL)
1584      {      {
1585        lex_error (NULL);        lex_error (NULL);
1586        return CMD_FAILURE;        goto error;
1587      }      }
1588    
   discard_variables ();  
   
   pgm->reader = pfm_open_reader (fh, &dict, NULL);  
   if (pgm->reader == NULL)  
     return CMD_FAILURE;  
   case_create (&pgm->bounce, dict_get_next_value_idx (dict));  
     
   start_case_map (dict);  
   if (!trim_dictionary (dict, OP_READ, NULL))  
     goto error;  
1589    pgm->map = finish_case_map (dict);    pgm->map = finish_case_map (dict);
1590        
1591    dict_destroy (default_dict);    dict_destroy (default_dict);
# Line 1619  struct case_map Line 1680  struct case_map
1680     at will before using finish_case_map() to produce the case     at will before using finish_case_map() to produce the case
1681     map.     map.
1682    
1683     Uses D's aux members, which may not otherwise be in use. */     Uses D's aux members, which must otherwise not be in use. */
1684  static void  static void
1685  start_case_map (struct dictionary *d)  start_case_map (struct dictionary *d)
1686  {  {

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.38

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26