44e5af4ad2403acc60a3289da1169c090d545538
[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           free (by);
891         }
892       else if (lex_match_id ("FIRST")) 
893         {
894           if (mtf.first[0] != '\0')
895             {
896               msg (SE, _("FIRST may appear at most once."));
897               goto error;
898             }
899               
900           lex_match ('=');
901           if (!lex_force_id ())
902             goto error;
903           strcpy (mtf.first, tokid);
904           lex_get ();
905         }
906       else if (lex_match_id ("LAST")) 
907         {
908           if (mtf.last[0] != '\0')
909             {
910               msg (SE, _("LAST may appear at most once."));
911               goto error;
912             }
913               
914           lex_match ('=');
915           if (!lex_force_id ())
916             goto error;
917           strcpy (mtf.last, tokid);
918           lex_get ();
919         }
920       else if (lex_match_id ("MAP"))
921         {
922           /* FIXME. */
923         }
924       else if (lex_match_id ("DROP")) 
925         {
926           if (!drop_variables (mtf.dict))
927             goto error;
928         }
929       else if (lex_match_id ("KEEP")) 
930         {
931           if (!keep_variables (mtf.dict))
932             goto error;
933         }
934       else
935         {
936           lex_error (NULL);
937           goto error;
938         }
939
940       if (!lex_match ('/') && token != '.') 
941         {
942           lex_end_of_command ();
943           goto error;
944         }
945     }
946
947   if (mtf.by_cnt == 0)
948     {
949       if (saw_table)
950         {
951           msg (SE, _("BY is required when TABLE is specified."));
952           goto error;
953         }
954       if (saw_in)
955         {
956           msg (SE, _("BY is required when IN is specified."));
957           goto error;
958         }
959     }
960
961   /* Set up mapping from each file's variables to master
962      variables. */
963   for (iter = mtf.head; iter != NULL; iter = iter->next)
964     {
965       struct dictionary *d = iter->dict;
966       int i;
967
968       for (i = 0; i < dict_get_var_cnt (d); i++)
969         {
970           struct variable *v = dict_get_var (d, i);
971           struct variable *mv = dict_lookup_var (mtf.dict, v->name);
972           if (mv != NULL)
973             set_master (v, mv);
974         }
975     }
976
977   /* Add IN variables to master dictionary. */
978   for (iter = mtf.head; iter != NULL; iter = iter->next) 
979     if (iter->in_name != NULL)
980       {
981         iter->in_var = dict_create_var (mtf.dict, iter->in_name, 0);
982         if (iter->in_var == NULL)
983           {
984             msg (SE, _("IN variable name %s duplicates an "
985                        "existing variable name."),
986                  iter->in_var);
987             goto error;
988           }
989         iter->in_var->print = iter->in_var->write
990           = make_output_format (FMT_F, 1, 0);
991       }
992     
993   /* MATCH FILES performs an n-way merge on all its input files.
994      Abstract algorithm:
995
996      1. Read one input record from every input FILE.
997
998      2. If no FILEs are left, stop.  Otherwise, proceed to step 3.
999
1000      3. Find the FILE input record(s) that have minimum BY
1001      values.  Store all the values from these input records into
1002      the output record.
1003
1004      4. For every TABLE, read another record as long as the BY values
1005      on the TABLE's input record are less than the FILEs' BY values.
1006      If an exact match is found, store all the values from the TABLE
1007      input record into the output record.
1008
1009      5. Write the output record.
1010
1011      6. Read another record from each input file FILE and TABLE that
1012      we stored values from above.  If we come to the end of one of the
1013      input files, remove it from the list of input files.
1014
1015      7. Repeat from step 2.
1016
1017      Unfortunately, this algorithm can't be implemented in a
1018      straightforward way because there's no function to read a
1019      record from the active file.  Instead, it has to be written
1020      as a state machine.
1021
1022      FIXME: For merging large numbers of files (more than 10?) a
1023      better algorithm would use a heap for finding minimum
1024      values. */
1025
1026   if (!used_active_file)
1027     discard_variables ();
1028
1029   dict_compact_values (mtf.dict);
1030   mtf.sink = create_case_sink (&storage_sink_class, mtf.dict, NULL);
1031   if (mtf.sink->class->open != NULL)
1032     mtf.sink->class->open (mtf.sink);
1033
1034   mtf.seq_nums = xcalloc (dict_get_var_cnt (mtf.dict), sizeof *mtf.seq_nums);
1035   case_create (&mtf.mtf_case, dict_get_next_value_idx (mtf.dict));
1036
1037   mtf_read_nonactive_records (&mtf);
1038   if (used_active_file)
1039     procedure (mtf_processing, &mtf);
1040   mtf_processing_finish (&mtf);
1041
1042   free_case_source (vfm_source);
1043   vfm_source = NULL;
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   if (mtf->head->type == MTF_TABLE)
1209     return 1;
1210   
1211   do
1212     {
1213       struct mtf_file *min_head, *min_tail; /* Files with minimum BY values. */
1214       struct mtf_file *max_head, *max_tail; /* Files with non-minimum BYs. */
1215       struct mtf_file *iter, *next;
1216
1217       read_active_file = false;
1218       
1219       /* 3. Find the FILE input record(s) that have minimum BY
1220          values.  Store all the values from these input records into
1221          the output record. */
1222       min_head = min_tail = mtf->head;
1223       max_head = max_tail = NULL;
1224       for (iter = mtf->head->next; iter && iter->type == MTF_FILE;
1225            iter = iter->next) 
1226         {
1227           int cmp = mtf_compare_BY_values (mtf, min_head, iter, c);
1228           if (cmp < 0) 
1229             {
1230               if (max_head)
1231                 max_tail = max_tail->next_min = iter;
1232               else
1233                 max_head = max_tail = iter;
1234             }
1235           else if (cmp == 0) 
1236             min_tail = min_tail->next_min = iter;
1237           else /* cmp > 0 */
1238             {
1239               if (max_head)
1240                 {
1241                   max_tail->next_min = min_head;
1242                   max_tail = min_tail;
1243                 }
1244               else
1245                 {
1246                   max_head = min_head;
1247                   max_tail = min_tail;
1248                 }
1249               min_head = min_tail = iter;
1250             }
1251         }
1252       
1253       /* 4. For every TABLE, read another record as long as the BY
1254          values on the TABLE's input record are less than the FILEs'
1255          BY values.  If an exact match is found, store all the values
1256          from the TABLE input record into the output record. */
1257       for (; iter != NULL; iter = next)
1258         {
1259           assert (iter->type == MTF_TABLE);
1260       
1261           next = iter->next;
1262           for (;;) 
1263             {
1264               int cmp = mtf_compare_BY_values (mtf, min_head, iter, c);
1265               if (cmp < 0) 
1266                 {
1267                   if (max_head)
1268                     max_tail = max_tail->next_min = iter;
1269                   else
1270                     max_head = max_tail = iter;
1271                 }
1272               else if (cmp == 0)
1273                 min_tail = min_tail->next_min = iter;
1274               else /* cmp > 0 */
1275                 {
1276                   if (iter->handle == NULL)
1277                     return 1;
1278                   if (sfm_read_case (iter->reader, &iter->input))
1279                     continue;
1280                   mtf_delete_file_in_place (mtf, &iter);
1281                 }
1282               break;
1283             }
1284         }
1285
1286       /* Next sequence number. */
1287       mtf->seq_num++;
1288
1289       /* Store data to all the records we are using. */
1290       if (min_tail)
1291         min_tail->next_min = NULL;
1292       for (iter = min_head; iter; iter = iter->next_min)
1293         {
1294           int i;
1295
1296           for (i = 0; i < dict_get_var_cnt (iter->dict); i++)
1297             {
1298               struct variable *v = dict_get_var (iter->dict, i);
1299               struct variable *mv = get_master (v);
1300           
1301               if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num) 
1302                 {
1303                   struct ccase *record
1304                     = case_is_null (&iter->input) ? c : &iter->input;
1305                   union value *out = case_data_rw (&mtf->mtf_case, mv->fv);
1306
1307                   mtf->seq_nums[mv->index] = mtf->seq_num;
1308                   if (v->type == NUMERIC)
1309                     out->f = case_num (record, v->fv);
1310                   else
1311                     memcpy (out->s, case_str (record, v->fv), v->width);
1312                 } 
1313             }
1314           if (iter->in_var != NULL)
1315             case_data_rw (&mtf->mtf_case, iter->in_var->fv)->f = 1.;
1316
1317           if (iter->type == MTF_FILE && iter->handle == NULL)
1318             read_active_file = true;
1319         }
1320
1321       /* Store missing values to all the records we're not
1322          using. */
1323       if (max_tail)
1324         max_tail->next_min = NULL;
1325       for (iter = max_head; iter; iter = iter->next_min)
1326         {
1327           int i;
1328
1329           for (i = 0; i < dict_get_var_cnt (iter->dict); i++)
1330             {
1331               struct variable *v = dict_get_var (iter->dict, i);
1332               struct variable *mv = get_master (v);
1333
1334               if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num) 
1335                 {
1336                   union value *out = case_data_rw (&mtf->mtf_case, mv->fv);
1337                   mtf->seq_nums[mv->index] = mtf->seq_num;
1338
1339                   if (v->type == NUMERIC)
1340                     out->f = SYSMIS;
1341                   else
1342                     memset (out->s, ' ', v->width);
1343                 }
1344             }
1345           if (iter->in_var != NULL)
1346             case_data_rw (&mtf->mtf_case, iter->in_var->fv)->f = 0.;
1347         }
1348
1349       /* 5. Write the output record. */
1350       mtf->sink->class->write (mtf->sink, &mtf->mtf_case);
1351
1352       /* 6. Read another record from each input file FILE and TABLE
1353          that we stored values from above.  If we come to the end of
1354          one of the input files, remove it from the list of input
1355          files. */
1356       for (iter = min_head; iter && iter->type == MTF_FILE; iter = next)
1357         {
1358           next = iter->next_min;
1359           if (iter->reader != NULL
1360               && !sfm_read_case (iter->reader, &iter->input))
1361             mtf_delete_file_in_place (mtf, &iter);
1362         }
1363     }
1364   while (!read_active_file
1365          && mtf->head != NULL && mtf->head->type == MTF_FILE);
1366
1367   return mtf->head != NULL && mtf->head->type == MTF_FILE;
1368 }
1369
1370 /* Merge the dictionary for file F into master dictionary M. */
1371 static int
1372 mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f)
1373 {
1374   struct dictionary *d = f->dict;
1375   const char *d_docs, *m_docs;
1376   int i;
1377
1378   if (dict_get_label (m) == NULL)
1379     dict_set_label (m, dict_get_label (d));
1380
1381   d_docs = dict_get_documents (d);
1382   m_docs = dict_get_documents (m);
1383   if (d_docs != NULL) 
1384     {
1385       if (m_docs == NULL)
1386         dict_set_documents (m, d_docs);
1387       else
1388         {
1389           char *new_docs;
1390           size_t new_len;
1391
1392           new_len = strlen (m_docs) + strlen (d_docs);
1393           new_docs = xmalloc (new_len + 1);
1394           strcpy (new_docs, m_docs);
1395           strcat (new_docs, d_docs);
1396           dict_set_documents (m, new_docs);
1397           free (new_docs);
1398         }
1399     }
1400   
1401   for (i = 0; i < dict_get_var_cnt (d); i++)
1402     {
1403       struct variable *dv = dict_get_var (d, i);
1404       struct variable *mv = dict_lookup_var (m, dv->name);
1405
1406       if (dict_class_from_id (dv->name) == DC_SCRATCH)
1407         continue;
1408
1409       if (mv != NULL)
1410         {
1411           if (mv->width != dv->width) 
1412             {
1413               msg (SE, _("Variable %s in file %s (%s) has different "
1414                          "type or width from the same variable in "
1415                          "earlier file (%s)."),
1416                    dv->name, handle_get_name (f->handle),
1417                    var_type_description (dv), var_type_description (mv));
1418               return 0;
1419             }
1420         
1421           if (dv->width == mv->width)
1422             {
1423               if (val_labs_count (dv->val_labs)
1424                   && !val_labs_count (mv->val_labs))
1425                 mv->val_labs = val_labs_copy (dv->val_labs);
1426               if (dv->miss_type != MISSING_NONE
1427                   && mv->miss_type == MISSING_NONE)
1428                 copy_missing_values (mv, dv);
1429             }
1430
1431           if (dv->label && !mv->label)
1432             mv->label = xstrdup (dv->label);
1433         }
1434       else
1435         mv = dict_clone_var_assert (m, dv, dv->name);
1436     }
1437
1438   return 1;
1439 }
1440
1441 /* Marks V's master variable as MASTER. */
1442 static void
1443 set_master (struct variable *v, struct variable *master) 
1444 {
1445   var_attach_aux (v, master, NULL);
1446 }
1447
1448 /* Returns the master variable corresponding to V,
1449    as set with set_master(). */
1450 static struct variable *
1451 get_master (struct variable *v) 
1452 {
1453   return v->aux;
1454 }
1455 \f
1456 /* IMPORT command. */
1457
1458 /* IMPORT input program. */
1459 struct import_pgm 
1460   {
1461     struct pfm_reader *reader;  /* Portable file reader. */
1462     struct case_map *map;       /* Map from system file to active file dict. */
1463     struct ccase bounce;        /* Bounce buffer. */
1464   };
1465
1466 static void import_pgm_free (struct import_pgm *);
1467
1468 /* Parses the IMPORT command. */
1469 int
1470 cmd_import (void)
1471 {
1472   struct import_pgm *pgm = NULL;
1473   struct file_handle *fh = NULL;
1474   struct dictionary *dict = NULL;
1475   int type;
1476
1477   pgm = xmalloc (sizeof *pgm);
1478   pgm->reader = NULL;
1479   pgm->map = NULL;
1480   case_nullify (&pgm->bounce);
1481
1482   for (;;)
1483     {
1484       lex_match ('/');
1485       
1486       if (lex_match_id ("FILE") || token == T_STRING)
1487         {
1488           lex_match ('=');
1489
1490           fh = fh_parse ();
1491           if (fh == NULL)
1492             return CMD_FAILURE;
1493         }
1494       else if (lex_match_id ("TYPE"))
1495         {
1496           lex_match ('=');
1497
1498           if (lex_match_id ("COMM"))
1499             type = PFM_COMM;
1500           else if (lex_match_id ("TAPE"))
1501             type = PFM_TAPE;
1502           else
1503             {
1504               lex_error (_("expecting COMM or TAPE"));
1505               return CMD_FAILURE;
1506             }
1507         }
1508       else break;
1509     }
1510   if (!lex_match ('/') && token != '.')
1511     {
1512       lex_error (NULL);
1513       return CMD_FAILURE;
1514     }
1515
1516   discard_variables ();
1517
1518   pgm->reader = pfm_open_reader (fh, &dict, NULL);
1519   if (pgm->reader == NULL)
1520     return CMD_FAILURE;
1521   case_create (&pgm->bounce, dict_get_next_value_idx (dict));
1522   
1523   start_case_map (dict);
1524   if (!trim_dictionary (dict, OP_READ, NULL))
1525     goto error;
1526   pgm->map = finish_case_map (dict);
1527   
1528   dict_destroy (default_dict);
1529   default_dict = dict;
1530
1531   vfm_source = create_case_source (&import_source_class, pgm);
1532
1533   return CMD_SUCCESS;
1534
1535  error:
1536   import_pgm_free (pgm);
1537   if (dict != NULL)
1538     dict_destroy (dict);
1539   return CMD_FAILURE;
1540 }
1541
1542 /* Frees a struct import_pgm. */
1543 static void
1544 import_pgm_free (struct import_pgm *pgm) 
1545 {
1546   if (pgm != NULL) 
1547     {
1548       pfm_close_reader (pgm->reader);
1549       destroy_case_map (pgm->map);
1550       case_destroy (&pgm->bounce);
1551       free (pgm);
1552     }
1553 }
1554
1555 /* Clears internal state related to IMPORT input procedure. */
1556 static void
1557 import_source_destroy (struct case_source *source)
1558 {
1559   struct import_pgm *pgm = source->aux;
1560   import_pgm_free (pgm);
1561 }
1562
1563 /* Reads all the cases from the data file into C and passes them
1564    to WRITE_CASE one by one, passing WC_DATA. */
1565 static void
1566 import_source_read (struct case_source *source,
1567                  struct ccase *c,
1568                  write_case_func *write_case, write_case_data wc_data)
1569 {
1570   struct import_pgm *pgm = source->aux;
1571   int ok;
1572
1573   do
1574     {
1575       if (pgm->map == NULL)
1576         ok = pfm_read_case (pgm->reader, c);
1577       else
1578         {
1579           ok = pfm_read_case (pgm->reader, &pgm->bounce);
1580           if (ok)
1581             map_case (pgm->map, &pgm->bounce, c);
1582         }
1583
1584       if (ok)
1585         ok = write_case (wc_data);
1586     }
1587   while (ok);
1588 }
1589
1590 const struct case_source_class import_source_class =
1591   {
1592     "IMPORT",
1593     NULL,
1594     import_source_read,
1595     import_source_destroy,
1596   };
1597
1598 \f
1599 /* Case map.
1600
1601    A case map copies data from a case that corresponds for one
1602    dictionary to a case that corresponds to a second dictionary
1603    derived from the first by, optionally, deleting, reordering,
1604    or renaming variables.  (No new variables may be created.)
1605    */
1606
1607 /* A case map. */
1608 struct case_map
1609   {
1610     size_t value_cnt;   /* Number of values in map. */
1611     int *map;           /* For each destination index, the
1612                            corresponding source index. */
1613   };
1614
1615 /* Prepares dictionary D for producing a case map.  Afterward,
1616    the caller may delete, reorder, or rename variables within D
1617    at will before using finish_case_map() to produce the case
1618    map.
1619
1620    Uses D's aux members, which may not otherwise be in use. */
1621 static void
1622 start_case_map (struct dictionary *d) 
1623 {
1624   size_t var_cnt = dict_get_var_cnt (d);
1625   size_t i;
1626   
1627   for (i = 0; i < var_cnt; i++)
1628     {
1629       struct variable *v = dict_get_var (d, i);
1630       int *src_fv = xmalloc (sizeof *src_fv);
1631       *src_fv = v->fv;
1632       var_attach_aux (v, src_fv, var_dtor_free);
1633     }
1634 }
1635
1636 /* Produces a case map from dictionary D, which must have been
1637    previously prepared with start_case_map().
1638
1639    Does not retain any reference to D, and clears the aux members
1640    set up by start_case_map().
1641
1642    Returns the new case map, or a null pointer if no mapping is
1643    required (that is, no data has changed position). */
1644 static struct case_map *
1645 finish_case_map (struct dictionary *d) 
1646 {
1647   struct case_map *map;
1648   size_t var_cnt = dict_get_var_cnt (d);
1649   size_t i;
1650   int identity_map;
1651
1652   map = xmalloc (sizeof *map);
1653   map->value_cnt = dict_get_next_value_idx (d);
1654   map->map = xmalloc (sizeof *map->map * map->value_cnt);
1655   for (i = 0; i < map->value_cnt; i++)
1656     map->map[i] = -1;
1657
1658   identity_map = 1;
1659   for (i = 0; i < var_cnt; i++) 
1660     {
1661       struct variable *v = dict_get_var (d, i);
1662       int *src_fv = (int *) var_detach_aux (v);
1663       size_t idx;
1664
1665       if (v->fv != *src_fv)
1666         identity_map = 0;
1667       
1668       for (idx = 0; idx < v->nv; idx++)
1669         {
1670           int src_idx = *src_fv + idx;
1671           int dst_idx = v->fv + idx;
1672           
1673           assert (map->map[dst_idx] == -1);
1674           map->map[dst_idx] = src_idx;
1675         }
1676       free (src_fv);
1677     }
1678
1679   if (identity_map) 
1680     {
1681       destroy_case_map (map);
1682       return NULL;
1683     }
1684
1685   while (map->value_cnt > 0 && map->map[map->value_cnt - 1] == -1)
1686     map->value_cnt--;
1687
1688   return map;
1689 }
1690
1691 /* Maps from SRC to DST, applying case map MAP. */
1692 static void
1693 map_case (const struct case_map *map,
1694           const struct ccase *src, struct ccase *dst) 
1695 {
1696   size_t dst_idx;
1697
1698   assert (map != NULL);
1699   assert (src != NULL);
1700   assert (dst != NULL);
1701   assert (src != dst);
1702
1703   for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
1704     {
1705       int src_idx = map->map[dst_idx];
1706       if (src_idx != -1)
1707         *case_data_rw (dst, dst_idx) = *case_data (src, src_idx);
1708     }
1709 }
1710
1711 /* Destroys case map MAP. */
1712 static void
1713 destroy_case_map (struct case_map *map) 
1714 {
1715   if (map != NULL) 
1716     {
1717       free (map->map);
1718       free (map);
1719     }
1720 }