]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/mujs/jsdump.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / mujs / jsdump.c
1 #include "jsi.h"
2 #include "jsparse.h"
3 #include "jscompile.h"
4 #include "jsvalue.h"
5
6 #include "utf.h"
7
8 #include <assert.h>
9
10 static const char *astname[] = {
11 #include "astnames.h"
12 };
13
14 static const char *opname[] = {
15 #include "opnames.h"
16 };
17
18 const char *jsP_aststring(enum js_AstType type)
19 {
20         if (type < nelem(astname))
21                 return astname[type];
22         return "<unknown>";
23 }
24
25 const char *jsC_opcodestring(enum js_OpCode opcode)
26 {
27         if (opcode < nelem(opname))
28                 return opname[opcode];
29         return "<unknown>";
30 }
31
32 static int prec(enum js_AstType type)
33 {
34         switch (type) {
35         case EXP_IDENTIFIER:
36         case EXP_NUMBER:
37         case EXP_STRING:
38         case EXP_REGEXP:
39         case EXP_UNDEF:
40         case EXP_NULL:
41         case EXP_TRUE:
42         case EXP_FALSE:
43         case EXP_THIS:
44         case EXP_ARRAY:
45         case EXP_OBJECT:
46                 return 170;
47
48         case EXP_FUN:
49         case EXP_INDEX:
50         case EXP_MEMBER:
51         case EXP_CALL:
52         case EXP_NEW:
53                 return 160;
54
55         case EXP_POSTINC:
56         case EXP_POSTDEC:
57                 return 150;
58
59         case EXP_DELETE:
60         case EXP_VOID:
61         case EXP_TYPEOF:
62         case EXP_PREINC:
63         case EXP_PREDEC:
64         case EXP_POS:
65         case EXP_NEG:
66         case EXP_BITNOT:
67         case EXP_LOGNOT:
68                 return 140;
69
70         case EXP_MOD:
71         case EXP_DIV:
72         case EXP_MUL:
73                 return 130;
74
75         case EXP_SUB:
76         case EXP_ADD:
77                 return 120;
78
79         case EXP_USHR:
80         case EXP_SHR:
81         case EXP_SHL:
82                 return 110;
83
84         case EXP_IN:
85         case EXP_INSTANCEOF:
86         case EXP_GE:
87         case EXP_LE:
88         case EXP_GT:
89         case EXP_LT:
90                 return 100;
91
92         case EXP_STRICTNE:
93         case EXP_STRICTEQ:
94         case EXP_NE:
95         case EXP_EQ:
96                 return 90;
97
98         case EXP_BITAND: return 80;
99         case EXP_BITXOR: return 70;
100         case EXP_BITOR: return 60;
101         case EXP_LOGAND: return 50;
102         case EXP_LOGOR: return 40;
103
104         case EXP_COND:
105                 return 30;
106
107         case EXP_ASS:
108         case EXP_ASS_MUL:
109         case EXP_ASS_DIV:
110         case EXP_ASS_MOD:
111         case EXP_ASS_ADD:
112         case EXP_ASS_SUB:
113         case EXP_ASS_SHL:
114         case EXP_ASS_SHR:
115         case EXP_ASS_USHR:
116         case EXP_ASS_BITAND:
117         case EXP_ASS_BITXOR:
118         case EXP_ASS_BITOR:
119                 return 20;
120
121 #define COMMA 15
122
123         case EXP_COMMA:
124                 return 10;
125
126         default:
127                 return 0;
128         }
129 }
130
131 static void pc(int c)
132 {
133         putchar(c);
134 }
135
136 static void ps(const char *s)
137 {
138         fputs(s, stdout);
139 }
140
141 static void in(int d)
142 {
143         while (d-- > 0)
144                 putchar('\t');
145 }
146
147 static void nl(void)
148 {
149         putchar('\n');
150 }
151
152 /* Pretty-printed Javascript syntax */
153
154 static void pstmlist(int d, js_Ast *list);
155 static void pexpi(int d, int i, js_Ast *exp);
156 static void pstm(int d, js_Ast *stm);
157 static void slist(int d, js_Ast *list);
158 static void sblock(int d, js_Ast *list);
159
160 static void pargs(int d, js_Ast *list)
161 {
162         while (list) {
163                 assert(list->type == AST_LIST);
164                 pexpi(d, COMMA, list->a);
165                 list = list->b;
166                 if (list)
167                         ps(", ");
168         }
169 }
170
171 static void parray(int d, js_Ast *list)
172 {
173         ps("[");
174         while (list) {
175                 assert(list->type == AST_LIST);
176                 pexpi(d, COMMA, list->a);
177                 list = list->b;
178                 if (list)
179                         ps(", ");
180         }
181         ps("]");
182 }
183
184 static void pobject(int d, js_Ast *list)
185 {
186         ps("{");
187         while (list) {
188                 js_Ast *kv = list->a;
189                 assert(list->type == AST_LIST);
190                 switch (kv->type) {
191                 case EXP_PROP_VAL:
192                         pexpi(d, COMMA, kv->a);
193                         ps(": ");
194                         pexpi(d, COMMA, kv->b);
195                         break;
196                 case EXP_PROP_GET:
197                         ps("get ");
198                         pexpi(d, COMMA, kv->a);
199                         ps("() {\n");
200                         pstmlist(d, kv->c);
201                         in(d); ps("}");
202                         break;
203                 case EXP_PROP_SET:
204                         ps("set ");
205                         pexpi(d, COMMA, kv->a);
206                         ps("(");
207                         pargs(d, kv->b);
208                         ps(") {\n");
209                         pstmlist(d, kv->c);
210                         in(d); ps("}");
211                         break;
212                 }
213                 list = list->b;
214                 if (list)
215                         ps(", ");
216         }
217         ps("}");
218 }
219
220 static void pstr(const char *s)
221 {
222         static const char *HEX = "0123456789ABCDEF";
223         Rune c;
224         pc('"');
225         while (*s) {
226                 s += chartorune(&c, s);
227                 switch (c) {
228                 case '"': ps("\\\""); break;
229                 case '\\': ps("\\\\"); break;
230                 case '\b': ps("\\b"); break;
231                 case '\f': ps("\\f"); break;
232                 case '\n': ps("\\n"); break;
233                 case '\r': ps("\\r"); break;
234                 case '\t': ps("\\t"); break;
235                 default:
236                         if (c < ' ' || c > 127) {
237                                 ps("\\u");
238                                 pc(HEX[(c>>12)&15]);
239                                 pc(HEX[(c>>8)&15]);
240                                 pc(HEX[(c>>4)&15]);
241                                 pc(HEX[c&15]);
242                         } else {
243                                 pc(c); break;
244                         }
245                 }
246         }
247         pc('"');
248 }
249
250 static void pregexp(const char *prog, int flags)
251 {
252         pc('/');
253         ps(prog);
254         pc('/');
255         if (flags & JS_REGEXP_G) pc('g');
256         if (flags & JS_REGEXP_I) pc('i');
257         if (flags & JS_REGEXP_M) pc('m');
258 }
259
260 static void pbin(int d, int p, js_Ast *exp, const char *op)
261 {
262         pexpi(d, p, exp->a);
263         ps(op);
264         pexpi(d, p, exp->b);
265 }
266
267 static void puna(int d, int p, js_Ast *exp, const char *pre, const char *suf)
268 {
269         ps(pre);
270         pexpi(d, p, exp->a);
271         ps(suf);
272 }
273
274 static void pexpi(int d, int p, js_Ast *exp)
275 {
276         int tp = prec(exp->type);
277         int paren = 0;
278         if (tp < p) {
279                 pc('(');
280                 paren = 1;
281         }
282         p = tp;
283
284         switch (exp->type) {
285         case AST_IDENTIFIER: ps(exp->string); break;
286         case EXP_IDENTIFIER: ps(exp->string); break;
287         case EXP_NUMBER: printf("%.9g", exp->number); break;
288         case EXP_STRING: pstr(exp->string); break;
289         case EXP_REGEXP: pregexp(exp->string, exp->number); break;
290
291         case EXP_UNDEF: break;
292         case EXP_NULL: ps("null"); break;
293         case EXP_TRUE: ps("true"); break;
294         case EXP_FALSE: ps("false"); break;
295         case EXP_THIS: ps("this"); break;
296
297         case EXP_OBJECT: pobject(d, exp->a); break;
298         case EXP_ARRAY: parray(d, exp->a); break;
299
300         case EXP_DELETE: puna(d, p, exp, "delete ", ""); break;
301         case EXP_VOID: puna(d, p, exp, "void ", ""); break;
302         case EXP_TYPEOF: puna(d, p, exp, "typeof ", ""); break;
303         case EXP_PREINC: puna(d, p, exp, "++", ""); break;
304         case EXP_PREDEC: puna(d, p, exp, "--", ""); break;
305         case EXP_POSTINC: puna(d, p, exp, "", "++"); break;
306         case EXP_POSTDEC: puna(d, p, exp, "", "--"); break;
307         case EXP_POS: puna(d, p, exp, "+", ""); break;
308         case EXP_NEG: puna(d, p, exp, "-", ""); break;
309         case EXP_BITNOT: puna(d, p, exp, "~", ""); break;
310         case EXP_LOGNOT: puna(d, p, exp, "!", ""); break;
311
312         case EXP_LOGOR: pbin(d, p, exp, " || "); break;
313         case EXP_LOGAND: pbin(d, p, exp, " && "); break;
314         case EXP_BITOR: pbin(d, p, exp, " | "); break;
315         case EXP_BITXOR: pbin(d, p, exp, " ^ "); break;
316         case EXP_BITAND: pbin(d, p, exp, " & "); break;
317         case EXP_EQ: pbin(d, p, exp, " == "); break;
318         case EXP_NE: pbin(d, p, exp, " != "); break;
319         case EXP_STRICTEQ: pbin(d, p, exp, " === "); break;
320         case EXP_STRICTNE: pbin(d, p, exp, " !== "); break;
321         case EXP_LT: pbin(d, p, exp, " < "); break;
322         case EXP_GT: pbin(d, p, exp, " > "); break;
323         case EXP_LE: pbin(d, p, exp, " <= "); break;
324         case EXP_GE: pbin(d, p, exp, " >= "); break;
325         case EXP_INSTANCEOF: pbin(d, p, exp, " instanceof "); break;
326         case EXP_IN: pbin(d, p, exp, " in "); break;
327         case EXP_SHL: pbin(d, p, exp, " << "); break;
328         case EXP_SHR: pbin(d, p, exp, " >> "); break;
329         case EXP_USHR: pbin(d, p, exp, " >>> "); break;
330         case EXP_ADD: pbin(d, p, exp, " + "); break;
331         case EXP_SUB: pbin(d, p, exp, " - "); break;
332         case EXP_MUL: pbin(d, p, exp, " * "); break;
333         case EXP_DIV: pbin(d, p, exp, " / "); break;
334         case EXP_MOD: pbin(d, p, exp, " % "); break;
335         case EXP_ASS: pbin(d, p, exp, " = "); break;
336         case EXP_ASS_MUL: pbin(d, p, exp, " *= "); break;
337         case EXP_ASS_DIV: pbin(d, p, exp, " /= "); break;
338         case EXP_ASS_MOD: pbin(d, p, exp, " %= "); break;
339         case EXP_ASS_ADD: pbin(d, p, exp, " += "); break;
340         case EXP_ASS_SUB: pbin(d, p, exp, " -= "); break;
341         case EXP_ASS_SHL: pbin(d, p, exp, " <<= "); break;
342         case EXP_ASS_SHR: pbin(d, p, exp, " >>= "); break;
343         case EXP_ASS_USHR: pbin(d, p, exp, " >>>= "); break;
344         case EXP_ASS_BITAND: pbin(d, p, exp, " &= "); break;
345         case EXP_ASS_BITXOR: pbin(d, p, exp, " ^= "); break;
346         case EXP_ASS_BITOR: pbin(d, p, exp, " |= "); break;
347
348         case EXP_COMMA: pbin(d, p, exp, ", "); break;
349
350         case EXP_COND:
351                 pexpi(d, p, exp->a);
352                 ps(" ? ");
353                 pexpi(d, p, exp->b);
354                 ps(" : ");
355                 pexpi(d, p, exp->c);
356                 break;
357
358         case EXP_INDEX:
359                 pexpi(d, p, exp->a);
360                 pc('[');
361                 pexpi(d, 0, exp->b);
362                 pc(']');
363                 break;
364
365         case EXP_MEMBER:
366                 pexpi(d, p, exp->a);
367                 pc('.');
368                 pexpi(d, 0, exp->b);
369                 break;
370
371         case EXP_CALL:
372                 pexpi(d, p, exp->a);
373                 pc('(');
374                 pargs(d, exp->b);
375                 pc(')');
376                 break;
377
378         case EXP_NEW:
379                 ps("new ");
380                 pexpi(d, p, exp->a);
381                 pc('(');
382                 pargs(d, exp->b);
383                 pc(')');
384                 break;
385
386         case EXP_FUN:
387                 if (p == 0) pc('(');
388                 ps("function ");
389                 if (exp->a) pexpi(d, 0, exp->a);
390                 pc('(');
391                 pargs(d, exp->b);
392                 ps(") {\n");
393                 pstmlist(d, exp->c);
394                 in(d); pc('}');
395                 if (p == 0) pc(')');
396                 break;
397
398         default:
399                 ps("<UNKNOWN>");
400                 break;
401         }
402
403         if (paren) pc(')');
404 }
405
406 static void pexp(int d, js_Ast *exp)
407 {
408         pexpi(d, 0, exp);
409 }
410
411 static void pvar(int d, js_Ast *var)
412 {
413         assert(var->type == EXP_VAR);
414         pexp(d, var->a);
415         if (var->b) {
416                 ps(" = ");
417                 pexp(d, var->b);
418         }
419 }
420
421 static void pvarlist(int d, js_Ast *list)
422 {
423         while (list) {
424                 assert(list->type == AST_LIST);
425                 pvar(d, list->a);
426                 list = list->b;
427                 if (list)
428                         ps(", ");
429         }
430 }
431
432 static void pblock(int d, js_Ast *block)
433 {
434         assert(block->type == STM_BLOCK);
435         ps(" {\n");
436         pstmlist(d, block->a);
437         in(d); pc('}');
438 }
439
440 static void pstmh(int d, js_Ast *stm)
441 {
442         if (stm->type == STM_BLOCK)
443                 pblock(d, stm);
444         else {
445                 nl();
446                 pstm(d+1, stm);
447         }
448 }
449
450 static void pcaselist(int d, js_Ast *list)
451 {
452         while (list) {
453                 js_Ast *stm = list->a;
454                 if (stm->type == STM_CASE) {
455                         in(d); ps("case "); pexp(d, stm->a); ps(":\n");
456                         pstmlist(d, stm->b);
457                 }
458                 if (stm->type == STM_DEFAULT) {
459                         in(d); ps("default:\n");
460                         pstmlist(d, stm->a);
461                 }
462                 list = list->b;
463         }
464 }
465
466 static void pstm(int d, js_Ast *stm)
467 {
468         if (stm->type == STM_BLOCK) {
469                 pblock(d, stm);
470                 return;
471         }
472
473         in(d);
474
475         switch (stm->type) {
476         case AST_FUNDEC:
477                 ps("function ");
478                 pexp(d, stm->a);
479                 pc('(');
480                 pargs(d, stm->b);
481                 ps(") {\n");
482                 pstmlist(d, stm->c);
483                 in(d); ps("}");
484                 break;
485
486         case STM_EMPTY:
487                 pc(';');
488                 break;
489
490         case STM_VAR:
491                 ps("var ");
492                 pvarlist(d, stm->a);
493                 ps(";");
494                 break;
495
496         case STM_IF:
497                 ps("if ("); pexp(d, stm->a); ps(")");
498                 pstmh(d, stm->b);
499                 if (stm->c) {
500                         nl(); in(d); ps("else");
501                         pstmh(d, stm->c);
502                 }
503                 break;
504
505         case STM_DO:
506                 ps("do");
507                 pstmh(d, stm->a);
508                 nl();
509                 in(d); ps("while ("); pexp(d, stm->b); ps(");");
510                 break;
511
512         case STM_WHILE:
513                 ps("while ("); pexp(d, stm->a); ps(")");
514                 pstmh(d, stm->b);
515                 break;
516
517         case STM_FOR:
518                 ps("for (");
519                 pexp(d, stm->a); ps("; ");
520                 pexp(d, stm->b); ps("; ");
521                 pexp(d, stm->c); ps(")");
522                 pstmh(d, stm->d);
523                 break;
524         case STM_FOR_VAR:
525                 ps("for (var ");
526                 pvarlist(d, stm->a); ps("; ");
527                 pexp(d, stm->b); ps("; ");
528                 pexp(d, stm->c); ps(")");
529                 pstmh(d, stm->d);
530                 break;
531         case STM_FOR_IN:
532                 ps("for (");
533                 pexp(d, stm->a); ps(" in ");
534                 pexp(d, stm->b); ps(")");
535                 pstmh(d, stm->c);
536                 break;
537         case STM_FOR_IN_VAR:
538                 ps("for (var ");
539                 pvarlist(d, stm->a); ps(" in ");
540                 pexp(d, stm->b); ps(")");
541                 pstmh(d, stm->c);
542                 break;
543
544         case STM_CONTINUE:
545                 if (stm->a) {
546                         ps("continue "); pexp(d, stm->a); ps(";");
547                 } else {
548                         ps("continue;");
549                 }
550                 break;
551
552         case STM_BREAK:
553                 if (stm->a) {
554                         ps("break "); pexp(d, stm->a); ps(";");
555                 } else {
556                         ps("break;");
557                 }
558                 break;
559
560         case STM_RETURN:
561                 if (stm->a) {
562                         ps("return "); pexp(d, stm->a); ps(";");
563                 } else {
564                         ps("return;");
565                 }
566                 break;
567
568         case STM_WITH:
569                 ps("with ("); pexp(d, stm->a); ps(")");
570                 pstmh(d, stm->b);
571                 break;
572
573         case STM_SWITCH:
574                 ps("switch (");
575                 pexp(d, stm->a);
576                 ps(") {\n");
577                 pcaselist(d, stm->b);
578                 in(d); ps("}");
579                 break;
580
581         case STM_THROW:
582                 ps("throw "); pexp(d, stm->a); ps(";");
583                 break;
584
585         case STM_TRY:
586                 ps("try");
587                 pstmh(d, stm->a);
588                 if (stm->b && stm->c) {
589                         nl(); in(d); ps("catch ("); pexp(d, stm->b); ps(")");
590                         pstmh(d, stm->c);
591                 }
592                 if (stm->d) {
593                         nl(); in(d); ps("finally");
594                         pstmh(d, stm->d);
595                 }
596                 break;
597
598         case STM_LABEL:
599                 pexp(d, stm->a); ps(": "); pstm(d, stm->b);
600                 break;
601
602         case STM_DEBUGGER:
603                 ps("debugger;");
604                 break;
605
606         default:
607                 pexp(d, stm); pc(';');
608         }
609 }
610
611 static void pstmlist(int d, js_Ast *list)
612 {
613         while (list) {
614                 assert(list->type == AST_LIST);
615                 pstm(d+1, list->a);
616                 nl();
617                 list = list->b;
618         }
619 }
620
621 void jsP_dumpsyntax(js_State *J, js_Ast *prog)
622 {
623         if (prog->type == AST_LIST)
624                 pstmlist(-1, prog);
625         else {
626                 pstm(0, prog);
627                 nl();
628         }
629 }
630
631 /* S-expression list representation */
632
633 static void snode(int d, js_Ast *node)
634 {
635         void (*afun)(int,js_Ast*) = snode;
636         void (*bfun)(int,js_Ast*) = snode;
637         void (*cfun)(int,js_Ast*) = snode;
638         void (*dfun)(int,js_Ast*) = snode;
639
640         if (!node) {
641                 return;
642         }
643
644         if (node->type == AST_LIST) {
645                 slist(d, node);
646                 return;
647         }
648
649         pc('(');
650         ps(astname[node->type]);
651         switch (node->type) {
652         case AST_IDENTIFIER: pc(' '); ps(node->string); break;
653         case EXP_IDENTIFIER: pc(' '); ps(node->string); break;
654         case EXP_STRING: pc(' '); pstr(node->string); break;
655         case EXP_REGEXP: pc(' '); pregexp(node->string, node->number); break;
656         case EXP_NUMBER: printf(" %.9g", node->number); break;
657         case STM_BLOCK: afun = sblock; break;
658         case AST_FUNDEC: case EXP_FUN: cfun = sblock; break;
659         case EXP_PROP_GET: cfun = sblock; break;
660         case EXP_PROP_SET: cfun = sblock; break;
661         case STM_SWITCH: bfun = sblock; break;
662         case STM_CASE: bfun = sblock; break;
663         case STM_DEFAULT: afun = sblock; break;
664         }
665         if (node->a) { pc(' '); afun(d, node->a); }
666         if (node->b) { pc(' '); bfun(d, node->b); }
667         if (node->c) { pc(' '); cfun(d, node->c); }
668         if (node->d) { pc(' '); dfun(d, node->d); }
669         pc(')');
670 }
671
672 static void slist(int d, js_Ast *list)
673 {
674         pc('[');
675         while (list) {
676                 assert(list->type == AST_LIST);
677                 snode(d, list->a);
678                 list = list->b;
679                 if (list)
680                         pc(' ');
681         }
682         pc(']');
683 }
684
685 static void sblock(int d, js_Ast *list)
686 {
687         ps("[\n");
688         in(d+1);
689         while (list) {
690                 assert(list->type == AST_LIST);
691                 snode(d+1, list->a);
692                 list = list->b;
693                 if (list) {
694                         nl();
695                         in(d+1);
696                 }
697         }
698         nl(); in(d); pc(']');
699 }
700
701 void jsP_dumplist(js_State *J, js_Ast *prog)
702 {
703         if (prog->type == AST_LIST)
704                 sblock(0, prog);
705         else
706                 snode(0, prog);
707         nl();
708 }
709
710 /* Compiled code */
711
712 void jsC_dumpfunction(js_State *J, js_Function *F)
713 {
714         js_Instruction *p = F->code;
715         js_Instruction *end = F->code + F->codelen;
716         unsigned int i;
717
718         printf("%s(%d)\n", F->name, F->numparams);
719         if (F->lightweight) printf("\tlightweight\n");
720         if (F->arguments) printf("\targuments\n");
721         printf("\tsource %s:%d\n", F->filename, F->line);
722         for (i = 0; i < F->funlen; ++i)
723                 printf("\tfunction %d %s\n", i, F->funtab[i]->name);
724         for (i = 0; i < F->varlen; ++i)
725                 printf("\tlocal %d %s\n", i + 1, F->vartab[i]);
726
727         printf("{\n");
728         while (p < end) {
729                 int c = *p++;
730
731                 printf("% 5d: ", (int)(p - F->code) - 1);
732                 ps(opname[c]);
733
734                 switch (c) {
735                 case OP_NUMBER:
736                         printf(" %.9g", F->numtab[*p++]);
737                         break;
738                 case OP_STRING:
739                         pc(' ');
740                         pstr(F->strtab[*p++]);
741                         break;
742                 case OP_NEWREGEXP:
743                         pc(' ');
744                         pregexp(F->strtab[p[0]], p[1]);
745                         p += 2;
746                         break;
747
748                 case OP_INITVAR:
749                 case OP_DEFVAR:
750                 case OP_GETVAR:
751                 case OP_SETVAR:
752                 case OP_DELVAR:
753                 case OP_GETPROP_S:
754                 case OP_SETPROP_S:
755                 case OP_DELPROP_S:
756                 case OP_CATCH:
757                         pc(' ');
758                         ps(F->strtab[*p++]);
759                         break;
760
761                 case OP_LINE:
762                 case OP_CLOSURE:
763                 case OP_INITLOCAL:
764                 case OP_GETLOCAL:
765                 case OP_SETLOCAL:
766                 case OP_DELLOCAL:
767                 case OP_NUMBER_POS:
768                 case OP_NUMBER_NEG:
769                 case OP_CALL:
770                 case OP_NEW:
771                 case OP_JUMP:
772                 case OP_JTRUE:
773                 case OP_JFALSE:
774                 case OP_JCASE:
775                 case OP_TRY:
776                         printf(" %d", *p++);
777                         break;
778                 }
779
780                 nl();
781         }
782         printf("}\n");
783
784         for (i = 0; i < F->funlen; ++i) {
785                 if (F->funtab[i] != F) {
786                         printf("function %d ", i);
787                         jsC_dumpfunction(J, F->funtab[i]);
788                 }
789         }
790 }
791
792 /* Runtime values */
793
794 void js_dumpvalue(js_State *J, js_Value v)
795 {
796         switch (v.type) {
797         case JS_TUNDEFINED: printf("undefined"); break;
798         case JS_TNULL: printf("null"); break;
799         case JS_TBOOLEAN: printf(v.u.boolean ? "true" : "false"); break;
800         case JS_TNUMBER: printf("%.9g", v.u.number); break;
801         case JS_TSHRSTR: printf("'%s'", v.u.shrstr); break;
802         case JS_TLITSTR: printf("'%s'", v.u.litstr); break;
803         case JS_TMEMSTR: printf("'%s'", v.u.memstr->p); break;
804         case JS_TOBJECT:
805                 if (v.u.object == J->G) {
806                         printf("[Global]");
807                         break;
808                 }
809                 switch (v.u.object->type) {
810                 case JS_COBJECT: printf("[Object %p]", v.u.object); break;
811                 case JS_CARRAY: printf("[Array %p]", v.u.object); break;
812                 case JS_CFUNCTION:
813                         printf("[Function %p, %s, %s:%d]",
814                                 v.u.object,
815                                 v.u.object->u.f.function->name,
816                                 v.u.object->u.f.function->filename,
817                                 v.u.object->u.f.function->line);
818                         break;
819                 case JS_CSCRIPT: printf("[Script %s]", v.u.object->u.f.function->filename); break;
820                 case JS_CCFUNCTION: printf("[CFunction %p]", v.u.object->u.c.function); break;
821                 case JS_CBOOLEAN: printf("[Boolean %d]", v.u.object->u.boolean); break;
822                 case JS_CNUMBER: printf("[Number %g]", v.u.object->u.number); break;
823                 case JS_CSTRING: printf("[String'%s']", v.u.object->u.s.string); break;
824                 case JS_CERROR: printf("[Error %s]", v.u.object->u.s.string); break;
825                 case JS_CITERATOR: printf("[Iterator %p]", v.u.object); break;
826                 case JS_CUSERDATA:
827                         printf("[Userdata %s %p]", v.u.object->u.user.tag, v.u.object->u.user.data);
828                         break;
829                 default: printf("[Object %p]", v.u.object); break;
830                 }
831                 break;
832         }
833 }
834
835 static void js_dumpproperty(js_State *J, js_Property *node)
836 {
837         if (node->left->level)
838                 js_dumpproperty(J, node->left);
839         printf("\t%s: ", node->name);
840         js_dumpvalue(J, node->value);
841         printf(",\n");
842         if (node->right->level)
843                 js_dumpproperty(J, node->right);
844 }
845
846 void js_dumpobject(js_State *J, js_Object *obj)
847 {
848         printf("{\n");
849         if (obj->properties->level)
850                 js_dumpproperty(J, obj->properties);
851         printf("}\n");
852 }