1185
1186 static struct symtab *
1187 slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{
1188 register char *p3; char c2,c3; struct symtab *np;
1189 c2= *p2; *p2='\0'; /* mark end of token */
1190 if ((p2-p1)>symlen)
1191 p3=p1+symlen;
1192 else
1193 p3=p2;
1194 c3= *p3; *p3='\0'; /* truncate to symlen chars or less */
1195 if (enterf==1)
1196 p1=copy(p1);
1197 np=lookup(p1,enterf); *p3=c3; *p2=c2;
1198 if (np->value!=0 && flslvl==0)
1199 newp=subst(p2,np);
1200 else
1201 newp=0;
1202 return(np);
1203 }
1204
1205 static char *
1206 subst(p,sp) register char *p; struct symtab *sp; {
1207 static char match[]="%s: argument mismatch";
1208 register char *ca,*vp; int params;
1209 char *actual[MAXFRM]; /* actual[n] is text of nth actual */
1210 char acttxt[BUFFERSIZ]; /* space for actuals */
1211
1212 if (0==(vp=sp->value)) return(p);
1213 if ((p-macforw)<=macdam) {
1214 if (++maclvl>symsiz && !rflag) {
1215 pperror("%s: macro recursion",sp->name);
1216 return(p);
1217 }
1218 } else {
1219 maclvl=0; /* level decreased */
1220 }
1221 macforw=p; macdam=0; /* new target for decrease in level */
1222 macnam=sp->name;
1223 dump();
1224 if (sp==ulnloc) {
1225 vp=acttxt; *vp++='\0';
1226 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1227 } else if (sp==uflloc) {
1228 vp=acttxt; *vp++='\0';
1229 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1230 }
1231 if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1232 register char **pa;
1233 ca=acttxt; pa=actual;
1234 if (params==0xFF)
1235 params=1; /* #define foo() ... */
1236 sloscan();
1237 ++flslvl; /* no expansion during search for actuals */
1238 plvl= -1;
1239 do p=skipbl(p); while (*inp=='\n'); /* skip \n too */
1240 if (*inp=='(') {
1241 maclin=lineno[ifno]; macfil=fnames[ifno];
1242 for (plvl=1; plvl!=0; ) {
1245 outp=inp=p; p=cotoken(p);
1246 if (*inp=='(') ++plvl;
1247 if (*inp==')' && --plvl==0) {
1248 --params;
1249 break;
1250 }
1251 if (plvl==1 && *inp==',') {
1252 --params;
1253 break;
1254 }
1255 while (inp<p) {
1256 /*
1257 * Sun cpp compatibility.
1258 * Needed for kernel assembler
1259 * preprocessing.
1260 * Replace newlines in actual
1261 * macro parameters by spaces.
1262 * Keep escaped newlines, they
1263 * are assumed to be inside a
1264 * string.
1265 */
1266 if (*inp == '\n' &&
1267 inp[-1] != '\\')
1268 *inp = ' ';
1269 *ca++= *inp++;
1270 }
1271 if (ca> &acttxt[BUFFERSIZ])
1272 pperror("%s: actuals too long",
1273 sp->name);
1274 }
1275 if (pa>= &actual[MAXFRM])
1276 ppwarn(match,sp->name);
1277 else
1278 *pa++=ca;
1279 }
1280 }
1281 if (params!=0)
1282 ppwarn(match,sp->name);
1283 while (--params>=0)
1284 *pa++=""+1; /* null string for missing actuals */
1285 --flslvl; fasscan();
1286 }
1287 for (;;) {/* push definition onto front of input stack */
1288 while (!iswarn(*--vp)) {
1289 if (bob(p)) {outp=inp=p; p=unfill(p);}
1290 *--p= *vp;
1291 }
1292 if (*vp==warnc) {/* insert actual param */
1293 ca=actual[*--vp-1];
1294 while (*--ca) {
1295 if (bob(p)) {outp=inp=p; p=unfill(p);}
1296 *--p= *ca;
1297 }
1298 } else break;
1299 }
1300 outp=inp=p;
1301 return(p);
1302 }
1303
1304 static char *
1305 trmdir(s) register char *s; {
1306 register char *p = s;
1307 while (*p++); --p; while (p>s && *--p!='/');
1308 # if unix
1309 if (p==s) *p++='.';
1310 # endif
1311 *p='\0';
1312 return(s);
1313 }
1314
1315 static char *
1316 copy(s) register char *s; {
1317 register char *old;
1318
|
1185
1186 static struct symtab *
1187 slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{
1188 register char *p3; char c2,c3; struct symtab *np;
1189 c2= *p2; *p2='\0'; /* mark end of token */
1190 if ((p2-p1)>symlen)
1191 p3=p1+symlen;
1192 else
1193 p3=p2;
1194 c3= *p3; *p3='\0'; /* truncate to symlen chars or less */
1195 if (enterf==1)
1196 p1=copy(p1);
1197 np=lookup(p1,enterf); *p3=c3; *p2=c2;
1198 if (np->value!=0 && flslvl==0)
1199 newp=subst(p2,np);
1200 else
1201 newp=0;
1202 return(np);
1203 }
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 */
1210 static char *
1211 subst(p,sp) register char *p; struct symtab *sp; {
1212 static char match[]="%s: argument mismatch";
1213 register char *ca,*vp; int params;
1214 char *actual[MAXFRM]; /* actual[n] is text of nth actual */
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 */
1219
1220 if (0==(vp=sp->value)) return(p);
1221 if ((p-macforw)<=macdam) {
1222 if (++maclvl>symsiz && !rflag) {
1223 pperror("%s: macro recursion",sp->name);
1224 return(p);
1225 }
1226 } else {
1227 maclvl=0; /* level decreased */
1228 }
1229 macforw=p; macdam=0; /* new target for decrease in level */
1230 macnam=sp->name;
1231 /* flush all buffered output prior to the expansion */
1232 dump();
1233 if (sp==ulnloc) {
1234 vp=acttxt; *vp++='\0';
1235 sprintf(vp,"%d",lineno[ifno]); while (*vp++);
1236 } else if (sp==uflloc) {
1237 vp=acttxt; *vp++='\0';
1238 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++);
1239 }
1240 if (0!=(params= *--vp&0xFF)) {/* definition calls for params */
1241 register char **pa;
1242 ca=acttxt; pa=actual;
1243 if (params==0xFF)
1244 params=1; /* #define foo() ... */
1245 sloscan();
1246 ++flslvl; /* no expansion during search for actuals */
1247 plvl= -1;
1248 do p=skipbl(p); while (*inp=='\n'); /* skip \n too */
1249 if (*inp=='(') {
1250 maclin=lineno[ifno]; macfil=fnames[ifno];
1251 for (plvl=1; plvl!=0; ) {
1254 outp=inp=p; p=cotoken(p);
1255 if (*inp=='(') ++plvl;
1256 if (*inp==')' && --plvl==0) {
1257 --params;
1258 break;
1259 }
1260 if (plvl==1 && *inp==',') {
1261 --params;
1262 break;
1263 }
1264 while (inp<p) {
1265 /*
1266 * Sun cpp compatibility.
1267 * Needed for kernel assembler
1268 * preprocessing.
1269 * Replace newlines in actual
1270 * macro parameters by spaces.
1271 * Keep escaped newlines, they
1272 * are assumed to be inside a
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.
1288 */
1289 if (*inp == '\n' &&
1290 inp[-1] != '\\')
1291 *inp = ' ';
1292 *ca++= *inp++;
1293 }
1294 if (ca> &acttxt[BUFFERSIZ])
1295 pperror("%s: actuals too long",
1296 sp->name);
1297 }
1298 if (pa>= &actual[MAXFRM])
1299 ppwarn(match,sp->name);
1300 else
1301 *pa++=ca;
1302 }
1303 }
1304 if (params!=0)
1305 ppwarn(match,sp->name);
1306 while (--params>=0)
1307 *pa++=""+1; /* null string for missing actuals */
1308 --flslvl; fasscan();
1309 }
1310
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 */
1317 while (!iswarn(*--vp)) {
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;
1342 *--p= *vp;
1343 pasted++;
1344 }
1345 if (*vp==warnc) {/* insert actual param */
1346 state = INTRA;
1347 ca=actual[*--vp-1];
1348 while (*--ca) {
1349 if (bob(p)) {outp=inp=p; p=unfill(p);}
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--;
1360 }
1361 break;
1362 }
1363 }
1364 outp=inp=p;
1365 return(p);
1366 }
1367
1368 static char *
1369 trmdir(s) register char *s; {
1370 register char *p = s;
1371 while (*p++); --p; while (p>s && *--p!='/');
1372 # if unix
1373 if (p==s) *p++='.';
1374 # endif
1375 *p='\0';
1376 return(s);
1377 }
1378
1379 static char *
1380 copy(s) register char *s; {
1381 register char *old;
1382
|