Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "jsi.h"
  2. #include "jslex.h"
  3. #include "jsvalue.h"
  4. #include "jsbuiltin.h"
  5. #include "jscompile.h"
  6. #include "utf.h"
  7.  
  8. static void reprvalue(js_State *J, js_Buffer **sb);
  9.  
  10. static void reprnum(js_State *J, js_Buffer **sb, double n)
  11. {
  12.         char buf[40];
  13.         if (n == 0 && signbit(n))
  14.                 js_puts(J, sb, "-0");
  15.         else
  16.                 js_puts(J, sb, jsV_numbertostring(J, buf, n));
  17. }
  18.  
  19. static void reprstr(js_State *J, js_Buffer **sb, const char *s)
  20. {
  21.         static const char *HEX = "0123456789ABCDEF";
  22.         int i, n;
  23.         Rune c;
  24.         js_putc(J, sb, '"');
  25.         while (*s) {
  26.                 n = chartorune(&c, s);
  27.                 switch (c) {
  28.                 case '"': js_puts(J, sb, "\\\""); break;
  29.                 case '\\': js_puts(J, sb, "\\\\"); break;
  30.                 case '\b': js_puts(J, sb, "\\b"); break;
  31.                 case '\f': js_puts(J, sb, "\\f"); break;
  32.                 case '\n': js_puts(J, sb, "\\n"); break;
  33.                 case '\r': js_puts(J, sb, "\\r"); break;
  34.                 case '\t': js_puts(J, sb, "\\t"); break;
  35.                 default:
  36.                         if (c < ' ') {
  37.                                 js_putc(J, sb, '\\');
  38.                                 js_putc(J, sb, 'x');
  39.                                 js_putc(J, sb, HEX[(c>>4)&15]);
  40.                                 js_putc(J, sb, HEX[c&15]);
  41.                         } else if (c < 128) {
  42.                                 js_putc(J, sb, c);
  43.                         } else if (c < 0x10000) {
  44.                                 js_putc(J, sb, '\\');
  45.                                 js_putc(J, sb, 'u');
  46.                                 js_putc(J, sb, HEX[(c>>12)&15]);
  47.                                 js_putc(J, sb, HEX[(c>>8)&15]);
  48.                                 js_putc(J, sb, HEX[(c>>4)&15]);
  49.                                 js_putc(J, sb, HEX[c&15]);
  50.                         } else {
  51.                                 for (i = 0; i < n; ++i)
  52.                                         js_putc(J, sb, s[i]);
  53.                         }
  54.                         break;
  55.                 }
  56.                 s += n;
  57.         }
  58.         js_putc(J, sb, '"');
  59. }
  60.  
  61. #ifndef isalpha
  62. #define isalpha(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
  63. #endif
  64. #ifndef isdigit
  65. #define isdigit(c) (c >= '0' && c <= '9')
  66. #endif
  67.  
  68. static void reprident(js_State *J, js_Buffer **sb, const char *name)
  69. {
  70.         const char *p = name;
  71.         if (isdigit(*p))
  72.                 while (isdigit(*p))
  73.                         ++p;
  74.         else if (isalpha(*p) || *p == '_')
  75.                 while (isdigit(*p) || isalpha(*p) || *p == '_')
  76.                         ++p;
  77.         if (p > name && *p == 0)
  78.                 js_puts(J, sb, name);
  79.         else
  80.                 reprstr(J, sb, name);
  81. }
  82.  
  83. static void reprobject(js_State *J, js_Buffer **sb)
  84. {
  85.         const char *key;
  86.         int i, n;
  87.  
  88.         n = js_gettop(J) - 1;
  89.         for (i = 0; i < n; ++i) {
  90.                 if (js_isobject(J, i)) {
  91.                         if (js_toobject(J, i) == js_toobject(J, -1)) {
  92.                                 js_puts(J, sb, "{}");
  93.                                 return;
  94.                         }
  95.                 }
  96.         }
  97.  
  98.         n = 0;
  99.         js_putc(J, sb, '{');
  100.         js_pushiterator(J, -1, 1);
  101.         while ((key = js_nextiterator(J, -1))) {
  102.                 if (n++ > 0)
  103.                         js_puts(J, sb, ", ");
  104.                 reprident(J, sb, key);
  105.                 js_puts(J, sb, ": ");
  106.                 js_getproperty(J, -2, key);
  107.                 reprvalue(J, sb);
  108.                 js_pop(J, 1);
  109.         }
  110.         js_pop(J, 1);
  111.         js_putc(J, sb, '}');
  112. }
  113.  
  114. static void reprarray(js_State *J, js_Buffer **sb)
  115. {
  116.         int n, i;
  117.  
  118.         n = js_gettop(J) - 1;
  119.         for (i = 0; i < n; ++i) {
  120.                 if (js_isobject(J, i)) {
  121.                         if (js_toobject(J, i) == js_toobject(J, -1)) {
  122.                                 js_puts(J, sb, "[]");
  123.                                 return;
  124.                         }
  125.                 }
  126.         }
  127.  
  128.         js_putc(J, sb, '[');
  129.         n = js_getlength(J, -1);
  130.         for (i = 0; i < n; ++i) {
  131.                 if (i > 0)
  132.                         js_puts(J, sb, ", ");
  133.                 if (js_hasindex(J, -1, i)) {
  134.                         reprvalue(J, sb);
  135.                         js_pop(J, 1);
  136.                 }
  137.         }
  138.         js_putc(J, sb, ']');
  139. }
  140.  
  141. static void reprfun(js_State *J, js_Buffer **sb, js_Function *fun)
  142. {
  143.         int i;
  144.         js_puts(J, sb, "function ");
  145.         js_puts(J, sb, fun->name);
  146.         js_putc(J, sb, '(');
  147.         for (i = 0; i < fun->numparams; ++i) {
  148.                 if (i > 0)
  149.                         js_puts(J, sb, ", ");
  150.                 js_puts(J, sb, fun->vartab[i]);
  151.         }
  152.         js_puts(J, sb, ") { [byte code] }");
  153. }
  154.  
  155. static void reprvalue(js_State *J, js_Buffer **sb)
  156. {
  157.         if (js_isundefined(J, -1))
  158.                 js_puts(J, sb, "undefined");
  159.         else if (js_isnull(J, -1))
  160.                 js_puts(J, sb, "null");
  161.         else if (js_isboolean(J, -1))
  162.                 js_puts(J, sb, js_toboolean(J, -1) ? "true" : "false");
  163.         else if (js_isnumber(J, -1))
  164.                 reprnum(J, sb, js_tonumber(J, -1));
  165.         else if (js_isstring(J, -1))
  166.                 reprstr(J, sb, js_tostring(J, -1));
  167.         else if (js_isobject(J, -1)) {
  168.                 js_Object *obj = js_toobject(J, -1);
  169.                 switch (obj->type) {
  170.                 default:
  171.                         reprobject(J, sb);
  172.                         break;
  173.                 case JS_CARRAY:
  174.                         reprarray(J, sb);
  175.                         break;
  176.                 case JS_CFUNCTION:
  177.                 case JS_CSCRIPT:
  178.                 case JS_CEVAL:
  179.                         reprfun(J, sb, obj->u.f.function);
  180.                         break;
  181.                 case JS_CCFUNCTION:
  182.                         js_puts(J, sb, "function ");
  183.                         js_puts(J, sb, obj->u.c.name);
  184.                         js_puts(J, sb, "() { [native code] }");
  185.                         break;
  186.                 case JS_CBOOLEAN:
  187.                         js_puts(J, sb, "(new Boolean(");
  188.                         js_puts(J, sb, obj->u.boolean ? "true" : "false");
  189.                         js_puts(J, sb, "))");
  190.                         break;
  191.                 case JS_CNUMBER:
  192.                         js_puts(J, sb, "(new Number(");
  193.                         reprnum(J, sb, obj->u.number);
  194.                         js_puts(J, sb, "))");
  195.                         break;
  196.                 case JS_CSTRING:
  197.                         js_puts(J, sb, "(new String(");
  198.                         reprstr(J, sb, obj->u.s.string);
  199.                         js_puts(J, sb, "))");
  200.                         break;
  201.                 case JS_CREGEXP:
  202.                         js_putc(J, sb, '/');
  203.                         js_puts(J, sb, obj->u.r.source);
  204.                         js_putc(J, sb, '/');
  205.                         if (obj->u.r.flags & JS_REGEXP_G) js_putc(J, sb, 'g');
  206.                         if (obj->u.r.flags & JS_REGEXP_I) js_putc(J, sb, 'i');
  207.                         if (obj->u.r.flags & JS_REGEXP_M) js_putc(J, sb, 'm');
  208.                         break;
  209.                 case JS_CDATE:
  210.                         {
  211.                                 char buf[40];
  212.                                 js_puts(J, sb, "(new Date(");
  213.                                 js_puts(J, sb, jsV_numbertostring(J, buf, obj->u.number));
  214.                                 js_puts(J, sb, "))");
  215.                         }
  216.                         break;
  217.                 case JS_CERROR:
  218.                         js_puts(J, sb, "(new ");
  219.                         js_getproperty(J, -1, "name");
  220.                         js_puts(J, sb, js_tostring(J, -1));
  221.                         js_pop(J, 1);
  222.                         js_putc(J, sb, '(');
  223.                         js_getproperty(J, -1, "message");
  224.                         reprstr(J, sb, js_tostring(J, -1));
  225.                         js_pop(J, 1);
  226.                         js_puts(J, sb, "))");
  227.                         break;
  228.                 case JS_CMATH:
  229.                         js_puts(J, sb, "Math");
  230.                         break;
  231.                 case JS_CJSON:
  232.                         js_puts(J, sb, "JSON");
  233.                         break;
  234.                 case JS_CITERATOR:
  235.                         js_puts(J, sb, "[iterator ");
  236.                         break;
  237.                 case JS_CUSERDATA:
  238.                         js_puts(J, sb, "[userdata ");
  239.                         js_puts(J, sb, obj->u.user.tag);
  240.                         js_putc(J, sb, ']');
  241.                         break;
  242.                 }
  243.         }
  244. }
  245.  
  246. void js_repr(js_State *J, int idx)
  247. {
  248.         js_Buffer *sb = NULL;
  249.         int savebot;
  250.  
  251.         if (js_try(J)) {
  252.                 js_free(J, sb);
  253.                 js_throw(J);
  254.         }
  255.  
  256.         js_copy(J, idx);
  257.  
  258.         savebot = J->bot;
  259.         J->bot = J->top - 1;
  260.         reprvalue(J, &sb);
  261.         J->bot = savebot;
  262.  
  263.         js_pop(J, 1);
  264.  
  265.         js_putc(J, &sb, 0);
  266.         js_pushstring(J, sb ? sb->s : "undefined");
  267.  
  268.         js_endtry(J);
  269.         js_free(J, sb);
  270. }
  271.  
  272. const char *js_torepr(js_State *J, int idx)
  273. {
  274.         js_repr(J, idx);
  275.         js_replace(J, idx < 0 ? idx-1 : idx);
  276.         return js_tostring(J, idx);
  277. }
  278.  
  279. const char *js_tryrepr(js_State *J, int idx, const char *error)
  280. {
  281.         const char *s;
  282.         if (js_try(J)) {
  283.                 js_pop(J, 1);
  284.                 return error;
  285.         }
  286.         s = js_torepr(J, idx);
  287.         js_endtry(J);
  288.         return s;
  289. }
  290.