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