Kernel part of bluetooth stack ported by Dmitry Komissaroff. Very much work
[dragonfly.git] / contrib / tcsh / sh.parse.c
blobb1a76d829e7947ea7c2574b87cf45f84e3d9f49d
1 /* $Header: /src/pub/tcsh/sh.parse.c,v 3.11 2002/03/08 17:36:46 christos Exp $ */
2 /*
3 * sh.parse.c: Interpret a list of tokens
4 */
5 /*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 #include "sh.h"
35 RCSID("$Id: sh.parse.c,v 3.11 2002/03/08 17:36:46 christos Exp $")
38 * C shell
40 static void asyntax __P((struct wordent *, struct wordent *));
41 static void asyn0 __P((struct wordent *, struct wordent *));
42 static void asyn3 __P((struct wordent *, struct wordent *));
43 static struct wordent *freenod __P((struct wordent *, struct wordent *));
44 static struct command *syn0 __P((struct wordent *, struct wordent *, int));
45 static struct command *syn1 __P((struct wordent *, struct wordent *, int));
46 static struct command *syn1a __P((struct wordent *, struct wordent *, int));
47 static struct command *syn1b __P((struct wordent *, struct wordent *, int));
48 static struct command *syn2 __P((struct wordent *, struct wordent *, int));
49 static struct command *syn3 __P((struct wordent *, struct wordent *, int));
51 #define ALEFT 51 /* max of 50 alias expansions */
52 #define HLEFT 11 /* max of 10 history expansions */
54 * Perform aliasing on the word list lexp
55 * Do a (very rudimentary) parse to separate into commands.
56 * If word 0 of a command has an alias, do it.
57 * Repeat a maximum of 50 times.
59 static int aleft;
60 extern int hleft;
61 void
62 alias(lexp)
63 register struct wordent *lexp;
65 jmp_buf_t osetexit;
67 aleft = ALEFT;
68 hleft = HLEFT;
69 getexit(osetexit);
70 (void) setexit();
71 if (haderr) {
72 resexit(osetexit);
73 reset();
75 if (--aleft == 0)
76 stderror(ERR_ALIASLOOP);
77 asyntax(lexp->next, lexp);
78 resexit(osetexit);
81 static void
82 asyntax(p1, p2)
83 register struct wordent *p1, *p2;
85 while (p1 != p2)
86 if (any(";&\n", p1->word[0]))
87 p1 = p1->next;
88 else {
89 asyn0(p1, p2);
90 return;
94 static void
95 asyn0(p1, p2)
96 struct wordent *p1;
97 register struct wordent *p2;
99 register struct wordent *p;
100 register int l = 0;
102 for (p = p1; p != p2; p = p->next)
103 switch (p->word[0]) {
105 case '(':
106 l++;
107 continue;
109 case ')':
110 l--;
111 if (l < 0)
112 stderror(ERR_TOOMANYRP);
113 continue;
115 case '>':
116 if (p->next != p2 && eq(p->next->word, STRand))
117 p = p->next;
118 continue;
120 case '&':
121 case '|':
122 case ';':
123 case '\n':
124 if (l != 0)
125 continue;
126 asyn3(p1, p);
127 asyntax(p->next, p2);
128 return;
130 default:
131 break;
133 if (l == 0)
134 asyn3(p1, p2);
137 static void
138 asyn3(p1, p2)
139 struct wordent *p1;
140 register struct wordent *p2;
142 register struct varent *ap;
143 struct wordent alout;
144 register bool redid;
146 if (p1 == p2)
147 return;
148 if (p1->word[0] == '(') {
149 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
150 if (p2 == p1)
151 return;
152 if (p2 == p1->next)
153 return;
154 asyn0(p1->next, p2);
155 return;
157 ap = adrof1(p1->word, &aliases);
158 if (ap == 0)
159 return;
160 alhistp = p1->prev;
161 alhistt = p2;
162 alvec = ap->vec;
163 redid = lex(&alout);
164 alhistp = alhistt = 0;
165 alvec = 0;
166 if (seterr) {
167 freelex(&alout);
168 stderror(ERR_OLD);
170 if (p1->word[0] && eq(p1->word, alout.next->word)) {
171 Char *cp = alout.next->word;
173 alout.next->word = Strspl(STRQNULL, cp);
174 xfree((ptr_t) cp);
176 p1 = freenod(p1, redid ? p2 : p1->next);
177 if (alout.next != &alout) {
178 p1->next->prev = alout.prev->prev;
179 alout.prev->prev->next = p1->next;
180 alout.next->prev = p1;
181 p1->next = alout.next;
182 xfree((ptr_t) alout.prev->word);
183 xfree((ptr_t) (alout.prev));
185 reset(); /* throw! */
188 static struct wordent *
189 freenod(p1, p2)
190 register struct wordent *p1, *p2;
192 register struct wordent *retp = p1->prev;
194 while (p1 != p2) {
195 xfree((ptr_t) p1->word);
196 p1 = p1->next;
197 xfree((ptr_t) (p1->prev));
199 retp->next = p2;
200 p2->prev = retp;
201 return (retp);
204 #define P_HERE 1
205 #define P_IN 2
206 #define P_OUT 4
207 #define P_DIAG 8
210 * syntax
211 * empty
212 * syn0
214 struct command *
215 syntax(p1, p2, flags)
216 register struct wordent *p1, *p2;
217 int flags;
220 while (p1 != p2)
221 if (any(";&\n", p1->word[0]))
222 p1 = p1->next;
223 else
224 return (syn0(p1, p2, flags));
225 return (0);
229 * syn0
230 * syn1
231 * syn1 & syntax
233 static struct command *
234 syn0(p1, p2, flags)
235 struct wordent *p1, *p2;
236 int flags;
238 register struct wordent *p;
239 register struct command *t, *t1;
240 int l;
242 l = 0;
243 for (p = p1; p != p2; p = p->next)
244 switch (p->word[0]) {
246 case '(':
247 l++;
248 continue;
250 case ')':
251 l--;
252 if (l < 0)
253 seterror(ERR_TOOMANYRP);
254 continue;
256 case '|':
257 if (p->word[1] == '|')
258 continue;
259 /*FALLTHROUGH*/
261 case '>':
262 if (p->next != p2 && eq(p->next->word, STRand))
263 p = p->next;
264 continue;
266 case '&':
267 if (l != 0)
268 break;
269 if (p->word[1] == '&')
270 continue;
271 t1 = syn1(p1, p, flags);
272 if (t1->t_dtyp == NODE_LIST ||
273 t1->t_dtyp == NODE_AND ||
274 t1->t_dtyp == NODE_OR) {
275 t = (struct command *) xcalloc(1, sizeof(*t));
276 t->t_dtyp = NODE_PAREN;
277 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
278 t->t_dspr = t1;
279 t1 = t;
281 else
282 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
283 t = (struct command *) xcalloc(1, sizeof(*t));
284 t->t_dtyp = NODE_LIST;
285 t->t_dflg = 0;
286 t->t_dcar = t1;
287 t->t_dcdr = syntax(p, p2, flags);
288 return (t);
289 default:
290 break;
292 if (l == 0)
293 return (syn1(p1, p2, flags));
294 seterror(ERR_TOOMANYLP);
295 return (0);
299 * syn1
300 * syn1a
301 * syn1a ; syntax
303 static struct command *
304 syn1(p1, p2, flags)
305 struct wordent *p1, *p2;
306 int flags;
308 register struct wordent *p;
309 register struct command *t;
310 int l;
312 l = 0;
313 for (p = p1; p != p2; p = p->next)
314 switch (p->word[0]) {
316 case '(':
317 l++;
318 continue;
320 case ')':
321 l--;
322 continue;
324 case ';':
325 case '\n':
326 if (l != 0)
327 break;
328 t = (struct command *) xcalloc(1, sizeof(*t));
329 t->t_dtyp = NODE_LIST;
330 t->t_dcar = syn1a(p1, p, flags);
331 t->t_dcdr = syntax(p->next, p2, flags);
332 if (t->t_dcdr == 0)
333 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
334 return (t);
336 default:
337 break;
339 return (syn1a(p1, p2, flags));
343 * syn1a
344 * syn1b
345 * syn1b || syn1a
347 static struct command *
348 syn1a(p1, p2, flags)
349 struct wordent *p1, *p2;
350 int flags;
352 register struct wordent *p;
353 register struct command *t;
354 register int l = 0;
356 for (p = p1; p != p2; p = p->next)
357 switch (p->word[0]) {
359 case '(':
360 l++;
361 continue;
363 case ')':
364 l--;
365 continue;
367 case '|':
368 if (p->word[1] != '|')
369 continue;
370 if (l == 0) {
371 t = (struct command *) xcalloc(1, sizeof(*t));
372 t->t_dtyp = NODE_OR;
373 t->t_dcar = syn1b(p1, p, flags);
374 t->t_dcdr = syn1a(p->next, p2, flags);
375 t->t_dflg = 0;
376 return (t);
378 continue;
380 default:
381 break;
383 return (syn1b(p1, p2, flags));
387 * syn1b
388 * syn2
389 * syn2 && syn1b
391 static struct command *
392 syn1b(p1, p2, flags)
393 struct wordent *p1, *p2;
394 int flags;
396 register struct wordent *p;
397 register struct command *t;
398 register int l = 0;
400 for (p = p1; p != p2; p = p->next)
401 switch (p->word[0]) {
403 case '(':
404 l++;
405 continue;
407 case ')':
408 l--;
409 continue;
411 case '&':
412 if (p->word[1] == '&' && l == 0) {
413 t = (struct command *) xcalloc(1, sizeof(*t));
414 t->t_dtyp = NODE_AND;
415 t->t_dcar = syn2(p1, p, flags);
416 t->t_dcdr = syn1b(p->next, p2, flags);
417 t->t_dflg = 0;
418 return (t);
420 continue;
422 default:
423 break;
425 return (syn2(p1, p2, flags));
429 * syn2
430 * syn3
431 * syn3 | syn2
432 * syn3 |& syn2
434 static struct command *
435 syn2(p1, p2, flags)
436 struct wordent *p1, *p2;
437 int flags;
439 register struct wordent *p, *pn;
440 register struct command *t;
441 register int l = 0;
442 int f;
444 for (p = p1; p != p2; p = p->next)
445 switch (p->word[0]) {
447 case '(':
448 l++;
449 continue;
451 case ')':
452 l--;
453 continue;
455 case '|':
456 if (l != 0)
457 continue;
458 t = (struct command *) xcalloc(1, sizeof(*t));
459 f = flags | P_OUT;
460 pn = p->next;
461 if (pn != p2 && pn->word[0] == '&') {
462 f |= P_DIAG;
463 t->t_dflg |= F_STDERR;
465 t->t_dtyp = NODE_PIPE;
466 t->t_dcar = syn3(p1, p, f);
467 if (pn != p2 && pn->word[0] == '&')
468 p = pn;
469 t->t_dcdr = syn2(p->next, p2, flags | P_IN);
470 return (t);
472 default:
473 break;
475 return (syn3(p1, p2, flags));
478 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
481 * syn3
482 * ( syn0 ) [ < in ] [ > out ]
483 * word word* [ < in ] [ > out ]
484 * KEYWORD ( word* ) word* [ < in ] [ > out ]
486 * KEYWORD = (@ exit foreach if set switch test while)
488 static struct command *
489 syn3(p1, p2, flags)
490 struct wordent *p1, *p2;
491 int flags;
493 register struct wordent *p;
494 struct wordent *lp, *rp;
495 register struct command *t;
496 register int l;
497 Char **av;
498 int n, c;
499 bool specp = 0;
501 if (p1 != p2) {
502 p = p1;
503 again:
504 switch (srchx(p->word)) {
506 case TC_ELSE:
507 p = p->next;
508 if (p != p2)
509 goto again;
510 break;
512 case TC_EXIT:
513 case TC_FOREACH:
514 case TC_IF:
515 case TC_LET:
516 case TC_SET:
517 case TC_SWITCH:
518 case TC_WHILE:
519 specp = 1;
520 break;
521 default:
522 break;
525 n = 0;
526 l = 0;
527 for (p = p1; p != p2; p = p->next)
528 switch (p->word[0]) {
530 case '(':
531 if (specp)
532 n++;
533 l++;
534 continue;
536 case ')':
537 if (specp)
538 n++;
539 l--;
540 continue;
542 case '>':
543 case '<':
544 if (l != 0) {
545 if (specp)
546 n++;
547 continue;
549 if (p->next == p2)
550 continue;
551 if (any(RELPAR, p->next->word[0]))
552 continue;
553 n--;
554 continue;
556 default:
557 if (!specp && l != 0)
558 continue;
559 n++;
560 continue;
562 if (n < 0)
563 n = 0;
564 t = (struct command *) xcalloc(1, sizeof(*t));
565 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
566 t->t_dcom = av;
567 n = 0;
568 if (p2->word[0] == ')')
569 t->t_dflg = F_NOFORK;
570 lp = 0;
571 rp = 0;
572 l = 0;
573 for (p = p1; p != p2; p = p->next) {
574 c = p->word[0];
575 switch (c) {
577 case '(':
578 if (l == 0) {
579 if (lp != 0 && !specp)
580 seterror(ERR_BADPLP);
581 lp = p->next;
583 l++;
584 goto savep;
586 case ')':
587 l--;
588 if (l == 0)
589 rp = p;
590 goto savep;
592 case '>':
593 if (l != 0)
594 goto savep;
595 if (p->word[1] == '>')
596 t->t_dflg |= F_APPEND;
597 if (p->next != p2 && eq(p->next->word, STRand)) {
598 t->t_dflg |= F_STDERR, p = p->next;
599 if (flags & (P_OUT | P_DIAG)) {
600 seterror(ERR_OUTRED);
601 continue;
604 if (p->next != p2 && eq(p->next->word, STRbang))
605 t->t_dflg |= F_OVERWRITE, p = p->next;
606 if (p->next == p2) {
607 seterror(ERR_MISRED);
608 continue;
610 p = p->next;
611 if (any(RELPAR, p->word[0])) {
612 seterror(ERR_MISRED);
613 continue;
615 if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit)
616 seterror(ERR_OUTRED);
617 else
618 t->t_drit = Strsave(p->word);
619 continue;
621 case '<':
622 if (l != 0)
623 goto savep;
624 if (p->word[1] == '<')
625 t->t_dflg |= F_READ;
626 if (p->next == p2) {
627 seterror(ERR_MISRED);
628 continue;
630 p = p->next;
631 if (any(RELPAR, p->word[0])) {
632 seterror(ERR_MISRED);
633 continue;
635 if ((flags & P_HERE) && (t->t_dflg & F_READ))
636 seterror(ERR_REDPAR);
637 else if ((flags & P_IN) || t->t_dlef)
638 seterror(ERR_INRED);
639 else
640 t->t_dlef = Strsave(p->word);
641 continue;
643 savep:
644 if (!specp)
645 continue;
646 default:
647 if (l != 0 && !specp)
648 continue;
649 if (seterr == 0)
650 av[n] = Strsave(p->word);
651 n++;
652 continue;
655 if (lp != 0 && !specp) {
656 if (n != 0)
657 seterror(ERR_BADPLPS);
658 t->t_dtyp = NODE_PAREN;
659 t->t_dspr = syn0(lp, rp, P_HERE);
661 else {
662 if (n == 0)
663 seterror(ERR_NULLCOM);
664 t->t_dtyp = NODE_COMMAND;
666 return (t);
669 void
670 freesyn(t)
671 register struct command *t;
673 register Char **v;
675 if (t == 0)
676 return;
677 switch (t->t_dtyp) {
679 case NODE_COMMAND:
680 for (v = t->t_dcom; *v; v++)
681 xfree((ptr_t) * v);
682 xfree((ptr_t) (t->t_dcom));
683 xfree((ptr_t) t->t_dlef);
684 xfree((ptr_t) t->t_drit);
685 break;
686 case NODE_PAREN:
687 freesyn(t->t_dspr);
688 xfree((ptr_t) t->t_dlef);
689 xfree((ptr_t) t->t_drit);
690 break;
692 case NODE_AND:
693 case NODE_OR:
694 case NODE_PIPE:
695 case NODE_LIST:
696 freesyn(t->t_dcar), freesyn(t->t_dcdr);
697 break;
698 default:
699 break;
701 xfree((ptr_t) t);