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; }
txBoolean fxFindURI(txMachine* the, txString base, txString name, txString dot, txID* id) { char path[PATH_MAX]; txSlot* key; if (*dot) { fxMergePath(base, name, path); if (fxFindArchive(the, path) || fxFindFile(the, path)) { key = fxNewNameC(the, path); *id = key->ID; return 1; } } else { txString* extension; for (extension = gxExtensions; *extension; extension++) { c_strcpy(dot, *extension); fxMergePath(base, name, path); if (fxFindArchive(the, path) || fxFindFile(the, path)) { key = fxNewNameC(the, path); *id = key->ID; return 1; } } *dot = 0; } *id = XS_NO_ID; return 0; }
void fxLoadModule(txMachine* the, txID moduleID) { txArchive* archive = the->archive; txSlot* key = fxGetKey(the, moduleID); char buffer[PATH_MAX]; txString path = buffer; txString dot; txString* extension; txLoader* loader; c_strcpy(path, key->value.key.string); if (archive) { if (!c_strncmp(path, archive->base, archive->baseLength)) { txInteger c = archive->scriptCount, i; txScript* script = archive->scripts; path += archive->baseLength; for (i = 0; i < c; i++) { if (!c_strcmp(path, script->path)) { fxResolveModule(the, moduleID, script, fxLoadLibrary(the, key->value.key.string, C_NULL), fxUnloadLibrary); return; } script++; } } } dot = c_strrchr(path, '.'); for (extension = gxExtensions, loader = gxLoaders; *extension; extension++, loader++) { if (!c_strcmp(dot, *extension)) { (**loader)(the, buffer, moduleID); return; } } }
txBoolean fxFindArchive(txMachine* the, txString path) { txArchive* archive = the->archive; if (archive) { if (!c_strncmp(path, archive->base, archive->baseLength)) { txInteger c = archive->scriptCount; txScript* script = archive->scripts; char name[PATH_MAX]; c_strcpy(name, path + archive->baseLength); #if mxWindows { char* separator = name; while (*separator) { if (*separator == '/') *separator = mxSeparator; separator++; } } #endif while (c > 0) { if (!c_strcmp(name, script->path)) return 1; c--; script++; } } } return 0; }
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); } }
static void addintlen (char *form) { size_t l = c_strlen(form); char spec = form[l - 1]; c_strcpy(form + l - 1, LUA_INTFRMLEN); form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; }
/* ** add length modifier into formats */ static void addlenmod (char *form, const char *lenmod) { size_t l = c_strlen(form); size_t lm = c_strlen(lenmod); char spec = form[l - 1]; c_strcpy(form + l - 1, lenmod); form[l + lm - 1] = spec; form[l + lm] = '\0'; }
txBoolean fxFindFile(txMachine* the, txString path) { char real[PATH_MAX]; if (realpath(path, real)) { c_strcpy(path, real); return 1; } return 0; }
void fxParseJSON(txMachine* the, void* theStream, txGetter theGetter) { txSlot* aStack = the->stack; txScriptParser *aParser; aParser = the->parser; if (NULL == aParser) { aParser = c_malloc(sizeof(txScriptParser)); if (NULL == aParser) { const char *msg = "Out of memory!"; #ifdef mxDebug fxDebugLoop(the, (char *)msg); #endif fxThrowMessage(the, XS_UNKNOWN_ERROR, (char *)msg); } the->parser = aParser; } c_memset(aParser, 0, sizeof(txScriptParser) - sizeof(aParser->buffer)); aParser->the = the; aParser->stream = theStream; aParser->getter = theGetter; aParser->path = C_NULL; aParser->line2 = 0; mxZeroSlot(--the->stack); aParser->flags = the->stack; aParser->flags->value.string = mxEmptyString.value.string; aParser->flags->kind = mxEmptyString.kind; mxZeroSlot(--the->stack); aParser->string = the->stack; aParser->string->value.string = mxEmptyString.value.string; aParser->string->kind = mxEmptyString.kind; mxZeroSlot(--the->stack); aParser->flags2 = the->stack; aParser->flags2->value.string = mxEmptyString.value.string; aParser->flags2->kind = mxEmptyString.kind; mxZeroSlot(--the->stack); aParser->string2 = the->stack; aParser->string2->value.string = mxEmptyString.value.string; aParser->string2->kind = mxEmptyString.kind; fxGetNextCharacter(aParser); fxGetNextJSONToken(aParser); fxGetNextJSONToken(aParser); fxParseJSONValue(aParser); fxMatchToken(aParser, XS_TOKEN_EOF); if (aParser->errorCount > 0) { the->stack = aStack; c_strcpy(aParser->buffer, "JSON error(s)!"); #ifdef mxDebug fxDebugLoop(the, aParser->buffer); #endif fxThrowMessage(the, XS_SYNTAX_ERROR, aParser->buffer); } }
// Lua: compile(filename) -- compile lua file into lua bytecode, and save to .lc static int node_compile( lua_State* L ) { Proto* f; int file_fd = FS_OPEN_OK - 1; size_t len; const char *fname = luaL_checklstring( L, 1, &len ); if ( len > FS_NAME_MAX_LENGTH ) return luaL_error(L, "filename too long"); char output[FS_NAME_MAX_LENGTH]; c_strcpy(output, fname); // check here that filename end with ".lua". if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) return luaL_error(L, "not a .lua file"); output[c_strlen(output) - 2] = 'c'; output[c_strlen(output) - 1] = '\0'; NODE_DBG(output); NODE_DBG("\n"); if (luaL_loadfsfile(L, fname) != 0) { return luaL_error(L, lua_tostring(L, -1)); } f = toproto(L, -1); int stripping = 1; /* strip debug information? */ file_fd = fs_open(output, fs_mode2flag("w+")); if (file_fd < FS_OPEN_OK) { return luaL_error(L, "cannot open/write to file"); } lua_lock(L); int result = luaU_dump(L, f, writer, &file_fd, stripping); lua_unlock(L); if (fs_flush(file_fd) < 0) { // result codes aren't propagated by flash_fs.h // overwrite Lua error, like writer() does in case of a file io error result = 1; } fs_close(file_fd); file_fd = FS_OPEN_OK - 1; if (result == LUA_ERR_CC_INTOVERFLOW) { return luaL_error(L, "value too big or small for target integer type"); } if (result == LUA_ERR_CC_NOTINTEGER) { return luaL_error(L, "target lua_Number is integral but fractional value found"); } if (result == 1) { // result status generated by writer() or fs_flush() fail return luaL_error(L, "writing to file failed"); } return 0; }
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_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 fxIDToString(txMachine* the, txInteger id, txString theBuffer, txSize theSize) { if (id < 0) { id &= 0x7FFF; if (id < the->keyCount) { txSlot* key = the->keyArray[id]; if (key) { if ((key->kind == XS_KEY_KIND) || (key->kind == XS_KEY_X_KIND)) snprintf(theBuffer, theSize, "%s", key->value.key.string); else if ((key->kind == XS_STRING_KIND) || (key->kind == XS_STRING_X_KIND)) snprintf(theBuffer, theSize, "[%s]", key->value.string); else c_strcpy(theBuffer, ""); } else c_strcpy(theBuffer, ""); } else c_strcpy(theBuffer, "?"); } else fxIntegerToString(the->dtoa, id, theBuffer, theSize); }
void fxDebugID(txMachine* the, txError theError, txString theFormat, txID theID) { char aBuffer[16]; txString aString = aBuffer; txSlot* aSymbol; aSymbol = fxGetSymbol(the, theID); if (aSymbol) aString = aSymbol->value.symbol.string; else if (theID != XS_NO_ID) fxIntegerToString(theID, aBuffer, sizeof(aBuffer)); else c_strcpy(aBuffer, "?"); fxDebug(the, theError, theFormat, aString); }
void fxLoadModule(txMachine* the, txID moduleID) { txArchive* archive = the->archive; txSlot* key = fxGetKey(the, moduleID); txString path = NULL; char buffer[PATH_MAX]; txString dot = NULL; txString* extension; txLoader* loader; KprURLToPath(key->value.key.string, &path); c_strcpy(buffer, path); c_free(path); path = buffer; if (archive) { if (!c_strncmp(path, archive->base, archive->baseLength)) { txInteger c = archive->scriptCount, i; txScript* script = archive->scripts; path += archive->baseLength; #if mxWindows { char* separator = path; while (*separator) { if (*separator == '/') *separator = mxSeparator; separator++; } } #endif for (i = 0; i < c; i++) { if (!c_strcmp(path, script->path)) { fxResolveModule(the, moduleID, script, C_NULL, C_NULL); return; } script++; } } } dot = FskStrRChr(path, '.'); for (extension = gxExtensions, loader = gxLoaders; *extension; extension++, loader++) { if (!FskStrCompare(dot, *extension)) { (**loader)(the, buffer, moduleID); break; } } }
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 readFrame(const char *Eof,const char *Eom, const char *Som, char *RET,unsigned int SZ, size_t TIMEOUT) { uint32_t now = 0; char *ptr; char *end; int min_sz = 0; size_t i = 0; char ret[BUFFER_SZ]; if( Eof != NULL && Eom != NULL && Som != NULL && RET != NULL && SZ != 0) { now = system_get_time() + (TIMEOUT * 1000000); min_sz = strlen(Eof); c_memset(RET, 0 , SZ); while( now > system_get_time() ) { system_soft_wdt_feed (); if( uart_getc(&ret[i & 0x1FF]) ) { if( ret[i] == 0 ) i--; i++; if( i >= min_sz ) { if( c_strstr(ret,Eof) != NULL ) { if( (ptr = c_strstr(ret,Som)) != NULL ) { ptr += strlen(Som); if( (end = c_strstr(ptr,Eom)) != NULL ) { *end = 0; c_strcpy(RET,ptr); return; } }else return; } } } } } }
void fxReadAddressAutomatic(txMachine* the) { /* read debugAddress and debugAutomatic from a file... */ #if TARGET_OS_ANDROID char *folder = NULL; char *file = FskStrDoCat(folder, "/sdcard/debug.txt"); { #else char *folder; if (kFskErrNone == FskDirectoryGetSpecialPath(kFskDirectorySpecialTypeApplicationPreference, true, NULL, &folder)) { char *file = FskStrDoCat(folder, "debug.txt"); #endif char *data; if (kFskErrNone == FskFileLoad(file, (FskMemPtr *)&data, NULL)) { char *lf = FskStrChr(data, 10); if ((NULL != lf) && (FskStrLen(data) < sizeof(debugAddress))) { *lf = 0; FskStrCopy(debugAddress, data); debugAutomatic = '1' == lf[1]; } FskMemPtrDispose(data); } else { FskECMAScriptGetDebug(&data, NULL, NULL); if (data) { FskStrCopy(debugAddress, data); FskStrCat(debugAddress, ":5002"); debugAutomatic = 1; } } FskMemPtrDispose(file); FskMemPtrDispose(folder); } } void fxSetAddress(txMachine* the, char* theAddress) { c_strcpy(debugAddress, theAddress); fxWriteAddressAutomatic(the); }
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); }
txSlot* fxNewNameC(txMachine* the, txString theString) { txU1* string; txU4 sum; txU4 modulo; txSlot* result; txID index; string = (txU1*)theString; sum = 0; while(*string != 0) { sum = (sum << 1) + *string++; } sum &= 0x7FFFFFFF; modulo = sum % the->nameModulo; result = the->nameTable[modulo]; while (result != C_NULL) { if (result->value.key.sum == sum) if (c_strcmp(result->value.key.string, theString) == 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->nameTable[modulo]; result->flag = XS_DONT_ENUM_FLAG; result->kind = XS_KEY_KIND; result->ID = 0x8000 | index; result->value.key.string = C_NULL; result->value.key.sum = sum; the->keyArray[index] = result; the->keyIndex++; the->nameTable[modulo] = result; result->value.key.string = (txString)fxNewChunk(the, c_strlen(theString) + 1); c_strcpy(result->value.key.string, theString); } return result; }
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++); } }
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) { 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; }
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; }
txID fxFindModule(txMachine* the, txID moduleID, txSlot* slot) { char name[PATH_MAX]; char base[PATH_MAX]; txBoolean absolute, relative, search; txSlot *key, *iterator, *result; txString dot, slash; txID id; fxToStringBuffer(the, slot, name, sizeof(name)); if ((!c_strncmp(name, "./", 2)) || (!c_strncmp(name, "../", 3))) { absolute = 0; relative = (moduleID == XS_NO_ID) ? 0 : 1; search = 0; } else if ((!c_strncmp(name, "/", 1))) { absolute = 1; relative = 0; search = 0; } else { absolute = 0; relative = (moduleID == XS_NO_ID) ? 0 : 1; search = 1; } slash = c_strrchr(name, '/'); if (!slash) slash = name; dot = c_strrchr(slash, '.'); if (!dot) dot = name + c_strlen(name); if (absolute) { if (fxFindURI(the, "", name, dot, &id)) return id; } if (relative) { key = fxGetKey(the, moduleID); c_strcpy(base, key->value.key.string); if (fxFindURI(the, base, name, dot, &id)) return id; } if (search) { mxCallID(&mxModulePaths, mxID(_Symbol_iterator), 0); iterator = the->stack; for (;;) { mxCallID(iterator, mxID(_next), 0); result = the->stack; mxGetID(result, mxID(_done)); if (fxToBoolean(the, the->stack)) break; the->stack++; mxGetID(result, mxID(_value)); fxToStringBuffer(the, the->stack++, base, sizeof(base)); if (fxFindURI(the, base, name, dot, &id)) return id; } } mxReferenceError("module \"%s\" not found", name); return XS_NO_ID; }