static int lexstring(js_State *J) { const char *s; int q = J->lexchar; jsY_next(J); textinit(J); while (J->lexchar != q) { if (J->lexchar == 0 || J->lexchar == '\n') jsY_error(J, "string not terminated"); if (jsY_accept(J, '\\')) { if (lexescape(J)) jsY_error(J, "malformed escape sequence"); } else { textpush(J, J->lexchar); jsY_next(J); } } jsY_expect(J, q); s = textend(J); J->text = js_intern(J, s); return TK_STRING; }
static js_Object *jsV_newstring(js_State *J, const char *v) { js_Object *obj = jsV_newobject(J, JS_CSTRING, J->String_prototype); obj->u.s.string = js_intern(J, v); /* TODO: js_String */ obj->u.s.length = utflen(v); return obj; }
static int lexregexp(js_State *J) { const char *s; int g, m, i; int inclass = 0; /* already consumed initial '/' */ textinit(J); /* regexp body */ while (J->lexchar != '/' || inclass) { if (J->lexchar == 0 || J->lexchar == '\n') { jsY_error(J, "regular expression not terminated"); } else if (jsY_accept(J, '\\')) { if (jsY_accept(J, '/')) { textpush(J, '/'); } else { textpush(J, '\\'); if (J->lexchar == 0 || J->lexchar == '\n') jsY_error(J, "regular expression not terminated"); textpush(J, J->lexchar); jsY_next(J); } } else { if (J->lexchar == '[' && !inclass) inclass = 1; if (J->lexchar == ']' && inclass) inclass = 0; textpush(J, J->lexchar); jsY_next(J); } } jsY_expect(J, '/'); s = textend(J); /* regexp flags */ g = i = m = 0; while (jsY_isidentifierpart(J->lexchar)) { if (jsY_accept(J, 'g')) ++g; else if (jsY_accept(J, 'i')) ++i; else if (jsY_accept(J, 'm')) ++m; else jsY_error(J, "illegal flag in regular expression: %c", J->lexchar); } if (g > 1 || i > 1 || m > 1) jsY_error(J, "duplicated flag in regular expression"); J->text = js_intern(J, s); J->number = 0; if (g) J->number += JS_REGEXP_G; if (i) J->number += JS_REGEXP_I; if (m) J->number += JS_REGEXP_M; return TK_REGEXP; }
static int jsY_findkeyword(js_State *J, const char *s) { int i = jsY_findword(s, keywords, nelem(keywords)); if (i >= 0) { J->text = keywords[i]; return TK_BREAK + i; /* first keyword + i */ } J->text = js_intern(J, s); return TK_IDENTIFIER; }
const char *js_ref(js_State *J) { js_Value *v = stackidx(J, -1); const char *s; char buf[32]; switch (v->type) { case JS_TUNDEFINED: s = "_Undefined"; break; case JS_TNULL: s = "_Null"; break; case JS_TBOOLEAN: s = v->u.boolean ? "_True" : "_False"; break; case JS_TOBJECT: sprintf(buf, "%p", (void*)v->u.object); s = js_intern(J, buf); break; default: sprintf(buf, "%d", J->nextref++); s = js_intern(J, buf); break; } js_setregistry(J, s); return s; }
static js_Property *newproperty(js_State *J, js_Object *obj, const char *name) { js_Property *node = js_malloc(J, sizeof *node); node->name = js_intern(J, name); node->left = node->right = &sentinel; node->level = 1; node->atts = 0; node->value.type = JS_TUNDEFINED; node->value.u.number = 0; node->getter = NULL; node->setter = NULL; ++obj->count; return node; }
/* ToString() on a number */ const char *jsV_numbertostring(js_State *J, double f) { char buf[32], digits[32], *p = buf, *s = digits; int exp, neg, ndigits, point; if (isnan(f)) return "NaN"; if (isinf(f)) return f < 0 ? "-Infinity" : "Infinity"; if (f == 0) return "0"; js_dtoa(f, digits, &exp, &neg, &ndigits); point = ndigits + exp; if (neg) *p++ = '-'; if (point < -5 || point > 21) { *p++ = *s++; if (ndigits > 1) { int n = ndigits - 1; *p++ = '.'; while (n--) *p++ = *s++; } js_fmtexp(p, point - 1); } else if (point <= 0) { *p++ = '0'; *p++ = '.'; while (point++ < 0) *p++ = '0'; while (ndigits-- > 0) *p++ = *s++; *p = 0; } else { while (ndigits-- > 0) { *p++ = *s++; if (--point == 0 && ndigits > 0) *p++ = '.'; } while (point-- > 0) *p++ = '0'; *p = 0; } return js_intern(J, buf); }
static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *body, int script) { js_Function *F = js_malloc(J, sizeof *F); memset(F, 0, sizeof *F); F->gcmark = 0; F->gcnext = J->gcfun; J->gcfun = F; ++J->gccounter; F->filename = js_intern(J, J->filename); F->line = name ? name->line : params ? params->line : body ? body->line : 1; F->script = script; F->name = name ? name->string : ""; cfunbody(J, F, name, params, body); return F; }
static void itwalk(js_State *J, js_Object *io, js_Object *top, int own) { js_Object *obj = top; js_Iterator *tail = NULL; char buf[32]; int k; #define ITADD(x) \ js_Iterator *node = js_malloc(J, sizeof *node); \ node->name = x; \ node->next = NULL; \ if (!tail) { \ io->u.iter.head = tail = node; \ } else { \ tail->next = node; \ tail = node; \ } while (obj) { js_Property *prop = obj->head; while (prop) { if (!(prop->atts & JS_DONTENUM) && !itshadow(J, top, obj, prop->name)) { ITADD(prop->name); } prop = prop->next; } if (obj->type == JS_CSTRING) { for (k = 0; k < obj->u.s.length; ++k) { js_itoa(buf, k); if (!itshadow(J, top, obj, buf)) { ITADD(js_intern(J, buf)); } } } if (own) break; obj = obj->prototype; } }