Support Mac OS classic CR line endings in linkerscripts

This also refactors `readChar(file)` to `nextChar()` to be
more like the rgbasm lexer.
This commit is contained in:
Rangi
2021-04-26 11:55:50 -04:00
committed by Rangi
parent e27a6d53a0
commit 43cf20b155
3 changed files with 26 additions and 29 deletions

View File

@@ -43,8 +43,7 @@ static void pushFile(char *newFileName)
if (!fileStackSize) /* Init file stack */ if (!fileStackSize) /* Init file stack */
fileStackSize = 4; fileStackSize = 4;
fileStackSize *= 2; fileStackSize *= 2;
fileStack = realloc(fileStack, fileStack = realloc(fileStack, sizeof(*fileStack) * fileStackSize);
sizeof(*fileStack) * fileStackSize);
if (!fileStack) if (!fileStack)
err(1, "%s(%" PRIu32 "): Internal INCLUDE error", err(1, "%s(%" PRIu32 "): Internal INCLUDE error",
linkerScriptName, lineNo); linkerScriptName, lineNo);
@@ -173,11 +172,11 @@ static char const * const commands[] = {
[COMMAND_ALIGN] = "ALIGN" [COMMAND_ALIGN] = "ALIGN"
}; };
static int readChar(FILE *file) static int nextChar(void)
{ {
int curchar = getc(file); int curchar = getc(linkerScript);
if (curchar == EOF && ferror(file)) if (curchar == EOF && ferror(linkerScript))
err(1, "%s(%" PRIu32 "): Unexpected error in %s", err(1, "%s(%" PRIu32 "): Unexpected error in %s",
linkerScriptName, lineNo, __func__); linkerScriptName, lineNo, __func__);
return curchar; return curchar;
@@ -194,14 +193,14 @@ static struct LinkerScriptToken *nextToken(void)
/* Skip initial whitespace... */ /* Skip initial whitespace... */
do do
curchar = readChar(linkerScript); curchar = nextChar();
while (isWhiteSpace(curchar)); while (isWhiteSpace(curchar));
/* If this is a comment, skip to the end of the line */ /* If this is a comment, skip to the end of the line */
if (curchar == ';') { if (curchar == ';') {
do do {
curchar = readChar(linkerScript); curchar = nextChar();
while (!isNewline(curchar) && curchar != EOF); } while (!isNewline(curchar) && curchar != EOF);
} }
if (curchar == EOF) { if (curchar == EOF) {
@@ -210,9 +209,14 @@ static struct LinkerScriptToken *nextToken(void)
/* If we have a newline char, this is a newline token */ /* If we have a newline char, this is a newline token */
token.type = TOKEN_NEWLINE; token.type = TOKEN_NEWLINE;
/* FIXME: This works with CRLF newlines, but not CR-only */ if (curchar == '\r') {
if (curchar == '\r') /* Handle CRLF */
readChar(linkerScript); /* Read and discard LF */ curchar = nextChar();
if (curchar != '\n') {
ungetc(curchar, linkerScript);
curchar = '\r';
}
}
} else if (curchar == '"') { } else if (curchar == '"') {
/* If we have a string start, this is a string */ /* If we have a string start, this is a string */
token.type = TOKEN_STRING; token.type = TOKEN_STRING;
@@ -222,7 +226,7 @@ static struct LinkerScriptToken *nextToken(void)
size_t capacity = 16; /* Half of the default capacity */ size_t capacity = 16; /* Half of the default capacity */
do { do {
curchar = readChar(linkerScript); curchar = nextChar();
if (curchar == EOF || isNewline(curchar)) { if (curchar == EOF || isNewline(curchar)) {
errx(1, "%s(%" PRIu32 "): Unterminated string", errx(1, "%s(%" PRIu32 "): Unterminated string",
linkerScriptName, lineNo); linkerScriptName, lineNo);
@@ -231,7 +235,7 @@ static struct LinkerScriptToken *nextToken(void)
curchar = '\0'; curchar = '\0';
} else if (curchar == '\\') { } else if (curchar == '\\') {
/* Backslashes are escape sequences */ /* Backslashes are escape sequences */
curchar = readChar(linkerScript); curchar = nextChar();
if (curchar == EOF || isNewline(curchar)) if (curchar == EOF || isNewline(curchar))
errx(1, "%s(%" PRIu32 "): Unterminated string", errx(1, "%s(%" PRIu32 "): Unterminated string",
linkerScriptName, lineNo); linkerScriptName, lineNo);
@@ -248,8 +252,7 @@ static struct LinkerScriptToken *nextToken(void)
if (size >= capacity || token.attr.string == NULL) { if (size >= capacity || token.attr.string == NULL) {
capacity *= 2; capacity *= 2;
token.attr.string = realloc(token.attr.string, token.attr.string = realloc(token.attr.string, capacity);
capacity);
if (!token.attr.string) if (!token.attr.string)
err(1, "%s: Failed to allocate memory for string", err(1, "%s: Failed to allocate memory for string",
__func__); __func__);
@@ -276,10 +279,9 @@ static struct LinkerScriptToken *nextToken(void)
if (!curchar) if (!curchar)
break; break;
curchar = readChar(linkerScript); curchar = nextChar();
/* Whitespace, a newline or a comment end the token */ /* Whitespace, a newline or a comment end the token */
if (isWhiteSpace(curchar) || isNewline(curchar) if (isWhiteSpace(curchar) || isNewline(curchar) || curchar == ';') {
|| curchar == ';') {
ungetc(curchar, linkerScript); ungetc(curchar, linkerScript);
curchar = '\0'; curchar = '\0';
} }
@@ -298,8 +300,7 @@ static struct LinkerScriptToken *nextToken(void)
if (token.type == TOKEN_INVALID) { if (token.type == TOKEN_INVALID) {
/* Try to match a bank specifier */ /* Try to match a bank specifier */
for (enum SectionType type = 0; type < SECTTYPE_INVALID; for (enum SectionType type = 0; type < SECTTYPE_INVALID; type++) {
type++) {
if (!strcmp(typeNames[type], str)) { if (!strcmp(typeNames[type], str)) {
token.type = TOKEN_BANK; token.type = TOKEN_BANK;
token.attr.secttype = type; token.attr.secttype = type;
@@ -329,8 +330,7 @@ static struct LinkerScriptToken *nextToken(void)
return &token; return &token;
} }
static void processCommand(enum LinkerScriptCommand command, uint16_t arg, static void processCommand(enum LinkerScriptCommand command, uint16_t arg, uint16_t *pc)
uint16_t *pc)
{ {
switch (command) { switch (command) {
case COMMAND_INVALID: case COMMAND_INVALID:
@@ -475,8 +475,7 @@ struct SectionPlacement *script_NextSection(void)
errx(1, "%s(%" PRIu32 "): Command specified without an argument", errx(1, "%s(%" PRIu32 "): Command specified without an argument",
linkerScriptName, lineNo); linkerScriptName, lineNo);
processCommand(attr.command, arg, processCommand(attr.command, arg, &curaddr[type][bankID]);
&curaddr[type][bankID]);
} else { /* TOKEN_BANK */ } else { /* TOKEN_BANK */
type = attr.secttype; type = attr.secttype;
/* /*

View File

@@ -1,3 +1 @@
ROM0 ; This uses CR line endings
"A\"B\tC\rD\nE"
"in\{valid"

View File

@@ -1 +1 @@
error: ./linkerscript-escapes-test.link(3): Illegal character escape error: ./linkerscript-escapes-test.link(4): Illegal character escape