1*3e12c5d1SDavid du Colombier #include <u.h> 2*3e12c5d1SDavid du Colombier #include <libc.h> 3*3e12c5d1SDavid du Colombier #include <stdio.h> 4*3e12c5d1SDavid du Colombier #include "cpp.h" 5*3e12c5d1SDavid du Colombier 6*3e12c5d1SDavid du Colombier /* 7*3e12c5d1SDavid du Colombier * do a macro definition. tp points to the name being defined in the line 8*3e12c5d1SDavid du Colombier */ 9*3e12c5d1SDavid du Colombier void 10*3e12c5d1SDavid du Colombier dodefine(Tokenrow *trp) 11*3e12c5d1SDavid du Colombier { 12*3e12c5d1SDavid du Colombier Token *tp; 13*3e12c5d1SDavid du Colombier Nlist *np; 14*3e12c5d1SDavid du Colombier Tokenrow *def, *args; 15*3e12c5d1SDavid du Colombier 16*3e12c5d1SDavid du Colombier tp = trp->tp+1; 17*3e12c5d1SDavid du Colombier if (tp>=trp->lp || tp->type!=NAME) { 18*3e12c5d1SDavid du Colombier error(ERROR, "#defined token is not a name"); 19*3e12c5d1SDavid du Colombier return; 20*3e12c5d1SDavid du Colombier } 21*3e12c5d1SDavid du Colombier np = lookup(tp, 1); 22*3e12c5d1SDavid du Colombier if (np->flag&ISUNCHANGE) { 23*3e12c5d1SDavid du Colombier error(ERROR, "#defined token %t can't be redefined", tp); 24*3e12c5d1SDavid du Colombier return; 25*3e12c5d1SDavid du Colombier } 26*3e12c5d1SDavid du Colombier /* collect arguments */ 27*3e12c5d1SDavid du Colombier tp += 1; 28*3e12c5d1SDavid du Colombier args = NULL; 29*3e12c5d1SDavid du Colombier if (tp<trp->lp && tp->type==LP && tp->wslen==0) { 30*3e12c5d1SDavid du Colombier /* macro with args */ 31*3e12c5d1SDavid du Colombier int narg = 0; 32*3e12c5d1SDavid du Colombier tp += 1; 33*3e12c5d1SDavid du Colombier args = new(Tokenrow); 34*3e12c5d1SDavid du Colombier maketokenrow(2, args); 35*3e12c5d1SDavid du Colombier if (tp->type!=RP) { 36*3e12c5d1SDavid du Colombier int err = 0; 37*3e12c5d1SDavid du Colombier for (;;) { 38*3e12c5d1SDavid du Colombier Token *atp; 39*3e12c5d1SDavid du Colombier if (tp->type!=NAME) { 40*3e12c5d1SDavid du Colombier err++; 41*3e12c5d1SDavid du Colombier break; 42*3e12c5d1SDavid du Colombier } 43*3e12c5d1SDavid du Colombier if (narg>=args->max) 44*3e12c5d1SDavid du Colombier growtokenrow(args); 45*3e12c5d1SDavid du Colombier for (atp=args->bp; atp<args->lp; atp++) 46*3e12c5d1SDavid du Colombier if (atp->len==tp->len 47*3e12c5d1SDavid du Colombier && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0) 48*3e12c5d1SDavid du Colombier error(ERROR, "Duplicate macro argument"); 49*3e12c5d1SDavid du Colombier *args->lp++ = *tp; 50*3e12c5d1SDavid du Colombier narg++; 51*3e12c5d1SDavid du Colombier tp += 1; 52*3e12c5d1SDavid du Colombier if (tp->type==RP) 53*3e12c5d1SDavid du Colombier break; 54*3e12c5d1SDavid du Colombier if (tp->type!=COMMA) { 55*3e12c5d1SDavid du Colombier err++; 56*3e12c5d1SDavid du Colombier break; 57*3e12c5d1SDavid du Colombier } 58*3e12c5d1SDavid du Colombier tp += 1; 59*3e12c5d1SDavid du Colombier } 60*3e12c5d1SDavid du Colombier if (err) { 61*3e12c5d1SDavid du Colombier error(ERROR, "Syntax error in macro parameters"); 62*3e12c5d1SDavid du Colombier return; 63*3e12c5d1SDavid du Colombier } 64*3e12c5d1SDavid du Colombier } 65*3e12c5d1SDavid du Colombier tp += 1; 66*3e12c5d1SDavid du Colombier } 67*3e12c5d1SDavid du Colombier trp->tp = tp; 68*3e12c5d1SDavid du Colombier if (((trp->lp)-1)->type==NL) 69*3e12c5d1SDavid du Colombier trp->lp -= 1; 70*3e12c5d1SDavid du Colombier def = normtokenrow(trp); 71*3e12c5d1SDavid du Colombier if (np->flag&ISDEFINED) { 72*3e12c5d1SDavid du Colombier if (comparetokens(def, np->vp) 73*3e12c5d1SDavid du Colombier || (np->ap==NULL) != (args==NULL) 74*3e12c5d1SDavid du Colombier || np->ap && comparetokens(args, np->ap)) 75*3e12c5d1SDavid du Colombier error(ERROR, "Macro redefinition of %t", tp); 76*3e12c5d1SDavid du Colombier } 77*3e12c5d1SDavid du Colombier if (args) { 78*3e12c5d1SDavid du Colombier Tokenrow *tap; 79*3e12c5d1SDavid du Colombier tap = normtokenrow(args); 80*3e12c5d1SDavid du Colombier dofree(args->bp); 81*3e12c5d1SDavid du Colombier args = tap; 82*3e12c5d1SDavid du Colombier } 83*3e12c5d1SDavid du Colombier np->ap = args; 84*3e12c5d1SDavid du Colombier np->vp = def; 85*3e12c5d1SDavid du Colombier np->flag |= ISDEFINED; 86*3e12c5d1SDavid du Colombier } 87*3e12c5d1SDavid du Colombier 88*3e12c5d1SDavid du Colombier /* 89*3e12c5d1SDavid du Colombier * Definition received via -D or -U 90*3e12c5d1SDavid du Colombier */ 91*3e12c5d1SDavid du Colombier void 92*3e12c5d1SDavid du Colombier doadefine(Tokenrow *trp, int type) 93*3e12c5d1SDavid du Colombier { 94*3e12c5d1SDavid du Colombier Nlist *np; 95*3e12c5d1SDavid du Colombier static Token onetoken = { NUMBER, 0, 0, 0, 1, (uchar*)"1" }; 96*3e12c5d1SDavid du Colombier static Tokenrow onetr = { &onetoken, &onetoken, &onetoken+1, 1 }; 97*3e12c5d1SDavid du Colombier 98*3e12c5d1SDavid du Colombier trp->tp = trp->bp; 99*3e12c5d1SDavid du Colombier if (type=='U') { 100*3e12c5d1SDavid du Colombier if (trp->lp-trp->tp != 2 || trp->tp->type!=NAME) 101*3e12c5d1SDavid du Colombier goto syntax; 102*3e12c5d1SDavid du Colombier if ((np = lookup(trp->tp, 0)) == NULL) 103*3e12c5d1SDavid du Colombier return; 104*3e12c5d1SDavid du Colombier np->flag &= ~ISDEFINED; 105*3e12c5d1SDavid du Colombier return; 106*3e12c5d1SDavid du Colombier } 107*3e12c5d1SDavid du Colombier if (trp->tp >= trp->lp || trp->tp->type!=NAME) 108*3e12c5d1SDavid du Colombier goto syntax; 109*3e12c5d1SDavid du Colombier np = lookup(trp->tp, 1); 110*3e12c5d1SDavid du Colombier np->flag |= ISDEFINED; 111*3e12c5d1SDavid du Colombier trp->tp += 1; 112*3e12c5d1SDavid du Colombier if (trp->tp >= trp->lp || trp->tp->type==END) { 113*3e12c5d1SDavid du Colombier np->vp = &onetr; 114*3e12c5d1SDavid du Colombier return; 115*3e12c5d1SDavid du Colombier } 116*3e12c5d1SDavid du Colombier if (trp->tp->type!=ASGN) 117*3e12c5d1SDavid du Colombier goto syntax; 118*3e12c5d1SDavid du Colombier trp->tp += 1; 119*3e12c5d1SDavid du Colombier if ((trp->lp-1)->type == END) 120*3e12c5d1SDavid du Colombier trp->lp -= 1; 121*3e12c5d1SDavid du Colombier np->vp = normtokenrow(trp); 122*3e12c5d1SDavid du Colombier return; 123*3e12c5d1SDavid du Colombier syntax: 124*3e12c5d1SDavid du Colombier error(FATAL, "Illegal -D or -U argument %r", trp); 125*3e12c5d1SDavid du Colombier } 126*3e12c5d1SDavid du Colombier 127*3e12c5d1SDavid du Colombier /* 128*3e12c5d1SDavid du Colombier * Do macro expansion in a row of tokens. 129*3e12c5d1SDavid du Colombier * Flag is NULL if more input can be gathered. 130*3e12c5d1SDavid du Colombier */ 131*3e12c5d1SDavid du Colombier void 132*3e12c5d1SDavid du Colombier expandrow(Tokenrow *trp, char *flag) 133*3e12c5d1SDavid du Colombier { 134*3e12c5d1SDavid du Colombier Token *tp; 135*3e12c5d1SDavid du Colombier Nlist *np; 136*3e12c5d1SDavid du Colombier 137*3e12c5d1SDavid du Colombier if (flag) 138*3e12c5d1SDavid du Colombier setsource(flag, -1, ""); 139*3e12c5d1SDavid du Colombier for (tp = trp->tp; tp<trp->lp; ) { 140*3e12c5d1SDavid du Colombier if (tp->type!=NAME 141*3e12c5d1SDavid du Colombier || quicklook(tp->t[0], tp->len>1?tp->t[1]:0)==0 142*3e12c5d1SDavid du Colombier || (np = lookup(tp, 0))==NULL 143*3e12c5d1SDavid du Colombier || (np->flag&(ISDEFINED|ISMAC))==0 144*3e12c5d1SDavid du Colombier || tp->hideset && checkhideset(tp->hideset, np)) { 145*3e12c5d1SDavid du Colombier tp++; 146*3e12c5d1SDavid du Colombier continue; 147*3e12c5d1SDavid du Colombier } 148*3e12c5d1SDavid du Colombier trp->tp = tp; 149*3e12c5d1SDavid du Colombier if (np->flag&ISMAC) 150*3e12c5d1SDavid du Colombier builtin(trp, np->val); 151*3e12c5d1SDavid du Colombier else { 152*3e12c5d1SDavid du Colombier expand(trp, np); 153*3e12c5d1SDavid du Colombier } 154*3e12c5d1SDavid du Colombier tp = trp->tp; 155*3e12c5d1SDavid du Colombier } 156*3e12c5d1SDavid du Colombier if (flag) 157*3e12c5d1SDavid du Colombier unsetsource(); 158*3e12c5d1SDavid du Colombier } 159*3e12c5d1SDavid du Colombier 160*3e12c5d1SDavid du Colombier /* 161*3e12c5d1SDavid du Colombier * Expand the macro whose name is np, at token trp->tp, in the tokenrow. 162*3e12c5d1SDavid du Colombier * Return trp->tp at the first token next to be expanded 163*3e12c5d1SDavid du Colombier * (ordinarily the beginning of the expansion) 164*3e12c5d1SDavid du Colombier */ 165*3e12c5d1SDavid du Colombier void 166*3e12c5d1SDavid du Colombier expand(Tokenrow *trp, Nlist *np) 167*3e12c5d1SDavid du Colombier { 168*3e12c5d1SDavid du Colombier Tokenrow ntr; 169*3e12c5d1SDavid du Colombier int ntokc, narg, i; 170*3e12c5d1SDavid du Colombier Token *tp; 171*3e12c5d1SDavid du Colombier Tokenrow *atr[NARG+1]; 172*3e12c5d1SDavid du Colombier int hs; 173*3e12c5d1SDavid du Colombier copytokenrow(&ntr, np->vp); /* copy macro value */ 174*3e12c5d1SDavid du Colombier if (np->ap==NULL) /* parameterless */ 175*3e12c5d1SDavid du Colombier ntokc = 1; 176*3e12c5d1SDavid du Colombier else { 177*3e12c5d1SDavid du Colombier ntokc = gatherargs(trp, atr, &narg); 178*3e12c5d1SDavid du Colombier if (narg<0) { /* not actually a call (no '(') */ 179*3e12c5d1SDavid du Colombier trp->tp += 1; 180*3e12c5d1SDavid du Colombier return; 181*3e12c5d1SDavid du Colombier } 182*3e12c5d1SDavid du Colombier if (narg != rowlen(np->ap)) { 183*3e12c5d1SDavid du Colombier error(ERROR, "Disagreement in number of macro arguments"); 184*3e12c5d1SDavid du Colombier trp->tp->hideset = newhideset(trp->tp->hideset, np); 185*3e12c5d1SDavid du Colombier trp->tp += ntokc; 186*3e12c5d1SDavid du Colombier return; 187*3e12c5d1SDavid du Colombier } 188*3e12c5d1SDavid du Colombier substargs(np, &ntr, atr); /* put args into replacement */ 189*3e12c5d1SDavid du Colombier for (i=0; i<narg; i++) { 190*3e12c5d1SDavid du Colombier dofree(atr[i]->bp); 191*3e12c5d1SDavid du Colombier dofree(atr[i]); 192*3e12c5d1SDavid du Colombier } 193*3e12c5d1SDavid du Colombier } 194*3e12c5d1SDavid du Colombier doconcat(&ntr); /* execute ## operators */ 195*3e12c5d1SDavid du Colombier hs = newhideset(trp->tp->hideset, np); 196*3e12c5d1SDavid du Colombier for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */ 197*3e12c5d1SDavid du Colombier if (tp->type==NAME) { 198*3e12c5d1SDavid du Colombier if (tp->hideset==0) 199*3e12c5d1SDavid du Colombier tp->hideset = hs; 200*3e12c5d1SDavid du Colombier else 201*3e12c5d1SDavid du Colombier tp->hideset = unionhideset(tp->hideset, hs); 202*3e12c5d1SDavid du Colombier } 203*3e12c5d1SDavid du Colombier } 204*3e12c5d1SDavid du Colombier ntr.tp = ntr.bp; 205*3e12c5d1SDavid du Colombier insertrow(trp, ntokc, &ntr); 206*3e12c5d1SDavid du Colombier trp->tp -= rowlen(&ntr); 207*3e12c5d1SDavid du Colombier dofree(ntr.bp); 208*3e12c5d1SDavid du Colombier return; 209*3e12c5d1SDavid du Colombier } 210*3e12c5d1SDavid du Colombier 211*3e12c5d1SDavid du Colombier /* 212*3e12c5d1SDavid du Colombier * Gather an arglist, starting in trp with tp pointing at the macro name. 213*3e12c5d1SDavid du Colombier * Return total number of tokens passed, stash number of args found. 214*3e12c5d1SDavid du Colombier * trp->tp is not changed relative to the tokenrow. 215*3e12c5d1SDavid du Colombier */ 216*3e12c5d1SDavid du Colombier int 217*3e12c5d1SDavid du Colombier gatherargs(Tokenrow *trp, Tokenrow **atr, int *narg) 218*3e12c5d1SDavid du Colombier { 219*3e12c5d1SDavid du Colombier int parens = 1; 220*3e12c5d1SDavid du Colombier int ntok = 0; 221*3e12c5d1SDavid du Colombier Token *bp, *lp; 222*3e12c5d1SDavid du Colombier Tokenrow ttr; 223*3e12c5d1SDavid du Colombier int ntokp; 224*3e12c5d1SDavid du Colombier 225*3e12c5d1SDavid du Colombier *narg = -1; /* means that there is no macro call */ 226*3e12c5d1SDavid du Colombier /* look for the ( */ 227*3e12c5d1SDavid du Colombier for (;;) { 228*3e12c5d1SDavid du Colombier trp->tp++; 229*3e12c5d1SDavid du Colombier ntok++; 230*3e12c5d1SDavid du Colombier if (trp->tp >= trp->lp) { 231*3e12c5d1SDavid du Colombier gettokens(trp, 0); 232*3e12c5d1SDavid du Colombier if ((trp->lp-1)->type==END) { 233*3e12c5d1SDavid du Colombier trp->lp -= 1; 234*3e12c5d1SDavid du Colombier trp->tp -= ntok; 235*3e12c5d1SDavid du Colombier return ntok; 236*3e12c5d1SDavid du Colombier } 237*3e12c5d1SDavid du Colombier } 238*3e12c5d1SDavid du Colombier if (trp->tp->type==LP) 239*3e12c5d1SDavid du Colombier break; 240*3e12c5d1SDavid du Colombier if (trp->tp->type!=NL) 241*3e12c5d1SDavid du Colombier return ntok; 242*3e12c5d1SDavid du Colombier } 243*3e12c5d1SDavid du Colombier *narg = 0; 244*3e12c5d1SDavid du Colombier ntok++; 245*3e12c5d1SDavid du Colombier ntokp = ntok; 246*3e12c5d1SDavid du Colombier trp->tp++; 247*3e12c5d1SDavid du Colombier /* search for the terminating ), possibly extending the row */ 248*3e12c5d1SDavid du Colombier while (parens>0) { 249*3e12c5d1SDavid du Colombier if (trp->tp >= trp->lp) 250*3e12c5d1SDavid du Colombier gettokens(trp, 0); 251*3e12c5d1SDavid du Colombier if (trp->tp->type==END) { 252*3e12c5d1SDavid du Colombier trp->lp -= 1; 253*3e12c5d1SDavid du Colombier trp->tp -= ntok; 254*3e12c5d1SDavid du Colombier error(ERROR, "EOF in macro arglist"); 255*3e12c5d1SDavid du Colombier return ntok; 256*3e12c5d1SDavid du Colombier } 257*3e12c5d1SDavid du Colombier if (trp->tp->type==NL) { 258*3e12c5d1SDavid du Colombier trp->tp += 1; 259*3e12c5d1SDavid du Colombier adjustrow(trp, -1); 260*3e12c5d1SDavid du Colombier trp->tp -= 1; 261*3e12c5d1SDavid du Colombier makespace(trp); 262*3e12c5d1SDavid du Colombier continue; 263*3e12c5d1SDavid du Colombier } 264*3e12c5d1SDavid du Colombier if (trp->tp->type==LP) 265*3e12c5d1SDavid du Colombier parens++; 266*3e12c5d1SDavid du Colombier else if (trp->tp->type==RP) 267*3e12c5d1SDavid du Colombier parens--; 268*3e12c5d1SDavid du Colombier trp->tp++; 269*3e12c5d1SDavid du Colombier ntok++; 270*3e12c5d1SDavid du Colombier } 271*3e12c5d1SDavid du Colombier trp->tp -= ntok; 272*3e12c5d1SDavid du Colombier /* Now trp->tp won't move underneath us */ 273*3e12c5d1SDavid du Colombier lp = bp = trp->tp+ntokp; 274*3e12c5d1SDavid du Colombier for (; parens>=0; lp++) { 275*3e12c5d1SDavid du Colombier if (lp->type == LP) { 276*3e12c5d1SDavid du Colombier parens++; 277*3e12c5d1SDavid du Colombier continue; 278*3e12c5d1SDavid du Colombier } 279*3e12c5d1SDavid du Colombier if (lp->type==RP) 280*3e12c5d1SDavid du Colombier parens--; 281*3e12c5d1SDavid du Colombier if (lp->type==DSHARP) 282*3e12c5d1SDavid du Colombier lp->type = DSHARP1; /* ## not special in arg */ 283*3e12c5d1SDavid du Colombier if (lp->type==COMMA && parens==0 || parens<0 && (lp-1)->type!=LP) { 284*3e12c5d1SDavid du Colombier if (*narg>=NARG-1) 285*3e12c5d1SDavid du Colombier error(FATAL, "Sorry, too many macro arguments"); 286*3e12c5d1SDavid du Colombier ttr.bp = ttr.tp = bp; 287*3e12c5d1SDavid du Colombier ttr.lp = lp; 288*3e12c5d1SDavid du Colombier atr[(*narg)++] = normtokenrow(&ttr); 289*3e12c5d1SDavid du Colombier bp = lp+1; 290*3e12c5d1SDavid du Colombier } 291*3e12c5d1SDavid du Colombier } 292*3e12c5d1SDavid du Colombier return ntok; 293*3e12c5d1SDavid du Colombier } 294*3e12c5d1SDavid du Colombier 295*3e12c5d1SDavid du Colombier /* 296*3e12c5d1SDavid du Colombier * substitute the argument list into the replacement string 297*3e12c5d1SDavid du Colombier * This would be simple except for ## and # 298*3e12c5d1SDavid du Colombier */ 299*3e12c5d1SDavid du Colombier void 300*3e12c5d1SDavid du Colombier substargs(Nlist *np, Tokenrow *rtr, Tokenrow **atr) 301*3e12c5d1SDavid du Colombier { 302*3e12c5d1SDavid du Colombier Tokenrow tatr; 303*3e12c5d1SDavid du Colombier Token *tp; 304*3e12c5d1SDavid du Colombier int ntok, argno; 305*3e12c5d1SDavid du Colombier 306*3e12c5d1SDavid du Colombier for (rtr->tp=rtr->bp; rtr->tp<rtr->lp; ) { 307*3e12c5d1SDavid du Colombier if (rtr->tp->type==SHARP) { /* string operator */ 308*3e12c5d1SDavid du Colombier tp = rtr->tp; 309*3e12c5d1SDavid du Colombier rtr->tp += 1; 310*3e12c5d1SDavid du Colombier if ((argno = lookuparg(np, rtr->tp))<0) { 311*3e12c5d1SDavid du Colombier error(ERROR, "# not followed by macro parameter"); 312*3e12c5d1SDavid du Colombier continue; 313*3e12c5d1SDavid du Colombier } 314*3e12c5d1SDavid du Colombier ntok = 1 + (rtr->tp - tp); 315*3e12c5d1SDavid du Colombier rtr->tp = tp; 316*3e12c5d1SDavid du Colombier insertrow(rtr, ntok, stringify(atr[argno])); 317*3e12c5d1SDavid du Colombier continue; 318*3e12c5d1SDavid du Colombier } 319*3e12c5d1SDavid du Colombier if (rtr->tp->type==NAME 320*3e12c5d1SDavid du Colombier && (argno = lookuparg(np, rtr->tp)) >= 0) { 321*3e12c5d1SDavid du Colombier if ((rtr->tp+1)->type==DSHARP 322*3e12c5d1SDavid du Colombier || (rtr->tp-1)->type==DSHARP) 323*3e12c5d1SDavid du Colombier insertrow(rtr, 1, atr[argno]); 324*3e12c5d1SDavid du Colombier else { 325*3e12c5d1SDavid du Colombier copytokenrow(&tatr, atr[argno]); 326*3e12c5d1SDavid du Colombier expandrow(&tatr, "<macro>"); 327*3e12c5d1SDavid du Colombier insertrow(rtr, 1, &tatr); 328*3e12c5d1SDavid du Colombier dofree(tatr.bp); 329*3e12c5d1SDavid du Colombier } 330*3e12c5d1SDavid du Colombier continue; 331*3e12c5d1SDavid du Colombier } 332*3e12c5d1SDavid du Colombier rtr->tp++; 333*3e12c5d1SDavid du Colombier } 334*3e12c5d1SDavid du Colombier } 335*3e12c5d1SDavid du Colombier 336*3e12c5d1SDavid du Colombier /* 337*3e12c5d1SDavid du Colombier * Evaluate the ## operators in a tokenrow 338*3e12c5d1SDavid du Colombier */ 339*3e12c5d1SDavid du Colombier void 340*3e12c5d1SDavid du Colombier doconcat(Tokenrow *trp) 341*3e12c5d1SDavid du Colombier { 342*3e12c5d1SDavid du Colombier Token *ltp, *ntp; 343*3e12c5d1SDavid du Colombier Tokenrow ntr; 344*3e12c5d1SDavid du Colombier int len; 345*3e12c5d1SDavid du Colombier 346*3e12c5d1SDavid du Colombier for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) { 347*3e12c5d1SDavid du Colombier if (trp->tp->type==DSHARP1) 348*3e12c5d1SDavid du Colombier trp->tp->type = DSHARP; 349*3e12c5d1SDavid du Colombier else if (trp->tp->type==DSHARP) { 350*3e12c5d1SDavid du Colombier char tt[128]; 351*3e12c5d1SDavid du Colombier ltp = trp->tp-1; 352*3e12c5d1SDavid du Colombier ntp = trp->tp+1; 353*3e12c5d1SDavid du Colombier if (ltp<trp->bp || ntp>=trp->lp) { 354*3e12c5d1SDavid du Colombier error(ERROR, "## occurs at border of replacement"); 355*3e12c5d1SDavid du Colombier continue; 356*3e12c5d1SDavid du Colombier } 357*3e12c5d1SDavid du Colombier len = ltp->len + ntp->len; 358*3e12c5d1SDavid du Colombier strncpy((char*)tt, (char*)ltp->t, ltp->len); 359*3e12c5d1SDavid du Colombier strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len); 360*3e12c5d1SDavid du Colombier tt[len] = '\0'; 361*3e12c5d1SDavid du Colombier setsource("<##>", -1, tt); 362*3e12c5d1SDavid du Colombier maketokenrow(3, &ntr); 363*3e12c5d1SDavid du Colombier gettokens(&ntr, 1); 364*3e12c5d1SDavid du Colombier unsetsource(); 365*3e12c5d1SDavid du Colombier if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS) 366*3e12c5d1SDavid du Colombier error(WARNING, "Bad token %r produced by ##", &ntr); 367*3e12c5d1SDavid du Colombier ntr.lp = ntr.bp+1; 368*3e12c5d1SDavid du Colombier trp->tp = ltp; 369*3e12c5d1SDavid du Colombier makespace(&ntr); 370*3e12c5d1SDavid du Colombier insertrow(trp, (ntp-ltp)+1, &ntr); 371*3e12c5d1SDavid du Colombier dofree(ntr.bp); 372*3e12c5d1SDavid du Colombier trp->tp--; 373*3e12c5d1SDavid du Colombier } 374*3e12c5d1SDavid du Colombier } 375*3e12c5d1SDavid du Colombier } 376*3e12c5d1SDavid du Colombier 377*3e12c5d1SDavid du Colombier /* 378*3e12c5d1SDavid du Colombier * tp is a potential parameter name of macro mac; 379*3e12c5d1SDavid du Colombier * look it up in mac's arglist, and if found, return the 380*3e12c5d1SDavid du Colombier * corresponding index in the argname array. Return -1 if not found. 381*3e12c5d1SDavid du Colombier */ 382*3e12c5d1SDavid du Colombier int 383*3e12c5d1SDavid du Colombier lookuparg(Nlist *mac, Token *tp) 384*3e12c5d1SDavid du Colombier { 385*3e12c5d1SDavid du Colombier Token *ap; 386*3e12c5d1SDavid du Colombier 387*3e12c5d1SDavid du Colombier if (tp->type!=NAME || mac->ap==NULL) 388*3e12c5d1SDavid du Colombier return -1; 389*3e12c5d1SDavid du Colombier for (ap=mac->ap->bp; ap<mac->ap->lp; ap++) { 390*3e12c5d1SDavid du Colombier if (ap->len==tp->len && strncmp((char*)ap->t,(char*)tp->t,ap->len)==0) 391*3e12c5d1SDavid du Colombier return ap - mac->ap->bp; 392*3e12c5d1SDavid du Colombier } 393*3e12c5d1SDavid du Colombier return -1; 394*3e12c5d1SDavid du Colombier } 395*3e12c5d1SDavid du Colombier 396*3e12c5d1SDavid du Colombier /* 397*3e12c5d1SDavid du Colombier * Return a quoted version of the tokenrow (from # arg) 398*3e12c5d1SDavid du Colombier */ 399*3e12c5d1SDavid du Colombier #define STRLEN 512 400*3e12c5d1SDavid du Colombier Tokenrow * 401*3e12c5d1SDavid du Colombier stringify(Tokenrow *vp) 402*3e12c5d1SDavid du Colombier { 403*3e12c5d1SDavid du Colombier static Token t = { STRING }; 404*3e12c5d1SDavid du Colombier static Tokenrow tr = { &t, &t, &t+1, 1 }; 405*3e12c5d1SDavid du Colombier Token *tp; 406*3e12c5d1SDavid du Colombier uchar s[STRLEN]; 407*3e12c5d1SDavid du Colombier uchar *sp = s, *cp; 408*3e12c5d1SDavid du Colombier int i, instring; 409*3e12c5d1SDavid du Colombier 410*3e12c5d1SDavid du Colombier *sp++ = '"'; 411*3e12c5d1SDavid du Colombier for (tp = vp->bp; tp < vp->lp; tp++) { 412*3e12c5d1SDavid du Colombier instring = tp->type==STRING || tp->type==CCON; 413*3e12c5d1SDavid du Colombier if (sp+2*tp->len >= &s[STRLEN-10]) { 414*3e12c5d1SDavid du Colombier error(ERROR, "Stringified macro arg is too long"); 415*3e12c5d1SDavid du Colombier break; 416*3e12c5d1SDavid du Colombier } 417*3e12c5d1SDavid du Colombier if (tp->wslen && (tp->flag&XPWS)==0) 418*3e12c5d1SDavid du Colombier *sp++ = ' '; 419*3e12c5d1SDavid du Colombier for (i=0, cp=tp->t; i<tp->len; i++) { 420*3e12c5d1SDavid du Colombier if (instring && (*cp=='"' || *cp=='\\')) 421*3e12c5d1SDavid du Colombier *sp++ = '\\'; 422*3e12c5d1SDavid du Colombier *sp++ = *cp++; 423*3e12c5d1SDavid du Colombier } 424*3e12c5d1SDavid du Colombier } 425*3e12c5d1SDavid du Colombier *sp++ = '"'; 426*3e12c5d1SDavid du Colombier *sp = '\0'; 427*3e12c5d1SDavid du Colombier sp = s; 428*3e12c5d1SDavid du Colombier t.len = strlen((char*)sp); 429*3e12c5d1SDavid du Colombier t.t = newstring(sp, t.len, 0); 430*3e12c5d1SDavid du Colombier return &tr; 431*3e12c5d1SDavid du Colombier } 432*3e12c5d1SDavid du Colombier 433*3e12c5d1SDavid du Colombier /* 434*3e12c5d1SDavid du Colombier * expand a builtin name 435*3e12c5d1SDavid du Colombier */ 436*3e12c5d1SDavid du Colombier void 437*3e12c5d1SDavid du Colombier builtin(Tokenrow *trp, int biname) 438*3e12c5d1SDavid du Colombier { 439*3e12c5d1SDavid du Colombier char *op; 440*3e12c5d1SDavid du Colombier Token *tp; 441*3e12c5d1SDavid du Colombier Source *s; 442*3e12c5d1SDavid du Colombier 443*3e12c5d1SDavid du Colombier tp = trp->tp; 444*3e12c5d1SDavid du Colombier trp->tp++; 445*3e12c5d1SDavid du Colombier /* need to find the real source */ 446*3e12c5d1SDavid du Colombier s = cursource; 447*3e12c5d1SDavid du Colombier while (s && s->fd==-1) 448*3e12c5d1SDavid du Colombier s = s->next; 449*3e12c5d1SDavid du Colombier if (s==NULL) 450*3e12c5d1SDavid du Colombier s = cursource; 451*3e12c5d1SDavid du Colombier /* most are strings */ 452*3e12c5d1SDavid du Colombier tp->type = STRING; 453*3e12c5d1SDavid du Colombier if (tp->wslen) { 454*3e12c5d1SDavid du Colombier *outp++ = ' '; 455*3e12c5d1SDavid du Colombier tp->wslen = 1; 456*3e12c5d1SDavid du Colombier } 457*3e12c5d1SDavid du Colombier op = outp; 458*3e12c5d1SDavid du Colombier *op++ = '"'; 459*3e12c5d1SDavid du Colombier switch (biname) { 460*3e12c5d1SDavid du Colombier 461*3e12c5d1SDavid du Colombier case KLINENO: 462*3e12c5d1SDavid du Colombier tp->type = NUMBER; 463*3e12c5d1SDavid du Colombier op = outnum(op-1, s->line); 464*3e12c5d1SDavid du Colombier break; 465*3e12c5d1SDavid du Colombier 466*3e12c5d1SDavid du Colombier case KFILE: 467*3e12c5d1SDavid du Colombier strcpy(op, s->filename); 468*3e12c5d1SDavid du Colombier op += strlen(s->filename); 469*3e12c5d1SDavid du Colombier break; 470*3e12c5d1SDavid du Colombier 471*3e12c5d1SDavid du Colombier case KDATE: 472*3e12c5d1SDavid du Colombier strncpy(op, curtime+4, 7); 473*3e12c5d1SDavid du Colombier strncpy(op+7, curtime+24, 4); /* Plan 9 asctime disobeys standard */ 474*3e12c5d1SDavid du Colombier op += 11; 475*3e12c5d1SDavid du Colombier break; 476*3e12c5d1SDavid du Colombier 477*3e12c5d1SDavid du Colombier case KTIME: 478*3e12c5d1SDavid du Colombier strncpy(op, curtime+11, 8); 479*3e12c5d1SDavid du Colombier op += 8; 480*3e12c5d1SDavid du Colombier break; 481*3e12c5d1SDavid du Colombier 482*3e12c5d1SDavid du Colombier default: 483*3e12c5d1SDavid du Colombier error(ERROR, "cpp botch: unknown internal macro"); 484*3e12c5d1SDavid du Colombier return; 485*3e12c5d1SDavid du Colombier } 486*3e12c5d1SDavid du Colombier if (tp->type==STRING) 487*3e12c5d1SDavid du Colombier *op++ = '"'; 488*3e12c5d1SDavid du Colombier tp->t = (uchar*)outp; 489*3e12c5d1SDavid du Colombier tp->len = op - outp; 490*3e12c5d1SDavid du Colombier outp = op; 491*3e12c5d1SDavid du Colombier } 492