date and time created 90/06/25 15:37:01 by bostic
[unix-history] / usr / src / old / dbx / object.c
CommitLineData
2a24676e 1/*
8a90f3aa
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
6ecf3d85 5 * %sccs.include.redist.c%
2a24676e 6 */
2c3a9a86 7
2a24676e 8#ifndef lint
6ecf3d85 9static char sccsid[] = "@(#)object.c 5.4 (Berkeley) %G%";
8a90f3aa 10#endif /* not lint */
2c3a9a86
ML
11
12/*
13 * Object code interface, mainly for extraction of symbolic information.
14 */
15
16#include "defs.h"
17#include "object.h"
2fd0f574 18#include "stabstring.h"
2c3a9a86
ML
19#include "main.h"
20#include "symbols.h"
21#include "names.h"
22#include "languages.h"
23#include "mappings.h"
24#include "lists.h"
25#include <a.out.h>
26#include <stab.h>
27#include <ctype.h>
28
29#ifndef public
30
31struct {
32 unsigned int stringsize; /* size of the dumped string table */
33 unsigned int nsyms; /* number of symbols */
34 unsigned int nfiles; /* number of files */
35 unsigned int nlines; /* number of lines */
36} nlhdr;
37
2fd0f574
SL
38#include "languages.h"
39#include "symbols.h"
40
41#endif
42
43#ifndef N_MOD2
44# define N_MOD2 0x50
2c3a9a86
ML
45#endif
46
47public String objname = "a.out";
2fd0f574
SL
48public integer objsize;
49
50public Language curlang;
51public Symbol curmodule;
52public Symbol curparam;
53public Symbol curcomm;
54public Symbol commchain;
2c3a9a86 55
2fd0f574
SL
56private char *stringtab;
57private struct nlist *curnp;
2c3a9a86 58private Boolean warned;
d5eceaed 59private Boolean strip_ = false;
2c3a9a86
ML
60
61private Filetab *filep;
cc4262e8 62private Linetab *linep, *prevlinep;
2c3a9a86 63
2fd0f574
SL
64public String curfilename ()
65{
66 return ((filep-1)->filename);
67}
2c3a9a86
ML
68
69/*
70 * Blocks are figured out on the fly while reading the symbol table.
71 */
72
73#define MAXBLKDEPTH 25
74
2fd0f574
SL
75public Symbol curblock;
76
2c3a9a86 77private Symbol blkstack[MAXBLKDEPTH];
2fd0f574
SL
78private integer curlevel;
79private integer bnum, nesting;
7005bb75 80private Address addrstk[MAXBLKDEPTH];
2c3a9a86 81
2fd0f574
SL
82public pushBlock (b)
83Symbol b;
84{
85 if (curlevel >= MAXBLKDEPTH) {
86 fatal("nesting depth too large (%d)", curlevel);
87 }
88 blkstack[curlevel] = curblock;
89 ++curlevel;
90 curblock = b;
91 if (traceblocks) {
92 printf("entering block %s\n", symname(b));
93 }
2c3a9a86
ML
94}
95
0022c355
ML
96/*
97 * Change the current block with saving the previous one,
98 * since it is assumed that the symbol for the current one is to be deleted.
99 */
100
101public changeBlock (b)
102Symbol b;
103{
104 curblock = b;
105}
106
2fd0f574
SL
107public enterblock (b)
108Symbol b;
109{
110 if (curblock == nil) {
111 b->level = 1;
112 } else {
113 b->level = curblock->level + 1;
114 }
115 b->block = curblock;
116 pushBlock(b);
117}
118
119public exitblock ()
120{
121 if (curblock->class == FUNC or curblock->class == PROC) {
122 if (prevlinep != linep) {
123 curblock->symvalue.funcv.src = true;
124 }
125 }
126 if (curlevel <= 0) {
127 panic("nesting depth underflow (%d)", curlevel);
128 }
129 --curlevel;
130 if (traceblocks) {
131 printf("exiting block %s\n", symname(curblock));
132 }
133 curblock = blkstack[curlevel];
2c3a9a86
ML
134}
135
136/*
137 * Enter a source line or file name reference into the appropriate table.
138 * Expanded inline to reduce procedure calls.
139 *
2fd0f574 140 * private enterline (linenumber, address)
2c3a9a86
ML
141 * Lineno linenumber;
142 * Address address;
143 * ...
144 */
145
146#define enterline(linenumber, address) \
147{ \
148 register Linetab *lp; \
149 \
150 lp = linep - 1; \
151 if (linenumber != lp->line) { \
152 if (address != lp->addr) { \
153 ++lp; \
154 } \
155 lp->line = linenumber; \
156 lp->addr = address; \
157 linep = lp + 1; \
158 } \
159}
160
2c3a9a86
ML
161/*
162 * Read in the namelist from the obj file.
163 *
164 * Reads and seeks are used instead of fread's and fseek's
165 * for efficiency sake; there's a lot of data being read here.
166 */
167
2fd0f574 168public readobj (file)
2c3a9a86
ML
169String file;
170{
171 Fileid f;
172 struct exec hdr;
173 struct nlist nlist;
174
175 f = open(file, 0);
176 if (f < 0) {
177 fatal("can't open %s", file);
178 }
179 read(f, &hdr, sizeof(hdr));
0022c355
ML
180 if (N_BADMAG(hdr)) {
181 objsize = 0;
182 nlhdr.nsyms = 0;
183 nlhdr.nfiles = 0;
184 nlhdr.nlines = 0;
185 } else {
186 objsize = hdr.a_text;
187 nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
188 nlhdr.nfiles = nlhdr.nsyms;
189 nlhdr.nlines = nlhdr.nsyms;
190 }
7005bb75
ML
191 if (nlhdr.nsyms > 0) {
192 lseek(f, (long) N_STROFF(hdr), 0);
193 read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
194 nlhdr.stringsize -= 4;
195 stringtab = newarr(char, nlhdr.stringsize);
196 read(f, stringtab, nlhdr.stringsize);
197 allocmaps(nlhdr.nfiles, nlhdr.nlines);
198 lseek(f, (long) N_SYMOFF(hdr), 0);
199 readsyms(f);
200 ordfunctab();
201 setnlines();
202 setnfiles();
0022c355
ML
203 } else {
204 initsyms();
7005bb75 205 }
2c3a9a86
ML
206 close(f);
207}
208
0022c355
ML
209/*
210 * Found the beginning of the externals in the object file
211 * (signified by the "-lg" or find an external), close the
212 * block for the last procedure.
213 */
214
215private foundglobals ()
216{
217 if (curblock->class != PROG) {
218 exitblock();
219 if (curblock->class != PROG) {
220 exitblock();
221 }
222 }
223 enterline(0, (linep-1)->addr + 1);
224}
225
2c3a9a86
ML
226/*
227 * Read in symbols from object file.
228 */
229
2fd0f574 230private readsyms (f)
2c3a9a86
ML
231Fileid f;
232{
233 struct nlist *namelist;
234 register struct nlist *np, *ub;
2c3a9a86 235 register String name;
9606e7b9 236 boolean afterlg, foundstab;
2fd0f574
SL
237 integer index;
238 char *lastchar;
2c3a9a86
ML
239
240 initsyms();
241 namelist = newarr(struct nlist, nlhdr.nsyms);
242 read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
243 afterlg = false;
9606e7b9 244 foundstab = false;
2c3a9a86 245 ub = &namelist[nlhdr.nsyms];
2fd0f574
SL
246 curnp = &namelist[0];
247 np = curnp;
248 while (np < ub) {
2c3a9a86
ML
249 index = np->n_un.n_strx;
250 if (index != 0) {
251 name = &stringtab[index - 4];
d5eceaed 252 /*
2fd0f574 253 * If the program contains any .f files a trailing _ is stripped
d5eceaed
AF
254 * from the name on the assumption it was added by the compiler.
255 * This only affects names that follow the sdb N_SO entry with
256 * the .f name.
257 */
7005bb75 258 if (strip_ and name[0] != '\0' ) {
2fd0f574
SL
259 lastchar = &name[strlen(name) - 1];
260 if (*lastchar == '_') {
261 *lastchar = '\0';
7005bb75 262 }
d5eceaed 263 }
2c3a9a86
ML
264 } else {
265 name = nil;
d5eceaed 266 }
2fd0f574 267
2c3a9a86 268 /*
2fd0f574 269 * Assumptions:
2c3a9a86
ML
270 * not an N_STAB ==> name != nil
271 * name[0] == '-' ==> name == "-lg"
272 * name[0] != '_' ==> filename or invisible
273 *
274 * The "-lg" signals the beginning of global loader symbols.
d5eceaed 275 *
2c3a9a86
ML
276 */
277 if ((np->n_type&N_STAB) != 0) {
9606e7b9 278 foundstab = true;
2c3a9a86
ML
279 enter_nl(name, np);
280 } else if (name[0] == '-') {
281 afterlg = true;
0022c355 282 foundglobals();
2d99de0e 283 } else if (afterlg) {
0022c355
ML
284 check_global(name, np);
285 } else if ((np->n_type&N_EXT) == N_EXT) {
286 afterlg = true;
287 foundglobals();
288 check_global(name, np);
2d99de0e
ML
289 } else if (name[0] == '_') {
290 check_local(&name[1], np);
2c3a9a86
ML
291 } else if ((np->n_type&N_TEXT) == N_TEXT) {
292 check_filename(name);
293 }
2fd0f574
SL
294 ++curnp;
295 np = curnp;
2c3a9a86 296 }
9606e7b9
DS
297 if (not foundstab) {
298 warning("no source compiled with -g");
299 }
2c3a9a86
ML
300 dispose(namelist);
301}
302
2fd0f574
SL
303/*
304 * Get a continuation entry from the name list.
305 * Return the beginning of the name.
306 */
307
308public String getcont ()
309{
310 register integer index;
311 register String name;
312
313 ++curnp;
314 index = curnp->n_un.n_strx;
315 if (index == 0) {
9606e7b9
DS
316 name = "";
317 } else {
318 name = &stringtab[index - 4];
2fd0f574 319 }
2fd0f574
SL
320 return name;
321}
322
2c3a9a86
ML
323/*
324 * Initialize symbol information.
325 */
326
2fd0f574 327private initsyms ()
2c3a9a86
ML
328{
329 curblock = nil;
330 curlevel = 0;
7005bb75 331 nesting = 0;
2fd0f574 332 program = insert(identname("", true));
2c3a9a86 333 program->class = PROG;
9606e7b9
DS
334 program->language = primlang;
335 program->symvalue.funcv.beginaddr = CODESTART;
7005bb75
ML
336 program->symvalue.funcv.inline = false;
337 newfunc(program, codeloc(program));
2c3a9a86
ML
338 findbeginning(program);
339 enterblock(program);
340 curmodule = program;
2c3a9a86
ML
341}
342
343/*
344 * Free all the object file information that's being stored.
345 */
346
2fd0f574 347public objfree ()
2c3a9a86
ML
348{
349 symbol_free();
0022c355
ML
350 /* keywords_free(); */
351 /* names_free(); */
352 /* dispose(stringtab); */
2c3a9a86
ML
353 clrfunctab();
354}
355
356/*
357 * Enter a namelist entry.
358 */
359
2fd0f574 360private enter_nl (name, np)
2c3a9a86
ML
361String name;
362register struct nlist *np;
363{
364 register Symbol s;
2fd0f574 365 register Name n;
2c3a9a86
ML
366
367 s = nil;
2c3a9a86 368 switch (np->n_type) {
7005bb75
ML
369 /*
370 * Build a symbol for the FORTRAN common area. All GSYMS that follow
371 * will be chained in a list with the head kept in common.offset, and
372 * the tail in common.chain.
373 */
214731a7
ML
374 case N_BCOMM:
375 if (curcomm) {
376 curcomm->symvalue.common.chain = commchain;
d5eceaed 377 }
2fd0f574 378 n = identname(name, true);
d5eceaed 379 curcomm = lookup(n);
214731a7
ML
380 if (curcomm == nil) {
381 curcomm = insert(n);
382 curcomm->class = COMMON;
383 curcomm->block = curblock;
384 curcomm->level = program->level;
385 curcomm->symvalue.common.chain = nil;
d5eceaed
AF
386 }
387 commchain = curcomm->symvalue.common.chain;
214731a7 388 break;
d5eceaed
AF
389
390 case N_ECOMM:
214731a7
ML
391 if (curcomm) {
392 curcomm->symvalue.common.chain = commchain;
393 curcomm = nil;
d5eceaed
AF
394 }
395 break;
7005bb75 396
2c3a9a86 397 case N_LBRAC:
7005bb75
ML
398 ++nesting;
399 addrstk[nesting] = (linep - 1)->addr;
2c3a9a86
ML
400 break;
401
402 case N_RBRAC:
2fd0f574 403 --nesting;
7005bb75
ML
404 if (addrstk[nesting] == NOADDR) {
405 exitblock();
406 newfunc(curblock, (linep - 1)->addr);
2fd0f574 407 addrstk[nesting] = (linep - 1)->addr;
7005bb75 408 }
2c3a9a86
ML
409 break;
410
411 case N_SLINE:
412 enterline((Lineno) np->n_desc, (Address) np->n_value);
413 break;
414
415 /*
7005bb75 416 * Source files.
2c3a9a86
ML
417 */
418 case N_SO:
2fd0f574 419 n = identname(name, true);
7005bb75 420 enterSourceModule(n, (Address) np->n_value);
2c3a9a86
ML
421 break;
422
423 /*
424 * Textually included files.
425 */
426 case N_SOL:
427 enterfile(name, (Address) np->n_value);
428 break;
429
430 /*
431 * These symbols are assumed to have non-nil names.
432 */
433 case N_GSYM:
434 case N_FUN:
435 case N_STSYM:
436 case N_LCSYM:
437 case N_RSYM:
438 case N_PSYM:
439 case N_LSYM:
440 case N_SSYM:
7005bb75 441 case N_LENG:
2c3a9a86
ML
442 if (index(name, ':') == nil) {
443 if (not warned) {
444 warned = true;
9606e7b9
DS
445 printf("warning: old style symbol information ");
446 printf("found in \"%s\"\n", curfilename());
2c3a9a86
ML
447 }
448 } else {
449 entersym(name, np);
450 }
451 break;
452
453 case N_PC:
2fd0f574 454 case N_MOD2:
2c3a9a86
ML
455 break;
456
438b5736 457 default:
7005bb75 458 printf("warning: stab entry unrecognized: ");
2c3a9a86 459 if (name != nil) {
7005bb75 460 printf("name %s,", name);
2c3a9a86 461 }
7005bb75 462 printf("ntype %2x, desc %x, value %x'\n",
2c3a9a86
ML
463 np->n_type, np->n_desc, np->n_value);
464 break;
465 }
466}
467
2fd0f574 468/*
0022c355
ML
469 * Try to find the symbol that is referred to by the given name. Since it's
470 * an external, we need to follow a level or two of indirection.
2fd0f574
SL
471 */
472
0022c355 473private Symbol findsym (n, var_isextref)
2fd0f574 474Name n;
0022c355 475boolean *var_isextref;
2fd0f574
SL
476{
477 register Symbol r, s;
478
0022c355 479 *var_isextref = false;
2fd0f574 480 find(s, n) where
0022c355
ML
481 (
482 s->level == program->level and (
483 s->class == EXTREF or s->class == VAR or
484 s->class == PROC or s->class == FUNC
485 )
486 ) or (
487 s->block == program and s->class == MODULE
488 )
2fd0f574 489 endfind(s);
0022c355
ML
490 if (s == nil) {
491 r = nil;
492 } else if (s->class == EXTREF) {
493 *var_isextref = true;
2fd0f574
SL
494 r = s->symvalue.extref;
495 delete(s);
0022c355
ML
496
497 /*
498 * Now check for another level of indirection that could come from
499 * a forward reference in procedure nesting information. In this case
500 * the symbol has already been deleted.
501 */
502 if (r != nil and r->class == EXTREF) {
503 r = r->symvalue.extref;
504 }
505/*
506 } else if (s->class == MODULE) {
507 s->class = FUNC;
508 s->level = program->level;
509 r = s;
510 */
2fd0f574
SL
511 } else {
512 r = s;
513 }
514 return r;
515}
516
0022c355
ML
517/*
518 * Create a symbol for a text symbol with no source information.
519 * We treat it as an assembly language function.
520 */
521
522private Symbol deffunc (n)
523Name n;
524{
525 Symbol f;
526
527 f = insert(n);
528 f->language = findlanguage(".s");
529 f->class = FUNC;
530 f->type = t_int;
531 f->block = curblock;
532 f->level = program->level;
533 f->symvalue.funcv.src = false;
534 f->symvalue.funcv.inline = false;
9606e7b9
DS
535 if (f->chain != nil) {
536 panic("chain not nil in deffunc");
537 }
0022c355
ML
538 return f;
539}
540
541/*
542 * Create a symbol for a data or bss symbol with no source information.
543 * We treat it as an assembly language variable.
544 */
545
546private Symbol defvar (n)
547Name n;
548{
549 Symbol v;
550
551 v = insert(n);
552 v->language = findlanguage(".s");
9606e7b9 553 v->storage = EXT;
0022c355
ML
554 v->class = VAR;
555 v->type = t_int;
556 v->level = program->level;
557 v->block = curblock;
558 return v;
559}
560
561/*
562 * Update a symbol entry with a text address.
563 */
564
565private updateTextSym (s, name, addr)
566Symbol s;
567char *name;
568Address addr;
569{
570 if (s->class == VAR) {
571 s->symvalue.offset = addr;
572 } else {
573 s->symvalue.funcv.beginaddr = addr;
574 if (name[0] == '_') {
575 newfunc(s, codeloc(s));
576 findbeginning(s);
577 }
578 }
579}
580
9606e7b9
DS
581/*
582 * Avoid seeing Pascal labels as text symbols.
583 */
584
585private boolean PascalLabel (n)
586Name n;
587{
588 boolean b;
589 register char *p;
590
591 b = false;
592 if (curlang == findlanguage(".p")) {
593 p = ident(n);
594 while (*p != '\0') {
595 if (*p == '_' and *(p+1) == '$') {
596 b = true;
597 break;
598 }
599 ++p;
600 }
601 }
602 return b;
603}
604
2c3a9a86
ML
605/*
606 * Check to see if a global _name is already in the symbol table,
607 * if not then insert it.
608 */
609
2fd0f574 610private check_global (name, np)
2c3a9a86
ML
611String name;
612register struct nlist *np;
613{
614 register Name n;
d5eceaed 615 register Symbol t, u;
0022c355
ML
616 char buf[4096];
617 boolean isextref;
618 integer count;
2c3a9a86 619
0022c355
ML
620 if (not streq(name, "_end")) {
621 if (name[0] == '_') {
622 n = identname(&name[1], true);
623 } else {
624 n = identname(name, true);
625 if (lookup(n) != nil) {
626 sprintf(buf, "$%s", name);
627 n = identname(buf, false);
628 }
629 }
2c3a9a86 630 if ((np->n_type&N_TYPE) == N_TEXT) {
0022c355
ML
631 count = 0;
632 t = findsym(n, &isextref);
633 while (isextref) {
634 ++count;
635 updateTextSym(t, name, np->n_value);
636 t = findsym(n, &isextref);
2c3a9a86 637 }
0022c355
ML
638 if (count == 0) {
639 if (t == nil) {
9606e7b9
DS
640 if (not PascalLabel(n)) {
641 t = deffunc(n);
642 updateTextSym(t, name, np->n_value);
643 if (tracesyms) {
644 printdecl(t);
645 }
0022c355
ML
646 }
647 } else {
648 if (t->class == MODULE) {
649 u = t;
650 t = deffunc(n);
651 t->block = u;
652 if (tracesyms) {
653 printdecl(t);
654 }
655 }
656 updateTextSym(t, name, np->n_value);
657 }
2fd0f574 658 }
9606e7b9 659 } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) {
2c3a9a86 660 find(t, n) where
214731a7 661 t->class == COMMON
2c3a9a86 662 endfind(t);
214731a7
ML
663 if (t != nil) {
664 u = (Symbol) t->symvalue.common.offset;
665 while (u != nil) {
666 u->symvalue.offset = u->symvalue.common.offset+np->n_value;
667 u = u->symvalue.common.chain;
668 }
669 } else {
670 check_var(np, n);
2c3a9a86 671 }
214731a7
ML
672 } else {
673 check_var(np, n);
2c3a9a86
ML
674 }
675 }
676}
677
214731a7
ML
678/*
679 * Check to see if a namelist entry refers to a variable.
680 * If not, create a variable for the entry. In any case,
681 * set the offset of the variable according to the value field
682 * in the entry.
0022c355
ML
683 *
684 * If the external name has been referred to by several other symbols,
685 * we must update each of them.
214731a7
ML
686 */
687
2fd0f574 688private check_var (np, n)
214731a7
ML
689struct nlist *np;
690register Name n;
691{
0022c355
ML
692 register Symbol t, u, next;
693 Symbol conflict;
214731a7 694
0022c355 695 t = lookup(n);
214731a7 696 if (t == nil) {
0022c355
ML
697 t = defvar(n);
698 t->symvalue.offset = np->n_value;
699 if (tracesyms) {
700 printdecl(t);
701 }
702 } else {
703 conflict = nil;
704 do {
705 next = t->next_sym;
706 if (t->name == n) {
707 if (t->class == MODULE and t->block == program) {
708 conflict = t;
709 } else if (t->class == EXTREF and t->level == program->level) {
710 u = t->symvalue.extref;
711 while (u != nil and u->class == EXTREF) {
712 u = u->symvalue.extref;
713 }
714 u->symvalue.offset = np->n_value;
715 delete(t);
716 } else if (t->level == program->level and
717 (t->class == VAR or t->class == PROC or t->class == FUNC)
718 ) {
719 conflict = nil;
720 t->symvalue.offset = np->n_value;
721 }
722 }
723 t = next;
724 } while (t != nil);
725 if (conflict != nil) {
726 u = defvar(n);
727 u->block = conflict;
728 u->symvalue.offset = np->n_value;
729 }
214731a7 730 }
214731a7
ML
731}
732
2c3a9a86
ML
733/*
734 * Check to see if a local _name is known in the current scope.
735 * If not then enter it.
736 */
737
2fd0f574 738private check_local (name, np)
2c3a9a86
ML
739String name;
740register struct nlist *np;
741{
742 register Name n;
743 register Symbol t, cur;
744
745 n = identname(name, true);
746 cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
747 find(t, n) where t->block == cur endfind(t);
748 if (t == nil) {
749 t = insert(n);
750 t->language = findlanguage(".s");
751 t->type = t_int;
752 t->block = cur;
9606e7b9 753 t->storage = EXT;
2c3a9a86
ML
754 t->level = cur->level;
755 if ((np->n_type&N_TYPE) == N_TEXT) {
756 t->class = FUNC;
cc4262e8 757 t->symvalue.funcv.src = false;
7005bb75 758 t->symvalue.funcv.inline = false;
2c3a9a86 759 t->symvalue.funcv.beginaddr = np->n_value;
7005bb75 760 newfunc(t, codeloc(t));
2c3a9a86
ML
761 findbeginning(t);
762 } else {
763 t->class = VAR;
764 t->symvalue.offset = np->n_value;
765 }
766 }
767}
768
769/*
770 * Check to see if a symbol corresponds to a object file name.
771 * For some reason these are listed as in the text segment.
772 */
773
2fd0f574 774private check_filename (name)
2c3a9a86
ML
775String name;
776{
777 register String mname;
2fd0f574 778 register integer i;
0022c355
ML
779 Name n;
780 Symbol s;
2c3a9a86
ML
781
782 mname = strdup(name);
783 i = strlen(mname) - 2;
784 if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
785 mname[i] = '\0';
786 --i;
787 while (mname[i] != '/' and i >= 0) {
788 --i;
789 }
0022c355
ML
790 n = identname(&mname[i+1], true);
791 find(s, n) where s->block == program and s->class == MODULE endfind(s);
792 if (s == nil) {
793 s = insert(n);
794 s->language = findlanguage(".s");
795 s->class = MODULE;
796 s->symvalue.funcv.beginaddr = 0;
797 findbeginning(s);
798 }
2c3a9a86
ML
799 if (curblock->class != PROG) {
800 exitblock();
801 if (curblock->class != PROG) {
802 exitblock();
803 }
804 }
805 enterblock(s);
806 curmodule = s;
807 }
808}
809
7005bb75
ML
810/*
811 * Check to see if a symbol is about to be defined within an unnamed block.
812 * If this happens, we create a procedure for the unnamed block, make it
813 * "inline" so that tracebacks don't associate an activation record with it,
814 * and enter it into the function table so that it will be detected
815 * by "whatblock".
816 */
817
2fd0f574 818public chkUnnamedBlock ()
7005bb75
ML
819{
820 register Symbol s;
821 static int bnum = 0;
822 char buf[100];
2fd0f574 823 Address startaddr;
7005bb75 824
2fd0f574
SL
825 if (nesting > 0 and addrstk[nesting] != NOADDR) {
826 startaddr = (linep - 1)->addr;
827 ++bnum;
828 sprintf(buf, "$b%d", bnum);
829 s = insert(identname(buf, false));
830 s->language = curlang;
831 s->class = PROC;
832 s->symvalue.funcv.src = false;
833 s->symvalue.funcv.inline = true;
834 s->symvalue.funcv.beginaddr = startaddr;
835 enterblock(s);
836 newfunc(s, startaddr);
837 addrstk[nesting] = NOADDR;
838 }
7005bb75
ML
839}
840
841/*
842 * Compilation unit. C associates scope with filenames
843 * so we treat them as "modules". The filename without
844 * the suffix is used for the module name.
845 *
846 * Because there is no explicit "end-of-block" mark in
847 * the object file, we must exit blocks for the current
848 * procedure and module.
849 */
850
2fd0f574 851private enterSourceModule (n, addr)
7005bb75
ML
852Name n;
853Address addr;
854{
855 register Symbol s;
856 Name nn;
857 String mname, suffix;
858
859 mname = strdup(ident(n));
860 if (rindex(mname, '/') != nil) {
861 mname = rindex(mname, '/') + 1;
862 }
863 suffix = rindex(mname, '.');
9606e7b9
DS
864 if (suffix > mname && *(suffix-1) == '.') {
865 /* special hack for C++ */
866 --suffix;
867 }
7005bb75
ML
868 curlang = findlanguage(suffix);
869 if (curlang == findlanguage(".f")) {
870 strip_ = true;
871 }
872 if (suffix != nil) {
873 *suffix = '\0';
874 }
2fd0f574 875 if (not (*language_op(curlang, L_HASMODULES))()) {
7005bb75
ML
876 if (curblock->class != PROG) {
877 exitblock();
2fd0f574 878 if (curblock->class != PROG) {
2c3a9a86
ML
879 exitblock();
880 }
2c3a9a86 881 }
2fd0f574
SL
882 nn = identname(mname, true);
883 if (curmodule == nil or curmodule->name != nn) {
884 s = insert(nn);
885 s->class = MODULE;
886 s->symvalue.funcv.beginaddr = 0;
887 findbeginning(s);
2c3a9a86 888 } else {
2fd0f574 889 s = curmodule;
2c3a9a86 890 }
2fd0f574
SL
891 s->language = curlang;
892 enterblock(s);
893 curmodule = s;
2c3a9a86 894 }
2fd0f574
SL
895 if (program->language == nil) {
896 program->language = curlang;
2c3a9a86 897 }
2fd0f574
SL
898 warned = false;
899 enterfile(ident(n), addr);
900 initTypeTable();
2c3a9a86
ML
901}
902
903/*
904 * Allocate file and line tables and initialize indices.
905 */
906
2fd0f574
SL
907private allocmaps (nf, nl)
908integer nf, nl;
2c3a9a86
ML
909{
910 if (filetab != nil) {
911 dispose(filetab);
912 }
913 if (linetab != nil) {
914 dispose(linetab);
915 }
916 filetab = newarr(Filetab, nf);
917 linetab = newarr(Linetab, nl);
918 filep = filetab;
919 linep = linetab;
920}
921
922/*
923 * Add a file to the file table.
214731a7
ML
924 *
925 * If the new address is the same as the previous file address
926 * this routine used to not enter the file, but this caused some
927 * problems so it has been removed. It's not clear that this in
928 * turn may not also cause a problem.
2c3a9a86
ML
929 */
930
2fd0f574 931private enterfile (filename, addr)
2c3a9a86
ML
932String filename;
933Address addr;
934{
214731a7
ML
935 filep->addr = addr;
936 filep->filename = filename;
937 filep->lineindex = linep - linetab;
938 ++filep;
2c3a9a86
ML
939}
940
941/*
942 * Since we only estimated the number of lines (and it was a poor
943 * estimation) and since we need to know the exact number of lines
944 * to do a binary search, we set it when we're done.
945 */
946
2fd0f574 947private setnlines ()
2c3a9a86
ML
948{
949 nlhdr.nlines = linep - linetab;
950}
951
952/*
953 * Similarly for nfiles ...
954 */
955
2fd0f574 956private setnfiles ()
2c3a9a86
ML
957{
958 nlhdr.nfiles = filep - filetab;
959 setsource(filetab[0].filename);
960}