txInteger fxToInteger(txMachine* the, txSlot* theSlot) { #if mxOptimize if (XS_INTEGER_KIND == theSlot->kind) return theSlot->value.integer; // this is the case over 90% of the time, so avoid the switch #endif again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) theSlot->value.integer = 0; else theSlot->value.integer = 1; break; case XS_INTEGER_KIND: break; case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber >= MODULO / 2) aNumber -= MODULO; else if (aNumber < -MODULO / 2) aNumber += MODULO; theSlot->value.integer = (txInteger)aNumber; } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to integer"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: mxTypeError("Cannot coerce to integer"); break; } return theSlot->value.integer; }
void fx_parseFloat(txMachine* the) { if (mxArgc < 1) { mxResult->value.number = C_NAN; mxResult->kind = XS_NUMBER_KIND; return; } fxToString(the, mxArgv(0)); mxResult->kind = XS_NUMBER_KIND; mxResult->value.number = fxStringToNumber(the->dtoa, mxArgv(0)->value.string, 0); }
txNumber fxToNumber(txMachine* the, txSlot* theSlot) { again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = C_NAN; break; case XS_NULL_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_NUMBER_KIND; if (theSlot->value.boolean == 0) theSlot->value.number = 0; else theSlot->value.number = 1; break; case XS_INTEGER_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = theSlot->value.integer; break; case XS_NUMBER_KIND: break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); break; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to number"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: mxTypeError("Cannot coerce to number"); break; } return theSlot->value.number; }
void fxGetNextNumberE(txParser* parser, int parseDot) { txString p = parser->buffer; if (parser->character == '-') { *p++ = (char)parser->character; fxGetNextCharacter(parser); } if (!parseDot) *p++ = '.'; while (('0' <= parser->character) && (parser->character <= '9')) { *p++ = (char)parser->character; fxGetNextCharacter(parser); } if (parseDot) { if (parser->character == '.') { *p++ = (char)parser->character; fxGetNextCharacter(parser); while (('0' <= parser->character) && (parser->character <= '9')) { *p++ = (char)parser->character; fxGetNextCharacter(parser); } } else *p++ = '.'; } if ((parser->character == 'e') || (parser->character == 'E')) { *p++ = '0'; *p++ = (char)parser->character; fxGetNextCharacter(parser); if ((parser->character == '+') || (parser->character == '-')) { *p++ = (char)parser->character; fxGetNextCharacter(parser); } while (('0' <= parser->character) && (parser->character <= '9')) { *p++ = (char)parser->character; fxGetNextCharacter(parser); } } *p++ = 0; fxGetNextNumber(parser, fxStringToNumber(parser->dtoa, parser->buffer, 1)); }
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; } } }
int main(int argc, char* argv[]) { int argi; txString base = NULL; txString output = NULL; txString input = NULL; char name[PATH_MAX]; char path[PATH_MAX]; txLinker _linker; txLinker* linker = &_linker; txInteger modulo = 0; txLinkerScript** link; txLinkerScript* script; FILE* file = C_NULL; txSize size; txByte byte; fxInitializeLinker(linker); if (c_setjmp(linker->jmp_buf) == 0) { c_strcpy(name, "a"); link = &(linker->firstScript); for (argi = 1; argi < argc; argi++) { if (!c_strcmp(argv[argi], "-a")) { argi++; c_strncpy(name, argv[argi], sizeof(name)); } else if (!c_strcmp(argv[argi], "-b")) { argi++; if (argi >= argc) fxReportError(linker, "-b: no directory"); base = fxRealDirectoryPath(linker, argv[argi]); if (!base) fxReportError(linker, "-b '%s': directory not found", argv[argi]); } else if (!c_strcmp(argv[argi], "-o")) { argi++; if (argi >= argc) fxReportError(linker, "-o: no directory"); output = fxRealDirectoryPath(linker, argv[argi]); if (!output) fxReportError(linker, "-o '%s': directory not found", argv[argi]); } else if (!c_strcmp(argv[argi], "-r")) { argi++; if (argi >= argc) fxReportError(linker, "-r: no modulo"); modulo = (txInteger)fxStringToNumber(linker->dtoa, argv[argi], 1); if (modulo <= 0) fxReportError(linker, "-r: invalid modulo"); linker->symbolModulo = modulo; } else { input = fxRealFilePath(linker, argv[argi]); if (!input) fxReportError(linker, "'%s': file not found", argv[argi]); fxLoadScript(linker, input, link, &file); link = &((*link)->nextScript); } } if (!output) output = fxRealDirectoryPath(linker, "."); if (!base) base = output; linker->symbolTable = fxNewLinkerChunkClear(linker, linker->symbolModulo * sizeof(txSymbol*)); c_strcpy(path, output); c_strcat(path, name); c_strcat(path, ".xsa"); if (!modulo && fxRealFilePath(linker, path)) fxLoadArchive(linker, path, &file); size = c_strlen(base); script = linker->firstScript; while (script) { fxBaseScript(linker, script, base, size); script = script->nextScript; } fxBufferPaths(linker); fxDefaultSymbols(linker); script = linker->firstScript; while (script) { fxMapScript(linker, script); script = script->nextScript; } fxBufferSymbols(linker, modulo); file = fopen(path, "wb"); mxThrowElse(file); size = 8 + 8 + 4 + 8 + linker->symbolsSize + 8 + linker->pathsSize + (8 * linker->scriptCount) + linker->codeSize; size = htonl(size); mxThrowElse(fwrite(&size, 4, 1, file) == 1); mxThrowElse(fwrite("XS6A", 4, 1, file) == 1); size = 8 + 4; size = htonl(size); mxThrowElse(fwrite(&size, 4, 1, file) == 1); mxThrowElse(fwrite("VERS", 4, 1, file) == 1); byte = XS_MAJOR_VERSION; mxThrowElse(fwrite(&byte, 1, 1, file) == 1); byte = XS_MINOR_VERSION; mxThrowElse(fwrite(&byte, 1, 1, file) == 1); byte = XS_PATCH_VERSION; mxThrowElse(fwrite(&byte, 1, 1, file) == 1); byte = (linker->hostsCount) ? 1 : 0; mxThrowElse(fwrite(&byte, 1, 1, file) == 1); size = 8 + linker->symbolsSize; size = htonl(size); mxThrowElse(fwrite(&size, 4, 1, file) == 1); mxThrowElse(fwrite("SYMB", 4, 1, file) == 1); mxThrowElse(fwrite(linker->symbolsBuffer, linker->symbolsSize, 1, file) == 1); size = 8 + linker->pathsSize; size = htonl(size); mxThrowElse(fwrite(&size, 4, 1, file) == 1); mxThrowElse(fwrite("PATH", 4, 1, file) == 1); mxThrowElse(fwrite(linker->pathsBuffer, linker->pathsSize, 1, file) == 1); script = linker->firstScript; while (script) { size = 8 + script->codeSize; size = htonl(size); mxThrowElse(fwrite(&size, 4, 1, file) == 1); mxThrowElse(fwrite("CODE", 4, 1, file) == 1); mxThrowElse(fwrite(script->codeBuffer, script->codeSize, 1, file) == 1); script = script->nextScript; } fclose(file); file = NULL; if (linker->hostsCount || modulo) { c_strcpy(path, base); c_strcat(path, name); c_strcat(path, ".xs.h"); file = fopen(path, "w"); mxThrowElse(file); fprintf(file, "/* XS GENERATED FILE; DO NOT EDIT! */\n\n"); fprintf(file, "#include <xs.h>\n\n"); fxWriteExterns(linker, file); fxWriteIDs(linker, file); fclose(file); file = NULL; c_strcpy(path, base); c_strcat(path, name); c_strcat(path, ".xs.c"); file = fopen(path, "w"); mxThrowElse(file); fprintf(file, "/* XS GENERATED FILE; DO NOT EDIT! */\n\n"); if (modulo) fprintf(file, "#include <xs6All.h>\n\n"); fprintf(file, "#include \"%s.xs.h\"\n\n", name); if (modulo) { txS2 c, i; txSymbol** address; c = (txS2)(linker->symbolIndex); address = &(linker->symbolArray[0]); for (i = 0; i < c; i++) { txSymbol* symbol = *address; fprintf(file, "static const txSlot xs_key_%d = {\n", symbol->ID & 0x7FFF); if (symbol->next) fprintf(file, "\t(txSlot *)&xs_key_%d,\n", symbol->next->ID & 0x7FFF); else fprintf(file, "\tNULL,\n"); if (i < XS_SYMBOL_ID_COUNT) { fprintf(file, "\tXS_NO_ID, XS_DONT_ENUM_FLAG | XS_MARK_FLAG, XS_STRING_X_KIND,\n"); fprintf(file, "\t{ .string = \""); fxWriteSymbolString(linker, file, symbol->string); fprintf(file, "\" }\n"); } else { fprintf(file, "\t%d, XS_DONT_ENUM_FLAG | XS_MARK_FLAG, XS_KEY_X_KIND,\n", (int)symbol->ID); fprintf(file, "\t{ .key = {\""); fxWriteSymbolString(linker, file, symbol->string); fprintf(file, "\", 0x%X} }\n", (int)symbol->sum); } fprintf(file, "};\n"); address++; } fprintf(file, "static const txSlot *xs_keys[%d] = {\n", c); address = &(linker->symbolArray[0]); for (i = 0; i < c; i++) { txSymbol* symbol = *address; fprintf(file, "\t&xs_key_%d,\n", symbol->ID & 0x7FFF); address++; } fprintf(file, "};\n\n"); fprintf(file, "static void xsHostKeys(txMachine* the)\n"); fprintf(file, "{\n"); fprintf(file, "\ttxSlot* code = &mxIDs;\n"); fprintf(file, "\ttxInteger i;\n"); fprintf(file, "\tmxCheck(the, the->nameModulo == %ld);\n", modulo); fprintf(file, "\tcode->value.code = (txByte *)fxNewChunk(the, %d * sizeof(txID));\n", c); fprintf(file, "\tcode->kind = XS_CODE_KIND;\n"); fprintf(file, "\tfor (i = 0; i < XS_SYMBOL_ID_COUNT; i++) {\n"); fprintf(file, "\t\ttxSlot *description = (txSlot *)xs_keys[i];\n"); fprintf(file, "\t\tthe->keyArray[i] = description;\n"); fprintf(file, "\t\tmxID(i) = 0x8000 | i;\n"); fprintf(file, "\t}\n"); fprintf(file, "\tfor (; i < %d; i++) {\n", c); fprintf(file, "\t\ttxSlot *key = (txSlot *)xs_keys[i];\n"); fprintf(file, "\t\tthe->keyArray[i] = key;\n"); fprintf(file, "\t\tthe->nameTable[key->value.key.sum %% %ld] = key;\n", modulo); fprintf(file, "\t\tmxID(i) = key->ID;\n"); fprintf(file, "\t}\n"); fprintf(file, "\tthe->keyIndex = %d;\n", c); fprintf(file, "\tthe->keyOffset = %d;\n", c); fprintf(file, "}\n\n"); } fxWriteHosts(linker, file, modulo); fclose(file); file = NULL; } } else { if (linker->error != C_EINVAL) { #if mxWindows char buffer[2048]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, linker->error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL); fprintf(stderr, "### %s\n", buffer); #else fprintf(stderr, "### %s\n", strerror(linker->error)); #endif } } if (file) fclose(file); fxTerminateLinker(linker); return linker->error; }
txUnsigned fxToUnsigned(txMachine* the, txSlot* theSlot) { txUnsigned result; again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; result = theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) result = theSlot->value.integer = 0; else result = theSlot->value.integer = 1; break; case XS_INTEGER_KIND: if (theSlot->value.integer >= 0) return (txUnsigned)theSlot->value.integer; theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = theSlot->value.integer; // continue case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: result = theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber < 0) aNumber += MODULO; result = (txUnsigned)aNumber; if (((txInteger)result) >= 0) { theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = (txInteger)result; } else { theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = aNumber; } } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: result = 0; mxTypeError("Cannot coerce symbol to unsigned"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: result = 0; mxTypeError("Cannot coerce to unsigned"); break; } return result; }
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; }