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