diff --git a/foo.asm b/foo.asm new file mode 100644 index 00000000..db07d9e6 --- /dev/null +++ b/foo.asm @@ -0,0 +1 @@ +println x diff --git a/foo.inc b/foo.inc new file mode 100644 index 00000000..7b2bde30 --- /dev/null +++ b/foo.inc @@ -0,0 +1 @@ +def x = 42 diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index 635a5128..9927849a 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -624,7 +624,7 @@ static uint32_t readBracketedMacroArgNum() { } if (c >= '0' && c <= '9') { - uint32_t n = readDecimalNumber(0); + uint32_t n = readDecimalNumber(bumpChar()); if (n > INT32_MAX) { error("Number in bracketed macro argument is too large"); return 0; @@ -1165,11 +1165,11 @@ static uint32_t readOctalNumber() { } static uint32_t readDecimalNumber(int initial) { - uint32_t value = initial ? initial - '0' : 0; - bool empty = !initial; + assume(initial >= '0' && initial <= '9'); + uint32_t value = initial - '0'; for (int c = peek();; c = nextChar()) { - if (c == '_' && !empty) { + if (c == '_') { continue; } else if (c >= '0' && c <= '9') { c = c - '0'; @@ -1181,12 +1181,6 @@ static uint32_t readDecimalNumber(int initial) { warning(WARNING_LARGE_CONSTANT, "Integer constant is too large"); } value = value * 10 + c; - - empty = false; - } - - if (empty) { - error("Invalid integer constant, no digits"); } return value; @@ -1393,9 +1387,9 @@ static void appendExpandedString(std::string &str, std::string const &expanded) case '\n': str += "\\n"; break; + // LCOV_EXCL_START case '\r': // A literal CR in a string may get treated as a LF, so '\r' is not tested. - // LCOV_EXCL_START str += "\\r"; break; // LCOV_EXCL_STOP @@ -1637,16 +1631,9 @@ static bool isGarbageCharacter(int c) { && (c == '\0' || !strchr("; \t~[](),+-*/|^=!<>:&%`\"\r\n\\", c)); } -static void skipGarbageCharacters(int c) { +static void reportGarbageCharacters(int c) { // '#' can be garbage if it doesn't start a raw string or identifier assume(isGarbageCharacter(c) || c == '#'); - - // Do not report weird characters when capturing, it'll be done later - if (lexerState->capturing) { - skipChars(isGarbageCharacter); - return; - } - if (isGarbageCharacter(peek())) { // At least two characters are garbage; group them into one error report std::string garbage = printChar(c); @@ -1966,7 +1953,7 @@ static Token yylex_NORMAL() { if (raw && startsIdentifier(peek())) { c = bumpChar(); } else if (!startsIdentifier(c)) { - skipGarbageCharacters(c); + reportGarbageCharacters(c); continue; } diff --git a/src/asm/opt.cpp b/src/asm/opt.cpp index 8cecf181..61e02cc5 100644 --- a/src/asm/opt.cpp +++ b/src/asm/opt.cpp @@ -7,6 +7,8 @@ #include #include +#include "helpers.hpp" // assume + #include "asm/fixpoint.hpp" #include "asm/fstack.hpp" #include "asm/lexer.hpp" @@ -77,9 +79,9 @@ void opt_Parse(char const *s) { result = sscanf(&s[1], "%x", &padByte); if (result != 1) { error("Invalid argument for option 'p'"); - } else if (padByte > 0xFF) { - error("Argument for option 'p' must be between 0 and 0xFF"); } else { + // Two characters cannot be scanned as a hex number greater than 0xFF + assume(padByte <= 0xFF); opt_P(padByte); } } else { diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp index 7f3028a2..f5670faa 100644 --- a/src/asm/rpn.cpp +++ b/src/asm/rpn.cpp @@ -325,9 +325,9 @@ void Expression::makeUnaryOp(RPNCommand op, Expression &&src) { case RPN_TZCOUNT: data = val != 0 ? ctz(uval) : 32; break; + // LCOV_EXCL_START default: // `makeUnaryOp` should never be called with a non-unary operator! - // LCOV_EXCL_START unreachable_(); } // LCOV_EXCL_STOP @@ -467,9 +467,9 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const data = op_exponent(lval, rval); break; + // LCOV_EXCL_START default: // `makeBinaryOp` should never be called with a non-binary operator! - // LCOV_EXCL_START unreachable_(); } // LCOV_EXCL_STOP diff --git a/test/asm/character-literals.asm b/test/asm/character-literals.asm index f50f146f..ee99ef0e 100644 --- a/test/asm/character-literals.asm +++ b/test/asm/character-literals.asm @@ -32,3 +32,4 @@ char '?', $3f ; ASCII char 'F', 0 char 'ABF', 0 char '\n\r\t', 0 +assert 0 == ' diff --git a/test/asm/character-literals.err b/test/asm/character-literals.err index b2eaa6f9..a68f4619 100644 --- a/test/asm/character-literals.err +++ b/test/asm/character-literals.err @@ -12,4 +12,8 @@ warning: character-literals.asm(34) -> character-literals.asm::char(13): [-Wunma Unmapped character '\t' error: character-literals.asm(34) -> character-literals.asm::char(13): Character literals must be a single charmap unit -Assembly aborted with 3 errors! +error: character-literals.asm(35): + Unterminated character +error: character-literals.asm(35): + Character literals must be a single charmap unit +Assembly aborted with 5 errors! diff --git a/test/asm/include-slash.asm b/test/asm/include-slash.asm new file mode 100644 index 00000000..db07d9e6 --- /dev/null +++ b/test/asm/include-slash.asm @@ -0,0 +1 @@ +println x diff --git a/test/asm/include-slash.err b/test/asm/include-slash.err new file mode 100644 index 00000000..a1aa9377 --- /dev/null +++ b/test/asm/include-slash.err @@ -0,0 +1,3 @@ +error: include-slash.asm(0): + Error reading pre-included file 'include-slash-nonexist.inc': No such file or directory +Assembly aborted with 1 error! diff --git a/test/asm/include-slash.flags b/test/asm/include-slash.flags new file mode 100644 index 00000000..abfee7da --- /dev/null +++ b/test/asm/include-slash.flags @@ -0,0 +1 @@ +-Weverything -P include-slash.inc -I include -P include-slash-nonexist.inc diff --git a/test/asm/include-slash.out b/test/asm/include-slash.out new file mode 100644 index 00000000..72555870 --- /dev/null +++ b/test/asm/include-slash.out @@ -0,0 +1 @@ +$2A diff --git a/test/asm/include/include-slash.inc b/test/asm/include/include-slash.inc new file mode 100644 index 00000000..7b2bde30 --- /dev/null +++ b/test/asm/include/include-slash.inc @@ -0,0 +1 @@ +def x = 42 diff --git a/test/asm/state-file/a.asm b/test/asm/state-file/a.asm index b8e47b31..c9e77adf 100644 --- a/test/asm/state-file/a.asm +++ b/test/asm/state-file/a.asm @@ -12,7 +12,7 @@ def variable += 1 def con2 equ -1 def var2 = variable**2 -def str2 equs strcat("{string}", "\0\n\t\r") +def str2 equs strcat("{string}", "\0\n\t\r\\\"\{") charmap "c2", 10, -11, 987654321 PURGE polo diff --git a/test/asm/state-file/a.dump.asm b/test/asm/state-file/a.dump.asm index d3205863..e7079ba1 100644 --- a/test/asm/state-file/a.dump.asm +++ b/test/asm/state-file/a.dump.asm @@ -10,7 +10,7 @@ def var2 = $9 ; String constants def string equs "goodbye~" -def str2 equs "hello!\0\n\t\r" +def str2 equs "hello!\0\n\t\r\\\"\{" ; Character maps newcharmap main diff --git a/test/asm/update-refs.sh b/test/asm/update-refs.sh deleted file mode 100755 index 192ff602..00000000 --- a/test/asm/update-refs.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -fname=$(mktemp) - -for i in *.asm; do - ../../rgbasm $i >$fname 2>&1 - mv -f $fname ${i%.asm}.out -done - -rm -f $fname -exit 0