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