Instead of making system or portable file readers responsible for
[pspp-builds.git] / src / get.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA. */
19
20 #include <config.h>
21 #include "error.h"
22 #include <stdlib.h>
23 #include "alloc.h"
24 #include "case.h"
25 #include "command.h"
26 #include "dictionary.h"
27 #include "error.h"
28 #include "file-handle.h"
29 #include "hash.h"
30 #include "lexer.h"
31 #include "misc.h"
32 #include "pfm-read.h"
33 #include "pfm-write.h"
34 #include "settings.h"
35 #include "sfm-read.h"
36 #include "sfm-write.h"
37 #include "str.h"
38 #include "value-labels.h"
39 #include "var.h"
40 #include "vfm.h"
41 #include "vfmP.h"
42
43 #include "debug-print.h"
44
45 /* Rearranging and reducing a dictionary. */
46 static void start_case_map (struct dictionary *);
47 static struct case_map *finish_case_map (struct dictionary *);
48 static void map_case (const struct case_map *,
49                       const struct ccase *, struct ccase *);
50 static void destroy_case_map (struct case_map *);
51
52 /* Operation type. */
53 enum operation 
54   {
55     OP_READ,    /* GET or IMPORT. */
56     OP_SAVE,    /* SAVE or XSAVE. */
57     OP_EXPORT,  /* EXPORT. */
58     OP_MATCH    /* MATCH FILES. */
59   };
60
61 static int trim_dictionary (struct dictionary *,
62                             enum operation, int *compress);
63 \f
64 /* GET input program. */
65 struct get_pgm 
66   {
67     struct sfm_reader *reader;  /* System file reader. */
68     struct case_map *map;       /* Map from system file to active file dict. */
69     struct ccase bounce;        /* Bounce buffer. */
70   };
71
72 static void get_pgm_free (struct get_pgm *);
73
74 /* Parses the GET command. */
75 int
76 cmd_get (void)
77 {
78   struct get_pgm *pgm = NULL;
79   struct file_handle *fh;
80   struct dictionary *dict = NULL;
81
82   pgm = xmalloc (sizeof *pgm);
83   pgm->reader = NULL;
84   pgm->map = NULL;
85   case_nullify (&pgm->bounce);
86
87   discard_variables ();
88
89   lex_match ('/');
90   if (lex_match_id ("FILE"))
91     lex_match ('=');
92   fh = fh_parse ();
93   if (fh == NULL)
94     goto error;
95
96   pgm->reader = sfm_open_reader (fh, &dict, NULL);
97   if (pgm->reader == NULL)
98     goto error;
99   case_create (&pgm->bounce, dict_get_next_value_idx (dict));
100
101   start_case_map (dict);
102   if (!trim_dictionary (dict, OP_READ, NULL))
103     goto error;
104   pgm->map = finish_case_map (dict);
105
106   dict_destroy (default_dict);
107   default_dict = dict;
108
109   vfm_source = create_case_source (&get_source_class, default_dict, pgm);
110
111   return CMD_SUCCESS;
112
113  error:
114   get_pgm_free (pgm);
115   if (dict != NULL)
116     dict_destroy (dict);
117   return CMD_FAILURE;
118 }
119
120 /* Frees a struct get_pgm. */
121 static void
122 get_pgm_free (struct get_pgm *pgm) 
123 {
124   if (pgm != NULL) 
125     {
126       sfm_close_reader (pgm->reader);
127       destroy_case_map (pgm->map);
128       case_destroy (&pgm->bounce);
129       free (pgm);
130     }
131 }
132
133 /* Clears internal state related to GET input procedure. */
134 static void
135 get_source_destroy (struct case_source *source)
136 {
137   struct get_pgm *pgm = source->aux;
138   get_pgm_free (pgm);
139 }
140
141 /* Reads all the cases from the data file into C and passes them
142    to WRITE_CASE one by one, passing WC_DATA. */
143 static void
144 get_source_read (struct case_source *source,
145                  struct ccase *c,
146                  write_case_func *write_case, write_case_data wc_data)
147 {
148   struct get_pgm *pgm = source->aux;
149   int ok;
150
151   do
152     {
153       if (pgm->map == NULL)
154         ok = sfm_read_case (pgm->reader, c);
155       else
156         {
157           ok = sfm_read_case (pgm->reader, &pgm->bounce);
158           if (ok)
159             map_case (pgm->map, &pgm->bounce, c);
160         }
161
162       if (ok)
163         ok = write_case (wc_data);
164     }
165   while (ok);
166 }
167
168 const struct case_source_class get_source_class =
169   {
170     "GET",
171     NULL,
172     get_source_read,
173     get_source_destroy,
174   };
175 \f
176 /* XSAVE transformation and SAVE procedure. */
177 struct save_trns
178   {
179     struct trns_header h;
180     struct sfm_writer *writer;  /* System file writer. */
181     struct case_map *map;       /* Map from active file to system file dict. */
182     struct ccase bounce;        /* Bounce buffer. */
183   };
184
185 static int save_write_case_func (struct ccase *, void *);
186 static trns_proc_func save_trns_proc;
187 static trns_free_func save_trns_free;
188
189 /* Parses the SAVE or XSAVE command
190    and returns the parsed transformation. */
191 static struct save_trns *
192 cmd_save_internal (void)
193 {
194   struct file_handle *fh;
195   struct dictionary *dict = NULL;
196   struct save_trns *t = NULL;
197   int compress = get_scompression ();
198
199   t = xmalloc (sizeof *t);
200   t->h.proc = save_trns_proc;
201   t->h.free = save_trns_free;
202   t->writer = NULL;
203   t->map = NULL;
204   case_nullify (&t->bounce);
205   
206   lex_match ('/');
207   if (lex_match_id ("OUTFILE"))
208     lex_match ('=');
209   fh = fh_parse ();
210   if (fh == NULL)
211     goto error;
212
213   dict = dict_clone (default_dict);
214   start_case_map (dict);
215   if (!trim_dictionary (dict, OP_SAVE, &compress))
216     goto error;
217   t->map = finish_case_map (dict);
218   if (t->map != NULL)
219     case_create (&t->bounce, dict_get_next_value_idx (dict));
220
221   t->writer = sfm_open_writer (fh, dict, compress);
222   if (t->writer == NULL)
223     goto error;
224
225   dict_destroy (dict);
226
227   return t;
228
229  error:
230   assert (t != NULL);
231   dict_destroy (dict);
232   save_trns_free (&t->h);
233   return NULL;
234 }
235
236 /* Parses and performs the SAVE procedure. */
237 int
238 cmd_save (void)
239 {
240   struct save_trns *t = cmd_save_internal ();
241   if (t != NULL) 
242     {
243       procedure (save_write_case_func, t);
244       save_trns_free (&t->h);
245       return CMD_SUCCESS;
246     }
247   else
248     return CMD_FAILURE;
249 }
250
251 /* Parses the XSAVE transformation command. */
252 int
253 cmd_xsave (void)
254 {
255   struct save_trns *t = cmd_save_internal ();
256   if (t != NULL) 
257     {
258       add_transformation (&t->h);
259       return CMD_SUCCESS; 
260     }
261   else
262     return CMD_FAILURE;
263 }
264
265 /* Writes the given C to the file specified by T. */
266 static void
267 do_write_case (struct save_trns *t, struct ccase *c) 
268 {
269   if (t->map == NULL)
270     sfm_write_case (t->writer, c);
271   else 
272     {
273       map_case (t->map, c, &t->bounce);
274       sfm_write_case (t->writer, &t->bounce);
275     }
276 }
277
278 /* Writes case C to the system file specified on SAVE. */
279 static int
280 save_write_case_func (struct ccase *c, void *aux UNUSED)
281 {
282   do_write_case (aux, c);
283   return 1;
284 }
285
286 /* Writes case C to the system file specified on XSAVE. */
287 static int
288 save_trns_proc (struct trns_header *h, struct ccase *c, int case_num UNUSED)
289 {
290   struct save_trns *t = (struct save_trns *) h;
291   do_write_case (t, c);
292   return -1;
293 }
294
295 /* Frees a SAVE transformation. */
296 static void
297 save_trns_free (struct trns_header *t_)
298 {
299   struct save_trns *t = (struct save_trns *) t_;
300
301   if (t != NULL) 
302     {
303       sfm_close_writer (t->writer);
304       destroy_case_map (t->map);
305       case_destroy (&t->bounce);
306     }
307 }
308
309 static int rename_variables (struct dictionary *dict);
310
311 /* Commands that read and write system files share a great deal
312    of common syntactic structure for rearranging and dropping
313    variables.  This function parses this syntax and modifies DICT
314    appropriately.
315
316    OP is the operation being performed.  For operations that
317    write a system file, *COMPRESS is set to 1 if the system file
318    should be compressed, 0 otherwise.
319    
320    Returns nonzero on success, zero on failure. */
321 /* FIXME: IN, FIRST, LAST, MAP. */
322 static int
323 trim_dictionary (struct dictionary *dict, enum operation op, int *compress)
324 {
325   assert ((compress != NULL) == (op == OP_SAVE));
326   if (get_scompression())
327     *compress = 1;
328
329   if (op == OP_SAVE || op == OP_EXPORT)
330     {
331       /* Delete all the scratch variables. */
332       struct variable **v;
333       size_t nv;
334       size_t i;
335
336       v = xmalloc (sizeof *v * dict_get_var_cnt (dict));
337       nv = 0;
338       for (i = 0; i < dict_get_var_cnt (dict); i++) 
339         if (dict_class_from_id (dict_get_var (dict, i)->name) == DC_SCRATCH)
340           v[nv++] = dict_get_var (dict, i);
341       dict_delete_vars (dict, v, nv);
342       free (v);
343     }
344   
345   while (op == OP_MATCH || lex_match ('/'))
346     {
347       if (op == OP_SAVE && lex_match_id ("COMPRESSED"))
348         *compress = 1;
349       else if (op == OP_SAVE && lex_match_id ("UNCOMPRESSED"))
350         *compress = 0;
351       else if (lex_match_id ("DROP"))
352         {
353           struct variable **v;
354           int nv;
355
356           lex_match ('=');
357           if (!parse_variables (dict, &v, &nv, PV_NONE))
358             return 0;
359           dict_delete_vars (dict, v, nv);
360           free (v);
361         }
362       else if (lex_match_id ("KEEP"))
363         {
364           struct variable **v;
365           int nv;
366           int i;
367
368           lex_match ('=');
369           if (!parse_variables (dict, &v, &nv, PV_NONE))
370             return 0;
371
372           /* Move the specified variables to the beginning. */
373           dict_reorder_vars (dict, v, nv);
374           
375           /* Delete the remaining variables. */
376           v = xrealloc (v, (dict_get_var_cnt (dict) - nv) * sizeof *v);
377           for (i = nv; i < dict_get_var_cnt (dict); i++)
378             v[i - nv] = dict_get_var (dict, i);
379           dict_delete_vars (dict, v, dict_get_var_cnt (dict) - nv);
380           free (v);
381         }
382       else if (lex_match_id ("RENAME"))
383         {
384           if (!rename_variables (dict))
385             return 0;
386         }
387       else
388         {
389           lex_error (_("while expecting a valid subcommand"));
390           return 0;
391         }
392
393       if (dict_get_var_cnt (dict) == 0)
394         {
395           msg (SE, _("All variables deleted from system file dictionary."));
396           return 0;
397         }
398
399       if (op == OP_MATCH)
400         goto success;
401     }
402
403   if (token != '.')
404     {
405       lex_error (_("expecting end of command"));
406       return 0;
407     }
408
409  success:
410   if (op != OP_MATCH)
411     dict_compact_values (dict);
412   return 1;
413 }
414
415 /* Parses and performs the RENAME subcommand of GET and SAVE. */
416 static int
417 rename_variables (struct dictionary *dict)
418 {
419   int i;
420
421   int success = 0;
422
423   struct variable **v;
424   char **new_names;
425   int nv, nn;
426   char *err_name;
427
428   int group;
429
430   lex_match ('=');
431   if (token != '(')
432     {
433       struct variable *v;
434
435       v = parse_dict_variable (dict);
436       if (v == NULL)
437         return 0;
438       if (!lex_force_match ('=')
439           || !lex_force_id ())
440         return 0;
441       if (!strncmp (tokid, v->name, 8))
442         return 1;
443       if (dict_lookup_var (dict, tokid) != NULL)
444         {
445           msg (SE, _("Cannot rename %s as %s because there already exists "
446                      "a variable named %s.  To rename variables with "
447                      "overlapping names, use a single RENAME subcommand "
448                      "such as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, "
449                      "\"/RENAME (A B C=B C A)\"."), v->name, tokid, tokid);
450           return 0;
451         }
452       
453       dict_rename_var (dict, v, tokid);
454       lex_get ();
455       return 1;
456     }
457
458   nv = nn = 0;
459   v = NULL;
460   new_names = 0;
461   group = 1;
462   while (lex_match ('('))
463     {
464       int old_nv = nv;
465
466       if (!parse_variables (dict, &v, &nv, PV_NO_DUPLICATE | PV_APPEND))
467         goto done;
468       if (!lex_match ('='))
469         {
470           msg (SE, _("`=' expected after variable list."));
471           goto done;
472         }
473       if (!parse_DATA_LIST_vars (&new_names, &nn, PV_APPEND | PV_NO_SCRATCH))
474         goto done;
475       if (nn != nv)
476         {
477           msg (SE, _("Number of variables on left side of `=' (%d) does not "
478                "match number of variables on right side (%d), in "
479                "parenthesized group %d of RENAME subcommand."),
480                nv - old_nv, nn - old_nv, group);
481           goto done;
482         }
483       if (!lex_force_match (')'))
484         goto done;
485       group++;
486     }
487
488   if (!dict_rename_vars (dict, v, new_names, nv, &err_name)) 
489     {
490       msg (SE, _("Requested renaming duplicates variable name %s."), err_name);
491       goto done;
492     }
493   success = 1;
494
495 done:
496   for (i = 0; i < nn; i++)
497     free (new_names[i]);
498   free (new_names);
499   free (v);
500
501   return success;
502 }
503 \f
504 /* EXPORT procedure. */
505 struct export_proc 
506   {
507     struct pfm_writer *writer;  /* System file writer. */
508     struct case_map *map;       /* Map from active file to system file dict. */
509     struct ccase bounce;        /* Bounce buffer. */
510   };
511
512 static int export_write_case_func (struct ccase *, void *);
513 static void export_proc_free (struct export_proc *);
514      
515 /* Parses the EXPORT command.  */
516 /* FIXME: same as cmd_save_internal(). */
517 int
518 cmd_export (void)
519 {
520   struct file_handle *fh;
521   struct dictionary *dict;
522   struct export_proc *proc;
523
524   proc = xmalloc (sizeof *proc);
525   proc->writer = NULL;
526   proc->map = NULL;
527   case_nullify (&proc->bounce);
528
529   lex_match ('/');
530   if (lex_match_id ("OUTFILE"))
531     lex_match ('=');
532   fh = fh_parse ();
533   if (fh == NULL)
534     return CMD_FAILURE;
535
536   dict = dict_clone (default_dict);
537   start_case_map (dict);
538   if (!trim_dictionary (dict, OP_EXPORT, NULL))
539     goto error;
540   proc->map = finish_case_map (dict);
541   if (proc->map != NULL)
542     case_create (&proc->bounce, dict_get_next_value_idx (dict));
543
544   proc->writer = pfm_open_writer (fh, dict);
545   if (proc->writer == NULL)
546     goto error;
547   
548   dict_destroy (dict);
549
550   procedure (export_write_case_func, proc);
551   export_proc_free (proc);
552
553   return CMD_SUCCESS;
554
555  error:
556   dict_destroy (dict);
557   export_proc_free (proc);
558   return CMD_FAILURE;
559 }
560
561 /* Writes case C to the EXPORT file. */
562 static int
563 export_write_case_func (struct ccase *c, void *aux) 
564 {
565   struct export_proc *proc = aux;
566   if (proc->map == NULL)
567     pfm_write_case (proc->writer, c);
568   else 
569     {
570       map_case (proc->map, c, &proc->bounce);
571       pfm_write_case (proc->writer, &proc->bounce);
572     }
573   return 1;
574 }
575
576 static void
577 export_proc_free (struct export_proc *proc) 
578 {
579   if (proc != NULL) 
580     {
581       pfm_close_writer (proc->writer);
582       destroy_case_map (proc->map);
583       case_destroy (&proc->bounce);
584     }
585 }
586 \f
587 /* MATCH FILES. */
588
589 #include "debug-print.h"
590
591 /* File types. */
592 enum
593   {
594     MTF_FILE,                   /* Specified on FILE= subcommand. */
595     MTF_TABLE                   /* Specified on TABLE= subcommand. */
596   };
597
598 /* One of the files on MATCH FILES. */
599 struct mtf_file
600   {
601     struct mtf_file *next, *prev;
602                                 /* Next, previous in the list of files. */
603     struct mtf_file *next_min;  /* Next in the chain of minimums. */
604     
605     int type;                   /* One of MTF_*. */
606     struct variable **by;       /* List of BY variables for this file. */
607     struct file_handle *handle; /* File handle. */
608     struct sfm_reader *reader;  /* System file reader. */
609     struct dictionary *dict;    /* Dictionary from system file. */
610     char in[9];                 /* Name of the variable from IN=. */
611     char first[9], last[9];     /* Name of the variables from FIRST=, LAST=. */
612     struct ccase input;         /* Input record. */
613   };
614
615 /* MATCH FILES procedure. */
616 struct mtf_proc 
617   {
618     struct mtf_file *head;      /* First file mentioned on FILE or TABLE. */
619     struct mtf_file *tail;      /* Last file mentioned on FILE or TABLE. */
620     
621     struct variable **by;       /* Variables on the BY subcommand. */
622     size_t by_cnt;              /* Number of variables on BY subcommand. */
623
624     struct dictionary *dict;    /* Dictionary of output file. */
625     struct case_sink *sink;     /* Sink to receive output. */
626     struct ccase *mtf_case;     /* Case used for output. */
627
628     unsigned seq_num;           /* Have we initialized this variable? */
629     unsigned *seq_nums;         /* Sequence numbers for each var in dict. */
630   };
631
632 static void mtf_free (struct mtf_proc *);
633 static void mtf_free_file (struct mtf_file *);
634 static int mtf_merge_dictionary (struct dictionary *const, struct mtf_file *);
635 static void mtf_delete_file_in_place (struct mtf_proc *, struct mtf_file **);
636
637 static void mtf_read_nonactive_records (void *);
638 static void mtf_processing_finish (void *);
639 static int mtf_processing (struct ccase *, void *);
640
641 static char *var_type_description (struct variable *);
642
643 static void set_master (struct variable *, struct variable *master);
644 static struct variable *get_master (struct variable *);
645
646 /* Parse and execute the MATCH FILES command. */
647 int
648 cmd_match_files (void)
649 {
650   struct mtf_proc mtf;
651   struct mtf_file *first_table = NULL;
652   struct mtf_file *iter;
653   
654   int seen = 0;
655   
656   mtf.head = mtf.tail = NULL;
657   mtf.by = NULL;
658   mtf.by_cnt = 0;
659   mtf.dict = dict_create ();
660   mtf.sink = NULL;
661   mtf.mtf_case = NULL;
662   mtf.seq_num = 0;
663   mtf.seq_nums = NULL;
664   dict_set_case_limit (mtf.dict, dict_get_case_limit (default_dict));
665   
666   do
667     {
668       lex_match ('/');
669
670       if (lex_match (T_BY))
671         {
672           if (seen & 1)
673             {
674               msg (SE, _("The BY subcommand may be given once at most."));
675               goto error;
676             }
677           seen |= 1;
678               
679           lex_match ('=');
680           if (!parse_variables (mtf.dict, &mtf.by, &mtf.by_cnt,
681                                 PV_NO_DUPLICATE | PV_NO_SCRATCH))
682             goto error;
683         }
684       else if (token != T_ID)
685         {
686           lex_error (NULL);
687           goto error;
688         }
689       else if (lex_id_match ("FILE", tokid) || lex_id_match ("TABLE", tokid))
690         {
691           struct mtf_file *file = xmalloc (sizeof *file);
692
693           if (lex_match_id ("FILE"))
694             file->type = MTF_FILE;
695           else if (lex_match_id ("TABLE"))
696             {
697               file->type = MTF_TABLE;
698               seen |= 4;
699             }
700           else
701             assert (0);
702
703           file->by = NULL;
704           file->handle = NULL;
705           file->reader = NULL;
706           file->dict = NULL;
707           file->in[0] = '\0';
708           file->first[0] = '\0';
709           file->last[0] = '\0';
710           case_nullify (&file->input);
711
712           /* FILEs go first, then TABLEs. */
713           if (file->type == MTF_TABLE || first_table == NULL)
714             {
715               file->next = NULL;
716               file->prev = mtf.tail;
717               if (mtf.tail)
718                 mtf.tail->next = file;
719               mtf.tail = file;
720               if (mtf.head == NULL)
721                 mtf.head = file;
722               if (file->type == MTF_TABLE && first_table == NULL)
723                 first_table = file;
724             }
725           else 
726             {
727               assert (file->type == MTF_FILE);
728               file->next = first_table;
729               file->prev = first_table->prev;
730               if (first_table->prev)
731                 first_table->prev->next = file;
732               else
733                 mtf.head = file;
734               first_table->prev = file;
735             }
736           
737           lex_match ('=');
738           
739           if (lex_match ('*'))
740             {
741               file->handle = NULL;
742               file->reader = NULL;
743               
744               if (seen & 2)
745                 {
746                   msg (SE, _("The active file may not be specified more "
747                              "than once."));
748                   goto error;
749                 }
750               seen |= 2;
751
752               assert (pgm_state != STATE_INPUT);
753               if (pgm_state == STATE_INIT)
754                 {
755                   msg (SE, _("Cannot specify the active file since no active "
756                              "file has been defined."));
757                   goto error;
758                 }
759
760               if (temporary != 0)
761                 {
762                   msg (SE,
763                        _("MATCH FILES may not be used after TEMPORARY when "
764                          "the active file is an input source.  "
765                          "Temporary transformations will be made permanent."));
766                   cancel_temporary (); 
767                 }
768
769               file->dict = default_dict;
770             }
771           else
772             {
773               file->handle = fh_parse ();
774               if (file->handle == NULL)
775                 goto error;
776
777               file->reader = sfm_open_reader (file->handle, &file->dict, NULL);
778               if (file->reader == NULL)
779                 goto error;
780
781               case_create (&file->input, dict_get_next_value_idx (file->dict));
782             }
783         }
784       else if (lex_id_match ("IN", tokid)
785                || lex_id_match ("FIRST", tokid)
786                || lex_id_match ("LAST", tokid))
787         {
788           const char *sbc;
789           char *name;
790           
791           if (mtf.tail == NULL)
792             {
793               msg (SE, _("IN, FIRST, and LAST subcommands may not occur "
794                          "before the first FILE or TABLE."));
795               goto error;
796             }
797
798           if (lex_match_id ("IN"))
799             {
800               name = mtf.tail->in;
801               sbc = "IN";
802             }
803           else if (lex_match_id ("FIRST"))
804             {
805               name = mtf.tail->first;
806               sbc = "FIRST";
807             }
808           else if (lex_match_id ("LAST"))
809             {
810               name = mtf.tail->last;
811               sbc = "LAST";
812             }
813           else 
814             {
815               assert (0);
816               abort ();
817             }
818
819           lex_match ('=');
820           if (token != T_ID)
821             {
822               lex_error (NULL);
823               goto error;
824             }
825
826           if (*name)
827             {
828               msg (SE, _("Multiple %s subcommands for a single FILE or "
829                          "TABLE."),
830                    sbc);
831               goto error;
832             }
833           strcpy (name, tokid);
834           lex_get ();
835
836           if (!dict_create_var (mtf.dict, name, 0))
837             {
838               msg (SE, _("Duplicate variable name %s while creating %s "
839                          "variable."),
840                    name, sbc);
841               goto error;
842             }
843         }
844       else if (lex_id_match ("RENAME", tokid)
845                || lex_id_match ("KEEP", tokid)
846                || lex_id_match ("DROP", tokid))
847         {
848           if (mtf.tail == NULL)
849             {
850               msg (SE, _("RENAME, KEEP, and DROP subcommands may not occur "
851                          "before the first FILE or TABLE."));
852               goto error;
853             }
854
855           if (!trim_dictionary (mtf.tail->dict, OP_MATCH, NULL))
856             goto error;
857         }
858       else if (lex_match_id ("MAP"))
859         {
860           /* FIXME. */
861         }
862       else
863         {
864           lex_error (NULL);
865           goto error;
866         }
867     }
868   while (token != '.');
869
870   for (iter = mtf.head; iter != NULL; iter = iter->next) 
871     mtf_merge_dictionary (mtf.dict, iter);
872
873   if (seen & 4)
874     {
875       if (!(seen & 1))
876         {
877           msg (SE, _("The BY subcommand is required when a TABLE subcommand "
878                      "is given."));
879           goto error;
880         }
881     }
882
883   if (seen & 1)
884     {
885       for (iter = mtf.head; iter != NULL; iter = iter->next)
886         {
887           int i;
888           
889           iter->by = xmalloc (sizeof *iter->by * mtf.by_cnt);
890
891           for (i = 0; i < mtf.by_cnt; i++)
892             {
893               iter->by[i] = dict_lookup_var (iter->dict, mtf.by[i]->name);
894               if (iter->by[i] == NULL)
895                 {
896                   msg (SE, _("File %s lacks BY variable %s."),
897                        iter->handle ? handle_get_name (iter->handle) : "*",
898                        mtf.by[i]->name);
899                   goto error;
900                 }
901             }
902         }
903     }
904
905   /* MATCH FILES performs an n-way merge on all its input files.
906      Abstract algorithm:
907
908      1. Read one input record from every input FILE.
909
910      2. If no FILEs are left, stop.  Otherwise, proceed to step 3.
911
912      3. Find the FILE input record with minimum BY values.  Store all
913      the values from this input record into the output record.
914
915      4. Find all the FILE input records with BY values identical to
916      the minimums.  Store all the values from these input records into
917      the output record.
918
919      5. For every TABLE, read another record as long as the BY values
920      on the TABLE's input record are less than the FILEs' BY values.
921      If an exact match is found, store all the values from the TABLE
922      input record into the output record.
923
924      6. Write the output record.
925
926      7. Read another record from each input file FILE and TABLE that
927      we stored values from above.  If we come to the end of one of the
928      input files, remove it from the list of input files.
929
930      8. Repeat from step 2.
931
932      Unfortunately, this algorithm can't be directly implemented
933      because there's no function to read a record from the active
934      file; instead, it has to be done using callbacks.
935
936      FIXME: For merging large numbers of files (more than 10?) a
937      better algorithm would use a heap for finding minimum
938      values. */
939
940   if (!(seen & 2))
941     discard_variables ();
942
943   mtf.sink = create_case_sink (&storage_sink_class, mtf.dict, NULL);
944
945   mtf.seq_nums = xmalloc (dict_get_var_cnt (mtf.dict)
946                           * sizeof *mtf.seq_nums);
947   memset (mtf.seq_nums, 0,
948           dict_get_var_cnt (mtf.dict) * sizeof *mtf.seq_nums);
949   mtf.mtf_case = xmalloc (dict_get_case_size (mtf.dict));
950
951   mtf_read_nonactive_records (NULL);
952   if (seen & 2)
953     procedure (mtf_processing, NULL);
954   mtf_processing_finish (NULL);
955
956   dict_destroy (default_dict);
957   default_dict = mtf.dict;
958   mtf.dict = NULL;
959   vfm_source = mtf.sink->class->make_source (mtf.sink);
960   free_case_sink (mtf.sink);
961   
962   mtf_free (&mtf);
963   return CMD_SUCCESS;
964   
965 error:
966   mtf_free (&mtf);
967   return CMD_FAILURE;
968 }
969
970 /* Repeats 2...8 an arbitrary number of times. */
971 static void
972 mtf_processing_finish (void *mtf_)
973 {
974   struct mtf_proc *mtf = mtf_;
975   struct mtf_file *iter;
976
977   /* Find the active file and delete it. */
978   for (iter = mtf->head; iter; iter = iter->next)
979     if (iter->handle == NULL)
980       {
981         mtf_delete_file_in_place (mtf, &iter);
982         break;
983       }
984   
985   while (mtf->head && mtf->head->type == MTF_FILE)
986     if (!mtf_processing (NULL, mtf))
987       break;
988 }
989
990 /* Return a string in a static buffer describing V's variable type and
991    width. */
992 static char *
993 var_type_description (struct variable *v)
994 {
995   static char buf[2][32];
996   static int x = 0;
997   char *s;
998
999   x ^= 1;
1000   s = buf[x];
1001
1002   if (v->type == NUMERIC)
1003     strcpy (s, "numeric");
1004   else
1005     {
1006       assert (v->type == ALPHA);
1007       sprintf (s, "string with width %d", v->width);
1008     }
1009   return s;
1010 }
1011
1012 /* Free FILE and associated data. */
1013 static void
1014 mtf_free_file (struct mtf_file *file)
1015 {
1016   free (file->by);
1017   sfm_close_reader (file->reader);
1018   if (file->dict != default_dict)
1019     dict_destroy (file->dict);
1020   case_destroy (&file->input);
1021   free (file);
1022 }
1023
1024 /* Free all the data for the MATCH FILES procedure. */
1025 static void
1026 mtf_free (struct mtf_proc *mtf)
1027 {
1028   struct mtf_file *iter, *next;
1029
1030   for (iter = mtf->head; iter; iter = next)
1031     {
1032       next = iter->next;
1033
1034       mtf_free_file (iter);
1035     }
1036   
1037   free (mtf->by);
1038   if (mtf->dict)
1039     dict_destroy (mtf->dict);
1040   free (mtf->seq_nums);
1041 }
1042
1043 /* Remove *FILE from the mtf_file chain.  Make *FILE point to the next
1044    file in the chain, or to NULL if was the last in the chain. */
1045 static void
1046 mtf_delete_file_in_place (struct mtf_proc *mtf, struct mtf_file **file)
1047 {
1048   struct mtf_file *f = *file;
1049
1050   if (f->prev)
1051     f->prev->next = f->next;
1052   if (f->next)
1053     f->next->prev = f->prev;
1054   if (f == mtf->head)
1055     mtf->head = f->next;
1056   if (f == mtf->tail)
1057     mtf->tail = f->prev;
1058   *file = f->next;
1059
1060   {
1061     int i;
1062
1063     for (i = 0; i < dict_get_var_cnt (f->dict); i++)
1064       {
1065         struct variable *v = dict_get_var (f->dict, i);
1066         union value *out = case_data_rw (mtf->mtf_case, get_master (v)->fv);
1067           
1068         if (v->type == NUMERIC)
1069           out->f = SYSMIS;
1070         else
1071           memset (out->s, ' ', v->width);
1072       }
1073   }
1074
1075   mtf_free_file (f);
1076 }
1077
1078 /* Read a record from every input file except the active file. */
1079 static void
1080 mtf_read_nonactive_records (void *mtf_ UNUSED)
1081 {
1082   struct mtf_proc *mtf = mtf_;
1083   struct mtf_file *iter;
1084
1085   for (iter = mtf->head; iter; )
1086     {
1087       if (iter->handle)
1088         {
1089           if (!sfm_read_case (iter->reader, &iter->input))
1090             mtf_delete_file_in_place (mtf, &iter);
1091           else
1092             iter = iter->next;
1093         }
1094       else
1095         iter = iter->next;
1096     }
1097 }
1098
1099 /* Compare the BY variables for files A and B; return -1 if A < B, 0
1100    if A == B, 1 if A > B. */
1101 static inline int
1102 mtf_compare_BY_values (struct mtf_proc *mtf,
1103                        struct mtf_file *a, struct mtf_file *b,
1104                        struct ccase *c)
1105 {
1106   struct ccase *a_input, *b_input;
1107   int i;
1108
1109   assert ((a == NULL) + (b == NULL) + (c == NULL) <= 1);
1110   a_input = case_is_null (&a->input) ? c : &a->input;
1111   b_input = case_is_null (&b->input) ? c : &b->input;
1112   for (i = 0; i < mtf->by_cnt; i++)
1113     {
1114       assert (a->by[i]->type == b->by[i]->type);
1115       assert (a->by[i]->width == b->by[i]->width);
1116       
1117       if (a->by[i]->type == NUMERIC)
1118         {
1119           double af = case_num (a_input, a->by[i]->fv);
1120           double bf = case_num (b_input, b->by[i]->fv);
1121
1122           if (af < bf)
1123             return -1;
1124           else if (af > bf)
1125             return 1;
1126         }
1127       else 
1128         {
1129           int result;
1130           
1131           assert (a->by[i]->type == ALPHA);
1132           result = memcmp (case_str (a_input, a->by[i]->fv),
1133                            case_str (b_input, b->by[i]->fv),
1134                            a->by[i]->width);
1135           if (result < 0)
1136             return -1;
1137           else if (result > 0)
1138             return 1;
1139         }
1140     }
1141   return 0;
1142 }
1143
1144 /* Perform one iteration of steps 3...7 above. */
1145 static int
1146 mtf_processing (struct ccase *c, void *mtf_ UNUSED)
1147 {
1148   struct mtf_proc *mtf = mtf_;
1149   struct mtf_file *min_head, *min_tail; /* Files with minimum BY values. */
1150   struct mtf_file *max_head, *max_tail; /* Files with non-minimum BY values. */
1151   struct mtf_file *iter;                /* Iterator. */
1152
1153   for (;;)
1154     {
1155       /* If the active file doesn't have the minimum BY values, don't
1156          return because that would cause a record to be skipped. */
1157       int advance = 1;
1158
1159       if (mtf->head->type == MTF_TABLE)
1160         return 0;
1161       
1162       /* 3. Find the FILE input record with minimum BY values.  Store
1163          all the values from this input record into the output record.
1164
1165          4. Find all the FILE input records with BY values identical
1166          to the minimums.  Store all the values from these input
1167          records into the output record. */
1168       min_head = min_tail = mtf->head;
1169       max_head = max_tail = NULL;
1170       for (iter = mtf->head->next; iter && iter->type == MTF_FILE;
1171            iter = iter->next)
1172         switch (mtf_compare_BY_values (mtf, min_head, iter, c))
1173           {
1174           case -1:
1175             if (max_head)
1176               max_tail = max_tail->next_min = iter;
1177             else
1178               max_head = max_tail = iter;
1179             break;
1180
1181           case 0:
1182             min_tail = min_tail->next_min = iter;
1183             break;
1184
1185           case 1:
1186             if (max_head)
1187               {
1188                 max_tail->next_min = min_head;
1189                 max_tail = min_tail;
1190               }
1191             else
1192               {
1193                 max_head = min_head;
1194                 max_tail = min_tail;
1195               }
1196             min_head = min_tail = iter;
1197             break;
1198
1199           default:
1200             assert (0);
1201           }
1202
1203       /* 5. For every TABLE, read another record as long as the BY
1204          values on the TABLE's input record are less than the FILEs'
1205          BY values.  If an exact match is found, store all the values
1206          from the TABLE input record into the output record. */
1207       while (iter)
1208         {
1209           struct mtf_file *next = iter->next;
1210           
1211           assert (iter->type == MTF_TABLE);
1212       
1213           if (iter->handle == NULL)
1214             advance = 0;
1215
1216         again:
1217           switch (mtf_compare_BY_values (mtf, min_head, iter, c))
1218             {
1219             case -1:
1220               if (max_head)
1221                 max_tail = max_tail->next_min = iter;
1222               else
1223                 max_head = max_tail = iter;
1224               break;
1225
1226             case 0:
1227               min_tail = min_tail->next_min = iter;
1228               break;
1229
1230             case 1:
1231               if (iter->handle == NULL)
1232                 return 1;
1233               if (sfm_read_case (iter->reader, &iter->input))
1234                 goto again;
1235               mtf_delete_file_in_place (mtf, &iter);
1236               break;
1237
1238             default:
1239               assert (0);
1240             }
1241
1242           iter = next;
1243         }
1244
1245       /* Next sequence number. */
1246       mtf->seq_num++;
1247   
1248       /* Store data to all the records we are using. */
1249       if (min_tail)
1250         min_tail->next_min = NULL;
1251       for (iter = min_head; iter; iter = iter->next_min)
1252         {
1253           int i;
1254
1255           for (i = 0; i < dict_get_var_cnt (iter->dict); i++)
1256             {
1257               struct variable *v = dict_get_var (iter->dict, i);
1258               struct ccase *record;
1259               union value *out;
1260           
1261               if (mtf->seq_nums[get_master (v)->index] == mtf->seq_num)
1262                 continue;
1263               mtf->seq_nums[get_master (v)->index] = mtf->seq_num;
1264
1265               record = case_is_null (&iter->input) ? c : &iter->input;
1266
1267               assert (v->type == NUMERIC || v->type == ALPHA);
1268               out = case_data_rw (mtf->mtf_case, get_master (v)->fv);
1269               if (v->type == NUMERIC)
1270                 out->f = case_num (record, v->fv);
1271               else
1272                 memcpy (out->s, case_str (record, v->fv), v->width);
1273             }
1274         }
1275
1276       /* Store missing values to all the records we're not using. */
1277       if (max_tail)
1278         max_tail->next_min = NULL;
1279       for (iter = max_head; iter; iter = iter->next_min)
1280         {
1281           int i;
1282
1283           for (i = 0; i < dict_get_var_cnt (iter->dict); i++)
1284             {
1285               struct variable *v = dict_get_var (iter->dict, i);
1286               union value *out;
1287           
1288               if (mtf->seq_nums[get_master (v)->index] == mtf->seq_num)
1289                 continue;
1290               mtf->seq_nums[get_master (v)->index] = mtf->seq_num;
1291
1292               out = case_data_rw (mtf->mtf_case, get_master (v)->fv);
1293               if (v->type == NUMERIC)
1294                 out->f = SYSMIS;
1295               else
1296                 memset (out->s, ' ', v->width);
1297             }
1298
1299           if (iter->handle == NULL)
1300             advance = 0;
1301         }
1302
1303       /* 6. Write the output record. */
1304       mtf->sink->class->write (mtf->sink, mtf->mtf_case);
1305
1306       /* 7. Read another record from each input file FILE and TABLE
1307          that we stored values from above.  If we come to the end of
1308          one of the input files, remove it from the list of input
1309          files. */
1310       for (iter = min_head; iter && iter->type == MTF_FILE; )
1311         {
1312           struct mtf_file *next = iter->next_min;
1313           
1314           if (iter->reader != NULL)
1315             {
1316               if (!sfm_read_case (iter->reader, &iter->input))
1317                 mtf_delete_file_in_place (mtf, &iter);
1318             }
1319
1320           iter = next;
1321         }
1322       
1323       if (advance)
1324         break;
1325     }
1326
1327   return (mtf->head && mtf->head->type != MTF_TABLE);
1328 }
1329
1330 /* Merge the dictionary for file F into master dictionary M. */
1331 static int
1332 mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f)
1333 {
1334   struct dictionary *d = f->dict;
1335   const char *d_docs, *m_docs;
1336
1337   if (dict_get_label (m) == NULL)
1338     dict_set_label (m, dict_get_label (d));
1339
1340   d_docs = dict_get_documents (d);
1341   m_docs = dict_get_documents (m);
1342   if (d_docs != NULL) 
1343     {
1344       if (m_docs == NULL)
1345         dict_set_documents (m, d_docs);
1346       else
1347         {
1348           char *new_docs;
1349           size_t new_len;
1350
1351           new_len = strlen (m_docs) + strlen (d_docs);
1352           new_docs = xmalloc (new_len + 1);
1353           strcpy (new_docs, m_docs);
1354           strcat (new_docs, d_docs);
1355           dict_set_documents (m, new_docs);
1356           free (new_docs);
1357         }
1358     }
1359   
1360   dict_compact_values (d);
1361
1362   {
1363     int i;
1364
1365     for (i = 0; i < dict_get_var_cnt (d); i++)
1366       {
1367         struct variable *dv = dict_get_var (d, i);
1368         struct variable *mv = dict_lookup_var (m, dv->name);
1369
1370         assert (dv->type == ALPHA || dv->width == 0);
1371         assert (!mv || mv->type == ALPHA || mv->width == 0);
1372         if (mv && dv->width == mv->width)
1373           {
1374             if (val_labs_count (dv->val_labs)
1375                 && !val_labs_count (mv->val_labs))
1376               mv->val_labs = val_labs_copy (dv->val_labs);
1377             if (dv->miss_type != MISSING_NONE
1378                 && mv->miss_type == MISSING_NONE)
1379               copy_missing_values (mv, dv);
1380           }
1381         if (mv && dv->label && !mv->label)
1382           mv->label = xstrdup (dv->label);
1383         if (!mv) 
1384           {
1385             mv = dict_clone_var (m, dv, dv->name);
1386             assert (mv != NULL);
1387           }
1388         else if (mv->width != dv->width)
1389           {
1390             msg (SE, _("Variable %s in file %s (%s) has different "
1391                        "type or width from the same variable in "
1392                        "earlier file (%s)."),
1393                  dv->name, handle_get_name (f->handle),
1394                  var_type_description (dv), var_type_description (mv));
1395             return 0;
1396           }
1397         set_master (dv, mv);
1398       }
1399   }
1400
1401   return 1;
1402 }
1403
1404 /* Marks V's master variable as MASTER. */
1405 static void
1406 set_master (struct variable *v, struct variable *master) 
1407 {
1408   var_attach_aux (v, master, NULL);
1409 }
1410
1411 /* Returns the master variable corresponding to V,
1412    as set with set_master(). */
1413 static struct variable *
1414 get_master (struct variable *v) 
1415 {
1416   assert (v->aux != NULL);
1417   return v->aux;
1418 }
1419 \f
1420 /* IMPORT command. */
1421
1422 /* IMPORT input program. */
1423 struct import_pgm 
1424   {
1425     struct pfm_reader *reader;  /* Portable file reader. */
1426     struct case_map *map;       /* Map from system file to active file dict. */
1427     struct ccase bounce;        /* Bounce buffer. */
1428   };
1429
1430 static void import_pgm_free (struct import_pgm *);
1431
1432 /* Parses the IMPORT command. */
1433 int
1434 cmd_import (void)
1435 {
1436   struct import_pgm *pgm = NULL;
1437   struct file_handle *fh = NULL;
1438   struct dictionary *dict = NULL;
1439   int type;
1440
1441   pgm = xmalloc (sizeof *pgm);
1442   pgm->reader = NULL;
1443   pgm->map = NULL;
1444   case_nullify (&pgm->bounce);
1445
1446   for (;;)
1447     {
1448       lex_match ('/');
1449       
1450       if (lex_match_id ("FILE") || token == T_STRING)
1451         {
1452           lex_match ('=');
1453
1454           fh = fh_parse ();
1455           if (fh == NULL)
1456             return CMD_FAILURE;
1457         }
1458       else if (lex_match_id ("TYPE"))
1459         {
1460           lex_match ('=');
1461
1462           if (lex_match_id ("COMM"))
1463             type = PFM_COMM;
1464           else if (lex_match_id ("TAPE"))
1465             type = PFM_TAPE;
1466           else
1467             {
1468               lex_error (_("expecting COMM or TAPE"));
1469               return CMD_FAILURE;
1470             }
1471         }
1472       else break;
1473     }
1474   if (!lex_match ('/') && token != '.')
1475     {
1476       lex_error (NULL);
1477       return CMD_FAILURE;
1478     }
1479
1480   discard_variables ();
1481
1482   pgm->reader = pfm_open_reader (fh, &dict, NULL);
1483   if (pgm->reader == NULL)
1484     return CMD_FAILURE;
1485   case_create (&pgm->bounce, dict_get_next_value_idx (dict));
1486   
1487   start_case_map (dict);
1488   if (!trim_dictionary (dict, OP_READ, NULL))
1489     goto error;
1490   pgm->map = finish_case_map (dict);
1491   
1492   dict_destroy (default_dict);
1493   default_dict = dict;
1494
1495   vfm_source = create_case_source (&import_source_class, default_dict, pgm);
1496
1497   return CMD_SUCCESS;
1498
1499  error:
1500   import_pgm_free (pgm);
1501   if (dict != NULL)
1502     dict_destroy (dict);
1503   return CMD_FAILURE;
1504 }
1505
1506 /* Frees a struct import_pgm. */
1507 static void
1508 import_pgm_free (struct import_pgm *pgm) 
1509 {
1510   if (pgm != NULL) 
1511     {
1512       pfm_close_reader (pgm->reader);
1513       destroy_case_map (pgm->map);
1514       case_destroy (&pgm->bounce);
1515       free (pgm);
1516     }
1517 }
1518
1519 /* Clears internal state related to IMPORT input procedure. */
1520 static void
1521 import_source_destroy (struct case_source *source)
1522 {
1523   struct import_pgm *pgm = source->aux;
1524   import_pgm_free (pgm);
1525 }
1526
1527 /* Reads all the cases from the data file into C and passes them
1528    to WRITE_CASE one by one, passing WC_DATA. */
1529 static void
1530 import_source_read (struct case_source *source,
1531                  struct ccase *c,
1532                  write_case_func *write_case, write_case_data wc_data)
1533 {
1534   struct import_pgm *pgm = source->aux;
1535   int ok;
1536
1537   do
1538     {
1539       if (pgm->map == NULL)
1540         ok = pfm_read_case (pgm->reader, c);
1541       else
1542         {
1543           ok = pfm_read_case (pgm->reader, &pgm->bounce);
1544           if (ok)
1545             map_case (pgm->map, &pgm->bounce, c);
1546         }
1547
1548       if (ok)
1549         ok = write_case (wc_data);
1550     }
1551   while (ok);
1552 }
1553
1554 const struct case_source_class import_source_class =
1555   {
1556     "IMPORT",
1557     NULL,
1558     import_source_read,
1559     import_source_destroy,
1560   };
1561
1562 \f
1563 /* Case map.
1564
1565    A case map copies data from a case that corresponds for one
1566    dictionary to a case that corresponds to a second dictionary
1567    derived from the first by, optionally, deleting, reordering,
1568    or renaming variables.  (No new variables may be created.)
1569    */
1570
1571 /* A case map. */
1572 struct case_map
1573   {
1574     size_t value_cnt;   /* Number of values in map. */
1575     int *map;           /* For each destination index, the
1576                            corresponding source index. */
1577   };
1578
1579 /* Prepares dictionary D for producing a case map.  Afterward,
1580    the caller may delete, reorder, or rename variables within D
1581    at will before using finish_case_map() to produce the case
1582    map.
1583
1584    Uses D's aux members, which may not otherwise be in use. */
1585 static void
1586 start_case_map (struct dictionary *d) 
1587 {
1588   size_t var_cnt = dict_get_var_cnt (d);
1589   size_t i;
1590   
1591   for (i = 0; i < var_cnt; i++)
1592     {
1593       struct variable *v = dict_get_var (d, i);
1594       int *src_fv = xmalloc (sizeof *src_fv);
1595       *src_fv = v->fv;
1596       var_attach_aux (v, src_fv, var_dtor_free);
1597     }
1598 }
1599
1600 /* Produces a case map from dictionary D, which must have been
1601    previously prepared with start_case_map().
1602
1603    Does not retain any reference to D, and clears the aux members
1604    set up by start_case_map().
1605
1606    Returns the new case map, or a null pointer if no mapping is
1607    required (that is, no data has changed position). */
1608 static struct case_map *
1609 finish_case_map (struct dictionary *d) 
1610 {
1611   struct case_map *map;
1612   size_t var_cnt = dict_get_var_cnt (d);
1613   size_t i;
1614   int identity_map;
1615
1616   map = xmalloc (sizeof *map);
1617   map->value_cnt = dict_get_next_value_idx (d);
1618   map->map = xmalloc (sizeof *map->map * map->value_cnt);
1619   for (i = 0; i < map->value_cnt; i++)
1620     map->map[i] = -1;
1621
1622   identity_map = 1;
1623   for (i = 0; i < var_cnt; i++) 
1624     {
1625       struct variable *v = dict_get_var (d, i);
1626       int src_fv = *(int *) var_detach_aux (v);
1627       size_t idx;
1628
1629       if (v->fv != src_fv)
1630         identity_map = 0;
1631       
1632       for (idx = 0; idx < v->nv; idx++)
1633         {
1634           int src_idx = src_fv + idx;
1635           int dst_idx = v->fv + idx;
1636           
1637           assert (map->map[dst_idx] == -1);
1638           map->map[dst_idx] = src_idx;
1639         }
1640     }
1641
1642   if (identity_map) 
1643     {
1644       destroy_case_map (map);
1645       return NULL;
1646     }
1647
1648   while (map->value_cnt > 0 && map->map[map->value_cnt - 1] == -1)
1649     map->value_cnt--;
1650
1651   return map;
1652 }
1653
1654 /* Maps from SRC to DST, applying case map MAP. */
1655 static void
1656 map_case (const struct case_map *map,
1657           const struct ccase *src, struct ccase *dst) 
1658 {
1659   size_t dst_idx;
1660
1661   assert (map != NULL);
1662   assert (src != NULL);
1663   assert (dst != NULL);
1664   assert (src != dst);
1665
1666   for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
1667     {
1668       int src_idx = map->map[dst_idx];
1669       if (src_idx != -1)
1670         *case_data_rw (dst, dst_idx) = *case_data (src, src_idx);
1671     }
1672 }
1673
1674 /* Destroys case map MAP. */
1675 static void
1676 destroy_case_map (struct case_map *map) 
1677 {
1678   if (map != NULL) 
1679     {
1680       free (map->map);
1681       free (map);
1682     }
1683 }