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 */