uniqstr.c 4.0 KB

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