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