03b96b9219bdb92f8094bc41699020564855871d
[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 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 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 }
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 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 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 i, j;
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 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 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 }