/contrib/groff/src/libs/libgroff/symbol.cpp

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 159 lines · 121 code · 11 blank · 27 comment · 38 complexity · 358c4dd34fff61b056132995894f5910 MD5 · raw file

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004
  3. Free Software Foundation, Inc.
  4. Written by James Clark (jjc@jclark.com)
  5. This file is part of groff.
  6. groff is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation; either version 2, or (at your option) any later
  9. version.
  10. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. for more details.
  14. You should have received a copy of the GNU General Public License along
  15. with groff; see the file COPYING. If not, write to the Free Software
  16. Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
  17. #include "lib.h"
  18. #include "errarg.h"
  19. #include "error.h"
  20. #include "symbol.h"
  21. const char **symbol::table = 0;
  22. int symbol::table_used = 0;
  23. int symbol::table_size = 0;
  24. char *symbol::block = 0;
  25. int symbol::block_size = 0;
  26. const symbol NULL_SYMBOL;
  27. const symbol EMPTY_SYMBOL("");
  28. #ifdef BLOCK_SIZE
  29. #undef BLOCK_SIZE
  30. #endif
  31. const int BLOCK_SIZE = 1024;
  32. // the table will increase in size as necessary
  33. // the size will be chosen from the following array
  34. // add some more if you want
  35. static const unsigned int table_sizes[] = {
  36. 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
  37. 160001, 500009, 1000003, 1500007, 2000003, 0
  38. };
  39. const double FULL_MAX = 0.3; // don't let the table get more than this full
  40. static unsigned int hash_string(const char *p)
  41. {
  42. // compute a hash code; this assumes 32-bit unsigned ints
  43. // see p436 of Compilers by Aho, Sethi & Ullman
  44. // give special treatment to two-character names
  45. unsigned int hc = 0, g;
  46. if (*p != 0) {
  47. hc = *p++;
  48. if (*p != 0) {
  49. hc <<= 7;
  50. hc += *p++;
  51. for (; *p != 0; p++) {
  52. hc <<= 4;
  53. hc += *p;
  54. if ((g = (hc & 0xf0000000)) == 0) {
  55. hc ^= g >> 24;
  56. hc ^= g;
  57. }
  58. }
  59. }
  60. }
  61. return hc;
  62. }
  63. // Tell compiler that a variable is intentionally unused.
  64. inline void unused(void *) { }
  65. symbol::symbol(const char *p, int how)
  66. {
  67. if (p == 0) {
  68. s = 0;
  69. return;
  70. }
  71. if (*p == 0) {
  72. s = "";
  73. return;
  74. }
  75. if (table == 0) {
  76. table_size = table_sizes[0];
  77. table = (const char **)new char*[table_size];
  78. for (int i = 0; i < table_size; i++)
  79. table[i] = 0;
  80. table_used = 0;
  81. }
  82. unsigned int hc = hash_string(p);
  83. const char **pp;
  84. for (pp = table + hc % table_size;
  85. *pp != 0;
  86. (pp == table ? pp = table + table_size - 1 : --pp))
  87. if (strcmp(p, *pp) == 0) {
  88. s = *pp;
  89. return;
  90. }
  91. if (how == MUST_ALREADY_EXIST) {
  92. s = 0;
  93. return;
  94. }
  95. if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
  96. const char **old_table = table;
  97. unsigned int old_table_size = table_size;
  98. int i;
  99. for (i = 1; table_sizes[i] <= old_table_size; i++)
  100. if (table_sizes[i] == 0)
  101. fatal("too many symbols");
  102. table_size = table_sizes[i];
  103. table_used = 0;
  104. table = (const char **)new char*[table_size];
  105. for (i = 0; i < table_size; i++)
  106. table[i] = 0;
  107. for (pp = old_table + old_table_size - 1;
  108. pp >= old_table;
  109. --pp) {
  110. symbol temp(*pp, 1); /* insert it into the new table */
  111. unused(&temp);
  112. }
  113. a_delete old_table;
  114. for (pp = table + hc % table_size;
  115. *pp != 0;
  116. (pp == table ? pp = table + table_size - 1 : --pp))
  117. ;
  118. }
  119. ++table_used;
  120. if (how == DONT_STORE) {
  121. s = *pp = p;
  122. }
  123. else {
  124. int len = strlen(p)+1;
  125. if (block == 0 || block_size < len) {
  126. block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
  127. block = new char [block_size];
  128. }
  129. (void)strcpy(block, p);
  130. s = *pp = block;
  131. block += len;
  132. block_size -= len;
  133. }
  134. }
  135. symbol concat(symbol s1, symbol s2)
  136. {
  137. char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
  138. strcpy(buf, s1.contents());
  139. strcat(buf, s2.contents());
  140. symbol res(buf);
  141. a_delete buf;
  142. return res;
  143. }
  144. symbol default_symbol("default");