variable-parser: Eliminate use of old hash table data structure.
[pspp] / src / language / lexer / variable-parser.c
index 26b2e1bfd2537d3fff65978a93e1458a09492a30..c6a2d5378b112ecd2210d74bc904f054df893d6e 100644 (file)
@@ -1,41 +1,41 @@
-/* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 1997-9, 2000, 2009, 2010 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
    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., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
 
-#include <language/lexer/variable-parser.h>
+#include "language/lexer/variable-parser.h"
 
 #include <ctype.h>
 #include <stdbool.h>
 #include <stdlib.h>
 
-#include "lexer.h"
-#include <data/dictionary.h>
-#include <data/procedure.h>
-#include <data/variable.h>
-#include <libpspp/alloc.h>
-#include <libpspp/assertion.h>
-#include <libpspp/bit-vector.h>
-#include <libpspp/hash.h>
-#include <libpspp/message.h>
-#include <libpspp/misc.h>
-#include <libpspp/pool.h>
-#include <libpspp/str.h>
+#include "data/dictionary.h"
+#include "data/procedure.h"
+#include "data/variable.h"
+#include "language/lexer/lexer.h"
+#include "libpspp/assertion.h"
+#include "libpspp/cast.h"
+#include "libpspp/hash-functions.h"
+#include "libpspp/hmapx.h"
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+#include "libpspp/pool.h"
+#include "libpspp/str.h"
+
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -116,12 +116,6 @@ parse_variables (struct lexer *lexer, const struct dictionary *d,
 
   vs = var_set_create_from_dict (d);
   success = parse_var_set_vars (lexer, vs, var, cnt, opts);
-  if ( success == 0 )
-    {
-      free ( *var ) ;
-      *var = NULL;
-      *cnt = 0;
-    }
   var_set_destroy (vs);
   return success;
 }
@@ -199,7 +193,7 @@ add_variable (struct variable ***v, size_t *nv, size_t *mv,
            && var_get_width (add) != var_get_width ((*v)[0]))
     msg (SE, _("%s and %s are string variables with different widths.  "
                "All variables in this variable list must have the "
-               "same width.  %s will be omttied from the list."),
+               "same width.  %s will be omitted from the list."),
          var_get_name ((*v)[0]), add_name, add_name);
   else if ((pv_opts & PV_NO_DUPLICATE) && included[idx])
     msg (SE, _("Variable %s appears twice in variable list."), add_name);
@@ -412,8 +406,8 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
   int d1, d2;
   int n;
   size_t nvar, mvar;
-  char name1[LONG_NAME_LEN + 1], name2[LONG_NAME_LEN + 1];
-  char root1[LONG_NAME_LEN + 1], root2[LONG_NAME_LEN + 1];
+  char name1[VAR_NAME_LEN + 1], name2[VAR_NAME_LEN + 1];
+  char root1[VAR_NAME_LEN + 1], root2[VAR_NAME_LEN + 1];
   int success = 0;
 
   assert (names != NULL);
@@ -481,7 +475,7 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
 
          for (n = n1; n <= n2; n++)
            {
-              char name[LONG_NAME_LEN + 1];
+              char name[VAR_NAME_LEN + 1];
              sprintf (name, "%s%0*d", root1, d1, n);
              (*names)[nvar] = xstrdup (name);
              nvar++;
@@ -671,7 +665,7 @@ var_set_lookup_var_idx (const struct var_set *vs, const char *name,
 {
   assert (vs != NULL);
   assert (name != NULL);
-  assert (strlen (name) <= LONG_NAME_LEN);
+  assert (strlen (name) <= VAR_NAME_LEN);
 
   return vs->lookup_var_idx (vs, name, idx);
 }
@@ -745,7 +739,7 @@ struct array_var_set
   {
     struct variable *const *var;/* Array of variables. */
     size_t var_cnt;             /* Number of elements in var. */
-    struct hsh_table *name_tab; /* Hash from variable names to variables. */
+    struct hmapx vars_by_name;  /* Variables hashed by name. */
   };
 
 /* Returns the number of variables in VS. */
@@ -764,7 +758,7 @@ array_var_set_get_var (const struct var_set *vs, size_t idx)
 {
   struct array_var_set *avs = vs->aux;
 
-  return (struct variable *) avs->var[idx];
+  return CONST_CAST (struct variable *, avs->var[idx]);
 }
 
 /* If VS contains a variable named NAME, sets *IDX to its index
@@ -774,19 +768,18 @@ array_var_set_lookup_var_idx (const struct var_set *vs, const char *name,
                               size_t *idx)
 {
   struct array_var_set *avs = vs->aux;
-  struct variable *v, *const *vpp;
+  struct hmapx_node *node;
+  struct variable **varp;
 
-  v = var_create (name, 0);
-  vpp = hsh_find (avs->name_tab, &v);
-  var_destroy (v);
+  HMAPX_FOR_EACH_WITH_HASH (varp, node, hash_case_string (name, 0),
+                            &avs->vars_by_name)
+    if (!strcasecmp (name, var_get_name (*varp)))
+      {
+        *idx = varp - avs->var;
+        return true;
+      }
 
-  if (vpp != NULL)
-    {
-      *idx = vpp - avs->var;
-      return true;
-    }
-  else
-    return false;
+  return false;
 }
 
 /* Destroys VS. */
@@ -795,13 +788,12 @@ array_var_set_destroy (struct var_set *vs)
 {
   struct array_var_set *avs = vs->aux;
 
-  hsh_destroy (avs->name_tab);
+  hmapx_destroy (&avs->vars_by_name);
   free (avs);
   free (vs);
 }
 
-/* Returns a variable set based on the VAR_CNT variables in
-   VAR. */
+/* Returns a variable set based on the VAR_CNT variables in VAR. */
 struct var_set *
 var_set_create_from_array (struct variable *const *var, size_t var_cnt)
 {
@@ -817,15 +809,20 @@ var_set_create_from_array (struct variable *const *var, size_t var_cnt)
   vs->aux = avs = xmalloc (sizeof *avs);
   avs->var = var;
   avs->var_cnt = var_cnt;
-  avs->name_tab = hsh_create (2 * var_cnt,
-                              compare_var_ptrs_by_name, hash_var_ptr_by_name,
-                              NULL, NULL);
+  hmapx_init (&avs->vars_by_name);
   for (i = 0; i < var_cnt; i++)
-    if (hsh_insert (avs->name_tab, (void *) &var[i]) != NULL)
-      {
-        var_set_destroy (vs);
-        return NULL;
-      }
+    {
+      const char *name = var_get_name (var[i]);
+      size_t idx;
+
+      if (array_var_set_lookup_var_idx (vs, name, &idx))
+        {
+          var_set_destroy (vs);
+          return NULL;
+        }
+      hmapx_insert (&avs->vars_by_name, CONST_CAST (void *, &avs->var[i]),
+                    hash_case_string (name, 0));
+    }
 
   return vs;
 }