8aa3eb3e7bf1a5e53213b720b52ecf124ef0ca32
[pspp-builds.git] / src / temporary.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 <assert.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24 #include "alloc.h"
25 #include "command.h"
26 #include "do-ifP.h"
27 #include "error.h"
28 #include "hash.h"
29 #include "lexer.h"
30 #include "str.h"
31 #include "value-labels.h"
32 #include "var.h"
33
34 #include "debug-print.h"
35
36 int temporary;
37 struct dictionary *temp_dict;
38 int temp_trns;
39
40 /* Parses the TEMPORARY command. */
41 int
42 cmd_temporary (void)
43 {
44   lex_match_id ("TEMPORARY");
45
46   /* TEMPORARY is not allowed inside DO IF or LOOP. */
47   if (ctl_stack)
48     {
49       msg (SE, _("This command is not valid inside DO IF or LOOP."));
50       return CMD_FAILURE;
51     }
52
53   /* TEMPORARY can only appear once! */
54   if (temporary)
55     {
56       msg (SE, _("This command may only appear once between "
57            "procedures and procedure-like commands."));
58       return CMD_FAILURE;
59     }
60
61   /* Everything is temporary, even if we think it'll last forever.
62      Especially then. */
63   temporary = 1;
64   temp_dict = save_dictionary ();
65   if (f_trns == n_trns)
66     temp_trns = -1;
67   else
68     temp_trns = n_trns;
69   debug_printf (("TEMPORARY: temp_trns=%d\n", temp_trns));
70
71   return lex_end_of_command ();
72 }
73
74 /* Copies a variable structure. */
75 void
76 copy_variable (struct variable *dest, const struct variable *src)
77 {
78   int i, n;
79
80   assert (dest != src);
81   dest->type = src->type;
82   dest->left = src->left;
83   dest->width = src->width;
84   dest->fv = src->fv;
85   dest->nv = src->nv;
86   dest->miss_type = src->miss_type;
87   
88   switch (src->miss_type)
89     {
90     case MISSING_NONE:
91       n = 0;
92       break;
93     case MISSING_1:
94       n = 1;
95       break;
96     case MISSING_2:
97     case MISSING_RANGE:
98       n = 2;
99       break;
100     case MISSING_3:
101     case MISSING_RANGE_1:
102       n = 3;
103       break;
104     default:
105       assert (0);
106       break;
107     }
108   
109   for (i = 0; i < n; i++)
110     dest->missing[i] = src->missing[i];
111   dest->print = src->print;
112   dest->write = src->write;
113
114   dest->val_labs = val_labs_copy (src->val_labs);
115   dest->label = src->label ? xstrdup (src->label) : NULL;
116 }
117
118 /* Returns a newly created empty dictionary.  The file label and
119    documents are copied from default_dict if COPY is nonzero. */
120 struct dictionary *
121 new_dictionary (int copy)
122 {
123   struct dictionary *d = xmalloc (sizeof *d);
124   
125   d->var = NULL;
126   d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
127   d->nvar = 0;
128
129   d->N = 0;
130
131   d->nval = 0;
132
133   d->n_splits = 0;
134   d->splits = NULL;
135
136   if (default_dict.label && copy)
137     d->label = xstrdup (default_dict.label);
138   else
139     d->label = NULL;
140
141   if (default_dict.n_documents && copy)
142     {
143       d->n_documents = default_dict.n_documents;
144       if (d->n_documents)
145         {
146           d->documents = malloc (default_dict.n_documents * 80);
147           memcpy (d->documents, default_dict.documents,
148                   default_dict.n_documents * 80);
149         }
150     }
151   else
152     {
153       d->n_documents = 0;
154       d->documents = NULL;
155     }
156   
157   d->weight_index = -1;
158   d->weight_var[0] = 0;
159
160   d->filter_var[0] = 0;
161
162   return d;
163 }
164     
165 /* Copies the current dictionary info into a newly allocated
166    dictionary structure, which is returned. */
167 struct dictionary *
168 save_dictionary (void)
169 {
170   /* Dictionary being created. */
171   struct dictionary *d;
172
173   int i;
174
175   d = xmalloc (sizeof *d);
176
177   /* First the easy stuff. */
178   *d = default_dict;
179   d->label = default_dict.label ? xstrdup (default_dict.label) : NULL;
180   if (default_dict.n_documents)
181     {
182       d->documents = malloc (default_dict.n_documents * 80);
183       memcpy (d->documents, default_dict.documents,
184               default_dict.n_documents * 80);
185     }
186   else d->documents = NULL;
187
188   /* Then the variables. */
189   d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
190   d->var = xmalloc (default_dict.nvar * sizeof *d->var);
191   for (i = 0; i < default_dict.nvar; i++)
192     {
193       d->var[i] = xmalloc (sizeof *d->var[i]);
194       copy_variable (d->var[i], default_dict.var[i]);
195       strcpy (d->var[i]->name, default_dict.var[i]->name);
196       d->var[i]->index = i;
197       hsh_force_insert (d->name_tab, d->var[i]);
198     }
199
200   /* Then the SPLIT FILE variables. */
201   if (default_dict.splits)
202     {
203       int i;
204
205       d->n_splits = default_dict.n_splits;
206       d->splits = xmalloc ((default_dict.n_splits + 1) * sizeof *d->splits);
207       for (i = 0; i < default_dict.n_splits; i++)
208         d->splits[i] = d->var[default_dict.splits[i]->index];
209       d->splits[default_dict.n_splits] = NULL;
210     }
211   else
212     {
213       d->n_splits = 0;
214       d->splits = NULL;
215     }
216   
217   return d;
218 }
219
220 /* Copies dictionary D into the active file dictionary.  Deletes
221    dictionary D. */
222 void
223 restore_dictionary (struct dictionary * d)
224 {
225   int i;
226
227   /* 1. Delete the current dictionary. */
228   default_dict.n_splits = 0;
229   free (default_dict.splits);
230   default_dict.splits = NULL;
231   
232   hsh_destroy (default_dict.name_tab);
233   default_dict.name_tab = NULL;
234   
235   for (i = 0; i < default_dict.nvar; i++)
236     {
237       clear_variable (&default_dict, default_dict.var[i]);
238       free (default_dict.var[i]);
239     }
240   
241   free (default_dict.var);
242   free (default_dict.label);
243   free (default_dict.documents);
244
245   /* 2. Copy dictionary D into the active file dictionary. */
246   default_dict = *d;
247   if (default_dict.name_tab == NULL)
248     {
249       default_dict.name_tab = hsh_create (8, compare_variables, hash_variable,
250                                           NULL, NULL);
251       
252       for (i = 0; i < default_dict.nvar; i++)
253         hsh_force_insert (default_dict.name_tab, default_dict.var[i]);
254     }
255
256   /* 3. Destroy dictionary D. */
257   free (d);
258 }
259
260 /* Destroys dictionary D. */
261 void
262 free_dictionary (struct dictionary * d)
263 {
264   int i;
265
266   d->n_splits = 0;
267   free (d->splits);
268   d->splits = NULL;
269   
270   if (d->name_tab)
271     hsh_destroy (d->name_tab);
272
273   for (i = 0; i < d->nvar; i++)
274     {
275       struct variable *v = d->var[i];
276
277       val_labs_destroy (v->val_labs);
278       if (v->label)
279         {
280           free (v->label);
281           v->label = NULL;
282         }
283       free (d->var[i]);
284     }
285   free (d->var);
286
287   free (d->label);
288   free (d->documents);
289
290   free (d);
291 }
292
293 /* Cancels the temporary transformation, if any. */
294 void
295 cancel_temporary (void)
296 {
297   if (temporary)
298     {
299       if (temp_dict)
300         free_dictionary (temp_dict);
301       temporary = 0;
302       temp_trns = 0;
303     }
304 }