this patch should be sufficient for full-blown c99 varadic macro support. Reference: /n/sources/patch/applied/cpp-varadic-macros Date: Sun Apr 9 03:48:19 CES 2006 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/cpp/macro.c Sun Apr 9 03:44:48 2006 +++ /sys/src/cmd/cpp/macro.c Sun Apr 9 03:44:41 2006 @@ -12,7 +12,9 @@ Token *tp; Nlist *np; Tokenrow *def, *args; + int dots; + dots = 0; tp = trp->tp+1; if (tp>=trp->lp || tp->type!=NAME) { error(ERROR, "#defined token is not a name"); @@ -36,13 +38,15 @@ int err = 0; for (;;) { Token *atp; - if (tp->type!=NAME) { + if(tp->type == ELLIPS) + dots++; + else if (tp->type!=NAME) { err++; break; } if (narg>=args->max) growtokenrow(args); - for (atp=args->bp; atplp; atp++) + for (atp=args->bp; !dots && atplp; atp++) if (atp->len==tp->len && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0) error(ERROR, "Duplicate macro argument"); @@ -51,6 +55,8 @@ tp += 1; if (tp->type==RP) break; + if(dots) + error(ERROR, "arguments after '...' in macro"); if (tp->type!=COMMA) { err++; break; @@ -83,6 +89,8 @@ np->ap = args; np->vp = def; np->flag |= ISDEFINED; + if(dots) + np->flag |= ISVARMAC; } /* @@ -184,6 +192,7 @@ Tokenrow *atr[NARG+1]; int hs; + memset(atr, 0, sizeof atr); copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap==NULL) /* parameterless */ ntokc = 1; @@ -194,7 +203,7 @@ /* gatherargs has already pushed trp->tr to the next token */ return; } - if (narg != rowlen(np->ap)) { + if (narg != rowlen(np->ap) && ((np->flag & ISVARMAC) && narg< rowlen(np->ap))) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp += ntokc; @@ -316,6 +325,20 @@ return ntok; } +static Token comma[] = { + {(uchar)COMMA, 0, 0, 0, 1, (uchar*)","}, + 0, +}; +static Tokenrow commatr = { + comma, comma, comma+1, 0 +}; + +static int +varargpos(Nlist *np) +{ + return np->ap->lp-np->ap->bp-1; // c.f. cpp.h definition of Nlist +} + /* * substitute the argument list into the replacement string * This would be simple except for ## and # @@ -338,6 +361,11 @@ ntok = 1 + (rtr->tp - tp); rtr->tp = tp; insertrow(rtr, ntok, stringify(atr[argno])); + if(argno == varargpos(np)) + for(; atr[++argno]; ){ + insertrow(rtr, 0, &commatr); + insertrow(rtr, 0, stringify(atr[argno])); + } continue; } if (rtr->tp->type==NAME @@ -352,6 +380,14 @@ expandrow(&tatr, ""); insertrow(rtr, 1, &tatr); dofree(tatr.bp); + if(argno == varargpos(np)) + for(; atr[++argno]; ){ + insertrow(rtr, 0, &commatr); + copytokenrow(&tatr, atr[argno]); + expandrow(&tatr, ""); + insertrow(rtr, 0, &tatr); + dofree(tatr.bp); + } } continue; } @@ -412,6 +448,8 @@ if (tp->type!=NAME || mac->ap==NULL) return -1; + if(mac->flag & ISVARMAC && strcmp((char*)tp->t, "__VA_ARGS__") == 0) + return mac->ap->lp-mac->ap->bp-1; for (ap=mac->ap->bp; apap->lp; ap++) { if (ap->len==tp->len && strncmp((char*)ap->t,(char*)tp->t,ap->len)==0) return ap - mac->ap->bp; --- /sys/src/cmd/cpp/cpp.h Sun Apr 9 03:45:09 2006 +++ /sys/src/cmd/cpp/cpp.h Sun Apr 9 03:45:04 2006 @@ -27,7 +27,7 @@ #define ISKW 02 /* is PP keyword */ #define ISUNCHANGE 04 /* can't be #defined in PP */ #define ISMAC 010 /* builtin macro, e.g. __LINE__ */ - +#define ISVARMAC 020 /* varadic macro */ #define EOB 0xFE /* sentinel for end of input buffer */ #define EOFC 0xFD /* sentinel for end of input file */ #define XPWS 1 /* token flag: white space to assure token sep. */