BSD 4_4 release
[unix-history] / usr / src / old / sh / macro.c
CommitLineData
f6227721 1#ifndef lint
ca67e7b4 2static char sccsid[] = "@(#)macro.c 4.4 4/24/88";
f6227721 3#endif
121105ee
KM
4
5#
6/*
7 * UNIX shell
8 *
9 * S. R. Bourne
10 * Bell Telephone Laboratories
11 *
12 */
13
14#include "defs.h"
15#include "sym.h"
16
17LOCAL CHAR quote; /* used locally */
18LOCAL CHAR quoted; /* used locally */
19
20
21
22LOCAL STRING copyto(endch)
23 REG CHAR endch;
24{
25 REG CHAR c;
26
27 WHILE (c=getch(endch))!=endch ANDF c
28 DO pushstak(c|quote) OD
29 zerostak();
30 IF c!=endch THEN error(badsub) FI
31}
32
33LOCAL skipto(endch)
34 REG CHAR endch;
35{
36 /* skip chars up to } */
37 REG CHAR c;
38 WHILE (c=readc()) ANDF c!=endch
39 DO SWITCH c IN
40
41 case SQUOTE: skipto(SQUOTE); break;
42
43 case DQUOTE: skipto(DQUOTE); break;
44
45 case DOLLAR: IF readc()==BRACE
46 THEN skipto('}');
47 FI
48 ENDSW
49 OD
50 IF c!=endch THEN error(badsub) FI
51}
52
53LOCAL getch(endch)
54 CHAR endch;
55{
56 REG CHAR d;
57
58retry:
59 d=readc();
60 IF !subchar(d)
61 THEN return(d);
62 FI
63 IF d==DOLLAR
64 THEN REG INT c;
65 IF (c=readc(), dolchar(c))
66 THEN NAMPTR n=NIL;
67 INT dolg=0;
68 BOOL bra;
69 REG STRING argp, v;
70 CHAR idb[2];
71 STRING id=idb;
72
73 IF bra=(c==BRACE) THEN c=readc() FI
74 IF letter(c)
75 THEN argp=relstak();
76 WHILE alphanum(c) DO pushstak(c); c=readc() OD
77 zerostak();
78 n=lookup(absstak(argp)); setstak(argp);
79 v = n->namval; id = n->namid;
80 peekc = c|MARK;;
81 ELIF digchar(c)
82 THEN *id=c; idb[1]=0;
83 IF astchar(c)
84 THEN dolg=1; c='1';
85 FI
86 c -= '0';
3cc4dafe 87 v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (STRING)(dolg=0));
121105ee
KM
88 ELIF c=='$'
89 THEN v=pidadr;
90 ELIF c=='!'
91 THEN v=pcsadr;
92 ELIF c=='#'
93 THEN v=dolladr;
94 ELIF c=='?'
95 THEN v=exitadr;
96 ELIF c=='-'
97 THEN v=flagadr;
98 ELIF bra THEN error(badsub);
99 ELSE goto retry;
100 FI
101 c = readc();
102 IF !defchar(c) ANDF bra
103 THEN error(badsub);
104 FI
105 argp=0;
106 IF bra
107 THEN IF c!='}'
108 THEN argp=relstak();
109 IF (v==0)NEQ(setchar(c))
110 THEN copyto('}');
111 ELSE skipto('}');
112 FI
113 argp=absstak(argp);
114 FI
115 ELSE peekc = c|MARK; c = 0;
116 FI
117 IF v
118 THEN IF c!='+'
119 THEN LOOP WHILE c = *v++
120 DO pushstak(c|quote); OD
121 IF dolg==0 ORF (++dolg>dolc)
122 THEN break;
123 ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0));
124 FI
125 POOL
126 FI
127 ELIF argp
128 THEN IF c=='?'
129 THEN failed(id,*argp?argp:badparam);
130 ELIF c=='='
131 THEN IF n
132 THEN assign(n,argp);
133 ELSE error(badsub);
134 FI
135 FI
136 ELIF flags&setflg
137 THEN failed(id,badparam);
138 FI
139 goto retry;
140 ELSE peekc=c|MARK;
141 FI
142 ELIF d==endch
143 THEN return(d);
144 ELIF d==SQUOTE
145 THEN comsubst(); goto retry;
146 ELIF d==DQUOTE
147 THEN quoted++; quote^=QUOTE; goto retry;
148 FI
149 return(d);
150}
151
152STRING macro(as)
153 STRING as;
154{
155 /* Strip "" and do $ substitution
156 * Leaves result on top of stack
157 */
158 REG BOOL savqu =quoted;
159 REG CHAR savq = quote;
160 FILEHDR fb;
161
162 push(&fb); estabf(as);
163 usestak();
164 quote=0; quoted=0;
165 copyto(0);
166 pop();
167 IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI
168 quote=savq; quoted=savqu;
169 return(fixstak());
170}
171
172LOCAL comsubst()
173{
174 /* command substn */
175 FILEBLK cb;
176 REG CHAR d;
177 REG STKPTR savptr = fixstak();
178
179 usestak();
180 WHILE (d=readc())!=SQUOTE ANDF d
181 DO pushstak(d) OD
182
183 BEGIN
184 REG STRING argc;
185 trim(argc=fixstak());
186 push(&cb); estabf(argc);
187 END
188 BEGIN
189 REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG));
190 INT pv[2];
191
192 /* this is done like this so that the pipe
193 * is open only when needed
194 */
195 chkpipe(pv);
196 initf(pv[INPIPE]);
197 execute(t, 0, 0, pv);
198 close(pv[OTPIPE]);
199 END
200 tdystak(savptr); staktop=movstr(savptr,stakbot);
eb594574 201 WHILE d=readc() DO locstak(); pushstak(d|quote) OD
121105ee
KM
202 await(0);
203 WHILE stakbot!=staktop
204 DO IF (*--staktop&STRIP)!=NL
205 THEN ++staktop; break;
206 FI
207 OD
208 pop();
209}
210
211#define CPYSIZ 512
212
213subst(in,ot)
214 INT in, ot;
215{
216 REG CHAR c;
217 FILEBLK fb;
218 REG INT count=CPYSIZ;
219
220 push(&fb); initf(in);
221 /* DQUOTE used to stop it from quoting */
222 WHILE c=(getch(DQUOTE)&STRIP)
223 DO pushstak(c);
224 IF --count == 0
225 THEN flush(ot); count=CPYSIZ;
226 FI
227 OD
228 flush(ot);
229 pop();
230}
231
232LOCAL flush(ot)
233{
234 write(ot,stakbot,staktop-stakbot);
235 IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI
236 staktop=stakbot;
237}