cpp: implement empty arg handling for function-like macros (thanks rod)

This commit is contained in:
Ori Bernstein 2024-12-22 00:48:14 +00:00
parent 60ea3e6d25
commit 66abd6e50a
3 changed files with 50 additions and 15 deletions

View file

@ -185,7 +185,7 @@ expandrow(Tokenrow *trp, char *flag)
void void
expand(Tokenrow *trp, Nlist *np) expand(Tokenrow *trp, Nlist *np)
{ {
int ntokc, narg, i, hs; int ntokc, narg, nparam, i, hs;
Tokenrow *atr[NARG+1]; Tokenrow *atr[NARG+1];
Tokenrow ntr; Tokenrow ntr;
Token *tp; Token *tp;
@ -202,7 +202,18 @@ expand(Tokenrow *trp, Nlist *np)
/* gatherargs has already pushed trp->tr to the next token */ /* gatherargs has already pushed trp->tr to the next token */
return; return;
} }
if (narg != rowlen(np->ap)) { nparam = rowlen(np->ap);
if(narg == nparam - 1
&& (narg == 0 || (np->flag&ISVARMAC))) {
if(narg == NARG)
error(ERROR, "Too many arguments");
atr[narg] = new(Tokenrow);
maketokenrow(0, atr[narg]);
narg++;
}
if (narg != nparam) {
error(ERROR, "Disagreement in number of macro arguments"); error(ERROR, "Disagreement in number of macro arguments");
trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp->hideset = newhideset(trp->tp->hideset, np);
trp->tp += ntokc; trp->tp += ntokc;

View file

@ -1,7 +1,10 @@
#line 1 "/sys/src/cmd/cpp/test/edges.out"
#line 1 "/sys/src/cmd/cpp/test/edges.in" #line 1 "/sys/src/cmd/cpp/test/edges.in"
-- test nop --
x fooEOF y x fooEOF y
x EOFfoo y x EOFfoo y
x(-1) y x(-1) y
@ -9,26 +12,34 @@ y foo x
x foo y x foo y
X y X y
-- test ncat --
foobar foobar
-- test xcat (no left arg) --
foo ## bar foo ## bar
-- test cat3 --
ablahb ablahb
-- test expand and cat --
33 33
-- test expand and cat 2 --
a bc d a bc d
WUT WUT
-- test varargs --
#line 36 "/sys/src/cmd/cpp/test/edges.in" print("hi","there")
print("hi",)
-- test expanding commas --
@ -48,8 +59,15 @@ WUT
-- test complex expressions --
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
f(2 * (2 +(3,4)- 0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^ m(0,1); f(2 * (2 +(3,4)- 0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^ m(0,1);
#line 59 "/sys/src/cmd/cpp/test/edges.in" #line 64 "/sys/src/cmd/cpp/test/edges.in"
#line 66 "/sys/src/cmd/cpp/test/edges.in" -- test empty args --
b
-- test complex expressions with empty args --
int i[] = {1,23,4,5, };
char c[2][6] = {"hello","" };

View file

@ -1,6 +1,8 @@
#define NOP(x) x #define NOP(x) x
#define CAT(a, b) a ## b #define CAT(a, b) a ## b
#define EOF (-1) #define EOF (-1)
-- test nop --
x NOP(CAT(foo, EOF)) y x NOP(CAT(foo, EOF)) y
x NOP(CAT(EOF, foo)) y x NOP(CAT(EOF, foo)) y
x CAT(, EOF) y x CAT(, EOF) y
@ -8,32 +10,34 @@ y CAT(foo,) x
x CAT(,foo) y x CAT(,foo) y
X NOP(CAT(,)) y X NOP(CAT(,)) y
-- test ncat --
#define NCAT(a) foo ## a #define NCAT(a) foo ## a
NCAT(bar) NCAT(bar)
-- test xcat (no left arg) --
#define XCAT(a) ## a #define XCAT(a) ## a
foo XCAT(bar) foo XCAT(bar)
-- test cat3 --
#define CAT3(foo) a##foo##b #define CAT3(foo) a##foo##b
CAT3(blah) CAT3(blah)
-- test expand and cat --
#define BAR 3 #define BAR 3
#define FOO CAT(BAR, 3) #define FOO CAT(BAR, 3)
FOO FOO
-- test expand and cat 2 --
/* Expected: a bc d */ /* Expected: a bc d */
CAT(a b, c d) CAT(a b, c d)
WUT WUT
/* -- test varargs --
* CURRENTLY BROKEN:
* __VA_ARGS__ requires at least one item.
* It should accept an empty list.
#define xprint(a, ...) print(a, __VA_ARGS__) #define xprint(a, ...) print(a, __VA_ARGS__)
xprint("hi", "there") xprint("hi", "there")
xprint("hi") xprint("hi")
*/
-- test expanding commas --
#define C a,b #define C a,b
#define X(a) a #define X(a) a
#define Y X(C) #define Y X(C)
@ -53,13 +57,15 @@ Y
#define q(x) x #define q(x) x
#define r(x,y) x ## y #define r(x,y) x ## y
#define str(x) # x #define str(x) # x
-- test complex expressions --
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
g(x+(3,4)-w) | h 5) & m g(x+(3,4)-w) | h 5) & m
(f)^m(m); (f)^m(m);
/*
* CURRENTLY BROKEN: -- test empty args --
* mac() needs at least one argument. #define ZARGS(a) a b a
* It should treat no args as a single empty arg list. ZARGS()
-- test complex expressions with empty args --
p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
char c[2][6] = { str(hello), str() }; char c[2][6] = { str(hello), str() };
*/