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 luaO_chunkid (char *out, const char *source, size_t bufflen) { if (*source == '=') { c_strncpy(out, source+1, bufflen); /* remove first char */ out[bufflen-1] = '\0'; /* ensures null termination */ } else { /* out = "source", or "...source" */ if (*source == '@') { size_t l; source++; /* skip the `@' */ bufflen -= sizeof(" '...' "); l = c_strlen(source); c_strcpy(out, ""); if (l > bufflen) { source += (l-bufflen); /* get last part of file name */ c_strcat(out, "..."); } c_strcat(out, source); } else { /* out = [string "string"] */ size_t len = c_strcspn(source, "\n\r"); /* stop at first newline */ bufflen -= sizeof(" [string \"...\"] "); if (len > bufflen) len = bufflen; c_strcpy(out, "[string \""); if (source[len] != '\0') { /* must truncate? */ c_strncat(out, source, len); c_strcat(out, "..."); } else c_strcat(out, source); c_strcat(out, "\"]"); } } }
txModuleData* fxLoadLibrary(txMachine* the, txString path, txScript* script) { txModuleData* data = C_NULL; if (script) { if (script->version[3] == 1) { char buffer[PATH_MAX]; char* dot; void* library; txCallback callback; c_strcpy(buffer, path); dot = c_strrchr(buffer, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(buffer, ".dll"); #if mxReport fxReport(the, "# Loading library \"%s\"\n", buffer); #endif library = LoadLibrary(buffer); mxElseError(library); callback = (txCallback)GetProcAddress(library, "xsHostModule"); mxElseError(callback); #else c_strcat(buffer, ".so"); #if mxReport fxReport(the, "# Loading library \"%s\"\n", buffer); #endif library = dlopen(buffer, RTLD_NOW); mxElseError(library); callback = (txCallback)dlsym(library, "xsHostModule"); mxElseError(callback); #endif data = c_malloc(sizeof(txModuleData) + c_strlen(buffer)); mxElseError(data); data->library = library; data->the = the; c_strcpy(data->path, buffer); script->callback = callback; return data; } } #if mxReport data = c_malloc(sizeof(txModuleData) + c_strlen(path)); mxElseError(data); data->library = C_NULL; data->the = the; c_strcpy(data->path, path); fxReport(the, "# Loading module \"%s\"\n", path); #endif return data; }
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 fxIncludeScript(txParser* parser, txString string) { txSymbol* symbol = parser->path; char buffer[PATH_MAX]; char include[PATH_MAX]; FILE* file = NULL; c_strcpy(include, string); c_strcat(include, ".js"); fxMergePath(symbol->string, include, buffer); mxParserThrowElse(realpath(buffer, include)); parser->path = fxNewParserSymbol(parser, include); file = fopen(include, "r"); mxParserThrowElse(file); fxParserTree(parser, file, (txGetter)fgetc, parser->flags, NULL); fclose(file); file = NULL; parser->path = symbol; }
void fx_String_concat(txMachine* the) { txString aString; txInteger aCount; txInteger aLength; txInteger anIndex; aString = fxCoerceToString(the, mxThis); if (!aString) mxDebug0(the, XS_TYPE_ERROR, "String.prototype.concat: this is null or undefined"); aCount = mxArgc; aLength = c_strlen(mxThis->value.string); for (anIndex = 0; anIndex < aCount; anIndex++) aLength += c_strlen(fxToString(the, mxArgv(anIndex))); mxResult->value.string = (txString)fxNewChunk(the, aLength + 1); mxResult->kind = XS_STRING_KIND; c_strcpy(mxResult->value.string, mxThis->value.string); for (anIndex = 0; anIndex < aCount; anIndex++) c_strcat(mxResult->value.string, mxArgv(anIndex)->value.string); }
void* fxMapArchive(txString base, txCallbackAt callbackAt) { int error = 0; txArchive* archive = C_NULL; #if mxWindows #else struct stat statbuf; #endif txString p; Atom atom; int c, i; txString* symbol; txScript* script; archive = c_malloc(sizeof(txArchive)); bailElse(archive); c_memset(archive, 0, sizeof(txArchive)); c_strcpy(archive->base, base); #if mxWindows archive->file = CreateFile(base, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); bailElse(archive->file != INVALID_HANDLE_VALUE); archive->size = GetFileSize(archive->file, &archive->size); bailElse(archive->size != INVALID_FILE_SIZE); archive->mapping = CreateFileMapping(archive->file, NULL, PAGE_READONLY, 0, (SIZE_T)archive->size, NULL); bailElse(archive->mapping != INVALID_HANDLE_VALUE); archive->address = MapViewOfFile(archive->mapping, FILE_MAP_READ, 0, 0, (SIZE_T)archive->size); bailElse(archive->address != NULL); #else archive->fd = open(base, O_RDONLY); bailElse(archive->fd >= 0); fstat(archive->fd, &statbuf); archive->size = statbuf.st_size; archive->address = mmap(NULL, archive->size, PROT_READ, MAP_SHARED, archive->fd, 0); bailElse(archive->address != MAP_FAILED); #endif p = archive->address; p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_ARCHIVE); p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); if ((*p++) && !callbackAt) { char* dot; dot = c_strrchr(archive->base, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(archive->base, ".dll"); archive->library = LoadLibrary(archive->base); bailElse(archive->library); callbackAt = (txCallbackAt)GetProcAddress(archive->library, "xsHostModuleAt"); bailElse(callbackAt); #else c_strcat(archive->base, ".so"); archive->library = dlopen(archive->base, RTLD_NOW); if (!archive->library) fprintf(stderr, "%s\n", dlerror()); bailElse(archive->library); callbackAt = (txCallbackAt)dlsym(archive->library, "xsHostModuleAt"); bailElse(callbackAt); #endif archive->keys = callbackAt(0); } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); c = archive->symbolCount = ntohs(*((unsigned short*)p)); p += 2; if (c) { symbol = archive->symbols = c_malloc(c * sizeof(txString)); for (i = 0; i < c; i++) { *symbol = p; p += c_strlen(p) + 1; symbol++; } } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_PATHS); c = archive->scriptCount = ntohs(*((unsigned short*)p)); p += 2; script = archive->scripts = c_malloc(c * sizeof(txScript)); c_memset(script, 0, c * sizeof(txScript)); for (i = 1; i <= c; i++) { if (callbackAt) script->callback = callbackAt(i); script->path = p; p += c_strlen(p) + 1; script++; } script = archive->scripts; for (i = 0; i < c; i++) { p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = (txS1*)p; p += script->codeSize; script++; } p = c_strrchr(archive->base, mxSeparator); if (p) { p++; *p = 0; archive->baseLength = p - archive->base; } bail: if (error) { fxUnmapArchive(archive); archive = C_NULL; } return archive; }
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; }
void* fxMapArchive(txString base, txCallbackAt callbackAt) { FskErr err = kFskErrNone; txArchive* archive = NULL; txString p; Atom atom; int c, i; txString* symbol; txScript* script; bailIfError(FskMemPtrNewClear(sizeof(txArchive), &archive)); c_strcpy(archive->base, base); bailIfError(FskFileMap(base, (unsigned char**)&(archive->address), &(archive->size), 0, &(archive->map))); p = archive->address; p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_ARCHIVE); p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_VERSION); bailAssert(*p++ == XS_MAJOR_VERSION); bailAssert(*p++ == XS_MINOR_VERSION); bailAssert(*p++ == XS_PATCH_VERSION); if ((*p++) && !callbackAt) { char* dot; dot = c_strrchr(archive->base, '.'); if (dot) *dot = 0; #if mxWindows c_strcat(archive->base, ".dll"); #else c_strcat(archive->base, ".so"); #endif bailIfError(FskLibraryLoad(&(archive->library), archive->base)); bailIfError(FskLibraryGetSymbolAddress(archive->library, "xsHostModuleAt", &callbackAt)); archive->keys = callbackAt(0); } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_SYMBOLS); mxDecode2(p, archive->symbolCount); c = archive->symbolCount; if (c) { bailIfError(FskMemPtrNew(c * sizeof(txString), &(archive->symbols))); symbol = archive->symbols; for (i = 0; i < c; i++) { *symbol = p; p += c_strlen(p) + 1; symbol++; } } p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_PATHS); mxDecode2(p, archive->scriptCount); c = archive->scriptCount; bailIfError(FskMemPtrNewClear(c * sizeof(txScript), &(archive->scripts))); script = archive->scripts; for (i = 1; i <= c; i++) { if (callbackAt) script->callback = callbackAt(i); script->path = p; bailIfNULL(script->path); p += c_strlen(p) + 1; script++; } script = archive->scripts; for (i = 0; i < c; i++) { p = fxMapAtom(p, &atom); bailAssert(atom.atomType == XS_ATOM_CODE); script->codeSize = atom.atomSize - sizeof(atom); script->codeBuffer = (txS1*)p; p += script->codeSize; script++; } p = c_strrchr(archive->base, '/'); if (p) { p++; *p = 0; archive->baseLength = p - archive->base; } bail: if (err) { fxUnmapArchive(archive); archive = NULL; } return archive; }