xref: /csrg-svn/old/sh/macro.c (revision 6695)
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