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