19676Slinton /* Copyright (c) 1982 Regents of the University of California */ 29676Slinton 3*16616Ssam static char sccsid[] = "@(#)printsym.c 1.12 8/10/83"; 49676Slinton 5*16616Ssam static char rcsid[] = "$Header: printsym.c,v 1.3 84/03/27 10:23:14 linton Exp $"; 6*16616Ssam 79676Slinton /* 89676Slinton * Printing of symbolic information. 99676Slinton */ 109676Slinton 119676Slinton #include "defs.h" 129676Slinton #include "symbols.h" 139676Slinton #include "languages.h" 149676Slinton #include "printsym.h" 159676Slinton #include "tree.h" 169676Slinton #include "eval.h" 179676Slinton #include "mappings.h" 189676Slinton #include "process.h" 199676Slinton #include "runtime.h" 209676Slinton #include "machine.h" 219676Slinton #include "names.h" 229676Slinton #include "main.h" 239676Slinton 249676Slinton #ifndef public 259676Slinton #endif 269676Slinton 279676Slinton /* 2811863Slinton * Maximum number of arguments to a function. 2911863Slinton * This is used as a check for the possibility that the stack has been 3011863Slinton * overwritten and therefore a saved argument pointer might indicate 3111863Slinton * to an absurdly large number of arguments. 3211863Slinton */ 3311863Slinton 3411863Slinton #define MAXARGSPASSED 20 3511863Slinton 3611863Slinton /* 379676Slinton * Return a pointer to the string for the name of the class that 389676Slinton * the given symbol belongs to. 399676Slinton */ 409676Slinton 419676Slinton private String clname[] = { 429676Slinton "bad use", "constant", "type", "variable", "array", "fileptr", 439676Slinton "record", "field", "procedure", "function", "funcvar", 449676Slinton "ref", "pointer", "file", "set", "range", "label", "withptr", 459676Slinton "scalar", "string", "program", "improper", "variant", 46*16616Ssam "procparam", "funcparam", "module", "tag", "common", "extref", "typeref" 479676Slinton }; 489676Slinton 499676Slinton public String classname(s) 509676Slinton Symbol s; 519676Slinton { 529676Slinton return clname[ord(s->class)]; 539676Slinton } 549676Slinton 559676Slinton /* 569676Slinton * Note the entry of the given block, unless it's the main program. 579676Slinton */ 589676Slinton 599676Slinton public printentry(s) 609676Slinton Symbol s; 619676Slinton { 629676Slinton if (s != program) { 639676Slinton printf("\nentering %s %s\n", classname(s), symname(s)); 649676Slinton } 659676Slinton } 669676Slinton 679676Slinton /* 689676Slinton * Note the exit of the given block 699676Slinton */ 709676Slinton 719676Slinton public printexit(s) 729676Slinton Symbol s; 739676Slinton { 749676Slinton if (s != program) { 759676Slinton printf("leaving %s %s\n\n", classname(s), symname(s)); 769676Slinton } 779676Slinton } 789676Slinton 799676Slinton /* 809676Slinton * Note the call of s from t. 819676Slinton */ 829676Slinton 839676Slinton public printcall(s, t) 849676Slinton Symbol s, t; 859676Slinton { 869676Slinton printf("calling %s", symname(s)); 879676Slinton printparams(s, nil); 889676Slinton printf(" from %s %s\n", classname(t), symname(t)); 899676Slinton } 909676Slinton 919676Slinton /* 929676Slinton * Note the return from s. If s is a function, print the value 939676Slinton * it is returning. This is somewhat painful, since the function 949676Slinton * has actually just returned. 959676Slinton */ 969676Slinton 979676Slinton public printrtn(s) 989676Slinton Symbol s; 999676Slinton { 1009676Slinton register Symbol t; 1019676Slinton register int len; 1029676Slinton Boolean isindirect; 1039676Slinton 1049676Slinton printf("returning "); 10512628Scsvaf if (s->class == FUNC && (!istypename(s->type,"void"))) { 1069676Slinton len = size(s->type); 1079676Slinton if (canpush(len)) { 1089676Slinton t = rtype(s->type); 1099676Slinton isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); 1109676Slinton pushretval(len, isindirect); 1119676Slinton printval(s->type); 1129676Slinton putchar(' '); 1139676Slinton } else { 1149676Slinton printf("(value too large) "); 1159676Slinton } 1169676Slinton } 1179676Slinton printf("from %s\n", symname(s)); 1189676Slinton } 1199676Slinton 1209676Slinton /* 1219676Slinton * Print the values of the parameters of the given procedure or function. 1229676Slinton * The frame distinguishes recursive instances of a procedure. 123*16616Ssam * 124*16616Ssam * If the procedure or function is internal, the argument count is 125*16616Ssam * not valid so we ignore it. 1269676Slinton */ 1279676Slinton 1289676Slinton public printparams(f, frame) 1299676Slinton Symbol f; 1309676Slinton Frame frame; 1319676Slinton { 1329676Slinton Symbol param; 1339676Slinton int n, m, s; 1349676Slinton 1359676Slinton n = nargspassed(frame); 136*16616Ssam if (isinternal(f)) { 137*16616Ssam n = 0; 138*16616Ssam } 1399676Slinton param = f->chain; 1409676Slinton if (param != nil or n > 0) { 1419676Slinton printf("("); 1429676Slinton m = n; 1439676Slinton if (param != nil) { 1449676Slinton for (;;) { 1459676Slinton s = size(param) div sizeof(Word); 1469676Slinton if (s == 0) { 1479676Slinton s = 1; 1489676Slinton } 1499676Slinton m -= s; 1509676Slinton printv(param, frame); 1519676Slinton param = param->chain; 1529676Slinton if (param == nil) break; 1539676Slinton printf(", "); 1549676Slinton } 1559676Slinton } 1569676Slinton if (m > 0) { 15711863Slinton if (m > MAXARGSPASSED) { 15811863Slinton m = MAXARGSPASSED; 15911863Slinton } 1609676Slinton if (f->chain != nil) { 1619676Slinton printf(", "); 1629676Slinton } 1639676Slinton for (;;) { 1649676Slinton --m; 1659676Slinton printf("0x%x", argn(n - m, frame)); 1669676Slinton if (m <= 0) break; 1679676Slinton printf(", "); 1689676Slinton } 1699676Slinton } 1709676Slinton printf(")"); 1719676Slinton } 1729676Slinton } 1739676Slinton 1749676Slinton /* 1759676Slinton * Test if a symbol should be printed. We don't print files, 1769676Slinton * for example, simply because there's no good way to do it. 1779676Slinton * The symbol must be within the given function. 1789676Slinton */ 1799676Slinton 1809676Slinton public Boolean should_print(s) 1819676Slinton Symbol s; 1829676Slinton { 1839676Slinton Boolean b; 1849676Slinton register Symbol t; 1859676Slinton 1869676Slinton switch (s->class) { 1879676Slinton case VAR: 1889676Slinton case FVAR: 18914339Slinton if (isparam(s)) { 19014339Slinton b = false; 19114339Slinton } else { 19214339Slinton t = rtype(s->type); 19314339Slinton if (t == nil) { 19414339Slinton b = false; 19514339Slinton } else { 19614339Slinton switch (t->class) { 19714339Slinton case FILET: 19814339Slinton case SET: 19914339Slinton case BADUSE: 20014339Slinton b = false; 20114339Slinton break; 20214339Slinton 20314339Slinton default: 20414339Slinton b = true; 20514339Slinton break; 20614339Slinton } 20714339Slinton } 20814339Slinton } 2099676Slinton break; 2109676Slinton 2119676Slinton default: 2129676Slinton b = false; 2139676Slinton break; 2149676Slinton } 2159676Slinton return b; 2169676Slinton } 2179676Slinton 2189676Slinton /* 2199676Slinton * Print the name and value of a variable. 2209676Slinton */ 2219676Slinton 2229676Slinton public printv(s, frame) 2239676Slinton Symbol s; 2249676Slinton Frame frame; 2259676Slinton { 2269676Slinton Address addr; 2279676Slinton int len; 228*16616Ssam Symbol t; 2299676Slinton 2309676Slinton if (isambiguous(s) and ismodule(container(s))) { 2319676Slinton printname(stdout, s); 2329676Slinton printf(" = "); 2339676Slinton } else { 2349676Slinton printf("%s = ", symname(s)); 2359676Slinton } 236*16616Ssam /* 237*16616Ssam * Not today. 238*16616Ssam t = rtype(s->type); 239*16616Ssam if (t->class == ARRAY and not istypename(t->type, "char")) { 240*16616Ssam printf("ARRAY"); 2419676Slinton } else { 242*16616Ssam */ 24312628Scsvaf if (isvarparam(s)) { 24412628Scsvaf rpush(address(s, frame), sizeof(Address)); 24512628Scsvaf addr = pop(Address); 24612628Scsvaf len = size(s->type); 24712628Scsvaf } else { 24812628Scsvaf addr = address(s, frame); 24912628Scsvaf len = size(s); 25012628Scsvaf } 25112628Scsvaf if (canpush(len)) { 25212628Scsvaf rpush(addr, len); 25312628Scsvaf printval(s->type); 25412628Scsvaf } else { 25512628Scsvaf printf("*** expression too large ***"); 25612628Scsvaf } 257*16616Ssam /* 258*16616Ssam * Matches brace commented out above. 25912628Scsvaf } 260*16616Ssam */ 2619676Slinton } 2629676Slinton 2639676Slinton /* 2649676Slinton * Print out the name of a symbol. 2659676Slinton */ 2669676Slinton 2679676Slinton public printname(f, s) 2689676Slinton File f; 2699676Slinton Symbol s; 2709676Slinton { 2719676Slinton if (s == nil) { 2729676Slinton fprintf(f, "(noname)"); 273*16616Ssam } else if (s == program) { 274*16616Ssam fprintf(f, "."); 2759676Slinton } else if (isredirected() or isambiguous(s)) { 2769676Slinton printwhich(f, s); 2779676Slinton } else { 2789676Slinton fprintf(f, "%s", symname(s)); 2799676Slinton } 2809676Slinton } 2819676Slinton 2829676Slinton /* 2839676Slinton * Print the fully specified variable that is described by the given identifer. 2849676Slinton */ 2859676Slinton 2869676Slinton public printwhich(f, s) 2879676Slinton File f; 2889676Slinton Symbol s; 2899676Slinton { 2909676Slinton printouter(f, container(s)); 2919676Slinton fprintf(f, "%s", symname(s)); 2929676Slinton } 2939676Slinton 2949676Slinton /* 2959676Slinton * Print the fully qualified name of each symbol that has the same name 2969676Slinton * as the given symbol. 2979676Slinton */ 2989676Slinton 2999676Slinton public printwhereis(f, s) 3009676Slinton File f; 3019676Slinton Symbol s; 3029676Slinton { 3039676Slinton register Name n; 3049676Slinton register Symbol t; 3059676Slinton 3069676Slinton checkref(s); 3079676Slinton n = s->name; 3089676Slinton t = lookup(n); 3099676Slinton printwhich(f, t); 3109676Slinton t = t->next_sym; 3119676Slinton while (t != nil) { 3129676Slinton if (t->name == n) { 3139676Slinton putc(' ', f); 3149676Slinton printwhich(f, t); 3159676Slinton } 3169676Slinton t = t->next_sym; 3179676Slinton } 3189676Slinton putc('\n', f); 3199676Slinton } 3209676Slinton 3219676Slinton private printouter(f, s) 3229676Slinton File f; 3239676Slinton Symbol s; 3249676Slinton { 3259676Slinton Symbol outer; 3269676Slinton 3279676Slinton if (s != nil) { 3289676Slinton outer = container(s); 3299676Slinton if (outer != nil and outer != program) { 3309676Slinton printouter(f, outer); 3319676Slinton } 3329676Slinton fprintf(f, "%s.", symname(s)); 3339676Slinton } 3349676Slinton } 3359676Slinton 3369676Slinton public printdecl(s) 3379676Slinton Symbol s; 3389676Slinton { 3399676Slinton checkref(s); 3409676Slinton (*language_op(s->language, L_PRINTDECL))(s); 3419676Slinton } 3429676Slinton 3439676Slinton /* 3449676Slinton * Straight dump of symbol information. 3459676Slinton */ 3469676Slinton 3479676Slinton public psym(s) 3489676Slinton Symbol s; 3499676Slinton { 3509676Slinton printf("name\t%s\n", symname(s)); 3519676Slinton printf("lang\t%s\n", language_name(s->language)); 3529676Slinton printf("level\t%d\n", s->level); 3539676Slinton printf("class\t%s\n", classname(s)); 3549676Slinton printf("type\t0x%x", s->type); 3559676Slinton if (s->type != nil and s->type->name != nil) { 3569676Slinton printf(" (%s)", symname(s->type)); 3579676Slinton } 3589676Slinton printf("\nchain\t0x%x", s->chain); 3599676Slinton if (s->chain != nil and s->chain->name != nil) { 3609676Slinton printf(" (%s)", symname(s->chain)); 3619676Slinton } 3629676Slinton printf("\nblock\t0x%x", s->block); 3639676Slinton if (s->block->name != nil) { 3649676Slinton printf(" ("); 3659676Slinton printname(stdout, s->block); 3669676Slinton putchar(')'); 3679676Slinton } 3689676Slinton putchar('\n'); 3699676Slinton switch (s->class) { 3709676Slinton case VAR: 3719676Slinton case REF: 3729676Slinton if (s->level >= 3) { 3739676Slinton printf("address\t0x%x\n", s->symvalue.offset); 3749676Slinton } else { 3759676Slinton printf("offset\t%d\n", s->symvalue.offset); 3769676Slinton } 37712545Scsvaf printf("size\t%d\n", size(s)); 3789676Slinton break; 3799676Slinton 3809676Slinton case RECORD: 3819676Slinton case VARNT: 3829676Slinton printf("size\t%d\n", s->symvalue.offset); 3839676Slinton break; 3849676Slinton 3859676Slinton case FIELD: 3869676Slinton printf("offset\t%d\n", s->symvalue.field.offset); 3879676Slinton printf("size\t%d\n", s->symvalue.field.length); 3889676Slinton break; 3899676Slinton 39014381Slinton case PROG: 3919676Slinton case PROC: 3929676Slinton case FUNC: 3939676Slinton printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 39414438Slinton if (isinline(s)) { 39514440Slinton printf("inline procedure\n"); 39614438Slinton } 39711863Slinton if (nosource(s)) { 39811863Slinton printf("does not have source information\n"); 39911863Slinton } else { 40011863Slinton printf("has source information\n"); 40111863Slinton } 4029676Slinton break; 4039676Slinton 4049676Slinton case RANGE: 40514381Slinton prangetype(s->symvalue.rangev.lowertype); 4069676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 40714381Slinton prangetype(s->symvalue.rangev.uppertype); 4089676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 4099676Slinton break; 4109676Slinton 4119676Slinton default: 4129676Slinton /* do nothing */ 4139676Slinton break; 4149676Slinton } 4159676Slinton } 4169676Slinton 41714381Slinton private prangetype(r) 41814381Slinton Rangetype r; 41914381Slinton { 42014381Slinton switch (r) { 42114381Slinton case R_CONST: 42214381Slinton printf("CONST"); 42314381Slinton break; 42414381Slinton 42514381Slinton case R_ARG: 42614381Slinton printf("ARG"); 42714381Slinton break; 42814381Slinton 42914381Slinton case R_TEMP: 43014381Slinton printf("TEMP"); 43114381Slinton break; 43214381Slinton 43314381Slinton case R_ADJUST: 43414381Slinton printf("ADJUST"); 43514381Slinton break; 43614381Slinton } 43714381Slinton } 43814381Slinton 4399676Slinton /* 4409676Slinton * Print out the value on top of the stack according to the given type. 4419676Slinton */ 4429676Slinton 4439676Slinton public printval(t) 4449676Slinton Symbol t; 4459676Slinton { 4469676Slinton Symbol s; 4479676Slinton 4489676Slinton checkref(t); 449*16616Ssam if (t->class == TYPEREF) { 450*16616Ssam resolveRef(t); 451*16616Ssam } 4529676Slinton switch (t->class) { 4539676Slinton case PROC: 4549676Slinton case FUNC: 4559676Slinton s = pop(Symbol); 4569676Slinton printf("%s", symname(s)); 4579676Slinton break; 4589676Slinton 4599676Slinton default: 4609676Slinton if (t->language == nil) { 4619676Slinton error("unknown language"); 462*16616Ssam } else if (t->language == primlang) { 463*16616Ssam (*language_op(findlanguage(".c"), L_PRINTVAL))(t); 4649676Slinton } else { 4659676Slinton (*language_op(t->language, L_PRINTVAL))(t); 4669676Slinton } 4679676Slinton break; 4689676Slinton } 4699676Slinton } 4709676Slinton 4719676Slinton /* 4729676Slinton * Print out the value of a record, field by field. 4739676Slinton */ 4749676Slinton 4759676Slinton public printrecord(s) 4769676Slinton Symbol s; 4779676Slinton { 478*16616Ssam Symbol f; 479*16616Ssam 4809676Slinton if (s->chain == nil) { 4819676Slinton error("record has no fields"); 4829676Slinton } 4839676Slinton printf("("); 4849676Slinton sp -= size(s); 485*16616Ssam f = s->chain; 486*16616Ssam if (f != nil) { 487*16616Ssam for (;;) { 488*16616Ssam printfield(f); 489*16616Ssam f = f->chain; 490*16616Ssam if (f == nil) break; 491*16616Ssam printf(", "); 492*16616Ssam } 493*16616Ssam } 4949676Slinton printf(")"); 4959676Slinton } 4969676Slinton 4979676Slinton /* 498*16616Ssam * Print out a field. 4999676Slinton */ 5009676Slinton 501*16616Ssam private printfield(f) 502*16616Ssam Symbol f; 5039676Slinton { 5049676Slinton Stack *savesp; 505*16616Ssam register int off, len; 5069676Slinton 507*16616Ssam printf("%s = ", symname(f)); 5089676Slinton savesp = sp; 509*16616Ssam off = f->symvalue.field.offset; 510*16616Ssam len = f->symvalue.field.length; 511*16616Ssam sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE); 512*16616Ssam printval(f); 5139676Slinton sp = savesp; 5149676Slinton } 5159676Slinton 5169676Slinton /* 5179676Slinton * Print out the contents of an array. 5189676Slinton * Haven't quite figured out what the best format is. 5199676Slinton * 5209676Slinton * This is rather inefficient. 5219676Slinton * 5229676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 5239676Slinton */ 5249676Slinton 5259676Slinton public printarray(a) 5269676Slinton Symbol a; 5279676Slinton { 5289676Slinton Stack *savesp, *newsp; 5299676Slinton Symbol eltype; 5309676Slinton long elsize; 5319676Slinton String sep; 5329676Slinton 5339676Slinton savesp = sp; 53412544Scsvaf sp -= (size(a)); 5359676Slinton newsp = sp; 5369676Slinton eltype = rtype(a->type); 5379676Slinton elsize = size(eltype); 5389676Slinton printf("("); 5399676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 5409676Slinton eltype->class == VARNT) { 5419676Slinton sep = "\n"; 5429676Slinton putchar('\n'); 5439676Slinton } else { 5449676Slinton sep = ", "; 5459676Slinton } 5469676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 5479676Slinton if (sp - elsize != newsp) { 5489676Slinton fputs(sep, stdout); 5499676Slinton } 5509676Slinton printval(eltype); 5519676Slinton } 5529676Slinton sp = newsp; 5539676Slinton if (streq(sep, "\n")) { 5549676Slinton putchar('\n'); 5559676Slinton } 5569676Slinton printf(")"); 5579676Slinton } 5589676Slinton 5599676Slinton /* 5609676Slinton * Print out the value of a real number in Pascal notation. 5619676Slinton * This is, unfortunately, different than what one gets 5629676Slinton * from "%g" in printf. 5639676Slinton */ 5649676Slinton 5659676Slinton public prtreal(r) 5669676Slinton double r; 5679676Slinton { 5689676Slinton extern char *index(); 5699676Slinton char buf[256]; 5709676Slinton 5719676Slinton sprintf(buf, "%g", r); 5729676Slinton if (buf[0] == '.') { 5739676Slinton printf("0%s", buf); 5749676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 5759676Slinton printf("-0%s", &buf[1]); 5769676Slinton } else { 5779676Slinton printf("%s", buf); 5789676Slinton } 5799676Slinton if (index(buf, '.') == nil) { 5809676Slinton printf(".0"); 5819676Slinton } 5829676Slinton } 5839676Slinton 5849676Slinton /* 5859676Slinton * Print out a character using ^? notation for unprintables. 5869676Slinton */ 5879676Slinton 5889676Slinton public printchar(c) 5899676Slinton char c; 5909676Slinton { 5919676Slinton if (c == 0) { 5929676Slinton putchar('\\'); 5939676Slinton putchar('0'); 5949676Slinton } else if (c == '\n') { 5959676Slinton putchar('\\'); 5969676Slinton putchar('n'); 5979676Slinton } else if (c > 0 and c < ' ') { 5989676Slinton putchar('^'); 5999676Slinton putchar(c - 1 + 'A'); 600*16616Ssam } else if (c >= ' ' && c <= '~') { 601*16616Ssam putchar(c); 6029676Slinton } else { 603*16616Ssam printf("\\0%o",c); 6049676Slinton } 6059676Slinton } 606