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