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