xref: /csrg-svn/local/toolchest/ksh/sh/macro.c (revision 35150)
1*35150Smarc /*
2*35150Smarc 
3*35150Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35150Smarc  *      All Rights Reserved
5*35150Smarc 
6*35150Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35150Smarc  *      CODE OF AT&T.
8*35150Smarc  *      The copyright notice above does not
9*35150Smarc  *      evidence any actual or intended
10*35150Smarc  *      publication of such source code.
11*35150Smarc 
12*35150Smarc  */
13*35150Smarc /* @(#)macro.c	1.1 */
14*35150Smarc /*
15*35150Smarc  * UNIX shell
16*35150Smarc  *
17*35150Smarc  * S. R. Bourne
18*35150Smarc  * AT&T Bell Laboratories
19*35150Smarc  * Rewritten by David Korn
20*35150Smarc  *
21*35150Smarc  */
22*35150Smarc 
23*35150Smarc #include	<sys/types.h>
24*35150Smarc #include	<sys/stat.h>
25*35150Smarc #include	"flags.h"
26*35150Smarc #include	"defs.h"
27*35150Smarc #include	"io.h"
28*35150Smarc #include	"sym.h"
29*35150Smarc #include	"stak.h"
30*35150Smarc #include	"name.h"
31*35150Smarc #include	"shtype.h"
32*35150Smarc #include	"mode.h"
33*35150Smarc #include	"jobs.h"
34*35150Smarc #include	"builtins.h"
35*35150Smarc #include	"brkincr.h"
36*35150Smarc #ifdef MULTIBYTE
37*35150Smarc #include	"national.h"
38*35150Smarc #endif /* MULTIBYTE */
39*35150Smarc 
40*35150Smarc #define unreadc(c)	(peekc = (c)|MARK)
41*35150Smarc #define blt_no(t)	((t)>>(COMBITS+1))
42*35150Smarc #define RBRACE		'}'
43*35150Smarc 
44*35150Smarc /* These routines are defined by this module */
45*35150Smarc char	*macro();
46*35150Smarc char	*mactry();
47*35150Smarc char	*mactrim();
48*35150Smarc void	mac_subst();
49*35150Smarc 
50*35150Smarc /* These external routines are referenced by this module */
51*35150Smarc extern char	*arg_dolminus();
52*35150Smarc extern void	assign();
53*35150Smarc extern void	await();
54*35150Smarc extern FILE	*chkopen();
55*35150Smarc extern void	chkpipe();
56*35150Smarc extern TREPTR	cmd();
57*35150Smarc extern void	exfunct();
58*35150Smarc extern void	failed();
59*35150Smarc extern void	initf();
60*35150Smarc extern char	*itos();
61*35150Smarc extern NAMPTR	lookup();
62*35150Smarc extern long	lseek();
63*35150Smarc extern TREPTR	makefork();
64*35150Smarc extern char	*match_paren();
65*35150Smarc extern char	*movstr();
66*35150Smarc extern void	p_setout();
67*35150Smarc extern int	readc();
68*35150Smarc extern char	*strcpy();
69*35150Smarc extern void	tdystak();
70*35150Smarc extern FILE	*tmp_open();
71*35150Smarc extern void	trim();
72*35150Smarc extern char	*valup();
73*35150Smarc 
74*35150Smarc #ifdef MULTIBYTE
75*35150Smarc static int	charlen();
76*35150Smarc #endif /* MULTIBYTE */
77*35150Smarc static char	*copyto();
78*35150Smarc static char	*substring();
79*35150Smarc static void	skipto();
80*35150Smarc static int	getch();
81*35150Smarc static void	comsubst();
82*35150Smarc static void	mac_error();
83*35150Smarc 
84*35150Smarc static char	quote;	/* used locally */
85*35150Smarc static char	quoted;	/* used locally */
86*35150Smarc static char	mflag;	/* set for macro expansion, unset for here docs */
87*35150Smarc static FILE	*w_fd;
88*35150Smarc static int mac_try;
89*35150Smarc static jmp_buf mac_buf;
90*35150Smarc static char	idb[2];
91*35150Smarc 
92*35150Smarc 
copyto(endch)93*35150Smarc static char *copyto(endch)
94*35150Smarc register char	endch;
95*35150Smarc {
96*35150Smarc 	register int	c;
97*35150Smarc 
98*35150Smarc 	while((c=getch(endch))!=endch && c)
99*35150Smarc 	{
100*35150Smarc 		if(quote || c==ESCAPE)
101*35150Smarc 		{
102*35150Smarc 			pushstak(ESCAPE);
103*35150Smarc 			if(c==ESCAPE)
104*35150Smarc 			{
105*35150Smarc 				c = readc();
106*35150Smarc 				if(quote && !escchar(c) && c!= '"')
107*35150Smarc 				{
108*35150Smarc 					pushstak(ESCAPE);
109*35150Smarc 					pushstak(ESCAPE);
110*35150Smarc 				}
111*35150Smarc 			}
112*35150Smarc 		}
113*35150Smarc 		pushstak(c);
114*35150Smarc 	}
115*35150Smarc 	zerostak();
116*35150Smarc 	if(c!=endch)
117*35150Smarc 		mac_error();
118*35150Smarc }
119*35150Smarc 
120*35150Smarc 	/* skip chars up to } */
skipto(endch)121*35150Smarc static void skipto(endch)
122*35150Smarc register char endch;
123*35150Smarc {
124*35150Smarc 	register char	c;
125*35150Smarc 	while((c=readc()) && c!=endch)
126*35150Smarc 	{
127*35150Smarc 		switch(c)
128*35150Smarc 		{
129*35150Smarc 			case SQUOTE:	case DQUOTE:
130*35150Smarc 				skipto(c);
131*35150Smarc 				break;
132*35150Smarc 
133*35150Smarc 			case DOLLAR:
134*35150Smarc 				if(readc()==BRACE)
135*35150Smarc 					skipto(RBRACE);
136*35150Smarc 		}
137*35150Smarc 	}
138*35150Smarc 	if(c!=endch)
139*35150Smarc 		mac_error();
140*35150Smarc }
141*35150Smarc 
getch(endch)142*35150Smarc static int getch(endch)
143*35150Smarc int	endch;
144*35150Smarc {
145*35150Smarc 	register int	c;
146*35150Smarc 	int atflag;  /* set if $@ or ${array[@]} within double quotes */
147*35150Smarc retry:
148*35150Smarc 	c = readc();
149*35150Smarc 	if(!subchar(c))
150*35150Smarc 		return(c);
151*35150Smarc 	if(c==DOLLAR)
152*35150Smarc 	{
153*35150Smarc 		register int	 bra = 0; /* {...} bra =1, {#...} bra=2 */
154*35150Smarc 		register char *v;
155*35150Smarc 		register char *argp;
156*35150Smarc 		register NAMPTR	 n=(NAMPTR)NULL;
157*35150Smarc 		int 	dolg=0;
158*35150Smarc 		int dolmax = dolc+1;
159*35150Smarc 		BOOL 	nulflg;
160*35150Smarc 		char *id=idb;
161*35150Smarc 		*id = 0;
162*35150Smarc 	retry1:
163*35150Smarc 		c = readc();
164*35150Smarc 		switch(c)
165*35150Smarc 		{
166*35150Smarc 			case DOLLAR:
167*35150Smarc 				v=pidadr;
168*35150Smarc 				break;
169*35150Smarc 
170*35150Smarc 			case '!':
171*35150Smarc 				v=pcsadr;
172*35150Smarc 				break;
173*35150Smarc 
174*35150Smarc 			case BRACE:
175*35150Smarc 				if(bra++ ==0)
176*35150Smarc 					goto retry1;
177*35150Smarc 
178*35150Smarc 			case LPAREN:
179*35150Smarc 				if(bra==0 && mac_try==0)
180*35150Smarc 				{
181*35150Smarc 					comsubst(1);
182*35150Smarc 					goto retry;
183*35150Smarc 				}
184*35150Smarc 				goto nosub;
185*35150Smarc 
186*35150Smarc 			case RBRACE:
187*35150Smarc 				if(bra!=2)
188*35150Smarc 					goto nosub;
189*35150Smarc 				bra = 0;
190*35150Smarc 			case '#':
191*35150Smarc 				if(bra ==1)
192*35150Smarc 				{
193*35150Smarc 					bra++;
194*35150Smarc 					goto retry1;
195*35150Smarc 				}
196*35150Smarc 				v=itos(dolc);
197*35150Smarc 				break;
198*35150Smarc 
199*35150Smarc 			case '?':
200*35150Smarc 				v=itos(savexit);
201*35150Smarc 				break;
202*35150Smarc 
203*35150Smarc 			case '-':
204*35150Smarc 				v=arg_dolminus();
205*35150Smarc 				break;
206*35150Smarc 
207*35150Smarc 			default:
208*35150Smarc 				if(isalpha(c))
209*35150Smarc 				{
210*35150Smarc 					argp=(char *) relstak();
211*35150Smarc 					while(isalnum(c))
212*35150Smarc 					{
213*35150Smarc 						pushstak(c);
214*35150Smarc 						c= readc();
215*35150Smarc 					}
216*35150Smarc 					if(c=='[' && bra)
217*35150Smarc 					{
218*35150Smarc 						if((c=readc(),astchar(c)))
219*35150Smarc 						{
220*35150Smarc 							*id = c;
221*35150Smarc 							if(c=readc()!=']')
222*35150Smarc 								mac_error();
223*35150Smarc 							dolmax = 0;
224*35150Smarc 						}
225*35150Smarc 						else
226*35150Smarc 						{
227*35150Smarc 							int savq = quote;
228*35150Smarc 							pushstak('[');
229*35150Smarc 							unreadc(c);
230*35150Smarc 							quote = 0;
231*35150Smarc 							copyto(']');
232*35150Smarc 							quote = savq;
233*35150Smarc 							pushstak(']');
234*35150Smarc 						}
235*35150Smarc 					}
236*35150Smarc 					else
237*35150Smarc 						unreadc(c);
238*35150Smarc 					zerostak();
239*35150Smarc 					n=lookup(absstak(argp));
240*35150Smarc 					setstak(argp);
241*35150Smarc 					v = valup(n);
242*35150Smarc 					id = n->namid;
243*35150Smarc 					if(dolmax == 0 && attest(n, ARRAY))
244*35150Smarc 					{
245*35150Smarc 						dolg = -((int)(arayp(n)->maxi) + 1);
246*35150Smarc 						while(v==0)
247*35150Smarc 						{
248*35150Smarc 							arayp(n)->adot++;
249*35150Smarc 							if(++dolg == 0)
250*35150Smarc 								break;
251*35150Smarc 							v = valup(n);
252*35150Smarc 						}
253*35150Smarc 					}
254*35150Smarc 					goto cont1;
255*35150Smarc 				}
256*35150Smarc 				if(digchar(c))
257*35150Smarc 				{
258*35150Smarc 					*id = c;
259*35150Smarc 					if(astchar(c))
260*35150Smarc 					{
261*35150Smarc 						dolg=1;
262*35150Smarc 						c=1;
263*35150Smarc 					}
264*35150Smarc 					else
265*35150Smarc 					{
266*35150Smarc 						c -= '0';
267*35150Smarc 						if(bra)
268*35150Smarc 						{
269*35150Smarc 							int d;
270*35150Smarc 							while((d=readc(),isdigit(d)))
271*35150Smarc 								c = 10*c + (d-'0');
272*35150Smarc 							unreadc(d);
273*35150Smarc 						}
274*35150Smarc 					}
275*35150Smarc 					v=((c==0)?cmdadr:(c<=dolc)?dolv[c] : (char *)(dolg=0));
276*35150Smarc 					goto cont1;
277*35150Smarc 	 			}
278*35150Smarc 			nosub:
279*35150Smarc 				if(bra)
280*35150Smarc 					mac_error();
281*35150Smarc 				else
282*35150Smarc 				{
283*35150Smarc 					unreadc(c);
284*35150Smarc 					return(DOLLAR);
285*35150Smarc 				}
286*35150Smarc 			}
287*35150Smarc 	cont1:
288*35150Smarc 		c = readc();
289*35150Smarc 		if(bra==2)
290*35150Smarc 		{
291*35150Smarc 			if(c!=RBRACE)
292*35150Smarc 				mac_error();
293*35150Smarc 			if(dolg==0 && dolmax)
294*35150Smarc #ifdef MULTIBYTE
295*35150Smarc 				c = (v?charlen(v):0);
296*35150Smarc #else
297*35150Smarc 				c = (v?strlen(v):0);
298*35150Smarc #endif /* MULTIBYTE */
299*35150Smarc 			else if(dolg>0)
300*35150Smarc 				c = dolc;
301*35150Smarc 			else if(dolg<0)
302*35150Smarc 				c = arayp(n)->maxi+1;
303*35150Smarc 			else
304*35150Smarc 				c = (v!=0);
305*35150Smarc 			v = itos(c);
306*35150Smarc 			dolg = 0;
307*35150Smarc 			c = RBRACE;
308*35150Smarc 		}
309*35150Smarc 		/* check for quotes @ */
310*35150Smarc 		if(idb[0]=='@' && quote && !atflag)
311*35150Smarc 		{
312*35150Smarc 			quoted--;
313*35150Smarc 			atflag = 1;
314*35150Smarc 		}
315*35150Smarc 		if(c==':' && bra)	/* null and unset fix */
316*35150Smarc 		{
317*35150Smarc 			nulflg=1;
318*35150Smarc 			c=readc();
319*35150Smarc 		}
320*35150Smarc 		else
321*35150Smarc 			nulflg=0;
322*35150Smarc 		if(!defchar(c) && bra)
323*35150Smarc 			mac_error();
324*35150Smarc 		argp = 0;
325*35150Smarc 		if(bra)
326*35150Smarc 		{
327*35150Smarc 			if(c!=RBRACE)
328*35150Smarc 			{
329*35150Smarc 				argp=(char *)relstak();
330*35150Smarc 				if((v==0 || (nulflg && *v==0)) ^ (setchar(c)!=0))
331*35150Smarc 					copyto(RBRACE);
332*35150Smarc 				else
333*35150Smarc 					skipto(RBRACE);
334*35150Smarc 				argp=absstak(argp);
335*35150Smarc 			}
336*35150Smarc 		}
337*35150Smarc 		else
338*35150Smarc 		{
339*35150Smarc 			unreadc(c);
340*35150Smarc 			c=0;
341*35150Smarc 		}
342*35150Smarc 		/* check for substring operations */
343*35150Smarc 		if(c == '#' || c == '%')
344*35150Smarc 		{
345*35150Smarc 			if(dolg != 0)
346*35150Smarc 				mac_error();
347*35150Smarc 			if(v && *v)
348*35150Smarc 			{
349*35150Smarc 				/* allow room for escapes */
350*35150Smarc 				staktop += strlen(v);
351*35150Smarc 				strcpy(staktop,v);
352*35150Smarc 				trim(argp);
353*35150Smarc 				if(*argp==c)
354*35150Smarc 				{
355*35150Smarc 					c |= MARK;
356*35150Smarc 					argp++;
357*35150Smarc 				}
358*35150Smarc 				v = substring(staktop,argp,c);
359*35150Smarc 				if(c&MARK)
360*35150Smarc 					argp--;
361*35150Smarc 			}
362*35150Smarc 			staktop = argp;
363*35150Smarc 		}
364*35150Smarc 		if(v && (!nulflg || *v ) && c!='+')
365*35150Smarc 		{
366*35150Smarc 			while(1)
367*35150Smarc 			{
368*35150Smarc 				BOOL no_ifs = 0;
369*35150Smarc 				int sep = SP;
370*35150Smarc 				argp = valup(IFSNOD);
371*35150Smarc 				if(argp==0 || *argp==0)
372*35150Smarc 					no_ifs++;
373*35150Smarc 				else
374*35150Smarc 					sep = *argp;
375*35150Smarc 				/* quoted null strings have to be marked */
376*35150Smarc 				if(*v==0 && quote)
377*35150Smarc 				{
378*35150Smarc 					pushstak(ESCAPE);
379*35150Smarc 					pushstak(0);
380*35150Smarc 				}
381*35150Smarc 				while(c = *v++)
382*35150Smarc 				{
383*35150Smarc 					if(staktop >= brkend)
384*35150Smarc 						setbrk(BRKINCR);
385*35150Smarc 					if(quote || (c==ESCAPE&&mflag)
386*35150Smarc 						 || (no_ifs&&isspace(c)))
387*35150Smarc 				 		pushstak(ESCAPE);
388*35150Smarc 			 		pushstak(c);
389*35150Smarc 				}
390*35150Smarc 				if(dolg==0 || (++dolg>=dolmax))
391*35150Smarc 					 break;
392*35150Smarc 				if(dolg>0)
393*35150Smarc 					v = dolv[dolg];
394*35150Smarc 				else
395*35150Smarc 				{
396*35150Smarc 					arayp(n)->adot++;
397*35150Smarc 					while((v=valup(n))==0)
398*35150Smarc 					{
399*35150Smarc 						arayp(n)->adot++;
400*35150Smarc 						if(dolg++==0)
401*35150Smarc 						break;
402*35150Smarc 					}
403*35150Smarc 						if(v==0)
404*35150Smarc 					break;
405*35150Smarc 				}
406*35150Smarc 				if(quote && *id=='*')
407*35150Smarc 				{
408*35150Smarc 					if(no_ifs)
409*35150Smarc 						continue;
410*35150Smarc 					pushstak(ESCAPE);
411*35150Smarc 				}
412*35150Smarc 				pushstak(sep);
413*35150Smarc 			}
414*35150Smarc 		}
415*35150Smarc 		else if(argp)
416*35150Smarc 		{
417*35150Smarc 			if(c=='?')
418*35150Smarc 			{
419*35150Smarc 				if(mac_try)
420*35150Smarc 					mac_error();
421*35150Smarc 				else
422*35150Smarc 				{
423*35150Smarc 					trim(argp);
424*35150Smarc 					failed(id,*argp?argp:badparam);
425*35150Smarc 				}
426*35150Smarc 			}
427*35150Smarc 			else if(c=='=')
428*35150Smarc 			{
429*35150Smarc 				if(n)
430*35150Smarc 				{
431*35150Smarc 					trim(argp);
432*35150Smarc 					assign(n,argp);
433*35150Smarc 					staktop = movstr(valup(n),argp);
434*35150Smarc 				}
435*35150Smarc 				else
436*35150Smarc 					mac_error();
437*35150Smarc 			}
438*35150Smarc 		}
439*35150Smarc 		else if(is_option(NOSET))
440*35150Smarc 		{
441*35150Smarc 			if(mac_try)
442*35150Smarc 				mac_error();
443*35150Smarc 			else
444*35150Smarc 				failed(id,unset);
445*35150Smarc 		}
446*35150Smarc 		goto retry;
447*35150Smarc 	}
448*35150Smarc 	else if(c==endch)
449*35150Smarc 		return(c);
450*35150Smarc 	else if(c==SQUOTE && mac_try==0)
451*35150Smarc 	{
452*35150Smarc 		comsubst(0);
453*35150Smarc 		goto retry;
454*35150Smarc 	}
455*35150Smarc 	else if(c==DQUOTE)
456*35150Smarc 	{
457*35150Smarc 		if(quote ==0)
458*35150Smarc 		{
459*35150Smarc 			atflag = 0;
460*35150Smarc 			quoted++;
461*35150Smarc 		}
462*35150Smarc 		quote ^= 1;
463*35150Smarc 		goto retry;
464*35150Smarc 	}
465*35150Smarc 	return(c);
466*35150Smarc }
467*35150Smarc 
468*35150Smarc 	/* Strip "" and do $ substitution
469*35150Smarc 	 * Leaves result on top of stack
470*35150Smarc 	 */
macro(as)471*35150Smarc char *macro(as)
472*35150Smarc char *as;
473*35150Smarc {
474*35150Smarc 	register BOOL	savqu =quoted;
475*35150Smarc 	register char	savq = quote;
476*35150Smarc 	FILE	fblk;
477*35150Smarc 	FILEBLK	cb;
478*35150Smarc 	mflag = 1;
479*35150Smarc 	push(&cb);
480*35150Smarc 	estabf(as,&fblk);
481*35150Smarc 	usestak();
482*35150Smarc 	quote=0;
483*35150Smarc 	quoted=0;
484*35150Smarc 	copyto(0);
485*35150Smarc 	pop(1);
486*35150Smarc 	if(quoted && (stakbot == staktop))
487*35150Smarc 	{
488*35150Smarc 		pushstak(ESCAPE);
489*35150Smarc 		pushstak(0);
490*35150Smarc 	}
491*35150Smarc 	/* above is the fix for *'.c' bug	*/
492*35150Smarc 	quote=savq;
493*35150Smarc 	quoted=savqu;
494*35150Smarc 	return(fixstak());
495*35150Smarc }
496*35150Smarc 
497*35150Smarc /*
498*35150Smarc  * command substitution
499*35150Smarc  * type==0 for ``
500*35150Smarc  * type==1 for $()
501*35150Smarc */
502*35150Smarc 
comsubst(type)503*35150Smarc static void comsubst(type)
504*35150Smarc int type;
505*35150Smarc {
506*35150Smarc 	FILEBLK	cb;
507*35150Smarc 	register FILE	*fd;
508*35150Smarc 	FILE 	*pv[2];
509*35150Smarc 	FILE	fblk;
510*35150Smarc 	char tmp_fname[TMPSIZ];
511*35150Smarc 	register unsigned int	d;
512*35150Smarc 	register TREPTR t;
513*35150Smarc 	register char *argc;
514*35150Smarc 	IOPTR saviotemp = iotemp;
515*35150Smarc 	int forkflag = FPOU|FCOMSUB;
516*35150Smarc 	STKPTR savtop = staktop;
517*35150Smarc 	STKPTR savptr = fixstak();
518*35150Smarc 	char inbuff[BUFSIZ];
519*35150Smarc 	int saveflag = states&FIXFLG;
520*35150Smarc 	register int waitflag = 0;
521*35150Smarc 	if(w_fd)
522*35150Smarc 		fflush(w_fd);	/* flush before executing command */
523*35150Smarc 	usestak();
524*35150Smarc 	if(type)
525*35150Smarc 	{
526*35150Smarc 		staktop = (STKPTR)(match_paren((char*)stakbot,LPAREN,RPAREN,0)-1);
527*35150Smarc 	}
528*35150Smarc 	else
529*35150Smarc 	{
530*35150Smarc 		while((d=readc())!=SQUOTE && d)
531*35150Smarc 		{
532*35150Smarc 			if(d==ESCAPE)
533*35150Smarc 			{
534*35150Smarc 				d = readc();
535*35150Smarc 				/*
536*35150Smarc 				 * This is wrong but it preserves compatibility with
537*35150Smarc 				 * the SVR2 shell
538*35150Smarc 				 */
539*35150Smarc 				if(!(escchar(d) || (d=='"' && quote)))
540*35150Smarc 					pushstak(ESCAPE);
541*35150Smarc 			}
542*35150Smarc 			pushstak(d);
543*35150Smarc 		}
544*35150Smarc 	}
545*35150Smarc 	argc=fixstak();
546*35150Smarc 	states &= ~FIXFLG;		/* do not save command subs in fc file */
547*35150Smarc 	push(&cb);
548*35150Smarc 	estabf(argc,&fblk);
549*35150Smarc 	subflag = 0;
550*35150Smarc 	exec_flag++;
551*35150Smarc 	t = cmd(EOFSYM,MTFLG|NLFLG);
552*35150Smarc 	exec_flag--;
553*35150Smarc 	d = t->tretyp;
554*35150Smarc 	if(!subflag && !t->treio && (d&COMMSK)==TCOM && blt_no(d)>SYSSPECIAL)
555*35150Smarc 	{
556*35150Smarc 		/* nested command subs not handled specially */
557*35150Smarc 		/* handle command substitution of most builtins separately */
558*35150Smarc 		/* exec, login, cd, ., eval and shift not handled this way */
559*35150Smarc 		/* put output into tmpfile */
560*35150Smarc 		FILE *save1_out = standout;
561*35150Smarc 		if((states&IS_TMP)==0)
562*35150Smarc 		{
563*35150Smarc 			/* create and keep open a /tmp file for command subs */
564*35150Smarc 			fd = tmp_open(tmp_fname);
565*35150Smarc 			fd = frenumber(fd,TMPIO);
566*35150Smarc 			states |= IS_TMP;
567*35150Smarc 			/* root cannot unlink because fsck could give bad ref count */
568*35150Smarc 			if(userid)
569*35150Smarc 				unlink(tmp_fname);
570*35150Smarc 			else
571*35150Smarc 				states |= RM_TMP;
572*35150Smarc 		}
573*35150Smarc 		else
574*35150Smarc 			fd = file_fd(TMPIO);
575*35150Smarc 		standout = fd;
576*35150Smarc 		/* this will only flush the buffer if output is fd already */
577*35150Smarc 		p_setout(fd);
578*35150Smarc #ifdef JOBS
579*35150Smarc 		states |= NONSTOP;
580*35150Smarc #endif	/* JOBS */
581*35150Smarc 		putc(0,fd);
582*35150Smarc 		exfunct(t,(char**)0,states&ERRFLG);
583*35150Smarc 		putc(0,fd);
584*35150Smarc #ifdef JOBS
585*35150Smarc 		states &= ~NONSTOP;
586*35150Smarc #endif	/* JOBS */
587*35150Smarc 		if(*_sobuf != 0)
588*35150Smarc 		{
589*35150Smarc 			/* file is larger than buffer, read from it */
590*35150Smarc 			fflush(fd);
591*35150Smarc 			fseek(fd,1L,0);
592*35150Smarc 			initf(fd);
593*35150Smarc 			waitflag = -1;
594*35150Smarc 		}
595*35150Smarc 		else
596*35150Smarc 		{
597*35150Smarc 			/* The file is all in the buffer */
598*35150Smarc 			setbuf(fd,NIL);
599*35150Smarc 			strcpy(inbuff,(char*)_sobuf+1);
600*35150Smarc 			setbuf(fd,(char*)_sobuf);
601*35150Smarc 			estabf(inbuff,(fd= &fblk));
602*35150Smarc 		}
603*35150Smarc 		standout = save1_out;
604*35150Smarc 		goto readit;
605*35150Smarc 	}
606*35150Smarc 	else if(d==0 && ((COMPTR)t)->comarg==0)
607*35150Smarc 	{
608*35150Smarc 		if(((t->treio)->iofile) == 0)
609*35150Smarc 			argc = mactrim((t->treio)->ioname,1);
610*35150Smarc 		else
611*35150Smarc 			argc = devnull;
612*35150Smarc 		fd = chkopen(argc);
613*35150Smarc 	}
614*35150Smarc 	else
615*35150Smarc 	{
616*35150Smarc 		waitflag++;
617*35150Smarc 		if(iotemp!=saviotemp)
618*35150Smarc 			forkflag |= FTMP;
619*35150Smarc 		t = makefork(forkflag,t);
620*35150Smarc 		  /* this is done like this so that the pipe
621*35150Smarc 		   * is open only when needed
622*35150Smarc 		   */
623*35150Smarc 		chkpipe(pv);
624*35150Smarc #ifdef JOBS
625*35150Smarc 		jobstat.cur_pgrp = jobstat.mypid;
626*35150Smarc 		jobstat.j_flag++;
627*35150Smarc #endif	/* JOBS */
628*35150Smarc 		execute(t, states&ERRFLG, (FILE**)0, pv);
629*35150Smarc #ifdef JOBS
630*35150Smarc 		jobstat.j_flag = 0;
631*35150Smarc #endif	/* JOBS */
632*35150Smarc 		fd = pv[INPIPE];
633*35150Smarc 		fclose(pv[OTPIPE]);
634*35150Smarc 	}
635*35150Smarc 	setbuf(fd,inbuff);
636*35150Smarc 	initf(fd);
637*35150Smarc 
638*35150Smarc readit:
639*35150Smarc 	tdystak(savptr);
640*35150Smarc 	d = savtop - savptr;
641*35150Smarc 	while(d--)
642*35150Smarc 		*staktop++ = *savptr++;
643*35150Smarc 	while(d=readc())
644*35150Smarc 	{
645*35150Smarc 		if(quote || (d==ESCAPE&&mflag))
646*35150Smarc 			pushstak(ESCAPE);
647*35150Smarc 		pushstak(d);
648*35150Smarc 	}
649*35150Smarc 	if(waitflag>0)
650*35150Smarc 		await(parent,0);
651*35150Smarc 	while(stakbot!=staktop)
652*35150Smarc 	{
653*35150Smarc 		if(*--staktop != NL)
654*35150Smarc 		{
655*35150Smarc 			*++staktop;
656*35150Smarc 			break;
657*35150Smarc 		}
658*35150Smarc 		else if(quote)
659*35150Smarc 			staktop--;
660*35150Smarc 	}
661*35150Smarc 	pop(waitflag>=0?0:1);
662*35150Smarc 	states |= saveflag;
663*35150Smarc }
664*35150Smarc 
665*35150Smarc 
mac_subst(in,ot)666*35150Smarc void mac_subst(in,ot)
667*35150Smarc FILE 	*in;
668*35150Smarc register FILE *ot;
669*35150Smarc {
670*35150Smarc 	register char	c;
671*35150Smarc 	register flag = is_option(EXECPR);
672*35150Smarc 	FILEBLK 	fb;
673*35150Smarc 	char inbuff[BUFSIZ];
674*35150Smarc 	char otbuff[BUFSIZ];
675*35150Smarc 	mflag = 0;
676*35150Smarc 	w_fd = ot;
677*35150Smarc 	push(&fb);
678*35150Smarc 	initf(in);
679*35150Smarc 	/* DQUOTE used to stop it from quoting */
680*35150Smarc 	setbuf(in,inbuff);
681*35150Smarc 	setbuf(ot,otbuff);
682*35150Smarc 	if(flag)
683*35150Smarc 		p_setout(stderr);
684*35150Smarc 	usestak();
685*35150Smarc 	while(1)
686*35150Smarc 	{
687*35150Smarc 		c=getch(DQUOTE);
688*35150Smarc 		if(c==ESCAPE)
689*35150Smarc 		{
690*35150Smarc 			c = readc();
691*35150Smarc 			if(!escchar(c))
692*35150Smarc 				pushstak(ESCAPE);
693*35150Smarc 		}
694*35150Smarc 		if(staktop!=stakbot)
695*35150Smarc 		{
696*35150Smarc 			*staktop = 0;
697*35150Smarc 			fputs(stakbot,ot);
698*35150Smarc 			if(flag)
699*35150Smarc 				fputs(stakbot,output);
700*35150Smarc 			staktop = stakbot;
701*35150Smarc 		}
702*35150Smarc 		if(c==0)
703*35150Smarc 			break;
704*35150Smarc 		putc(c,ot);
705*35150Smarc 		if(flag)
706*35150Smarc 			putc(c,output);
707*35150Smarc 	}
708*35150Smarc 	pop(0);
709*35150Smarc 	w_fd = NULL;
710*35150Smarc 	fflush(ot);
711*35150Smarc 	fseek(ot,0L,0);
712*35150Smarc 	setbuf(ot,NIL);
713*35150Smarc }
714*35150Smarc 
715*35150Smarc 
716*35150Smarc 
717*35150Smarc /*
718*35150Smarc  * Computes the substring of STRING using the expression PAT
719*35150Smarc  * depending on which FLAG is set.
720*35150Smarc  */
721*35150Smarc 
substring(string,pat,flag)722*35150Smarc static char *substring(string,pat,flag)
723*35150Smarc char *string;
724*35150Smarc char *pat;
725*35150Smarc int flag;
726*35150Smarc {
727*35150Smarc 	register char *sp = string;
728*35150Smarc 	register char *cp;
729*35150Smarc 	switch(flag)
730*35150Smarc 	{
731*35150Smarc 		case '#':
732*35150Smarc 		case MARK|'#':
733*35150Smarc 		{
734*35150Smarc 			register int c;
735*35150Smarc 			cp = sp;
736*35150Smarc 			do
737*35150Smarc 			{
738*35150Smarc #ifdef MULTIBYTE
739*35150Smarc 				c = *sp;
740*35150Smarc 				c = echarset(c);
741*35150Smarc 				sp += (in_csize(c)+(c>=2));
742*35150Smarc 				c = *sp;
743*35150Smarc #else
744*35150Smarc 				c= *++sp;
745*35150Smarc #endif /* MULTIBYTE */
746*35150Smarc 				*sp=0;
747*35150Smarc 				if(gmatch(string,pat))
748*35150Smarc 				{
749*35150Smarc 					cp = sp;
750*35150Smarc 					if(flag=='#')
751*35150Smarc 						break;
752*35150Smarc 				}
753*35150Smarc 				*sp = c;
754*35150Smarc 			}
755*35150Smarc 			while(c);
756*35150Smarc 			*sp = c;
757*35150Smarc 			return(cp);
758*35150Smarc 		}
759*35150Smarc 
760*35150Smarc 		case '%':
761*35150Smarc 		case MARK|'%':
762*35150Smarc 		{
763*35150Smarc 			sp += strlen(sp);
764*35150Smarc 			cp = sp;
765*35150Smarc 			while(sp>=string)
766*35150Smarc 			{
767*35150Smarc 				if(gmatch(sp,pat))
768*35150Smarc 				{
769*35150Smarc 					cp = sp;
770*35150Smarc 					if(flag=='%')
771*35150Smarc 						break;
772*35150Smarc 				}
773*35150Smarc 				sp--;
774*35150Smarc #ifdef MULTIBYTE
775*35150Smarc 				if(*sp&HIGHBIT)
776*35150Smarc 				{
777*35150Smarc 					if(*(sp-in_csize(3))==ESS3)
778*35150Smarc 						sp -= in_csize(3);
779*35150Smarc 					else if(*(sp-in_csize(2))==ESS2)
780*35150Smarc 						sp -= in_csize(2);
781*35150Smarc 					else
782*35150Smarc 						sp -= (in_csize(1)-1);
783*35150Smarc 				}
784*35150Smarc #endif /* MULTIBYTE */
785*35150Smarc 			}
786*35150Smarc 			*cp = 0;
787*35150Smarc 			return(string);
788*35150Smarc 		}
789*35150Smarc 	}
790*35150Smarc 	return(sp);
791*35150Smarc }
792*35150Smarc 
793*35150Smarc 
794*35150Smarc /*
795*35150Smarc  * do parameter and command substitution and strip of quotes
796*35150Smarc  * attempt file name expansion if <type> not zero
797*35150Smarc  */
798*35150Smarc 
mactrim(s,type)799*35150Smarc char *mactrim(s,type)
800*35150Smarc char *	s;
801*35150Smarc {
802*35150Smarc 	register char *t=macro(s);
803*35150Smarc 	ARGPTR schain = gchain;
804*35150Smarc 	if(type && f_complete(t,nullstr)==1)
805*35150Smarc 		t = gchain->argval;
806*35150Smarc 	gchain = schain;
807*35150Smarc 	trim(t);
808*35150Smarc 	return(t);
809*35150Smarc }
810*35150Smarc 
811*35150Smarc /*
812*35150Smarc  * perform only parameter substitution and catch failures
813*35150Smarc  */
814*35150Smarc 
mactry(s)815*35150Smarc char *mactry(s)
816*35150Smarc register char *s;
817*35150Smarc {
818*35150Smarc 	mac_try++;
819*35150Smarc 	if(setjmp(mac_buf)==0)
820*35150Smarc 		s = mactrim(s,0);
821*35150Smarc 	mac_try = 0;
822*35150Smarc 	return(s);
823*35150Smarc }
824*35150Smarc 
mac_error()825*35150Smarc static void mac_error()
826*35150Smarc {
827*35150Smarc 	if(mac_try)
828*35150Smarc 		longjmp(mac_buf,1);
829*35150Smarc 	error(badsub);
830*35150Smarc }
831*35150Smarc 
832*35150Smarc 
833*35150Smarc 
834*35150Smarc #ifdef MULTIBYTE
charlen(str)835*35150Smarc static int	charlen(str)
836*35150Smarc register char *str;
837*35150Smarc {
838*35150Smarc 	register int n = 0;
839*35150Smarc 	register int c;
840*35150Smarc 	while(*str)
841*35150Smarc 	{
842*35150Smarc 		c = echarset(*str);		/* find character set */
843*35150Smarc 		str += (in_csize(c)+(c>=2));	/* move to next char */
844*35150Smarc 		n += out_csize(c);		/* add character size */
845*35150Smarc 	}
846*35150Smarc 	return(n);
847*35150Smarc }
848*35150Smarc #endif /* MULTIBYTE */
849