1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)printval.c	5.1 (Berkeley) 06/06/85";
9 #endif not lint
10 
11 /*
12  * Print out the value at the top of the stack using the given type.
13  */
14 
15 #include "defs.h"
16 #include "sym.h"
17 #include "btypes.h"
18 #include "classes.h"
19 #include "tree.h"
20 #include "process.h"
21 #include "mappings.h"
22 #include "sym.rep"
23 
24 printval(s)
25 SYM *s;
26 {
27     SYM *t;
28     ADDRESS a;
29     int len;
30     double r;
31 
32     if (s->class == REF) {
33 	s = s->type;
34     }
35     switch (s->class) {
36 	case ARRAY:
37 	    t = rtype(s->type);
38 	    if (t == t_char || (t->class == RANGE && t->type == t_char)) {
39 		len = size(s);
40 		sp -= len;
41 		printf("'%.*s'", len, sp);
42 		break;
43 	    } else {
44 		printarray(s);
45 	    }
46 	    break;
47 
48 	case RECORD:
49 	    printrecord(s);
50 	    break;
51 
52 	case VARNT:
53 	    error("can't print out variant records");
54 	    break;
55 
56 	case RANGE:
57 	    if (s == t_real) {
58 		prtreal(pop(double));
59 	    } else {
60 		printordinal(popsmall(s), rtype(s->type));
61 	    }
62 	    break;
63 
64 	case FILET:
65 	case PTR:
66 	    a = pop(ADDRESS);
67 	    if (a == 0) {
68 		printf("nil");
69 	    } else {
70 		printf("0%o", a);
71 	    }
72 	    break;
73 
74 	case FIELD:
75 	    error("missing record specification");
76 	    break;
77 
78 	case SCAL:
79 	    printordinal(popsmall(s), s);
80 	    break;
81 
82 	case FPROC:
83 	case FFUNC:
84 	    a = fparamaddr(pop(long));
85 	    t = whatblock(a);
86 	    if (t == NIL) {
87 		printf("(proc %d)", a);
88 	    } else {
89 		printf("%s", t->symbol);
90 	    }
91 	    break;
92 
93 	default:
94 	    if (s->class < BADUSE || s->class > VARNT) {
95 		panic("printval: bad class %d", s->class);
96 	    }
97 	    error("don't know how to print a %s", classname(s));
98 	    /* NOTREACHED */
99     }
100 }
101 
102 /*
103  * Print out an ordinal value (either an integer, character, or
104  * an enumeration constant).
105  */
106 
107 printordinal(v, t)
108 long v;
109 SYM *t;
110 {
111     BOOLEAN found;
112     SYM *c;
113     int iv;
114 
115     iv = v;
116     if (t->class == SCAL) {
117 	c = t->chain;
118 	while (c != NIL && c->symvalue.iconval != iv) {
119 	    c = c->chain;
120 	}
121 	if (c == NIL) {
122 	    printf("(scalar = %d)", iv);
123 	} else {
124 	    printf("%s", c->symbol);
125 	}
126     } else if (t == t_char) {
127 	printf("'%c'", iv);
128     } else if (t == t_boolean) {
129 	printf("%s", (iv == TRUE) ? "true" : "false");
130     } else {
131 	printf("%ld", v);
132     }
133 }
134 
135 /*
136  * Print out the value of a record, field by field.
137  */
138 
139 LOCAL printrecord(s)
140 SYM *s;
141 {
142     SYM *t;
143 
144     if ((t = s->chain) == NIL) {
145 	error("record has no fields");
146     }
147     printf("(");
148     sp -= size(s);
149     printfield(t);
150     printf(")");
151 }
152 
153 /*
154  * Print out a field, first printing out other fields.
155  * This is done because the fields are chained together backwards.
156  */
157 
158 LOCAL printfield(s)
159 SYM *s;
160 {
161     STACK *savesp;
162 
163     if (s->chain != NIL) {
164 	printfield(s->chain);
165 	printf(", ");
166     }
167     printf("%s = ", s->symbol);
168     savesp = sp;
169     sp += (s->symvalue.offset + size(s->type));
170     printval(s->type);
171     sp = savesp;
172 }
173 
174 /*
175  * Print out the contents of an array.
176  * Haven't quite figured out what the best format is.
177  *
178  * This is rather inefficient.
179  *
180  * The "2*elsize" is there since "printval" drops the stack by elsize.
181  */
182 
183 LOCAL printarray(a)
184 SYM *a;
185 {
186     STACK *savesp, *newsp;
187     SYM *eltype;
188     long elsize;
189 
190     savesp = sp;
191     sp -= size(a);
192     newsp = sp;
193     eltype = a->type;
194     elsize = size(eltype);
195     printf("(");
196     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
197 	if (sp - elsize != newsp) {
198 	    printf(", ");
199 	}
200 	printval(eltype);
201     }
202     sp = newsp;
203     printf(")");
204 }
205 
206 /*
207  * Print out the value of a real number.
208  * Pascal notation is somewhat different that what one gets
209  * from "%g" in printf.
210  */
211 
212 LOCAL prtreal(r)
213 double r;
214 {
215     extern char *index();
216     char *p, buf[256];
217 
218     sprintf(buf, "%g", r);
219     if (buf[0] == '.') {
220 	printf("0%s", buf);
221     } else if (buf[0] == '-' && buf[1] == '.') {
222 	printf("-0%s", &buf[1]);
223     } else {
224 	printf("%s", buf);
225     }
226     if (index(buf, '.') == NIL) {
227 	printf(".0");
228     }
229 }
230