You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
-#include "avl.h"
#include "command.h"
#include "error.h"
+#include "hash.h"
#include "lexer.h"
#include "str.h"
+#include "value-labels.h"
#include "var.h"
\f
/* Declarations. */
-#include "debug-print.h"
-
-/* Variable list. */
-static struct variable **v;
-
-/* Number of variables. */
-static int nv;
-
static int do_value_labels (int);
-static int verify_val_labs (int erase);
-static int get_label (void);
-
-#if DEBUGGING
-static void debug_print (void);
-#endif
+static int verify_val_labs (struct variable **vars, int var_cnt);
+static void erase_labels (struct variable **vars, int var_cnt);
+static int get_label (struct variable **vars, int var_cnt);
\f
/* Stubs. */
-static void
-init (void)
-{
- v = NULL;
-}
-
-static void
-done (void)
-{
- free (v);
-}
-
int
cmd_value_labels (void)
{
- int code;
- init ();
- lex_match_id ("VALUE");
- lex_match_id ("LABELS");
- code = do_value_labels (1);
- done ();
- return code;
+ return do_value_labels (1);
}
int
cmd_add_value_labels (void)
{
- int code;
- lex_match_id ("ADD");
- lex_match_id ("VALUE");
- lex_match_id ("LABELS");
- code = do_value_labels (0);
- done ();
- return code;
+ return do_value_labels (0);
}
\f
/* Do it. */
static int
do_value_labels (int erase)
{
+ struct variable **vars; /* Variable list. */
+ int var_cnt; /* Number of variables. */
+ int parse_err=0; /* true if error parsing variables */
+
lex_match ('/');
while (token != '.')
{
- parse_variables (NULL, &v, &nv, PV_SAME_TYPE);
- if (!verify_val_labs (erase))
- return CMD_PART_SUCCESS_MAYBE;
+ parse_err = !parse_variables (default_dict, &vars, &var_cnt,
+ PV_SAME_TYPE) ;
+ if (var_cnt < 1)
+ {
+ free(vars);
+ return CMD_FAILURE;
+ }
+ if (!verify_val_labs (vars, var_cnt))
+ goto lossage;
+ if (erase)
+ erase_labels (vars, var_cnt);
while (token != '/' && token != '.')
- if (!get_label ())
- return CMD_PART_SUCCESS_MAYBE;
+ if (!get_label (vars, var_cnt))
+ goto lossage;
if (token != '/')
+ {
+ free (vars);
break;
+ }
+
lex_get ();
- free (v);
- v = NULL;
+ free (vars);
}
if (token != '.')
return CMD_TRAILING_GARBAGE;
}
-#if 0 && DEBUGGING
- debug_print ();
-#endif
- return CMD_SUCCESS;
+ return parse_err ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
+
+ lossage:
+ free (vars);
+ return CMD_PART_SUCCESS_MAYBE;
}
+/* Verifies that none of the VAR_CNT variables in VARS are long
+ string variables. */
static int
-verify_val_labs (int erase)
+verify_val_labs (struct variable **vars, int var_cnt)
{
int i;
- if (!nv)
- return 1;
-
- for (i = 0; i < nv; i++)
+ for (i = 0; i < var_cnt; i++)
{
- struct variable *vp = v[i];
+ struct variable *vp = vars[i];
- if (vp->type == ALPHA && vp->width > 8)
+ if (vp->type == ALPHA && vp->width > MAX_SHORT_STRING)
{
msg (SE, _("It is not possible to assign value labels to long "
"string variables such as %s."), vp->name);
return 0;
}
-
- if (erase && v[i]->val_lab)
- {
- avl_destroy (vp->val_lab, free_val_lab);
- vp->val_lab = NULL;
- }
}
return 1;
}
-/* Parse all the labels for a particular set of variables and add the
- specified labels to those variables. */
-static int
-get_label (void)
+/* Erases all the labels for the VAR_CNT variables in VARS. */
+static void
+erase_labels (struct variable **vars, int var_cnt)
{
int i;
- /* Make sure there's some variables. */
- if (!nv)
- {
- if (token != T_STRING && token != T_NUM)
- return 0;
- lex_get ();
- return 1;
- }
+ /* Erase old value labels if desired. */
+ for (i = 0; i < var_cnt; i++)
+ val_labs_clear (vars[i]->val_labs);
+}
+/* Parse all the labels for the VAR_CNT variables in VARS and add
+ the specified labels to those variables. */
+static int
+get_label (struct variable **vars, int var_cnt)
+{
/* Parse all the labels and add them to the variables. */
do
{
- struct value_label *label;
+ union value value;
+ char *label;
+ int i;
- /* Allocate label. */
- label = xmalloc (sizeof *label);
- label->ref_count = nv;
-
- /* Set label->v. */
- if (v[0]->type == ALPHA)
+ /* Set value. */
+ if (vars[0]->type == ALPHA)
{
if (token != T_STRING)
{
- msg (SE, _("String expected for value."));
+ lex_error (_("expecting string"));
return 0;
}
- st_bare_pad_copy (label->v.s, ds_value (&tokstr), MAX_SHORT_STRING);
+ st_bare_pad_copy (value.s, ds_c_str (&tokstr), MAX_SHORT_STRING);
}
else
{
- if (token != T_NUM)
+ if (!lex_is_number ())
{
- msg (SE, _("Number expected for value."));
+ lex_error (_("expecting integer"));
return 0;
}
- if (!lex_integer_p ())
+ if (!lex_is_integer ())
msg (SW, _("Value label `%g' is not integer."), tokval);
- label->v.f = tokval;
+ value.f = tokval;
}
-
- /* Set label->s. */
lex_get ();
+
+ /* Set label. */
if (!lex_force_string ())
return 0;
if (ds_length (&tokstr) > 60)
msg (SW, _("Truncating value label to 60 characters."));
ds_truncate (&tokstr, 60);
}
- label->s = xstrdup (ds_value (&tokstr));
+ label = ds_c_str (&tokstr);
- for (i = 0; i < nv; i++)
- {
- if (!v[i]->val_lab)
- v[i]->val_lab = avl_create (NULL, val_lab_cmp,
- (void *) (v[i]->width));
-
- {
- struct value_label *old;
-
- old = avl_replace (v[i]->val_lab, label);
- if (old)
- free_value_label (old);
- }
- }
+ for (i = 0; i < var_cnt; i++)
+ val_labs_replace (vars[i]->val_labs, value, label);
lex_get ();
}
return 1;
}
-
-#if 0 && DEBUGGING
-static void
-debug_print ()
-{
- int i;
-
- puts (_("Value labels:"));
- for (i = 0; i < nvar; i++)
- {
- AVLtraverser *t = NULL;
- struct value_label *val;
-
- printf (" %s\n", var[i]->name);
- if (var[i]->val_lab)
- if (var[i]->type == NUMERIC)
- for (val = avltrav (var[i]->val_lab, &t);
- val; val = avltrav (var[i]->val_lab, &t))
- printf (" %g: `%s'\n", val->v.f, val->s);
- else
- for (val = avltrav (var[i]->val_lab, &t);
- val; val = avltrav (var[i]->val_lab, &t))
- printf (" `%.8s': `%s'\n", val->v.s, val->s);
- else
- printf (_(" (no value labels)\n"));
- }
-}
-#endif /* DEBUGGING */
-
-/* Compares two value labels and returns a strcmp()-type result. */
-int
-val_lab_cmp (const void *a, const void *b, void *param)
-{
- if ((int) param)
- return strncmp (((struct value_label *) a)->v.s,
- ((struct value_label *) b)->v.s,
- (int) param);
- else
- {
- int temp = (((struct value_label *) a)->v.f
- - ((struct value_label *) b)->v.f);
- if (temp > 0)
- return 1;
- else if (temp < 0)
- return -1;
- else
- return 0;
- }
-}
-
-/* Callback function to increment the reference count for a value
- label. */
-void *
-inc_ref_count (void *pv, void *param unused)
-{
- ((struct value_label *) pv)->ref_count++;
- return pv;
-}
-
-/* Copy the avl tree of value labels and return a pointer to the
- copy. */
-avl_tree *
-copy_value_labels (avl_tree *src)
-{
- avl_tree *dest;
-
- if (src == NULL)
- return NULL;
- dest = avl_copy (NULL, src, inc_ref_count);
-
- return dest;
-}