xref: /csrg-svn/old/dbx/object.c (revision 14443)
19673Slinton /* Copyright (c) 1982 Regents of the University of California */
29673Slinton 
3*14443Slinton static char sccsid[] = "@(#)object.c 1.11 08/10/83";
49673Slinton 
59673Slinton /*
69673Slinton  * Object code interface, mainly for extraction of symbolic information.
79673Slinton  */
89673Slinton 
99673Slinton #include "defs.h"
109673Slinton #include "object.h"
119673Slinton #include "main.h"
129673Slinton #include "symbols.h"
139673Slinton #include "names.h"
149673Slinton #include "languages.h"
159673Slinton #include "mappings.h"
169673Slinton #include "lists.h"
179673Slinton #include <a.out.h>
189673Slinton #include <stab.h>
199673Slinton #include <ctype.h>
209673Slinton 
219673Slinton #ifndef public
229673Slinton 
239673Slinton struct {
249673Slinton     unsigned int stringsize;	/* size of the dumped string table */
259673Slinton     unsigned int nsyms;		/* number of symbols */
269673Slinton     unsigned int nfiles;	/* number of files */
279673Slinton     unsigned int nlines;	/* number of lines */
289673Slinton } nlhdr;
299673Slinton 
309673Slinton #endif
319673Slinton 
329673Slinton public String objname = "a.out";
339673Slinton public Integer objsize;
349673Slinton public char *stringtab;
359673Slinton 
369673Slinton private String progname = nil;
379673Slinton private Language curlang;
389673Slinton private Symbol curmodule;
399673Slinton private Symbol curparam;
409673Slinton private Boolean warned;
4112542Scsvaf private Symbol curcomm;
4212542Scsvaf private Symbol commchain;
4312542Scsvaf private Boolean strip_ = false;
449673Slinton 
459673Slinton private Filetab *filep;
4611875Slinton private Linetab *linep, *prevlinep;
479673Slinton 
489673Slinton #define curfilename() (filep-1)->filename
499673Slinton 
509673Slinton /*
519673Slinton  * Blocks are figured out on the fly while reading the symbol table.
529673Slinton  */
539673Slinton 
549673Slinton #define MAXBLKDEPTH 25
559673Slinton 
569673Slinton private Symbol curblock;
579673Slinton private Symbol blkstack[MAXBLKDEPTH];
589673Slinton private Integer curlevel;
59*14443Slinton private Integer bnum, nesting;
60*14443Slinton private Address addrstk[MAXBLKDEPTH];
619673Slinton 
629673Slinton #define enterblock(b) { \
639673Slinton     blkstack[curlevel] = curblock; \
649673Slinton     ++curlevel; \
659673Slinton     b->level = curlevel; \
669673Slinton     b->block = curblock; \
679673Slinton     curblock = b; \
689673Slinton }
699673Slinton 
709673Slinton #define exitblock() { \
7111875Slinton     if (curblock->class == FUNC or curblock->class == PROC) { \
7211875Slinton 	if (prevlinep != linep) { \
7311875Slinton 	    curblock->symvalue.funcv.src = true; \
7411875Slinton 	} \
7511875Slinton     } \
769673Slinton     --curlevel; \
779673Slinton     curblock = blkstack[curlevel]; \
789673Slinton }
799673Slinton 
809673Slinton /*
819673Slinton  * Enter a source line or file name reference into the appropriate table.
829673Slinton  * Expanded inline to reduce procedure calls.
839673Slinton  *
849673Slinton  * private enterline(linenumber, address)
859673Slinton  * Lineno linenumber;
869673Slinton  * Address address;
879673Slinton  *  ...
889673Slinton  */
899673Slinton 
909673Slinton #define enterline(linenumber, address) \
919673Slinton { \
929673Slinton     register Linetab *lp; \
939673Slinton  \
949673Slinton     lp = linep - 1; \
959673Slinton     if (linenumber != lp->line) { \
969673Slinton 	if (address != lp->addr) { \
979673Slinton 	    ++lp; \
989673Slinton 	} \
999673Slinton 	lp->line = linenumber; \
1009673Slinton 	lp->addr = address; \
1019673Slinton 	linep = lp + 1; \
1029673Slinton     } \
1039673Slinton }
1049673Slinton 
1059673Slinton #define NTYPES 1000
1069673Slinton 
1079673Slinton private Symbol typetable[NTYPES];
1089673Slinton 
1099673Slinton /*
1109673Slinton  * Read in the namelist from the obj file.
1119673Slinton  *
1129673Slinton  * Reads and seeks are used instead of fread's and fseek's
1139673Slinton  * for efficiency sake; there's a lot of data being read here.
1149673Slinton  */
1159673Slinton 
1169673Slinton public readobj(file)
1179673Slinton String file;
1189673Slinton {
1199673Slinton     Fileid f;
1209673Slinton     struct exec hdr;
1219673Slinton     struct nlist nlist;
1229673Slinton 
1239673Slinton     f = open(file, 0);
1249673Slinton     if (f < 0) {
1259673Slinton 	fatal("can't open %s", file);
1269673Slinton     }
1279673Slinton     read(f, &hdr, sizeof(hdr));
1289673Slinton     objsize = hdr.a_text;
1299673Slinton     nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
1309673Slinton     nlhdr.nfiles = nlhdr.nsyms;
1319673Slinton     nlhdr.nlines = nlhdr.nsyms;
132*14443Slinton     if (nlhdr.nsyms > 0) {
133*14443Slinton 	lseek(f, (long) N_STROFF(hdr), 0);
134*14443Slinton 	read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
135*14443Slinton 	nlhdr.stringsize -= 4;
136*14443Slinton 	stringtab = newarr(char, nlhdr.stringsize);
137*14443Slinton 	read(f, stringtab, nlhdr.stringsize);
138*14443Slinton 	allocmaps(nlhdr.nfiles, nlhdr.nlines);
139*14443Slinton 	lseek(f, (long) N_SYMOFF(hdr), 0);
140*14443Slinton 	readsyms(f);
141*14443Slinton 	ordfunctab();
142*14443Slinton 	setnlines();
143*14443Slinton 	setnfiles();
144*14443Slinton     }
1459673Slinton     close(f);
1469673Slinton }
1479673Slinton 
1489673Slinton /*
1499673Slinton  * Read in symbols from object file.
1509673Slinton  */
1519673Slinton 
1529673Slinton private readsyms(f)
1539673Slinton Fileid f;
1549673Slinton {
1559673Slinton     struct nlist *namelist;
1569673Slinton     register struct nlist *np, *ub;
1579673Slinton     register int index;
1589673Slinton     register String name;
1599673Slinton     register Boolean afterlg;
1609673Slinton 
1619673Slinton     initsyms();
1629673Slinton     namelist = newarr(struct nlist, nlhdr.nsyms);
1639673Slinton     read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
1649673Slinton     afterlg = false;
1659673Slinton     ub = &namelist[nlhdr.nsyms];
1669673Slinton     for (np = &namelist[0]; np < ub; np++) {
1679673Slinton 	index = np->n_un.n_strx;
1689673Slinton 	if (index != 0) {
1699673Slinton 	    name = &stringtab[index - 4];
17012542Scsvaf 	    /*
17112542Scsvaf              *  if the program contains any .f files a trailing _ is stripped
17212542Scsvaf        	     *  from the name on the assumption it was added by the compiler.
17312542Scsvaf 	     *  This only affects names that follow the sdb N_SO entry with
17412542Scsvaf              *  the .f name.
17512542Scsvaf              */
176*14443Slinton             if (strip_ and name[0] != '\0' ) {
177*14443Slinton 		register char *p;
178*14443Slinton 
179*14443Slinton 		p = name;
180*14443Slinton 		while (*p != '\0') {
181*14443Slinton 		    ++p;
182*14443Slinton 		}
183*14443Slinton 		--p;
184*14443Slinton 		if (*p == '-') {
185*14443Slinton 		    *p = '\0';
186*14443Slinton 		}
18712542Scsvaf             }
18812542Scsvaf 
1899673Slinton 	} else {
1909673Slinton 	    name = nil;
19112542Scsvaf 	}
1929673Slinton 	/*
1939673Slinton 	 * assumptions:
1949673Slinton 	 *	not an N_STAB	==> name != nil
1959673Slinton 	 *	name[0] == '-'	==> name == "-lg"
1969673Slinton 	 *	name[0] != '_'	==> filename or invisible
1979673Slinton 	 *
1989673Slinton 	 * The "-lg" signals the beginning of global loader symbols.
19912542Scsvaf          *
2009673Slinton 	 */
2019673Slinton 	if ((np->n_type&N_STAB) != 0) {
2029673Slinton 	    enter_nl(name, np);
2039673Slinton 	} else if (name[0] == '-') {
2049673Slinton 	    afterlg = true;
2059673Slinton 	    if (curblock->class != PROG) {
2069673Slinton 		exitblock();
2079673Slinton 		if (curblock->class != PROG) {
2089673Slinton 		    exitblock();
2099673Slinton 		}
2109673Slinton 	    }
2119673Slinton 	    enterline(0, (linep-1)->addr + 1);
21211104Slinton 	} else if (afterlg) {
21311104Slinton 	    if (name[0] == '_') {
2149673Slinton 		check_global(&name[1], np);
2159673Slinton 	    }
21611104Slinton 	} else if (name[0] == '_') {
21711104Slinton 	    check_local(&name[1], np);
2189673Slinton 	} else if ((np->n_type&N_TEXT) == N_TEXT) {
2199673Slinton 	    check_filename(name);
2209673Slinton 	}
2219673Slinton     }
222*14443Slinton     if (not afterlg) {
223*14443Slinton 	panic("not linked for debugging, use \"cc -g ...\"");
224*14443Slinton     }
2259673Slinton     dispose(namelist);
2269673Slinton }
2279673Slinton 
2289673Slinton /*
2299673Slinton  * Initialize symbol information.
2309673Slinton  */
2319673Slinton 
2329673Slinton private initsyms()
2339673Slinton {
2349673Slinton     curblock = nil;
2359673Slinton     curlevel = 0;
236*14443Slinton     nesting = 0;
2379673Slinton     if (progname == nil) {
2389673Slinton 	progname = strdup(objname);
2399673Slinton 	if (rindex(progname, '/') != nil) {
2409673Slinton 	    progname = rindex(progname, '/') + 1;
2419673Slinton 	}
2429673Slinton 	if (index(progname, '.') != nil) {
2439673Slinton 	    *(index(progname, '.')) = '\0';
2449673Slinton 	}
2459673Slinton     }
2469673Slinton     program = insert(identname(progname, true));
2479673Slinton     program->class = PROG;
24811769Slinton     program->symvalue.funcv.beginaddr = 0;
249*14443Slinton     program->symvalue.funcv.inline = false;
250*14443Slinton     newfunc(program, codeloc(program));
25111769Slinton     findbeginning(program);
2529673Slinton     enterblock(program);
2539673Slinton     curmodule = program;
2549673Slinton     t_boolean = maketype("$boolean", 0L, 1L);
2559673Slinton     t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
2569673Slinton     t_char = maketype("$char", 0L, 127L);
25713838Slinton     t_real = maketype("$real", 8L, 0L);
2589673Slinton     t_nil = maketype("$nil", 0L, 0L);
2599673Slinton }
2609673Slinton 
2619673Slinton /*
2629673Slinton  * Free all the object file information that's being stored.
2639673Slinton  */
2649673Slinton 
2659673Slinton public objfree()
2669673Slinton {
2679673Slinton     symbol_free();
2689673Slinton     keywords_free();
2699673Slinton     names_free();
2709673Slinton     dispose(stringtab);
2719673Slinton     clrfunctab();
2729673Slinton }
2739673Slinton 
2749673Slinton /*
2759673Slinton  * Enter a namelist entry.
2769673Slinton  */
2779673Slinton 
2789673Slinton private enter_nl(name, np)
2799673Slinton String name;
2809673Slinton register struct nlist *np;
2819673Slinton {
2829673Slinton     register Symbol s;
28311875Slinton     register Name n, nn;
284*14443Slinton     char buf[100];
2859673Slinton 
2869673Slinton     s = nil;
2879673Slinton     if (name == nil) {
2889673Slinton 	n = nil;
2899673Slinton     } else {
2909673Slinton 	n = identname(name, true);
2919673Slinton     }
2929673Slinton     switch (np->n_type) {
293*14443Slinton 	/*
294*14443Slinton 	 * Build a symbol for the FORTRAN common area.  All GSYMS that follow
295*14443Slinton 	 * will be chained in a list with the head kept in common.offset, and
296*14443Slinton 	 * the tail in common.chain.
297*14443Slinton 	 */
29813938Slinton 	case N_BCOMM:
29913938Slinton  	    if (curcomm) {
30013938Slinton 		curcomm->symvalue.common.chain = commchain;
30112542Scsvaf 	    }
30212542Scsvaf 	    curcomm = lookup(n);
30313938Slinton 	    if (curcomm == nil) {
30413938Slinton 		curcomm = insert(n);
30513938Slinton 		curcomm->class = COMMON;
30613938Slinton 		curcomm->block = curblock;
30713938Slinton 		curcomm->level = program->level;
30813938Slinton 		curcomm->symvalue.common.chain = nil;
30912542Scsvaf 	    }
31012542Scsvaf 	    commchain = curcomm->symvalue.common.chain;
31113938Slinton 	    break;
31212542Scsvaf 
31312542Scsvaf 	case N_ECOMM:
31413938Slinton 	    if (curcomm) {
31513938Slinton 		curcomm->symvalue.common.chain = commchain;
31613938Slinton 		curcomm = nil;
31712542Scsvaf 	    }
31812542Scsvaf 	    break;
319*14443Slinton 
3209673Slinton 	case N_LBRAC:
321*14443Slinton 	    ++nesting;
322*14443Slinton 	    addrstk[nesting] = (linep - 1)->addr;
3239673Slinton 	    break;
3249673Slinton 
3259673Slinton 	case N_RBRAC:
326*14443Slinton 	    if (addrstk[nesting] == NOADDR) {
327*14443Slinton 		exitblock();
328*14443Slinton 		newfunc(curblock, (linep - 1)->addr);
329*14443Slinton 	    }
330*14443Slinton 	    --nesting;
3319673Slinton 	    break;
3329673Slinton 
3339673Slinton 	case N_SLINE:
3349673Slinton 	    enterline((Lineno) np->n_desc, (Address) np->n_value);
3359673Slinton 	    break;
3369673Slinton 
3379673Slinton 	/*
338*14443Slinton 	 * Source files.
3399673Slinton 	 */
3409673Slinton 	case N_SO:
341*14443Slinton 	    enterSourceModule(n, (Address) np->n_value);
3429673Slinton 	    break;
3439673Slinton 
3449673Slinton 	/*
3459673Slinton 	 * Textually included files.
3469673Slinton 	 */
3479673Slinton 	case N_SOL:
3489673Slinton 	    enterfile(name, (Address) np->n_value);
3499673Slinton 	    break;
3509673Slinton 
3519673Slinton 	/*
3529673Slinton 	 * These symbols are assumed to have non-nil names.
3539673Slinton 	 */
3549673Slinton 	case N_GSYM:
3559673Slinton 	case N_FUN:
3569673Slinton 	case N_STSYM:
3579673Slinton 	case N_LCSYM:
3589673Slinton 	case N_RSYM:
3599673Slinton 	case N_PSYM:
3609673Slinton 	case N_LSYM:
3619673Slinton 	case N_SSYM:
362*14443Slinton 	case N_LENG:
3639673Slinton 	    if (index(name, ':') == nil) {
3649673Slinton 		if (not warned) {
3659673Slinton 		    warned = true;
3669673Slinton 		    warning("old style symbol information found in \"%s\"",
3679673Slinton 			curfilename());
3689673Slinton 		}
3699673Slinton 	    } else {
3709673Slinton 		entersym(name, np);
3719673Slinton 	    }
3729673Slinton 	    break;
3739673Slinton 
3749673Slinton 	case N_PC:
3759673Slinton 	    break;
3769673Slinton 
37711558Slinton 	default:
378*14443Slinton 	    printf("warning:  stab entry unrecognized: ");
3799673Slinton 	    if (name != nil) {
380*14443Slinton 		printf("name %s,", name);
3819673Slinton 	    }
382*14443Slinton 	    printf("ntype %2x, desc %x, value %x'\n",
3839673Slinton 		np->n_type, np->n_desc, np->n_value);
3849673Slinton 	    break;
3859673Slinton     }
3869673Slinton }
3879673Slinton 
3889673Slinton /*
3899673Slinton  * Check to see if a global _name is already in the symbol table,
3909673Slinton  * if not then insert it.
3919673Slinton  */
3929673Slinton 
3939673Slinton private check_global(name, np)
3949673Slinton String name;
3959673Slinton register struct nlist *np;
3969673Slinton {
3979673Slinton     register Name n;
39812542Scsvaf     register Symbol t, u;
3999673Slinton 
4009673Slinton     if (not streq(name, "end")) {
4019673Slinton 	n = identname(name, true);
4029673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
4039673Slinton 	    find(t, n) where
404*14443Slinton 		t->level == program->level and
405*14443Slinton 		(t->class == PROC or t->class == FUNC)
4069673Slinton 	    endfind(t);
4079673Slinton 	    if (t == nil) {
4089673Slinton 		t = insert(n);
4099673Slinton 		t->language = findlanguage(".s");
4109673Slinton 		t->class = FUNC;
4119673Slinton 		t->type = t_int;
4129673Slinton 		t->block = curblock;
4139673Slinton 		t->level = program->level;
41411875Slinton 		t->symvalue.funcv.src = false;
415*14443Slinton 		t->symvalue.funcv.inline = false;
4169673Slinton 	    }
4179673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
418*14443Slinton 	    newfunc(t, codeloc(t));
4199673Slinton 	    findbeginning(t);
42013938Slinton 	} else if ((np->n_type&N_TYPE) == N_BSS) {
4219673Slinton 	    find(t, n) where
42213938Slinton 		t->class == COMMON
42312542Scsvaf 	    endfind(t);
42413938Slinton 	    if (t != nil) {
42513938Slinton 		u = (Symbol) t->symvalue.common.offset;
42613938Slinton 		while (u != nil) {
42713938Slinton 		    u->symvalue.offset = u->symvalue.common.offset+np->n_value;
42813938Slinton 		    u = u->symvalue.common.chain;
42913938Slinton 		}
43013938Slinton             } else {
43113938Slinton 		check_var(np, n);
4329673Slinton 	    }
43313938Slinton         } else {
43413938Slinton 	    check_var(np, n);
4359673Slinton 	}
4369673Slinton     }
4379673Slinton }
4389673Slinton 
4399673Slinton /*
44013938Slinton  * Check to see if a namelist entry refers to a variable.
44113938Slinton  * If not, create a variable for the entry.  In any case,
44213938Slinton  * set the offset of the variable according to the value field
44313938Slinton  * in the entry.
44413938Slinton  */
44513938Slinton 
44613938Slinton private check_var(np, n)
44713938Slinton struct nlist *np;
44813938Slinton register Name n;
44913938Slinton {
45013938Slinton     register Symbol t;
45113938Slinton 
45213938Slinton     find(t, n) where
45313938Slinton 	t->class == VAR and t->level == program->level
45413938Slinton     endfind(t);
45513938Slinton     if (t == nil) {
45613938Slinton 	t = insert(n);
45713938Slinton 	t->language = findlanguage(".s");
45813938Slinton 	t->class = VAR;
45913938Slinton 	t->type = t_int;
46013938Slinton 	t->level = program->level;
46113938Slinton     }
46213938Slinton     t->block = curblock;
46313938Slinton     t->symvalue.offset = np->n_value;
46413938Slinton }
46513938Slinton 
46613938Slinton /*
4679673Slinton  * Check to see if a local _name is known in the current scope.
4689673Slinton  * If not then enter it.
4699673Slinton  */
4709673Slinton 
4719673Slinton private check_local(name, np)
4729673Slinton String name;
4739673Slinton register struct nlist *np;
4749673Slinton {
4759673Slinton     register Name n;
4769673Slinton     register Symbol t, cur;
4779673Slinton 
4789673Slinton     n = identname(name, true);
4799673Slinton     cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
4809673Slinton     find(t, n) where t->block == cur endfind(t);
4819673Slinton     if (t == nil) {
4829673Slinton 	t = insert(n);
4839673Slinton 	t->language = findlanguage(".s");
4849673Slinton 	t->type = t_int;
4859673Slinton 	t->block = cur;
4869673Slinton 	t->level = cur->level;
4879673Slinton 	if ((np->n_type&N_TYPE) == N_TEXT) {
4889673Slinton 	    t->class = FUNC;
48911875Slinton 	    t->symvalue.funcv.src = false;
490*14443Slinton 	    t->symvalue.funcv.inline = false;
4919673Slinton 	    t->symvalue.funcv.beginaddr = np->n_value;
492*14443Slinton 	    newfunc(t, codeloc(t));
4939673Slinton 	    findbeginning(t);
4949673Slinton 	} else {
4959673Slinton 	    t->class = VAR;
4969673Slinton 	    t->symvalue.offset = np->n_value;
4979673Slinton 	}
4989673Slinton     }
4999673Slinton }
5009673Slinton 
5019673Slinton /*
5029673Slinton  * Check to see if a symbol corresponds to a object file name.
5039673Slinton  * For some reason these are listed as in the text segment.
5049673Slinton  */
5059673Slinton 
5069673Slinton private check_filename(name)
5079673Slinton String name;
5089673Slinton {
5099673Slinton     register String mname;
5109673Slinton     register Integer i;
5119673Slinton     register Symbol s;
5129673Slinton 
5139673Slinton     mname = strdup(name);
5149673Slinton     i = strlen(mname) - 2;
5159673Slinton     if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
5169673Slinton 	mname[i] = '\0';
5179673Slinton 	--i;
5189673Slinton 	while (mname[i] != '/' and i >= 0) {
5199673Slinton 	    --i;
5209673Slinton 	}
5219673Slinton 	s = insert(identname(&mname[i+1], true));
5229673Slinton 	s->language = findlanguage(".s");
5239673Slinton 	s->class = MODULE;
52411769Slinton 	s->symvalue.funcv.beginaddr = 0;
52511769Slinton 	findbeginning(s);
5269673Slinton 	if (curblock->class != PROG) {
5279673Slinton 	    exitblock();
5289673Slinton 	    if (curblock->class != PROG) {
5299673Slinton 		exitblock();
5309673Slinton 	    }
5319673Slinton 	}
5329673Slinton 	enterblock(s);
5339673Slinton 	curmodule = s;
5349673Slinton     }
5359673Slinton }
5369673Slinton 
5379673Slinton /*
538*14443Slinton  * Check to see if a symbol is about to be defined within an unnamed block.
539*14443Slinton  * If this happens, we create a procedure for the unnamed block, make it
540*14443Slinton  * "inline" so that tracebacks don't associate an activation record with it,
541*14443Slinton  * and enter it into the function table so that it will be detected
542*14443Slinton  * by "whatblock".
543*14443Slinton  */
544*14443Slinton 
545*14443Slinton private unnamed_block()
546*14443Slinton {
547*14443Slinton     register Symbol s;
548*14443Slinton     static int bnum = 0;
549*14443Slinton     char buf[100];
550*14443Slinton 
551*14443Slinton     ++bnum;
552*14443Slinton     sprintf(buf, "$b%d", bnum);
553*14443Slinton     s = insert(identname(buf, false));
554*14443Slinton     s->class = PROG;
555*14443Slinton     s->symvalue.funcv.src = false;
556*14443Slinton     s->symvalue.funcv.inline = true;
557*14443Slinton     s->symvalue.funcv.beginaddr = addrstk[nesting];
558*14443Slinton     enterblock(s);
559*14443Slinton     newfunc(s, addrstk[nesting]);
560*14443Slinton     addrstk[nesting] = NOADDR;
561*14443Slinton }
562*14443Slinton 
563*14443Slinton /*
564*14443Slinton  * Compilation unit.  C associates scope with filenames
565*14443Slinton  * so we treat them as "modules".  The filename without
566*14443Slinton  * the suffix is used for the module name.
567*14443Slinton  *
568*14443Slinton  * Because there is no explicit "end-of-block" mark in
569*14443Slinton  * the object file, we must exit blocks for the current
570*14443Slinton  * procedure and module.
571*14443Slinton  */
572*14443Slinton 
573*14443Slinton private enterSourceModule(n, addr)
574*14443Slinton Name n;
575*14443Slinton Address addr;
576*14443Slinton {
577*14443Slinton     register Symbol s;
578*14443Slinton     Name nn;
579*14443Slinton     String mname, suffix;
580*14443Slinton 
581*14443Slinton     mname = strdup(ident(n));
582*14443Slinton     if (rindex(mname, '/') != nil) {
583*14443Slinton 	mname = rindex(mname, '/') + 1;
584*14443Slinton     }
585*14443Slinton     suffix = rindex(mname, '.');
586*14443Slinton     curlang = findlanguage(suffix);
587*14443Slinton     if (curlang == findlanguage(".f")) {
588*14443Slinton 	strip_ = true;
589*14443Slinton     }
590*14443Slinton     if (suffix != nil) {
591*14443Slinton 	*suffix = '\0';
592*14443Slinton     }
593*14443Slinton     if (curblock->class != PROG) {
594*14443Slinton 	exitblock();
595*14443Slinton 	if (curblock->class != PROG) {
596*14443Slinton 	    exitblock();
597*14443Slinton 	}
598*14443Slinton     }
599*14443Slinton     nn = identname(mname, true);
600*14443Slinton     if (curmodule == nil or curmodule->name != nn) {
601*14443Slinton 	s = insert(nn);
602*14443Slinton 	s->class = MODULE;
603*14443Slinton 	s->symvalue.funcv.beginaddr = 0;
604*14443Slinton 	findbeginning(s);
605*14443Slinton     } else {
606*14443Slinton 	s = curmodule;
607*14443Slinton     }
608*14443Slinton     s->language = curlang;
609*14443Slinton     enterblock(s);
610*14443Slinton     curmodule = s;
611*14443Slinton     if (program->language == nil) {
612*14443Slinton 	program->language = curlang;
613*14443Slinton     }
614*14443Slinton     warned = false;
615*14443Slinton     enterfile(ident(n), addr);
616*14443Slinton     bzero(typetable, sizeof(typetable));
617*14443Slinton }
618*14443Slinton 
619*14443Slinton /*
6209673Slinton  * Put an nlist into the symbol table.
6219673Slinton  * If it's already there just add the associated information.
6229673Slinton  *
6239673Slinton  * Type information is encoded in the name following a ":".
6249673Slinton  */
6259673Slinton 
6269673Slinton private Symbol constype();
6279673Slinton private Char *curchar;
6289673Slinton 
6299673Slinton #define skipchar(ptr, ch) { \
6309673Slinton     if (*ptr != ch) { \
6319673Slinton 	panic("expected char '%c', found char '%c'", ch, *ptr); \
6329673Slinton     } \
6339673Slinton     ++ptr; \
6349673Slinton }
6359673Slinton 
6369673Slinton private entersym(str, np)
6379673Slinton String str;
6389673Slinton struct nlist *np;
6399673Slinton {
6409673Slinton     register Symbol s;
6419673Slinton     register char *p;
6429673Slinton     register int c;
6439673Slinton     register Name n;
6449673Slinton     register Integer i;
6459673Slinton     Boolean knowtype, isnew;
6469673Slinton     Symclass class;
6479673Slinton     Integer level;
6489673Slinton 
6499673Slinton     p = index(str, ':');
6509673Slinton     *p = '\0';
6519673Slinton     c = *(p+1);
6529673Slinton     n = identname(str, true);
6539673Slinton     if (index("FfGV", c) != nil) {
6549673Slinton 	if (c == 'F' or c == 'f') {
6559673Slinton 	    class = FUNC;
6569673Slinton 	} else {
6579673Slinton 	    class = VAR;
6589673Slinton 	}
6599673Slinton 	level = (c == 'f' ? curmodule->level : program->level);
6609673Slinton 	find(s, n) where s->level == level and s->class == class endfind(s);
6619673Slinton 	if (s == nil) {
6629673Slinton 	    isnew = true;
6639673Slinton 	    s = insert(n);
6649673Slinton 	} else {
6659673Slinton 	    isnew = false;
6669673Slinton 	}
6679673Slinton     } else {
6689673Slinton 	isnew = true;
6699673Slinton 	s = insert(n);
6709673Slinton     }
6719673Slinton 
672*14443Slinton     if (nesting > 0 and addrstk[nesting] != NOADDR) {
673*14443Slinton 	unnamed_block();
674*14443Slinton     }
675*14443Slinton 
6769673Slinton     /*
6779673Slinton      * Default attributes.
6789673Slinton      */
6799673Slinton     s->language = curlang;
6809673Slinton     s->class = VAR;
6819673Slinton     s->block = curblock;
6829673Slinton     s->level = curlevel;
6839673Slinton     s->symvalue.offset = np->n_value;
6849673Slinton     curchar = p + 2;
6859673Slinton     knowtype = false;
6869673Slinton     switch (c) {
6879673Slinton 	case 't':	/* type name */
6889673Slinton 	    s->class = TYPE;
6899673Slinton 	    i = getint();
6909673Slinton 	    if (i == 0) {
6919673Slinton 		panic("bad input on type \"%s\" at \"%s\"", symname(s),
6929673Slinton 		    curchar);
6939673Slinton 	    } else if (i >= NTYPES) {
6949673Slinton 		panic("too many types in file \"%s\"", curfilename());
6959673Slinton 	    }
6969673Slinton 	    /*
6979673Slinton 	     * A hack for C typedefs that don't create new types,
6989673Slinton 	     * e.g. typedef unsigned int Hashvalue;
69911558Slinton 	     *  or  typedef struct blah BLAH;
7009673Slinton 	     */
7019673Slinton 	    if (*curchar == '\0') {
7029673Slinton 		s->type = typetable[i];
7039673Slinton 		if (s->type == nil) {
70411558Slinton 		    s->type = symbol_alloc();
70511558Slinton 		    typetable[i] = s->type;
7069673Slinton 		}
7079673Slinton 		knowtype = true;
7089673Slinton 	    } else {
7099673Slinton 		typetable[i] = s;
7109673Slinton 		skipchar(curchar, '=');
7119673Slinton 	    }
7129673Slinton 	    break;
7139673Slinton 
7149673Slinton 	case 'T':	/* tag */
7159673Slinton 	    s->class = TAG;
7169673Slinton 	    i = getint();
7179673Slinton 	    if (i == 0) {
7189673Slinton 		panic("bad input on tag \"%s\" at \"%s\"", symname(s),
7199673Slinton 		    curchar);
7209673Slinton 	    } else if (i >= NTYPES) {
7219673Slinton 		panic("too many types in file \"%s\"", curfilename());
7229673Slinton 	    }
7239673Slinton 	    if (typetable[i] != nil) {
7249673Slinton 		typetable[i]->language = curlang;
7259673Slinton 		typetable[i]->class = TYPE;
7269673Slinton 		typetable[i]->type = s;
7279673Slinton 	    } else {
7289673Slinton 		typetable[i] = s;
7299673Slinton 	    }
7309673Slinton 	    skipchar(curchar, '=');
7319673Slinton 	    break;
7329673Slinton 
7339673Slinton 	case 'F':	/* public function */
7349673Slinton 	case 'f':	/* private function */
7359673Slinton 	    s->class = FUNC;
7369673Slinton 	    if (curblock->class == FUNC or curblock->class == PROC) {
7379673Slinton 		exitblock();
7389673Slinton 	    }
7399673Slinton 	    enterblock(s);
7409673Slinton 	    if (c == 'F') {
7419673Slinton 		s->level = program->level;
7429673Slinton 		isnew = false;
7439673Slinton 	    }
7449673Slinton 	    curparam = s;
7459673Slinton 	    if (isnew) {
74611875Slinton 		s->symvalue.funcv.src = false;
747*14443Slinton 		s->symvalue.funcv.inline = false;
7489673Slinton 		s->symvalue.funcv.beginaddr = np->n_value;
749*14443Slinton 		newfunc(s, codeloc(s));
7509673Slinton 		findbeginning(s);
7519673Slinton 	    }
7529673Slinton 	    break;
7539673Slinton 
7549673Slinton 	case 'G':	/* public variable */
7559673Slinton 	    s->level = program->level;
7569673Slinton 	    break;
7579673Slinton 
7589673Slinton 	case 'S':	/* private variable */
7599673Slinton 	    s->level = curmodule->level;
7609673Slinton 	    s->block = curmodule;
7619673Slinton 	    break;
7629673Slinton 
76312542Scsvaf /*
76412542Scsvaf  *  keep global BSS variables chained so can resolve when get the start
76512542Scsvaf  *  of common; keep the list in order so f77 can display all vars in a COMMON
76612542Scsvaf */
7679673Slinton 	case 'V':	/* own variable */
7689673Slinton 	    s->level = 2;
76912542Scsvaf 	    if (curcomm) {
77012542Scsvaf 	      if (commchain != nil) {
77112542Scsvaf  		  commchain->symvalue.common.chain = s;
77212542Scsvaf 	      }
77312542Scsvaf 	      else {
77412542Scsvaf 		  curcomm->symvalue.common.offset = (int) s;
77512542Scsvaf 	      }
77612542Scsvaf               commchain = s;
77712542Scsvaf               s->symvalue.common.offset = np->n_value;
77812542Scsvaf               s->symvalue.common.chain = nil;
77912542Scsvaf 	    }
7809673Slinton 	    break;
7819673Slinton 
7829673Slinton 	case 'r':	/* register variable */
7839673Slinton 	    s->level = -(s->level);
7849673Slinton 	    break;
7859673Slinton 
7869673Slinton 	case 'p':	/* parameter variable */
7879673Slinton 	    curparam->chain = s;
7889673Slinton 	    curparam = s;
7899673Slinton 	    break;
7909673Slinton 
7919673Slinton 	case 'v':	/* varies parameter */
7929673Slinton 	    s->class = REF;
7939673Slinton 	    s->symvalue.offset = np->n_value;
7949673Slinton 	    curparam->chain = s;
7959673Slinton 	    curparam = s;
7969673Slinton 	    break;
7979673Slinton 
7989673Slinton 	default:	/* local variable */
7999673Slinton 	    --curchar;
8009673Slinton 	    break;
8019673Slinton     }
8029673Slinton     if (not knowtype) {
8039673Slinton 	s->type = constype(nil);
8049673Slinton 	if (s->class == TAG) {
8059673Slinton 	    addtag(s);
8069673Slinton 	}
8079673Slinton     }
8089673Slinton     if (tracesyms) {
8099673Slinton 	printdecl(s);
8109673Slinton 	fflush(stdout);
8119673Slinton     }
8129673Slinton }
8139673Slinton 
8149673Slinton /*
8159673Slinton  * Construct a type out of a string encoding.
8169673Slinton  *
8179673Slinton  * The forms of the string are
8189673Slinton  *
8199673Slinton  *	<number>
8209673Slinton  *	<number>=<type>
8219673Slinton  *	r<type>;<number>;<number>		$ subrange
8229673Slinton  *	a<type>;<type>				$ array[index] of element
8239673Slinton  *	s{<name>:<type>;<number>;<number>}	$ record
8249673Slinton  *	*<type>					$ pointer
8259673Slinton  */
8269673Slinton 
8279673Slinton private Symbol constype(type)
8289673Slinton Symbol type;
8299673Slinton {
8309673Slinton     register Symbol t, u;
8319673Slinton     register Char *p, *cur;
8329673Slinton     register Integer n;
8339673Slinton     Integer b;
8349673Slinton     Name name;
8359673Slinton     Char class;
8369673Slinton 
8379673Slinton     b = curlevel;
8389673Slinton     if (isdigit(*curchar)) {
8399673Slinton 	n = getint();
8409673Slinton 	if (n == 0) {
8419673Slinton 	    panic("bad type number at \"%s\"", curchar);
8429673Slinton 	} else if (n >= NTYPES) {
8439673Slinton 	    panic("too many types in file \"%s\"", curfilename());
8449673Slinton 	}
8459673Slinton 	if (*curchar == '=') {
8469673Slinton 	    if (typetable[n] != nil) {
8479673Slinton 		t = typetable[n];
8489673Slinton 	    } else {
8499673Slinton 		t = symbol_alloc();
8509673Slinton 		typetable[n] = t;
8519673Slinton 	    }
8529673Slinton 	    ++curchar;
8539673Slinton 	    constype(t);
8549673Slinton 	} else {
8559673Slinton 	    t = typetable[n];
8569673Slinton 	    if (t == nil) {
8579673Slinton 		t = symbol_alloc();
8589673Slinton 		typetable[n] = t;
8599673Slinton 	    }
8609673Slinton 	}
8619673Slinton     } else {
8629673Slinton 	if (type == nil) {
8639673Slinton 	    t = symbol_alloc();
8649673Slinton 	} else {
8659673Slinton 	    t = type;
8669673Slinton 	}
8679673Slinton 	t->language = curlang;
8689673Slinton 	t->level = b;
86912542Scsvaf 	t->block = curblock;
8709673Slinton 	class = *curchar++;
8719673Slinton 	switch (class) {
87212542Scsvaf 
8739673Slinton 	    case 'r':
8749673Slinton 		t->class = RANGE;
8759673Slinton 		t->type = constype(nil);
8769673Slinton 		skipchar(curchar, ';');
87712542Scsvaf                 /* some letters indicate a dynamic bound, ie what follows
87812542Scsvaf                    is the offset from the fp which contains the bound; this will
87912542Scsvaf                    need a different encoding when pc a['A'..'Z'] is
88012542Scsvaf                    added; J is a special flag to handle fortran a(*) bounds
88112542Scsvaf                 */
88212542Scsvaf 		switch(*curchar) {
88312542Scsvaf 			case 'A':
88412542Scsvaf 				t->symvalue.rangev.lowertype = R_ARG;
88512542Scsvaf                   		curchar++;
88612542Scsvaf 			        break;
88712542Scsvaf 
88812542Scsvaf 			case 'T':
88912542Scsvaf 				t->symvalue.rangev.lowertype = R_TEMP;
89012542Scsvaf                   		curchar++;
89112542Scsvaf 			        break;
89212542Scsvaf 
89312542Scsvaf 			case 'J':
89412542Scsvaf 				t->symvalue.rangev.lowertype = R_ADJUST;
89512542Scsvaf                   		curchar++;
89612542Scsvaf 			  	break;
89712542Scsvaf 
89812542Scsvaf 			default:
89912542Scsvaf 				 t->symvalue.rangev.lowertype = R_CONST;
90012542Scsvaf 			  	 break;
90112542Scsvaf 
90212542Scsvaf 		}
90312542Scsvaf 	        t->symvalue.rangev.lower = getint();
9049673Slinton 		skipchar(curchar, ';');
90512542Scsvaf 		switch(*curchar) {
90612542Scsvaf 			case 'A':
90712542Scsvaf 				t->symvalue.rangev.uppertype = R_ARG;
90812542Scsvaf                   		curchar++;
90912542Scsvaf 			        break;
91012542Scsvaf 
91112542Scsvaf 			case 'T':
91212542Scsvaf 				t->symvalue.rangev.uppertype = R_TEMP;
91312542Scsvaf                   		curchar++;
91412542Scsvaf 			        break;
91512542Scsvaf 
91612542Scsvaf 			case 'J':
91712542Scsvaf 				t->symvalue.rangev.uppertype = R_ADJUST;
91812542Scsvaf                   		curchar++;
91912542Scsvaf 			  	break;
92012542Scsvaf 
92112542Scsvaf 			default:
92212542Scsvaf 				 t->symvalue.rangev.uppertype = R_CONST;
92312542Scsvaf 			  	 break;
92412542Scsvaf 
92512542Scsvaf 		}
9269673Slinton 		t->symvalue.rangev.upper = getint();
9279673Slinton 		break;
9289673Slinton 
9299673Slinton 	    case 'a':
9309673Slinton 		t->class = ARRAY;
9319673Slinton 		t->chain = constype(nil);
9329673Slinton 		skipchar(curchar, ';');
9339673Slinton 		t->type = constype(nil);
9349673Slinton 		break;
9359673Slinton 
9369673Slinton 	    case 's':
9379673Slinton 	    case 'u':
9389673Slinton 		t->class = (class == 's') ? RECORD : VARNT;
9399673Slinton 		t->symvalue.offset = getint();
9409673Slinton 		u = t;
9419673Slinton 		cur = curchar;
9429673Slinton 		while (*cur != ';' and *cur != '\0') {
9439673Slinton 		    p = index(cur, ':');
9449673Slinton 		    if (p == nil) {
9459673Slinton 			panic("index(\"%s\", ':') failed", curchar);
9469673Slinton 		    }
9479673Slinton 		    *p = '\0';
9489673Slinton 		    name = identname(cur, true);
9499673Slinton 		    u->chain = newSymbol(name, b, FIELD, nil, nil);
9509673Slinton 		    cur = p + 1;
9519673Slinton 		    u = u->chain;
9529673Slinton 		    u->language = curlang;
9539673Slinton 		    curchar = cur;
9549673Slinton 		    u->type = constype(nil);
9559673Slinton 		    skipchar(curchar, ',');
9569673Slinton 		    u->symvalue.field.offset = getint();
9579673Slinton 		    skipchar(curchar, ',');
9589673Slinton 		    u->symvalue.field.length = getint();
9599673Slinton 		    skipchar(curchar, ';');
9609673Slinton 		    cur = curchar;
9619673Slinton 		}
9629673Slinton 		if (*cur == ';') {
9639673Slinton 		    ++cur;
9649673Slinton 		}
9659673Slinton 		curchar = cur;
9669673Slinton 		break;
9679673Slinton 
9689673Slinton 	    case 'e':
9699673Slinton 		t->class = SCAL;
9709673Slinton 		u = t;
9719673Slinton 		while (*curchar != ';' and *curchar != '\0') {
9729673Slinton 		    p = index(curchar, ':');
9739673Slinton 		    assert(p != nil);
9749673Slinton 		    *p = '\0';
9759673Slinton 		    u->chain = insert(identname(curchar, true));
9769673Slinton 		    curchar = p + 1;
9779673Slinton 		    u = u->chain;
9789673Slinton 		    u->language = curlang;
9799673Slinton 		    u->class = CONST;
9809673Slinton 		    u->level = b;
9819673Slinton 		    u->block = curblock;
9829673Slinton 		    u->type = t;
9839673Slinton 		    u->symvalue.iconval = getint();
9849673Slinton 		    skipchar(curchar, ',');
9859673Slinton 		}
9869673Slinton 		break;
9879673Slinton 
9889673Slinton 	    case '*':
9899673Slinton 		t->class = PTR;
9909673Slinton 		t->type = constype(nil);
9919673Slinton 		break;
9929673Slinton 
9939673Slinton 	    case 'f':
9949673Slinton 		t->class = FUNC;
9959673Slinton 		t->type = constype(nil);
9969673Slinton 		break;
9979673Slinton 
9989673Slinton 	    default:
9999673Slinton 		badcaseval(class);
10009673Slinton 	}
10019673Slinton     }
10029673Slinton     return t;
10039673Slinton }
10049673Slinton 
10059673Slinton /*
10069673Slinton  * Read an integer from the current position in the type string.
10079673Slinton  */
10089673Slinton 
10099673Slinton private Integer getint()
10109673Slinton {
10119673Slinton     register Integer n;
10129673Slinton     register char *p;
10139673Slinton     register Boolean isneg;
10149673Slinton 
10159673Slinton     n = 0;
10169673Slinton     p = curchar;
10179673Slinton     if (*p == '-') {
10189673Slinton 	isneg = true;
10199673Slinton 	++p;
10209673Slinton     } else {
10219673Slinton 	isneg = false;
10229673Slinton     }
10239673Slinton     while (isdigit(*p)) {
10249673Slinton 	n = 10*n + (*p - '0');
10259673Slinton 	++p;
10269673Slinton     }
10279673Slinton     curchar = p;
10289673Slinton     return isneg ? (-n) : n;
10299673Slinton }
10309673Slinton 
10319673Slinton /*
10329673Slinton  * Add a tag name.  This is a kludge to be able to refer
10339673Slinton  * to tags that have the same name as some other symbol
10349673Slinton  * in the same block.
10359673Slinton  */
10369673Slinton 
10379673Slinton private addtag(s)
10389673Slinton register Symbol s;
10399673Slinton {
10409673Slinton     register Symbol t;
10419673Slinton     char buf[100];
10429673Slinton 
10439673Slinton     sprintf(buf, "$$%.90s", ident(s->name));
10449673Slinton     t = insert(identname(buf, false));
10459673Slinton     t->language = s->language;
10469673Slinton     t->class = TAG;
10479673Slinton     t->type = s->type;
10489673Slinton     t->block = s->block;
10499673Slinton }
10509673Slinton 
10519673Slinton /*
10529673Slinton  * Allocate file and line tables and initialize indices.
10539673Slinton  */
10549673Slinton 
10559673Slinton private allocmaps(nf, nl)
10569673Slinton Integer nf, nl;
10579673Slinton {
10589673Slinton     if (filetab != nil) {
10599673Slinton 	dispose(filetab);
10609673Slinton     }
10619673Slinton     if (linetab != nil) {
10629673Slinton 	dispose(linetab);
10639673Slinton     }
10649673Slinton     filetab = newarr(Filetab, nf);
10659673Slinton     linetab = newarr(Linetab, nl);
10669673Slinton     filep = filetab;
10679673Slinton     linep = linetab;
10689673Slinton }
10699673Slinton 
10709673Slinton /*
10719673Slinton  * Add a file to the file table.
107213938Slinton  *
107313938Slinton  * If the new address is the same as the previous file address
107413938Slinton  * this routine used to not enter the file, but this caused some
107513938Slinton  * problems so it has been removed.  It's not clear that this in
107613938Slinton  * turn may not also cause a problem.
10779673Slinton  */
10789673Slinton 
10799673Slinton private enterfile(filename, addr)
10809673Slinton String filename;
10819673Slinton Address addr;
10829673Slinton {
108313938Slinton     filep->addr = addr;
108413938Slinton     filep->filename = filename;
108513938Slinton     filep->lineindex = linep - linetab;
108613938Slinton     ++filep;
10879673Slinton }
10889673Slinton 
10899673Slinton /*
10909673Slinton  * Since we only estimated the number of lines (and it was a poor
10919673Slinton  * estimation) and since we need to know the exact number of lines
10929673Slinton  * to do a binary search, we set it when we're done.
10939673Slinton  */
10949673Slinton 
10959673Slinton private setnlines()
10969673Slinton {
10979673Slinton     nlhdr.nlines = linep - linetab;
10989673Slinton }
10999673Slinton 
11009673Slinton /*
11019673Slinton  * Similarly for nfiles ...
11029673Slinton  */
11039673Slinton 
11049673Slinton private setnfiles()
11059673Slinton {
11069673Slinton     nlhdr.nfiles = filep - filetab;
11079673Slinton     setsource(filetab[0].filename);
11089673Slinton }
1109