Use LCOV_EXCL comments to exclude some lines from test coverage (#1662)

This commit is contained in:
Rangi
2025-02-16 19:56:55 +01:00
committed by GitHub
parent c9060c7f2d
commit 632342b254
30 changed files with 133 additions and 100 deletions

1
.gitignore vendored
View File

@@ -14,4 +14,5 @@ CMakeCache.txt
CMakeFiles/
cmake_install.cmake
build/
*.dSYM/
callgrind.out.*

View File

@@ -82,7 +82,6 @@ Symbol *sym_RedefEqu(std::string const &symName, int32_t value);
Symbol *sym_AddVar(std::string const &symName, int32_t value);
int32_t sym_GetRSValue();
void sym_SetRSValue(int32_t value);
uint32_t sym_GetConstantValue(std::string const &symName);
// Find a symbol by exact name, bypassing expansion checks
Symbol *sym_FindExactSymbol(std::string const &symName);
// Find a symbol, possibly scoped, by name

View File

@@ -103,7 +103,7 @@ public:
} else if (other._tag == other._t2.tag_value) {
*this = other._t2.value;
} else {
_tag = nulltag;
_tag = nulltag; // LCOV_EXCL_LINE
}
return *this;
}

View File

@@ -119,9 +119,11 @@ void fstk_SetPreIncludeFile(std::string const &path) {
warnx("Overriding pre-included filename %s", preIncludeName.c_str());
}
preIncludeName = path;
// LCOV_EXCL_START
if (verbose) {
printf("Pre-included filename %s\n", preIncludeName.c_str());
}
// LCOV_EXCL_STOP
}
static void printDep(std::string const &path) {
@@ -308,9 +310,11 @@ void fstk_RunInclude(std::string const &path, bool preInclude) {
if (!fullPath) {
if (generatedMissingIncludes && !preInclude) {
// LCOV_EXCL_START
if (verbose) {
printf("Aborting (-MG) on INCLUDE file '%s' (%s)\n", path.c_str(), strerror(errno));
}
// LCOV_EXCL_STOP
failedOnMissingInclude = true;
} else {
error("Unable to open included file '%s': %s\n", path.c_str(), strerror(errno));
@@ -319,7 +323,7 @@ void fstk_RunInclude(std::string const &path, bool preInclude) {
}
if (!newFileContext(*fullPath, false)) {
fatalerror("Failed to set up lexer for file include\n");
fatalerror("Failed to set up lexer for file include\n"); // LCOV_EXCL_LINE
}
}

View File

@@ -77,6 +77,7 @@ struct FileUnmapDeleter {
static char *mapFile(int fd, std::string const &path, size_t size) {
void *mappingAddr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
// LCOV_EXCL_START
if (mappingAddr == MAP_FAILED && errno == ENOTSUP) {
// The implementation may not support MAP_PRIVATE; try again with MAP_SHARED
// instead, offering, I believe, weaker guarantees about external modifications to
@@ -86,6 +87,7 @@ static char *mapFile(int fd, std::string const &path, size_t size) {
}
mappingAddr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
}
// LCOV_EXCL_STOP
return mappingAddr != MAP_FAILED ? static_cast<char *>(mappingAddr) : nullptr;
}
@@ -412,21 +414,27 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
if (filePath == "-") {
path = "<stdin>";
content.emplace<BufferedContent>(STDIN_FILENO);
// LCOV_EXCL_START
if (verbose) {
printf("Opening stdin\n");
}
// LCOV_EXCL_STOP
} else {
struct stat statBuf;
if (stat(filePath.c_str(), &statBuf) != 0) {
// LCOV_EXCL_START
error("Failed to stat file \"%s\": %s\n", filePath.c_str(), strerror(errno));
return false;
// LCOV_EXCL_STOP
}
path = filePath;
int fd = open(path.c_str(), O_RDONLY);
if (fd < 0) {
// LCOV_EXCL_START
error("Failed to open file \"%s\": %s\n", path.c_str(), strerror(errno));
return false;
// LCOV_EXCL_STOP
}
bool isMmapped = false;
@@ -438,9 +446,11 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
content.emplace<ViewedContent>(
std::shared_ptr<char[]>(mappingAddr, FileUnmapDeleter(size)), size
);
// LCOV_EXCL_START
if (verbose) {
printf("File \"%s\" is mmap()ped\n", path.c_str());
}
// LCOV_EXCL_STOP
isMmapped = true;
}
}
@@ -448,6 +458,7 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
if (!isMmapped) {
// Sometimes mmap() fails or isn't available, so have a fallback
content.emplace<BufferedContent>(fd);
// LCOV_EXCL_START
if (verbose) {
if (statBuf.st_size == 0) {
printf("File \"%s\" is empty\n", path.c_str());
@@ -457,6 +468,7 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
);
}
}
// LCOV_EXCL_STOP
}
}
@@ -552,7 +564,9 @@ size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
ssize_t nbReadChars = read(fd, &buf[startIndex], nbChars);
if (nbReadChars == -1) {
// LCOV_EXCL_START
fatalerror("Error while reading \"%s\": %s\n", lexerState->path.c_str(), strerror(errno));
// LCOV_EXCL_STOP
}
size += nbReadChars;
@@ -761,7 +775,9 @@ int LexerState::peekCharAhead() {
// and `.peekCharAhead()` will continue with its parent
assume(exp.offset <= exp.size());
if (exp.offset + distance < exp.size()) {
return static_cast<uint8_t>((*exp.contents)[exp.offset + distance]);
// Macro args can't be recursive, since `peek()` marks them as scanned, so
// this is a failsafe that (as far as I can tell) won't ever actually run.
return static_cast<uint8_t>((*exp.contents)[exp.offset + distance]); // LCOV_EXCL_LINE
}
distance -= exp.size() - exp.offset;
}
@@ -1323,8 +1339,11 @@ static void appendEscapedString(std::string &str, std::string const &escape) {
str += "\\n";
break;
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
case '\t':
str += "\\t";
break;
@@ -2163,7 +2182,8 @@ static Token skipIfBlock(bool toEndc) {
case T_(POP_ELIF):
if (lexer_ReachedELSEBlock()) {
fatalerror("Found ELIF after an ELSE block\n");
// This should be redundant, as the parser handles this error first.
fatalerror("Found ELIF after an ELSE block\n"); // LCOV_EXCL_LINE
}
if (!toEndc && lexer_GetIFDepth() == startingDepth) {
return token;
@@ -2255,9 +2275,8 @@ static Token yylex_SKIP_TO_ENDR() {
case T_(POP_ENDR):
depth--;
if (!depth) {
return Token(T_(YYEOF)); // yywrap() will finish the REPT/FOR loop
}
// `lexer_CaptureRept` has already guaranteed that the `ENDR`s are balanced
assume(depth > 0);
break;
case T_(POP_IF):

View File

@@ -87,6 +87,7 @@ static option const longopts[] = {
{nullptr, no_argument, nullptr, 0 }
};
// LCOV_EXCL_START
static void printUsage() {
fputs(
"Usage: rgbasm [-EhVvw] [-b chars] [-D name[=value]] [-g chars] [-I path]\n"
@@ -107,6 +108,7 @@ static void printUsage() {
stderr
);
}
// LCOV_EXCL_STOP
int main(int argc, char *argv[]) {
time_t now = time(nullptr);
@@ -176,8 +178,10 @@ int main(int argc, char *argv[]) {
break;
case 'h':
// LCOV_EXCL_START
printUsage();
exit(0);
// LCOV_EXCL_STOP
case 'I':
fstk_AddIncludePath(musl_optarg);
@@ -195,7 +199,7 @@ int main(int argc, char *argv[]) {
dependFileName = "<stdout>";
}
if (dependFile == nullptr) {
err("Failed to open dependfile \"%s\"", dependFileName);
err("Failed to open dependfile \"%s\"", dependFileName); // LCOV_EXCL_LINE
}
break;
@@ -302,9 +306,11 @@ int main(int argc, char *argv[]) {
if (stateFileSpecs.find(name) != stateFileSpecs.end()) {
warnx("Overriding state filename %s", name);
}
// LCOV_EXCL_START
if (verbose) {
printf("State filename %s\n", name);
}
// LCOV_EXCL_STOP
stateFileSpecs.emplace(name, std::move(features));
break;
}
@@ -314,8 +320,10 @@ int main(int argc, char *argv[]) {
exit(0);
case 'v':
// LCOV_EXCL_START
verbose = true;
break;
// LCOV_EXCL_STOP
case 'W':
opt_W(musl_optarg);
@@ -367,8 +375,10 @@ int main(int argc, char *argv[]) {
// Unrecognized options
default:
// LCOV_EXCL_START
printUsage();
exit(1);
// LCOV_EXCL_STOP
}
}
@@ -391,7 +401,7 @@ int main(int argc, char *argv[]) {
std::string mainFileName = argv[musl_optind];
if (verbose) {
printf("Assembling %s\n", mainFileName.c_str());
printf("Assembling %s\n", mainFileName.c_str()); // LCOV_EXCL_LINE
}
if (dependFile) {

View File

@@ -61,7 +61,7 @@ void out_RegisterNode(std::shared_ptr<FileStackNode> node) {
}
}
// Return a section's ID, or UINT32_MAX if the section is not in the list
// Return a section's ID, or UINT32_MAX if the section does not exist
static uint32_t getSectIDIfAny(Section *sect) {
if (!sect) {
return UINT32_MAX;
@@ -71,7 +71,8 @@ static uint32_t getSectIDIfAny(Section *sect) {
return static_cast<uint32_t>(search->second);
}
fatalerror("Unknown section '%s'\n", sect->name.c_str());
// Every section that exists should be in `sectionMap`
fatalerror("Unknown section '%s'\n", sect->name.c_str()); // LCOV_EXCL_LINE
}
static void writePatch(Patch const &patch, FILE *file) {
@@ -175,7 +176,7 @@ static void writeRpn(std::vector<uint8_t> &rpnexpr, std::vector<uint8_t> const &
sym = sym_FindExactSymbol(symName);
if (sym->isConstant()) {
rpnexpr[rpnptr++] = RPN_CONST;
value = sym_GetConstantValue(symName);
value = sym->getConstantValue();
} else {
rpnexpr[rpnptr++] = RPN_SYM;
registerUnregisteredSymbol(*sym); // Ensure that `sym->ID` is set
@@ -323,7 +324,7 @@ void out_WriteObject() {
file = stdout;
}
if (!file) {
err("Failed to open object file '%s'", objectFileName.c_str());
err("Failed to open object file '%s'", objectFileName.c_str()); // LCOV_EXCL_LINE
}
Defer closeFile{[&] { fclose(file); }};
@@ -343,14 +344,7 @@ void out_WriteObject() {
writeFileStackNode(node, file);
// The list is supposed to have decrementing IDs
if (it + 1 != fileStackNodes.end() && it[1]->ID != node.ID - 1) {
fatalerror(
"Internal error: fstack node #%" PRIu32 " follows #%" PRIu32
". Please report this to the developers!\n",
it[1]->ID,
node.ID
);
}
assume(it + 1 == fileStackNodes.end() || it[1]->ID == node.ID - 1);
}
for (Symbol const *sym : objectSymbols) {
@@ -373,9 +367,11 @@ void out_SetFileName(std::string const &name) {
warnx("Overriding output filename %s", objectFileName.c_str());
}
objectFileName = name;
// LCOV_EXCL_START
if (verbose) {
printf("Output filename %s\n", objectFileName.c_str());
}
// LCOV_EXCL_STOP
}
static void dumpString(std::string const &escape, FILE *file) {
@@ -528,7 +524,7 @@ void out_WriteState(std::string name, std::vector<StateFeature> const &features)
file = stdout;
}
if (!file) {
err("Failed to open state file '%s'", name.c_str());
err("Failed to open state file '%s'", name.c_str()); // LCOV_EXCL_LINE
}
Defer closeFile{[&] { fclose(file); }};

View File

@@ -94,7 +94,7 @@ void Expression::makeSymbol(std::string const &symName) {
*ptr++ = RPN_SYM;
memcpy(ptr, sym->name.c_str(), nameLen);
} else {
data = static_cast<int32_t>(sym_GetConstantValue(symName));
data = static_cast<int32_t>(sym->getConstantValue());
}
}
@@ -325,42 +325,12 @@ void Expression::makeUnaryOp(RPNCommand op, Expression &&src) {
case RPN_TZCOUNT:
data = val != 0 ? ctz(uval) : 32;
break;
case RPN_LOGOR:
case RPN_LOGAND:
case RPN_LOGEQ:
case RPN_LOGGT:
case RPN_LOGLT:
case RPN_LOGGE:
case RPN_LOGLE:
case RPN_LOGNE:
case RPN_ADD:
case RPN_SUB:
case RPN_XOR:
case RPN_OR:
case RPN_AND:
case RPN_SHL:
case RPN_SHR:
case RPN_USHR:
case RPN_MUL:
case RPN_DIV:
case RPN_MOD:
case RPN_EXP:
case RPN_BANK_SYM:
case RPN_BANK_SECT:
case RPN_BANK_SELF:
case RPN_SIZEOF_SECT:
case RPN_STARTOF_SECT:
case RPN_SIZEOF_SECTTYPE:
case RPN_STARTOF_SECTTYPE:
case RPN_HRAM:
case RPN_RST:
case RPN_BIT_INDEX:
case RPN_CONST:
case RPN_SYM:
default:
// `makeUnaryOp` should never be called with a non-unary operator!
// LCOV_EXCL_START
unreachable_();
}
// LCOV_EXCL_STOP
} else if (op == RPN_LOGNOT && tryConstLogNot(src)) {
data = 0;
} else if (int32_t constVal; op == RPN_LOW && (constVal = tryConstLow(src)) != -1) {
@@ -503,29 +473,12 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
data = op_exponent(lval, rval);
break;
case RPN_NEG:
case RPN_NOT:
case RPN_LOGNOT:
case RPN_BANK_SYM:
case RPN_BANK_SECT:
case RPN_BANK_SELF:
case RPN_SIZEOF_SECT:
case RPN_STARTOF_SECT:
case RPN_SIZEOF_SECTTYPE:
case RPN_STARTOF_SECTTYPE:
case RPN_HRAM:
case RPN_RST:
case RPN_BIT_INDEX:
case RPN_HIGH:
case RPN_LOW:
case RPN_BITWIDTH:
case RPN_TZCOUNT:
case RPN_CONST:
case RPN_SYM:
default:
// `makeBinaryOp` should never be called with a non-binary operator!
// LCOV_EXCL_START
unreachable_();
}
// LCOV_EXCL_STOP
} else if (op == RPN_SUB && src1.isDiffConstant(src2.symbolOf())) {
data = src1.symbolOf()->getValue() - src2.symbolOf()->getValue();
} else if ((op == RPN_LOGAND || op == RPN_AND) && tryConstZero(src1, src2)) {

View File

@@ -875,9 +875,11 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
}
if (!file) {
if (generatedMissingIncludes) {
// LCOV_EXCL_START
if (verbose) {
printf("Aborting (-MG) on INCBIN file '%s' (%s)\n", name.c_str(), strerror(errno));
}
// LCOV_EXCL_STOP
failedOnMissingInclude = true;
} else {
error("Error opening INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
@@ -942,9 +944,11 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
}
if (!file) {
if (generatedMissingIncludes) {
// LCOV_EXCL_START
if (verbose) {
printf("Aborting (-MG) on INCBIN file '%s' (%s)\n", name.c_str(), strerror(errno));
}
// LCOV_EXCL_STOP
failedOnMissingInclude = true;
} else {
error("Error opening INCBIN file '%s': %s\n", name.c_str(), strerror(errno));

View File

@@ -325,19 +325,6 @@ uint32_t Symbol::getConstantValue() const {
return 0;
}
uint32_t sym_GetConstantValue(std::string const &symName) {
if (Symbol const *sym = sym_FindScopedSymbol(symName); sym) {
return sym->getConstantValue();
}
if (sym_IsPurgedScoped(symName)) {
error("'%s' not defined; it was purged\n", symName.c_str());
} else {
error("'%s' not defined\n", symName.c_str());
}
return 0;
}
std::pair<Symbol const *, Symbol const *> sym_GetCurrentLabelScopes() {
return {globalScope, localScope};
}
@@ -528,8 +515,10 @@ static uint32_t anonLabelID = 0;
Symbol *sym_AddAnonLabel() {
if (anonLabelID == UINT32_MAX) {
// LCOV_EXCL_START
error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID);
return nullptr;
// LCOV_EXCL_STOP
}
std::string anon = sym_MakeAnonLabelName(0, true); // The direction is important!
@@ -555,6 +544,7 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
} else {
ofs--; // We're referencing symbols that haven't been created yet...
if (ofs > UINT32_MAX - anonLabelID) {
// LCOV_EXCL_START
error(
"Reference to anonymous label %" PRIu32 " after, when only %" PRIu32
" may still be created\n",
@@ -562,6 +552,7 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
UINT32_MAX - anonLabelID
);
} else {
// LCOV_EXCL_STOP
id = anonLabelID + ofs;
}
}
@@ -571,8 +562,11 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
void sym_Export(std::string const &symName) {
if (symName.starts_with('!')) {
// LCOV_EXCL_START
// The parser does not accept anonymous labels for an `EXPORT` directive
error("Anonymous labels cannot be exported\n");
return;
// LCOV_EXCL_STOP
}
Symbol *sym = sym_FindScopedSymbol(symName);
@@ -654,11 +648,13 @@ void sym_Init(time_t now) {
sym_AddEqu("__RGBDS_RC__"s, PACKAGE_VERSION_RC)->isBuiltin = true;
#endif
// LCOV_EXCL_START
if (now == static_cast<time_t>(-1)) {
warn("Failed to determine current time");
// Fall back by pretending we are at the Epoch
now = 0;
}
// LCOV_EXCL_STOP
tm const *time_local = localtime(&now);

View File

@@ -54,6 +54,7 @@ static option const longopts[] = {
{nullptr, no_argument, nullptr, 0 }
};
// LCOV_EXCL_START
static void printUsage() {
fputs(
"Usage: rgbfix [-hjOsVv] [-C | -c] [-f <fix_spec>] [-i <game_id>] [-k <licensee>]\n"
@@ -72,6 +73,7 @@ static void printUsage() {
stderr
);
}
// LCOV_EXCL_STOP
static uint8_t nbErrors;
@@ -1322,8 +1324,10 @@ int main(int argc, char *argv[]) {
break;
case 'h':
// LCOV_EXCL_START
printUsage();
exit(0);
// LCOV_EXCL_STOP
case 'i':
gameID = musl_optarg;

View File

@@ -156,6 +156,7 @@ static option const longopts[] = {
{nullptr, no_argument, nullptr, 0 }
};
// LCOV_EXCL_START
static void printUsage() {
fputs(
"Usage: rgbgfx [-r stride] [-ChmOuVXYZ] [-v [-v ...]] [-a <attr_map> | -A]\n"
@@ -174,6 +175,7 @@ static void printUsage() {
stderr
);
}
// LCOV_EXCL_STOP
// Parses a number at the beginning of a string, moving the pointer to skip the parsed characters.
// Returns the provided errVal on error.
@@ -425,8 +427,10 @@ static char *parseArgv(int argc, char *argv[]) {
}
break;
case 'h':
// LCOV_EXCL_START
printUsage();
exit(0);
// LCOV_EXCL_STOP
case 'i':
if (!options.inputTileset.empty()) {
warning("Overriding input tileset file %s", options.inputTileset.c_str());
@@ -615,8 +619,10 @@ static char *parseArgv(int argc, char *argv[]) {
}
break;
default:
// LCOV_EXCL_START
printUsage();
exit(1);
// LCOV_EXCL_STOP
}
}

View File

@@ -163,6 +163,7 @@ static option const longopts[] = {
{nullptr, no_argument, nullptr, 0 }
};
// LCOV_EXCL_START
static void printUsage() {
fputs(
"Usage: rgblink [-dhMtVvwx] [-l script] [-m map_file] [-n sym_file]\n"
@@ -181,6 +182,7 @@ static void printUsage() {
stderr
);
}
// LCOV_EXCL_STOP
enum ScrambledRegion {
SCRAMBLE_ROMX,
@@ -335,8 +337,10 @@ int main(int argc, char *argv[]) {
isWRAM0Mode = true;
break;
case 'h':
// LCOV_EXCL_START
printUsage();
exit(0);
// LCOV_EXCL_STOP
case 'l':
if (linkerScriptName) {
warnx("Overriding linker script %s", linkerScriptName);
@@ -407,8 +411,10 @@ int main(int argc, char *argv[]) {
is32kMode = true;
break;
default:
// LCOV_EXCL_START
printUsage();
exit(1);
// LCOV_EXCL_STOP
}
}

View File

@@ -7,6 +7,17 @@ FOR V, 1, 100
PRINTLN "cont"
ENDR
WARN "done {d:V}"
rept 2
break
; skips nested code
rept 3
println "\tinner"
endr
if 1
println "\tconditional"
endc
println "outer"
endr
rept 1
break
; skips invalid code

View File

@@ -1,8 +1,8 @@
warning: break.asm(9): [-Wuser]
done 5
warning: break.asm(17): [-Wuser]
warning: break.asm(28): [-Wuser]
OK
error: break.asm(18):
error: break.asm(29):
BREAK can only be used inside a REPT/FOR block
FATAL: break.asm(19) -> break.asm::REPT~1(23):
FATAL: break.asm(30) -> break.asm::REPT~1(34):
Ended block with 1 unterminated IF construct

View File

@@ -19,7 +19,7 @@ DEF copy EQUS STRSUB("{invalid}", 1)
println "\"{#s:invalid}\" == \"{#s:copy}\" ({d:n})"
DEF mid1 EQUS STRSUB("{invalid}", 5, 2)
DEF mid2 EQUS STRSUB("{invalid}", 9, 1)
DEF mid2 EQUS STRSLICE("{invalid}", 8, 9)
println "\"{#s:mid2}{#s:mid1}\""
; characters:
@@ -53,3 +53,6 @@ println "\"{#s:invalid}\": {d:n} == {d:r}"
DEF final EQUS STRSUB("{invalid}", 4, 1)
println "\"{#s:invalid}\" ends \"{#s:final}\""
REDEF final EQUS STRSLICE("{invalid}", 3, 4)
println "\"{#s:invalid}\" ends \"{#s:final}\""

View File

@@ -15,9 +15,9 @@ error: invalid-utf-8-strings.asm(17):
error: invalid-utf-8-strings.asm(17):
STRSUB: Invalid UTF-8 byte 0xA2
error: invalid-utf-8-strings.asm(22):
STRSUB: Invalid UTF-8 byte 0xA3
STRSLICE: Invalid UTF-8 byte 0xA3
error: invalid-utf-8-strings.asm(22):
STRSUB: Invalid UTF-8 byte 0xA4
STRSLICE: Invalid UTF-8 byte 0xA4
error: invalid-utf-8-strings.asm(35):
STRLEN: Invalid UTF-8 byte 0xFE
error: invalid-utf-8-strings.asm(35):
@@ -56,4 +56,6 @@ error: invalid-utf-8-strings.asm(50):
STRLEN: Incomplete UTF-8 character
error: invalid-utf-8-strings.asm(54):
STRSUB: Incomplete UTF-8 character
error: Assembly aborted (29 errors)!
error: invalid-utf-8-strings.asm(57):
STRSLICE: Incomplete UTF-8 character
error: Assembly aborted (30 errors)!

View File

@@ -4,3 +4,4 @@
"漢<>"
"abc<62><63>": 4 == 4
"abc<62><63>" ends "<22><>"
"abc<62><63>" ends "<22><>"

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
MACRO mac
DEF s EQUS "\#"
println "{#s:s}"
ENDM
mac \\\"\t\r\0\n\{\}\,\(\)\w\

View File

@@ -1,5 +1,5 @@
error: macro-arg-escape-chars.asm(5):
error: macro-arg-illegal-escape.asm(5):
Illegal character escape 'w'
error: macro-arg-escape-chars.asm(5):
error: macro-arg-illegal-escape.asm(5):
Illegal character escape at end of input
error: Assembly aborted (2 errors)!

View File

@@ -0,0 +1 @@
\\\"\t\r\0\n\{},()w\\

View File

@@ -28,7 +28,10 @@ purge #name
assert !def(name) && !def(#name) && def(hello)
section "test", rom0
#label:
db #hello
dw #hello
dl #hello
#label:
dw BANK(#label), #label

Binary file not shown.

View File

@@ -0,0 +1,2 @@
if 0
; no newline at end of file

View File

@@ -0,0 +1,2 @@
FATAL: unterminated-if-eof.asm(2):
Ended block with 1 unterminated IF construct

View File

@@ -109,6 +109,10 @@ for f in *.[12]bpp; do
runTest && tryCmp "$f" result.2bpp || failTest $?
done
# Test writing to stdout
newTest "$RGBGFX -m -o - write_stdout.bin > result.2bpp"
runTest && tryCmp write_stdout.out.2bpp result.2bpp || failTest $?
if [[ "$failed" -eq 0 ]]; then
echo "${bold}${green}All ${tests} tests passed!${rescolors}${resbold}"
else

BIN
test/gfx/write_stdout.bin Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

View File

@@ -0,0 +1 @@
? @@˙Ś˙˙€˙€đđŹxG~A? ˙ńâ~‚üřŕŕ