Print this page
cpp: only consider macro calls unterminated if they ever began
We should only error about an unterminated macro parameter list if a
parameter list was begun.  If we never even seen the _first_
parenthesis, there is nothing to terminate.
Previously, we would set the parenthesis level to -1 when expecting
parameters (such that when we saw the opening paren it became the 0th
level), but when checking for unterminated expansion we would strictly
compare to 0, and thus flag a macro which needed parameters but lacked
them as having an unterminated parameter list.


 381         while (op<p) *np++= *op++;
 382         p=np;
 383         for (;;) {
 384                 if (mactop>inctop[ifno]) {
 385                         /* retrieve hunk of pushed-back macro text */
 386                         op=instack[--mactop]; np=pbuf;
 387                         do {
 388                                 while ((*np++= *op++) != '\0');
 389                         } while (op<endbuf[mactop]); pend=np-1;
 390                         /* make buffer space avail for 'include' processing */
 391                         if (fretop<MAXFRE) bufstack[fretop++]=instack[mactop];
 392                         return(p);
 393                 } else {/* get more text from file(s) */
 394                         maclvl=0;
 395                         if (0<(ninbuf=read(fin,pbuf,BUFFERSIZ))) {
 396                                 pend=pbuf+ninbuf; *pend='\0';
 397                                 return(p);
 398                         }
 399                         /* end of #include file */
 400                         if (ifno==0) {/* end of input */
 401                                 if (plvl!=0) {
 402                                         int n=plvl,tlin=lineno[ifno];
 403                                         char *tfil=fnames[ifno];
 404                                         lineno[ifno]=maclin;
 405                                         fnames[ifno]=macfil;
 406                                         pperror("%s: unterminated macro call",
 407                                             macnam);
 408                                         lineno[ifno]=tlin; fnames[ifno]=tfil;
 409                                         np=p;
 410                                         /*
 411                                          * shut off unterminated quoted string
 412                                          */
 413                                         *np++='\n';
 414                                         /* supply missing parens */
 415                                         while (--n>=0) *np++=')';
 416                                         pend=np; *np='\0';
 417                                         if (plvl<0) plvl=0;
 418                                         return(p);
 419                                 }
 420                                 inp=p; dump(); exit(exfail);
 421                         }


1147         else
1148                 p3=p2;
1149         c3= *p3; *p3='\0';      /* truncate to symlen chars or less */
1150         if (enterf==1)
1151                 p1=copy(p1);
1152         np=lookup(p1,enterf); *p3=c3; *p2=c2;
1153         if (np->value!=0 && flslvl==0)
1154                 newp=subst(p2,np);
1155         else
1156                 newp=0;
1157         return(np);
1158 }
1159 
1160 /*
1161  * When a macro substitution must happen, arrange the input stack based on the
1162  * macro definition and any parameters such that the expanded macro is what is
1163  * next read by the preprocessor as if it were input
1164  */
1165 static char *
1166 subst(p,sp) register char *p; struct symtab *sp; {
1167         static char match[]="%s: argument mismatch";
1168         register char *ca,*vp; int params;
1169         char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1170         char acttxt[BUFFERSIZ]; /* space for actuals */
1171         /* State while pasting, TRAIL is trailing space, INTRA is in the body */
1172         enum { TRAIL, INTRA } state = TRAIL;
1173         int pasted = 0;         /* # of character pasted */
1174 
1175         if (0==(vp=sp->value)) return(p);
1176         if ((p-macforw)<=macdam) {
1177                 if (++maclvl>symsiz && !rflag) {
1178                         pperror("%s: macro recursion",sp->name);
1179                         return(p);
1180                 }
1181         } else {
1182                 maclvl=0;       /* level decreased */
1183         }
1184         macforw=p; macdam=0;    /* new target for decrease in level */
1185         macnam=sp->name;
1186         /* flush all buffered output prior to the expansion */
1187         dump();


1234                                                  * into spaces, but inserts an
1235                                                  * equal number of newlines
1236                                                  * prior to pasting the body.
1237                                                  *
1238                                                  * 2) Sun does _not_ preserved
1239                                                  * escaped newlines, the \ is
1240                                                  * removed, and the newline
1241                                                  * otherwise treated
1242                                                  * identically to in #1.
1243                                                  */
1244                                                 if (*inp == '\n' &&
1245                                                     inp[-1] != '\\')
1246                                                         *inp = ' ';
1247                                                 *ca++= *inp++;
1248                                         }
1249                                         if (ca> &acttxt[BUFFERSIZ])
1250                                                 pperror("%s: actuals too long",
1251                                                     sp->name);
1252                                 }
1253                                 if (pa>= &actual[MAXFRM])
1254                                         ppwarn(match,sp->name);

1255                                 else
1256                                         *pa++=ca;
1257                         }
1258                 }
1259                 if (params!=0)
1260                         ppwarn(match,sp->name);
1261                 while (--params>=0)
1262                         *pa++=""+1;     /* null string for missing actuals */
1263                 --flslvl; fasscan();
1264         }
1265 
1266         for (;;) {/* push definition onto front of input stack */
1267                 /*
1268                  * Loop until we hit the end of the macro, or a parameter
1269                  * placement.  Note that we expand the macro into the input
1270                  * backwards (so it replays forwards.)
1271                  */
1272                 while (!iswarn(*--vp)) {
1273                         if (bob(p)) {outp=inp=p; p=unfill(p);}
1274                                 
1275                         /* Unless we are mid-paste, swallow all spaces */
1276                         if (state == TRAIL) {
1277                                 while (isspace(*vp) && !iswarn(*vp))
1278                                         vp--;
1279                         } else {
1280                                 /*




 381         while (op<p) *np++= *op++;
 382         p=np;
 383         for (;;) {
 384                 if (mactop>inctop[ifno]) {
 385                         /* retrieve hunk of pushed-back macro text */
 386                         op=instack[--mactop]; np=pbuf;
 387                         do {
 388                                 while ((*np++= *op++) != '\0');
 389                         } while (op<endbuf[mactop]); pend=np-1;
 390                         /* make buffer space avail for 'include' processing */
 391                         if (fretop<MAXFRE) bufstack[fretop++]=instack[mactop];
 392                         return(p);
 393                 } else {/* get more text from file(s) */
 394                         maclvl=0;
 395                         if (0<(ninbuf=read(fin,pbuf,BUFFERSIZ))) {
 396                                 pend=pbuf+ninbuf; *pend='\0';
 397                                 return(p);
 398                         }
 399                         /* end of #include file */
 400                         if (ifno==0) {/* end of input */
 401                                 if (plvl > 0) {
 402                                         int n=plvl,tlin=lineno[ifno];
 403                                         char *tfil=fnames[ifno];
 404                                         lineno[ifno]=maclin;
 405                                         fnames[ifno]=macfil;
 406                                         pperror("%s: unterminated macro call",
 407                                             macnam);
 408                                         lineno[ifno]=tlin; fnames[ifno]=tfil;
 409                                         np=p;
 410                                         /*
 411                                          * shut off unterminated quoted string
 412                                          */
 413                                         *np++='\n';
 414                                         /* supply missing parens */
 415                                         while (--n>=0) *np++=')';
 416                                         pend=np; *np='\0';
 417                                         if (plvl<0) plvl=0;
 418                                         return(p);
 419                                 }
 420                                 inp=p; dump(); exit(exfail);
 421                         }


1147         else
1148                 p3=p2;
1149         c3= *p3; *p3='\0';      /* truncate to symlen chars or less */
1150         if (enterf==1)
1151                 p1=copy(p1);
1152         np=lookup(p1,enterf); *p3=c3; *p2=c2;
1153         if (np->value!=0 && flslvl==0)
1154                 newp=subst(p2,np);
1155         else
1156                 newp=0;
1157         return(np);
1158 }
1159 
1160 /*
1161  * When a macro substitution must happen, arrange the input stack based on the
1162  * macro definition and any parameters such that the expanded macro is what is
1163  * next read by the preprocessor as if it were input
1164  */
1165 static char *
1166 subst(p,sp) register char *p; struct symtab *sp; {

1167         register char *ca,*vp; int params;
1168         char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1169         char acttxt[BUFFERSIZ]; /* space for actuals */
1170         /* State while pasting, TRAIL is trailing space, INTRA is in the body */
1171         enum { TRAIL, INTRA } state = TRAIL;
1172         int pasted = 0;         /* # of character pasted */
1173 
1174         if (0==(vp=sp->value)) return(p);
1175         if ((p-macforw)<=macdam) {
1176                 if (++maclvl>symsiz && !rflag) {
1177                         pperror("%s: macro recursion",sp->name);
1178                         return(p);
1179                 }
1180         } else {
1181                 maclvl=0;       /* level decreased */
1182         }
1183         macforw=p; macdam=0;    /* new target for decrease in level */
1184         macnam=sp->name;
1185         /* flush all buffered output prior to the expansion */
1186         dump();


1233                                                  * into spaces, but inserts an
1234                                                  * equal number of newlines
1235                                                  * prior to pasting the body.
1236                                                  *
1237                                                  * 2) Sun does _not_ preserved
1238                                                  * escaped newlines, the \ is
1239                                                  * removed, and the newline
1240                                                  * otherwise treated
1241                                                  * identically to in #1.
1242                                                  */
1243                                                 if (*inp == '\n' &&
1244                                                     inp[-1] != '\\')
1245                                                         *inp = ' ';
1246                                                 *ca++= *inp++;
1247                                         }
1248                                         if (ca> &acttxt[BUFFERSIZ])
1249                                                 pperror("%s: actuals too long",
1250                                                     sp->name);
1251                                 }
1252                                 if (pa>= &actual[MAXFRM])
1253                                         ppwarn("%s: argument mismatch" ,
1254                                             sp->name);
1255                                 else
1256                                         *pa++=ca;
1257                         }
1258                 }
1259                 if (params!=0)
1260                         ppwarn("%s: argument mismatch", sp->name);
1261                 while (--params>=0)
1262                         *pa++=""+1;     /* null string for missing actuals */
1263                 --flslvl; fasscan();
1264         }
1265 
1266         for (;;) {/* push definition onto front of input stack */
1267                 /*
1268                  * Loop until we hit the end of the macro, or a parameter
1269                  * placement.  Note that we expand the macro into the input
1270                  * backwards (so it replays forwards.)
1271                  */
1272                 while (!iswarn(*--vp)) {
1273                         if (bob(p)) {outp=inp=p; p=unfill(p);}
1274                                 
1275                         /* Unless we are mid-paste, swallow all spaces */
1276                         if (state == TRAIL) {
1277                                 while (isspace(*vp) && !iswarn(*vp))
1278                                         vp--;
1279                         } else {
1280                                 /*