/[pspp]/pspp/src/dictionary.c
ViewVC logotype

Diff of /pspp/src/dictionary.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.20 by jmd, Fri Apr 29 01:02:14 2005 UTC revision 1.21 by blp, Mon May 2 06:21:20 2005 UTC
# Line 27  Line 27 
27  #include "error.h"  #include "error.h"
28  #include "hash.h"  #include "hash.h"
29  #include "misc.h"  #include "misc.h"
30    #include "settings.h"
31  #include "str.h"  #include "str.h"
32  #include "value-labels.h"  #include "value-labels.h"
33  #include "var.h"  #include "var.h"
# Line 37  struct dictionary Line 38  struct dictionary
38      struct variable **var;      /* Variables. */      struct variable **var;      /* Variables. */
39      size_t var_cnt, var_cap;    /* Number of variables, capacity. */      size_t var_cnt, var_cap;    /* Number of variables, capacity. */
40      struct hsh_table *name_tab; /* Variable index by name. */      struct hsh_table *name_tab; /* Variable index by name. */
     struct hsh_table *long_name_tab; /* Variable indexed by long name */  
41      int next_value_idx;         /* Index of next `union value' to allocate. */      int next_value_idx;         /* Index of next `union value' to allocate. */
42      struct variable **split;    /* SPLIT FILE vars. */      struct variable **split;    /* SPLIT FILE vars. */
43      size_t split_cnt;           /* SPLIT FILE count. */      size_t split_cnt;           /* SPLIT FILE count. */
# Line 50  struct dictionary Line 50  struct dictionary
50      size_t vector_cnt;          /* Number of vectors. */      size_t vector_cnt;          /* Number of vectors. */
51    };    };
52    
   
   
   
   
 int  
 compare_long_names(const void *a_, const void *b_, void *aux UNUSED)  
 {  
   const struct name_table_entry *a = a_;  
   const struct name_table_entry *b = b_;  
   
   return strcasecmp(a->longname, b->longname);  
 }  
   
   
 /* Long names use case insensitive comparison */  
 unsigned int  
 hash_long_name (const void *e_, void *aux UNUSED)  
 {  
   const struct name_table_entry *e = e_;  
   unsigned int hash;  
   int i;  
   
   char *s = strdup(e->longname);  
   
   for ( i = 0 ; i < strlen(s) ; ++i )  
     s[i] = toupper(s[i]);  
   
   hash = hsh_hash_string (s);  
     
   free (s);  
   
   return hash;  
 }  
   
   
   
   
 static char *make_short_name(struct dictionary *dict, const char *longname) ;  
   
   
53  /* Creates and returns a new dictionary. */  /* Creates and returns a new dictionary. */
54  struct dictionary *  struct dictionary *
55  dict_create (void)  dict_create (void)
# Line 99  dict_create (void) Line 59  dict_create (void)
59    d->var = NULL;    d->var = NULL;
60    d->var_cnt = d->var_cap = 0;    d->var_cnt = d->var_cap = 0;
61    d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL);    d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL);
   d->long_name_tab = hsh_create (8, compare_long_names, hash_long_name,  
                                  (hsh_free_func *) free_nte, NULL);  
62    d->next_value_idx = 0;    d->next_value_idx = 0;
63    d->split = NULL;    d->split = NULL;
64    d->split_cnt = 0;    d->split_cnt = 0;
# Line 127  dict_clone (const struct dictionary *s) Line 85  dict_clone (const struct dictionary *s)
85    
86    d = dict_create ();    d = dict_create ();
87    
88    for (i = 0; i < s->var_cnt; i++)    for (i = 0; i < s->var_cnt; i++)
89      dict_clone_var (d, s->var[i], s->var[i]->name, s->var[i]->longname);      {
90          struct variable *sv = s->var[i];
91          struct variable *dv = dict_clone_var_assert (d, sv, sv->name);
92          var_set_short_name (dv, sv->short_name);
93        }
94    
95    d->next_value_idx = s->next_value_idx;    d->next_value_idx = s->next_value_idx;
96    
# Line 150  dict_clone (const struct dictionary *s) Line 112  dict_clone (const struct dictionary *s)
112    dict_set_label (d, dict_get_label (s));    dict_set_label (d, dict_get_label (s));
113    dict_set_documents (d, dict_get_documents (s));    dict_set_documents (d, dict_get_documents (s));
114    
115      d->vector_cnt = s->vector_cnt;
116      d->vector = xmalloc (d->vector_cnt * sizeof *d->vector);
117    for (i = 0; i < s->vector_cnt; i++)    for (i = 0; i < s->vector_cnt; i++)
118      dict_create_vector (d, s->vector[i]->name,      {
119                          s->vector[i]->var, s->vector[i]->cnt);        struct vector *sv = s->vector[i];
120          struct vector *dv = d->vector[i] = xmalloc (sizeof *dv);
121          int j;
122          
123          dv->idx = i;
124          strcpy (dv->name, sv->name);
125          dv->cnt = sv->cnt;
126          dv->var = xmalloc (dv->cnt * sizeof *dv->var);
127          for (j = 0; j < dv->cnt; j++)
128            dv->var[j] = d->var[sv->var[j]->index];
129        }
130    
131    return d;    return d;
132  }  }
# Line 180  dict_clear (struct dictionary *d) Line 154  dict_clear (struct dictionary *d)
154    d->var = NULL;    d->var = NULL;
155    d->var_cnt = d->var_cap = 0;    d->var_cnt = d->var_cap = 0;
156    hsh_clear (d->name_tab);    hsh_clear (d->name_tab);
   if ( d->long_name_tab)  
     hsh_clear (d->long_name_tab);  
157    d->next_value_idx = 0;    d->next_value_idx = 0;
158    free (d->split);    free (d->split);
159    d->split = NULL;    d->split = NULL;
# Line 196  dict_clear (struct dictionary *d) Line 168  dict_clear (struct dictionary *d)
168    dict_clear_vectors (d);    dict_clear_vectors (d);
169  }  }
170    
 /* Allocate the pointer TEXT and fill it with text representing the  
    long variable name buffer.  SIZE will contain the size of TEXT.  
    TEXT must be freed by the caller when no longer required.  
 */  
 void  
 dict_get_varname_block(const struct dictionary *dict, char **text, int *size)  
 {  
   char *buf = 0;  
   int bufsize = 0;  
   struct hsh_iterator hi;  
   struct name_table_entry *nte;  
   short first = 1;  
   
   for ( nte = hsh_first(dict->long_name_tab, &hi);  
         nte;  
         nte = hsh_next(dict->long_name_tab, &hi))  
     {  
       bufsize += strlen(nte->name) + strlen(nte->longname) + 2;  
       buf = xrealloc(buf, bufsize + 1);  
       if ( first )  
         strcpy(buf, "");  
       first = 0;  
   
       strcat(buf, nte->name);  
       strcat(buf, "=");  
       strcat(buf, nte->longname);  
       strcat(buf, "\t");  
     }  
   
   if ( bufsize > 0 )  
     {  
       /* Loose the final delimiting TAB */  
       buf[bufsize]='\0';  
       bufsize--;  
     }  
     
   *text = buf;  
   *size = bufsize;  
 }  
   
 /* Add a new entry into the dictionary's long name table, and update the  
    corresponding variable with the relevant long name.  
 */  
 void  
 dict_add_longvar_entry(struct dictionary *d,  
                        const char *name,  
                        const char *longname)  
 {  
   struct variable *v;  
   assert ( name ) ;  
   assert ( longname );  
   struct name_table_entry *nte = xmalloc (sizeof (struct name_table_entry));  
   nte->longname = strdup(longname);  
   nte->name = strdup(name);  
   
   /* Look up the name in name_tab */  
   v = hsh_find ( d->name_tab, name);  
   if ( !v )  
     {  
       msg (FE, _("The entry \"%s\" in the variable name map, has no corresponding variable"), name);  
       return ;  
     }  
   assert ( 0 == strcmp(v->name, name) );  
   v->longname = nte->longname;  
   
   hsh_insert(d->long_name_tab, nte);  
 }  
   
 /* Destroy and free up an nte */  
 void  
 free_nte(struct name_table_entry *nte)  
 {  
   assert(nte);  
   free(nte->longname);  
   free(nte->name);  
   free(nte);  
 }  
   
   
171  /* Destroys the aux data for every variable in D, by calling  /* Destroys the aux data for every variable in D, by calling
172     var_clear_aux() for each variable. */     var_clear_aux() for each variable. */
173  void  void
# Line 296  dict_destroy (struct dictionary *d) Line 189  dict_destroy (struct dictionary *d)
189      {      {
190        dict_clear (d);        dict_clear (d);
191        hsh_destroy (d->name_tab);        hsh_destroy (d->name_tab);
       hsh_destroy (d->long_name_tab);  
192        free (d);        free (d);
193      }      }
194  }  }
# Line 354  dict_get_vars (const struct dictionary * Line 246  dict_get_vars (const struct dictionary *
246  }  }
247    
248    
 static struct variable * dict_create_var_x (struct dictionary *d,  
                                             const char *name, int width,  
                                             short name_is_short) ;  
   
 /* Creates and returns a new variable in D with the given LONGNAME  
    and WIDTH.  Returns a null pointer if the given LONGNAME would  
    duplicate that of an existing variable in the dictionary.  
 */  
 struct variable *  
 dict_create_var (struct dictionary *d, const char *longname, int width)  
 {  
   return dict_create_var_x(d, longname, width, 0);  
 }  
   
   
 /* Creates and returns a new variable in D with the given SHORTNAME and  
    WIDTH.  The long name table is not updated */  
 struct variable *  
 dict_create_var_from_short (struct dictionary *d, const char *shortname,  
                             int width)  
 {  
   return dict_create_var_x(d, shortname, width, 1);  
 }  
   
   
   
249  /* Creates and returns a new variable in D with the given NAME  /* Creates and returns a new variable in D with the given NAME
250     and WIDTH.       and WIDTH.  Returns a null pointer if the given NAME would
251     If NAME_IS_SHORT, assume NAME is the short name.  Otherwise assumes     duplicate that of an existing variable in the dictionary. */
252     NAME is the long name, and creates the corresponding entry in the  struct variable *
253     Dictionary's lookup name table .  dict_create_var (struct dictionary *d, const char *name, int width)
    Returns a null pointer if the given NAME would  
    duplicate that of an existing variable in the dictionary.  
     
 */  
 static struct variable *  
 dict_create_var_x (struct dictionary *d, const char *name, int width,  
                  short name_is_short)  
254  {  {
255    struct variable *v;    struct variable *v;
256    
# Line 399  dict_create_var_x (struct dictionary *d, Line 258  dict_create_var_x (struct dictionary *d,
258    assert (name != NULL);    assert (name != NULL);
259    
260    assert (strlen (name) >= 1);    assert (strlen (name) >= 1);
261      assert (strlen (name) <= LONG_NAME_LEN);
262    
263    assert (width >= 0 && width < 256);    assert (width >= 0 && width < 256);
264            
   if ( name_is_short )  
     assert(strlen (name) <= SHORT_NAME_LEN);  
   else  
     assert(strlen (name) <= LONG_NAME_LEN);  
   
265    /* Make sure there's not already a variable by that name. */    /* Make sure there's not already a variable by that name. */
266    if (dict_lookup_var (d, name) != NULL)    if (dict_lookup_var (d, name) != NULL)
267      return NULL;      return NULL;
268    
269    /* Allocate and initialize variable. */    /* Allocate and initialize variable. */
270    v = xmalloc (sizeof *v);    v = xmalloc (sizeof *v);
271      st_trim_copy (v->name, name, sizeof v->name);
   if ( name_is_short )  
     {  
       strncpy (v->name, name, sizeof v->name);  
       v->name[SHORT_NAME_LEN] = '\0';  
     }  
   else  
     {  
       const char *sn = make_short_name(d, name);  
       strncpy(v->name, sn, SHORT_NAME_LEN + 1);  
       free(sn);  
     }  
     
   
   v->index = d->var_cnt;  
272    v->type = width == 0 ? NUMERIC : ALPHA;    v->type = width == 0 ? NUMERIC : ALPHA;
273    v->width = width;    v->width = width;
274    v->fv = d->next_value_idx;    v->fv = d->next_value_idx;
275    v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);    v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
276    v->init = 1;    v->init = 1;
277    v->reinit = dict_class_from_id (v->name) != DC_SCRATCH;    v->reinit = dict_class_from_id (v->name) != DC_SCRATCH;
278      v->index = d->var_cnt;
279    v->miss_type = MISSING_NONE;    v->miss_type = MISSING_NONE;
280    if (v->type == NUMERIC)    if (v->type == NUMERIC)
281      {      {
# Line 458  dict_create_var_x (struct dictionary *d, Line 300  dict_create_var_x (struct dictionary *d,
300    v->write = v->print;    v->write = v->print;
301    v->val_labs = val_labs_create (v->width);    v->val_labs = val_labs_create (v->width);
302    v->label = NULL;    v->label = NULL;
303      var_clear_short_name (v);
304    v->aux = NULL;    v->aux = NULL;
305    v->aux_dtor = NULL;    v->aux_dtor = NULL;
306    
# Line 471  dict_create_var_x (struct dictionary *d, Line 314  dict_create_var_x (struct dictionary *d,
314    d->var_cnt++;    d->var_cnt++;
315    hsh_force_insert (d->name_tab, v);    hsh_force_insert (d->name_tab, v);
316    
   if ( ! name_is_short)  
     dict_add_longvar_entry(d, v->name, name);  
   
317    d->next_value_idx += v->nv;    d->next_value_idx += v->nv;
318    
319    return v;    return v;
# Line 483  dict_create_var_x (struct dictionary *d, Line 323  dict_create_var_x (struct dictionary *d,
323     and WIDTH.  Assert-fails if the given NAME would duplicate     and WIDTH.  Assert-fails if the given NAME would duplicate
324     that of an existing variable in the dictionary. */     that of an existing variable in the dictionary. */
325  struct variable *  struct variable *
326  dict_create_var_assert (struct dictionary *d, const char *longname, int width)  dict_create_var_assert (struct dictionary *d, const char *name, int width)
327  {  {
328    struct variable *v = dict_create_var (d, longname, width);    struct variable *v = dict_create_var (d, name, width);
329    assert (v != NULL);    assert (v != NULL);
330    return v;    return v;
331  }  }
332    
333  /* Creates a new variable in D with longname LONGNAME, as a copy of  /* Creates and returns a new variable in D with name NAME, as a
334     existing  variable OV, which need not be in D or in any     copy of existing variable OV, which need not be in D or in any
335     dictionary.     dictionary.  Returns a null pointer if the given NAME would
336     If SHORTNAME is non null, it will be used as the short name     duplicate that of an existing variable in the dictionary. */
    otherwise a new short name will be generated.  
 */  
337  struct variable *  struct variable *
338  dict_clone_var (struct dictionary *d, const struct variable *ov,  dict_clone_var (struct dictionary *d, const struct variable *ov,
339                  const char *name, const char *longname)                  const char *name)
340  {  {
341    struct variable *nv;    struct variable *nv;
342    
343    assert (d != NULL);    assert (d != NULL);
344    assert (ov != NULL);    assert (ov != NULL);
345    assert (strlen (longname) <= LONG_NAME_LEN);    assert (name != NULL);
   
   struct name_table_entry *nte = xmalloc (sizeof (struct name_table_entry));  
   
   nte->longname = strdup(longname);  
   if ( name )  
     {  
       assert (strlen (name) >= 1);  
       assert (strlen (name) <= SHORT_NAME_LEN);  
       nte->name = strdup(name);  
     }  
   else  
     nte->name = make_short_name(d, longname);  
346    
347      assert (strlen (name) >= 1);
348      assert (strlen (name) <= LONG_NAME_LEN);
349    
350    nv = dict_create_var_from_short (d, nte->name, ov->width);    nv = dict_create_var (d, name, ov->width);
351    if (nv == NULL)    if (nv == NULL)
352      return NULL;      return NULL;
353    
354    hsh_insert(d->long_name_tab, nte);    /* Copy most members not copied via dict_create_var().
355    nv->longname = nte->longname;       short_name[] is intentionally not copied, because there is
356         no reason to give a new variable with potentially a new name
357         the same short name. */
358    nv->init = 1;    nv->init = 1;
359    nv->reinit = ov->reinit;    nv->reinit = ov->reinit;
360    nv->miss_type = ov->miss_type;    nv->miss_type = ov->miss_type;
# Line 536  dict_clone_var (struct dictionary *d, co Line 365  dict_clone_var (struct dictionary *d, co
365    nv->val_labs = val_labs_copy (ov->val_labs);    nv->val_labs = val_labs_copy (ov->val_labs);
366    if (ov->label != NULL)    if (ov->label != NULL)
367      nv->label = xstrdup (ov->label);      nv->label = xstrdup (ov->label);
   
   nv->alignment = ov->alignment;  
368    nv->measure = ov->measure;    nv->measure = ov->measure;
369    nv->display_width = ov->display_width;    nv->display_width = ov->display_width;
370      nv->alignment = ov->alignment;
371    
372    return nv;    return nv;
373  }  }
374    
375  /* Changes the name of V in D to name NEW_NAME.  Assert-fails if  /* Creates and returns a new variable in D with name NAME, as a
376     a variable named NEW_NAME is already in D, except that     copy of existing variable OV, which need not be in D or in any
377     NEW_NAME may be the same as V's existing name. */     dictionary.  Assert-fails if the given NAME would duplicate
378  void     that of an existing variable in the dictionary. */
379  dict_rename_var (struct dictionary *d, struct variable *v,  struct variable *
380                   const char *new_name)  dict_clone_var_assert (struct dictionary *d, const struct variable *ov,
381                           const char *name)
382  {  {
383    assert (d != NULL);    struct variable *v = dict_clone_var (d, ov, name);
384    assert (v != NULL);    assert (v != NULL);
385    assert (new_name != NULL);    return v;
   assert (strlen (new_name) >= 1 && strlen (new_name) <= SHORT_NAME_LEN);  
   assert (dict_contains_var (d, v));  
   
   if (!strcmp (v->name, new_name))  
     return;  
   
   assert (dict_lookup_var (d, new_name) == NULL);  
   
   hsh_force_delete (d->name_tab, v);  
   strncpy (v->name, new_name, sizeof v->name);  
   v->name[SHORT_NAME_LEN] = '\0';  
   hsh_force_insert (d->name_tab, v);  
   dict_add_longvar_entry (d, new_name, new_name);  
386  }  }
387    
388  /* Returns the variable named NAME in D, or a null pointer if no  /* Returns the variable named NAME in D, or a null pointer if no
# Line 575  struct variable * Line 391  struct variable *
391  dict_lookup_var (const struct dictionary *d, const char *name)  dict_lookup_var (const struct dictionary *d, const char *name)
392  {  {
393    struct variable v;    struct variable v;
   struct variable *vr;  
394        
   char *short_name;  
   struct name_table_entry key;  
   struct name_table_entry *nte;  
   
395    assert (d != NULL);    assert (d != NULL);
396    assert (name != NULL);    assert (name != NULL);
   assert (strlen (name) >= 1 && strlen (name) <= LONG_NAME_LEN);  
   
   key.longname = name;  
   nte = hsh_find (d->long_name_tab, &key);  
     
   if ( ! nte )  
   {  
     return 0;  
   }  
397    
398    short_name = nte->name ;    st_trim_copy (v.name, name, sizeof v.name);
399      return hsh_find (d->name_tab, &v);
   strncpy (v.name, short_name, sizeof v.name);  
   v.name[SHORT_NAME_LEN] = '\0';  
   
   vr = hsh_find (d->name_tab, &v);  
   
   return vr;  
400  }  }
401    
   
402  /* Returns the variable named NAME in D.  Assert-fails if no  /* Returns the variable named NAME in D.  Assert-fails if no
403     variable has that name. */     variable has that name. */
404  struct variable *  struct variable *
# Line 701  dict_delete_vars (struct dictionary *d, Line 496  dict_delete_vars (struct dictionary *d,
496      dict_delete_var (d, *vars++);      dict_delete_var (d, *vars++);
497  }  }
498    
499    /* Moves V to 0-based position IDX in D.  Other variables in D,
500       if any, retain their relative positions.  Runs in time linear
501       in the distance moved. */
502    void
503    dict_reorder_var (struct dictionary *d, struct variable *v,
504                      size_t new_index)
505    {
506      size_t min_idx, max_idx;
507      size_t i;
508      
509      assert (d != NULL);
510      assert (v != NULL);
511      assert (dict_contains_var (d, v));
512      assert (new_index < d->var_cnt);
513    
514      move_element (d->var, d->var_cnt, sizeof *d->var, v->index, new_index);
515    
516      min_idx = min (v->index, new_index);
517      max_idx = max (v->index, new_index);
518      for (i = min_idx; i <= max_idx; i++)
519        d->var[i]->index = i;
520    }
521    
522  /* Reorders the variables in D, placing the COUNT variables  /* Reorders the variables in D, placing the COUNT variables
523     listed in ORDER in that order at the beginning of D.  The     listed in ORDER in that order at the beginning of D.  The
524     other variables in D, if any, retain their relative     other variables in D, if any, retain their relative
# Line 736  dict_reorder_vars (struct dictionary *d, Line 554  dict_reorder_vars (struct dictionary *d,
554    d->var = new_var;    d->var = new_var;
555  }  }
556    
557    /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
558       a variable named NEW_NAME is already in D, except that
559       NEW_NAME may be the same as V's existing name. */
560    void
561    dict_rename_var (struct dictionary *d, struct variable *v,
562                     const char *new_name)
563    {
564      assert (d != NULL);
565      assert (v != NULL);
566      assert (new_name != NULL);
567      assert (var_is_valid_name (new_name, false));
568      assert (dict_contains_var (d, v));
569      assert (!compare_var_names (v->name, new_name, NULL)
570              || dict_lookup_var (d, new_name) == NULL);
571    
572      hsh_force_delete (d->name_tab, v);
573      st_trim_copy (v->name, new_name, sizeof v->name);
574      hsh_force_insert (d->name_tab, v);
575    
576      if (get_algorithm () == ENHANCED)
577        var_clear_short_name (v);
578    }
579    
580  /* Renames COUNT variables specified in VARS to the names given  /* Renames COUNT variables specified in VARS to the names given
581     in NEW_NAMES within dictionary D.  If the renaming would     in NEW_NAMES within dictionary D.  If the renaming would
582     result in a duplicate variable name, returns zero and stores a     result in a duplicate variable name, returns zero and stores a
# Line 751  dict_rename_vars (struct dictionary *d, Line 592  dict_rename_vars (struct dictionary *d,
592    size_t i;    size_t i;
593    int success = 1;    int success = 1;
594    
   
595    assert (d != NULL);    assert (d != NULL);
596    assert (count == 0 || vars != NULL);    assert (count == 0 || vars != NULL);
597    assert (count == 0 || new_names != NULL);    assert (count == 0 || new_names != NULL);
598    
599      /* Remove the variables to be renamed from the name hash,
600         save their names, and rename them. */
601    old_names = xmalloc (count * sizeof *old_names);    old_names = xmalloc (count * sizeof *old_names);
602    for (i = 0; i < count; i++)    for (i = 0; i < count; i++)
603      {      {
604        assert (d->var[vars[i]->index] == vars[i]);        assert (d->var[vars[i]->index] == vars[i]);
605          assert (var_is_valid_name (new_names[i], false));
606        hsh_force_delete (d->name_tab, vars[i]);        hsh_force_delete (d->name_tab, vars[i]);
607        old_names[i] = xstrdup (vars[i]->name);        old_names[i] = xstrdup (vars[i]->name);
608          strcpy (vars[i]->name, new_names[i]);
609      }      }
610      
611      /* Add the renamed variables back into the name hash,
612         checking for conflicts. */
613    for (i = 0; i < count; i++)    for (i = 0; i < count; i++)
614      {      {
       char *sn;  
       struct name_table_entry key;  
       struct name_table_entry *nte;  
615        assert (new_names[i] != NULL);        assert (new_names[i] != NULL);
616        assert (*new_names[i] != '\0');        assert (*new_names[i] != '\0');
617        assert (strlen (new_names[i]) <= LONG_NAME_LEN );        assert (strlen (new_names[i]) >= 1);
618                assert (strlen (new_names[i]) <= LONG_NAME_LEN);
       sn = make_short_name(d, new_names[i]);  
       strncpy(vars[i]->name, sn, SHORT_NAME_LEN + 1);  
       free(sn);  
         
   
   
       key.longname = vars[i]->longname;  
       nte = hsh_find (d->long_name_tab, &key);  
         
       free( nte->longname ) ;  
       nte->longname = strdup ( new_names[i]);  
       vars[i]->longname = nte->longname;  
619    
620        if (hsh_insert (d->name_tab, vars[i]) != NULL )        if (hsh_insert (d->name_tab, vars[i]) != NULL)
621          {          {
622              /* There is a name conflict.
623                 Back out all the name changes that have already
624                 taken place, and indicate failure. */
625            size_t fail_idx = i;            size_t fail_idx = i;
626            if (err_name != NULL)            if (err_name != NULL)
627              *err_name = new_names[i];              *err_name = new_names[i];
# Line 800  dict_rename_vars (struct dictionary *d, Line 633  dict_rename_vars (struct dictionary *d,
633              {              {
634                strcpy (vars[i]->name, old_names[i]);                strcpy (vars[i]->name, old_names[i]);
635                hsh_force_insert (d->name_tab, vars[i]);                hsh_force_insert (d->name_tab, vars[i]);
   
       key.longname = vars[i]->longname;  
       nte = hsh_find (d->long_name_tab, &key);  
         
       free( nte->longname ) ;  
       nte->longname = strdup ( old_names[i]);  
       vars[i]->longname = nte->longname;  
   
636              }              }
637    
638            success = 0;            success = 0;
639            break;            goto done;
640          }          }
641      }      }
642    
643      /* Clear short names. */
644      if (get_algorithm () == ENHANCED)
645        for (i = 0; i < count; i++)
646          var_clear_short_name (vars[i]);
647    
648     done:
649      /* Free the old names we kept around. */
650    for (i = 0; i < count; i++)    for (i = 0; i < count; i++)
651      free (old_names[i]);      free (old_names[i]);
652    free (old_names);    free (old_names);
# Line 1125  dict_create_vector (struct dictionary *d Line 957  dict_create_vector (struct dictionary *d
957                      struct variable **var, size_t cnt)                      struct variable **var, size_t cnt)
958  {  {
959    struct vector *vector;    struct vector *vector;
960      size_t i;
961    
962    assert (d != NULL);    assert (d != NULL);
963    assert (name != NULL);    assert (name != NULL);
964    assert (strlen (name) > 0 && strlen (name) <= SHORT_NAME_LEN );    assert (var_is_valid_name (name, false));
965    assert (var != NULL);    assert (var != NULL);
966    assert (cnt > 0);    assert (cnt > 0);
967        
# Line 1138  dict_create_vector (struct dictionary *d Line 971  dict_create_vector (struct dictionary *d
971    d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);    d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
972    vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);    vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
973    vector->idx = d->vector_cnt++;    vector->idx = d->vector_cnt++;
974    strncpy (vector->name, name, SHORT_NAME_LEN);    st_trim_copy (vector->name, name, sizeof vector->name);
   vector->name[SHORT_NAME_LEN] = '\0';  
975    vector->var = xmalloc (cnt * sizeof *var);    vector->var = xmalloc (cnt * sizeof *var);
976    memcpy (vector->var, var, cnt * sizeof *var);    for (i = 0; i < cnt; i++)
977        {
978          assert (dict_contains_var (d, var[i]));
979          vector->var[i] = var[i];
980        }
981    vector->cnt = cnt;    vector->cnt = cnt;
982        
983    return 1;    return 1;
# Line 1178  dict_lookup_vector (const struct diction Line 1014  dict_lookup_vector (const struct diction
1014    assert (name != NULL);    assert (name != NULL);
1015    
1016    for (i = 0; i < d->vector_cnt; i++)    for (i = 0; i < d->vector_cnt; i++)
1017      if (!strcmp (d->vector[i]->name, name))      if (!strcasecmp (d->vector[i]->name, name))
1018        return d->vector[i];        return d->vector[i];
1019    return NULL;    return NULL;
1020  }  }
# Line 1201  dict_clear_vectors (struct dictionary *d Line 1037  dict_clear_vectors (struct dictionary *d
1037    d->vector_cnt = 0;    d->vector_cnt = 0;
1038  }  }
1039    
1040    /* Compares two strings. */
1041  static const char * quasi_base27(int i);  static int
1042    compare_strings (const void *a, const void *b, void *aux UNUSED)
   
 /* Convert I to quasi base 27  
    The result is a staticly allocated string.  
 */  
 static const char *  
 quasi_base27(int i)  
1043  {  {
1044    static char result[SHORT_NAME_LEN + 1];    return strcmp (a, b);
   static char reverse[SHORT_NAME_LEN + 1];  
   
   /* FIXME: check the result cant overflow these arrays */  
   
   char *s = result ;  
   const int radix = 27;  
   int units;  
   
   /* and here's the quasi-ness of this routine */  
   i = i + ( i / radix );  
   
   strcpy(result,"");  
   do {  
     units = i % radix;  
     *s++ = (units > 0 ) ? units + 'A' - 1 : 'A';  
     i = i / radix;  
   } while (i > 0 ) ;  
   *s = '\0';  
   
   /* Reverse the result */  
   i = strlen(result);  
   s = reverse;  
   while(i >= 0)  
         *s++ = result[--i];  
   *s = '\0';  
           
   return reverse;  
1045  }  }
1046    
1047    /* Hashes a string. */
1048  /* Generate a short name, given a long name.  static unsigned
1049     The return value of this function must be freed by the caller.  hash_string (const void *s, void *aux UNUSED)
 */  
 static char *  
 make_short_name(struct dictionary *dict, const char *longname)  
1050  {  {
1051    int i = 0;    return hsh_hash_string (s);
1052    char *p;  }
   
   
   char *d = xmalloc ( SHORT_NAME_LEN + 1);  
1053    
1054    /* Truncate the name */  /* Assigns a valid, unique short_name[] to each variable in D.
1055    strncpy(d, longname, SHORT_NAME_LEN);     Each variable whose actual name is short has highest priority
1056    d[SHORT_NAME_LEN] = '\0';     for that short name.  Otherwise, variables with an existing
1057       short_name[] have the next highest priority for a given short
1058       name; if it is already taken, then the variable is treated as
1059       if short_name[] had been empty.  Otherwise, long names are
1060       truncated to form short names.  If that causes conflicts,
1061       variables are renamed as PREFIX_A, PREFIX_B, and so on. */
1062    void
1063    dict_assign_short_names (struct dictionary *d)
1064    {
1065      struct hsh_table *short_names;
1066      size_t i;
1067    
1068    /* Convert to upper case */    /* Give variables whose names are short the corresponding short
1069    for ( p = d; *p ; ++p )       names, and clear short_names[] that conflict with a variable
1070          *p = toupper(*p);       name. */
1071      for (i = 0; i < d->var_cnt; i++)
1072        {
1073          struct variable *v = d->var[i];
1074          if (strlen (v->name) <= SHORT_NAME_LEN)
1075            var_set_short_name (v, v->name);
1076          else if (dict_lookup_var (d, v->short_name) != NULL)
1077            var_clear_short_name (v);
1078        }
1079    
1080    /* If a variable with that name already exists, then munge it    /* Each variable with an assigned short_name[] now gets it
1081       until there's no conflict */       unless there is a conflict. */
1082    while (0 != hsh_find (dict->name_tab, d))    short_names = hsh_create (d->var_cnt, compare_strings, hash_string,
1083    {                              NULL, NULL);
1084          const char *suffix = quasi_base27(i++);    for (i = 0; i < d->var_cnt; i++)
1085        {
1086          struct variable *v = d->var[i];
1087          if (v->short_name[0] && hsh_insert (short_names, v->short_name) != NULL)
1088            var_clear_short_name (v);
1089        }
1090      
1091      /* Now assign short names to remaining variables. */
1092      for (i = 0; i < d->var_cnt; i++)
1093        {
1094          struct variable *v = d->var[i];
1095          if (v->short_name[0] == '\0')
1096            {
1097              int sfx;
1098    
1099          d[SHORT_NAME_LEN -  strlen(suffix) - 1 ] = '_';            /* Form initial short_name. */
1100          d[SHORT_NAME_LEN -  strlen(suffix)  ] = '\0';            var_set_short_name (v, v->name);
         strcat(d, suffix);  
   }  
1101    
1102              /* Try _A, _B, ... _AA, _AB, etc., if needed. */
1103              for (sfx = 0; hsh_insert (short_names, v->short_name) != NULL; sfx++)
1104                var_set_short_name_suffix (v, v->name, sfx);
1105            }
1106        }
1107    
1108    return d;    /* Get rid of hash table. */
1109      hsh_destroy (short_names);
1110  }  }
   
   
   
   

Legend:
Removed from v.1.20  
changed lines
  Added in v.1.21

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26