Implemented long variable names a la spss V12.
[pspp-builds.git] / src / vars-atr.c
index cf4ef4e32c2030d5fbd9ab21498f545e782de241..19effedc8ecc6ae294632085a6652840bc9b8446 100644 (file)
 #include <stdlib.h>
 #include "alloc.h"
 #include "command.h"
+#include "dictionary.h"
 #include "do-ifP.h"
-#include "expr.h"
+#include "expressions/public.h"
 #include "file-handle.h"
 #include "hash.h"
+#include "lexer.h"
 #include "misc.h"
 #include "str.h"
 #include "value-labels.h"
 
 #include "debug-print.h"
 
+void *
+var_attach_aux (struct variable *v,
+                void *aux, void (*aux_dtor) (struct variable *)) 
+{
+  assert (v->aux == NULL);
+  assert (aux != NULL);
+  v->aux = aux;
+  v->aux_dtor = aux_dtor;
+  return aux;
+}
+
+void *
+var_detach_aux (struct variable *v) 
+{
+  void *aux = v->aux;
+  assert (aux != NULL);
+  v->aux = NULL;
+  return aux;
+}
+
+void
+var_clear_aux (struct variable *v) 
+{
+  assert (v != NULL);
+  if (v->aux != NULL) 
+    {
+      if (v->aux_dtor != NULL)
+        v->aux_dtor (v);
+      v->aux = NULL;
+    }
+}
+
+void
+var_dtor_free (struct variable *v) 
+{
+  free (v->aux);
+}
+
 /* Compares A and B, which both have the given WIDTH, and returns
    a strcmp()-type result. */
 int
@@ -42,16 +82,32 @@ compare_values (const union value *a, const union value *b, int width)
   if (width == 0) 
     return a->f < b->f ? -1 : a->f > b->f;
   else
-    return memcmp (a->s, b->s, width);
+    return memcmp (a->s, b->s, min(MAX_SHORT_STRING, width));
+}
+
+/* Create a hash of v */
+unsigned 
+hash_value(const union value  *v, int width)
+{
+  unsigned id_hash;
+
+  if ( 0 == width ) 
+    id_hash = hsh_hash_double (v->f);
+  else
+    id_hash = hsh_hash_bytes (v->s, min(MAX_SHORT_STRING, width));
+
+  return id_hash;
 }
 
+
+
 /* 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 = inline_file;
+  default_handle = NULL;
 
   n_lag = 0;
   
@@ -113,6 +169,7 @@ is_num_user_missing (double x, const struct 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:
@@ -175,10 +232,64 @@ is_user_missing (const union value *val, const struct variable *v)
   abort ();
 }
 \f
+/* Returns true if NAME is an acceptable name for a variable,
+   false otherwise.  If ISSUE_ERROR is true, issues an
+   explanatory error message on failure. */
+bool
+var_is_valid_name (const char *name, bool issue_error) 
+{
+  size_t length, i;
+  
+  assert (name != NULL);
+
+  length = strlen (name);
+  if (length < 1) 
+    {
+      if (issue_error)
+        msg (SE, _("Variable names must be at least 1 character long."));
+      return false;
+    }
+  else if (length > SHORT_NAME_LEN) 
+    {
+      if (issue_error)
+        msg (SE, _("Variable name %s exceeds %d-character limit."),
+             (int) SHORT_NAME_LEN);
+      return false;
+    }
+
+  for (i = 0; i < length; i++)
+    if (!CHAR_IS_IDN (name[i])) 
+      {
+        if (issue_error)
+          msg (SE, _("Character `%c' (in %s) may not appear in "
+                     "a variable name."),
+               name);
+        return false;
+      }
+        
+  if (!CHAR_IS_ID1 (name[0]))
+    {
+      if (issue_error)
+        msg (SE, _("Character `%c' (in %s), may not appear "
+                   "as the first character in a variable name."), 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 "
+                   "is a reserved word."), name);
+      return false;
+    }
+
+  return true;
+}
+
 /* A hsh_compare_func that orders variables A and B by their
    names. */
 int
-compare_variables (const void *a_, const void *b_, void *foo UNUSED) 
+compare_var_names (const void *a_, const void *b_, void *foo UNUSED) 
 {
   const struct variable *a = a_;
   const struct variable *b = b_;
@@ -188,9 +299,30 @@ compare_variables (const void *a_, const void *b_, void *foo UNUSED)
 
 /* A hsh_hash_func that hashes variable V based on its name. */
 unsigned
-hash_variable (const void *v_, void *foo UNUSED) 
+hash_var_name (const void *v_, void *foo UNUSED) 
 {
   const struct variable *v = v_;
 
   return hsh_hash_string (v->name);
 }
+
+/* A hsh_compare_func that orders pointers to variables A and B
+   by their names. */
+int
+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);
+}
+
+/* A hsh_hash_func that hashes pointer to variable V based on its
+   name. */
+unsigned
+hash_var_ptr_name (const void *v_, void *foo UNUSED) 
+{
+  struct variable *const *v = v_;
+
+  return hsh_hash_string ((*v)->name);
+}