121619Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621619Sdist */ 179676Slinton 1821619Sdist #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)printsym.c 5.6 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 219676Slinton 229676Slinton /* 239676Slinton * Printing of symbolic information. 249676Slinton */ 259676Slinton 269676Slinton #include "defs.h" 279676Slinton #include "symbols.h" 289676Slinton #include "languages.h" 299676Slinton #include "printsym.h" 309676Slinton #include "tree.h" 319676Slinton #include "eval.h" 329676Slinton #include "mappings.h" 339676Slinton #include "process.h" 349676Slinton #include "runtime.h" 359676Slinton #include "machine.h" 369676Slinton #include "names.h" 3718229Slinton #include "keywords.h" 389676Slinton #include "main.h" 3929820Ssam #include <ctype.h> 409676Slinton 419676Slinton #ifndef public 429676Slinton #endif 439676Slinton 449676Slinton /* 4511863Slinton * Maximum number of arguments to a function. 4611863Slinton * This is used as a check for the possibility that the stack has been 4711863Slinton * overwritten and therefore a saved argument pointer might indicate 4811863Slinton * to an absurdly large number of arguments. 4911863Slinton */ 5011863Slinton 5111863Slinton #define MAXARGSPASSED 20 5211863Slinton 5311863Slinton /* 549676Slinton * Return a pointer to the string for the name of the class that 559676Slinton * the given symbol belongs to. 569676Slinton */ 579676Slinton 589676Slinton private String clname[] = { 5933330Sdonn "bad use", "constant", "type", "variable", "array", "array", 6033330Sdonn "dynarray", "subarray", "fileptr", "record", "field", 6118229Slinton "procedure", "function", "funcvar", 629676Slinton "ref", "pointer", "file", "set", "range", "label", "withptr", 639676Slinton "scalar", "string", "program", "improper", "variant", 6416616Ssam "procparam", "funcparam", "module", "tag", "common", "extref", "typeref" 659676Slinton }; 669676Slinton 679676Slinton public String classname(s) 689676Slinton Symbol s; 699676Slinton { 709676Slinton return clname[ord(s->class)]; 719676Slinton } 729676Slinton 739676Slinton /* 749676Slinton * Note the entry of the given block, unless it's the main program. 759676Slinton */ 769676Slinton 779676Slinton public printentry(s) 789676Slinton Symbol s; 799676Slinton { 809676Slinton if (s != program) { 8118229Slinton printf("\nentering %s ", classname(s)); 8218229Slinton printname(stdout, s); 8318229Slinton printf("\n"); 849676Slinton } 859676Slinton } 869676Slinton 879676Slinton /* 889676Slinton * Note the exit of the given block 899676Slinton */ 909676Slinton 919676Slinton public printexit(s) 929676Slinton Symbol s; 939676Slinton { 949676Slinton if (s != program) { 9518229Slinton printf("leaving %s ", classname(s)); 9618229Slinton printname(stdout, s); 9718229Slinton printf("\n\n"); 989676Slinton } 999676Slinton } 1009676Slinton 1019676Slinton /* 1029676Slinton * Note the call of s from t. 1039676Slinton */ 1049676Slinton 1059676Slinton public printcall(s, t) 1069676Slinton Symbol s, t; 1079676Slinton { 10818229Slinton printf("calling "); 10918229Slinton printname(stdout, s); 1109676Slinton printparams(s, nil); 11118229Slinton printf(" from %s ", classname(t)); 11218229Slinton printname(stdout, t); 11318229Slinton printf("\n"); 1149676Slinton } 1159676Slinton 1169676Slinton /* 1179676Slinton * Note the return from s. If s is a function, print the value 1189676Slinton * it is returning. This is somewhat painful, since the function 1199676Slinton * has actually just returned. 1209676Slinton */ 1219676Slinton 1229676Slinton public printrtn(s) 1239676Slinton Symbol s; 1249676Slinton { 1259676Slinton register Symbol t; 1269676Slinton register int len; 1279676Slinton Boolean isindirect; 1289676Slinton 1299676Slinton printf("returning "); 13012628Scsvaf if (s->class == FUNC && (!istypename(s->type,"void"))) { 1319676Slinton len = size(s->type); 1329676Slinton if (canpush(len)) { 1339676Slinton t = rtype(s->type); 1349676Slinton isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); 1359676Slinton pushretval(len, isindirect); 1369676Slinton printval(s->type); 1379676Slinton putchar(' '); 1389676Slinton } else { 1399676Slinton printf("(value too large) "); 1409676Slinton } 1419676Slinton } 14218229Slinton printf("from "); 14318229Slinton printname(stdout, s); 14418229Slinton printf("\n"); 1459676Slinton } 1469676Slinton 1479676Slinton /* 1489676Slinton * Print the values of the parameters of the given procedure or function. 1499676Slinton * The frame distinguishes recursive instances of a procedure. 15016616Ssam * 15116616Ssam * If the procedure or function is internal, the argument count is 15216616Ssam * not valid so we ignore it. 1539676Slinton */ 1549676Slinton 1559676Slinton public printparams(f, frame) 1569676Slinton Symbol f; 1579676Slinton Frame frame; 1589676Slinton { 1599676Slinton Symbol param; 1609676Slinton int n, m, s; 1619676Slinton 1629676Slinton n = nargspassed(frame); 16316616Ssam if (isinternal(f)) { 16416616Ssam n = 0; 16516616Ssam } 16618229Slinton printf("("); 1679676Slinton param = f->chain; 1689676Slinton if (param != nil or n > 0) { 1699676Slinton m = n; 1709676Slinton if (param != nil) { 1719676Slinton for (;;) { 17218229Slinton s = psize(param) div sizeof(Word); 1739676Slinton if (s == 0) { 1749676Slinton s = 1; 1759676Slinton } 1769676Slinton m -= s; 17718229Slinton if (showaggrs) { 17818229Slinton printv(param, frame); 17918229Slinton } else { 18018229Slinton printparamv(param, frame); 18118229Slinton } 1829676Slinton param = param->chain; 1839676Slinton if (param == nil) break; 1849676Slinton printf(", "); 1859676Slinton } 1869676Slinton } 1879676Slinton if (m > 0) { 18811863Slinton if (m > MAXARGSPASSED) { 18911863Slinton m = MAXARGSPASSED; 19011863Slinton } 1919676Slinton if (f->chain != nil) { 1929676Slinton printf(", "); 1939676Slinton } 1949676Slinton for (;;) { 1959676Slinton --m; 1969676Slinton printf("0x%x", argn(n - m, frame)); 1979676Slinton if (m <= 0) break; 1989676Slinton printf(", "); 1999676Slinton } 2009676Slinton } 2019676Slinton } 20218229Slinton printf(")"); 2039676Slinton } 2049676Slinton 2059676Slinton /* 2069676Slinton * Test if a symbol should be printed. We don't print files, 2079676Slinton * for example, simply because there's no good way to do it. 2089676Slinton * The symbol must be within the given function. 2099676Slinton */ 2109676Slinton 2119676Slinton public Boolean should_print(s) 2129676Slinton Symbol s; 2139676Slinton { 2149676Slinton Boolean b; 2159676Slinton register Symbol t; 2169676Slinton 2179676Slinton switch (s->class) { 2189676Slinton case VAR: 2199676Slinton case FVAR: 22014339Slinton if (isparam(s)) { 22114339Slinton b = false; 22214339Slinton } else { 22314339Slinton t = rtype(s->type); 22414339Slinton if (t == nil) { 22514339Slinton b = false; 22614339Slinton } else { 22714339Slinton switch (t->class) { 22814339Slinton case FILET: 22914339Slinton case SET: 23014339Slinton case BADUSE: 23114339Slinton b = false; 23214339Slinton break; 23314339Slinton 23414339Slinton default: 23514339Slinton b = true; 23614339Slinton break; 23714339Slinton } 23814339Slinton } 23914339Slinton } 2409676Slinton break; 2419676Slinton 2429676Slinton default: 2439676Slinton b = false; 2449676Slinton break; 2459676Slinton } 2469676Slinton return b; 2479676Slinton } 2489676Slinton 2499676Slinton /* 25018229Slinton * Print out a parameter value. 25118229Slinton * 25218229Slinton * Since this is intended to be printed on a single line with other information 25318229Slinton * aggregate values are not printed. 25418229Slinton */ 25518229Slinton 25618229Slinton public printparamv (p, frame) 25718229Slinton Symbol p; 25818229Slinton Frame frame; 25918229Slinton { 26018229Slinton Symbol t; 26118229Slinton 26218229Slinton t = rtype(p->type); 26318229Slinton switch (t->class) { 26418229Slinton case ARRAY: 26533330Sdonn case OPENARRAY: 26618229Slinton case DYNARRAY: 26718229Slinton case SUBARRAY: 26818229Slinton t = rtype(t->type); 26918229Slinton if (compatible(t, t_char)) { 27018229Slinton printv(p, frame); 27118229Slinton } else { 27218229Slinton printf("%s = (...)", symname(p)); 27318229Slinton } 27418229Slinton break; 27518229Slinton 27618229Slinton case RECORD: 27718229Slinton printf("%s = (...)", symname(p)); 27818229Slinton break; 27918229Slinton 28018229Slinton default: 28118229Slinton printv(p, frame); 28218229Slinton break; 28318229Slinton } 28418229Slinton } 28518229Slinton 28618229Slinton /* 2879676Slinton * Print the name and value of a variable. 2889676Slinton */ 2899676Slinton 2909676Slinton public printv(s, frame) 2919676Slinton Symbol s; 2929676Slinton Frame frame; 2939676Slinton { 2949676Slinton Address addr; 2959676Slinton int len; 2969676Slinton 2979676Slinton if (isambiguous(s) and ismodule(container(s))) { 2989676Slinton printname(stdout, s); 2999676Slinton printf(" = "); 3009676Slinton } else { 3019676Slinton printf("%s = ", symname(s)); 3029676Slinton } 30318229Slinton if (isvarparam(s) and not isopenarray(s)) { 30418229Slinton rpush(address(s, frame), sizeof(Address)); 30518229Slinton addr = pop(Address); 3069676Slinton } else { 30718229Slinton addr = address(s, frame); 30818229Slinton } 30918229Slinton len = size(s); 31024554Smckusick if (not canpush(len)) { 31124554Smckusick printf("*** expression too large ***"); 31224554Smckusick } else if (isreg(s)) { 31324554Smckusick push(Address, addr); 31424554Smckusick printval(s->type); 31524554Smckusick } else { 31618229Slinton rpush(addr, len); 31718229Slinton printval(s->type); 31818229Slinton } 3199676Slinton } 3209676Slinton 3219676Slinton /* 3229676Slinton * Print out the name of a symbol. 3239676Slinton */ 3249676Slinton 3259676Slinton public printname(f, s) 3269676Slinton File f; 3279676Slinton Symbol s; 3289676Slinton { 3299676Slinton if (s == nil) { 3309676Slinton fprintf(f, "(noname)"); 33116616Ssam } else if (s == program) { 33216616Ssam fprintf(f, "."); 3339676Slinton } else if (isredirected() or isambiguous(s)) { 3349676Slinton printwhich(f, s); 3359676Slinton } else { 3369676Slinton fprintf(f, "%s", symname(s)); 3379676Slinton } 3389676Slinton } 3399676Slinton 3409676Slinton /* 3419676Slinton * Print the fully specified variable that is described by the given identifer. 3429676Slinton */ 3439676Slinton 3449676Slinton public printwhich(f, s) 3459676Slinton File f; 3469676Slinton Symbol s; 3479676Slinton { 3489676Slinton printouter(f, container(s)); 3499676Slinton fprintf(f, "%s", symname(s)); 3509676Slinton } 3519676Slinton 3529676Slinton /* 3539676Slinton * Print the fully qualified name of each symbol that has the same name 3549676Slinton * as the given symbol. 3559676Slinton */ 3569676Slinton 3579676Slinton public printwhereis(f, s) 3589676Slinton File f; 3599676Slinton Symbol s; 3609676Slinton { 3619676Slinton register Name n; 3629676Slinton register Symbol t; 3639676Slinton 3649676Slinton checkref(s); 3659676Slinton n = s->name; 3669676Slinton t = lookup(n); 3679676Slinton printwhich(f, t); 3689676Slinton t = t->next_sym; 3699676Slinton while (t != nil) { 3709676Slinton if (t->name == n) { 3719676Slinton putc(' ', f); 3729676Slinton printwhich(f, t); 3739676Slinton } 3749676Slinton t = t->next_sym; 3759676Slinton } 3769676Slinton putc('\n', f); 3779676Slinton } 3789676Slinton 3799676Slinton private printouter(f, s) 3809676Slinton File f; 3819676Slinton Symbol s; 3829676Slinton { 3839676Slinton Symbol outer; 3849676Slinton 3859676Slinton if (s != nil) { 3869676Slinton outer = container(s); 3879676Slinton if (outer != nil and outer != program) { 3889676Slinton printouter(f, outer); 3899676Slinton } 3909676Slinton fprintf(f, "%s.", symname(s)); 3919676Slinton } 3929676Slinton } 3939676Slinton 3949676Slinton public printdecl(s) 3959676Slinton Symbol s; 3969676Slinton { 39718229Slinton Language lang; 39818229Slinton 3999676Slinton checkref(s); 40018229Slinton if (s->language == nil or s->language == primlang) { 40118229Slinton lang = findlanguage(".s"); 40218229Slinton } else { 40318229Slinton lang = s->language; 40418229Slinton } 40518229Slinton (*language_op(lang, L_PRINTDECL))(s); 4069676Slinton } 4079676Slinton 4089676Slinton /* 4099676Slinton * Straight dump of symbol information. 4109676Slinton */ 4119676Slinton 4129676Slinton public psym(s) 4139676Slinton Symbol s; 4149676Slinton { 4159676Slinton printf("name\t%s\n", symname(s)); 4169676Slinton printf("lang\t%s\n", language_name(s->language)); 4179676Slinton printf("level\t%d\n", s->level); 4189676Slinton printf("class\t%s\n", classname(s)); 4199676Slinton printf("type\t0x%x", s->type); 4209676Slinton if (s->type != nil and s->type->name != nil) { 4219676Slinton printf(" (%s)", symname(s->type)); 4229676Slinton } 4239676Slinton printf("\nchain\t0x%x", s->chain); 4249676Slinton if (s->chain != nil and s->chain->name != nil) { 4259676Slinton printf(" (%s)", symname(s->chain)); 4269676Slinton } 4279676Slinton printf("\nblock\t0x%x", s->block); 42833330Sdonn if (s->block != nil and s->block->name != nil) { 4299676Slinton printf(" ("); 4309676Slinton printname(stdout, s->block); 4319676Slinton putchar(')'); 4329676Slinton } 4339676Slinton putchar('\n'); 4349676Slinton switch (s->class) { 43518229Slinton case TYPE: 43618229Slinton printf("size\t%d\n", size(s)); 43718229Slinton break; 43818229Slinton 4399676Slinton case VAR: 4409676Slinton case REF: 44133330Sdonn switch (s->storage) { 44233330Sdonn case INREG: 44333330Sdonn printf("reg\t%d\n", s->symvalue.offset); 44433330Sdonn break; 44533330Sdonn 44633330Sdonn case STK: 44733330Sdonn printf("offset\t%d\n", s->symvalue.offset); 44833330Sdonn break; 44933330Sdonn 45033330Sdonn case EXT: 45133330Sdonn printf("address\t0x%x\n", s->symvalue.offset); 45233330Sdonn break; 4539676Slinton } 45412545Scsvaf printf("size\t%d\n", size(s)); 4559676Slinton break; 4569676Slinton 4579676Slinton case RECORD: 4589676Slinton case VARNT: 4599676Slinton printf("size\t%d\n", s->symvalue.offset); 4609676Slinton break; 4619676Slinton 4629676Slinton case FIELD: 4639676Slinton printf("offset\t%d\n", s->symvalue.field.offset); 4649676Slinton printf("size\t%d\n", s->symvalue.field.length); 4659676Slinton break; 4669676Slinton 46714381Slinton case PROG: 4689676Slinton case PROC: 4699676Slinton case FUNC: 4709676Slinton printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 47114438Slinton if (isinline(s)) { 47214440Slinton printf("inline procedure\n"); 47314438Slinton } 47411863Slinton if (nosource(s)) { 47511863Slinton printf("does not have source information\n"); 47611863Slinton } else { 47711863Slinton printf("has source information\n"); 47811863Slinton } 4799676Slinton break; 4809676Slinton 4819676Slinton case RANGE: 48214381Slinton prangetype(s->symvalue.rangev.lowertype); 4839676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 48414381Slinton prangetype(s->symvalue.rangev.uppertype); 4859676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 4869676Slinton break; 4879676Slinton 4889676Slinton default: 4899676Slinton /* do nothing */ 4909676Slinton break; 4919676Slinton } 4929676Slinton } 4939676Slinton 49414381Slinton private prangetype(r) 49514381Slinton Rangetype r; 49614381Slinton { 49714381Slinton switch (r) { 49814381Slinton case R_CONST: 49914381Slinton printf("CONST"); 50014381Slinton break; 50114381Slinton 50214381Slinton case R_ARG: 50314381Slinton printf("ARG"); 50414381Slinton break; 50514381Slinton 50614381Slinton case R_TEMP: 50714381Slinton printf("TEMP"); 50814381Slinton break; 50914381Slinton 51014381Slinton case R_ADJUST: 51114381Slinton printf("ADJUST"); 51214381Slinton break; 51314381Slinton } 51414381Slinton } 51514381Slinton 5169676Slinton /* 5179676Slinton * Print out the value on top of the stack according to the given type. 5189676Slinton */ 5199676Slinton 5209676Slinton public printval(t) 5219676Slinton Symbol t; 5229676Slinton { 5239676Slinton Symbol s; 5249676Slinton 5259676Slinton checkref(t); 52616616Ssam if (t->class == TYPEREF) { 52716616Ssam resolveRef(t); 52816616Ssam } 5299676Slinton switch (t->class) { 5309676Slinton case PROC: 5319676Slinton case FUNC: 5329676Slinton s = pop(Symbol); 5339676Slinton printf("%s", symname(s)); 5349676Slinton break; 5359676Slinton 5369676Slinton default: 53718229Slinton if (t->language == nil or t->language == primlang) { 53826478Ssam (*language_op(findlanguage(".c"), L_PRINTVAL))(t); 5399676Slinton } else { 5409676Slinton (*language_op(t->language, L_PRINTVAL))(t); 5419676Slinton } 5429676Slinton break; 5439676Slinton } 5449676Slinton } 5459676Slinton 5469676Slinton /* 5479676Slinton * Print out the value of a record, field by field. 5489676Slinton */ 5499676Slinton 5509676Slinton public printrecord(s) 5519676Slinton Symbol s; 5529676Slinton { 55316616Ssam Symbol f; 55416616Ssam 5559676Slinton if (s->chain == nil) { 5569676Slinton error("record has no fields"); 5579676Slinton } 5589676Slinton printf("("); 5599676Slinton sp -= size(s); 56016616Ssam f = s->chain; 56116616Ssam if (f != nil) { 56216616Ssam for (;;) { 56316616Ssam printfield(f); 56416616Ssam f = f->chain; 56516616Ssam if (f == nil) break; 56616616Ssam printf(", "); 56716616Ssam } 56816616Ssam } 5699676Slinton printf(")"); 5709676Slinton } 5719676Slinton 5729676Slinton /* 57316616Ssam * Print out a field. 5749676Slinton */ 5759676Slinton 57616616Ssam private printfield(f) 57716616Ssam Symbol f; 5789676Slinton { 5799676Slinton Stack *savesp; 58016616Ssam register int off, len; 5819676Slinton 58216616Ssam printf("%s = ", symname(f)); 5839676Slinton savesp = sp; 58416616Ssam off = f->symvalue.field.offset; 58516616Ssam len = f->symvalue.field.length; 58616616Ssam sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE); 58716616Ssam printval(f); 5889676Slinton sp = savesp; 5899676Slinton } 5909676Slinton 5919676Slinton /* 5929676Slinton * Print out the contents of an array. 5939676Slinton * Haven't quite figured out what the best format is. 5949676Slinton * 5959676Slinton * This is rather inefficient. 5969676Slinton * 5979676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 5989676Slinton */ 5999676Slinton 6009676Slinton public printarray(a) 6019676Slinton Symbol a; 6029676Slinton { 6039676Slinton Stack *savesp, *newsp; 6049676Slinton Symbol eltype; 6059676Slinton long elsize; 6069676Slinton String sep; 6079676Slinton 6089676Slinton savesp = sp; 60912544Scsvaf sp -= (size(a)); 6109676Slinton newsp = sp; 6119676Slinton eltype = rtype(a->type); 6129676Slinton elsize = size(eltype); 6139676Slinton printf("("); 6149676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 6159676Slinton eltype->class == VARNT) { 6169676Slinton sep = "\n"; 6179676Slinton putchar('\n'); 6189676Slinton } else { 6199676Slinton sep = ", "; 6209676Slinton } 6219676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 6229676Slinton if (sp - elsize != newsp) { 6239676Slinton fputs(sep, stdout); 6249676Slinton } 6259676Slinton printval(eltype); 6269676Slinton } 6279676Slinton sp = newsp; 6289676Slinton if (streq(sep, "\n")) { 6299676Slinton putchar('\n'); 6309676Slinton } 6319676Slinton printf(")"); 6329676Slinton } 6339676Slinton 6349676Slinton /* 6359676Slinton * Print out the value of a real number in Pascal notation. 6369676Slinton * This is, unfortunately, different than what one gets 6379676Slinton * from "%g" in printf. 6389676Slinton */ 6399676Slinton 6409676Slinton public prtreal(r) 6419676Slinton double r; 6429676Slinton { 6439676Slinton extern char *index(); 6449676Slinton char buf[256]; 6459676Slinton 64633330Sdonn # ifdef IRIS 64733330Sdonn sprintf(buf, "%lg", r); 64833330Sdonn # else 64933330Sdonn sprintf(buf, "%g", r); 65033330Sdonn # endif 6519676Slinton if (buf[0] == '.') { 6529676Slinton printf("0%s", buf); 6539676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 6549676Slinton printf("-0%s", &buf[1]); 6559676Slinton } else { 6569676Slinton printf("%s", buf); 6579676Slinton } 6589676Slinton if (index(buf, '.') == nil) { 6599676Slinton printf(".0"); 6609676Slinton } 6619676Slinton } 6629676Slinton 6639676Slinton /* 6649676Slinton * Print out a character using ^? notation for unprintables. 6659676Slinton */ 6669676Slinton 6679676Slinton public printchar(c) 6689676Slinton char c; 6699676Slinton { 6709676Slinton if (c == 0) { 6719676Slinton putchar('\\'); 6729676Slinton putchar('0'); 6739676Slinton } else if (c == '\n') { 6749676Slinton putchar('\\'); 6759676Slinton putchar('n'); 6769676Slinton } else if (c > 0 and c < ' ') { 6779676Slinton putchar('^'); 6789676Slinton putchar(c - 1 + 'A'); 67916616Ssam } else if (c >= ' ' && c <= '~') { 68016616Ssam putchar(c); 6819676Slinton } else { 68229820Ssam printf("\\0%o",c&0xff); 6839676Slinton } 6849676Slinton } 68518229Slinton 68618229Slinton /* 68718229Slinton * Print out a value for a range type (integer, char, or boolean). 68818229Slinton */ 68918229Slinton 69018229Slinton public printRangeVal (val, t) 69118229Slinton long val; 69218229Slinton Symbol t; 69318229Slinton { 69418229Slinton if (t == t_boolean->type or istypename(t->type, "boolean")) { 69518229Slinton if ((boolean) val) { 69618229Slinton printf("true"); 69718229Slinton } else { 69818229Slinton printf("false"); 69918229Slinton } 70018229Slinton } else if (t == t_char->type or istypename(t->type, "char")) { 70118229Slinton if (varIsSet("$hexchars")) { 70218229Slinton printf("0x%lx", val); 70318229Slinton } else { 70418229Slinton putchar('\''); 70518229Slinton printchar(val); 70618229Slinton putchar('\''); 70718229Slinton } 70818229Slinton } else if (varIsSet("$hexints")) { 70918229Slinton printf("0x%lx", val); 71018229Slinton } else if (t->symvalue.rangev.lower >= 0) { 71118229Slinton printf("%lu", val); 71218229Slinton } else { 71318229Slinton printf("%ld", val); 71418229Slinton } 71518229Slinton } 71618229Slinton 71718229Slinton /* 71818229Slinton * Print out an enumerated value by finding the corresponding 71918229Slinton * name in the enumeration list. 72018229Slinton */ 72118229Slinton 72218229Slinton public printEnum (i, t) 72318229Slinton integer i; 72418229Slinton Symbol t; 72518229Slinton { 72618229Slinton register Symbol e; 72718229Slinton 72818229Slinton e = t->chain; 72918229Slinton while (e != nil and e->symvalue.constval->value.lcon != i) { 73018229Slinton e = e->chain; 73118229Slinton } 73218229Slinton if (e != nil) { 73318229Slinton printf("%s", symname(e)); 73418229Slinton } else { 73518229Slinton printf("%d", i); 73618229Slinton } 73718229Slinton } 73818229Slinton 73918229Slinton /* 74018229Slinton * Print out a null-terminated string (pointer to char) 74118229Slinton * starting at the given address. 74218229Slinton */ 74318229Slinton 74418229Slinton public printString (addr, quotes) 74518229Slinton Address addr; 74618229Slinton boolean quotes; 74718229Slinton { 74818229Slinton register Address a; 74918229Slinton register integer i, len; 75018229Slinton register boolean endofstring; 75129820Ssam register int unprintables; 75229820Ssam #define MAXGARBAGE 4 75318229Slinton union { 75418229Slinton char ch[sizeof(Word)]; 75518229Slinton int word; 75618229Slinton } u; 75718229Slinton 75818229Slinton if (varIsSet("$hexstrings")) { 75918229Slinton printf("0x%x", addr); 76018229Slinton } else { 76118229Slinton if (quotes) { 76218229Slinton putchar('"'); 76318229Slinton } 76418229Slinton a = addr; 76529820Ssam unprintables = 0; 76618229Slinton endofstring = false; 76718229Slinton while (not endofstring) { 76818229Slinton dread(&u, a, sizeof(u)); 76918229Slinton i = 0; 77018229Slinton do { 77118229Slinton if (u.ch[i] == '\0') { 77218229Slinton endofstring = true; 77318229Slinton } else { 77418229Slinton printchar(u.ch[i]); 77529820Ssam if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) { 77629820Ssam endofstring = true; 77729820Ssam printf("..."); 77829820Ssam } 77918229Slinton } 78018229Slinton ++i; 78118229Slinton } while (i < sizeof(Word) and not endofstring); 78218229Slinton a += sizeof(Word); 78318229Slinton } 78418229Slinton if (quotes) { 78518229Slinton putchar('"'); 78618229Slinton } 78718229Slinton } 78818229Slinton } 789