Use a Defer struct to close files and restore lexer state with RAII (#1379)

This commit is contained in:
Sylvie
2024-03-27 10:42:53 -04:00
committed by GitHub
parent 32db0a0f18
commit a68bebf4a2
13 changed files with 131 additions and 172 deletions

View File

@@ -393,7 +393,7 @@ void assign_AssignSections() {
fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';' : ',', section->name.c_str());
nbSections++;
if (nbSections == 10)
goto max_out;
goto max_out; // Can't `break` out of a nested loop
}
}

View File

@@ -320,7 +320,7 @@ static void parseScrambleSpec(char const *spec) {
argErr('S', "Cannot imply limit for region \"%.*s\"", regionNamePrintLen, regionName);
}
next:
next: // Can't `continue` a `for` loop with this nontrivial iteration logic
if (spec) {
assert(*spec == ',' || *spec == '\0');
if (*spec == ',')

View File

@@ -473,7 +473,6 @@ static void readAssertion(
void obj_ReadFile(char const *fileName, unsigned int fileID) {
FILE *file;
if (strcmp(fileName, "-")) {
file = fopen(fileName, "rb");
} else {
@@ -482,6 +481,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
}
if (!file)
err("Failed to open file \"%s\"", fileName);
Defer closeFile{[&] { fclose(file); }};
// First, check if the object is a RGBDS object or a SDCC one. If the first byte is 'R',
// we'll assume it's a RGBDS object file, and otherwise, that it's a SDCC object file.
@@ -630,8 +630,6 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
}
}
}
fclose(file);
}
void obj_CheckAssertions() {

View File

@@ -199,6 +199,10 @@ static void writeROM() {
if (!outputFile)
err("Failed to open output file \"%s\"", outputFileName);
}
Defer closeOutputFile{[&] {
if (outputFile)
fclose(outputFile);
}};
if (overlayFileName) {
if (strcmp(overlayFileName, "-")) {
@@ -210,6 +214,10 @@ static void writeROM() {
if (!overlayFile)
err("Failed to open overlay file \"%s\"", overlayFileName);
}
Defer closeOverlayFile{[&] {
if (overlayFile)
fclose(overlayFile);
}};
uint32_t nbOverlayBanks = checkOverlaySize();
@@ -230,11 +238,6 @@ static void writeROM() {
sectionTypeInfo[SECTTYPE_ROMX].size
);
}
if (outputFile)
fclose(outputFile);
if (overlayFile)
fclose(overlayFile);
}
// Checks whether this character is legal as the first character of a symbol's name in a sym file
@@ -533,6 +536,7 @@ static void writeSym() {
}
if (!symFile)
err("Failed to open sym file \"%s\"", symFileName);
Defer closeSymFile{[&] { fclose(symFile); }};
fputs("; File generated by rgblink\n", symFile);
@@ -542,8 +546,6 @@ static void writeSym() {
for (uint32_t bank = 0; bank < sections[type].size(); bank++)
writeSymBank(sections[type][bank], type, bank);
}
fclose(symFile);
}
// Writes the map file, if applicable.
@@ -559,6 +561,7 @@ static void writeMap() {
}
if (!mapFile)
err("Failed to open map file \"%s\"", mapFileName);
Defer closeMapFile{[&] { fclose(mapFile); }};
writeMapSummary();
@@ -568,8 +571,6 @@ static void writeMap() {
for (uint32_t bank = 0; bank < sections[type].size(); bank++)
writeMapBank(sections[type][bank], type, bank);
}
fclose(mapFile);
}
void out_WriteFiles() {

View File

@@ -225,7 +225,6 @@ static uint8_t parseHexDigit(int c) {
}
yy::parser::symbol_type yylex() {
try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) think it can end.
auto &context = lexerStack.back();
auto c = context.file.sbumpc();
@@ -245,7 +244,7 @@ try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) t
// Basically yywrap().
if (lexerStack.size() != 1) {
lexerStack.pop_back();
goto try_again;
return yylex();
} else if (!atEof) {
// Inject a newline at EOF, to avoid errors for files that don't end with one.
atEof = true;
@@ -353,7 +352,7 @@ try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) t
}
scriptError(context, "Unknown keyword \"%s\"", ident.c_str());
goto try_again; // Try lexing another token.
return yylex();
} else {
scriptError(context, "Unexpected character '%s'", printChar(c));
// Keep reading characters until the EOL, to avoid reporting too many errors.
@@ -363,7 +362,7 @@ try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) t
}
context.file.sbumpc();
}
goto try_again;
return yylex();
}
// Not marking as unreachable; this will generate a warning if any codepath forgets to return.
}

View File

@@ -797,6 +797,10 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
}
}
#undef expectEol
#undef expectToken
#undef getToken
if (!data.empty())
warning(&where, lineNo, "Last 'T' line had no 'R' line (ignored)");
if (fileSections.size() < expectedNbAreas)
@@ -841,10 +845,4 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
// Calling `sect_AddSection` invalidates the contents of `fileSections`!
sect_AddSection(std::move(section));
}
#undef expectEol
#undef expectToken
#undef getToken
fclose(file);
}