Combine sect_BinaryFile and sect_BinaryFileSlice (#2169)

This commit is contained in:
Rangi authored and GitHub committed 2026-09-26 22:05:39 -04:00
1 parent 321ad497fa
commit fcd4031034
3 files changed
+39 -85

No files matched your search

+3 -3
View File
@@ -1035,17 +1035,17 @@ include:
incbin:
POP_INCBIN string {
if (sect_BinaryFile($2, 0)) {
if (sect_BinaryFile($2, 0, std::nullopt)) {
YYACCEPT;
}
}
| POP_INCBIN string COMMA uconst {
if (sect_BinaryFile($2, $4)) {
if (sect_BinaryFile($2, $4, std::nullopt)) {
YYACCEPT;
}
}
| POP_INCBIN string COMMA uconst COMMA uconst {
if (sect_BinaryFileSlice($2, $4, $6)) {
if (sect_BinaryFile($2, $4, $6)) {
YYACCEPT;
}
}
+34 -80
View File
@@ -978,10 +978,13 @@ void sect_PCRelByte(Expression const &expr, uint32_t pcShift) {
}
}
bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<uint32_t> length) {
if (!requireCodeSection()) {
return false;
}
if (length.has_value() && *length == 0) { // Don't even bother with 0-byte slices
return false;
}
FILE *file = nullptr;
if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {
@@ -1002,6 +1005,16 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
*fileSize
);
return false;
} else if (length.has_value() && *length > *fileSize - startPos) {
error(
"Specified range in `INCBIN` file \"%s\" is out of bounds (%" PRIu32 " + %" PRIu32
" > %" PRIu64 ")",
name.c_str(),
startPos,
*length,
*fileSize
);
return false;
}
// The file is seekable; skip to the specified start position
fseek(file, startPos, SEEK_SET);
@@ -1024,8 +1037,26 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
// LCOV_EXCL_STOP
}
for (int byte; (byte = fgetc(file)) != EOF;) {
writeByte(byte);
if (length.has_value()) {
uint32_t remaining = *length;
for (; remaining; --remaining) {
if (int byte = fgetc(file); byte == EOF) {
break; // LCOV_EXCL_LINE
} else {
writeByte(byte);
}
}
if (remaining > 0 && !ferror(file)) {
error(
"Premature end of `INCBIN` file \"%s\" (%" PRId32 " bytes left to read)",
name.c_str(),
remaining
);
}
} else {
for (int byte; (byte = fgetc(file)) != EOF;) {
writeByte(byte);
}
}
if (ferror(file)) {
@@ -1036,83 +1067,6 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
return false;
}
bool sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length) {
if (!requireCodeSection()) {
return false;
}
if (length == 0) { // Don't even bother with 0-byte slices
return false;
}
FILE *file = nullptr;
if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {
file = fopen(fullPath->c_str(), "rb");
}
if (!file) {
return fstk_FileError(name, "`INCBIN`");
}
Defer closeFile{[&] { xfclose(file); }};
if (std::optional<uint64_t> fileSize = seekSize(file); fileSize.has_value()) {
if (startPos > *fileSize) {
error(
"Specified start position (%" PRIu32 ") is greater than length of \"%s\" (%" PRIu64
")",
startPos,
name.c_str(),
*fileSize
);
return false;
} else if (length > *fileSize - startPos) {
error(
"Specified range in `INCBIN` file \"%s\" is out of bounds (%" PRIu32 " + %" PRIu32
" > %" PRIu64 ")",
name.c_str(),
startPos,
length,
*fileSize
);
return false;
}
// The file is seekable; skip to the specified start position
fseek(file, startPos, SEEK_SET);
} else {
// LCOV_EXCL_START
if (errno != ESPIPE) {
error(
"Error determining size of `INCBIN` file \"%s\": %s", name.c_str(), strerror(errno)
);
}
// The file isn't seekable, so we'll just skip bytes one at a time
while (startPos--) {
if (fgetc(file) == EOF) {
error(
"Specified start position is greater than length of file \"%s\"", name.c_str()
);
return false;
}
}
// LCOV_EXCL_STOP
}
while (length--) {
if (int byte = fgetc(file); byte != EOF) {
writeByte(byte);
// LCOV_EXCL_START
} else if (ferror(file)) {
error("Error reading `INCBIN` file \"%s\": %s", name.c_str(), strerror(errno));
} else {
error(
"Premature end of `INCBIN` file \"%s\" (%" PRId32 " bytes left to read)",
name.c_str(),
length + 1
);
// LCOV_EXCL_STOP
}
}
return false;
}
void sect_PushSection() {
sectionStack.push_front({
.section = currentSection,