Implemented long variable names a la spss V12.
[pspp-builds.git] / src / dictionary.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 "dictionary.h"
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include "algorithm.h"
25 #include "alloc.h"
26 #include "case.h"
27 #include "error.h"
28 #include "hash.h"
29 #include "misc.h"
30 #include "str.h"
31 #include "value-labels.h"
32 #include "var.h"
33
34 /* A dictionary. */
35 struct dictionary
36   {
37     struct variable **var;      /* Variables. */
38     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
39     struct hsh_table *name_tab; /* Variable index by name. */
40     struct hsh_table *long_name_tab; /* Variable indexed by long name */
41     int next_value_idx;         /* Index of next `union value' to allocate. */
42     struct variable **split;    /* SPLIT FILE vars. */
43     size_t split_cnt;           /* SPLIT FILE count. */
44     struct variable *weight;    /* WEIGHT variable. */
45     struct variable *filter;    /* FILTER variable. */
46     int case_limit;             /* Current case limit (N command). */
47     char *label;                /* File label. */
48     char *documents;            /* Documents, as a string. */
49     struct vector **vector;     /* Vectors of variables. */
50     size_t vector_cnt;          /* Number of vectors. */
51   };
52
53
54
55
56
57 int
58 compare_long_names(const void *a_, const void *b_, void *aux UNUSED)
59 {
60   const struct name_table_entry *a = a_;
61   const struct name_table_entry *b = b_;
62
63   return strcasecmp(a->longname, b->longname);
64 }
65
66
67 /* Long names use case insensitive comparison */
68 unsigned int
69 hash_long_name (const void *e_, void *aux UNUSED) 
70 {
71   const struct name_table_entry *e = e_;
72   unsigned int hash;
73   int i;
74
75   char *s = strdup(e->longname);
76
77   for ( i = 0 ; i < strlen(s) ; ++i ) 
78     s[i] = toupper(s[i]);
79
80   hash = hsh_hash_string (s);
81   
82   free (s);
83
84   return hash;
85 }
86
87 static char *make_short_name(struct dictionary *dict, const char *longname) ;
88
89
90 /* Creates and returns a new dictionary. */
91 struct dictionary *
92 dict_create (void) 
93 {
94   struct dictionary *d = xmalloc (sizeof *d);
95   
96   d->var = NULL;
97   d->var_cnt = d->var_cap = 0;
98   d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL);
99   d->long_name_tab = hsh_create (8, compare_long_names, hash_long_name, NULL, NULL);
100   d->next_value_idx = 0;
101   d->split = NULL;
102   d->split_cnt = 0;
103   d->weight = NULL;
104   d->filter = NULL;
105   d->case_limit = 0;
106   d->label = NULL;
107   d->documents = NULL;
108   d->vector = NULL;
109   d->vector_cnt = 0;
110
111   return d;
112 }
113
114 /* Creates and returns a (deep) copy of an existing
115    dictionary. */
116 struct dictionary *
117 dict_clone (const struct dictionary *s) 
118 {
119   struct dictionary *d;
120   size_t i;
121
122   assert (s != NULL);
123
124   d = dict_create ();
125
126   for (i = 0; i < s->var_cnt; i++)
127     dict_clone_var (d, s->var[i], s->var[i]->name, s->var[i]->longname);
128
129   d->next_value_idx = s->next_value_idx;
130
131   d->split_cnt = s->split_cnt;
132   if (d->split_cnt > 0) 
133     {
134       d->split = xmalloc (d->split_cnt * sizeof *d->split);
135       for (i = 0; i < d->split_cnt; i++) 
136         d->split[i] = dict_lookup_var_assert (d, s->split[i]->name);
137     }
138
139   if (s->weight != NULL) 
140     d->weight = dict_lookup_var_assert (d, s->weight->name);
141
142   if (s->filter != NULL) 
143     d->filter = dict_lookup_var_assert (d, s->filter->name);
144
145   d->case_limit = s->case_limit;
146   dict_set_label (d, dict_get_label (s));
147   dict_set_documents (d, dict_get_documents (s));
148
149   for (i = 0; i < s->vector_cnt; i++) 
150     dict_create_vector (d, s->vector[i]->name,
151                         s->vector[i]->var, s->vector[i]->cnt);
152
153   return d;
154 }
155
156 /* Clears the contents from a dictionary without destroying the
157    dictionary itself. */
158 void
159 dict_clear (struct dictionary *d) 
160 {
161   /* FIXME?  Should we really clear case_limit, label, documents?
162      Others are necessarily cleared by deleting all the variables.*/
163   int i;
164
165   assert (d != NULL);
166
167   for (i = 0; i < d->var_cnt; i++) 
168     {
169       struct variable *v = d->var[i];
170       var_clear_aux (v);
171       val_labs_destroy (v->val_labs);
172       free (v->label);
173       free (v); 
174     }
175   free (d->var);
176   d->var = NULL;
177   d->var_cnt = d->var_cap = 0;
178   hsh_clear (d->name_tab);
179   if ( d->long_name_tab) 
180     hsh_clear (d->long_name_tab);
181   d->next_value_idx = 0;
182   free (d->split);
183   d->split = NULL;
184   d->split_cnt = 0;
185   d->weight = NULL;
186   d->filter = NULL;
187   d->case_limit = 0;
188   free (d->label);
189   d->label = NULL;
190   free (d->documents);
191   d->documents = NULL;
192   dict_clear_vectors (d);
193 }
194
195 /* Allocate the pointer TEXT and fill it with text representing the
196    long variable name buffer.  SIZE will contain the size of TEXT.
197    TEXT must be freed by the caller when no longer required.
198 */
199 void
200 dict_get_varname_block(const struct dictionary *dict, char **text, int *size)
201 {
202   char *buf = 0;
203   int bufsize = 0;
204   struct hsh_iterator hi;
205   struct name_table_entry *nte;
206   short first = 1;
207
208   for ( nte = hsh_first(dict->long_name_tab, &hi);
209         nte; 
210         nte = hsh_next(dict->long_name_tab, &hi))
211     {
212       bufsize += strlen(nte->name) + strlen(nte->longname) + 2;
213       buf = xrealloc(buf, bufsize + 1);
214       if ( first ) 
215         strcpy(buf, "");
216       first = 0;
217
218       strcat(buf, nte->name);
219       strcat(buf, "=");
220       strcat(buf, nte->longname);
221       strcat(buf, "\t");
222     }
223
224   if ( bufsize > 0 ) 
225     {
226       /* Loose the final delimiting TAB */
227       buf[bufsize]='\0';
228       bufsize--;
229     }
230   
231   *text = buf;
232   *size = bufsize;
233 }
234
235
236 /* Add a new entry into the dictionary's long name table, and update the 
237    corresponding varible with the relevant long name.
238 */
239 void
240 dict_add_longvar_entry(struct dictionary *d, 
241                        const char *name, 
242                        const char *longname)
243 {
244   struct variable *v;
245   assert ( name ) ;
246   assert ( longname );
247   struct name_table_entry *nte = xmalloc (sizeof (struct name_table_entry));
248   nte->longname = strdup(longname);
249   nte->name = strdup(name);
250
251
252   /* Look up the name in name_tab */
253   v = hsh_find ( d->name_tab, name);
254   if ( !v ) 
255     {
256       msg (FE, _("The entry \"%s\" in the variable name map, has no corresponding variable"), name);
257       return ;
258     }
259   assert ( 0 == strcmp(v->name, name) );
260   v->longname = nte->longname;
261
262   hsh_insert(d->long_name_tab, nte);
263   
264
265 }
266
267 /* Destroys the aux data for every variable in D, by calling
268    var_clear_aux() for each variable. */
269 void
270 dict_clear_aux (struct dictionary *d) 
271 {
272   int i;
273   
274   assert (d != NULL);
275   
276   for (i = 0; i < d->var_cnt; i++)
277     var_clear_aux (d->var[i]);
278 }
279
280 /* Clears a dictionary and destroys it. */
281 void
282 dict_destroy (struct dictionary *d)
283 {
284   if (d != NULL) 
285     {
286       dict_clear (d);
287       hsh_destroy (d->name_tab);
288       hsh_destroy (d->long_name_tab);
289       free (d);
290     }
291 }
292
293 /* Returns the number of variables in D. */
294 size_t
295 dict_get_var_cnt (const struct dictionary *d) 
296 {
297   assert (d != NULL);
298
299   return d->var_cnt;
300 }
301
302 /* Returns the variable in D with index IDX, which must be
303    between 0 and the count returned by dict_get_var_cnt(),
304    exclusive. */
305 struct variable *
306 dict_get_var (const struct dictionary *d, size_t idx) 
307 {
308   assert (d != NULL);
309   assert (idx < d->var_cnt);
310
311   return d->var[idx];
312 }
313
314 /* Sets *VARS to an array of pointers to variables in D and *CNT
315    to the number of variables in *D.  By default all variables
316    are returned, but bits may be set in EXCLUDE_CLASSES to
317    exclude ordinary, system, and/or scratch variables. */
318 void
319 dict_get_vars (const struct dictionary *d, struct variable ***vars,
320                size_t *cnt, unsigned exclude_classes)
321 {
322   size_t count;
323   size_t i;
324   
325   assert (d != NULL);
326   assert (vars != NULL);
327   assert (cnt != NULL);
328   assert ((exclude_classes & ~((1u << DC_ORDINARY)
329                                | (1u << DC_SYSTEM)
330                                | (1u << DC_SCRATCH))) == 0);
331   
332   count = 0;
333   for (i = 0; i < d->var_cnt; i++)
334     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
335       count++;
336
337   *vars = xmalloc (count * sizeof **vars);
338   *cnt = 0;
339   for (i = 0; i < d->var_cnt; i++)
340     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
341       (*vars)[(*cnt)++] = d->var[i];
342   assert (*cnt == count);
343 }
344
345
346 static struct variable * dict_create_var_x (struct dictionary *d, 
347                                             const char *name, int width, 
348                                             short name_is_short) ;
349
350 /* Creates and returns a new variable in D with the given LONGNAME
351    and WIDTH.  Returns a null pointer if the given LONGNAME would
352    duplicate that of an existing variable in the dictionary.
353 */
354 struct variable *
355 dict_create_var (struct dictionary *d, const char *longname, int width)
356 {
357   return dict_create_var_x(d, longname, width, 0);
358 }
359
360
361 /* Creates and returns a new variable in D with the given SHORTNAME and 
362    WIDTH.  The long name table is not updated */
363 struct variable *
364 dict_create_var_from_short (struct dictionary *d, const char *shortname, 
365                             int width)
366 {
367   return dict_create_var_x(d, shortname, width, 1);
368 }
369
370
371
372 /* Creates and returns a new variable in D with the given NAME
373    and WIDTH.  
374    If NAME_IS_SHORT, assume NAME is the short name.  Otherwise assumes
375    NAME is the long name, and creates the corresponding entry in the 
376    Dictionary's lookup name table .
377    Returns a null pointer if the given NAME would
378    duplicate that of an existing variable in the dictionary. 
379    
380 */
381 static struct variable *
382 dict_create_var_x (struct dictionary *d, const char *name, int width, 
383                  short name_is_short) 
384 {
385   struct variable *v;
386
387   assert (d != NULL);
388   assert (name != NULL);
389
390   assert (strlen (name) >= 1);
391
392   assert (width >= 0 && width < 256);
393     
394   if ( name_is_short ) 
395     assert(strlen (name) <= SHORT_NAME_LEN);
396   else
397     assert(strlen (name) <= LONG_NAME_LEN);
398
399   /* Make sure there's not already a variable by that name. */
400   if (dict_lookup_var (d, name) != NULL)
401     return NULL;
402
403   /* Allocate and initialize variable. */
404   v = xmalloc (sizeof *v);
405
406   if ( name_is_short )
407     {
408       strncpy (v->name, name, sizeof v->name);
409       v->name[SHORT_NAME_LEN] = '\0';
410     }
411   else
412     strcpy(v->name,make_short_name(d, name));
413   
414
415   v->index = d->var_cnt;
416   v->type = width == 0 ? NUMERIC : ALPHA;
417   v->width = width;
418   v->fv = d->next_value_idx;
419   v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
420   v->init = 1;
421   v->reinit = dict_class_from_id (v->name) != DC_SCRATCH;
422   v->miss_type = MISSING_NONE;
423   if (v->type == NUMERIC)
424     {
425       v->print.type = FMT_F;
426       v->print.w = 8;
427       v->print.d = 2;
428
429       v->alignment = ALIGN_RIGHT;
430       v->display_width = 8;
431       v->measure = MEASURE_SCALE;
432     }
433   else
434     {
435       v->print.type = FMT_A;
436       v->print.w = v->width;
437       v->print.d = 0;
438
439       v->alignment = ALIGN_LEFT;
440       v->display_width = 8;
441       v->measure = MEASURE_NOMINAL;
442     }
443   v->write = v->print;
444   v->val_labs = val_labs_create (v->width);
445   v->label = NULL;
446   v->aux = NULL;
447   v->aux_dtor = NULL;
448
449   /* Update dictionary. */
450   if (d->var_cnt >= d->var_cap) 
451     {
452       d->var_cap = 8 + 2 * d->var_cap; 
453       d->var = xrealloc (d->var, d->var_cap * sizeof *d->var);
454     }
455   d->var[v->index] = v;
456   d->var_cnt++;
457   hsh_force_insert (d->name_tab, v);
458
459   if ( ! name_is_short) 
460     dict_add_longvar_entry(d, v->name, name);
461
462   d->next_value_idx += v->nv;
463
464   return v;
465 }
466
467 /* Creates and returns a new variable in D with the given NAME
468    and WIDTH.  Assert-fails if the given NAME would duplicate
469    that of an existing variable in the dictionary. */
470 struct variable *
471 dict_create_var_assert (struct dictionary *d, const char *longname, int width)
472 {
473   struct variable *v = dict_create_var (d, longname, width);
474   assert (v != NULL);
475   return v;
476 }
477
478 /* Creates a new variable in D with longname LONGNAME, as a copy of
479    existing  variable OV, which need not be in D or in any
480    dictionary. 
481    If SHORTNAME is non null, it will be used as the short name
482    otherwise a new short name will be generated.
483 */
484 struct variable *
485 dict_clone_var (struct dictionary *d, const struct variable *ov,
486                 const char *name, const char *longname)
487 {
488   struct variable *nv;
489
490   assert (d != NULL);
491   assert (ov != NULL);
492   assert (strlen (longname) <= LONG_NAME_LEN);
493
494   struct name_table_entry *nte = xmalloc (sizeof (struct name_table_entry));
495
496   nte->longname = strdup(longname);
497   if ( name ) 
498     {
499       assert (strlen (name) >= 1);
500       assert (strlen (name) <= SHORT_NAME_LEN);
501       nte->name = strdup(name);
502     }
503   else 
504     nte->name = make_short_name(d, longname);
505
506
507   nv = dict_create_var_from_short (d, nte->name, ov->width);
508   if (nv == NULL)
509     return NULL;
510
511   hsh_insert(d->long_name_tab, nte);
512   nv->longname = nte->longname;
513
514   nv->init = 1;
515   nv->reinit = ov->reinit;
516   nv->miss_type = ov->miss_type;
517   memcpy (nv->missing, ov->missing, sizeof nv->missing);
518   nv->print = ov->print;
519   nv->write = ov->write;
520   val_labs_destroy (nv->val_labs);
521   nv->val_labs = val_labs_copy (ov->val_labs);
522   if (ov->label != NULL)
523     nv->label = xstrdup (ov->label);
524
525   nv->alignment = ov->alignment;
526   nv->measure = ov->measure;
527   nv->display_width = ov->display_width;
528
529   return nv;
530 }
531
532 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
533    a variable named NEW_NAME is already in D, except that
534    NEW_NAME may be the same as V's existing name. */
535 void 
536 dict_rename_var (struct dictionary *d, struct variable *v,
537                  const char *new_name) 
538 {
539   assert (d != NULL);
540   assert (v != NULL);
541   assert (new_name != NULL);
542   assert (strlen (new_name) >= 1 && strlen (new_name) <= SHORT_NAME_LEN);
543   assert (dict_contains_var (d, v));
544
545   if (!strcmp (v->name, new_name))
546     return;
547
548   assert (dict_lookup_var (d, new_name) == NULL);
549
550   hsh_force_delete (d->name_tab, v);
551   strncpy (v->name, new_name, sizeof v->name);
552   v->name[SHORT_NAME_LEN] = '\0';
553   hsh_force_insert (d->name_tab, v);
554 }
555
556 /* Returns the variable named NAME in D, or a null pointer if no
557    variable has that name. */
558 struct variable *
559 dict_lookup_var (const struct dictionary *d, const char *name)
560 {
561   struct variable v;
562   struct variable *vr;
563   
564   char *short_name;
565   struct name_table_entry key;
566   struct name_table_entry *nte;
567
568   assert (d != NULL);
569   assert (name != NULL);
570   assert (strlen (name) >= 1 && strlen (name) <= LONG_NAME_LEN);
571
572   key.longname = name;
573   nte = hsh_find (d->long_name_tab, &key);
574   
575   if ( ! nte ) 
576   {
577     return 0;
578   }
579
580   short_name = nte->name ;
581
582   strncpy (v.name, short_name, sizeof v.name);
583   v.name[SHORT_NAME_LEN] = '\0';
584
585   vr = hsh_find (d->name_tab, &v);
586
587   return vr; 
588 }
589
590
591 /* Returns the variable named NAME in D.  Assert-fails if no
592    variable has that name. */
593 struct variable *
594 dict_lookup_var_assert (const struct dictionary *d, const char *name)
595 {
596   struct variable *v = dict_lookup_var (d, name);
597   assert (v != NULL);
598   return v;
599 }
600
601 /* Returns nonzero if variable V is in dictionary D. */
602 int
603 dict_contains_var (const struct dictionary *d, const struct variable *v)
604 {
605   assert (d != NULL);
606   assert (v != NULL);
607
608   return v->index >= 0 && v->index < d->var_cnt && d->var[v->index] == v;
609 }
610
611 /* Compares two double pointers to variables, which should point
612    to elements of a struct dictionary's `var' member array. */
613 static int
614 compare_var_ptrs (const void *a_, const void *b_, void *aux UNUSED) 
615 {
616   struct variable *const *a = a_;
617   struct variable *const *b = b_;
618
619   return *a < *b ? -1 : *a > *b;
620 }
621
622 /* Deletes variable V from dictionary D and frees V.
623
624    This is a very bad idea if there might be any pointers to V
625    from outside D.  In general, no variable in default_dict
626    should be deleted when any transformations are active, because
627    those transformations might reference the deleted variable.
628    The safest time to delete a variable is just after a procedure
629    has been executed, as done by MODIFY VARS.
630
631    Pointers to V within D are not a problem, because
632    dict_delete_var() knows to remove V from split variables,
633    weights, filters, etc. */
634 void
635 dict_delete_var (struct dictionary *d, struct variable *v) 
636 {
637   size_t i;
638
639   assert (d != NULL);
640   assert (v != NULL);
641   assert (dict_contains_var (d, v));
642   assert (d->var[v->index] == v);
643
644   /* Delete aux data. */
645   var_clear_aux (v);
646
647   /* Remove V from splits, weight, filter variables. */
648   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
649                                &v, compare_var_ptrs, NULL);
650   if (d->weight == v)
651     d->weight = NULL;
652   if (d->filter == v)
653     d->filter = NULL;
654   dict_clear_vectors (d);
655
656   /* Remove V from var array. */
657   remove_element (d->var, d->var_cnt, sizeof *d->var, v->index);
658   d->var_cnt--;
659
660   /* Update index. */
661   for (i = v->index; i < d->var_cnt; i++)
662     d->var[i]->index = i;
663
664   /* Update name hash. */
665   hsh_force_delete (d->name_tab, v);
666
667   /* Free memory. */
668   val_labs_destroy (v->val_labs);
669   free (v->label);
670   free (v);
671 }
672
673 /* Deletes the COUNT variables listed in VARS from D.  This is
674    unsafe; see the comment on dict_delete_var() for details. */
675 void 
676 dict_delete_vars (struct dictionary *d,
677                   struct variable *const *vars, size_t count) 
678 {
679   /* FIXME: this can be done in O(count) time, but this algorithm
680      is O(count**2). */
681   assert (d != NULL);
682   assert (count == 0 || vars != NULL);
683
684   while (count-- > 0)
685     dict_delete_var (d, *vars++);
686 }
687
688 /* Reorders the variables in D, placing the COUNT variables
689    listed in ORDER in that order at the beginning of D.  The
690    other variables in D, if any, retain their relative
691    positions. */
692 void 
693 dict_reorder_vars (struct dictionary *d,
694                    struct variable *const *order, size_t count) 
695 {
696   struct variable **new_var;
697   size_t i;
698   
699   assert (d != NULL);
700   assert (count == 0 || order != NULL);
701   assert (count <= d->var_cnt);
702
703   new_var = xmalloc (d->var_cnt * sizeof *new_var);
704   memcpy (new_var, order, count * sizeof *new_var);
705   for (i = 0; i < count; i++) 
706     {
707       assert (d->var[order[i]->index] != NULL);
708       d->var[order[i]->index] = NULL;
709       order[i]->index = i;
710     }
711   for (i = 0; i < d->var_cnt; i++)
712     if (d->var[i] != NULL)
713       {
714         assert (count < d->var_cnt);
715         new_var[count] = d->var[i];
716         new_var[count]->index = count;
717         count++;
718       }
719   free (d->var);
720   d->var = new_var;
721 }
722
723 /* Renames COUNT variables specified in VARS to the names given
724    in NEW_NAMES within dictionary D.  If the renaming would
725    result in a duplicate variable name, returns zero and stores a
726    name that would be duplicated into *ERR_NAME (if ERR_NAME is
727    non-null).  Otherwise, the renaming is successful, and nonzero
728    is returned. */
729 int
730 dict_rename_vars (struct dictionary *d,
731                   struct variable **vars, char **new_names,
732                   size_t count, char **err_name) 
733 {
734   char **old_names;
735   size_t i;
736   int success = 1;
737
738
739   assert (d != NULL);
740   assert (count == 0 || vars != NULL);
741   assert (count == 0 || new_names != NULL);
742
743
744   old_names = xmalloc (count * sizeof *old_names);
745   for (i = 0; i < count; i++) 
746     {
747       assert (d->var[vars[i]->index] == vars[i]);
748       hsh_force_delete (d->name_tab, vars[i]);
749       old_names[i] = xstrdup (vars[i]->name);
750     }
751   
752   for (i = 0; i < count; i++)
753     {
754       struct name_table_entry key;
755       struct name_table_entry *nte;
756       assert (new_names[i] != NULL);
757       assert (*new_names[i] != '\0');
758       assert (strlen (new_names[i]) <= LONG_NAME_LEN );
759       strcpy (vars[i]->name, make_short_name(d, new_names[i]));
760
761
762       key.longname = vars[i]->longname;
763       nte = hsh_find (d->long_name_tab, &key);
764       
765       free( nte->longname ) ;
766       nte->longname = strdup ( new_names[i]);
767       vars[i]->longname = nte->longname;
768
769       if (hsh_insert (d->name_tab, vars[i]) != NULL )
770         {
771           size_t fail_idx = i;
772           if (err_name != NULL) 
773             *err_name = new_names[i];
774
775           for (i = 0; i < fail_idx; i++)
776             hsh_force_delete (d->name_tab, vars[i]);
777           
778           for (i = 0; i < count; i++)
779             {
780               strcpy (vars[i]->name, old_names[i]);
781               hsh_force_insert (d->name_tab, vars[i]);
782  
783       key.longname = vars[i]->longname;
784       nte = hsh_find (d->long_name_tab, &key);
785       
786       free( nte->longname ) ;
787       nte->longname = strdup ( old_names[i]);
788       vars[i]->longname = nte->longname;
789
790             }
791
792           success = 0;
793           break;
794         }
795     }
796
797   for (i = 0; i < count; i++)
798     free (old_names[i]);
799   free (old_names);
800
801   return success;
802 }
803
804 /* Returns the weighting variable in dictionary D, or a null
805    pointer if the dictionary is unweighted. */
806 struct variable *
807 dict_get_weight (const struct dictionary *d) 
808 {
809   assert (d != NULL);
810   assert (d->weight == NULL || dict_contains_var (d, d->weight));
811   
812   return d->weight;
813 }
814
815 /* Returns the value of D's weighting variable in case C, except that a
816    negative weight is returned as 0.  Returns 1 if the dictionary is
817    unweighted. Will warn about missing, negative, or zero values if
818    warn_on_invalid is nonzero. The function will set warn_on_invalid to zero
819    if an invalid weight is found. */
820 double
821 dict_get_case_weight (const struct dictionary *d, const struct ccase *c, 
822                       int *warn_on_invalid)
823 {
824   assert (d != NULL);
825   assert (c != NULL);
826
827   if (d->weight == NULL)
828     return 1.0;
829   else 
830     {
831       double w = case_num (c, d->weight->fv);
832       if ( w < 0.0 || w == SYSMIS || is_num_user_missing(w, d->weight) )
833         w = 0.0;
834       if ( w == 0.0 && *warn_on_invalid ) {
835           *warn_on_invalid = 0;
836           msg (SW, _("At least one case in the data file had a weight value "
837                      "that was user-missing, system-missing, zero, or "
838                      "negative.  These case(s) were ignored."));
839       }
840       return w;
841     }
842 }
843
844 /* Sets the weighting variable of D to V, or turning off
845    weighting if V is a null pointer. */
846 void
847 dict_set_weight (struct dictionary *d, struct variable *v) 
848 {
849   assert (d != NULL);
850   assert (v == NULL || dict_contains_var (d, v));
851   assert (v == NULL || v->type == NUMERIC);
852
853   d->weight = v;
854 }
855
856 /* Returns the filter variable in dictionary D (see cmd_filter())
857    or a null pointer if the dictionary is unfiltered. */
858 struct variable *
859 dict_get_filter (const struct dictionary *d) 
860 {
861   assert (d != NULL);
862   assert (d->filter == NULL || dict_contains_var (d, d->filter));
863   
864   return d->filter;
865 }
866
867 /* Sets V as the filter variable for dictionary D.  Passing a
868    null pointer for V turn off filtering. */
869 void
870 dict_set_filter (struct dictionary *d, struct variable *v)
871 {
872   assert (d != NULL);
873   assert (v == NULL || dict_contains_var (d, v));
874
875   d->filter = v;
876 }
877
878 /* Returns the case limit for dictionary D, or zero if the number
879    of cases is unlimited (see cmd_n()). */
880 int
881 dict_get_case_limit (const struct dictionary *d) 
882 {
883   assert (d != NULL);
884
885   return d->case_limit;
886 }
887
888 /* Sets CASE_LIMIT as the case limit for dictionary D.  Zero for
889    CASE_LIMIT indicates no limit. */
890 void
891 dict_set_case_limit (struct dictionary *d, int case_limit) 
892 {
893   assert (d != NULL);
894   assert (case_limit >= 0);
895
896   d->case_limit = case_limit;
897 }
898
899 /* Returns the index of the next value to be added to D.  This
900    value is the number of `union value's that need to be
901    allocated to store a case for dictionary D. */
902 int
903 dict_get_next_value_idx (const struct dictionary *d) 
904 {
905   assert (d != NULL);
906
907   return d->next_value_idx;
908 }
909
910 /* Returns the number of bytes needed to store a case for
911    dictionary D. */
912 size_t
913 dict_get_case_size (const struct dictionary *d) 
914 {
915   assert (d != NULL);
916
917   return sizeof (union value) * dict_get_next_value_idx (d);
918 }
919
920 /* Deletes scratch variables in dictionary D and reassigns values
921    so that fragmentation is eliminated. */
922 void
923 dict_compact_values (struct dictionary *d) 
924 {
925   size_t i;
926
927   d->next_value_idx = 0;
928   for (i = 0; i < d->var_cnt; )
929     {
930       struct variable *v = d->var[i];
931
932       if (dict_class_from_id (v->name) != DC_SCRATCH) 
933         {
934           v->fv = d->next_value_idx;
935           d->next_value_idx += v->nv;
936           i++;
937         }
938       else
939         dict_delete_var (default_dict, v);
940     }
941 }
942
943 /* Copies values from SRC, which represents a case arranged
944    according to dictionary D, to DST, which represents a case
945    arranged according to the dictionary that will be produced by
946    dict_compact_values(D). */
947 void
948 dict_compact_case (const struct dictionary *d,
949                    struct ccase *dst, const struct ccase *src)
950 {
951   size_t i;
952   size_t value_idx;
953
954   value_idx = 0;
955   for (i = 0; i < d->var_cnt; i++) 
956     {
957       struct variable *v = d->var[i];
958
959       if (dict_class_from_id (v->name) != DC_SCRATCH)
960         {
961           case_copy (dst, value_idx, src, v->fv, v->nv);
962           value_idx += v->nv;
963         }
964     }
965 }
966
967 /* Returns the number of values that would be used by a case if
968    dict_compact_values() were called. */
969 size_t
970 dict_get_compacted_value_cnt (const struct dictionary *d) 
971 {
972   size_t i;
973   size_t cnt;
974
975   cnt = 0;
976   for (i = 0; i < d->var_cnt; i++)
977     if (dict_class_from_id (d->var[i]->name) != DC_SCRATCH) 
978       cnt += d->var[i]->nv;
979   return cnt;
980 }
981
982 /* Creates and returns an array mapping from a dictionary index
983    to the `fv' that the corresponding variable will have after
984    calling dict_compact_values().  Scratch variables receive -1
985    for `fv' because dict_compact_values() will delete them. */
986 int *
987 dict_get_compacted_idx_to_fv (const struct dictionary *d) 
988 {
989   size_t i;
990   size_t next_value_idx;
991   int *idx_to_fv;
992   
993   idx_to_fv = xmalloc (d->var_cnt * sizeof *idx_to_fv);
994   next_value_idx = 0;
995   for (i = 0; i < d->var_cnt; i++)
996     {
997       struct variable *v = d->var[i];
998
999       if (dict_class_from_id (v->name) != DC_SCRATCH) 
1000         {
1001           idx_to_fv[i] = next_value_idx;
1002           next_value_idx += v->nv;
1003         }
1004       else 
1005         idx_to_fv[i] = -1;
1006     }
1007   return idx_to_fv;
1008 }
1009
1010 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
1011    dict_get_split_cnt() to determine how many SPLIT FILE vars
1012    there are.  Returns a null pointer if and only if there are no
1013    SPLIT FILE vars. */
1014 struct variable *const *
1015 dict_get_split_vars (const struct dictionary *d) 
1016 {
1017   assert (d != NULL);
1018   
1019   return d->split;
1020 }
1021
1022 /* Returns the number of SPLIT FILE vars. */
1023 size_t
1024 dict_get_split_cnt (const struct dictionary *d) 
1025 {
1026   assert (d != NULL);
1027
1028   return d->split_cnt;
1029 }
1030
1031 /* Sets CNT split vars SPLIT in dictionary D. */
1032 void
1033 dict_set_split_vars (struct dictionary *d,
1034                      struct variable *const *split, size_t cnt)
1035 {
1036   assert (d != NULL);
1037   assert (cnt == 0 || split != NULL);
1038
1039   d->split_cnt = cnt;
1040   d->split = xrealloc (d->split, cnt * sizeof *d->split);
1041   memcpy (d->split, split, cnt * sizeof *d->split);
1042 }
1043
1044 /* Returns the file label for D, or a null pointer if D is
1045    unlabeled (see cmd_file_label()). */
1046 const char *
1047 dict_get_label (const struct dictionary *d) 
1048 {
1049   assert (d != NULL);
1050
1051   return d->label;
1052 }
1053
1054 /* Sets D's file label to LABEL, truncating it to a maximum of 60
1055    characters. */
1056 void
1057 dict_set_label (struct dictionary *d, const char *label) 
1058 {
1059   assert (d != NULL);
1060
1061   free (d->label);
1062   if (label == NULL)
1063     d->label = NULL;
1064   else if (strlen (label) < 60)
1065     d->label = xstrdup (label);
1066   else 
1067     {
1068       d->label = xmalloc (61);
1069       memcpy (d->label, label, 60);
1070       d->label[60] = '\0';
1071     }
1072 }
1073
1074 /* Returns the documents for D, or a null pointer if D has no
1075    documents (see cmd_document()).. */
1076 const char *
1077 dict_get_documents (const struct dictionary *d) 
1078 {
1079   assert (d != NULL);
1080
1081   return d->documents;
1082 }
1083
1084 /* Sets the documents for D to DOCUMENTS, or removes D's
1085    documents if DOCUMENT is a null pointer. */
1086 void
1087 dict_set_documents (struct dictionary *d, const char *documents)
1088 {
1089   assert (d != NULL);
1090
1091   free (d->documents);
1092   if (documents == NULL)
1093     d->documents = NULL;
1094   else
1095     d->documents = xstrdup (documents);
1096 }
1097
1098 /* Creates in D a vector named NAME that contains CNT variables
1099    VAR (see cmd_vector()).  Returns nonzero if successful, or
1100    zero if a vector named NAME already exists in D. */
1101 int
1102 dict_create_vector (struct dictionary *d,
1103                     const char *name,
1104                     struct variable **var, size_t cnt) 
1105 {
1106   struct vector *vector;
1107
1108   assert (d != NULL);
1109   assert (name != NULL);
1110   assert (strlen (name) > 0 && strlen (name) <= SHORT_NAME_LEN );
1111   assert (var != NULL);
1112   assert (cnt > 0);
1113   
1114   if (dict_lookup_vector (d, name) != NULL)
1115     return 0;
1116
1117   d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
1118   vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
1119   vector->idx = d->vector_cnt++;
1120   strncpy (vector->name, name, SHORT_NAME_LEN);
1121   vector->name[SHORT_NAME_LEN] = '\0';
1122   vector->var = xmalloc (cnt * sizeof *var);
1123   memcpy (vector->var, var, cnt * sizeof *var);
1124   vector->cnt = cnt;
1125   
1126   return 1;
1127 }
1128
1129 /* Returns the vector in D with index IDX, which must be less
1130    than dict_get_vector_cnt (D). */
1131 const struct vector *
1132 dict_get_vector (const struct dictionary *d, size_t idx) 
1133 {
1134   assert (d != NULL);
1135   assert (idx < d->vector_cnt);
1136
1137   return d->vector[idx];
1138 }
1139
1140 /* Returns the number of vectors in D. */
1141 size_t
1142 dict_get_vector_cnt (const struct dictionary *d) 
1143 {
1144   assert (d != NULL);
1145
1146   return d->vector_cnt;
1147 }
1148
1149 /* Looks up and returns the vector within D with the given
1150    NAME. */
1151 const struct vector *
1152 dict_lookup_vector (const struct dictionary *d, const char *name) 
1153 {
1154   size_t i;
1155
1156   assert (d != NULL);
1157   assert (name != NULL);
1158
1159   for (i = 0; i < d->vector_cnt; i++)
1160     if (!strcmp (d->vector[i]->name, name))
1161       return d->vector[i];
1162   return NULL;
1163 }
1164
1165 /* Deletes all vectors from D. */
1166 void
1167 dict_clear_vectors (struct dictionary *d) 
1168 {
1169   size_t i;
1170   
1171   assert (d != NULL);
1172
1173   for (i = 0; i < d->vector_cnt; i++) 
1174     {
1175       free (d->vector[i]->var);
1176       free (d->vector[i]);
1177     }
1178   free (d->vector);
1179   d->vector = NULL;
1180   d->vector_cnt = 0;
1181 }
1182
1183
1184 static const char * quasi_base27(int i);
1185
1186
1187 /* Convert I to quasi base 27 
1188    The result is a staticly allocated string.
1189 */
1190 static const char *
1191 quasi_base27(int i)
1192 {
1193   static char result[SHORT_NAME_LEN + 1];
1194   static char reverse[SHORT_NAME_LEN + 1];
1195
1196   /* FIXME: check the result cant overflow these arrays */
1197
1198   char *s = result ;
1199   const int radix = 27;
1200   int units;
1201
1202   /* and here's the quasi-ness of this routine */
1203   i = i + ( i / radix );
1204
1205   strcpy(result,"");
1206   do {
1207     units = i % radix;
1208     *s++ = (units > 0 ) ? units + 'A' - 1 : 'A';
1209     i = i / radix; 
1210   } while (i > 0 ) ;
1211   *s = '\0';
1212
1213   /* Reverse the result */
1214   i = strlen(result);
1215   s = reverse;
1216   while(i >= 0)
1217         *s++ = result[--i];
1218   *s = '\0';
1219         
1220   return reverse;
1221 }
1222
1223
1224 /* Generate a short name, given a long name.
1225    The return value of this function must be freed by the caller. 
1226 */
1227 static char *
1228 make_short_name(struct dictionary *dict, const char *longname)
1229 {
1230   int i = 0;
1231   char *p;
1232  
1233
1234   char *d = xmalloc ( SHORT_NAME_LEN + 1);
1235
1236   /* Truncate the name */
1237   strncpy(d, longname, SHORT_NAME_LEN);
1238   d[SHORT_NAME_LEN] = '\0';
1239
1240   /* Convert to upper case */
1241   for ( p = d; *p ; ++p )
1242         *p = toupper(*p);
1243
1244   /* If a variable with that name already exists, then munge it
1245      until there's no conflict */
1246   while (0 != hsh_find (dict->name_tab, d))
1247   {
1248         const char *suffix = quasi_base27(i++);
1249
1250         d[SHORT_NAME_LEN -  strlen(suffix) - 1 ] = '_';
1251         d[SHORT_NAME_LEN -  strlen(suffix)  ] = '\0';
1252         strcat(d, suffix);
1253   }
1254
1255   return d;
1256 }
1257
1258
1259
1260