xref: /csrg-svn/old/dbx/printsym.c (revision 29820)
121619Sdist /*
221619Sdist  * Copyright (c) 1983 Regents of the University of California.
321619Sdist  * All rights reserved.  The Berkeley software License Agreement
421619Sdist  * specifies the terms and conditions for redistribution.
521619Sdist  */
69676Slinton 
721619Sdist #ifndef lint
8*29820Ssam static char sccsid[] = "@(#)printsym.c	5.4 (Berkeley) 09/01/86";
921619Sdist #endif not lint
109676Slinton 
1118229Slinton static char rcsid[] = "$Header: printsym.c,v 1.5 84/12/26 10:41:28 linton Exp $";
1218229Slinton 
139676Slinton /*
149676Slinton  * Printing of symbolic information.
159676Slinton  */
169676Slinton 
179676Slinton #include "defs.h"
189676Slinton #include "symbols.h"
199676Slinton #include "languages.h"
209676Slinton #include "printsym.h"
219676Slinton #include "tree.h"
229676Slinton #include "eval.h"
239676Slinton #include "mappings.h"
249676Slinton #include "process.h"
259676Slinton #include "runtime.h"
269676Slinton #include "machine.h"
279676Slinton #include "names.h"
2818229Slinton #include "keywords.h"
299676Slinton #include "main.h"
30*29820Ssam #include <ctype.h>
319676Slinton 
329676Slinton #ifndef public
339676Slinton #endif
349676Slinton 
359676Slinton /*
3611863Slinton  * Maximum number of arguments to a function.
3711863Slinton  * This is used as a check for the possibility that the stack has been
3811863Slinton  * overwritten and therefore a saved argument pointer might indicate
3911863Slinton  * to an absurdly large number of arguments.
4011863Slinton  */
4111863Slinton 
4211863Slinton #define MAXARGSPASSED 20
4311863Slinton 
4411863Slinton /*
459676Slinton  * Return a pointer to the string for the name of the class that
469676Slinton  * the given symbol belongs to.
479676Slinton  */
489676Slinton 
499676Slinton private String clname[] = {
5018229Slinton     "bad use", "constant", "type", "variable", "array", "@dynarray",
5118229Slinton     "@subarray", "fileptr", "record", "field",
5218229Slinton     "procedure", "function", "funcvar",
539676Slinton     "ref", "pointer", "file", "set", "range", "label", "withptr",
549676Slinton     "scalar", "string", "program", "improper", "variant",
5516616Ssam     "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
569676Slinton };
579676Slinton 
589676Slinton public String classname(s)
599676Slinton Symbol s;
609676Slinton {
619676Slinton     return clname[ord(s->class)];
629676Slinton }
639676Slinton 
649676Slinton /*
659676Slinton  * Note the entry of the given block, unless it's the main program.
669676Slinton  */
679676Slinton 
689676Slinton public printentry(s)
699676Slinton Symbol s;
709676Slinton {
719676Slinton     if (s != program) {
7218229Slinton 	printf("\nentering %s ", classname(s));
7318229Slinton 	printname(stdout, s);
7418229Slinton 	printf("\n");
759676Slinton     }
769676Slinton }
779676Slinton 
789676Slinton /*
799676Slinton  * Note the exit of the given block
809676Slinton  */
819676Slinton 
829676Slinton public printexit(s)
839676Slinton Symbol s;
849676Slinton {
859676Slinton     if (s != program) {
8618229Slinton 	printf("leaving %s ", classname(s));
8718229Slinton 	printname(stdout, s);
8818229Slinton 	printf("\n\n");
899676Slinton     }
909676Slinton }
919676Slinton 
929676Slinton /*
939676Slinton  * Note the call of s from t.
949676Slinton  */
959676Slinton 
969676Slinton public printcall(s, t)
979676Slinton Symbol s, t;
989676Slinton {
9918229Slinton     printf("calling ");
10018229Slinton     printname(stdout, s);
1019676Slinton     printparams(s, nil);
10218229Slinton     printf(" from %s ", classname(t));
10318229Slinton     printname(stdout, t);
10418229Slinton     printf("\n");
1059676Slinton }
1069676Slinton 
1079676Slinton /*
1089676Slinton  * Note the return from s.  If s is a function, print the value
1099676Slinton  * it is returning.  This is somewhat painful, since the function
1109676Slinton  * has actually just returned.
1119676Slinton  */
1129676Slinton 
1139676Slinton public printrtn(s)
1149676Slinton Symbol s;
1159676Slinton {
1169676Slinton     register Symbol t;
1179676Slinton     register int len;
1189676Slinton     Boolean isindirect;
1199676Slinton 
1209676Slinton     printf("returning ");
12112628Scsvaf     if (s->class == FUNC && (!istypename(s->type,"void"))) {
1229676Slinton 	len = size(s->type);
1239676Slinton 	if (canpush(len)) {
1249676Slinton 	    t = rtype(s->type);
1259676Slinton 	    isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
1269676Slinton 	    pushretval(len, isindirect);
1279676Slinton 	    printval(s->type);
1289676Slinton 	    putchar(' ');
1299676Slinton 	} else {
1309676Slinton 	    printf("(value too large) ");
1319676Slinton 	}
1329676Slinton     }
13318229Slinton     printf("from ");
13418229Slinton     printname(stdout, s);
13518229Slinton     printf("\n");
1369676Slinton }
1379676Slinton 
1389676Slinton /*
1399676Slinton  * Print the values of the parameters of the given procedure or function.
1409676Slinton  * The frame distinguishes recursive instances of a procedure.
14116616Ssam  *
14216616Ssam  * If the procedure or function is internal, the argument count is
14316616Ssam  * not valid so we ignore it.
1449676Slinton  */
1459676Slinton 
1469676Slinton public printparams(f, frame)
1479676Slinton Symbol f;
1489676Slinton Frame frame;
1499676Slinton {
1509676Slinton     Symbol param;
1519676Slinton     int n, m, s;
1529676Slinton 
1539676Slinton     n = nargspassed(frame);
15416616Ssam     if (isinternal(f)) {
15516616Ssam 	n = 0;
15616616Ssam     }
15718229Slinton     printf("(");
1589676Slinton     param = f->chain;
1599676Slinton     if (param != nil or n > 0) {
1609676Slinton 	m = n;
1619676Slinton 	if (param != nil) {
1629676Slinton 	    for (;;) {
16318229Slinton 		s = psize(param) div sizeof(Word);
1649676Slinton 		if (s == 0) {
1659676Slinton 		    s = 1;
1669676Slinton 		}
1679676Slinton 		m -= s;
16818229Slinton 		if (showaggrs) {
16918229Slinton 		    printv(param, frame);
17018229Slinton 		} else {
17118229Slinton 		    printparamv(param, frame);
17218229Slinton 		}
1739676Slinton 		param = param->chain;
1749676Slinton 	    if (param == nil) break;
1759676Slinton 		printf(", ");
1769676Slinton 	    }
1779676Slinton 	}
1789676Slinton 	if (m > 0) {
17911863Slinton 	    if (m > MAXARGSPASSED) {
18011863Slinton 		m = MAXARGSPASSED;
18111863Slinton 	    }
1829676Slinton 	    if (f->chain != nil) {
1839676Slinton 		printf(", ");
1849676Slinton 	    }
1859676Slinton 	    for (;;) {
1869676Slinton 		--m;
1879676Slinton 		printf("0x%x", argn(n - m, frame));
1889676Slinton 	    if (m <= 0) break;
1899676Slinton 		printf(", ");
1909676Slinton 	    }
1919676Slinton 	}
1929676Slinton     }
19318229Slinton     printf(")");
1949676Slinton }
1959676Slinton 
1969676Slinton /*
1979676Slinton  * Test if a symbol should be printed.  We don't print files,
1989676Slinton  * for example, simply because there's no good way to do it.
1999676Slinton  * The symbol must be within the given function.
2009676Slinton  */
2019676Slinton 
2029676Slinton public Boolean should_print(s)
2039676Slinton Symbol s;
2049676Slinton {
2059676Slinton     Boolean b;
2069676Slinton     register Symbol t;
2079676Slinton 
2089676Slinton     switch (s->class) {
2099676Slinton 	case VAR:
2109676Slinton 	case FVAR:
21114339Slinton 	    if (isparam(s)) {
21214339Slinton 		b = false;
21314339Slinton 	    } else {
21414339Slinton 		t = rtype(s->type);
21514339Slinton 		if (t == nil) {
21614339Slinton 		    b = false;
21714339Slinton 		} else {
21814339Slinton 		    switch (t->class) {
21914339Slinton 			case FILET:
22014339Slinton 			case SET:
22114339Slinton 			case BADUSE:
22214339Slinton 			    b = false;
22314339Slinton 			    break;
22414339Slinton 
22514339Slinton 			default:
22614339Slinton 			    b = true;
22714339Slinton 			    break;
22814339Slinton 		    }
22914339Slinton 		}
23014339Slinton 	    }
2319676Slinton 	    break;
2329676Slinton 
2339676Slinton 	default:
2349676Slinton 	    b = false;
2359676Slinton 	    break;
2369676Slinton     }
2379676Slinton     return b;
2389676Slinton }
2399676Slinton 
2409676Slinton /*
24118229Slinton  * Print out a parameter value.
24218229Slinton  *
24318229Slinton  * Since this is intended to be printed on a single line with other information
24418229Slinton  * aggregate values are not printed.
24518229Slinton  */
24618229Slinton 
24718229Slinton public printparamv (p, frame)
24818229Slinton Symbol p;
24918229Slinton Frame frame;
25018229Slinton {
25118229Slinton     Symbol t;
25218229Slinton 
25318229Slinton     t = rtype(p->type);
25418229Slinton     switch (t->class) {
25518229Slinton 	case ARRAY:
25618229Slinton 	case DYNARRAY:
25718229Slinton 	case SUBARRAY:
25818229Slinton 	    t = rtype(t->type);
25918229Slinton 	    if (compatible(t, t_char)) {
26018229Slinton 		printv(p, frame);
26118229Slinton 	    } else {
26218229Slinton 		printf("%s = (...)", symname(p));
26318229Slinton 	    }
26418229Slinton 	    break;
26518229Slinton 
26618229Slinton 	case RECORD:
26718229Slinton 	    printf("%s = (...)", symname(p));
26818229Slinton 	    break;
26918229Slinton 
27018229Slinton 	default:
27118229Slinton 	    printv(p, frame);
27218229Slinton 	    break;
27318229Slinton     }
27418229Slinton }
27518229Slinton 
27618229Slinton /*
2779676Slinton  * Print the name and value of a variable.
2789676Slinton  */
2799676Slinton 
2809676Slinton public printv(s, frame)
2819676Slinton Symbol s;
2829676Slinton Frame frame;
2839676Slinton {
2849676Slinton     Address addr;
2859676Slinton     int len;
2869676Slinton 
2879676Slinton     if (isambiguous(s) and ismodule(container(s))) {
2889676Slinton 	printname(stdout, s);
2899676Slinton 	printf(" = ");
2909676Slinton     } else {
2919676Slinton 	printf("%s = ", symname(s));
2929676Slinton     }
29318229Slinton     if (isvarparam(s) and not isopenarray(s)) {
29418229Slinton 	rpush(address(s, frame), sizeof(Address));
29518229Slinton 	addr = pop(Address);
2969676Slinton     } else {
29718229Slinton 	addr = address(s, frame);
29818229Slinton     }
29918229Slinton     len = size(s);
30024554Smckusick     if (not canpush(len)) {
30124554Smckusick 	printf("*** expression too large ***");
30224554Smckusick     } else if (isreg(s)) {
30324554Smckusick 	push(Address, addr);
30424554Smckusick 	printval(s->type);
30524554Smckusick     } else {
30618229Slinton 	rpush(addr, len);
30718229Slinton 	printval(s->type);
30818229Slinton     }
3099676Slinton }
3109676Slinton 
3119676Slinton /*
3129676Slinton  * Print out the name of a symbol.
3139676Slinton  */
3149676Slinton 
3159676Slinton public printname(f, s)
3169676Slinton File f;
3179676Slinton Symbol s;
3189676Slinton {
3199676Slinton     if (s == nil) {
3209676Slinton 	fprintf(f, "(noname)");
32116616Ssam     } else if (s == program) {
32216616Ssam 	fprintf(f, ".");
3239676Slinton     } else if (isredirected() or isambiguous(s)) {
3249676Slinton 	printwhich(f, s);
3259676Slinton     } else {
3269676Slinton 	fprintf(f, "%s", symname(s));
3279676Slinton     }
3289676Slinton }
3299676Slinton 
3309676Slinton /*
3319676Slinton  * Print the fully specified variable that is described by the given identifer.
3329676Slinton  */
3339676Slinton 
3349676Slinton public printwhich(f, s)
3359676Slinton File f;
3369676Slinton Symbol s;
3379676Slinton {
3389676Slinton     printouter(f, container(s));
3399676Slinton     fprintf(f, "%s", symname(s));
3409676Slinton }
3419676Slinton 
3429676Slinton /*
3439676Slinton  * Print the fully qualified name of each symbol that has the same name
3449676Slinton  * as the given symbol.
3459676Slinton  */
3469676Slinton 
3479676Slinton public printwhereis(f, s)
3489676Slinton File f;
3499676Slinton Symbol s;
3509676Slinton {
3519676Slinton     register Name n;
3529676Slinton     register Symbol t;
3539676Slinton 
3549676Slinton     checkref(s);
3559676Slinton     n = s->name;
3569676Slinton     t = lookup(n);
3579676Slinton     printwhich(f, t);
3589676Slinton     t = t->next_sym;
3599676Slinton     while (t != nil) {
3609676Slinton 	if (t->name == n) {
3619676Slinton 	    putc(' ', f);
3629676Slinton 	    printwhich(f, t);
3639676Slinton 	}
3649676Slinton 	t = t->next_sym;
3659676Slinton     }
3669676Slinton     putc('\n', f);
3679676Slinton }
3689676Slinton 
3699676Slinton private printouter(f, s)
3709676Slinton File f;
3719676Slinton Symbol s;
3729676Slinton {
3739676Slinton     Symbol outer;
3749676Slinton 
3759676Slinton     if (s != nil) {
3769676Slinton 	outer = container(s);
3779676Slinton 	if (outer != nil and outer != program) {
3789676Slinton 	    printouter(f, outer);
3799676Slinton 	}
3809676Slinton 	fprintf(f, "%s.", symname(s));
3819676Slinton     }
3829676Slinton }
3839676Slinton 
3849676Slinton public printdecl(s)
3859676Slinton Symbol s;
3869676Slinton {
38718229Slinton     Language lang;
38818229Slinton 
3899676Slinton     checkref(s);
39018229Slinton     if (s->language == nil or s->language == primlang) {
39118229Slinton 	lang = findlanguage(".s");
39218229Slinton     } else {
39318229Slinton 	lang = s->language;
39418229Slinton     }
39518229Slinton     (*language_op(lang, L_PRINTDECL))(s);
3969676Slinton }
3979676Slinton 
3989676Slinton /*
3999676Slinton  * Straight dump of symbol information.
4009676Slinton  */
4019676Slinton 
4029676Slinton public psym(s)
4039676Slinton Symbol s;
4049676Slinton {
4059676Slinton     printf("name\t%s\n", symname(s));
4069676Slinton     printf("lang\t%s\n", language_name(s->language));
4079676Slinton     printf("level\t%d\n", s->level);
4089676Slinton     printf("class\t%s\n", classname(s));
4099676Slinton     printf("type\t0x%x", s->type);
4109676Slinton     if (s->type != nil and s->type->name != nil) {
4119676Slinton 	printf(" (%s)", symname(s->type));
4129676Slinton     }
4139676Slinton     printf("\nchain\t0x%x", s->chain);
4149676Slinton     if (s->chain != nil and s->chain->name != nil) {
4159676Slinton 	printf(" (%s)", symname(s->chain));
4169676Slinton     }
4179676Slinton     printf("\nblock\t0x%x", s->block);
4189676Slinton     if (s->block->name != nil) {
4199676Slinton 	printf(" (");
4209676Slinton 	printname(stdout, s->block);
4219676Slinton 	putchar(')');
4229676Slinton     }
4239676Slinton     putchar('\n');
4249676Slinton     switch (s->class) {
42518229Slinton 	case TYPE:
42618229Slinton 	    printf("size\t%d\n", size(s));
42718229Slinton 	    break;
42818229Slinton 
4299676Slinton 	case VAR:
4309676Slinton 	case REF:
4319676Slinton 	    if (s->level >= 3) {
4329676Slinton 		printf("address\t0x%x\n", s->symvalue.offset);
4339676Slinton 	    } else {
4349676Slinton 		printf("offset\t%d\n", s->symvalue.offset);
4359676Slinton 	    }
43612545Scsvaf 	    printf("size\t%d\n", size(s));
4379676Slinton 	    break;
4389676Slinton 
4399676Slinton 	case RECORD:
4409676Slinton 	case VARNT:
4419676Slinton 	    printf("size\t%d\n", s->symvalue.offset);
4429676Slinton 	    break;
4439676Slinton 
4449676Slinton 	case FIELD:
4459676Slinton 	    printf("offset\t%d\n", s->symvalue.field.offset);
4469676Slinton 	    printf("size\t%d\n", s->symvalue.field.length);
4479676Slinton 	    break;
4489676Slinton 
44914381Slinton 	case PROG:
4509676Slinton 	case PROC:
4519676Slinton 	case FUNC:
4529676Slinton 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
45314438Slinton 	    if (isinline(s)) {
45414440Slinton 		printf("inline procedure\n");
45514438Slinton 	    }
45611863Slinton 	    if (nosource(s)) {
45711863Slinton 		printf("does not have source information\n");
45811863Slinton 	    } else {
45911863Slinton 		printf("has source information\n");
46011863Slinton 	    }
4619676Slinton 	    break;
4629676Slinton 
4639676Slinton 	case RANGE:
46414381Slinton 	    prangetype(s->symvalue.rangev.lowertype);
4659676Slinton 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
46614381Slinton 	    prangetype(s->symvalue.rangev.uppertype);
4679676Slinton 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
4689676Slinton 	    break;
4699676Slinton 
4709676Slinton 	default:
4719676Slinton 	    /* do nothing */
4729676Slinton 	    break;
4739676Slinton     }
4749676Slinton }
4759676Slinton 
47614381Slinton private prangetype(r)
47714381Slinton Rangetype r;
47814381Slinton {
47914381Slinton     switch (r) {
48014381Slinton 	case R_CONST:
48114381Slinton 	    printf("CONST");
48214381Slinton 	    break;
48314381Slinton 
48414381Slinton 	case R_ARG:
48514381Slinton 	    printf("ARG");
48614381Slinton 	    break;
48714381Slinton 
48814381Slinton 	case R_TEMP:
48914381Slinton 	    printf("TEMP");
49014381Slinton 	    break;
49114381Slinton 
49214381Slinton 	case R_ADJUST:
49314381Slinton 	    printf("ADJUST");
49414381Slinton 	    break;
49514381Slinton     }
49614381Slinton }
49714381Slinton 
4989676Slinton /*
4999676Slinton  * Print out the value on top of the stack according to the given type.
5009676Slinton  */
5019676Slinton 
5029676Slinton public printval(t)
5039676Slinton Symbol t;
5049676Slinton {
5059676Slinton     Symbol s;
5069676Slinton 
5079676Slinton     checkref(t);
50816616Ssam     if (t->class == TYPEREF) {
50916616Ssam 	resolveRef(t);
51016616Ssam     }
5119676Slinton     switch (t->class) {
5129676Slinton 	case PROC:
5139676Slinton 	case FUNC:
5149676Slinton 	    s = pop(Symbol);
5159676Slinton 	    printf("%s", symname(s));
5169676Slinton 	    break;
5179676Slinton 
5189676Slinton 	default:
51918229Slinton 	    if (t->language == nil or t->language == primlang) {
52026478Ssam 		(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
5219676Slinton 	    } else {
5229676Slinton 		(*language_op(t->language, L_PRINTVAL))(t);
5239676Slinton 	    }
5249676Slinton 	    break;
5259676Slinton     }
5269676Slinton }
5279676Slinton 
5289676Slinton /*
5299676Slinton  * Print out the value of a record, field by field.
5309676Slinton  */
5319676Slinton 
5329676Slinton public printrecord(s)
5339676Slinton Symbol s;
5349676Slinton {
53516616Ssam     Symbol f;
53616616Ssam 
5379676Slinton     if (s->chain == nil) {
5389676Slinton 	error("record has no fields");
5399676Slinton     }
5409676Slinton     printf("(");
5419676Slinton     sp -= size(s);
54216616Ssam     f = s->chain;
54316616Ssam     if (f != nil) {
54416616Ssam 	for (;;) {
54516616Ssam 	    printfield(f);
54616616Ssam 	    f = f->chain;
54716616Ssam 	if (f == nil) break;
54816616Ssam 	    printf(", ");
54916616Ssam 	}
55016616Ssam     }
5519676Slinton     printf(")");
5529676Slinton }
5539676Slinton 
5549676Slinton /*
55516616Ssam  * Print out a field.
5569676Slinton  */
5579676Slinton 
55816616Ssam private printfield(f)
55916616Ssam Symbol f;
5609676Slinton {
5619676Slinton     Stack *savesp;
56216616Ssam     register int off, len;
5639676Slinton 
56416616Ssam     printf("%s = ", symname(f));
5659676Slinton     savesp = sp;
56616616Ssam     off = f->symvalue.field.offset;
56716616Ssam     len = f->symvalue.field.length;
56816616Ssam     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
56916616Ssam     printval(f);
5709676Slinton     sp = savesp;
5719676Slinton }
5729676Slinton 
5739676Slinton /*
5749676Slinton  * Print out the contents of an array.
5759676Slinton  * Haven't quite figured out what the best format is.
5769676Slinton  *
5779676Slinton  * This is rather inefficient.
5789676Slinton  *
5799676Slinton  * The "2*elsize" is there since "printval" drops the stack by elsize.
5809676Slinton  */
5819676Slinton 
5829676Slinton public printarray(a)
5839676Slinton Symbol a;
5849676Slinton {
5859676Slinton     Stack *savesp, *newsp;
5869676Slinton     Symbol eltype;
5879676Slinton     long elsize;
5889676Slinton     String sep;
5899676Slinton 
5909676Slinton     savesp = sp;
59112544Scsvaf     sp -= (size(a));
5929676Slinton     newsp = sp;
5939676Slinton     eltype = rtype(a->type);
5949676Slinton     elsize = size(eltype);
5959676Slinton     printf("(");
5969676Slinton     if (eltype->class == RECORD or eltype->class == ARRAY or
5979676Slinton       eltype->class == VARNT) {
5989676Slinton 	sep = "\n";
5999676Slinton 	putchar('\n');
6009676Slinton     } else {
6019676Slinton 	sep = ", ";
6029676Slinton     }
6039676Slinton     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
6049676Slinton 	if (sp - elsize != newsp) {
6059676Slinton 	    fputs(sep, stdout);
6069676Slinton 	}
6079676Slinton 	printval(eltype);
6089676Slinton     }
6099676Slinton     sp = newsp;
6109676Slinton     if (streq(sep, "\n")) {
6119676Slinton 	putchar('\n');
6129676Slinton     }
6139676Slinton     printf(")");
6149676Slinton }
6159676Slinton 
6169676Slinton /*
6179676Slinton  * Print out the value of a real number in Pascal notation.
6189676Slinton  * This is, unfortunately, different than what one gets
6199676Slinton  * from "%g" in printf.
6209676Slinton  */
6219676Slinton 
6229676Slinton public prtreal(r)
6239676Slinton double r;
6249676Slinton {
6259676Slinton     extern char *index();
6269676Slinton     char buf[256];
6279676Slinton 
6289676Slinton     sprintf(buf, "%g", r);
6299676Slinton     if (buf[0] == '.') {
6309676Slinton 	printf("0%s", buf);
6319676Slinton     } else if (buf[0] == '-' and buf[1] == '.') {
6329676Slinton 	printf("-0%s", &buf[1]);
6339676Slinton     } else {
6349676Slinton 	printf("%s", buf);
6359676Slinton     }
6369676Slinton     if (index(buf, '.') == nil) {
6379676Slinton 	printf(".0");
6389676Slinton     }
6399676Slinton }
6409676Slinton 
6419676Slinton /*
6429676Slinton  * Print out a character using ^? notation for unprintables.
6439676Slinton  */
6449676Slinton 
6459676Slinton public printchar(c)
6469676Slinton char c;
6479676Slinton {
6489676Slinton     if (c == 0) {
6499676Slinton 	putchar('\\');
6509676Slinton 	putchar('0');
6519676Slinton     } else if (c == '\n') {
6529676Slinton 	putchar('\\');
6539676Slinton 	putchar('n');
6549676Slinton     } else if (c > 0 and c < ' ') {
6559676Slinton 	putchar('^');
6569676Slinton 	putchar(c - 1 + 'A');
65716616Ssam     } else if (c >= ' ' && c <= '~') {
65816616Ssam 	putchar(c);
6599676Slinton     } else {
660*29820Ssam 	printf("\\0%o",c&0xff);
6619676Slinton     }
6629676Slinton }
66318229Slinton 
66418229Slinton /*
66518229Slinton  * Print out a value for a range type (integer, char, or boolean).
66618229Slinton  */
66718229Slinton 
66818229Slinton public printRangeVal (val, t)
66918229Slinton long val;
67018229Slinton Symbol t;
67118229Slinton {
67218229Slinton     if (t == t_boolean->type or istypename(t->type, "boolean")) {
67318229Slinton 	if ((boolean) val) {
67418229Slinton 	    printf("true");
67518229Slinton 	} else {
67618229Slinton 	    printf("false");
67718229Slinton 	}
67818229Slinton     } else if (t == t_char->type or istypename(t->type, "char")) {
67918229Slinton 	if (varIsSet("$hexchars")) {
68018229Slinton 	    printf("0x%lx", val);
68118229Slinton 	} else {
68218229Slinton 	    putchar('\'');
68318229Slinton 	    printchar(val);
68418229Slinton 	    putchar('\'');
68518229Slinton 	}
68618229Slinton     } else if (varIsSet("$hexints")) {
68718229Slinton 	printf("0x%lx", val);
68818229Slinton     } else if (t->symvalue.rangev.lower >= 0) {
68918229Slinton 	printf("%lu", val);
69018229Slinton     } else {
69118229Slinton 	printf("%ld", val);
69218229Slinton     }
69318229Slinton }
69418229Slinton 
69518229Slinton /*
69618229Slinton  * Print out an enumerated value by finding the corresponding
69718229Slinton  * name in the enumeration list.
69818229Slinton  */
69918229Slinton 
70018229Slinton public printEnum (i, t)
70118229Slinton integer i;
70218229Slinton Symbol t;
70318229Slinton {
70418229Slinton     register Symbol e;
70518229Slinton 
70618229Slinton     e = t->chain;
70718229Slinton     while (e != nil and e->symvalue.constval->value.lcon != i) {
70818229Slinton 	e = e->chain;
70918229Slinton     }
71018229Slinton     if (e != nil) {
71118229Slinton 	printf("%s", symname(e));
71218229Slinton     } else {
71318229Slinton 	printf("%d", i);
71418229Slinton     }
71518229Slinton }
71618229Slinton 
71718229Slinton /*
71818229Slinton  * Print out a null-terminated string (pointer to char)
71918229Slinton  * starting at the given address.
72018229Slinton  */
72118229Slinton 
72218229Slinton public printString (addr, quotes)
72318229Slinton Address addr;
72418229Slinton boolean quotes;
72518229Slinton {
72618229Slinton     register Address a;
72718229Slinton     register integer i, len;
72818229Slinton     register boolean endofstring;
729*29820Ssam     register int unprintables;
730*29820Ssam #define	MAXGARBAGE	4
73118229Slinton     union {
73218229Slinton 	char ch[sizeof(Word)];
73318229Slinton 	int word;
73418229Slinton     } u;
73518229Slinton 
73618229Slinton     if (varIsSet("$hexstrings")) {
73718229Slinton 	printf("0x%x", addr);
73818229Slinton     } else {
73918229Slinton 	if (quotes) {
74018229Slinton 	    putchar('"');
74118229Slinton 	}
74218229Slinton 	a = addr;
743*29820Ssam 	unprintables = 0;
74418229Slinton 	endofstring = false;
74518229Slinton 	while (not endofstring) {
74618229Slinton 	    dread(&u, a, sizeof(u));
74718229Slinton 	    i = 0;
74818229Slinton 	    do {
74918229Slinton 		if (u.ch[i] == '\0') {
75018229Slinton 		    endofstring = true;
75118229Slinton 		} else {
75218229Slinton 		    printchar(u.ch[i]);
753*29820Ssam 		    if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
754*29820Ssam 			endofstring = true;
755*29820Ssam 			printf("...");
756*29820Ssam 		    }
75718229Slinton 		}
75818229Slinton 		++i;
75918229Slinton 	    } while (i < sizeof(Word) and not endofstring);
76018229Slinton 	    a += sizeof(Word);
76118229Slinton 	}
76218229Slinton 	if (quotes) {
76318229Slinton 	    putchar('"');
76418229Slinton 	}
76518229Slinton     }
76618229Slinton }
767