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