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.


  59  *
  60  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
  61  * INTERNATIONAL, INC.  AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
  62  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  63  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  64  * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR
  65  * ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  66  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  67  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  68  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  69  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  70  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  71  * POSSIBILITY OF SUCH DAMAGE.
  72  */
  73 #include <stdio.h>
  74 #include <unistd.h>
  75 #include <stdlib.h>
  76 #include <fcntl.h>
  77 #include <string.h>
  78 #include <stdarg.h>

  79 
  80 #include "cpp.h"
  81 
  82 #define SYMLEN  128
  83 static  int symlen = SYMLEN;
  84 
  85 
  86 #define SALT '#'
  87 #ifndef BUFSIZ
  88 #define BUFSIZ 512
  89 #endif
  90 
  91 static  char *pbeg;
  92 static  char *pbuf;
  93 static  char *pend;
  94 char *outp,*inp;
  95 char *newp;
  96 static  char cinit;
  97 
  98 /* some code depends on whether characters are sign or zero extended */


 619                 while (isid(*p++));
 620                 if (eob(--p)) {refill(p); p=inp+1; continue;}
 621                 goto lokid;
 622         endid:
 623                 if (eob(--p)) {refill(p); p=inp+1; continue;}
 624                 tmac2(p[-1],0,-1+(p-inp));
 625         lokid:
 626                 slookup(inp,p,0); if (newp) {p=newp; goto again;}
 627                 else break;
 628         nomac:
 629                 while (isid(*p++));
 630                 if (eob(--p)) {p=refill(p); goto nomac;}
 631                 else break;
 632         } break;
 633         } /* end of switch */
 634         
 635         if (isslo) return(p);
 636 } /* end of infinite loop */
 637 }
 638 





 639 char *
 640 skipbl(p) register char *p; {/* get next non-blank token */
 641         do {
 642                 outp=inp=p;
 643                 p=cotoken(p);
 644         } while ((toktyp+COFF)[(int)*inp]==BLANK);
 645         return(p);
 646 }
 647 
 648 static char *
 649 unfill(p) register char *p; {
 650 /*
 651  * take <= BUFFERSIZ chars from right end of buffer and put them on instack .
 652  * slide rest of buffer to the right, update pointers, return new p.
 653  */
 654         register char *np,*op; register int d;
 655         if (mactop>=MAXFRE) {
 656                 pperror("%s: too much pushback",macnam);
 657                 p=inp=pend; dump();     /* begin flushing pushback */
 658                 while (mactop>inctop[ifno]) {p=refill(p); p=inp=pend; dump();}


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();
1187         if (sp==ulnloc) {
1188                 vp=acttxt; *vp++='\0';
1189                 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1190         } else if (sp==uflloc) {
1191                 vp=acttxt; *vp++='\0';
1192                 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1193         }
1194         if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1195                 register char **pa;

1196                 ca=acttxt; pa=actual;
1197                 if (params==0xFF)
1198                         params=1;       /* #define foo() ... */
1199                 sloscan();
1200                 ++flslvl; /* no expansion during search for actuals */
1201                 plvl= -1;
1202                 do p=skipbl(p); while (*inp=='\n');     /* skip \n too */












1203                 if (*inp=='(') {
1204                         maclin=lineno[ifno]; macfil=fnames[ifno];
1205                         for (plvl=1; plvl!=0; ) {
1206                                 *ca++='\0';
1207                                 for (;;) {
1208                                         outp=inp=p; p=cotoken(p);
1209                                         if (*inp=='(') ++plvl;
1210                                         if (*inp==')' && --plvl==0) {
1211                                                 --params;
1212                                                 break;
1213                                         }
1214                                         if (plvl==1 && *inp==',') {
1215                                                 --params;
1216                                                 break;
1217                                         }
1218                                         while (inp<p) {
1219                                                 /*
1220                                                  * Sun cpp compatibility.
1221                                                  * Needed for kernel assembler
1222                                                  * preprocessing.


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))




  59  *
  60  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
  61  * INTERNATIONAL, INC.  AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
  62  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  63  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  64  * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR
  65  * ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  66  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  67  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  68  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  69  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  70  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  71  * POSSIBILITY OF SUCH DAMAGE.
  72  */
  73 #include <stdio.h>
  74 #include <unistd.h>
  75 #include <stdlib.h>
  76 #include <fcntl.h>
  77 #include <string.h>
  78 #include <stdarg.h>
  79 #include <ctype.h>
  80 
  81 #include "cpp.h"
  82 
  83 #define SYMLEN  128
  84 static  int symlen = SYMLEN;
  85 
  86 
  87 #define SALT '#'
  88 #ifndef BUFSIZ
  89 #define BUFSIZ 512
  90 #endif
  91 
  92 static  char *pbeg;
  93 static  char *pbuf;
  94 static  char *pend;
  95 char *outp,*inp;
  96 char *newp;
  97 static  char cinit;
  98 
  99 /* some code depends on whether characters are sign or zero extended */


 620                 while (isid(*p++));
 621                 if (eob(--p)) {refill(p); p=inp+1; continue;}
 622                 goto lokid;
 623         endid:
 624                 if (eob(--p)) {refill(p); p=inp+1; continue;}
 625                 tmac2(p[-1],0,-1+(p-inp));
 626         lokid:
 627                 slookup(inp,p,0); if (newp) {p=newp; goto again;}
 628                 else break;
 629         nomac:
 630                 while (isid(*p++));
 631                 if (eob(--p)) {p=refill(p); goto nomac;}
 632                 else break;
 633         } break;
 634         } /* end of switch */
 635         
 636         if (isslo) return(p);
 637 } /* end of infinite loop */
 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  */
 645 char *
 646 skipbl(p) register char *p; {/* get next non-blank token */
 647         do {
 648                 outp=inp=p;
 649                 p=cotoken(p);
 650         } while ((toktyp+COFF)[(int)*inp]==BLANK);
 651         return(p);
 652 }
 653 
 654 static char *
 655 unfill(p) register char *p; {
 656 /*
 657  * take <= BUFFERSIZ chars from right end of buffer and put them on instack .
 658  * slide rest of buffer to the right, update pointers, return new p.
 659  */
 660         register char *np,*op; register int d;
 661         if (mactop>=MAXFRE) {
 662                 pperror("%s: too much pushback",macnam);
 663                 p=inp=pend; dump();     /* begin flushing pushback */
 664                 while (mactop>inctop[ifno]) {p=refill(p); p=inp=pend; dump();}


1182                 if (++maclvl>symsiz && !rflag) {
1183                         pperror("%s: macro recursion",sp->name);
1184                         return(p);
1185                 }
1186         } else {
1187                 maclvl=0;       /* level decreased */
1188         }
1189         macforw=p; macdam=0;    /* new target for decrease in level */
1190         macnam=sp->name;
1191         /* flush all buffered output prior to the expansion */
1192         dump();
1193         if (sp==ulnloc) {
1194                 vp=acttxt; *vp++='\0';
1195                 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1196         } else if (sp==uflloc) {
1197                 vp=acttxt; *vp++='\0';
1198                 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1199         }
1200         if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1201                 register char **pa;
1202                 char *savp, *savinp, *savoutp;
1203                 ca=acttxt; pa=actual;
1204                 if (params==0xFF)
1205                         params=1;       /* #define foo() ... */
1206                 sloscan();
1207                 ++flslvl; /* no expansion during search for actuals */
1208                 plvl= -1;
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 
1222                 if (*inp=='(') {
1223                         maclin=lineno[ifno]; macfil=fnames[ifno];
1224                         for (plvl=1; plvl!=0; ) {
1225                                 *ca++='\0';
1226                                 for (;;) {
1227                                         outp=inp=p; p=cotoken(p);
1228                                         if (*inp=='(') ++plvl;
1229                                         if (*inp==')' && --plvl==0) {
1230                                                 --params;
1231                                                 break;
1232                                         }
1233                                         if (plvl==1 && *inp==',') {
1234                                                 --params;
1235                                                 break;
1236                                         }
1237                                         while (inp<p) {
1238                                                 /*
1239                                                  * Sun cpp compatibility.
1240                                                  * Needed for kernel assembler
1241                                                  * preprocessing.


1257                                                  * escaped newlines, the \ is
1258                                                  * removed, and the newline
1259                                                  * otherwise treated
1260                                                  * identically to in #1.
1261                                                  */
1262                                                 if (*inp == '\n' &&
1263                                                     inp[-1] != '\\')
1264                                                         *inp = ' ';
1265                                                 *ca++= *inp++;
1266                                         }
1267                                         if (ca> &acttxt[BUFFERSIZ])
1268                                                 pperror("%s: actuals too long",
1269                                                     sp->name);
1270                                 }
1271                                 if (pa>= &actual[MAXFRM])
1272                                         ppwarn("%s: argument mismatch" ,
1273                                             sp->name);
1274                                 else
1275                                         *pa++=ca;
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;
1285                 }
1286                 if (params!=0)
1287                         ppwarn("%s: argument mismatch", sp->name);
1288                 while (--params>=0)
1289                         *pa++=""+1;     /* null string for missing actuals */
1290                 --flslvl; fasscan();
1291         }
1292 
1293         for (;;) {/* push definition onto front of input stack */
1294                 /*
1295                  * Loop until we hit the end of the macro, or a parameter
1296                  * placement.  Note that we expand the macro into the input
1297                  * backwards (so it replays forwards.)
1298                  */
1299                 while (!iswarn(*--vp)) {
1300                         if (bob(p)) {outp=inp=p; p=unfill(p);}
1301                                 
1302                         /* Unless we are mid-paste, swallow all spaces */
1303                         if (state == TRAIL) {
1304                                 while (isspace(*vp) && !iswarn(*vp))