114478Ssam #ifndef lint
2*34082Sbostic static char sccsid[] = "@(#)macro.c 4.4 04/24/88";
314478Ssam #endif
46695Smckusick
56695Smckusick #
66695Smckusick /*
76695Smckusick * UNIX shell
86695Smckusick *
96695Smckusick * S. R. Bourne
106695Smckusick * Bell Telephone Laboratories
116695Smckusick *
126695Smckusick */
136695Smckusick
146695Smckusick #include "defs.h"
156695Smckusick #include "sym.h"
166695Smckusick
176695Smckusick LOCAL CHAR quote; /* used locally */
186695Smckusick LOCAL CHAR quoted; /* used locally */
196695Smckusick
206695Smckusick
216695Smckusick
copyto(endch)226695Smckusick LOCAL STRING copyto(endch)
236695Smckusick REG CHAR endch;
246695Smckusick {
256695Smckusick REG CHAR c;
266695Smckusick
276695Smckusick WHILE (c=getch(endch))!=endch ANDF c
286695Smckusick DO pushstak(c|quote) OD
296695Smckusick zerostak();
306695Smckusick IF c!=endch THEN error(badsub) FI
316695Smckusick }
326695Smckusick
skipto(endch)336695Smckusick LOCAL skipto(endch)
346695Smckusick REG CHAR endch;
356695Smckusick {
366695Smckusick /* skip chars up to } */
376695Smckusick REG CHAR c;
386695Smckusick WHILE (c=readc()) ANDF c!=endch
396695Smckusick DO SWITCH c IN
406695Smckusick
416695Smckusick case SQUOTE: skipto(SQUOTE); break;
426695Smckusick
436695Smckusick case DQUOTE: skipto(DQUOTE); break;
446695Smckusick
456695Smckusick case DOLLAR: IF readc()==BRACE
466695Smckusick THEN skipto('}');
476695Smckusick FI
486695Smckusick ENDSW
496695Smckusick OD
506695Smckusick IF c!=endch THEN error(badsub) FI
516695Smckusick }
526695Smckusick
getch(endch)536695Smckusick LOCAL getch(endch)
546695Smckusick CHAR endch;
556695Smckusick {
566695Smckusick REG CHAR d;
576695Smckusick
586695Smckusick retry:
596695Smckusick d=readc();
606695Smckusick IF !subchar(d)
616695Smckusick THEN return(d);
626695Smckusick FI
636695Smckusick IF d==DOLLAR
646695Smckusick THEN REG INT c;
656695Smckusick IF (c=readc(), dolchar(c))
666695Smckusick THEN NAMPTR n=NIL;
676695Smckusick INT dolg=0;
686695Smckusick BOOL bra;
696695Smckusick REG STRING argp, v;
706695Smckusick CHAR idb[2];
716695Smckusick STRING id=idb;
726695Smckusick
736695Smckusick IF bra=(c==BRACE) THEN c=readc() FI
746695Smckusick IF letter(c)
756695Smckusick THEN argp=relstak();
766695Smckusick WHILE alphanum(c) DO pushstak(c); c=readc() OD
776695Smckusick zerostak();
786695Smckusick n=lookup(absstak(argp)); setstak(argp);
796695Smckusick v = n->namval; id = n->namid;
806695Smckusick peekc = c|MARK;;
816695Smckusick ELIF digchar(c)
826695Smckusick THEN *id=c; idb[1]=0;
836695Smckusick IF astchar(c)
846695Smckusick THEN dolg=1; c='1';
856695Smckusick FI
866695Smckusick c -= '0';
87*34082Sbostic v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (STRING)(dolg=0));
886695Smckusick ELIF c=='$'
896695Smckusick THEN v=pidadr;
906695Smckusick ELIF c=='!'
916695Smckusick THEN v=pcsadr;
926695Smckusick ELIF c=='#'
936695Smckusick THEN v=dolladr;
946695Smckusick ELIF c=='?'
956695Smckusick THEN v=exitadr;
966695Smckusick ELIF c=='-'
976695Smckusick THEN v=flagadr;
986695Smckusick ELIF bra THEN error(badsub);
996695Smckusick ELSE goto retry;
1006695Smckusick FI
1016695Smckusick c = readc();
1026695Smckusick IF !defchar(c) ANDF bra
1036695Smckusick THEN error(badsub);
1046695Smckusick FI
1056695Smckusick argp=0;
1066695Smckusick IF bra
1076695Smckusick THEN IF c!='}'
1086695Smckusick THEN argp=relstak();
1096695Smckusick IF (v==0)NEQ(setchar(c))
1106695Smckusick THEN copyto('}');
1116695Smckusick ELSE skipto('}');
1126695Smckusick FI
1136695Smckusick argp=absstak(argp);
1146695Smckusick FI
1156695Smckusick ELSE peekc = c|MARK; c = 0;
1166695Smckusick FI
1176695Smckusick IF v
1186695Smckusick THEN IF c!='+'
1196695Smckusick THEN LOOP WHILE c = *v++
1206695Smckusick DO pushstak(c|quote); OD
1216695Smckusick IF dolg==0 ORF (++dolg>dolc)
1226695Smckusick THEN break;
1236695Smckusick ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0));
1246695Smckusick FI
1256695Smckusick POOL
1266695Smckusick FI
1276695Smckusick ELIF argp
1286695Smckusick THEN IF c=='?'
1296695Smckusick THEN failed(id,*argp?argp:badparam);
1306695Smckusick ELIF c=='='
1316695Smckusick THEN IF n
1326695Smckusick THEN assign(n,argp);
1336695Smckusick ELSE error(badsub);
1346695Smckusick FI
1356695Smckusick FI
1366695Smckusick ELIF flags&setflg
1376695Smckusick THEN failed(id,badparam);
1386695Smckusick FI
1396695Smckusick goto retry;
1406695Smckusick ELSE peekc=c|MARK;
1416695Smckusick FI
1426695Smckusick ELIF d==endch
1436695Smckusick THEN return(d);
1446695Smckusick ELIF d==SQUOTE
1456695Smckusick THEN comsubst(); goto retry;
1466695Smckusick ELIF d==DQUOTE
1476695Smckusick THEN quoted++; quote^=QUOTE; goto retry;
1486695Smckusick FI
1496695Smckusick return(d);
1506695Smckusick }
1516695Smckusick
macro(as)1526695Smckusick STRING macro(as)
1536695Smckusick STRING as;
1546695Smckusick {
1556695Smckusick /* Strip "" and do $ substitution
1566695Smckusick * Leaves result on top of stack
1576695Smckusick */
1586695Smckusick REG BOOL savqu =quoted;
1596695Smckusick REG CHAR savq = quote;
1606695Smckusick FILEHDR fb;
1616695Smckusick
1626695Smckusick push(&fb); estabf(as);
1636695Smckusick usestak();
1646695Smckusick quote=0; quoted=0;
1656695Smckusick copyto(0);
1666695Smckusick pop();
1676695Smckusick IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI
1686695Smckusick quote=savq; quoted=savqu;
1696695Smckusick return(fixstak());
1706695Smckusick }
1716695Smckusick
comsubst()1726695Smckusick LOCAL comsubst()
1736695Smckusick {
1746695Smckusick /* command substn */
1756695Smckusick FILEBLK cb;
1766695Smckusick REG CHAR d;
1776695Smckusick REG STKPTR savptr = fixstak();
1786695Smckusick
1796695Smckusick usestak();
1806695Smckusick WHILE (d=readc())!=SQUOTE ANDF d
1816695Smckusick DO pushstak(d) OD
1826695Smckusick
1836695Smckusick BEGIN
1846695Smckusick REG STRING argc;
1856695Smckusick trim(argc=fixstak());
1866695Smckusick push(&cb); estabf(argc);
1876695Smckusick END
1886695Smckusick BEGIN
1896695Smckusick REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG));
1906695Smckusick INT pv[2];
1916695Smckusick
1926695Smckusick /* this is done like this so that the pipe
1936695Smckusick * is open only when needed
1946695Smckusick */
1956695Smckusick chkpipe(pv);
1966695Smckusick initf(pv[INPIPE]);
1976695Smckusick execute(t, 0, 0, pv);
1986695Smckusick close(pv[OTPIPE]);
1996695Smckusick END
2006695Smckusick tdystak(savptr); staktop=movstr(savptr,stakbot);
20110805Ssam WHILE d=readc() DO locstak(); pushstak(d|quote) OD
2026695Smckusick await(0);
2036695Smckusick WHILE stakbot!=staktop
2046695Smckusick DO IF (*--staktop&STRIP)!=NL
2056695Smckusick THEN ++staktop; break;
2066695Smckusick FI
2076695Smckusick OD
2086695Smckusick pop();
2096695Smckusick }
2106695Smckusick
2116695Smckusick #define CPYSIZ 512
2126695Smckusick
subst(in,ot)2136695Smckusick subst(in,ot)
2146695Smckusick INT in, ot;
2156695Smckusick {
2166695Smckusick REG CHAR c;
2176695Smckusick FILEBLK fb;
2186695Smckusick REG INT count=CPYSIZ;
2196695Smckusick
2206695Smckusick push(&fb); initf(in);
2216695Smckusick /* DQUOTE used to stop it from quoting */
2226695Smckusick WHILE c=(getch(DQUOTE)&STRIP)
2236695Smckusick DO pushstak(c);
2246695Smckusick IF --count == 0
2256695Smckusick THEN flush(ot); count=CPYSIZ;
2266695Smckusick FI
2276695Smckusick OD
2286695Smckusick flush(ot);
2296695Smckusick pop();
2306695Smckusick }
2316695Smckusick
flush(ot)2326695Smckusick LOCAL flush(ot)
2336695Smckusick {
2346695Smckusick write(ot,stakbot,staktop-stakbot);
2356695Smckusick IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI
2366695Smckusick staktop=stakbot;
2376695Smckusick }
238