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.

Split Close
Expand all
Collapse all
          --- old/cpp/cpp.c
          +++ new/cpp/cpp.c
↓ open down ↓ 68 lines elided ↑ open up ↑
  69   69   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  70   70   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  71   71   * POSSIBILITY OF SUCH DAMAGE.
  72   72   */
  73   73  #include <stdio.h>
  74   74  #include <unistd.h>
  75   75  #include <stdlib.h>
  76   76  #include <fcntl.h>
  77   77  #include <string.h>
  78   78  #include <stdarg.h>
       79 +#include <ctype.h>
  79   80  
  80   81  #include "cpp.h"
  81   82  
  82   83  #define SYMLEN  128
  83   84  static  int symlen = SYMLEN;
  84   85  
  85   86  
  86   87  #define SALT '#'
  87   88  #ifndef BUFSIZ
  88   89  #define BUFSIZ 512
↓ open down ↓ 540 lines elided ↑ open up ↑
 629  630                  while (isid(*p++));
 630  631                  if (eob(--p)) {p=refill(p); goto nomac;}
 631  632                  else break;
 632  633          } break;
 633  634          } /* end of switch */
 634  635          
 635  636          if (isslo) return(p);
 636  637  } /* end of infinite loop */
 637  638  }
 638  639  
      640 +/*
      641 + * XXX: This unconditionally consumes one token (presuming it's blank? that we
      642 + * already consumed it?).  That's pretty terrible, but it's also very fragile,
      643 + * and I don't want to change it.
      644 + */
 639  645  char *
 640  646  skipbl(p) register char *p; {/* get next non-blank token */
 641  647          do {
 642  648                  outp=inp=p;
 643  649                  p=cotoken(p);
 644  650          } while ((toktyp+COFF)[(int)*inp]==BLANK);
 645  651          return(p);
 646  652  }
 647  653  
 648  654  static char *
↓ open down ↓ 537 lines elided ↑ open up ↑
1186 1192          dump();
1187 1193          if (sp==ulnloc) {
1188 1194                  vp=acttxt; *vp++='\0';
1189 1195                  sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1190 1196          } else if (sp==uflloc) {
1191 1197                  vp=acttxt; *vp++='\0';
1192 1198                  sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1193 1199          }
1194 1200          if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1195 1201                  register char **pa;
     1202 +                char *savp, *savinp, *savoutp;
1196 1203                  ca=acttxt; pa=actual;
1197 1204                  if (params==0xFF)
1198 1205                          params=1;       /* #define foo() ... */
1199 1206                  sloscan();
1200 1207                  ++flslvl; /* no expansion during search for actuals */
1201 1208                  plvl= -1;
1202      -                do p=skipbl(p); while (*inp=='\n');     /* skip \n too */
     1209 +                /*
     1210 +                 * Skip any blanks (including \n), until we hit the macro
     1211 +                 * arguments.
     1212 +                 *
     1213 +                 * save our state so we can roll back if none are called.
     1214 +                 */
     1215 +                savp = p;
     1216 +                savinp = inp;
     1217 +                savoutp = outp;
     1218 +                do {
     1219 +                        p=skipbl(p);
     1220 +                } while (*inp=='\n');   /* skip \n too */
     1221 +
1203 1222                  if (*inp=='(') {
1204 1223                          maclin=lineno[ifno]; macfil=fnames[ifno];
1205 1224                          for (plvl=1; plvl!=0; ) {
1206 1225                                  *ca++='\0';
1207 1226                                  for (;;) {
1208 1227                                          outp=inp=p; p=cotoken(p);
1209 1228                                          if (*inp=='(') ++plvl;
1210 1229                                          if (*inp==')' && --plvl==0) {
1211 1230                                                  --params;
1212 1231                                                  break;
↓ open down ↓ 35 lines elided ↑ open up ↑
1248 1267                                          if (ca> &acttxt[BUFFERSIZ])
1249 1268                                                  pperror("%s: actuals too long",
1250 1269                                                      sp->name);
1251 1270                                  }
1252 1271                                  if (pa>= &actual[MAXFRM])
1253 1272                                          ppwarn("%s: argument mismatch" ,
1254 1273                                              sp->name);
1255 1274                                  else
1256 1275                                          *pa++=ca;
1257 1276                          }
     1277 +                } else {
     1278 +                        /*
     1279 +                         * Didn't find any parameters, rollback our state so
     1280 +                         * we don't chew more output than necessary
     1281 +                         */
     1282 +                        p = savp;
     1283 +                        inp = savinp;
     1284 +                        outp = savoutp;
1258 1285                  }
1259 1286                  if (params!=0)
1260 1287                          ppwarn("%s: argument mismatch", sp->name);
1261 1288                  while (--params>=0)
1262 1289                          *pa++=""+1;     /* null string for missing actuals */
1263 1290                  --flslvl; fasscan();
1264 1291          }
1265 1292  
1266 1293          for (;;) {/* push definition onto front of input stack */
1267 1294                  /*
↓ open down ↓ 304 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX