Use std::vector for SDCC object line buffer

This commit is contained in:
Rangi42
2024-02-28 22:50:14 -05:00
committed by Sylvie
parent e90084ad06
commit c44b336e1b

View File

@@ -32,10 +32,10 @@ static void consumeLF(struct FileStackNode const *where, uint32_t lineNo, FILE *
static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales
static int nextLine(char **restrict lineBuf, size_t *restrict bufLen, uint32_t *restrict lineNo, static int nextLine(std::vector<char> &lineBuf, uint32_t &lineNo,
struct FileStackNode const *where, FILE *file) { struct FileStackNode const *where, FILE *file) {
retry: retry:
++*lineNo; ++lineNo;
int firstChar = getc(file); int firstChar = getc(file);
switch (firstChar) { switch (firstChar) {
@@ -50,36 +50,25 @@ retry:
// fallthrough // fallthrough
case '\r': case '\r':
if (firstChar == '\r' && getc(file) != '\n') if (firstChar == '\r' && getc(file) != '\n')
consumeLF(where, *lineNo, file); consumeLF(where, lineNo, file);
// fallthrough // fallthrough
case '\n': case '\n':
goto retry; goto retry;
} }
size_t i = 0;
for (;;) { for (;;) {
if (i >= *bufLen) {
assert(*bufLen != 0);
*bufLen *= 2;
*lineBuf = (char *)realloc(*lineBuf, *bufLen);
if (!*lineBuf)
fatal(where, *lineNo, "Failed to realloc: %s", strerror(errno));
}
int c = getc(file); int c = getc(file);
switch (c) { switch (c) {
case '\r': case '\r':
consumeLF(where, *lineNo, file); consumeLF(where, lineNo, file);
// fallthrough // fallthrough
case '\n': case '\n':
case EOF: case EOF:
(*lineBuf)[i] = '\0'; // Terminate the string (space was ensured above) lineBuf.push_back('\0'); // Terminate the string (space was ensured above)
return firstChar; return firstChar;
} }
(*lineBuf)[i] = c; lineBuf.push_back(c);
++i;
} }
} }
@@ -145,8 +134,7 @@ enum RelocFlags {
}; };
void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<struct Symbol> &fileSymbols) { void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<struct Symbol> &fileSymbols) {
size_t bufLen = 256; std::vector<char> line(256);
char *line = (char *)malloc(bufLen);
char const *token; char const *token;
#define getToken(ptr, ...) do { \ #define getToken(ptr, ...) do { \
@@ -166,10 +154,8 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
(lineType), (expected), token); \ (lineType), (expected), token); \
} while (0) } while (0)
if (!line)
fatal(where, 0, "Failed to alloc a line buffer: %s", strerror(errno));
uint32_t lineNo = 0; uint32_t lineNo = 0;
int lineType = nextLine(&line, &bufLen, &lineNo, where, file); int lineType = nextLine(line, lineNo, where, file);
enum NumberType numberType; enum NumberType numberType;
// The first letter (thus, the line type) identifies the integer type // The first letter (thus, the line type) identifies the integer type
@@ -208,12 +194,12 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
// Header line // Header line
lineType = nextLine(&line, &bufLen, &lineNo, where, file); lineType = nextLine(line, lineNo, where, file);
if (lineType != 'H') if (lineType != 'H')
fatal(where, lineNo, "Expected header line, got '%c' line", lineType); fatal(where, lineNo, "Expected header line, got '%c' line", lineType);
// Expected format: "A areas S global symbols" // Expected format: "A areas S global symbols"
getToken(line, "Empty 'H' line"); getToken(line.data(), "Empty 'H' line");
uint32_t expectedNbAreas = parseNumber(where, lineNo, token, numberType); uint32_t expectedNbAreas = parseNumber(where, lineNo, token, numberType);
expectToken("areas", 'H'); expectToken("areas", 'H');
@@ -242,7 +228,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
fatal(where, lineNo, "Failed to alloc data buffer: %s", strerror(errno)); fatal(where, lineNo, "Failed to alloc data buffer: %s", strerror(errno));
for (;;) { for (;;) {
lineType = nextLine(&line, &bufLen, &lineNo, where, file); lineType = nextLine(line, lineNo, where, file);
if (lineType == EOF) if (lineType == EOF)
break; break;
switch (lineType) { switch (lineType) {
@@ -260,7 +246,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
if (!curSection) if (!curSection)
fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno)); fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno));
getToken(line, "'A' line is too short"); getToken(line.data(), "'A' line is too short");
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
// The following is required for fragment offsets to be reliably predicted // The following is required for fragment offsets to be reliably predicted
for (struct FileSection &entry : fileSections) { for (struct FileSection &entry : fileSections) {
@@ -356,7 +342,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
// No need to set the `sectionID`, since we can directly set the pointer // No need to set the `sectionID`, since we can directly set the pointer
symbol.section = !fileSections.empty() ? fileSections.back().section : NULL; symbol.section = !fileSections.empty() ? fileSections.back().section : NULL;
getToken(line, "'S' line is too short"); getToken(line.data(), "'S' line is too short");
symbol.name = token; symbol.name = token;
getToken(NULL, "'S' line is too short"); getToken(NULL, "'S' line is too short");
@@ -413,7 +399,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
warning(where, lineNo, "Previous 'T' line had no 'R' line (ignored)"); warning(where, lineNo, "Previous 'T' line had no 'R' line (ignored)");
nbBytes = 0; nbBytes = 0;
for (token = strtok(line, delim); token; token = strtok(NULL, delim)) { for (token = strtok(line.data(), delim); token; token = strtok(NULL, delim)) {
if (dataCapacity == nbBytes) { if (dataCapacity == nbBytes) {
dataCapacity *= 2; dataCapacity *= 2;
data = (uint8_t *)realloc(data, sizeof(*data) * dataCapacity); data = (uint8_t *)realloc(data, sizeof(*data) * dataCapacity);
@@ -438,7 +424,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
} }
// First two bytes are ignored // First two bytes are ignored
getToken(line, "'R' line is too short"); getToken(line.data(), "'R' line is too short");
getToken(NULL, "'R' line is too short"); getToken(NULL, "'R' line is too short");
uint16_t areaIdx; uint16_t areaIdx;
@@ -727,6 +713,5 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
#undef expectToken #undef expectToken
#undef getToken #undef getToken
free(data);
fclose(file); fclose(file);
} }