diff --git a/src/asm/lexer.c b/src/asm/lexer.c index 20b6690a..30a940a7 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -6,6 +6,7 @@ * SPDX-License-Identifier: MIT */ +#include #include #include #include @@ -110,6 +111,21 @@ void yy_delete_buffer(YY_BUFFER_STATE buf) free(buf); } +/* + * Maintains the following invariants: + * 1. nBufferSize < capacity + * 2. The buffer is terminated with 0 + * 3. nBufferSize is the size without the terminator + */ +static void yy_buffer_append(YY_BUFFER_STATE buf, uint32_t capacity, char c) +{ + assert(buf->pBuffer[buf->nBufferSize] == 0); + assert(buf->nBufferSize + 1 < capacity); + + buf->pBuffer[buf->nBufferSize++] = c; + buf->pBuffer[buf->nBufferSize] = 0; +} + YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size) { YY_BUFFER_STATE pBuffer = malloc(sizeof(struct yy_buffer_state)); @@ -145,7 +161,10 @@ YY_BUFFER_STATE yy_create_buffer(FILE *f) size = ftell(f); fseek(f, 0, SEEK_SET); - pBuffer->pBufferRealStart = malloc(size + 2 + SAFETYMARGIN); + /* Give extra room for 2 newlines and terminator */ + uint32_t capacity = size + 3; + + pBuffer->pBufferRealStart = malloc(capacity + SAFETYMARGIN); if (pBuffer->pBufferRealStart == NULL) fatalerror("%s: Out of memory for buffer!", __func__); @@ -155,9 +174,8 @@ YY_BUFFER_STATE yy_create_buffer(FILE *f) size = fread(pBuffer->pBuffer, sizeof(uint8_t), size, f); - pBuffer->pBuffer[size] = '\n'; - pBuffer->pBuffer[size + 1] = 0; - pBuffer->nBufferSize = size + 1; + pBuffer->pBuffer[size] = 0; + pBuffer->nBufferSize = size; /* Convert all line endings to LF and spaces */ @@ -218,6 +236,22 @@ YY_BUFFER_STATE yy_create_buffer(FILE *f) } } + /* Add newline if file doesn't end with one */ + if (size == 0 || pBuffer->pBuffer[size - 1] != '\n') + yy_buffer_append(pBuffer, capacity, '\n'); + + /* Add newline if \ will eat the last newline */ + if (pBuffer->nBufferSize >= 2) { + size_t pos = pBuffer->nBufferSize - 2; + + /* Skip spaces */ + while (pos > 0 && pBuffer->pBuffer[pos] == ' ') + pos--; + + if (pBuffer->pBuffer[pos] == '\\') + yy_buffer_append(pBuffer, capacity, '\n'); + } + pBuffer->oAtLineStart = 1; return pBuffer; } diff --git a/test/asm/line-continuation.asm b/test/asm/line-continuation.asm new file mode 100644 index 00000000..5474f368 --- /dev/null +++ b/test/asm/line-continuation.asm @@ -0,0 +1 @@ +foo @bar\ \ No newline at end of file diff --git a/test/asm/line-continuation.out b/test/asm/line-continuation.out new file mode 100644 index 00000000..1d1dd81b --- /dev/null +++ b/test/asm/line-continuation.out @@ -0,0 +1,2 @@ +ERROR: line-continuation.asm(2) -> @(-1): + Macro '@' not defined