mirror of
https://github.com/gbdev/rgbds.git
synced 2026-10-03 10:45:37 +00:00
Combine sect_BinaryFile and sect_BinaryFileSlice (#2169)
This commit is contained in:
1 parent
321ad497fa
commit
fcd4031034
3 files changed
+37
-83
No files matched your search
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
@@ -100,8 +101,7 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> 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);
|
||||
bool sect_BinaryFile(std::string const &name, uint32_t startPos);
|
||||
bool sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length);
|
||||
bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<uint32_t> length);
|
||||
|
||||
void sect_EndSection();
|
||||
void sect_PushSection();
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+32
-78
@@ -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,9 +1037,27 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
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)) {
|
||||
// LCOV_EXCL_START
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user