Print this page
cpp: if a macro with parameters is invoked without any, don't destroy state
Previously, we would parse a macro foo() presuming that we would always
see the opening parenthesis indicating the begining of the parameter
list. If we saw 'foo' we would consume the token _following_ 'foo'
presuming it would be the parenthesis, and if it was not, would not
paste it to the output.
*** 74,83 ****
--- 74,84 ----
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>
+ #include <ctype.h>
#include "cpp.h"
#define SYMLEN 128
static int symlen = SYMLEN;
*** 634,643 ****
--- 635,649 ----
if (isslo) return(p);
} /* end of infinite loop */
}
+ /*
+ * XXX: This unconditionally consumes one token (presuming it's blank? that we
+ * already consumed it?). That's pretty terrible, but it's also very fragile,
+ * and I don't want to change it.
+ */
char *
skipbl(p) register char *p; {/* get next non-blank token */
do {
outp=inp=p;
p=cotoken(p);
*** 1191,1207 ****
vp=acttxt; *vp++='\0';
sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
}
if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
register char **pa;
ca=acttxt; pa=actual;
if (params==0xFF)
params=1; /* #define foo() ... */
sloscan();
++flslvl; /* no expansion during search for actuals */
plvl= -1;
! do p=skipbl(p); while (*inp=='\n'); /* skip \n too */
if (*inp=='(') {
maclin=lineno[ifno]; macfil=fnames[ifno];
for (plvl=1; plvl!=0; ) {
*ca++='\0';
for (;;) {
--- 1197,1226 ----
vp=acttxt; *vp++='\0';
sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
}
if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
register char **pa;
+ char *savp, *savinp, *savoutp;
ca=acttxt; pa=actual;
if (params==0xFF)
params=1; /* #define foo() ... */
sloscan();
++flslvl; /* no expansion during search for actuals */
plvl= -1;
! /*
! * Skip any blanks (including \n), until we hit the macro
! * arguments.
! *
! * save our state so we can roll back if none are called.
! */
! savp = p;
! savinp = inp;
! savoutp = outp;
! do {
! p=skipbl(p);
! } while (*inp=='\n'); /* skip \n too */
!
if (*inp=='(') {
maclin=lineno[ifno]; macfil=fnames[ifno];
for (plvl=1; plvl!=0; ) {
*ca++='\0';
for (;;) {
*** 1253,1262 ****
--- 1272,1289 ----
ppwarn("%s: argument mismatch" ,
sp->name);
else
*pa++=ca;
}
+ } else {
+ /*
+ * Didn't find any parameters, rollback our state so
+ * we don't chew more output than necessary
+ */
+ p = savp;
+ inp = savinp;
+ outp = savoutp;
}
if (params!=0)
ppwarn("%s: argument mismatch", sp->name);
while (--params>=0)
*pa++=""+1; /* null string for missing actuals */