/[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.15 by blp, Tue Mar 15 06:04:10 2005 UTC revision 1.16 by jmd, Wed Apr 13 10:09:59 2005 UTC
# Line 20  Line 20 
20  #include <config.h>  #include <config.h>
21  #include "dictionary.h"  #include "dictionary.h"
22  #include <stdlib.h>  #include <stdlib.h>
23    #include <ctype.h>
24  #include "algorithm.h"  #include "algorithm.h"
25  #include "alloc.h"  #include "alloc.h"
26  #include "case.h"  #include "case.h"
# Line 36  struct dictionary Line 37  struct dictionary
37      struct variable **var;      /* Variables. */      struct variable **var;      /* Variables. */
38      size_t var_cnt, var_cap;    /* Number of variables, capacity. */      size_t var_cnt, var_cap;    /* Number of variables, capacity. */
39      struct hsh_table *name_tab; /* Variable index by name. */      struct hsh_table *name_tab; /* Variable index by name. */
40        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 48  struct dictionary Line 50  struct dictionary
50      size_t vector_cnt;          /* Number of vectors. */      size_t vector_cnt;          /* Number of vectors. */
51    };    };
52    
53    
54    
55    
56    
57    int
58    compare_long_names(const void *a_, const void *b_, void *aux UNUSED)
59    {
60      const struct name_table_entry *a = a_;
61      const struct name_table_entry *b = b_;
62    
63      return strcasecmp(a->longname, b->longname);
64    }
65    
66    
67    /* Long names use case insensitive comparison */
68    unsigned int
69    hash_long_name (const void *e_, void *aux UNUSED)
70    {
71      const struct name_table_entry *e = e_;
72      unsigned int hash;
73      int i;
74    
75      char *s = strdup(e->longname);
76    
77      for ( i = 0 ; i < strlen(s) ; ++i )
78        s[i] = toupper(s[i]);
79    
80      hash = hsh_hash_string (s);
81      
82      free (s);
83    
84      return hash;
85    }
86    
87    static char *make_short_name(struct dictionary *dict, const char *longname) ;
88    
89    
90  /* Creates and returns a new dictionary. */  /* Creates and returns a new dictionary. */
91  struct dictionary *  struct dictionary *
92  dict_create (void)  dict_create (void)
# Line 57  dict_create (void) Line 96  dict_create (void)
96    d->var = NULL;    d->var = NULL;
97    d->var_cnt = d->var_cap = 0;    d->var_cnt = d->var_cap = 0;
98    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);
99      d->long_name_tab = hsh_create (8, compare_long_names, hash_long_name, NULL, NULL);
100    d->next_value_idx = 0;    d->next_value_idx = 0;
101    d->split = NULL;    d->split = NULL;
102    d->split_cnt = 0;    d->split_cnt = 0;
# Line 78  dict_clone (const struct dictionary *s) Line 118  dict_clone (const struct dictionary *s)
118  {  {
119    struct dictionary *d;    struct dictionary *d;
120    size_t i;    size_t i;
121      
122    assert (s != NULL);    assert (s != NULL);
123      
124    d = dict_create ();    d = dict_create ();
125    
126    for (i = 0; i < s->var_cnt; i++)    for (i = 0; i < s->var_cnt; i++)
127      dict_clone_var (d, s->var[i], s->var[i]->name);      dict_clone_var (d, s->var[i], s->var[i]->name, s->var[i]->longname);
128    
129    d->next_value_idx = s->next_value_idx;    d->next_value_idx = s->next_value_idx;
130    
131    d->split_cnt = s->split_cnt;    d->split_cnt = s->split_cnt;
# Line 134  dict_clear (struct dictionary *d) Line 176  dict_clear (struct dictionary *d)
176    d->var = NULL;    d->var = NULL;
177    d->var_cnt = d->var_cap = 0;    d->var_cnt = d->var_cap = 0;
178    hsh_clear (d->name_tab);    hsh_clear (d->name_tab);
179      if ( d->long_name_tab)
180        hsh_clear (d->long_name_tab);
181    d->next_value_idx = 0;    d->next_value_idx = 0;
182    free (d->split);    free (d->split);
183    d->split = NULL;    d->split = NULL;
# Line 148  dict_clear (struct dictionary *d) Line 192  dict_clear (struct dictionary *d)
192    dict_clear_vectors (d);    dict_clear_vectors (d);
193  }  }
194    
195    /* Allocate the pointer TEXT and fill it with text representing the
196       long variable name buffer.  SIZE will contain the size of TEXT.
197       TEXT must be freed by the caller when no longer required.
198    */
199    void
200    dict_get_varname_block(const struct dictionary *dict, char **text, int *size)
201    {
202      char *buf = 0;
203      int bufsize = 0;
204      struct hsh_iterator hi;
205      struct name_table_entry *nte;
206      short first = 1;
207    
208      for ( nte = hsh_first(dict->long_name_tab, &hi);
209            nte;
210            nte = hsh_next(dict->long_name_tab, &hi))
211        {
212          bufsize += strlen(nte->name) + strlen(nte->longname) + 2;
213          buf = xrealloc(buf, bufsize + 1);
214          if ( first )
215            strcpy(buf, "");
216          first = 0;
217    
218          strcat(buf, nte->name);
219          strcat(buf, "=");
220          strcat(buf, nte->longname);
221          strcat(buf, "\t");
222        }
223    
224      if ( bufsize > 0 )
225        {
226          /* Loose the final delimiting TAB */
227          buf[bufsize]='\0';
228          bufsize--;
229        }
230      
231      *text = buf;
232      *size = bufsize;
233    }
234    
235    
236    /* Add a new entry into the dictionary's long name table, and update the
237       corresponding varible with the relevant long name.
238    */
239    void
240    dict_add_longvar_entry(struct dictionary *d,
241                           const char *name,
242                           const char *longname)
243    {
244      struct variable *v;
245      assert ( name ) ;
246      assert ( longname );
247      struct name_table_entry *nte = xmalloc (sizeof (struct name_table_entry));
248      nte->longname = strdup(longname);
249      nte->name = strdup(name);
250    
251    
252      /* Look up the name in name_tab */
253      v = hsh_find ( d->name_tab, name);
254      if ( !v )
255        {
256          msg (FE, _("The entry \"%s\" in the variable name map, has no corresponding variable"), name);
257          return ;
258        }
259      assert ( 0 == strcmp(v->name, name) );
260      v->longname = nte->longname;
261    
262      hsh_insert(d->long_name_tab, nte);
263      
264    
265    }
266    
267  /* Destroys the aux data for every variable in D, by calling  /* Destroys the aux data for every variable in D, by calling
268     var_clear_aux() for each variable. */     var_clear_aux() for each variable. */
269  void  void
# Line 169  dict_destroy (struct dictionary *d) Line 285  dict_destroy (struct dictionary *d)
285      {      {
286        dict_clear (d);        dict_clear (d);
287        hsh_destroy (d->name_tab);        hsh_destroy (d->name_tab);
288          hsh_destroy (d->long_name_tab);
289        free (d);        free (d);
290      }      }
291  }  }
# Line 225  dict_get_vars (const struct dictionary * Line 342  dict_get_vars (const struct dictionary *
342    assert (*cnt == count);    assert (*cnt == count);
343  }  }
344    
345  /* Creates and returns a new variable in D with the given NAME  
346     and WIDTH.  Returns a null pointer if the given NAME would  static struct variable * dict_create_var_x (struct dictionary *d,
347     duplicate that of an existing variable in the dictionary. */                                              const char *name, int width,
348                                                short name_is_short) ;
349    
350    /* Creates and returns a new variable in D with the given LONGNAME
351       and WIDTH.  Returns a null pointer if the given LONGNAME would
352       duplicate that of an existing variable in the dictionary.
353    */
354  struct variable *  struct variable *
355  dict_create_var (struct dictionary *d, const char *name, int width)  dict_create_var (struct dictionary *d, const char *longname, int width)
356    {
357      return dict_create_var_x(d, longname, width, 0);
358    }
359    
360    
361    /* Creates and returns a new variable in D with the given SHORTNAME and
362       WIDTH.  The long name table is not updated */
363    struct variable *
364    dict_create_var_from_short (struct dictionary *d, const char *shortname,
365                                int width)
366    {
367      return dict_create_var_x(d, shortname, width, 1);
368    }
369    
370    
371    
372    /* Creates and returns a new variable in D with the given NAME
373       and WIDTH.  
374       If NAME_IS_SHORT, assume NAME is the short name.  Otherwise assumes
375       NAME is the long name, and creates the corresponding entry in the
376       Dictionary's lookup name table .
377       Returns a null pointer if the given NAME would
378       duplicate that of an existing variable in the dictionary.
379      
380    */
381    static struct variable *
382    dict_create_var_x (struct dictionary *d, const char *name, int width,
383                     short name_is_short)
384  {  {
385    struct variable *v;    struct variable *v;
386    
387    assert (d != NULL);    assert (d != NULL);
388    assert (name != NULL);    assert (name != NULL);
389    assert (strlen (name) >= 1 && strlen (name) <= 8);  
390      assert (strlen (name) >= 1);
391    
392    assert (width >= 0 && width < 256);    assert (width >= 0 && width < 256);
393        
394      if ( name_is_short )
395        assert(strlen (name) <= SHORT_NAME_LEN);
396      else
397        assert(strlen (name) <= LONG_NAME_LEN);
398    
399    /* Make sure there's not already a variable by that name. */    /* Make sure there's not already a variable by that name. */
400    if (dict_lookup_var (d, name) != NULL)    if (dict_lookup_var (d, name) != NULL)
# Line 244  dict_create_var (struct dictionary *d, c Line 402  dict_create_var (struct dictionary *d, c
402    
403    /* Allocate and initialize variable. */    /* Allocate and initialize variable. */
404    v = xmalloc (sizeof *v);    v = xmalloc (sizeof *v);
405    strncpy (v->name, name, sizeof v->name);  
406    v->name[8] = '\0';    if ( name_is_short )
407        {
408          strncpy (v->name, name, sizeof v->name);
409          v->name[SHORT_NAME_LEN] = '\0';
410        }
411      else
412        strcpy(v->name,make_short_name(d, name));
413      
414    
415    v->index = d->var_cnt;    v->index = d->var_cnt;
416    v->type = width == 0 ? NUMERIC : ALPHA;    v->type = width == 0 ? NUMERIC : ALPHA;
417    v->width = width;    v->width = width;
418    v->fv = d->next_value_idx;    v->fv = d->next_value_idx;
419    v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);    v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
420    v->init = 1;    v->init = 1;
421    v->reinit = dict_class_from_id (name) != DC_SCRATCH;    v->reinit = dict_class_from_id (v->name) != DC_SCRATCH;
422    v->miss_type = MISSING_NONE;    v->miss_type = MISSING_NONE;
423    if (v->type == NUMERIC)    if (v->type == NUMERIC)
424      {      {
425        v->print.type = FMT_F;        v->print.type = FMT_F;
426        v->print.w = 8;        v->print.w = 8;
427        v->print.d = 2;        v->print.d = 2;
428    
429          v->alignment = ALIGN_RIGHT;
430          v->display_width = 8;
431          v->measure = MEASURE_SCALE;
432      }      }
433    else    else
434      {      {
435        v->print.type = FMT_A;        v->print.type = FMT_A;
436        v->print.w = v->width;        v->print.w = v->width;
437        v->print.d = 0;        v->print.d = 0;
438    
439          v->alignment = ALIGN_LEFT;
440          v->display_width = 8;
441          v->measure = MEASURE_NOMINAL;
442      }      }
443    v->write = v->print;    v->write = v->print;
444    v->val_labs = val_labs_create (v->width);    v->val_labs = val_labs_create (v->width);
# Line 281  dict_create_var (struct dictionary *d, c Line 455  dict_create_var (struct dictionary *d, c
455    d->var[v->index] = v;    d->var[v->index] = v;
456    d->var_cnt++;    d->var_cnt++;
457    hsh_force_insert (d->name_tab, v);    hsh_force_insert (d->name_tab, v);
458    
459      if ( ! name_is_short)
460        dict_add_longvar_entry(d, v->name, name);
461    
462    d->next_value_idx += v->nv;    d->next_value_idx += v->nv;
463    
464    return v;    return v;
# Line 290  dict_create_var (struct dictionary *d, c Line 468  dict_create_var (struct dictionary *d, c
468     and WIDTH.  Assert-fails if the given NAME would duplicate     and WIDTH.  Assert-fails if the given NAME would duplicate
469     that of an existing variable in the dictionary. */     that of an existing variable in the dictionary. */
470  struct variable *  struct variable *
471  dict_create_var_assert (struct dictionary *d, const char *name, int width)  dict_create_var_assert (struct dictionary *d, const char *longname, int width)
472  {  {
473    struct variable *v = dict_create_var (d, name, width);    struct variable *v = dict_create_var (d, longname, width);
474    assert (v != NULL);    assert (v != NULL);
475    return v;    return v;
476  }  }
477    
478  /* Creates a new variable in D named NAME, as a copy of existing  /* Creates a new variable in D with longname LONGNAME, as a copy of
479     variable OV, which need not be in D or in any dictionary. */     existing  variable OV, which need not be in D or in any
480       dictionary.
481       If SHORTNAME is non null, it will be used as the short name
482       otherwise a new short name will be generated.
483    */
484  struct variable *  struct variable *
485  dict_clone_var (struct dictionary *d, const struct variable *ov,  dict_clone_var (struct dictionary *d, const struct variable *ov,
486                  const char *name)                  const char *name, const char *longname)
487  {  {
488    struct variable *nv;    struct variable *nv;
489    
490    assert (d != NULL);    assert (d != NULL);
491    assert (ov != NULL);    assert (ov != NULL);
492    assert (name != NULL);    assert (strlen (longname) <= LONG_NAME_LEN);
493    assert (strlen (name) >= 1 && strlen (name) <= 8);  
494      struct name_table_entry *nte = xmalloc (sizeof (struct name_table_entry));
495    
496      nte->longname = strdup(longname);
497      if ( name )
498        {
499          assert (strlen (name) >= 1);
500          assert (strlen (name) <= SHORT_NAME_LEN);
501          nte->name = strdup(name);
502        }
503      else
504        nte->name = make_short_name(d, longname);
505    
506    
507    nv = dict_create_var (d, name, ov->width);    nv = dict_create_var_from_short (d, nte->name, ov->width);
508    if (nv == NULL)    if (nv == NULL)
509      return NULL;      return NULL;
510    
511      hsh_insert(d->long_name_tab, nte);
512      nv->longname = nte->longname;
513    
514    nv->init = 1;    nv->init = 1;
515    nv->reinit = ov->reinit;    nv->reinit = ov->reinit;
516    nv->miss_type = ov->miss_type;    nv->miss_type = ov->miss_type;
# Line 325  dict_clone_var (struct dictionary *d, co Line 522  dict_clone_var (struct dictionary *d, co
522    if (ov->label != NULL)    if (ov->label != NULL)
523      nv->label = xstrdup (ov->label);      nv->label = xstrdup (ov->label);
524    
525      nv->alignment = ov->alignment;
526      nv->measure = ov->measure;
527      nv->display_width = ov->display_width;
528    
529    return nv;    return nv;
530  }  }
531    
# Line 338  dict_rename_var (struct dictionary *d, s Line 539  dict_rename_var (struct dictionary *d, s
539    assert (d != NULL);    assert (d != NULL);
540    assert (v != NULL);    assert (v != NULL);
541    assert (new_name != NULL);    assert (new_name != NULL);
542    assert (strlen (new_name) >= 1 && strlen (new_name) <= 8);    assert (strlen (new_name) >= 1 && strlen (new_name) <= SHORT_NAME_LEN);
543    assert (dict_contains_var (d, v));    assert (dict_contains_var (d, v));
544    
545    if (!strcmp (v->name, new_name))    if (!strcmp (v->name, new_name))
# Line 348  dict_rename_var (struct dictionary *d, s Line 549  dict_rename_var (struct dictionary *d, s
549    
550    hsh_force_delete (d->name_tab, v);    hsh_force_delete (d->name_tab, v);
551    strncpy (v->name, new_name, sizeof v->name);    strncpy (v->name, new_name, sizeof v->name);
552    v->name[8] = '\0';    v->name[SHORT_NAME_LEN] = '\0';
553    hsh_force_insert (d->name_tab, v);    hsh_force_insert (d->name_tab, v);
554  }  }
555    
# Line 358  struct variable * Line 559  struct variable *
559  dict_lookup_var (const struct dictionary *d, const char *name)  dict_lookup_var (const struct dictionary *d, const char *name)
560  {  {
561    struct variable v;    struct variable v;
562      struct variable *vr;
563        
564      char *short_name;
565      struct name_table_entry key;
566      struct name_table_entry *nte;
567    
568    assert (d != NULL);    assert (d != NULL);
569    assert (name != NULL);    assert (name != NULL);
570    assert (strlen (name) >= 1 && strlen (name) <= 8);    assert (strlen (name) >= 1 && strlen (name) <= LONG_NAME_LEN);
571    
572      key.longname = name;
573      nte = hsh_find (d->long_name_tab, &key);
574      
575      if ( ! nte )
576      {
577        return 0;
578      }
579    
580      short_name = nte->name ;
581    
582    strncpy (v.name, name, sizeof v.name);    strncpy (v.name, short_name, sizeof v.name);
583    v.name[8] = '\0';    v.name[SHORT_NAME_LEN] = '\0';
584    
585    return hsh_find (d->name_tab, &v);    vr = hsh_find (d->name_tab, &v);
586    
587      return vr;
588  }  }
589    
590    
591  /* Returns the variable named NAME in D.  Assert-fails if no  /* Returns the variable named NAME in D.  Assert-fails if no
592     variable has that name. */     variable has that name. */
593  struct variable *  struct variable *
# Line 516  dict_rename_vars (struct dictionary *d, Line 735  dict_rename_vars (struct dictionary *d,
735    size_t i;    size_t i;
736    int success = 1;    int success = 1;
737    
738    
739    assert (d != NULL);    assert (d != NULL);
740    assert (count == 0 || vars != NULL);    assert (count == 0 || vars != NULL);
741    assert (count == 0 || new_names != NULL);    assert (count == 0 || new_names != NULL);
742    
743    
744    old_names = xmalloc (count * sizeof *old_names);    old_names = xmalloc (count * sizeof *old_names);
745    for (i = 0; i < count; i++)    for (i = 0; i < count; i++)
746      {      {
# Line 530  dict_rename_vars (struct dictionary *d, Line 751  dict_rename_vars (struct dictionary *d,
751        
752    for (i = 0; i < count; i++)    for (i = 0; i < count; i++)
753      {      {
754          struct name_table_entry key;
755          struct name_table_entry *nte;
756        assert (new_names[i] != NULL);        assert (new_names[i] != NULL);
757        assert (*new_names[i] != '\0');        assert (*new_names[i] != '\0');
758        assert (strlen (new_names[i]) < 9);        assert (strlen (new_names[i]) <= LONG_NAME_LEN );
759        strcpy (vars[i]->name, new_names[i]);        strcpy (vars[i]->name, make_short_name(d, new_names[i]));
760        if (hsh_insert (d->name_tab, vars[i]) != NULL)  
761    
762          key.longname = vars[i]->longname;
763          nte = hsh_find (d->long_name_tab, &key);
764          
765          free( nte->longname ) ;
766          nte->longname = strdup ( new_names[i]);
767          vars[i]->longname = nte->longname;
768    
769          if (hsh_insert (d->name_tab, vars[i]) != NULL )
770          {          {
771            size_t fail_idx = i;            size_t fail_idx = i;
772            if (err_name != NULL)            if (err_name != NULL)
# Line 547  dict_rename_vars (struct dictionary *d, Line 779  dict_rename_vars (struct dictionary *d,
779              {              {
780                strcpy (vars[i]->name, old_names[i]);                strcpy (vars[i]->name, old_names[i]);
781                hsh_force_insert (d->name_tab, vars[i]);                hsh_force_insert (d->name_tab, vars[i]);
782    
783          key.longname = vars[i]->longname;
784          nte = hsh_find (d->long_name_tab, &key);
785          
786          free( nte->longname ) ;
787          nte->longname = strdup ( old_names[i]);
788          vars[i]->longname = nte->longname;
789    
790              }              }
791    
792            success = 0;            success = 0;
# Line 867  dict_create_vector (struct dictionary *d Line 1107  dict_create_vector (struct dictionary *d
1107    
1108    assert (d != NULL);    assert (d != NULL);
1109    assert (name != NULL);    assert (name != NULL);
1110    assert (strlen (name) > 0 && strlen (name) < 9);    assert (strlen (name) > 0 && strlen (name) <= SHORT_NAME_LEN );
1111    assert (var != NULL);    assert (var != NULL);
1112    assert (cnt > 0);    assert (cnt > 0);
1113        
# Line 877  dict_create_vector (struct dictionary *d Line 1117  dict_create_vector (struct dictionary *d
1117    d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);    d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
1118    vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);    vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
1119    vector->idx = d->vector_cnt++;    vector->idx = d->vector_cnt++;
1120    strncpy (vector->name, name, 8);    strncpy (vector->name, name, SHORT_NAME_LEN);
1121    vector->name[8] = '\0';    vector->name[SHORT_NAME_LEN] = '\0';
1122    vector->var = xmalloc (cnt * sizeof *var);    vector->var = xmalloc (cnt * sizeof *var);
1123    memcpy (vector->var, var, cnt * sizeof *var);    memcpy (vector->var, var, cnt * sizeof *var);
1124    vector->cnt = cnt;    vector->cnt = cnt;
# Line 939  dict_clear_vectors (struct dictionary *d Line 1179  dict_clear_vectors (struct dictionary *d
1179    d->vector = NULL;    d->vector = NULL;
1180    d->vector_cnt = 0;    d->vector_cnt = 0;
1181  }  }
1182    
1183    
1184    static const char * quasi_base27(int i);
1185    
1186    
1187    /* Convert I to quasi base 27
1188       The result is a staticly allocated string.
1189    */
1190    static const char *
1191    quasi_base27(int i)
1192    {
1193      static char result[SHORT_NAME_LEN + 1];
1194      static char reverse[SHORT_NAME_LEN + 1];
1195    
1196      /* FIXME: check the result cant overflow these arrays */
1197    
1198      char *s = result ;
1199      const int radix = 27;
1200      int units;
1201    
1202      /* and here's the quasi-ness of this routine */
1203      i = i + ( i / radix );
1204    
1205      strcpy(result,"");
1206      do {
1207        units = i % radix;
1208        *s++ = (units > 0 ) ? units + 'A' - 1 : 'A';
1209        i = i / radix;
1210      } while (i > 0 ) ;
1211      *s = '\0';
1212    
1213      /* Reverse the result */
1214      i = strlen(result);
1215      s = reverse;
1216      while(i >= 0)
1217            *s++ = result[--i];
1218      *s = '\0';
1219            
1220      return reverse;
1221    }
1222    
1223    
1224    /* Generate a short name, given a long name.
1225       The return value of this function must be freed by the caller.
1226    */
1227    static char *
1228    make_short_name(struct dictionary *dict, const char *longname)
1229    {
1230      int i = 0;
1231      char *p;
1232    
1233    
1234      char *d = xmalloc ( SHORT_NAME_LEN + 1);
1235    
1236      /* Truncate the name */
1237      strncpy(d, longname, SHORT_NAME_LEN);
1238      d[SHORT_NAME_LEN] = '\0';
1239    
1240      /* Convert to upper case */
1241      for ( p = d; *p ; ++p )
1242            *p = toupper(*p);
1243    
1244      /* If a variable with that name already exists, then munge it
1245         until there's no conflict */
1246      while (0 != hsh_find (dict->name_tab, d))
1247      {
1248            const char *suffix = quasi_base27(i++);
1249    
1250            d[SHORT_NAME_LEN -  strlen(suffix) - 1 ] = '_';
1251            d[SHORT_NAME_LEN -  strlen(suffix)  ] = '\0';
1252            strcat(d, suffix);
1253      }
1254    
1255      return d;
1256    }
1257    
1258    
1259    
1260    

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

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