1 /*
2 * Copyright (c) 2003
3 * David Leonard. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of David Leonard nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #if HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #if STDC_HEADERS
36 # include <stdio.h>
37 #endif
38
39 #include <see/try.h>
40 #include <see/value.h>
41 #include <see/object.h>
42 #include <see/string.h>
43 #include <see/debug.h>
44 #include <see/interpreter.h>
45 #include "function.h"
46
47 static void print_traceback(struct SEE_interpreter *interp,
48 struct SEE_traceback *traceback, FILE *f);
49
50 /*
51 * Print the contents of a value, without raising an exception
52 */
53 void
SEE_PrintValue(interp,v,f)54 SEE_PrintValue(interp, v, f)
55 struct SEE_interpreter *interp;
56 const struct SEE_value *v;
57 FILE *f;
58 {
59 if (!f) f=stderr;
60 if (v == NULL) {
61 fprintf(f, "NULL");
62 return;
63 }
64 switch (SEE_VALUE_GET_TYPE(v)) {
65 case SEE_UNDEFINED:
66 fprintf(f, "undefined");
67 break;
68 case SEE_NULL:
69 fprintf(f, "null");
70 break;
71 case SEE_BOOLEAN:
72 fprintf(f, v->u.boolean ? "true" : "false");
73 break;
74 case SEE_NUMBER:
75 fprintf(f, "%.30g", v->u.number);
76 break;
77 case SEE_STRING:
78 SEE_PrintString(interp, v->u.string, f);
79 break;
80 case SEE_OBJECT:
81 SEE_PrintObject(interp, v->u.object, f);
82 break;
83 case SEE_REFERENCE:
84 fprintf(f, "<ref base=<object %p> prop=",
85 (void *)v->u.reference.base);
86 SEE_string_fputs(v->u.reference.property, f);
87 fprintf(f, ">");
88 break;
89 case SEE_COMPLETION:
90 switch (v->u.completion.type) {
91 case SEE_COMPLETION_NORMAL:
92 fprintf(f, "<normal");
93 if (v->u.completion.value) {
94 fprintf(f, " ");
95 SEE_PrintValue(interp, v->u.completion.value, f);
96 }
97 fprintf(f, ">");
98 break;
99 case SEE_COMPLETION_BREAK:
100 fprintf(f, "<break %u>", v->u.completion.target);
101 break;
102 case SEE_COMPLETION_CONTINUE:
103 fprintf(f, "<continue %u>", v->u.completion.target);
104 break;
105 case SEE_COMPLETION_RETURN:
106 fprintf(f, "<return ");
107 SEE_PrintValue(interp, v->u.completion.value, f);
108 fprintf(f, ">");
109 break;
110 case SEE_COMPLETION_THROW:
111 fprintf(f, "<throw ");
112 SEE_PrintValue(interp, v->u.completion.value, f);
113 fprintf(f, ">");
114 break;
115 default:
116 fprintf(f, "<BAD completion %d>", v->u.completion.type);
117 }
118 break;
119 default:
120 fprintf(f, "<BAD value %d>", SEE_VALUE_GET_TYPE(v));
121 }
122 }
123
124 /*
125 * Print an object without raising an exception.
126 * The object's class is shown in quotes.
127 * If the object is known to the interpreter (eg Object, Array.prototype, etc.)
128 * then its original name is shown in parentheses.
129 */
130 void
SEE_PrintObject(interp,o,f)131 SEE_PrintObject(interp, o, f)
132 struct SEE_interpreter *interp;
133 const struct SEE_object *o;
134 FILE *f;
135 {
136 const char *known;
137
138 if (!f) f=stderr;
139 if (o == NULL) known = "NULL";
140 else if (interp == NULL) known = NULL;
141 else if (o == interp->Global) known = "Global";
142 else if (o == interp->Object) known = "Object";
143 else if (o == interp->Object_prototype) known = "Object.prototype";
144 else if (o == interp->Error) known = "Error";
145 else if (o == interp->EvalError) known = "EvalError";
146 else if (o == interp->RangeError) known = "RangeError";
147 else if (o == interp->ReferenceError) known = "ReferenceError";
148 else if (o == interp->SyntaxError) known = "SyntaxError";
149 else if (o == interp->TypeError) known = "TypeError";
150 else if (o == interp->URIError) known = "URIError";
151 else if (o == interp->String) known = "String";
152 else if (o == interp->String_prototype) known = "String.prototype";
153 else if (o == interp->Function) known = "Function";
154 else if (o == interp->Function_prototype)known = "Function.prototype";
155 else if (o == interp->Array) known = "Array";
156 else if (o == interp->Array_prototype) known = "Array.prototype";
157 else if (o == interp->Number) known = "Number";
158 else if (o == interp->Number_prototype) known = "Number.prototype";
159 else if (o == interp->Boolean) known = "Boolean";
160 else if (o == interp->Boolean_prototype)known = "Boolean.prototype";
161 else if (o == interp->Math) known = "Math";
162 else if (o == interp->RegExp) known = "RegExp";
163 else if (o == interp->RegExp_prototype) known = "RegExp.prototype";
164 else if (o == interp->Date) known = "Date";
165 else if (o == interp->Date_prototype) known = "Date.prototype";
166 else known = NULL;
167
168 fprintf(f, "<object %p", (void *)o);
169 if (known)
170 fprintf(f, " (%s)", known);
171 if (o && o->objectclass && !known) {
172 fprintf(f, " \"%s\"", o->objectclass->Class);
173 }
174 if (o->host_data)
175 fprintf(f, " %p", o->host_data);
176 fprintf(f, ">");
177 }
178
179 /*
180 * Print a string, in 'literal' form to the given stdio file.
181 */
182 void
SEE_PrintString(interp,s,f)183 SEE_PrintString(interp, s, f)
184 struct SEE_interpreter *interp;
185 const struct SEE_string *s;
186 FILE *f;
187 {
188 unsigned int i;
189
190 if (!f) f=stderr;
191 if (s == NULL)
192 fprintf(f, "<NULL>");
193 else {
194 /* NB Replicates most of SEE_string_literal(). */
195 fprintf(f, "\"");
196 for (i = 0; i < s->length; i++) {
197 SEE_char_t c = s->data[i];
198 if (c == '\\') fprintf(f, "\\\\");
199 else if (c == '\"') fprintf(f, "\\\"");
200 else if (c == '\n') fprintf(f, "\\n");
201 else if (c == '\t') fprintf(f, "\\t");
202 else if (c >= ' ' && c <= '~')
203 fputc(c & 0x7f, f);
204 else if (c < 0x100)
205 fprintf(f, "\\x%02x", c);
206 else
207 fprintf(f, "\\u%04x", c);
208 if (i < s->length && i >= 1024) {
209 fprintf(f, "\\(...len=%u)", s->length);
210 break;
211 }
212 }
213 fprintf(f, "\"<%s%p>",
214 s->flags & SEE_STRING_FLAG_INTERNED ? "i" : "",
215 (void *)s);
216 }
217 }
218
219 static void
print_traceback(interp,traceback,f)220 print_traceback(interp, traceback, f)
221 struct SEE_interpreter *interp;
222 struct SEE_traceback *traceback;
223 FILE *f;
224 {
225 struct SEE_traceback *tb;
226 struct SEE_string *locstr, *fname;
227 struct SEE_object *fo;
228
229 if (!f) f=stderr;
230 if (!traceback)
231 return;
232 fprintf(f, "traceback:\n");
233 for (tb = traceback; tb; tb = tb->prev) {
234 locstr = SEE_location_string(interp, tb->call_location);
235 fprintf(f, "\t");
236 SEE_string_fputs(locstr, f);
237 fo = tb->callee;
238 if (tb->call_type == SEE_CALLTYPE_THROW)
239 fprintf(f, "<throw>");
240 else if (fo == NULL)
241 fprintf(f, "?");
242 else if (tb->call_type == SEE_CALLTYPE_CONSTRUCT)
243 fprintf(f, "new %s", fo->objectclass->Class
244 ? fo->objectclass->Class
245 : "?");
246 else if (tb->call_type == SEE_CALLTYPE_CALL) {
247 fprintf(f, "call ");
248 /* XXX is fo == interp->Global_eval case handled OK? */
249 fname = SEE_function_getname(interp, fo);
250 if (fname) {
251 SEE_string_fputs(fname, f);
252 fprintf(f, "()");
253 } else
254 fprintf(f, "<anonymous function>");
255 } else
256 SEE_PrintObject(interp, fo, f);
257 fprintf(f, "\n");
258 }
259 }
260
261 void
SEE_PrintTraceback(interp,f)262 SEE_PrintTraceback(interp, f)
263 struct SEE_interpreter *interp;
264 FILE *f;
265 {
266 print_traceback(interp, interp->traceback, f);
267 }
268
269 void
SEE_PrintContextTraceback(interp,ctxt,f)270 SEE_PrintContextTraceback(interp, ctxt, f)
271 struct SEE_interpreter *interp;
272 volatile struct SEE_try_context *ctxt;
273 FILE *f;
274 {
275 print_traceback(interp, ctxt->traceback, f);
276 }
277