(root)/
bison-3.8.2/
src/
uniqstr.c
       1  /* Keep a unique copy of strings.
       2  
       3     Copyright (C) 2002-2005, 2009-2015, 2018-2021 Free Software
       4     Foundation, Inc.
       5  
       6     This file is part of Bison, the GNU Compiler Compiler.
       7  
       8     This program is free software: you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation, either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     This program is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      20  
      21  #include <config.h>
      22  #include "system.h"
      23  
      24  #include <attribute.h>
      25  #include <error.h>
      26  #include <hash.h>
      27  #include <quotearg.h>
      28  #include <stdarg.h>
      29  
      30  #include "uniqstr.h"
      31  
      32  /*-----------------------.
      33  | A uniqstr hash table.  |
      34  `-----------------------*/
      35  
      36  /* Initial capacity of uniqstr hash table.  */
      37  #define HT_INITIAL_CAPACITY 257
      38  
      39  static struct hash_table *uniqstrs_table = NULL;
      40  
      41  /*-------------------------------------.
      42  | Create the uniqstr for S if needed.  |
      43  `-------------------------------------*/
      44  
      45  uniqstr
      46  uniqstr_new (char const *str)
      47  {
      48    uniqstr res = hash_lookup (uniqstrs_table, str);
      49    if (!res)
      50      {
      51        /* First insertion in the hash. */
      52        res = xstrdup (str);
      53        hash_xinsert (uniqstrs_table, res);
      54      }
      55    return res;
      56  }
      57  
      58  uniqstr
      59  uniqstr_concat (int nargs, ...)
      60  {
      61    va_list args;
      62  
      63    va_start (args, nargs);
      64    size_t reslen = 0;
      65    for (int i = 0; i < nargs; i++)
      66      reslen += strlen (va_arg (args, char const *));
      67    va_end (args);
      68  
      69    char *str = xmalloc (reslen + 1);
      70    char *p = str;
      71  
      72    va_start (args, nargs);
      73    for (int i = 0; i < nargs; i++)
      74      {
      75        char const *arg = va_arg (args, char const *);
      76        size_t arglen = strlen (arg);
      77        memcpy (p, arg, arglen);
      78        p += arglen;
      79      }
      80    va_end (args);
      81  
      82    *p = '\0';
      83    uniqstr res = hash_xinsert (uniqstrs_table, str);
      84    if (res != str)
      85      free (str);
      86    return res;
      87  }
      88  
      89  /*------------------------------.
      90  | Abort if S is not a uniqstr.  |
      91  `------------------------------*/
      92  
      93  void
      94  uniqstr_assert (char const *str)
      95  {
      96    uniqstr s = hash_lookup (uniqstrs_table, str);
      97    if (!s || s != str)
      98      {
      99        error (0, 0,
     100               "not a uniqstr: %s", quotearg (str));
     101        abort ();
     102      }
     103  }
     104  
     105  
     106  /*--------------------.
     107  | Print the uniqstr.  |
     108  `--------------------*/
     109  
     110  static inline bool
     111  uniqstr_print (uniqstr ustr)
     112  {
     113    fprintf (stderr, "%s\n", ustr);
     114    return true;
     115  }
     116  
     117  static bool
     118  uniqstr_print_processor (void *ustr, void *null MAYBE_UNUSED)
     119  {
     120    return uniqstr_print (ustr);
     121  }
     122  
     123  int
     124  uniqstr_cmp (uniqstr l, uniqstr r)
     125  {
     126    return (l == r ? 0
     127            : !l ? -1
     128            : !r ? +1
     129            : strcmp (l, r));
     130  }
     131  
     132  
     133  /*-----------------------.
     134  | A uniqstr hash table.  |
     135  `-----------------------*/
     136  
     137  static bool
     138  hash_compare_uniqstr (void const *m1, void const *m2)
     139  {
     140    return STREQ (m1, m2);
     141  }
     142  
     143  static size_t
     144  hash_uniqstr (void const *m, size_t tablesize)
     145  {
     146    return hash_string (m, tablesize);
     147  }
     148  
     149  
     150  /*----------------------------.
     151  | Create the uniqstrs table.  |
     152  `----------------------------*/
     153  
     154  void
     155  uniqstrs_new (void)
     156  {
     157    uniqstrs_table = hash_xinitialize (HT_INITIAL_CAPACITY,
     158                                       NULL,
     159                                       hash_uniqstr,
     160                                       hash_compare_uniqstr,
     161                                       free);
     162  }
     163  
     164  
     165  /*-------------------------------------.
     166  | Perform a task on all the uniqstrs.  |
     167  `-------------------------------------*/
     168  
     169  static void
     170  uniqstrs_do (Hash_processor processor, void *processor_data)
     171  {
     172    hash_do_for_each (uniqstrs_table, processor, processor_data);
     173  }
     174  
     175  
     176  /*-----------------.
     177  | Print them all.  |
     178  `-----------------*/
     179  
     180  void
     181  uniqstrs_print (void)
     182  {
     183    uniqstrs_do (uniqstr_print_processor, NULL);
     184  }
     185  
     186  
     187  /*--------------------.
     188  | Free the uniqstrs.  |
     189  `--------------------*/
     190  
     191  void
     192  uniqstrs_free (void)
     193  {
     194    hash_free (uniqstrs_table);
     195  }