diff --git a/sjasm/sjasm.cpp b/sjasm/sjasm.cpp index 49b91e10..5884cbeb 100644 --- a/sjasm/sjasm.cpp +++ b/sjasm/sjasm.cpp @@ -206,7 +206,7 @@ byte* MemoryPointer=NULL; int macronummer = 0, lijst = 0, reglenwidth = 0; TextFilePos CurSourcePos, DefinitionPos; uint32_t maxlin = 0; -aint CurAddress = 0, CompiledCurrentLine = 0, LastParsedLabelLine = 0; +aint CurAddress = 0, CompiledCurrentLine = 0, LastParsedLabelLine = 0, PredefinedCounter = 0; aint destlen = 0, size = -1L,PreviousErrorLine = -1L, comlin = 0; char* CurrentDirectory=NULL; @@ -282,6 +282,13 @@ void InitPass() { DefineTable.Replace("__ERRORS__", "0"); // migrated from _ERRORS DefineTable.Replace("__WARNINGS__", "0"); // migrated from _WARNINGS DefineTable.Replace("__PASS__", pass); // current pass of assembler + DefineTable.Replace("__INCLUDE_LEVEL__", "-1"); // include nesting + DefineTable.Replace("__BASE_FILE__", ""); // the include-level 0 file + DefineTable.Replace("__FILE__", ""); // current file + DefineTable.Replace("__LINE__", ""); // current line in current file + DefineTable.Replace("__COUNTER__", ""); // gcc-like, incremented upon every use + PredefinedCounter = 0; + // resurrect "global" device here if (globalDeviceID && !SetDevice(globalDeviceID, globalDeviceZxRamTop)) { Error("Failed to re-initialize global device", globalDeviceID, FATAL); diff --git a/sjasm/sjasm.h b/sjasm/sjasm.h index e9af4ce7..8807bd67 100644 --- a/sjasm/sjasm.h +++ b/sjasm/sjasm.h @@ -136,7 +136,7 @@ extern byte* MemoryPointer; extern int macronummer, lijst, reglenwidth; extern TextFilePos CurSourcePos, DefinitionPos; extern uint32_t maxlin; -extern aint CurAddress, CompiledCurrentLine, LastParsedLabelLine; +extern aint CurAddress, CompiledCurrentLine, LastParsedLabelLine, PredefinedCounter; extern aint destlen, size, PreviousErrorLine, comlin; extern char* vorlabp, * macrolabp, * LastParsedLabel; diff --git a/sjasm/sjio.cpp b/sjasm/sjio.cpp index 733d0965..831dac86 100644 --- a/sjasm/sjio.cpp +++ b/sjasm/sjio.cpp @@ -610,6 +610,11 @@ void OpenFile(const char* nfilename, bool systemPathsBeforeCurrent, stdin_log_t* fileNameFull = ofnIt->c_str(); // get const pointer into archive CurSourcePos.newFile(Options::IsShowFullPath ? fileNameFull : FilenameBasePos(fileNameFull)); + // refresh pre-defined values related to file/include + DefineTable.Replace("__INCLUDE_LEVEL__", IncludeLevel); + DefineTable.Replace("__FILE__", fileNameFull); + if (0 == IncludeLevel) DefineTable.Replace("__BASE_FILE__", fileNameFull); + // open default listing file for each new source file (if default listing is ON) if (LASTPASS == pass && 0 == IncludeLevel && Options::IsDefaultListingName) { OpenDefaultList(fullpath); // explicit listing file is already opened @@ -665,6 +670,11 @@ void OpenFile(const char* nfilename, bool systemPathsBeforeCurrent, stdin_log_t* } fileNameFull = oFileNameFull; CurSourcePos = oSourcePos; + + // refresh pre-defined values related to file/include + DefineTable.Replace("__INCLUDE_LEVEL__", IncludeLevel); + DefineTable.Replace("__FILE__", fileNameFull ? fileNameFull : ""); + if (-1 == IncludeLevel) DefineTable.Replace("__BASE_FILE__", ""); } void IncludeFile(const char* nfilename, bool systemPathsBeforeCurrent) diff --git a/sjasm/tables.cpp b/sjasm/tables.cpp index f5ef086c..b945a817 100644 --- a/sjasm/tables.cpp +++ b/sjasm/tables.cpp @@ -654,8 +654,23 @@ void CDefineTable::Add(const char* name, const char* value, CStringsList* nss) { defs[(*name)&127] = new CDefineTableEntry(name, value, nss, defs[(*name)&127]); } +static char defineGet__Counter__Buffer[32] = {}; +static char defineGet__Line__Buffer[32] = {}; + char* CDefineTable::Get(const char* name) { if (NULL != name) { + // the __COUNTER__ and __LINE__ have fully dynamic custom implementation here + if ('_' == name[1]) { + if (!strcmp(name, "__COUNTER__")) { + SPRINTF1(defineGet__Counter__Buffer, 30, "%d", PredefinedCounter); + ++PredefinedCounter; + return defineGet__Counter__Buffer; + } + if (!strcmp(name, "__LINE__")) { + SPRINTF1(defineGet__Line__Buffer, 30, "%d", CurSourcePos.line); + return defineGet__Line__Buffer; + } + } CDefineTableEntry* p = defs[(*name)&127]; while (p) { if (!strcmp(name, p->name)) { diff --git a/tests/define/predefined_base_file.asm b/tests/define/predefined_base_file.asm new file mode 100644 index 00000000..0a4cafac --- /dev/null +++ b/tests/define/predefined_base_file.asm @@ -0,0 +1,21 @@ + ; the __FILE__ and __LINE__ values are raw without quotes, so they are currently + ; difficult to use with sjasmplus, the Lua script can manipulate them well + ; but sjasmplus itself would need maybe some string operators... or even more? + OUTPUT "predefined_base_file.bin" + + DB 0, 1, 2, 3, 255, 254, 253, 252, 10, 10, 10 ; make sure git doesn't treat this as text file + DB "Main file before INCLUDE:\n" + LUA ALLPASS + _pc("DB \"base: " .. sj.get_define("__BASE_FILE__") .. "\\n\"") + _pc("DB \"file: " .. sj.get_define("__FILE__") .. "\\n\"") + _pc("DB \"ENDLUA line: " .. sj.get_define("__LINE__") .. "\\n\"") + ENDLUA + + INCLUDE "predefined_base_file.i.asm" + + DB "Main file after INCLUDE:\n" + LUA ALLPASS + _pc("DB \"base: " .. sj.get_define("__BASE_FILE__") .. "\\n\"") + _pc("DB \"file: " .. sj.get_define("__FILE__") .. "\\n\"") + _pc("DB \"ENDLUA line: " .. sj.get_define("__LINE__") .. "\\n\"") + ENDLUA diff --git a/tests/define/predefined_base_file.bin b/tests/define/predefined_base_file.bin new file mode 100644 index 00000000..ccaa6391 Binary files /dev/null and b/tests/define/predefined_base_file.bin differ diff --git a/tests/define/predefined_base_file.i.asm b/tests/define/predefined_base_file.i.asm new file mode 100644 index 00000000..d42c7c41 --- /dev/null +++ b/tests/define/predefined_base_file.i.asm @@ -0,0 +1,28 @@ + IF 1 == __INCLUDE_LEVEL__ + + DB "Before second INCLUDE:\n" + LUA ALLPASS + _pc("DB \"base: " .. sj.get_define("__BASE_FILE__") .. "\\n\"") + _pc("DB \"file: " .. sj.get_define("__FILE__") .. "\\n\"") + _pc("DB \"ENDLUA line: " .. sj.get_define("__LINE__") .. "\\n\"") + ENDLUA + + INCLUDE "predefined_base_file.i.asm" + + DB "After second INCLUDE:\n" + LUA ALLPASS + _pc("DB \"base: " .. sj.get_define("__BASE_FILE__") .. "\\n\"") + _pc("DB \"file: " .. sj.get_define("__FILE__") .. "\\n\"") + _pc("DB \"ENDLUA line: " .. sj.get_define("__LINE__") .. "\\n\"") + ENDLUA + + ELSE + + DB "Inside second INCLUDE:\n" + LUA ALLPASS + _pc("DB \"base: " .. sj.get_define("__BASE_FILE__") .. "\\n\"") + _pc("DB \"file: " .. sj.get_define("__FILE__") .. "\\n\"") + _pc("DB \"ENDLUA line: " .. sj.get_define("__LINE__") .. "\\n\"") + ENDLUA + + ENDIF diff --git a/tests/define/predefined_counter.asm b/tests/define/predefined_counter.asm new file mode 100644 index 00000000..cc98f95c --- /dev/null +++ b/tests/define/predefined_counter.asm @@ -0,0 +1,16 @@ + DB __COUNTER__ + +TestLabel__COUNTER__: + ; ^^ does NOT work, because "_" at beginning of __COUNTER__ + ; prevents sub-word substitution = TODO for sjasmplus v2.x + + LUA ALLPASS ; as usually, lua for the rescue + sj.insert_label("lua_label_" .. sj.get_define("__COUNTER__"), sj.current_address) + sj.add_byte(sj.get_define("__COUNTER__")) + sj.insert_label("lua_label_" .. sj.get_define("__COUNTER__"), sj.current_address) + sj.add_byte(sj.get_define("__COUNTER__")) + sj.insert_label("lua_label_" .. sj.get_define("__COUNTER__"), sj.current_address) + sj.add_byte(sj.get_define("__COUNTER__")) + ENDLUA + + DB __COUNTER__ diff --git a/tests/define/predefined_counter.lst b/tests/define/predefined_counter.lst new file mode 100644 index 00000000..5a3b0dea --- /dev/null +++ b/tests/define/predefined_counter.lst @@ -0,0 +1,26 @@ +# file opened: predefined_counter.asm + 1 0000 00 DB 0 + 2 0001 + 3 0001 TestLabel__COUNTER__: + 4 0001 ; ^^ does NOT work, because "_" at beginning of __COUNTER__ + 5 0001 ; prevents sub-word substitution = TODO for sjasmplus v2.x + 6 0001 + 7 0001 LUA ALLPASS ; as usually, lua for the rescue + 8 0001 ~ sj.insert_label("lua_label_" .. sj.get_define("__COUNTER__"), sj.current_address) + 9 0001 ~ sj.add_byte(sj.get_define("__COUNTER__")) +10 0001 ~ sj.insert_label("lua_label_" .. sj.get_define("__COUNTER__"), sj.current_address) +11 0001 ~ sj.add_byte(sj.get_define("__COUNTER__")) +12 0001 ~ sj.insert_label("lua_label_" .. sj.get_define("__COUNTER__"), sj.current_address) +13 0001 ~ sj.add_byte(sj.get_define("__COUNTER__")) +14 0001 02 04 06 ENDLUA +15 0004 +16 0004 07 DB 7 +17 0005 +# file closed: predefined_counter.asm + +Value Label +------ - ----------------------------------------------------------- +0x0001 X TestLabel__COUNTER__ +0x0001 X lua_label_1 +0x0002 X lua_label_3 +0x0003 X lua_label_5 diff --git a/tests/define/predefined_include_level.asm b/tests/define/predefined_include_level.asm new file mode 100644 index 00000000..0468950d --- /dev/null +++ b/tests/define/predefined_include_level.asm @@ -0,0 +1,19 @@ + IFNDEF MAIN_FILE + DEFINE MAIN_FILE + OUTPUT "predefined_include_level.bin" +myIncludeLevel = 0 + ENDIF + + ; before another INCLUDE + ASSERT __INCLUDE_LEVEL__ == myIncludeLevel + DB __INCLUDE_LEVEL__, myIncludeLevel + + IF myIncludeLevel < 6 +myIncludeLevel = myIncludeLevel + 1 + INCLUDE "predefined_include_level.asm" +myIncludeLevel = myIncludeLevel - 1 + ENDIF + + ; after another INCLUDE + ASSERT __INCLUDE_LEVEL__ == myIncludeLevel + DB __INCLUDE_LEVEL__, myIncludeLevel diff --git a/tests/define/predefined_include_level.bin b/tests/define/predefined_include_level.bin new file mode 100644 index 00000000..057bea6e Binary files /dev/null and b/tests/define/predefined_include_level.bin differ