Print this page
cpp: squash spaces correctly-ish whilst pasting macros
Sun cpp removes all leading and trailing space from a macro pasting, and
compress whitespace in the macro body to a single space character.
There is some deviation from this in the Sun implementation which we
don't duplicate.
1) The presence of comments in the macro body affect the minimization of
   runs of spaces.
2) When newlines are encountered in the parameter list of a macro
   invocation, Sun cpp inserts that many newlines prior to any of the
   pasted text, and then in the pasted text pastes those newlines as
   (minimized) spaces.  Escaped new-lines are de-escaped, and otherwise
   treated similarly (in effect, the \ is removed).

Split Close
Expand all
Collapse all
          --- old/cpp/cpp.c
          +++ new/cpp/cpp.c
↓ open down ↓ 1194 lines elided ↑ open up ↑
1195 1195          if (enterf==1)
1196 1196                  p1=copy(p1);
1197 1197          np=lookup(p1,enterf); *p3=c3; *p2=c2;
1198 1198          if (np->value!=0 && flslvl==0)
1199 1199                  newp=subst(p2,np);
1200 1200          else
1201 1201                  newp=0;
1202 1202          return(np);
1203 1203  }
1204 1204  
     1205 +/*
     1206 + * When a macro substitution must happen, arrange the input stack based on the
     1207 + * macro definition and any parameters such that the expanded macro is what is
     1208 + * next read by the preprocessor as if it were input
     1209 + */
1205 1210  static char *
1206 1211  subst(p,sp) register char *p; struct symtab *sp; {
1207 1212          static char match[]="%s: argument mismatch";
1208 1213          register char *ca,*vp; int params;
1209 1214          char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1210 1215          char acttxt[BUFFERSIZ]; /* space for actuals */
     1216 +        /* State while pasting, TRAIL is trailing space, INTRA is in the body */
     1217 +        enum { TRAIL, INTRA } state = TRAIL;
     1218 +        int pasted = 0;         /* # of character pasted */
1211 1219  
1212 1220          if (0==(vp=sp->value)) return(p);
1213 1221          if ((p-macforw)<=macdam) {
1214 1222                  if (++maclvl>symsiz && !rflag) {
1215 1223                          pperror("%s: macro recursion",sp->name);
1216 1224                          return(p);
1217 1225                  }
1218 1226          } else {
1219 1227                  maclvl=0;       /* level decreased */
1220 1228          }
1221 1229          macforw=p; macdam=0;    /* new target for decrease in level */
1222 1230          macnam=sp->name;
     1231 +        /* flush all buffered output prior to the expansion */
1223 1232          dump();
1224 1233          if (sp==ulnloc) {
1225 1234                  vp=acttxt; *vp++='\0';
1226 1235                  sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1227 1236          } else if (sp==uflloc) {
1228 1237                  vp=acttxt; *vp++='\0';
1229 1238                  sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1230 1239          }
1231 1240          if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1232 1241                  register char **pa;
↓ open down ↓ 22 lines elided ↑ open up ↑
1255 1264                                          while (inp<p) {
1256 1265                                                  /*
1257 1266                                                   * Sun cpp compatibility.
1258 1267                                                   * Needed for kernel assembler
1259 1268                                                   * preprocessing.
1260 1269                                                   * Replace newlines in actual
1261 1270                                                   * macro parameters by spaces.
1262 1271                                                   * Keep escaped newlines, they
1263 1272                                                   * are assumed to be inside a
1264 1273                                                   * string.
     1274 +                                                 * 
     1275 +                                                 * XXX: The above is actually
     1276 +                                                 * false in a couple of ways.
     1277 +                                                 *
     1278 +                                                 * 1) Sun cpp turns newlines
     1279 +                                                 * into spaces, but inserts an
     1280 +                                                 * equal number of newlines
     1281 +                                                 * prior to pasting the body.
     1282 +                                                 *
     1283 +                                                 * 2) Sun does _not_ preserved
     1284 +                                                 * escaped newlines, the \ is
     1285 +                                                 * removed, and the newline
     1286 +                                                 * otherwise treated
     1287 +                                                 * identically to in #1.
1265 1288                                                   */
1266 1289                                                  if (*inp == '\n' &&
1267 1290                                                      inp[-1] != '\\')
1268 1291                                                          *inp = ' ';
1269 1292                                                  *ca++= *inp++;
1270 1293                                          }
1271 1294                                          if (ca> &acttxt[BUFFERSIZ])
1272 1295                                                  pperror("%s: actuals too long",
1273 1296                                                      sp->name);
1274 1297                                  }
↓ open down ↓ 2 lines elided ↑ open up ↑
1277 1300                                  else
1278 1301                                          *pa++=ca;
1279 1302                          }
1280 1303                  }
1281 1304                  if (params!=0)
1282 1305                          ppwarn(match,sp->name);
1283 1306                  while (--params>=0)
1284 1307                          *pa++=""+1;     /* null string for missing actuals */
1285 1308                  --flslvl; fasscan();
1286 1309          }
     1310 +
1287 1311          for (;;) {/* push definition onto front of input stack */
     1312 +                /*
     1313 +                 * Loop until we hit the end of the macro, or a parameter
     1314 +                 * placement.  Note that we expand the macro into the input
     1315 +                 * backwards (so it replays forwards.)
     1316 +                 */
1288 1317                  while (!iswarn(*--vp)) {
1289 1318                          if (bob(p)) {outp=inp=p; p=unfill(p);}
     1319 +                                
     1320 +                        /* Unless we are mid-paste, swallow all spaces */
     1321 +                        if (state == TRAIL) {
     1322 +                                while (isspace(*vp) && !iswarn(*vp))
     1323 +                                        vp--;
     1324 +                        } else {
     1325 +                                /*
     1326 +                                 * If we're mid-paste, compress spaces to a
     1327 +                                 * single space
     1328 +                                 */
     1329 +                                while (isspace(*vp)) {
     1330 +                                        if (!isspace(vp[1])) {
     1331 +                                                *vp = ' ';
     1332 +                                                break;
     1333 +                                        } else {
     1334 +                                                vp--;
     1335 +                                        }
     1336 +                                }
     1337 +                        }
     1338 +                        state = INTRA; /* Hit a non-space */
     1339 +                        
     1340 +                        if (iswarn(*vp))
     1341 +                                break;
1290 1342                          *--p= *vp;
     1343 +                        pasted++;
1291 1344                  }
1292 1345                  if (*vp==warnc) {/* insert actual param */
     1346 +                        state = INTRA;
1293 1347                          ca=actual[*--vp-1];
1294 1348                          while (*--ca) {
1295 1349                                  if (bob(p)) {outp=inp=p; p=unfill(p);}
1296 1350                                  *--p= *ca;
     1351 +                                pasted++;
     1352 +                        }
     1353 +                } else {
     1354 +                        /*
     1355 +                         * Trim leading spaces, but only those from our pasting
     1356 +                         */
     1357 +                        while (isspace(*p) && pasted > 0) {
     1358 +                                p++;
     1359 +                                pasted--;
1297 1360                          }
1298      -                } else break;
     1361 +                        break;
     1362 +                }
1299 1363          }
1300 1364          outp=inp=p;
1301 1365          return(p);
1302 1366  }
1303 1367  
1304 1368  static char *
1305 1369  trmdir(s) register char *s; {
1306 1370          register char *p = s;
1307 1371          while (*p++); --p; while (p>s && *--p!='/');
1308 1372  # if unix
↓ open down ↓ 245 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX