Commit | Line | Data |
---|---|---|
2c3a9a86 ML |
1 | /* Copyright (c) 1982 Regents of the University of California */ |
2 | ||
e1f4dbca | 3 | static char sccsid[] = "@(#)object.c 1.15 (Berkeley) %G%"; |
2c3a9a86 ML |
4 | |
5 | /* | |
6 | * Object code interface, mainly for extraction of symbolic information. | |
7 | */ | |
8 | ||
9 | #include "defs.h" | |
10 | #include "object.h" | |
2fd0f574 | 11 | #include "stabstring.h" |
2c3a9a86 ML |
12 | #include "main.h" |
13 | #include "symbols.h" | |
14 | #include "names.h" | |
15 | #include "languages.h" | |
16 | #include "mappings.h" | |
17 | #include "lists.h" | |
18 | #include <a.out.h> | |
19 | #include <stab.h> | |
20 | #include <ctype.h> | |
21 | ||
22 | #ifndef public | |
23 | ||
24 | struct { | |
25 | unsigned int stringsize; /* size of the dumped string table */ | |
26 | unsigned int nsyms; /* number of symbols */ | |
27 | unsigned int nfiles; /* number of files */ | |
28 | unsigned int nlines; /* number of lines */ | |
29 | } nlhdr; | |
30 | ||
2fd0f574 SL |
31 | #include "languages.h" |
32 | #include "symbols.h" | |
33 | ||
34 | #endif | |
35 | ||
36 | #ifndef N_MOD2 | |
37 | # define N_MOD2 0x50 | |
2c3a9a86 ML |
38 | #endif |
39 | ||
40 | public String objname = "a.out"; | |
2fd0f574 SL |
41 | public integer objsize; |
42 | ||
43 | public Language curlang; | |
44 | public Symbol curmodule; | |
45 | public Symbol curparam; | |
46 | public Symbol curcomm; | |
47 | public Symbol commchain; | |
2c3a9a86 | 48 | |
2fd0f574 SL |
49 | private char *stringtab; |
50 | private struct nlist *curnp; | |
2c3a9a86 | 51 | private Boolean warned; |
d5eceaed | 52 | private Boolean strip_ = false; |
2c3a9a86 ML |
53 | |
54 | private Filetab *filep; | |
cc4262e8 | 55 | private Linetab *linep, *prevlinep; |
2c3a9a86 | 56 | |
2fd0f574 SL |
57 | public String curfilename () |
58 | { | |
59 | return ((filep-1)->filename); | |
60 | } | |
2c3a9a86 ML |
61 | |
62 | /* | |
63 | * Blocks are figured out on the fly while reading the symbol table. | |
64 | */ | |
65 | ||
66 | #define MAXBLKDEPTH 25 | |
67 | ||
2fd0f574 SL |
68 | public Symbol curblock; |
69 | ||
2c3a9a86 | 70 | private Symbol blkstack[MAXBLKDEPTH]; |
2fd0f574 SL |
71 | private integer curlevel; |
72 | private integer bnum, nesting; | |
7005bb75 | 73 | private Address addrstk[MAXBLKDEPTH]; |
2c3a9a86 | 74 | |
2fd0f574 SL |
75 | public pushBlock (b) |
76 | Symbol b; | |
77 | { | |
78 | if (curlevel >= MAXBLKDEPTH) { | |
79 | fatal("nesting depth too large (%d)", curlevel); | |
80 | } | |
81 | blkstack[curlevel] = curblock; | |
82 | ++curlevel; | |
83 | curblock = b; | |
84 | if (traceblocks) { | |
85 | printf("entering block %s\n", symname(b)); | |
86 | } | |
2c3a9a86 ML |
87 | } |
88 | ||
2fd0f574 SL |
89 | public enterblock (b) |
90 | Symbol b; | |
91 | { | |
92 | if (curblock == nil) { | |
93 | b->level = 1; | |
94 | } else { | |
95 | b->level = curblock->level + 1; | |
96 | } | |
97 | b->block = curblock; | |
98 | pushBlock(b); | |
99 | } | |
100 | ||
101 | public exitblock () | |
102 | { | |
103 | if (curblock->class == FUNC or curblock->class == PROC) { | |
104 | if (prevlinep != linep) { | |
105 | curblock->symvalue.funcv.src = true; | |
106 | } | |
107 | } | |
108 | if (curlevel <= 0) { | |
109 | panic("nesting depth underflow (%d)", curlevel); | |
110 | } | |
111 | --curlevel; | |
112 | if (traceblocks) { | |
113 | printf("exiting block %s\n", symname(curblock)); | |
114 | } | |
115 | curblock = blkstack[curlevel]; | |
2c3a9a86 ML |
116 | } |
117 | ||
118 | /* | |
119 | * Enter a source line or file name reference into the appropriate table. | |
120 | * Expanded inline to reduce procedure calls. | |
121 | * | |
2fd0f574 | 122 | * private enterline (linenumber, address) |
2c3a9a86 ML |
123 | * Lineno linenumber; |
124 | * Address address; | |
125 | * ... | |
126 | */ | |
127 | ||
128 | #define enterline(linenumber, address) \ | |
129 | { \ | |
130 | register Linetab *lp; \ | |
131 | \ | |
132 | lp = linep - 1; \ | |
133 | if (linenumber != lp->line) { \ | |
134 | if (address != lp->addr) { \ | |
135 | ++lp; \ | |
136 | } \ | |
137 | lp->line = linenumber; \ | |
138 | lp->addr = address; \ | |
139 | linep = lp + 1; \ | |
140 | } \ | |
141 | } | |
142 | ||
2c3a9a86 ML |
143 | /* |
144 | * Read in the namelist from the obj file. | |
145 | * | |
146 | * Reads and seeks are used instead of fread's and fseek's | |
147 | * for efficiency sake; there's a lot of data being read here. | |
148 | */ | |
149 | ||
2fd0f574 | 150 | public readobj (file) |
2c3a9a86 ML |
151 | String file; |
152 | { | |
153 | Fileid f; | |
154 | struct exec hdr; | |
155 | struct nlist nlist; | |
156 | ||
157 | f = open(file, 0); | |
158 | if (f < 0) { | |
159 | fatal("can't open %s", file); | |
160 | } | |
161 | read(f, &hdr, sizeof(hdr)); | |
162 | objsize = hdr.a_text; | |
163 | nlhdr.nsyms = hdr.a_syms / sizeof(nlist); | |
164 | nlhdr.nfiles = nlhdr.nsyms; | |
165 | nlhdr.nlines = nlhdr.nsyms; | |
7005bb75 ML |
166 | if (nlhdr.nsyms > 0) { |
167 | lseek(f, (long) N_STROFF(hdr), 0); | |
168 | read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); | |
169 | nlhdr.stringsize -= 4; | |
170 | stringtab = newarr(char, nlhdr.stringsize); | |
171 | read(f, stringtab, nlhdr.stringsize); | |
172 | allocmaps(nlhdr.nfiles, nlhdr.nlines); | |
173 | lseek(f, (long) N_SYMOFF(hdr), 0); | |
174 | readsyms(f); | |
175 | ordfunctab(); | |
176 | setnlines(); | |
177 | setnfiles(); | |
178 | } | |
2c3a9a86 ML |
179 | close(f); |
180 | } | |
181 | ||
182 | /* | |
183 | * Read in symbols from object file. | |
184 | */ | |
185 | ||
2fd0f574 | 186 | private readsyms (f) |
2c3a9a86 ML |
187 | Fileid f; |
188 | { | |
189 | struct nlist *namelist; | |
190 | register struct nlist *np, *ub; | |
2c3a9a86 ML |
191 | register String name; |
192 | register Boolean afterlg; | |
2fd0f574 SL |
193 | integer index; |
194 | char *lastchar; | |
2c3a9a86 ML |
195 | |
196 | initsyms(); | |
197 | namelist = newarr(struct nlist, nlhdr.nsyms); | |
198 | read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); | |
199 | afterlg = false; | |
200 | ub = &namelist[nlhdr.nsyms]; | |
2fd0f574 SL |
201 | curnp = &namelist[0]; |
202 | np = curnp; | |
203 | while (np < ub) { | |
2c3a9a86 ML |
204 | index = np->n_un.n_strx; |
205 | if (index != 0) { | |
206 | name = &stringtab[index - 4]; | |
d5eceaed | 207 | /* |
2fd0f574 | 208 | * If the program contains any .f files a trailing _ is stripped |
d5eceaed AF |
209 | * from the name on the assumption it was added by the compiler. |
210 | * This only affects names that follow the sdb N_SO entry with | |
211 | * the .f name. | |
212 | */ | |
7005bb75 | 213 | if (strip_ and name[0] != '\0' ) { |
2fd0f574 SL |
214 | lastchar = &name[strlen(name) - 1]; |
215 | if (*lastchar == '_') { | |
216 | *lastchar = '\0'; | |
7005bb75 | 217 | } |
d5eceaed | 218 | } |
2c3a9a86 ML |
219 | } else { |
220 | name = nil; | |
d5eceaed | 221 | } |
2fd0f574 | 222 | |
2c3a9a86 | 223 | /* |
2fd0f574 | 224 | * Assumptions: |
2c3a9a86 ML |
225 | * not an N_STAB ==> name != nil |
226 | * name[0] == '-' ==> name == "-lg" | |
227 | * name[0] != '_' ==> filename or invisible | |
228 | * | |
229 | * The "-lg" signals the beginning of global loader symbols. | |
d5eceaed | 230 | * |
2c3a9a86 ML |
231 | */ |
232 | if ((np->n_type&N_STAB) != 0) { | |
233 | enter_nl(name, np); | |
234 | } else if (name[0] == '-') { | |
235 | afterlg = true; | |
236 | if (curblock->class != PROG) { | |
237 | exitblock(); | |
238 | if (curblock->class != PROG) { | |
239 | exitblock(); | |
240 | } | |
241 | } | |
242 | enterline(0, (linep-1)->addr + 1); | |
2d99de0e ML |
243 | } else if (afterlg) { |
244 | if (name[0] == '_') { | |
2c3a9a86 | 245 | check_global(&name[1], np); |
2c3a9a86 | 246 | } |
2d99de0e ML |
247 | } else if (name[0] == '_') { |
248 | check_local(&name[1], np); | |
2c3a9a86 ML |
249 | } else if ((np->n_type&N_TEXT) == N_TEXT) { |
250 | check_filename(name); | |
251 | } | |
2fd0f574 SL |
252 | ++curnp; |
253 | np = curnp; | |
2c3a9a86 | 254 | } |
7005bb75 | 255 | if (not afterlg) { |
46ec848e | 256 | fatal("not linked for debugging, use \"cc -g ...\""); |
7005bb75 | 257 | } |
2c3a9a86 ML |
258 | dispose(namelist); |
259 | } | |
260 | ||
2fd0f574 SL |
261 | /* |
262 | * Get a continuation entry from the name list. | |
263 | * Return the beginning of the name. | |
264 | */ | |
265 | ||
266 | public String getcont () | |
267 | { | |
268 | register integer index; | |
269 | register String name; | |
270 | ||
271 | ++curnp; | |
272 | index = curnp->n_un.n_strx; | |
273 | if (index == 0) { | |
274 | panic("continuation followed by empty stab"); | |
275 | } | |
276 | name = &stringtab[index - 4]; | |
277 | return name; | |
278 | } | |
279 | ||
2c3a9a86 ML |
280 | /* |
281 | * Initialize symbol information. | |
282 | */ | |
283 | ||
2fd0f574 | 284 | private initsyms () |
2c3a9a86 ML |
285 | { |
286 | curblock = nil; | |
287 | curlevel = 0; | |
7005bb75 | 288 | nesting = 0; |
2fd0f574 | 289 | program = insert(identname("", true)); |
2c3a9a86 | 290 | program->class = PROG; |
e7df52e4 | 291 | program->symvalue.funcv.beginaddr = 0; |
7005bb75 ML |
292 | program->symvalue.funcv.inline = false; |
293 | newfunc(program, codeloc(program)); | |
2c3a9a86 ML |
294 | findbeginning(program); |
295 | enterblock(program); | |
296 | curmodule = program; | |
2fd0f574 SL |
297 | t_boolean = maketype("$boolean", 0L, 1L); |
298 | t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); | |
299 | t_char = maketype("$char", 0L, 255L); | |
300 | t_real = maketype("$real", 8L, 0L); | |
301 | t_nil = maketype("$nil", 0L, 0L); | |
302 | t_open = maketype("integer", 0L, -1L); | |
2c3a9a86 ML |
303 | } |
304 | ||
305 | /* | |
306 | * Free all the object file information that's being stored. | |
307 | */ | |
308 | ||
2fd0f574 | 309 | public objfree () |
2c3a9a86 ML |
310 | { |
311 | symbol_free(); | |
312 | keywords_free(); | |
313 | names_free(); | |
314 | dispose(stringtab); | |
315 | clrfunctab(); | |
316 | } | |
317 | ||
318 | /* | |
319 | * Enter a namelist entry. | |
320 | */ | |
321 | ||
2fd0f574 | 322 | private enter_nl (name, np) |
2c3a9a86 ML |
323 | String name; |
324 | register struct nlist *np; | |
325 | { | |
326 | register Symbol s; | |
2fd0f574 | 327 | register Name n; |
2c3a9a86 ML |
328 | |
329 | s = nil; | |
2c3a9a86 | 330 | switch (np->n_type) { |
7005bb75 ML |
331 | /* |
332 | * Build a symbol for the FORTRAN common area. All GSYMS that follow | |
333 | * will be chained in a list with the head kept in common.offset, and | |
334 | * the tail in common.chain. | |
335 | */ | |
214731a7 ML |
336 | case N_BCOMM: |
337 | if (curcomm) { | |
338 | curcomm->symvalue.common.chain = commchain; | |
d5eceaed | 339 | } |
2fd0f574 | 340 | n = identname(name, true); |
d5eceaed | 341 | curcomm = lookup(n); |
214731a7 ML |
342 | if (curcomm == nil) { |
343 | curcomm = insert(n); | |
344 | curcomm->class = COMMON; | |
345 | curcomm->block = curblock; | |
346 | curcomm->level = program->level; | |
347 | curcomm->symvalue.common.chain = nil; | |
d5eceaed AF |
348 | } |
349 | commchain = curcomm->symvalue.common.chain; | |
214731a7 | 350 | break; |
d5eceaed AF |
351 | |
352 | case N_ECOMM: | |
214731a7 ML |
353 | if (curcomm) { |
354 | curcomm->symvalue.common.chain = commchain; | |
355 | curcomm = nil; | |
d5eceaed AF |
356 | } |
357 | break; | |
7005bb75 | 358 | |
2c3a9a86 | 359 | case N_LBRAC: |
7005bb75 ML |
360 | ++nesting; |
361 | addrstk[nesting] = (linep - 1)->addr; | |
2c3a9a86 ML |
362 | break; |
363 | ||
364 | case N_RBRAC: | |
2fd0f574 | 365 | --nesting; |
7005bb75 ML |
366 | if (addrstk[nesting] == NOADDR) { |
367 | exitblock(); | |
368 | newfunc(curblock, (linep - 1)->addr); | |
2fd0f574 | 369 | addrstk[nesting] = (linep - 1)->addr; |
7005bb75 | 370 | } |
2c3a9a86 ML |
371 | break; |
372 | ||
373 | case N_SLINE: | |
374 | enterline((Lineno) np->n_desc, (Address) np->n_value); | |
375 | break; | |
376 | ||
377 | /* | |
7005bb75 | 378 | * Source files. |
2c3a9a86 ML |
379 | */ |
380 | case N_SO: | |
2fd0f574 | 381 | n = identname(name, true); |
7005bb75 | 382 | enterSourceModule(n, (Address) np->n_value); |
2c3a9a86 ML |
383 | break; |
384 | ||
385 | /* | |
386 | * Textually included files. | |
387 | */ | |
388 | case N_SOL: | |
389 | enterfile(name, (Address) np->n_value); | |
390 | break; | |
391 | ||
392 | /* | |
393 | * These symbols are assumed to have non-nil names. | |
394 | */ | |
395 | case N_GSYM: | |
396 | case N_FUN: | |
397 | case N_STSYM: | |
398 | case N_LCSYM: | |
399 | case N_RSYM: | |
400 | case N_PSYM: | |
401 | case N_LSYM: | |
402 | case N_SSYM: | |
7005bb75 | 403 | case N_LENG: |
2c3a9a86 ML |
404 | if (index(name, ':') == nil) { |
405 | if (not warned) { | |
406 | warned = true; | |
2c3a9a86 ML |
407 | warning("old style symbol information found in \"%s\"", |
408 | curfilename()); | |
2c3a9a86 ML |
409 | } |
410 | } else { | |
411 | entersym(name, np); | |
412 | } | |
413 | break; | |
414 | ||
415 | case N_PC: | |
2fd0f574 | 416 | case N_MOD2: |
2c3a9a86 ML |
417 | break; |
418 | ||
438b5736 | 419 | default: |
7005bb75 | 420 | printf("warning: stab entry unrecognized: "); |
2c3a9a86 | 421 | if (name != nil) { |
7005bb75 | 422 | printf("name %s,", name); |
2c3a9a86 | 423 | } |
7005bb75 | 424 | printf("ntype %2x, desc %x, value %x'\n", |
2c3a9a86 ML |
425 | np->n_type, np->n_desc, np->n_value); |
426 | break; | |
427 | } | |
428 | } | |
429 | ||
2fd0f574 SL |
430 | /* |
431 | * Try to find the symbol that is referred to by the given name. | |
432 | * Since it's an external, we may want to follow a level of indirection. | |
433 | */ | |
434 | ||
435 | private Symbol findsym (n) | |
436 | Name n; | |
437 | { | |
438 | register Symbol r, s; | |
439 | ||
440 | find(s, n) where | |
441 | s->level == program->level and | |
442 | (s->class == EXTREF or s->class == VAR or | |
443 | s->class == PROC or s->class == FUNC) | |
444 | endfind(s); | |
445 | if (s != nil and s->class == EXTREF) { | |
446 | r = s->symvalue.extref; | |
447 | delete(s); | |
448 | } else { | |
449 | r = s; | |
450 | } | |
451 | return r; | |
452 | } | |
453 | ||
2c3a9a86 ML |
454 | /* |
455 | * Check to see if a global _name is already in the symbol table, | |
456 | * if not then insert it. | |
457 | */ | |
458 | ||
2fd0f574 | 459 | private check_global (name, np) |
2c3a9a86 ML |
460 | String name; |
461 | register struct nlist *np; | |
462 | { | |
463 | register Name n; | |
d5eceaed | 464 | register Symbol t, u; |
2c3a9a86 ML |
465 | |
466 | if (not streq(name, "end")) { | |
467 | n = identname(name, true); | |
468 | if ((np->n_type&N_TYPE) == N_TEXT) { | |
2fd0f574 | 469 | t = findsym(n); |
2c3a9a86 ML |
470 | if (t == nil) { |
471 | t = insert(n); | |
472 | t->language = findlanguage(".s"); | |
473 | t->class = FUNC; | |
474 | t->type = t_int; | |
475 | t->block = curblock; | |
476 | t->level = program->level; | |
cc4262e8 | 477 | t->symvalue.funcv.src = false; |
7005bb75 | 478 | t->symvalue.funcv.inline = false; |
2c3a9a86 | 479 | } |
2fd0f574 SL |
480 | if (t->class == VAR) { |
481 | t->symvalue.offset = np->n_value; | |
482 | } else { | |
483 | t->symvalue.funcv.beginaddr = np->n_value; | |
484 | newfunc(t, codeloc(t)); | |
485 | findbeginning(t); | |
486 | } | |
214731a7 | 487 | } else if ((np->n_type&N_TYPE) == N_BSS) { |
2c3a9a86 | 488 | find(t, n) where |
214731a7 | 489 | t->class == COMMON |
2c3a9a86 | 490 | endfind(t); |
214731a7 ML |
491 | if (t != nil) { |
492 | u = (Symbol) t->symvalue.common.offset; | |
493 | while (u != nil) { | |
494 | u->symvalue.offset = u->symvalue.common.offset+np->n_value; | |
495 | u = u->symvalue.common.chain; | |
496 | } | |
497 | } else { | |
498 | check_var(np, n); | |
2c3a9a86 | 499 | } |
214731a7 ML |
500 | } else { |
501 | check_var(np, n); | |
2c3a9a86 ML |
502 | } |
503 | } | |
504 | } | |
505 | ||
214731a7 ML |
506 | /* |
507 | * Check to see if a namelist entry refers to a variable. | |
508 | * If not, create a variable for the entry. In any case, | |
509 | * set the offset of the variable according to the value field | |
510 | * in the entry. | |
511 | */ | |
512 | ||
2fd0f574 | 513 | private check_var (np, n) |
214731a7 ML |
514 | struct nlist *np; |
515 | register Name n; | |
516 | { | |
517 | register Symbol t; | |
518 | ||
2fd0f574 | 519 | t = findsym(n); |
214731a7 ML |
520 | if (t == nil) { |
521 | t = insert(n); | |
522 | t->language = findlanguage(".s"); | |
523 | t->class = VAR; | |
524 | t->type = t_int; | |
525 | t->level = program->level; | |
2fd0f574 | 526 | t->block = curblock; |
214731a7 | 527 | } |
214731a7 ML |
528 | t->symvalue.offset = np->n_value; |
529 | } | |
530 | ||
2c3a9a86 ML |
531 | /* |
532 | * Check to see if a local _name is known in the current scope. | |
533 | * If not then enter it. | |
534 | */ | |
535 | ||
2fd0f574 | 536 | private check_local (name, np) |
2c3a9a86 ML |
537 | String name; |
538 | register struct nlist *np; | |
539 | { | |
540 | register Name n; | |
541 | register Symbol t, cur; | |
542 | ||
543 | n = identname(name, true); | |
544 | cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; | |
545 | find(t, n) where t->block == cur endfind(t); | |
546 | if (t == nil) { | |
547 | t = insert(n); | |
548 | t->language = findlanguage(".s"); | |
549 | t->type = t_int; | |
550 | t->block = cur; | |
551 | t->level = cur->level; | |
552 | if ((np->n_type&N_TYPE) == N_TEXT) { | |
553 | t->class = FUNC; | |
cc4262e8 | 554 | t->symvalue.funcv.src = false; |
7005bb75 | 555 | t->symvalue.funcv.inline = false; |
2c3a9a86 | 556 | t->symvalue.funcv.beginaddr = np->n_value; |
7005bb75 | 557 | newfunc(t, codeloc(t)); |
2c3a9a86 ML |
558 | findbeginning(t); |
559 | } else { | |
560 | t->class = VAR; | |
561 | t->symvalue.offset = np->n_value; | |
562 | } | |
563 | } | |
564 | } | |
565 | ||
566 | /* | |
567 | * Check to see if a symbol corresponds to a object file name. | |
568 | * For some reason these are listed as in the text segment. | |
569 | */ | |
570 | ||
2fd0f574 | 571 | private check_filename (name) |
2c3a9a86 ML |
572 | String name; |
573 | { | |
574 | register String mname; | |
2fd0f574 | 575 | register integer i; |
2c3a9a86 ML |
576 | register Symbol s; |
577 | ||
578 | mname = strdup(name); | |
579 | i = strlen(mname) - 2; | |
580 | if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { | |
581 | mname[i] = '\0'; | |
582 | --i; | |
583 | while (mname[i] != '/' and i >= 0) { | |
584 | --i; | |
585 | } | |
586 | s = insert(identname(&mname[i+1], true)); | |
587 | s->language = findlanguage(".s"); | |
588 | s->class = MODULE; | |
e7df52e4 ML |
589 | s->symvalue.funcv.beginaddr = 0; |
590 | findbeginning(s); | |
2c3a9a86 ML |
591 | if (curblock->class != PROG) { |
592 | exitblock(); | |
593 | if (curblock->class != PROG) { | |
594 | exitblock(); | |
595 | } | |
596 | } | |
597 | enterblock(s); | |
598 | curmodule = s; | |
599 | } | |
600 | } | |
601 | ||
7005bb75 ML |
602 | /* |
603 | * Check to see if a symbol is about to be defined within an unnamed block. | |
604 | * If this happens, we create a procedure for the unnamed block, make it | |
605 | * "inline" so that tracebacks don't associate an activation record with it, | |
606 | * and enter it into the function table so that it will be detected | |
607 | * by "whatblock". | |
608 | */ | |
609 | ||
2fd0f574 | 610 | public chkUnnamedBlock () |
7005bb75 ML |
611 | { |
612 | register Symbol s; | |
613 | static int bnum = 0; | |
614 | char buf[100]; | |
2fd0f574 | 615 | Address startaddr; |
7005bb75 | 616 | |
2fd0f574 SL |
617 | if (nesting > 0 and addrstk[nesting] != NOADDR) { |
618 | startaddr = (linep - 1)->addr; | |
619 | ++bnum; | |
620 | sprintf(buf, "$b%d", bnum); | |
621 | s = insert(identname(buf, false)); | |
622 | s->language = curlang; | |
623 | s->class = PROC; | |
624 | s->symvalue.funcv.src = false; | |
625 | s->symvalue.funcv.inline = true; | |
626 | s->symvalue.funcv.beginaddr = startaddr; | |
627 | enterblock(s); | |
628 | newfunc(s, startaddr); | |
629 | addrstk[nesting] = NOADDR; | |
630 | } | |
7005bb75 ML |
631 | } |
632 | ||
633 | /* | |
634 | * Compilation unit. C associates scope with filenames | |
635 | * so we treat them as "modules". The filename without | |
636 | * the suffix is used for the module name. | |
637 | * | |
638 | * Because there is no explicit "end-of-block" mark in | |
639 | * the object file, we must exit blocks for the current | |
640 | * procedure and module. | |
641 | */ | |
642 | ||
2fd0f574 | 643 | private enterSourceModule (n, addr) |
7005bb75 ML |
644 | Name n; |
645 | Address addr; | |
646 | { | |
647 | register Symbol s; | |
648 | Name nn; | |
649 | String mname, suffix; | |
650 | ||
651 | mname = strdup(ident(n)); | |
652 | if (rindex(mname, '/') != nil) { | |
653 | mname = rindex(mname, '/') + 1; | |
654 | } | |
655 | suffix = rindex(mname, '.'); | |
656 | curlang = findlanguage(suffix); | |
657 | if (curlang == findlanguage(".f")) { | |
658 | strip_ = true; | |
659 | } | |
660 | if (suffix != nil) { | |
661 | *suffix = '\0'; | |
662 | } | |
2fd0f574 | 663 | if (not (*language_op(curlang, L_HASMODULES))()) { |
7005bb75 ML |
664 | if (curblock->class != PROG) { |
665 | exitblock(); | |
2fd0f574 | 666 | if (curblock->class != PROG) { |
2c3a9a86 ML |
667 | exitblock(); |
668 | } | |
2c3a9a86 | 669 | } |
2fd0f574 SL |
670 | nn = identname(mname, true); |
671 | if (curmodule == nil or curmodule->name != nn) { | |
672 | s = insert(nn); | |
673 | s->class = MODULE; | |
674 | s->symvalue.funcv.beginaddr = 0; | |
675 | findbeginning(s); | |
2c3a9a86 | 676 | } else { |
2fd0f574 | 677 | s = curmodule; |
2c3a9a86 | 678 | } |
2fd0f574 SL |
679 | s->language = curlang; |
680 | enterblock(s); | |
681 | curmodule = s; | |
2c3a9a86 | 682 | } |
2fd0f574 SL |
683 | if (program->language == nil) { |
684 | program->language = curlang; | |
2c3a9a86 | 685 | } |
2fd0f574 SL |
686 | warned = false; |
687 | enterfile(ident(n), addr); | |
688 | initTypeTable(); | |
2c3a9a86 ML |
689 | } |
690 | ||
691 | /* | |
692 | * Allocate file and line tables and initialize indices. | |
693 | */ | |
694 | ||
2fd0f574 SL |
695 | private allocmaps (nf, nl) |
696 | integer nf, nl; | |
2c3a9a86 ML |
697 | { |
698 | if (filetab != nil) { | |
699 | dispose(filetab); | |
700 | } | |
701 | if (linetab != nil) { | |
702 | dispose(linetab); | |
703 | } | |
704 | filetab = newarr(Filetab, nf); | |
705 | linetab = newarr(Linetab, nl); | |
706 | filep = filetab; | |
707 | linep = linetab; | |
708 | } | |
709 | ||
710 | /* | |
711 | * Add a file to the file table. | |
214731a7 ML |
712 | * |
713 | * If the new address is the same as the previous file address | |
714 | * this routine used to not enter the file, but this caused some | |
715 | * problems so it has been removed. It's not clear that this in | |
716 | * turn may not also cause a problem. | |
2c3a9a86 ML |
717 | */ |
718 | ||
2fd0f574 | 719 | private enterfile (filename, addr) |
2c3a9a86 ML |
720 | String filename; |
721 | Address addr; | |
722 | { | |
214731a7 ML |
723 | filep->addr = addr; |
724 | filep->filename = filename; | |
725 | filep->lineindex = linep - linetab; | |
726 | ++filep; | |
2c3a9a86 ML |
727 | } |
728 | ||
729 | /* | |
730 | * Since we only estimated the number of lines (and it was a poor | |
731 | * estimation) and since we need to know the exact number of lines | |
732 | * to do a binary search, we set it when we're done. | |
733 | */ | |
734 | ||
2fd0f574 | 735 | private setnlines () |
2c3a9a86 ML |
736 | { |
737 | nlhdr.nlines = linep - linetab; | |
738 | } | |
739 | ||
740 | /* | |
741 | * Similarly for nfiles ... | |
742 | */ | |
743 | ||
2fd0f574 | 744 | private setnfiles () |
2c3a9a86 ML |
745 | { |
746 | nlhdr.nfiles = filep - filetab; | |
747 | setsource(filetab[0].filename); | |
748 | } |