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