void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set) { js_State *J = imp->J; js_getregistry(J, (const char *)type); { js_newcfunction(J, wrapgetter, 0); { js_pushnull(J); js_newuserdata(J, "getter", get); js_defproperty(J, -2, "__get", JS_READONLY | JS_DONTENUM | JS_DONTCONF); js_pushstring(J, (const char *)type); js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF); } js_newcfunction(J, wrapsetter, 0); { js_pushnull(J); js_newuserdata(J, "setter", set); js_defproperty(J, -2, "__set", JS_READONLY | JS_DONTENUM | JS_DONTCONF); js_pushstring(J, (const char *)type); js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF); } js_defaccessor(J, -3, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF); } js_pop(J, 1); }
static void Sp_concat(js_State *J) { unsigned int i, top = js_gettop(J); unsigned int n; char * volatile out; const char *s; if (top == 1) return; s = js_tostring(J, 0); n = strlen(s); out = js_malloc(J, n + 1); strcpy(out, s); if (js_try(J)) { js_free(J, out); js_throw(J); } for (i = 1; i < top; ++i) { s = js_tostring(J, i); n += strlen(s); out = realloc(out, n + 1); strcat(out, s); } js_pushstring(J, out); js_endtry(J); js_free(J, out); }
void js_concat(js_State *J) { js_Value va = js_toprimitive(J, -2, JS_HNONE); js_Value vb = js_toprimitive(J, -1, JS_HNONE); if (va.type == JS_TSTRING || vb.type == JS_TSTRING) { const char *sa = jsV_tostring(J, &va); const char *sb = jsV_tostring(J, &vb); char *sab = js_malloc(J, strlen(sa) + strlen(sb) + 1); strcpy(sab, sa); strcat(sab, sb); if (js_try(J)) { js_free(J, sab); js_throw(J); } js_pop(J, 2); js_pushstring(J, sab); js_endtry(J); js_free(J, sab); } else { double x = jsV_tonumber(J, &va); double y = jsV_tonumber(J, &vb); js_pop(J, 2); js_pushnumber(J, x + y); } }
static void Encode(js_State *J, const char *str, const char *unescaped) { js_Buffer *sb = NULL; static const char *HEX = "0123456789ABCDEF"; while (*str) { int c = (unsigned char) *str++; if (strchr(unescaped, c)) js_putc(J, &sb, c); else { js_putc(J, &sb, '%'); js_putc(J, &sb, HEX[(c >> 4) & 0xf]); js_putc(J, &sb, HEX[c & 0xf]); } } js_putc(J, &sb, 0); if (js_try(J)) { js_free(J, sb); js_throw(J); } js_pushstring(J, sb ? sb->s : ""); js_endtry(J); js_free(J, sb); }
void js_concat(js_State *J) { js_toprimitive(J, -2, JS_HNONE); js_toprimitive(J, -1, JS_HNONE); if (js_isstring(J, -2) || js_isstring(J, -1)) { const char *sa = js_tostring(J, -2); const char *sb = js_tostring(J, -1); /* TODO: create js_String directly */ char *sab = js_malloc(J, strlen(sa) + strlen(sb) + 1); strcpy(sab, sa); strcat(sab, sb); if (js_try(J)) { js_free(J, sab); js_throw(J); } js_pop(J, 2); js_pushstring(J, sab); js_endtry(J); js_free(J, sab); } else { double x = js_tonumber(J, -2); double y = js_tonumber(J, -1); js_pop(J, 2); js_pushnumber(J, x + y); } }
static void Fp_toString(js_State *J) { js_Object *self = js_toobject(J, 0); char *s; unsigned int i, n; if (!js_iscallable(J, 0)) js_typeerror(J, "not a function"); if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) { js_Function *F = self->u.f.function; n = strlen("function () { ... }"); n += strlen(F->name); for (i = 0; i < F->numparams; ++i) n += strlen(F->vartab[i]) + 1; s = js_malloc(J, n); strcpy(s, "function "); strcat(s, F->name); strcat(s, "("); for (i = 0; i < F->numparams; ++i) { if (i > 0) strcat(s, ","); strcat(s, F->vartab[i]); } strcat(s, ") { ... }"); if (js_try(J)) { js_free(J, s); js_throw(J); } js_pushstring(J, s); js_free(J, s); js_endtry(J); } else { js_pushliteral(J, "function () { ... }"); } }
static void Sp_replace_string(js_State *J) { const char *source, *needle, *s, *r; js_Buffer *sb = NULL; int n; source = js_tostring(J, 0); needle = js_tostring(J, 1); s = strstr(source, needle); if (!s) { js_copy(J, 0); return; } n = strlen(needle); if (js_iscallable(J, 2)) { js_copy(J, 2); js_pushglobal(J); js_pushlstring(J, s, n); /* arg 1: substring that matched */ js_pushnumber(J, s - source); /* arg 2: offset within search string */ js_copy(J, 0); /* arg 3: search string */ js_call(J, 3); r = js_tostring(J, -1); js_putm(J, &sb, source, s); js_puts(J, &sb, r); js_puts(J, &sb, s + n); js_putc(J, &sb, 0); js_pop(J, 1); } else { r = js_tostring(J, 2); js_putm(J, &sb, source, s); while (*r) { if (*r == '$') { switch (*(++r)) { case '$': js_putc(J, &sb, '$'); break; case '&': js_putm(J, &sb, s, s + n); break; case '`': js_putm(J, &sb, source, s); break; case '\'': js_puts(J, &sb, s + n); break; default: js_putc(J, &sb, '$'); js_putc(J, &sb, *r); break; } ++r; } else { js_putc(J, &sb, *r++); } } js_puts(J, &sb, s + n); js_putc(J, &sb, 0); } if (js_try(J)) { js_free(J, sb); js_throw(J); } js_pushstring(J, sb ? sb->s : ""); js_endtry(J); js_free(J, sb); }
static void Sp_split_regexp(js_State *J) { js_Regexp *re; const char *text; unsigned int limit, len, k; const char *p, *a, *b, *c, *e; Resub m; text = js_tostring(J, 0); re = js_toregexp(J, 1); limit = js_isdefined(J, 2) ? js_touint32(J, 2) : 1 << 30; js_newarray(J); len = 0; e = text + strlen(text); /* splitting the empty string */ if (e == 0) { if (js_regexec(re->prog, text, &m, 0)) { if (len == limit) return; js_pushliteral(J, ""); js_setindex(J, -2, 0); } return; } p = a = text; while (a < e) { if (js_regexec(re->prog, a, &m, a > text ? REG_NOTBOL : 0)) break; /* no match */ b = m.sub[0].sp; c = m.sub[0].ep; /* empty string at end of last match */ if (b == p) { ++a; continue; } if (len == limit) return; js_pushlstring(J, p, b - p); js_setindex(J, -2, len++); for (k = 1; k < m.nsub; ++k) { if (len == limit) return; js_pushlstring(J, m.sub[k].sp, m.sub[k].ep - m.sub[k].sp); js_setindex(J, -2, len++); } a = p = c; } if (len == limit) return; js_pushstring(J, p); js_setindex(J, -2, len); }
static void js_pushrune(js_State *J, Rune rune) { char buf[UTFmax + 1]; if (rune > 0) { buf[runetochar(buf, &rune)] = 0; js_pushstring(J, buf); } else { js_pushundefined(J); } }
static void jsB_readline(js_State *J) { char line[256]; int n; if (!fgets(line, sizeof line, stdin)) js_error(J, "cannot read line from stdin"); n = strlen(line); if (n > 0 && line[n-1] == '\n') line[n-1] = 0; js_pushstring(J, line); }
static void Ap_join(js_State *J) { char * volatile out = NULL; const char *sep; const char *r; unsigned int seplen; unsigned int k, n, len; len = js_getlength(J, 0); if (js_isdefined(J, 1)) { sep = js_tostring(J, 1); seplen = strlen(sep); } else { sep = ","; seplen = 1; } if (len == 0) { js_pushliteral(J, ""); return; } if (js_try(J)) { js_free(J, out); js_throw(J); } n = 1; for (k = 0; k < len; ++k) { js_getindex(J, 0, k); if (js_isundefined(J, -1) || js_isnull(J, -1)) r = ""; else r = js_tostring(J, -1); n += strlen(r); if (k == 0) { out = js_malloc(J, n); strcpy(out, r); } else { n += seplen; out = realloc(out, n); strcat(out, sep); strcat(out, r); } js_pop(J, 1); } js_pushstring(J, out); js_endtry(J); js_free(J, out); }
static void jsB_readline(js_State *J) { char *line = readline(""); if (!line) { js_pushnull(J); return; } js_pushstring(J, line); if (*line) add_history(line); free(line); }
static void Sp_charAt(js_State *J) { char buf[UTFmax + 1]; const char *s = js_tostring(J, 0); int pos = js_tointeger(J, 1); Rune rune = js_runeat(J, s, pos); if (rune > 0) { buf[runetochar(buf, &rune)] = 0; js_pushstring(J, buf); } else { js_pushliteral(J, ""); } }
void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth) { js_State *J = imp->J; js_getregistry(J, (const char *)type); { js_newcfunction(J, wrapmethod, 0); { js_pushnull(J); js_newuserdata(J, "method", meth); js_defproperty(J, -2, "__call", JS_READONLY | JS_DONTENUM | JS_DONTCONF); js_pushstring(J, (const char *)type); js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF); } js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF); } js_pop(J, 1); }
static void jsB_read(js_State *J) { const char *filename = js_tostring(J, 1); FILE *f; char *s; int n, t; f = fopen(filename, "rb"); if (!f) { js_error(J, "cannot open file '%s': %s", filename, strerror(errno)); } if (fseek(f, 0, SEEK_END) < 0) { fclose(f); js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno)); } n = ftell(f); if (n < 0) { fclose(f); js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno)); } if (fseek(f, 0, SEEK_SET) < 0) { fclose(f); js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno)); } s = malloc(n + 1); if (!s) { fclose(f); js_error(J, "out of memory"); } t = fread(s, 1, n, f); if (t != n) { free(s); fclose(f); js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno)); } s[n] = 0; js_pushstring(J, s); free(s); fclose(f); }
static void Sp_toUpperCase(js_State *J) { const char *src = js_tostring(J, 0); char *dst = js_malloc(J, UTFmax * strlen(src) + 1); const char *s = src; char *d = dst; Rune rune; while (*s) { s += chartorune(&rune, s); rune = toupperrune(rune); d += runetochar(d, &rune); } *d = 0; if (js_try(J)) { js_free(J, dst); js_throw(J); } js_pushstring(J, dst); js_endtry(J); js_free(J, dst); }
void js_util_pushjsonnode(js_State *state, JsonNode *node) { GType type; if (!JSON_NODE_HOLDS_VALUE(node)) { js_pushundefined(state); return; } type = json_node_get_value_type(node); if (type == G_TYPE_STRING) js_pushstring(state, json_node_get_string(node)); else if (type == G_TYPE_INT) js_pushnumber(state, json_node_get_int(node)); else if (type == G_TYPE_BOOLEAN) js_pushboolean(state, json_node_get_boolean(node)); else js_pushundefined(state); }
static void S_fromCharCode(js_State *J) { unsigned int i, top = js_gettop(J); Rune c; char *s, *p; s = p = js_malloc(J, (top-1) * UTFmax + 1); if (js_try(J)) { js_free(J, s); js_throw(J); } for (i = 1; i < top; ++i) { c = js_touint16(J, i); p += runetochar(p, &c); } *p = 0; js_pushstring(J, s); js_endtry(J); js_free(J, s); }
static void Sp_split_string(js_State *J) { const char *str = js_tostring(J, 0); const char *sep = js_tostring(J, 1); unsigned int limit = js_isdefined(J, 2) ? js_touint32(J, 2) : 1 << 30; unsigned int i, n; js_newarray(J); n = strlen(sep); /* empty string */ if (n == 0) { Rune rune; for (i = 0; *str && i < limit; ++i) { n = chartorune(&rune, str); js_pushlstring(J, str, n); js_setindex(J, -2, i); str += n; } return; } for (i = 0; str && i < limit; ++i) { const char *s = strstr(str, sep); if (s) { js_pushlstring(J, str, s-str); js_setindex(J, -2, i); str = s + n; } else { js_pushstring(J, str); js_setindex(J, -2, i); str = NULL; } } }
static void Decode(js_State *J, const char *str, const char *reserved) { js_Buffer *sb = NULL; int a, b; while (*str) { int c = (unsigned char) *str++; if (c != '%') js_putc(J, &sb, c); else { if (!str[0] || !str[1]) js_urierror(J, "truncated escape sequence"); a = *str++; b = *str++; if (!jsY_ishex(a) || !jsY_ishex(b)) js_urierror(J, "invalid escape sequence"); c = jsY_tohex(a) << 4 | jsY_tohex(b); if (!strchr(reserved, c)) js_putc(J, &sb, c); else { js_putc(J, &sb, '%'); js_putc(J, &sb, a); js_putc(J, &sb, b); } } } js_putc(J, &sb, 0); if (js_try(J)) { js_free(J, sb); js_throw(J); } js_pushstring(J, sb ? sb->s : ""); js_endtry(J); js_free(J, sb); }
static void Sp_replace_regexp(js_State *J) { js_Regexp *re; const char *source, *s, *r; js_Buffer *sb = NULL; unsigned int n, x; Resub m; source = js_tostring(J, 0); re = js_toregexp(J, 1); if (js_regexec(re->prog, source, &m, 0)) { js_copy(J, 0); return; } re->last = 0; loop: s = m.sub[0].sp; n = m.sub[0].ep - m.sub[0].sp; if (js_iscallable(J, 2)) { js_copy(J, 2); js_pushglobal(J); for (x = 0; m.sub[x].sp; ++x) /* arg 0..x: substring and subexps that matched */ js_pushlstring(J, m.sub[x].sp, m.sub[x].ep - m.sub[x].sp); js_pushnumber(J, s - source); /* arg x+2: offset within search string */ js_copy(J, 0); /* arg x+3: search string */ js_call(J, 2 + x); r = js_tostring(J, -1); js_putm(J, &sb, source, s); js_puts(J, &sb, r); js_pop(J, 1); } else { r = js_tostring(J, 2); js_putm(J, &sb, source, s); while (*r) { if (*r == '$') { switch (*(++r)) { case '$': js_putc(J, &sb, '$'); break; case '`': js_putm(J, &sb, source, s); break; case '\'': js_puts(J, &sb, s + n); break; case '&': js_putm(J, &sb, s, s + n); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': x = *r - '0'; if (r[1] >= '0' && r[1] <= '9') x = x * 10 + *(++r) - '0'; if (x > 0 && x < m.nsub) { js_putm(J, &sb, m.sub[x].sp, m.sub[x].ep); } else { js_putc(J, &sb, '$'); if (x > 10) { js_putc(J, &sb, '0' + x / 10); js_putc(J, &sb, '0' + x % 10); } else { js_putc(J, &sb, '0' + x); } } break; default: js_putc(J, &sb, '$'); js_putc(J, &sb, *r); break; } ++r; } else { js_putc(J, &sb, *r++); } } } if (re->flags & JS_REGEXP_G) { source = m.sub[0].ep; if (n == 0) { if (*source) js_putc(J, &sb, *source++); else goto end; } if (!js_regexec(re->prog, source, &m, REG_NOTBOL)) goto loop; } end: js_puts(J, &sb, s + n); js_putc(J, &sb, 0); if (js_try(J)) { js_free(J, sb); js_throw(J); } js_pushstring(J, sb ? sb->s : ""); js_endtry(J); js_free(J, sb); }
pdf_jsimp_obj *pdf_jsimp_from_string(pdf_jsimp *imp, char *str) { js_State *J = imp->J; js_pushstring(J, str); return NEWOBJ(J, -1); }
int main(int argc, char **argv) { char *input; js_State *J; int status = 0; int strict = 0; int interactive = 0; int i, c; while ((c = xgetopt(argc, argv, "is")) != -1) { switch (c) { default: usage(); break; case 'i': interactive = 1; break; case 's': strict = 1; break; } } J = js_newstate(NULL, NULL, strict ? JS_STRICT : 0); js_newcfunction(J, jsB_gc, "gc", 0); js_setglobal(J, "gc"); js_newcfunction(J, jsB_load, "load", 1); js_setglobal(J, "load"); js_newcfunction(J, jsB_compile, "compile", 2); js_setglobal(J, "compile"); js_newcfunction(J, jsB_print, "print", 0); js_setglobal(J, "print"); js_newcfunction(J, jsB_write, "write", 0); js_setglobal(J, "write"); js_newcfunction(J, jsB_read, "read", 1); js_setglobal(J, "read"); js_newcfunction(J, jsB_readline, "readline", 0); js_setglobal(J, "readline"); js_newcfunction(J, jsB_repr, "repr", 0); js_setglobal(J, "repr"); js_newcfunction(J, jsB_quit, "quit", 1); js_setglobal(J, "quit"); js_dostring(J, require_js); js_dostring(J, stacktrace_js); if (xoptind == argc) { interactive = 1; } else { c = xoptind++; js_newarray(J); i = 0; while (xoptind < argc) { js_pushstring(J, argv[xoptind++]); js_setindex(J, -2, i++); } js_setglobal(J, "scriptArgs"); if (js_dofile(J, argv[c])) status = 1; } if (interactive) { if (isatty(0)) { using_history(); rl_bind_key('\t', rl_insert); input = readline(PS1); while (input) { eval_print(J, input); if (*input) add_history(input); free(input); input = readline(PS1); } putchar('\n'); } else { input = read_stdin(); if (!input || !js_dostring(J, input)) status = 1; free(input); } } js_gc(J, 0); js_freestate(J); return status; }