shithub: rgbds

Download patch

ref: 847cae5b95c43b6ff5317335b4185ac22161bd52
parent: 3cd1d46a1bf66df5fafe04dde885cc6f3dfcdb28
parent: df15c97b6e85ab622e21889137184038c0476987
author: Antonio Niño Díaz <antonio_nd@outlook.com>
date: Thu Jul 4 19:02:42 EDT 2019

Merge pull request #329 from NieDzejkob/allow-stdin-input

Allow using - to indicate input from stdin (resolves #305)

--- a/include/asm/lexer.h
+++ b/include/asm/lexer.h
@@ -31,7 +31,7 @@
 	/* Address where the data is initially written after a safety margin */
 	char *pBufferStart;
 	char *pBuffer;
-	uint32_t nBufferSize;
+	size_t nBufferSize;
 	uint32_t oAtLineStart;
 };
 
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -405,23 +405,25 @@
 /*
  * Initialize the filestack routines
  */
-void fstk_Init(char *s)
+void fstk_Init(char *pFileName)
 {
-	char tzFileName[_MAX_PATH + 1];
 	char tzSymFileName[_MAX_PATH + 1 + 2];
 
-	snprintf(tzSymFileName, sizeof(tzSymFileName), "\"%s\"", s);
+	snprintf(tzSymFileName, sizeof(tzSymFileName), "\"%s\"", pFileName);
 	sym_AddString("__FILE__", tzSymFileName);
 
-	strcpy(tzFileName, s);
 	pFileStack = NULL;
-	pCurrentFile = fopen(tzFileName, "rb");
-	if (pCurrentFile == NULL)
-		err(1, "Unable to open file '%s'", tzFileName);
+	if (strcmp(pFileName, "-") == 0) {
+		pCurrentFile = stdin;
+	} else {
+		pCurrentFile = fopen(pFileName, "rb");
+		if (pCurrentFile == NULL)
+			err(1, "Unable to open file '%s'", pFileName);
+	}
 
 	nMacroCount = 0;
 	nCurrentStatus = STAT_isInclude;
-	snprintf(tzCurrentFileName, _MAX_PATH + 1, "%s", tzFileName);
+	snprintf(tzCurrentFileName, _MAX_PATH + 1, "%s", pFileName);
 	CurrentFlexHandle = yy_create_buffer(pCurrentFile);
 	yy_switch_to_buffer(CurrentFlexHandle);
 	nLineNo = 1;
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -156,27 +156,70 @@
 	if (pBuffer == NULL)
 		fatalerror("%s: Out of memory!", __func__);
 
-	uint32_t size;
+	size_t size = 0, capacity = -1;
+	char *buf = NULL;
 
-	fseek(f, 0, SEEK_END);
-	size = ftell(f);
-	fseek(f, 0, SEEK_SET);
+	/*
+	 * Check if we can get the file size without implementation-defined
+	 * behavior:
+	 *
+	 * From ftell(3p):
+	 * [On error], ftell() and ftello() shall return −1, and set errno to
+	 * indicate the error.
+	 *
+	 * The ftell() and ftello() functions shall fail if: [...]
+	 * ESPIPE The file descriptor underlying stream is associated with a
+	 * pipe, FIFO, or socket.
+	 *
+	 * From fseek(3p):
+	 * The behavior of fseek() on devices which are incapable of seeking
+	 * is implementation-defined.
+	 */
+	if (ftell(f) != -1) {
+		fseek(f, 0, SEEK_END);
+		capacity = ftell(f);
+		rewind(f);
+	}
 
-	/* Give extra room for 2 newlines and terminator */
-	uint32_t capacity = size + 3;
+	// If ftell errored or the block above wasn't executed
+	if (capacity == -1)
+		capacity = 4096;
+	// Handle 0-byte files gracefully
+	else if (capacity == 0)
+		capacity = 1;
 
-	pBuffer->pBufferRealStart = malloc(capacity + SAFETYMARGIN);
+	while (!feof(f)) {
+		if (buf == NULL || size >= capacity) {
+			if (buf)
+				capacity *= 2;
+			/* Give extra room for 2 newlines and terminator */
+			buf = realloc(buf, capacity + SAFETYMARGIN + 3);
 
-	if (pBuffer->pBufferRealStart == NULL)
-		fatalerror("%s: Out of memory for buffer!", __func__);
+			if (buf == NULL)
+				fatalerror("%s: Out of memory for buffer!",
+					   __func__);
+		}
 
-	pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
-	pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
+		char *bufpos = buf + SAFETYMARGIN + size;
+		size_t read_count = fread(bufpos, 1, capacity - size, f);
 
-	size = fread(pBuffer->pBuffer, sizeof(uint8_t), size, f);
+		if (read_count == 0 && !feof(f))
+			fatalerror("%s: fread error", __func__);
 
+		size += read_count;
+	}
+
+	pBuffer->pBufferRealStart = buf;
+	pBuffer->pBufferStart = buf + SAFETYMARGIN;
+	pBuffer->pBuffer = buf + SAFETYMARGIN;
 	pBuffer->pBuffer[size] = 0;
 	pBuffer->nBufferSize = size;
+
+	/* This is added here to make the buffer scaling above easy to express,
+	 * while taking the newline space into account
+	 * for the `yy_buffer_append`s below.
+	 */
+	capacity += 3;
 
 	/* Convert all line endings to LF and spaces */
 
--- /dev/null
+++ b/test/asm/divzero-instr.out.pipe
@@ -1,0 +1,2 @@
+ERROR: -(2):
+    Division by zero
--- /dev/null
+++ b/test/asm/divzero-section-bank.out.pipe
@@ -1,0 +1,4 @@
+ERROR: -(1):
+    Invalid integer constant
+ERROR: -(1):
+    Division by zero
--- /dev/null
+++ b/test/asm/label-redefinition.out.pipe
@@ -1,0 +1,3 @@
+ERROR: -(7):
+    'Sym' already defined in m(6)
+error: Assembly aborted (1 errors)!
--- /dev/null
+++ b/test/asm/line-continuation.out.pipe
@@ -1,0 +1,2 @@
+ERROR: -(2) -> @(-1):
+    Macro '@' not defined
--- /dev/null
+++ b/test/asm/local-wrong-parent.out.pipe
@@ -1,0 +1,3 @@
+ERROR: -(5):
+    Not currently in the scope of 'WrongParent'
+error: Assembly aborted (1 errors)!
--- /dev/null
+++ b/test/asm/macro-@.out.pipe
@@ -1,0 +1,2 @@
+ERROR: -(1) -> @(-1):
+    Macro '@' not defined
--- /dev/null
+++ b/test/asm/null-in-macro.out.pipe
@@ -1,0 +1,2 @@
+ERROR: -(1):
+    Unterminated MACRO definition.
--- /dev/null
+++ b/test/asm/reference-undefined-sym.out.pipe
@@ -1,0 +1,3 @@
+ERROR: -(4):
+    'X' already referenced at -(2)
+error: Assembly aborted (1 errors)!
--- /dev/null
+++ b/test/asm/remote-local-noexist.out.pipe
@@ -1,0 +1,2 @@
+ERROR: -(7):
+    'Parent.child.fail' is a nonsensical reference to a nested local symbol
--- /dev/null
+++ b/test/asm/strlen.out.pipe
@@ -1,0 +1,2 @@
+$3
+$4
--- /dev/null
+++ b/test/asm/strsub.out.pipe
@@ -1,0 +1,31 @@
+warning: -(13) -> xstrsub(1):
+    STRSUB: Length too big: 32
+warning: -(14) -> xstrsub(1):
+    STRSUB: Length too big: 300
+warning: -(15) -> xstrsub(1):
+    STRSUB: Position starts at 1
+warning: -(15) -> xstrsub(1):
+    STRSUB: Length too big: 300
+warning: -(16) -> xstrsub(1):
+    STRSUB: Position 4 is past the end of the string
+warning: -(17) -> xstrsub(1):
+    STRSUB: Position 4 is past the end of the string
+warning: -(17) -> xstrsub(1):
+    STRSUB: Length too big: 1
+warning: -(20) -> xstrsub(1):
+    STRSUB: Length too big: 10
+A
+B
+C
+AB
+BC
+BC
+BC
+ABC
+
+
+カタ
+カナ
+カナ
+g
+g̈
--- a/test/asm/test.sh
+++ b/test/asm/test.sh
@@ -6,18 +6,25 @@
 rc=0
 
 for i in *.asm; do
-	../../rgbasm -o $o $i > $after 2>&1
-	diff -u ${i%.asm}.out $after
-	rc=$(($? || $rc))
-	bin=${i%.asm}.out.bin
-	if [ -f $bin ]; then
-		../../rgblink -o $gb $o > $after 2>&1
-		head -c $(wc -c < $bin) $gb > $after 2>&1
-		hexdump -C $after > $before && mv $before $after
-		hexdump -C $bin > $before
-		diff -u $before $after
+	for variant in '' '.pipe'; do
+		if [ -z "$variant" ]; then
+			../../rgbasm -o $o $i > $after 2>&1
+		else
+			cat $i | ../../rgbasm -o $o - > $after 2>&1
+		fi
+
+		diff -u ${i%.asm}.out$variant $after
 		rc=$(($? || $rc))
-	fi
+		bin=${i%.asm}.out.bin
+		if [ -f $bin ]; then
+			../../rgblink -o $gb $o > $after 2>&1
+			head -c $(wc -c < $bin) $gb > $after 2>&1
+			hexdump -C $after > $before && mv $before $after
+			hexdump -C $bin > $before
+			diff -u $before $after
+			rc=$(($? || $rc))
+		fi
+	done
 done
 
 rm -f $o $gb $before $after
--- /dev/null
+++ b/test/asm/undefined-dot.out.pipe
@@ -1,0 +1,1 @@
+error: -(3) : '.' not defined