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