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