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