Merge branch 'cleanups'
[unleashed.git] / usr / src / cmd / csh / sh.parse.c
blobb936126c8d5e02afe8426fe64fc39598e1eb7622
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
17 #include "sh.h"
18 #include "sh.tconst.h"
21 * C shell
24 void asyntax(struct wordent *, struct wordent *);
25 void asyn0(struct wordent *, struct wordent *);
26 void asyn3(struct wordent *, struct wordent *);
27 void chr_blkfree(char **);
28 struct command *syn0(struct wordent *, struct wordent *, int);
29 struct command *syn1(struct wordent *, struct wordent *, int);
30 struct command *syn1a(struct wordent *, struct wordent *, int);
31 struct command *syn1b(struct wordent *, struct wordent *, int);
32 struct command *syn2(struct wordent *, struct wordent *, int);
33 struct command *syn3(struct wordent *, struct wordent *, int);
34 struct wordent *freenod(struct wordent *, struct wordent *);
37 * Perform aliasing on the word list lex
38 * Do a (very rudimentary) parse to separate into commands.
39 * If word 0 of a command has an alias, do it.
40 * Repeat a maximum of 20 times.
42 void
43 alias(struct wordent *lex)
45 int aleft = 21;
46 jmp_buf osetexit;
48 #ifdef TRACE
49 tprintf("TRACE- alias()\n");
50 #endif
51 getexit(osetexit);
52 setexit();
53 if (haderr) {
54 resexit(osetexit);
55 reset();
57 if (--aleft == 0)
58 error("Alias loop");
59 asyntax(lex->next, lex);
60 resexit(osetexit);
63 void
64 asyntax(struct wordent *p1, struct wordent *p2)
66 #ifdef TRACE
67 tprintf("TRACE- asyntax()\n");
68 #endif
70 while (p1 != p2)
71 /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */
72 if (p1->word[0] == ';' ||
73 p1->word[0] == '&' ||
74 p1->word[0] == '\n')
75 p1 = p1->next;
76 else {
77 asyn0(p1, p2);
78 return;
82 void
83 asyn0(struct wordent *p1, struct wordent *p2)
85 struct wordent *p;
86 int l = 0;
88 #ifdef TRACE
89 tprintf("TRACE- asyn0()\n");
90 #endif
91 for (p = p1; p != p2; p = p->next)
92 switch (p->word[0]) {
94 case '(':
95 l++;
96 continue;
98 case ')':
99 l--;
100 if (l < 0)
101 error("Too many )'s");
102 continue;
104 case '>':
105 if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/))
106 p = p->next;
107 continue;
109 case '&':
110 case '|':
111 case ';':
112 case '\n':
113 if (l != 0)
114 continue;
115 asyn3(p1, p);
116 asyntax(p->next, p2);
117 return;
119 if (l == 0)
120 asyn3(p1, p2);
123 void
124 asyn3(struct wordent *p1, struct wordent *p2)
126 struct varent *ap;
127 struct wordent alout;
128 bool redid;
130 #ifdef TRACE
131 tprintf("TRACE- asyn3()\n");
132 #endif
133 if (p1 == p2)
134 return;
135 if (p1->word[0] == '(') {
136 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
137 if (p2 == p1)
138 return;
139 if (p2 == p1->next)
140 return;
141 asyn0(p1->next, p2);
142 return;
144 ap = adrof1(p1->word, &aliases);
145 if (ap == 0)
146 return;
147 alhistp = p1->prev;
148 alhistt = p2;
149 alvec = ap->vec;
150 redid = lex(&alout);
151 alhistp = alhistt = 0;
152 alvec = 0;
153 if (err) {
154 freelex(&alout);
155 error("%s", gettext(err));
157 if (p1->word[0] && eq(p1->word, alout.next->word)) {
158 tchar *cp = alout.next->word;
160 alout.next->word = strspl(S_TOPBIT /* "\200" */, cp);
161 xfree(cp);
163 p1 = freenod(p1, redid ? p2 : p1->next);
164 if (alout.next != &alout) {
165 p1->next->prev = alout.prev->prev;
166 alout.prev->prev->next = p1->next;
167 alout.next->prev = p1;
168 p1->next = alout.next;
169 xfree(alout.prev->word);
170 xfree(alout.prev);
172 reset(); /* throw! */
175 struct wordent *
176 freenod(struct wordent *p1, struct wordent *p2)
178 struct wordent *retp = p1->prev;
180 #ifdef TRACE
181 tprintf("TRACE- freenod()\n");
182 #endif
183 while (p1 != p2) {
184 xfree(p1->word);
185 p1 = p1->next;
186 xfree(p1->prev);
188 retp->next = p2;
189 p2->prev = retp;
190 return (retp);
193 #define PHERE 1
194 #define PIN 2
195 #define POUT 4
196 #define PDIAG 8
199 * syntax
200 * empty
201 * syn0
203 struct command *
204 syntax(struct wordent *p1, struct wordent *p2, int flags)
206 #ifdef TRACE
207 tprintf("TRACE- syntax()\n");
208 #endif
210 while (p1 != p2)
211 /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */
212 if (p1->word[0] == ';' ||
213 p1->word[0] == '&' ||
214 p1->word[0] == '\n')
215 p1 = p1->next;
216 else
217 return (syn0(p1, p2, flags));
218 return (0);
222 * syn0
223 * syn1
224 * syn1 & syntax
226 struct command *
227 syn0(struct wordent *p1, struct wordent *p2, int flags)
229 struct wordent *p;
230 struct command *t, *t1;
231 int l;
233 #ifdef TRACE
234 tprintf("TRACE- syn0()\n");
235 #endif
236 l = 0;
237 for (p = p1; p != p2; p = p->next)
238 switch (p->word[0]) {
240 case '(':
241 l++;
242 continue;
244 case ')':
245 l--;
246 if (l < 0)
247 seterr("Too many )'s");
248 continue;
250 case '|':
251 if (p->word[1] == '|')
252 continue;
253 /* fall into ... */
255 case '>':
256 if (p->next != p2 && eq(p->next->word, S_AND /* "&" */))
257 p = p->next;
258 continue;
260 case '&':
261 if (l != 0)
262 break;
263 if (p->word[1] == '&')
264 continue;
265 t1 = syn1(p1, p, flags);
266 if (t1->t_dtyp == TLST ||
267 t1->t_dtyp == TAND ||
268 t1->t_dtyp == TOR) {
269 t = (struct command *)xcalloc(1, sizeof (*t));
270 t->t_dtyp = TPAR;
271 t->t_dflg = FAND|FINT;
272 t->t_dspr = t1;
273 t1 = t;
274 } else
275 t1->t_dflg |= FAND|FINT;
276 t = (struct command *)xcalloc(1, sizeof (*t));
277 t->t_dtyp = TLST;
278 t->t_dflg = 0;
279 t->t_dcar = t1;
280 t->t_dcdr = syntax(p, p2, flags);
281 return (t);
283 if (l == 0)
284 return (syn1(p1, p2, flags));
285 seterr("Too many ('s");
286 return (0);
290 * syn1
291 * syn1a
292 * syn1a ; syntax
294 struct command *
295 syn1(struct wordent *p1, struct wordent *p2, int flags)
297 struct wordent *p;
298 struct command *t;
299 int l;
301 #ifdef TRACE
302 tprintf("TRACE- syn1()\n");
303 #endif
304 l = 0;
305 for (p = p1; p != p2; p = p->next)
306 switch (p->word[0]) {
308 case '(':
309 l++;
310 continue;
312 case ')':
313 l--;
314 continue;
316 case ';':
317 case '\n':
318 if (l != 0)
319 break;
320 t = (struct command *)xcalloc(1, sizeof (*t));
321 t->t_dtyp = TLST;
322 t->t_dcar = syn1a(p1, p, flags);
323 t->t_dcdr = syntax(p->next, p2, flags);
324 if (t->t_dcdr == 0)
325 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
326 return (t);
328 return (syn1a(p1, p2, flags));
332 * syn1a
333 * syn1b
334 * syn1b || syn1a
336 struct command *
337 syn1a(struct wordent *p1, struct wordent *p2, int flags)
339 struct wordent *p;
340 struct command *t;
341 int l = 0;
343 #ifdef TRACE
344 tprintf("TRACE- syn1a()\n");
345 #endif
346 for (p = p1; p != p2; p = p->next)
347 switch (p->word[0]) {
349 case '(':
350 l++;
351 continue;
353 case ')':
354 l--;
355 continue;
357 case '|':
358 if (p->word[1] != '|')
359 continue;
360 if (l == 0) {
361 t = (struct command *)xcalloc(1, sizeof (*t));
362 t->t_dtyp = TOR;
363 t->t_dcar = syn1b(p1, p, flags);
364 t->t_dcdr = syn1a(p->next, p2, flags);
365 t->t_dflg = 0;
366 return (t);
368 continue;
370 return (syn1b(p1, p2, flags));
374 * syn1b
375 * syn2
376 * syn2 && syn1b
378 struct command *
379 syn1b(struct wordent *p1, struct wordent *p2, int flags)
381 struct wordent *p;
382 struct command *t;
383 int l = 0;
385 #ifdef TRACE
386 tprintf("TRACE- syn1b()\n");
387 #endif
388 l = 0;
389 for (p = p1; p != p2; p = p->next)
390 switch (p->word[0]) {
392 case '(':
393 l++;
394 continue;
396 case ')':
397 l--;
398 continue;
400 case '&':
401 if (p->word[1] == '&' && l == 0) {
402 t = (struct command *)xcalloc(1, sizeof (*t));
403 t->t_dtyp = TAND;
404 t->t_dcar = syn2(p1, p, flags);
405 t->t_dcdr = syn1b(p->next, p2, flags);
406 t->t_dflg = 0;
407 return (t);
409 continue;
411 return (syn2(p1, p2, flags));
415 * syn2
416 * syn3
417 * syn3 | syn2
418 * syn3 |& syn2
420 struct command *
421 syn2(struct wordent *p1, struct wordent *p2, int flags)
423 struct wordent *p, *pn;
424 struct command *t;
425 int l = 0;
426 int f;
428 #ifdef TRACE
429 tprintf("TRACE- syn2()\n");
430 #endif
431 for (p = p1; p != p2; p = p->next)
432 switch (p->word[0]) {
434 case '(':
435 l++;
436 continue;
438 case ')':
439 l--;
440 continue;
442 case '|':
443 if (l != 0)
444 continue;
445 t = (struct command *)xcalloc(1, sizeof (*t));
446 f = flags | POUT;
447 pn = p->next;
448 if (pn != p2 && pn->word[0] == '&') {
449 f |= PDIAG;
450 t->t_dflg |= FDIAG;
452 t->t_dtyp = TFIL;
453 t->t_dcar = syn3(p1, p, f);
454 if (pn != p2 && pn->word[0] == '&')
455 p = pn;
456 t->t_dcdr = syn2(p->next, p2, flags | PIN);
457 return (t);
459 return (syn3(p1, p2, flags));
462 tchar RELPAR[] = {'<', '>', '(', ')', 0}; /* "<>()" */
465 * syn3
466 * ( syn0 ) [ < in ] [ > out ]
467 * word word* [ < in ] [ > out ]
468 * KEYWORD ( word* ) word* [ < in ] [ > out ]
470 * KEYWORD = (@ exit foreach if set switch test while)
472 struct command *
473 syn3(struct wordent *p1, struct wordent *p2, int flags)
475 struct wordent *p;
476 struct wordent *lp, *rp;
477 struct command *t;
478 int l;
479 tchar **av;
480 int n, c;
481 bool specp = 0;
483 #ifdef TRACE
484 tprintf("TRACE- syn3()\n");
485 #endif
486 if (p1 != p2) {
487 p = p1;
488 again:
489 switch (srchx(p->word)) {
491 case ZELSE:
492 p = p->next;
493 if (p != p2)
494 goto again;
495 break;
497 case ZEXIT:
498 case ZFOREACH:
499 case ZIF:
500 case ZLET:
501 case ZSET:
502 case ZSWITCH:
503 case ZWHILE:
504 specp = 1;
505 break;
508 n = 0;
509 l = 0;
510 for (p = p1; p != p2; p = p->next)
511 switch (p->word[0]) {
513 case '(':
514 if (specp)
515 n++;
516 l++;
517 continue;
519 case ')':
520 if (specp)
521 n++;
522 l--;
523 continue;
525 case '>':
526 case '<':
527 if (l != 0) {
528 if (specp)
529 n++;
530 continue;
532 if (p->next == p2)
533 continue;
534 if (any(p->next->word[0], RELPAR))
535 continue;
536 n--;
537 continue;
539 default:
540 if (!specp && l != 0)
541 continue;
542 n++;
543 continue;
545 if (n < 0)
546 n = 0;
547 t = (struct command *)xcalloc(1, sizeof (*t));
548 av = (tchar **)xcalloc((unsigned)(n + 1), sizeof (tchar **));
549 t->t_dcom = av;
550 n = 0;
551 if (p2->word[0] == ')')
552 t->t_dflg = FPAR;
553 lp = 0;
554 rp = 0;
555 l = 0;
556 for (p = p1; p != p2; p = p->next) {
557 c = p->word[0];
558 switch (c) {
560 case '(':
561 if (l == 0) {
562 if (lp != 0 && !specp)
563 seterr("Badly placed (");
564 lp = p->next;
566 l++;
567 goto savep;
569 case ')':
570 l--;
571 if (l == 0)
572 rp = p;
573 goto savep;
575 case '>':
576 if (l != 0)
577 goto savep;
578 if (p->word[1] == '>')
579 t->t_dflg |= FCAT;
580 if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) {
581 t->t_dflg |= FDIAG, p = p->next;
582 if (flags & (POUT|PDIAG))
583 goto badout;
585 if (p->next != p2 && eq(p->next->word, S_EXAS /* "!" */))
586 t->t_dflg |= FANY, p = p->next;
587 if (p->next == p2) {
588 missfile:
589 seterr("Missing name for redirect");
590 continue;
592 p = p->next;
593 if (any(p->word[0], RELPAR))
594 goto missfile;
595 if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
596 badout:
597 seterr("Ambiguous output redirect");
598 else
599 t->t_drit = savestr(p->word);
600 continue;
602 case '<':
603 if (l != 0)
604 goto savep;
605 if (p->word[1] == '<')
606 t->t_dflg |= FHERE;
607 if (p->next == p2)
608 goto missfile;
609 p = p->next;
610 if (any(p->word[0], RELPAR))
611 goto missfile;
612 if ((flags & PHERE) && (t->t_dflg & FHERE))
613 seterr("Can't << within ()'s");
614 else if ((flags & PIN) || t->t_dlef)
615 seterr("Ambiguous input redirect");
616 else
617 t->t_dlef = savestr(p->word);
618 continue;
620 savep:
621 if (!specp)
622 continue;
623 default:
624 if (l != 0 && !specp)
625 continue;
626 if (err == 0)
627 av[n] = savestr(p->word);
628 n++;
629 continue;
632 if (lp != 0 && !specp) {
633 if (n != 0)
634 seterr("Badly placed ()'s");
635 t->t_dtyp = TPAR;
636 t->t_dspr = syn0(lp, rp, PHERE);
637 } else {
638 if (n == 0)
639 seterr("Invalid null command");
640 t->t_dtyp = TCOM;
642 return (t);
645 void
646 freesyn(struct command *t)
648 #ifdef TRACE
649 tprintf("TRACE- freesyn()\n");
650 #endif
651 if (t == 0)
652 return;
653 switch (t->t_dtyp) {
655 case TCOM:
656 blkfree(t->t_dcom);
657 if (t->cfname)
658 xfree(t->cfname);
659 if (t->cargs)
660 chr_blkfree(t->cargs);
661 goto lr;
663 case TPAR:
664 freesyn(t->t_dspr);
665 /* fall into ... */
668 xfree(t->t_dlef);
669 xfree(t->t_drit);
670 break;
672 case TAND:
673 case TOR:
674 case TFIL:
675 case TLST:
676 freesyn(t->t_dcar), freesyn(t->t_dcdr);
677 break;
679 xfree(t);
683 void
684 chr_blkfree(char **vec)
686 char **av;
688 for (av = vec; *av; av++)
689 xfree(*av);
690 xfree(vec);