mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 02:32:06 +00:00
Use automatic allocation for tryReadstring
This commit is contained in:
@@ -97,34 +97,7 @@ static int64_t readlong(FILE *file)
|
|||||||
tryRead(getc, int, EOF, type, var, file, __VA_ARGS__)
|
tryRead(getc, int, EOF, type, var, file, __VA_ARGS__)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads a '\0'-terminated string from a file.
|
* Helper macro for readings '\0'-terminated strings from a file, and errors out if it fails to.
|
||||||
* @param file The file to read from. The file position will be advanced.
|
|
||||||
* @return The string read, or NULL on failure.
|
|
||||||
* If a non-NULL pointer is returned, make sure to `free` it when done!
|
|
||||||
*/
|
|
||||||
static std::string *readstring(FILE *file)
|
|
||||||
{
|
|
||||||
std::string *str = new(std::nothrow) std::string();
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
return NULL;
|
|
||||||
for (;;) {
|
|
||||||
// Read char
|
|
||||||
int byte = getc(file);
|
|
||||||
|
|
||||||
if (byte == EOF) {
|
|
||||||
delete str;
|
|
||||||
return NULL;
|
|
||||||
} else if (byte == '\0') {
|
|
||||||
return str;
|
|
||||||
} else {
|
|
||||||
str->push_back(byte);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper macro for reading bytes from a file, and errors out if it fails to.
|
|
||||||
* Not as a function to avoid overhead in the general case.
|
* Not as a function to avoid overhead in the general case.
|
||||||
* @param var The variable to stash the string into
|
* @param var The variable to stash the string into
|
||||||
* @param file The file to read from. Its position will be advanced
|
* @param file The file to read from. Its position will be advanced
|
||||||
@@ -132,7 +105,19 @@ static std::string *readstring(FILE *file)
|
|||||||
* argument is provided, the reason for failure
|
* argument is provided, the reason for failure
|
||||||
*/
|
*/
|
||||||
#define tryReadstring(var, file, ...) \
|
#define tryReadstring(var, file, ...) \
|
||||||
tryRead(readstring, std::string *, NULL, std::string *, var, file, __VA_ARGS__)
|
do { \
|
||||||
|
FILE *tmpFile = file; \
|
||||||
|
std::string &tmpVal = var; \
|
||||||
|
for (int tmpByte = getc(tmpFile); tmpByte != '\0'; tmpByte = getc(tmpFile)) { \
|
||||||
|
if (tmpByte == EOF) { \
|
||||||
|
errx(__VA_ARGS__, feof(tmpFile) \
|
||||||
|
? "Unexpected end of file" \
|
||||||
|
: strerror(errno)); \
|
||||||
|
} else { \
|
||||||
|
tmpVal.push_back(tmpByte); \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
// Functions to parse object files
|
// Functions to parse object files
|
||||||
|
|
||||||
@@ -157,13 +142,11 @@ static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fil
|
|||||||
tryGetc(enum FileStackNodeType, node.type, file,
|
tryGetc(enum FileStackNodeType, node.type, file,
|
||||||
"%s: Cannot read node #%" PRIu32 "'s type: %s", fileName, i);
|
"%s: Cannot read node #%" PRIu32 "'s type: %s", fileName, i);
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
std::string *name;
|
|
||||||
case NODE_FILE:
|
case NODE_FILE:
|
||||||
case NODE_MACRO:
|
case NODE_MACRO:
|
||||||
tryReadstring(name, file,
|
node.data = "";
|
||||||
|
tryReadstring(node.name(), file,
|
||||||
"%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i);
|
"%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i);
|
||||||
node.data = *name;
|
|
||||||
delete name;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
uint32_t depth;
|
uint32_t depth;
|
||||||
@@ -190,11 +173,7 @@ static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fil
|
|||||||
static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName,
|
static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName,
|
||||||
std::vector<struct FileStackNode> const &fileNodes)
|
std::vector<struct FileStackNode> const &fileNodes)
|
||||||
{
|
{
|
||||||
std::string *name;
|
tryReadstring(symbol->name, file, "%s: Cannot read symbol name: %s", fileName);
|
||||||
|
|
||||||
tryReadstring(name, file, "%s: Cannot read symbol name: %s", fileName);
|
|
||||||
symbol->name = *name;
|
|
||||||
delete name;
|
|
||||||
tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s",
|
tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s",
|
||||||
fileName, symbol->name.c_str());
|
fileName, symbol->name.c_str());
|
||||||
// If the symbol is defined in this file, read its definition
|
// If the symbol is defined in this file, read its definition
|
||||||
@@ -283,11 +262,8 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
|
|||||||
{
|
{
|
||||||
int32_t tmp;
|
int32_t tmp;
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
std::string *str;
|
|
||||||
|
|
||||||
tryReadstring(str, file, "%s: Cannot read section name: %s", fileName);
|
tryReadstring(section->name, file, "%s: Cannot read section name: %s", fileName);
|
||||||
section->name = *str;
|
|
||||||
delete str;
|
|
||||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section->name.c_str());
|
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section->name.c_str());
|
||||||
if (tmp < 0 || tmp > UINT16_MAX)
|
if (tmp < 0 || tmp > UINT16_MAX)
|
||||||
errx("\"%s\"'s section size (%" PRId32 ") is invalid", section->name.c_str(), tmp);
|
errx("\"%s\"'s section size (%" PRId32 ") is invalid", section->name.c_str(), tmp);
|
||||||
@@ -384,14 +360,11 @@ static void readAssertion(FILE *file, struct Assertion *assert, char const *file
|
|||||||
std::vector<struct FileStackNode> const &fileNodes)
|
std::vector<struct FileStackNode> const &fileNodes)
|
||||||
{
|
{
|
||||||
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
|
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
|
||||||
std::string *name;
|
|
||||||
|
|
||||||
snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i);
|
snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i);
|
||||||
|
|
||||||
readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes);
|
readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes);
|
||||||
tryReadstring(name, file, "%s: Cannot read assertion's message: %s", fileName);
|
tryReadstring(assert->message, file, "%s: Cannot read assertion's message: %s", fileName);
|
||||||
assert->message = *name;
|
|
||||||
delete name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Section *getMainSection(struct Section *section)
|
static struct Section *getMainSection(struct Section *section)
|
||||||
|
|||||||
Reference in New Issue
Block a user