From 0022c35531b08c553c52295f220a84179e89c2f1 Mon Sep 17 00:00:00 2001 From: Mark Linton Date: Sat, 2 Mar 1985 04:32:43 -0800 Subject: [PATCH] update to version 3.0 SCCS-vsn: old/dbx/Makefile 4.11 SCCS-vsn: old/dbx/asm.c 1.4 SCCS-vsn: old/dbx/c.c 1.9 SCCS-vsn: old/dbx/cerror.vax.s 1.3 SCCS-vsn: old/dbx/check.c 1.7 SCCS-vsn: old/dbx/commands.y 1.14 SCCS-vsn: old/dbx/coredump.c 1.7 SCCS-vsn: old/dbx/debug.c 1.5 SCCS-vsn: old/dbx/defs.h 1.4 SCCS-vsn: old/dbx/eval.c 1.15 SCCS-vsn: old/dbx/events.c 1.7 SCCS-vsn: old/dbx/fortran.c 1.6 SCCS-vsn: old/dbx/keywords.c 1.7 SCCS-vsn: old/dbx/languages.c 1.5 SCCS-vsn: old/dbx/library.c 1.6 SCCS-vsn: old/dbx/lists.c 1.4 SCCS-vsn: old/dbx/vax.c 1.13 SCCS-vsn: old/dbx/main.c 1.11 SCCS-vsn: old/dbx/makedefs.c 1.4 SCCS-vsn: old/dbx/mappings.c 1.6 SCCS-vsn: old/dbx/mkdate.c 1.4 SCCS-vsn: old/dbx/names.c 1.5 SCCS-vsn: old/dbx/object.c 1.16 SCCS-vsn: old/dbx/operators.c 1.9 SCCS-vsn: old/dbx/ops.c 1.5 SCCS-vsn: old/dbx/ops.vax.c 1.5 SCCS-vsn: old/dbx/pascal.c 1.4 SCCS-vsn: old/dbx/printsym.c 1.14 SCCS-vsn: old/dbx/process.c 1.17 SCCS-vsn: old/dbx/runtime.c 1.13 SCCS-vsn: old/dbx/runtime.vax.c 1.13 SCCS-vsn: old/dbx/scanner.c 1.12 SCCS-vsn: old/dbx/source.c 1.12 SCCS-vsn: old/dbx/stabstring.c 1.2 SCCS-vsn: old/dbx/symbols.c 1.17 SCCS-vsn: old/dbx/tree.c 1.8 --- usr/src/old/dbx/Makefile | 179 ++++-- usr/src/old/dbx/asm.c | 55 +- usr/src/old/dbx/c.c | 203 ++---- usr/src/old/dbx/cerror.vax.s | 4 +- usr/src/old/dbx/check.c | 60 +- usr/src/old/dbx/commands.y | 496 ++++++++------- usr/src/old/dbx/coredump.c | 320 ++++++++-- usr/src/old/dbx/debug.c | 296 +++------ usr/src/old/dbx/defs.h | 3 +- usr/src/old/dbx/eval.c | 448 +++++++------ usr/src/old/dbx/events.c | 263 +++----- usr/src/old/dbx/fortran.c | 64 +- usr/src/old/dbx/keywords.c | 499 +++++++++++---- usr/src/old/dbx/languages.c | 4 +- usr/src/old/dbx/library.c | 18 +- usr/src/old/dbx/lists.c | 4 +- usr/src/old/dbx/main.c | 97 ++- usr/src/old/dbx/makedefs.c | 4 +- usr/src/old/dbx/mappings.c | 96 ++- usr/src/old/dbx/mkdate.c | 4 +- usr/src/old/dbx/names.c | 34 +- usr/src/old/dbx/object.c | 299 +++++++-- usr/src/old/dbx/operators.c | 35 +- usr/src/old/dbx/ops.c | 4 +- usr/src/old/dbx/ops.vax.c | 4 +- usr/src/old/dbx/pascal.c | 679 ++++++++++++++------ usr/src/old/dbx/printsym.c | 227 +++++-- usr/src/old/dbx/process.c | 308 +++++---- usr/src/old/dbx/runtime.c | 416 ++++++++---- usr/src/old/dbx/runtime.vax.c | 416 ++++++++---- usr/src/old/dbx/scanner.c | 1113 +++++++++++++++++++-------------- usr/src/old/dbx/source.c | 210 +++++-- usr/src/old/dbx/stabstring.c | 272 ++++++-- usr/src/old/dbx/symbols.c | 669 +++++++++++--------- usr/src/old/dbx/tree.c | 233 ++++--- usr/src/old/dbx/vax.c | 214 ++++--- 36 files changed, 5244 insertions(+), 3006 deletions(-) diff --git a/usr/src/old/dbx/Makefile b/usr/src/old/dbx/Makefile index 5279e51e8a..e8a8011f8f 100644 --- a/usr/src/old/dbx/Makefile +++ b/usr/src/old/dbx/Makefile @@ -1,64 +1,157 @@ -# Makefile 4.10 84/08/17 +# Makefile 4.11 85/03/01 # # make file for debugger "dbx" # # The file "defs.h" is included by all. # -AOUT= tdbx -DESTDIR= -DEST= ${DESTDIR}/usr/ucb/dbx -LIBS= -CFLAGS= -O -YFLAGS= -d -LDFLAGS= -HDR= asm.h events.h c.h check.h coredump.h eval.h fortran.h keywords.h \ - languages.h lists.h machine.h main.h mappings.h modula-2.h names.h \ - object.h operators.h pascal.h printsym.h process.h re.h \ - runtime.h scanner.h source.h stabstring.h symbols.h tree.h ops.h -SRCS= asm.c events.c c.c cerror.s check.c coredump.c debug.c eval.c \ - fortran.c keywords.c languages.c library.c lists.c machine.c main.c \ - mappings.c modula-2.c names.c object.c operators.c pascal.c printsym.c \ - process.c re.c runtime.c scanner.c source.c symbols.c tree.c ops.c -OBJS= y.tab.o asm.o events.o c.o cerror.o check.o coredump.o \ - debug.o eval.o fortran.o keywords.o languages.o library.o \ - lists.o machine.o main.o mappings.o modula-2.o names.o \ - object.o operators.o pascal.o printsym.o process.o re.o \ - runtime.o scanner.o source.o stabstring.o symbols.o tree.o \ - ops.o .SUFFIXES: .SUFFIXES: .h .c .s .o +AOUT = tdbx +DEST = /usr/ucb/dbx + +CC = cc +CFLAGS = '-DMAINTAINER="linton@shasta"' -g + +LD = cc +LDFLAGS = -g +LIBRARIES = + +# LD = /bin/oldld +# LDFLAGS = -X /lib/crt0.o +# LIBRARIES = -lg -lc + +OBJ = \ + y.tab.o \ + asm.o \ + events.o \ + c.o \ + cerror.o \ + check.o \ + coredump.o \ + debug.o \ + eval.o \ + fortran.o \ + keywords.o \ + languages.o \ + library.o \ + lists.o \ + machine.o \ + main.o \ + mappings.o \ + modula-2.o \ + names.o \ + object.o \ + operators.o \ + pascal.o \ + printsym.o \ + process.o \ + runtime.o \ + scanner.o \ + source.o \ + stabstring.o \ + symbols.o \ + tree.o \ + ops.o + +HDR = \ + asm.h \ + events.h \ + c.h \ + check.h \ + coredump.h \ + debug.h \ + eval.h \ + fortran.h \ + keywords.h \ + languages.h \ + lists.h \ + machine.h \ + main.h \ + mappings.h \ + modula-2.h \ + names.h \ + object.h \ + operators.h \ + pascal.h \ + printsym.h \ + process.h \ + runtime.h \ + scanner.h \ + source.h \ + stabstring.h \ + symbols.h \ + tree.h \ + ops.h + +SRC = \ + defs.h \ + commands.y \ + asm.c \ + events.c \ + c.c \ + cerror.s \ + check.c \ + coredump.c \ + debug.c \ + eval.c \ + fortran.c \ + keywords.c \ + languages.c \ + library.c \ + lists.c \ + machine.c \ + main.c \ + mappings.c \ + modula-2.c \ + names.c \ + object.c \ + operators.c \ + pascal.c \ + printsym.c \ + process.c \ + runtime.c \ + scanner.c \ + source.c \ + stabstring.c \ + symbols.c \ + tree.c \ + ops.c + .c.o: - ${CC} ${CFLAGS} -c $*.c + @echo "compiling $*.c" + @${CC} ${CFLAGS} -c $*.c .s.o: - ${CC} -c $*.s + @echo "assembling $*.s" + @${CC} -c $*.s .c.h: - @./makedefs -f $*.c $*.h + ./makedefs -f $*.c $*.h -${AOUT}: makedefs mkdate ${HDR} ${OBJS} +${AOUT}: makedefs mkdate ${HDR} ${OBJ} @rm -f date.c @./mkdate > date.c @echo "linking" - @${CC} ${LDFLAGS} date.c ${OBJS} ${LIBS} -o ${AOUT} + @${CC} ${CFLAGS} -c date.c + @${LD} ${LDFLAGS} date.o ${OBJ} ${LIBRARIES} -o ${AOUT} -profile: ${HDR} ${OBJS} +profile: ${HDR} ${OBJ} @rm -f date.c @./mkdate > date.c @echo "linking with -p" - @${CC} ${LDFLAGS} -p date.c ${OBJS} ${LIBS} -o ${AOUT} + @${CC} ${LDFLAGS} -p date.c ${OBJ} ${LIBRARIES} -o ${AOUT} y.tab.c: commands.y @echo "expect 2 shift/reduce conflicts" - ${YACC} ${YFLAGS} commands.y + yacc -d commands.y makedefs: makedefs.c library.o cerror.o - ${CC} ${CFLAGS} ${LDFLAGS} makedefs.c library.o cerror.o -o makedefs + ${CC} -g makedefs.c library.o cerror.o -o makedefs mkdate: mkdate.c - ${CC} ${CFLAGS} ${LDFLAGS} mkdate.c -o mkdate + ${CC} -g mkdate.c -o mkdate print: @echo "don't print it, it's too long" @@ -67,10 +160,13 @@ print: # Don't worry about the removal of header files, they're created from # the source files. # + clean: - rm -f ${HDR} ${OBJS} y.tab.c y.tab.h ${AOUT} \ - mkdate mkdate.o makedefs makedefs.o date.c core mon.out \ - prof.out errs + rm -f ${HDR} ${OBJ} y.tab.c y.tab.h ${AOUT} mkdate mkdate.o \ + makedefs makedefs.o date.c core mon.out prof.out make.out + +cleandefs: + rm -f ${HDR} y.tab.h testinstall: ${AOUT} test install @@ -80,8 +176,16 @@ test: install: ${AOUT} install ${AOUT} ${DEST} -tags: defs.h ${SRCS} - ctags -w defs.h ${SRCS} +# +# Create a tar file called "tape" containing relevant files. +# + +TAPE = tape + +tape: + @tar cf ${TAPE} \ + Makefile History version READ_ME ${SRC} \ + makedefs.c mkdate.c tests pchanges ptests # # Header dependencies are purposely incomplete since header files @@ -94,4 +198,5 @@ tags: defs.h ${SRCS} # but misfortunately silly make does a "makedefs y.tab.c y.tab.h" which # destroys y.tab.h. # + symbols.o tree.o check.o eval.o events.o: operators.h diff --git a/usr/src/old/dbx/asm.c b/usr/src/old/dbx/asm.c index d625da3a3d..b45ce48b85 100644 --- a/usr/src/old/dbx/asm.c +++ b/usr/src/old/dbx/asm.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)asm.c 1.3 (Berkeley) %G%"; +static char sccsid[] = "@(#)asm.c 1.4 (Berkeley) %G%"; + +static char rcsid[] = "$Header: asm.c,v 1.5 84/12/26 10:38:19 linton Exp $"; /* * Assembly language dependent symbol routines. @@ -34,6 +36,8 @@ public asm_init() language_setop(lang, L_PRINTDECL, asm_printdecl); language_setop(lang, L_PRINTVAL, asm_printval); language_setop(lang, L_TYPEMATCH, asm_typematch); + language_setop(lang, L_BUILDAREF, asm_buildaref); + language_setop(lang, L_EVALAREF, asm_evalaref); language_setop(lang, L_HASMODULES, asm_hasmodules); language_setop(lang, L_PASSADDR, asm_passaddr); } @@ -55,6 +59,10 @@ public asm_printdecl(s) Symbol s; { switch (s->class) { + case CONST: + printf("%s = %d", symname(s), s->symvalue.constval->value.lcon); + break; + case VAR: case REF: printf("&%s = 0x%x", symname(s), s->symvalue.offset); @@ -65,8 +73,17 @@ Symbol s; printf("%s (0x%x):", symname(s), codeloc(s)); break; + case TYPE: + printf("%s", symname(s)); + break; + + case ARRAY: + printf("$string"); + break; + default: - error("class %s in c_printdecl", classname(s)); + printf("[%s]", classname(s)); + break; } putchar('\n'); } @@ -100,6 +117,40 @@ register Symbol s; } } +/* + * Treat subscripting as indirection through pointer to integer. + */ + +public Node asm_buildaref(a, slist) +Node a, slist; +{ + Symbol t, eltype; + Node p, r; + + t = rtype(a->nodetype); + eltype = t->type; + p = slist->value.arg[0]; + r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); + r = build(O_ADD, build(O_RVAL, a), r); + r->nodetype = eltype; + return r; +} + +/* + * Evaluate a subscript index. Assumes dimension is [0..n]. + */ + +public asm_evalaref(s, base, i) +Symbol s; +Address base; +long i; +{ + Symbol t; + + t = rtype(s); + push(long, base + i * size(t->type)); +} + public boolean asm_hasmodules () { return false; diff --git a/usr/src/old/dbx/c.c b/usr/src/old/dbx/c.c index aabbda1437..717783c714 100644 --- a/usr/src/old/dbx/c.c +++ b/usr/src/old/dbx/c.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)c.c 1.8 (Berkeley) %G%"; +static char sccsid[] = "@(#)c.c 1.9 (Berkeley) %G%"; + +static char rcsid[] = "$Header: c.c,v 1.5 84/12/26 10:38:23 linton Exp $"; /* * C-dependent symbol routines. @@ -79,6 +81,10 @@ Symbol type1, type2; (t2 == t_char->type or t2 == t_int->type) ) or ( t1->class == RANGE and isdouble(t1) and t2 == t_real->type + ) or ( + t1->class == RANGE and t2->class == RANGE and + t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and + t1->symvalue.rangev.upper == t2->symvalue.rangev.upper ) or ( t1->type == t2->type and ( (t1->class == t2->class) or @@ -95,31 +101,6 @@ Symbol type1, type2; return b; } -/* - * Decide if a field is a bit field. - */ - -private Boolean isbitfield(s) -register Symbol s; -{ - Boolean b; - register Integer off, len; - register Symbol t; - - off = s->symvalue.field.offset; - len = s->symvalue.field.length; - if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { - b = true; - } else { - t = rtype(s->type); - b = (Boolean) - (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE) or - len != (size(t)*BITSPERBYTE) - ); - } - return b; -} - /* * Print out the declaration of a C variable. */ @@ -148,8 +129,9 @@ Integer indent; switch (s->class) { case CONST: if (s->type->class == SCAL) { - printf("(enumeration constant, ord %ld)", - s->symvalue.iconval); + printf("enumeration constant with value "); + eval(s->symvalue.constval); + c_printval(s); } else { printf("const %s = ", symname(s)); printval(s); @@ -158,12 +140,8 @@ Integer indent; case TYPE: case VAR: - if (s->class != TYPE) { - if (s->level == 1 and s->block != program) { - printf("static "); - } else if (s->level < 0) { - printf("register "); - } + if (s->class != TYPE and s->level < 0) { + printf("register "); } if (s->type->class == ARRAY) { printtype(s->type, s->type->type, indent); @@ -212,10 +190,15 @@ Integer indent; case RECORD: case VARNT: case PTR: + case FFUNC: semicolon = false; printtype(s, s, indent); break; + case SCAL: + printf("(enumeration constant, value %d)", s->symvalue.iconval); + break; + case PROC: semicolon = false; printf("%s", symname(s)); @@ -245,7 +228,8 @@ Integer indent; break; default: - error("class %s in c_printdecl", classname(s)); + printf("[%s]", classname(s)); + break; } if (semicolon) { putchar(';'); @@ -463,9 +447,9 @@ Symbol s; i &= ((1 << s->symvalue.field.length) - 1); t = rtype(s->type); if (t->class == SCAL) { - printenum(i, t); + printEnum(i, t); } else { - printrange(i, t); + printRangeVal(i, t); } } else { c_printval(s->type); @@ -479,7 +463,11 @@ Symbol s; ) { len = size(s); sp -= len; - printf("\"%.*s\"", len, sp); + if (s->language == primlang) { + printf("%.*s", len, sp); + } else { + printf("\"%.*s\"", len, sp); + } } else { printarray(s); } @@ -490,11 +478,11 @@ Symbol s; break; case RANGE: - if (istypename(s->type, "boolean")) { - printrange(popsmall(s), s); - } else if (istypename(s->type, "char")) { - printrange(pop(char), s); - } else if (isdouble(s)) { + if (s == t_boolean->type or istypename(s->type, "boolean")) { + printRangeVal(popsmall(s), s); + } else if (s == t_char->type or istypename(s->type, "char")) { + printRangeVal(pop(char), s); + } else if (s == t_real->type or isdouble(s)) { switch (s->symvalue.rangev.lower) { case sizeof(float): prtreal(pop(float)); @@ -509,7 +497,7 @@ Symbol s; break; } } else { - printrange(popsmall(s), s); + printRangeVal(popsmall(s), s); } break; @@ -519,7 +507,7 @@ Symbol s; if (a == 0) { printf("(nil)"); } else if (t->class == RANGE and istypename(t->type, "char")) { - printstring(a); + printString(a, (boolean) (s->language != primlang)); } else { printf("0x%x", a); } @@ -527,7 +515,15 @@ Symbol s; case SCAL: i = pop(Integer); - printenum(i, s); + printEnum(i, s); + break; + + /* + * Unresolved structure pointers? + */ + case BADUSE: + a = pop(Address); + printf("@%x", a); break; default: @@ -544,12 +540,12 @@ Symbol s; * Print out a C structure. */ -private c_printstruct(s) +private c_printstruct (s) Symbol s; { - register Symbol f; - register Stack *savesp; - register Integer n, off, len; + Symbol f; + Stack *savesp; + integer n, off, len; sp -= size(s); savesp = sp; @@ -570,84 +566,6 @@ Symbol s; printf(")"); } -/* - * Print out a range type (integer, char, or boolean). - */ - -private printrange(i, t) -Integer i; -register Symbol t; -{ - if (istypename(t->type, "boolean")) { - printf(((Boolean) i) == true ? "true" : "false"); - } else if (istypename(t->type, "char")) { - putchar('\''); - printchar(i); - putchar('\''); - } else if (t->symvalue.rangev.lower >= 0) { - printf("%lu", i); - } else { - printf("%ld", i); - } -} - -/* - * Print out a null-terminated string (pointer to char) - * starting at the given address. - */ - -private printstring(addr) -Address addr; -{ - register Address a; - register Integer i, len; - register Boolean endofstring; - union { - char ch[sizeof(Word)]; - int word; - } u; - - putchar('"'); - a = addr; - endofstring = false; - while (not endofstring) { - dread(&u, a, sizeof(u)); - i = 0; - do { - if (u.ch[i] == '\0') { - endofstring = true; - } else { - printchar(u.ch[i]); - } - ++i; - } while (i < sizeof(Word) and not endofstring); - a += sizeof(Word); - } - putchar('"'); -} - -/* - * Print out an enumerated value by finding the corresponding - * name in the enumeration list. - */ - -private printenum(i, t) -Integer i; -Symbol t; -{ - register Symbol e; - - e = t->chain; - while (e != nil and e->symvalue.iconval != i) { - e = e->chain; - } - if (e != nil) { - printf("%s", symname(e)); - } else { - printf("%d", i); - } -} - /* * Return the C name for the particular class of a symbol. */ @@ -675,23 +593,22 @@ Symbol s; } return str; } + public Node c_buildaref(a, slist) Node a, slist; { register Symbol t; register Node p; Symbol etype, atype, eltype; - Node esub, r; + Node r, esub; - r = a; t = rtype(a->nodetype); eltype = t->type; if (t->class == PTR) { p = slist->value.arg[0]; if (not compatible(p->nodetype, t_int)) { beginerrmsg(); - fprintf(stderr, "bad type for subscript of "); - prtree(stderr, a); + fprintf(stderr, "subscript must be integer-compatible"); enderrmsg(); } r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); @@ -699,10 +616,12 @@ Node a, slist; r->nodetype = eltype; } else if (t->class != ARRAY) { beginerrmsg(); + fprintf(stderr, "\""); prtree(stderr, a); - fprintf(stderr, " is not an array"); + fprintf(stderr, "\" is not an array"); enderrmsg(); } else { + r = a; p = slist; t = t->chain; for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { @@ -711,9 +630,9 @@ Node a, slist; atype = rtype(t); if (not compatible(atype, etype)) { beginerrmsg(); - fprintf(stderr, "subscript "); + fprintf(stderr, "subscript \""); prtree(stderr, esub); - fprintf(stderr, " is the wrong type"); + fprintf(stderr, "\" is the wrong type"); enderrmsg(); } r = build(O_INDEX, r, esub); @@ -722,11 +641,12 @@ Node a, slist; if (p != nil or t != nil) { beginerrmsg(); if (p != nil) { - fprintf(stderr, "too many subscripts for "); + fprintf(stderr, "too many subscripts for \""); } else { - fprintf(stderr, "not enough subscripts for "); + fprintf(stderr, "not enough subscripts for \""); } prtree(stderr, a); + fprintf(stderr, "\""); enderrmsg(); } } @@ -737,19 +657,22 @@ Node a, slist; * Evaluate a subscript index. */ -public int c_evalaref(s, i) +public c_evalaref(s, base, i) Symbol s; +Address base; long i; { + Symbol t; long lb, ub; - s = rtype(s)->chain; + t = rtype(s); + s = t->chain; lb = s->symvalue.rangev.lower; ub = s->symvalue.rangev.upper; if (i < lb or i > ub) { error("subscript out of range"); } - return (i - lb); + push(long, base + (i - lb) * size(t->type)); } /* diff --git a/usr/src/old/dbx/cerror.vax.s b/usr/src/old/dbx/cerror.vax.s index 7c59d096ea..dd4f70639e 100644 --- a/usr/src/old/dbx/cerror.vax.s +++ b/usr/src/old/dbx/cerror.vax.s @@ -1,6 +1,8 @@ # Copyright (c) 1982 Regents of the University of California # -# static char sccsid[] = "@(#)cerror.vax.s 1.2 (Berkeley) %G%"; +# static char sccsid[] = "@(#)cerror.vax.s 1.3 (Berkeley) %G%"; +# +# static char rcsid[] = "$Header: cerror.s,v 1.5 84/12/26 10:38:33 linton Exp $"; # # modified version of cerror # diff --git a/usr/src/old/dbx/check.c b/usr/src/old/dbx/check.c index becdd3a7e3..81543c3da0 100644 --- a/usr/src/old/dbx/check.c +++ b/usr/src/old/dbx/check.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)check.c 1.6 (Berkeley) %G%"; +static char sccsid[] = "@(#)check.c 1.7 (Berkeley) %G%"; + +static char rcsid[] = "$Header: check.c,v 1.5 84/12/26 10:38:35 linton Exp $"; /* * Check a tree for semantic correctness. @@ -16,6 +18,7 @@ static char sccsid[] = "@(#)check.c 1.6 (Berkeley) %G%"; #include "object.h" #include "mappings.h" #include "process.h" +#include #ifndef public #endif @@ -30,11 +33,52 @@ static char sccsid[] = "@(#)check.c 1.6 (Berkeley) %G%"; public check(p) register Node p; { + Node p1, p2; Address addr; Symbol f; checkref(p); switch (p->op) { + case O_ASSIGN: + p1 = p->value.arg[0]; + p2 = p->value.arg[1]; + if (not compatible(p1->nodetype, p2->nodetype)) { + error("incompatible types"); + } + break; + + case O_CATCH: + case O_IGNORE: + if (p->value.lcon < 0 or p->value.lcon > NSIG) { + error("invalid signal number"); + } + break; + + case O_CONT: + if (p->value.lcon != DEFSIG and ( + p->value.lcon < 0 or p->value.lcon > NSIG) + ) { + error("invalid signal number"); + } + break; + + case O_DUMP: + if (p->value.arg[0] != nil) { + if (p->value.arg[0]->op == O_SYM) { + f = p->value.arg[0]->value.sym; + if (not isblock(f)) { + error("\"%s\" is not a block", symname(f)); + } + } else { + beginerrmsg(); + fprintf(stderr, "expected a symbol, found \""); + prtree(stderr, p->value.arg[0]); + fprintf(stderr, "\""); + enderrmsg(); + } + } + break; + case O_LIST: if (p->value.arg[0]->op == O_SYM) { f = p->value.arg[0]->value.sym; @@ -58,6 +102,7 @@ register Node p; chkstop(p); break; + case O_CALLPROC: case O_CALL: if (not isroutine(p->value.arg[0]->nodetype)) { beginerrmsg(); @@ -68,6 +113,13 @@ register Node p; } break; + case O_WHEREIS: + if (p->value.arg[0]->op == O_SYM and + p->value.arg[0]->value.sym == nil) { + error("symbol not defined"); + } + break; + default: break; } @@ -173,6 +225,12 @@ Node b; b->value.sym = p; } } + } else if ( + b->value.sym->class == VAR and + b->value.sym->name == b->value.sym->block->name and + b->value.sym->block->class == FUNC + ) { + b->value.sym = b->value.sym->block; } else if (not isblock(b->value.sym)) { error("\"%s\" is not a subprogram", symname(b->value.sym)); } diff --git a/usr/src/old/dbx/commands.y b/usr/src/old/dbx/commands.y index 2cb6b32eda..9b6285e46f 100644 --- a/usr/src/old/dbx/commands.y +++ b/usr/src/old/dbx/commands.y @@ -1,7 +1,10 @@ %{ + /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)commands.y 1.13 (Berkeley) %G%"; +static char sccsid[] = "@(#)commands.y 1.14 (Berkeley) %G%"; + +static char rcsid[] = "$Header: commands.y,v 1.5 84/12/26 10:38:41 linton Exp $"; /* * Yacc grammar for debugger commands. @@ -14,9 +17,9 @@ static char sccsid[] = "@(#)commands.y 1.13 (Berkeley) %G%"; #include "process.h" #include "source.h" #include "scanner.h" +#include "keywords.h" #include "names.h" #include "lists.h" -#include private String curformat = "X"; @@ -25,12 +28,12 @@ private String curformat = "X"; %term ALIAS AND ASSIGN AT CALL CATCH CONT DEBUG DELETE DIV DOWN DUMP EDIT FILE FUNC GRIPE HELP IF IGNORE IN LIST MOD NEXT NEXTI NIL NOT OR - PRINT PSYM QUIT RERUN RETURN RUN SH SKIP SOURCE STATUS STEP STEPI - STOP STOPI TRACE TRACEI UP - USE WHATIS WHEN WHERE WHEREIS WHICH + PRINT PSYM QUIT RERUN RETURN RUN SET SH SKIP SOURCE STATUS STEP STEPI + STOP STOPI TRACE TRACEI UNALIAS UNSET UP USE + WHATIS WHEN WHERE WHEREIS WHICH -%term INT REAL NAME STRING -%term LFORMER RFORMER ABSTRACTION ARROW +%term INT CHAR REAL NAME STRING +%term ARROW %right INT %binary REDIRECT @@ -38,8 +41,8 @@ private String curformat = "X"; %left '+' '-' OR %left UNARYSIGN %left '*' '/' DIV MOD AND -%left NOT '(' '[' '.' '^' ARROW %left '\\' +%left NOT '(' '[' '.' '^' ARROW %union { Name y_name; @@ -48,6 +51,7 @@ private String curformat = "X"; Integer y_int; Operator y_op; long y_long; + char y_char; double y_real; String y_string; Boolean y_bool; @@ -56,67 +60,50 @@ private String curformat = "X"; }; %type trace stop -%type INT count +%type INT count signal +%type CHAR %type REAL %type STRING redirectout filename opt_filename mode %type ALIAS AND ASSIGN AT CALL CATCH CONT %type DEBUG DELETE DIV DOWN DUMP %type EDIT FILE FUNC GRIPE HELP IF IGNORE IN LIST MOD %type NEXT NEXTI NIL NOT OR -%type PRINT PSYM QUIT RERUN RETURN RUN SH SKIP SOURCE STATUS +%type PRINT PSYM QUIT RERUN RETURN RUN SET SH SKIP SOURCE STATUS %type STEP STEPI STOP STOPI TRACE TRACEI -%type UP USE WHATIS WHEN WHERE WHEREIS WHICH +%type UNALIAS UNSET UP USE WHATIS WHEN WHERE WHEREIS WHICH %type name NAME keyword %type opt_qual_symbol symbol %type command rcommand cmd step what where examine %type event opt_exp_list opt_cond %type exp_list exp term boolean_exp constant address %type integer_list alias_command list_command line_number -%type something search_command pattern -%type signal_list signal %type actions -%type sourcepath +%type sourcepath name_list %% input: input command_nl -{ - endshellmode(); - startaliasing(); -} | /* empty */ ; - command_nl: command_line '\n' -{ - if (istty()) { - printf("(%s) ", cmdname); - fflush(stdout); - } -} | command_line ';' -| - '\n' { - if (istty()) { - printf("(%s) ", cmdname); - fflush(stdout); - } + chkalias = true; } +| + '\n' ; command_line: command { if ($1 != nil) { - if(debug_flag[2]) {dumptree(stderr,$1); fflush (stderr);} - eval($1); + topeval($1); } - startaliasing(); } | rcommand redirectout @@ -124,15 +111,12 @@ command_line: if ($1 != nil) { if ($2 != nil) { setout($2); - if(debug_flag[2]) {dumptree(stderr,$1); fflush (stderr);} - eval($1); + topeval($1); unsetout(); } else { - if(debug_flag[2]) {dumptree(stderr,$1); fflush (stderr);} - eval($1); + topeval($1); } } - startaliasing(); } ; redirectout: @@ -156,19 +140,19 @@ command: $$ = $1; } | - ASSIGN stopaliasing term '=' exp + ASSIGN exp '=' exp { - $$ = build(O_ASSIGN, $3, $5); + $$ = build(O_ASSIGN, unrval($2), $4); } | - CATCH + CATCH signal { - $$ = build(O_CATCH, nil); + $$ = build(O_CATCH, $2); } | - CATCH stopaliasing signal_list + CATCH { - $$ = build(O_CATCH, $3); + $$ = build(O_CATCH, 0); } | CONT @@ -176,7 +160,7 @@ command: $$ = build(O_CONT, (long) DEFSIG); } | - CONT INT + CONT signal { $$ = build(O_CONT, $2); } @@ -211,9 +195,9 @@ command: $$ = build(O_FUNC, nil); } | - FUNC stopaliasing symbol + FUNC opt_qual_symbol { - $$ = build(O_FUNC, $3); + $$ = build(O_FUNC, $2); } | GRIPE @@ -226,14 +210,14 @@ command: $$ = build(O_HELP); } | - IGNORE + IGNORE signal { - $$ = build(O_IGNORE, nil); + $$ = build(O_IGNORE, $2); } | - IGNORE stopaliasing signal_list + IGNORE { - $$ = build(O_IGNORE, $3); + $$ = build(O_IGNORE, 0); } | list_command @@ -241,9 +225,9 @@ command: $$ = $1; } | - PSYM stopaliasing term + PSYM exp { - $$ = build(O_PSYM, $3); + $$ = build(O_PSYM, unrval($2)); } | QUIT @@ -260,9 +244,9 @@ command: $$ = build(O_RETURN, nil); } | - RETURN stopaliasing opt_qual_symbol + RETURN opt_qual_symbol { - $$ = build(O_RETURN, $3); + $$ = build(O_RETURN, $2); } | runcommand @@ -270,6 +254,21 @@ command: run(); /* NOTREACHED */ } +| + SET name '=' exp +{ + $$ = build(O_SET, build(O_NAME, $2), $4); +} +| + SET name +{ + $$ = build(O_SET, build(O_NAME, $2), nil); +} +| + SET +{ + $$ = build(O_SET, nil, nil); +} | SH { @@ -321,6 +320,16 @@ command: { $$ = build($1, nil, nil, $2); } +| + UNALIAS name +{ + $$ = build(O_UNALIAS, build(O_NAME, $2)); +} +| + UNSET name +{ + $$ = build(O_UNSET, build(O_NAME, $2)); +} | UP { @@ -350,96 +359,62 @@ command: } } | - WHATIS stopaliasing term + WHATIS opt_qual_symbol { - $$ = build(O_WHATIS, $3); + $$ = build(O_WHATIS, $2); } | - WHEN stopaliasing event '{' actions '}' + WHEN event '{' actions '}' { - $$ = build(O_ADDEVENT, $3, $5); + $$ = build(O_ADDEVENT, $2, $4); } | - WHEREIS stopaliasing symbol -{ - $$ = build(O_WHEREIS, $3); -} -| - WHICH stopaliasing symbol -{ - $$ = build(O_WHICH, $3); -} -| - search_command -{ - $$ = $1; -} -; - - -search_command: - '/' pattern + WHEREIS name { - $$ = build(O_SEARCH, build(O_LCON, 1), $2); + $$ = build(O_WHEREIS, build(O_SYM, lookup($2))); } | - '?' pattern -{ - $$ = build(O_SEARCH, build(O_LCON, 0), $2); -} -; - -pattern: - STRING + WHICH symbol { - $$ = build(O_SCON, $1); -} -; - -integer_list: - INT -{ - $$ = build(O_LCON, $1); + $$ = build(O_WHICH, $2); } | - INT integer_list + '/' { - $$ = build(O_COMMA, build(O_LCON, $1), $2); -} -; - -signal_list: - signal -{ - $$ = build(O_COMMA, $1, nil); + $$ = build(O_SEARCH, + build(O_LCON, (long) '/'), + build(O_SCON, strdup(scanner_linebuf)) + ); + gobble(); + insertinput("\n"); } | - signal signal_list + '?' { - $$ = build(O_COMMA, $1, $2); + $$ = build(O_SEARCH, + build(O_LCON, (long) '?'), + build(O_SCON, strdup(scanner_linebuf)) + ); + gobble(); + insertinput("\n"); } ; - signal: INT { - if ($1 < 1 || $1 > NSIG) - error("Invalid signal %d.", $1); - $$ = build(O_LCON, $1); + $$ = $1; } | - NAME + name { - $$ = build(O_LCON, signalname(ident($1))); + $$ = siglookup(ident($1)); } ; - runcommand: run arglist | run ; - run: RUN shellmode { @@ -458,12 +433,12 @@ arglist: arg ; arg: - NAME + NAME { newarg(ident($1)); } | - STRING + STRING { newarg($1); } @@ -479,22 +454,22 @@ arg: } ; step: - STEP stopaliasing + STEP { $$ = build(O_STEP, true, false); } | - STEPI stopaliasing + STEPI { $$ = build(O_STEP, false, false); } | - NEXT stopaliasing + NEXT { $$ = build(O_STEP, true, true); } | - NEXTI stopaliasing + NEXTI { $$ = build(O_STEP, false, true); } @@ -503,7 +478,6 @@ shellmode: /* empty */ { beginshellmode(); - stopaliasing(); } ; sourcepath: @@ -546,9 +520,9 @@ cmd: * Redirectable commands. */ rcommand: - PRINT stopaliasing exp_list + PRINT exp_list { - $$ = build(O_PRINT, $3); + $$ = build(O_PRINT, $2); } | WHERE @@ -561,19 +535,34 @@ rcommand: $$ = $1; } | - CALL stopaliasing term '(' opt_exp_list ')' + CALL term '(' opt_exp_list ')' { - $$ = build(O_CALL, $3, $5); + $$ = build(O_CALLPROC, $2, $4); } | DEBUG INT { $$ = build(O_DEBUG, $2); } +| + DEBUG '-' INT +{ + $$ = build(O_DEBUG, -$3); +} +| + DUMP opt_qual_symbol +{ + $$ = build(O_DUMP, $2); +} +| + DUMP '.' +{ + $$ = build(O_DUMP, nil); +} | DUMP { - $$ = build(O_DUMP); + $$ = build(O_DUMP, build(O_SYM, curfunc)); } | STATUS @@ -582,51 +571,65 @@ rcommand: } ; alias_command: - alias name something + ALIAS name name { - $$ = build(O_ALIAS, build(O_NAME, $2), $3); + $$ = build(O_ALIAS, build(O_NAME, $2), build(O_NAME, $3)); } | - alias name + ALIAS name STRING +{ + $$ = build(O_ALIAS, build(O_NAME, $2), build(O_SCON, $3)); +} +| + ALIAS name '(' name_list ')' STRING +{ + $$ = build(O_ALIAS, + build(O_COMMA, build(O_NAME, $2), (Node) $4), + build(O_SCON, $6) + ); +} +| + ALIAS name { $$ = build(O_ALIAS, build(O_NAME, $2), nil); } | - alias + ALIAS { $$ = build(O_ALIAS, nil, nil); } ; - -alias: - ALIAS stopaliasing -; - -stopaliasing: - /* empty */ +name_list: + name_list ',' name { - stopaliasing(); + $$ = $1; + list_append(list_item($3), nil, $$); +} +| + name +{ + $$ = list_alloc(); + list_append(list_item($1), nil, $$); } ; - trace: - TRACE stopaliasing + TRACE { $$ = O_TRACE; } | - TRACEI stopaliasing + TRACEI { $$ = O_TRACEI; } ; stop: - STOP stopaliasing + STOP { $$ = O_STOP; } | - STOPI stopaliasing + STOPI { $$ = O_STOPI; } @@ -643,14 +646,14 @@ what: } ; where: - IN term + IN exp { - $$ = $2; + $$ = unrval($2); } | AT line_number { - $$ = build(O_QLINE, build(O_SCON, cursource), $2); + $$ = build(O_QLINE, build(O_SCON, strdup(cursource)), $2); } | AT STRING ':' line_number @@ -687,7 +690,7 @@ opt_exp_list: } ; list_command: - list + LIST { $$ = build(O_LIST, build(O_LCON, (long) cursrcline), @@ -695,26 +698,32 @@ list_command: ); } | - list line_number + LIST line_number { $$ = build(O_LIST, $2, $2); } | - list line_number ',' line_number + LIST line_number ',' line_number { $$ = build(O_LIST, $2, $4); } | - list symbol + LIST opt_qual_symbol { - $$ = build(O_LIST, $2, nil); + $$ = build(O_LIST, $2); } ; - -list: - LIST stopaliasing +integer_list: + INT +{ + $$ = build(O_LCON, $1); +} +| + INT integer_list +{ + $$ = build(O_COMMA, build(O_LCON, $1), $2); +} ; - line_number: INT { @@ -736,11 +745,6 @@ examine: { $$ = build(O_EXAMINE, $5, $1, $3, 0); } -| - '/' stopaliasing count mode -{ - $$ = build(O_EXAMINE, $4, build(O_LCON, (long) prtaddr), nil, $3); -} | address '=' mode { @@ -748,14 +752,19 @@ examine: } ; address: - INT stopaliasing + INT { $$ = build(O_LCON, $1); } | - '&' stopaliasing term + '.' +{ + $$ = build(O_LCON, (long) prtaddr); +} +| + '&' term { - $$ = amper($3); + $$ = amper($2); } | address '+' address @@ -773,14 +782,40 @@ address: $$ = build(O_MUL, $1, $3); } | - '*' stopaliasing address %prec UNARYSIGN + '*' address %prec UNARYSIGN +{ + $$ = build(O_INDIR, $2); +} +| + '-' address %prec UNARYSIGN +{ + $$ = build(O_NEG, $2); +} +| + '(' exp ')' +{ + $$ = $2; +} +; +term: + symbol +{ + $$ = $1; +} +| + term '.' name +{ + $$ = unrval(dot($1, $3)); +} +| + term ARROW name { - $$ = build(O_INDIR, $3); + $$ = unrval(dot($1, $3)); } | - '(' stopaliasing exp ')' + term '[' exp_list ']' { - $$ = $3; + $$ = unrval(subscript($1, $3)); } ; count: @@ -829,20 +864,55 @@ exp_list: } ; exp: - term + symbol { $$ = build(O_RVAL, $1); } | - constant + exp '[' exp_list ']' { - $$ = $1; + $$ = subscript(unrval($1), $3); +} +| + exp '.' name +{ + $$ = dot($1, $3); +} +| + exp ARROW name +{ + $$ = dot($1, $3); +} +| + '*' exp %prec UNARYSIGN +{ + $$ = build(O_INDIR, $2); +} +| + exp '^' %prec UNARYSIGN +{ + $$ = build(O_INDIR, $1); } | exp '\\' opt_qual_symbol { $$ = build(O_TYPERENAME, $1, $3); } +| + exp '\\' '&' opt_qual_symbol %prec '\\' +{ + $$ = renameptr($1, $4); +} +| + exp '(' opt_exp_list ')' +{ + $$ = build(O_CALL, unrval($1), $3); +} +| + constant +{ + $$ = $1; +} | '+' exp %prec UNARYSIGN { @@ -944,57 +1014,6 @@ exp: $$ = $2; } ; -term: - symbol -{ - $$ = $1; -} -| - term '[' exp_list ']' -{ - $$ = subscript($1, $3); -} -| - term '.' name -{ - $$ = dot($1, $3); -} -| - term ARROW name -{ - $$ = dot($1, $3); -} -| - '*' term %prec UNARYSIGN -{ - $$ = build(O_INDIR, $2); -} -| - '*' '(' exp ')' %prec UNARYSIGN -{ - $$ = build(O_INDIR, $3); -} -| - term '^' %prec UNARYSIGN -{ - $$ = build(O_INDIR, $1); -} -| - '#' term %prec UNARYSIGN -{ - $$ = concrete($2); -} -| - '#' '(' exp ')' %prec UNARYSIGN -{ - $$ = concrete($3); -} -| - term '(' opt_exp_list ')' -{ - $$ = build(O_CALL, $1, $3); -} -; boolean_exp: exp { @@ -1007,6 +1026,11 @@ constant: { $$ = build(O_LCON, $1); } +| + CHAR +{ + $$ = build(O_CCON, $1); +} | REAL { @@ -1032,7 +1056,10 @@ opt_qual_symbol: symbol: name { - $$ = build(O_SYM, which($1)); + $$ = findvar($1); + if ($$ == nil) { + $$ = build(O_SYM, which($1)); + } } | '.' name @@ -1054,24 +1081,7 @@ keyword: ALIAS | AND | ASSIGN | AT | CALL | CATCH | CONT | DEBUG | DELETE | DIV | DOWN | DUMP | EDIT | FILE | FUNC | GRIPE | HELP | IGNORE | IN | LIST | MOD | NEXT | NEXTI | NIL | NOT | OR | PRINT | PSYM | QUIT | - RERUN | RETURN | RUN | SH | SKIP | SOURCE | STATUS | STEP | STEPI | - STOP | STOPI | TRACE | TRACEI | UP | - USE | WHATIS | WHEN | WHERE | WHEREIS | WHICH -; - -something: - NAME -{ - $$ = build(O_NAME, $1); -} -| - keyword -{ - $$ = build(O_NAME, $1); -} -| - STRING -{ - $$ = build(O_SCON, $1); -} + RERUN | RETURN | RUN | SET | SH | SKIP | SOURCE | STATUS | STEP | STEPI | + STOP | STOPI | TRACE | TRACEI | UNALIAS | UNSET | UP | USE | + WHATIS | WHEN | WHERE | WHEREIS | WHICH ; diff --git a/usr/src/old/dbx/coredump.c b/usr/src/old/dbx/coredump.c index 240ed8b5df..1b75fdd61d 100644 --- a/usr/src/old/dbx/coredump.c +++ b/usr/src/old/dbx/coredump.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)coredump.c 1.6 (Berkeley) %G%"; +static char sccsid[] = "@(#)coredump.c 1.7 (Berkeley) %G%"; + +static char rcsid[] = "$Header: coredump.c,v 1.5 84/12/26 10:38:56 linton Exp $"; /* * Deal with the core dump anachronism. @@ -39,30 +41,72 @@ private File objfile; private struct exec hdr; /* - * Read the user area information from the core dump. + * Special variables for debugging the kernel. */ -public coredump_xreadin(mask, reg, signo) -int *mask; -Word reg[]; -int *signo; +private integer masterpcbb; +private integer slr; +private struct pte *sbr; +private struct pcb pcb; + +private getpcb () { - register struct user *up; - register Word *savreg; - union { - struct user u; - char dummy[ctob(UPAGES)]; - } ustruct; + fseek(corefile, masterpcbb & ~0x80000000, 0); + get(corefile, pcb); + pcb.pcb_p0lr &= ~AST_CLR; + printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", + pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr + ); + setreg(0, pcb.pcb_r0); + setreg(1, pcb.pcb_r1); + setreg(2, pcb.pcb_r2); + setreg(3, pcb.pcb_r3); + setreg(4, pcb.pcb_r4); + setreg(5, pcb.pcb_r5); + setreg(6, pcb.pcb_r6); + setreg(7, pcb.pcb_r7); + setreg(8, pcb.pcb_r8); + setreg(9, pcb.pcb_r9); + setreg(10, pcb.pcb_r10); + setreg(11, pcb.pcb_r11); + setreg(ARGP, pcb.pcb_ap); + setreg(FRP, pcb.pcb_fp); + setreg(STKP, pcb.pcb_ksp); + setreg(PROGCTR, pcb.pcb_pc); +} - objfile = fopen(objname, "r"); - if (objfile == nil) { - fatal("can't read \"%s\"", objname); +public coredump_getkerinfo () +{ + Symbol s; + + s = lookup(identname("Sysmap", true)); + if (s == nil) { + panic("can't find 'Sysmap'"); } - get(objfile, hdr); - up = &(ustruct.u); - fread(up, ctob(UPAGES), 1, corefile); - savreg = (Word *) &(ustruct.dummy[ctob(UPAGES)]); - *mask = savreg[PS]; + sbr = (struct pte *) (s->symvalue.offset); + s = lookup(identname("Syssize", true)); + if (s == nil) { + panic("can't find 'Syssize'"); + } + slr = (integer) (s->symvalue.offset); + printf("sbr %lx slr %lx\n", sbr, slr); + s = lookup(identname("masterpaddr", true)); + if (s == nil) { + panic("can't find 'masterpaddr'"); + } + fseek( + corefile, + datamap.seekaddr + s->symvalue.offset&0x7fffffff - datamap.begin, + 0 + ); + get(corefile, masterpcbb); + masterpcbb = (masterpcbb&PG_PFNUM)*512; + getpcb(); +} + +private copyregs (savreg, reg) +Word savreg[], reg[]; +{ reg[0] = savreg[R0]; reg[1] = savreg[R1]; reg[2] = savreg[R2]; @@ -79,25 +123,74 @@ int *signo; reg[FRP] = savreg[FP]; reg[STKP] = savreg[SP]; reg[PROGCTR] = savreg[PC]; - *signo = up->u_arg[0]; - datamap.seekaddr = ctob(UPAGES); - stkmap.begin = MAXSTKADDR - ctob(up->u_ssize); - stkmap.end = MAXSTKADDR; - stkmap.seekaddr = datamap.seekaddr + ctob(up->u_dsize); - switch (hdr.a_magic) { - case OMAGIC: - datamap.begin = 0; - datamap.end = ctob(up->u_tsize) + ctob(up->u_dsize); - break; +} - case NMAGIC: - case ZMAGIC: - datamap.begin = (Address) ptob(btop(ctob(up->u_tsize) - 1) + 1); - datamap.end = datamap.begin + ctob(up->u_dsize); - break; +/* + * Read the user area information from the core dump. + */ - default: - fatal("bad magic number 0x%x", hdr.a_magic); +public coredump_xreadin(mask, reg, signo) +int *mask; +Word reg[]; +int *signo; +{ + register struct user *up; + register Word *savreg; + union { + struct user u; + char dummy[ctob(UPAGES)]; + } ustruct; + Symbol s; + + objfile = fopen(objname, "r"); + if (objfile == nil) { + fatal("can't read \"%s\"", objname); + } + get(objfile, hdr); + if (vaddrs) { + datamap.begin = 0; + datamap.end = 0xffffffff; + stkmap.begin = 0xffffffff; + stkmap.end = 0xffffffff; + } else { + up = &(ustruct.u); + fread(up, ctob(UPAGES), 1, corefile); + savreg = (Word *) &(ustruct.dummy[ctob(UPAGES)]); + *mask = savreg[PS]; + copyregs(savreg, reg); + *signo = up->u_arg[0]; + datamap.seekaddr = ctob(UPAGES); + stkmap.begin = MAXSTKADDR - ctob(up->u_ssize); + stkmap.end = MAXSTKADDR; + stkmap.seekaddr = datamap.seekaddr + ctob(up->u_dsize); + switch (hdr.a_magic) { + case OMAGIC: + datamap.begin = 0; + datamap.end = ctob(up->u_tsize) + ctob(up->u_dsize); + break; + + case NMAGIC: + case ZMAGIC: + datamap.begin = (Address) ptob(btop(ctob(up->u_tsize) - 1) + 1); + datamap.end = datamap.begin + ctob(up->u_dsize); + break; + + default: + fatal("bad magic number 0x%x", hdr.a_magic); + } +#ifdef UXMAG + /* + * Core dump not from this object file? + */ + if (hdr.a_magic != 0 and up->u_exdata.ux_mag != 0 and + hdr.a_magic != up->u_exdata.ux_mag) { + warning("core dump ignored"); + coredump = false; + fclose(corefile); + fclose(objfile); + start(nil, nil, nil); + } +#endif } } @@ -111,7 +204,7 @@ char *buff; Address addr; int nbytes; { - if (hdr.a_magic == OMAGIC) { + if (hdr.a_magic == OMAGIC or vaddrs) { coredump_readdata(buff, addr, nbytes); } else { fseek(objfile, N_TXTOFF(hdr) + addr, 0); @@ -119,24 +212,155 @@ int nbytes; } } +/* + * Map a virtual address to a physical address. + */ + +private Address vmap (addr) +Address addr; +{ + Address r; + integer v, n; + struct pte pte; + + r = addr & ~0xc0000000; + v = btop(r); + switch (addr&0xc0000000) { + case 0xc0000000: + case 0x80000000: + /* + * In system space, so get system pte. + * If it is valid or reclaimable then the physical address + * is the combination of its page number and the page offset + * of the original address. + */ + if (v >= slr) { + error("address %x out of segment", addr); + } + r = ((long) (sbr + v)) & ~0x80000000; + goto simple; + + case 0x40000000: + /* + * In p1 space, must not be in shadow region. + */ + if (v < pcb.pcb_p1lr) { + error("address %x out of segment", addr); + } + r = (Address) (pcb.pcb_p1br + v); + break; + + case 0x00000000: + /* + * In p0 space, must not be off end of region. + */ + if (v >= pcb.pcb_p0lr) { + error("address %x out of segment", addr); + } + r = (Address) (pcb.pcb_p0br + v); + break; + + default: + /* do nothing */ + break; + } + /* + * For p0/p1 address, user-level page table should be in + * kernel virtual memory. Do second-level indirect by recursing. + */ + if ((r & 0x80000000) == 0) { + error("bad p0br or p1br in pcb"); + } + r = vmap(r); +simple: + /* + * "r" is now the address of the pte of the page + * we are interested in; get the pte and paste up the physical address. + */ + fseek(corefile, r, 0); + n = fread(&pte, sizeof(pte), 1, corefile); + if (n != 1) { + error("page table botch (fread at %x returns %d)", r, n); + } + if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { + error("page no valid or reclamable"); + } + return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); +} + public coredump_readdata(buff, addr, nbytes) char *buff; Address addr; int nbytes; { - if (addr < datamap.begin) { + Address a; + + a = addr; + if (a < datamap.begin) { if (hdr.a_magic == OMAGIC) { - error("data address 0x%x too low (lb = 0x%x)", addr, datamap.begin); + error("[data address 0x%x too low (lb = 0x%x)]", a, datamap.begin); + } else { + coredump_readtext(buff, a, nbytes); + } + } else if (a > stkmap.end) { + error("data address 0x%x too high (ub = 0x%x)", a, stkmap.end); + } else { + if (vaddrs) { + vreadfromfile(corefile, a, buff, nbytes); } else { - coredump_readtext(buff, addr, nbytes); + readfromfile(corefile, a, buff, nbytes); } - } else if (addr > stkmap.end) { - error("data address 0x%x too high (ub = 0x%x)", addr, stkmap.end); - } else if (addr < stkmap.begin) { - fseek(corefile, datamap.seekaddr + addr - datamap.begin, 0); - fread(buff, nbytes, sizeof(Byte), corefile); + } +} + +/* + * Read a block of data from a memory image, mapping virtual addresses. + * Have to watch out for page boundaries. + */ + +private vreadfromfile (corefile, v, buff, nbytes) +File corefile; +Address v; +char *buff; +integer nbytes; +{ + Address a; + integer i, remainder, pagesize; + char *bufp; + + a = v; + pagesize = (integer) ptob(1); + remainder = pagesize - (a mod pagesize); + if (remainder >= nbytes) { + readfromfile(corefile, vmap(a), buff, nbytes); + } else { + readfromfile(corefile, vmap(a), buff, remainder); + a += remainder; + i = nbytes - remainder; + bufp = buff + remainder; + while (i > pagesize) { + readfromfile(corefile, vmap(a), bufp, pagesize); + a += pagesize; + bufp += pagesize; + i -= pagesize; + } + readfromfile(corefile, vmap(a), bufp, i); + } +} + +private readfromfile (f, a, buff, nbytes) +File f; +Address a; +char *buff; +integer nbytes; +{ + integer fileaddr; + + if (a < stkmap.begin) { + fileaddr = datamap.seekaddr + a - datamap.begin; } else { - fseek(corefile, stkmap.seekaddr + addr - stkmap.begin, 0); - fread(buff, nbytes, sizeof(Byte), corefile); + fileaddr = stkmap.seekaddr + a - stkmap.begin; } + fseek(f, fileaddr, 0); + fread(buff, nbytes, sizeof(Byte), f); } diff --git a/usr/src/old/dbx/debug.c b/usr/src/old/dbx/debug.c index b1c88ec7da..af580af270 100644 --- a/usr/src/old/dbx/debug.c +++ b/usr/src/old/dbx/debug.c @@ -1,7 +1,8 @@ - /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)debug.c 1.4\t%G%"; +static char sccsid[] = "@(#)debug.c 1.5\t%G%"; + +static char rcsid[] = "$Header: debug.c,v 1.5 84/12/26 10:39:01 linton Exp $"; /* * Debug routines @@ -16,218 +17,111 @@ static char sccsid[] = "@(#)debug.c 1.4\t%G%"; #include "scanner.h" #include "source.h" #include "object.h" +#include "main.h" #include "mappings.h" #include "process.h" #include "machine.h" +#include "debug.h" #include +public boolean tracetree; /* trace building of parse trees */ +public boolean traceeval; /* trace tree evaluation */ -public int debug_flag[20]; +/* + * Dynamically turn on/off a debug flag, or display some information. + */ -public debug(p) +public debug (p) Node p; { - int code; - code = p->value.lcon; - - if ( (code >= 0) and (code < 10) ) { - switch(code) { - case 2: if(debug_flag[2]) debug_flag[2]=0; - else debug_flag[2] =1; - printf(" flag 2 is %d \n",debug_flag[2]); - break; - - case 3: if(debug_flag[3]) debug_flag[3]=0; - else debug_flag[3] =1; - printf(" flag 3 is %d \n",debug_flag[3]); - break; - - case 4: if(debug_flag[4]) debug_flag[4]=0; - else debug_flag[4] =1; - printf(" flag 4 is %d \n",debug_flag[4]); - break; - - case 5: if(debug_flag[5]) debug_flag[5]=0; - else debug_flag[5] =1; - printf(" flag 5 is %d \n",debug_flag[5]); - break; - - case 6: dumpfunctab(); - break; - - default: printf(" unknown debug code %ld \n",p->value.lcon); - break; - } - } - else if (debug_flag[3]) symbol_dump(code); - else if (debug_flag[4]) psym(code); -} - -public char *showoperator(op) -Operator op; -{ -static char *operator_str[] = { -"O_NOP", "O_NAME", "O_SYM", "O_LCON", "O_FCON", "O_SCON", "O_RVAL", "O_INDEX", -"O_INDIR", "O_DOT", "O_COMMA", "O_ITOF", "O_ADD", "O_ADDF", "O_SUB", "O_SUBF", -"O_NEG", "O_NEGF", "O_MUL", "O_MULF", "O_DIVF", "O_DIV", "O_MOD", "O_AND", -"O_OR", "O_LT", "O_LTF", "O_LE", "O_LEF", "O_GT", "O_GTF", "O_GE", "O_GEF", -"O_EQ", "O_EQF", "O_NE", "O_NEF", "O_ALIAS", "O_ASSIGN", "O_CALL", "O_CATCH", -"O_CHFILE", "O_CONT", "O_DEBUG", "O_DELETE", "O_DUMP", "O_EDIT", "O_FUNC", -"O_GRIPE", "O_HELP", "O_IGNORE", "O_LIST", "O_PRINT", "O_PSYM", "O_RUN", -"O_SKIP", "O_SOURCE", "O_STATUS", "O_STEP", "O_STOP", "O_STOPI", "O_TRACE", -"O_TRACEI", "O_WHATIS", "O_WHERE", "O_WHEREIS", "O_WHICH", "O_EXAMINE", -"O_ADDEVENT", "O_ENDX", "O_IF", "O_ONCE", "O_PRINTCALL", "O_PRINTIFCHANGED", -"O_PRINTRTN", "O_PRINTSRCPOS", "O_PROCRTN", "O_QLINE", "O_STOPIFCHANGED", -"O_STOPX", "O_TRACEON", "O_TRACEOFF", "O_TYPERENAME", "O_LASTOP" }; -return( operator_str[ord(op)] ); + int code; + + code = p->value.lcon; + switch (code) { + case 0: + puts("debugging flags:"); + puts(" 1 trace scanner return values"); + puts(" 2 trace breakpoints"); + puts(" 3 trace execution"); + puts(" 4 trace tree building"); + puts(" 5 trace tree evaluation"); + puts(" -[12345] turns off corresponding flag"); + puts(" 6 dump function table"); + break; + + case 1: + case -1: +# ifdef LEXDEBUG + lexdebug = (boolean) (code > 0); +# else + error("can't debug scanner (not compiled with LEXDEBUG)"); +# endif + break; + + case 2: + case -2: + tracebpts = (boolean) (code > 0); + break; + + case 3: + case -3: + traceexec = (boolean) (code > 0); + break; + + case 4: + case -4: + tracetree = (boolean) (code > 0); + break; + + case 5: + case -5: + traceeval = (boolean) (code > 0); + break; + + case 6: + dumpfunctab(); + break; + + default: + error("unknown debug flag"); + break; + } } -/* - * Dump a tree recursively - */ +private String leafname[] = { + "nop", "name", "sym", "lcon", "fcon", "scon", "rval", "index" +}; -public dumptree(f, p) -File f; -register Node p; +public String opname (op) +Operator op; { - register Node q; - Operator op; - static recurse =0; - ++recurse; - - if (p != nil) { - op = p->op; - if (ord(op) > ord(O_LASTOP)) { - panic("bad op %d in dumptree", p->op); - } - { int n_args; - fprintf(f, "\n level %d op %s node %ld ",recurse,showoperator(op), p); - for(n_args=0;n_args < nargs(op); n_args++) - fprintf(f," arg%d %ld ",n_args,p->value.arg[n_args]); - fprintf(f,"\n"); - } - if(p->nodetype) {fprintf(f,"nodetype: "); psym(p->nodetype);} - switch (op) { - case O_NAME: - fprintf(f, "%s", ident(p->value.name)); - break; - - case O_SYM: - printname(f, p->value.sym); - break; - - case O_QLINE: - if (nlhdr.nfiles > 1) { - dumptree(f, p->value.arg[0]); - fprintf(f, ":"); - } - dumptree(f, p->value.arg[1]); - break; - - case O_LCON: - if (compatible(p->nodetype, t_char)) { - fprintf(f, "'%c'", p->value.lcon); - } else { - fprintf(f, "%d", p->value.lcon); - } - break; - - case O_FCON: - fprintf(f, "%g", p->value.fcon); - break; - - case O_SCON: - fprintf(f, "\"%s\"", p->value.scon); - break; - - case O_INDEX: - dumptree(f, p->value.arg[0]); - fprintf(f, "["); - dumptree(f, p->value.arg[1]); - fprintf(f, "]"); - break; - - case O_COMMA: - dumptree(f, p->value.arg[0]); - if (p->value.arg[1] != nil) { - fprintf(f, ", "); - dumptree(f, p->value.arg[1]); - } - break; - - case O_RVAL: - if (p->value.arg[0]->op == O_SYM) { - printname(f, p->value.arg[0]->value.sym); - } else { - dumptree(f, p->value.arg[0]); - } - break; - - case O_ITOF: - dumptree(f, p->value.arg[0]); - break; - - case O_CALL: - dumptree(f, p->value.arg[0]); - if (p->value.arg[1]!= nil) { - fprintf(f, "("); - dumptree(f, p->value.arg[1]); - fprintf(f, ")"); - } - break; - - case O_INDIR: - q = p->value.arg[0]; - if (isvarparam(q->nodetype)) { - dumptree(f, q); - } else { - if (q->op == O_SYM or q->op == O_LCON or q->op == O_DOT) { - dumptree(f, q); - fprintf(f, "^"); - } else { - fprintf(f, "*("); - dumptree(f, q); - fprintf(f, ")"); - } - } - break; - - case O_DOT: - q = p->value.arg[0]; - if (q->op == O_INDIR) { - dumptree(f, q->value.arg[0]); - } else { - dumptree(f, q); - } - fprintf(f, ".%s", symname(p->value.arg[1]->value.sym)); - break; - - default: - switch (degree(op)) { - case BINARY: - dumptree(f, p->value.arg[0]); - fprintf(f, "%s", opinfo[ord(op)].opstring); - dumptree(f, p->value.arg[1]); - break; - - case UNARY: - fprintf(f, "%s", opinfo[ord(op)].opstring); - dumptree(f, p->value.arg[0]); - break; - - default: - if(degree(op) < ord(O_LASTOP) ) - { int i; - if( nargs(op) != 0) - for(i=0;ivalue.arg[i]); - } - else - error("internal error: bad op %d in dumptree", op); + String s; + static char buf[100]; + + switch (op) { + case O_ITOF: + s = "itof"; + break; + + case O_ENDX: + s = "endx"; + break; + + case O_QLINE: + s = "qline"; + break; + + default: + if (ord(op) <= ord(O_INDEX)) { + s = leafname[ord(op)]; + } else { + s = opinfo[ord(op)].opstring; + if (s == nil) { + sprintf(buf, "[op %d]", op); + s = buf; } - break; - } + } + break; } - recurse--; - fflush(f); + return s; } diff --git a/usr/src/old/dbx/defs.h b/usr/src/old/dbx/defs.h index 8c78302354..e7b06e3fad 100644 --- a/usr/src/old/dbx/defs.h +++ b/usr/src/old/dbx/defs.h @@ -1,4 +1,4 @@ -/* defs.h 1.3 84/08/12 */ +/* defs.h 1.4 85/03/01 */ /* * Public definitions, common to all. @@ -51,7 +51,6 @@ typedef char *String; #define strdup(s) strcpy(malloc((unsigned) strlen(s) + 1), s) #define streq(s1, s2) (strcmp(s1, s2) == 0) -#define strneq(s1, s2, n) (strncmp(s1, s2, n) == 0) typedef FILE *File; typedef int Fileid; diff --git a/usr/src/old/dbx/eval.c b/usr/src/old/dbx/eval.c index a944cb0969..38c6a1ff66 100644 --- a/usr/src/old/dbx/eval.c +++ b/usr/src/old/dbx/eval.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)eval.c 1.14 (Berkeley) %G%"; +static char sccsid[] = "@(#)eval.c 1.15 (Berkeley) %G%"; + +static char rcsid[] = "$Header: eval.c,v 1.5 84/12/26 10:39:08 linton Exp $"; /* * Tree evaluation. @@ -9,6 +11,7 @@ static char sccsid[] = "@(#)eval.c 1.14 (Berkeley) %G%"; #include "defs.h" #include "tree.h" #include "operators.h" +#include "debug.h" #include "eval.h" #include "events.h" #include "symbols.h" @@ -74,6 +77,25 @@ public Boolean useInstLoc = false; #define Boolrep char /* underlying representation type for booleans */ +/* + * Command-level evaluation. + */ + +public Node topnode; + +public topeval (p) +Node p; +{ + if (traceeval) { + fprintf(stderr, "topeval("); + prtree(stderr, p); + fprintf(stderr, ")\n"); + fflush(stderr); + } + topnode = p; + eval(p); +} + /* * Evaluate a parse tree leaving the value on the top of the stack. */ @@ -86,14 +108,15 @@ register Node p; Address addr; long i, n; int len; - Symbol s, f; + Symbol s; Node n1, n2; - Boolean b; + boolean b; File file; + String str; checkref(p); - if (debug_flag[2]) { - fprintf(stderr," evaluating %s \n",showoperator(p->op)); + if (traceeval) { + fprintf(stderr, "begin eval %s\n", opname(p->op)); } switch (degree(p->op)) { case BINARY: @@ -113,21 +136,26 @@ register Node p; s = p->value.sym; if (s == retaddrsym) { push(long, return_addr()); - } else { - if (isvariable(s)) { - if (s != program and not isactive(container(s))) { - error("\"%s\" is not active", symname(s)); - } - push(long, address(s, nil)); - } else if (isblock(s)) { - push(Symbol, s); + } else if (isvariable(s)) { + if (s != program and not isactive(container(s))) { + error("\"%s\" is not active", symname(s)); + } + if (isvarparam(s) and not isopenarray(s)) { + rpush(address(s, nil), sizeof(Address)); } else { - error("can't evaluate a %s", classname(s)); + push(Address, address(s, nil)); } + } else if (isblock(s)) { + push(Symbol, s); + } else if (isconst(s)) { + eval(constval(s)); + } else { + error("can't evaluate a %s", classname(s)); } break; case O_LCON: + case O_CCON: r0 = p->value.lcon; pushsmall(p->nodetype, r0); break; @@ -143,15 +171,19 @@ register Node p; break; case O_INDEX: - n = pop(long); - i = evalindex(p->value.arg[0]->nodetype, - popsmall(p->value.arg[1]->nodetype)); - push(long, n + i*size(p->nodetype)); + s = p->value.arg[0]->nodetype; + p->value.arg[0]->nodetype = t_addr; + eval(p->value.arg[0]); + p->value.arg[0]->nodetype = s; + n = pop(Address); + eval(p->value.arg[1]); + evalindex(s, n, popsmall(p->value.arg[1]->nodetype)); break; case O_DOT: s = p->value.arg[1]->value.sym; - n = lval(p->value.arg[0]); + eval(p->value.arg[0]); + n = pop(long); push(long, n + (s->symvalue.field.offset div 8)); break; @@ -166,25 +198,33 @@ register Node p; if (addr == 0) { error("reference through nil pointer"); } - if (p->op == O_INDIR) { - len = sizeof(long); - } else { - len = size(p->nodetype); - } + len = size(p->nodetype); rpush(addr, len); break; /* - * Effectively, we want to pop n bytes off for the evaluated subtree - * and push len bytes on for the new type of the same tree. + * Move the stack pointer so that the top of the stack has + * something corresponding to the size of the current node type. + * If this new type is bigger than the subtree (len > 0), + * then the stack is padded with nulls. If it's smaller, + * the stack is just dropped by the appropriate amount. */ case O_TYPERENAME: - n = size(p->value.arg[0]->nodetype); - len = size(p->nodetype); - sp = sp - n + len; + len = size(p->nodetype) - size(p->value.arg[0]->nodetype); + if (len > 0) { + for (n = 0; n < len; n++) { + *sp++ = '\0'; + } + } else if (len < 0) { + sp += len; + } break; case O_COMMA: + eval(p->value.arg[0]); + if (p->value.arg[1] != nil) { + eval(p->value.arg[1]); + } break; case O_ITOF: @@ -316,51 +356,11 @@ register Node p; break; case O_LIST: - if (p->value.arg[0]->op == O_SYM) { - f = p->value.arg[0]->value.sym; - addr = firstline(f); - if (addr == NOADDR) { - error("no source lines for \"%s\"", symname(f)); - } - setsource(srcfilename(addr)); - r0 = srcline(addr) - 5; - r1 = r0 + 10; - if (r0 < 1) { - r0 = 1; - } - } else { - eval(p->value.arg[0]); - r0 = pop(long); - eval(p->value.arg[1]); - r1 = pop(long); - } - printlines((Lineno) r0, (Lineno) r1); + list(p); break; case O_FUNC: - if (p->value.arg[0] == nil) { - printname(stdout, curfunc); - putchar('\n'); - } else { - s = p->value.arg[0]->value.sym; - if (isroutine(s)) { - setcurfunc(s); - } else { - find(f, s->name) where isroutine(f) endfind(f); - if (f == nil) { - error("%s is not a procedure or function", symname(s)); - } - setcurfunc(f); - } - addr = codeloc(curfunc); - if (addr != NOADDR) { - setsource(srcfilename(addr)); - cursrcline = srcline(addr) - 5; - if (cursrcline < 1) { - cursrcline = 1; - } - } - } + func(p->value.arg[0]); break; case O_EXAMINE: @@ -434,17 +434,17 @@ register Node p; case O_WHEREIS: if (p->value.arg[0]->op == O_SYM) { - printwhereis(stdout,p->value.arg[0]->value.sym); + printwhereis(stdout, p->value.arg[0]->value.sym); } else { - printwhereis(stdout,p->value.arg[0]->nodetype); + printwhereis(stdout, p->value.arg[0]->nodetype); } break; case O_WHICH: if (p->value.arg[0]->op == O_SYM) { - printwhich(stdout,p->value.arg[0]->value.sym); + printwhich(stdout, p->value.arg[0]->value.sym); } else { - printwhich(stdout,p->value.arg[0]->nodetype); + printwhich(stdout, p->value.arg[0]->nodetype); } putchar('\n'); break; @@ -452,21 +452,46 @@ register Node p; case O_ALIAS: n1 = p->value.arg[0]; n2 = p->value.arg[1]; - if (n1 == nil) { - print_alias(nil); - } else if (n2 == nil) { - print_alias(n1->value.name); + if (n2 == nil) { + if (n1 == nil) { + alias(nil, nil, nil); + } else { + alias(n1->value.name, nil, nil); + } + } else if (n2->op == O_NAME) { + str = ident(n2->value.name); + alias(n1->value.name, nil, strdup(str)); } else { - enter_alias(n1->value.name, n2); + if (n1->op == O_COMMA) { + alias( + n1->value.arg[0]->value.name, + (List) n1->value.arg[1], + n2->value.scon + ); + } else { + alias(n1->value.name, nil, n2->value.scon); + } } break; + case O_UNALIAS: + unalias(p->value.arg[0]->value.name); + break; + + case O_CALLPROC: + callproc(p, false); + break; + case O_CALL: - callproc(p->value.arg[0], p->value.arg[1]); + callproc(p, true); break; case O_CATCH: - catchsigs(p->value.arg[0]); + if (p->value.lcon == 0) { + printsigscaught(process); + } else { + psigtrace(process, p->value.lcon, true); + } break; case O_EDIT: @@ -484,7 +509,16 @@ register Node p; break; case O_DUMP: - dump(); + if (p->value.arg[0] == nil) { + dumpall(); + } else { + s = p->value.arg[0]->value.sym; + if (s == curfunc) { + dump(nil); + } else { + dump(s); + } + } break; case O_GRIPE: @@ -496,7 +530,11 @@ register Node p; break; case O_IGNORE: - ignoresigs(p->value.arg[0]); + if (p->value.lcon == 0) { + printsigsignored(process); + } else { + psigtrace(process, p->value.lcon, false); + } break; case O_RETURN: @@ -512,6 +550,14 @@ register Node p; run(); break; + case O_SET: + set(p->value.arg[0], p->value.arg[1]); + break; + + case O_SEARCH: + search(p->value.arg[0]->value.lcon, p->value.arg[1]->value.scon); + break; + case O_SOURCE: setinput(p->value.scon); break; @@ -530,6 +576,10 @@ register Node p; stop(p); break; + case O_UNSET: + undefvar(p->value.arg[0]->value.name); + break; + case O_UP: checkref(p->value.arg[0]); assert(p->value.arg[0]->op == O_LCON); @@ -593,8 +643,10 @@ register Node p; printf("tracei: "); printinst(pc, pc); } else { - printf("trace: "); - printlines(curline, curline); + if (canReadSource()) { + printf("trace: "); + printlines(curline, curline); + } } } else { printsrcpos(); @@ -631,10 +683,9 @@ register Node p; default: panic("eval: bad op %d", p->op); } - if(debug_flag[2]) { - fprintf(stderr," evaluated %s \n",showoperator(p->op)); - } - + if (traceeval) { + fprintf(stderr, "end eval %s\n", opname(p->op)); + } } /* @@ -716,23 +767,26 @@ long v; public long popsmall(t) Symbol t; { + register integer n; long r; - switch (size(t)) { - case sizeof(char): + n = size(t); + if (n == sizeof(char)) { + if (t->class == RANGE and t->symvalue.rangev.lower >= 0) { + r = (long) pop(unsigned char); + } else { r = (long) pop(char); - break; - - case sizeof(short): + } + } else if (n == sizeof(short)) { + if (t->class == RANGE and t->symvalue.rangev.lower >= 0) { + r = (long) pop(unsigned short); + } else { r = (long) pop(short); - break; - - case sizeof(long): - r = pop(long); - break; - - default: - panic("popsmall: size is %d", size(t)); + } + } else if (n == sizeof(long)) { + r = pop(long); + } else { + error("[internal error: size %d in popsmall]", n); } return r; } @@ -848,7 +902,7 @@ Node cond; Event e; if (exp->op == O_LCON) { - wh = build(O_QLINE, build(O_SCON, cursource), exp); + wh = build(O_QLINE, build(O_SCON, strdup(cursource)), exp); } else { wh = exp; } @@ -1091,48 +1145,131 @@ Node exp; long lvalue; float fvalue; - if (not compatible(var->nodetype, exp->nodetype)) { - error("incompatible types"); - } - addr = lval(var); - varsize = size(var->nodetype); - expsize = size(exp->nodetype); - eval(exp); - if (varsize == sizeof(float) and expsize == sizeof(double)) { - fvalue = (float) pop(double); - dwrite(&fvalue, addr, sizeof(fvalue)); + if (var->op == O_SYM and regnum(var->value.sym) != -1) { + eval(exp); + setreg(regnum(var->value.sym), pop(Address)); } else { - if (varsize < sizeof(long)) { - lvalue = 0; - popn(expsize, &lvalue); - switch (varsize) { - case sizeof(char): + addr = lval(var); + varsize = size(var->nodetype); + expsize = size(exp->nodetype); + eval(exp); + if (varsize == sizeof(float) and expsize == sizeof(double)) { + fvalue = (float) pop(double); + dwrite(&fvalue, addr, sizeof(fvalue)); + } else { + if (varsize < sizeof(long)) { + lvalue = 0; + popn(expsize, &lvalue); + if (varsize == sizeof(char)) { cvalue = lvalue; dwrite(&cvalue, addr, sizeof(cvalue)); - break; - - case sizeof(short): + } else if (varsize == sizeof(short)) { svalue = lvalue; dwrite(&svalue, addr, sizeof(svalue)); - break; - - default: - panic("bad size %d", varsize); + } else { + error("[internal error: bad size %d in assign]", varsize); + } + } else { + if (expsize <= varsize) { + sp -= expsize; + dwrite(sp, addr, expsize); + } else { + sp -= expsize; + dwrite(sp, addr, varsize); + } } + } + } +} + +/* + * Set a debugger variable. + */ + +private set (var, exp) +Node var, exp; +{ + Symbol t; + + if (var == nil) { + defvar(nil, nil); + } else if (exp == nil) { + defvar(var->value.name, nil); + } else if (var->value.name == identname("$frame", true)) { + t = exp->nodetype; + if (not compatible(t, t_int) and not compatible(t, t_addr)) { + error("$frame must be an address"); + } + eval(exp); + getnewregs(pop(Address)); + } else { + defvar(var->value.name, unrval(exp)); + } +} + +/* + * Execute a list command. + */ + +private list (p) +Node p; +{ + Symbol f; + Address addr; + Lineno line, l1, l2; + + if (p->value.arg[0]->op == O_SYM) { + f = p->value.arg[0]->value.sym; + addr = firstline(f); + if (addr == NOADDR) { + error("no source lines for \"%s\"", symname(f)); + } + setsource(srcfilename(addr)); + line = srcline(addr); + getsrcwindow(line, &l1, &l2); + } else { + eval(p->value.arg[0]); + l1 = (Lineno) (pop(long)); + eval(p->value.arg[1]); + l2 = (Lineno) (pop(long)); + } + printlines(l1, l2); +} + +/* + * Execute a func command. + */ + +private func (p) +Node p; +{ + Symbol s, f; + Address addr; + + if (p == nil) { + printname(stdout, curfunc); + putchar('\n'); + } else { + s = p->value.sym; + if (isroutine(s)) { + setcurfunc(s); } else { - if (expsize <= varsize) { - sp -= expsize; - dwrite(sp, addr, expsize); - } else { - sp -= expsize; - dwrite(sp, addr, varsize); + find(f, s->name) where isroutine(f) endfind(f); + if (f == nil) { + error("%s is not a procedure or function", symname(s)); } + setcurfunc(f); + } + addr = codeloc(curfunc); + if (addr != NOADDR) { + setsource(srcfilename(addr)); + cursrcline = srcline(addr); } } } /* - * Send some nasty mail to the current support person. + * Send a message to the current support person. */ public gripe() @@ -1142,14 +1279,13 @@ public gripe() int pid, status; extern int versionNumber; char subject[100]; - char *maintainer = "linton@berkeley"; puts("Type control-D to end your message. Be sure to include"); puts("your name and the name of the file you are debugging."); putchar('\n'); old = signal(SIGINT, SIG_DFL); - sprintf(subject, "dbx (version %d) gripe", versionNumber); - pid = back("Mail", stdin, stdout, "-s", subject, maintainer, nil); + sprintf(subject, "dbx (version 3.%d) gripe", versionNumber); + pid = back("Mail", stdin, stdout, "-s", subject, MAINTAINER, nil); signal(SIGINT, SIG_IGN); pwait(pid, &status); signal(SIGINT, old); @@ -1187,46 +1323,6 @@ public help() puts("quit - exit dbx"); } -/* - * Mark one or more signals to be - * intercepted by the debugger. - */ -private catchsigs(p) -register Node p; -{ - - if (p == nil) { - printsigscaught(process); - return; - } - while (p != nil) { - eval(p->value.arg[0]); - psigtrace(process, popsmall(p->value.arg[0]->nodetype), true); - p = p->value.arg[1]; - } -} - -/* - * Mark one or more signals to - * be ignored by the debugger - * (and automatically passed through - * to the running process). - */ -private ignoresigs(p) -register Node p; -{ - - if (p == nil) { - printsigsignored(process); - return; - } - while (p != nil) { - eval(p->value.arg[0]); - psigtrace(process, popsmall(p->value.arg[0]->nodetype), false); - p = p->value.arg[1]; - } -} - /* * Divert output to the given file name. * Cannot redirect to an existing file. diff --git a/usr/src/old/dbx/events.c b/usr/src/old/dbx/events.c index b36a05934d..97fdf568cb 100644 --- a/usr/src/old/dbx/events.c +++ b/usr/src/old/dbx/events.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)events.c 1.6 (Berkeley) %G%"; +static char sccsid[] = "@(#)events.c 1.7 (Berkeley) %G%"; + +static char rcsid[] = "$Header: events.c,v 1.5 84/12/26 10:39:26 linton Exp $"; /* * Event/breakpoint managment. @@ -23,9 +25,9 @@ static char sccsid[] = "@(#)events.c 1.6 (Berkeley) %G%"; typedef struct Event *Event; typedef struct Breakpoint *Breakpoint; -Boolean inst_tracing; -Boolean single_stepping; -Boolean isstopped; +boolean inst_tracing; +boolean single_stepping; +boolean isstopped; #include "symbols.h" @@ -41,7 +43,7 @@ Symbol retaddrsym; struct Event { unsigned int id; - Boolean temporary; + boolean temporary; Node condition; Cmdlist actions; }; @@ -51,6 +53,7 @@ struct Breakpoint { Address bpaddr; Lineno bpline; Cmdlist actions; + boolean temporary; }; typedef List Eventlist; @@ -61,8 +64,9 @@ typedef List Bplist; private Eventlist eventlist; /* list of active events */ private Bplist bplist; /* list of active breakpoints */ -private Integer eventid; /* id number of next allocated event */ -private Integer trid; /* id number of next allocated trace */ +private Event curevent; /* most recently created event */ +private integer eventid; /* id number of current event */ +private integer trid; /* id number of current trace */ typedef struct Trcmd { Integer trid; @@ -113,23 +117,20 @@ public bpinit() */ public Event event_alloc(istmp, econd, cmdlist) -Boolean istmp; +boolean istmp; Node econd; Cmdlist cmdlist; { register Event e; e = new(Event); - e->id = ++eventid; + ++eventid; + e->id = eventid; e->temporary = istmp; e->condition = econd; e->actions = cmdlist; - if (tracebpts) { - debugevent("event_alloc: new", e); - putchar('\n'); - fflush(stdout); - } eventlist_append(e, eventlist); + curevent = e; translate(e); return e; } @@ -153,8 +154,10 @@ unsigned int id; found = true; foreach (Breakpoint, bp, bplist) if (bp->event == e) { - if (tracebpts) - debugbpt("delevent: deleting", bp); + if (tracebpts) { + printf("deleting breakpoint at 0x%x\n", bp->bpaddr); + fflush(stdout); + } list_delete(list_curitem(bplist), bplist); } endfor @@ -322,11 +325,11 @@ Node exp; * This can only be done if there are no breakpoints within the function. */ -public Boolean canskip(f) +public boolean canskip(f) Symbol f; { Breakpoint p; - Boolean ok; + boolean ok; ok = true; foreach (Breakpoint, p, bplist) @@ -444,8 +447,15 @@ Cmdlist actions; p->bpaddr = addr; p->bpline = line; p->actions = actions; - if (tracebpts) - debugbpt("bp_alloc: new", p); + p->temporary = false; + if (tracebpts) { + if (e == nil) { + printf("new bp at 0x%x for event ??\n", addr, e->id); + } else { + printf("new bp at 0x%x for event %d\n", addr, e->id); + } + fflush(stdout); + } bplist_append(p, bplist); return p; } @@ -472,22 +482,33 @@ public bpfree() * and if so do the associated commands. */ -public Boolean bpact() +public boolean bpact() { register Breakpoint p; - Boolean found; + boolean found; integer eventId; found = false; foreach (Breakpoint, p, bplist) if (p->bpaddr == pc) { - if (tracebpts) - debugbpt("bpact: found", p); + if (tracebpts) { + printf("breakpoint for event %d found at location 0x%x\n", + p->event->id, pc); + } found = true; + if (p->event->temporary) { + if (not delevent(p->event->id)) { + printf("!! dbx.bpact: can't find event %d\n", + p->event->id); + } + } evalcmdlist(p->actions); - eventId = p->event->id; - if (p->event->temporary and not delevent(p->event->id)) - printf("!! dbx.bpact: can't find event %d\n", eventId); + if (isstopped) { + eventId = p->event->id; + } + if (p->temporary) { + list_delete(list_curitem(bplist), bplist); + } } endfor if (isstopped) { @@ -510,20 +531,26 @@ public Boolean bpact() */ public traceon(inst, event, cmdlist) -Boolean inst; +boolean inst; Event event; Cmdlist cmdlist; { register Trcmd trcmd; + Breakpoint bp; Cmdlist actions; Address ret; + Event e; + if (event == nil) { + e = curevent; + } else { + e = event; + } trcmd = new(Trcmd); - trcmd->trid = ++trid; - trcmd->event = event; + ++trid; + trcmd->trid = trid; + trcmd->event = e; trcmd->cmdlist = cmdlist; - if (tracebpts) - debugtrace("traceon: adding", trcmd); single_stepping = true; if (inst) { inst_tracing = true; @@ -533,16 +560,12 @@ Cmdlist cmdlist; } ret = return_addr(); if (ret != 0) { - /* - * Must create new temporary event for traceoff action; - * otherwise traceoff will take place but the breakpoint - * won't be deleted. This results in a panic the next - * time we enter the region where tracing takes place since - * the associate trace id (of the traceoff command) no - * longer exists. - */ - event_once(build(O_EQ, build(O_SYM, pcsym), build(O_LCON, ret)), - buildcmdlist(build(O_TRACEOFF, trcmd->trid))); + actions = buildcmdlist(build(O_TRACEOFF, trcmd->trid)); + bp = bp_alloc(e, (Address) ret, 0, actions); + bp->temporary = true; + } + if (tracebpts) { + printf("adding trace %d for event %d\n", trcmd->trid, e->id); } } @@ -555,7 +578,7 @@ public traceoff(id) Integer id; { register Trcmd t; - register Boolean found; + register boolean found; found = false; foreach (Trcmd, t, eachline) @@ -576,8 +599,8 @@ Integer id; } endfor if (not found) { - debugallevents("traceoff"); - panic("missing trid %d", id); + beginerrmsg(); + fprintf(stderr, "[internal error: trace id %d not found]\n", id); } } if (list_size(eachinst) == 0) { @@ -595,120 +618,13 @@ Integer id; private printrmtr(t) Trcmd t; { - if (tracebpts) - debugtrace("removing", t); -} - -/* - * Debugging routines. - */ -debugallevents(s) -String s; -{ - register Trcmd t; - register Event e; - register Breakpoint bp; - - if (s) - printf("%s:\n", s); - if (eachline) { - printf("Traces (eachline):\n"); - foreach (Trcmd, t, eachline) - debugtrace("\t", t); - endfor - } - if (eachinst) { - printf("Trace (eachinst):\n"); - foreach (Trcmd, t, eachinst) - debugtrace("\t", t); - endfor - } - if (bplist) { - printf("Breakpoints:\n"); - foreach (Breakpoint, bp, bplist) - debugbpt("\t", bp); - endfor - } - if (eventlist) { - printf("Events:\n"); - foreach (Event, e, eventlist) - debugevent("\t", e); - putchar('\n'); - endfor - } - fflush(stdout); -} - -private debugtrace(s, t) -String s; -Trcmd t; -{ - - if (s) - printf("%s ", s); - printf("trace %d ", t->trid); - debugevent("for", t->event); - printf("\n"); - fflush(stdout); -} - -private debugbpt(s, bp) -String s; -Breakpoint bp; -{ - - if (s) - printf("%s ", s); - debugevent("breakpoint for", bp->event); - printf("; loc 0x%x", bp->bpaddr); - if (bp->actions) - debugactions(" ", bp->actions, nil); - putchar('\n'); - fflush(stdout); -} - -private debugevent(s, e) -String s; -Event e; -{ - - if (s) - printf("%s ", s); - if (e == nil) { - printf("nil event"); - return; - } - if (e->temporary) - printf("temporary "); - printf("event %d", e->id); -} - -debugactions(s, cl, condition) -String s; -Cmdlist cl; -Node condition; -{ - Command c; - - if (s) - printf("%s ", s); - c = list_element(Command, list_head(cl)); - if (c->op == O_PRINTCALL) { - printf("trace "); - printname(stdout, c->value.sym); - return; + if (tracebpts) { + printf("removing trace %d", t->trid); + if (t->event != nil) { + printf(" for event %d", t->event->id); + } + printf("\n"); } - if (list_size(cl) > 1) - printf("{ "); - foreach (Command, c, cl) - printcmd(stdout, c); - if (not list_islast()) - printf("; "); - endfor - if (list_size(cl) > 1) - printf(" }"); - if (condition) - printcond(condition); } /* @@ -733,19 +649,19 @@ public printnews() * note it if we're tracing lines. */ -private Boolean chklist(); +private boolean chklist(); public callnews(iscall) -Boolean iscall; +boolean iscall; { if (not chklist(eachline, iscall)) { chklist(eachinst, iscall); } } -private Boolean chklist(list, iscall) +private boolean chklist(list, iscall) List list; -Boolean iscall; +boolean iscall; { register Trcmd t; register Command cmd; @@ -799,7 +715,7 @@ private Trinfo findtrinfo(p) Node p; { register Trinfo tp; - Boolean isnew; + boolean isnew; isnew = true; if (trinfolist == nil) { @@ -827,12 +743,6 @@ Node p; return tp; } -#define cast(size, loc, val) \ - switch (size) { \ - case sizeof (char): *(char *)(loc) = (val); break; \ - case sizeof (short): *(short *)(loc) = (val); break; \ - default: *(int *)(loc) = (val); break; \ - } /* * Print out the value of a variable if it has changed since the * last time we checked. @@ -844,22 +754,20 @@ Node p; register Trinfo tp; register int n; char buff[MAXTRSIZE]; + Filename curfile; static Lineno prevline; + static Filename prevfile; tp = findtrinfo(p); n = size(p->nodetype); - if (p->op == O_SYM and isreg(p->value.sym)) { - int regval = address(p->value.sym, nil); - - cast(n, buff, regval); - } else - dread(buff, tp->traddr, n); + dread(buff, tp->traddr, n); + curfile = srcfilename(pc); if (tp->trvalue == nil) { tp->trvalue = newarr(char, n); mov(buff, tp->trvalue, n); mov(buff, sp, n); sp += n; - printf("initially (at line %d):\t", curline); + printf("initially (at line %d in \"%s\"):\t", curline, curfile); prtree(stdout, p); printf(" = "); printval(p->nodetype); @@ -868,13 +776,14 @@ Node p; mov(buff, tp->trvalue, n); mov(buff, sp, n); sp += n; - printf("after line %d:\t", prevline); + printf("after line %d in \"%s\":\t", prevline, prevfile); prtree(stdout, p); printf(" = "); printval(p->nodetype); putchar('\n'); } prevline = curline; + prevfile = curfile; } /* diff --git a/usr/src/old/dbx/fortran.c b/usr/src/old/dbx/fortran.c index 0e286f62fe..8371409829 100644 --- a/usr/src/old/dbx/fortran.c +++ b/usr/src/old/dbx/fortran.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)fortran.c 1.5 (Berkeley) %G%"; +static char sccsid[] = "@(#)fortran.c 1.6 (Berkeley) %G%"; + +static char rcsid[] = "$Header: fortran.c,v 1.5 84/12/26 10:39:37 linton Exp $"; /* * FORTRAN dependent symbol routines. @@ -258,8 +260,8 @@ Symbol s; register Symbol t; register Address a; register int i, len; + double d1, d2; - /* printf("fortran_printval with class %s \n",classname(s)); OUT*/ switch (s->class) { case CONST: case TYPE: @@ -289,14 +291,17 @@ Symbol s; break; case sizeof(double): - if(istypename(s->type,"complex")) { - printf("("); - prtreal(pop(float)); - printf(","); - prtreal(pop(float)); - printf(")"); + if (istypename(s->type,"complex")) { + d2 = pop(float); + d1 = pop(float); + printf("("); + prtreal(d1); + printf(","); + prtreal(d2); + printf(")"); + } else { + prtreal(pop(double)); } - else prtreal(pop(double)); break; default: @@ -465,34 +470,45 @@ Node a, slist; * Evaluate a subscript index. */ -public int fortran_evalaref(s, i) +public fortran_evalaref(s, base, i) Symbol s; +Address base; long i; { - Symbol r; + Symbol r, t; long lb, ub; - r = rtype(s)->chain; - if(r->symvalue.rangev.lowertype == R_ARG or - r->symvalue.rangev.lowertype == R_TEMP ) { - if(! getbound(s,r->symvalue.rangev.lower, - r->symvalue.rangev.lowertype,&lb)) + t = rtype(s); + r = t->chain; + if ( + r->symvalue.rangev.lowertype == R_ARG or + r->symvalue.rangev.lowertype == R_TEMP + ) { + if (not getbound( + s, r->symvalue.rangev.lower, r->symvalue.rangev.lowertype, &lb + )) { error("dynamic bounds not currently available"); + } + } else { + lb = r->symvalue.rangev.lower; } - else lb = r->symvalue.rangev.lower; - - if(r->symvalue.rangev.uppertype == R_ARG or - r->symvalue.rangev.uppertype == R_TEMP ) { - if(! getbound(s,r->symvalue.rangev.upper, - r->symvalue.rangev.uppertype,&ub)) + if ( + r->symvalue.rangev.uppertype == R_ARG or + r->symvalue.rangev.uppertype == R_TEMP + ) { + if (not getbound( + s, r->symvalue.rangev.upper, r->symvalue.rangev.uppertype, &ub + )) { error("dynamic bounds not currently available"); + } + } else { + ub = r->symvalue.rangev.upper; } - else ub = r->symvalue.rangev.upper; if (i < lb or i > ub) { error("subscript out of range"); } - return (i - lb); + push(long, base + (i - lb) * size(t->type)); } private fortran_printarray(a) diff --git a/usr/src/old/dbx/keywords.c b/usr/src/old/dbx/keywords.c index 5db0e47d1f..5e0b359ad1 100644 --- a/usr/src/old/dbx/keywords.c +++ b/usr/src/old/dbx/keywords.c @@ -1,9 +1,11 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)keywords.c 1.6 (Berkeley) %G%"; +static char sccsid[] = "@(#)keywords.c 1.7 (Berkeley) %G%"; + +static char rcsid[] = "$Header: keywords.c,v 1.5 84/12/26 10:39:45 linton Exp $"; /* - * Keyword and alias management. + * Keywords, variables, and aliases (oh my!). */ #include "defs.h" @@ -12,10 +14,15 @@ static char sccsid[] = "@(#)keywords.c 1.6 (Berkeley) %G%"; #include "names.h" #include "symbols.h" #include "tree.h" +#include "lists.h" +#include "main.h" #include "y.tab.h" #ifndef public + #include "scanner.h" +#include "tree.h" + #endif private String reserved[] ={ @@ -24,236 +31,452 @@ private String reserved[] ={ "gripe", "help", "if", "ignore", "in", "list", "mod", "next", "nexti", "nil", "not", "or", "print", "psym", "quit", "rerun", "return", "run", - "sh", "skip", "source", "status", "step", "stepi", - "stop", "stopi", "trace", "tracei", "up", - "use", "whatis", "when", "where", "whereis", "which", - "INT", "REAL", "NAME", "STRING", - "LFORMER", "RFORMER", "#^", "->" + "set", "sh", "skip", "source", "status", "step", "stepi", + "stop", "stopi", "trace", "tracei", "unalias", "unset", "up", "use", + "whatis", "when", "where", "whereis", "which", + "INT", "CHAR", "REAL", "NAME", "STRING", "->" }; /* * The keyword table is a traditional hash table with collisions * resolved by chaining. */ + +#define HASHTABLESIZE 1007 + +typedef enum { ISKEYWORD, ISALIAS, ISVAR } KeywordType; + typedef struct Keyword { Name name; - Token toknum : 16; + KeywordType class : 16; + union { + /* ISKEYWORD: */ + Token toknum; + + /* ISALIAS: */ + struct { + List paramlist; + String expansion; + } alias; + + /* ISVAR: */ + Node var; + } value; struct Keyword *chain; } *Keyword; typedef unsigned int Hashvalue; -#define KEYWORDHASH 101 -private Keyword hashtab[KEYWORDHASH]; -#define keyhash(n) ((((unsigned) n) >> 2) mod KEYWORDHASH) +private Keyword hashtab[HASHTABLESIZE]; -/* - * The alias table is virtually the same, just - * replace the token id with a string to which - * the alias expands. - */ -typedef struct Alias { - Name name; - Name expansion; - struct Alias *chain; -} *Alias; - -#define ALIASHASH 503 -private Alias aliashashtab[ALIASHASH]; -#define aliashash(n) ((((unsigned) n) >> 2) mod ALIASHASH) +#define hash(n) ((((unsigned) n) >> 2) mod HASHTABLESIZE) /* * Enter all the reserved words into the keyword table. + * + * If the vaddrs flag is set (through the -k command line option) then + * set the special "$mapaddrs" variable. This assumes that the + * command line arguments are scanned before this routine is called. */ + public enterkeywords() { - register Integer i; + register integer i; - for (i = ALIAS; i <= WHICH; i++) + for (i = ALIAS; i <= WHICH; i++) { keyword(reserved[ord(i) - ord(ALIAS)], i); - keyword("set", ASSIGN); - - alias(identname("c", true), identname(keywdstring(CONT), true)); - alias(identname("d", true), identname(keywdstring(DELETE), true)); - alias(identname("h", true), identname(keywdstring(HELP), true)); - alias(identname("e", true), identname(keywdstring(EDIT), true)); - alias(identname("l", true), identname(keywdstring(LIST), true)); - alias(identname("n", true), identname(keywdstring(NEXT), true)); - alias(identname("p", true), identname(keywdstring(PRINT), true)); - alias(identname("q", true), identname(keywdstring(QUIT), true)); - alias(identname("r", true), identname(keywdstring(RUN), true)); - alias(identname("s", true), identname(keywdstring(STEP), true)); - alias(identname("st", true), identname(keywdstring(STOP), true)); - alias(identname("j", true), identname(keywdstring(STATUS), true)); - alias(identname("t", true), identname(keywdstring(WHERE), true)); + } + defalias("c", "cont"); + defalias("d", "delete"); + defalias("h", "help"); + defalias("e", "edit"); + defalias("l", "list"); + defalias("n", "next"); + defalias("p", "print"); + defalias("q", "quit"); + defalias("r", "run"); + defalias("s", "step"); + defalias("st", "stop"); + defalias("j", "status"); + defalias("t", "where"); + if (vaddrs) { + defvar(identname("$mapaddrs", true), nil); + } } /* - * Deallocate the keyword and alias tables. + * Deallocate the keyword table. */ + public keywords_free() { register Integer i; register Keyword k, nextk; - register Alias a, nexta; - for (i = 0; i < KEYWORDHASH; i++) { - for (k = hashtab[i]; k != nil; k = nextk) { + for (i = 0; i < HASHTABLESIZE; i++) { + k = hashtab[i]; + while (k != nil) { nextk = k->chain; dispose(k); + k = nextk; } hashtab[i] = nil; } - for (i = 0; i < ALIASHASH; i++) { - for (a = aliashashtab[i]; a != nil; a = nexta) { - nexta = a->chain; - dispose(a); +} + +/* + * Insert a name into the keyword table and return the keyword for it. + */ + +private Keyword keywords_insert (n) +Name n; +{ + Hashvalue h; + Keyword k; + + h = hash(n); + k = new(Keyword); + k->name = n; + k->chain = hashtab[h]; + hashtab[h] = k; + return k; +} + +/* + * Find the keyword associated with the given name. + */ + +private Keyword keywords_lookup (n) +Name n; +{ + Hashvalue h; + register Keyword k; + + h = hash(n); + k = hashtab[h]; + while (k != nil and k->name != n) { + k = k->chain; + } + return k; +} + +/* + * Delete the given keyword of the given class. + */ + +private boolean keywords_delete (n, class) +Name n; +KeywordType class; +{ + Hashvalue h; + register Keyword k, prevk; + boolean b; + + h = hash(n); + k = hashtab[h]; + prevk = nil; + while (k != nil and (k->name != n or k->class != class)) { + prevk = k; + k = k->chain; + } + if (k != nil) { + b = true; + if (prevk == nil) { + hashtab[h] = k->chain; + } else { + prevk->chain = k->chain; } - aliashashtab[i] = nil; + dispose(k); + } else { + b = false; } + return b; } /* - * Enter a keyword into the name table. - * It is assumed to not be there already. + * Enter a keyword into the table. It is assumed to not be there already. * The string is assumed to be statically allocated. */ -private keyword(s, t) + +private keyword (s, t) String s; Token t; { - register Keyword k; - Hashvalue h; + Keyword k; Name n; n = identname(s, true); - h = keyhash(n); - k = new(Keyword); - k->name = n; - k->toknum = t; - k->chain = hashtab[h]; - hashtab[h] = k; + k = keywords_insert(n); + k->class = ISKEYWORD; + k->value.toknum = t; } /* - * Return the string associated with a token corresponding to a keyword. + * Define a builtin command name alias. */ -public String keywdstring(t) -Token t; + +private defalias (s1, s2) +String s1, s2; { - return reserved[ord(t) - ord(ALIAS)]; + alias(identname(s1, true), nil, s2); } /* - * Return the token associated with a given keyword string. - * We assume that tokens cannot legitimately be nil (0). + * Look for a word of a particular class. */ -public Token findkeyword(n) +private Keyword findword (n, class) Name n; +KeywordType class; { register Keyword k; - for (k = hashtab[keyhash(n)]; k != nil && k->name != n; k = k->chain) - ; - return (k == nil ? nil : k->toknum); + k = keywords_lookup(n); + while (k != nil and (k->name != n or k->class != class)) { + k = k->chain; + } + return k; +} + +/* + * Return the token associated with a given keyword string. + * If there is none, return the given default value. + */ + +public Token findkeyword (n, def) +Name n; +Token def; +{ + Keyword k; + Token t; + + k = findword(n, ISKEYWORD); + if (k == nil) { + t = def; + } else { + t = k->value.toknum; + } + return t; } -public String findalias(n) +/* + * Return the associated string if there is an alias with the given name. + */ + +public boolean findalias (n, pl, str) Name n; +List *pl; +String *str; +{ + Keyword k; + boolean b; + + k = findword(n, ISALIAS); + if (k == nil) { + b = false; + } else { + *pl = k->value.alias.paramlist; + *str = k->value.alias.expansion; + } + return b; +} + +/* + * Return the string associated with a token corresponding to a keyword. + */ + +public String keywdstring (t) +Token t; +{ + return reserved[ord(t) - ord(ALIAS)]; +} + +/* + * Process an alias command, either entering a new alias or printing out + * an existing one. + */ + +public alias (newcmd, args, str) +Name newcmd; +List args; +String str; { - register Alias a; + Keyword k; - for (a = aliashashtab[aliashash(n)]; a != nil && a->name != n; a = a->chain) - ; - return (a == nil ? nil : ident(a->expansion)); + if (str == nil) { + print_alias(newcmd); + } else { + k = findword(newcmd, ISALIAS); + if (k == nil) { + k = keywords_insert(newcmd); + } + k->class = ISALIAS; + k->value.alias.paramlist = args; + k->value.alias.expansion = str; + } } /* - * Create an alias. + * Print out an alias. */ -public enter_alias(cmd, p) + +private print_alias (cmd) Name cmd; -Node p; { - Token t; + register Keyword k; + register Integer i; Name n; - t = findkeyword(cmd); - if (t != nil) { - error("\"%s\" can't alias a command", ident(cmd)); - return; + if (cmd == nil) { + for (i = 0; i < HASHTABLESIZE; i++) { + for (k = hashtab[i]; k != nil; k = k->chain) { + if (k->class == ISALIAS) { + if (isredirected()) { + printf("alias %s", ident(k->name)); + printparams(k->value.alias.paramlist); + printf("\t\"%s\"\n", k->value.alias.expansion); + } else { + printf("%s", ident(k->name)); + printparams(k->value.alias.paramlist); + printf("\t%s\n", k->value.alias.expansion); + } + } + } + } + } else { + k = findword(cmd, ISALIAS); + if (k == nil) { + printf("\n"); + } else { + printparams(k->value.alias.paramlist); + printf("%s\n", k->value.alias.expansion); + } } - if (p->op == O_SCON) - n = identname(p->value.scon, true); - else - n = identname(ident(p->value.name), true); - alias(cmd, n); } -private alias(cmd, n) -Name cmd, n; +private printparams (pl) +List pl; { - register Alias a; - Hashvalue h; + Name n; - h = aliashash(cmd); - for (a = aliashashtab[h]; a != nil && a->name != cmd; a = a->chain) - ; - if (a != nil) { - /* interpret ``alias x x'' as ``unalias x'' */ - if (streq(ident(cmd), ident(n))) - unalias(h, a); - else - a->expansion = n; - return; + if (pl != nil) { + printf("("); + foreach(Name, n, pl) + printf("%s", ident(n)); + if (not list_islast()) { + printf(", "); + } + endfor + printf(")"); } - if (!streq(ident(cmd), ident(n))) { /* as above */ - a = new(Alias); - a->name = cmd; - a->expansion = n; - a->chain = aliashashtab[h]; - aliashashtab[h] = a; +} + +/* + * Remove an alias. + */ + +public unalias (n) +Name n; +{ + if (not keywords_delete(n, ISALIAS)) { + error("%s is not aliased", ident(n)); } } -private unalias(h, a) -Alias a; -Hashvalue h; +/* + * Define a variable. + */ + +public defvar (n, val) +Name n; +Node val; { - register Alias *ap; + Keyword k; - for (ap = &aliashashtab[h]; *ap != nil && *ap != a; ap = &(*ap)->chain) - ; - assert(*ap == a); - *ap = a->chain; - dispose(a); + if (n == nil) { + print_vars(); + } else { + if (lookup(n) != nil) { + error("\"%s\" is a program symbol -- use assign", ident(n)); + } + k = findword(n, ISVAR); + if (k == nil) { + k = keywords_insert(n); + } + k->class = ISVAR; + k->value.var = val; + if (n == identname("$mapaddrs", true)) { + vaddrs = true; + } + } } /* - * Print out an alias. + * Return the value associated with a variable. */ -public print_alias(cmd) -Name cmd; + +public Node findvar (n) +Name n; { - register Alias a; - register Integer i; - String s; + Keyword k; + Node val; - if (cmd != nil) { - s = findalias(cmd); - if (s != nil) - printf("%s\n", s); - return; + k = findword(n, ISVAR); + if (k == nil) { + val = nil; + } else { + val = k->value.var; } - /* - * Dump the alias table. - */ - for (i = 0; i < ALIASHASH; i++) { - for (a = aliashashtab[i]; a != nil; a = a->chain) { - if (isredirected()) - printf("alias "); - printf("%s\t%s\n", ident(a->name), ident(a->expansion)); + return val; +} + +/* + * Return whether or not a variable is set. + */ + +public boolean varIsSet (s) +String s; +{ + return (boolean) (findword(identname(s, false), ISVAR) != nil); +} + +/* + * Delete a variable. + */ + +public undefvar (n) +Name n; +{ + if (not keywords_delete(n, ISVAR)) { + error("%s is not set", ident(n)); + } + if (n == identname("$mapaddrs", true)) { + vaddrs = false; + } +} + +/* + * Print out all the values of set variables. + */ + +private print_vars () +{ + register integer i; + register Keyword k; + + for (i = 0; i < HASHTABLESIZE; i++) { + for (k = hashtab[i]; k != nil; k = k->chain) { + if (k->class == ISVAR) { + if (isredirected()) { + printf("set "); + } + printf("%s", ident(k->name)); + if (k->value.var != nil) { + printf("\t"); + prtree(stdout, k->value.var); + } + printf("\n"); + } } } } diff --git a/usr/src/old/dbx/languages.c b/usr/src/old/dbx/languages.c index 6c0c7d4b1a..48ba0192a3 100644 --- a/usr/src/old/dbx/languages.c +++ b/usr/src/old/dbx/languages.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)languages.c 1.4 (Berkeley) %G%"; +static char sccsid[] = "@(#)languages.c 1.5 (Berkeley) %G%"; + +static char rcsid[] = "$Header: languages.c,v 1.5 84/12/26 10:39:49 linton Exp $"; /* * Language management. diff --git a/usr/src/old/dbx/library.c b/usr/src/old/dbx/library.c index e431b22634..c1d1561d75 100644 --- a/usr/src/old/dbx/library.c +++ b/usr/src/old/dbx/library.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)library.c 1.5 (Berkeley) %G%"; +static char sccsid[] = "@(#)library.c 1.6 (Berkeley) %G%"; + +static char rcsid[] = "$Header: library.c,v 1.5 84/12/26 10:39:52 linton Exp $"; /* * General purpose routines. @@ -394,6 +396,20 @@ public catcherrs() initErrInfo(); } +/* + * Turn off the error catching mechanism completely by having all errors + * ignored. This is most useful between a fork and an exec. + */ + +public nocatcherrs() +{ + integer i; + + for (i = 0; i < sys_nerr; i++) { + errinfo[i].func = ERR_IGNORE; + } +} + /* * Change the action on receipt of an error. */ diff --git a/usr/src/old/dbx/lists.c b/usr/src/old/dbx/lists.c index 9ae1137a9a..4ec65d3692 100644 --- a/usr/src/old/dbx/lists.c +++ b/usr/src/old/dbx/lists.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)lists.c 1.3 (Berkeley) %G%"; +static char sccsid[] = "@(#)lists.c 1.4 (Berkeley) %G%"; + +static char rcsid[] = "$Header: lists.c,v 1.5 84/12/26 10:40:00 linton Exp $"; /* * General list definitions. diff --git a/usr/src/old/dbx/main.c b/usr/src/old/dbx/main.c index be281dd098..698032bf79 100644 --- a/usr/src/old/dbx/main.c +++ b/usr/src/old/dbx/main.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)main.c 1.10 (Berkeley) %G%"; +static char sccsid[] = "@(#)main.c 1.11 (Berkeley) %G%"; + +static char rcsid[] = "$Header: main.c,v 1.5 84/12/26 10:40:16 linton Exp $"; /* * Debugger main routine. @@ -11,13 +13,17 @@ static char sccsid[] = "@(#)main.c 1.10 (Berkeley) %G%"; #include #include #include "main.h" +#include "eval.h" +#include "debug.h" #include "symbols.h" #include "scanner.h" +#include "keywords.h" #include "process.h" #include "runtime.h" #include "source.h" #include "object.h" #include "mappings.h" +#include "coredump.h" #ifndef public @@ -27,24 +33,25 @@ static char sccsid[] = "@(#)main.c 1.10 (Berkeley) %G%"; #include typedef struct { - struct sgttyb sg; /* standard sgttyb structure */ - struct tchars tc; /* terminal characters */ - struct ltchars ltc; /* local special characters */ - int ldisc; /* line discipline */ - int local; /* TIOCLGET */ - int fcflags; /* fcntl(2) F_GETFL, F_SETFL */ + struct sgttyb sg; /* standard sgttyb structure */ + struct tchars tc; /* terminal characters */ + struct ltchars ltc; /* local special characters */ + integer ldisc; /* line discipline */ + integer local; /* TIOCLGET */ + integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */ } Ttyinfo; #endif -public Boolean coredump; /* true if using a core dump */ -public Boolean runfirst; /* run program immediately */ -public Boolean interactive; /* standard input IS a terminal */ -public Boolean lexdebug; /* trace yylex return values */ -public Boolean tracebpts; /* trace create/delete breakpoints */ -public Boolean traceexec; /* trace process execution */ -public Boolean tracesyms; /* print symbols as their read */ -public Boolean traceblocks; /* trace blocks while reading symbols */ +public boolean coredump; /* true if using a core dump */ +public boolean runfirst; /* run program immediately */ +public boolean interactive; /* standard input IS a terminal */ +public boolean lexdebug; /* trace scanner return values */ +public boolean tracebpts; /* trace create/delete breakpoints */ +public boolean traceexec; /* trace execution */ +public boolean tracesyms; /* print symbols are they are read */ +public boolean traceblocks; /* trace blocks while reading symbols */ +public boolean vaddrs; /* map addresses through page tables */ public File corefile; /* File id of core dump */ @@ -52,10 +59,12 @@ public File corefile; /* File id of core dump */ private Boolean initdone = false; /* true if initialization done */ private jmp_buf env; /* setjmp/longjmp data */ +private char outbuf[BUFSIZ]; /* standard output buffer */ private char namebuf[512]; /* possible name of object file */ private int firstarg; /* first program argument (for -r) */ private Ttyinfo ttyinfo; +private String corename; /* name of core file */ private catchintr(); @@ -74,12 +83,13 @@ String argv[]; cmdname = argv[0]; catcherrs(); onsyserr(EINTR, nil); - setlinebuf(stderr); - printf("dbx version %d of %s.\nType 'help' for help.\n", + setbuf(stdout, outbuf); + printf("dbx version 3.%d of %s.\nType 'help' for help.\n", versionNumber, date); fflush(stdout); scanargs(argc, argv); language_init(); + symbols_init(); process_init(); if (runfirst) { if (setjmp(env) == FIRST_TIME) { @@ -99,12 +109,6 @@ String argv[]; restoretty(stdout, &ttyinfo); } signal(SIGINT, catchintr); - if (isterm(stdin)) { - printf("(%s) ", cmdname); - fflush(stdout); - } - endshellmode(); /* after an error longjmp */ - startaliasing(); yyparse(); putchar('\n'); quit(0); @@ -134,6 +138,10 @@ public init() printf("\n"); fflush(stdout); if (coredump) { + printf("[using memory image in %s]\n", corename); + if (vaddrs) { + coredump_getkerinfo(); + } setcurfunc(whatblock(pc)); } else { setcurfunc(program); @@ -187,7 +195,7 @@ String outfile; tmpfile = mktemp("/tmp/dbxXXXX"); setout(tmpfile); status(); - print_alias(nil); + alias(nil, nil, nil); if (argv != nil) { printf("run"); for (i = 1; argv[i] != nil; i++) { @@ -204,6 +212,7 @@ String outfile; unsetout(); bpfree(); objfree(); + symbols_init(); process_init(); enterkeywords(); scanner_init(); @@ -219,7 +228,8 @@ String outfile; } /* - * After a non-fatal error we jump back to command parsing. + * After a non-fatal error we skip the rest of the current input line, and + * jump back to command parsing. */ public erecover() @@ -236,6 +246,10 @@ public erecover() private catchintr() { + if (isredirected()) { + fflush(stdout); + unsetout(); + } putchar('\n'); longjmp(env, 1); } @@ -260,13 +274,14 @@ String argv[]; traceexec = false; tracesyms = false; traceblocks = false; + vaddrs = false; foundfile = false; corefile = nil; coredump = true; sourcepath = list_alloc(); list_append(list_item("."), nil, sourcepath); i = 1; - while (i < argc and (not foundfile or corefile == nil)) { + while (i < argc and (not foundfile or (coredump and corefile == nil))) { if (argv[i][0] == '-') { if (streq(argv[i], "-I")) { ++i; @@ -274,6 +289,12 @@ String argv[]; fatal("missing directory for -I"); } list_append(list_item(argv[i]), nil, sourcepath); + } else if (streq(argv[i], "-c")) { + ++i; + if (i >= argc) { + fatal("missing command file name for -c"); + } + initfile = argv[i]; } else { for (j = 1; argv[i][j] != '\0'; j++) { setoption(argv[i][j]); @@ -284,6 +305,7 @@ String argv[]; foundfile = true; } else if (coredump and corefile == nil) { corefile = fopen(argv[i], "r"); + corename = argv[i]; if (corefile == nil) { coredump = false; } @@ -314,9 +336,18 @@ String argv[]; list_append(list_item(tmp), nil, sourcepath); } if (coredump and corefile == nil) { - corefile = fopen("core", "r"); - if (corefile == nil) { - coredump = false; + if (vaddrs) { + corefile = fopen("/dev/mem", "r"); + corename = "/dev/mem"; + if (corefile == nil) { + panic("can't open /dev/mem"); + } + } else { + corefile = fopen("core", "r"); + corename = "core"; + if (corefile == nil) { + coredump = false; + } } } } @@ -354,8 +385,16 @@ char c; traceblocks = true; break; + case 'k': + vaddrs = true; + break; + case 'l': +# ifdef LEXDEBUG lexdebug = true; +# else + fatal("\"-l\" only applicable when compiled with LEXDEBUG"); +# endif break; default: diff --git a/usr/src/old/dbx/makedefs.c b/usr/src/old/dbx/makedefs.c index c032beb51b..9528bc0a68 100644 --- a/usr/src/old/dbx/makedefs.c +++ b/usr/src/old/dbx/makedefs.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)makedefs.c 1.3 (Berkeley) %G%"; +static char sccsid[] = "@(#)makedefs.c 1.4 (Berkeley) %G%"; + +static char rcsid[] = "$Header: makedefs.c,v 1.4 84/12/26 10:40:22 linton Exp $"; /* * Create a definitions file (e.g. .h) from an implementation file (e.g. .c). diff --git a/usr/src/old/dbx/mappings.c b/usr/src/old/dbx/mappings.c index c2ac1fcab2..c6adc09eaa 100644 --- a/usr/src/old/dbx/mappings.c +++ b/usr/src/old/dbx/mappings.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)mappings.c 1.5 (Berkeley) %G%"; +static char sccsid[] = "@(#)mappings.c 1.6 (Berkeley) %G%"; + +static char rcsid[] = "$Header: mappings.c,v 1.4 84/12/26 10:40:25 linton Exp $"; /* * Source-to-object and vice versa mappings. @@ -80,11 +82,12 @@ Address addr; * Find the line associated with the given address. * If the second parameter is true, then the address must match * a source line exactly. Otherwise the nearest source line - * below the given address is returned. In any case, if no suitable - * line exists, 0 is returned. + * below the given address is returned. + * + * Return the index of the line table entry or -1 if none suitable. */ -private Lineno findline(addr, exact) +private integer findline (addr, exact) Address addr; Boolean exact; { @@ -93,16 +96,16 @@ Boolean exact; register Address a; if (nlhdr.nlines == 0 or addr < linetab[0].addr) { - r = 0; + r = -1; } else { i = 0; j = nlhdr.nlines - 1; if (addr == linetab[i].addr) { - r = linetab[i].line; + r = i; } else if (addr == linetab[j].addr) { - r = linetab[j].line; + r = j; } else if (addr > linetab[j].addr) { - r = exact ? 0 : linetab[j].line; + r = exact ? -1 : j; } else { do { k = (i + j) div 2; @@ -115,13 +118,13 @@ Boolean exact; } } while (i <= j); if (a == addr) { - r = linetab[k].line; + r = k; } else if (exact) { - r = 0; + r = -1; } else if (addr > linetab[i].addr) { - r = linetab[i].line; + r = i; } else { - r = linetab[i-1].line; + r = i - 1; } } } @@ -129,13 +132,42 @@ Boolean exact; } /* - * Lookup the source line number nearest from below to an address. + * Lookup the source line number nearest (from below) to an address. + * + * It is possible (unfortunately) that the compiler will generate + * code before line number for a procedure. Therefore we check + * to see that the found line is in the same procedure as the given address. + * If it isn't, then we walk forward until the first suitable line is found. */ public Lineno srcline(addr) Address addr; { - return findline(addr, false); + integer i; + Lineno r; + Symbol f1, f2; + + i = findline(addr, false); + if (i == -1) { + r = 0; + } else { + r = linetab[i].line; + if (linetab[i].addr != addr) { + f1 = whatblock(addr); + if (nosource(f1)) { + r = 0; + } else { + f2 = whatblock(linetab[i].addr + 1); + if (f1 != f2) { + do { + ++i; + } while (linetab[i].addr < addr and i < nlhdr.nlines); + r = linetab[i].line; + } + } + } + } + return r; } /* @@ -145,7 +177,16 @@ Address addr; public Lineno linelookup(addr) Address addr; { - return findline(addr, true); + integer i; + Lineno r; + + i = findline(addr, true); + if (i == -1) { + r = 0; + } else { + r = linetab[i].line; + } + return r; } /* @@ -189,7 +230,7 @@ String name; } } if (not foundfile) { - error("unknown source file \"%s\"", name); + error("source file \"%s\" not compiled with -g", name); } return NOADDR; } @@ -198,19 +239,19 @@ String name; * Table for going from object addresses to the functions in which they belong. */ -#define MAXNFUNCS 1001 /* maximum number of functions allowed */ +#define NFUNCS 500 /* initial size of function table */ typedef struct { Symbol func; Address addr; } AddrOfFunc; -private AddrOfFunc functab[MAXNFUNCS]; -private int nfuncs; +private AddrOfFunc *functab; +private int nfuncs = 0; +private int functablesize = 0; /* * Insert a new function into the table. - * The table is ordered by object address. */ public newfunc(f, addr) @@ -218,9 +259,20 @@ Symbol f; Address addr; { register AddrOfFunc *af; + register int i; + AddrOfFunc *newfunctab; - if (nfuncs >= MAXNFUNCS) { - panic("too many procedures/functions"); + if (nfuncs >= functablesize) { + if (functablesize == 0) { + functab = newarr(AddrOfFunc, NFUNCS); + functablesize = NFUNCS; + } else { + functablesize *= 2; + newfunctab = newarr(AddrOfFunc, functablesize); + bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc)); + dispose(functab); + functab = newfunctab; + } } af = &functab[nfuncs]; af->func = f; diff --git a/usr/src/old/dbx/mkdate.c b/usr/src/old/dbx/mkdate.c index a0e374c981..5f2b58f8a8 100644 --- a/usr/src/old/dbx/mkdate.c +++ b/usr/src/old/dbx/mkdate.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)mkdate.c 1.3 (Berkeley) %G%"; +static char sccsid[] = "@(#)mkdate.c 1.4 (Berkeley) %G%"; + +static char rcsid[] = "$Header: mkdate.c,v 1.5 84/12/26 10:40:30 linton Exp $"; #include #include diff --git a/usr/src/old/dbx/names.c b/usr/src/old/dbx/names.c index 020bc86829..1e95b71ab7 100644 --- a/usr/src/old/dbx/names.c +++ b/usr/src/old/dbx/names.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)names.c 1.4 (Berkeley) %G%"; +static char sccsid[] = "@(#)names.c 1.5 (Berkeley) %G%"; + +static char rcsid[] = "$Header: names.c,v 1.4 84/12/26 10:40:47 linton Exp $"; /* * Name are the internal representation for identifiers. @@ -129,36 +131,22 @@ match: return n; } -/* - * Return the identifier associated with a name. - * - * Currently compiled inline. - * - * - * public String ident(n) -Name n; -{ - return (n == nil) ? "(noname)" : n->identifier; -} - * - */ - /* * Deallocate the name table. */ public names_free() { - register int i; - register Name n, next; + Namepool n, m; + register integer i; + n = namepool; + while (n != nil) { + m = n->prevpool; + dispose(n); + n = m; + } for (i = 0; i < HASHTABLESIZE; i++) { - n = nametable[i]; - while (n != nil) { - next = n->chain; - dispose(n); - n = next; - } nametable[i] = nil; } namepool = nil; diff --git a/usr/src/old/dbx/object.c b/usr/src/old/dbx/object.c index d8fcde2333..c26613b81b 100644 --- a/usr/src/old/dbx/object.c +++ b/usr/src/old/dbx/object.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)object.c 1.15 (Berkeley) %G%"; +static char sccsid[] = "@(#)object.c 1.16 (Berkeley) %G%"; + +static char rcsid[] = "$Header: object.c,v 1.6 84/12/26 10:40:51 linton Exp $"; /* * Object code interface, mainly for extraction of symbolic information. @@ -86,6 +88,17 @@ Symbol b; } } +/* + * Change the current block with saving the previous one, + * since it is assumed that the symbol for the current one is to be deleted. + */ + +public changeBlock (b) +Symbol b; +{ + curblock = b; +} + public enterblock (b) Symbol b; { @@ -159,10 +172,17 @@ String file; fatal("can't open %s", file); } read(f, &hdr, sizeof(hdr)); - objsize = hdr.a_text; - nlhdr.nsyms = hdr.a_syms / sizeof(nlist); - nlhdr.nfiles = nlhdr.nsyms; - nlhdr.nlines = nlhdr.nsyms; + if (N_BADMAG(hdr)) { + objsize = 0; + nlhdr.nsyms = 0; + nlhdr.nfiles = 0; + nlhdr.nlines = 0; + } else { + objsize = hdr.a_text; + nlhdr.nsyms = hdr.a_syms / sizeof(nlist); + nlhdr.nfiles = nlhdr.nsyms; + nlhdr.nlines = nlhdr.nsyms; + } if (nlhdr.nsyms > 0) { lseek(f, (long) N_STROFF(hdr), 0); read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); @@ -175,10 +195,29 @@ String file; ordfunctab(); setnlines(); setnfiles(); + } else { + initsyms(); } close(f); } +/* + * Found the beginning of the externals in the object file + * (signified by the "-lg" or find an external), close the + * block for the last procedure. + */ + +private foundglobals () +{ + if (curblock->class != PROG) { + exitblock(); + if (curblock->class != PROG) { + exitblock(); + } + } + enterline(0, (linep-1)->addr + 1); +} + /* * Read in symbols from object file. */ @@ -233,17 +272,13 @@ Fileid f; enter_nl(name, np); } else if (name[0] == '-') { afterlg = true; - if (curblock->class != PROG) { - exitblock(); - if (curblock->class != PROG) { - exitblock(); - } - } - enterline(0, (linep-1)->addr + 1); + foundglobals(); } else if (afterlg) { - if (name[0] == '_') { - check_global(&name[1], np); - } + check_global(name, np); + } else if ((np->n_type&N_EXT) == N_EXT) { + afterlg = true; + foundglobals(); + check_global(name, np); } else if (name[0] == '_') { check_local(&name[1], np); } else if ((np->n_type&N_TEXT) == N_TEXT) { @@ -252,9 +287,6 @@ Fileid f; ++curnp; np = curnp; } - if (not afterlg) { - fatal("not linked for debugging, use \"cc -g ...\""); - } dispose(namelist); } @@ -294,12 +326,6 @@ private initsyms () findbeginning(program); enterblock(program); curmodule = program; - t_boolean = maketype("$boolean", 0L, 1L); - t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); - t_char = maketype("$char", 0L, 255L); - t_real = maketype("$real", 8L, 0L); - t_nil = maketype("$nil", 0L, 0L); - t_open = maketype("integer", 0L, -1L); } /* @@ -309,9 +335,9 @@ private initsyms () public objfree () { symbol_free(); - keywords_free(); - names_free(); - dispose(stringtab); + /* keywords_free(); */ + /* names_free(); */ + /* dispose(stringtab); */ clrfunctab(); } @@ -428,29 +454,114 @@ register struct nlist *np; } /* - * Try to find the symbol that is referred to by the given name. - * Since it's an external, we may want to follow a level of indirection. + * Try to find the symbol that is referred to by the given name. Since it's + * an external, we need to follow a level or two of indirection. */ -private Symbol findsym (n) +private Symbol findsym (n, var_isextref) Name n; +boolean *var_isextref; { register Symbol r, s; + *var_isextref = false; find(s, n) where - s->level == program->level and - (s->class == EXTREF or s->class == VAR or - s->class == PROC or s->class == FUNC) + ( + s->level == program->level and ( + s->class == EXTREF or s->class == VAR or + s->class == PROC or s->class == FUNC + ) + ) or ( + s->block == program and s->class == MODULE + ) endfind(s); - if (s != nil and s->class == EXTREF) { + if (s == nil) { + r = nil; + } else if (s->class == EXTREF) { + *var_isextref = true; r = s->symvalue.extref; delete(s); + + /* + * Now check for another level of indirection that could come from + * a forward reference in procedure nesting information. In this case + * the symbol has already been deleted. + */ + if (r != nil and r->class == EXTREF) { + r = r->symvalue.extref; + } +/* + } else if (s->class == MODULE) { + s->class = FUNC; + s->level = program->level; + r = s; + */ } else { r = s; } return r; } +/* + * Create a symbol for a text symbol with no source information. + * We treat it as an assembly language function. + */ + +private Symbol deffunc (n) +Name n; +{ + Symbol f; + + f = insert(n); + f->language = findlanguage(".s"); + f->class = FUNC; + f->type = t_int; + f->block = curblock; + f->level = program->level; + f->symvalue.funcv.src = false; + f->symvalue.funcv.inline = false; + return f; +} + +/* + * Create a symbol for a data or bss symbol with no source information. + * We treat it as an assembly language variable. + */ + +private Symbol defvar (n) +Name n; +{ + Symbol v; + + v = insert(n); + v->language = findlanguage(".s"); + v->class = VAR; + v->type = t_int; + v->level = program->level; + v->block = curblock; + return v; +} + +/* + * Update a symbol entry with a text address. + */ + +private updateTextSym (s, name, addr) +Symbol s; +char *name; +Address addr; +{ + if (s->class == VAR) { + s->symvalue.offset = addr; + } else { + s->symvalue.funcv.beginaddr = addr; + if (name[0] == '_') { + newfunc(s, codeloc(s)); + findbeginning(s); + } + } +} + /* * Check to see if a global _name is already in the symbol table, * if not then insert it. @@ -462,27 +573,46 @@ register struct nlist *np; { register Name n; register Symbol t, u; + char buf[4096]; + boolean isextref; + integer count; - if (not streq(name, "end")) { - n = identname(name, true); + if (not streq(name, "_end")) { + if (name[0] == '_') { + n = identname(&name[1], true); + } else { + n = identname(name, true); + if (lookup(n) != nil) { + sprintf(buf, "$%s", name); + n = identname(buf, false); + } + } if ((np->n_type&N_TYPE) == N_TEXT) { - t = findsym(n); - if (t == nil) { - t = insert(n); - t->language = findlanguage(".s"); - t->class = FUNC; - t->type = t_int; - t->block = curblock; - t->level = program->level; - t->symvalue.funcv.src = false; - t->symvalue.funcv.inline = false; + count = 0; + t = findsym(n, &isextref); + while (isextref) { + ++count; + updateTextSym(t, name, np->n_value); + t = findsym(n, &isextref); } - if (t->class == VAR) { - t->symvalue.offset = np->n_value; - } else { - t->symvalue.funcv.beginaddr = np->n_value; - newfunc(t, codeloc(t)); - findbeginning(t); + if (count == 0) { + if (t == nil) { + t = deffunc(n); + updateTextSym(t, name, np->n_value); + if (tracesyms) { + printdecl(t); + } + } else { + if (t->class == MODULE) { + u = t; + t = deffunc(n); + t->block = u; + if (tracesyms) { + printdecl(t); + } + } + updateTextSym(t, name, np->n_value); + } } } else if ((np->n_type&N_TYPE) == N_BSS) { find(t, n) where @@ -508,24 +638,54 @@ register struct nlist *np; * If not, create a variable for the entry. In any case, * set the offset of the variable according to the value field * in the entry. + * + * If the external name has been referred to by several other symbols, + * we must update each of them. */ private check_var (np, n) struct nlist *np; register Name n; { - register Symbol t; + register Symbol t, u, next; + Symbol conflict; - t = findsym(n); + t = lookup(n); if (t == nil) { - t = insert(n); - t->language = findlanguage(".s"); - t->class = VAR; - t->type = t_int; - t->level = program->level; - t->block = curblock; + t = defvar(n); + t->symvalue.offset = np->n_value; + if (tracesyms) { + printdecl(t); + } + } else { + conflict = nil; + do { + next = t->next_sym; + if (t->name == n) { + if (t->class == MODULE and t->block == program) { + conflict = t; + } else if (t->class == EXTREF and t->level == program->level) { + u = t->symvalue.extref; + while (u != nil and u->class == EXTREF) { + u = u->symvalue.extref; + } + u->symvalue.offset = np->n_value; + delete(t); + } else if (t->level == program->level and + (t->class == VAR or t->class == PROC or t->class == FUNC) + ) { + conflict = nil; + t->symvalue.offset = np->n_value; + } + } + t = next; + } while (t != nil); + if (conflict != nil) { + u = defvar(n); + u->block = conflict; + u->symvalue.offset = np->n_value; + } } - t->symvalue.offset = np->n_value; } /* @@ -573,7 +733,8 @@ String name; { register String mname; register integer i; - register Symbol s; + Name n; + Symbol s; mname = strdup(name); i = strlen(mname) - 2; @@ -583,11 +744,15 @@ String name; while (mname[i] != '/' and i >= 0) { --i; } - s = insert(identname(&mname[i+1], true)); - s->language = findlanguage(".s"); - s->class = MODULE; - s->symvalue.funcv.beginaddr = 0; - findbeginning(s); + n = identname(&mname[i+1], true); + find(s, n) where s->block == program and s->class == MODULE endfind(s); + if (s == nil) { + s = insert(n); + s->language = findlanguage(".s"); + s->class = MODULE; + s->symvalue.funcv.beginaddr = 0; + findbeginning(s); + } if (curblock->class != PROG) { exitblock(); if (curblock->class != PROG) { diff --git a/usr/src/old/dbx/operators.c b/usr/src/old/dbx/operators.c index ff91a0a4e1..5baa04f589 100644 --- a/usr/src/old/dbx/operators.c +++ b/usr/src/old/dbx/operators.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)operators.c 1.8 (Berkeley) %G%"; +static char sccsid[] = "@(#)operators.c 1.9 (Berkeley) %G%"; + +static char rcsid[] = "$Header: operators.c,v 1.5 84/12/26 10:41:01 linton Exp $"; /* * Tree node classes. @@ -18,7 +20,7 @@ typedef struct { typedef enum { O_NOP, - O_NAME, O_SYM, O_LCON, O_FCON, O_SCON, + O_NAME, O_SYM, O_LCON, O_CCON, O_FCON, O_SCON, O_RVAL, O_INDEX, O_INDIR, O_DOT, O_COMMA, @@ -48,7 +50,6 @@ typedef enum { O_PRINT, /* print the values of a list of expressions */ O_PSYM, /* print symbol information */ O_RUN, /* start up program */ - O_SEARCH, /* regular expression search of source file */ O_SKIP, /* skip the current line */ O_SOURCE, /* read commands from a file */ O_STATUS, /* display currently active trace/stop's */ @@ -71,7 +72,7 @@ typedef enum { O_PRINTIFCHANGED, /* print the value of the argument if it has changed */ O_PRINTRTN, /* print out the routine and value that just returned */ O_PRINTSRCPOS, /* print out the current source position */ - O_PROCRTN, /* CALLPROC completed */ + O_PROCRTN, /* call completed */ O_QLINE, /* filename, line number */ O_STOPIFCHANGED, /* stop if the value of the argument has changed */ O_STOPX, /* stop execution */ @@ -83,6 +84,11 @@ typedef enum { O_RETURN, /* continue execution until procedure returns */ O_UP, /* move current function up the call stack */ O_DOWN, /* move current function down the call stack */ + O_CALLPROC, /* call command */ + O_SEARCH, /* regular expression pattern search through source */ + O_SET, /* set a debugger variable */ + O_UNSET, /* unset a debugger variable */ + O_UNALIAS, /* remove an alias */ O_LASTOP } Operator; @@ -121,13 +127,14 @@ public Opinfo opinfo[] ={ /* O_NAME */ -1, LEAF, 0, /* O_SYM */ -1, LEAF, 0, /* O_LCON */ -1, LEAF, 0, +/* O_CCON */ -1, LEAF, 0, /* O_FCON */ -1, LEAF, 0, /* O_SCON */ -1, LEAF, 0, /* O_RVAL */ 1, UNARY, 0, -/* O_INDEX */ 2, BINARY, 0, +/* O_INDEX */ 2, null, 0, /* O_INDIR */ 1, UNARY, "^", /* O_DOT */ 2, null, ".", -/* O_COMMA */ 2, BINARY, ",", +/* O_COMMA */ 2, null, ",", /* O_ITOF */ 1, UNARY|INTOP, 0, /* O_ADD */ 2, BINARY|INTOP, "+", /* O_ADDF */ 2, BINARY|REALOP, "+", @@ -156,24 +163,23 @@ public Opinfo opinfo[] ={ /* O_NEF */ 2, BINARY|REALOP, " <> ", /* O_ALIAS */ 2, null, "alias", -/* O_ASSIGN */ 2, BINARY, " := ", +/* O_ASSIGN */ 2, null, " := ", /* O_CALL */ 2, null, "call", -/* O_CATCH */ 1, null, "catch", +/* O_CATCH */ 0, null, "catch", /* O_CHFILE */ 0, null, "file", /* O_CONT */ 0, null, "cont", /* O_DEBUG */ 0, null, "debug", /* O_DELETE */ 1, null, "delete", -/* O_DUMP */ 0, null, "dump", +/* O_DUMP */ 1, null, "dump", /* O_EDIT */ 0, null, "edit", /* O_FUNC */ 1, null, "func", /* O_GRIPE */ 0, null, "gripe", /* O_HELP */ 0, null, "help", -/* O_IGNORE */ 1, null, "ignore", +/* O_IGNORE */ 0, null, "ignore", /* O_LIST */ 2, null, "list", /* O_PRINT */ 1, null, "print", /* O_PSYM */ 1, null, "psym", /* O_RUN */ 0, null, "run", -/* O_SEARCH */ 2, null, "search", /* O_SKIP */ 0, null, "skip", /* O_SOURCE */ 0, null, "source", /* O_STATUS */ 0, null, "status", @@ -202,9 +208,14 @@ public Opinfo opinfo[] ={ /* O_STOPX */ 0, null, "stop", /* O_TRACEON */ 1, null, "traceon", /* O_TRACEOFF */ 1, null, "traceoff", -/* O_TYPERENAME */ 2, UNARY, "typerename", +/* O_TYPERENAME */ 2, UNARY, "type rename", /* O_RERUN */ 0, null, "rerun", /* O_RETURN */ 1, null, "return", /* O_UP */ 1, UNARY, "up", /* O_DOWN */ 1, UNARY, "down", +/* O_CALLPROC */ 2, null, "call", +/* O_SEARCH */ 2, null, "search", +/* O_SET */ 2, null, "set", +/* O_UNSET */ 1, null, "unset", +/* O_UNALIAS */ 1, null, "unalias", }; diff --git a/usr/src/old/dbx/ops.c b/usr/src/old/dbx/ops.c index b32a0de971..1034c3cd33 100644 --- a/usr/src/old/dbx/ops.c +++ b/usr/src/old/dbx/ops.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)ops.c 1.4 (Berkeley) %G%"; +static char sccsid[] = "@(#)ops.c 1.5 (Berkeley) %G%"; + +static char rcsid[] = "$Header: ops.c,v 1.5 84/12/26 10:41:07 linton Exp $"; /* * Machine operators. diff --git a/usr/src/old/dbx/ops.vax.c b/usr/src/old/dbx/ops.vax.c index 6c305a09bb..ce6b7df02a 100644 --- a/usr/src/old/dbx/ops.vax.c +++ b/usr/src/old/dbx/ops.vax.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)ops.vax.c 1.4 (Berkeley) %G%"; +static char sccsid[] = "@(#)ops.vax.c 1.5 (Berkeley) %G%"; + +static char rcsid[] = "$Header: ops.c,v 1.5 84/12/26 10:41:07 linton Exp $"; /* * Machine operators. diff --git a/usr/src/old/dbx/pascal.c b/usr/src/old/dbx/pascal.c index 3658d81f09..6a1a633f9e 100644 --- a/usr/src/old/dbx/pascal.c +++ b/usr/src/old/dbx/pascal.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)pascal.c 1.3 (Berkeley) %G%"; +static char sccsid[] = "@(#)pascal.c 1.4 (Berkeley) %G%"; + +static char rcsid[] = "$Header: pascal.c,v 1.5 84/12/26 10:41:18 linton Exp $"; /* * Pascal-dependent symbol routines. @@ -21,6 +23,7 @@ static char sccsid[] = "@(#)pascal.c 1.3 (Berkeley) %G%"; #endif private Language pasc; +private boolean initialized; /* * Initialize Pascal information. @@ -37,58 +40,176 @@ public pascal_init() language_setop(pasc, L_MODINIT, pascal_modinit); language_setop(pasc, L_HASMODULES, pascal_hasmodules); language_setop(pasc, L_PASSADDR, pascal_passaddr); - initTypes(); + initialized = false; } /* - * Compatible tests if two types are compatible. The issue - * is complicated a bit by ranges. - * - * Integers and reals are not compatible since they cannot always be mixed. + * Typematch tests if two types are compatible. The issue + * is a bit complicated, so several subfunctions are used for + * various kinds of compatibility. */ -public Boolean pascal_typematch(type1, type2) -Symbol type1, type2; +private boolean builtinmatch (t1, t2) +register Symbol t1, t2; +{ + boolean b; + + b = (boolean) ( + ( + t2 == t_int->type and + t1->class == RANGE and istypename(t1->type, "integer") + ) or ( + t2 == t_char->type and + t1->class == RANGE and istypename(t1->type, "char") + ) or ( + t2 == t_real->type and + t1->class == RANGE and istypename(t1->type, "real") + ) or ( + t2 == t_boolean->type and + t1->class == RANGE and istypename(t1->type, "boolean") + ) + ); + return b; +} + +private boolean rangematch (t1, t2) +register Symbol t1, t2; { - Boolean b; - register Symbol t1, t2; - - t1 = rtype(t1); - t2 = rtype(t2); - b = (Boolean) - (t1->type == t2->type and ( - (t1->class == RANGE and t2->class == RANGE) or - (t1->class == SCAL and t2->class == CONST) or - (t1->class == CONST and t2->class == SCAL) or - (t1->type == t_char and t1->class == ARRAY and t2->class == ARRAY) - ) or + boolean b; + register Symbol rt1, rt2; + + if (t1->class == RANGE and t2->class == RANGE) { + rt1 = rtype(t1->type); + rt2 = rtype(t2->type); + b = (boolean) (rt1->type == rt2->type); + } else { + b = false; + } + return b; +} + +private boolean nilMatch (t1, t2) +register Symbol t1, t2; +{ + boolean b; + + b = (boolean) ( (t1 == t_nil and t2->class == PTR) or (t1->class == PTR and t2 == t_nil) ); return b; } -public pascal_printdecl(s) +private boolean enumMatch (t1, t2) +register Symbol t1, t2; +{ + boolean b; + + b = (boolean) ( + (t1->class == SCAL and t2->class == CONST and t2->type == t1) or + (t1->class == CONST and t2->class == SCAL and t1->type == t2) + ); + return b; +} + +private boolean isConstString (t) +register Symbol t; +{ + boolean b; + + b = (boolean) ( + t->language == primlang and t->class == ARRAY and t->type == t_char + ); + return b; +} + +private boolean stringArrayMatch (t1, t2) +register Symbol t1, t2; +{ + boolean b; + + b = (boolean) ( + ( + isConstString(t1) and + t2->class == ARRAY and compatible(t2->type, t_char->type) + ) or ( + isConstString(t2) and + t1->class == ARRAY and compatible(t1->type, t_char->type) + ) + ); + return b; +} + +public boolean pascal_typematch (type1, type2) +Symbol type1, type2; +{ + boolean b; + Symbol t1, t2, tmp; + + t1 = rtype(type1); + t2 = rtype(type2); + if (t1 == t2) { + b = true; + } else { + if (t1 == t_char->type or t1 == t_int->type or + t1 == t_real->type or t1 == t_boolean->type + ) { + tmp = t1; + t1 = t2; + t2 = tmp; + } + b = (Boolean) ( + builtinmatch(t1, t2) or rangematch(t1, t2) or + nilMatch(t1, t2) or enumMatch(t1, t2) or + stringArrayMatch(t1, t2) + ); + } + return b; +} + +/* + * Indent n spaces. + */ + +private indent (n) +int n; +{ + if (n > 0) { + printf("%*c", n, ' '); + } +} + +public pascal_printdecl (s) Symbol s; { register Symbol t; Boolean semicolon; semicolon = true; + if (s->class == TYPEREF) { + resolveRef(t); + } switch (s->class) { case CONST: if (s->type->class == SCAL) { - printf("(enumeration constant, ord %ld)", - s->symvalue.iconval); + semicolon = false; + printf("enum constant, ord "); + eval(s->symvalue.constval); + pascal_printval(s); } else { printf("const %s = ", symname(s)); - printval(s); + eval(s->symvalue.constval); + pascal_printval(s); } break; case TYPE: printf("type %s = ", symname(s)); - printtype(s, s->type); + printtype(s, s->type, 0); + break; + + case TYPEREF: + printf("type %s", symname(s)); break; case VAR: @@ -97,12 +218,12 @@ Symbol s; } else { printf("var %s : ", symname(s)); } - printtype(s, s->type); + printtype(s, s->type, 0); break; case REF: printf("(var parameter) %s : ", symname(s)); - printtype(s, s->type); + printtype(s, s->type, 0); break; case RANGE: @@ -110,18 +231,19 @@ Symbol s; case RECORD: case VARNT: case PTR: - printtype(s, s); + case FILET: + printtype(s, s, 0); semicolon = false; break; case FVAR: printf("(function variable) %s : ", symname(s)); - printtype(s, s->type); + printtype(s, s->type, 0); break; case FIELD: printf("(field) %s : ", symname(s)); - printtype(s, s->type); + printtype(s, s->type, 0); break; case PROC: @@ -131,25 +253,35 @@ Symbol s; case PROG: printf("program %s", symname(s)); - t = s->chain; - if (t != nil) { - printf("(%s", symname(t)); - for (t = t->chain; t != nil; t = t->chain) { - printf(", %s", symname(t)); - } - printf(")"); - } + listparams(s); break; case FUNC: printf("function %s", symname(s)); listparams(s); printf(" : "); - printtype(s, s->type); + printtype(s, s->type, 0); + break; + + case MODULE: + printf("module %s", symname(s)); + break; + + /* + * the parameter list of the following should be printed + * eventually + */ + case FPROC: + printf("procedure %s()", symname(s)); + break; + + case FFUNC: + printf("function %s()", symname(s)); break; default: - error("class %s in printdecl", classname(s)); + printf("%s : (class %s)", symname(s), classname(s)); + break; } if (semicolon) { putchar(';'); @@ -159,18 +291,22 @@ Symbol s; /* * Recursive whiz-bang procedure to print the type portion - * of a declaration. Doesn't work quite right for variant records. + * of a declaration. * * The symbol associated with the type is passed to allow * searching for type names without getting "type blah = blah". */ -private printtype(s, t) +private printtype (s, t, n) Symbol s; Symbol t; +int n; { register Symbol tmp; + if (t->class == TYPEREF) { + resolveRef(t); + } switch (t->class) { case VAR: case CONST: @@ -184,7 +320,7 @@ Symbol t; tmp = t->chain; if (tmp != nil) { for (;;) { - printtype(tmp, tmp); + printtype(tmp, tmp, n); tmp = tmp->chain; if (tmp == nil) { break; @@ -193,79 +329,62 @@ Symbol t; } } printf("] of "); - printtype(t, t->type); + printtype(t, t->type, n); break; case RECORD: - printf("record\n"); - if (t->chain != nil) { - printtype(t->chain, t->chain); - } - printf("end"); + printRecordDecl(t, n); break; case FIELD: if (t->chain != nil) { - printtype(t->chain, t->chain); + printtype(t->chain, t->chain, n); } printf("\t%s : ", symname(t)); - printtype(t, t->type); + printtype(t, t->type, n); printf(";\n"); break; - case RANGE: { - long r0, r1; - - r0 = t->symvalue.rangev.lower; - r1 = t->symvalue.rangev.upper; - if (t == t_char or istypename(t,"char")) { - if (r0 < 0x20 or r0 > 0x7e) { - printf("%ld..", r0); - } else { - printf("'%c'..", (char) r0); - } - if (r1 < 0x20 or r1 > 0x7e) { - printf("\\%lo", r1); - } else { - printf("'%c'", (char) r1); - } - } else if (r0 > 0 and r1 == 0) { - printf("%ld byte real", r0); - } else if (r0 >= 0) { - printf("%lu..%lu", r0, r1); - } else { - printf("%ld..%ld", r0, r1); - } + case RANGE: + printRangeDecl(t); break; - } case PTR: - putchar('*'); - printtype(t, t->type); + printf("^"); + printtype(t, t->type, n); break; case TYPE: - if (symname(t) != nil) { - printf("%s", symname(t)); + if (t->name != nil and ident(t->name)[0] != '\0') { + printname(stdout, t); } else { - printtype(t, t->type); + printtype(t, t->type, n); } break; case SCAL: - printf("("); - t = t->chain; - if (t != nil) { - printf("%s", symname(t)); - t = t->chain; - while (t != nil) { - printf(", %s", symname(t)); - t = t->chain; - } - } else { - panic("empty enumeration"); - } - printf(")"); + printEnumDecl(t, n); + break; + + case SET: + printf("set of "); + printtype(t, t->type, n); + break; + + case FILET: + printf("file of "); + printtype(t, t->type, n); + break; + + case TYPEREF: + break; + + case FPROC: + printf("procedure"); + break; + + case FFUNC: + printf("function"); break; default: @@ -274,6 +393,85 @@ Symbol t; } } +/* + * Print out a record declaration. + */ + +private printRecordDecl (t, n) +Symbol t; +int n; +{ + register Symbol f; + + if (t->chain == nil) { + printf("record end"); + } else { + printf("record\n"); + for (f = t->chain; f != nil; f = f->chain) { + indent(n+4); + printf("%s : ", symname(f)); + printtype(f->type, f->type, n+4); + printf(";\n"); + } + indent(n); + printf("end"); + } +} + +/* + * Print out the declaration of a range type. + */ + +private printRangeDecl (t) +Symbol t; +{ + long r0, r1; + + r0 = t->symvalue.rangev.lower; + r1 = t->symvalue.rangev.upper; + if (t == t_char or istypename(t, "char")) { + if (r0 < 0x20 or r0 > 0x7e) { + printf("%ld..", r0); + } else { + printf("'%c'..", (char) r0); + } + if (r1 < 0x20 or r1 > 0x7e) { + printf("\\%lo", r1); + } else { + printf("'%c'", (char) r1); + } + } else if (r0 > 0 and r1 == 0) { + printf("%ld byte real", r0); + } else if (r0 >= 0) { + printf("%lu..%lu", r0, r1); + } else { + printf("%ld..%ld", r0, r1); + } +} + +/* + * Print out an enumeration declaration. + */ + +private printEnumDecl (e, n) +Symbol e; +int n; +{ + Symbol t; + + printf("("); + t = e->chain; + if (t != nil) { + printf("%s", symname(t)); + t = t->chain; + while (t != nil) { + printf(", %s", symname(t)); + t = t->chain; + } + } + printf(")"); +} + /* * List the parameters of a procedure or function. * No attempt is made to combine like types. @@ -292,14 +490,6 @@ Symbol s; printf("var "); break; - case FPROC: - printf("procedure "); - break; - - case FFUNC: - printf("function "); - break; - case VAR: break; @@ -321,28 +511,44 @@ Symbol s; * in the format for the type of the given symbol. */ -public pascal_printval(s) +public pascal_printval (s) Symbol s; +{ + prval(s, size(s)); +} + +private prval (s, n) +Symbol s; +integer n; { Symbol t; Address a; - int len; + integer len; double r; + integer i; + if (s->class == TYPEREF) { + resolveRef(s); + } switch (s->class) { case CONST: case TYPE: - case VAR: case REF: + case VAR: case FVAR: case TAG: + prval(s->type, n); + break; + case FIELD: - pascal_printval(s->type); + prval(s->type, n); break; case ARRAY: t = rtype(s->type); - if (t->class==RANGE and istypename(t->type,"char")) { + if (t == t_char->type or + (t->class == RANGE and istypename(t->type, "char")) + ) { len = size(s); sp -= len; printf("'%.*s'", len, sp); @@ -357,91 +563,186 @@ Symbol s; break; case VARNT: - error("can't print out variant records"); + printf("[variant]"); break; - case RANGE: - if (s == t_boolean) { - printf(((Boolean) popsmall(s)) == true ? "true" : "false"); - } else if (s == t_char or istypename(s,"char")) { - printf("'%c'", pop(char)); - } else if (s->symvalue.rangev.upper == 0 and - s->symvalue.rangev.lower > 0) { - switch (s->symvalue.rangev.lower) { - case sizeof(float): - prtreal(pop(float)); - break; - - case sizeof(double): - prtreal(pop(double)); - break; + printrange(s, n); + break; - default: - panic("bad real size %d", s->symvalue.rangev.lower); - break; - } - } else if (s->symvalue.rangev.lower >= 0) { - printf("%lu", popsmall(s)); + case FILET: + a = pop(Address); + if (a == 0) { + printf("nil"); } else { - printf("%ld", popsmall(s)); + printf("0x%x", a); } break; - case FILET: - case PTR: { - Address addr; - - addr = pop(Address); - if (addr == 0) { - printf("0, (nil)"); + case PTR: + a = pop(Address); + if (a == 0) { + printf("nil"); } else { - printf("0x%x, 0%o", addr, addr); + printf("0x%x", a); } break; - } - - case SCAL: { - int scalar; - Boolean found; - - scalar = popsmall(s); - found = false; - for (t = s->chain; t != nil; t = t->chain) { - if (t->symvalue.iconval == scalar) { - printf("%s", symname(t)); - found = true; - break; - } - } - if (not found) { - printf("(scalar = %d)", scalar); + case SCAL: + i = 0; + popn(n, &i); + if (s->symvalue.iconval < 256) { + i &= 0xff; + } else if (s->symvalue.iconval < 65536) { + i &= 0xffff; } + printEnum(i, s); break; - } case FPROC: case FFUNC: - { - Address a; - - a = fparamaddr(pop(long)); + a = pop(long); t = whatblock(a); if (t == nil) { - printf("(proc %d)", a); + printf("(proc 0x%x)", a); } else { printf("%s", symname(t)); } break; - } + + case SET: + printSet(s); + break; default: if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { panic("printval: bad class %d", ord(s->class)); } - error("don't know how to print a %s", classname(s)); - /* NOTREACHED */ + printf("[%s]", classname(s)); + break; + } +} + +/* + * Print out the value of a scalar (non-enumeration) type. + */ + +private printrange (s, n) +Symbol s; +integer n; +{ + double d; + float f; + integer i; + + if (s->symvalue.rangev.upper == 0 and s->symvalue.rangev.lower > 0) { + if (n == sizeof(float)) { + popn(n, &f); + d = f; + } else { + popn(n, &d); + } + prtreal(d); + } else { + i = 0; + popn(n, &i); + printRangeVal(i, s); + } +} + +/* + * Print out a set. + */ + +private printSet (s) +Symbol s; +{ + Symbol t; + integer nbytes; + + nbytes = size(s); + t = rtype(s->type); + printf("["); + sp -= nbytes; + if (t->class == SCAL) { + printSetOfEnum(t); + } else if (t->class == RANGE) { + printSetOfRange(t); + } else { + error("internal error: expected range or enumerated base type for set"); + } + printf("]"); +} + +/* + * Print out a set of an enumeration. + */ + +private printSetOfEnum (t) +Symbol t; +{ + register Symbol e; + register integer i, j, *p; + boolean first; + + p = (int *) sp; + i = *p; + j = 0; + e = t->chain; + first = true; + while (e != nil) { + if ((i&1) == 1) { + if (first) { + first = false; + printf("%s", symname(e)); + } else { + printf(", %s", symname(e)); + } + } + i >>= 1; + ++j; + if (j >= sizeof(integer)*BITSPERBYTE) { + j = 0; + ++p; + i = *p; + } + e = e->chain; + } +} + +/* + * Print out a set of a subrange type. + */ + +private printSetOfRange (t) +Symbol t; +{ + register integer i, j, *p; + long v; + boolean first; + + p = (int *) sp; + i = *p; + j = 0; + v = t->symvalue.rangev.lower; + first = true; + while (v <= t->symvalue.rangev.upper) { + if ((i&1) == 1) { + if (first) { + first = false; + printf("%ld", v); + } else { + printf(", %ld", v); + } + } + i >>= 1; + ++j; + if (j >= sizeof(integer)*BITSPERBYTE) { + j = 0; + ++p; + i = *p; + } + ++v; } } @@ -457,15 +758,15 @@ Node a, slist; Symbol etype, atype, eltype; Node esub, r; - r = a; t = rtype(a->nodetype); - eltype = t->type; if (t->class != ARRAY) { beginerrmsg(); prtree(stderr, a); fprintf(stderr, " is not an array"); enderrmsg(); } else { + r = a; + eltype = t->type; p = slist; t = t->chain; for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { @@ -500,19 +801,21 @@ Node a, slist; * Evaluate a subscript index. */ -public int pascal_evalaref (s, i) +public pascal_evalaref (s, base, i) Symbol s; +Address base; long i; { + Symbol t; long lb, ub; - s = rtype(rtype(s)->chain); - lb = s->symvalue.rangev.lower; - ub = s->symvalue.rangev.upper; + t = rtype(s); + s = rtype(t->chain); + findbounds(s, &lb, &ub); if (i < lb or i > ub) { error("subscript %d out of range [%d..%d]", i, lb, ub); } - return (i - lb); + push(long, base + (i - lb) * size(t->type)); } /* @@ -521,31 +824,35 @@ long i; #define NTYPES 4 -private Symbol inittype[NTYPES]; -private integer count; +private Symbol inittype[NTYPES + 1]; -private addType (s, lower, upper) +private addType (n, s, lower, upper) +integer n; String s; long lower, upper; { register Symbol t; - if (count > NTYPES) { - panic("too many initial types"); + if (n > NTYPES) { + panic("initial Pascal type number too large for '%s'", s); } - t = maketype(s, lower, upper); + t = insert(identname(s, true)); t->language = pasc; - inittype[count] = t; - ++count; + t->class = TYPE; + t->type = newSymbol(nil, 0, RANGE, t, nil); + t->type->symvalue.rangev.lower = lower; + t->type->symvalue.rangev.upper = upper; + t->type->language = pasc; + inittype[n] = t; } private initTypes () { - count = 1; - addType("integer", 0x80000000L, 0x7fffffffL); - addType("char", 0L, 255L); - addType("boolean", 0L, 1L); - addType("real", 4L, 0L); + addType(1, "boolean", 0L, 1L); + addType(2, "char", 0L, 255L); + addType(3, "integer", 0x80000000L, 0x7fffffffL); + addType(4, "real", 8L, 0L); + initialized = true; } /* @@ -557,7 +864,11 @@ Symbol typetable[]; { register integer i; - for (i = 1; i < NTYPES; i++) { + if (not initialized) { + initTypes(); + initialized = true; + } + for (i = 1; i <= NTYPES; i++) { typetable[i] = inittype[i]; } } diff --git a/usr/src/old/dbx/printsym.c b/usr/src/old/dbx/printsym.c index 76bbb69a7a..8220860053 100644 --- a/usr/src/old/dbx/printsym.c +++ b/usr/src/old/dbx/printsym.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)printsym.c 1.13 (Berkeley) %G%"; +static char sccsid[] = "@(#)printsym.c 1.14 (Berkeley) %G%"; + +static char rcsid[] = "$Header: printsym.c,v 1.5 84/12/26 10:41:28 linton Exp $"; /* * Printing of symbolic information. @@ -17,6 +19,7 @@ static char sccsid[] = "@(#)printsym.c 1.13 (Berkeley) %G%"; #include "runtime.h" #include "machine.h" #include "names.h" +#include "keywords.h" #include "main.h" #ifndef public @@ -37,8 +40,9 @@ static char sccsid[] = "@(#)printsym.c 1.13 (Berkeley) %G%"; */ private String clname[] = { - "bad use", "constant", "type", "variable", "array", "fileptr", - "record", "field", "procedure", "function", "funcvar", + "bad use", "constant", "type", "variable", "array", "@dynarray", + "@subarray", "fileptr", "record", "field", + "procedure", "function", "funcvar", "ref", "pointer", "file", "set", "range", "label", "withptr", "scalar", "string", "program", "improper", "variant", "procparam", "funcparam", "module", "tag", "common", "extref", "typeref" @@ -58,7 +62,9 @@ public printentry(s) Symbol s; { if (s != program) { - printf("\nentering %s %s\n", classname(s), symname(s)); + printf("\nentering %s ", classname(s)); + printname(stdout, s); + printf("\n"); } } @@ -70,7 +76,9 @@ public printexit(s) Symbol s; { if (s != program) { - printf("leaving %s %s\n\n", classname(s), symname(s)); + printf("leaving %s ", classname(s)); + printname(stdout, s); + printf("\n\n"); } } @@ -81,9 +89,12 @@ Symbol s; public printcall(s, t) Symbol s, t; { - printf("calling %s", symname(s)); + printf("calling "); + printname(stdout, s); printparams(s, nil); - printf(" from %s %s\n", classname(t), symname(t)); + printf(" from %s ", classname(t)); + printname(stdout, t); + printf("\n"); } /* @@ -112,7 +123,9 @@ Symbol s; printf("(value too large) "); } } - printf("from %s\n", symname(s)); + printf("from "); + printname(stdout, s); + printf("\n"); } /* @@ -134,18 +147,22 @@ Frame frame; if (isinternal(f)) { n = 0; } + printf("("); param = f->chain; if (param != nil or n > 0) { - printf("("); m = n; if (param != nil) { for (;;) { - s = size(param) div sizeof(Word); + s = psize(param) div sizeof(Word); if (s == 0) { s = 1; } m -= s; - printv(param, frame); + if (showaggrs) { + printv(param, frame); + } else { + printparamv(param, frame); + } param = param->chain; if (param == nil) break; printf(", "); @@ -165,8 +182,8 @@ Frame frame; printf(", "); } } - printf(")"); } + printf(")"); } /* @@ -213,6 +230,42 @@ Symbol s; return b; } +/* + * Print out a parameter value. + * + * Since this is intended to be printed on a single line with other information + * aggregate values are not printed. + */ + +public printparamv (p, frame) +Symbol p; +Frame frame; +{ + Symbol t; + + t = rtype(p->type); + switch (t->class) { + case ARRAY: + case DYNARRAY: + case SUBARRAY: + t = rtype(t->type); + if (compatible(t, t_char)) { + printv(p, frame); + } else { + printf("%s = (...)", symname(p)); + } + break; + + case RECORD: + printf("%s = (...)", symname(p)); + break; + + default: + printv(p, frame); + break; + } +} + /* * Print the name and value of a variable. */ @@ -231,31 +284,19 @@ Frame frame; } else { printf("%s = ", symname(s)); } -/* - * Not today. - t = rtype(s->type); - if (t->class == ARRAY and not istypename(t->type, "char")) { - printf("ARRAY"); + if (isvarparam(s) and not isopenarray(s)) { + rpush(address(s, frame), sizeof(Address)); + addr = pop(Address); } else { - */ - if (isvarparam(s)) { - rpush(address(s, frame), sizeof(Address)); - addr = pop(Address); - len = size(s->type); - } else { - addr = address(s, frame); - len = size(s); - } - if (canpush(len)) { - rpush(addr, len); - printval(s->type); - } else { - printf("*** expression too large ***"); - } -/* - * Matches brace commented out above. - } - */ + addr = address(s, frame); + } + len = size(s); + if (canpush(len)) { + rpush(addr, len); + printval(s->type); + } else { + printf("*** expression too large ***"); + } } /* @@ -334,8 +375,15 @@ Symbol s; public printdecl(s) Symbol s; { + Language lang; + checkref(s); - (*language_op(s->language, L_PRINTDECL))(s); + if (s->language == nil or s->language == primlang) { + lang = findlanguage(".s"); + } else { + lang = s->language; + } + (*language_op(lang, L_PRINTDECL))(s); } /* @@ -365,6 +413,10 @@ Symbol s; } putchar('\n'); switch (s->class) { + case TYPE: + printf("size\t%d\n", size(s)); + break; + case VAR: case REF: if (s->level >= 3) { @@ -455,9 +507,7 @@ Symbol t; break; default: - if (t->language == nil) { - error("unknown language"); - } else if (t->language == primlang) { + if (t->language == nil or t->language == primlang) { (*language_op(findlanguage(".c"), L_PRINTVAL))(t); } else { (*language_op(t->language, L_PRINTVAL))(t); @@ -601,3 +651,100 @@ char c; printf("\\0%o",c); } } + +/* + * Print out a value for a range type (integer, char, or boolean). + */ + +public printRangeVal (val, t) +long val; +Symbol t; +{ + if (t == t_boolean->type or istypename(t->type, "boolean")) { + if ((boolean) val) { + printf("true"); + } else { + printf("false"); + } + } else if (t == t_char->type or istypename(t->type, "char")) { + if (varIsSet("$hexchars")) { + printf("0x%lx", val); + } else { + putchar('\''); + printchar(val); + putchar('\''); + } + } else if (varIsSet("$hexints")) { + printf("0x%lx", val); + } else if (t->symvalue.rangev.lower >= 0) { + printf("%lu", val); + } else { + printf("%ld", val); + } +} + +/* + * Print out an enumerated value by finding the corresponding + * name in the enumeration list. + */ + +public printEnum (i, t) +integer i; +Symbol t; +{ + register Symbol e; + + e = t->chain; + while (e != nil and e->symvalue.constval->value.lcon != i) { + e = e->chain; + } + if (e != nil) { + printf("%s", symname(e)); + } else { + printf("%d", i); + } +} + +/* + * Print out a null-terminated string (pointer to char) + * starting at the given address. + */ + +public printString (addr, quotes) +Address addr; +boolean quotes; +{ + register Address a; + register integer i, len; + register boolean endofstring; + union { + char ch[sizeof(Word)]; + int word; + } u; + + if (varIsSet("$hexstrings")) { + printf("0x%x", addr); + } else { + if (quotes) { + putchar('"'); + } + a = addr; + endofstring = false; + while (not endofstring) { + dread(&u, a, sizeof(u)); + i = 0; + do { + if (u.ch[i] == '\0') { + endofstring = true; + } else { + printchar(u.ch[i]); + } + ++i; + } while (i < sizeof(Word) and not endofstring); + a += sizeof(Word); + } + if (quotes) { + putchar('"'); + } + } +} diff --git a/usr/src/old/dbx/process.c b/usr/src/old/dbx/process.c index 06f35b764a..f6dd774826 100644 --- a/usr/src/old/dbx/process.c +++ b/usr/src/old/dbx/process.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)process.c 1.16 (Berkeley) %G%"; +static char sccsid[] = "@(#)process.c 1.17 (Berkeley) %G%"; + +static char rcsid[] = "$Header: process.c,v 1.5 84/12/26 10:41:37 linton Exp $"; /* * Process management. @@ -23,7 +25,6 @@ static char sccsid[] = "@(#)process.c 1.16 (Berkeley) %G%"; #include "coredump.h" #include #include -#include #include #include #include @@ -70,7 +71,7 @@ struct Process { Word oreg[NREG]; /* registers when process last stopped */ short status; /* either STOPPED or FINISHED */ short signo; /* signal that stopped process */ - short sigcode; /* auxiliary signal info code */ + short sigcode; /* extra signal information */ int exitval; /* return value from exit() */ long sigset; /* bit array of traced signals */ CacheWord word[CSIZE]; /* text segment cache */ @@ -87,7 +88,7 @@ typedef enum { TEXTSEG, DATASEG } PioSeg; private struct Process pbuf; -#define MAXNCMDARGS 100 /* maximum number of arguments to RUN */ +#define MAXNCMDARGS 1000 /* maximum number of arguments to RUN */ extern int errno; @@ -176,10 +177,10 @@ String infile, outfile; } else { argv[argc] = nil; } + pstart(process, argv, infile, outfile); if (remade(objname)) { reinit(argv, infile, outfile); } - pstart(process, argv, infile, outfile); if (process->status == STOPPED) { pc = 0; setcurfunc(program); @@ -309,9 +310,6 @@ typedef int Intfunc(); private Intfunc *dbintr; private intr(); -#define succeeds == true -#define fails == false - public cont(signo) integer signo; { @@ -336,7 +334,7 @@ integer signo; resume(s); unsetallbps(); s = DEFSIG; - if (bpact() fails) { + if (not isbperr() or not bpact()) { printstatus(); } } @@ -346,12 +344,12 @@ integer signo; } /* - * This routine is called if we get an interrupt while "running" px + * This routine is called if we get an interrupt while "running" * but actually in the debugger. Could happen, for example, while * processing breakpoints. * * We basically just want to keep going; the assumption is - * that when the process resumes it will get the interrupt + * that when the process resumes it will get the interrupt, * which will then be handled. */ @@ -381,7 +379,11 @@ int signo; if (p->signo != 0) { error("program terminated by signal %d", p->signo); } else if (not runfirst) { - error("program unexpectedly exited with %d", p->exitval); + if (p->exitval == 0) { + error("program exited"); + } else { + error("program exited with code %d", p->exitval); + } } } } @@ -457,7 +459,7 @@ Symbol f; contto(addr); } } - if (bpact() fails) { + if (not bpact()) { isstopped = true; printstatus(); } @@ -495,9 +497,8 @@ public stepover() } /* - * Resume execution up to the given address. It is assumed that - * no breakpoints exist between the current address and the one - * we're stepping to. This saves us from setting all the breakpoints. + * Resume execution up to the given address. We can either ignore + * breakpoints (stepto) or catch them (contto). */ public stepto(addr) @@ -611,16 +612,43 @@ Process p; } /* - * Return the signal number which stopped the process. + * Predicate to test if the reason the process stopped was because + * of a breakpoint. If so, as a side effect clear the local copy of + * signal handler associated with process. We must do this so as to + * not confuse future stepping or continuing by possibly concluding + * the process should continue with a SIGTRAP handler. */ -public Integer errnum(p) +public boolean isbperr() +{ + Process p; + boolean b; + + p = process; + if (p->status == STOPPED and p->signo == SIGTRAP) { + b = true; + p->sigstatus = 0; + } else { + b = false; + } + return b; +} + +/* + * Return the signal number that stopped the process. + */ + +public integer errnum (p) Process p; { return p->signo; } -public Integer errcode(p) +/* + * Return the signal code associated with the signal. + */ + +public integer errcode (p) Process p; { return p->sigcode; @@ -630,7 +658,7 @@ Process p; * Return the termination code of the process. */ -public Integer exitcode(p) +public integer exitcode (p) Process p; { return p->exitval; @@ -704,14 +732,16 @@ int nbytes; { Intfunc *f; - f = onsyserr(EIO, read_err); badaddr = addr; if (coredump) { + f = onsyserr(EFAULT, read_err); coredump_readdata(buff, addr, nbytes); + onsyserr(EFAULT, f); } else { + f = onsyserr(EIO, read_err); pio(process, PREAD, DATASEG, buff, addr, nbytes); + onsyserr(EIO, f); } - onsyserr(EIO, f); } /* @@ -769,10 +799,24 @@ private write_err() #define FIRSTSIG SIGINT #define LASTSIG SIGQUIT #define ischild(pid) ((pid) == 0) -#define traceme() ptrace(PT_TRACE_ME, 0, 0, 0) +#define traceme() ptrace(0, 0, 0, 0) #define setrep(n) (1 << ((n)-1)) #define istraced(p) (p->sigset&setrep(p->signo)) +/* + * Ptrace options (specified in first argument). + */ + +#define UREAD 3 /* read from process's user structure */ +#define UWRITE 6 /* write to process's user structure */ +#define IREAD 1 /* read from process's instruction space */ +#define IWRITE 4 /* write to process's instruction space */ +#define DREAD 2 /* read from process's data space */ +#define DWRITE 5 /* write to process's data space */ +#define CONT 7 /* continue stopped process */ +#define SSTEP 9 /* continue for approximately one instruction */ +#define PKILL 8 /* terminate the process */ + /* * Start up a new process by forking and exec-ing the * given argument list, returning when the process is loaded @@ -794,13 +838,16 @@ String outfile; if (p->pid != 0) { pterm(p); + cacheflush(p); } + fflush(stdout); psigtrace(p, SIGTRAP, true); p->pid = vfork(); if (p->pid == -1) { panic("can't fork"); } if (ischild(p->pid)) { + nocatcherrs(); traceme(); if (infile != nil) { infrom(infile); @@ -809,17 +856,16 @@ String outfile; outto(outfile); } execv(argv[0], argv); - write(2, "can't exec ", 11); - write(2, argv[0], strlen(argv[0])); - write(2, "\n", 1); _exit(1); } pwait(p->pid, &status); getinfo(p, status); if (p->status != STOPPED) { - error("program could not begin execution"); + beginerrmsg(); + fprintf(stderr, "warning: cannot execute %s\n", argv[0]); + } else { + ptraced(p->pid); } - ptraced(p->pid); } /* @@ -832,7 +878,7 @@ Process p; integer status; if (p != nil and p->pid != 0) { - ptrace(PT_KILL, p->pid, 0, 0); + ptrace(PKILL, p->pid, 0, 0); pwait(p->pid, &status); unptraced(p->pid); } @@ -855,7 +901,7 @@ int signo; int s, status; if (p->pid == 0) { - error("program not active"); + error("program is not active"); } s = signo; do { @@ -866,14 +912,15 @@ int signo; fflush(stdout); } sigs_off(); - if (ptrace(PT_CONTINUE, p->pid, p->reg[PROGCTR], p->signo) < 0) { + if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) { panic("error %d trying to continue process", errno); } pwait(p->pid, &status); sigs_on(); getinfo(p, status); - if (traceexec and not istraced(p)) { - printf("!! ignored signal %d at 0x%x\n", p->signo, p->reg[PROGCTR]); + if (p->status == STOPPED and traceexec and not istraced(p)) { + printf("!! ignored signal %d at 0x%x\n", + p->signo, p->reg[PROGCTR]); fflush(stdout); } s = p->signo; @@ -892,27 +939,41 @@ public pstep(p, signo) Process p; integer signo; { - int status; + int s, status; - setinfo(p, signo); - if (traceexec) { - printf("!! pstep from pc 0x%x with signal %d (%d)\n", - p->reg[PROGCTR], signo, p->signo); - fflush(stdout); - } - sigs_off(); - if (ptrace(PT_STEP, p->pid, p->reg[PROGCTR], p->signo) < 0) { - panic("error %d trying to step process", errno); - } - pwait(p->pid, &status); - sigs_on(); - getinfo(p, status); + s = signo; + do { + setinfo(p, s); + if (traceexec) { + printf("!! pstep from 0x%x with signal %d (%d)\n", + p->reg[PROGCTR], s, p->signo); + fflush(stdout); + } + sigs_off(); + if (ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo) < 0) { + panic("error %d trying to step process", errno); + } + pwait(p->pid, &status); + sigs_on(); + getinfo(p, status); + if (p->status == STOPPED and traceexec and not istraced(p)) { + printf("!! pstep ignored signal %d at 0x%x\n", + p->signo, p->reg[PROGCTR]); + fflush(stdout); + } + s = p->signo; + } while (p->status == STOPPED and not istraced(p)); if (traceexec) { - printf("!! pstep to pc 0x%x on signal %d\n", p->reg[PROGCTR], p->signo); + printf("!! pstep to 0x%x on signal %d\n", + p->reg[PROGCTR], p->signo); fflush(stdout); } if (p->status != STOPPED) { - error("program unexpectedly exited with %d\n", p->exitval); + if (p->exitval == 0) { + error("program exited\n"); + } else { + error("program exited with code %d\n", p->exitval); + } } } @@ -999,16 +1060,16 @@ register int status; } else { p->status = p->signo; p->signo = p->exitval; - p->sigcode = ptrace(PT_READ_U, p->pid, &((struct user *)0)->u_code, 0); + p->sigcode = ptrace(UREAD, p->pid, &((struct user *) 0)->u_code, 0); p->exitval = 0; - p->mask = ptrace(PT_READ_U, p->pid, regloc(PS), 0); + p->mask = ptrace(UREAD, p->pid, regloc(PS), 0); for (i = 0; i < NREG; i++) { - p->reg[i] = ptrace(PT_READ_U, p->pid, regloc(rloc[i]), 0); + p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0); p->oreg[i] = p->reg[i]; } savetty(stdout, &(p->ttyinfo)); addr = (Address) &(((struct user *) 0)->u_signal[p->signo]); - p->sigstatus = (Address) ptrace(PT_READ_U, p->pid, addr, 0); + p->sigstatus = (Address) ptrace(UREAD, p->pid, addr, 0); } } @@ -1032,7 +1093,7 @@ int signo; } for (i = 0; i < NREG; i++) { if ((r = p->reg[i]) != p->oreg[i]) { - ptrace(PT_WRITE_U, p->pid, regloc(rloc[i]), r); + ptrace(UWRITE, p->pid, regloc(rloc[i]), r); } } restoretty(stdout, &(p->ttyinfo)); @@ -1164,7 +1225,7 @@ register int addr; wp = &p->word[cachehash(addr)]; if (addr == 0 or wp->addr != addr) { ++nreads; - w = ptrace(PT_READ_I, p->pid, addr, 0); + w = ptrace(IREAD, p->pid, addr, 0); wp->addr = addr; wp->val = w; } else { @@ -1173,7 +1234,7 @@ register int addr; break; case DATASEG: - w = ptrace(PT_READ_D, p->pid, addr, 0); + w = ptrace(DREAD, p->pid, addr, 0); break; default: @@ -1202,11 +1263,11 @@ Word data; wp = &p->word[cachehash(addr)]; wp->addr = addr; wp->val = data; - ptrace(PT_WRITE_I, p->pid, addr, data); + ptrace(IWRITE, p->pid, addr, data); break; case DATASEG: - ptrace(PT_WRITE_D, p->pid, addr, data); + ptrace(DWRITE, p->pid, addr, data); break; default: @@ -1215,6 +1276,16 @@ Word data; } } +/* + * Flush the instruction cache associated with a process. + */ + +private cacheflush (p) +Process p; +{ + bzero(p->word, sizeof(p->word)); +} + public printptraceinfo() { printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites); @@ -1276,64 +1347,71 @@ Fileid newfd; } } -#define bit(i) (1 << ((i)-1)) /* - * Signal manipulation routines. + * Signal name manipulation. */ -static String signames[NSIG] = { - 0, - "HUP", - "INT", - "QUIT", - "ILL", - "TRAP", - "IOT", - "EMT", - "FPE", - "KILL", - "BUS", - "SEGV", - "SYS", - "PIPE", - "ALRM", - "TERM", - 0, - "STOP", - "TSTP", - "CONT", - "CHLD", - "TTIN", - "TTOU", - "TINT", - "XCPU", - "XFSZ", + +private String signames[NSIG] = { + 0, + "HUP", "INT", "QUIT", "ILL", "TRAP", + "IOT", "EMT", "FPE", "KILL", "BUS", + "SEGV", "SYS", "PIPE", "ALRM", "TERM", + 0, "STOP", "TSTP", "CONT", "CHLD", + "TTIN", "TTOU", "TINT", "XCPU", "XFSZ", }; /* - * Map a signal name to a number. + * Get the signal number associated with a given name. + * The name is first translated to upper case if necessary. */ -public signalname(s) + +public integer siglookup (s) String s; { - register String *p; - - if (strneq(s, "SIG", 3)) - s += 3; - for (p = signames; p < &signames[NSIG]; p++) - if (*p && streq(*p, s)) - return (p - signames); - error("%s: Unknown signal.", s); + register char *p, *q; + char buf[100]; + integer i; + + p = s; + q = buf; + while (*p != '\0') { + if (*p >= 'a' and *p <= 'z') { + *q = (*p - 'a') + 'A'; + } else { + *q = *p; + } + ++p; + ++q; + } + *q = '\0'; + p = buf; + if (buf[0] == 'S' and buf[1] == 'I' and buf[2] == 'G') { + p += 3; + } + i = 1; + for (;;) { + if (i >= sizeof(signames) div sizeof(signames[0])) { + error("signal \"%s\" unknown", s); + i = 0; + break; + } + if (signames[i] != nil and streq(signames[i], p)) { + break; + } + ++i; + } + return i; } /* - * Print all signals being ignored by the - * debugger. These signals are auotmatically + * Print all signals being ignored by the debugger. + * These signals are auotmatically * passed on to the debugged process. */ -public printsigsignored(p) + +public printsigsignored (p) Process p; { - printsigs(~p->sigset); } @@ -1341,26 +1419,30 @@ Process p; * Print all signals being intercepted by * the debugger for the specified process. */ + public printsigscaught(p) Process p; { - printsigs(p->sigset); } -private printsigs(vec) -register Integer vec; +private printsigs (set) +integer set; { - register Integer s; - String sep = ""; - - for (s = 1; s < NSIG; s++) - if (vec & bit(s) && signames[s]) { - printf("%s%s", sep, signames[s]); - sep = " "; + integer s; + char separator[2]; + + separator[0] = '\0'; + for (s = 1; s < sizeof(signames) div sizeof(signames[0]); s++) { + if (set & setrep(s)) { + if (signames[s] != nil) { + printf("%s%s", separator, signames[s]); + separator[0] = ' '; + separator[1] = '\0'; + } } - if (*sep != '\0') { + } + if (separator[0] == ' ') { putchar('\n'); - fflush(stdout); } } diff --git a/usr/src/old/dbx/runtime.c b/usr/src/old/dbx/runtime.c index b398db0827..5fb37932a3 100644 --- a/usr/src/old/dbx/runtime.c +++ b/usr/src/old/dbx/runtime.c @@ -1,7 +1,8 @@ - /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)runtime.c 1.12 (Berkeley) %G%"; +static char sccsid[] = "@(#)runtime.c 1.13 (Berkeley) %G%"; + +static char rcsid[] = "$Header: runtime.c,v 1.5 84/12/26 10:41:52 linton Exp $"; /* * Runtime organization dependent routines, mostly dealing with @@ -30,8 +31,8 @@ typedef struct Frame *Frame; #define NSAVEREG 12 struct Frame { - Integer condition_handler; - Integer mask; + integer condition_handler; + integer mask; Address save_ap; /* argument pointer */ Address save_fp; /* frame pointer */ Address save_pc; /* program counter */ @@ -44,12 +45,23 @@ private Boolean walkingstack = false; #define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp) +#define isstackaddr(addr) \ + (((addr) < 0x80000000) and ((addr) > 0x80000000 - 0x200 * UPAGES)) + +typedef struct { + Node callnode; + Node cmdnode; + boolean isfunc; +} CallEnv; + +private CallEnv endproc; + /* * Set a frame to the current activation record. */ private getcurframe(frp) -register Frame frp; +Frame frp; { register int i; @@ -57,28 +69,48 @@ register Frame frp; frp->mask = reg(NREG); frp->save_ap = reg(ARGP); frp->save_fp = reg(FRP); - frp->save_pc = reg(PROGCTR) + 1; + frp->save_pc = reg(PROGCTR); for (i = 0; i < NSAVEREG; i++) { frp->save_reg[i] = reg(i); } } +/* + * Get the saved registers from one frame to another + * given mask specifying which registers were actually saved. + */ + +#define bis(b, n) ((b & (1 << (n))) != 0) + +private getsaveregs (newfrp, frp, mask) +Frame newfrp, frp; +integer mask; +{ + integer i, j; + + j = 0; + for (i = 0; i < NSAVEREG; i++) { + if (bis(mask, i)) { + newfrp->save_reg[i] = frp->save_reg[j]; + ++j; + } + } +} + /* * Return a pointer to the next activation record up the stack. * Return nil if there is none. * Writes over space pointed to by given argument. */ -#define bis(b, n) ((b & (1 << (n))) != 0) - private Frame nextframe(frp) Frame frp; { - register Frame newfrp; + Frame newfrp; struct Frame frame; - register Integer i, j, mask; + integer mask; Address prev_frame, callpc; - static Integer ntramp = 0; + static integer ntramp = 0; newfrp = frp; prev_frame = frp->save_fp; @@ -112,23 +144,17 @@ nextf: } else { callpc = frame.save_pc; } - if (frame.save_fp == nil) { + if (frame.save_fp == nil or frame.save_pc == (Address) -1) { newfrp = nil; - } else if (callpc > 0x80000000 - 0x200 * UPAGES ) { - ntramp++; - prev_frame = frame.save_fp; - goto nextf; + } else if (isstackaddr(callpc)) { + ntramp++; + prev_frame = frame.save_fp; + goto nextf; } else { frame.save_pc = callpc; ntramp = 0; mask = ((frame.mask >> 16) & 0x0fff); - j = 0; - for (i = 0; i < NSAVEREG; i++) { - if (bis(mask, i)) { - newfrp->save_reg[i] = frame.save_reg[j]; - ++j; - } - } + getsaveregs(newfrp, &frame, mask); newfrp->condition_handler = frame.condition_handler; newfrp->mask = mask; newfrp->save_ap = frame.save_ap; @@ -158,7 +184,7 @@ Symbol *fp; * are returned. */ -private Frame nextfunc (frp, fp) +public Frame nextfunc (frp, fp) Frame frp; Symbol *fp; { @@ -192,36 +218,61 @@ Symbol *fp; public Frame findframe(f) Symbol f; { - register Frame frp; + Frame frp; static struct Frame frame; Symbol p; + Boolean done; frp = &frame; getcurframe(frp); - if (f == nil) - return (frp); - /* - * Starting at the current stack frame, - * walk backwards looking for a symbol - * match. Beware of local blocks which - * have a back pointer but no stack frame. - */ - p = whatblock(frp->save_pc); - while (p != f) { - if (p == program) { - frp = nil; - break; + if (f != nil) { + if (f == curfunc and curframe != nil) { + *frp = *curframe; + } else { + done = false; + p = whatblock(frp->save_pc); + do { + if (p == f) { + done = true; + } else if (p == program) { + done = true; + frp = nil; + } else { + frp = nextfunc(frp, &p); + if (frp == nil) { + done = true; + } + } + } while (not done); } - if (isinline(p)) { - p = container(p); - continue; + } + return frp; +} + +/* + * Set the registers according to the given frame pointer. + */ + +public getnewregs (addr) +Address addr; +{ + struct Frame frame; + integer i, j, mask; + + dread(&frame, addr, sizeof(frame)); + setreg(ARGP, frame.save_ap); + setreg(FRP, frame.save_fp); + setreg(PROGCTR, frame.save_pc); + mask = ((frame.mask >> 16) & 0x0fff); + j = 0; + for (i = 0; i < NSAVEREG; i++) { + if (bis(mask, i)) { + setreg(i, frame.save_reg[j]); + ++j; } - frp = nextframe(frp); - if (frp == nil) - break; - p = whatblock(frp->save_pc); } - return (frp); + pc = frame.save_pc; + setcurfunc(whatblock(pc)); } /* @@ -250,8 +301,8 @@ public Address return_addr() */ public pushretval(len, isindirect) -Integer len; -Boolean isindirect; +integer len; +boolean isindirect; { Word r0; @@ -275,7 +326,7 @@ Boolean isindirect; push(Word, r0); push(Word, reg(1)); } else { - panic("not indirect in pushretval?"); + error("[internal error: bad size %d in pushretval]", len); } break; } @@ -287,7 +338,7 @@ Boolean isindirect; */ public Address locals_base(frp) -register Frame frp; +Frame frp; { return (frp == nil) ? reg(FRP) : frp->save_fp; } @@ -297,7 +348,7 @@ register Frame frp; */ public Address args_base(frp) -register Frame frp; +Frame frp; { return (frp == nil) ? reg(ARGP) : frp->save_ap; } @@ -307,10 +358,10 @@ register Frame frp; */ public Word savereg(n, frp) -register Integer n; -register Frame frp; +integer n; +Frame frp; { - register Word w; + Word w; if (frp == nil) { w = reg(n); @@ -346,7 +397,7 @@ register Frame frp; */ public Word argn(n, frp) -Integer n; +integer n; Frame frp; { Word w; @@ -356,34 +407,45 @@ Frame frp; } /* - * Calculate the entry address for a procedure or function parameter, - * given the address of the descriptor. + * Print a list of currently active blocks starting with most recent. */ -public Address fparamaddr(a) -Address a; +public wherecmd() { - Address r; - - dread(&r, a, sizeof(r)); - return r; + walkstack(false); } /* - * Print a list of currently active blocks starting with most recent. + * Print the variables in the given frame or the current one if nil. */ -public wherecmd() +public dump (func) +Symbol func; { - walkstack(false); + Symbol f; + Frame frp; + + if (func == nil) { + f = curfunc; + if (curframe != nil) { + frp = curframe; + } else { + frp = findframe(f); + } + } else { + f = func; + frp = findframe(f); + } + showaggrs = true; + printcallinfo(f, frp); + dumpvars(f, frp); } /* - * Dump the world to the given file. - * Like "where", but variables are dumped also. + * Dump all values. */ -public dump() +public dumpall () { walkstack(true); } @@ -396,37 +458,30 @@ public dump() private walkstack(dumpvariables) Boolean dumpvariables; { - register Frame frp; - register Boolean save; - register Lineno line; + Frame frp; + boolean save; Symbol f; struct Frame frame; - if (notstarted(process)) { + if (notstarted(process) or isfinished(process)) { error("program is not active"); } else { save = walkingstack; walkingstack = true; + showaggrs = dumpvariables; frp = &frame; getcurfunc(frp, &f); - do { - printf("%s", symname(f)); - if (not isinline(f)) { - printparams(f, frp); - } - line = srcline(frp->save_pc - 1); - if (line != 0) { - printf(", line %d", line); - printf(" in \"%s\"\n", srcfilename(frp->save_pc - 1)); - } else { - printf(" at 0x%x\n", frp->save_pc); - } + for (;;) { + printcallinfo(f, frp); if (dumpvariables) { dumpvars(f, frp); putchar('\n'); } frp = nextfunc(frp, &f); - } while (frp != nil and f != program); + if (frp == nil or f == program) { + break; + } + } if (dumpvariables) { printf("in \"%s\":\n", symname(program)); dumpvars(program, nil); @@ -436,6 +491,35 @@ Boolean dumpvariables; } } +/* + * Print out the information about a call, i.e., + * routine name, parameter values, and source location. + */ + +private printcallinfo (f, frp) +Symbol f; +Frame frp; +{ + Lineno line; + Address savepc; + + savepc = frp->save_pc; + if (frp->save_fp != reg(FRP)) { + savepc -= 1; + } + printname(stdout, f); + if (not isinline(f)) { + printparams(f, frp); + } + line = srcline(savepc); + if (line != 0) { + printf(", line %d", line); + printf(" in \"%s\"\n", srcfilename(savepc)); + } else { + printf(" at 0x%x\n", savepc); + } +} + /* * Set the current function to the given symbol. * We must adjust "curframe" so that subsequent operations are @@ -449,6 +533,27 @@ Symbol f; curframe = nil; } +/* + * Return the frame for the current function. + * The space for the frame is allocated statically. + */ + +public Frame curfuncframe () +{ + static struct Frame frame; + Frame frp; + + if (curframe == nil) { + frp = findframe(curfunc); + curframe = &curframerec; + *curframe = *frp; + } else { + frp = &frame; + *frp = *curframe; + } + return frp; +} + /* * Set curfunc to be N up/down the stack from its current value. */ @@ -468,11 +573,7 @@ integer n; } else { i = 0; f = curfunc; - if (curframe != nil) { - frp = curframe; - } else { - frp = findframe(f); - } + frp = curfuncframe(); done = false; do { if (frp == nil) { @@ -483,6 +584,8 @@ integer n; curfunc = f; curframe = &curframerec; *curframe = *frp; + showaggrs = false; + printcallinfo(curfunc, curframe); } else if (f == program) { done = true; error("not that many levels"); @@ -498,7 +601,7 @@ public down (n) integer n; { integer i, depth; - register Frame frp; + Frame frp, curfrp; Symbol f; struct Frame frame; @@ -511,8 +614,9 @@ integer n; frp = &frame; getcurfunc(frp, &f); if (curframe == nil) { + curfrp = findframe(curfunc); curframe = &curframerec; - *curframe = *(findframe(curfunc)); + *curframe = *curfrp; } while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) { frp = nextfunc(frp, &f); @@ -530,6 +634,8 @@ integer n; } curfunc = f; *curframe = *frp; + showaggrs = false; + printcallinfo(curfunc, curframe); } } } @@ -538,7 +644,7 @@ integer n; * Find the entry point of a procedure or function. */ -public findbeginning(f) +public findbeginning (f) Symbol f; { if (isinternal(f)) { @@ -592,7 +698,7 @@ public runtofirst() public Address lastaddr() { - register Symbol s; + Symbol s; s = lookup(identname("exit", true)); if (s == nil) { @@ -611,7 +717,7 @@ public Address lastaddr() public Boolean isactive(f) Symbol f; { - register Boolean b; + Boolean b; if (isfinished(process)) { b = false; @@ -630,13 +736,16 @@ Symbol f; * Evaluate a call to a procedure. */ -public callproc(procnode, arglist) -Node procnode; -Node arglist; +public callproc(exprnode, isfunc) +Node exprnode; +boolean isfunc; { + Node procnode, arglist; Symbol proc; - Integer argc; + integer argc; + procnode = exprnode->value.arg[0]; + arglist = exprnode->value.arg[1]; if (procnode->op != O_SYM) { beginerrmsg(); fprintf(stderr, "can't call \""); @@ -649,14 +758,26 @@ Node arglist; if (not isblock(proc)) { error("\"%s\" is not a procedure or function", symname(proc)); } + endproc.isfunc = isfunc; + endproc.callnode = exprnode; + endproc.cmdnode = topnode; pushenv(); pc = codeloc(proc); argc = pushargs(proc, arglist); beginproc(proc, argc); - isstopped = true; - event_once(build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)), - buildcmdlist(build(O_PROCRTN, proc))); - cont(0); + event_once( + build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)), + buildcmdlist(build(O_PROCRTN, proc)) + ); + isstopped = false; + if (not bpact()) { + isstopped = true; + cont(0); + } + /* + * bpact() won't return true, it will call printstatus() and go back + * to command input if a breakpoint is found. + */ /* NOTREACHED */ } @@ -666,7 +787,7 @@ Node arglist; * space. */ -private Integer pushargs(proc, arglist) +private integer pushargs(proc, arglist) Symbol proc; Node arglist; { @@ -708,9 +829,19 @@ boolean chk; b = false; } } - if (b and formal != nil and isvarparam(formal) and - not isopenarray(formal->type) and actual->op != O_RVAL) - { + if (b and formal != nil and + isvarparam(formal) and not isopenarray(formal->type) and + not ( + actual->op == O_RVAL or actual->nodetype == t_addr or + ( + actual->op == O_TYPERENAME and + ( + actual->value.arg[0]->op == O_RVAL or + actual->value.arg[0]->nodetype == t_addr + ) + ) + ) + ) { beginerrmsg(); fprintf(stderr, "expected variable, found \""); prtree(stderr, actual); @@ -726,6 +857,12 @@ boolean chk; * Normally we pass either the address or value, but in some cases * (such as C strings) we want to copy the value onto the stack and * pass its address. + * + * Another special case raised by strings is the possibility that + * the actual parameter will be larger than the formal, even with + * appropriate type-checking. This occurs because we assume during + * evaluation that strings are null-terminated, whereas some languages, + * notably Pascal, do not work under that assumption. */ private passparam (actual, formal) @@ -735,21 +872,33 @@ Symbol formal; boolean b; Address addr; Stack *savesp; - integer paramsize; + integer actsize, formsize; - if (isvarparam(formal) and not isopenarray(formal->type)) { + if (formal != nil and isvarparam(formal) and + (not isopenarray(formal->type)) + ) { addr = lval(actual->value.arg[0]); push(Address, addr); } else if (passaddr(formal, actual->nodetype)) { savesp = sp; eval(actual); - paramsize = sp - savesp; - setreg(STKP, reg(STKP) - paramsize); - dwrite(savesp, reg(STKP), paramsize); + actsize = sp - savesp; + setreg(STKP, + reg(STKP) - ((actsize + sizeof(Word) - 1) & ~(sizeof(Word) - 1)) + ); + dwrite(savesp, reg(STKP), actsize); sp = savesp; push(Address, reg(STKP)); if (formal != nil and isopenarray(formal->type)) { - push(integer, paramsize div size(formal->type->type)); + push(integer, actsize div size(formal->type->type)); + } + } else if (formal != nil) { + formsize = size(formal); + savesp = sp; + eval(actual); + actsize = sp - savesp; + if (actsize > formsize) { + sp -= (actsize - formsize); } } else { eval(actual); @@ -760,14 +909,14 @@ Symbol formal; * Evaluate an argument list left-to-right. */ -private Integer evalargs(proc, arglist) +private integer evalargs(proc, arglist) Symbol proc; Node arglist; { Node p, actual; Symbol formal; Stack *savesp; - Integer count; + integer count; boolean chk; savesp = sp; @@ -800,11 +949,32 @@ Node arglist; public procreturn(f) Symbol f; { + integer retvalsize; + Node tmp; + char *copy; + flushoutput(); - putchar('\n'); - printname(stdout, f); - printf(" returns successfully\n"); popenv(); + if (endproc.isfunc) { + retvalsize = size(f->type); + if (retvalsize > sizeof(long)) { + pushretval(retvalsize, true); + copy = newarr(char, retvalsize); + popn(retvalsize, copy); + tmp = build(O_SCON, copy); + } else { + tmp = build(O_LCON, (long) (reg(0))); + } + tmp->nodetype = f->type; + tfree(endproc.callnode); + *(endproc.callnode) = *(tmp); + dispose(tmp); + eval(endproc.cmdnode); + } else { + putchar('\n'); + printname(stdout, f); + printf(" returns successfully\n", symname(f)); + } erecover(); } @@ -821,6 +991,7 @@ private pushenv() push(Symbol, curfunc); push(Frame, curframe); push(struct Frame, curframerec); + push(CallEnv, endproc); push(Word, reg(PROGCTR)); push(Word, reg(STKP)); } @@ -831,10 +1002,11 @@ private pushenv() public popenv() { - register String filename; + String filename; setreg(STKP, pop(Word)); setreg(PROGCTR, pop(Word)); + endproc = pop(CallEnv); curframerec = pop(struct Frame); curframe = pop(Frame); curfunc = pop(Symbol); @@ -853,8 +1025,8 @@ public popenv() public flushoutput() { - register Symbol p, iob; - register Stack *savesp; + Symbol p, iob; + Stack *savesp; p = lookup(identname("fflush", true)); while (p != nil and not isblock(p)) { diff --git a/usr/src/old/dbx/runtime.vax.c b/usr/src/old/dbx/runtime.vax.c index 0847e92160..889a67e7a2 100644 --- a/usr/src/old/dbx/runtime.vax.c +++ b/usr/src/old/dbx/runtime.vax.c @@ -1,7 +1,8 @@ - /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)runtime.vax.c 1.12 (Berkeley) %G%"; +static char sccsid[] = "@(#)runtime.vax.c 1.13 (Berkeley) %G%"; + +static char rcsid[] = "$Header: runtime.c,v 1.5 84/12/26 10:41:52 linton Exp $"; /* * Runtime organization dependent routines, mostly dealing with @@ -30,8 +31,8 @@ typedef struct Frame *Frame; #define NSAVEREG 12 struct Frame { - Integer condition_handler; - Integer mask; + integer condition_handler; + integer mask; Address save_ap; /* argument pointer */ Address save_fp; /* frame pointer */ Address save_pc; /* program counter */ @@ -44,12 +45,23 @@ private Boolean walkingstack = false; #define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp) +#define isstackaddr(addr) \ + (((addr) < 0x80000000) and ((addr) > 0x80000000 - 0x200 * UPAGES)) + +typedef struct { + Node callnode; + Node cmdnode; + boolean isfunc; +} CallEnv; + +private CallEnv endproc; + /* * Set a frame to the current activation record. */ private getcurframe(frp) -register Frame frp; +Frame frp; { register int i; @@ -57,28 +69,48 @@ register Frame frp; frp->mask = reg(NREG); frp->save_ap = reg(ARGP); frp->save_fp = reg(FRP); - frp->save_pc = reg(PROGCTR) + 1; + frp->save_pc = reg(PROGCTR); for (i = 0; i < NSAVEREG; i++) { frp->save_reg[i] = reg(i); } } +/* + * Get the saved registers from one frame to another + * given mask specifying which registers were actually saved. + */ + +#define bis(b, n) ((b & (1 << (n))) != 0) + +private getsaveregs (newfrp, frp, mask) +Frame newfrp, frp; +integer mask; +{ + integer i, j; + + j = 0; + for (i = 0; i < NSAVEREG; i++) { + if (bis(mask, i)) { + newfrp->save_reg[i] = frp->save_reg[j]; + ++j; + } + } +} + /* * Return a pointer to the next activation record up the stack. * Return nil if there is none. * Writes over space pointed to by given argument. */ -#define bis(b, n) ((b & (1 << (n))) != 0) - private Frame nextframe(frp) Frame frp; { - register Frame newfrp; + Frame newfrp; struct Frame frame; - register Integer i, j, mask; + integer mask; Address prev_frame, callpc; - static Integer ntramp = 0; + static integer ntramp = 0; newfrp = frp; prev_frame = frp->save_fp; @@ -112,23 +144,17 @@ nextf: } else { callpc = frame.save_pc; } - if (frame.save_fp == nil) { + if (frame.save_fp == nil or frame.save_pc == (Address) -1) { newfrp = nil; - } else if (callpc > 0x80000000 - 0x200 * UPAGES ) { - ntramp++; - prev_frame = frame.save_fp; - goto nextf; + } else if (isstackaddr(callpc)) { + ntramp++; + prev_frame = frame.save_fp; + goto nextf; } else { frame.save_pc = callpc; ntramp = 0; mask = ((frame.mask >> 16) & 0x0fff); - j = 0; - for (i = 0; i < NSAVEREG; i++) { - if (bis(mask, i)) { - newfrp->save_reg[i] = frame.save_reg[j]; - ++j; - } - } + getsaveregs(newfrp, &frame, mask); newfrp->condition_handler = frame.condition_handler; newfrp->mask = mask; newfrp->save_ap = frame.save_ap; @@ -158,7 +184,7 @@ Symbol *fp; * are returned. */ -private Frame nextfunc (frp, fp) +public Frame nextfunc (frp, fp) Frame frp; Symbol *fp; { @@ -192,36 +218,61 @@ Symbol *fp; public Frame findframe(f) Symbol f; { - register Frame frp; + Frame frp; static struct Frame frame; Symbol p; + Boolean done; frp = &frame; getcurframe(frp); - if (f == nil) - return (frp); - /* - * Starting at the current stack frame, - * walk backwards looking for a symbol - * match. Beware of local blocks which - * have a back pointer but no stack frame. - */ - p = whatblock(frp->save_pc); - while (p != f) { - if (p == program) { - frp = nil; - break; + if (f != nil) { + if (f == curfunc and curframe != nil) { + *frp = *curframe; + } else { + done = false; + p = whatblock(frp->save_pc); + do { + if (p == f) { + done = true; + } else if (p == program) { + done = true; + frp = nil; + } else { + frp = nextfunc(frp, &p); + if (frp == nil) { + done = true; + } + } + } while (not done); } - if (isinline(p)) { - p = container(p); - continue; + } + return frp; +} + +/* + * Set the registers according to the given frame pointer. + */ + +public getnewregs (addr) +Address addr; +{ + struct Frame frame; + integer i, j, mask; + + dread(&frame, addr, sizeof(frame)); + setreg(ARGP, frame.save_ap); + setreg(FRP, frame.save_fp); + setreg(PROGCTR, frame.save_pc); + mask = ((frame.mask >> 16) & 0x0fff); + j = 0; + for (i = 0; i < NSAVEREG; i++) { + if (bis(mask, i)) { + setreg(i, frame.save_reg[j]); + ++j; } - frp = nextframe(frp); - if (frp == nil) - break; - p = whatblock(frp->save_pc); } - return (frp); + pc = frame.save_pc; + setcurfunc(whatblock(pc)); } /* @@ -250,8 +301,8 @@ public Address return_addr() */ public pushretval(len, isindirect) -Integer len; -Boolean isindirect; +integer len; +boolean isindirect; { Word r0; @@ -275,7 +326,7 @@ Boolean isindirect; push(Word, r0); push(Word, reg(1)); } else { - panic("not indirect in pushretval?"); + error("[internal error: bad size %d in pushretval]", len); } break; } @@ -287,7 +338,7 @@ Boolean isindirect; */ public Address locals_base(frp) -register Frame frp; +Frame frp; { return (frp == nil) ? reg(FRP) : frp->save_fp; } @@ -297,7 +348,7 @@ register Frame frp; */ public Address args_base(frp) -register Frame frp; +Frame frp; { return (frp == nil) ? reg(ARGP) : frp->save_ap; } @@ -307,10 +358,10 @@ register Frame frp; */ public Word savereg(n, frp) -register Integer n; -register Frame frp; +integer n; +Frame frp; { - register Word w; + Word w; if (frp == nil) { w = reg(n); @@ -346,7 +397,7 @@ register Frame frp; */ public Word argn(n, frp) -Integer n; +integer n; Frame frp; { Word w; @@ -356,34 +407,45 @@ Frame frp; } /* - * Calculate the entry address for a procedure or function parameter, - * given the address of the descriptor. + * Print a list of currently active blocks starting with most recent. */ -public Address fparamaddr(a) -Address a; +public wherecmd() { - Address r; - - dread(&r, a, sizeof(r)); - return r; + walkstack(false); } /* - * Print a list of currently active blocks starting with most recent. + * Print the variables in the given frame or the current one if nil. */ -public wherecmd() +public dump (func) +Symbol func; { - walkstack(false); + Symbol f; + Frame frp; + + if (func == nil) { + f = curfunc; + if (curframe != nil) { + frp = curframe; + } else { + frp = findframe(f); + } + } else { + f = func; + frp = findframe(f); + } + showaggrs = true; + printcallinfo(f, frp); + dumpvars(f, frp); } /* - * Dump the world to the given file. - * Like "where", but variables are dumped also. + * Dump all values. */ -public dump() +public dumpall () { walkstack(true); } @@ -396,37 +458,30 @@ public dump() private walkstack(dumpvariables) Boolean dumpvariables; { - register Frame frp; - register Boolean save; - register Lineno line; + Frame frp; + boolean save; Symbol f; struct Frame frame; - if (notstarted(process)) { + if (notstarted(process) or isfinished(process)) { error("program is not active"); } else { save = walkingstack; walkingstack = true; + showaggrs = dumpvariables; frp = &frame; getcurfunc(frp, &f); - do { - printf("%s", symname(f)); - if (not isinline(f)) { - printparams(f, frp); - } - line = srcline(frp->save_pc - 1); - if (line != 0) { - printf(", line %d", line); - printf(" in \"%s\"\n", srcfilename(frp->save_pc - 1)); - } else { - printf(" at 0x%x\n", frp->save_pc); - } + for (;;) { + printcallinfo(f, frp); if (dumpvariables) { dumpvars(f, frp); putchar('\n'); } frp = nextfunc(frp, &f); - } while (frp != nil and f != program); + if (frp == nil or f == program) { + break; + } + } if (dumpvariables) { printf("in \"%s\":\n", symname(program)); dumpvars(program, nil); @@ -436,6 +491,35 @@ Boolean dumpvariables; } } +/* + * Print out the information about a call, i.e., + * routine name, parameter values, and source location. + */ + +private printcallinfo (f, frp) +Symbol f; +Frame frp; +{ + Lineno line; + Address savepc; + + savepc = frp->save_pc; + if (frp->save_fp != reg(FRP)) { + savepc -= 1; + } + printname(stdout, f); + if (not isinline(f)) { + printparams(f, frp); + } + line = srcline(savepc); + if (line != 0) { + printf(", line %d", line); + printf(" in \"%s\"\n", srcfilename(savepc)); + } else { + printf(" at 0x%x\n", savepc); + } +} + /* * Set the current function to the given symbol. * We must adjust "curframe" so that subsequent operations are @@ -449,6 +533,27 @@ Symbol f; curframe = nil; } +/* + * Return the frame for the current function. + * The space for the frame is allocated statically. + */ + +public Frame curfuncframe () +{ + static struct Frame frame; + Frame frp; + + if (curframe == nil) { + frp = findframe(curfunc); + curframe = &curframerec; + *curframe = *frp; + } else { + frp = &frame; + *frp = *curframe; + } + return frp; +} + /* * Set curfunc to be N up/down the stack from its current value. */ @@ -468,11 +573,7 @@ integer n; } else { i = 0; f = curfunc; - if (curframe != nil) { - frp = curframe; - } else { - frp = findframe(f); - } + frp = curfuncframe(); done = false; do { if (frp == nil) { @@ -483,6 +584,8 @@ integer n; curfunc = f; curframe = &curframerec; *curframe = *frp; + showaggrs = false; + printcallinfo(curfunc, curframe); } else if (f == program) { done = true; error("not that many levels"); @@ -498,7 +601,7 @@ public down (n) integer n; { integer i, depth; - register Frame frp; + Frame frp, curfrp; Symbol f; struct Frame frame; @@ -511,8 +614,9 @@ integer n; frp = &frame; getcurfunc(frp, &f); if (curframe == nil) { + curfrp = findframe(curfunc); curframe = &curframerec; - *curframe = *(findframe(curfunc)); + *curframe = *curfrp; } while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) { frp = nextfunc(frp, &f); @@ -530,6 +634,8 @@ integer n; } curfunc = f; *curframe = *frp; + showaggrs = false; + printcallinfo(curfunc, curframe); } } } @@ -538,7 +644,7 @@ integer n; * Find the entry point of a procedure or function. */ -public findbeginning(f) +public findbeginning (f) Symbol f; { if (isinternal(f)) { @@ -592,7 +698,7 @@ public runtofirst() public Address lastaddr() { - register Symbol s; + Symbol s; s = lookup(identname("exit", true)); if (s == nil) { @@ -611,7 +717,7 @@ public Address lastaddr() public Boolean isactive(f) Symbol f; { - register Boolean b; + Boolean b; if (isfinished(process)) { b = false; @@ -630,13 +736,16 @@ Symbol f; * Evaluate a call to a procedure. */ -public callproc(procnode, arglist) -Node procnode; -Node arglist; +public callproc(exprnode, isfunc) +Node exprnode; +boolean isfunc; { + Node procnode, arglist; Symbol proc; - Integer argc; + integer argc; + procnode = exprnode->value.arg[0]; + arglist = exprnode->value.arg[1]; if (procnode->op != O_SYM) { beginerrmsg(); fprintf(stderr, "can't call \""); @@ -649,14 +758,26 @@ Node arglist; if (not isblock(proc)) { error("\"%s\" is not a procedure or function", symname(proc)); } + endproc.isfunc = isfunc; + endproc.callnode = exprnode; + endproc.cmdnode = topnode; pushenv(); pc = codeloc(proc); argc = pushargs(proc, arglist); beginproc(proc, argc); - isstopped = true; - event_once(build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)), - buildcmdlist(build(O_PROCRTN, proc))); - cont(0); + event_once( + build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)), + buildcmdlist(build(O_PROCRTN, proc)) + ); + isstopped = false; + if (not bpact()) { + isstopped = true; + cont(0); + } + /* + * bpact() won't return true, it will call printstatus() and go back + * to command input if a breakpoint is found. + */ /* NOTREACHED */ } @@ -666,7 +787,7 @@ Node arglist; * space. */ -private Integer pushargs(proc, arglist) +private integer pushargs(proc, arglist) Symbol proc; Node arglist; { @@ -708,9 +829,19 @@ boolean chk; b = false; } } - if (b and formal != nil and isvarparam(formal) and - not isopenarray(formal->type) and actual->op != O_RVAL) - { + if (b and formal != nil and + isvarparam(formal) and not isopenarray(formal->type) and + not ( + actual->op == O_RVAL or actual->nodetype == t_addr or + ( + actual->op == O_TYPERENAME and + ( + actual->value.arg[0]->op == O_RVAL or + actual->value.arg[0]->nodetype == t_addr + ) + ) + ) + ) { beginerrmsg(); fprintf(stderr, "expected variable, found \""); prtree(stderr, actual); @@ -726,6 +857,12 @@ boolean chk; * Normally we pass either the address or value, but in some cases * (such as C strings) we want to copy the value onto the stack and * pass its address. + * + * Another special case raised by strings is the possibility that + * the actual parameter will be larger than the formal, even with + * appropriate type-checking. This occurs because we assume during + * evaluation that strings are null-terminated, whereas some languages, + * notably Pascal, do not work under that assumption. */ private passparam (actual, formal) @@ -735,21 +872,33 @@ Symbol formal; boolean b; Address addr; Stack *savesp; - integer paramsize; + integer actsize, formsize; - if (isvarparam(formal) and not isopenarray(formal->type)) { + if (formal != nil and isvarparam(formal) and + (not isopenarray(formal->type)) + ) { addr = lval(actual->value.arg[0]); push(Address, addr); } else if (passaddr(formal, actual->nodetype)) { savesp = sp; eval(actual); - paramsize = sp - savesp; - setreg(STKP, reg(STKP) - paramsize); - dwrite(savesp, reg(STKP), paramsize); + actsize = sp - savesp; + setreg(STKP, + reg(STKP) - ((actsize + sizeof(Word) - 1) & ~(sizeof(Word) - 1)) + ); + dwrite(savesp, reg(STKP), actsize); sp = savesp; push(Address, reg(STKP)); if (formal != nil and isopenarray(formal->type)) { - push(integer, paramsize div size(formal->type->type)); + push(integer, actsize div size(formal->type->type)); + } + } else if (formal != nil) { + formsize = size(formal); + savesp = sp; + eval(actual); + actsize = sp - savesp; + if (actsize > formsize) { + sp -= (actsize - formsize); } } else { eval(actual); @@ -760,14 +909,14 @@ Symbol formal; * Evaluate an argument list left-to-right. */ -private Integer evalargs(proc, arglist) +private integer evalargs(proc, arglist) Symbol proc; Node arglist; { Node p, actual; Symbol formal; Stack *savesp; - Integer count; + integer count; boolean chk; savesp = sp; @@ -800,11 +949,32 @@ Node arglist; public procreturn(f) Symbol f; { + integer retvalsize; + Node tmp; + char *copy; + flushoutput(); - putchar('\n'); - printname(stdout, f); - printf(" returns successfully\n"); popenv(); + if (endproc.isfunc) { + retvalsize = size(f->type); + if (retvalsize > sizeof(long)) { + pushretval(retvalsize, true); + copy = newarr(char, retvalsize); + popn(retvalsize, copy); + tmp = build(O_SCON, copy); + } else { + tmp = build(O_LCON, (long) (reg(0))); + } + tmp->nodetype = f->type; + tfree(endproc.callnode); + *(endproc.callnode) = *(tmp); + dispose(tmp); + eval(endproc.cmdnode); + } else { + putchar('\n'); + printname(stdout, f); + printf(" returns successfully\n", symname(f)); + } erecover(); } @@ -821,6 +991,7 @@ private pushenv() push(Symbol, curfunc); push(Frame, curframe); push(struct Frame, curframerec); + push(CallEnv, endproc); push(Word, reg(PROGCTR)); push(Word, reg(STKP)); } @@ -831,10 +1002,11 @@ private pushenv() public popenv() { - register String filename; + String filename; setreg(STKP, pop(Word)); setreg(PROGCTR, pop(Word)); + endproc = pop(CallEnv); curframerec = pop(struct Frame); curframe = pop(Frame); curfunc = pop(Symbol); @@ -853,8 +1025,8 @@ public popenv() public flushoutput() { - register Symbol p, iob; - register Stack *savesp; + Symbol p, iob; + Stack *savesp; p = lookup(identname("fflush", true)); while (p != nil and not isblock(p)) { diff --git a/usr/src/old/dbx/scanner.c b/usr/src/old/dbx/scanner.c index 9f3a6fe9e2..06f9d041f4 100644 --- a/usr/src/old/dbx/scanner.c +++ b/usr/src/old/dbx/scanner.c @@ -1,12 +1,13 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)scanner.c 1.11 (Berkeley) %G%"; +static char sccsid[] = "@(#)scanner.c 1.12 (Berkeley) %G%"; + +static char rcsid[] = "$Header: scanner.c,v 1.5 84/12/26 10:42:05 linton Exp $"; /* * Debugger scanner. */ -#include #include "defs.h" #include "scanner.h" #include "main.h" @@ -18,626 +19,814 @@ static char sccsid[] = "@(#)scanner.c 1.11 (Berkeley) %G%"; #ifndef public typedef int Token; -#endif -typedef struct { - int s_type; -#define ST_FILE 0 -#define ST_ALIAS 1 - char *s_name; - int s_lineno; - union { - File su_file; - struct sum { - char *sum_data; - char *sum_cur; - } su_macro; - } su; -#define s_file su.su_file -#define s_macro su.su_macro -#define s_data s_macro.sum_data -#define s_cur s_macro.sum_cur -} STREAM; - -#define NSTREAMS 10 -private STREAM stack[NSTREAMS]; -private STREAM *sp = &stack[-1]; +#define MAXLINESIZE 10240 + +#endif public String initfile = ".dbxinit"; +typedef enum { WHITE, ALPHA, NUM, OTHER } Charclass; + +private Charclass class[256 + 1]; +private Charclass *lexclass = class + 1; + +#define isdigit(c) (lexclass[c] == NUM) +#define isalnum(c) (lexclass[c] == ALPHA or lexclass[c] == NUM) +#define ishexdigit(c) ( \ + isdigit(c) or (c >= 'a' and c <= 'f') or (c >= 'A' and c <= 'F') \ +) + +public boolean chkalias; +public char scanner_linebuf[MAXLINESIZE]; + +private File in; +private char *curchar, *prevchar; + +#define MAXINCLDEPTH 10 + +private struct { + File savefile; + Filename savefn; + int savelineno; +} inclinfo[MAXINCLDEPTH]; + +private unsigned int curinclindex; + private Token getident(); private Token getnum(); private Token getstring(); -private Char charcon(); +private Boolean eofinput(); +private char charcon(); -#define MAXLINESIZE 1024 -private Char yytext[MAXLINESIZE]; -private Boolean shellmode; -private Boolean doaliases; +private enterlexclass(class, s) +Charclass class; +String s; +{ + register char *p; + + for (p = s; *p != '\0'; p++) { + lexclass[*p] = class; + } +} public scanner_init() { - register Integer i; - - if (sp < stack) - (void) pushinput(ST_FILE, nil, stdin); - shellmode = false; - doaliases = true; - errfilename = nil; - errlineno = sp->s_lineno = 0; - yytext[0] = '\0'; + register Integer i; + + for (i = 0; i < 257; i++) { + class[i] = OTHER; + } + enterlexclass(WHITE, " \t"); + enterlexclass(ALPHA, "abcdefghijklmnopqrstuvwxyz"); + enterlexclass(ALPHA, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_$"); + enterlexclass(NUM, "0123456789"); + in = stdin; + errfilename = nil; + errlineno = 0; + curchar = scanner_linebuf; + scanner_linebuf[0] = '\0'; + chkalias = true; } -#define MAXDEPTH 25 /* * Read a single token. + * + * The input is line buffered. Tokens cannot cross line boundaries. + * * There are two "modes" of operation: one as in a compiler, - * and one for reading shell-like syntax. + * and one for reading shell-like syntax. In the first mode + * there is the additional choice of doing alias processing. */ + +private Boolean shellmode; + public Token yylex() { - register int c; - register char *p; - register Token t; - static int depth = 0; - - depth++; - if (depth > MAXDEPTH) { - depth = 0; - error("alias loop (maximum %d deep)", MAXDEPTH); + register int c; + register char *p; + register Token t; + String line; + integer n; + + p = curchar; + if (*p == '\0') { + do { + if (isterm(in)) { + printf("(%s) ", cmdname); + } + fflush(stdout); + line = fgets(scanner_linebuf, MAXLINESIZE, in); + } while (line == nil and not eofinput()); + if (line == nil) { + c = EOF; + } else { + p = scanner_linebuf; + while (lexclass[*p] == WHITE) { + p++; + } + shellmode = false; } -again: - do - c = getch(); - while (c == ' ' || c == '\t'); - if (isalpha(c) || c == '_' || c == '$') { - t = getident(c); - if (t == NAME && doaliases) { - p = findalias(yylval.y_name); - if (p != nil) { - if (lexdebug) - fprintf(stderr, "alias %s to \"%s\"\n", - ident(yylval.y_name), p); - if (!pushinput(ST_ALIAS, "", p)) { - unwindinput(ST_ALIAS); - error("Alias stack overflow."); - } - t = yylex(); - } - } - goto done; + chkalias = true; + } else { + while (lexclass[*p] == WHITE) { + p++; } - if (isdigit(c)) { - t = shellmode ? getident(c) : getnum(c); - goto done; + } + curchar = p; + prevchar = curchar; + c = *p; + if (lexclass[c] == ALPHA) { + t = getident(chkalias); + } else if (lexclass[c] == NUM) { + if (shellmode) { + t = getident(chkalias); + } else { + t = getnum(); } + } else { + ++curchar; switch (c) { - - case '\n': + case '\n': t = '\n'; - if (sp->s_lineno != 0) { - sp->s_lineno++; - if (sp->s_type == ST_FILE) - errlineno = sp->s_lineno; + if (errlineno != 0) { + errlineno++; } break; - case '"': - case '\'': + case '"': + case '\'': t = getstring(c); break; - case '.': + case '.': if (shellmode) { - t = getident(c); - break; + --curchar; + t = getident(chkalias); + } else if (isdigit(*curchar)) { + --curchar; + t = getnum(); + } else { + t = '.'; } - c = getch(); - ungetch(c); - t = isdigit(c) ? getnum('.') : '.'; - break; - - case '<': - c = getch(); - if (shellmode || c != '<') { - ungetch(c); - t = '<'; - } else - t = LFORMER; break; - case '>': - c = getch(); - if (shellmode || c != '>') { - ungetch(c); - t = '>'; - } else - t = RFORMER; + case '-': + if (shellmode) { + --curchar; + t = getident(chkalias); + } else if (*curchar == '>') { + ++curchar; + t = ARROW; + } else { + t = '-'; + } break; - case '#': - c = getch(); - if (c != '^') { - ungetch(c); - t = '#'; - } else - t = ABSTRACTION; + case '#': + if (not isterm(in)) { + *p = '\0'; + curchar = p; + t = '\n'; + ++errlineno; + } else { + t = '#'; + } break; - case '-': - if (shellmode) { - t = getident(c); - break; + case '\\': + if (*(p+1) == '\n') { + n = MAXLINESIZE - (p - &scanner_linebuf[0]); + if (n > 1) { + if (fgets(p, n, in) == nil) { + t = 0; + } else { + curchar = p; + t = yylex(); + } + } else { + t = '\\'; + } + } else { + t = '\\'; } - c = getch(); - if (c != '>') { - ungetch(c); - t = '-'; - } else - t = ARROW; break; - case EOF: + case EOF: t = 0; break; - default: - t = shellmode && index("!&*()[];", c) == nil ? - getident(c) : c; + default: + if (shellmode and index("!&*<>()[]", c) == nil) { + --curchar; + t = getident(chkalias); + } else { + t = c; + } break; } -done: + } + chkalias = false; +# ifdef LEXDEBUG if (lexdebug) { - fprintf(stderr, "token "); - print_token(stderr, t); - fprintf(stderr, "\n"); + fprintf(stderr, "yylex returns "); + print_token(stderr, t); + fprintf(stderr, "\n"); } - depth--; - return (t); +# endif + return t; } /* - * Scan an identifier and check to see if it's a keyword. + * Put the given string before the current character + * in the current line, thus inserting it into the input stream. */ -private Token getident(c) -Char c; -{ - register Char *p, *q; - Token t; - q = yytext; - if (shellmode) { - do { - *q++ = c; - c = getch(); - } while (index(" \t\n!&<>*[]();", c) == nil); - } else { - do { - *q++ = c; - c = getch(); - } while (isalnum(c) || c == '_' || c == '$'); - } - ungetch(c); - *q = '\0'; - yylval.y_name = identname(yytext, false); - if (shellmode) - return (NAME); - t = findkeyword(yylval.y_name); - return (t == nil ? NAME : t); -} - -/* - * Scan a number. - */ -private Token getnum(c) -Char c; +public insertinput (s) +String s; { - register Char *q; - register Token t; - Integer base = 10; - - q = yytext; - if (c == '0') { - c = getch(); - if (c == 'x') { - base = 16; - } else { - base = 8; - ungetch(c); - c = '0'; - } + register char *p, *q; + int need, avail, shift; + + q = s; + need = strlen(q); + avail = curchar - &scanner_linebuf[0]; + if (need <= avail) { + curchar = &scanner_linebuf[avail - need]; + p = curchar; + while (*q != '\0') { + *p++ = *q++; } - if (base == 16) { - while (isdigit(c = getch()) || - (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) - *q++ = c; - } else { - do { - *q++ = c; - c = getch(); - } while (isdigit(c)); + } else { + p = curchar; + while (*p != '\0') { + ++p; } - if (c == '.') { - do { - *q++ = c; - c = getch(); - } while (isdigit(c)); - if (c == 'e' || c == 'E') { - c = getch(); - if (c == '+' || c == '-' || isdigit(c)) { - *q++ = 'e'; - do { - *q++ = c; - c = getch(); - } while (isdigit(c)); - } - } - ungetch(c); - *q = '\0'; - yylval.y_real = atof(yytext); - return (REAL); + shift = need - avail; + if (p + shift >= &scanner_linebuf[MAXLINESIZE]) { + error("alias expansion too large"); } - ungetch(c); - *q = '\0'; - switch (base) { - - case 10: - yylval.y_int = atol(yytext); - break; - - case 8: - yylval.y_int = octal(yytext); - break; - - case 16: - yylval.y_int = hex(yytext); + for (;;) { + *(p + shift) = *p; + if (p == curchar) { break; - - default: - badcaseval(base); + } + --p; + } + p = &scanner_linebuf[0]; + while (*q != '\0') { + *p++ = *q++; } - return (INT); + curchar = &scanner_linebuf[0]; + } } /* - * Convert a string of octal digits to an integer. + * Get the actuals for a macro call. */ -private int octal(s) -String s; -{ - register Char *p; - register Integer n; - - n = 0; - for (p = s; *p != '\0'; p++) - n = (n << 3) + (*p - '0'); - return (n); -} -/* - * Convert a string of hexadecimal digits to an integer. - */ -private int hex(s) -String s; +private String movetochar (str, c) +String str; +char c; { - register Char *p; - register Integer n; - - n = 0; - for (p = s; *p != '\0'; p++) { - n <<= 4; - if (*p >= 'a' && *p <= 'f') - n += (*p - 'a' + 10); - else if (*p >= 'A' && *p <= 'F') - n += (*p - 'A' + 10); - else - n += (*p - '0'); + register char *p; + + while (*p != c) { + if (*p == '\0') { + error("missing ')' in macro call"); + } else if (*p == ')') { + error("not enough parameters in macro call"); + } else if (*p == ',') { + error("too many parameters in macro call"); } - return (n); + ++p; + } + return p; } -/* - * Scan a string. - */ -private Token getstring(match) -Char match; +private String *getactuals (n) +integer n; { - register Char *q, c; - - q = yytext; - for (;;) { - c = getch(); - if (c == '\n' || c == EOF) { - error("Unterminated string."); - break; - } - if (c == match) - break; - *q++ = charcon(c); + String *a; + register char *p; + int i; + + a = newarr(String, n); + p = curchar; + while (*p != '(') { + if (lexclass[*p] != WHITE) { + error("missing actuals for macro"); } - *q = '\0'; - yylval.y_string = strdup(yytext); - return (STRING); + ++p; + } + ++p; + for (i = 0; i < n - 1; i++) { + a[i] = p; + p = movetochar(p, ','); + *p = '\0'; + ++p; + } + a[n-1] = p; + p = movetochar(p, ')'); + *p = '\0'; + curchar = p + 1; + return a; } /* - * Process a character constant. - * Watch out for backslashes. + * Do command macro expansion, assuming curchar points to the beginning + * of the actuals, and we are not in shell mode. */ -private Char charcon(c) -Char c; + +private expand (pl, str) +List pl; +String str; { - register char *cp; - - if (c == '\\') { - c = getch(); - if (isdigit(c)) { - int v; - - v = 0; - do { - v = (v << 3) + (c - '0'); - c = getch(); - } while (isdigit(c)); - ungetch(c); - return (v); + char buf[4096], namebuf[100]; + register char *p, *q, *r; + String *actual; + Name n; + integer i; + boolean match; + + if (pl == nil) { + insertinput(str); + } else { + actual = getactuals(list_size(pl)); + p = buf; + q = str; + while (*q != '\0') { + if (p >= &buf[4096]) { + error("alias expansion too large"); + } + if (lexclass[*q] == ALPHA) { + r = namebuf; + do { + *r++ = *q++; + } while (isalnum(*q)); + *r = '\0'; + i = 0; + match = false; + foreach(Name, n, pl) + if (streq(ident(n), namebuf)) { + match = true; + break; + } + ++i; + endfor + if (match) { + r = actual[i]; + } else { + r = namebuf; } - for (cp = "f\ft\tb\bn\nr\rv\v"; *cp != c; cp += 2) - ; - if (*cp != '\0') - c = *cp; + while (*r != '\0') { + *p++ = *r++; + } + } else { + *p++ = *q++; + } } - return (c); + *p = '\0'; + insertinput(buf); + } } /* * Parser error handling. */ + public yyerror(s) String s; { - - if (streq(s, "syntax error")) { - beginerrmsg(); - fprintf(stderr, "Syntax error"); - if (yytext[0] != '\0') - fprintf(stderr, " on \"%s\".", yytext); - enderrmsg(); - return; + register char *p; + register integer start; + + if (streq(s, "syntax error")) { + beginerrmsg(); + p = prevchar; + start = p - &scanner_linebuf[0]; + if (p > &scanner_linebuf[0]) { + while (lexclass[*p] == WHITE and p > &scanner_linebuf[0]) { + --p; + } + } + fprintf(stderr, "%s", scanner_linebuf); + if (start != 0) { + fprintf(stderr, "%*c", start, ' '); + } + if (p == &scanner_linebuf[0]) { + fprintf(stderr, "^ unrecognized command"); + } else { + fprintf(stderr, "^ syntax error"); } + enderrmsg(); + } else { error(s); + } } /* * Eat the current line. */ -private Char lastc = '\0'; -public gobble() +public gobble () { - register char c; - - if (lastc != '\n' && lastc != EOF) - while ((c = getch()) != EOF && c != '\n') - ; + curchar = scanner_linebuf; + scanner_linebuf[0] = '\0'; } /* - * Input file management routines. + * Scan an identifier. + * + * If chkalias is true, check first to see if it's an alias. + * Otherwise, check to see if it's a keyword. */ -public setinput(filename) -Filename filename; + +private Token getident (chkalias) +boolean chkalias; { - File f; - - f = fopen(filename, "r"); - if (f == nil) - error("%s: Can't open.", filename); - if (!pushinput(ST_FILE, filename, f)) { - unwindinput(ST_FILE); - error("Source file nesting too deep."); + char buf[1024]; + register char *p, *q; + register Token t; + List pl; + String str; + + p = curchar; + q = buf; + if (shellmode) { + do { + *q++ = *p++; + } while (index(" \t\n!&<>*[]()'\"", *p) == nil); + } else { + do { + *q++ = *p++; + } while (isalnum(*p)); + } + curchar = p; + *q = '\0'; + yylval.y_name = identname(buf, false); + if (chkalias) { + if (findalias(yylval.y_name, &pl, &str)) { + expand(pl, str); + while (lexclass[*curchar] == WHITE) { + ++curchar; + } + if (pl == nil) { + t = getident(false); + } else { + t = getident(true); + } + } else if (shellmode) { + t = NAME; + } else { + t = findkeyword(yylval.y_name, NAME); } + } else if (shellmode) { + t = NAME; + } else { + t = findkeyword(yylval.y_name, NAME); + } + return t; } /* - * Send the current line to the shell. + * Scan a number. */ -public shellline() + +private Token getnum() { - register Char *p, c; + char buf[1024]; + register Char *p, *q; + register Token t; + Integer base; + + p = curchar; + q = buf; + if (*p == '0') { + if (*(p+1) == 'x') { + p += 2; + base = 16; + } else if (*(p+1) == 't') { + base = 10; + } else if (varIsSet("$hexin")) { + base = 16; + } else { + base = 8; + } + } else if (varIsSet("$hexin")) { + base = 16; + } else if (varIsSet("$octin")) { + base = 8; + } else { + base = 10; + } + if (base == 16) { + do { + *q++ = *p++; + } while (ishexdigit(*p)); + } else { + do { + *q++ = *p++; + } while (isdigit(*p)); + } + if (*p == '.') { + do { + *q++ = *p++; + } while (isdigit(*p)); + if (*p == 'e' or *p == 'E') { + p++; + if (*p == '+' or *p == '-' or isdigit(*p)) { + *q++ = 'e'; + do { + *q++ = *p++; + } while (isdigit(*p)); + } + } + *q = '\0'; + yylval.y_real = atof(buf); + t = REAL; + } else { + *q = '\0'; + switch (base) { + case 10: + yylval.y_int = atol(buf); + break; - for (p = yytext; (c = getch()) != EOF && c != '\n'; *p++ = c) - ; - *p = '\0'; - shell(yytext); - erecover(); + case 8: + yylval.y_int = octal(buf); + break; + + case 16: + yylval.y_int = hex(buf); + break; + + default: + badcaseval(base); + } + t = INT; + } + curchar = p; + return t; } /* - * Read the rest of the current line in "shell mode". + * Convert a string of octal digits to an integer. */ -public beginshellmode() -{ - shellmode = true; -} - -public endshellmode() +private int octal(s) +String s; { - - shellmode = false; + register Char *p; + register Integer n; + + n = 0; + for (p = s; *p != '\0'; p++) { + n = 8*n + (*p - '0'); + } + return n; } -public stopaliasing() -{ - - doaliases = false; -} +/* + * Convert a string of hexadecimal digits to an integer. + */ -public startaliasing() +private int hex(s) +String s; { - - doaliases = true; + register Char *p; + register Integer n; + + n = 0; + for (p = s; *p != '\0'; p++) { + n *= 16; + if (*p >= 'a' and *p <= 'f') { + n += (*p - 'a' + 10); + } else if (*p >= 'A' and *p <= 'F') { + n += (*p - 'A' + 10); + } else { + n += (*p - '0'); + } + } + return n; } /* - * Print out a token for debugging. + * Scan a string. */ -public print_token(f, t) -File f; -Token t; -{ - - switch (t) { - - case '\n': - fprintf(f, "char '\\n'"); - return; - case EOF: - fprintf(f, "EOF"); - return; - - case NAME: - case STRING: - fprintf(f, "%s, \"%s\"", keywdstring(t), ident(yylval.y_name)); - return; +private Token getstring (quote) +char quote; +{ + register char *p, *q; + char buf[MAXLINESIZE]; + boolean endofstring; + Token t; + + p = curchar; + q = buf; + endofstring = false; + while (not endofstring) { + if (*p == '\\' and *(p+1) == '\n') { + if (fgets(scanner_linebuf, MAXLINESIZE, in) == nil) { + error("non-terminated string"); + } + p = &scanner_linebuf[0] - 1; + } else if (*p == '\n' or *p == '\0') { + error("non-terminated string"); + endofstring = true; + } else if (*p == quote) { + endofstring = true; + } else { + curchar = p; + *q++ = charcon(p); + p = curchar; } - if (t < 256) - fprintf(f, "char '%c'", t); - else - fprintf(f, "%s", keywdstring(t)); + p++; + } + curchar = p; + *q = '\0'; + if (quote == '\'' and buf[1] == '\0') { + yylval.y_char = buf[0]; + t = CHAR; + } else { + yylval.y_string = strdup(buf); + t = STRING; + } + return t; } -public int getch() -{ - int c; - -again: - switch (sp->s_type) { +/* + * Process a character constant. + * Watch out for backslashes. + */ - case ST_FILE: - c = getc(sp->s_file); - if (c == EOF && isterm(sp->s_file)) { - clearerr(sp->s_file); - putchar('\n'); - c = '\n'; - } +private char charcon (s) +String s; +{ + register char *p, *q; + char c, buf[10]; + + p = s; + if (*p == '\\') { + ++p; + switch (*p) { + case '\\': + c = '\\'; break; - case ST_ALIAS: - c = *sp->s_cur++; - if (c == '\0') { - c = EOF; - --sp->s_cur; - } + case 'n': + c = '\n'; break; - default: - panic("Invalid input stream (type %d) to getch.", - sp->s_type); - } - if (c == EOF && popinput()) - goto again; - return (lastc = c); -} - -private int ungetch(c) -Char c; -{ - Char uc; - - if (c != EOF) switch (sp->s_type) { + case 'r': + c = '\r'; + break; - case ST_FILE: - uc = ungetc(c, sp->s_file); + case 't': + c = '\t'; break; - case ST_ALIAS: - if (sp->s_cur == sp->s_data) - panic("Illegal ungetch on alias."); - *--sp->s_cur = c; - uc = c; + case '\'': + case '"': + c = *p; break; - default: - panic("Invalid input stream (type %d) to ungetch.", - sp->s_type); + default: + if (isdigit(*p)) { + q = buf; + do { + *q++ = *p++; + } while (isdigit(*p)); + *q = '\0'; + c = (char) octal(buf); + } + --p; + break; } - lastc = '\0'; - return (uc); + curchar = p; + } else { + c = *p; + } + return c; } /* - * Push the current input stream and - * make the supplied stream the current. + * Input file management routines. */ -/*VARARGS3*/ -public pushinput(type, name, info) -int type; -Filename name; -{ - - if (sp >= &stack[NSTREAMS]) - return (0); - ++sp; - sp->s_type = type; - switch (type) { - case ST_FILE: - sp->s_file = (File)info; - errfilename = sp->s_name = name; - errlineno = sp->s_lineno = 1; - break; - - case ST_ALIAS: - sp->s_cur = sp->s_data = (char *)info; - break; - - default: - panic("Invalid input stream (type %d) to pushinput.", type); +public setinput(filename) +Filename filename; +{ + File f; + + f = fopen(filename, "r"); + if (f == nil) { + error("can't open %s", filename); + } else { + if (curinclindex >= MAXINCLDEPTH) { + error("unreasonable input nesting on \"%s\"", filename); } - return (1); + inclinfo[curinclindex].savefile = in; + inclinfo[curinclindex].savefn = errfilename; + inclinfo[curinclindex].savelineno = errlineno; + curinclindex++; + in = f; + errfilename = filename; + errlineno = 1; + } } -public popinput() +private Boolean eofinput() { + register Boolean b; - if (sp <= &stack[0]) /* never pop stdin or equivalent */ - return (0); - if (sp->s_type == ST_FILE && sp->s_file != stdin) - fclose(sp->s_file); - --sp; - if (sp->s_type == ST_FILE) - errfilename = sp->s_name; - errlineno = sp->s_lineno; - return (1); + if (curinclindex == 0) { + if (isterm(in)) { + putchar('\n'); + clearerr(in); + b = false; + } else { + b = true; + } + } else { + fclose(in); + --curinclindex; + in = inclinfo[curinclindex].savefile; + errfilename = inclinfo[curinclindex].savefn; + errlineno = inclinfo[curinclindex].savelineno; + b = false; + } + return b; } /* - * Unwind the input stack of all input types specified. - * This is called to recover from an infinite - * loop in alias processing or source file including. + * Pop the current input. Return whether successful. */ -public unwindinput(type) -Integer type; -{ - while (sp->s_type == type && popinput()) - ; +public Boolean popinput() +{ + Boolean b; + + if (curinclindex == 0) { + b = false; + } else { + b = (Boolean) (not eofinput()); + } + return b; } /* * Return whether we are currently reading from standard input. */ + public Boolean isstdin() { + return (Boolean) (in == stdin); +} - return ((Boolean)(sp->s_type == ST_FILE && sp->s_file == stdin)); +/* + * Send the current line to the shell. + */ + +public shellline() +{ + register char *p; + + p = curchar; + while (*p != '\0' and (*p == '\n' or lexclass[*p] == WHITE)) { + ++p; + } + shell(p); + if (*p == '\0' and isterm(in)) { + putchar('\n'); + } + erecover(); } -public Boolean istty() +/* + * Read the rest of the current line in "shell mode". + */ + +public beginshellmode() { + shellmode = true; +} - return ((Boolean)isterm(sp->s_file)); +/* + * Print out a token for debugging. + */ + +public print_token(f, t) +File f; +Token t; +{ + if (t == '\n') { + fprintf(f, "char '\\n'"); + } else if (t == EOF) { + fprintf(f, "EOF"); + } else if (t < 256) { + fprintf(f, "char '%c'", t); + } else { + fprintf(f, "\"%s\"", keywdstring(t)); + } } diff --git a/usr/src/old/dbx/source.c b/usr/src/old/dbx/source.c index 3c86bac9e4..0386a929c8 100644 --- a/usr/src/old/dbx/source.c +++ b/usr/src/old/dbx/source.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)source.c 1.11 (Berkeley) %G%"; +static char sccsid[] = "@(#)source.c 1.12 (Berkeley) %G%"; + +static char rcsid[] = "$Header: source.c,v 1.4 84/06/07 16:29:38 linton Exp $"; /* * Source file management. @@ -11,6 +13,9 @@ static char sccsid[] = "@(#)source.c 1.11 (Berkeley) %G%"; #include "object.h" #include "mappings.h" #include "machine.h" +#include "keywords.h" +#include "tree.h" +#include "eval.h" #include #ifndef public @@ -27,6 +32,8 @@ Lineno cursrcline; List sourcepath; #endif +extern char *re_comp(); + private Lineno lastlinenum; private String prevsource = nil; @@ -48,7 +55,7 @@ private String prevsource = nil; typedef long Seekaddr; -#define NSLOTS 20 +#define NSLOTS 40 #define NLINESPERSLOT 500 #define slotno(line) ((line) div NLINESPERSLOT) @@ -59,6 +66,25 @@ typedef long Seekaddr; private File srcfp; private Seekaddr *seektab[NSLOTS]; +/* + * Determine if the current source file is available. + */ + +public boolean canReadSource () +{ + boolean b; + + if (cursource == nil) { + b = false; + } else if (cursource != prevsource) { + skimsource(); + b = (boolean) (lastlinenum != 0); + } else { + b = true; + } + return b; +} + /* * Print out the given lines from the source. */ @@ -81,8 +107,8 @@ Lineno l1, l2; beginerrmsg(); fprintf(stderr, "couldn't read \"%s\"\n", cursource); } else { - lb = (l1 == 0) ? lastlinenum : l1; - ub = (l2 == 0) ? lastlinenum : l2; + lb = (l1 == LASTLINE) ? lastlinenum : l1; + ub = (l2 == LASTLINE) ? lastlinenum : l2; if (lb < 1) { beginerrmsg(); fprintf(stderr, "line number must be positive\n"); @@ -307,71 +333,135 @@ String filename; } else { sprintf(lineno, "+1"); } - call(ed, stdin, stdout, lineno, src, nil); + if (streq(ed, "vi") or streq(ed, "ex")) { + call(ed, stdin, stdout, lineno, src, nil); + } else { + call(ed, stdin, stdout, src, nil); + } } -#include "re.h" /* - * Search the current file with - * a regular expression. + * Strip away portions of a given pattern not part of the regular expression. */ -public search(forward, re) - Boolean forward; - String re; + +private String getpattern (pattern) +String pattern; { - register String p; - register File f; - register Lineno line; - Lineno l1, l2; - Boolean matched; - Char buf[512]; - - if (cursource == nil) { - beginerrmsg(); - fprintf(stderr, "No source file.\n"); - return; + register char *p, *r; + + p = pattern; + while (*p == ' ' or *p == '\t') { + ++p; + } + r = p; + while (*p != '\0') { + ++p; + } + --p; + if (*p == '\n') { + *p = '\0'; + --p; + } + if (*p == *r) { + *p = '\0'; + --p; + } + return r + 1; +} + +/* + * Search the current file for a regular expression. + */ + +public search (direction, pattern) +char direction; +String pattern; +{ + register String p; + register File f; + String re, err; + Lineno line; + boolean matched; + char buf[512]; + + if (cursource == nil) { + beginerrmsg(); + fprintf(stderr, "no source file\n"); + } else { + if (cursource != prevsource) { + skimsource(); } - if (cursource != prevsource) - skimsource(); if (lastlinenum == 0) { - beginerrmsg(); - fprintf(stderr, "Couldn't read \"%s\"\n", cursource); - return; - } - circf = 0; - if (re != nil && *re != '\0') - recompile(re); - matched = false; - f = srcfp; - line = cursrcline; - do { - if (forward) { - line++; - if (line > lastlinenum) - line = 1; + beginerrmsg(); + fprintf(stderr, "couldn't read \"%s\"\n", cursource); + } else { + re = getpattern(pattern); + /* circf = 0; */ + if (re != nil and *re != '\0') { + err = re_comp(re); + if (err != nil) { + error(err); + } + } + matched = false; + f = srcfp; + line = cursrcline; + do { + if (direction == '/') { + ++line; + if (line > lastlinenum) { + line = 1; + } } else { - line--; - if (line < 1) - line = lastlinenum; + --line; + if (line < 1) { + line = lastlinenum; + } } fseek(f, srcaddr(line), L_SET); - for (p = buf; (*p = getc(f)) != '\n'; p++) - if (*p == EOF) - error("Unexpected EOF."); + p = buf; + *p = getc(f); + while ((*p != '\n') and (*p != EOF)) { + ++p; + *p = getc(f); + } *p = '\0'; - matched = (Boolean)rematch(buf); - if (matched) - break; - } while (line != cursrcline); - if (!matched) - error("No match"); -#define WINDOW 10 /* should be used globally */ - l1 = line - WINDOW / 2; - if (l1 < 1) - l1 = 1; - l2 = line + WINDOW / 2; - if (l2 > lastlinenum) - l2 = lastlinenum; - printlines(l1, l2); - cursrcline = line; /* override printlines */ + matched = (boolean) re_exec(buf); + } while (not matched and line != cursrcline); + if (not matched) { + beginerrmsg(); + fprintf(stderr, "no match\n"); + } else { + printlines(line, line); + cursrcline = line; + } + } + } +} + +/* + * Compute a small window around the given line. + */ + +public getsrcwindow (line, l1, l2) +Lineno line, *l1, *l2; +{ + Node s; + integer size; + + s = findvar(identname("$listwindow", true)); + if (s == nil) { + size = 10; + } else { + eval(s); + size = pop(integer); + } + *l1 = line - (size div 2); + if (*l1 < 1) { + *l1 = 1; + } + *l2 = *l1 + size; + if (lastlinenum != LASTLINE and *l2 > lastlinenum) { + *l2 = lastlinenum; + } } diff --git a/usr/src/old/dbx/stabstring.c b/usr/src/old/dbx/stabstring.c index 5226778579..ec194c6c7b 100644 --- a/usr/src/old/dbx/stabstring.c +++ b/usr/src/old/dbx/stabstring.c @@ -1,7 +1,11 @@ +/* Copyright (c) 1982 Regents of the University of California */ + #ifndef lint -static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/27 10:24:04 linton Exp */ +static char sccsid[] = "@(#)stabstring.c 1.2 (Berkeley) %G%"; /* from 1.4 84/03/27 10:24:04 linton Exp */ #endif +static char rcsid[] = "$Header: stabstring.c,v 1.6 84/12/26 10:42:17 linton Exp $"; + /* * String information interpretation * @@ -15,6 +19,7 @@ static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/ #include "symbols.h" #include "names.h" #include "languages.h" +#include "tree.h" #include #include @@ -25,6 +30,7 @@ static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/ * Special characters in symbol table information. */ +#define CONSTNAME 'c' #define TYPENAME 't' #define TAGNAME 'T' #define MODULEBEGIN 'm' @@ -48,7 +54,10 @@ static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/ #define T_SUBRANGE 'r' #define T_ARRAY 'a' -#define T_OPENARRAY 'A' +#define T_OLDOPENARRAY 'A' +#define T_OPENARRAY 'O' +#define T_DYNARRAY 'D' +#define T_SUBARRAY 'E' #define T_RECORD 's' #define T_UNION 'u' #define T_ENUM 'e' @@ -58,6 +67,7 @@ static char sccsid[] = "@(#)stabstring.c 1.1 (Berkeley) %G%"; /* from 1.4 84/03/ #define T_IMPORTED 'i' #define T_SET 'S' #define T_OPAQUE 'o' +#define T_FILE 'd' /* * Table of types indexed by per-file unique identification number. @@ -135,7 +145,7 @@ public entersym (name, np) String name; struct nlist *np; { - Symbol s; + Symbol s, t; char *p; register Name n; char c; @@ -147,25 +157,32 @@ struct nlist *np; chkUnnamedBlock(); curchar = p + 2; switch (c) { + case CONSTNAME: + newSym(s, n); + constName(s); + break; + case TYPENAME: newSym(s, n); typeName(s); break; case TAGNAME: - newSym(s, n); + s = symbol_alloc(); + s->name = n; + s->level = curblock->level + 1; + s->language = curlang; + s->block = curblock; tagName(s); break; case MODULEBEGIN: - newSym(s, n); - publicRoutine(s, MODULE, np->n_value); + publicRoutine(&s, n, MODULE, np->n_value, false); curmodule = s; break; case EXTPROCEDURE: - newSym(s, n); - publicRoutine(s, PROC, np->n_value); + publicRoutine(&s, n, PROC, np->n_value, false); break; case PRIVPROCEDURE: @@ -173,14 +190,11 @@ struct nlist *np; break; case INTPROCEDURE: - newSym(s, n); - markInternal(s); - publicRoutine(s, PROC, np->n_value); + publicRoutine(&s, n, PROC, np->n_value, true); break; case EXTFUNCTION: - newSym(s, n); - publicRoutine(s, FUNC, np->n_value); + publicRoutine(&s, n, FUNC, np->n_value, false); break; case PRIVFUNCTION: @@ -188,21 +202,11 @@ struct nlist *np; break; case INTFUNCTION: - newSym(s, n); - markInternal(s); - publicRoutine(s, FUNC, np->n_value); + publicRoutine(&s, n, FUNC, np->n_value, true); break; case EXTVAR: - find(s, n) where - s->level == program->level and s->class == VAR - endfind(s); - if (s == nil) { - makeVariable(s, n, np->n_value); - s->level = program->level; - s->block = program; - getExtRef(s); - } + extVar(&s, n, np->n_value); break; case MODULEVAR: @@ -245,6 +249,84 @@ struct nlist *np; } } +/* + * Enter a named constant. + */ + +private constName (s) +Symbol s; +{ + integer i; + double d; + char *p, buf[1000]; + + s->class = CONST; + skipchar(curchar, '='); + p = curchar; + ++curchar; + switch (*p) { + case 'b': + s->type = t_boolean; + s->symvalue.constval = build(O_LCON, getint()); + break; + + case 'c': + s->type = t_char; + s->symvalue.constval = build(O_LCON, getint()); + break; + + case 'i': + s->type = t_int; + s->symvalue.constval = build(O_LCON, getint()); + break; + + case 'r': + sscanf(curchar, "%lf", &d); + while (*curchar != '\0' and *curchar != ';') { + ++curchar; + } + --curchar; + s->type = t_real; + s->symvalue.constval = build(O_FCON, d); + break; + + case 's': + p = &buf[0]; + skipchar(curchar, '\''); + while (*curchar != '\'') { + *p = *curchar; + ++p; + ++curchar; + } + *p = '\0'; + s->symvalue.constval = build(O_SCON, strdup(buf)); + s->type = s->symvalue.constval->nodetype; + break; + + case 'e': + getType(s); + skipchar(curchar, ','); + s->symvalue.constval = build(O_LCON, getint()); + break; + + case 'S': + getType(s); + skipchar(curchar, ','); + i = getint(); /* set size */ + skipchar(curchar, ','); + i = getint(); /* number of bits in constant */ + s->symvalue.constval = build(O_LCON, 0); + break; + + default: + s->type = t_int; + s->symvalue.constval = build(O_LCON, 0); + printf("[internal error: unknown constant type '%c']", *p); + break; + } + s->symvalue.constval->nodetype = s->type; +} + /* * Enter a type name. */ @@ -317,15 +399,52 @@ Symbol s; /* * Setup a symbol entry for a public procedure or function. + * + * If it contains nested procedures, then it may already be defined + * in the current block as a MODULE. */ -private publicRoutine (s, class, addr) -Symbol s; +private publicRoutine (s, n, class, addr, isinternal) +Symbol *s; +Name n; Symclass class; Address addr; +boolean isinternal; { - enterRoutine(s, class); - s->level = program->level; + Symbol nt, t; + + newSym(nt, n); + if (isinternal) { + markInternal(nt); + } + enterRoutine(nt, class); + find(t, n) where + t != nt and t->class == MODULE and t->block == nt->block + endfind(t); + if (t == nil) { + t = nt; + } else { + t->language = nt->language; + t->class = nt->class; + t->type = nt->type; + t->chain = nt->chain; + t->symvalue = nt->symvalue; + nt->class = EXTREF; + nt->symvalue.extref = t; + delete(nt); + curparam = t; + changeBlock(t); + } + if (t->block == program) { + t->level = program->level; + } else if (t->class == MODULE) { + t->level = t->block->level; + } else if (t->block->class == MODULE) { + t->level = t->block->block->level; + } else { + t->level = t->block->level + 1; + } + *s = t; } /* @@ -399,6 +518,33 @@ Symclass class; curparam = s; } +/* + * Handling an external variable is tricky, since we might already + * know it but need to define it's type for other type information + * in the file. So just in case we read the type information anyway. + */ + +private extVar (symp, n, off) +Symbol *symp; +Name n; +integer off; +{ + Symbol s, t; + + find(s, n) where + s->level == program->level and s->class == VAR + endfind(s); + if (s == nil) { + makeVariable(s, n, off); + s->level = program->level; + s->block = curmodule; + getExtRef(s); + } else { + t = constype(nil); + } + *symp = s; +} + /* * Check to see if the stab string contains the name of the external * reference. If so, we create a symbol with that name and class EXTREF, and @@ -526,22 +672,6 @@ Symbol s; /* * Construct a type out of a string encoding. - * - * The forms of the string are - * - * - * = - * r;; -- subrange - * a; -- array[index] of element - * A -- open array - * s{:;;}-- record - * u{:;;}-- union - * * -- pointer - * f,; -- function variable - * p; -- procedure variable - * S -- set of type - * o[,] -- opaque type - * i, -- imported type */ private Rangetype getRangeBoundType(); @@ -552,7 +682,17 @@ Symbol type; register Symbol t; register integer n; char class; + char *p; + while (*curchar == '@') { + p = index(curchar, ';'); + if (p == nil) { + fflush(stdout); + fprintf(stderr, "missing ';' after type attributes"); + } else { + curchar = p + 1; + } + } if (isdigit(*curchar)) { n = getint(); if (n >= NTYPES) { @@ -597,10 +737,24 @@ Symbol type; t->type = constype(nil); break; + case T_OLDOPENARRAY: + t->class = DYNARRAY; + t->symvalue.ndims = 1; + t->type = constype(nil); + t->chain = t_int; + break; + case T_OPENARRAY: - t->class = ARRAY; - t->chain = t_open; + case T_DYNARRAY: + consDynarray(t); + break; + + case T_SUBARRAY: + t->class = SUBARRAY; + t->symvalue.ndims = getint(); + skipchar(curchar, ','); t->type = constype(nil); + t->chain = t_int; break; case T_RECORD: @@ -650,6 +804,11 @@ Symbol type; consOpaqType(t); break; + case T_FILE: + t->class = FILET; + t->type = constype(nil); + break; + default: badcaseval(class); } @@ -712,6 +871,20 @@ private Rangetype getRangeBoundType () return r; } +/* + * Construct a dynamic array descriptor. + */ + +private consDynarray (t) +register Symbol t; +{ + t->class = DYNARRAY; + t->symvalue.ndims = getint(); + skipchar(curchar, ','); + t->type = constype(nil); + t->chain = t_int; +} + /* * Construct a record or union type. */ @@ -783,7 +956,7 @@ Symbol t; u->level = curblock->level + 1; u->block = curblock; u->type = t; - u->symvalue.iconval = getint(); + u->symvalue.constval = build(O_LCON, (long) getint()); ++count; skipchar(curchar, ','); chkcont(curchar); @@ -842,10 +1015,11 @@ Symbol t; } t->class = TYPEREF; t->symvalue.typeref = curchar; - curchar = p + 1; if (*p == ',') { curchar = p + 1; tmp = constype(nil); + } else { + curchar = p; } skipchar(curchar, ';'); *p = '\0'; diff --git a/usr/src/old/dbx/symbols.c b/usr/src/old/dbx/symbols.c index ae7b0368cb..a2e6f7b246 100644 --- a/usr/src/old/dbx/symbols.c +++ b/usr/src/old/dbx/symbols.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)symbols.c 1.16 (Berkeley) %G%"; +static char sccsid[] = "@(#)symbols.c 1.17 (Berkeley) %G%"; + +static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton Exp $"; /* * Symbol management. @@ -26,13 +28,14 @@ typedef struct Symbol *Symbol; #include "machine.h" #include "names.h" #include "languages.h" +#include "tree.h" /* * Symbol classes */ typedef enum { - BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, + BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD, PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF @@ -48,9 +51,11 @@ struct Symbol { Symbol type; Symbol chain; union { + Node constval; /* value of constant symbol */ int offset; /* variable address */ long iconval; /* integer constant value */ double fconval; /* floating constant value */ + int ndims; /* no. of dimensions for dynamic/sub-arrays */ struct { /* field offset and size (both in bits) */ int offset; int length; @@ -94,11 +99,13 @@ Symbol t_char; Symbol t_int; Symbol t_real; Symbol t_nil; -Symbol t_open; +Symbol t_addr; Symbol program; Symbol curfunc; +boolean showaggrs; + #define symname(s) ident(s->name) #define codeloc(f) ((f)->symvalue.funcv.beginaddr) #define isblock(s) (Boolean) ( \ @@ -108,7 +115,6 @@ Symbol curfunc; #define isroutine(s) (Boolean) ( \ s->class == FUNC or s->class == PROC \ ) -#define isreg(s) (s->level < 0) #define nosource(f) (not (f)->symvalue.funcv.src) #define isinline(f) ((f)->symvalue.funcv.inline) @@ -172,23 +178,26 @@ public Symbol symbol_alloc() return &(sympool->sym[nleft]); } - -public symbol_dump(func) +public symbol_dump (func) Symbol func; { - register Symbol s; - register Integer i; + register Symbol s; + register integer i; - printf(" symbols in %s \n",symname(func)); - for(i=0; i< HASHTABLESIZE; i++) - for(s=hashtab[i]; s != nil; s=s->next_sym) { - if (s->block == func) psym(s); - } + printf(" symbols in %s \n",symname(func)); + for (i = 0; i < HASHTABLESIZE; i++) { + for (s = hashtab[i]; s != nil; s = s->next_sym) { + if (s->block == func) { + psym(s); + } + } + } } /* * Free all the symbols currently allocated. */ + public symbol_free() { Sympool s, t; @@ -222,6 +231,7 @@ Symbol chain; s = symbol_alloc(); s->name = name; + s->language = primlang; s->level = blevel; s->class = class; s->type = type; @@ -294,7 +304,7 @@ Symbol s; /* * Dump out all the variables associated with the given - * procedure, function, or program at the given recursive level. + * procedure, function, or program associated with the given stack frame. * * This is quite inefficient. We traverse the entire symbol table * each time we're called. The assumption is that this routine @@ -327,44 +337,60 @@ Frame frame; * Builtin types are circular in that btype->type->type = btype. */ -public Symbol maketype(name, lower, upper) +private Symbol maketype(name, lower, upper) String name; long lower; long upper; { register Symbol s; + Name n; - s = newSymbol(identname(name, true), 0, TYPE, nil, nil); + if (name == nil) { + n = nil; + } else { + n = identname(name, true); + } + s = insert(n); s->language = primlang; + s->level = 0; + s->class = TYPE; + s->type = nil; + s->chain = nil; s->type = newSymbol(nil, 0, RANGE, s, nil); - s->type->language = s->language; s->type->symvalue.rangev.lower = lower; s->type->symvalue.rangev.upper = upper; return s; } /* - * These functions are now compiled inline. - * - * public String symname(s) -Symbol s; -{ - checkref(s); - return ident(s->name); -} + * Create the builtin symbols. + */ - * - * public Address codeloc(f) -Symbol f; +public symbols_init () { - checkref(f); - if (not isblock(f)) { - panic("codeloc: \"%s\" is not a block", ident(f->name)); - } - return f->symvalue.funcv.beginaddr; + Symbol s; + + t_boolean = maketype("$boolean", 0L, 1L); + t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); + t_char = maketype("$char", 0L, 255L); + t_real = maketype("$real", 8L, 0L); + t_nil = maketype("$nil", 0L, 0L); + t_addr = insert(identname("$address", true)); + t_addr->language = primlang; + t_addr->level = 0; + t_addr->class = TYPE; + t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); + s = insert(identname("true", true)); + s->class = CONST; + s->type = t_boolean; + s->symvalue.constval = build(O_LCON, 1L); + s->symvalue.constval->nodetype = t_boolean; + s = insert(identname("false", true)); + s->class = CONST; + s->type = t_boolean; + s->symvalue.constval = build(O_LCON, 0L); + s->symvalue.constval->nodetype = t_boolean; } - * - */ /* * Reduce type to avoid worrying about type names. @@ -377,7 +403,9 @@ Symbol type; t = type; if (t != nil) { - if (t->class == VAR or t->class == FIELD or t->class == REF ) { + if (t->class == VAR or t->class == CONST or + t->class == FIELD or t->class == REF + ) { t = t->type; } if (t->class == TYPEREF) { @@ -471,11 +499,18 @@ Symbol t; } } -public Integer level(s) +public integer regnum (s) Symbol s; { + integer r; + checkref(s); - return s->level; + if (s->level < 0) { + r = s->symvalue.offset; + } else { + r = -1; + } + return r; } public Symbol container(s) @@ -485,6 +520,16 @@ Symbol s; return s->block; } +public Node constval(s) +Symbol s; +{ + checkref(s); + if (s->class != CONST) { + error("[internal error: constval(non-CONST)]"); + } + return s->symvalue.constval; +} + /* * Return the object address of the given symbol. * @@ -499,8 +544,9 @@ Symbol s; #define isglobal(s) (s->level == 1) #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) +#define isreg(s) (s->level < 0) -public Address address(s, frame) +public Address address (s, frame) Symbol s; Frame frame; { @@ -521,11 +567,14 @@ Frame frame; cur = cur->block; } if (cur == nil) { - cur = whatblock(pc); - } - frp = findframe(cur); - if (frp == nil) { - panic("unexpected nil frame for \"%s\"", symname(s)); + frp = nil; + } else { + frp = findframe(cur); + if (frp == nil) { + error("[internal error: unexpected nil frame for \"%s\"]", + symname(s) + ); + } } } if (islocaloff(s)) { @@ -545,20 +594,17 @@ Frame frame; * Define a symbol used to access register values. */ -public defregname(n, r) +public defregname (n, r) Name n; -Integer r; +integer r; { - register Symbol s, t; + Symbol s; s = insert(n); - t = newSymbol(nil, 0, PTR, t_int, nil); - t->language = primlang; - s->language = t->language; + s->language = t_addr->language; s->class = VAR; s->level = -3; - s->type = t; - s->block = program; + s->type = t_addr; s->symvalue.offset = r; } @@ -587,11 +633,17 @@ Symbol s; if (prev == nil) { error("couldn't find link to type reference"); } - find(t, prev->name) where - t != prev and t->block->class == MODULE and t->class == prev->class and - t->type != nil and t->type->type != nil and - t->type->type->class != BADUSE - endfind(t); + t = lookup(prev->name); + while (t != nil and + not ( + t != prev and t->name == prev->name and + t->block->class == MODULE and t->class == prev->class and + t->type != nil and t->type->type != nil and + t->type->type->class != BADUSE + ) + ) { + t = t->next_sym; + } if (t == nil) { error("couldn't resolve reference"); } else { @@ -614,27 +666,6 @@ Symbol s; #define MINSHORT -32768 #define MAXSHORT 32767 -/* - * When necessary, compute the upper bound for an open array (Modula-2 style). - */ - -public chkOpenArray (sym) -Symbol sym; -{ - Symbol t; - Address a; - integer n; - - if (sym->class == REF or sym->class == VAR) { - t = rtype(sym->type); - if (t->class == ARRAY and t->chain == t_open) { - a = address(sym, nil); - dread(&n, a + sizeof(Word), sizeof(n)); - t->chain->type->symvalue.rangev.upper = n - 1; - } - } -} - public findbounds (u, lower, upper) Symbol u; long *lower, *upper; @@ -665,7 +696,7 @@ long *lower, *upper; *lower = 0; *upper = u->symvalue.iconval - 1; } else { - panic("unexpected array bound type"); + error("[internal error: unexpected array bound type]"); } } @@ -718,10 +749,16 @@ Symbol sym; r = nel*elsize; break; + case DYNARRAY: + r = (t->symvalue.ndims + 1) * sizeof(Word); + break; + + case SUBARRAY: + r = (2 * t->symvalue.ndims + 1) * sizeof(Word); + break; + case REF: case VAR: - case FVAR: - chkOpenArray(t); r = size(t->type); /* * @@ -731,7 +768,9 @@ Symbol sym; */ break; + case FVAR: case CONST: + case TAG: r = size(t->type); break; @@ -742,15 +781,10 @@ Symbol sym; r = size(t->type); break; - case TAG: - r = size(t->type); - break; - case FIELD: off = t->symvalue.field.offset; len = t->symvalue.field.length; r = (off + len + 7) div 8 - (off div 8); - /* r = (t->symvalue.field.length + 7) div 8; */ break; case RECORD: @@ -762,6 +796,7 @@ Symbol sym; break; case PTR: + case TYPEREF: case FILET: r = sizeof(Word); break; @@ -809,11 +844,19 @@ Symbol sym; r = (r + BITSPERBYTE - 1) div BITSPERBYTE; break; + /* + * These can happen in C (unfortunately) for unresolved type references + * Assume they are pointers. + */ + case BADUSE: + r = sizeof(Address); + break; + default: if (ord(t->class) > ord(TYPEREF)) { panic("size: bad class (%d)", ord(t->class)); } else { - fprintf(stderr, "!! size(%s) ??", classname(t)); + fprintf(stderr, "can't compute size of a %s\n", classname(t)); } r = 0; break; @@ -821,6 +864,33 @@ Symbol sym; return r; } +/* + * Return the size associated with a symbol that takes into account + * reference parameters. This might be better as the normal size function, but + * too many places already depend on it working the way it does. + */ + +public integer psize (s) +Symbol s; +{ + integer r; + Symbol t; + + if (s->class == REF) { + t = rtype(s->type); + if (t->class == DYNARRAY) { + r = (t->symvalue.ndims + 1) * sizeof(Word); + } else if (t->class == SUBARRAY) { + r = (2 * t->symvalue.ndims + 1) * sizeof(Word); + } else { + r = sizeof(Word); + } + } else { + r = size(s); + } + return r; +} + /* * Test if a symbol is a parameter. This is true if there * is a cycle from s->block to s via chain pointers. @@ -842,15 +912,17 @@ Symbol s; * Test if a type is an open array parameter type. */ -public Boolean isopenarray (t) -Symbol t; +public boolean isopenarray (type) +Symbol type; { - return (Boolean) (t->class == ARRAY and t->chain == t_open); + Symbol t; + + t = rtype(type); + return (boolean) (t->class == DYNARRAY); } /* - * Test if a symbol is a var parameter, i.e. has class REF but - * is not an open array parameter (those are treated special). + * Test if a symbol is a var parameter, i.e. has class REF. */ public Boolean isvarparam(s) @@ -865,27 +937,20 @@ Symbol s; */ public Boolean isvariable(s) -register Symbol s; +Symbol s; { return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); } /* - * Test if a symbol is a block, e.g. function, procedure, or the - * main program. - * - * This function is now expanded inline for efficiency. - * - * public Boolean isblock(s) -register Symbol s; + * Test if a symbol is a constant. + */ + +public Boolean isconst(s) +Symbol s; { - return (Boolean) ( - s->class == FUNC or s->class == PROC or - s->class == MODULE or s->class == PROG - ); + return (Boolean) (s->class == CONST); } - * - */ /* * Test if a symbol is a module. @@ -897,17 +962,6 @@ register Symbol s; return (Boolean) (s->class == MODULE); } -/* - * Test if a symbol is builtin, that is, a predefined type or - * reserved word. - */ - -public Boolean isbuiltin(s) -register Symbol s; -{ - return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); -} - /* * Mark a procedure or function as internal, meaning that it is called * with a different calling sequence. @@ -925,6 +979,50 @@ Symbol s; return s->symvalue.funcv.intern; } +/* + * Decide if a field begins or ends on a bit rather than byte boundary. + */ + +public Boolean isbitfield(s) +register Symbol s; +{ + boolean b; + register integer off, len; + register Symbol t; + + off = s->symvalue.field.offset; + len = s->symvalue.field.length; + if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { + b = true; + } else { + t = rtype(s->type); + b = (Boolean) ( + (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or + len != (size(t)*BITSPERBYTE) + ); + } + return b; +} + +private boolean primlang_typematch (t1, t2) +Symbol t1, t2; +{ + return (boolean) ( + (t1 == t2) or + ( + t1->class == RANGE and t2->class == RANGE and + t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and + t1->symvalue.rangev.upper == t2->symvalue.rangev.upper + ) or ( + t1->class == PTR and t2->class == RANGE and + t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower + ) or ( + t2->class == PTR and t1->class == RANGE and + t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower + ) + ); +} + /* * Test if two types match. * Equivalent names implies a match in any language. @@ -948,13 +1046,7 @@ register Symbol t1, t2; b = isblock(t1); } else if (t1->language == primlang) { if (t2->language == primlang) { - rt1 = rtype(t1); - rt2 = rtype(t2); - b = (boolean) ( - (rt1->type == t_open and rt2->type == t_int) or - (rt2->type == t_open and rt1->type == t_int) or - rt1 == rt2 - ); + b = primlang_typematch(rtype(t1), rtype(t2)); } else { b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); } @@ -966,10 +1058,6 @@ register Symbol t1, t2; } else { b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); } - } else if (t2->language == nil) { - b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); - } else if (isbuiltin(t1) or isbuiltin(t1->type)) { - b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); } else { b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); } @@ -984,14 +1072,17 @@ public Boolean istypename(type, name) Symbol type; String name; { - Symbol t; + register Symbol t; Boolean b; t = type; - checkref(t); - b = (Boolean) ( - t->class == TYPE and streq(ident(t->name), name) - ); + if (t == nil) { + b = false; + } else { + b = (Boolean) ( + t->class == TYPE and streq(ident(t->name), name) + ); + } return b; } @@ -1036,15 +1127,15 @@ typedef char *Arglist; #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] private Symbol mkstring(); -private Symbol namenode(); /* * Determine the type of a parse tree. + * * Also make some symbol-dependent changes to the tree such as - * changing removing RVAL nodes for constant symbols. + * removing indirection for constant or register symbols. */ -public assigntypes(p) +public assigntypes (p) register Node p; { register Node p1; @@ -1052,30 +1143,35 @@ register Node p; switch (p->op) { case O_SYM: - p->nodetype = namenode(p); + p->nodetype = p->value.sym; break; case O_LCON: p->nodetype = t_int; break; + case O_CCON: + p->nodetype = t_char; + break; + case O_FCON: p->nodetype = t_real; break; case O_SCON: - p->value.scon = strdup(p->value.scon); - s = mkstring(p->value.scon); - if (s == t_char) { - p->op = O_LCON; - p->value.lcon = p->value.scon[0]; - } - p->nodetype = s; + p->nodetype = mkstring(p->value.scon); break; case O_INDIR: p1 = p->value.arg[0]; - chkclass(p1, PTR); + s = rtype(p1->nodetype); + if (s->class != PTR) { + beginerrmsg(); + fprintf(stderr, "\""); + prtree(stderr, p1); + fprintf(stderr, "\" is not a pointer"); + enderrmsg(); + } p->nodetype = rtype(p1->nodetype)->type; break; @@ -1087,21 +1183,16 @@ register Node p; p1 = p->value.arg[0]; p->nodetype = p1->nodetype; if (p1->op == O_SYM) { - if (p1->nodetype->class == FUNC) { - p->op = O_CALL; - p->value.arg[1] = nil; + if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { + p->op = p1->op; + p->value.sym = p1->value.sym; + p->nodetype = p1->nodetype; + dispose(p1); } else if (p1->value.sym->class == CONST) { - if (compatible(p1->value.sym->type, t_real)) { - p->op = O_FCON; - p->value.fcon = p1->value.sym->symvalue.fconval; - p->nodetype = t_real; - dispose(p1); - } else { - p->op = O_LCON; - p->value.lcon = p1->value.sym->symvalue.iconval; - p->nodetype = p1->value.sym->type; - dispose(p1); - } + p->op = p1->op; + p->value = p1->value; + p->nodetype = p1->nodetype; + dispose(p1); } else if (isreg(p1->value.sym)) { p->op = O_SYM; p->value.sym = p1->value.sym; @@ -1118,9 +1209,11 @@ register Node p; } break; - /* - * Perform a cast if the call is of the form "type(expr)". - */ + case O_COMMA: + p->nodetype = p->value.arg[0]->nodetype; + break; + + case O_CALLPROC: case O_CALL: p1 = p->value.arg[0]; p->nodetype = rtype(p1->nodetype)->type; @@ -1243,40 +1336,6 @@ Symbol t; } } -/* - * Create a node for a name. The symbol for the name has already - * been chosen, either implicitly with "which" or explicitly from - * the dot routine. - */ - -private Symbol namenode(p) -Node p; -{ - register Symbol r, s; - register Node np; - - s = p->value.sym; - if (s->class == REF) { - np = new(Node); - np->op = p->op; - np->nodetype = s; - np->value.sym = s; - p->op = O_INDIR; - p->value.arg[0] = np; - } -/* - * Old way - * - if (s->class == CONST or s->class == VAR or s->class == FVAR) { - r = s->type; - } else { - r = s; - } - * - */ - return s; -} - /* * Convert a tree to a type via a conversion operator; * if this isn't possible generate an error. @@ -1322,26 +1381,27 @@ public Node dot(record, fieldname) Node record; Name fieldname; { - register Node p; + register Node rec, p; register Symbol s, t; - if (isblock(record->nodetype)) { + rec = record; + if (isblock(rec->nodetype)) { find(s, fieldname) where - s->block == record->nodetype and - s->class != FIELD and s->class != TAG + s->block == rec->nodetype and + s->class != FIELD endfind(s); if (s == nil) { beginerrmsg(); fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); - printname(stderr, record->nodetype); + printname(stderr, rec->nodetype); enderrmsg(); } p = new(Node); p->op = O_SYM; p->value.sym = s; - p->nodetype = namenode(p); + p->nodetype = s; } else { - p = record; + p = rec; t = rtype(p->nodetype); if (t->class == PTR) { s = findfield(fieldname, t->type); @@ -1351,15 +1411,16 @@ Name fieldname; if (s == nil) { beginerrmsg(); fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); - prtree(stderr, record); + prtree(stderr, rec); enderrmsg(); } - if (t->class == PTR and not isreg(record->nodetype)) { - p = build(O_INDIR, record); + if (t->class != PTR or isreg(rec->nodetype)) { + p = unrval(p); } + p->nodetype = t_addr; p = build(O_DOT, p, build(O_SYM, s)); } - return p; + return build(O_RVAL, p); } /* @@ -1371,31 +1432,36 @@ public Node subscript(a, slist) Node a, slist; { Symbol t; + Node p; t = rtype(a->nodetype); - if (t->language == nil) { - error("unknown language"); + if (t->language == nil or t->language == primlang) { + p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); } else { - return (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); + p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); } + return build(O_RVAL, p); } /* * Evaluate a subscript index. */ -public int evalindex(s, i) +public int evalindex(s, base, i) Symbol s; +Address base; long i; { Symbol t; + int r; t = rtype(s); - if (t->language == nil) { - error("unknown language"); + if (t->language == nil or t->language == primlang) { + r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); } else { - return ((*language_op(t->language, L_EVALAREF)) (s, i)); + r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); } + return r; } /* @@ -1414,26 +1480,6 @@ register Node p; } } -/* - * Check to make sure the given tree has a type of the given class. - */ - -private chkclass(p, class) -Node p; -Symclass class; -{ - struct Symbol tmpsym; - - tmpsym.class = class; - if (rtype(p->nodetype)->class != class) { - beginerrmsg(); - fprintf(stderr, "\""); - prtree(stderr, p); - fprintf(stderr, "\" is not a %s", classname(&tmpsym)); - enderrmsg(); - } -} - /* * Construct a node for the type of a string. */ @@ -1441,32 +1487,13 @@ Symclass class; private Symbol mkstring(str) String str; { - register char *p, *q; register Symbol s; - integer len; - p = str; - q = str; - while (*p != '\0') { - if (*p == '\\') { - ++p; - } - *q = *p; - ++p; - ++q; - } - *q = '\0'; - len = p - str; - if (len == 1) { - s = t_char; - } else { - s = newSymbol(nil, 0, ARRAY, t_char, nil); - s->language = primlang; - s->chain = newSymbol(nil, 0, RANGE, t_int, nil); - s->chain->language = s->language; - s->chain->symvalue.rangev.lower = 1; - s->chain->symvalue.rangev.upper = len + 1; - } + s = newSymbol(nil, 0, ARRAY, t_char, nil); + s->chain = newSymbol(nil, 0, RANGE, t_int, nil); + s->chain->language = s->language; + s->chain->symvalue.rangev.lower = 1; + s->chain->symvalue.rangev.upper = strlen(str) + 1; return s; } @@ -1481,49 +1508,121 @@ Symbol s; } /* - * Figure out the "current" variable or function being referred to, - * this is either the active one or the most visible from the - * current scope. + * Figure out the "current" variable or function being referred to + * by the name n. */ -public Symbol which(n) +private boolean stwhich(), dynwhich(); + +public Symbol which (n) Name n; { - register Symbol s, p, t, f; + Symbol s; - find(s, n) - where s->class != FIELD and s->class != TAG and s->class != MODULE - endfind(s); - if (s == nil) { - s = lookup(n); - } + s = lookup(n); if (s == nil) { error("\"%s\" is not defined", ident(n)); - } else if (s == program or isbuiltin(s)) { - t = s; + } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { + printf("[using "); + printname(stdout, s); + printf("]\n"); + } + return s; +} + +/* + * Static search. + */ + +private boolean stwhich (var_s) +Symbol *var_s; +{ + Name n; /* name of desired symbol */ + Symbol s; /* iteration variable for symbols with name n */ + Symbol f; /* iteration variable for blocks containing s */ + integer count; /* number of levels from s->block to curfunc */ + Symbol t; /* current best answer for stwhich(n) */ + integer mincount; /* relative level for current best answer (t) */ + boolean b; /* return value, true if symbol found */ + + s = *var_s; + n = s->name; + t = s; + mincount = 10000; /* force first match to set mincount */ + do { + if (s->name == n and s->class != FIELD and s->class != TAG) { + f = curfunc; + count = 0; + while (f != nil and f != s->block) { + ++count; + f = f->block; + } + if (f != nil and count < mincount) { + t = s; + mincount = count; + b = true; + } + } + s = s->next_sym; + } while (s != nil); + if (mincount != 10000) { + *var_s = t; + b = true; } else { - /* start with current function */ - p = curfunc; - do { - find(t, n) where - t->block == p and - t->class != FIELD and t->class != TAG and t->class != MODULE - endfind(t); - p = p->block; - } while (t == nil and p != nil); - if (t == nil) { - t = s; + b = false; + } + return b; +} + +/* + * Dynamic search. + */ + +private boolean dynwhich (var_s) +Symbol *var_s; +{ + Name n; /* name of desired symbol */ + Symbol s; /* iteration variable for possible symbols */ + Symbol f; /* iteration variable for active functions */ + Frame frp; /* frame associated with stack walk */ + boolean b; /* return value */ + + f = curfunc; + frp = curfuncframe(); + n = (*var_s)->name; + b = false; + if (frp != nil) { + frp = nextfunc(frp, &f); + while (frp != nil) { + s = *var_s; + while (s != nil and + ( + s->name != n or s->block != f or + s->class == FIELD or s->class == TAG + ) + ) { + s = s->next_sym; + } + if (s != nil) { + *var_s = s; + b = true; + break; + } + if (f == program) { + break; + } + frp = nextfunc(frp, &f); } } - return t; + return b; } /* - * Find the symbol which is has the same name and scope as the + * Find the symbol that has the same name and scope as the * given symbol but is of the given field. Return nil if there is none. */ -public Symbol findfield(fieldname, record) +public Symbol findfield (fieldname, record) Name fieldname; Symbol record; { diff --git a/usr/src/old/dbx/tree.c b/usr/src/old/dbx/tree.c index fce6e130a5..6db7e8569b 100644 --- a/usr/src/old/dbx/tree.c +++ b/usr/src/old/dbx/tree.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)tree.c 1.7 (Berkeley) %G%"; +static char sccsid[] = "@(#)tree.c 1.8 (Berkeley) %G%"; + +static char rcsid[] = "$Header: tree.c,v 1.5 84/12/26 10:42:55 linton Exp $"; /* * Parse tree management. @@ -9,6 +11,7 @@ static char sccsid[] = "@(#)tree.c 1.7 (Berkeley) %G%"; #include "defs.h" #include "tree.h" #include "operators.h" +#include "debug.h" #include "eval.h" #include "events.h" #include "symbols.h" @@ -103,7 +106,10 @@ Operator op; case O_DEBUG: case O_LCON: + case O_CCON: case O_CONT: + case O_CATCH: + case O_IGNORE: case O_TRACEOFF: p->value.lcon = nextarg(long); break; @@ -120,22 +126,26 @@ Operator op; break; case O_RVAL: - q = nextarg(Node); - if (q->op == O_CALL) { - *p = *q; - dispose(q); - } else { - p->value.arg[0] = q; - } + case O_INDIR: + p->value.arg[0] = nextarg(Node); break; - case O_INDIR: + case O_CALL: q = nextarg(Node); - if (q != nil and q->op == O_RVAL) { + if (q->op == O_SYM and + (q->value.sym->class == TYPE or q->value.sym->class == TAG) + ) { + p->op = O_TYPERENAME; + p->value.arg[0] = nextarg(Node); + p->value.arg[1] = q; + q = p->value.arg[0]; + if (q->value.arg[1] != nil) { + error("too many arguments to type rename"); + } p->value.arg[0] = q->value.arg[0]; - dispose(q); } else { p->value.arg[0] = q; + p->value.arg[1] = nextarg(Node); } break; @@ -172,25 +182,51 @@ Operator op; } check(p); assigntypes(p); - if(debug_flag[5]) { - fprintf(stderr," built %s node %d with arg0 %d arg1 %d \n", - showoperator(p->op), p, p->value.arg[0],p->value.arg[1]); + if (tracetree) { + printf("built %s node 0x%x with arg[0] 0x%x arg[1] 0x%x\n", + opname(p->op), p, p->value.arg[0], p->value.arg[1]); + fflush(stdout); } return p; } /* - * Create a command list from a single command. + * Strip away indirection from a node, thus returning a node for + * interpreting the expression as an lvalue. */ -public Cmdlist buildcmdlist(cmd) -Command cmd; +public Node unrval (exp) +Node exp; { - Cmdlist cmdlist; + Node p; + Symbol t; + + if (exp->op == O_RVAL) { + p = exp->value.arg[0]; + dispose(exp); + } else if (exp->op == O_INDIR) { + p = exp->value.arg[0]; + if (p->op == O_RVAL) { + p->op = O_INDIR; + p->nodetype = exp->nodetype; + } + dispose(exp); + } else { + p = exp; + } + return p; +} - cmdlist = list_alloc(); - cmdlist_append(cmd, cmdlist); - return cmdlist; +/* + * Create a node for renaming a node to a pointer type. + */ + +public Node renameptr (p, t) +Node p; +Node t; +{ + t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil); + p = build(O_TYPERENAME, p, t); } /* @@ -205,12 +241,15 @@ Node p; checkref(p); switch (p->op) { case O_RVAL: + case O_INDIR: r = p->value.arg[0]; + r->nodetype = t_addr; + dispose(p); break; - case O_CALL: - r = build(O_LCON, codeloc(p->value.arg[0]->value.sym)); - tfree(p); + case O_TYPERENAME: + r = p; + r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil); break; case O_SYM: @@ -219,27 +258,24 @@ Node p; } else { r = build(O_LCON, address(p->value.sym, nil)); } - tfree(p); + r->nodetype = t_addr; + dispose(p); break; case O_DOT: r = p; - break; - - case O_INDIR: - r = p->value.arg[0]; - dispose(p); + r->nodetype = t_addr; break; default: beginerrmsg(); - fprintf(stderr, "expected variable, found "); + fprintf(stderr, "expected variable, found \""); prtree(stderr, p); + fprintf(stderr, "\""); tfree(p); enderrmsg(); /* NOTREACHED */ } - r->nodetype = t_int; return r; } @@ -256,6 +292,20 @@ Node p; return build(O_INDIR, p); } +/* + * Create a command list from a single command. + */ + +public Cmdlist buildcmdlist(cmd) +Command cmd; +{ + Cmdlist cmdlist; + + cmdlist = list_alloc(); + cmdlist_append(cmd, cmdlist); + return cmdlist; +} + /* * Print out a command. */ @@ -314,6 +364,8 @@ Command cmd; fprintf(f, "%s", cmd->value.scon); break; + case O_CATCH: + case O_IGNORE: case O_TRACEOFF: fprintf(f, "%d", cmd->value.lcon); break; @@ -442,11 +494,11 @@ register Node p; break; case O_LCON: - if (compatible(p->nodetype, t_char)) { - fprintf(f, "'%c'", p->value.lcon); - } else { - fprintf(f, "%d", p->value.lcon); - } + fprintf(f, "%d", p->value.lcon); + break; + + case O_CCON: + fprintf(f, "'%c'", p->value.lcon); break; case O_FCON: @@ -473,13 +525,6 @@ register Node p; break; case O_RVAL: - if (p->value.arg[0]->op == O_SYM) { - printname(f, p->value.arg[0]->value.sym); - } else { - prtree(f, p->value.arg[0]); - } - break; - case O_ITOF: prtree(f, p->value.arg[0]); break; @@ -494,31 +539,22 @@ register Node p; break; case O_INDIR: - q = p->value.arg[0]; - if (isvarparam(q->nodetype)) { - prtree(f, q); - } else { - if (q->op == O_SYM or q->op == O_LCON or q->op == O_DOT) { - prtree(f, q); - fprintf(f, "^"); - } else { - fprintf(f, "*("); - prtree(f, q); - fprintf(f, ")"); - } - } + prtree(f, p->value.arg[0]); + fprintf(f, "^"); break; case O_DOT: - q = p->value.arg[0]; - if (q->op == O_INDIR) { - prtree(f, q->value.arg[0]); - } else { - prtree(f, q); - } + prtree(f, p->value.arg[0]); fprintf(f, ".%s", symname(p->value.arg[1]->value.sym)); break; + case O_TYPERENAME: + prtree(f, p->value.arg[1]); + fprintf(f, "("); + prtree(f, p->value.arg[0]); + fprintf(f, ")"); + break; + default: switch (degree(op)) { case BINARY: @@ -533,7 +569,12 @@ register Node p; break; default: - error("internal error: bad op %d in prtree", op); + if (opinfo[ord(op)].opstring == nil) { + fprintf(f, "[op %d]", ord(op)); + } else { + fprintf(f, "%s", opinfo[ord(op)].opstring); + } + break; } break; } @@ -573,67 +614,3 @@ Node p; } dispose(p); } - -/* - * A recursive tree search routine to test if two trees are equivalent. - */ - -public Boolean tr_equal(t1, t2) -register Node t1; -register Node t2; -{ - register Boolean b; - - if (t1 == nil and t2 == nil) { - b = true; - } else if (t1 == nil or t2 == nil) { - b = false; - } else if (t1->op != t2->op or degree(t1->op) != degree(t2->op)) { - b = false; - } else { - switch (degree(t1->op)) { - case LEAF: - switch (t1->op) { - case O_NAME: - b = (Boolean) (t1->value.name == t2->value.name); - break; - - case O_SYM: - b = (Boolean) (t1->value.sym == t2->value.sym); - break; - - case O_LCON: - b = (Boolean) (t1->value.lcon == t2->value.lcon); - break; - - case O_FCON: - b = (Boolean) (t1->value.fcon == t2->value.fcon); - break; - - case O_SCON: - b = (Boolean) (t1->value.scon == t2->value.scon); - break; - - default: - panic("tr_equal: leaf %d\n", t1->op); - } - /*NOTREACHED*/ - - case BINARY: - if (not tr_equal(t1->value.arg[0], t2->value.arg[0])) { - b = false; - } else { - b = tr_equal(t1->value.arg[1], t2->value.arg[1]); - } - break; - - case UNARY: - b = tr_equal(t1->value.arg[0], t2->value.arg[0]); - break; - - default: - panic("tr_equal: bad degree for op %d\n", t1->op); - } - } - return b; -} diff --git a/usr/src/old/dbx/vax.c b/usr/src/old/dbx/vax.c index e3ee5a11cb..f98ad0574b 100644 --- a/usr/src/old/dbx/vax.c +++ b/usr/src/old/dbx/vax.c @@ -1,6 +1,8 @@ /* Copyright (c) 1982 Regents of the University of California */ -static char sccsid[] = "@(#)vax.c 1.12 (Berkeley) %G%"; +static char sccsid[] = "@(#)vax.c 1.13 (Berkeley) %G%"; + +static char rcsid[] = "$Header: machine.c,v 1.5 84/12/26 10:40:05 linton Exp $"; /* * Target machine dependent stuff. @@ -16,6 +18,7 @@ static char sccsid[] = "@(#)vax.c 1.12 (Berkeley) %G%"; #include "source.h" #include "mappings.h" #include "object.h" +#include "keywords.h" #include "ops.h" #include @@ -289,7 +292,15 @@ int mode; printf("%x", argval); } } else { - printf("%d(%s)", argval, reg); + if (varIsSet("$hexoffsets")) { + if (argval < 0) { + printf("-%x(%s)", -(argval), reg); + } else { + printf("%x(%s)", argval, reg); + } + } else { + printf("%d(%s)", argval, reg); + } } return argval; } @@ -472,24 +483,27 @@ public printerror() { extern Integer sys_nsig; extern String sys_siglist[]; - Integer err; + integer err; if (isfinished(process)) { err = exitcode(process); - printf("\"%s\" terminated", objname); - if (err) - printf("abnormally (exit code %d)", err); - putchar('\n'); + if (err == 0) { + printf("\"%s\" terminated normally\n", objname); + } else { + printf("\"%s\" terminated abnormally (exit code %d)\n", + objname, err + ); + } erecover(); } if (runfirst) { - fprintf(stderr, "Entering debugger ..."); + fprintf(stderr, "Entering debugger ...\n"); init(); - fprintf(stderr, " type 'help' for help\n"); } err = errnum(process); putchar('\n'); printsig(err); + putchar(' '); printloc(); putchar('\n'); if (curline > 0) { @@ -500,48 +514,49 @@ public printerror() erecover(); } +/* + * Print out a signal. + */ + private String illinames[] = { - "reserved addressing fault", - "priviliged instruction fault", - "reserved operand fault" + "reserved addressing fault", + "priviliged instruction fault", + "reserved operand fault" }; + private String fpenames[] = { - nil, - "integer overflow trap", - "integer divide by zero trap", - "floating overflow trap", - "floating/decimal divide by zero trap", - "floating underflow trap", - "decimal overflow trap", - "subscript out of range trap", - "floating overflow fault", - "floating divide by zero fault", - "floating undeflow fault" + nil, + "integer overflow trap", + "integer divide by zero trap", + "floating overflow trap", + "floating/decimal divide by zero trap", + "floating underflow trap", + "decimal overflow trap", + "subscript out of range trap", + "floating overflow fault", + "floating divide by zero fault", + "floating undeflow fault" }; -public printsig(signo) - Integer signo; +public printsig (signo) +integer signo; { - Integer sigcode; - - if (0 < signo && signo < sys_nsig) - printf("%s ", sys_siglist[signo]); - else - printf("signal %d ", signo); - sigcode = errcode(process); - switch (signo) { - - case SIGFPE: - if (sigcode > 0 && - sigcode < sizeof fpenames / sizeof fpenames[0]) - printf("(%s) ", fpenames[sigcode]); - break; + integer code; - case SIGILL: - if (sigcode >= 0 && - sigcode < sizeof illinames / sizeof illinames[0]) - printf("(%s) ", illinames[sigcode]); - break; + if (signo < 0 or signo > sys_nsig) { + printf("[signal %d]", signo); + } else { + printf("%s", sys_siglist[signo]); + } + code = errcode(process); + if (signo == SIGILL) { + if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { + printf(" (%s)", illinames[code]); + } + } else if (signo == SIGFPE) { + if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { + printf(" (%s)", fpenames[code]); + } } } @@ -559,10 +574,11 @@ public endprogram() stepto(nextaddr(pc, true)); printnews(); exitcode = argn(1, nil); - printf("\nexecution completed"); - if (exitcode) - printf(" (exit code %d)", exitcode); - putchar('\n'); + if (exitcode != 0) { + printf("\nexecution completed (exit code %d)\n", exitcode); + } else { + printf("\nexecution completed\n"); + } getsrcpos(); erecover(); } @@ -572,7 +588,6 @@ public endprogram() * is true). If "isnext" is true, skip over procedure calls. */ -private Address findnextaddr(); private Address getcall(); public dostep(isnext) @@ -581,25 +596,20 @@ Boolean isnext; register Address addr; register Lineno line; String filename; - Address startaddr, prevaddr; + Address startaddr; startaddr = pc; - prevaddr = startaddr; addr = nextaddr(pc, isnext); if (not inst_tracing and nlhdr.nlines != 0) { line = linelookup(addr); while (line == 0) { - prevaddr = addr; - addr = findnextaddr(addr, isnext); + addr = nextaddr(addr, isnext); line = linelookup(addr); } curline = line; } else { curline = 0; } - if (addr == startaddr) { - stepto(prevaddr); - } stepto(addr); filename = srcfilename(addr); setsource(filename); @@ -617,6 +627,8 @@ Boolean isnext; * that branches is the branch address (or relative offset). */ +private Address findnextaddr(); + public Address nextaddr(startaddr, isnext) Address startaddr; boolean isnext; @@ -630,6 +642,27 @@ boolean isnext; return addr; } +/* + * Determine if it's ok to skip function f entered by instruction ins. + * If so, we're going to compute the return address and step to it. + * Therefore we cannot skip over a function entered by a jsb or bsb, + * since the return address is not easily computed for them. + */ + +private boolean skipfunc (ins, f) +VaxOpcode ins; +Symbol f; +{ + boolean b; + + b = (boolean) ( + ins != O_JSB and ins != O_BSBB and ins != O_BSBW and + not inst_tracing and nlhdr.nlines != 0 and + nosource(curfunc) and canskip(curfunc) + ); + return b; +} + private Address findnextaddr(startaddr, isnext) Address startaddr; Boolean isnext; @@ -648,55 +681,64 @@ Boolean isnext; addr = startaddr; iread(&ins, addr, sizeof(ins)); switch (ins) { + /* + * It used to be that unconditional jumps and branches were handled + * by taking their destination address as the next address. While + * saving the cost of starting up the process, this approach + * doesn't work when jumping indirect (since the value in the + * register might not yet have been set). + * + * So unconditional jumps and branches are now handled the same way + * as conditional jumps and branches. + * case O_BRB: case O_BRW: addrstatus = BRANCH; break; + * + */ case O_BSBB: case O_BSBW: case O_JSB: case O_CALLG: case O_CALLS: - if (isnext) { - addrstatus = SEQUENTIAL; - } else { + addrstatus = KNOWN; + stepto(addr); + pstep(process, DEFSIG); + addr = reg(PROGCTR); + pc = addr; + setcurfunc(whatblock(pc)); + if (not isbperr()) { + printstatus(); + /* NOTREACHED */ + } + bpact(); + if (isnext or skipfunc(ins, curfunc)) { addrstatus = KNOWN; + addr = return_addr(); stepto(addr); - pstep(process, DEFSIG); - addr = reg(PROGCTR); - pc = addr; - setcurfunc(whatblock(pc)); - if (not isbperr()) { - printstatus(); - /* NOTREACHED */ - } bpact(); - if (nosource(curfunc) and canskip(curfunc) and - nlhdr.nlines != 0) { - addrstatus = KNOWN; - addr = return_addr(); - stepto(addr); - bpact(); - } else { - callnews(/* iscall = */ true); - } + } else { + callnews(/* iscall = */ true); } break; case O_RSB: case O_RET: addrstatus = KNOWN; + stepto(addr); callnews(/* iscall = */ false); - addr = return_addr(); - if (addr == pc) { /* recursive ret to self */ - pstep(process, DEFSIG); - } else { - stepto(addr); + pstep(process, DEFSIG); + addr = reg(PROGCTR); + pc = addr; + if (not isbperr()) { + printstatus(); } bpact(); break; + case O_BRB: case O_BRW: case O_JMP: /* because it may be jmp (r1) */ case O_BNEQ: case O_BEQL: case O_BGTR: case O_BLEQ: case O_BGEQ: case O_BLSS: @@ -940,16 +982,6 @@ Address addr; panic("unsetbp: couldn't find address %d", addr); } -/* - * Predicate to test if the reason the process stopped was because - * of a breakpoint. - */ - -public Boolean isbperr() -{ - return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); -} - /* * Enter a procedure by creating and executing a call instruction. */ -- 2.20.1