Commit | Line | Data |
---|---|---|
aaa7ced1 BJ |
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 | ||
13 | LOCAL CHAR quote; /* used locally */ | |
14 | LOCAL CHAR quoted; /* used locally */ | |
15 | ||
16 | ||
17 | ||
18 | LOCAL 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 | ||
29 | LOCAL 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 | ||
49 | LOCAL getch(endch) | |
50 | CHAR endch; | |
51 | { | |
52 | REG CHAR d; | |
53 | ||
54 | retry: | |
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 | ||
148 | STRING 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 | ||
168 | LOCAL 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 | ||
209 | subst(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 | ||
228 | LOCAL flush(ot) | |
229 | { | |
230 | write(ot,stakbot,staktop-stakbot); | |
231 | IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI | |
232 | staktop=stakbot; | |
233 | } |