mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Refactor code that handles when included files are missing
- Single unified routine for erroring out or handling missing dependencies - Single three-state enum instead of two Booleans for missing dependencies (this causes `-MC` to imply `-MG` instead of needing `-MG -MC`) - Functions than can miss included files return a Boolean for whether the parser should `YYACCEPT` and exit
This commit is contained in:
@@ -58,9 +58,10 @@ MacroArgs *fstk_GetCurrentMacroArgs();
|
|||||||
void fstk_AddIncludePath(std::string const &path);
|
void fstk_AddIncludePath(std::string const &path);
|
||||||
void fstk_SetPreIncludeFile(std::string const &path);
|
void fstk_SetPreIncludeFile(std::string const &path);
|
||||||
std::optional<std::string> fstk_FindFile(std::string const &path);
|
std::optional<std::string> fstk_FindFile(std::string const &path);
|
||||||
|
bool fstk_FileError(std::string const &path, char const *functionName);
|
||||||
|
|
||||||
bool yywrap();
|
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> macroArgs);
|
void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macroArgs);
|
||||||
void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span);
|
void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span);
|
||||||
void fstk_RunFor(
|
void fstk_RunFor(
|
||||||
|
|||||||
@@ -15,11 +15,16 @@ extern bool verbose;
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} 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 FILE *dependFile;
|
||||||
extern std::string targetFileName;
|
extern std::string targetFileName;
|
||||||
extern bool continueAfterMissingIncludes;
|
extern MissingInclude missingIncludeState;
|
||||||
extern bool generatedMissingIncludes;
|
|
||||||
extern bool failedOnMissingInclude;
|
|
||||||
extern bool generatePhonyDeps;
|
extern bool generatePhonyDeps;
|
||||||
|
extern bool failedOnMissingInclude;
|
||||||
|
|
||||||
#endif // RGBDS_ASM_MAIN_HPP
|
#endif // RGBDS_ASM_MAIN_HPP
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> const &exprs);
|
|||||||
void sect_RelWord(Expression const &expr, uint32_t pcShift);
|
void sect_RelWord(Expression const &expr, uint32_t pcShift);
|
||||||
void sect_RelLong(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_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);
|
||||||
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);
|
||||||
|
|
||||||
void sect_EndSection();
|
void sect_EndSection();
|
||||||
void sect_PushSection();
|
void sect_PushSection();
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ Write
|
|||||||
dependencies to
|
dependencies to
|
||||||
.Ar depend_file .
|
.Ar depend_file .
|
||||||
.It Fl MC
|
.It Fl MC
|
||||||
To be used in conjunction with
|
Implies
|
||||||
.Fl MG .
|
.Fl MG .
|
||||||
This makes
|
This makes
|
||||||
.Nm
|
.Nm
|
||||||
@@ -143,7 +143,9 @@ exits normally or continues processing (depending on whether
|
|||||||
was enabled) instead of erroring out.
|
was enabled) instead of erroring out.
|
||||||
This feature is used in automatic updating of Makefiles.
|
This feature is used in automatic updating of Makefiles.
|
||||||
.It Fl MP
|
.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
|
This prevents
|
||||||
.Xr make 1
|
.Xr make 1
|
||||||
from erroring out when dependency files are deleted.
|
from erroring out when dependency files are deleted.
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ std::optional<std::string> fstk_FindFile(std::string const &path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
if (generatedMissingIncludes) {
|
if (missingIncludeState != INC_ERROR) {
|
||||||
printDep(path);
|
printDep(path);
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -302,26 +302,30 @@ static Context &newReptContext(int32_t reptLineNo, ContentSpan const &span, uint
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_RunInclude(std::string const &path, bool preInclude) {
|
bool fstk_FileError(std::string const &path, char const *functionName) {
|
||||||
std::optional<std::string> fullPath = fstk_FindFile(path);
|
if (missingIncludeState == INC_ERROR) {
|
||||||
|
error("Error opening %s file '%s': %s", functionName, path.c_str(), strerror(errno));
|
||||||
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 {
|
} else {
|
||||||
error("Unable to open included file '%s': %s", path.c_str(), strerror(errno));
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fstk_RunInclude(std::string const &path) {
|
||||||
|
if (std::optional<std::string> fullPath = fstk_FindFile(path); fullPath) {
|
||||||
newFileContext(*fullPath, false);
|
newFileContext(*fullPath, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return fstk_FileError(path, "INCLUDE");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macroArgs) {
|
void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macroArgs) {
|
||||||
@@ -410,6 +414,12 @@ void fstk_Init(std::string const &mainPath, size_t maxDepth) {
|
|||||||
maxRecursionDepth = maxDepth;
|
maxRecursionDepth = maxDepth;
|
||||||
|
|
||||||
if (!preIncludeName.empty()) {
|
if (!preIncludeName.empty()) {
|
||||||
fstk_RunInclude(preIncludeName, true);
|
if (std::optional<std::string> fullPath = fstk_FindFile(preIncludeName); fullPath) {
|
||||||
|
newFileContext(*fullPath, false);
|
||||||
|
} else {
|
||||||
|
error(
|
||||||
|
"Error reading pre-included file '%s': %s", preIncludeName.c_str(), strerror(errno)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,13 @@
|
|||||||
#include "asm/symbol.hpp"
|
#include "asm/symbol.hpp"
|
||||||
#include "asm/warning.hpp"
|
#include "asm/warning.hpp"
|
||||||
|
|
||||||
|
bool verbose = false; // -v
|
||||||
|
|
||||||
FILE *dependFile = nullptr; // -M
|
FILE *dependFile = nullptr; // -M
|
||||||
bool continueAfterMissingIncludes = false; // -MC
|
MissingInclude missingIncludeState = INC_ERROR; // -MC, -MG
|
||||||
bool generatedMissingIncludes = false; // -MG
|
|
||||||
bool generatePhonyDeps = false; // -MP
|
bool generatePhonyDeps = false; // -MP
|
||||||
std::string targetFileName; // -MQ, -MT
|
std::string targetFileName; // -MQ, -MT
|
||||||
bool failedOnMissingInclude = false;
|
bool failedOnMissingInclude = false;
|
||||||
bool verbose = false; // -v
|
|
||||||
|
|
||||||
// Escapes Make-special chars from a string
|
// Escapes Make-special chars from a string
|
||||||
static std::string make_escape(std::string &str) {
|
static std::string make_escape(std::string &str) {
|
||||||
@@ -371,11 +371,11 @@ int main(int argc, char *argv[]) {
|
|||||||
case 0:
|
case 0:
|
||||||
switch (depType) {
|
switch (depType) {
|
||||||
case 'C':
|
case 'C':
|
||||||
continueAfterMissingIncludes = true;
|
missingIncludeState = GEN_CONTINUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
generatedMissingIncludes = true;
|
missingIncludeState = GEN_EXIT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
|
|||||||
@@ -1139,8 +1139,7 @@ export_def:
|
|||||||
|
|
||||||
include:
|
include:
|
||||||
label POP_INCLUDE string endofline {
|
label POP_INCLUDE string endofline {
|
||||||
fstk_RunInclude($3, false);
|
if (fstk_RunInclude($3)) {
|
||||||
if (failedOnMissingInclude && !continueAfterMissingIncludes) {
|
|
||||||
YYACCEPT;
|
YYACCEPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1148,20 +1147,17 @@ include:
|
|||||||
|
|
||||||
incbin:
|
incbin:
|
||||||
POP_INCBIN string {
|
POP_INCBIN string {
|
||||||
sect_BinaryFile($2, 0);
|
if (sect_BinaryFile($2, 0)) {
|
||||||
if (failedOnMissingInclude && !continueAfterMissingIncludes) {
|
|
||||||
YYACCEPT;
|
YYACCEPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| POP_INCBIN string COMMA uconst {
|
| POP_INCBIN string COMMA uconst {
|
||||||
sect_BinaryFile($2, $4);
|
if (sect_BinaryFile($2, $4)) {
|
||||||
if (failedOnMissingInclude && !continueAfterMissingIncludes) {
|
|
||||||
YYACCEPT;
|
YYACCEPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| POP_INCBIN string COMMA uconst COMMA uconst {
|
| POP_INCBIN string COMMA uconst COMMA uconst {
|
||||||
sect_BinaryFileSlice($2, $4, $6);
|
if (sect_BinaryFileSlice($2, $4, $6)) {
|
||||||
if (failedOnMissingInclude && !continueAfterMissingIncludes) {
|
|
||||||
YYACCEPT;
|
YYACCEPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()) {
|
if (!requireCodeSection()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *file = nullptr;
|
FILE *file = nullptr;
|
||||||
@@ -884,24 +884,14 @@ void sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
|||||||
file = fopen(fullPath->c_str(), "rb");
|
file = fopen(fullPath->c_str(), "rb");
|
||||||
}
|
}
|
||||||
if (!file) {
|
if (!file) {
|
||||||
if (generatedMissingIncludes) {
|
return fstk_FileError(name, "INCBIN");
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
Defer closeFile{[&] { fclose(file); }};
|
Defer closeFile{[&] { fclose(file); }};
|
||||||
|
|
||||||
if (fseek(file, 0, SEEK_END) != -1) {
|
if (fseek(file, 0, SEEK_END) != -1) {
|
||||||
if (startPos > ftell(file)) {
|
if (startPos > ftell(file)) {
|
||||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
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
|
// The file is seekable; skip to the specified start position
|
||||||
fseek(file, startPos, SEEK_SET);
|
fseek(file, startPos, SEEK_SET);
|
||||||
@@ -913,7 +903,7 @@ void sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
|||||||
while (startPos--) {
|
while (startPos--) {
|
||||||
if (fgetc(file) == EOF) {
|
if (fgetc(file) == EOF) {
|
||||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
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)) {
|
if (ferror(file)) {
|
||||||
error("Error reading INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
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()) {
|
if (!requireCodeSection()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (length == 0) { // Don't even bother with 0-byte slices
|
if (length == 0) { // Don't even bother with 0-byte slices
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *file = nullptr;
|
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");
|
file = fopen(fullPath->c_str(), "rb");
|
||||||
}
|
}
|
||||||
if (!file) {
|
if (!file) {
|
||||||
if (generatedMissingIncludes) {
|
return fstk_FileError(name, "INCBIN");
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
Defer closeFile{[&] { fclose(file); }};
|
Defer closeFile{[&] { fclose(file); }};
|
||||||
|
|
||||||
if (fseek(file, 0, SEEK_END) != -1) {
|
if (fseek(file, 0, SEEK_END) != -1) {
|
||||||
if (long fsize = ftell(file); startPos > fsize) {
|
if (long fsize = ftell(file); startPos > fsize) {
|
||||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
error("Specified start position is greater than length of file '%s'", name.c_str());
|
||||||
return;
|
return false;
|
||||||
} else if (startPos + length > fsize) {
|
} else if (startPos + length > fsize) {
|
||||||
error(
|
error(
|
||||||
"Specified range in INCBIN file '%s' is out of bounds (%" PRIu32 " + %" PRIu32
|
"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,
|
length,
|
||||||
fsize
|
fsize
|
||||||
);
|
);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// The file is seekable; skip to the specified start position
|
// The file is seekable; skip to the specified start position
|
||||||
fseek(file, startPos, SEEK_SET);
|
fseek(file, startPos, SEEK_SET);
|
||||||
@@ -979,7 +960,7 @@ void sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t l
|
|||||||
while (startPos--) {
|
while (startPos--) {
|
||||||
if (fgetc(file) == EOF) {
|
if (fgetc(file) == EOF) {
|
||||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
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() {
|
void sect_PushSection() {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
error: nonexist-include.asm(1):
|
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!
|
Assembly aborted with 1 error!
|
||||||
|
|||||||
Reference in New Issue
Block a user