19676Slinton /* Copyright (c) 1982 Regents of the University of California */ 29676Slinton 3*14339Slinton static char sccsid[] = "@(#)printsym.c 1.8 08/05/83"; 49676Slinton 59676Slinton /* 69676Slinton * Printing of symbolic information. 79676Slinton */ 89676Slinton 99676Slinton #include "defs.h" 109676Slinton #include "symbols.h" 119676Slinton #include "languages.h" 129676Slinton #include "printsym.h" 139676Slinton #include "tree.h" 149676Slinton #include "eval.h" 159676Slinton #include "mappings.h" 169676Slinton #include "process.h" 179676Slinton #include "runtime.h" 189676Slinton #include "machine.h" 199676Slinton #include "names.h" 209676Slinton #include "main.h" 219676Slinton 229676Slinton #ifndef public 239676Slinton #endif 249676Slinton 259676Slinton /* 2611863Slinton * Maximum number of arguments to a function. 2711863Slinton * This is used as a check for the possibility that the stack has been 2811863Slinton * overwritten and therefore a saved argument pointer might indicate 2911863Slinton * to an absurdly large number of arguments. 3011863Slinton */ 3111863Slinton 3211863Slinton #define MAXARGSPASSED 20 3311863Slinton 3411863Slinton /* 359676Slinton * Return a pointer to the string for the name of the class that 369676Slinton * the given symbol belongs to. 379676Slinton */ 389676Slinton 399676Slinton private String clname[] = { 409676Slinton "bad use", "constant", "type", "variable", "array", "fileptr", 419676Slinton "record", "field", "procedure", "function", "funcvar", 429676Slinton "ref", "pointer", "file", "set", "range", "label", "withptr", 439676Slinton "scalar", "string", "program", "improper", "variant", 4412544Scsvaf "procparam", "funcparam", "module", "tag", "common", "typeref" 459676Slinton }; 469676Slinton 479676Slinton public String classname(s) 489676Slinton Symbol s; 499676Slinton { 509676Slinton return clname[ord(s->class)]; 519676Slinton } 529676Slinton 539676Slinton /* 549676Slinton * Note the entry of the given block, unless it's the main program. 559676Slinton */ 569676Slinton 579676Slinton public printentry(s) 589676Slinton Symbol s; 599676Slinton { 609676Slinton if (s != program) { 619676Slinton printf("\nentering %s %s\n", classname(s), symname(s)); 629676Slinton } 639676Slinton } 649676Slinton 659676Slinton /* 669676Slinton * Note the exit of the given block 679676Slinton */ 689676Slinton 699676Slinton public printexit(s) 709676Slinton Symbol s; 719676Slinton { 729676Slinton if (s != program) { 739676Slinton printf("leaving %s %s\n\n", classname(s), symname(s)); 749676Slinton } 759676Slinton } 769676Slinton 779676Slinton /* 789676Slinton * Note the call of s from t. 799676Slinton */ 809676Slinton 819676Slinton public printcall(s, t) 829676Slinton Symbol s, t; 839676Slinton { 849676Slinton printf("calling %s", symname(s)); 859676Slinton printparams(s, nil); 869676Slinton printf(" from %s %s\n", classname(t), symname(t)); 879676Slinton } 889676Slinton 899676Slinton /* 909676Slinton * Note the return from s. If s is a function, print the value 919676Slinton * it is returning. This is somewhat painful, since the function 929676Slinton * has actually just returned. 939676Slinton */ 949676Slinton 959676Slinton public printrtn(s) 969676Slinton Symbol s; 979676Slinton { 989676Slinton register Symbol t; 999676Slinton register int len; 1009676Slinton Boolean isindirect; 1019676Slinton 1029676Slinton printf("returning "); 10312628Scsvaf if (s->class == FUNC && (!istypename(s->type,"void"))) { 1049676Slinton len = size(s->type); 1059676Slinton if (canpush(len)) { 1069676Slinton t = rtype(s->type); 1079676Slinton isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); 1089676Slinton pushretval(len, isindirect); 1099676Slinton printval(s->type); 1109676Slinton putchar(' '); 1119676Slinton } else { 1129676Slinton printf("(value too large) "); 1139676Slinton } 1149676Slinton } 1159676Slinton printf("from %s\n", symname(s)); 1169676Slinton } 1179676Slinton 1189676Slinton /* 1199676Slinton * Print the values of the parameters of the given procedure or function. 1209676Slinton * The frame distinguishes recursive instances of a procedure. 1219676Slinton */ 1229676Slinton 1239676Slinton public printparams(f, frame) 1249676Slinton Symbol f; 1259676Slinton Frame frame; 1269676Slinton { 1279676Slinton Symbol param; 1289676Slinton int n, m, s; 1299676Slinton 1309676Slinton n = nargspassed(frame); 1319676Slinton param = f->chain; 1329676Slinton if (param != nil or n > 0) { 1339676Slinton printf("("); 1349676Slinton m = n; 1359676Slinton if (param != nil) { 1369676Slinton for (;;) { 1379676Slinton s = size(param) div sizeof(Word); 1389676Slinton if (s == 0) { 1399676Slinton s = 1; 1409676Slinton } 1419676Slinton m -= s; 1429676Slinton printv(param, frame); 1439676Slinton param = param->chain; 1449676Slinton if (param == nil) break; 1459676Slinton printf(", "); 1469676Slinton } 1479676Slinton } 1489676Slinton if (m > 0) { 14911863Slinton if (m > MAXARGSPASSED) { 15011863Slinton m = MAXARGSPASSED; 15111863Slinton } 1529676Slinton if (f->chain != nil) { 1539676Slinton printf(", "); 1549676Slinton } 1559676Slinton for (;;) { 1569676Slinton --m; 1579676Slinton printf("0x%x", argn(n - m, frame)); 1589676Slinton if (m <= 0) break; 1599676Slinton printf(", "); 1609676Slinton } 1619676Slinton } 1629676Slinton printf(")"); 1639676Slinton } 1649676Slinton } 1659676Slinton 1669676Slinton /* 1679676Slinton * Test if a symbol should be printed. We don't print files, 1689676Slinton * for example, simply because there's no good way to do it. 1699676Slinton * The symbol must be within the given function. 1709676Slinton */ 1719676Slinton 1729676Slinton public Boolean should_print(s) 1739676Slinton Symbol s; 1749676Slinton { 1759676Slinton Boolean b; 1769676Slinton register Symbol t; 1779676Slinton 1789676Slinton switch (s->class) { 1799676Slinton case VAR: 1809676Slinton case FVAR: 181*14339Slinton if (isparam(s)) { 182*14339Slinton b = false; 183*14339Slinton } else { 184*14339Slinton t = rtype(s->type); 185*14339Slinton if (t == nil) { 186*14339Slinton b = false; 187*14339Slinton } else { 188*14339Slinton switch (t->class) { 189*14339Slinton case FILET: 190*14339Slinton case SET: 191*14339Slinton case VARNT: 192*14339Slinton case BADUSE: 193*14339Slinton b = false; 194*14339Slinton break; 195*14339Slinton 196*14339Slinton default: 197*14339Slinton b = true; 198*14339Slinton break; 199*14339Slinton } 200*14339Slinton } 201*14339Slinton } 2029676Slinton break; 2039676Slinton 2049676Slinton default: 2059676Slinton b = false; 2069676Slinton break; 2079676Slinton } 2089676Slinton return b; 2099676Slinton } 2109676Slinton 2119676Slinton /* 2129676Slinton * Print the name and value of a variable. 2139676Slinton */ 2149676Slinton 2159676Slinton public printv(s, frame) 2169676Slinton Symbol s; 2179676Slinton Frame frame; 2189676Slinton { 2199676Slinton Address addr; 2209676Slinton int len; 2219676Slinton 2229676Slinton if (isambiguous(s) and ismodule(container(s))) { 2239676Slinton printname(stdout, s); 2249676Slinton printf(" = "); 2259676Slinton } else { 2269676Slinton printf("%s = ", symname(s)); 2279676Slinton } 22812628Scsvaf if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) { 22912628Scsvaf printf(" ARRAY "); 2309676Slinton } else { 23112628Scsvaf if (isvarparam(s)) { 23212628Scsvaf rpush(address(s, frame), sizeof(Address)); 23312628Scsvaf addr = pop(Address); 23412628Scsvaf len = size(s->type); 23512628Scsvaf } else { 23612628Scsvaf addr = address(s, frame); 23712628Scsvaf len = size(s); 23812628Scsvaf } 23912628Scsvaf if (canpush(len)) { 24012628Scsvaf rpush(addr, len); 24112628Scsvaf printval(s->type); 24212628Scsvaf } else { 24312628Scsvaf printf("*** expression too large ***"); 24412628Scsvaf } 24512628Scsvaf } 2469676Slinton } 2479676Slinton 2489676Slinton /* 2499676Slinton * Print out the name of a symbol. 2509676Slinton */ 2519676Slinton 2529676Slinton public printname(f, s) 2539676Slinton File f; 2549676Slinton Symbol s; 2559676Slinton { 2569676Slinton if (s == nil) { 2579676Slinton fprintf(f, "(noname)"); 2589676Slinton } else if (isredirected() or isambiguous(s)) { 2599676Slinton printwhich(f, s); 2609676Slinton } else { 2619676Slinton fprintf(f, "%s", symname(s)); 2629676Slinton } 2639676Slinton } 2649676Slinton 2659676Slinton /* 2669676Slinton * Print the fully specified variable that is described by the given identifer. 2679676Slinton */ 2689676Slinton 2699676Slinton public printwhich(f, s) 2709676Slinton File f; 2719676Slinton Symbol s; 2729676Slinton { 2739676Slinton printouter(f, container(s)); 2749676Slinton fprintf(f, "%s", symname(s)); 2759676Slinton } 2769676Slinton 2779676Slinton /* 2789676Slinton * Print the fully qualified name of each symbol that has the same name 2799676Slinton * as the given symbol. 2809676Slinton */ 2819676Slinton 2829676Slinton public printwhereis(f, s) 2839676Slinton File f; 2849676Slinton Symbol s; 2859676Slinton { 2869676Slinton register Name n; 2879676Slinton register Symbol t; 2889676Slinton 2899676Slinton checkref(s); 2909676Slinton n = s->name; 2919676Slinton t = lookup(n); 2929676Slinton printwhich(f, t); 2939676Slinton t = t->next_sym; 2949676Slinton while (t != nil) { 2959676Slinton if (t->name == n) { 2969676Slinton putc(' ', f); 2979676Slinton printwhich(f, t); 2989676Slinton } 2999676Slinton t = t->next_sym; 3009676Slinton } 3019676Slinton putc('\n', f); 3029676Slinton } 3039676Slinton 3049676Slinton private printouter(f, s) 3059676Slinton File f; 3069676Slinton Symbol s; 3079676Slinton { 3089676Slinton Symbol outer; 3099676Slinton 3109676Slinton if (s != nil) { 3119676Slinton outer = container(s); 3129676Slinton if (outer != nil and outer != program) { 3139676Slinton printouter(f, outer); 3149676Slinton } 3159676Slinton fprintf(f, "%s.", symname(s)); 3169676Slinton } 3179676Slinton } 3189676Slinton 3199676Slinton public printdecl(s) 3209676Slinton Symbol s; 3219676Slinton { 3229676Slinton checkref(s); 3239676Slinton (*language_op(s->language, L_PRINTDECL))(s); 3249676Slinton } 3259676Slinton 3269676Slinton /* 3279676Slinton * Straight dump of symbol information. 3289676Slinton */ 3299676Slinton 3309676Slinton public psym(s) 3319676Slinton Symbol s; 3329676Slinton { 3339676Slinton printf("name\t%s\n", symname(s)); 3349676Slinton printf("lang\t%s\n", language_name(s->language)); 3359676Slinton printf("level\t%d\n", s->level); 3369676Slinton printf("class\t%s\n", classname(s)); 3379676Slinton printf("type\t0x%x", s->type); 3389676Slinton if (s->type != nil and s->type->name != nil) { 3399676Slinton printf(" (%s)", symname(s->type)); 3409676Slinton } 3419676Slinton printf("\nchain\t0x%x", s->chain); 3429676Slinton if (s->chain != nil and s->chain->name != nil) { 3439676Slinton printf(" (%s)", symname(s->chain)); 3449676Slinton } 3459676Slinton printf("\nblock\t0x%x", s->block); 3469676Slinton if (s->block->name != nil) { 3479676Slinton printf(" ("); 3489676Slinton printname(stdout, s->block); 3499676Slinton putchar(')'); 3509676Slinton } 3519676Slinton putchar('\n'); 3529676Slinton switch (s->class) { 3539676Slinton case VAR: 3549676Slinton case REF: 3559676Slinton if (s->level >= 3) { 3569676Slinton printf("address\t0x%x\n", s->symvalue.offset); 3579676Slinton } else { 3589676Slinton printf("offset\t%d\n", s->symvalue.offset); 3599676Slinton } 36012545Scsvaf printf("size\t%d\n", size(s)); 3619676Slinton break; 3629676Slinton 3639676Slinton case RECORD: 3649676Slinton case VARNT: 3659676Slinton printf("size\t%d\n", s->symvalue.offset); 3669676Slinton break; 3679676Slinton 3689676Slinton case FIELD: 3699676Slinton printf("offset\t%d\n", s->symvalue.field.offset); 3709676Slinton printf("size\t%d\n", s->symvalue.field.length); 3719676Slinton break; 3729676Slinton 3739676Slinton case PROC: 3749676Slinton case FUNC: 3759676Slinton printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 37611863Slinton if (nosource(s)) { 37711863Slinton printf("does not have source information\n"); 37811863Slinton } else { 37911863Slinton printf("has source information\n"); 38011863Slinton } 3819676Slinton break; 3829676Slinton 3839676Slinton case RANGE: 38412544Scsvaf switch(s->symvalue.rangev.lowertype) { 38512544Scsvaf 38612544Scsvaf case R_CONST : printf("CONST"); 38712544Scsvaf break; 38812544Scsvaf case R_ARG : printf("ARG"); 38912544Scsvaf break; 39012544Scsvaf case R_TEMP : printf("TEMP"); 39112544Scsvaf break; 39212544Scsvaf case R_ADJUST : printf("ADJUST"); 39312544Scsvaf break; 39412544Scsvaf } 3959676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 39612544Scsvaf 39712544Scsvaf switch(s->symvalue.rangev.uppertype) { 39812544Scsvaf 39912544Scsvaf case R_CONST : printf("CONST"); 40012544Scsvaf break; 40112544Scsvaf case R_ARG : printf("ARG"); 40212544Scsvaf break; 40312544Scsvaf case R_TEMP : printf("TEMP"); 40412544Scsvaf break; 40512544Scsvaf case R_ADJUST : printf("ADJUST"); 40612544Scsvaf break; 40712544Scsvaf } 40812544Scsvaf 4099676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 4109676Slinton break; 4119676Slinton 4129676Slinton default: 4139676Slinton /* do nothing */ 4149676Slinton break; 4159676Slinton } 4169676Slinton } 4179676Slinton 4189676Slinton /* 4199676Slinton * Print out the value on top of the stack according to the given type. 4209676Slinton */ 4219676Slinton 4229676Slinton public printval(t) 4239676Slinton Symbol t; 4249676Slinton { 4259676Slinton Symbol s; 4269676Slinton 4279676Slinton checkref(t); 4289676Slinton switch (t->class) { 4299676Slinton case PROC: 4309676Slinton case FUNC: 4319676Slinton s = pop(Symbol); 4329676Slinton printf("%s", symname(s)); 4339676Slinton break; 4349676Slinton 4359676Slinton default: 4369676Slinton if (t->language == nil) { 4379676Slinton error("unknown language"); 4389676Slinton } else { 4399676Slinton (*language_op(t->language, L_PRINTVAL))(t); 4409676Slinton } 4419676Slinton break; 4429676Slinton } 4439676Slinton } 4449676Slinton 4459676Slinton /* 4469676Slinton * Print out the value of a record, field by field. 4479676Slinton */ 4489676Slinton 4499676Slinton public printrecord(s) 4509676Slinton Symbol s; 4519676Slinton { 4529676Slinton if (s->chain == nil) { 4539676Slinton error("record has no fields"); 4549676Slinton } 4559676Slinton printf("("); 4569676Slinton sp -= size(s); 4579676Slinton printfield(s->chain); 4589676Slinton printf(")"); 4599676Slinton } 4609676Slinton 4619676Slinton /* 4629676Slinton * Print out a field, first printing out other fields. 4639676Slinton * This is done because the fields are chained together backwards. 4649676Slinton */ 4659676Slinton 4669676Slinton private printfield(s) 4679676Slinton Symbol s; 4689676Slinton { 4699676Slinton Stack *savesp; 4709676Slinton 4719676Slinton if (s->chain != nil) { 4729676Slinton printfield(s->chain); 4739676Slinton printf(", "); 4749676Slinton } 4759676Slinton printf("%s = ", symname(s)); 4769676Slinton savesp = sp; 4779676Slinton sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); 4789676Slinton printval(s); 4799676Slinton sp = savesp; 4809676Slinton } 4819676Slinton 4829676Slinton /* 4839676Slinton * Print out the contents of an array. 4849676Slinton * Haven't quite figured out what the best format is. 4859676Slinton * 4869676Slinton * This is rather inefficient. 4879676Slinton * 4889676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 4899676Slinton */ 4909676Slinton 4919676Slinton public printarray(a) 4929676Slinton Symbol a; 4939676Slinton { 4949676Slinton Stack *savesp, *newsp; 4959676Slinton Symbol eltype; 4969676Slinton long elsize; 4979676Slinton String sep; 4989676Slinton 4999676Slinton savesp = sp; 50012544Scsvaf sp -= (size(a)); 5019676Slinton newsp = sp; 5029676Slinton eltype = rtype(a->type); 5039676Slinton elsize = size(eltype); 5049676Slinton printf("("); 5059676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 5069676Slinton eltype->class == VARNT) { 5079676Slinton sep = "\n"; 5089676Slinton putchar('\n'); 5099676Slinton } else { 5109676Slinton sep = ", "; 5119676Slinton } 5129676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 5139676Slinton if (sp - elsize != newsp) { 5149676Slinton fputs(sep, stdout); 5159676Slinton } 5169676Slinton printval(eltype); 5179676Slinton } 5189676Slinton sp = newsp; 5199676Slinton if (streq(sep, "\n")) { 5209676Slinton putchar('\n'); 5219676Slinton } 5229676Slinton printf(")"); 5239676Slinton } 5249676Slinton 5259676Slinton /* 5269676Slinton * Print out the value of a real number in Pascal notation. 5279676Slinton * This is, unfortunately, different than what one gets 5289676Slinton * from "%g" in printf. 5299676Slinton */ 5309676Slinton 5319676Slinton public prtreal(r) 5329676Slinton double r; 5339676Slinton { 5349676Slinton extern char *index(); 5359676Slinton char buf[256]; 5369676Slinton 5379676Slinton sprintf(buf, "%g", r); 5389676Slinton if (buf[0] == '.') { 5399676Slinton printf("0%s", buf); 5409676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 5419676Slinton printf("-0%s", &buf[1]); 5429676Slinton } else { 5439676Slinton printf("%s", buf); 5449676Slinton } 5459676Slinton if (index(buf, '.') == nil) { 5469676Slinton printf(".0"); 5479676Slinton } 5489676Slinton } 5499676Slinton 5509676Slinton /* 5519676Slinton * Print out a character using ^? notation for unprintables. 5529676Slinton */ 5539676Slinton 5549676Slinton public printchar(c) 5559676Slinton char c; 5569676Slinton { 5579676Slinton if (c == 0) { 5589676Slinton putchar('\\'); 5599676Slinton putchar('0'); 5609676Slinton } else if (c == '\n') { 5619676Slinton putchar('\\'); 5629676Slinton putchar('n'); 5639676Slinton } else if (c > 0 and c < ' ') { 5649676Slinton putchar('^'); 5659676Slinton putchar(c - 1 + 'A'); 5669676Slinton } else { 5679676Slinton putchar(c); 5689676Slinton } 5699676Slinton } 570