Start development on BSD 2
[unix-history] / .ref-BSD-1 / ashell / sh_parse.c
CommitLineData
1a5078b8
BJ
1#include "sh.h"
2
3/*
4 * syntax
5 * empty
6 * syn0
7 */
8syntax(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 */
25syn0(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 */
73syn1(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 */
108syn2(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 */
150syn3(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
278freesyn(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]);
292lr:
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}