|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)object.c 1.14 10/22/83";
4:
5: /*
6: * Object code interface, mainly for extraction of symbolic information.
7: */
8:
9: #include "defs.h"
10: #include "object.h"
11: #include "main.h"
12: #include "symbols.h"
13: #include "names.h"
14: #include "languages.h"
15: #include "mappings.h"
16: #include "lists.h"
17: #include <a.out.h>
18: #include <stab.h>
19: #include <ctype.h>
20:
21: #ifndef public
22:
23: struct {
24: unsigned int stringsize; /* size of the dumped string table */
25: unsigned int nsyms; /* number of symbols */
26: unsigned int nfiles; /* number of files */
27: unsigned int nlines; /* number of lines */
28: } nlhdr;
29:
30: #endif
31:
32: public String objname = "a.out";
33: public Integer objsize;
34: public char *stringtab;
35:
36: private String progname = nil;
37: private Language curlang;
38: private Symbol curmodule;
39: private Symbol curparam;
40: private Boolean warned;
41: private Symbol curcomm;
42: private Symbol commchain;
43: private Boolean strip_ = false;
44:
45: private Filetab *filep;
46: private Linetab *linep, *prevlinep;
47:
48: #define curfilename() (filep-1)->filename
49:
50: /*
51: * Blocks are figured out on the fly while reading the symbol table.
52: */
53:
54: #define MAXBLKDEPTH 25
55:
56: private Symbol curblock;
57: private Symbol blkstack[MAXBLKDEPTH];
58: private Integer curlevel;
59: private Integer bnum, nesting;
60: private Address addrstk[MAXBLKDEPTH];
61:
62: #define enterblock(b) { \
63: blkstack[curlevel] = curblock; \
64: ++curlevel; \
65: b->level = curlevel; \
66: b->block = curblock; \
67: curblock = b; \
68: }
69:
70: #define exitblock() { \
71: if (curblock->class == FUNC or curblock->class == PROC) { \
72: if (prevlinep != linep) { \
73: curblock->symvalue.funcv.src = true; \
74: } \
75: } \
76: --curlevel; \
77: curblock = blkstack[curlevel]; \
78: }
79:
80: /*
81: * Enter a source line or file name reference into the appropriate table.
82: * Expanded inline to reduce procedure calls.
83: *
84: * private enterline(linenumber, address)
85: * Lineno linenumber;
86: * Address address;
87: * ...
88: */
89:
90: #define enterline(linenumber, address) \
91: { \
92: register Linetab *lp; \
93: \
94: lp = linep - 1; \
95: if (linenumber != lp->line) { \
96: if (address != lp->addr) { \
97: ++lp; \
98: } \
99: lp->line = linenumber; \
100: lp->addr = address; \
101: linep = lp + 1; \
102: } \
103: }
104:
105: #define NTYPES 1000
106:
107: private Symbol typetable[NTYPES];
108:
109: /*
110: * Read in the namelist from the obj file.
111: *
112: * Reads and seeks are used instead of fread's and fseek's
113: * for efficiency sake; there's a lot of data being read here.
114: */
115:
116: public readobj(file)
117: String file;
118: {
119: Fileid f;
120: struct exec hdr;
121: struct nlist nlist;
122:
123: f = open(file, 0);
124: if (f < 0) {
125: fatal("can't open %s", file);
126: }
127: read(f, &hdr, sizeof(hdr));
128: objsize = hdr.a_text;
129: nlhdr.nsyms = hdr.a_syms / sizeof(nlist);
130: nlhdr.nfiles = nlhdr.nsyms;
131: nlhdr.nlines = nlhdr.nsyms;
132: if (nlhdr.nsyms > 0) {
133: lseek(f, (long) N_STROFF(hdr), 0);
134: read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize));
135: nlhdr.stringsize -= 4;
136: stringtab = newarr(char, nlhdr.stringsize);
137: read(f, stringtab, nlhdr.stringsize);
138: allocmaps(nlhdr.nfiles, nlhdr.nlines);
139: lseek(f, (long) N_SYMOFF(hdr), 0);
140: readsyms(f);
141: ordfunctab();
142: setnlines();
143: setnfiles();
144: }
145: close(f);
146: }
147:
148: /*
149: * Read in symbols from object file.
150: */
151:
152: private readsyms(f)
153: Fileid f;
154: {
155: struct nlist *namelist;
156: register struct nlist *np, *ub;
157: register int index;
158: register String name;
159: register Boolean afterlg;
160:
161: initsyms();
162: namelist = newarr(struct nlist, nlhdr.nsyms);
163: read(f, namelist, nlhdr.nsyms * sizeof(struct nlist));
164: afterlg = false;
165: ub = &namelist[nlhdr.nsyms];
166: for (np = &namelist[0]; np < ub; np++) {
167: index = np->n_un.n_strx;
168: if (index != 0) {
169: name = &stringtab[index - 4];
170: /*
171: * if the program contains any .f files a trailing _ is stripped
172: * from the name on the assumption it was added by the compiler.
173: * This only affects names that follow the sdb N_SO entry with
174: * the .f name.
175: */
176: if (strip_ and name[0] != '\0' ) {
177: register char *p;
178:
179: p = name;
180: while (*p != '\0') {
181: ++p;
182: }
183: --p;
184: if (*p == '_') {
185: *p = '\0';
186: }
187: }
188:
189: } else {
190: name = nil;
191: }
192: /*
193: * assumptions:
194: * not an N_STAB ==> name != nil
195: * name[0] == '-' ==> name == "-lg"
196: * name[0] != '_' ==> filename or invisible
197: *
198: * The "-lg" signals the beginning of global loader symbols.
199: *
200: */
201: if ((np->n_type&N_STAB) != 0) {
202: enter_nl(name, np);
203: } else if (name[0] == '-') {
204: afterlg = true;
205: if (curblock->class != PROG) {
206: exitblock();
207: if (curblock->class != PROG) {
208: exitblock();
209: }
210: }
211: enterline(0, (linep-1)->addr + 1);
212: } else if (afterlg) {
213: if (name[0] == '_') {
214: check_global(&name[1], np);
215: }
216: } else if (name[0] == '_') {
217: check_local(&name[1], np);
218: } else if ((np->n_type&N_TEXT) == N_TEXT) {
219: check_filename(name);
220: }
221: }
222: if (not afterlg) {
223: fatal("not linked for debugging, use \"cc -g ...\"");
224: }
225: dispose(namelist);
226: }
227:
228: /*
229: * Initialize symbol information.
230: */
231:
232: private initsyms()
233: {
234: curblock = nil;
235: curlevel = 0;
236: nesting = 0;
237: if (progname == nil) {
238: progname = strdup(objname);
239: if (rindex(progname, '/') != nil) {
240: progname = rindex(progname, '/') + 1;
241: }
242: if (index(progname, '.') != nil) {
243: *(index(progname, '.')) = '\0';
244: }
245: }
246: program = insert(identname(progname, true));
247: program->class = PROG;
248: program->symvalue.funcv.beginaddr = 0;
249: program->symvalue.funcv.inline = false;
250: newfunc(program, codeloc(program));
251: findbeginning(program);
252: enterblock(program);
253: curmodule = program;
254: }
255:
256: /*
257: * Free all the object file information that's being stored.
258: */
259:
260: public objfree()
261: {
262: symbol_free();
263: keywords_free();
264: names_free();
265: dispose(stringtab);
266: clrfunctab();
267: }
268:
269: /*
270: * Enter a namelist entry.
271: */
272:
273: private enter_nl(name, np)
274: String name;
275: register struct nlist *np;
276: {
277: register Symbol s;
278: register Name n, nn;
279: char buf[100];
280:
281: s = nil;
282: if (name == nil) {
283: n = nil;
284: } else {
285: n = identname(name, true);
286: }
287: switch (np->n_type) {
288: /*
289: * Build a symbol for the FORTRAN common area. All GSYMS that follow
290: * will be chained in a list with the head kept in common.offset, and
291: * the tail in common.chain.
292: */
293: case N_BCOMM:
294: if (curcomm) {
295: curcomm->symvalue.common.chain = commchain;
296: }
297: curcomm = lookup(n);
298: if (curcomm == nil) {
299: curcomm = insert(n);
300: curcomm->class = COMMON;
301: curcomm->block = curblock;
302: curcomm->level = program->level;
303: curcomm->symvalue.common.chain = nil;
304: }
305: commchain = curcomm->symvalue.common.chain;
306: break;
307:
308: case N_ECOMM:
309: if (curcomm) {
310: curcomm->symvalue.common.chain = commchain;
311: curcomm = nil;
312: }
313: break;
314:
315: case N_LBRAC:
316: ++nesting;
317: addrstk[nesting] = (linep - 1)->addr;
318: break;
319:
320: case N_RBRAC:
321: if (addrstk[nesting] == NOADDR) {
322: exitblock();
323: newfunc(curblock, (linep - 1)->addr);
324: }
325: --nesting;
326: break;
327:
328: case N_SLINE:
329: enterline((Lineno) np->n_desc, (Address) np->n_value);
330: break;
331:
332: /*
333: * Source files.
334: */
335: case N_SO:
336: enterSourceModule(n, (Address) np->n_value);
337: break;
338:
339: /*
340: * Textually included files.
341: */
342: case N_SOL:
343: enterfile(name, (Address) np->n_value);
344: break;
345:
346: /*
347: * These symbols are assumed to have non-nil names.
348: */
349: case N_GSYM:
350: case N_FUN:
351: case N_STSYM:
352: case N_LCSYM:
353: case N_RSYM:
354: case N_PSYM:
355: case N_LSYM:
356: case N_SSYM:
357: case N_LENG:
358: if (index(name, ':') == nil) {
359: if (not warned) {
360: warned = true;
361: warning("old style symbol information found in \"%s\"",
362: curfilename());
363: }
364: } else {
365: entersym(name, np);
366: }
367: break;
368:
369: case N_PC:
370: break;
371:
372: default:
373: printf("warning: stab entry unrecognized: ");
374: if (name != nil) {
375: printf("name %s,", name);
376: }
377: printf("ntype %2x, desc %x, value %x'\n",
378: np->n_type, np->n_desc, np->n_value);
379: break;
380: }
381: }
382:
383: /*
384: * Check to see if a global _name is already in the symbol table,
385: * if not then insert it.
386: */
387:
388: private check_global(name, np)
389: String name;
390: register struct nlist *np;
391: {
392: register Name n;
393: register Symbol t, u;
394:
395: if (not streq(name, "end")) {
396: n = identname(name, true);
397: if ((np->n_type&N_TYPE) == N_TEXT) {
398: find(t, n) where
399: t->level == program->level and
400: (t->class == PROC or t->class == FUNC)
401: endfind(t);
402: if (t == nil) {
403: t = insert(n);
404: t->language = findlanguage(".s");
405: t->class = FUNC;
406: t->type = t_int;
407: t->block = curblock;
408: t->level = program->level;
409: t->symvalue.funcv.src = false;
410: t->symvalue.funcv.inline = false;
411: }
412: t->symvalue.funcv.beginaddr = np->n_value;
413: newfunc(t, codeloc(t));
414: findbeginning(t);
415: } else if ((np->n_type&N_TYPE) == N_BSS) {
416: find(t, n) where
417: t->class == COMMON
418: endfind(t);
419: if (t != nil) {
420: u = (Symbol) t->symvalue.common.offset;
421: while (u != nil) {
422: u->symvalue.offset = u->symvalue.common.offset+np->n_value;
423: u = u->symvalue.common.chain;
424: }
425: } else {
426: check_var(np, n);
427: }
428: } else {
429: check_var(np, n);
430: }
431: }
432: }
433:
434: /*
435: * Check to see if a namelist entry refers to a variable.
436: * If not, create a variable for the entry. In any case,
437: * set the offset of the variable according to the value field
438: * in the entry.
439: */
440:
441: private check_var(np, n)
442: struct nlist *np;
443: register Name n;
444: {
445: register Symbol t;
446:
447: find(t, n) where
448: t->class == VAR and t->level == program->level
449: endfind(t);
450: if (t == nil) {
451: t = insert(n);
452: t->language = findlanguage(".s");
453: t->class = VAR;
454: t->type = t_int;
455: t->level = program->level;
456: }
457: t->block = curblock;
458: t->symvalue.offset = np->n_value;
459: }
460:
461: /*
462: * Check to see if a local _name is known in the current scope.
463: * If not then enter it.
464: */
465:
466: private check_local(name, np)
467: String name;
468: register struct nlist *np;
469: {
470: register Name n;
471: register Symbol t, cur;
472:
473: n = identname(name, true);
474: cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock;
475: find(t, n) where t->block == cur endfind(t);
476: if (t == nil) {
477: t = insert(n);
478: t->language = findlanguage(".s");
479: t->type = t_int;
480: t->block = cur;
481: t->level = cur->level;
482: if ((np->n_type&N_TYPE) == N_TEXT) {
483: t->class = FUNC;
484: t->symvalue.funcv.src = false;
485: t->symvalue.funcv.inline = false;
486: t->symvalue.funcv.beginaddr = np->n_value;
487: newfunc(t, codeloc(t));
488: findbeginning(t);
489: } else {
490: t->class = VAR;
491: t->symvalue.offset = np->n_value;
492: }
493: }
494: }
495:
496: /*
497: * Check to see if a symbol corresponds to a object file name.
498: * For some reason these are listed as in the text segment.
499: */
500:
501: private check_filename(name)
502: String name;
503: {
504: register String mname;
505: register Integer i;
506: register Symbol s;
507:
508: mname = strdup(name);
509: i = strlen(mname) - 2;
510: if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') {
511: mname[i] = '\0';
512: --i;
513: while (mname[i] != '/' and i >= 0) {
514: --i;
515: }
516: s = insert(identname(&mname[i+1], true));
517: s->language = findlanguage(".s");
518: s->class = MODULE;
519: s->symvalue.funcv.beginaddr = 0;
520: findbeginning(s);
521: if (curblock->class != PROG) {
522: exitblock();
523: if (curblock->class != PROG) {
524: exitblock();
525: }
526: }
527: enterblock(s);
528: curmodule = s;
529: }
530: }
531:
532: /*
533: * Check to see if a symbol is about to be defined within an unnamed block.
534: * If this happens, we create a procedure for the unnamed block, make it
535: * "inline" so that tracebacks don't associate an activation record with it,
536: * and enter it into the function table so that it will be detected
537: * by "whatblock".
538: */
539:
540: private unnamed_block()
541: {
542: register Symbol s;
543: static int bnum = 0;
544: char buf[100];
545:
546: ++bnum;
547: sprintf(buf, "$b%d", bnum);
548: s = insert(identname(buf, false));
549: s->class = PROG;
550: s->symvalue.funcv.src = false;
551: s->symvalue.funcv.inline = true;
552: s->symvalue.funcv.beginaddr = addrstk[nesting];
553: enterblock(s);
554: newfunc(s, addrstk[nesting]);
555: addrstk[nesting] = NOADDR;
556: }
557:
558: /*
559: * Compilation unit. C associates scope with filenames
560: * so we treat them as "modules". The filename without
561: * the suffix is used for the module name.
562: *
563: * Because there is no explicit "end-of-block" mark in
564: * the object file, we must exit blocks for the current
565: * procedure and module.
566: */
567:
568: private enterSourceModule(n, addr)
569: Name n;
570: Address addr;
571: {
572: register Symbol s;
573: Name nn;
574: String mname, suffix;
575:
576: mname = strdup(ident(n));
577: if (rindex(mname, '/') != nil) {
578: mname = rindex(mname, '/') + 1;
579: }
580: suffix = rindex(mname, '.');
581: curlang = findlanguage(suffix);
582: if (curlang == findlanguage(".f")) {
583: strip_ = true;
584: }
585: if (suffix != nil) {
586: *suffix = '\0';
587: }
588: if (curblock->class != PROG) {
589: exitblock();
590: if (curblock->class != PROG) {
591: exitblock();
592: }
593: }
594: nn = identname(mname, true);
595: if (curmodule == nil or curmodule->name != nn) {
596: s = insert(nn);
597: s->class = MODULE;
598: s->symvalue.funcv.beginaddr = 0;
599: findbeginning(s);
600: } else {
601: s = curmodule;
602: }
603: s->language = curlang;
604: enterblock(s);
605: curmodule = s;
606: if (program->language == nil) {
607: program->language = curlang;
608: }
609: warned = false;
610: enterfile(ident(n), addr);
611: bzero(typetable, sizeof(typetable));
612: }
613:
614: /*
615: * Put an nlist into the symbol table.
616: * If it's already there just add the associated information.
617: *
618: * Type information is encoded in the name following a ":".
619: */
620:
621: private Symbol constype();
622: private Char *curchar;
623:
624: #define skipchar(ptr, ch) { \
625: if (*ptr != ch) { \
626: panic("expected char '%c', found char '%c'", ch, *ptr); \
627: } \
628: ++ptr; \
629: }
630:
631: private entersym(str, np)
632: String str;
633: struct nlist *np;
634: {
635: register Symbol s;
636: register char *p;
637: register int c;
638: register Name n;
639: register Integer i;
640: Boolean knowtype, isnew;
641: Symclass class;
642: Integer level;
643:
644: p = index(str, ':');
645: *p = '\0';
646: c = *(p+1);
647: n = identname(str, true);
648: if (index("FfGV", c) != nil) {
649: if (c == 'F' or c == 'f') {
650: class = FUNC;
651: } else {
652: class = VAR;
653: }
654: level = (c == 'f' ? curmodule->level : program->level);
655: find(s, n) where s->level == level and s->class == class endfind(s);
656: if (s == nil) {
657: isnew = true;
658: s = insert(n);
659: } else {
660: isnew = false;
661: }
662: } else {
663: isnew = true;
664: s = insert(n);
665: }
666:
667: if (nesting > 0 and addrstk[nesting] != NOADDR) {
668: unnamed_block();
669: }
670:
671: /*
672: * Default attributes.
673: */
674: s->language = curlang;
675: s->class = VAR;
676: s->block = curblock;
677: s->level = curlevel;
678: s->symvalue.offset = np->n_value;
679: curchar = p + 2;
680: knowtype = false;
681: switch (c) {
682: case 't': /* type name */
683: s->class = TYPE;
684: i = getint();
685: if (i == 0) {
686: panic("bad input on type \"%s\" at \"%s\"", symname(s),
687: curchar);
688: } else if (i >= NTYPES) {
689: panic("too many types in file \"%s\"", curfilename());
690: }
691: /*
692: * A hack for C typedefs that don't create new types,
693: * e.g. typedef unsigned int Hashvalue;
694: * or typedef struct blah BLAH;
695: */
696: if (*curchar == '\0') {
697: s->type = typetable[i];
698: if (s->type == nil) {
699: s->type = symbol_alloc();
700: typetable[i] = s->type;
701: }
702: knowtype = true;
703: } else {
704: typetable[i] = s;
705: skipchar(curchar, '=');
706: }
707: break;
708:
709: case 'T': /* tag */
710: s->class = TAG;
711: i = getint();
712: if (i == 0) {
713: panic("bad input on tag \"%s\" at \"%s\"", symname(s),
714: curchar);
715: } else if (i >= NTYPES) {
716: panic("too many types in file \"%s\"", curfilename());
717: }
718: if (typetable[i] != nil) {
719: typetable[i]->language = curlang;
720: typetable[i]->class = TYPE;
721: typetable[i]->type = s;
722: } else {
723: typetable[i] = s;
724: }
725: skipchar(curchar, '=');
726: break;
727:
728: case 'F': /* public function */
729: case 'f': /* private function */
730: s->class = FUNC;
731: if (curblock->class == FUNC or curblock->class == PROC) {
732: exitblock();
733: }
734: enterblock(s);
735: if (c == 'F') {
736: s->level = program->level;
737: isnew = false;
738: }
739: curparam = s;
740: if (isnew) {
741: s->symvalue.funcv.src = false;
742: s->symvalue.funcv.inline = false;
743: s->symvalue.funcv.beginaddr = np->n_value;
744: newfunc(s, codeloc(s));
745: findbeginning(s);
746: }
747: break;
748:
749: case 'G': /* public variable */
750: s->level = program->level;
751: break;
752:
753: case 'S': /* private variable */
754: s->level = curmodule->level;
755: s->block = curmodule;
756: break;
757:
758: /*
759: * keep global BSS variables chained so can resolve when get the start
760: * of common; keep the list in order so f77 can display all vars in a COMMON
761: */
762: case 'V': /* own variable */
763: s->level = 2;
764: if (curcomm) {
765: if (commchain != nil) {
766: commchain->symvalue.common.chain = s;
767: }
768: else {
769: curcomm->symvalue.common.offset = (int) s;
770: }
771: commchain = s;
772: s->symvalue.common.offset = np->n_value;
773: s->symvalue.common.chain = nil;
774: }
775: break;
776:
777: case 'r': /* register variable */
778: s->level = -(s->level);
779: break;
780:
781: case 'p': /* parameter variable */
782: curparam->chain = s;
783: curparam = s;
784: break;
785:
786: case 'v': /* varies parameter */
787: s->class = REF;
788: s->symvalue.offset = np->n_value;
789: curparam->chain = s;
790: curparam = s;
791: break;
792:
793: default: /* local variable */
794: --curchar;
795: break;
796: }
797: if (not knowtype) {
798: s->type = constype(nil);
799: if (s->class == TAG) {
800: addtag(s);
801: }
802: }
803: if (tracesyms) {
804: printdecl(s);
805: fflush(stdout);
806: }
807: }
808:
809: /*
810: * Construct a type out of a string encoding.
811: *
812: * The forms of the string are
813: *
814: * <number>
815: * <number>=<type>
816: * r<type>;<number>;<number> $ subrange
817: * a<type>;<type> $ array[index] of element
818: * s{<name>:<type>;<number>;<number>} $ record
819: * S<type> $ set
820: * *<type> $ pointer
821: */
822:
823: private Rangetype getrangetype();
824:
825: private Symbol constype(type)
826: Symbol type;
827: {
828: register Symbol t, u;
829: register Char *p, *cur;
830: register Integer n;
831: Integer b;
832: Name name;
833: Char class;
834:
835: b = curlevel;
836: if (isdigit(*curchar)) {
837: n = getint();
838: if (n == 0) {
839: panic("bad type number at \"%s\"", curchar);
840: } else if (n >= NTYPES) {
841: panic("too many types in file \"%s\"", curfilename());
842: }
843: if (*curchar == '=') {
844: if (typetable[n] != nil) {
845: t = typetable[n];
846: } else {
847: t = symbol_alloc();
848: typetable[n] = t;
849: }
850: ++curchar;
851: constype(t);
852: } else {
853: t = typetable[n];
854: if (t == nil) {
855: t = symbol_alloc();
856: typetable[n] = t;
857: }
858: }
859: } else {
860: if (type == nil) {
861: t = symbol_alloc();
862: } else {
863: t = type;
864: }
865: t->language = curlang;
866: t->level = b;
867: t->block = curblock;
868: class = *curchar++;
869: switch (class) {
870: case 'r':
871: t->class = RANGE;
872: t->type = constype(nil);
873: skipchar(curchar, ';');
874: t->symvalue.rangev.lowertype = getrangetype();
875: t->symvalue.rangev.lower = getint();
876: skipchar(curchar, ';');
877: t->symvalue.rangev.uppertype = getrangetype();
878: t->symvalue.rangev.upper = getint();
879: break;
880:
881: case 'a':
882: t->class = ARRAY;
883: t->chain = constype(nil);
884: skipchar(curchar, ';');
885: t->type = constype(nil);
886: break;
887:
888: case 'S':
889: t->class = SET;
890: t->type = constype(nil);
891: break;
892:
893: case 's':
894: case 'u':
895: t->class = (class == 's') ? RECORD : VARNT;
896: t->symvalue.offset = getint();
897: u = t;
898: cur = curchar;
899: while (*cur != ';' and *cur != '\0') {
900: p = index(cur, ':');
901: if (p == nil) {
902: panic("index(\"%s\", ':') failed", curchar);
903: }
904: *p = '\0';
905: name = identname(cur, true);
906: u->chain = newSymbol(name, b, FIELD, nil, nil);
907: cur = p + 1;
908: u = u->chain;
909: u->language = curlang;
910: curchar = cur;
911: u->type = constype(nil);
912: skipchar(curchar, ',');
913: u->symvalue.field.offset = getint();
914: skipchar(curchar, ',');
915: u->symvalue.field.length = getint();
916: skipchar(curchar, ';');
917: cur = curchar;
918: }
919: if (*cur == ';') {
920: ++cur;
921: }
922: curchar = cur;
923: break;
924:
925: case 'e':
926: t->class = SCAL;
927: u = t;
928: while (*curchar != ';' and *curchar != '\0') {
929: p = index(curchar, ':');
930: assert(p != nil);
931: *p = '\0';
932: u->chain = insert(identname(curchar, true));
933: curchar = p + 1;
934: u = u->chain;
935: u->language = curlang;
936: u->class = CONST;
937: u->level = b;
938: u->block = curblock;
939: u->type = t;
940: u->symvalue.iconval = getint();
941: skipchar(curchar, ',');
942: }
943: if (*curchar == ';')
944: curchar++;
945: break;
946:
947: case '*':
948: t->class = PTR;
949: t->type = constype(nil);
950: break;
951:
952: case 'f':
953: t->class = FUNC;
954: t->type = constype(nil);
955: break;
956:
957: default:
958: badcaseval(class);
959: }
960: }
961: return t;
962: }
963:
964: /*
965: * Get a range type.
966: *
967: * Special letters indicate a dynamic bound, i.e. what follows
968: * is the offset from the fp which contains the bound.
969: * J is a special flag to handle fortran a(*) bounds.
970: */
971:
972: private Rangetype getrangetype()
973: {
974: Rangetype t;
975:
976: switch (*curchar) {
977: case 'A':
978: t = R_ARG;
979: curchar++;
980: break;
981:
982: case 'T':
983: t = R_TEMP;
984: curchar++;
985: break;
986:
987: case 'J':
988: t = R_ADJUST;
989: curchar++;
990: break;
991:
992: default:
993: t = R_CONST;
994: break;
995: }
996: return t;
997: }
998:
999: /*
1000: * Read an integer from the current position in the type string.
1001: */
1002:
1003: private Integer getint()
1004: {
1005: register Integer n;
1006: register char *p;
1007: register Boolean isneg;
1008:
1009: n = 0;
1010: p = curchar;
1011: if (*p == '-') {
1012: isneg = true;
1013: ++p;
1014: } else {
1015: isneg = false;
1016: }
1017: while (isdigit(*p)) {
1018: n = 10*n + (*p - '0');
1019: ++p;
1020: }
1021: curchar = p;
1022: return isneg ? (-n) : n;
1023: }
1024:
1025: /*
1026: * Add a tag name. This is a kludge to be able to refer
1027: * to tags that have the same name as some other symbol
1028: * in the same block.
1029: */
1030:
1031: private addtag(s)
1032: register Symbol s;
1033: {
1034: register Symbol t;
1035: char buf[100];
1036:
1037: sprintf(buf, "$$%.90s", ident(s->name));
1038: t = insert(identname(buf, false));
1039: t->language = s->language;
1040: t->class = TAG;
1041: t->type = s->type;
1042: t->block = s->block;
1043: }
1044:
1045: /*
1046: * Allocate file and line tables and initialize indices.
1047: */
1048:
1049: private allocmaps(nf, nl)
1050: Integer nf, nl;
1051: {
1052: if (filetab != nil) {
1053: dispose(filetab);
1054: }
1055: if (linetab != nil) {
1056: dispose(linetab);
1057: }
1058: filetab = newarr(Filetab, nf);
1059: linetab = newarr(Linetab, nl);
1060: filep = filetab;
1061: linep = linetab;
1062: }
1063:
1064: /*
1065: * Add a file to the file table.
1066: *
1067: * If the new address is the same as the previous file address
1068: * this routine used to not enter the file, but this caused some
1069: * problems so it has been removed. It's not clear that this in
1070: * turn may not also cause a problem.
1071: */
1072:
1073: private enterfile(filename, addr)
1074: String filename;
1075: Address addr;
1076: {
1077: filep->addr = addr;
1078: filep->filename = filename;
1079: filep->lineindex = linep - linetab;
1080: ++filep;
1081: }
1082:
1083: /*
1084: * Since we only estimated the number of lines (and it was a poor
1085: * estimation) and since we need to know the exact number of lines
1086: * to do a binary search, we set it when we're done.
1087: */
1088:
1089: private setnlines()
1090: {
1091: nlhdr.nlines = linep - linetab;
1092: }
1093:
1094: /*
1095: * Similarly for nfiles ...
1096: */
1097:
1098: private setnfiles()
1099: {
1100: nlhdr.nfiles = filep - filetab;
1101: setsource(filetab[0].filename);
1102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.