19c80ee16f9525428f2e5b6e2a983a0d9e7266ea
[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         /* Never reached */
179 }
180
181 /*)Function     sym *   lkpsym(id,f)
182  *
183  *              char *  id              symbol name string
184  *              int     f               f == 0, lookup only
185  *                                      f != 0, create if not found
186  *
187  *      The function lookup() searches the symbol hash tables for
188  *      a symbol name match returning a pointer to the sym structure.
189  *      If the symbol is not found then a sym structure is created,
190  *      initialized, and linked to the appropriate hash table if f != 0.
191  *      A pointer to this new sym structure is returned or a NULL
192  *      pointer is returned if f == 0.
193  *
194  *      local variables:
195  *              int     h               computed hash value
196  *              sym *   sp              pointer to a sym structure
197  *
198  *      global varaibles:
199  *              sym * symhash[]         array of pointers to NHASH
200  *                                      linked symbol lists
201  *
202  *      functions called:
203  *              int     hash()          lksym.c
204  *              VOID *  new()           lksym.c
205  *              int     symeq()         lksym.c
206  *
207  *      side effects:
208  *              If the function new() fails to allocate space
209  *              for the new sym structure the linker terminates.
210  */
211
212 struct sym *
213 lkpsym(id, f)
214 char *id;
215 {
216         register struct sym *sp;
217         register int h;
218
219         h = hash(id);
220         sp = symhash[h];
221         while (sp != NULL) {
222                 if (symeq(id, sp->s_id))
223                         return (sp);
224                 sp = sp->s_sp;
225         }
226         if (f == 0)
227                 return (NULL);
228         sp = (struct sym *) new (sizeof(struct sym));
229         sp->s_sp = symhash[h];
230         symhash[h] = sp;
231         strncpy(sp->s_id, id, NCPS);
232         return (sp);
233 }
234
235 /*)Function     Addr_T  symval(tsp)
236  *
237  *              sym *   tsp             pointer to a symbol structure
238  *
239  *      The function symval() returns the value of the
240  *      relocated symbol by adding the variable definition
241  *      value to the areax base address.
242  *
243  *      local variables:
244  *              Addr_T  val             relocated address value
245  *
246  *      global variables:
247  *              none
248  *
249  *      functions called:
250  *              none
251  *
252  *      side effects:
253  *              none
254  */
255
256 Addr_T
257 symval(tsp)
258 register struct sym *tsp;
259 {
260         register Addr_T val;
261
262         val = tsp->s_addr;
263         if (tsp->s_axp) {
264                 val += tsp->s_axp->a_addr;
265         }
266         return(val);
267 }
268
269 /*)Function     VOID    symdef(fp)
270  *
271  *              FILE *  fp              file handle for output
272  *
273  *      The function symdef() scans the hashed symbol table
274  *      searching for variables referenced but not defined.
275  *      Undefined variables are linked to the default
276  *      area "_CODE" and reported as referenced by the
277  *      appropriate module.
278  *
279  *      local variables:
280  *              int     i               hash table index loop variable
281  *              sym *   sp              pointer to linked symbol structure
282  *
283  *      global variables:
284  *              area    *areap          The pointer to the first
285  *                                      area structure of a linked list
286  *              sym *symhash[NHASH]     array of pointers to NHASH
287  *                                      linked symbol lists
288  *
289  *      functions called:
290  *              symmod()                lksym.c
291  *
292  *      side effects:
293  *              Undefined variables have their areas set to "_CODE".
294  */
295
296 VOID
297 symdef(fp)
298 FILE *fp;
299 {
300         register struct sym *sp;
301         register int i;
302
303         for (i=0; i<NHASH; ++i) {
304                 sp = symhash[i];
305                 while (sp) {
306                         if (sp->s_axp == NULL)
307                                 sp->s_axp = areap->a_axp;
308                         if ((sp->s_type & S_DEF) == 0)
309                                 symmod(fp, sp);
310                         sp = sp->s_sp;
311                 }
312         }
313 }
314
315 /*)Function     VOID    symmod(fp,tsp)
316  *
317  *              FILE *  fp              output file handle
318  *              sym *   tsp             pointer to a symbol structure
319  *
320  *      The function symmod() scans the header structures
321  *      searching for a reference to the symbol structure
322  *      pointer to by tsp.  The function then generates an error
323  *      message whichs names the module having referenced the
324  *      undefined variable.
325  *
326  *      local variables:
327  *              int     i               loop counter
328  *              sym **  p               pointer to a list of pointers
329  *                                      to symbol structures
330  *
331  *      global variables:
332  *              head    *headp          The pointer to the first
333  *                                      head structure of a linked list
334  *              head    *hp             Pointer to the current
335  *                                      head structure
336  *              int     lkerr           error flag
337  *
338  *      functions called:
339  *              int     fprintf()       c_library
340  *
341  *      side effects:
342  *              Error output generated.
343  */
344
345 VOID
346 symmod(fp, tsp)
347 FILE *fp;
348 struct sym *tsp;
349 {
350     register int i;
351         struct sym **p;
352
353         if ((hp = headp) != NULL) {
354             while(hp) {
355                 p = hp->s_list;
356                 for (i=0; i<hp->h_nglob; ++i) {
357                     if (p[i] == tsp) {
358                         fprintf(fp, "\n?ASlink-Warning-Undefined Global %s ", tsp->s_id);
359                         fprintf(fp, "referenced by module %s\n", hp->m_id);
360                         lkerr++;
361                     }
362                 }
363             hp = hp->h_hp;
364             }
365         }
366 }
367
368 /*)Function     int     symeq(p1, p2)
369  *
370  *              char *  p1              name string
371  *              char *  p2              name string
372  *
373  *      The function symeq() compares the two name strings for a match.
374  *      The return value is 1 for a match and 0 for no match.
375  *
376  *      local variables:
377  *              int     h               loop counter
378  *
379  *      global variables:
380  *              char    ccase[]         an array of characters which
381  *                                      perform the case translation function
382  *
383  *      functions called:
384  *              none
385  *
386  *      side effects:
387  *              none
388  *
389  */
390
391 int
392 symeq(p1, p2)
393 register char *p1, *p2;
394 {
395         register int n;
396
397         n = NCPS;
398         do {
399
400 #if     CASE_SENSITIVE
401                 if (*p1++ != *p2++)
402                         return (0);
403 #else
404                 if (ccase[*p1++] != ccase[*p2++])
405                         return (0);
406 #endif
407
408         } while (--n);
409         return (1);
410 }
411
412 /*)Function     int     hash(p)
413  *
414  *              char *  p               pointer to string to hash
415  *
416  *      The function hash() computes a hash code using the sum
417  *      of all characters mod table size algorithm.
418  *
419  *      local variables:
420  *              int     h               accumulated character sum
421  *              int     n               loop counter
422  *
423  *      global variables:
424  *              char    ccase[]         an array of characters which
425  *                                      perform the case translation function
426  *
427  *      functions called:
428  *              none
429  *
430  *      side effects:
431  *              none
432  *
433  */
434  
435 int
436 hash(p)
437 register char *p;
438 {
439         register int h, n;
440
441         h = 0;
442         n = NCPS;
443         do {
444
445 #if     CASE_SENSITIVE
446                 h += *p++;
447 #else
448                 h += ccase[*p++];
449 #endif
450
451         } while (--n);
452         return (h&HMASK);
453 }
454
455 /*)Function     VOID *  new(n)
456  *
457  *              unsigned int    n       allocation size in bytes
458  *
459  *      The function new() allocates n bytes of space and returns
460  *      a pointer to this memory.  If no space is available the
461  *      linker is terminated.
462  *
463  *      local variables:
464  *              char *  p               a general pointer
465  *              char *  q               a general pointer
466  *
467  *      global variables:
468  *              none
469  *
470  *      functions called:
471  *              int     fprintf()       c_library
472  *              VOID *  malloc()        c_library
473  *
474  *      side effects:
475  *              Memory is allocated, if allocation fails
476  *              the linker is terminated.
477  */
478
479 VOID *
480 new(n)
481 unsigned int n;
482 {
483         register char *p,*q;
484         register unsigned int i;
485
486         if ((p = (char *) malloc(n)) == NULL) {
487                 fprintf(stderr, "Out of space!\n");
488                 lkexit(1);
489         }
490         for (i=0,q=p; i<n; i++) {
491                 *q++ = 0;
492         }
493         return (p);
494 }