Commit | Line | Data |
---|---|---|
1a5078b8 BJ |
1 | #include "sh.h" |
2 | ||
3 | /* | |
4 | * syntax | |
5 | * empty | |
6 | * syn0 | |
7 | */ | |
8 | syntax(p1, p2) | |
9 | register struct shvar2 *p1, *p2; | |
10 | { | |
11 | ||
12 | while (p1 != p2) | |
13 | if (any(p1->value[0], ";&\n")) | |
14 | p1 = p1->next; | |
15 | else | |
16 | return (syn0(p1, p2)); | |
17 | return (0); | |
18 | } | |
19 | ||
20 | /* | |
21 | * syn0 | |
22 | * syn1 | |
23 | * syn1 & syntax | |
24 | */ | |
25 | syn0(p1, p2) | |
26 | struct shvar2 *p1, *p2; | |
27 | { | |
28 | register struct shvar2 *p; | |
29 | register *t, *t1; | |
30 | int l; | |
31 | ||
32 | l = 0; | |
33 | for (p = p1; p != p2; p = p->next) | |
34 | switch (p->value[0]) { | |
35 | case '(': | |
36 | l++; | |
37 | continue; | |
38 | case ')': | |
39 | l--; | |
40 | if (l < 0) | |
41 | seterr("Too many )'s"); | |
42 | continue; | |
43 | case '&': | |
44 | if (l != 0) | |
45 | break; | |
46 | t1 = syn1(p1, p); | |
47 | if (t1[DTYP] == TLST) { | |
48 | t = calloc(2, 5); | |
49 | t[DTYP] = TPAR; | |
50 | t[DFLG] = FAND|FPRS|FINT; | |
51 | t[DSPR] = t1; | |
52 | t1 = t; | |
53 | } else | |
54 | t1[DFLG] =| FAND|FPRS|FINT; | |
55 | t = calloc(2, 4); | |
56 | t[DTYP] = TLST; | |
57 | t[DFLG] = 0; | |
58 | t[DLEF] = t1; | |
59 | t[DRIT] = syntax(p, p2); | |
60 | return(t); | |
61 | } | |
62 | if (l == 0) | |
63 | return (syn1(p1, p2)); | |
64 | seterr("Too many ('s"); | |
65 | return(0); | |
66 | } | |
67 | ||
68 | /* | |
69 | * syn1 | |
70 | * syn2 | |
71 | * syn2 ; syn1 | |
72 | */ | |
73 | syn1(p1, p2) | |
74 | struct shvar2 *p1, *p2; | |
75 | { | |
76 | register struct shvar *p; | |
77 | register *t; | |
78 | int l; | |
79 | ||
80 | l = 0; | |
81 | for (p = p1; p != p2; p = p->next) | |
82 | switch (p->value[0]) { | |
83 | case '(': | |
84 | l++; | |
85 | continue; | |
86 | case ')': | |
87 | l--; | |
88 | continue; | |
89 | case ';': | |
90 | case '\n': | |
91 | if (l != 0) | |
92 | break; | |
93 | t = calloc(2, 4); | |
94 | t[DTYP] = TLST; | |
95 | t[DLEF] = syn2(p1, p); | |
96 | t[DRIT] = syntax(p->next, p2); | |
97 | return (t); | |
98 | } | |
99 | return (syn2(p1, p2)); | |
100 | } | |
101 | ||
102 | /* | |
103 | * syn2 | |
104 | * syn3 | |
105 | * syn3 | syn2 | |
106 | * syn3 |* syn2 | |
107 | */ | |
108 | syn2(p1, p2) | |
109 | struct shvar2 *p1, *p2; | |
110 | { | |
111 | register struct shvar2 *p, *pn; | |
112 | register int *t; | |
113 | int l; | |
114 | ||
115 | l = 0; | |
116 | for (p = p1; p != p2; p = p->next) | |
117 | switch (p->value[0]) { | |
118 | case '(': | |
119 | l++; | |
120 | continue; | |
121 | case ')': | |
122 | l--; | |
123 | continue; | |
124 | case '|': | |
125 | case '^': | |
126 | if (l != 0) | |
127 | continue; | |
128 | t = calloc(2, 4); | |
129 | t[DTYP] = TFIL; | |
130 | t[DLEF] = syn3(p1, p); | |
131 | pn = p->next; | |
132 | if (pn != p2 && pn->value[0] == '*') { | |
133 | t[DFLG] = FDIAG; | |
134 | if (pn->value[1] != 0) | |
135 | pn->value++; | |
136 | else | |
137 | p = pn; | |
138 | } | |
139 | t[DRIT] = syn2(p->next, p2); | |
140 | return (t); | |
141 | } | |
142 | return (syn3(p1, p2)); | |
143 | } | |
144 | ||
145 | /* | |
146 | * syn3 | |
147 | * ( syn0 ) [ < in ] [ > out ] | |
148 | * word word* [ < in ] [ > out ] | |
149 | */ | |
150 | syn3(p1, p2) | |
151 | struct shvar2 *p1, *p2; | |
152 | { | |
153 | register struct shvar2 *p; | |
154 | struct shvar *lp, *rp; | |
155 | register int *t; | |
156 | int n, l, c; | |
157 | ||
158 | n = 0; | |
159 | l = 0; | |
160 | for (p = p1; p != p2; p = p->next) | |
161 | switch (p->value[0]) { | |
162 | case '(': | |
163 | l++; | |
164 | continue; | |
165 | case ')': | |
166 | l--; | |
167 | continue; | |
168 | case '>': | |
169 | case '<': | |
170 | if (l != 0) | |
171 | continue; | |
172 | if (p->next == p2) | |
173 | continue; | |
174 | if (any(p->next->value[0], "<>(*")) | |
175 | continue; | |
176 | n--; | |
177 | continue; | |
178 | default: | |
179 | if (l != 0) | |
180 | continue; | |
181 | n++; | |
182 | continue; | |
183 | } | |
184 | if (n < 0) | |
185 | n = 0; | |
186 | t = calloc(2, 5 + n + 1); | |
187 | n = 0; | |
188 | if (p2->value[0] == ')') | |
189 | t[DFLG] = FPAR; | |
190 | lp = 0; | |
191 | rp = 0; | |
192 | l = 0; | |
193 | for (p = p1; p != p2; p = p->next) { | |
194 | c = p->value[0]; | |
195 | switch (c) { | |
196 | case '(': | |
197 | if (l == 0) { | |
198 | if (lp != 0) | |
199 | seterr("Badly placed ("); | |
200 | lp = p->next; | |
201 | } | |
202 | l++; | |
203 | continue; | |
204 | case ')': | |
205 | l--; | |
206 | if (l == 0) | |
207 | rp = p; | |
208 | continue; | |
209 | case '>': | |
210 | if (l != 0) | |
211 | continue; | |
212 | if (p->next != p2) { | |
213 | p = p->next; | |
214 | if (p->value[0] == '>') | |
215 | t[DFLG] =| FCAT; | |
216 | else | |
217 | p = p->prev; | |
218 | } | |
219 | if (p->next != p2) { | |
220 | p = p->next; | |
221 | if (p->value[0] == '*') { | |
222 | t[DFLG] =| FDIAG; | |
223 | if (p->value[1]) { | |
224 | p->value++; | |
225 | p = p->prev; | |
226 | } | |
227 | } else | |
228 | p = p->prev; | |
229 | } | |
230 | case '<': | |
231 | if (l != 0) | |
232 | continue; | |
233 | if (p->next == p2) { | |
234 | seterr("Missing file for redirect"); | |
235 | continue; | |
236 | } | |
237 | p = p->next; | |
238 | if (any(p->value[0], "<>(")) { | |
239 | seterr("Syntax error in redirection"); | |
240 | continue; | |
241 | } | |
242 | if (c == '<') { | |
243 | if (t[DLEF] != 0) { | |
244 | seterr("Multiple < redirect"); | |
245 | continue; | |
246 | } | |
247 | t[DLEF] = p->value; | |
248 | continue; | |
249 | } | |
250 | if (t[DRIT] != 0) { | |
251 | seterr("Multiple output redirect"); | |
252 | continue; | |
253 | } | |
254 | t[DRIT] = p->value; | |
255 | continue; | |
256 | default: | |
257 | if (l != 0) | |
258 | continue; | |
259 | t[DCOM + n] = p->value; | |
260 | n++; | |
261 | continue; | |
262 | } | |
263 | } | |
264 | if (lp != 0) { | |
265 | if (n != 0) | |
266 | seterr("Only redirect allowed outside ()'s"); | |
267 | t[DTYP] = TPAR; | |
268 | t[DSPR] = syn0(lp, rp); | |
269 | } else { | |
270 | if (n == 0) | |
271 | seterr("Inappropriate empty command"); | |
272 | t[DCOM + n] = 0; | |
273 | t[DTYP] = TCOM; | |
274 | } | |
275 | return (t); | |
276 | } | |
277 | ||
278 | freesyn(t) | |
279 | register int *t; | |
280 | { | |
281 | register char **v; | |
282 | ||
283 | if (t == 0) | |
284 | return; | |
285 | switch (t[DTYP]) { | |
286 | case TCOM: | |
287 | for (v = &t[DCOM]; *v; v++) | |
288 | xfree(*v); | |
289 | goto lr; | |
290 | case TPAR: | |
291 | freesyn(t[DSPR]); | |
292 | lr: | |
293 | xfree(t[DLEF]); | |
294 | xfree(t[DRIT]); | |
295 | break; | |
296 | case TFIL: | |
297 | case TLST: | |
298 | freesyn(t[DLEF]); | |
299 | freesyn(t[DRIT]); | |
300 | break; | |
301 | } | |
302 | cfree(t); | |
303 | } |