1*6695Smckusick /* macro.c 4.1 82/05/07 */ 2*6695Smckusick 3*6695Smckusick # 4*6695Smckusick /* 5*6695Smckusick * UNIX shell 6*6695Smckusick * 7*6695Smckusick * S. R. Bourne 8*6695Smckusick * Bell Telephone Laboratories 9*6695Smckusick * 10*6695Smckusick */ 11*6695Smckusick 12*6695Smckusick #include "defs.h" 13*6695Smckusick #include "sym.h" 14*6695Smckusick 15*6695Smckusick LOCAL CHAR quote; /* used locally */ 16*6695Smckusick LOCAL CHAR quoted; /* used locally */ 17*6695Smckusick 18*6695Smckusick 19*6695Smckusick 20*6695Smckusick LOCAL STRING copyto(endch) 21*6695Smckusick REG CHAR endch; 22*6695Smckusick { 23*6695Smckusick REG CHAR c; 24*6695Smckusick 25*6695Smckusick WHILE (c=getch(endch))!=endch ANDF c 26*6695Smckusick DO pushstak(c|quote) OD 27*6695Smckusick zerostak(); 28*6695Smckusick IF c!=endch THEN error(badsub) FI 29*6695Smckusick } 30*6695Smckusick 31*6695Smckusick LOCAL skipto(endch) 32*6695Smckusick REG CHAR endch; 33*6695Smckusick { 34*6695Smckusick /* skip chars up to } */ 35*6695Smckusick REG CHAR c; 36*6695Smckusick WHILE (c=readc()) ANDF c!=endch 37*6695Smckusick DO SWITCH c IN 38*6695Smckusick 39*6695Smckusick case SQUOTE: skipto(SQUOTE); break; 40*6695Smckusick 41*6695Smckusick case DQUOTE: skipto(DQUOTE); break; 42*6695Smckusick 43*6695Smckusick case DOLLAR: IF readc()==BRACE 44*6695Smckusick THEN skipto('}'); 45*6695Smckusick FI 46*6695Smckusick ENDSW 47*6695Smckusick OD 48*6695Smckusick IF c!=endch THEN error(badsub) FI 49*6695Smckusick } 50*6695Smckusick 51*6695Smckusick LOCAL getch(endch) 52*6695Smckusick CHAR endch; 53*6695Smckusick { 54*6695Smckusick REG CHAR d; 55*6695Smckusick 56*6695Smckusick retry: 57*6695Smckusick d=readc(); 58*6695Smckusick IF !subchar(d) 59*6695Smckusick THEN return(d); 60*6695Smckusick FI 61*6695Smckusick IF d==DOLLAR 62*6695Smckusick THEN REG INT c; 63*6695Smckusick IF (c=readc(), dolchar(c)) 64*6695Smckusick THEN NAMPTR n=NIL; 65*6695Smckusick INT dolg=0; 66*6695Smckusick BOOL bra; 67*6695Smckusick REG STRING argp, v; 68*6695Smckusick CHAR idb[2]; 69*6695Smckusick STRING id=idb; 70*6695Smckusick 71*6695Smckusick IF bra=(c==BRACE) THEN c=readc() FI 72*6695Smckusick IF letter(c) 73*6695Smckusick THEN argp=relstak(); 74*6695Smckusick WHILE alphanum(c) DO pushstak(c); c=readc() OD 75*6695Smckusick zerostak(); 76*6695Smckusick n=lookup(absstak(argp)); setstak(argp); 77*6695Smckusick v = n->namval; id = n->namid; 78*6695Smckusick peekc = c|MARK;; 79*6695Smckusick ELIF digchar(c) 80*6695Smckusick THEN *id=c; idb[1]=0; 81*6695Smckusick IF astchar(c) 82*6695Smckusick THEN dolg=1; c='1'; 83*6695Smckusick FI 84*6695Smckusick c -= '0'; 85*6695Smckusick v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (dolg=0)); 86*6695Smckusick ELIF c=='$' 87*6695Smckusick THEN v=pidadr; 88*6695Smckusick ELIF c=='!' 89*6695Smckusick THEN v=pcsadr; 90*6695Smckusick ELIF c=='#' 91*6695Smckusick THEN v=dolladr; 92*6695Smckusick ELIF c=='?' 93*6695Smckusick THEN v=exitadr; 94*6695Smckusick ELIF c=='-' 95*6695Smckusick THEN v=flagadr; 96*6695Smckusick ELIF bra THEN error(badsub); 97*6695Smckusick ELSE goto retry; 98*6695Smckusick FI 99*6695Smckusick c = readc(); 100*6695Smckusick IF !defchar(c) ANDF bra 101*6695Smckusick THEN error(badsub); 102*6695Smckusick FI 103*6695Smckusick argp=0; 104*6695Smckusick IF bra 105*6695Smckusick THEN IF c!='}' 106*6695Smckusick THEN argp=relstak(); 107*6695Smckusick IF (v==0)NEQ(setchar(c)) 108*6695Smckusick THEN copyto('}'); 109*6695Smckusick ELSE skipto('}'); 110*6695Smckusick FI 111*6695Smckusick argp=absstak(argp); 112*6695Smckusick FI 113*6695Smckusick ELSE peekc = c|MARK; c = 0; 114*6695Smckusick FI 115*6695Smckusick IF v 116*6695Smckusick THEN IF c!='+' 117*6695Smckusick THEN LOOP WHILE c = *v++ 118*6695Smckusick DO pushstak(c|quote); OD 119*6695Smckusick IF dolg==0 ORF (++dolg>dolc) 120*6695Smckusick THEN break; 121*6695Smckusick ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0)); 122*6695Smckusick FI 123*6695Smckusick POOL 124*6695Smckusick FI 125*6695Smckusick ELIF argp 126*6695Smckusick THEN IF c=='?' 127*6695Smckusick THEN failed(id,*argp?argp:badparam); 128*6695Smckusick ELIF c=='=' 129*6695Smckusick THEN IF n 130*6695Smckusick THEN assign(n,argp); 131*6695Smckusick ELSE error(badsub); 132*6695Smckusick FI 133*6695Smckusick FI 134*6695Smckusick ELIF flags&setflg 135*6695Smckusick THEN failed(id,badparam); 136*6695Smckusick FI 137*6695Smckusick goto retry; 138*6695Smckusick ELSE peekc=c|MARK; 139*6695Smckusick FI 140*6695Smckusick ELIF d==endch 141*6695Smckusick THEN return(d); 142*6695Smckusick ELIF d==SQUOTE 143*6695Smckusick THEN comsubst(); goto retry; 144*6695Smckusick ELIF d==DQUOTE 145*6695Smckusick THEN quoted++; quote^=QUOTE; goto retry; 146*6695Smckusick FI 147*6695Smckusick return(d); 148*6695Smckusick } 149*6695Smckusick 150*6695Smckusick STRING macro(as) 151*6695Smckusick STRING as; 152*6695Smckusick { 153*6695Smckusick /* Strip "" and do $ substitution 154*6695Smckusick * Leaves result on top of stack 155*6695Smckusick */ 156*6695Smckusick REG BOOL savqu =quoted; 157*6695Smckusick REG CHAR savq = quote; 158*6695Smckusick FILEHDR fb; 159*6695Smckusick 160*6695Smckusick push(&fb); estabf(as); 161*6695Smckusick usestak(); 162*6695Smckusick quote=0; quoted=0; 163*6695Smckusick copyto(0); 164*6695Smckusick pop(); 165*6695Smckusick IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI 166*6695Smckusick quote=savq; quoted=savqu; 167*6695Smckusick return(fixstak()); 168*6695Smckusick } 169*6695Smckusick 170*6695Smckusick LOCAL comsubst() 171*6695Smckusick { 172*6695Smckusick /* command substn */ 173*6695Smckusick FILEBLK cb; 174*6695Smckusick REG CHAR d; 175*6695Smckusick REG STKPTR savptr = fixstak(); 176*6695Smckusick 177*6695Smckusick usestak(); 178*6695Smckusick WHILE (d=readc())!=SQUOTE ANDF d 179*6695Smckusick DO pushstak(d) OD 180*6695Smckusick 181*6695Smckusick BEGIN 182*6695Smckusick REG STRING argc; 183*6695Smckusick trim(argc=fixstak()); 184*6695Smckusick push(&cb); estabf(argc); 185*6695Smckusick END 186*6695Smckusick BEGIN 187*6695Smckusick REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG)); 188*6695Smckusick INT pv[2]; 189*6695Smckusick 190*6695Smckusick /* this is done like this so that the pipe 191*6695Smckusick * is open only when needed 192*6695Smckusick */ 193*6695Smckusick chkpipe(pv); 194*6695Smckusick initf(pv[INPIPE]); 195*6695Smckusick execute(t, 0, 0, pv); 196*6695Smckusick close(pv[OTPIPE]); 197*6695Smckusick END 198*6695Smckusick tdystak(savptr); staktop=movstr(savptr,stakbot); 199*6695Smckusick WHILE d=readc() DO pushstak(d|quote) OD 200*6695Smckusick await(0); 201*6695Smckusick WHILE stakbot!=staktop 202*6695Smckusick DO IF (*--staktop&STRIP)!=NL 203*6695Smckusick THEN ++staktop; break; 204*6695Smckusick FI 205*6695Smckusick OD 206*6695Smckusick pop(); 207*6695Smckusick } 208*6695Smckusick 209*6695Smckusick #define CPYSIZ 512 210*6695Smckusick 211*6695Smckusick subst(in,ot) 212*6695Smckusick INT in, ot; 213*6695Smckusick { 214*6695Smckusick REG CHAR c; 215*6695Smckusick FILEBLK fb; 216*6695Smckusick REG INT count=CPYSIZ; 217*6695Smckusick 218*6695Smckusick push(&fb); initf(in); 219*6695Smckusick /* DQUOTE used to stop it from quoting */ 220*6695Smckusick WHILE c=(getch(DQUOTE)&STRIP) 221*6695Smckusick DO pushstak(c); 222*6695Smckusick IF --count == 0 223*6695Smckusick THEN flush(ot); count=CPYSIZ; 224*6695Smckusick FI 225*6695Smckusick OD 226*6695Smckusick flush(ot); 227*6695Smckusick pop(); 228*6695Smckusick } 229*6695Smckusick 230*6695Smckusick LOCAL flush(ot) 231*6695Smckusick { 232*6695Smckusick write(ot,stakbot,staktop-stakbot); 233*6695Smckusick IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI 234*6695Smckusick staktop=stakbot; 235*6695Smckusick } 236