1 /* assym.c */
2
3 /*
4 * Copyright (C) 1989-2009 Alan R. Baldwin
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 *
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
23 *
24 * With enhancements from
25 *
26 * John L. Hartman (JLH)
27 * jhartman at compuserve dot com
28 */
29
30 /*
31 * 10-Nov-07 borutr:
32 * - use strsto instead StoreString and include it in assym.c
33 * for compatibility with the original asxxxx
34 * - applied changes from 28-Oct-97 JLH:
35 * - lookup: Use StoreString for sym construction
36 * - change symeq() to do length-independent string compare
37 * - change hash() to do length-independent hash calculation
38 * - applied changes from 29-Oct-97 JLH:
39 * - make mnemonics case insensitive ALWAYS
40 * - make hash() case-insensitive always
41 * - replace symeq() call in mlookup with strcmpi
42 */
43
44 #include "asxxxx.h"
45
46 /*)Module assym.c
47 *
48 * The module assym.c contains the functions that operate
49 * on the mnemonic/directive and symbol structures.
50 *
51 * assym.c contains the following functions:
52 * VOID allglob()
53 * area * alookup()
54 * int hash()
55 * sym * lookup()
56 * mne * mlookup()
57 * char * new()
58 * char * strsto()
59 * int symeq()
60 * VOID syminit()
61 * VOID symglob()
62 *
63 * assym.c contains the static variables:
64 * char * pnext
65 * int bytes
66 * used by the string store function.
67 */
68
69 /*)Function VOID syminit()
70 *
71 * The function syminit() is called early in the game
72 * to set up the hashtables. First all buckets in a
73 * table are cleared. Then a pass is made through
74 * the respective symbol lists, linking them into
75 * their hash buckets. Finally the base area pointer
76 * is set to 'dca'.
77 *
78 * local variables:
79 * int h computed hash value
80 * mne * mp pointer to a mne structure
81 * mne ** mpp pointer to an array of
82 * mne structure pointers
83 * sym * sp pointer to a sym structure
84 * sym ** spp pointer to an array of
85 * sym structure pointers
86 *
87 * global variables:
88 * area area[] single elememt area array
89 * area dca defined as area[0]
90 * mne * mnehash[] array of pointers to NHASH
91 * linked mnemonic/directive lists
92 * sym * symhash[] array of pointers to NHASH
93 * linked symbol lists
94 *
95 * functions called:
96 * none
97 *
98 * side effects:
99 * (1) The symbol hash tables are initialized,
100 * the predefined symbols are '.' and '.__.ABS.'.
101 * (2) The mnemonic/directive hash tables are
102 * initialized with the assembler directives
103 * and mnemonics found in the machine dependent
104 * file ___pst.c.
105 * (3) The area pointer is initialized to dca (area[0]).
106 */
107
108 VOID
syminit(void)109 syminit(void)
110 {
111 struct mne *mp;
112 struct mne **mpp;
113 struct sym *sp;
114 struct sym **spp;
115 int h;
116
117 mpp = &mnehash[0];
118 while (mpp < &mnehash[NHASH])
119 *mpp++ = NULL;
120 mp = &mne[0];
121 for (;;) {
122 h = hash(mp->m_id, 1);
123 mp->m_mp = mnehash[h];
124 mnehash[h] = mp;
125 if (mp->m_flag&S_EOL)
126 break;
127 ++mp;
128 }
129
130 spp = &symhash[0];
131 while (spp < &symhash[NHASH])
132 *spp++ = NULL;
133 sp = &sym[0];
134 for (;;) {
135 h = hash(sp->s_id, zflag);
136 sp->s_sp = symhash[h];
137 symhash[h] = sp;
138 if (sp->s_flag&S_EOL)
139 break;
140 ++sp;
141 }
142
143 areap = &dca;
144 }
145
146 /*)Function area * alookup(id)
147 *
148 * char * id area name string
149 *
150 * The function alookup() searches the area list for a
151 * match with id. If the area is defined then a pointer
152 * to this area is returned else a NULL is returned.
153 *
154 * local variables:
155 * area * ap pointer to area structure
156 *
157 * global variables:
158 * area * areap pointer to an area structure
159 *
160 * functions called:
161 * int symeq() assym.c
162 *
163 * side effects:
164 * none
165 */
166
167 struct area *
alookup(char * id)168 alookup(char *id)
169 {
170 struct area *ap;
171
172 ap = areap;
173 while (ap) {
174 /*
175 * JLH: case insensitive lookup always
176 */
177 if(symeq(id, ap->a_id, 0))
178 return (ap);
179 ap = ap->a_ap;
180 }
181 return(NULL);
182 }
183
184 /*)Function mne * mlookup(id)
185 *
186 * char * id mnemonic/directive name string
187 *
188 * The function mlookup() searches the mnemonic/directive
189 * hash tables for a match returning a pointer to the
190 * mne structure else it returns a NULL.
191 *
192 * local variables:
193 * mne * mp pointer to mne structure
194 * int h calculated hash value
195 *
196 * global variables:
197 * mne * mnehash[] array of pointers to NHASH
198 * linked mnemonic/directive lists
199 *
200 * functions called:
201 * none
202 *
203 * side effects:
204 * none
205 */
206
207 struct mne *
mlookup(char * id)208 mlookup(char *id)
209 {
210 struct mne *mp;
211 int h;
212
213 /*
214 * JLH: case insensitive lookup always
215 */
216 h = hash(id, 1);
217 mp = mnehash[h];
218 while (mp) {
219 if(symeq(id, mp->m_id, 1))
220 return (mp);
221 mp = mp->m_mp;
222 }
223 return (NULL);
224 }
225
226 /*)Function sym * lookup(id)
227 *
228 * char * id symbol name string
229 *
230 * The function lookup() searches the symbol hash tables for
231 * a symbol name match returning a pointer to the sym structure.
232 * If the symbol is not found then a sym structure is created,
233 * initialized, and linked to the appropriate hash table.
234 * A pointer to this new sym structure is returned.
235 *
236 * local variables:
237 * int h computed hash value
238 * sym * sp pointer to a sym structure
239 *
240 * global varaibles:
241 * sym * symhash[] array of pointers to NHASH
242 * linked symbol lists
243 * int zflag disable symbol case sensitivity
244 *
245 * functions called:
246 * int hash() assym.c
247 * char * new() assym.c
248 * char * strsto() assym.c
249 * int symeq() assym.c
250 *
251 * side effects:
252 * If the function new() fails to allocate space
253 * for the new sym structure the assembly terminates.
254 */
255
256 struct sym *
lookup(const char * id)257 lookup(const char *id)
258 {
259 struct sym *sp;
260 int h;
261
262 h = hash(id, zflag);
263 sp = symhash[h];
264 while (sp) {
265 if(symeq(id, sp->s_id, zflag))
266 return (sp);
267 sp = sp->s_sp;
268 }
269 sp = (struct sym *) new (sizeof(struct sym));
270 sp->s_sp = symhash[h];
271 symhash[h] = sp;
272 sp->s_tsym = NULL;
273 sp->s_id = strsto(id);
274 sp->s_type = S_NEW;
275 sp->s_flag = 0;
276 sp->s_area = NULL;
277 sp->s_ref = 0;
278 sp->s_addr = 0;
279 return (sp);
280 }
281
282 /*)Function VOID symglob()
283 *
284 * The function symglob() will mark all symbols of
285 * type S_NEW as global. Called at
286 * the beginning of pass 1 if the assembly
287 * option -g was specified.
288 *
289 * local variables:
290 * sym * sp pointer to a sym structure
291 * int i loop index
292 *
293 * global variables:
294 * sym * symhash[] array of pointers to NHASH
295 * linked symbol lists
296 *
297 * functions called:
298 * none
299 *
300 * side effects:
301 * Symbol types changed.
302 */
303
304 VOID
symglob(void)305 symglob(void)
306 {
307 struct sym *sp;
308 int i;
309
310 for (i=0; i<NHASH; ++i) {
311 sp = symhash[i];
312 while (sp != NULL) {
313 if (sp->s_type == S_NEW)
314 sp->s_flag |= S_GBL;
315 sp = sp->s_sp;
316 }
317 }
318 }
319
320 /*)Function VOID allglob()
321 *
322 * The function allglob() will mark all symbols of
323 * type S_USER as global. Called at
324 * the beginning of pass 1 if the assembly
325 * option -a was specified.
326 *
327 * local variables:
328 * sym * sp pointer to a sym structure
329 * int i loop index
330 *
331 * global variables:
332 * sym * symhash[] array of pointers to NHASH
333 * linked symbol lists
334 *
335 * functions called:
336 * none
337 *
338 * side effects:
339 * Symbol types changed.
340 */
341
342 VOID
allglob(void)343 allglob(void)
344 {
345 struct sym *sp;
346 int i;
347
348 for (i=0; i<NHASH; ++i) {
349 sp = symhash[i];
350 while (sp != NULL) {
351 if (sp != &dot && sp->s_type == S_USER)
352 sp->s_flag |= S_GBL;
353 sp = sp->s_sp;
354 }
355 }
356 }
357
358 /*)Function int symeq(p1, p2, flag)
359 *
360 * int flag case sensitive flag
361 * char * p1 name string
362 * char * p2 name string
363 *
364 * The function symeq() compares the two name strings for a match.
365 * The return value is 1 for a match and 0 for no match.
366 *
367 * flag == 0 case sensitive compare
368 * flag != 0 case insensitive compare
369 *
370 * local variables:
371 * int n loop counter
372 *
373 * global variables:
374 * char ccase[] an array of characters which
375 * perform the case translation function
376 *
377 * functions called:
378 * none
379 *
380 * side effects:
381 * none
382 *
383 */
384
385 int
symeq(const char * p1,const char * p2,int flag)386 symeq(const char *p1, const char *p2, int flag)
387 {
388 size_t n;
389
390 n = strlen(p1) + 1;
391 if(flag) {
392 /*
393 * Case Insensitive Compare
394 */
395 do {
396 if (ccase[*p1++ & 0x007F] != ccase[*p2++ & 0x007F])
397 return (0);
398 } while (--n);
399 } else {
400 /*
401 * Case Sensitive Compare
402 */
403 do {
404 if (*p1++ != *p2++)
405 return (0);
406 } while (--n);
407 }
408 return (1);
409 }
410
411 /*)Function int hash(p, flag)
412 *
413 * char * p pointer to string to hash
414 * int flag case sensitive flag
415 *
416 * The function hash() computes a hash code using the sum
417 * of all characters mod table size algorithm.
418 *
419 * flag == 0 case insensitve hash
420 * flag != 0 case sensitive hash
421 *
422 * local variables:
423 * int h accumulated character sum
424 *
425 * global variables:
426 * char ccase[] an array of characters which
427 * perform the case translation function
428 *
429 * functions called:
430 * none
431 *
432 * side effects:
433 * none
434 */
435
436 int
hash(const char * p,int flag)437 hash(const char *p, int flag)
438 {
439 int h;
440
441 h = 0;
442 while (*p) {
443 if(flag) {
444 /*
445 * Case Insensitive Hash
446 */
447 h += ccase[*p++ & 0x007F];
448 } else {
449 /*
450 * Case Sensitive Hash
451 */
452 h += *p++;
453 }
454 }
455 return (h&HMASK);
456 }
457
458 /*)Function char * strsto(str)
459 *
460 * char * str pointer to string to save
461 *
462 * Allocate space for "str", copy str into new space.
463 * Return a pointer to the allocated string.
464 *
465 * This function based on code by
466 * John L. Hartman
467 * jhartman at compuserve dot com
468 *
469 * local variables:
470 * int bytes bytes remaining in buffer area
471 * int len string length + 1
472 * char * p pointer to head of copied string
473 * char * pnext next location in buffer area
474 *
475 * global variables:
476 * none
477 *
478 * functions called:
479 * char * new() assym.c
480 * char * strncpy() c_library
481 * int * strlen() c_library
482 *
483 * side effects:
484 * Space allocated for string, string copied
485 * to space. Out of Space terminates assembler.
486 */
487
488 /*
489 * To avoid wasting memory headers on small allocations, we
490 * allocate a big chunk and parcel it out as required.
491 * These static variables remember our hunk.
492 */
493
494 #define STR_SPC 1024
495
496 static char * pnext = NULL;
497 static int bytes = 0;
498
499 char *
strsto(const char * str)500 strsto(const char *str)
501 {
502 int len;
503 char *p;
504
505 /*
506 * What we need, including a null.
507 */
508 len = strlen(str) + 1;
509
510 if (len > bytes) {
511 /*
512 * No space. Allocate a new hunk.
513 * We lose the pointer to any old hunk.
514 * We don't care, as the names are never deleted.
515 */
516 pnext = (char *) new (STR_SPC);
517 bytes = STR_SPC;
518 }
519
520 /*
521 * Copy the name and terminating null.
522 */
523 p = pnext;
524 strncpy(p, str, len);
525
526 pnext += len;
527 bytes -= len;
528
529 return(p);
530 }
531
532 /*)Function char * new(n)
533 *
534 * unsigned int n allocation size in bytes
535 *
536 * The function new() allocates n bytes of space and returns
537 * a pointer to this memory. If no space is available the
538 * assembly is terminated.
539 *
540 * local variables:
541 * VOID * p a general pointer
542 *
543 * global variables:
544 * none
545 *
546 * functions called:
547 * VOID asexit() asmain.c
548 * int fprintf() c_library
549 * VOID * malloc() c_library
550 *
551 * side effects:
552 * Memory is allocated, if allocation fails
553 * the assembly is terminated.
554 */
555
556 char *
new(unsigned int n)557 new(unsigned int n)
558 {
559 VOID *p;
560
561 if ((p = (VOID *) malloc(n)) == NULL) {
562 fprintf(stderr, "Out of space!\n");
563 asexit(ER_FATAL);
564 }
565 memset (p, 0, n);
566 return (p);
567 }
568