diff --git a/include/asm/fstack.hpp b/include/asm/fstack.hpp index 0e7103a9..43ced126 100644 --- a/include/asm/fstack.hpp +++ b/include/asm/fstack.hpp @@ -58,9 +58,10 @@ MacroArgs *fstk_GetCurrentMacroArgs(); void fstk_AddIncludePath(std::string const &path); void fstk_SetPreIncludeFile(std::string const &path); std::optional fstk_FindFile(std::string const &path); +bool fstk_FileError(std::string const &path, char const *functionName); bool yywrap(); -void fstk_RunInclude(std::string const &path, bool updateStateNow); +bool fstk_RunInclude(std::string const &path); void fstk_RunMacro(std::string const ¯oName, std::shared_ptr macroArgs); void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span); void fstk_RunFor( diff --git a/include/asm/main.hpp b/include/asm/main.hpp index cb506edf..220f73e1 100644 --- a/include/asm/main.hpp +++ b/include/asm/main.hpp @@ -15,11 +15,16 @@ extern bool verbose; } \ } while (0) +enum MissingInclude { + INC_ERROR, // A missing included file is an error that halts assembly + GEN_EXIT, // A missing included file is assumed to be generated; exit normally + GEN_CONTINUE, // A missing included file is assumed to be generated; continue assembling +}; + extern FILE *dependFile; extern std::string targetFileName; -extern bool continueAfterMissingIncludes; -extern bool generatedMissingIncludes; -extern bool failedOnMissingInclude; +extern MissingInclude missingIncludeState; extern bool generatePhonyDeps; +extern bool failedOnMissingInclude; #endif // RGBDS_ASM_MAIN_HPP diff --git a/include/asm/section.hpp b/include/asm/section.hpp index e37fa044..184eedf0 100644 --- a/include/asm/section.hpp +++ b/include/asm/section.hpp @@ -96,8 +96,8 @@ void sect_RelBytes(uint32_t n, std::vector const &exprs); void sect_RelWord(Expression const &expr, uint32_t pcShift); void sect_RelLong(Expression const &expr, uint32_t pcShift); void sect_PCRelByte(Expression const &expr, uint32_t pcShift); -void sect_BinaryFile(std::string const &name, uint32_t startPos); -void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length); +bool sect_BinaryFile(std::string const &name, uint32_t startPos); +bool sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length); void sect_EndSection(); void sect_PushSection(); diff --git a/man/rgbasm.1 b/man/rgbasm.1 index e9839c79..5d84a3ec 100644 --- a/man/rgbasm.1 +++ b/man/rgbasm.1 @@ -116,7 +116,7 @@ Write dependencies to .Ar depend_file . .It Fl MC -To be used in conjunction with +Implies .Fl MG . This makes .Nm @@ -143,7 +143,9 @@ exits normally or continues processing (depending on whether was enabled) instead of erroring out. This feature is used in automatic updating of Makefiles. .It Fl MP -When enabled, this causes a phony target to be added for each dependency other than the main file. +When enabled, this adds a phony target to the rules emitted by +.Fl M +for each dependency other than the main file. This prevents .Xr make 1 from erroring out when dependency files are deleted. diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index 2aa68995..045ab930 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -146,7 +146,7 @@ std::optional fstk_FindFile(std::string const &path) { } errno = ENOENT; - if (generatedMissingIncludes) { + if (missingIncludeState != INC_ERROR) { printDep(path); } return std::nullopt; @@ -302,26 +302,30 @@ static Context &newReptContext(int32_t reptLineNo, ContentSpan const &span, uint return context; } -void fstk_RunInclude(std::string const &path, bool preInclude) { - std::optional fullPath = fstk_FindFile(path); - - if (!fullPath) { - if (generatedMissingIncludes && !preInclude) { - // LCOV_EXCL_START - if (!continueAfterMissingIncludes) { - verbosePrint( - "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", path.c_str(), strerror(errno)); +bool fstk_FileError(std::string const &path, char const *functionName) { + if (missingIncludeState == INC_ERROR) { + error("Error opening %s file '%s': %s", functionName, path.c_str(), strerror(errno)); + } else { + failedOnMissingInclude = true; + // LCOV_EXCL_START + if (missingIncludeState == GEN_EXIT) { + verbosePrint( + "Aborting (-MG) on %s file '%s' (%s)\n", functionName, path.c_str(), strerror(errno) + ); + return true; } - return; + assume(missingIncludeState == GEN_CONTINUE); + // LCOV_EXCL_STOP } + return false; +} - newFileContext(*fullPath, false); +bool fstk_RunInclude(std::string const &path) { + if (std::optional fullPath = fstk_FindFile(path); fullPath) { + newFileContext(*fullPath, false); + return false; + } + return fstk_FileError(path, "INCLUDE"); } void fstk_RunMacro(std::string const ¯oName, std::shared_ptr macroArgs) { @@ -410,6 +414,12 @@ void fstk_Init(std::string const &mainPath, size_t maxDepth) { maxRecursionDepth = maxDepth; if (!preIncludeName.empty()) { - fstk_RunInclude(preIncludeName, true); + if (std::optional fullPath = fstk_FindFile(preIncludeName); fullPath) { + newFileContext(*fullPath, false); + } else { + error( + "Error reading pre-included file '%s': %s", preIncludeName.c_str(), strerror(errno) + ); + } } } diff --git a/src/asm/main.cpp b/src/asm/main.cpp index 1892c0a7..4fcac9d4 100644 --- a/src/asm/main.cpp +++ b/src/asm/main.cpp @@ -24,14 +24,14 @@ #include "asm/symbol.hpp" #include "asm/warning.hpp" -FILE *dependFile = nullptr; // -M -bool continueAfterMissingIncludes = false; // -MC -bool generatedMissingIncludes = false; // -MG -bool generatePhonyDeps = false; // -MP -std::string targetFileName; // -MQ, -MT -bool failedOnMissingInclude = false; bool verbose = false; // -v +FILE *dependFile = nullptr; // -M +MissingInclude missingIncludeState = INC_ERROR; // -MC, -MG +bool generatePhonyDeps = false; // -MP +std::string targetFileName; // -MQ, -MT +bool failedOnMissingInclude = false; + // Escapes Make-special chars from a string static std::string make_escape(std::string &str) { std::string escaped; @@ -371,11 +371,11 @@ int main(int argc, char *argv[]) { case 0: switch (depType) { case 'C': - continueAfterMissingIncludes = true; + missingIncludeState = GEN_CONTINUE; break; case 'G': - generatedMissingIncludes = true; + missingIncludeState = GEN_EXIT; break; case 'P': diff --git a/src/asm/parser.y b/src/asm/parser.y index 3d4067b1..5a9e788d 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -1139,8 +1139,7 @@ export_def: include: label POP_INCLUDE string endofline { - fstk_RunInclude($3, false); - if (failedOnMissingInclude && !continueAfterMissingIncludes) { + if (fstk_RunInclude($3)) { YYACCEPT; } } @@ -1148,20 +1147,17 @@ include: incbin: POP_INCBIN string { - sect_BinaryFile($2, 0); - if (failedOnMissingInclude && !continueAfterMissingIncludes) { + if (sect_BinaryFile($2, 0)) { YYACCEPT; } } | POP_INCBIN string COMMA uconst { - sect_BinaryFile($2, $4); - if (failedOnMissingInclude && !continueAfterMissingIncludes) { + if (sect_BinaryFile($2, $4)) { YYACCEPT; } } | POP_INCBIN string COMMA uconst COMMA uconst { - sect_BinaryFileSlice($2, $4, $6); - if (failedOnMissingInclude && !continueAfterMissingIncludes) { + if (sect_BinaryFileSlice($2, $4, $6)) { YYACCEPT; } } diff --git a/src/asm/section.cpp b/src/asm/section.cpp index 9dad0139..da796ced 100644 --- a/src/asm/section.cpp +++ b/src/asm/section.cpp @@ -874,9 +874,9 @@ void sect_PCRelByte(Expression const &expr, uint32_t pcShift) { } } -void sect_BinaryFile(std::string const &name, uint32_t startPos) { +bool sect_BinaryFile(std::string const &name, uint32_t startPos) { if (!requireCodeSection()) { - return; + return false; } FILE *file = nullptr; @@ -884,24 +884,14 @@ void sect_BinaryFile(std::string const &name, uint32_t startPos) { file = fopen(fullPath->c_str(), "rb"); } if (!file) { - if (generatedMissingIncludes) { - // LCOV_EXCL_START - if (verbose && !continueAfterMissingIncludes) { - 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", name.c_str(), strerror(errno)); - } - return; + return fstk_FileError(name, "INCBIN"); } Defer closeFile{[&] { fclose(file); }}; if (fseek(file, 0, SEEK_END) != -1) { if (startPos > ftell(file)) { error("Specified start position is greater than length of file '%s'", name.c_str()); - return; + return false; } // The file is seekable; skip to the specified start position fseek(file, startPos, SEEK_SET); @@ -913,7 +903,7 @@ void sect_BinaryFile(std::string const &name, uint32_t startPos) { while (startPos--) { if (fgetc(file) == EOF) { error("Specified start position is greater than length of file '%s'", name.c_str()); - return; + return false; } } } @@ -925,14 +915,15 @@ void sect_BinaryFile(std::string const &name, uint32_t startPos) { if (ferror(file)) { error("Error reading INCBIN file '%s': %s", name.c_str(), strerror(errno)); } + return false; } -void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length) { +bool sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length) { if (!requireCodeSection()) { - return; + return false; } if (length == 0) { // Don't even bother with 0-byte slices - return; + return false; } FILE *file = nullptr; @@ -940,24 +931,14 @@ void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t l file = fopen(fullPath->c_str(), "rb"); } if (!file) { - if (generatedMissingIncludes) { - // LCOV_EXCL_START - if (verbose && !continueAfterMissingIncludes) { - 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", name.c_str(), strerror(errno)); - } - return; + return fstk_FileError(name, "INCBIN"); } Defer closeFile{[&] { fclose(file); }}; if (fseek(file, 0, SEEK_END) != -1) { if (long fsize = ftell(file); startPos > fsize) { error("Specified start position is greater than length of file '%s'", name.c_str()); - return; + return false; } else if (startPos + length > fsize) { error( "Specified range in INCBIN file '%s' is out of bounds (%" PRIu32 " + %" PRIu32 @@ -967,7 +948,7 @@ void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t l length, fsize ); - return; + return false; } // The file is seekable; skip to the specified start position fseek(file, startPos, SEEK_SET); @@ -979,7 +960,7 @@ void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t l while (startPos--) { if (fgetc(file) == EOF) { error("Specified start position is greater than length of file '%s'", name.c_str()); - return; + return false; } } } @@ -997,6 +978,7 @@ void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t l ); } } + return false; } void sect_PushSection() { diff --git a/test/asm/nonexist-include.err b/test/asm/nonexist-include.err index e83bd20c..058c887c 100644 --- a/test/asm/nonexist-include.err +++ b/test/asm/nonexist-include.err @@ -1,3 +1,3 @@ error: nonexist-include.asm(1): - Unable to open included file 'nonexist-include.inc': No such file or directory + Error opening INCLUDE file 'nonexist-include.inc': No such file or directory Assembly aborted with 1 error!