19676Slinton /* Copyright (c) 1982 Regents of the University of California */ 29676Slinton 3*14438Slinton static char sccsid[] = "@(#)printsym.c 1.11 08/10/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: 18114339Slinton if (isparam(s)) { 18214339Slinton b = false; 18314339Slinton } else { 18414339Slinton t = rtype(s->type); 18514339Slinton if (t == nil) { 18614339Slinton b = false; 18714339Slinton } else { 18814339Slinton switch (t->class) { 18914339Slinton case FILET: 19014339Slinton case SET: 19114339Slinton case BADUSE: 19214339Slinton b = false; 19314339Slinton break; 19414339Slinton 19514339Slinton default: 19614339Slinton b = true; 19714339Slinton break; 19814339Slinton } 19914339Slinton } 20014339Slinton } 2019676Slinton break; 2029676Slinton 2039676Slinton default: 2049676Slinton b = false; 2059676Slinton break; 2069676Slinton } 2079676Slinton return b; 2089676Slinton } 2099676Slinton 2109676Slinton /* 2119676Slinton * Print the name and value of a variable. 2129676Slinton */ 2139676Slinton 2149676Slinton public printv(s, frame) 2159676Slinton Symbol s; 2169676Slinton Frame frame; 2179676Slinton { 2189676Slinton Address addr; 2199676Slinton int len; 2209676Slinton 2219676Slinton if (isambiguous(s) and ismodule(container(s))) { 2229676Slinton printname(stdout, s); 2239676Slinton printf(" = "); 2249676Slinton } else { 2259676Slinton printf("%s = ", symname(s)); 2269676Slinton } 22712628Scsvaf if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) { 22812628Scsvaf printf(" ARRAY "); 2299676Slinton } else { 23012628Scsvaf if (isvarparam(s)) { 23112628Scsvaf rpush(address(s, frame), sizeof(Address)); 23212628Scsvaf addr = pop(Address); 23312628Scsvaf len = size(s->type); 23412628Scsvaf } else { 23512628Scsvaf addr = address(s, frame); 23612628Scsvaf len = size(s); 23712628Scsvaf } 23812628Scsvaf if (canpush(len)) { 23912628Scsvaf rpush(addr, len); 24012628Scsvaf printval(s->type); 24112628Scsvaf } else { 24212628Scsvaf printf("*** expression too large ***"); 24312628Scsvaf } 24412628Scsvaf } 2459676Slinton } 2469676Slinton 2479676Slinton /* 2489676Slinton * Print out the name of a symbol. 2499676Slinton */ 2509676Slinton 2519676Slinton public printname(f, s) 2529676Slinton File f; 2539676Slinton Symbol s; 2549676Slinton { 2559676Slinton if (s == nil) { 2569676Slinton fprintf(f, "(noname)"); 2579676Slinton } else if (isredirected() or isambiguous(s)) { 2589676Slinton printwhich(f, s); 2599676Slinton } else { 2609676Slinton fprintf(f, "%s", symname(s)); 2619676Slinton } 2629676Slinton } 2639676Slinton 2649676Slinton /* 2659676Slinton * Print the fully specified variable that is described by the given identifer. 2669676Slinton */ 2679676Slinton 2689676Slinton public printwhich(f, s) 2699676Slinton File f; 2709676Slinton Symbol s; 2719676Slinton { 2729676Slinton printouter(f, container(s)); 2739676Slinton fprintf(f, "%s", symname(s)); 2749676Slinton } 2759676Slinton 2769676Slinton /* 2779676Slinton * Print the fully qualified name of each symbol that has the same name 2789676Slinton * as the given symbol. 2799676Slinton */ 2809676Slinton 2819676Slinton public printwhereis(f, s) 2829676Slinton File f; 2839676Slinton Symbol s; 2849676Slinton { 2859676Slinton register Name n; 2869676Slinton register Symbol t; 2879676Slinton 2889676Slinton checkref(s); 2899676Slinton n = s->name; 2909676Slinton t = lookup(n); 2919676Slinton printwhich(f, t); 2929676Slinton t = t->next_sym; 2939676Slinton while (t != nil) { 2949676Slinton if (t->name == n) { 2959676Slinton putc(' ', f); 2969676Slinton printwhich(f, t); 2979676Slinton } 2989676Slinton t = t->next_sym; 2999676Slinton } 3009676Slinton putc('\n', f); 3019676Slinton } 3029676Slinton 3039676Slinton private printouter(f, s) 3049676Slinton File f; 3059676Slinton Symbol s; 3069676Slinton { 3079676Slinton Symbol outer; 3089676Slinton 3099676Slinton if (s != nil) { 3109676Slinton outer = container(s); 3119676Slinton if (outer != nil and outer != program) { 3129676Slinton printouter(f, outer); 3139676Slinton } 3149676Slinton fprintf(f, "%s.", symname(s)); 3159676Slinton } 3169676Slinton } 3179676Slinton 3189676Slinton public printdecl(s) 3199676Slinton Symbol s; 3209676Slinton { 3219676Slinton checkref(s); 3229676Slinton (*language_op(s->language, L_PRINTDECL))(s); 3239676Slinton } 3249676Slinton 3259676Slinton /* 3269676Slinton * Straight dump of symbol information. 3279676Slinton */ 3289676Slinton 3299676Slinton public psym(s) 3309676Slinton Symbol s; 3319676Slinton { 3329676Slinton printf("name\t%s\n", symname(s)); 3339676Slinton printf("lang\t%s\n", language_name(s->language)); 3349676Slinton printf("level\t%d\n", s->level); 3359676Slinton printf("class\t%s\n", classname(s)); 3369676Slinton printf("type\t0x%x", s->type); 3379676Slinton if (s->type != nil and s->type->name != nil) { 3389676Slinton printf(" (%s)", symname(s->type)); 3399676Slinton } 3409676Slinton printf("\nchain\t0x%x", s->chain); 3419676Slinton if (s->chain != nil and s->chain->name != nil) { 3429676Slinton printf(" (%s)", symname(s->chain)); 3439676Slinton } 3449676Slinton printf("\nblock\t0x%x", s->block); 3459676Slinton if (s->block->name != nil) { 3469676Slinton printf(" ("); 3479676Slinton printname(stdout, s->block); 3489676Slinton putchar(')'); 3499676Slinton } 3509676Slinton putchar('\n'); 3519676Slinton switch (s->class) { 3529676Slinton case VAR: 3539676Slinton case REF: 3549676Slinton if (s->level >= 3) { 3559676Slinton printf("address\t0x%x\n", s->symvalue.offset); 3569676Slinton } else { 3579676Slinton printf("offset\t%d\n", s->symvalue.offset); 3589676Slinton } 35912545Scsvaf printf("size\t%d\n", size(s)); 3609676Slinton break; 3619676Slinton 3629676Slinton case RECORD: 3639676Slinton case VARNT: 3649676Slinton printf("size\t%d\n", s->symvalue.offset); 3659676Slinton break; 3669676Slinton 3679676Slinton case FIELD: 3689676Slinton printf("offset\t%d\n", s->symvalue.field.offset); 3699676Slinton printf("size\t%d\n", s->symvalue.field.length); 3709676Slinton break; 3719676Slinton 37214381Slinton case PROG: 3739676Slinton case PROC: 3749676Slinton case FUNC: 3759676Slinton printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 376*14438Slinton if (isinline(s)) { 377*14438Slinton printf("inline procedure"); 378*14438Slinton } 37911863Slinton if (nosource(s)) { 38011863Slinton printf("does not have source information\n"); 38111863Slinton } else { 38211863Slinton printf("has source information\n"); 38311863Slinton } 3849676Slinton break; 3859676Slinton 3869676Slinton case RANGE: 38712544Scsvaf 38814381Slinton prangetype(s->symvalue.rangev.lowertype); 3899676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 39014381Slinton prangetype(s->symvalue.rangev.uppertype); 3919676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 3929676Slinton break; 3939676Slinton 3949676Slinton default: 3959676Slinton /* do nothing */ 3969676Slinton break; 3979676Slinton } 3989676Slinton } 3999676Slinton 40014381Slinton private prangetype(r) 40114381Slinton Rangetype r; 40214381Slinton { 40314381Slinton switch (r) { 40414381Slinton case R_CONST: 40514381Slinton printf("CONST"); 40614381Slinton break; 40714381Slinton 40814381Slinton case R_ARG: 40914381Slinton printf("ARG"); 41014381Slinton break; 41114381Slinton 41214381Slinton case R_TEMP: 41314381Slinton printf("TEMP"); 41414381Slinton break; 41514381Slinton 41614381Slinton case R_ADJUST: 41714381Slinton printf("ADJUST"); 41814381Slinton break; 41914381Slinton } 42014381Slinton } 42114381Slinton 4229676Slinton /* 4239676Slinton * Print out the value on top of the stack according to the given type. 4249676Slinton */ 4259676Slinton 4269676Slinton public printval(t) 4279676Slinton Symbol t; 4289676Slinton { 4299676Slinton Symbol s; 4309676Slinton 4319676Slinton checkref(t); 4329676Slinton switch (t->class) { 4339676Slinton case PROC: 4349676Slinton case FUNC: 4359676Slinton s = pop(Symbol); 4369676Slinton printf("%s", symname(s)); 4379676Slinton break; 4389676Slinton 4399676Slinton default: 4409676Slinton if (t->language == nil) { 4419676Slinton error("unknown language"); 4429676Slinton } else { 4439676Slinton (*language_op(t->language, L_PRINTVAL))(t); 4449676Slinton } 4459676Slinton break; 4469676Slinton } 4479676Slinton } 4489676Slinton 4499676Slinton /* 4509676Slinton * Print out the value of a record, field by field. 4519676Slinton */ 4529676Slinton 4539676Slinton public printrecord(s) 4549676Slinton Symbol s; 4559676Slinton { 4569676Slinton if (s->chain == nil) { 4579676Slinton error("record has no fields"); 4589676Slinton } 4599676Slinton printf("("); 4609676Slinton sp -= size(s); 4619676Slinton printfield(s->chain); 4629676Slinton printf(")"); 4639676Slinton } 4649676Slinton 4659676Slinton /* 4669676Slinton * Print out a field, first printing out other fields. 4679676Slinton * This is done because the fields are chained together backwards. 4689676Slinton */ 4699676Slinton 4709676Slinton private printfield(s) 4719676Slinton Symbol s; 4729676Slinton { 4739676Slinton Stack *savesp; 4749676Slinton 4759676Slinton if (s->chain != nil) { 4769676Slinton printfield(s->chain); 4779676Slinton printf(", "); 4789676Slinton } 4799676Slinton printf("%s = ", symname(s)); 4809676Slinton savesp = sp; 4819676Slinton sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); 4829676Slinton printval(s); 4839676Slinton sp = savesp; 4849676Slinton } 4859676Slinton 4869676Slinton /* 4879676Slinton * Print out the contents of an array. 4889676Slinton * Haven't quite figured out what the best format is. 4899676Slinton * 4909676Slinton * This is rather inefficient. 4919676Slinton * 4929676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 4939676Slinton */ 4949676Slinton 4959676Slinton public printarray(a) 4969676Slinton Symbol a; 4979676Slinton { 4989676Slinton Stack *savesp, *newsp; 4999676Slinton Symbol eltype; 5009676Slinton long elsize; 5019676Slinton String sep; 5029676Slinton 5039676Slinton savesp = sp; 50412544Scsvaf sp -= (size(a)); 5059676Slinton newsp = sp; 5069676Slinton eltype = rtype(a->type); 5079676Slinton elsize = size(eltype); 5089676Slinton printf("("); 5099676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 5109676Slinton eltype->class == VARNT) { 5119676Slinton sep = "\n"; 5129676Slinton putchar('\n'); 5139676Slinton } else { 5149676Slinton sep = ", "; 5159676Slinton } 5169676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 5179676Slinton if (sp - elsize != newsp) { 5189676Slinton fputs(sep, stdout); 5199676Slinton } 5209676Slinton printval(eltype); 5219676Slinton } 5229676Slinton sp = newsp; 5239676Slinton if (streq(sep, "\n")) { 5249676Slinton putchar('\n'); 5259676Slinton } 5269676Slinton printf(")"); 5279676Slinton } 5289676Slinton 5299676Slinton /* 5309676Slinton * Print out the value of a real number in Pascal notation. 5319676Slinton * This is, unfortunately, different than what one gets 5329676Slinton * from "%g" in printf. 5339676Slinton */ 5349676Slinton 5359676Slinton public prtreal(r) 5369676Slinton double r; 5379676Slinton { 5389676Slinton extern char *index(); 5399676Slinton char buf[256]; 5409676Slinton 5419676Slinton sprintf(buf, "%g", r); 5429676Slinton if (buf[0] == '.') { 5439676Slinton printf("0%s", buf); 5449676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 5459676Slinton printf("-0%s", &buf[1]); 5469676Slinton } else { 5479676Slinton printf("%s", buf); 5489676Slinton } 5499676Slinton if (index(buf, '.') == nil) { 5509676Slinton printf(".0"); 5519676Slinton } 5529676Slinton } 5539676Slinton 5549676Slinton /* 5559676Slinton * Print out a character using ^? notation for unprintables. 5569676Slinton */ 5579676Slinton 5589676Slinton public printchar(c) 5599676Slinton char c; 5609676Slinton { 5619676Slinton if (c == 0) { 5629676Slinton putchar('\\'); 5639676Slinton putchar('0'); 5649676Slinton } else if (c == '\n') { 5659676Slinton putchar('\\'); 5669676Slinton putchar('n'); 5679676Slinton } else if (c > 0 and c < ' ') { 5689676Slinton putchar('^'); 5699676Slinton putchar(c - 1 + 'A'); 5709676Slinton } else { 5719676Slinton putchar(c); 5729676Slinton } 5739676Slinton } 574