sh.parse.c revision 145479
134840Sjlemon/* $Header: /src/pub/tcsh/sh.parse.c,v 3.13 2004/11/23 02:10:49 christos Exp $ */
234840Sjlemon/*
334840Sjlemon * sh.parse.c: Interpret a list of tokens
434840Sjlemon */
534840Sjlemon/*-
634840Sjlemon * Copyright (c) 1980, 1991 The Regents of the University of California.
734840Sjlemon * All rights reserved.
834840Sjlemon *
934840Sjlemon * Redistribution and use in source and binary forms, with or without
1034840Sjlemon * modification, are permitted provided that the following conditions
1134840Sjlemon * are met:
1234840Sjlemon * 1. Redistributions of source code must retain the above copyright
1334840Sjlemon *    notice, this list of conditions and the following disclaimer.
1434840Sjlemon * 2. Redistributions in binary form must reproduce the above copyright
1534840Sjlemon *    notice, this list of conditions and the following disclaimer in the
1634840Sjlemon *    documentation and/or other materials provided with the distribution.
1734840Sjlemon * 3. Neither the name of the University nor the names of its contributors
1834840Sjlemon *    may be used to endorse or promote products derived from this software
1934840Sjlemon *    without specific prior written permission.
2034840Sjlemon *
2134840Sjlemon * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2234840Sjlemon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2334840Sjlemon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2434840Sjlemon * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2534840Sjlemon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2650477Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2734840Sjlemon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2834840Sjlemon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2971257Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3071256Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3134840Sjlemon * SUCH DAMAGE.
3234840Sjlemon */
3334840Sjlemon#include "sh.h"
3434840Sjlemon
3534840SjlemonRCSID("$Id: sh.parse.c,v 3.13 2004/11/23 02:10:49 christos Exp $")
3637889Sjlemon
3737889Sjlemon/*
3837889Sjlemon * C shell
3937889Sjlemon */
4037889Sjlemonstatic	void		 asyntax __P((struct wordent *, struct wordent *));
41145025Speterstatic	void		 asyn0 	 __P((struct wordent *, struct wordent *));
42145025Speterstatic	void		 asyn3	 __P((struct wordent *, struct wordent *));
4337889Sjlemonstatic	struct wordent	*freenod __P((struct wordent *, struct wordent *));
4434840Sjlemonstatic	struct command	*syn0	 __P((struct wordent *, struct wordent *, int));
4534840Sjlemonstatic	struct command	*syn1	 __P((struct wordent *, struct wordent *, int));
4634840Sjlemonstatic	struct command	*syn1a	 __P((struct wordent *, struct wordent *, int));
47106542Sdavidxustatic	struct command	*syn1b	 __P((struct wordent *, struct wordent *, int));
4834840Sjlemonstatic	struct command	*syn2	 __P((struct wordent *, struct wordent *, int));
4973011Sjakestatic	struct command	*syn3	 __P((struct wordent *, struct wordent *, int));
5034840Sjlemon
5134840Sjlemon#define ALEFT	51		/* max of 50 alias expansions	 */
5234840Sjlemon#define HLEFT	11		/* max of 10 history expansions */
5334840Sjlemon/*
5434840Sjlemon * Perform aliasing on the word list lexp
5534840Sjlemon * Do a (very rudimentary) parse to separate into commands.
5634840Sjlemon * If word 0 of a command has an alias, do it.
5773011Sjake * Repeat a maximum of 50 times.
5834840Sjlemon */
5937889Sjlemonstatic int aleft;
6034840Sjlemonextern int hleft;
6134840Sjlemonvoid
6234840Sjlemonalias(lexp)
6334840Sjlemon    struct wordent *lexp;
6434840Sjlemon{
6534840Sjlemon    jmp_buf_t osetexit;
6671257Speter
6776904Sbde    aleft = ALEFT;
6876904Sbde    hleft = HLEFT;
6983366Sjulian    getexit(osetexit);
7087702Sjhb    (void) setexit();
7134840Sjlemon    if (haderr) {
7239872Sjlemon	resexit(osetexit);
7339872Sjlemon	reset();
7439046Syokota    }
7583366Sjulian    if (--aleft == 0)
76217587Sjkim	stderror(ERR_ALIASLOOP);
7773011Sjake    asyntax(lexp->next, lexp);
78217587Sjkim    resexit(osetexit);
7934840Sjlemon}
8076904Sbde
8176904Sbdestatic void
8234840Sjlemonasyntax(p1, p2)
8334840Sjlemon    struct wordent *p1, *p2;
8437889Sjlemon{
8534840Sjlemon    while (p1 != p2)
8637889Sjlemon	if (any(";&\n", p1->word[0]))
8747080Sluoqi	    p1 = p1->next;
8834840Sjlemon	else {
8934840Sjlemon	    asyn0(p1, p2);
9034840Sjlemon	    return;
9134840Sjlemon	}
9269971Sjake}
9334840Sjlemon
9469971Sjakestatic void
9534840Sjlemonasyn0(p1, p2)
9669971Sjake    struct wordent *p1;
9734840Sjlemon    struct wordent *p2;
9837889Sjlemon{
9934840Sjlemon    struct wordent *p;
10034840Sjlemon    int l = 0;
10137889Sjlemon
10234840Sjlemon    for (p = p1; p != p2; p = p->next)
10334840Sjlemon	switch (p->word[0]) {
10434840Sjlemon
10534840Sjlemon	case '(':
10634840Sjlemon	    l++;
10734840Sjlemon	    continue;
10847081Sluoqi
10934840Sjlemon	case ')':
11034840Sjlemon	    l--;
11134840Sjlemon	    if (l < 0)
11234840Sjlemon		stderror(ERR_TOOMANYRP);
11373011Sjake	    continue;
11434840Sjlemon
11534840Sjlemon	case '>':
11634840Sjlemon	    if (p->next != p2 && eq(p->next->word, STRand))
11734840Sjlemon		p = p->next;
11834840Sjlemon	    continue;
11934840Sjlemon
12037889Sjlemon	case '&':
12134840Sjlemon	case '|':
12237889Sjlemon	case ';':
12334840Sjlemon	case '\n':
12434840Sjlemon	    if (l != 0)
125282065Skib		continue;
126112841Sjake	    asyn3(p1, p);
127112841Sjake	    asyntax(p->next, p2);
12834840Sjlemon	    return;
12937889Sjlemon
130165302Skmacy	default:
131165302Skmacy	    break;
132165302Skmacy	}
133165302Skmacy    if (l == 0)
13434840Sjlemon	asyn3(p1, p2);
13534840Sjlemon}
13673011Sjake
13734840Sjlemonstatic void
13834840Sjlemonasyn3(p1, p2)
13973011Sjake    struct wordent *p1;
14034840Sjlemon    struct wordent *p2;
14134840Sjlemon{
14234840Sjlemon    struct varent *ap;
14334840Sjlemon    struct wordent alout;
14434840Sjlemon    int redid;
14534840Sjlemon
14673011Sjake    if (p1 == p2)
14734840Sjlemon	return;
14834840Sjlemon    if (p1->word[0] == '(') {
14937889Sjlemon	for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
15047080Sluoqi	    if (p2 == p1)
15134840Sjlemon		return;
15234840Sjlemon	if (p2 == p1->next)
15334840Sjlemon	    return;
15434840Sjlemon	asyn0(p1->next, p2);
15537889Sjlemon	return;
15634840Sjlemon    }
15734840Sjlemon    ap = adrof1(p1->word, &aliases);
15834840Sjlemon    if (ap == 0)
15934840Sjlemon	return;
16034840Sjlemon    alhistp = p1->prev;
16134840Sjlemon    alhistt = p2;
16269971Sjake    alvec = ap->vec;
16337889Sjlemon    redid = lex(&alout);
16434840Sjlemon    alhistp = alhistt = 0;
16537889Sjlemon    alvec = 0;
16634840Sjlemon    if (seterr) {
16747081Sluoqi	freelex(&alout);
16834840Sjlemon	stderror(ERR_OLD);
16934840Sjlemon    }
17069971Sjake    if (p1->word[0] && eq(p1->word, alout.next->word)) {
17137889Sjlemon	Char   *cp = alout.next->word;
17234840Sjlemon
17334840Sjlemon	alout.next->word = Strspl(STRQNULL, cp);
17434840Sjlemon	xfree((ptr_t) cp);
17534840Sjlemon    }
17634840Sjlemon    p1 = freenod(p1, redid ? p2 : p1->next);
17734840Sjlemon    if (alout.next != &alout) {
17834840Sjlemon	p1->next->prev = alout.prev->prev;
17934840Sjlemon	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));
184    }
185    reset();			/* throw! */
186}
187
188static struct wordent *
189freenod(p1, p2)
190    struct wordent *p1, *p2;
191{
192    struct wordent *retp = p1->prev;
193
194    while (p1 != p2) {
195	xfree((ptr_t) p1->word);
196	p1 = p1->next;
197	xfree((ptr_t) (p1->prev));
198    }
199    retp->next = p2;
200    p2->prev = retp;
201    return (retp);
202}
203
204#define	P_HERE	1
205#define	P_IN	2
206#define	P_OUT	4
207#define	P_DIAG	8
208
209/*
210 * syntax
211 *	empty
212 *	syn0
213 */
214struct command *
215syntax(p1, p2, flags)
216    struct wordent *p1, *p2;
217    int     flags;
218{
219
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);
226}
227
228/*
229 * syn0
230 *	syn1
231 *	syn1 & syntax
232 */
233static struct command *
234syn0(p1, p2, flags)
235    struct wordent *p1, *p2;
236    int     flags;
237{
238    struct wordent *p;
239    struct command *t, *t1;
240    int     l;
241
242    l = 0;
243    for (p = p1; p != p2; p = p->next)
244	switch (p->word[0]) {
245
246	case '(':
247	    l++;
248	    continue;
249
250	case ')':
251	    l--;
252	    if (l < 0)
253		seterror(ERR_TOOMANYRP);
254	    continue;
255
256	case '|':
257	    if (p->word[1] == '|')
258		continue;
259	    /*FALLTHROUGH*/
260
261	case '>':
262	    if (p->next != p2 && eq(p->next->word, STRand))
263		p = p->next;
264	    continue;
265
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;
280	    }
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;
291	}
292    if (l == 0)
293	return (syn1(p1, p2, flags));
294    seterror(ERR_TOOMANYLP);
295    return (0);
296}
297
298/*
299 * syn1
300 *	syn1a
301 *	syn1a ; syntax
302 */
303static struct command *
304syn1(p1, p2, flags)
305    struct wordent *p1, *p2;
306    int     flags;
307{
308    struct wordent *p;
309    struct command *t;
310    int     l;
311
312    l = 0;
313    for (p = p1; p != p2; p = p->next)
314	switch (p->word[0]) {
315
316	case '(':
317	    l++;
318	    continue;
319
320	case ')':
321	    l--;
322	    continue;
323
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);
335
336	default:
337	    break;
338	}
339    return (syn1a(p1, p2, flags));
340}
341
342/*
343 * syn1a
344 *	syn1b
345 *	syn1b || syn1a
346 */
347static struct command *
348syn1a(p1, p2, flags)
349    struct wordent *p1, *p2;
350    int     flags;
351{
352    struct wordent *p;
353    struct command *t;
354    int l = 0;
355
356    for (p = p1; p != p2; p = p->next)
357	switch (p->word[0]) {
358
359	case '(':
360	    l++;
361	    continue;
362
363	case ')':
364	    l--;
365	    continue;
366
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);
377	    }
378	    continue;
379
380	default:
381	    break;
382	}
383    return (syn1b(p1, p2, flags));
384}
385
386/*
387 * syn1b
388 *	syn2
389 *	syn2 && syn1b
390 */
391static struct command *
392syn1b(p1, p2, flags)
393    struct wordent *p1, *p2;
394    int     flags;
395{
396    struct wordent *p;
397    struct command *t;
398    int l = 0;
399
400    for (p = p1; p != p2; p = p->next)
401	switch (p->word[0]) {
402
403	case '(':
404	    l++;
405	    continue;
406
407	case ')':
408	    l--;
409	    continue;
410
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);
419	    }
420	    continue;
421
422	default:
423	    break;
424	}
425    return (syn2(p1, p2, flags));
426}
427
428/*
429 * syn2
430 *	syn3
431 *	syn3 | syn2
432 *	syn3 |& syn2
433 */
434static struct command *
435syn2(p1, p2, flags)
436    struct wordent *p1, *p2;
437    int     flags;
438{
439    struct wordent *p, *pn;
440    struct command *t;
441    int l = 0;
442    int     f;
443
444    for (p = p1; p != p2; p = p->next)
445	switch (p->word[0]) {
446
447	case '(':
448	    l++;
449	    continue;
450
451	case ')':
452	    l--;
453	    continue;
454
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;
464	    }
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);
471
472	default:
473	    break;
474	}
475    return (syn3(p1, p2, flags));
476}
477
478static char RELPAR[] = {'<', '>', '(', ')', '\0'};
479
480/*
481 * syn3
482 *	( syn0 ) [ < in  ] [ > out ]
483 *	word word* [ < in ] [ > out ]
484 *	KEYWORD ( word* ) word* [ < in ] [ > out ]
485 *
486 *	KEYWORD = (@ exit foreach if set switch test while)
487 */
488static struct command *
489syn3(p1, p2, flags)
490    struct wordent *p1, *p2;
491    int     flags;
492{
493    struct wordent *p;
494    struct wordent *lp, *rp;
495    struct command *t;
496    int l;
497    Char  **av;
498    int     n, c;
499    int    specp = 0;
500
501    if (p1 != p2) {
502	p = p1;
503again:
504	switch (srchx(p->word)) {
505
506	case TC_ELSE:
507	    p = p->next;
508	    if (p != p2)
509		goto again;
510	    break;
511
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;
523	}
524    }
525    n = 0;
526    l = 0;
527    for (p = p1; p != p2; p = p->next)
528	switch (p->word[0]) {
529
530	case '(':
531	    if (specp)
532		n++;
533	    l++;
534	    continue;
535
536	case ')':
537	    if (specp)
538		n++;
539	    l--;
540	    continue;
541
542	case '>':
543	case '<':
544	    if (l != 0) {
545		if (specp)
546		    n++;
547		continue;
548	    }
549	    if (p->next == p2)
550		continue;
551	    if (any(RELPAR, p->next->word[0]))
552		continue;
553	    n--;
554	    continue;
555
556	default:
557	    if (!specp && l != 0)
558		continue;
559	    n++;
560	    continue;
561	}
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) {
576
577	case '(':
578	    if (l == 0) {
579		if (lp != 0 && !specp)
580		    seterror(ERR_BADPLP);
581		lp = p->next;
582	    }
583	    l++;
584	    goto savep;
585
586	case ')':
587	    l--;
588	    if (l == 0)
589		rp = p;
590	    goto savep;
591
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;
602		}
603	    }
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;
609	    }
610	    p = p->next;
611	    if (any(RELPAR, p->word[0])) {
612		seterror(ERR_MISRED);
613		continue;
614	    }
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;
620
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;
629	    }
630	    p = p->next;
631	    if (any(RELPAR, p->word[0])) {
632		seterror(ERR_MISRED);
633		continue;
634	    }
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;
642
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;
653	}
654    }
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);
660    }
661    else {
662	if (n == 0)
663	    seterror(ERR_NULLCOM);
664	t->t_dtyp = NODE_COMMAND;
665    }
666    return (t);
667}
668
669void
670freesyn(t)
671    struct command *t;
672{
673    Char **v;
674
675    if (t == 0)
676	return;
677    switch (t->t_dtyp) {
678
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;
691
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;
700    }
701    xfree((ptr_t) t);
702}
703