table.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* table.c - keyword tables and symbol table lookup for assembler */
  2. #include "syshead.h"
  3. #include "const.h"
  4. #include "type.h"
  5. #include "globvar.h"
  6. #include "opcode.h"
  7. #include "scan.h"
  8. #define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */
  9. #ifdef I80386
  10. # ifdef MNSIZE
  11. EXTERN char bytesizeops[];
  12. # endif
  13. #endif
  14. EXTERN char ops[];
  15. EXTERN char page1ops[];
  16. EXTERN char page2ops[];
  17. EXTERN char regs[];
  18. #ifdef I80386
  19. EXTERN char typesizes[];
  20. #endif
  21. #ifdef DEBUG_HASH
  22. unsigned nhash;
  23. unsigned nlookup;
  24. unsigned nsym;
  25. unsigned nx[30];
  26. FORWARD void printchain P((void));
  27. #endif
  28. FORWARD void install P((register char *keyptr, int data));
  29. PUBLIC void inst_keywords()
  30. {
  31. install(regs, REGBIT);
  32. #ifdef I80386
  33. install(typesizes, SIZEBIT);
  34. #endif
  35. install(ops, 0);
  36. install(page1ops, PAGE1);
  37. install(page2ops, PAGE2);
  38. #ifdef I80386
  39. # ifdef MNSIZE
  40. install(bytesizeops, PAGE1 | PAGE2);
  41. # endif
  42. #endif
  43. }
  44. PRIVATE void install(keyptr, data)
  45. register char *keyptr;
  46. unsigned char data;
  47. {
  48. char lowcasebuf[20];
  49. unsigned namelength;
  50. char *nameptr;
  51. char *namend;
  52. register struct sym_s *symptr;
  53. while (*keyptr != 0)
  54. {
  55. namelength = *keyptr++;
  56. lineptr = (symname = keyptr) + namelength;
  57. for (nameptr = lowcasebuf, namend = lowcasebuf + namelength;
  58. nameptr < namend;)
  59. {
  60. if (*keyptr < 'A' || *keyptr > 'Z')
  61. *nameptr++ = *keyptr++;
  62. else
  63. *nameptr++ = *keyptr++ + ('a' - 'A');
  64. }
  65. symptr = lookup();
  66. symptr->type = MNREGBIT;
  67. symptr->data = data;
  68. symptr->value_reg_or_op.op.routine = *keyptr;
  69. symptr->value_reg_or_op.op.opcode = keyptr[1];
  70. lineptr = (symname = lowcasebuf) + namelength;
  71. symptr = lookup();
  72. symptr->type = MNREGBIT;
  73. symptr->data = data;
  74. symptr->value_reg_or_op.op.routine = *keyptr;
  75. symptr->value_reg_or_op.op.opcode = keyptr[1];
  76. keyptr += 2;
  77. }
  78. }
  79. /* Lookup() searches symbol table for the string from symname to lineptr - 1.
  80. * If string is not found and ifflag is TRUE, string is added to table, with
  81. * type = 0
  82. * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM)
  83. * Returns pointer to symbol entry (NUL_PTR if not found and not installed)
  84. * unless symbol table overflows, when routine aborts.
  85. */
  86. PUBLIC struct sym_s *lookup()
  87. {
  88. struct sym_s **hashptr;
  89. register char *nameptr;
  90. register struct sym_s *symptr;
  91. register unsigned hashval;
  92. register unsigned length;
  93. #ifdef DEBUG_HASH
  94. int tries;
  95. ++nlookup;
  96. tries = 0;
  97. #endif
  98. /* Hash function is a weighted xor of 1 to 4 chars in the string.
  99. * This works seems to work better than looking at all the chars.
  100. * It is important that the function be fast.
  101. * The string comparision function should also be fast and it helps
  102. * if it is optimized for mostly identical comparisions.
  103. * The multiplication by MULTIPLIER should compile as a shift.
  104. */
  105. #define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII))
  106. #define USEFUL_BITS_IN_ASCII 6
  107. nameptr = lineptr;
  108. length = nameptr - symname;
  109. if (length <= 3)
  110. {
  111. if (length <= 2)
  112. hashval = hconv(nameptr[-1]) * MULTIPLIER;
  113. else
  114. hashval = hconv(nameptr[-2]) * MULTIPLIER,
  115. hashval ^= hconv(nameptr[-1]);
  116. }
  117. else
  118. hashval = hconv(symname[length-(length / 2)]) * MULTIPLIER,
  119. hashval ^= hconv(nameptr[-2]) << 2,
  120. hashval ^= hconv(nameptr[-1]);
  121. nameptr = symname;
  122. if ((symptr = *(hashptr = spt +
  123. (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ))
  124. != NUL_PTR)
  125. {
  126. do
  127. {
  128. #ifdef DEBUG_HASH
  129. if (tries != 0)
  130. --nx[tries];
  131. ++tries;
  132. if (tries < sizeof nx / sizeof nx[0])
  133. ++nx[tries];
  134. if (tries >= 5)
  135. printchain(hashptr - spt);
  136. #endif
  137. if ((unsigned char) length != symptr->length)
  138. continue;
  139. if (memcmp(symptr->name, nameptr, length) == 0)
  140. return symptr;
  141. }
  142. while ((symptr = symptr->next) != NUL_PTR);
  143. /* Calculate last non-NUL_PTR hash ptr.
  144. * This is faster than keeping hashptr up to date in previous loop
  145. * since most lookups are successful and hash ptr is not needed.
  146. */
  147. do
  148. {
  149. symptr = *hashptr;
  150. hashptr = &symptr->next;
  151. }
  152. while (symptr->next != NUL_PTR);
  153. }
  154. if (!ifflag)
  155. return NUL_PTR;
  156. #ifdef DEBUG_HASH
  157. ++nsym;
  158. if (hashptr >= spt && hashptr < spt + SPTSIZ)
  159. ++nhash;
  160. #endif
  161. *hashptr = symptr = asalloc(sizeof(struct sym_s) + length);
  162. symptr->type = 0;
  163. symptr->data = inidata;
  164. symptr->length = length;
  165. symptr->value_reg_or_op.value = (offset_t) (symptr->next = NUL_PTR);
  166. memcpy(symptr->name, nameptr, length);
  167. symptr->name[length] = 0;
  168. return symptr;
  169. }
  170. #ifdef DEBUG_HASH
  171. static void printchain(hashval)
  172. unsigned hashval;
  173. {
  174. register struct sym_s *symptr;
  175. printf("%04x ", hashval);
  176. for (symptr = spt[hashval]; symptr != NUL_PTR; symptr = symptr->next)
  177. printf("%s ", symptr->name);
  178. printf("\n");
  179. }
  180. #endif
  181. PUBLIC void statistics()
  182. {
  183. #ifdef DEBUG_HASH
  184. int i;
  185. int weight;
  186. for (i = 0; i < SPTSIZ; ++i)
  187. printchain(i);
  188. printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup);
  189. weight = 0;
  190. for (i = 0; i < 30; ++i)
  191. {
  192. printf("%5d", nx[i]);
  193. weight += nx[i] * i;
  194. }
  195. printf("\n");
  196. printf("weight = %d%d\n", weight);
  197. #endif
  198. }