1*d95322bbSmartijn /* $OpenBSD: parse.c,v 1.15 2018/10/24 06:01:03 martijn Exp $ */
2df930be7Sderaadt /* $NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $ */
3df930be7Sderaadt
4df930be7Sderaadt /*-
5df930be7Sderaadt * Copyright (c) 1980, 1991, 1993
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt * modification, are permitted provided that the following conditions
10df930be7Sderaadt * are met:
11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt * documentation and/or other materials provided with the distribution.
1629295d1cSmillert * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt * may be used to endorse or promote products derived from this software
18df930be7Sderaadt * without specific prior written permission.
19df930be7Sderaadt *
20df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt * SUCH DAMAGE.
31df930be7Sderaadt */
32df930be7Sderaadt
33df930be7Sderaadt #include <sys/types.h>
34df930be7Sderaadt #include <stdlib.h>
35df930be7Sderaadt #include <string.h>
36df930be7Sderaadt #include <stdarg.h>
37df930be7Sderaadt
38df930be7Sderaadt #include "csh.h"
39df930be7Sderaadt #include "extern.h"
40df930be7Sderaadt
41c72b5b24Smillert static void asyntax(struct wordent *, struct wordent *);
42c72b5b24Smillert static void asyn0(struct wordent *, struct wordent *);
43c72b5b24Smillert static void asyn3(struct wordent *, struct wordent *);
44df930be7Sderaadt static struct wordent
45c72b5b24Smillert *freenod(struct wordent *, struct wordent *);
46df930be7Sderaadt static struct command
47c72b5b24Smillert *syn0(struct wordent *, struct wordent *, int);
48df930be7Sderaadt static struct command
49c72b5b24Smillert *syn1(struct wordent *, struct wordent *, int);
50df930be7Sderaadt static struct command
51c72b5b24Smillert *syn1a(struct wordent *, struct wordent *, int);
52df930be7Sderaadt static struct command
53c72b5b24Smillert *syn1b(struct wordent *, struct wordent *, int);
54df930be7Sderaadt static struct command
55c72b5b24Smillert *syn2(struct wordent *, struct wordent *, int);
56df930be7Sderaadt static struct command
57c72b5b24Smillert *syn3(struct wordent *, struct wordent *, int);
58df930be7Sderaadt
59df930be7Sderaadt #define ALEFT 21 /* max of 20 alias expansions */
60df930be7Sderaadt #define HLEFT 11 /* max of 10 history expansions */
61df930be7Sderaadt /*
62df930be7Sderaadt * Perform aliasing on the word list lex
63df930be7Sderaadt * Do a (very rudimentary) parse to separate into commands.
64df930be7Sderaadt * If word 0 of a command has an alias, do it.
65df930be7Sderaadt * Repeat a maximum of 20 times.
66df930be7Sderaadt */
67df930be7Sderaadt static int aleft;
68df930be7Sderaadt extern int hleft;
69df930be7Sderaadt void
alias(struct wordent * lex)70e757c91eSderaadt alias(struct wordent *lex)
71df930be7Sderaadt {
72df930be7Sderaadt jmp_buf osetexit;
73df930be7Sderaadt
74df930be7Sderaadt aleft = ALEFT;
75df930be7Sderaadt hleft = HLEFT;
76df930be7Sderaadt getexit(osetexit);
77df930be7Sderaadt (void) setexit();
78df930be7Sderaadt if (haderr) {
79df930be7Sderaadt resexit(osetexit);
80df930be7Sderaadt reset();
81df930be7Sderaadt }
82df930be7Sderaadt if (--aleft == 0)
83df930be7Sderaadt stderror(ERR_ALIASLOOP);
84df930be7Sderaadt asyntax(lex->next, lex);
85df930be7Sderaadt resexit(osetexit);
86df930be7Sderaadt }
87df930be7Sderaadt
88df930be7Sderaadt static void
asyntax(struct wordent * p1,struct wordent * p2)89e757c91eSderaadt asyntax(struct wordent *p1, struct wordent *p2)
90df930be7Sderaadt {
91df930be7Sderaadt while (p1 != p2)
925f867525Sderaadt if (any(";&\n", p1->word[0]))
93df930be7Sderaadt p1 = p1->next;
94df930be7Sderaadt else {
95df930be7Sderaadt asyn0(p1, p2);
96df930be7Sderaadt return;
97df930be7Sderaadt }
98df930be7Sderaadt }
99df930be7Sderaadt
100df930be7Sderaadt static void
asyn0(struct wordent * p1,struct wordent * p2)101e757c91eSderaadt asyn0(struct wordent *p1, struct wordent *p2)
102df930be7Sderaadt {
103e757c91eSderaadt struct wordent *p;
104e757c91eSderaadt int l = 0;
105df930be7Sderaadt
106df930be7Sderaadt for (p = p1; p != p2; p = p->next)
107df930be7Sderaadt switch (p->word[0]) {
108df930be7Sderaadt
109df930be7Sderaadt case '(':
110df930be7Sderaadt l++;
111df930be7Sderaadt continue;
112df930be7Sderaadt
113df930be7Sderaadt case ')':
114df930be7Sderaadt l--;
115df930be7Sderaadt if (l < 0)
116df930be7Sderaadt stderror(ERR_TOOMANYRP);
117df930be7Sderaadt continue;
118df930be7Sderaadt
119df930be7Sderaadt case '>':
120df930be7Sderaadt if (p->next != p2 && eq(p->next->word, STRand))
121df930be7Sderaadt p = p->next;
122df930be7Sderaadt continue;
123df930be7Sderaadt
124df930be7Sderaadt case '&':
125df930be7Sderaadt case '|':
126df930be7Sderaadt case ';':
127df930be7Sderaadt case '\n':
128df930be7Sderaadt if (l != 0)
129df930be7Sderaadt continue;
130df930be7Sderaadt asyn3(p1, p);
131df930be7Sderaadt asyntax(p->next, p2);
132df930be7Sderaadt return;
133df930be7Sderaadt }
134df930be7Sderaadt if (l == 0)
135df930be7Sderaadt asyn3(p1, p2);
136df930be7Sderaadt }
137df930be7Sderaadt
138df930be7Sderaadt static void
asyn3(struct wordent * p1,struct wordent * p2)139e757c91eSderaadt asyn3(struct wordent *p1, struct wordent *p2)
140df930be7Sderaadt {
141e757c91eSderaadt struct varent *ap;
142df930be7Sderaadt struct wordent alout;
143e757c91eSderaadt bool redid;
144df930be7Sderaadt
145df930be7Sderaadt if (p1 == p2)
146df930be7Sderaadt return;
147df930be7Sderaadt if (p1->word[0] == '(') {
148df930be7Sderaadt for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
149df930be7Sderaadt if (p2 == p1)
150df930be7Sderaadt return;
151df930be7Sderaadt if (p2 == p1->next)
152df930be7Sderaadt return;
153df930be7Sderaadt asyn0(p1->next, p2);
154df930be7Sderaadt return;
155df930be7Sderaadt }
156df930be7Sderaadt ap = adrof1(p1->word, &aliases);
157df930be7Sderaadt if (ap == 0)
158df930be7Sderaadt return;
159df930be7Sderaadt alhistp = p1->prev;
160df930be7Sderaadt alhistt = p2;
161df930be7Sderaadt alvec = ap->vec;
162df930be7Sderaadt redid = lex(&alout);
163df930be7Sderaadt alhistp = alhistt = 0;
164df930be7Sderaadt alvec = 0;
165df930be7Sderaadt if (seterr) {
166df930be7Sderaadt freelex(&alout);
167df930be7Sderaadt stderror(ERR_OLD);
168df930be7Sderaadt }
169df930be7Sderaadt if (p1->word[0] && eq(p1->word, alout.next->word)) {
170df930be7Sderaadt Char *cp = alout.next->word;
171df930be7Sderaadt
172df930be7Sderaadt alout.next->word = Strspl(STRQNULL, cp);
173acdb3202Smestre free(cp);
174df930be7Sderaadt }
175df930be7Sderaadt p1 = freenod(p1, redid ? p2 : p1->next);
176df930be7Sderaadt if (alout.next != &alout) {
177df930be7Sderaadt p1->next->prev = alout.prev->prev;
178df930be7Sderaadt alout.prev->prev->next = p1->next;
179df930be7Sderaadt alout.next->prev = p1;
180df930be7Sderaadt p1->next = alout.next;
181acdb3202Smestre free(alout.prev->word);
182acdb3202Smestre free((alout.prev));
183df930be7Sderaadt }
184df930be7Sderaadt reset(); /* throw! */
185df930be7Sderaadt }
186df930be7Sderaadt
187df930be7Sderaadt static struct wordent *
freenod(struct wordent * p1,struct wordent * p2)188e757c91eSderaadt freenod(struct wordent *p1, struct wordent *p2)
189df930be7Sderaadt {
190e757c91eSderaadt struct wordent *retp = p1->prev;
191df930be7Sderaadt
192df930be7Sderaadt while (p1 != p2) {
193acdb3202Smestre free(p1->word);
194df930be7Sderaadt p1 = p1->next;
195acdb3202Smestre free((p1->prev));
196df930be7Sderaadt }
197df930be7Sderaadt retp->next = p2;
198df930be7Sderaadt p2->prev = retp;
199df930be7Sderaadt return (retp);
200df930be7Sderaadt }
201df930be7Sderaadt
202df930be7Sderaadt #define PHERE 1
203df930be7Sderaadt #define PIN 2
204df930be7Sderaadt #define POUT 4
205df930be7Sderaadt #define PERR 8
206df930be7Sderaadt
207df930be7Sderaadt /*
208df930be7Sderaadt * syntax
209df930be7Sderaadt * empty
210df930be7Sderaadt * syn0
211df930be7Sderaadt */
212df930be7Sderaadt struct command *
syntax(struct wordent * p1,struct wordent * p2,int flags)213e757c91eSderaadt syntax(struct wordent *p1, struct wordent *p2, int flags)
214df930be7Sderaadt {
215df930be7Sderaadt
216df930be7Sderaadt while (p1 != p2)
2175f867525Sderaadt if (any(";&\n", p1->word[0]))
218df930be7Sderaadt p1 = p1->next;
219df930be7Sderaadt else
220df930be7Sderaadt return (syn0(p1, p2, flags));
221df930be7Sderaadt return (0);
222df930be7Sderaadt }
223df930be7Sderaadt
224df930be7Sderaadt /*
225df930be7Sderaadt * syn0
226df930be7Sderaadt * syn1
227df930be7Sderaadt * syn1 & syntax
228df930be7Sderaadt */
229df930be7Sderaadt static struct command *
syn0(struct wordent * p1,struct wordent * p2,int flags)230e757c91eSderaadt syn0(struct wordent *p1, struct wordent *p2, int flags)
231df930be7Sderaadt {
232e757c91eSderaadt struct wordent *p;
233e757c91eSderaadt struct command *t, *t1;
234df930be7Sderaadt int l;
235df930be7Sderaadt
236df930be7Sderaadt l = 0;
237df930be7Sderaadt for (p = p1; p != p2; p = p->next)
238df930be7Sderaadt switch (p->word[0]) {
239df930be7Sderaadt
240df930be7Sderaadt case '(':
241df930be7Sderaadt l++;
242df930be7Sderaadt continue;
243df930be7Sderaadt
244df930be7Sderaadt case ')':
245df930be7Sderaadt l--;
246df930be7Sderaadt if (l < 0)
247df930be7Sderaadt seterror(ERR_TOOMANYRP);
248df930be7Sderaadt continue;
249df930be7Sderaadt
250df930be7Sderaadt case '|':
251df930be7Sderaadt if (p->word[1] == '|')
252df930be7Sderaadt continue;
253df930be7Sderaadt /* fall into ... */
254df930be7Sderaadt
255df930be7Sderaadt case '>':
256df930be7Sderaadt if (p->next != p2 && eq(p->next->word, STRand))
257df930be7Sderaadt p = p->next;
258df930be7Sderaadt continue;
259df930be7Sderaadt
260df930be7Sderaadt case '&':
261df930be7Sderaadt if (l != 0)
262df930be7Sderaadt break;
263df930be7Sderaadt if (p->word[1] == '&')
264df930be7Sderaadt continue;
265df930be7Sderaadt t1 = syn1(p1, p, flags);
266df930be7Sderaadt if (t1->t_dtyp == NODE_LIST ||
267df930be7Sderaadt t1->t_dtyp == NODE_AND ||
268df930be7Sderaadt t1->t_dtyp == NODE_OR) {
269d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
270df930be7Sderaadt t->t_dtyp = NODE_PAREN;
271df930be7Sderaadt t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
272df930be7Sderaadt t->t_dspr = t1;
273df930be7Sderaadt t1 = t;
274df930be7Sderaadt }
275df930be7Sderaadt else
276df930be7Sderaadt t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
277d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
278df930be7Sderaadt t->t_dtyp = NODE_LIST;
279df930be7Sderaadt t->t_dflg = 0;
280df930be7Sderaadt t->t_dcar = t1;
281df930be7Sderaadt t->t_dcdr = syntax(p, p2, flags);
282df930be7Sderaadt return (t);
283df930be7Sderaadt }
284df930be7Sderaadt if (l == 0)
285df930be7Sderaadt return (syn1(p1, p2, flags));
286df930be7Sderaadt seterror(ERR_TOOMANYLP);
287df930be7Sderaadt return (0);
288df930be7Sderaadt }
289df930be7Sderaadt
290df930be7Sderaadt /*
291df930be7Sderaadt * syn1
292df930be7Sderaadt * syn1a
293df930be7Sderaadt * syn1a ; syntax
294df930be7Sderaadt */
295df930be7Sderaadt static struct command *
syn1(struct wordent * p1,struct wordent * p2,int flags)296e757c91eSderaadt syn1(struct wordent *p1, struct wordent *p2, int flags)
297df930be7Sderaadt {
298e757c91eSderaadt struct wordent *p;
299e757c91eSderaadt struct command *t;
300df930be7Sderaadt int l;
301df930be7Sderaadt
302df930be7Sderaadt l = 0;
303df930be7Sderaadt for (p = p1; p != p2; p = p->next)
304df930be7Sderaadt switch (p->word[0]) {
305df930be7Sderaadt
306df930be7Sderaadt case '(':
307df930be7Sderaadt l++;
308df930be7Sderaadt continue;
309df930be7Sderaadt
310df930be7Sderaadt case ')':
311df930be7Sderaadt l--;
312df930be7Sderaadt continue;
313df930be7Sderaadt
314df930be7Sderaadt case ';':
315df930be7Sderaadt case '\n':
316df930be7Sderaadt if (l != 0)
317df930be7Sderaadt break;
318d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
319df930be7Sderaadt t->t_dtyp = NODE_LIST;
320df930be7Sderaadt t->t_dcar = syn1a(p1, p, flags);
321df930be7Sderaadt t->t_dcdr = syntax(p->next, p2, flags);
322df930be7Sderaadt if (t->t_dcdr == 0)
323df930be7Sderaadt t->t_dcdr = t->t_dcar, t->t_dcar = 0;
324df930be7Sderaadt return (t);
325df930be7Sderaadt }
326df930be7Sderaadt return (syn1a(p1, p2, flags));
327df930be7Sderaadt }
328df930be7Sderaadt
329df930be7Sderaadt /*
330df930be7Sderaadt * syn1a
331df930be7Sderaadt * syn1b
332df930be7Sderaadt * syn1b || syn1a
333df930be7Sderaadt */
334df930be7Sderaadt static struct command *
syn1a(struct wordent * p1,struct wordent * p2,int flags)335e757c91eSderaadt syn1a(struct wordent *p1, struct wordent *p2, int flags)
336df930be7Sderaadt {
337e757c91eSderaadt struct wordent *p;
338e757c91eSderaadt struct command *t;
339e757c91eSderaadt int l = 0;
340df930be7Sderaadt
341df930be7Sderaadt for (p = p1; p != p2; p = p->next)
342df930be7Sderaadt switch (p->word[0]) {
343df930be7Sderaadt
344df930be7Sderaadt case '(':
345df930be7Sderaadt l++;
346df930be7Sderaadt continue;
347df930be7Sderaadt
348df930be7Sderaadt case ')':
349df930be7Sderaadt l--;
350df930be7Sderaadt continue;
351df930be7Sderaadt
352df930be7Sderaadt case '|':
353df930be7Sderaadt if (p->word[1] != '|')
354df930be7Sderaadt continue;
355df930be7Sderaadt if (l == 0) {
356d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
357df930be7Sderaadt t->t_dtyp = NODE_OR;
358df930be7Sderaadt t->t_dcar = syn1b(p1, p, flags);
359df930be7Sderaadt t->t_dcdr = syn1a(p->next, p2, flags);
360df930be7Sderaadt t->t_dflg = 0;
361df930be7Sderaadt return (t);
362df930be7Sderaadt }
363df930be7Sderaadt continue;
364df930be7Sderaadt }
365df930be7Sderaadt return (syn1b(p1, p2, flags));
366df930be7Sderaadt }
367df930be7Sderaadt
368df930be7Sderaadt /*
369df930be7Sderaadt * syn1b
370df930be7Sderaadt * syn2
371df930be7Sderaadt * syn2 && syn1b
372df930be7Sderaadt */
373df930be7Sderaadt static struct command *
syn1b(struct wordent * p1,struct wordent * p2,int flags)374e757c91eSderaadt syn1b(struct wordent *p1, struct wordent *p2, int flags)
375df930be7Sderaadt {
376e757c91eSderaadt struct wordent *p;
377e757c91eSderaadt struct command *t;
378e757c91eSderaadt int l = 0;
379df930be7Sderaadt
380df930be7Sderaadt for (p = p1; p != p2; p = p->next)
381df930be7Sderaadt switch (p->word[0]) {
382df930be7Sderaadt
383df930be7Sderaadt case '(':
384df930be7Sderaadt l++;
385df930be7Sderaadt continue;
386df930be7Sderaadt
387df930be7Sderaadt case ')':
388df930be7Sderaadt l--;
389df930be7Sderaadt continue;
390df930be7Sderaadt
391df930be7Sderaadt case '&':
392df930be7Sderaadt if (p->word[1] == '&' && l == 0) {
393d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
394df930be7Sderaadt t->t_dtyp = NODE_AND;
395df930be7Sderaadt t->t_dcar = syn2(p1, p, flags);
396df930be7Sderaadt t->t_dcdr = syn1b(p->next, p2, flags);
397df930be7Sderaadt t->t_dflg = 0;
398df930be7Sderaadt return (t);
399df930be7Sderaadt }
400df930be7Sderaadt continue;
401df930be7Sderaadt }
402df930be7Sderaadt return (syn2(p1, p2, flags));
403df930be7Sderaadt }
404df930be7Sderaadt
405df930be7Sderaadt /*
406df930be7Sderaadt * syn2
407df930be7Sderaadt * syn3
408df930be7Sderaadt * syn3 | syn2
409df930be7Sderaadt * syn3 |& syn2
410df930be7Sderaadt */
411df930be7Sderaadt static struct command *
syn2(struct wordent * p1,struct wordent * p2,int flags)412e757c91eSderaadt syn2(struct wordent *p1, struct wordent *p2, int flags)
413df930be7Sderaadt {
414e757c91eSderaadt struct wordent *p, *pn;
415e757c91eSderaadt struct command *t;
416e757c91eSderaadt int l = 0;
417df930be7Sderaadt int f;
418df930be7Sderaadt
419df930be7Sderaadt for (p = p1; p != p2; p = p->next)
420df930be7Sderaadt switch (p->word[0]) {
421df930be7Sderaadt
422df930be7Sderaadt case '(':
423df930be7Sderaadt l++;
424df930be7Sderaadt continue;
425df930be7Sderaadt
426df930be7Sderaadt case ')':
427df930be7Sderaadt l--;
428df930be7Sderaadt continue;
429df930be7Sderaadt
430df930be7Sderaadt case '|':
431df930be7Sderaadt if (l != 0)
432df930be7Sderaadt continue;
433d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
434df930be7Sderaadt f = flags | POUT;
435df930be7Sderaadt pn = p->next;
436df930be7Sderaadt if (pn != p2 && pn->word[0] == '&') {
437df930be7Sderaadt f |= PERR;
438df930be7Sderaadt t->t_dflg |= F_STDERR;
439df930be7Sderaadt }
440df930be7Sderaadt t->t_dtyp = NODE_PIPE;
441df930be7Sderaadt t->t_dcar = syn3(p1, p, f);
442df930be7Sderaadt if (pn != p2 && pn->word[0] == '&')
443df930be7Sderaadt p = pn;
444df930be7Sderaadt t->t_dcdr = syn2(p->next, p2, flags | PIN);
445df930be7Sderaadt return (t);
446df930be7Sderaadt }
447df930be7Sderaadt return (syn3(p1, p2, flags));
448df930be7Sderaadt }
449df930be7Sderaadt
450df930be7Sderaadt static char RELPAR[] = {'<', '>', '(', ')', '\0'};
451df930be7Sderaadt
452df930be7Sderaadt /*
453df930be7Sderaadt * syn3
454df930be7Sderaadt * ( syn0 ) [ < in ] [ > out ]
455df930be7Sderaadt * word word* [ < in ] [ > out ]
456df930be7Sderaadt * KEYWORD ( word* ) word* [ < in ] [ > out ]
457df930be7Sderaadt *
458df930be7Sderaadt * KEYWORD = (@ exit foreach if set switch test while)
459df930be7Sderaadt */
460df930be7Sderaadt static struct command *
syn3(struct wordent * p1,struct wordent * p2,int flags)461e757c91eSderaadt syn3(struct wordent *p1, struct wordent *p2, int flags)
462df930be7Sderaadt {
463e757c91eSderaadt struct wordent *p;
464df930be7Sderaadt struct wordent *lp, *rp;
465e757c91eSderaadt struct command *t;
466e757c91eSderaadt int l;
467df930be7Sderaadt Char **av;
468df930be7Sderaadt int n, c;
469df930be7Sderaadt bool specp = 0;
470df930be7Sderaadt
471df930be7Sderaadt if (p1 != p2) {
472df930be7Sderaadt p = p1;
473df930be7Sderaadt again:
474df930be7Sderaadt switch (srchx(p->word)) {
475df930be7Sderaadt
476df930be7Sderaadt case T_ELSE:
477df930be7Sderaadt p = p->next;
478df930be7Sderaadt if (p != p2)
479df930be7Sderaadt goto again;
480df930be7Sderaadt break;
481df930be7Sderaadt
482df930be7Sderaadt case T_EXIT:
483df930be7Sderaadt case T_FOREACH:
484df930be7Sderaadt case T_IF:
485df930be7Sderaadt case T_LET:
486df930be7Sderaadt case T_SET:
487df930be7Sderaadt case T_SWITCH:
488df930be7Sderaadt case T_WHILE:
489df930be7Sderaadt specp = 1;
490df930be7Sderaadt break;
491df930be7Sderaadt }
492df930be7Sderaadt }
493df930be7Sderaadt n = 0;
494df930be7Sderaadt l = 0;
495df930be7Sderaadt for (p = p1; p != p2; p = p->next)
496df930be7Sderaadt switch (p->word[0]) {
497df930be7Sderaadt
498df930be7Sderaadt case '(':
499df930be7Sderaadt if (specp)
500df930be7Sderaadt n++;
501df930be7Sderaadt l++;
502df930be7Sderaadt continue;
503df930be7Sderaadt
504df930be7Sderaadt case ')':
505df930be7Sderaadt if (specp)
506df930be7Sderaadt n++;
507df930be7Sderaadt l--;
508df930be7Sderaadt continue;
509df930be7Sderaadt
510df930be7Sderaadt case '>':
511df930be7Sderaadt case '<':
512df930be7Sderaadt if (l != 0) {
513df930be7Sderaadt if (specp)
514df930be7Sderaadt n++;
515df930be7Sderaadt continue;
516df930be7Sderaadt }
517df930be7Sderaadt if (p->next == p2)
518df930be7Sderaadt continue;
5195f867525Sderaadt if (any(RELPAR, p->next->word[0]))
520df930be7Sderaadt continue;
521df930be7Sderaadt n--;
522df930be7Sderaadt continue;
523df930be7Sderaadt
524df930be7Sderaadt default:
525df930be7Sderaadt if (!specp && l != 0)
526df930be7Sderaadt continue;
527df930be7Sderaadt n++;
528df930be7Sderaadt continue;
529df930be7Sderaadt }
530df930be7Sderaadt if (n < 0)
531df930be7Sderaadt n = 0;
532d29fd0a0Stedu t = xcalloc(1, sizeof(*t));
533*d95322bbSmartijn av = xcalloc(n + 1, sizeof(*av));
534df930be7Sderaadt t->t_dcom = av;
535df930be7Sderaadt n = 0;
536df930be7Sderaadt if (p2->word[0] == ')')
537df930be7Sderaadt t->t_dflg = F_NOFORK;
538df930be7Sderaadt lp = 0;
539df930be7Sderaadt rp = 0;
540df930be7Sderaadt l = 0;
541df930be7Sderaadt for (p = p1; p != p2; p = p->next) {
542df930be7Sderaadt c = p->word[0];
543df930be7Sderaadt switch (c) {
544df930be7Sderaadt
545df930be7Sderaadt case '(':
546df930be7Sderaadt if (l == 0) {
547df930be7Sderaadt if (lp != 0 && !specp)
548df930be7Sderaadt seterror(ERR_BADPLP);
549df930be7Sderaadt lp = p->next;
550df930be7Sderaadt }
551df930be7Sderaadt l++;
552df930be7Sderaadt goto savep;
553df930be7Sderaadt
554df930be7Sderaadt case ')':
555df930be7Sderaadt l--;
556df930be7Sderaadt if (l == 0)
557df930be7Sderaadt rp = p;
558df930be7Sderaadt goto savep;
559df930be7Sderaadt
560df930be7Sderaadt case '>':
561df930be7Sderaadt if (l != 0)
562df930be7Sderaadt goto savep;
563df930be7Sderaadt if (p->word[1] == '>')
564df930be7Sderaadt t->t_dflg |= F_APPEND;
565df930be7Sderaadt if (p->next != p2 && eq(p->next->word, STRand)) {
566df930be7Sderaadt t->t_dflg |= F_STDERR, p = p->next;
567df930be7Sderaadt if (flags & (POUT | PERR)) {
568df930be7Sderaadt seterror(ERR_OUTRED);
569df930be7Sderaadt continue;
570df930be7Sderaadt }
571df930be7Sderaadt }
572df930be7Sderaadt if (p->next != p2 && eq(p->next->word, STRbang))
573df930be7Sderaadt t->t_dflg |= F_OVERWRITE, p = p->next;
574df930be7Sderaadt if (p->next == p2) {
575df930be7Sderaadt seterror(ERR_MISRED);
576df930be7Sderaadt continue;
577df930be7Sderaadt }
578df930be7Sderaadt p = p->next;
5795f867525Sderaadt if (any(RELPAR, p->word[0])) {
580df930be7Sderaadt seterror(ERR_MISRED);
581df930be7Sderaadt continue;
582df930be7Sderaadt }
583df930be7Sderaadt if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
584df930be7Sderaadt seterror(ERR_OUTRED);
585df930be7Sderaadt else
586df930be7Sderaadt t->t_drit = Strsave(p->word);
587df930be7Sderaadt continue;
588df930be7Sderaadt
589df930be7Sderaadt case '<':
590df930be7Sderaadt if (l != 0)
591df930be7Sderaadt goto savep;
592df930be7Sderaadt if (p->word[1] == '<')
593df930be7Sderaadt t->t_dflg |= F_READ;
594df930be7Sderaadt if (p->next == p2) {
595df930be7Sderaadt seterror(ERR_MISRED);
596df930be7Sderaadt continue;
597df930be7Sderaadt }
598df930be7Sderaadt p = p->next;
5995f867525Sderaadt if (any(RELPAR, p->word[0])) {
600df930be7Sderaadt seterror(ERR_MISRED);
601df930be7Sderaadt continue;
602df930be7Sderaadt }
603df930be7Sderaadt if ((flags & PHERE) && (t->t_dflg & F_READ))
604df930be7Sderaadt seterror(ERR_REDPAR);
605df930be7Sderaadt else if ((flags & PIN) || t->t_dlef)
606df930be7Sderaadt seterror(ERR_INRED);
607df930be7Sderaadt else
608df930be7Sderaadt t->t_dlef = Strsave(p->word);
609df930be7Sderaadt continue;
610df930be7Sderaadt
611df930be7Sderaadt savep:
612df930be7Sderaadt if (!specp)
613df930be7Sderaadt continue;
614df930be7Sderaadt default:
615df930be7Sderaadt if (l != 0 && !specp)
616df930be7Sderaadt continue;
617df930be7Sderaadt if (seterr == 0)
618df930be7Sderaadt av[n] = Strsave(p->word);
619df930be7Sderaadt n++;
620df930be7Sderaadt continue;
621df930be7Sderaadt }
622df930be7Sderaadt }
623df930be7Sderaadt if (lp != 0 && !specp) {
624df930be7Sderaadt if (n != 0)
625df930be7Sderaadt seterror(ERR_BADPLPS);
626df930be7Sderaadt t->t_dtyp = NODE_PAREN;
627df930be7Sderaadt t->t_dspr = syn0(lp, rp, PHERE);
628df930be7Sderaadt }
629df930be7Sderaadt else {
630df930be7Sderaadt if (n == 0)
631df930be7Sderaadt seterror(ERR_NULLCOM);
632df930be7Sderaadt t->t_dtyp = NODE_COMMAND;
633df930be7Sderaadt }
634df930be7Sderaadt return (t);
635df930be7Sderaadt }
636df930be7Sderaadt
637df930be7Sderaadt void
freesyn(struct command * t)638e757c91eSderaadt freesyn(struct command *t)
639df930be7Sderaadt {
640e757c91eSderaadt Char **v;
641df930be7Sderaadt
642df930be7Sderaadt if (t == 0)
643df930be7Sderaadt return;
644df930be7Sderaadt switch (t->t_dtyp) {
645df930be7Sderaadt
646df930be7Sderaadt case NODE_COMMAND:
647df930be7Sderaadt for (v = t->t_dcom; *v; v++)
648acdb3202Smestre free(* v);
649acdb3202Smestre free((t->t_dcom));
650acdb3202Smestre free(t->t_dlef);
651acdb3202Smestre free(t->t_drit);
652df930be7Sderaadt break;
653df930be7Sderaadt case NODE_PAREN:
654df930be7Sderaadt freesyn(t->t_dspr);
655acdb3202Smestre free(t->t_dlef);
656acdb3202Smestre free(t->t_drit);
657df930be7Sderaadt break;
658df930be7Sderaadt
659df930be7Sderaadt case NODE_AND:
660df930be7Sderaadt case NODE_OR:
661df930be7Sderaadt case NODE_PIPE:
662df930be7Sderaadt case NODE_LIST:
663df930be7Sderaadt freesyn(t->t_dcar), freesyn(t->t_dcdr);
664df930be7Sderaadt break;
665df930be7Sderaadt }
666acdb3202Smestre free(t);
667df930be7Sderaadt }
668