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