void fx_Error_toString(txMachine* the) { txInteger aLength; mxPushSlot(mxThis); fxGetID(the, mxID(_name)); if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, "Error"); else fxToString(the, the->stack); mxPushSlot(mxThis); fxGetID(the, mxID(_message)); if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, ""); else fxToString(the, the->stack); aLength = c_strlen(the->stack->value.string); if (aLength) { aLength += c_strlen((the->stack + 1)->value.string) + 2; mxResult->value.string = (txString)fxNewChunk(the, aLength + 1); mxResult->kind = XS_STRING_KIND; c_strcpy(mxResult->value.string, (the->stack + 1)->value.string); c_strcat(mxResult->value.string, ": "); c_strcat(mxResult->value.string, the->stack->value.string); the->stack++; the->stack++; } else { the->stack++; mxPullSlot(mxResult); } }
void fx_Number_prototype_toString(txMachine* the) { char buffer[256]; txInteger radix; txSlot* slot = fxCheckNumber(the, mxThis); if (!slot) mxTypeError("this is no number"); if (mxArgc > 0) { radix = fxToInteger(the, mxArgv(0)); if (radix) { if ((radix < 2) || (36 < radix)) mxRangeError("invalid radix"); } else radix = 10; } else radix = 10; mxResult->kind = slot->kind; mxResult->value = slot->value; if (radix == 10) fxToString(the, mxResult); else { static char gxDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; txString string = buffer + sizeof(buffer); txNumber value; txBoolean minus; value = mxResult->value.number; switch (c_fpclassify(value)) { case C_FP_INFINITE: if (value < 0) fxCopyStringC(the, mxResult, "-Infinity"); else fxCopyStringC(the, mxResult, "Infinity"); break; case C_FP_NAN: fxCopyStringC(the, mxResult, "NaN"); break; case C_FP_ZERO: fxCopyStringC(the, mxResult, "0"); break; default: *(--string) = 0; if (value < 0) { minus = 1; value = -value; } else minus = 0; do { *(--string) = gxDigits[(txInteger)c_fmod(value, radix)]; value = value / radix; } while (value >= 1); if (minus) *(--string) = '-'; fxCopyStringC(the, mxResult, string); } } }
void fxBuildKeys(txMachine* the) { txArchive* archive = the->archive; if (archive && archive->keys) (*archive->keys)(the); else { #ifdef mxParse txSlot* code = &mxIDs; txID c, i; if (archive) { c = archive->symbolCount; code->value.code = (txByte *)fxNewChunk(the, c * sizeof(txID)); code->kind = XS_CODE_KIND; for (i = 0; i < XS_SYMBOL_ID_COUNT; i++) { txString string = archive->symbols[i]; txID id = the->keyIndex; txSlot* description = fxNewSlot(the); description->flag = XS_DONT_ENUM_FLAG; fxCopyStringC(the, description, string); the->keyArray[id] = description; the->keyIndex++; mxID(i) = 0x8000 | id; } for (; i < c; i++) { txString string = archive->symbols[i]; mxID(i) = fxNewNameX(the, string)->ID; } } else { code->value.code = (txByte *)fxNewChunk(the, XS_ID_COUNT * sizeof(txID)); code->kind = XS_CODE_KIND; for (i = 0; i < XS_SYMBOL_ID_COUNT; i++) { txID id = the->keyIndex; txSlot* description = fxNewSlot(the); description->flag = XS_DONT_ENUM_FLAG; fxCopyStringC(the, description, gxIDStrings[i]); the->keyArray[id] = description; the->keyIndex++; mxID(i) = 0x8000 | id; } for (; i < XS_ID_COUNT; i++) { mxID(i) = fxID(the, gxIDStrings[i]); } } #else fxCheck(the, __FILE__, __LINE__); #endif } }
void fxSymbolToString(txMachine* the, txSlot* slot) { txSlot* key = fxGetKey(the, slot->value.ID); fxCopyStringC(the, slot, "Symbol("); if (key) fxConcatStringC(the, slot, key->value.string); fxConcatStringC(the, slot, ")"); }
txSlot* fxNextStringProperty(txMachine* the, txSlot* property, txString string, txID id, txFlag flag) { property = property->next = fxNewSlot(the); property->flag = flag; property->ID = id; fxCopyStringC(the, property, string); return property; }
void fx_Date_prototype_toUTCString(txMachine* the) { char buffer[256]; txTimeDescription td; txSlot* slot = fx_Date_prototype_getUTC_aux(the, &td); if (slot) c_strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S GMT", &(td.tm)); else c_strcpy(buffer, "Invalid Date"); fxCopyStringC(the, mxResult, buffer); }
void fx_Number_prototype_toPrecision(txMachine* the) { char buffer[256]; int precision; txSlot* slot = fxCheckNumber(the, mxThis); if (!slot) mxTypeError("this is no number"); if (mxArgc > 0) precision = fxToInteger(the, mxArgv(0)); else precision = 0; fxNumberToString(the->dtoa, slot->value.number, buffer, sizeof(buffer), 'g', precision); fxCopyStringC(the, mxResult, buffer); }
void fx_Error_toString(txMachine* the) { txSlot* anError; txSlot* aProperty; txInteger aLength; anError = fxGetInstance(the, mxThis); aProperty = fxGetProperty(the, anError, fxID(the, "name")); --the->stack; the->stack->kind = aProperty->kind; the->stack->value = aProperty->value; if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, "Error"); else fxToString(the, the->stack); aProperty = fxGetProperty(the, anError, fxID(the, "message")); --the->stack; the->stack->kind = aProperty->kind; the->stack->value = aProperty->value; if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, ""); else fxToString(the, the->stack); aLength = c_strlen(the->stack->value.string); if (aLength) { aLength += c_strlen((the->stack + 1)->value.string) + 2; mxResult->value.string = (txString)fxNewChunk(the, aLength + 1); mxResult->kind = XS_STRING_KIND; c_strcpy(mxResult->value.string, (the->stack + 1)->value.string); c_strcat(mxResult->value.string, ": "); c_strcat(mxResult->value.string, the->stack->value.string); the->stack++; the->stack++; } else { the->stack++; *mxResult = *(the->stack++); } }
void fx_Date_prototype_toJSON(txMachine* the) { char buffer[256]; int c; txTimeDescription td; txSlot* slot = fx_Date_prototype_getUTC_aux(the, &td); if (slot) { c_strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", &(td.tm)); c = c_strlen(buffer); snprintf(buffer + c, sizeof(buffer) - c, ".%03dZ", td.ms); } else c_strcpy(buffer, "Invalid Date"); fxCopyStringC(the, mxResult, buffer); }
void fx_Number_toString(txMachine* the) { txSlot* aNumber; txSlot* aProperty; txInteger aRadix; aNumber = fxGetInstance(the, mxThis); mxCheckNumber(aNumber); aProperty = aNumber->next; if (mxArgc > 0) { aRadix = fxToInteger(the, mxArgv(0)); if (aRadix) { if ((aRadix < 2) || (36 < aRadix)) mxDebug0(the, XS_RANGE_ERROR, "invalid radix"); } else aRadix = 10; } else aRadix = 10; mxResult->kind = aProperty->kind; mxResult->value = aProperty->value; if (aRadix == 10) fxToString(the, mxResult); else { static char gxDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char aBuffer[256]; txString aString; txNumber aValue; txBoolean aMinus; fxToNumber(the, mxResult); aString = aBuffer + sizeof(aBuffer); *(--aString) = 0; aValue = mxResult->value.number; if (aValue < 0) { aMinus = 1; aValue = -aValue; } else aMinus = 0; do { *(--aString) = gxDigits[(txInteger)c_fmod(aValue, aRadix)]; aValue = aValue / aRadix; } while (aValue >= 1); if (aMinus) *(--aString) = '-'; fxCopyStringC(the, mxResult, aString); } }
void fx_Number_toPrecision(txMachine* the) { txSlot* aNumber; txSlot* aProperty; int aPrecision; char aBuffer[256]; aNumber = fxGetInstance(the, mxThis); mxCheckNumber(aNumber); aProperty = aNumber->next; if (mxArgc > 0) aPrecision = fxToInteger(the, mxArgv(0)); else aPrecision = 0; fxNumberToString(the, aProperty->value.number, aBuffer, sizeof(aBuffer), 'g', aPrecision); fxCopyStringC(the, mxResult, aBuffer); }
void fx_Function_prototype_get_name(txMachine* the) { txSlot* instance = fxCheckFunctionInstance(the, mxThis); txSlot* info = mxFunctionInstanceInfo(instance); txSlot* key = fxGetKey(the, info->value.info.name); if (key) { if (key->kind == XS_KEY_KIND) { mxResult->kind = XS_STRING_KIND; mxResult->value.string = key->value.key.string; } else if (key->kind == XS_KEY_X_KIND) { mxResult->kind = XS_STRING_X_KIND; mxResult->value.string = key->value.key.string; } else { fxCopyStringC(the, mxResult, "["); fxConcatStringC(the, mxResult, key->value.string); fxConcatStringC(the, mxResult, "]"); } return; } *mxResult = mxEmptyString; }
void fxKeyAt(txMachine* the, txID id, txIndex index, txSlot* slot) { if (id) { txSlot* key = fxGetKey(the, id); if (key && (key->flag & XS_DONT_ENUM_FLAG)) { if (key->kind == XS_KEY_KIND) { slot->kind = XS_STRING_KIND; slot->value.string = key->value.key.string; } else{ slot->kind = XS_STRING_X_KIND; slot->value.string = key->value.key.string; } } else { slot->kind = XS_SYMBOL_KIND; slot->value.symbol = id; } } else { char buffer[16]; fxCopyStringC(the, slot, fxNumberToString(the->dtoa, index, buffer, sizeof(buffer), 0, 0)); } }
void fxIDToSlot(txMachine* the, txInteger id, txSlot* slot) { if (id < 0) { txSlot* key = fxGetKey(the, (txID)id); if (key && (key->flag & XS_DONT_ENUM_FLAG)) { if (key->kind == XS_KEY_KIND) { slot->kind = XS_STRING_KIND; slot->value.string = key->value.key.string; } else { slot->kind = XS_STRING_X_KIND; slot->value.string = key->value.key.string; } } else { slot->kind = XS_SYMBOL_KIND; slot->value.ID = (txID)id; } } else { char buffer[16]; fxCopyStringC(the, slot, fxIntegerToString(the->dtoa, id, buffer, sizeof(buffer))); } }
txString fxToString(txMachine* the, txSlot* theSlot) { char aBuffer[256]; again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: fxCopyStringC(the, theSlot, "undefined"); break; case XS_NULL_KIND: fxCopyStringC(the, theSlot, "null"); break; case XS_BOOLEAN_KIND: if (theSlot->value.boolean == 0) fxCopyStringC(the, theSlot, "false"); else fxCopyStringC(the, theSlot, "true"); break; case XS_INTEGER_KIND: fxCopyStringC(the, theSlot, fxIntegerToString(the->dtoa, theSlot->value.integer, aBuffer, sizeof(aBuffer))); break; case XS_NUMBER_KIND: fxCopyStringC(the, theSlot, fxNumberToString(the->dtoa, theSlot->value.number, aBuffer, sizeof(aBuffer), 0, 0)); break; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to string"); break; case XS_STRING_KIND: case XS_STRING_X_KIND: break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_STRING_HINT); goto again; default: mxTypeError("Cannot coerce to string"); break; } return theSlot->value.string; }
void fx_Function(txMachine* the) { txSlot* aFunction; txInteger aCount, anIndex, aFileIndex, aLineIndex; txFlag aFlag; txSlot* aSlot; txStringStream aStream; txByte* aCode; txSlot* aProperty; if (mxResult->kind == XS_UNDEFINED_KIND) { mxPush(mxFunctionPrototype); aFunction = fxNewFunctionInstance(the); *mxResult = *(the->stack++); } else aFunction = fxGetOwnInstance(the, mxResult); mxCheckFunction(aFunction); aCount = mxArgc; anIndex = 0; aFileIndex = aCount - 2; aLineIndex = aCount - 1; aFlag = XS_NO_FLAG; if ((aCount >= 4) && (mxArgv(aLineIndex)->kind == XS_INTEGER_KIND)) { aCount -= 2; aFlag |= XS_DEBUG_FLAG; } aSlot = fxGetInstance(the, mxThis); if (aSlot && (aSlot->flag & XS_SANDBOX_FLAG)) aFlag |= XS_SANDBOX_FLAG; else aFlag |= the->frame->next->flag & XS_SANDBOX_FLAG; mxZeroSlot(--the->stack); fxCopyStringC(the, the->stack, "("); while (aCount > 1) { fxToString(the, mxArgv(anIndex)); fxConcatString(the, the->stack, mxArgv(anIndex)); if (aCount > 2) fxConcatStringC(the, the->stack, ", "); aCount--; anIndex++; } fxConcatStringC(the, the->stack, "){"); if (aCount > 0) { fxToString(the, mxArgv(anIndex)); fxConcatString(the, the->stack, mxArgv(anIndex)); } fxConcatStringC(the, the->stack, "}"); aStream.slot = the->stack; aStream.offset = 0; aStream.size = c_strlen(the->stack->value.string); #ifdef mxDebug if (aFlag & XS_DEBUG_FLAG) aCode = fxParseScript(the, &aStream, fxStringGetter, fxNewFile(the, mxArgv(aFileIndex)), mxArgv(aLineIndex)->value.integer, aFlag, C_NULL); else #endif aCode = fxParseScript(the, &aStream, fxStringGetter, C_NULL, 0, aFlag, C_NULL); aFunction->next->value.code = aCode; aProperty = fxSetProperty(the, aFunction, the->bodyID, C_NULL); aProperty->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; aProperty->value.string = mxArgv(anIndex)->value.string; aProperty->kind = mxArgv(anIndex)->kind; the->stack++; }
void fxString(txMachine* the, txSlot* theSlot, txString theValue) { fxCopyStringC(the, theSlot, theValue); }
void fxGetNextJSONToken(txScriptParser* theParser) { txMachine* the = theParser->the; int c; txString p; txString q; txString r; txString s; txU4 t = 0; txNumber aNumber; theParser->line = theParser->line2; theParser->crlf = theParser->crlf2; theParser->escaped = theParser->escaped2; theParser->flags->value.string = theParser->flags2->value.string; theParser->integer = theParser->integer2; theParser->number = theParser->number2; theParser->string->value.string = theParser->string2->value.string; theParser->symbol = theParser->symbol2; theParser->token = theParser->token2; theParser->crlf2 = 0; theParser->escaped2 = 0; theParser->flags2->value.string = mxEmptyString.value.string; theParser->integer2 = 0; theParser->number2 = 0; theParser->string2->value.string = mxEmptyString.value.string; theParser->symbol2 = C_NULL; theParser->token2 = XS_NO_TOKEN; while (theParser->token2 == XS_NO_TOKEN) { switch (theParser->character) { case C_EOF: theParser->token2 = XS_TOKEN_EOF; break; case 10: theParser->line2++; fxGetNextCharacter(theParser); theParser->crlf2 = 1; break; case 13: theParser->line2++; fxGetNextCharacter(theParser); if (theParser->character == 10) fxGetNextCharacter(theParser); theParser->crlf2 = 1; break; case '\t': case ' ': fxGetNextCharacter(theParser); break; case '0': fxGetNextCharacter(theParser); c = theParser->character; if (c == '.') { fxGetNextCharacter(theParser); c = theParser->character; if ((('0' <= c) && (c <= '9')) || (c == 'e') || (c == 'E')) fxGetNextNumber(theParser, 0); else { theParser->number2 = 0; theParser->token2 = XS_TOKEN_NUMBER; } } else if ((c == 'e') || (c == 'E')) { fxGetNextNumber(theParser, 0); } else if ((c == 'x') || (c == 'X')) { p = theParser->buffer; *p++ = '0'; *p++ = 'x'; for (;;) { fxGetNextCharacter(theParser); c = theParser->character; if (('0' <= c) && (c <= '9')) *p++ = c; else if (('A' <= c) && (c <= 'Z')) *p++ = c; else if (('a' <= c) && (c <= 'z')) *p++ = c; else break; } *p = 0; theParser->number2 = fxStringToNumber(theParser->the, theParser->buffer, 1); theParser->integer2 = (txInteger)theParser->number2; aNumber = theParser->integer2; if (theParser->number2 == aNumber) theParser->token2 = XS_TOKEN_INTEGER; else theParser->token2 = XS_TOKEN_NUMBER; } else { theParser->integer2 = 0; theParser->token2 = XS_TOKEN_INTEGER; } break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': fxGetNextNumber(theParser, 1); break; case ',': theParser->token2 = XS_TOKEN_COMMA; fxGetNextCharacter(theParser); break; case ':': theParser->token2 = XS_TOKEN_COLON; fxGetNextCharacter(theParser); break; case '[': theParser->token2 = XS_TOKEN_LEFT_BRACKET; fxGetNextCharacter(theParser); break; case ']': theParser->token2 = XS_TOKEN_RIGHT_BRACKET; fxGetNextCharacter(theParser); break; case '{': theParser->token2 = XS_TOKEN_LEFT_BRACE; fxGetNextCharacter(theParser); break; case '}': theParser->token2 = XS_TOKEN_RIGHT_BRACE; fxGetNextCharacter(theParser); break; case '"': p = theParser->buffer; q = p + sizeof(theParser->buffer) - 1; r = C_NULL; fxGetNextCharacter(theParser); for (;;) { if (theParser->character == C_EOF) { fxReportParserError(theParser, "end of file in string"); break; } else if ((theParser->character == 10) || (theParser->character == 13)) { fxReportParserError(theParser, "end of line in string"); break; } else if ((0 <= theParser->character) && (theParser->character < 32)) { fxReportParserError(theParser, "invalid character in string"); break; } else if (theParser->character == '"') { fxGetNextCharacter(theParser); break; } else if (theParser->character == '"') { fxGetNextCharacter(theParser); break; } else if (theParser->character == '\\') { theParser->escaped2 = 1; r = C_NULL; fxGetNextCharacter(theParser); switch (theParser->character) { case 10: theParser->line2++; fxGetNextCharacter(theParser); break; case 13: theParser->line2++; fxGetNextCharacter(theParser); if (theParser->character == 10) fxGetNextCharacter(theParser); break; case '\'': if (p < q) *p++ = '\''; fxGetNextCharacter(theParser); break; case '"': if (p < q) *p++ = '"'; fxGetNextCharacter(theParser); break; case '\\': if (p < q) *p++ = '\\'; fxGetNextCharacter(theParser); break; case '0': if (p < q) *p++ = 0; fxGetNextCharacter(theParser); break; case 'b': if (p < q) *p++ = '\b'; fxGetNextCharacter(theParser); break; case 'f': if (p < q) *p++ = '\f'; fxGetNextCharacter(theParser); break; case 'n': if (p < q) *p++ = '\n'; fxGetNextCharacter(theParser); break; case 'r': if (p < q) *p++ = '\r'; fxGetNextCharacter(theParser); break; case 't': if (p < q) *p++ = '\t'; fxGetNextCharacter(theParser); break; case 'u': r = p; t = 5; if (p < q) *p++ = 'u'; fxGetNextCharacter(theParser); break; case 'v': if (p < q) *p++ = '\v'; fxGetNextCharacter(theParser); break; case 'x': r = p; t = 3; if (p < q) *p++ = 'x'; fxGetNextCharacter(theParser); break; default: p = (txString)fsX2UTF8(theParser, theParser->character, (txU1*)p, q - p); fxGetNextCharacter(theParser); break; } } else { p = (txString)fsX2UTF8(theParser, theParser->character, (txU1*)p, q - p); if (r) { if ((txU4)(p - r) > t) r = C_NULL; else if (((txU4)(p - r) == t) && (p < q)) { *p = 0; t = c_strtoul(r + 1, &s, 16); if (!*s) p = (txString)fsX2UTF8(theParser, t, (txU1*)r, q - r); r = C_NULL; } } fxGetNextCharacter(theParser); } } *p = 0; if (p == q) fxReportParserError(theParser, "string overflow"); fxCopyStringC(theParser->the, theParser->string2, theParser->buffer); theParser->token2 = XS_TOKEN_STRING; break; default: if (fxIsIdentifierFirst(theParser->character)) { p = theParser->buffer; q = p + sizeof(theParser->buffer) - 1; for (;;) { if (p == q) { fxReportParserError(theParser, "identifier overflow"); break; } *p++ = theParser->character; fxGetNextCharacter(theParser); if (!fxIsIdentifierNext(theParser->character)) break; } *p = 0; fxGetNextJSONKeyword(theParser); } else { mxDebug1(theParser->the, XS_SYNTAX_ERROR, "invalid character %d", theParser->character); fxGetNextCharacter(theParser); } break; } } }
void fx_xs_debug_getAddress(txMachine* the) { fxCopyStringC(the, mxResult, fxGetAddress(the)); }
void fx_Date(txMachine* the) { txTimeDescription td; c_timeval tv; char buffer[256]; c_time_t time; txNumber number; if ((mxThis->kind == XS_REFERENCE_KIND) && ((mxThis->value.reference->flag & XS_SHARED_FLAG) == 0)) { txSlot* anInstance = mxThis->value.reference; if (mxIsDate(anInstance)) { if (mxArgc > 1) { td.tm.tm_year = fxToInteger(the, mxArgv(0)); if ((td.tm.tm_year < 0) || (99 < td.tm.tm_year)) td.tm.tm_year -= 1900; 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 = -1; time = c_mktime(&(td.tm)); if (time == -1) number = NAN; else number = (time * 1000.0) + td.ms; } else if (mxArgc > 0) { number = fxToNumber(the, mxArgv(0)); } else { c_gettimeofday(&tv, NULL); // According to 15.9.1.1, time precision in JS is milliseconds number = ((txNumber)(tv.tv_sec) * 1000.0) + ((txNumber)(tv.tv_usec / 1000)); } anInstance->next->value.number = number; *mxResult = *mxThis; } return; } { c_time_t sec; c_gettimeofday(&tv, NULL); sec = tv.tv_sec; // necessary because on Windows tv.tv_sec is a long (32 bits), which is diffrent from time_t (64 bits) td.tm = *c_localtime(&sec); c_strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S", &(td.tm)); fxCopyStringC(the, mxResult, buffer); } }