From 7a314e7aff2a6e9a0f82cc7f98269276fcc167cb Mon Sep 17 00:00:00 2001 From: Rangi Date: Sun, 18 Apr 2021 23:47:10 -0400 Subject: [PATCH] Support numeric symbol names in \(parentheses) For example, \(_NARG) will get the last argument --- src/asm/lexer.c | 35 ++++++++++++++++++++++++--- src/asm/rgbasm.5 | 13 +++++++--- test/asm/invalid-macro-arg-symbol.asm | 1 + test/asm/invalid-macro-arg-symbol.err | 2 ++ test/asm/invalid-macro-arg-symbol.out | 0 test/asm/parenthetic-macro-args.asm | 2 ++ test/asm/parenthetic-macro-args.out | 1 + 7 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 test/asm/invalid-macro-arg-symbol.asm create mode 100644 test/asm/invalid-macro-arg-symbol.err create mode 100644 test/asm/invalid-macro-arg-symbol.out diff --git a/src/asm/lexer.c b/src/asm/lexer.c index a6f78236..f4a79355 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -724,6 +724,8 @@ static bool isMacroChar(char c) static int peek(void); static void shiftChar(void); static uint32_t readNumber(int radix, uint32_t baseValue); +static bool startsIdentifier(int c); +static bool continuesIdentifier(int c); static uint32_t readParentheticMacroArgNum(void) { @@ -736,15 +738,42 @@ static uint32_t readParentheticMacroArgNum(void) uint32_t num = 0; int c = peek(); - bool hasDigit = c >= '0' && c <= '9'; + bool empty = false; - if (hasDigit) + if (c >= '0' && c <= '9') { num = readNumber(10, 0); + } else if (startsIdentifier(c)) { + char symName[MAXSYMLEN + 1]; + size_t i = 0; + + for (; continuesIdentifier(c); c = peek()) { + if (i < sizeof(symName)) + symName[i++] = c; + shiftChar(); + } + + if (i == sizeof(symName)) { + warning(WARNING_LONG_STR, "Symbol name too long\n"); + i--; + } + symName[i] = '\0'; + + struct Symbol const *sym = sym_FindScopedSymbol(symName); + + if (!sym) + fatalerror("Parenthetic symbol \"%s\" does not exist\n", symName); + else if (!sym_IsNumeric(sym)) + fatalerror("Parenthetic symbol \"%s\" is not numeric\n", symName); + + num = sym_GetConstantSymValue(sym); + } else { + empty = true; + } c = peek(); if (c != ')') fatalerror("Invalid character in parenthetic macro argument %s\n", printChar(c)); - else if (!hasDigit) + else if (empty) fatalerror("Empty parenthetic macro argument\n"); else if (num == 0) fatalerror("Invalid parenthetic macro argument '\\(0)'\n"); diff --git a/src/asm/rgbasm.5 b/src/asm/rgbasm.5 index 9c6e6917..7ad25e22 100644 --- a/src/asm/rgbasm.5 +++ b/src/asm/rgbasm.5 @@ -1569,7 +1569,10 @@ does not need to be escaped because string literals also work as usual inside ma Since there are only nine digits, you can only access the first nine macro arguments like this. To use the rest, you need to put the multi-digit argument number in parentheses, like .Ql \[rs](10) . -This parenthetic syntax only supports decimal numbers. +This parenthetic syntax supports decimal numbers and numeric symbol names. +For example, +.Ql \[rs](_NARG) +will get the last argument. .Pp Other macro arguments and symbol interpolations will be expanded inside the parentheses. For example, if @@ -1580,10 +1583,12 @@ then .Ql \[rs](\[rs]1) will expand to .Ql \[rs](13) . -And if -.Ql x = 42 , +Or if +.Ql v10 = 42 +and +.Ql x = 10 , then -.Ql \[rs]({d:x}) +.Ql \[rs](v{d:x}) will expand to .Ql \[rs](42) . .Pp diff --git a/test/asm/invalid-macro-arg-symbol.asm b/test/asm/invalid-macro-arg-symbol.asm new file mode 100644 index 00000000..76c9462c --- /dev/null +++ b/test/asm/invalid-macro-arg-symbol.asm @@ -0,0 +1 @@ +\(foo) diff --git a/test/asm/invalid-macro-arg-symbol.err b/test/asm/invalid-macro-arg-symbol.err new file mode 100644 index 00000000..bebe2c40 --- /dev/null +++ b/test/asm/invalid-macro-arg-symbol.err @@ -0,0 +1,2 @@ +FATAL: invalid-macro-arg-symbol.asm(1): + Parenthetic symbol "foo" does not exist diff --git a/test/asm/invalid-macro-arg-symbol.out b/test/asm/invalid-macro-arg-symbol.out new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/parenthetic-macro-args.asm b/test/asm/parenthetic-macro-args.asm index 7f4d30ba..e9ea6569 100644 --- a/test/asm/parenthetic-macro-args.asm +++ b/test/asm/parenthetic-macro-args.asm @@ -12,6 +12,8 @@ MACRO mac println \(2__) + \(1_2) + \(\1) x = 2 println \({d:x}) + \(1_{d:x}) + \(\(\(13))) +y equs "NARG" + println \(x) + \(1_{d:x}_) + \(\(\(_{y}))) ENDM mac 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 1 diff --git a/test/asm/parenthetic-macro-args.out b/test/asm/parenthetic-macro-args.out index e5bb3394..0d4ff09c 100644 --- a/test/asm/parenthetic-macro-args.out +++ b/test/asm/parenthetic-macro-args.out @@ -4,3 +4,4 @@ next = C last = D $F0 $F0 +$F0