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