Fix memory leaks.
[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 "error.h"
22 #include <stdlib.h>
23 #include "algorithm.h"
24 #include "alloc.h"
25 #include "case.h"
26 #include "hash.h"
27 #include "misc.h"
28 #include "str.h"
29 #include "value-labels.h"
30 #include "var.h"
31
32 /* A dictionary. */
33 struct dictionary
34   {
35     struct variable **var;      /* Variables. */
36     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
37     struct hsh_table *name_tab; /* Variable index by name. */
38     int next_value_idx;         /* Index of next `union value' to allocate. */
39     struct variable **split;    /* SPLIT FILE vars. */
40     size_t split_cnt;           /* SPLIT FILE count. */
41     struct variable *weight;    /* WEIGHT variable. */
42     struct variable *filter;    /* FILTER variable. */
43     int case_limit;             /* Current case limit (N command). */
44     char *label;                /* File label. */
45     char *documents;            /* Documents, as a string. */
46     struct vector **vector;     /* Vectors of variables. */
47     size_t vector_cnt;          /* Number of vectors. */
48   };
49
50 /* Creates and returns a new dictionary. */
51 struct dictionary *
52 dict_create (void) 
53 {
54   struct dictionary *d = xmalloc (sizeof *d);
55   
56   d->var = NULL;
57   d->var_cnt = d->var_cap = 0;
58   d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
59   d->next_value_idx = 0;
60   d->split = NULL;
61   d->split_cnt = 0;
62   d->weight = NULL;
63   d->filter = NULL;
64   d->case_limit = 0;
65   d->label = NULL;
66   d->documents = NULL;
67   d->vector = NULL;
68   d->vector_cnt = 0;
69
70   return d;
71 }
72
73 /* Creates and returns a (deep) copy of an existing
74    dictionary. */
75 struct dictionary *
76 dict_clone (const struct dictionary *s) 
77 {
78   struct dictionary *d;
79   size_t i;
80   
81   assert (s != NULL);
82   
83   d = dict_create ();
84   for (i = 0; i < s->var_cnt; i++)
85     dict_clone_var (d, s->var[i], s->var[i]->name);
86   d->next_value_idx = s->next_value_idx;
87
88   d->split_cnt = s->split_cnt;
89   if (d->split_cnt > 0) 
90     {
91       d->split = xmalloc (d->split_cnt * sizeof *d->split);
92       for (i = 0; i < d->split_cnt; i++) 
93         d->split[i] = dict_lookup_var_assert (d, s->split[i]->name);
94     }
95
96   if (s->weight != NULL) 
97     d->weight = dict_lookup_var_assert (d, s->weight->name);
98
99   if (s->filter != NULL) 
100     d->filter = dict_lookup_var_assert (d, s->filter->name);
101
102   d->case_limit = s->case_limit;
103   dict_set_label (d, dict_get_label (s));
104   dict_set_documents (d, dict_get_documents (s));
105
106   for (i = 0; i < s->vector_cnt; i++) 
107     dict_create_vector (d, s->vector[i]->name,
108                         s->vector[i]->var, s->vector[i]->cnt);
109
110   return d;
111 }
112
113 /* Clears the contents from a dictionary without destroying the
114    dictionary itself. */
115 void
116 dict_clear (struct dictionary *d) 
117 {
118   /* FIXME?  Should we really clear case_limit, label, documents?
119      Others are necessarily cleared by deleting all the variables.*/
120   int i;
121
122   assert (d != NULL);
123
124   for (i = 0; i < d->var_cnt; i++) 
125     {
126       struct variable *v = d->var[i];
127       val_labs_destroy (v->val_labs);
128       free (v->label);
129       free (v); 
130     }
131   free (d->var);
132   d->var = NULL;
133   d->var_cnt = d->var_cap = 0;
134   hsh_clear (d->name_tab);
135   d->next_value_idx = 0;
136   free (d->split);
137   d->split = NULL;
138   d->split_cnt = 0;
139   d->weight = NULL;
140   d->filter = NULL;
141   d->case_limit = 0;
142   free (d->label);
143   d->label = NULL;
144   free (d->documents);
145   d->documents = NULL;
146   dict_clear_vectors (d);
147 }
148
149 /* Clears a dictionary and destroys it. */
150 void
151 dict_destroy (struct dictionary *d)
152 {
153   if (d != NULL) 
154     {
155       dict_clear (d);
156       hsh_destroy (d->name_tab);
157       free (d);
158     }
159 }
160
161 /* Returns the number of variables in D. */
162 size_t
163 dict_get_var_cnt (const struct dictionary *d) 
164 {
165   assert (d != NULL);
166
167   return d->var_cnt;
168 }
169
170 /* Returns the variable in D with index IDX, which must be
171    between 0 and the count returned by dict_get_var_cnt(),
172    exclusive. */
173 struct variable *
174 dict_get_var (const struct dictionary *d, size_t idx) 
175 {
176   assert (d != NULL);
177   assert (idx < d->var_cnt);
178
179   return d->var[idx];
180 }
181
182 /* Sets *VARS to an array of pointers to variables in D and *CNT
183    to the number of variables in *D.  By default all variables
184    are returned, but bits may be set in EXCLUDE_CLASSES to
185    exclude ordinary, system, and/or scratch variables. */
186 void
187 dict_get_vars (const struct dictionary *d, struct variable ***vars,
188                size_t *cnt, unsigned exclude_classes)
189 {
190   size_t count;
191   size_t i;
192   
193   assert (d != NULL);
194   assert (vars != NULL);
195   assert (cnt != NULL);
196   assert ((exclude_classes & ~((1u << DC_ORDINARY)
197                                | (1u << DC_SYSTEM)
198                                | (1u << DC_SCRATCH))) == 0);
199   
200   count = 0;
201   for (i = 0; i < d->var_cnt; i++)
202     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
203       count++;
204
205   *vars = xmalloc (count * sizeof **vars);
206   *cnt = 0;
207   for (i = 0; i < d->var_cnt; i++)
208     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
209       (*vars)[(*cnt)++] = d->var[i];
210   assert (*cnt == count);
211 }
212
213 /* Creates and returns a new variable in D with the given NAME
214    and WIDTH.  Returns a null pointer if the given NAME would
215    duplicate that of an existing variable in the dictionary. */
216 struct variable *
217 dict_create_var (struct dictionary *d, const char *name, int width) 
218 {
219   struct variable *v;
220
221   assert (d != NULL);
222   assert (name != NULL);
223   assert (strlen (name) >= 1 && strlen (name) <= 8);
224   assert (width >= 0 && width < 256);
225
226   /* Make sure there's not already a variable by that name. */
227   if (dict_lookup_var (d, name) != NULL)
228     return NULL;
229
230   /* Allocate and initialize variable. */
231   v = xmalloc (sizeof *v);
232   strncpy (v->name, name, sizeof v->name);
233   v->name[8] = '\0';
234   v->index = d->var_cnt;
235   v->type = width == 0 ? NUMERIC : ALPHA;
236   v->width = width;
237   v->fv = d->next_value_idx;
238   v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
239   v->init = 1;
240   v->reinit = dict_class_from_id (name) != DC_SCRATCH;
241   v->miss_type = MISSING_NONE;
242   if (v->type == NUMERIC)
243     {
244       v->print.type = FMT_F;
245       v->print.w = 8;
246       v->print.d = 2;
247     }
248   else
249     {
250       v->print.type = FMT_A;
251       v->print.w = v->width;
252       v->print.d = 0;
253     }
254   v->write = v->print;
255   v->val_labs = val_labs_create (v->width);
256   v->label = NULL;
257
258   /* Update dictionary. */
259   if (d->var_cnt >= d->var_cap) 
260     {
261       d->var_cap = 8 + 2 * d->var_cap; 
262       d->var = xrealloc (d->var, d->var_cap * sizeof *d->var);
263     }
264   d->var[v->index] = v;
265   d->var_cnt++;
266   hsh_force_insert (d->name_tab, v);
267   d->next_value_idx += v->nv;
268
269   return v;
270 }
271
272 /* Creates and returns a new variable in D with the given NAME
273    and WIDTH.  Assert-fails if the given NAME would duplicate
274    that of an existing variable in the dictionary. */
275 struct variable *
276 dict_create_var_assert (struct dictionary *d, const char *name, int width) 
277 {
278   struct variable *v = dict_create_var (d, name, width);
279   assert (v != NULL);
280   return v;
281 }
282
283 /* Creates a new variable in D named NAME, as a copy of existing
284    variable OV, which need not be in D or in any dictionary. */
285 struct variable *
286 dict_clone_var (struct dictionary *d, const struct variable *ov,
287                 const char *name)
288 {
289   struct variable *nv;
290
291   assert (d != NULL);
292   assert (ov != NULL);
293   assert (name != NULL);
294   assert (strlen (name) >= 1 && strlen (name) <= 8);
295
296   nv = dict_create_var (d, name, ov->width);
297   if (nv == NULL)
298     return NULL;
299
300   nv->init = 1;
301   nv->reinit = ov->reinit;
302   nv->miss_type = ov->miss_type;
303   memcpy (nv->missing, ov->missing, sizeof nv->missing);
304   nv->print = ov->print;
305   nv->write = ov->write;
306   val_labs_destroy (nv->val_labs);
307   nv->val_labs = val_labs_copy (ov->val_labs);
308   if (ov->label != NULL)
309     nv->label = xstrdup (ov->label);
310
311   return nv;
312 }
313
314 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
315    a variable named NEW_NAME is already in D, except that
316    NEW_NAME may be the same as V's existing name. */
317 void 
318 dict_rename_var (struct dictionary *d, struct variable *v,
319                  const char *new_name) 
320 {
321   assert (d != NULL);
322   assert (v != NULL);
323   assert (new_name != NULL);
324   assert (strlen (new_name) >= 1 && strlen (new_name) <= 8);
325   assert (dict_contains_var (d, v));
326
327   if (!strcmp (v->name, new_name))
328     return;
329
330   assert (dict_lookup_var (d, new_name) == NULL);
331
332   hsh_force_delete (d->name_tab, v);
333   strncpy (v->name, new_name, sizeof v->name);
334   v->name[8] = '\0';
335   hsh_force_insert (d->name_tab, v);
336 }
337
338 /* Returns the variable named NAME in D, or a null pointer if no
339    variable has that name. */
340 struct variable *
341 dict_lookup_var (const struct dictionary *d, const char *name)
342 {
343   struct variable v;
344   
345   assert (d != NULL);
346   assert (name != NULL);
347   assert (strlen (name) >= 1 && strlen (name) <= 8);
348
349   strncpy (v.name, name, sizeof v.name);
350   v.name[8] = '\0';
351
352   return hsh_find (d->name_tab, &v);
353 }
354
355 /* Returns the variable named NAME in D.  Assert-fails if no
356    variable has that name. */
357 struct variable *
358 dict_lookup_var_assert (const struct dictionary *d, const char *name)
359 {
360   struct variable *v = dict_lookup_var (d, name);
361   assert (v != NULL);
362   return v;
363 }
364
365 /* Returns nonzero if variable V is in dictionary D. */
366 int
367 dict_contains_var (const struct dictionary *d, const struct variable *v)
368 {
369   assert (d != NULL);
370   assert (v != NULL);
371
372   return v->index >= 0 && v->index < d->var_cnt && d->var[v->index] == v;
373 }
374
375 /* Compares two double pointers to variables, which should point
376    to elements of a struct dictionary's `var' member array. */
377 static int
378 compare_variable_dblptrs (const void *a_, const void *b_, void *aux UNUSED) 
379 {
380   struct variable *const *a = a_;
381   struct variable *const *b = b_;
382
383   if (a > b)
384     return 1;
385   else if (a < b)
386     return -1;
387   else
388     return 0;
389 }
390
391 /* Deletes variable V from dictionary D and frees V.
392
393    This is a very bad idea if there might be any pointers to V
394    from outside D.  In general, no variable in default_dict
395    should be deleted when any transformations are active, because
396    those transformations might reference the deleted variable.
397    The safest time to delete a variable is just after a procedure
398    has been executed, as done by MODIFY VARS.
399
400    Pointers to V within D are not a problem, because
401    dict_delete_var() knows to remove V from split variables,
402    weights, filters, etc. */
403 void
404 dict_delete_var (struct dictionary *d, struct variable *v) 
405 {
406   size_t i;
407
408   assert (d != NULL);
409   assert (v != NULL);
410   assert (dict_contains_var (d, v));
411   assert (d->var[v->index] == v);
412
413   /* Remove v from splits, weight, filter variables. */
414   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
415                                &v,
416                                compare_variable_dblptrs, NULL);
417   if (d->weight == v)
418     d->weight = NULL;
419   if (d->filter == v)
420     d->filter = NULL;
421   dict_clear_vectors (d);
422
423   /* Remove v from var array. */
424   d->var_cnt--;
425   memmove (d->var + v->index, d->var + v->index + 1,
426            (d->var_cnt - v->index) * sizeof *d->var);
427
428   /* Update index. */
429   for (i = v->index; i < d->var_cnt; i++)
430     d->var[i]->index = i;
431
432   /* Update name hash. */
433   hsh_force_delete (d->name_tab, v);
434
435   /* Free memory. */
436   val_labs_destroy (v->val_labs);
437   free (v->label);
438   free (v);
439 }
440
441 /* Deletes the COUNT variables listed in VARS from D.  This is
442    unsafe; see the comment on dict_delete_var() for details. */
443 void 
444 dict_delete_vars (struct dictionary *d,
445                   struct variable *const *vars, size_t count) 
446 {
447   /* FIXME: this can be done in O(count) time, but this algorithm
448      is O(count**2). */
449   assert (d != NULL);
450   assert (count == 0 || vars != NULL);
451
452   while (count-- > 0)
453     dict_delete_var (d, *vars++);
454 }
455
456 /* Reorders the variables in D, placing the COUNT variables
457    listed in ORDER in that order at the beginning of D.  The
458    other variables in D, if any, retain their relative
459    positions. */
460 void 
461 dict_reorder_vars (struct dictionary *d,
462                    struct variable *const *order, size_t count) 
463 {
464   struct variable **new_var;
465   size_t i;
466   
467   assert (d != NULL);
468   assert (count == 0 || order != NULL);
469   assert (count <= d->var_cnt);
470
471   new_var = xmalloc (d->var_cnt * sizeof *new_var);
472   memcpy (new_var, order, count * sizeof *new_var);
473   for (i = 0; i < count; i++) 
474     {
475       assert (d->var[order[i]->index] != NULL);
476       d->var[order[i]->index] = NULL;
477       order[i]->index = i;
478     }
479   for (i = 0; i < d->var_cnt; i++)
480     if (d->var[i] != NULL)
481       {
482         assert (count < d->var_cnt);
483         new_var[count] = d->var[i];
484         new_var[count]->index = count;
485         count++;
486       }
487   free (d->var);
488   d->var = new_var;
489 }
490
491 /* Renames COUNT variables specified in VARS to the names given
492    in NEW_NAMES within dictionary D.  If the renaming would
493    result in a duplicate variable name, returns zero and stores a
494    name that would be duplicated into *ERR_NAME (if ERR_NAME is
495    non-null).  Otherwise, the renaming is successful, and nonzero
496    is returned. */
497 int
498 dict_rename_vars (struct dictionary *d,
499                   struct variable **vars, char **new_names,
500                   size_t count, char **err_name) 
501 {
502   char **old_names;
503   size_t i;
504   int success = 1;
505
506   assert (d != NULL);
507   assert (count == 0 || vars != NULL);
508   assert (count == 0 || new_names != NULL);
509
510   old_names = xmalloc (count * sizeof *old_names);
511   for (i = 0; i < count; i++) 
512     {
513       assert (d->var[vars[i]->index] == vars[i]);
514       hsh_force_delete (d->name_tab, vars[i]);
515       old_names[i] = xstrdup (vars[i]->name);
516     }
517   
518   for (i = 0; i < count; i++)
519     {
520       assert (new_names[i] != NULL);
521       assert (*new_names[i] != '\0');
522       assert (strlen (new_names[i]) < 9);
523       strcpy (vars[i]->name, new_names[i]);
524       if (hsh_insert (d->name_tab, vars[i]) != NULL) 
525         {
526           size_t fail_idx = i;
527           if (err_name != NULL) 
528             *err_name = new_names[i];
529
530           for (i = 0; i < fail_idx; i++)
531             hsh_force_delete (d->name_tab, vars[i]);
532           
533           for (i = 0; i < count; i++)
534             {
535               strcpy (vars[i]->name, old_names[i]);
536               hsh_force_insert (d->name_tab, vars[i]);
537             }
538
539           success = 0;
540           break;
541         }
542     }
543
544   for (i = 0; i < count; i++)
545     free (old_names[i]);
546   free (old_names);
547
548   return success;
549 }
550
551 /* Returns the weighting variable in dictionary D, or a null
552    pointer if the dictionary is unweighted. */
553 struct variable *
554 dict_get_weight (const struct dictionary *d) 
555 {
556   assert (d != NULL);
557   assert (d->weight == NULL || dict_contains_var (d, d->weight));
558   
559   return d->weight;
560 }
561
562 /* Returns the value of D's weighting variable in case C, except that a
563    negative weight is returned as 0.  Returns 1 if the dictionary is
564    unweighted. Will warn about missing, negative, or zero values if
565    warn_on_invalid is nonzero. The function will set warn_on_invalid to zero
566    if an invalid weight is found. */
567 double
568 dict_get_case_weight (const struct dictionary *d, const struct ccase *c, 
569                       int *warn_on_invalid)
570 {
571   assert (d != NULL);
572   assert (c != NULL);
573
574   if (d->weight == NULL)
575     return 1.0;
576   else 
577     {
578       double w = case_num (c, d->weight->fv);
579       if ( w < 0.0 || w == SYSMIS || is_num_user_missing(w, d->weight) )
580         w = 0.0;
581       if ( w == 0.0 && *warn_on_invalid ) {
582           *warn_on_invalid = 0;
583           msg (SW, _("At least one case in the data file had a weight value "
584                      "that was user-missing, system-missing, zero, or "
585                      "negative.  These case(s) were ignored."));
586       }
587       return w;
588     }
589 }
590
591 /* Sets the weighting variable of D to V, or turning off
592    weighting if V is a null pointer. */
593 void
594 dict_set_weight (struct dictionary *d, struct variable *v) 
595 {
596   assert (d != NULL);
597   assert (v == NULL || dict_contains_var (d, v));
598   assert (v == NULL || v->type == NUMERIC);
599
600   d->weight = v;
601 }
602
603 /* Returns the filter variable in dictionary D (see cmd_filter())
604    or a null pointer if the dictionary is unfiltered. */
605 struct variable *
606 dict_get_filter (const struct dictionary *d) 
607 {
608   assert (d != NULL);
609   assert (d->filter == NULL || dict_contains_var (d, d->filter));
610   
611   return d->filter;
612 }
613
614 /* Sets V as the filter variable for dictionary D.  Passing a
615    null pointer for V turn off filtering. */
616 void
617 dict_set_filter (struct dictionary *d, struct variable *v)
618 {
619   assert (d != NULL);
620   assert (v == NULL || dict_contains_var (d, v));
621
622   d->filter = v;
623 }
624
625 /* Returns the case limit for dictionary D, or zero if the number
626    of cases is unlimited (see cmd_n()). */
627 int
628 dict_get_case_limit (const struct dictionary *d) 
629 {
630   assert (d != NULL);
631
632   return d->case_limit;
633 }
634
635 /* Sets CASE_LIMIT as the case limit for dictionary D.  Zero for
636    CASE_LIMIT indicates no limit. */
637 void
638 dict_set_case_limit (struct dictionary *d, int case_limit) 
639 {
640   assert (d != NULL);
641   assert (case_limit >= 0);
642
643   d->case_limit = case_limit;
644 }
645
646 /* Returns the index of the next value to be added to D.  This
647    value is the number of `union value's that need to be
648    allocated to store a case for dictionary D. */
649 int
650 dict_get_next_value_idx (const struct dictionary *d) 
651 {
652   assert (d != NULL);
653
654   return d->next_value_idx;
655 }
656
657 /* Returns the number of bytes needed to store a case for
658    dictionary D. */
659 size_t
660 dict_get_case_size (const struct dictionary *d) 
661 {
662   assert (d != NULL);
663
664   return sizeof (union value) * dict_get_next_value_idx (d);
665 }
666
667 /* Deletes scratch variables in dictionary D and reassigns values
668    so that fragmentation is eliminated. */
669 void
670 dict_compact_values (struct dictionary *d) 
671 {
672   size_t i;
673
674   d->next_value_idx = 0;
675   for (i = 0; i < d->var_cnt; )
676     {
677       struct variable *v = d->var[i];
678
679       if (dict_class_from_id (v->name) != DC_SCRATCH) 
680         {
681           v->fv = d->next_value_idx;
682           d->next_value_idx += v->nv;
683           i++;
684         }
685       else
686         dict_delete_var (default_dict, v);
687     }
688 }
689
690 /* Returns the number of values that would be used by a case if
691    dict_compact_values() were called. */
692 size_t
693 dict_get_compacted_value_cnt (const struct dictionary *d) 
694 {
695   size_t i;
696   size_t cnt;
697
698   cnt = 0;
699   for (i = 0; i < d->var_cnt; i++)
700     if (dict_class_from_id (d->var[i]->name) != DC_SCRATCH) 
701       cnt += d->var[i]->nv;
702   return cnt;
703 }
704
705 /* Creates and returns an array mapping from a dictionary index
706    to the `fv' that the corresponding variable will have after
707    calling dict_compact_values().  Scratch variables receive -1
708    for `fv' because dict_compact_values() will delete them. */
709 int *
710 dict_get_compacted_idx_to_fv (const struct dictionary *d) 
711 {
712   size_t i;
713   size_t next_value_idx;
714   int *idx_to_fv;
715   
716   idx_to_fv = xmalloc (d->var_cnt * sizeof *idx_to_fv);
717   next_value_idx = 0;
718   for (i = 0; i < d->var_cnt; i++)
719     {
720       struct variable *v = d->var[i];
721
722       if (dict_class_from_id (v->name) != DC_SCRATCH) 
723         {
724           idx_to_fv[i] = next_value_idx;
725           next_value_idx += v->nv;
726         }
727       else 
728         idx_to_fv[i] = -1;
729     }
730   return idx_to_fv;
731 }
732
733 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
734    dict_get_split_cnt() to determine how many SPLIT FILE vars
735    there are.  Returns a null pointer if and only if there are no
736    SPLIT FILE vars. */
737 struct variable *const *
738 dict_get_split_vars (const struct dictionary *d) 
739 {
740   assert (d != NULL);
741   
742   return d->split;
743 }
744
745 /* Returns the number of SPLIT FILE vars. */
746 size_t
747 dict_get_split_cnt (const struct dictionary *d) 
748 {
749   assert (d != NULL);
750
751   return d->split_cnt;
752 }
753
754 /* Sets CNT split vars SPLIT in dictionary D. */
755 void
756 dict_set_split_vars (struct dictionary *d,
757                      struct variable *const *split, size_t cnt)
758 {
759   assert (d != NULL);
760   assert (cnt == 0 || split != NULL);
761
762   d->split_cnt = cnt;
763   d->split = xrealloc (d->split, cnt * sizeof *d->split);
764   memcpy (d->split, split, cnt * sizeof *d->split);
765 }
766
767 /* Returns the file label for D, or a null pointer if D is
768    unlabeled (see cmd_file_label()). */
769 const char *
770 dict_get_label (const struct dictionary *d) 
771 {
772   assert (d != NULL);
773
774   return d->label;
775 }
776
777 /* Sets D's file label to LABEL, truncating it to a maximum of 60
778    characters. */
779 void
780 dict_set_label (struct dictionary *d, const char *label) 
781 {
782   assert (d != NULL);
783
784   free (d->label);
785   if (label == NULL)
786     d->label = NULL;
787   else if (strlen (label) < 60)
788     d->label = xstrdup (label);
789   else 
790     {
791       d->label = xmalloc (61);
792       memcpy (d->label, label, 60);
793       d->label[60] = '\0';
794     }
795 }
796
797 /* Returns the documents for D, or a null pointer if D has no
798    documents (see cmd_document()).. */
799 const char *
800 dict_get_documents (const struct dictionary *d) 
801 {
802   assert (d != NULL);
803
804   return d->documents;
805 }
806
807 /* Sets the documents for D to DOCUMENTS, or removes D's
808    documents if DOCUMENT is a null pointer. */
809 void
810 dict_set_documents (struct dictionary *d, const char *documents)
811 {
812   assert (d != NULL);
813
814   free (d->documents);
815   if (documents == NULL)
816     d->documents = NULL;
817   else
818     d->documents = xstrdup (documents);
819 }
820
821 /* Creates in D a vector named NAME that contains CNT variables
822    VAR (see cmd_vector()).  Returns nonzero if successful, or
823    zero if a vector named NAME already exists in D. */
824 int
825 dict_create_vector (struct dictionary *d,
826                     const char *name,
827                     struct variable **var, size_t cnt) 
828 {
829   struct vector *vector;
830
831   assert (d != NULL);
832   assert (name != NULL);
833   assert (strlen (name) > 0 && strlen (name) < 9);
834   assert (var != NULL);
835   assert (cnt > 0);
836   
837   if (dict_lookup_vector (d, name) != NULL)
838     return 0;
839
840   d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
841   vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
842   vector->idx = d->vector_cnt++;
843   strncpy (vector->name, name, 8);
844   vector->name[8] = '\0';
845   vector->var = xmalloc (cnt * sizeof *var);
846   memcpy (vector->var, var, cnt * sizeof *var);
847   vector->cnt = cnt;
848   
849   return 1;
850 }
851
852 /* Returns the vector in D with index IDX, which must be less
853    than dict_get_vector_cnt (D). */
854 const struct vector *
855 dict_get_vector (const struct dictionary *d, size_t idx) 
856 {
857   assert (d != NULL);
858   assert (idx < d->vector_cnt);
859
860   return d->vector[idx];
861 }
862
863 /* Returns the number of vectors in D. */
864 size_t
865 dict_get_vector_cnt (const struct dictionary *d) 
866 {
867   assert (d != NULL);
868
869   return d->vector_cnt;
870 }
871
872 /* Looks up and returns the vector within D with the given
873    NAME. */
874 const struct vector *
875 dict_lookup_vector (const struct dictionary *d, const char *name) 
876 {
877   size_t i;
878
879   assert (d != NULL);
880   assert (name != NULL);
881
882   for (i = 0; i < d->vector_cnt; i++)
883     if (!strcmp (d->vector[i]->name, name))
884       return d->vector[i];
885   return NULL;
886 }
887
888 /* Deletes all vectors from D. */
889 void
890 dict_clear_vectors (struct dictionary *d) 
891 {
892   size_t i;
893   
894   assert (d != NULL);
895
896   for (i = 0; i < d->vector_cnt; i++) 
897     {
898       free (d->vector[i]->var);
899       free (d->vector[i]);
900     }
901   free (d->vector);
902   d->vector = NULL;
903   d->vector_cnt = 0;
904 }