diff --git a/README.md b/README.md index 7f5807d..0479154 100644 --- a/README.md +++ b/README.md @@ -647,6 +647,10 @@ Seed the random number generator used by the RND() function. If this is not use Assemble the supplied assembly language string. For example `ASM "LDA #&41"`. +`SOURCELINE [,]` + +For error reporting act as if the following lines started at `` in ``. This is similar to `#line` in C/C++. + ## 7. TIPS AND TRICKS BeebAsm's approach of treating memory as a canvas which can be written to, saved, and rewritten if desired makes it very easy to create certain types of applications. diff --git a/src/asmexception.h b/src/asmexception.h index 6e4ceef..fa28864 100644 --- a/src/asmexception.h +++ b/src/asmexception.h @@ -252,6 +252,7 @@ DEFINE_SYNTAX_EXCEPTION( NoAnonSave, "Cannot specify SAVE without a filename if DEFINE_SYNTAX_EXCEPTION( OnlyOneAnonSave, "Can only use SAVE without a filename once per project." ); DEFINE_SYNTAX_EXCEPTION( TypeMismatch, "Type mismatch." ); DEFINE_SYNTAX_EXCEPTION( OutOfIntegerRange, "Number out of range for a 32-bit integer." ); +DEFINE_SYNTAX_EXCEPTION( SourceLineNotLast, "SOURCELINE must be the final statement on a line." ); diff --git a/src/commands.cpp b/src/commands.cpp index 79e34eb..0024c7e 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "lineparser.h" #include "globaldata.h" @@ -86,7 +87,8 @@ const LineParser::Token LineParser::m_gaTokenTable[] = { N("ERROR"), &LineParser::HandleError, 0 }, { N("COPYBLOCK"), &LineParser::HandleCopyBlock, 0 }, { N("RANDOMIZE"), &LineParser::HandleRandomize, 0 }, - { N("ASM"), &LineParser::HandleAsm, 0 } + { N("ASM"), &LineParser::HandleAsm, 0 }, + { N("SOURCELINE"), &LineParser::HandleSourceLine, 0 } }; #undef N @@ -1887,3 +1889,28 @@ void LineParser::HandleAsm() parser.HandleAssembler(instruction); } + +/*************************************************************************************************/ +/** + LineParser::HandleSourceLine() +*/ +/*************************************************************************************************/ +void LineParser::HandleSourceLine() +{ + ArgListParser args(*this); + int line = args.ParseInt().Range(0, INT_MAX); + StringArg fileParam = args.ParseString(); + args.CheckComplete(); + + if (m_column != m_line.length()) + { + // This must be the last thing on the line + throw AsmException_SyntaxError_SourceLineNotLast( m_line, m_column ); + } + + m_sourceCode->SetLineNumber(line - 1); + if (fileParam.Found()) + { + m_sourceCode->SetFileName(static_cast(fileParam)); + } +} diff --git a/src/lineparser.h b/src/lineparser.h index e1c0d0e..a4a7098 100644 --- a/src/lineparser.h +++ b/src/lineparser.h @@ -168,6 +168,7 @@ class LineParser void HandleCopyBlock(); void HandleRandomize(); void HandleAsm(); + void HandleSourceLine(); // expression evaluating methods diff --git a/src/sourcecode.h b/src/sourcecode.h index d453fea..7a68503 100644 --- a/src/sourcecode.h +++ b/src/sourcecode.h @@ -137,6 +137,9 @@ class SourceCode void StartMacro( const std::string& line, int column ); void EndMacro( const std::string& line, int column ); bool IsRealForLevel( int level ) const; + // For SOURCELINE + void SetLineNumber(int line) { m_lineNumber = line; } + void SetFileName(const std::string& name) { m_filename = name; } protected: diff --git a/test/3-directives/sourceline/last.fail.6502 b/test/3-directives/sourceline/last.fail.6502 new file mode 100644 index 0000000..54b3b03 --- /dev/null +++ b/test/3-directives/sourceline/last.fail.6502 @@ -0,0 +1 @@ +SOURCELINE 1,"first.6502":PRINT"HELLO" diff --git a/test/3-directives/sourceline/linefile.fail.6502 b/test/3-directives/sourceline/linefile.fail.6502 new file mode 100644 index 0000000..28421ad --- /dev/null +++ b/test/3-directives/sourceline/linefile.fail.6502 @@ -0,0 +1,2 @@ +SOURCELINE 5, "other.asm" +LDZ #2 diff --git a/test/3-directives/sourceline/linefile.fail.gold.txt b/test/3-directives/sourceline/linefile.fail.gold.txt new file mode 100644 index 0000000..beb4893 --- /dev/null +++ b/test/3-directives/sourceline/linefile.fail.gold.txt @@ -0,0 +1 @@ +other.asm:5: error: Unrecognised token. diff --git a/test/3-directives/sourceline/lineonly.fail.6502 b/test/3-directives/sourceline/lineonly.fail.6502 new file mode 100644 index 0000000..acd4a45 --- /dev/null +++ b/test/3-directives/sourceline/lineonly.fail.6502 @@ -0,0 +1,2 @@ +SOURCELINE 5 +LDZ #2 diff --git a/test/3-directives/sourceline/lineonly.fail.gold.txt b/test/3-directives/sourceline/lineonly.fail.gold.txt new file mode 100644 index 0000000..d97e5ce --- /dev/null +++ b/test/3-directives/sourceline/lineonly.fail.gold.txt @@ -0,0 +1 @@ +lineonly.fail.6502:5: error: Unrecognised token. diff --git a/test/3-directives/sourceline/macro.fail.6502 b/test/3-directives/sourceline/macro.fail.6502 new file mode 100644 index 0000000..5847e80 --- /dev/null +++ b/test/3-directives/sourceline/macro.fail.6502 @@ -0,0 +1,9 @@ +MACRO SL pass +IF pass=2 + LDZ #1 +ENDIF +SOURCELINE 1,"random.asm" +ENDMACRO + +SL 1 +SL 2 diff --git a/test/3-directives/sourceline/macro.fail.gold.txt b/test/3-directives/sourceline/macro.fail.gold.txt new file mode 100644 index 0000000..ddca9a7 --- /dev/null +++ b/test/3-directives/sourceline/macro.fail.gold.txt @@ -0,0 +1 @@ +macro.fail.6502:3: error: Unrecognised token. \ No newline at end of file diff --git a/test/3-directives/sourceline/macro2.fail.6502 b/test/3-directives/sourceline/macro2.fail.6502 new file mode 100644 index 0000000..6b5f435 --- /dev/null +++ b/test/3-directives/sourceline/macro2.fail.6502 @@ -0,0 +1,9 @@ +MACRO SL pass +SOURCELINE 20,"random.asm" +IF pass=2 + LDZ #1 +ENDIF +ENDMACRO + +SL 1 +SL 2 diff --git a/test/3-directives/sourceline/macro2.fail.gold.txt b/test/3-directives/sourceline/macro2.fail.gold.txt new file mode 100644 index 0000000..13a277f --- /dev/null +++ b/test/3-directives/sourceline/macro2.fail.gold.txt @@ -0,0 +1 @@ +random.asm:21: error: Unrecognised token. \ No newline at end of file