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