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