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