txDestructor fxGetHostDestructor(txMachine* the, txSlot* slot) { txSlot* host = fxCheckHostObject(the, slot); if (host) { if (!(host->flag & XS_HOST_HOOKS_FLAG)) return host->value.host.variant.destructor; mxSyntaxError("C: xsGetHostDestructor: no host destructor"); } mxSyntaxError("C: xsGetHostDestructor: no host object"); return NULL; }
txHostHooks* fxGetHostHooks(txMachine* the, txSlot* slot) { txSlot* host = fxCheckHostObject(the, slot); if (host) { if (host->flag & XS_HOST_HOOKS_FLAG) return host->value.host.variant.hooks; mxSyntaxError("C: xsGetHostHooks: no host hooks"); } mxSyntaxError("C: xsGetHostHooks: no host object"); return NULL; }
void fxParseJSONObject(txMachine* the, txJSONParser* theParser) { txSlot* anObject; txSlot* at; txSlot* aProperty; fxGetNextJSONToken(the, theParser); mxPush(mxObjectPrototype); anObject = fxNewObjectInstance(the); for (;;) { if (theParser->token == XS_JSON_TOKEN_RIGHT_BRACE) break; if (theParser->token != XS_JSON_TOKEN_STRING) { mxSyntaxError("missing name"); break; } mxPushString(theParser->string->value.string); at = fxAt(the, the->stack); if (theParser->reviver) mxPushString(theParser->string->value.string); fxGetNextJSONToken(the, theParser); if (theParser->token != XS_JSON_TOKEN_COLON) { mxSyntaxError("missing :"); break; } fxGetNextJSONToken(the, theParser); fxParseJSONValue(the, theParser); if (theParser->reviver) { mxPushInteger(2); mxPushReference(anObject); mxPushReference(theParser->reviver); fxCall(the); } if (the->stack->kind != XS_UNDEFINED_KIND) { aProperty = fxSetProperty(the, anObject, at->value.at.id, at->value.at.index, XS_OWN); aProperty->kind = the->stack->kind; aProperty->value = the->stack->value; } the->stack++; the->stack++; if (theParser->token != XS_JSON_TOKEN_COMMA) break; fxGetNextJSONToken(the, theParser); } if (theParser->token != XS_JSON_TOKEN_RIGHT_BRACE) mxSyntaxError("missing }"); fxGetNextJSONToken(the, theParser); }
void fx_decodeURIComponent(txMachine* the) { if (mxArgc < 1) mxSyntaxError("no URI Component parameter"); fxToString(the, mxArgv(0)); fxDecodeURI(the, (txString)gxURIEmptySet); }
void fxParseJSONArray(txMachine* the, txJSONParser* theParser) { txSlot* anArray; txIndex aLength; txSlot* anItem; fxGetNextJSONToken(the, theParser); mxPush(mxArrayPrototype); anArray = fxNewArrayInstance(the); aLength = 0; anItem = fxLastProperty(the, anArray); for (;;) { if (theParser->token == XS_JSON_TOKEN_RIGHT_BRACKET) break; fxParseJSONValue(the, theParser); aLength++; anItem->next = fxNewSlot(the); anItem = anItem->next; anItem->kind = the->stack->kind; anItem->value = the->stack->value; the->stack++; if (theParser->token != XS_JSON_TOKEN_COMMA) break; fxGetNextJSONToken(the, theParser); } anArray->next->value.array.length = aLength; fxCacheArray(the, anArray); if (theParser->token != XS_JSON_TOKEN_RIGHT_BRACKET) mxSyntaxError("missing ]"); fxGetNextJSONToken(the, theParser); }
void fx_decodeURI(txMachine* the) { if (mxArgc < 1) mxSyntaxError("no URI parameter"); fxToString(the, mxArgv(0)); fxDecodeURI(the, (txString)gxURIReservedSet); }
txInteger fxCheckVar(txMachine* the, txInteger theIndex) { #if mxBoundsCheck if ((theIndex < 0) || (mxVarc <= theIndex)) mxSyntaxError("C: xsVar(%ld): invalid index", theIndex); #endif return theIndex; }
void fxSetHostData(txMachine* the, txSlot* slot, void* theData) { txSlot* host = fxCheckHostObject(the, slot); if (host) host->value.host.data = theData; else mxSyntaxError("C: xsSetHostData: no host object"); }
void* fxGetHostData(txMachine* the, txSlot* slot) { txSlot* host = fxCheckHostObject(the, slot); if (host) return host->value.host.data; mxSyntaxError("C: xsGetHostData: no host object"); return NULL; }
void fx_Date_UTC(txMachine* the) { txTimeDescription td; c_time_t time; txNumber number; if (mxArgc < 1) mxSyntaxError("no year parameter"); td.tm.tm_year = fxToInteger(the, mxArgv(0)); if ((td.tm.tm_year < 0) || (99 < td.tm.tm_year)) td.tm.tm_year -= 1900; if (mxArgc < 2) mxSyntaxError("no month parameter"); td.tm.tm_mon = fxToInteger(the, mxArgv(1)); if (mxArgc > 2) td.tm.tm_mday = fxToInteger(the, mxArgv(2)); else td.tm.tm_mday = 1; if (mxArgc > 3) td.tm.tm_hour = fxToInteger(the, mxArgv(3)); else td.tm.tm_hour = 0; if (mxArgc > 4) td.tm.tm_min = fxToInteger(the, mxArgv(4)); else td.tm.tm_min = 0; if (mxArgc > 5) td.tm.tm_sec = fxToInteger(the, mxArgv(5)); else td.tm.tm_sec = 0; if (mxArgc > 6) td.ms = fxToInteger(the, mxArgv(6)); else td.ms = 0; td.tm.tm_isdst = 0; time = c_mktime(&(td.tm)); if (time == -1) number = NAN; else { number = (time * 1000.0) + td.ms; number -= gxDeltaTime; } mxResult->value.number = number; mxResult->kind = XS_NUMBER_KIND; }
void fxParseJSON(txMachine* the, txJSONParser* theParser) { mxPush(mxEmptyString); theParser->string = the->stack; fxGetNextJSONToken(the, theParser); fxParseJSONValue(the, theParser); if (theParser->token != XS_JSON_TOKEN_EOF) mxSyntaxError("missing EOF"); }
void fxSetHostDestructor(txMachine* the, txSlot* slot, txDestructor theDestructor) { txSlot* host = fxCheckHostObject(the, slot); if (host) { host->flag &= ~XS_HOST_HOOKS_FLAG; host->value.host.variant.destructor = theDestructor; } else mxSyntaxError("C: xsSetHostDestructor: no host object"); }
void fxSetHostHooks(txMachine* the, txSlot* slot, txHostHooks* theHooks) { txSlot* host = fxCheckHostObject(the, slot); if (host) { host->flag |= XS_HOST_HOOKS_FLAG; host->value.host.variant.hooks = theHooks; } else mxSyntaxError("C: xsSetHostHooks: no host object"); }
void fxSerializeJSON(txMachine* the, txJSONSerializer* theSerializer) { txSlot* aSlot; txInteger aFlag; aSlot = fxGetInstance(the, mxThis); theSerializer->offset = 0; theSerializer->size = 1024; theSerializer->buffer = c_malloc(1024); if (!theSerializer->buffer) mxUnknownError("out of memory"); if (mxArgc > 1) { aSlot = mxArgv(1); if (mxIsReference(aSlot)) { aSlot = fxGetInstance(the, aSlot); if (mxIsFunction(aSlot)) theSerializer->replacer = mxArgv(1); else if (mxIsArray(aSlot)) mxSyntaxError("not yet implememented"); } } if (mxArgc > 2) { aSlot = mxArgv(2); if (mxIsReference(aSlot)) { aSlot = fxGetInstance(the, aSlot); if (mxIsNumber(aSlot) || mxIsString(aSlot)) aSlot = aSlot->next; } if ((aSlot->kind == XS_INTEGER_KIND) || (aSlot->kind == XS_NUMBER_KIND)) { txInteger aCount = fxToInteger(the, aSlot), anIndex; if (aCount < 0) aCount = 0; else if (aCount > 10) aCount = 10; for (anIndex = 0; anIndex < aCount; anIndex++) theSerializer->indent[anIndex] = ' '; } else if (mxIsStringPrimitive(aSlot)) c_strncpy((char *)theSerializer->indent, aSlot->value.string, 10); } theSerializer->stack = the->stack; mxPush(mxObjectPrototype); fxNewObjectInstance(the); aFlag = 0; if (mxArgc > 0) mxPushSlot(mxArgv(0)); else mxPushUndefined(); mxPush(mxEmptyString); fxSerializeJSONProperty(the, theSerializer, &aFlag); the->stack++; }
txInteger fxCheckArg(txMachine* the, txInteger theIndex) { txInteger aCount = mxArgc; #if mxBoundsCheck #if !mxOptimize if ((theIndex < 0) || (aCount <= theIndex)) mxSyntaxError("C: xsArg(%ld): invalid index", theIndex); return aCount - 1 - theIndex; #else aCount -= theIndex; if (aCount >= 0) return aCount - 1; mxSyntaxError("C: xsArg(%ld): invalid index", theIndex); return 0; // never happens #endif #else return aCount - theIndex - 1; #endif }
void fxVars(txMachine* the, txInteger theCount) { txSlot* aStack = the->frame - 1; if (aStack != the->stack) mxSyntaxError("C: xsVars: too late"); fxOverflow(the, theCount, C_NULL, 0); aStack->value.integer = theCount; while (theCount) { mxPushUndefined(); theCount--; } }
void fx_Symbol_keyFor(txMachine* the) { txSlot* slot; txSlot* key; if (mxArgc < 1) mxSyntaxError("no sym parameter"); slot = fxCheckSymbol(the, mxArgv(0)); if (!slot) mxTypeError("sym is no symbol"); key = fxGetKey(the, slot->value.ID); if (key && ((key->flag & XS_DONT_ENUM_FLAG) == 0)) { mxResult->kind = XS_STRING_KIND; mxResult->value.string = key->value.key.string; } }
void fx_JSON_parse(txMachine* the) { volatile txJSONParser* aParser = C_NULL; txSlot* slot; mxTry(the) { if (mxArgc < 1) mxSyntaxError("no buffer"); aParser = c_malloc(sizeof(txJSONParser)); if (NULL == aParser) mxUnknownError("out of memory"); c_memset((txJSONParser*)aParser, 0, sizeof(txJSONParser)); if (mxArgc > 1) { slot = mxArgv(1); if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference; if (slot->next && ((slot->next->kind == XS_CODE_KIND) || (slot->next->kind == XS_CODE_X_KIND) || (slot->next->kind == XS_CALLBACK_KIND))) aParser->reviver = slot; } } slot = mxArgv(0); if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference->next; if (slot && (slot->flag & XS_INTERNAL_FLAG) && (slot->kind == XS_HOST_KIND)) { aParser->data = slot->value.host.data; aParser->offset = 0; mxPushSlot(mxArgv(0)); fxGetID(the, mxID(_length)); aParser->size = fxToInteger(the, the->stack++); } } if (!aParser->data) { fxToString(the, mxArgv(0)); aParser->slot = mxArgv(0); aParser->offset = 0; aParser->size = c_strlen(aParser->slot->value.string); } fxParseJSON(the, (txJSONParser*)aParser); mxPullSlot(mxResult); c_free((txJSONParser*)aParser); // @@ reviver } mxCatch(the) { if (aParser) c_free((txJSONParser*)aParser); fxJump(the); } }
void fx_Symbol_for(txMachine* the) { txString string; txU1* p; txU4 sum; txU4 modulo; txSlot* result; txID index; if (mxArgc < 1) mxSyntaxError("no key parameter"); string = fxToString(the, mxArgv(0)); p = (txU1*)string; sum = 0; while(*p != 0) { sum = (sum << 1) + *p++; } sum &= 0x7FFFFFFF; modulo = sum % the->symbolModulo; result = the->symbolTable[modulo]; while (result != C_NULL) { if (result->value.key.sum == sum) if (c_strcmp(result->value.key.string, string) == 0) break; result = result->next; } if (result == C_NULL) { index = the->keyIndex; if (index == the->keyCount) mxUnknownError("not enough IDs"); result = fxNewSlot(the); result->next = the->symbolTable[modulo]; result->kind = XS_KEY_KIND; result->ID = 0x8000 | index; result->value.key.string = mxArgv(0)->value.string; result->value.key.sum = sum; the->keyArray[index] = result; the->keyIndex++; the->symbolTable[modulo] = result; } mxResult->kind = XS_SYMBOL_KIND; mxResult->value.ID = result->ID; }
void fxParseJSONValue(txMachine* the, txJSONParser* theParser) { switch (theParser->token) { case XS_JSON_TOKEN_FALSE: mxPushBoolean(0); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_TRUE: mxPushBoolean(1); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_NULL: mxPushNull(); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_INTEGER: mxPushInteger(theParser->integer); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_NUMBER: mxPushNumber(theParser->number); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_STRING: mxPushString(theParser->string->value.string); fxGetNextJSONToken(the, theParser); break; case XS_JSON_TOKEN_LEFT_BRACE: fxParseJSONObject(the, theParser); break; case XS_JSON_TOKEN_LEFT_BRACKET: fxParseJSONArray(the, theParser); break; default: mxPushUndefined(); mxSyntaxError("invalid value"); break; } }
void fx_encodeURI(txMachine* the) { if (mxArgc < 1) mxSyntaxError("no URI parameter"); fxEncodeURI(the, (txString)gxURIReservedAndUnescapedSet); }
void fx_encodeURIComponent(txMachine* the) { if (mxArgc < 1) mxSyntaxError("no URI Component parameter"); fxEncodeURI(the, (txString)gxURIUnescapedSet); }
void fxGetNextJSONToken(txMachine* the, txJSONParser* theParser) { txString p; txString q; txString r; txString s; char c; txInteger i; txBoolean escaped; txNumber number; txU4 size; txU4 value; const txUTF8Sequence* sequence; txString string; theParser->integer = 0; theParser->number = 0; theParser->string->value.string = mxEmptyString.value.string; theParser->token = XS_NO_JSON_TOKEN; r = (theParser->data) ? theParser->data : theParser->slot->value.string; p = r + theParser->offset; q = r + theParser->size; c = (p < q) ? *p : 0; while (theParser->token == XS_NO_JSON_TOKEN) { switch (c) { case 0: theParser->token = XS_JSON_TOKEN_EOF; break; case '\n': case '\r': case '\t': case ' ': c = (++p < q) ? *p : 0; break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': s = p; if (c == '-') c = (++p < q) ? *p : 0; if (('0' <= c) && (c <= '9')) { if (c == '0') { c = (++p < q) ? *p : 0; } else { c = (++p < q) ? *p : 0; while (('0' <= c) && (c <= '9')) { c = (++p < q) ? *p : 0; } } if (c == '.') { c = (++p < q) ? *p : 0; if (('0' <= c) && (c <= '9')) { c = (++p < q) ? *p : 0; while (('0' <= c) && (c <= '9')) { c = (++p < q) ? *p : 0; } } else mxSyntaxError("invalid character in number"); } if ((c == 'e') || (c == 'E')) { c = (++p < q) ? *p : 0; if ((c== '+') || (c == '-')) { c = (++p < q) ? *p : 0; } if (('0' <= c) && (c <= '9')) { c = (++p < q) ? *p : 0; while (('0' <= c) && (c <= '9')) { c = (++p < q) ? *p : 0; } } else mxSyntaxError("invalid character in number"); } size = p - s; if ((size + 1) > sizeof(the->nameBuffer)) mxSyntaxError("number overflow"); c_memcpy(the->nameBuffer, s, size); the->nameBuffer[size] = 0; theParser->number = fxStringToNumber(the->dtoa, the->nameBuffer, 0); theParser->integer = (txInteger)theParser->number; number = theParser->integer; if (theParser->number == number) theParser->token = XS_JSON_TOKEN_INTEGER; else theParser->token = XS_JSON_TOKEN_NUMBER; } else mxSyntaxError("invalid character in number"); break; case ',': p++; theParser->token = XS_JSON_TOKEN_COMMA; break; case ':': p++; theParser->token = XS_JSON_TOKEN_COLON; break; case '[': p++; theParser->token = XS_JSON_TOKEN_LEFT_BRACKET; break; case ']': p++; theParser->token = XS_JSON_TOKEN_RIGHT_BRACKET; break; case '{': p++; theParser->token = XS_JSON_TOKEN_LEFT_BRACE; break; case '}': p++; theParser->token = XS_JSON_TOKEN_RIGHT_BRACE; break; case '"': c = (++p < q) ? *p : 0; s = p; escaped = 0; size = 0; for (;;) { if ((0 <= c) && (c < 32)) { mxSyntaxError("invalid character in string"); break; } else if (c == '"') { break; } else if (c == '\\') { escaped = 1; c = (++p < q) ? *p : 0; switch (c) { case '"': case '/': case '\\': case 'b': case 'f': case 'n': case 'r': case 't': size++; c = (++p < q) ? *p : 0; break; case 'u': value = 0; for (i = 0; i < 4; i++) { c = (++p < q) ? *p : 0; if (('0' <= c) && (c <= '9')) value = (value * 16) + (c - '0'); else if (('a' <= c) && (c <= 'f')) value = (value * 16) + (10 + c - 'a'); else if (('A' <= c) && (c <= 'F')) value = (value * 16) + (10 + c - 'A'); else mxSyntaxError("invalid character in string"); } // surrogate pair? for (sequence = gxUTF8Sequences; sequence->size; sequence++) if (value <= sequence->lmask) break; size += sequence->size; c = (++p < q) ? *p : 0; break; default: mxSyntaxError("invalid character in string"); break; } } else { size++; c = (++p < q) ? *p : 0; } } { txSize after = p - r; txSize before = s - r; string = theParser->string->value.string = (txString)fxNewChunk(the, size + 1); r = (theParser->data) ? theParser->data : theParser->slot->value.string; p = r + after; q = r + theParser->size; s = r + before; } if (escaped) { p = s; c = *p; for (;;) { if (c == '"') { break; } else if (c == '\\') { p++; c = *p; switch (c) { case '"': case '/': case '\\': *string++ = c; p++; c = *p; break; case 'b': *string++ = '\b'; p++; c = *p; break; case 'f': *string++ = '\f'; p++; c = *p; break; case 'n': *string++ = '\n'; p++; c = *p; break; case 'r': *string++ = '\r'; p++; c = *p; break; case 't': *string++ = '\t'; p++; c = *p; break; case 'u': value = 0; for (i = 0; i < 4; i++) { p++; c = *p; if (('0' <= c) && (c <= '9')) value = (value * 16) + (c - '0'); else if (('a' <= c) && (c <= 'f')) value = (value * 16) + (10 + c - 'a'); else value = (value * 16) + (10 + c - 'A'); } // surrogate pair? string = (txString)fsX2UTF8(value, (txU1*)string, 0x7FFFFFFF); p++; c = *p; break; } } else { *string++ = c; p++; c = *p; } } *string = 0; } else { c_memcpy(string, s, size); string[size] = 0; } p++; theParser->token = XS_JSON_TOKEN_STRING; break; default: if ((q - p >= 5) && (!c_strncmp(p, "false", 5))) { p += 5; theParser->token = XS_JSON_TOKEN_FALSE; } else if ((q - p >= 4) && (!c_strncmp(p, "null", 4))) { p += 4; theParser->token = XS_JSON_TOKEN_NULL; } else if ((q - p >= 4) && (!c_strncmp(p, "true", 4))) { p += 4; theParser->token = XS_JSON_TOKEN_TRUE; } else mxSyntaxError("invalid character"); break; } } theParser->offset = p - r; }
void fxNewInstanceOf(txMachine* the) { txSlot* aParent; if (the->stack->kind == XS_NULL_KIND) { txSlot* instance = fxNewSlot(the); instance->kind = XS_INSTANCE_KIND; instance->value.instance.garbage = C_NULL; instance->value.instance.prototype = C_NULL; the->stack->value.reference = instance; the->stack->kind = XS_REFERENCE_KIND; } else { fxToInstance(the, the->stack); aParent = fxGetInstance(the, the->stack); if (aParent->flag & XS_VALUE_FLAG) { switch (aParent->next->kind) { case XS_CALLBACK_KIND: case XS_CODE_KIND: fxNewFunctionInstance(the, XS_NO_ID); break; case XS_ARRAY_KIND: fxNewArrayInstance(the); break; case XS_STRING_KIND: case XS_STRING_X_KIND: fxNewStringInstance(the); break; case XS_BOOLEAN_KIND: fxNewBooleanInstance(the); break; case XS_NUMBER_KIND: fxNewNumberInstance(the); break; case XS_DATE_KIND: fxNewDateInstance(the); break; case XS_REGEXP_KIND: fxNewRegExpInstance(the); break; case XS_SYMBOL_KIND: fxNewSymbolInstance(the); break; case XS_HOST_KIND: fxNewHostInstance(the); break; case XS_PROMISE_KIND: fxNewPromiseInstance(the); break; case XS_PROXY_KIND: fxNewProxyInstance(the); break; case XS_MAP_KIND: fxNewMapInstance(the); break; case XS_SET_KIND: fxNewSetInstance(the); break; case XS_WEAK_MAP_KIND: fxNewWeakMapInstance(the); break; case XS_WEAK_SET_KIND: fxNewWeakSetInstance(the); break; case XS_ARRAY_BUFFER_KIND: fxNewArrayBufferInstance(the); break; case XS_DATA_VIEW_KIND: fxNewDataViewInstance(the); break; case XS_TYPED_ARRAY_KIND: fxNewTypedArrayInstance(the, aParent->next->value.typedArray); break; case XS_STACK_KIND: fxNewGeneratorInstance(the); break; default: mxSyntaxError("C: xsNewInstanceOf: invalid prototype"); break; } } else fxNewObjectInstance(the); } }