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