Allow negative values to count macro arguments from the end (#1670)

This commit is contained in:
Rangi
2025-04-20 00:37:50 -04:00
committed by GitHub
parent df83bc31d2
commit 0b7cda9e0c
7 changed files with 91 additions and 11 deletions

View File

@@ -9,11 +9,11 @@
#include <vector> #include <vector>
struct MacroArgs { struct MacroArgs {
unsigned int shift; uint32_t shift;
std::vector<std::shared_ptr<std::string>> args; std::vector<std::shared_ptr<std::string>> args;
uint32_t nbArgs() const { return args.size() - shift; } uint32_t nbArgs() const { return args.size() - shift; }
std::shared_ptr<std::string> getArg(uint32_t i) const; std::shared_ptr<std::string> getArg(int32_t i) const;
std::shared_ptr<std::string> getAllArgs() const; std::shared_ptr<std::string> getAllArgs() const;
void appendArg(std::shared_ptr<std::string> arg); void appendArg(std::shared_ptr<std::string> arg);

View File

@@ -1877,9 +1877,11 @@ being the second, and so on. Since there are only nine digits, you can only use
To use the rest, you put the argument number in angle brackets, like To use the rest, you put the argument number in angle brackets, like
.Ic \e<10> . .Ic \e<10> .
.Pp .Pp
This bracketed syntax supports decimal numbers and numeric symbols. This bracketed syntax supports decimal numbers and numeric symbols, where negative values count from the last argument.
For example, For example,
.Ql \e<_NARG> .Ql \e<_NARG>
or
.Ql \e<-1>
will get the last argument. will get the last argument.
.Pp .Pp
Other macro arguments and symbol interpolations will also be expanded inside the angle brackets. Other macro arguments and symbol interpolations will also be expanded inside the angle brackets.

View File

@@ -625,13 +625,24 @@ static uint32_t readBracketedMacroArgNum() {
lexerState->disableInterpolation = disableInterpolation; lexerState->disableInterpolation = disableInterpolation;
}}; }};
uint32_t num = 0; int32_t num = 0;
int c = peek(); int c = peek();
bool empty = false; bool empty = false;
bool symbolError = false; bool symbolError = false;
bool negative = c == '-';
if (negative) {
shiftChar();
c = peek();
}
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
num = readNumber(10, 0); uint32_t n = readNumber(10, 0);
if (n > INT32_MAX) {
error("Number in bracketed macro argument is too large\n");
return 0;
}
num = negative ? -n : static_cast<int32_t>(n);
} else if (startsIdentifier(c) || c == '#') { } else if (startsIdentifier(c) || c == '#') {
if (c == '#') { if (c == '#') {
shiftChar(); shiftChar();
@@ -664,7 +675,7 @@ static uint32_t readBracketedMacroArgNum() {
num = 0; num = 0;
symbolError = true; symbolError = true;
} else { } else {
num = sym->getConstantValue(); num = static_cast<int32_t>(sym->getConstantValue());
} }
} else { } else {
empty = true; empty = true;
@@ -704,7 +715,7 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
assume(str); // '\#' should always be defined (at least as an empty string) assume(str); // '\#' should always be defined (at least as an empty string)
return str; return str;
} else if (name == '<') { } else if (name == '<') {
uint32_t num = readBracketedMacroArgNum(); int32_t num = readBracketedMacroArgNum();
if (num == 0) { if (num == 0) {
// The error was already reported by `readBracketedMacroArgNum`. // The error was already reported by `readBracketedMacroArgNum`.
return nullptr; return nullptr;
@@ -718,7 +729,7 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
auto str = macroArgs->getArg(num); auto str = macroArgs->getArg(num);
if (!str) { if (!str) {
error("Macro argument '\\<%" PRIu32 ">' not defined\n", num); error("Macro argument '\\<%" PRId32 ">' not defined\n", num);
} }
return str; return str;
} else { } else {

View File

@@ -8,10 +8,16 @@
#include "asm/warning.hpp" #include "asm/warning.hpp"
std::shared_ptr<std::string> MacroArgs::getArg(uint32_t i) const { std::shared_ptr<std::string> MacroArgs::getArg(int32_t i) const {
uint32_t realIndex = i + shift - 1; // Bracketed macro arguments adjust negative indexes such that -1 is the last argument.
if (i < 0) {
i += args.size() + 1;
}
return realIndex >= args.size() ? nullptr : args[realIndex]; int32_t realIndex = i + shift - 1;
return realIndex < 0 || static_cast<uint32_t>(realIndex) >= args.size() ? nullptr
: args[realIndex];
} }
std::shared_ptr<std::string> MacroArgs::getAllArgs() const { std::shared_ptr<std::string> MacroArgs::getAllArgs() const {

View File

@@ -0,0 +1,21 @@
MACRO mac
for i, -1, -_NARG - 1, -1
println "{d:i}: \<i> == \<{d:i}>"
endr
; error cases
def i = 0
println "{d:i}: \<i> == \<{d:i}>"
def i = -_NARG - 1
println "{d:i}: \<i> == \<{d:i}>"
def i = $7fff_ffff
println "{d:i}: \<i> == \<{d:i}>"
; signed/unsigned difference error cases
def i = $8000_0000
println "{d:i}: \<i> == \<{d:i}>"
println "{u:i}: \<i> == \<{u:i}>"
def i = $ffff_ffff
println "{d:i}: \<i> == \<{d:i}>"
println "{u:i}: \<i> == \<{u:i}>"
ENDM
mac A, B, C, D, E, F, G

View File

@@ -0,0 +1,26 @@
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(7):
Invalid bracketed macro argument '\<0>'
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(7):
Invalid bracketed macro argument '\<0>'
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(9):
Macro argument '\<-8>' not defined
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(9):
Macro argument '\<-8>' not defined
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(11):
Macro argument '\<2147483647>' not defined
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(11):
Macro argument '\<2147483647>' not defined
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(14):
Macro argument '\<-2147483648>' not defined
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(14):
Number in bracketed macro argument is too large
while expanding symbol "-2147483648"
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(15):
Macro argument '\<-2147483648>' not defined
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(15):
Number in bracketed macro argument is too large
while expanding symbol "2147483648"
error: negative-macro-args.asm(21) -> negative-macro-args.asm::mac(18):
Number in bracketed macro argument is too large
while expanding symbol "4294967295"
error: Assembly aborted (11 errors)!

View File

@@ -0,0 +1,14 @@
-1: G == G
-2: F == F
-3: E == E
-4: D == D
-5: C == C
-6: B == B
-7: A == A
0: ==
-8: ==
2147483647: ==
-2147483648: == >
2147483648: == >
-1: G == G
4294967295: G == >