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