10Sstevel@tonic-gate /*
2356Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
70Sstevel@tonic-gate /* All Rights Reserved */
80Sstevel@tonic-gate
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
110Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
120Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
130Sstevel@tonic-gate */
140Sstevel@tonic-gate
150Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
160Sstevel@tonic-gate
170Sstevel@tonic-gate #include "sh.h"
180Sstevel@tonic-gate #include "sh.tconst.h"
190Sstevel@tonic-gate
200Sstevel@tonic-gate /*
210Sstevel@tonic-gate * C shell
220Sstevel@tonic-gate */
230Sstevel@tonic-gate
24356Smuffin void asyntax(struct wordent *, struct wordent *);
25356Smuffin void asyn0(struct wordent *, struct wordent *);
26356Smuffin void asyn3(struct wordent *, struct wordent *);
27356Smuffin void chr_blkfree(char **);
28356Smuffin struct command *syn0(struct wordent *, struct wordent *, int);
29356Smuffin struct command *syn1(struct wordent *, struct wordent *, int);
30356Smuffin struct command *syn1a(struct wordent *, struct wordent *, int);
31356Smuffin struct command *syn1b(struct wordent *, struct wordent *, int);
32356Smuffin struct command *syn2(struct wordent *, struct wordent *, int);
33356Smuffin struct command *syn3(struct wordent *, struct wordent *, int);
34356Smuffin struct wordent *freenod(struct wordent *, struct wordent *);
35356Smuffin
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate * Perform aliasing on the word list lex
380Sstevel@tonic-gate * Do a (very rudimentary) parse to separate into commands.
390Sstevel@tonic-gate * If word 0 of a command has an alias, do it.
400Sstevel@tonic-gate * Repeat a maximum of 20 times.
410Sstevel@tonic-gate */
42356Smuffin void
alias(struct wordent * lex)43356Smuffin alias(struct wordent *lex)
440Sstevel@tonic-gate {
450Sstevel@tonic-gate int aleft = 21;
460Sstevel@tonic-gate jmp_buf osetexit;
470Sstevel@tonic-gate
480Sstevel@tonic-gate #ifdef TRACE
490Sstevel@tonic-gate tprintf("TRACE- alias()\n");
500Sstevel@tonic-gate #endif
510Sstevel@tonic-gate getexit(osetexit);
520Sstevel@tonic-gate setexit();
530Sstevel@tonic-gate if (haderr) {
540Sstevel@tonic-gate resexit(osetexit);
550Sstevel@tonic-gate reset();
560Sstevel@tonic-gate }
570Sstevel@tonic-gate if (--aleft == 0)
580Sstevel@tonic-gate error("Alias loop");
590Sstevel@tonic-gate asyntax(lex->next, lex);
600Sstevel@tonic-gate resexit(osetexit);
610Sstevel@tonic-gate }
620Sstevel@tonic-gate
63356Smuffin void
asyntax(struct wordent * p1,struct wordent * p2)64356Smuffin asyntax(struct wordent *p1, struct wordent *p2)
650Sstevel@tonic-gate {
660Sstevel@tonic-gate #ifdef TRACE
670Sstevel@tonic-gate tprintf("TRACE- asyntax()\n");
680Sstevel@tonic-gate #endif
690Sstevel@tonic-gate
700Sstevel@tonic-gate while (p1 != p2)
710Sstevel@tonic-gate /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */
720Sstevel@tonic-gate if (p1->word[0] == ';' ||
730Sstevel@tonic-gate p1->word[0] == '&' ||
740Sstevel@tonic-gate p1->word[0] == '\n')
750Sstevel@tonic-gate p1 = p1->next;
760Sstevel@tonic-gate else {
770Sstevel@tonic-gate asyn0(p1, p2);
780Sstevel@tonic-gate return;
790Sstevel@tonic-gate }
800Sstevel@tonic-gate }
810Sstevel@tonic-gate
82356Smuffin void
asyn0(struct wordent * p1,struct wordent * p2)83356Smuffin asyn0(struct wordent *p1, struct wordent *p2)
840Sstevel@tonic-gate {
85356Smuffin struct wordent *p;
86356Smuffin int l = 0;
870Sstevel@tonic-gate
880Sstevel@tonic-gate #ifdef TRACE
890Sstevel@tonic-gate tprintf("TRACE- asyn0()\n");
900Sstevel@tonic-gate #endif
910Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
920Sstevel@tonic-gate switch (p->word[0]) {
930Sstevel@tonic-gate
940Sstevel@tonic-gate case '(':
950Sstevel@tonic-gate l++;
960Sstevel@tonic-gate continue;
970Sstevel@tonic-gate
980Sstevel@tonic-gate case ')':
990Sstevel@tonic-gate l--;
1000Sstevel@tonic-gate if (l < 0)
1010Sstevel@tonic-gate error("Too many )'s");
1020Sstevel@tonic-gate continue;
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate case '>':
1050Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/))
1060Sstevel@tonic-gate p = p->next;
1070Sstevel@tonic-gate continue;
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate case '&':
1100Sstevel@tonic-gate case '|':
1110Sstevel@tonic-gate case ';':
1120Sstevel@tonic-gate case '\n':
1130Sstevel@tonic-gate if (l != 0)
1140Sstevel@tonic-gate continue;
1150Sstevel@tonic-gate asyn3(p1, p);
1160Sstevel@tonic-gate asyntax(p->next, p2);
1170Sstevel@tonic-gate return;
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate if (l == 0)
1200Sstevel@tonic-gate asyn3(p1, p2);
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate
123356Smuffin void
asyn3(struct wordent * p1,struct wordent * p2)124356Smuffin asyn3(struct wordent *p1, struct wordent *p2)
1250Sstevel@tonic-gate {
126356Smuffin struct varent *ap;
1270Sstevel@tonic-gate struct wordent alout;
128356Smuffin bool redid;
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate #ifdef TRACE
1310Sstevel@tonic-gate tprintf("TRACE- asyn3()\n");
1320Sstevel@tonic-gate #endif
1330Sstevel@tonic-gate if (p1 == p2)
1340Sstevel@tonic-gate return;
1350Sstevel@tonic-gate if (p1->word[0] == '(') {
1360Sstevel@tonic-gate for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
1370Sstevel@tonic-gate if (p2 == p1)
1380Sstevel@tonic-gate return;
1390Sstevel@tonic-gate if (p2 == p1->next)
1400Sstevel@tonic-gate return;
1410Sstevel@tonic-gate asyn0(p1->next, p2);
1420Sstevel@tonic-gate return;
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate ap = adrof1(p1->word, &aliases);
1450Sstevel@tonic-gate if (ap == 0)
1460Sstevel@tonic-gate return;
1470Sstevel@tonic-gate alhistp = p1->prev;
1480Sstevel@tonic-gate alhistt = p2;
1490Sstevel@tonic-gate alvec = ap->vec;
1500Sstevel@tonic-gate redid = lex(&alout);
1510Sstevel@tonic-gate alhistp = alhistt = 0;
1520Sstevel@tonic-gate alvec = 0;
1530Sstevel@tonic-gate if (err) {
1540Sstevel@tonic-gate freelex(&alout);
1550Sstevel@tonic-gate error("%s", gettext(err));
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate if (p1->word[0] && eq(p1->word, alout.next->word)) {
1580Sstevel@tonic-gate tchar *cp = alout.next->word;
1590Sstevel@tonic-gate
160*559Snakanon alout.next->word = strspl(S_TOPBIT /* "\200" */, cp);
161*559Snakanon xfree(cp);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate p1 = freenod(p1, redid ? p2 : p1->next);
1640Sstevel@tonic-gate if (alout.next != &alout) {
1650Sstevel@tonic-gate p1->next->prev = alout.prev->prev;
1660Sstevel@tonic-gate alout.prev->prev->next = p1->next;
1670Sstevel@tonic-gate alout.next->prev = p1;
1680Sstevel@tonic-gate p1->next = alout.next;
169*559Snakanon xfree(alout.prev->word);
170*559Snakanon xfree(alout.prev);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate reset(); /* throw! */
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate struct wordent *
freenod(struct wordent * p1,struct wordent * p2)176356Smuffin freenod(struct wordent *p1, struct wordent *p2)
1770Sstevel@tonic-gate {
178356Smuffin struct wordent *retp = p1->prev;
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate #ifdef TRACE
1810Sstevel@tonic-gate tprintf("TRACE- freenod()\n");
1820Sstevel@tonic-gate #endif
1830Sstevel@tonic-gate while (p1 != p2) {
184*559Snakanon xfree(p1->word);
1850Sstevel@tonic-gate p1 = p1->next;
186*559Snakanon xfree(p1->prev);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate retp->next = p2;
1890Sstevel@tonic-gate p2->prev = retp;
1900Sstevel@tonic-gate return (retp);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate #define PHERE 1
1940Sstevel@tonic-gate #define PIN 2
1950Sstevel@tonic-gate #define POUT 4
1960Sstevel@tonic-gate #define PDIAG 8
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate /*
1990Sstevel@tonic-gate * syntax
2000Sstevel@tonic-gate * empty
2010Sstevel@tonic-gate * syn0
2020Sstevel@tonic-gate */
2030Sstevel@tonic-gate struct command *
syntax(struct wordent * p1,struct wordent * p2,int flags)204356Smuffin syntax(struct wordent *p1, struct wordent *p2, int flags)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate #ifdef TRACE
2070Sstevel@tonic-gate tprintf("TRACE- syntax()\n");
2080Sstevel@tonic-gate #endif
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate while (p1 != p2)
2110Sstevel@tonic-gate /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */
2120Sstevel@tonic-gate if (p1->word[0] == ';' ||
2130Sstevel@tonic-gate p1->word[0] == '&' ||
2140Sstevel@tonic-gate p1->word[0] == '\n')
2150Sstevel@tonic-gate p1 = p1->next;
2160Sstevel@tonic-gate else
2170Sstevel@tonic-gate return (syn0(p1, p2, flags));
2180Sstevel@tonic-gate return (0);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /*
2220Sstevel@tonic-gate * syn0
2230Sstevel@tonic-gate * syn1
2240Sstevel@tonic-gate * syn1 & syntax
2250Sstevel@tonic-gate */
2260Sstevel@tonic-gate struct command *
syn0(struct wordent * p1,struct wordent * p2,int flags)227356Smuffin syn0(struct wordent *p1, struct wordent *p2, int flags)
2280Sstevel@tonic-gate {
229356Smuffin struct wordent *p;
230356Smuffin struct command *t, *t1;
2310Sstevel@tonic-gate int l;
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate #ifdef TRACE
2340Sstevel@tonic-gate tprintf("TRACE- syn0()\n");
2350Sstevel@tonic-gate #endif
2360Sstevel@tonic-gate l = 0;
2370Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
2380Sstevel@tonic-gate switch (p->word[0]) {
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate case '(':
2410Sstevel@tonic-gate l++;
2420Sstevel@tonic-gate continue;
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate case ')':
2450Sstevel@tonic-gate l--;
2460Sstevel@tonic-gate if (l < 0)
2470Sstevel@tonic-gate seterr("Too many )'s");
2480Sstevel@tonic-gate continue;
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate case '|':
2510Sstevel@tonic-gate if (p->word[1] == '|')
2520Sstevel@tonic-gate continue;
2530Sstevel@tonic-gate /* fall into ... */
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate case '>':
256*559Snakanon if (p->next != p2 && eq(p->next->word, S_AND /* "&" */))
2570Sstevel@tonic-gate p = p->next;
2580Sstevel@tonic-gate continue;
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate case '&':
2610Sstevel@tonic-gate if (l != 0)
2620Sstevel@tonic-gate break;
2630Sstevel@tonic-gate if (p->word[1] == '&')
2640Sstevel@tonic-gate continue;
2650Sstevel@tonic-gate t1 = syn1(p1, p, flags);
2660Sstevel@tonic-gate if (t1->t_dtyp == TLST ||
267*559Snakanon t1->t_dtyp == TAND ||
268*559Snakanon t1->t_dtyp == TOR) {
269*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
2700Sstevel@tonic-gate t->t_dtyp = TPAR;
2710Sstevel@tonic-gate t->t_dflg = FAND|FINT;
2720Sstevel@tonic-gate t->t_dspr = t1;
2730Sstevel@tonic-gate t1 = t;
2740Sstevel@tonic-gate } else
2750Sstevel@tonic-gate t1->t_dflg |= FAND|FINT;
276*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
2770Sstevel@tonic-gate t->t_dtyp = TLST;
2780Sstevel@tonic-gate t->t_dflg = 0;
2790Sstevel@tonic-gate t->t_dcar = t1;
2800Sstevel@tonic-gate t->t_dcdr = syntax(p, p2, flags);
281*559Snakanon return (t);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate if (l == 0)
2840Sstevel@tonic-gate return (syn1(p1, p2, flags));
2850Sstevel@tonic-gate seterr("Too many ('s");
2860Sstevel@tonic-gate return (0);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate /*
2900Sstevel@tonic-gate * syn1
2910Sstevel@tonic-gate * syn1a
2920Sstevel@tonic-gate * syn1a ; syntax
2930Sstevel@tonic-gate */
2940Sstevel@tonic-gate struct command *
syn1(struct wordent * p1,struct wordent * p2,int flags)295356Smuffin syn1(struct wordent *p1, struct wordent *p2, int flags)
2960Sstevel@tonic-gate {
297356Smuffin struct wordent *p;
298356Smuffin struct command *t;
2990Sstevel@tonic-gate int l;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate #ifdef TRACE
3020Sstevel@tonic-gate tprintf("TRACE- syn1()\n");
3030Sstevel@tonic-gate #endif
3040Sstevel@tonic-gate l = 0;
3050Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
3060Sstevel@tonic-gate switch (p->word[0]) {
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate case '(':
3090Sstevel@tonic-gate l++;
3100Sstevel@tonic-gate continue;
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate case ')':
3130Sstevel@tonic-gate l--;
3140Sstevel@tonic-gate continue;
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate case ';':
3170Sstevel@tonic-gate case '\n':
3180Sstevel@tonic-gate if (l != 0)
3190Sstevel@tonic-gate break;
320*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
3210Sstevel@tonic-gate t->t_dtyp = TLST;
3220Sstevel@tonic-gate t->t_dcar = syn1a(p1, p, flags);
3230Sstevel@tonic-gate t->t_dcdr = syntax(p->next, p2, flags);
3240Sstevel@tonic-gate if (t->t_dcdr == 0)
3250Sstevel@tonic-gate t->t_dcdr = t->t_dcar, t->t_dcar = 0;
3260Sstevel@tonic-gate return (t);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate return (syn1a(p1, p2, flags));
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate /*
3320Sstevel@tonic-gate * syn1a
3330Sstevel@tonic-gate * syn1b
3340Sstevel@tonic-gate * syn1b || syn1a
3350Sstevel@tonic-gate */
3360Sstevel@tonic-gate struct command *
syn1a(struct wordent * p1,struct wordent * p2,int flags)337356Smuffin syn1a(struct wordent *p1, struct wordent *p2, int flags)
3380Sstevel@tonic-gate {
339356Smuffin struct wordent *p;
340356Smuffin struct command *t;
341356Smuffin int l = 0;
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate #ifdef TRACE
3440Sstevel@tonic-gate tprintf("TRACE- syn1a()\n");
3450Sstevel@tonic-gate #endif
3460Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
3470Sstevel@tonic-gate switch (p->word[0]) {
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate case '(':
3500Sstevel@tonic-gate l++;
3510Sstevel@tonic-gate continue;
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate case ')':
3540Sstevel@tonic-gate l--;
3550Sstevel@tonic-gate continue;
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate case '|':
3580Sstevel@tonic-gate if (p->word[1] != '|')
3590Sstevel@tonic-gate continue;
3600Sstevel@tonic-gate if (l == 0) {
361*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
3620Sstevel@tonic-gate t->t_dtyp = TOR;
3630Sstevel@tonic-gate t->t_dcar = syn1b(p1, p, flags);
3640Sstevel@tonic-gate t->t_dcdr = syn1a(p->next, p2, flags);
3650Sstevel@tonic-gate t->t_dflg = 0;
3660Sstevel@tonic-gate return (t);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate continue;
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate return (syn1b(p1, p2, flags));
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate /*
3740Sstevel@tonic-gate * syn1b
3750Sstevel@tonic-gate * syn2
3760Sstevel@tonic-gate * syn2 && syn1b
3770Sstevel@tonic-gate */
3780Sstevel@tonic-gate struct command *
syn1b(struct wordent * p1,struct wordent * p2,int flags)379356Smuffin syn1b(struct wordent *p1, struct wordent *p2, int flags)
3800Sstevel@tonic-gate {
381356Smuffin struct wordent *p;
382356Smuffin struct command *t;
383356Smuffin int l = 0;
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate #ifdef TRACE
3860Sstevel@tonic-gate tprintf("TRACE- syn1b()\n");
3870Sstevel@tonic-gate #endif
3880Sstevel@tonic-gate l = 0;
3890Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
3900Sstevel@tonic-gate switch (p->word[0]) {
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate case '(':
3930Sstevel@tonic-gate l++;
3940Sstevel@tonic-gate continue;
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate case ')':
3970Sstevel@tonic-gate l--;
3980Sstevel@tonic-gate continue;
3990Sstevel@tonic-gate
4000Sstevel@tonic-gate case '&':
4010Sstevel@tonic-gate if (p->word[1] == '&' && l == 0) {
402*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
4030Sstevel@tonic-gate t->t_dtyp = TAND;
4040Sstevel@tonic-gate t->t_dcar = syn2(p1, p, flags);
4050Sstevel@tonic-gate t->t_dcdr = syn1b(p->next, p2, flags);
4060Sstevel@tonic-gate t->t_dflg = 0;
4070Sstevel@tonic-gate return (t);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate continue;
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate return (syn2(p1, p2, flags));
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate /*
4150Sstevel@tonic-gate * syn2
4160Sstevel@tonic-gate * syn3
4170Sstevel@tonic-gate * syn3 | syn2
4180Sstevel@tonic-gate * syn3 |& syn2
4190Sstevel@tonic-gate */
4200Sstevel@tonic-gate struct command *
syn2(struct wordent * p1,struct wordent * p2,int flags)421356Smuffin syn2(struct wordent *p1, struct wordent *p2, int flags)
4220Sstevel@tonic-gate {
423356Smuffin struct wordent *p, *pn;
424356Smuffin struct command *t;
425356Smuffin int l = 0;
4260Sstevel@tonic-gate int f;
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate #ifdef TRACE
4290Sstevel@tonic-gate tprintf("TRACE- syn2()\n");
4300Sstevel@tonic-gate #endif
4310Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
4320Sstevel@tonic-gate switch (p->word[0]) {
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate case '(':
4350Sstevel@tonic-gate l++;
4360Sstevel@tonic-gate continue;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate case ')':
4390Sstevel@tonic-gate l--;
4400Sstevel@tonic-gate continue;
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate case '|':
4430Sstevel@tonic-gate if (l != 0)
4440Sstevel@tonic-gate continue;
445*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
4460Sstevel@tonic-gate f = flags | POUT;
4470Sstevel@tonic-gate pn = p->next;
4480Sstevel@tonic-gate if (pn != p2 && pn->word[0] == '&') {
4490Sstevel@tonic-gate f |= PDIAG;
4500Sstevel@tonic-gate t->t_dflg |= FDIAG;
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate t->t_dtyp = TFIL;
4530Sstevel@tonic-gate t->t_dcar = syn3(p1, p, f);
4540Sstevel@tonic-gate if (pn != p2 && pn->word[0] == '&')
4550Sstevel@tonic-gate p = pn;
4560Sstevel@tonic-gate t->t_dcdr = syn2(p->next, p2, flags | PIN);
4570Sstevel@tonic-gate return (t);
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate return (syn3(p1, p2, flags));
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate tchar RELPAR[] = {'<', '>', '(', ')', 0}; /* "<>()" */
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate /*
4650Sstevel@tonic-gate * syn3
4660Sstevel@tonic-gate * ( syn0 ) [ < in ] [ > out ]
4670Sstevel@tonic-gate * word word* [ < in ] [ > out ]
4680Sstevel@tonic-gate * KEYWORD ( word* ) word* [ < in ] [ > out ]
4690Sstevel@tonic-gate *
4700Sstevel@tonic-gate * KEYWORD = (@ exit foreach if set switch test while)
4710Sstevel@tonic-gate */
4720Sstevel@tonic-gate struct command *
syn3(struct wordent * p1,struct wordent * p2,int flags)473356Smuffin syn3(struct wordent *p1, struct wordent *p2, int flags)
4740Sstevel@tonic-gate {
475356Smuffin struct wordent *p;
4760Sstevel@tonic-gate struct wordent *lp, *rp;
477356Smuffin struct command *t;
478356Smuffin int l;
4790Sstevel@tonic-gate tchar **av;
4800Sstevel@tonic-gate int n, c;
4810Sstevel@tonic-gate bool specp = 0;
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate #ifdef TRACE
4840Sstevel@tonic-gate tprintf("TRACE- syn3()\n");
4850Sstevel@tonic-gate #endif
4860Sstevel@tonic-gate if (p1 != p2) {
4870Sstevel@tonic-gate p = p1;
4880Sstevel@tonic-gate again:
4890Sstevel@tonic-gate switch (srchx(p->word)) {
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate case ZELSE:
4920Sstevel@tonic-gate p = p->next;
4930Sstevel@tonic-gate if (p != p2)
4940Sstevel@tonic-gate goto again;
4950Sstevel@tonic-gate break;
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate case ZEXIT:
4980Sstevel@tonic-gate case ZFOREACH:
4990Sstevel@tonic-gate case ZIF:
5000Sstevel@tonic-gate case ZLET:
5010Sstevel@tonic-gate case ZSET:
5020Sstevel@tonic-gate case ZSWITCH:
5030Sstevel@tonic-gate case ZWHILE:
5040Sstevel@tonic-gate specp = 1;
5050Sstevel@tonic-gate break;
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate n = 0;
5090Sstevel@tonic-gate l = 0;
5100Sstevel@tonic-gate for (p = p1; p != p2; p = p->next)
5110Sstevel@tonic-gate switch (p->word[0]) {
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate case '(':
5140Sstevel@tonic-gate if (specp)
5150Sstevel@tonic-gate n++;
5160Sstevel@tonic-gate l++;
5170Sstevel@tonic-gate continue;
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate case ')':
5200Sstevel@tonic-gate if (specp)
5210Sstevel@tonic-gate n++;
5220Sstevel@tonic-gate l--;
5230Sstevel@tonic-gate continue;
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate case '>':
5260Sstevel@tonic-gate case '<':
5270Sstevel@tonic-gate if (l != 0) {
5280Sstevel@tonic-gate if (specp)
5290Sstevel@tonic-gate n++;
5300Sstevel@tonic-gate continue;
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate if (p->next == p2)
5330Sstevel@tonic-gate continue;
5340Sstevel@tonic-gate if (any(p->next->word[0], RELPAR))
5350Sstevel@tonic-gate continue;
5360Sstevel@tonic-gate n--;
5370Sstevel@tonic-gate continue;
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate default:
5400Sstevel@tonic-gate if (!specp && l != 0)
5410Sstevel@tonic-gate continue;
5420Sstevel@tonic-gate n++;
5430Sstevel@tonic-gate continue;
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate if (n < 0)
5460Sstevel@tonic-gate n = 0;
547*559Snakanon t = (struct command *)xcalloc(1, sizeof (*t));
548*559Snakanon av = (tchar **)xcalloc((unsigned)(n + 1), sizeof (tchar **));
5490Sstevel@tonic-gate t->t_dcom = av;
5500Sstevel@tonic-gate n = 0;
5510Sstevel@tonic-gate if (p2->word[0] == ')')
5520Sstevel@tonic-gate t->t_dflg = FPAR;
5530Sstevel@tonic-gate lp = 0;
5540Sstevel@tonic-gate rp = 0;
5550Sstevel@tonic-gate l = 0;
5560Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) {
5570Sstevel@tonic-gate c = p->word[0];
5580Sstevel@tonic-gate switch (c) {
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate case '(':
5610Sstevel@tonic-gate if (l == 0) {
5620Sstevel@tonic-gate if (lp != 0 && !specp)
5630Sstevel@tonic-gate seterr("Badly placed (");
5640Sstevel@tonic-gate lp = p->next;
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate l++;
5670Sstevel@tonic-gate goto savep;
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate case ')':
5700Sstevel@tonic-gate l--;
5710Sstevel@tonic-gate if (l == 0)
5720Sstevel@tonic-gate rp = p;
5730Sstevel@tonic-gate goto savep;
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate case '>':
5760Sstevel@tonic-gate if (l != 0)
5770Sstevel@tonic-gate goto savep;
5780Sstevel@tonic-gate if (p->word[1] == '>')
5790Sstevel@tonic-gate t->t_dflg |= FCAT;
580*559Snakanon if (p->next != p2 && eq(p->next->word, S_AND /* "&" */)) {
5810Sstevel@tonic-gate t->t_dflg |= FDIAG, p = p->next;
5820Sstevel@tonic-gate if (flags & (POUT|PDIAG))
5830Sstevel@tonic-gate goto badout;
5840Sstevel@tonic-gate }
585*559Snakanon if (p->next != p2 && eq(p->next->word, S_EXAS /* "!" */))
5860Sstevel@tonic-gate t->t_dflg |= FANY, p = p->next;
5870Sstevel@tonic-gate if (p->next == p2) {
5880Sstevel@tonic-gate missfile:
5890Sstevel@tonic-gate seterr("Missing name for redirect");
5900Sstevel@tonic-gate continue;
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate p = p->next;
5930Sstevel@tonic-gate if (any(p->word[0], RELPAR))
5940Sstevel@tonic-gate goto missfile;
5950Sstevel@tonic-gate if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
5960Sstevel@tonic-gate badout:
5970Sstevel@tonic-gate seterr("Ambiguous output redirect");
5980Sstevel@tonic-gate else
5990Sstevel@tonic-gate t->t_drit = savestr(p->word);
6000Sstevel@tonic-gate continue;
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate case '<':
6030Sstevel@tonic-gate if (l != 0)
6040Sstevel@tonic-gate goto savep;
6050Sstevel@tonic-gate if (p->word[1] == '<')
6060Sstevel@tonic-gate t->t_dflg |= FHERE;
6070Sstevel@tonic-gate if (p->next == p2)
6080Sstevel@tonic-gate goto missfile;
6090Sstevel@tonic-gate p = p->next;
6100Sstevel@tonic-gate if (any(p->word[0], RELPAR))
6110Sstevel@tonic-gate goto missfile;
6120Sstevel@tonic-gate if ((flags & PHERE) && (t->t_dflg & FHERE))
6130Sstevel@tonic-gate seterr("Can't << within ()'s");
6140Sstevel@tonic-gate else if ((flags & PIN) || t->t_dlef)
6150Sstevel@tonic-gate seterr("Ambiguous input redirect");
6160Sstevel@tonic-gate else
6170Sstevel@tonic-gate t->t_dlef = savestr(p->word);
6180Sstevel@tonic-gate continue;
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate savep:
6210Sstevel@tonic-gate if (!specp)
6220Sstevel@tonic-gate continue;
6230Sstevel@tonic-gate default:
6240Sstevel@tonic-gate if (l != 0 && !specp)
6250Sstevel@tonic-gate continue;
6260Sstevel@tonic-gate if (err == 0)
6270Sstevel@tonic-gate av[n] = savestr(p->word);
6280Sstevel@tonic-gate n++;
6290Sstevel@tonic-gate continue;
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate if (lp != 0 && !specp) {
6330Sstevel@tonic-gate if (n != 0)
6340Sstevel@tonic-gate seterr("Badly placed ()'s");
6350Sstevel@tonic-gate t->t_dtyp = TPAR;
6360Sstevel@tonic-gate t->t_dspr = syn0(lp, rp, PHERE);
6370Sstevel@tonic-gate } else {
6380Sstevel@tonic-gate if (n == 0)
6390Sstevel@tonic-gate seterr("Invalid null command");
6400Sstevel@tonic-gate t->t_dtyp = TCOM;
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate return (t);
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate
645356Smuffin void
freesyn(struct command * t)646356Smuffin freesyn(struct command *t)
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate #ifdef TRACE
6490Sstevel@tonic-gate tprintf("TRACE- freesyn()\n");
6500Sstevel@tonic-gate #endif
6510Sstevel@tonic-gate if (t == 0)
6520Sstevel@tonic-gate return;
6530Sstevel@tonic-gate switch (t->t_dtyp) {
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate case TCOM:
6560Sstevel@tonic-gate blkfree(t->t_dcom);
6570Sstevel@tonic-gate if (t->cfname)
6580Sstevel@tonic-gate xfree(t->cfname);
6590Sstevel@tonic-gate if (t->cargs)
6600Sstevel@tonic-gate chr_blkfree(t->cargs);
6610Sstevel@tonic-gate goto lr;
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate case TPAR:
6640Sstevel@tonic-gate freesyn(t->t_dspr);
6650Sstevel@tonic-gate /* fall into ... */
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate lr:
668*559Snakanon xfree(t->t_dlef);
669*559Snakanon xfree(t->t_drit);
6700Sstevel@tonic-gate break;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate case TAND:
6730Sstevel@tonic-gate case TOR:
6740Sstevel@tonic-gate case TFIL:
6750Sstevel@tonic-gate case TLST:
6760Sstevel@tonic-gate freesyn(t->t_dcar), freesyn(t->t_dcdr);
6770Sstevel@tonic-gate break;
6780Sstevel@tonic-gate }
679*559Snakanon xfree(t);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate
683356Smuffin void
chr_blkfree(char ** vec)684356Smuffin chr_blkfree(char **vec)
6850Sstevel@tonic-gate {
686356Smuffin char **av;
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate for (av = vec; *av; av++)
6890Sstevel@tonic-gate xfree(*av);
6900Sstevel@tonic-gate xfree(vec);
6910Sstevel@tonic-gate }
692