1 /* table.c - keyword tables and symbol table lookup for assembler */
10 #define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */
14 EXTERN
char bytesizeops
[];
18 EXTERN
char page1ops
[];
19 EXTERN
char page2ops
[];
22 EXTERN
char typesizes
[];
30 FORWARD
void printchain
P((void));
33 FORWARD
void install
P((register char *keyptr
, int data
));
35 PUBLIC
void inst_keywords()
37 install(regs
, REGBIT
);
39 install(typesizes
, SIZEBIT
);
42 install(page1ops
, PAGE1
);
43 install(page2ops
, PAGE2
);
46 install(bytesizeops
, PAGE1
| PAGE2
);
51 PRIVATE
void install(keyptr
, data
)
52 register char *keyptr
;
59 register struct sym_s
*symptr
;
63 namelength
= *keyptr
++;
64 lineptr
= (symname
= keyptr
) + namelength
;
65 for (nameptr
= lowcasebuf
, namend
= lowcasebuf
+ namelength
;
68 if (*keyptr
< 'A' || *keyptr
> 'Z')
69 *nameptr
++ = *keyptr
++;
71 *nameptr
++ = *keyptr
++ + ('a' - 'A');
74 symptr
->type
= MNREGBIT
;
76 symptr
->value_reg_or_op
.op
.routine
= *keyptr
;
77 symptr
->value_reg_or_op
.op
.opcode
= keyptr
[1];
78 lineptr
= (symname
= lowcasebuf
) + namelength
;
80 symptr
->type
= MNREGBIT
;
82 symptr
->value_reg_or_op
.op
.routine
= *keyptr
;
83 symptr
->value_reg_or_op
.op
.opcode
= keyptr
[1];
88 /* Lookup() searches symbol table for the string from symname to lineptr - 1.
89 * If string is not found and ifflag is TRUE, string is added to table, with
91 * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM)
92 * Returns pointer to symbol entry (NUL_PTR if not found and not installed)
93 * unless symbol table overflows, when routine aborts.
96 PUBLIC
struct sym_s
*lookup()
98 struct sym_s
**hashptr
;
99 register char *nameptr
;
100 register struct sym_s
*symptr
;
101 register unsigned hashval
;
102 register unsigned length
;
110 /* Hash function is a weighted xor of 1 to 4 chars in the string.
111 * This works seems to work better than looking at all the chars.
112 * It is important that the function be fast.
113 * The string comparision function should also be fast and it helps
114 * if it is optimized for mostly identical comparisions.
115 * The multiplication by MULTIPLIER should compile as a shift.
118 #define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII))
119 #define USEFUL_BITS_IN_ASCII 6
122 length
= nameptr
- symname
;
126 hashval
= hconv(nameptr
[-1]) * MULTIPLIER
;
128 hashval
= hconv(nameptr
[-2]) * MULTIPLIER
,
129 hashval
^= hconv(nameptr
[-1]);
132 hashval
= hconv(symname
[length
-(length
/ 2)]) * MULTIPLIER
,
133 hashval
^= hconv(nameptr
[-2]) << 2,
134 hashval
^= hconv(nameptr
[-1]);
136 if ((symptr
= *(hashptr
= spt
+
137 (hashval
^ (hconv(nameptr
[0]) << 1)) % SPTSIZ
))
146 if (tries
< sizeof nx
/ sizeof nx
[0])
149 printchain(hashptr
- spt
);
151 if ((unsigned char) length
!= symptr
->length
)
153 if (memcmp(symptr
->name
, nameptr
, length
) == 0)
156 while ((symptr
= symptr
->next
) != NUL_PTR
);
158 /* Calculate last non-NUL_PTR hash ptr.
159 * This is faster than keeping hashptr up to date in previous loop
160 * since most lookups are successful and hash ptr is not needed.
165 hashptr
= &symptr
->next
;
167 while (symptr
->next
!= NUL_PTR
);
173 if (hashptr
>= spt
&& hashptr
< spt
+ SPTSIZ
)
176 *hashptr
= symptr
= asalloc(sizeof(struct sym_s
) + length
);
178 symptr
->data
= inidata
;
179 symptr
->length
= length
;
180 symptr
->value_reg_or_op
.value
= (offset_t
) (symptr
->next
= NUL_PTR
);
181 memcpy(symptr
->name
, nameptr
, length
);
182 symptr
->name
[length
] = 0;
188 static void printchain(hashval
)
191 register struct sym_s
*symptr
;
193 printf("%04x ", hashval
);
194 for (symptr
= spt
[hashval
]; symptr
!= NUL_PTR
; symptr
= symptr
->next
)
195 printf("%s ", symptr
->name
);
201 PUBLIC
void statistics()
207 for (i
= 0; i
< SPTSIZ
; ++i
)
209 printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash
, nsym
, nlookup
);
211 for (i
= 0; i
< 30; ++i
)
213 printf("%5d", nx
[i
]);
217 printf("weight = %d%d\n", weight
);