From 2be1815c9a6b0c41fe11d0fc311f46ac7d99088c Mon Sep 17 00:00:00 2001 From: Lukas Krickl Date: Wed, 31 Dec 2025 06:17:29 +0100 Subject: [PATCH] ulas: Added line escaping Lines can now be escape using '\'. When the last printable character of a line is '\' the next line is read before executing the preprocessor. This allows breaking up lines into more readable variants. --- TODO.md | 1 - makefile | 1 + src/test.c | 1 + src/ulas.c | 56 +++++++++++++++++++++++++++++++++++++++++--- tests/multiline.bin | Bin 0 -> 17 bytes tests/multiline.s | 17 ++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/multiline.bin create mode 100644 tests/multiline.s diff --git a/TODO.md b/TODO.md index 4820496..cd055f7 100644 --- a/TODO.md +++ b/TODO.md @@ -9,7 +9,6 @@ - Assert `.section` in full test - Add `.bank.` directive allowing users to set the current bank number (ulas.bank) which can be used for symbol files. - Allow nested begin and end scope calls -- Add `forth-like` mode. This mode should allow defining words similar to forth. It should have a built-in word for `assembly output` that can be implemented by the user. - Add `.extern` directive allowing the user to define external labels - Add `.scope` for `.def` and `.de.` variables - Add `#cop n, ...` preprocessor directive. It should work just like .rep but just insert the line n times into the source code and then preprocess the result. diff --git a/makefile b/makefile index 7badfd8..4b66e38 100644 --- a/makefile +++ b/makefile @@ -52,4 +52,5 @@ install: buildtests: bin ./$(NAME) tests/t0.s -D ULAS_PREDEF -l - -o tests/t0.bin + ./$(NAME) tests/multiline.s -D ULAS_PREDEF -l - -o tests/multiline.bin ./$(NAME) tests/t0.bin -d - -o tests/t0_dasm.s diff --git a/src/test.c b/src/test.c index 0fa1c23..553d5f8 100644 --- a/src/test.c +++ b/src/test.c @@ -421,6 +421,7 @@ void test_full_asm(void) { TESTBEGIN("testfullasm"); ASSERT_FULL_ASM(0, "tests/t0.s", "tests/t0.bin"); + ASSERT_FULL_ASM(0, "tests/multiline.s", "tests/multiline.bin"); TESTEND("testfullasm"); } diff --git a/src/ulas.c b/src/ulas.c index 19894ba..9f1d3d8 100644 --- a/src/ulas.c +++ b/src/ulas.c @@ -1290,11 +1290,61 @@ found: return ULAS_PPDIR_NONE; } +// checks if the last printable char in a string is '\' +// side-effect: also replaced that what with \0 if it is found +int ulas_last_print_is_escape(char *buf, int n) { + int found_escape = 0; + // check if last printable char is an escape char + unsigned int buf_len = strnlen(buf, n); + if (buf_len == 0) { + return 0; + } + + for (int i = buf_len - 1; i >= 0; i--) { + if (isprint(buf[i])) { + found_escape = buf[i] == '\\'; + if (found_escape) { + buf[i] = '\0'; + } + break; + } + } + + return found_escape; +} + +// call fgets and concats into buf until either buf is full (fatal error) +// or a non-escape character is *not* the last chracter of a line +// returns number of lines read +int ulas_fgets(char *buf, int n, FILE *src) { + char internal_buf[ULAS_LINEMAX+1]; + buf[0] = '\0'; + internal_buf[ULAS_LINEMAX] = '\0'; + + int lines_read = 0; + + do { + char *res = fgets(internal_buf, ULAS_LINEMAX, src); + + // bail early + if (res == NULL) { + break; + } + + strncat(buf, internal_buf, n); + + lines_read++; + } while(ulas_last_print_is_escape(buf, n)); + + return lines_read; +} + int ulas_preprocnext(struct ulas_preproc *pp, FILE *dst, FILE *src, char *buf, int n) { int rc = 1; - if (fgets(buf, n, src) != NULL) { - ulas.line++; + int lines_read = 0; + if ((lines_read = ulas_fgets(buf, n, src)) != 0) { + ulas.line += lines_read; unsigned long buflen = strlen(buf); @@ -2707,7 +2757,7 @@ fail: int ulas_asmnext(FILE *dst, FILE *src, char *buf, int n) { int rc = 1; - if (fgets(buf, n, src) != NULL) { + if (ulas_fgets(buf, n, src) != 0) { unsigned long buflen = strlen(buf); if (ulas_asmline(dst, src, buf, buflen) == -1) { rc = -1; diff --git a/tests/multiline.bin b/tests/multiline.bin new file mode 100644 index 0000000000000000000000000000000000000000..955058a6897aaa47f707007d39245fc800bbf760 GIT binary patch literal 17 YcmZ=@P;_|Ykdc~`lV6@+l#{{$05hTn00000 literal 0 HcmV?d00001 diff --git a/tests/multiline.s b/tests/multiline.s new file mode 100644 index 0000000..65bbcb7 --- /dev/null +++ b/tests/multiline.s @@ -0,0 +1,17 @@ +#define test 123\ +456 + +ld b\ + , b +nop +ld hl, test + +ld b\ +\ +\ +, b + +.str "hello\ +world" + +nop -- 2.30.2