Pre 2.95-2
[fw/sdcc] / link / z80 / lksym.c
1 /* lksym.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <alloc.h>
15 #include "aslink.h"
16
17 /*)Module       lksym.c
18  *
19  *      The module lksym.c contains the functions that operate
20  *      on the symbol structures.
21  *
22  *      lksym.c contains the following functions:
23  *              int     hash()
24  *              sym *   lkpsym()
25  *              VOID *  new()
26  *              sym *   newsym()
27  *              VOID    symdef()
28  *              int     symeq()
29  *              VOID    syminit()
30  *              VOID    symmod()
31  *              addr_t  symval()
32  *
33  *      lksym.c contains no local/static variables.
34  */
35
36 /*)Function     VOID    syminit()
37  *
38  *      The function syminit() is called to clear the hashtable.
39  *
40  *      local variables:
41  *              int     h               computed hash value
42  *              sym **  spp             pointer to an array of
43  *                                      sym structure pointers
44  *
45  *      global variables:
46  *              sym * symhash[]         array of pointers to NHASH
47  *                                      linked symbol lists
48  *
49  *      functions called:
50  *              none
51  *
52  *      side effects:
53  *              (1)     The symbol hash tables are cleared
54  */
55
56 VOID
57 syminit()
58 {
59         register int h;
60         struct sym **spp;
61
62         spp = &symhash[0];
63         while (spp < &symhash[NHASH])
64                 *spp++ = NULL;
65 }
66
67 /*)Function     sym *   newsym()
68  *
69  *      The function newsym() is called to evaluate the symbol
70  *      definition/reference directive from the .rel file(s).
71  *      If the symbol is not found in the symbol table a new
72  *      symbol structure is created.  Evaluation of the
73  *      directive determines if this is a reference or a definition.
74  *      Multiple definitions of the same variable will be flagged
75  *      as an error if the values are not identical.  A symbol
76  *      definition places the symbol value and area extension
77  *      into the symbols data structure.  And finally, a pointer
78  *      to the symbol structure is placed into the head structure
79  *      symbol list.  Refer to the description of the header, symbol,
80  *      area, and areax structures in lkdata.c for structure and
81  *      linkage details.
82  *
83  *      local variables:
84  *              int     c               character from input text
85  *              int     i               evaluation value
86  *              char    id[]            symbol name
87  *              int     nglob           number of symbols in this header
88  *              sym *   tsp             pointer to symbol structure
89  *              sym **  s               list of pointers to symbol structures
90  *
91  *      global variables:
92  *              areax   *axp            Pointer to the current
93  *                                      areax structure
94  *              head    *headp          The pointer to the first
95  *                                      head structure of a linked list
96  *              int     lkerr           error flag
97  *
98  *      functions called:
99  *              addr_t  eval()          lkeval.c
100  *              VOID    exit()          c_library
101  *              int     fprintf()       c_library
102  *              char    get()           lklex.c
103  *              char    getnb()         lklex.c
104  *              sym *   lkpsym()        lksym.c
105  *
106  *      side effects:
107  *              A symbol structure is created and/or modified.
108  *              If structure space allocation fails linker will abort.
109  *              Several severe errors (these are internal errors
110  *              indicating a corrupted .rel file or corrupted
111  *              assembler or linker) will terminated the linker.
112  */
113
114 /*
115  * Find/Create a global symbol entry.
116  *
117  * S xxxxxx Defnnnn
118  *   |      |  |
119  *   |      |  `-- sp->s_addr
120  *   |      `----- sp->s_type
121  *   `------------ sp->s_id
122  *
123  */
124 struct sym *
125 newsym()
126 {
127         register int c, i, nglob;
128         struct sym *tsp;
129         struct sym **s;
130         char id[NCPS];
131
132         getid(id, -1);
133         tsp = lkpsym(id, 1);
134         c = getnb();get();get();
135         if (c == 'R') {
136                 tsp->s_type |= S_REF;
137                 if (eval()) {
138                         fprintf(stderr, "Non zero S_REF\n");
139                         lkerr++;
140                 }
141         } else
142         if (c == 'D') {
143                 i = eval();
144                 if (tsp->s_type & S_DEF && tsp->s_addr != i) {
145 #ifdef SDK
146                         fprintf(stderr, "Multiple definition of %s\n", id);
147 #else
148                         fprintf(stderr, "Multiple definition of %.8s\n", id);
149 #endif
150                         lkerr++;
151                 }
152                 tsp->s_type |= S_DEF;
153                 /*
154                  * Set value and area extension link.
155                  */
156                 tsp->s_addr = i;
157                 tsp->s_axp = axp;
158         } else {
159                 fprintf(stderr, "Invalid symbol type %c for %.8s\n", c, id);
160                 lkexit(1);
161         }
162         /*
163          * Place pointer in header symbol list
164          */
165         if (headp == NULL) {
166                 fprintf(stderr, "No header defined\n");
167                 lkexit(1);
168         }
169         nglob = hp->h_nglob;
170         s = hp->s_list;
171         for (i=0; i < nglob ;++i) {
172                 if (s[i] == NULL) {
173                         s[i] = tsp;
174                         return(tsp);
175                 }
176         }
177         fprintf(stderr, "Header symbol list overflow\n");
178         lkexit(1);
179         /* Never reached */
180 }
181
182 /*)Function     sym *   lkpsym(id,f)
183  *
184  *              char *  id              symbol name string
185  *              int     f               f == 0, lookup only
186  *                                      f != 0, create if not found
187  *
188  *      The function lookup() searches the symbol hash tables for
189  *      a symbol name match returning a pointer to the sym structure.
190  *      If the symbol is not found then a sym structure is created,
191  *      initialized, and linked to the appropriate hash table if f != 0.
192  *      A pointer to this new sym structure is returned or a NULL
193  *      pointer is returned if f == 0.
194  *
195  *      local variables:
196  *              int     h               computed hash value
197  *              sym *   sp              pointer to a sym structure
198  *
199  *      global varaibles:
200  *              sym * symhash[]         array of pointers to NHASH
201  *                                      linked symbol lists
202  *
203  *      functions called:
204  *              int     hash()          lksym.c
205  *              VOID *  new()           lksym.c
206  *              int     symeq()         lksym.c
207  *
208  *      side effects:
209  *              If the function new() fails to allocate space
210  *              for the new sym structure the linker terminates.
211  */
212
213 struct sym *
214 lkpsym(id, f)
215 char *id;
216 {
217         register struct sym *sp;
218         register int h;
219
220         h = hash(id);
221         sp = symhash[h];
222         while (sp != NULL) {
223                 if (symeq(id, sp->s_id))
224                         return (sp);
225                 sp = sp->s_sp;
226         }
227         if (f == 0)
228                 return (NULL);
229         sp = (struct sym *) new (sizeof(struct sym));
230         sp->s_sp = symhash[h];
231         symhash[h] = sp;
232         strncpy(sp->s_id, id, NCPS);
233         return (sp);
234 }
235
236 /*)Function     addr_t  symval(tsp)
237  *
238  *              sym *   tsp             pointer to a symbol structure
239  *
240  *      The function symval() returns the value of the
241  *      relocated symbol by adding the variable definition
242  *      value to the areax base address.
243  *
244  *      local variables:
245  *              addr_t  val             relocated address value
246  *
247  *      global variables:
248  *              none
249  *
250  *      functions called:
251  *              none
252  *
253  *      side effects:
254  *              none
255  */
256
257 addr_t
258 symval(tsp)
259 register struct sym *tsp;
260 {
261         register addr_t val;
262
263         val = tsp->s_addr;
264         if (tsp->s_axp) {
265                 val += tsp->s_axp->a_addr;
266         }
267         return(val);
268 }
269
270 /*)Function     VOID    symdef(fp)
271  *
272  *              FILE *  fp              file handle for output
273  *
274  *      The function symdef() scans the hashed symbol table
275  *      searching for variables referenced but not defined.
276  *      Undefined variables are linked to the default
277  *      area "_CODE" and reported as referenced by the
278  *      appropriate module.
279  *
280  *      local variables:
281  *              int     i               hash table index loop variable
282  *              sym *   sp              pointer to linked symbol structure
283  *
284  *      global variables:
285  *              area    *areap          The pointer to the first
286  *                                      area structure of a linked list
287  *              sym *symhash[NHASH]     array of pointers to NHASH
288  *                                      linked symbol lists
289  *
290  *      functions called:
291  *              symmod()                lksym.c
292  *
293  *      side effects:
294  *              Undefined variables have their areas set to "_CODE".
295  */
296
297 VOID
298 symdef(fp)
299 FILE *fp;
300 {
301         register struct sym *sp;
302         register int i;
303
304         for (i=0; i<NHASH; ++i) {
305                 sp = symhash[i];
306                 while (sp) {
307                         if (sp->s_axp == NULL)
308                                 sp->s_axp = areap->a_axp;
309                         if ((sp->s_type & S_DEF) == 0)
310                                 symmod(fp, sp);
311                         sp = sp->s_sp;
312                 }
313         }
314 }
315
316 /*)Function     VOID    symmod(fp,tsp)
317  *
318  *              FILE *  fp              output file handle
319  *              sym *   tsp             pointer to a symbol structure
320  *
321  *      The function symmod() scans the header structures
322  *      searching for a reference to the symbol structure
323  *      pointer to by tsp.  The function then generates an error
324  *      message whichs names the module having referenced the
325  *      undefined variable.
326  *
327  *      local variables:
328  *              int     i               loop counter
329  *              sym **  p               pointer to a list of pointers
330  *                                      to symbol structures
331  *
332  *      global variables:
333  *              head    *headp          The pointer to the first
334  *                                      head structure of a linked list
335  *              head    *hp             Pointer to the current
336  *                                      head structure
337  *              int     lkerr           error flag
338  *
339  *      functions called:
340  *              int     fprintf()       c_library
341  *
342  *      side effects:
343  *              Error output generated.
344  */
345
346 VOID
347 symmod(fp, tsp)
348 FILE *fp;
349 struct sym *tsp;
350 {
351         register int i, j;
352         struct sym **p;
353
354         if ((hp = headp) != NULL) {
355             while(hp) {
356                 p = hp->s_list;
357                 for (i=0; i<hp->h_nglob; ++i) {
358                     if (p[i] == tsp) {
359                         fprintf(fp, "\n?ASlink-Warning-Undefined Global %s ", tsp->s_id);
360                         fprintf(fp, "referenced by module %s\n", hp->m_id);
361                         lkerr++;
362                     }
363                 }
364             hp = hp->h_hp;
365             }
366         }
367 }
368
369 /*)Function     int     symeq(p1, p2)
370  *
371  *              char *  p1              name string
372  *              char *  p2              name string
373  *
374  *      The function symeq() compares the two name strings for a match.
375  *      The return value is 1 for a match and 0 for no match.
376  *
377  *      local variables:
378  *              int     h               loop counter
379  *
380  *      global variables:
381  *              char    ccase[]         an array of characters which
382  *                                      perform the case translation function
383  *
384  *      functions called:
385  *              none
386  *
387  *      side effects:
388  *              none
389  *
390  */
391
392 int
393 symeq(p1, p2)
394 register char *p1, *p2;
395 {
396         register int n;
397
398         n = NCPS;
399         do {
400
401 #if     CASE_SENSITIVE
402                 if (*p1++ != *p2++)
403                         return (0);
404 #else
405                 if (ccase[*p1++] != ccase[*p2++])
406                         return (0);
407 #endif
408
409         } while (--n);
410         return (1);
411 }
412
413 /*)Function     int     hash(p)
414  *
415  *              char *  p               pointer to string to hash
416  *
417  *      The function hash() computes a hash code using the sum
418  *      of all characters mod table size algorithm.
419  *
420  *      local variables:
421  *              int     h               accumulated character sum
422  *              int     n               loop counter
423  *
424  *      global variables:
425  *              char    ccase[]         an array of characters which
426  *                                      perform the case translation function
427  *
428  *      functions called:
429  *              none
430  *
431  *      side effects:
432  *              none
433  *
434  */
435  
436 int
437 hash(p)
438 register char *p;
439 {
440         register int h, n;
441
442         h = 0;
443         n = NCPS;
444         do {
445
446 #if     CASE_SENSITIVE
447                 h += *p++;
448 #else
449                 h += ccase[*p++];
450 #endif
451
452         } while (--n);
453         return (h&HMASK);
454 }
455
456 /*)Function     VOID *  new(n)
457  *
458  *              unsigned int    n       allocation size in bytes
459  *
460  *      The function new() allocates n bytes of space and returns
461  *      a pointer to this memory.  If no space is available the
462  *      linker is terminated.
463  *
464  *      local variables:
465  *              char *  p               a general pointer
466  *              char *  q               a general pointer
467  *
468  *      global variables:
469  *              none
470  *
471  *      functions called:
472  *              int     fprintf()       c_library
473  *              VOID *  malloc()        c_library
474  *
475  *      side effects:
476  *              Memory is allocated, if allocation fails
477  *              the linker is terminated.
478  */
479
480 VOID *
481 new(n)
482 unsigned int n;
483 {
484         register char *p,*q;
485         register unsigned int i;
486
487         if ((p = (char *) malloc(n)) == NULL) {
488                 fprintf(stderr, "Out of space!\n");
489                 lkexit(1);
490         }
491         for (i=0,q=p; i<n; i++) {
492                 *q++ = 0;
493         }
494         return (p);
495 }