Clean up treatment of missing values by moving all the code into
[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 (!mv_is_empty (&dv->miss) && mv_is_empty (&mv->miss))
1430                 mv_copy (&mv->miss, &dv->miss);
1431             }
1432
1433           if (dv->label && !mv->label)
1434             mv->label = xstrdup (dv->label);
1435         }
1436       else
1437         mv = dict_clone_var_assert (m, dv, dv->name);
1438     }
1439
1440   return 1;
1441 }
1442
1443 /* Marks V's master variable as MASTER. */
1444 static void
1445 set_master (struct variable *v, struct variable *master) 
1446 {
1447   var_attach_aux (v, master, NULL);
1448 }
1449
1450 /* Returns the master variable corresponding to V,
1451    as set with set_master(). */
1452 static struct variable *
1453 get_master (struct variable *v) 
1454 {
1455   return v->aux;
1456 }
1457 \f
1458 /* IMPORT command. */
1459
1460 /* IMPORT input program. */
1461 struct import_pgm 
1462   {
1463     struct pfm_reader *reader;  /* Portable file reader. */
1464     struct case_map *map;       /* Map from system file to active file dict. */
1465     struct ccase bounce;        /* Bounce buffer. */
1466   };
1467
1468 static void import_pgm_free (struct import_pgm *);
1469
1470 /* Parses the IMPORT command. */
1471 int
1472 cmd_import (void)
1473 {
1474   struct import_pgm *pgm = NULL;
1475   struct file_handle *fh = NULL;
1476   struct dictionary *dict = NULL;
1477   int type;
1478
1479   pgm = xmalloc (sizeof *pgm);
1480   pgm->reader = NULL;
1481   pgm->map = NULL;
1482   case_nullify (&pgm->bounce);
1483
1484   for (;;)
1485     {
1486       lex_match ('/');
1487       
1488       if (lex_match_id ("FILE") || token == T_STRING)
1489         {
1490           lex_match ('=');
1491
1492           fh = fh_parse ();
1493           if (fh == NULL)
1494             return CMD_FAILURE;
1495         }
1496       else if (lex_match_id ("TYPE"))
1497         {
1498           lex_match ('=');
1499
1500           if (lex_match_id ("COMM"))
1501             type = PFM_COMM;
1502           else if (lex_match_id ("TAPE"))
1503             type = PFM_TAPE;
1504           else
1505             {
1506               lex_error (_("expecting COMM or TAPE"));
1507               return CMD_FAILURE;
1508             }
1509         }
1510       else break;
1511     }
1512   if (!lex_match ('/') && token != '.')
1513     {
1514       lex_error (NULL);
1515       return CMD_FAILURE;
1516     }
1517
1518   discard_variables ();
1519
1520   pgm->reader = pfm_open_reader (fh, &dict, NULL);
1521   if (pgm->reader == NULL)
1522     return CMD_FAILURE;
1523   case_create (&pgm->bounce, dict_get_next_value_idx (dict));
1524   
1525   start_case_map (dict);
1526   if (!trim_dictionary (dict, OP_READ, NULL))
1527     goto error;
1528   pgm->map = finish_case_map (dict);
1529   
1530   dict_destroy (default_dict);
1531   default_dict = dict;
1532
1533   vfm_source = create_case_source (&import_source_class, pgm);
1534
1535   return CMD_SUCCESS;
1536
1537  error:
1538   import_pgm_free (pgm);
1539   if (dict != NULL)
1540     dict_destroy (dict);
1541   return CMD_FAILURE;
1542 }
1543
1544 /* Frees a struct import_pgm. */
1545 static void
1546 import_pgm_free (struct import_pgm *pgm) 
1547 {
1548   if (pgm != NULL) 
1549     {
1550       pfm_close_reader (pgm->reader);
1551       destroy_case_map (pgm->map);
1552       case_destroy (&pgm->bounce);
1553       free (pgm);
1554     }
1555 }
1556
1557 /* Clears internal state related to IMPORT input procedure. */
1558 static void
1559 import_source_destroy (struct case_source *source)
1560 {
1561   struct import_pgm *pgm = source->aux;
1562   import_pgm_free (pgm);
1563 }
1564
1565 /* Reads all the cases from the data file into C and passes them
1566    to WRITE_CASE one by one, passing WC_DATA. */
1567 static void
1568 import_source_read (struct case_source *source,
1569                  struct ccase *c,
1570                  write_case_func *write_case, write_case_data wc_data)
1571 {
1572   struct import_pgm *pgm = source->aux;
1573   int ok;
1574
1575   do
1576     {
1577       if (pgm->map == NULL)
1578         ok = pfm_read_case (pgm->reader, c);
1579       else
1580         {
1581           ok = pfm_read_case (pgm->reader, &pgm->bounce);
1582           if (ok)
1583             map_case (pgm->map, &pgm->bounce, c);
1584         }
1585
1586       if (ok)
1587         ok = write_case (wc_data);
1588     }
1589   while (ok);
1590 }
1591
1592 const struct case_source_class import_source_class =
1593   {
1594     "IMPORT",
1595     NULL,
1596     import_source_read,
1597     import_source_destroy,
1598   };
1599
1600 \f
1601 /* Case map.
1602
1603    A case map copies data from a case that corresponds for one
1604    dictionary to a case that corresponds to a second dictionary
1605    derived from the first by, optionally, deleting, reordering,
1606    or renaming variables.  (No new variables may be created.)
1607    */
1608
1609 /* A case map. */
1610 struct case_map
1611   {
1612     size_t value_cnt;   /* Number of values in map. */
1613     int *map;           /* For each destination index, the
1614                            corresponding source index. */
1615   };
1616
1617 /* Prepares dictionary D for producing a case map.  Afterward,
1618    the caller may delete, reorder, or rename variables within D
1619    at will before using finish_case_map() to produce the case
1620    map.
1621
1622    Uses D's aux members, which may not otherwise be in use. */
1623 static void
1624 start_case_map (struct dictionary *d) 
1625 {
1626   size_t var_cnt = dict_get_var_cnt (d);
1627   size_t i;
1628   
1629   for (i = 0; i < var_cnt; i++)
1630     {
1631       struct variable *v = dict_get_var (d, i);
1632       int *src_fv = xmalloc (sizeof *src_fv);
1633       *src_fv = v->fv;
1634       var_attach_aux (v, src_fv, var_dtor_free);
1635     }
1636 }
1637
1638 /* Produces a case map from dictionary D, which must have been
1639    previously prepared with start_case_map().
1640
1641    Does not retain any reference to D, and clears the aux members
1642    set up by start_case_map().
1643
1644    Returns the new case map, or a null pointer if no mapping is
1645    required (that is, no data has changed position). */
1646 static struct case_map *
1647 finish_case_map (struct dictionary *d) 
1648 {
1649   struct case_map *map;
1650   size_t var_cnt = dict_get_var_cnt (d);
1651   size_t i;
1652   int identity_map;
1653
1654   map = xmalloc (sizeof *map);
1655   map->value_cnt = dict_get_next_value_idx (d);
1656   map->map = xmalloc (sizeof *map->map * map->value_cnt);
1657   for (i = 0; i < map->value_cnt; i++)
1658     map->map[i] = -1;
1659
1660   identity_map = 1;
1661   for (i = 0; i < var_cnt; i++) 
1662     {
1663       struct variable *v = dict_get_var (d, i);
1664       int *src_fv = (int *) var_detach_aux (v);
1665       size_t idx;
1666
1667       if (v->fv != *src_fv)
1668         identity_map = 0;
1669       
1670       for (idx = 0; idx < v->nv; idx++)
1671         {
1672           int src_idx = *src_fv + idx;
1673           int dst_idx = v->fv + idx;
1674           
1675           assert (map->map[dst_idx] == -1);
1676           map->map[dst_idx] = src_idx;
1677         }
1678       free (src_fv);
1679     }
1680
1681   if (identity_map) 
1682     {
1683       destroy_case_map (map);
1684       return NULL;
1685     }
1686
1687   while (map->value_cnt > 0 && map->map[map->value_cnt - 1] == -1)
1688     map->value_cnt--;
1689
1690   return map;
1691 }
1692
1693 /* Maps from SRC to DST, applying case map MAP. */
1694 static void
1695 map_case (const struct case_map *map,
1696           const struct ccase *src, struct ccase *dst) 
1697 {
1698   size_t dst_idx;
1699
1700   assert (map != NULL);
1701   assert (src != NULL);
1702   assert (dst != NULL);
1703   assert (src != dst);
1704
1705   for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
1706     {
1707       int src_idx = map->map[dst_idx];
1708       if (src_idx != -1)
1709         *case_data_rw (dst, dst_idx) = *case_data (src, src_idx);
1710     }
1711 }
1712
1713 /* Destroys case map MAP. */
1714 static void
1715 destroy_case_map (struct case_map *map) 
1716 {
1717   if (map != NULL) 
1718     {
1719       free (map->map);
1720       free (map);
1721     }
1722 }