mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Allow negative values to count macro arguments from the end (#1670)
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
21
test/asm/negative-macro-args.asm
Normal file
21
test/asm/negative-macro-args.asm
Normal 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
|
||||||
26
test/asm/negative-macro-args.err
Normal file
26
test/asm/negative-macro-args.err
Normal 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)!
|
||||||
14
test/asm/negative-macro-args.out
Normal file
14
test/asm/negative-macro-args.out
Normal 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 == >
|
||||||
Reference in New Issue
Block a user