shithub: rgbds

Download patch

ref: 43cf20b155f9888b838ef226f348983923992380
parent: e27a6d53a0219deda031496767e73999bb988b74
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Mon Apr 26 07:55:50 EDT 2021

Support Mac OS classic CR line endings in linkerscripts

This also refactors `readChar(file)` to `nextChar()` to be
more like the rgbasm lexer.

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