Removed extra free
[pspp-builds.git] / src / vars-atr.c
index a3024d0c8eb4dfb465b6c980d2c9e096b25d4990..970ce5673f45c0154ae08640b28bcb92171cc99b 100644 (file)
 #include "error.h"
 #include <stdlib.h>
 #include "alloc.h"
-#include "command.h"
 #include "dictionary.h"
-#include "do-ifP.h"
-#include "expressions/public.h"
-#include "file-handle.h"
 #include "hash.h"
-#include "lexer.h"
+#include "lex-def.h"
 #include "misc.h"
 #include "str.h"
 #include "value-labels.h"
-#include "vfm.h"
 
-#include "debug-print.h"
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Returns an adjective describing the given variable TYPE,
+   suitable for use in phrases like "numeric variable". */
+const char *
+var_type_adj (enum var_type type) 
+{
+  return type == NUMERIC ? _("numeric") : _("string");
+}
+
+/* Returns a noun describing a value of the given variable TYPE,
+   suitable for use in phrases like "a number". */
+const char *
+var_type_noun (enum var_type type) 
+{
+  return type == NUMERIC ? _("number") : _("string");
+}
 
 /* Assign auxiliary data AUX to variable V, which must not
    already have auxiliary data.  Before V's auxiliary data is
@@ -111,136 +123,6 @@ hash_value(const union value  *v, int width)
 
 
 
-/* Discards all the current state in preparation for a data-input
-   command like DATA LIST or GET. */
-void
-discard_variables (void)
-{
-  dict_clear (default_dict);
-  default_handle = NULL;
-
-  n_lag = 0;
-  
-  if (vfm_source != NULL)
-    {
-      free_case_source (vfm_source);
-      vfm_source = NULL;
-    }
-
-  cancel_transformations ();
-
-  ctl_stack = NULL;
-
-  expr_free (process_if_expr);
-  process_if_expr = NULL;
-
-  cancel_temporary ();
-
-  pgm_state = STATE_INIT;
-}
-
-/* Return nonzero only if X is a user-missing value for numeric
-   variable V. */
-inline int
-is_num_user_missing (double x, const struct variable *v)
-{
-  switch (v->miss_type)
-    {
-    case MISSING_NONE:
-      return 0;
-    case MISSING_1:
-      return x == v->missing[0].f;
-    case MISSING_2:
-      return x == v->missing[0].f || x == v->missing[1].f;
-    case MISSING_3:
-      return (x == v->missing[0].f || x == v->missing[1].f
-              || x == v->missing[2].f);
-    case MISSING_RANGE:
-      return x >= v->missing[0].f && x <= v->missing[1].f;
-    case MISSING_LOW:
-      return x <= v->missing[0].f;
-    case MISSING_HIGH:
-      return x >= v->missing[0].f;
-    case MISSING_RANGE_1:
-      return ((x >= v->missing[0].f && x <= v->missing[1].f)
-             || x == v->missing[2].f);
-    case MISSING_LOW_1:
-      return x <= v->missing[0].f || x == v->missing[1].f;
-    case MISSING_HIGH_1:
-      return x >= v->missing[0].f || x == v->missing[1].f;
-    default:
-      assert (0);
-    }
-  abort ();
-}
-
-/* Return nonzero only if string S is a user-missing variable for
-   string variable V. */
-inline int
-is_str_user_missing (const unsigned char s[], const struct variable *v)
-{
-  /* FIXME: should these be memcmp()? */
-  switch (v->miss_type)
-    {
-    case MISSING_NONE:
-      return 0;
-    case MISSING_1:
-      return !strncmp (s, v->missing[0].s, v->width);
-    case MISSING_2:
-      return (!strncmp (s, v->missing[0].s, v->width)
-             || !strncmp (s, v->missing[1].s, v->width));
-    case MISSING_3:
-      return (!strncmp (s, v->missing[0].s, v->width)
-             || !strncmp (s, v->missing[1].s, v->width)
-             || !strncmp (s, v->missing[2].s, v->width));
-    default:
-      assert (0);
-    }
-  abort ();
-}
-
-/* Return nonzero only if value VAL is system-missing for variable
-   V. */
-int
-is_system_missing (const union value *val, const struct variable *v)
-{
-  return v->type == NUMERIC && val->f == SYSMIS;
-}
-
-/* Return nonzero only if value VAL is system- or user-missing for
-   variable V. */
-int
-is_missing (const union value *val, const struct variable *v)
-{
-  switch (v->type)
-    {
-    case NUMERIC:
-      if (val->f == SYSMIS)
-       return 1;
-      return is_num_user_missing (val->f, v);
-    case ALPHA:
-      return is_str_user_missing (val->s, v);
-    default:
-      assert (0);
-    }
-  abort ();
-}
-
-/* Return nonzero only if value VAL is user-missing for variable V. */
-int
-is_user_missing (const union value *val, const struct variable *v)
-{
-  switch (v->type)
-    {
-    case NUMERIC:
-      return is_num_user_missing (val->f, v);
-    case ALPHA:
-      return is_str_user_missing (val->s, v);
-    default:
-      assert (0);
-    }
-  abort ();
-}
 \f
 /* Returns true if NAME is an acceptable name for a variable,
    false otherwise.  If ISSUE_ERROR is true, issues an
@@ -256,14 +138,14 @@ var_is_valid_name (const char *name, bool issue_error)
   if (length < 1) 
     {
       if (issue_error)
-        msg (SE, _("Variable names must be at least 1 character long."));
+        msg (SE, _("Variable name cannot be empty string."));
       return false;
     }
-  else if (length > SHORT_NAME_LEN) 
+  else if (length > LONG_NAME_LEN) 
     {
       if (issue_error)
         msg (SE, _("Variable name %s exceeds %d-character limit."),
-             (int) SHORT_NAME_LEN);
+             name, (int) LONG_NAME_LEN);
       return false;
     }
 
@@ -273,7 +155,7 @@ var_is_valid_name (const char *name, bool issue_error)
         if (issue_error)
           msg (SE, _("Character `%c' (in %s) may not appear in "
                      "a variable name."),
-               name);
+               name[i], name);
         return false;
       }
         
@@ -281,14 +163,15 @@ var_is_valid_name (const char *name, bool issue_error)
     {
       if (issue_error)
         msg (SE, _("Character `%c' (in %s), may not appear "
-                   "as the first character in a variable name."), name);
+                   "as the first character in a variable name."),
+             name[0], name);
       return false;
     }
 
   if (lex_id_to_token (name, strlen (name)) != T_ID) 
     {
       if (issue_error)
-        msg (SE, _("%s may not be used as a variable name because it "
+        msg (SE, _("`%s' may not be used as a variable name because it "
                    "is a reserved word."), name);
       return false;
     }
@@ -304,7 +187,7 @@ compare_var_names (const void *a_, const void *b_, void *foo UNUSED)
   const struct variable *a = a_;
   const struct variable *b = b_;
 
-  return strcmp (a->name, b->name);
+  return strcasecmp (a->name, b->name);
 }
 
 /* A hsh_hash_func that hashes variable V based on its name. */
@@ -313,7 +196,7 @@ hash_var_name (const void *v_, void *foo UNUSED)
 {
   const struct variable *v = v_;
 
-  return hsh_hash_string (v->name);
+  return hsh_hash_case_string (v->name);
 }
 
 /* A hsh_compare_func that orders pointers to variables A and B
@@ -324,7 +207,7 @@ compare_var_ptr_names (const void *a_, const void *b_, void *foo UNUSED)
   struct variable *const *a = a_;
   struct variable *const *b = b_;
 
-  return strcmp ((*a)->name, (*b)->name);
+  return strcasecmp ((*a)->name, (*b)->name);
 }
 
 /* A hsh_hash_func that hashes pointer to variable V based on its
@@ -334,5 +217,103 @@ hash_var_ptr_name (const void *v_, void *foo UNUSED)
 {
   struct variable *const *v = v_;
 
-  return hsh_hash_string ((*v)->name);
+  return hsh_hash_case_string ((*v)->name);
+}
+\f
+/* Sets V's short_name to SHORT_NAME, truncating it to
+   SHORT_NAME_LEN characters and converting it to uppercase in
+   the process. */
+void
+var_set_short_name (struct variable *v, const char *short_name) 
+{
+  assert (v != NULL);
+  assert (short_name[0] == '\0' || var_is_valid_name (short_name, false));
+  
+  str_copy_trunc (v->short_name, sizeof v->short_name, short_name);
+  str_uppercase (v->short_name);
+}
+
+/* Clears V's short name. */
+void
+var_clear_short_name (struct variable *v) 
+{
+  assert (v != NULL);
+
+  v->short_name[0] = '\0';
+}
+
+/* Sets V's short name to BASE, followed by a suffix of the form
+   _A, _B, _C, ..., _AA, _AB, etc. according to the value of
+   SUFFIX.  Truncates BASE as necessary to fit. */
+void
+var_set_short_name_suffix (struct variable *v, const char *base, int suffix)
+{
+  char string[SHORT_NAME_LEN + 1];
+  char *start, *end;
+  int len, ofs;
+
+  assert (v != NULL);
+  assert (suffix >= 0);
+  assert (strlen (v->short_name) > 0);
+
+  /* Set base name. */
+  var_set_short_name (v, base);
+
+  /* Compose suffix_string. */
+  start = end = string + sizeof string - 1;
+  *end = '\0';
+  do 
+    {
+      *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix % 26];
+      if (start <= string + 1)
+        msg (SE, _("Variable suffix too large."));
+      suffix /= 26;
+    }
+  while (suffix > 0);
+  *--start = '_';
+
+  /* Append suffix_string to V's short name. */
+  len = end - start;
+  if (len + strlen (v->short_name) > SHORT_NAME_LEN)
+    ofs = SHORT_NAME_LEN - len;
+  else
+    ofs = strlen (v->short_name);
+  strcpy (v->short_name + ofs, start);
+}
+
+
+/* Returns the dictionary class corresponding to a variable named
+   NAME. */
+enum dict_class
+dict_class_from_id (const char *name) 
+{
+  assert (name != NULL);
+
+  switch (name[0]) 
+    {
+    default:
+      return DC_ORDINARY;
+    case '$':
+      return DC_SYSTEM;
+    case '#':
+      return DC_SCRATCH;
+    }
+}
+
+/* Returns the name of dictionary class DICT_CLASS. */
+const char *
+dict_class_to_name (enum dict_class dict_class) 
+{
+  switch (dict_class) 
+    {
+    case DC_ORDINARY:
+      return _("ordinary");
+    case DC_SYSTEM:
+      return _("system");
+    case DC_SCRATCH:
+      return _("scratch");
+    default:
+      assert (0);
+      abort ();
+    }
 }