4 * (C) Copyright 1989-1995
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
24 * The module lksym.c contains the functions that operate
25 * on the symbol structures.
27 * lksym.c contains the following functions:
38 * lksym.c contains no local/static variables.
41 /*)Function VOID syminit()
43 * The function syminit() is called to clear the hashtable.
46 * int h computed hash value
47 * sym ** spp pointer to an array of
48 * sym structure pointers
51 * sym * symhash[] array of pointers to NHASH
58 * (1) The symbol hash tables are cleared
67 while (spp < &symhash[NHASH])
71 /*)Function sym * newsym()
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
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
96 * areax *axp Pointer to the current
98 * head *headp The pointer to the first
99 * head structure of a linked list
100 * int lkerr error flag
103 * Addr_T eval() lkeval.c
104 * VOID exit() c_library
105 * int fprintf() c_library
106 * char getSid() lklex.c
108 * char getnb() lklex.c
109 * sym * lkpsym() lksym.c
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.
120 * Find/Create a global symbol entry.
125 * | `----- sp->s_type
126 * `------------ sp->s_id
132 register unsigned i ;
133 register unsigned nglob ;
139 getSid(id); // old: getid(id, -1);
141 c = getnb();get();get();
143 tsp->s_type |= S_REF;
145 fprintf(stderr, "Non zero S_REF\n");
151 if (tsp->s_type & S_DEF && tsp->s_addr != i) {
152 fprintf(stderr, "Multiple definition of %s\n", id);
155 tsp->s_type |= S_DEF;
157 * Set value and area extension link.
162 fprintf(stderr, "Invalid symbol type %c for %s\n", c, id);
166 * Place pointer in header symbol list
169 fprintf(stderr, "No header defined\n");
174 for (i=0; i < nglob ;++i) {
180 fprintf(stderr, "Header symbol list overflow\n");
187 /*)Function sym * lkpsym(id,f)
189 * char * id symbol name string
190 * int f f == 0, lookup only
191 * f != 0, create if not found
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.
201 * int h computed hash value
202 * sym * sp pointer to a sym structure
205 * sym * symhash[] array of pointers to NHASH
206 * linked symbol lists
210 * VOID * new() lksym.c
211 * int symeq() lksym.c
214 * If the function new() fails to allocate space
215 * for the new sym structure the linker terminates.
219 lkpsym(char *id, int f)
221 register struct sym *sp;
227 if (symeq(id, sp->s_id))
233 sp = (struct sym *) new (sizeof(struct sym));
234 sp->s_sp = symhash[h];
236 sp->s_id = StoreString( id ); /* JLH */
240 /*)Function Addr_T symval(tsp)
242 * sym * tsp pointer to a symbol structure
244 * The function symval() returns the value of the
245 * relocated symbol by adding the variable definition
246 * value to the areax base address.
249 * Addr_T val relocated address value
262 symval(register struct sym *tsp)
268 val += tsp->s_axp->a_addr;
273 /*)Function VOID symdef(fp)
275 * FILE * fp file handle for output
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.
284 * int i hash table index loop variable
285 * sym * sp pointer to linked symbol structure
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
297 * Undefined variables have their areas set to "_CODE".
303 register struct sym *sp;
306 for (i=0; i<NHASH; ++i) {
309 if (sp->s_axp == NULL)
310 sp->s_axp = areap->a_axp;
311 if ((sp->s_type & S_DEF) == 0)
318 /*)Function VOID symmod(fp,tsp)
320 * FILE * fp output file handle
321 * sym * tsp pointer to a symbol structure
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.
331 * sym ** p pointer to a list of pointers
332 * to symbol structures
335 * head *headp The pointer to the first
336 * head structure of a linked list
337 * head *hp Pointer to the current
339 * int lkerr error flag
342 * int fprintf() c_library
345 * Error output generated.
349 symmod(FILE *fp, struct sym *tsp)
354 if ((hp = headp) != NULL) {
357 for (i=0; i<hp->h_nglob; ++i) {
359 fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id);
360 fprintf(fp, "referenced by module '%s'\n", hp->m_id);
369 /*)Function int symeq(p1, p2)
371 * char * p1 name string
372 * char * p2 name string
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.
381 * char ccase[] an array of characters which
382 * perform the case translation function
393 symeq(register char *p1, register char *p2)
396 return (strncmp( p1, p2, NCPS ) == 0);
398 return (as_strncmpi( p1, p2, NCPS ) == 0);
402 /*)Function int hash(p)
404 * char * p pointer to string to hash
406 * The function hash() computes a hash code using the sum
407 * of all characters mod table size algorithm.
410 * int h accumulated character sum
414 * char ccase[] an array of characters which
415 * perform the case translation function
426 hash(register char *p)
437 h += ccase[(unsigned char)(*p++)];
444 /*)Function VOID * new(n)
446 * unsigned int n allocation size in bytes
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.
453 * char * p a general pointer
454 * char * q a general pointer
460 * int fprintf() c_library
461 * VOID * malloc() c_library
464 * Memory is allocated, if allocation fails
465 * the linker is terminated.
473 if ((p = (char *) calloc(n, 1)) == NULL) {
474 fprintf(stderr, "Out of space!\n");