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