/* * substitute the argument list into the replacement string * This would be simple except for ## and # */ void substargs(Nlist* np, Tokenrow* rtr, Tokenrow** atr) { Tokenrow tatr; Token* tp; int ntok, argno; for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) { if (rtr->tp->type == SHARP) { /* string operator */ tp = rtr->tp; rtr->tp += 1; if ((argno = lookuparg(np, rtr->tp)) < 0) { error(ERROR, "# not followed by macro parameter"); continue; } ntok = 1 + (rtr->tp - tp); rtr->tp = tp; insertrow(rtr, ntok, stringify(atr[argno])); continue; } if (rtr->tp->type == NAME && (argno = lookuparg(np, rtr->tp)) >= 0) { if ((rtr->tp + 1)->type == DSHARP || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) insertrow(rtr, 1, atr[argno]); else { copytokenrow(&tatr, atr[argno]); expandrow(&tatr, "<macro>"); insertrow(rtr, 1, &tatr); dofree(tatr.bp); } continue; } rtr->tp++; } }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) */ void expand(Tokenrow *trp, Nlist *np) { Tokenrow ntr; int ntokc, narg, i; Token *tp; int hs; #ifdef __ORCAC__ Tokenrow **atr; atr = domalloc(sizeof(Tokenrow *) * (NARG+1)); #define RETURN free(atr);return #else Tokenrow *atr[NARG+1]; #define RETURN return; #endif copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap==NULL) /* parameterless */ ntokc = 1; else { ntokc = gatherargs(trp, atr, &narg); if (narg<0) { /* not actually a call (no '(') */ trp->tp++; RETURN; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp += ntokc; RETURN; } substargs(np, &ntr, atr); /* put args into replacement */ for (i=0; i<narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ hs = newhideset(trp->tp->hideset, np); for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */ if (tp->type==NAME) { if (tp->hideset==0) tp->hideset = hs; else tp->hideset = unionhideset(tp->hideset, hs); } } ntr.tp = ntr.bp; insertrow(trp, ntokc, &ntr); trp->tp -= rowlen(&ntr); dofree(ntr.bp); RETURN; }
void rmenu(void) /* Executes the commands in the row menu */ { switch(getcommand(RMENU, RCOMMAND)) { case 0 : insertrow(currow); break; case 1 : deleterow(currow); break; } /* switch */ } /* rmenu */
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) */ void expand(Tokenrow *trp, Nlist *np) { Tokenrow ntr; int ntokc, narg, i; Token *tp; Tokenrow *atr[NARG+1]; int hs; copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap==NULL) /* parameterless */ ntokc = 1; else { ntokc = gatherargs(trp, atr, &narg); if (narg<0) { /* not actually a call (no '(') */ /* gatherargs has already pushed trp->tr to the next token */ return; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp += ntokc; return; } substargs(np, &ntr, atr); /* put args into replacement */ for (i=0; i<narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ hs = newhideset(trp->tp->hideset, np); for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */ if (tp->type==NAME) { if (tp->hideset==0) tp->hideset = hs; else tp->hideset = unionhideset(tp->hideset, hs); } } ntr.tp = ntr.bp; insertrow(trp, ntokc, &ntr); trp->tp -= rowlen(&ntr); dofree(ntr.bp); return; }
/* * Evaluate the ## operators in a tokenrow */ void doconcat(Tokenrow *trp) { Token *ltp, *ntp; STATIC Tokenrow ntr; int len; CHECKIN(); for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) { if (trp->tp->type==DSHARP1) trp->tp->type = DSHARP; else if (trp->tp->type==DSHARP) { STATIC char tt[128]; ltp = trp->tp-1; ntp = trp->tp+1; if (ltp<trp->bp || ntp>=trp->lp) { error(ERROR, "## occurs at border of replacement"); continue; } len = ltp->len + ntp->len; strncpy((char*)tt, (char*)ltp->t, ltp->len); strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len); tt[len] = '\0'; setsource("<##>", -1, tt); maketokenrow(3, &ntr); gettokens(&ntr, 1); unsetsource(); if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS) error(WARNING, "Bad token %r produced by ##", &ntr); ntr.lp = ntr.bp+1; trp->tp = ltp; makespace(&ntr); insertrow(trp, (ntp-ltp)+1, &ntr); dofree(ntr.bp); trp->tp--; } } CHECKOUT(); }
/* * Evaluate the ## operators in a tokenrow */ void doconcat(Tokenrow * trp) { Token *ltp, *ntp; Tokenrow ntr; size_t len; for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) { if (trp->tp->type == DSHARP1) trp->tp->type = DSHARP; else if (trp->tp->type == DSHARP) { int i; char tt[NCONCAT]; ltp = trp->tp - 1; ntp = trp->tp + 1; if (ltp < trp->bp || ntp >= trp->lp) { error(ERROR, "## occurs at border of replacement"); continue; } ntp = ltp; i = 1; len = 0; do { if (len + ntp->len + ntp->wslen > sizeof(tt)) { error(ERROR, "## string concatination buffer overrun"); break; } if (ntp != trp->tp + 1) { strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, ntp->len + ntp->wslen); len += ntp->len + ntp->wslen; } else // Leerzeichen um ## herum entfernen: { strncpy((char *) tt + len, (char *) ntp->t, ntp->len); len += ntp->len; } ntp = trp->tp + i; i++; } while (ntp < trp->lp); tt[len] = '\0'; setsource("<##>", -1, -1, tt, 0); maketokenrow(3, &ntr); gettokens(&ntr, 1); unsetsource(); if (ntr.bp->type == UNCLASS) error(WARNING, "Bad token %r produced by ##", &ntr); while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp) ntr.lp--; doconcat(&ntr); trp->tp = ltp; makespace(&ntr, ltp); insertrow(trp, (int)(ntp - ltp), &ntr); dofree(ntr.bp); trp->tp--; } } }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) * I.e.: the same position as before! * Only one expansion is performed, then we return to the expandrow() * loop and start at same position. */ void expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators) { Tokenrow ntr; int ntokc, narg; Tokenrow *atr[NARG + 1]; if (Mflag == 2) { if (np->ap) error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); else error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); } copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap == NULL) /* parameterless */ ntokc = 1; else { int i; ntokc = gatherargs(trp, atr, &narg); if (narg < 0) { /* not actually a call (no '(') */ trp->tp++; return; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp += ntokc; return; } /** If gatherargs passed a macro validating token, this token must become valid here. trp->tp+0 was checked in expandrow(), so we don't need to do it again here: */ for (i = 1; i < ntokc; i++) { mvl_check(pValidators,trp->tp+i); } substargs(np, &ntr, atr); /* put args into replacement */ for (i = 0; i < narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ ntr.tp = ntr.bp; makespace(&ntr, trp->tp); tokenrow_zeroTokenIdentifiers(&ntr); insertrow(trp, ntokc, &ntr); /* add validator for just invalidated macro: */ np->flag |= ISACTIVE; if (trp->tp != trp->lp) { /* tp is a valid pointer: */ mvl_add(pValidators,np,trp->tp); } else { /* tp is == lp, therefore does not point to valid memory: */ mvl_add(pValidators,np,0); } /* reset trp->tp to original position: */ trp->tp -= ntr.lp - ntr.bp; /* so the result will be tested for macros from the same position again */ dofree(ntr.bp); return; }