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
28 * The module lksym.c contains the functions that operate
29 * on the symbol structures.
31 * lksym.c contains the following functions:
42 * lksym.c contains no local/static variables.
45 /*)Function VOID syminit()
47 * The function syminit() is called to clear the hashtable.
50 * int h computed hash value
51 * sym ** spp pointer to an array of
52 * sym structure pointers
55 * sym * symhash[] array of pointers to NHASH
62 * (1) The symbol hash tables are cleared
72 while (spp < &symhash[NHASH])
76 /*)Function sym * newsym()
78 * The function newsym() is called to evaluate the symbol
79 * definition/reference directive from the .rel file(s).
80 * If the symbol is not found in the symbol table a new
81 * symbol structure is created. Evaluation of the
82 * directive determines if this is a reference or a definition.
83 * Multiple definitions of the same variable will be flagged
84 * as an error if the values are not identical. A symbol
85 * definition places the symbol value and area extension
86 * into the symbols data structure. And finally, a pointer
87 * to the symbol structure is placed into the head structure
88 * symbol list. Refer to the description of the header, symbol,
89 * area, and areax structures in lkdata.c for structure and
93 * int c character from input text
94 * int i evaluation value
95 * char id[] symbol name
96 * int nglob number of symbols in this header
97 * sym * tsp pointer to symbol structure
98 * sym ** s list of pointers to symbol structures
101 * areax *axp Pointer to the current
103 * head *headp The pointer to the first
104 * head structure of a linked list
105 * int lkerr error flag
108 * Addr_T eval() lkeval.c
109 * VOID exit() c_library
110 * int fprintf() c_library
112 * char getnb() lklex.c
113 * sym * lkpsym() lksym.c
116 * A symbol structure is created and/or modified.
117 * If structure space allocation fails linker will abort.
118 * Several severe errors (these are internal errors
119 * indicating a corrupted .rel file or corrupted
120 * assembler or linker) will terminated the linker.
124 * Find/Create a global symbol entry.
129 * | `----- sp->s_type
130 * `------------ sp->s_id
136 register int c, i, nglob;
143 c = getnb();get();get();
145 tsp->s_type |= S_REF;
147 fprintf(stderr, "Non zero S_REF\n");
153 if (tsp->s_type & S_DEF && tsp->s_addr != i) {
154 fprintf(stderr, "Multiple definition of %8s\n", id);
157 tsp->s_type |= S_DEF;
159 * Set value and area extension link.
164 fprintf(stderr, "Invalid symbol type %c for %8s\n", c, id);
168 * Place pointer in header symbol list
171 fprintf(stderr, "No header defined\n");
176 for (i=0; i < nglob ;++i) {
182 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.
222 register struct sym *sp;
228 if (symeq(id, sp->s_id))
234 sp = (struct sym *) new (sizeof(struct sym));
235 sp->s_sp = symhash[h];
237 sp->s_id = StoreString( id ); /* JLH */
241 /*)Function Addr_T symval(tsp)
243 * sym * tsp pointer to a symbol structure
245 * The function symval() returns the value of the
246 * relocated symbol by adding the variable definition
247 * value to the areax base address.
250 * Addr_T val relocated address value
264 register struct sym *tsp;
270 val += tsp->s_axp->a_addr;
275 /*)Function VOID symdef(fp)
277 * FILE * fp file handle for output
279 * The function symdef() scans the hashed symbol table
280 * searching for variables referenced but not defined.
281 * Undefined variables are linked to the default
282 * area "_CODE" and reported as referenced by the
283 * appropriate module.
286 * int i hash table index loop variable
287 * sym * sp pointer to linked symbol structure
290 * area *areap The pointer to the first
291 * area structure of a linked list
292 * sym *symhash[NHASH] array of pointers to NHASH
293 * linked symbol lists
299 * Undefined variables have their areas set to "_CODE".
306 register struct sym *sp;
309 for (i=0; i<NHASH; ++i) {
312 if (sp->s_axp == NULL)
313 sp->s_axp = areap->a_axp;
314 if ((sp->s_type & S_DEF) == 0)
321 /*)Function VOID symmod(fp,tsp)
323 * FILE * fp output file handle
324 * sym * tsp pointer to a symbol structure
326 * The function symmod() scans the header structures
327 * searching for a reference to the symbol structure
328 * pointer to by tsp. The function then generates an error
329 * message whichs names the module having referenced the
330 * undefined variable.
334 * sym ** p pointer to a list of pointers
335 * to symbol structures
338 * head *headp The pointer to the first
339 * head structure of a linked list
340 * head *hp Pointer to the current
342 * int lkerr error flag
345 * int fprintf() c_library
348 * Error output generated.
359 if ((hp = headp) != NULL) {
362 for (i=0; i<hp->h_nglob; ++i) {
364 fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id);
365 fprintf(fp, "referenced by module '%s'\n", hp->m_id);
374 /*)Function int symeq(p1, p2)
376 * char * p1 name string
377 * char * p2 name string
379 * The function symeq() compares the two name strings for a match.
380 * The return value is 1 for a match and 0 for no match.
386 * char ccase[] an array of characters which
387 * perform the case translation function
399 register char *p1, *p2;
402 return (strcmp( p1, p2 ) == 0);
404 return (strcmpi( p1, p2 ) == 0);
408 /*)Function int hash(p)
410 * char * p pointer to string to hash
412 * The function hash() computes a hash code using the sum
413 * of all characters mod table size algorithm.
416 * int h accumulated character sum
420 * char ccase[] an array of characters which
421 * perform the case translation function
450 /*)Function VOID * new(n)
452 * unsigned int n allocation size in bytes
454 * The function new() allocates n bytes of space and returns
455 * a pointer to this memory. If no space is available the
456 * linker is terminated.
459 * char * p a general pointer
460 * char * q a general pointer
466 * int fprintf() c_library
467 * VOID * malloc() c_library
470 * Memory is allocated, if allocation fails
471 * the linker is terminated.
479 register unsigned int i;
481 if ((p = (char *) malloc(n)) == NULL) {
482 fprintf(stderr, "Out of space!\n");
485 for (i=0,q=p; i<n; i++) {