801 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			801 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
#define Extern extern
 | 
						|
#include <sys/types.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <setjmp.h>
 | 
						|
#include "sh.h"
 | 
						|
 | 
						|
/* -------- csyn.c -------- */
 | 
						|
/*
 | 
						|
 * shell: syntax (C version)
 | 
						|
 */
 | 
						|
 | 
						|
typedef union {
 | 
						|
	char	*cp;
 | 
						|
	char	**wp;
 | 
						|
	int	i;
 | 
						|
	struct	op *o;
 | 
						|
} YYSTYPE;
 | 
						|
#define	WORD	256
 | 
						|
#define	LOGAND	257
 | 
						|
#define	LOGOR	258
 | 
						|
#define	BREAK	259
 | 
						|
#define	IF	260
 | 
						|
#define	THEN	261
 | 
						|
#define	ELSE	262
 | 
						|
#define	ELIF	263
 | 
						|
#define	FI	264
 | 
						|
#define	CASE	265
 | 
						|
#define	ESAC	266
 | 
						|
#define	FOR	267
 | 
						|
#define	WHILE	268
 | 
						|
#define	UNTIL	269
 | 
						|
#define	DO	270
 | 
						|
#define	DONE	271
 | 
						|
#define	IN	272
 | 
						|
#define	YYERRCODE 300
 | 
						|
 | 
						|
/* flags to yylex */
 | 
						|
#define	CONTIN	01	/* skip new lines to complete command */
 | 
						|
 | 
						|
/* #include "sh.h" */
 | 
						|
#define	SYNTAXERR	zzerr()
 | 
						|
static	int	startl;
 | 
						|
static	int	peeksym;
 | 
						|
static	int	nlseen;
 | 
						|
static	int	iounit = IODEFAULT;
 | 
						|
 | 
						|
static	YYSTYPE	yylval;
 | 
						|
 | 
						|
_PROTOTYPE(static struct op *pipeline, (int cf ));
 | 
						|
_PROTOTYPE(static struct op *andor, (void));
 | 
						|
_PROTOTYPE(static struct op *c_list, (void));
 | 
						|
_PROTOTYPE(static int synio, (int cf ));
 | 
						|
_PROTOTYPE(static void musthave, (int c, int cf ));
 | 
						|
_PROTOTYPE(static struct op *simple, (void));
 | 
						|
_PROTOTYPE(static struct op *nested, (int type, int mark ));
 | 
						|
_PROTOTYPE(static struct op *command, (int cf ));
 | 
						|
_PROTOTYPE(static struct op *dogroup, (int onlydone ));
 | 
						|
_PROTOTYPE(static struct op *thenpart, (void));
 | 
						|
_PROTOTYPE(static struct op *elsepart, (void));
 | 
						|
_PROTOTYPE(static struct op *caselist, (void));
 | 
						|
_PROTOTYPE(static struct op *casepart, (void));
 | 
						|
_PROTOTYPE(static char **pattern, (void));
 | 
						|
_PROTOTYPE(static char **wordlist, (void));
 | 
						|
_PROTOTYPE(static struct op *list, (struct op *t1, struct op *t2 ));
 | 
						|
_PROTOTYPE(static struct op *block, (int type, struct op *t1, struct op *t2, char **wp ));
 | 
						|
_PROTOTYPE(static struct op *newtp, (void));
 | 
						|
_PROTOTYPE(static struct op *namelist, (struct op *t ));
 | 
						|
_PROTOTYPE(static char **copyw, (void));
 | 
						|
_PROTOTYPE(static void word, (char *cp ));
 | 
						|
_PROTOTYPE(static struct ioword **copyio, (void));
 | 
						|
_PROTOTYPE(static struct ioword *io, (int u, int f, char *cp ));
 | 
						|
_PROTOTYPE(static void zzerr, (void));
 | 
						|
_PROTOTYPE(void yyerror, (char *s ));
 | 
						|
_PROTOTYPE(static int yylex, (int cf ));
 | 
						|
_PROTOTYPE(int collect, (int c, int c1 ));
 | 
						|
_PROTOTYPE(int dual, (int c ));
 | 
						|
_PROTOTYPE(static void diag, (int ec ));
 | 
						|
_PROTOTYPE(static char *tree, (unsigned size ));
 | 
						|
_PROTOTYPE(void printf, (char *s ));
 | 
						|
 | 
						|
int
 | 
						|
yyparse()
 | 
						|
{
 | 
						|
	startl  = 1;
 | 
						|
	peeksym = 0;
 | 
						|
	yynerrs = 0;
 | 
						|
	outtree = c_list();
 | 
						|
	musthave('\n', 0);
 | 
						|
	return(yynerrs!=0);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
pipeline(cf)
 | 
						|
int cf;
 | 
						|
{
 | 
						|
	register struct op *t, *p;
 | 
						|
	register int c;
 | 
						|
 | 
						|
	t = command(cf);
 | 
						|
	if (t != NULL) {
 | 
						|
		while ((c = yylex(0)) == '|') {
 | 
						|
			if ((p = command(CONTIN)) == NULL)
 | 
						|
				SYNTAXERR;
 | 
						|
			if (t->type != TPAREN && t->type != TCOM) {
 | 
						|
				/* shell statement */
 | 
						|
				t = block(TPAREN, t, NOBLOCK, NOWORDS);
 | 
						|
			}
 | 
						|
			t = block(TPIPE, t, p, NOWORDS);
 | 
						|
		}
 | 
						|
		peeksym = c;
 | 
						|
	}
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
andor()
 | 
						|
{
 | 
						|
	register struct op *t, *p;
 | 
						|
	register int c;
 | 
						|
 | 
						|
	t = pipeline(0);
 | 
						|
	if (t != NULL) {
 | 
						|
		while ((c = yylex(0)) == LOGAND || c == LOGOR) {
 | 
						|
			if ((p = pipeline(CONTIN)) == NULL)
 | 
						|
				SYNTAXERR;
 | 
						|
			t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
 | 
						|
		}
 | 
						|
		peeksym = c;
 | 
						|
	}
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
c_list()
 | 
						|
{
 | 
						|
	register struct op *t, *p;
 | 
						|
	register int c;
 | 
						|
 | 
						|
	t = andor();
 | 
						|
	if (t != NULL) {
 | 
						|
		if((peeksym = yylex(0)) == '&')
 | 
						|
			t = block(TASYNC, t, NOBLOCK, NOWORDS);
 | 
						|
		while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) {
 | 
						|
			if ((p = andor()) == NULL)
 | 
						|
				return(t);
 | 
						|
			if((peeksym = yylex(0)) == '&')
 | 
						|
				p = block(TASYNC, p, NOBLOCK, NOWORDS);
 | 
						|
			t = list(t, p);
 | 
						|
		}
 | 
						|
		peeksym = c;
 | 
						|
	}
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
synio(cf)
 | 
						|
int cf;
 | 
						|
{
 | 
						|
	register struct ioword *iop;
 | 
						|
	register int i;
 | 
						|
	register int c;
 | 
						|
 | 
						|
	if ((c = yylex(cf)) != '<' && c != '>') {
 | 
						|
		peeksym = c;
 | 
						|
		return(0);
 | 
						|
	}
 | 
						|
	i = yylval.i;
 | 
						|
	musthave(WORD, 0);
 | 
						|
	iop = io(iounit, i, yylval.cp);
 | 
						|
	iounit = IODEFAULT;
 | 
						|
	if (i & IOHERE)
 | 
						|
		markhere(yylval.cp, iop);
 | 
						|
	return(1);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
musthave(c, cf)
 | 
						|
int c, cf;
 | 
						|
{
 | 
						|
	if ((peeksym = yylex(cf)) != c)
 | 
						|
		SYNTAXERR;
 | 
						|
	peeksym = 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
simple()
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	t = NULL;
 | 
						|
	for (;;) {
 | 
						|
		switch (peeksym = yylex(0)) {
 | 
						|
		case '<':
 | 
						|
		case '>':
 | 
						|
			(void) synio(0);
 | 
						|
			break;
 | 
						|
 | 
						|
		case WORD:
 | 
						|
			if (t == NULL) {
 | 
						|
				t = newtp();
 | 
						|
				t->type = TCOM;
 | 
						|
			}
 | 
						|
			peeksym = 0;
 | 
						|
			word(yylval.cp);
 | 
						|
			break;
 | 
						|
 | 
						|
		default:
 | 
						|
			return(t);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
nested(type, mark)
 | 
						|
int type, mark;
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	multiline++;
 | 
						|
	t = c_list();
 | 
						|
	musthave(mark, 0);
 | 
						|
	multiline--;
 | 
						|
	return(block(type, t, NOBLOCK, NOWORDS));
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
command(cf)
 | 
						|
int cf;
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
	struct wdblock *iosave;
 | 
						|
	register int c;
 | 
						|
 | 
						|
	iosave = iolist;
 | 
						|
	iolist = NULL;
 | 
						|
	if (multiline)
 | 
						|
		cf |= CONTIN;
 | 
						|
	while (synio(cf))
 | 
						|
		cf = 0;
 | 
						|
	switch (c = yylex(cf)) {
 | 
						|
	default:
 | 
						|
		peeksym = c;
 | 
						|
		if ((t = simple()) == NULL) {
 | 
						|
			if (iolist == NULL)
 | 
						|
				return((struct op *)NULL);
 | 
						|
			t = newtp();
 | 
						|
			t->type = TCOM;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case '(':
 | 
						|
		t = nested(TPAREN, ')');
 | 
						|
		break;
 | 
						|
 | 
						|
	case '{':
 | 
						|
		t = nested(TBRACE, '}');
 | 
						|
		break;
 | 
						|
 | 
						|
	case FOR:
 | 
						|
		t = newtp();
 | 
						|
		t->type = TFOR;
 | 
						|
		musthave(WORD, 0);
 | 
						|
		startl = 1;
 | 
						|
		t->str = yylval.cp;
 | 
						|
		multiline++;
 | 
						|
		t->words = wordlist();
 | 
						|
		if ((c = yylex(0)) != '\n' && c != ';')
 | 
						|
			peeksym = c;
 | 
						|
		t->left = dogroup(0);
 | 
						|
		multiline--;
 | 
						|
		break;
 | 
						|
 | 
						|
	case WHILE:
 | 
						|
	case UNTIL:
 | 
						|
		multiline++;
 | 
						|
		t = newtp();
 | 
						|
		t->type = c == WHILE? TWHILE: TUNTIL;
 | 
						|
		t->left = c_list();
 | 
						|
		t->right = dogroup(1);
 | 
						|
		t->words = NULL;
 | 
						|
		multiline--;
 | 
						|
		break;
 | 
						|
 | 
						|
	case CASE:
 | 
						|
		t = newtp();
 | 
						|
		t->type = TCASE;
 | 
						|
		musthave(WORD, 0);
 | 
						|
		t->str = yylval.cp;
 | 
						|
		startl++;
 | 
						|
		multiline++;
 | 
						|
		musthave(IN, CONTIN);
 | 
						|
		startl++;
 | 
						|
		t->left = caselist();
 | 
						|
		musthave(ESAC, 0);
 | 
						|
		multiline--;
 | 
						|
		break;
 | 
						|
 | 
						|
	case IF:
 | 
						|
		multiline++;
 | 
						|
		t = newtp();
 | 
						|
		t->type = TIF;
 | 
						|
		t->left = c_list();
 | 
						|
		t->right = thenpart();
 | 
						|
		musthave(FI, 0);
 | 
						|
		multiline--;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	while (synio(0))
 | 
						|
		;
 | 
						|
	t = namelist(t);
 | 
						|
	iolist = iosave;
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
dogroup(onlydone)
 | 
						|
int onlydone;
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
	register struct op *list;
 | 
						|
 | 
						|
	c = yylex(CONTIN);
 | 
						|
	if (c == DONE && onlydone)
 | 
						|
		return((struct op *)NULL);
 | 
						|
	if (c != DO)
 | 
						|
		SYNTAXERR;
 | 
						|
	list = c_list();
 | 
						|
	musthave(DONE, 0);
 | 
						|
	return(list);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
thenpart()
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	if ((c = yylex(0)) != THEN) {
 | 
						|
		peeksym = c;
 | 
						|
		return((struct op *)NULL);
 | 
						|
	}
 | 
						|
	t = newtp();
 | 
						|
	t->type = 0;
 | 
						|
	t->left = c_list();
 | 
						|
	if (t->left == NULL)
 | 
						|
		SYNTAXERR;
 | 
						|
	t->right = elsepart();
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
elsepart()
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	switch (c = yylex(0)) {
 | 
						|
	case ELSE:
 | 
						|
		if ((t = c_list()) == NULL)
 | 
						|
			SYNTAXERR;
 | 
						|
		return(t);
 | 
						|
 | 
						|
	case ELIF:
 | 
						|
		t = newtp();
 | 
						|
		t->type = TELIF;
 | 
						|
		t->left = c_list();
 | 
						|
		t->right = thenpart();
 | 
						|
		return(t);
 | 
						|
 | 
						|
	default:
 | 
						|
		peeksym = c;
 | 
						|
		return((struct op *)NULL);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
caselist()
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	t = NULL;
 | 
						|
	while ((peeksym = yylex(CONTIN)) != ESAC)
 | 
						|
		t = list(t, casepart());
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
casepart()
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	t = newtp();
 | 
						|
	t->type = TPAT;
 | 
						|
	t->words = pattern();
 | 
						|
	musthave(')', 0);
 | 
						|
	t->left = c_list();
 | 
						|
	if ((peeksym = yylex(CONTIN)) != ESAC)
 | 
						|
		musthave(BREAK, CONTIN);
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static char **
 | 
						|
pattern()
 | 
						|
{
 | 
						|
	register int c, cf;
 | 
						|
 | 
						|
	cf = CONTIN;
 | 
						|
	do {
 | 
						|
		musthave(WORD, cf);
 | 
						|
		word(yylval.cp);
 | 
						|
		cf = 0;
 | 
						|
	} while ((c = yylex(0)) == '|');
 | 
						|
	peeksym = c;
 | 
						|
	word(NOWORD);
 | 
						|
	return(copyw());
 | 
						|
}
 | 
						|
 | 
						|
static char **
 | 
						|
wordlist()
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
 | 
						|
	if ((c = yylex(0)) != IN) {
 | 
						|
		peeksym = c;
 | 
						|
		return((char **)NULL);
 | 
						|
	}
 | 
						|
	startl = 0;
 | 
						|
	while ((c = yylex(0)) == WORD)
 | 
						|
		word(yylval.cp);
 | 
						|
	word(NOWORD);
 | 
						|
	peeksym = c;
 | 
						|
	return(copyw());
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * supporting functions
 | 
						|
 */
 | 
						|
static struct op *
 | 
						|
list(t1, t2)
 | 
						|
register struct op *t1, *t2;
 | 
						|
{
 | 
						|
	if (t1 == NULL)
 | 
						|
		return(t2);
 | 
						|
	if (t2 == NULL)
 | 
						|
		return(t1);
 | 
						|
	return(block(TLIST, t1, t2, NOWORDS));
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
block(type, t1, t2, wp)
 | 
						|
int type;
 | 
						|
struct op *t1, *t2;
 | 
						|
char **wp;
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	t = newtp();
 | 
						|
	t->type = type;
 | 
						|
	t->left = t1;
 | 
						|
	t->right = t2;
 | 
						|
	t->words = wp;
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
struct res {
 | 
						|
	char	*r_name;
 | 
						|
	int	r_val;
 | 
						|
} restab[] = {
 | 
						|
	"for",		FOR,
 | 
						|
	"case",		CASE,
 | 
						|
	"esac",		ESAC,
 | 
						|
	"while",	WHILE,
 | 
						|
	"do",		DO,
 | 
						|
	"done",		DONE,
 | 
						|
	"if",		IF,
 | 
						|
	"in",		IN,
 | 
						|
	"then",		THEN,
 | 
						|
	"else",		ELSE,
 | 
						|
	"elif",		ELIF,
 | 
						|
	"until",	UNTIL,
 | 
						|
	"fi",		FI,
 | 
						|
 | 
						|
	";;",		BREAK,
 | 
						|
	"||",		LOGOR,
 | 
						|
	"&&",		LOGAND,
 | 
						|
	"{",		'{',
 | 
						|
	"}",		'}',
 | 
						|
 | 
						|
	0,
 | 
						|
};
 | 
						|
 | 
						|
int
 | 
						|
rlookup(n)
 | 
						|
register char *n;
 | 
						|
{
 | 
						|
	register struct res *rp;
 | 
						|
 | 
						|
	for (rp = restab; rp->r_name; rp++)
 | 
						|
		if (strcmp(rp->r_name, n) == 0)
 | 
						|
			return(rp->r_val);
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
newtp()
 | 
						|
{
 | 
						|
	register struct op *t;
 | 
						|
 | 
						|
	t = (struct op *)tree(sizeof(*t));
 | 
						|
	t->type = 0;
 | 
						|
	t->words = NULL;
 | 
						|
	t->ioact = NULL;
 | 
						|
	t->left = NULL;
 | 
						|
	t->right = NULL;
 | 
						|
	t->str = NULL;
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static struct op *
 | 
						|
namelist(t)
 | 
						|
register struct op *t;
 | 
						|
{
 | 
						|
	if (iolist) {
 | 
						|
		iolist = addword((char *)NULL, iolist);
 | 
						|
		t->ioact = copyio();
 | 
						|
	} else
 | 
						|
		t->ioact = NULL;
 | 
						|
	if (t->type != TCOM) {
 | 
						|
		if (t->type != TPAREN && t->ioact != NULL) {
 | 
						|
			t = block(TPAREN, t, NOBLOCK, NOWORDS);
 | 
						|
			t->ioact = t->left->ioact;
 | 
						|
			t->left->ioact = NULL;
 | 
						|
		}
 | 
						|
		return(t);
 | 
						|
	}
 | 
						|
	word(NOWORD);
 | 
						|
	t->words = copyw();
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
static char **
 | 
						|
copyw()
 | 
						|
{
 | 
						|
	register char **wd;
 | 
						|
 | 
						|
	wd = getwords(wdlist);
 | 
						|
	wdlist = 0;
 | 
						|
	return(wd);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
word(cp)
 | 
						|
char *cp;
 | 
						|
{
 | 
						|
	wdlist = addword(cp, wdlist);
 | 
						|
}
 | 
						|
 | 
						|
static struct ioword **
 | 
						|
copyio()
 | 
						|
{
 | 
						|
	register struct ioword **iop;
 | 
						|
 | 
						|
	iop = (struct ioword **) getwords(iolist);
 | 
						|
	iolist = 0;
 | 
						|
	return(iop);
 | 
						|
}
 | 
						|
 | 
						|
static struct ioword *
 | 
						|
io(u, f, cp)
 | 
						|
int u;
 | 
						|
int f;
 | 
						|
char *cp;
 | 
						|
{
 | 
						|
	register struct ioword *iop;
 | 
						|
 | 
						|
	iop = (struct ioword *) tree(sizeof(*iop));
 | 
						|
	iop->io_unit = u;
 | 
						|
	iop->io_flag = f;
 | 
						|
	iop->io_name = cp;
 | 
						|
	iolist = addword((char *)iop, iolist);
 | 
						|
	return(iop);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
zzerr()
 | 
						|
{
 | 
						|
	yyerror("syntax error");
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
yyerror(s)
 | 
						|
char *s;
 | 
						|
{
 | 
						|
	yynerrs++;
 | 
						|
	if (talking && e.iop <= iostack) {
 | 
						|
		multiline = 0;
 | 
						|
		while (eofc() == 0 && yylex(0) != '\n')
 | 
						|
			;
 | 
						|
	}
 | 
						|
	err(s);
 | 
						|
	fail();
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
yylex(cf)
 | 
						|
int cf;
 | 
						|
{
 | 
						|
	register int c, c1;
 | 
						|
	int atstart;
 | 
						|
 | 
						|
	if ((c = peeksym) > 0) {
 | 
						|
		peeksym = 0;
 | 
						|
		if (c == '\n')
 | 
						|
			startl = 1;
 | 
						|
		return(c);
 | 
						|
	}
 | 
						|
	nlseen = 0;
 | 
						|
	e.linep = line;
 | 
						|
	atstart = startl;
 | 
						|
	startl = 0;
 | 
						|
	yylval.i = 0;
 | 
						|
 | 
						|
loop:
 | 
						|
	while ((c = getc(0)) == ' ' || c == '\t')
 | 
						|
		;
 | 
						|
	switch (c) {
 | 
						|
	default:
 | 
						|
		if (any(c, "0123456789")) {
 | 
						|
			unget(c1 = getc(0));
 | 
						|
			if (c1 == '<' || c1 == '>') {
 | 
						|
				iounit = c - '0';
 | 
						|
				goto loop;
 | 
						|
			}
 | 
						|
			*e.linep++ = c;
 | 
						|
			c = c1;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case '#':
 | 
						|
		while ((c = getc(0)) != 0 && c != '\n')
 | 
						|
			;
 | 
						|
		unget(c);
 | 
						|
		goto loop;
 | 
						|
 | 
						|
	case 0:
 | 
						|
		return(c);
 | 
						|
 | 
						|
	case '$':
 | 
						|
		*e.linep++ = c;
 | 
						|
		if ((c = getc(0)) == '{') {
 | 
						|
			if ((c = collect(c, '}')) != '\0')
 | 
						|
				return(c);
 | 
						|
			goto pack;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case '`':
 | 
						|
	case '\'':
 | 
						|
	case '"':
 | 
						|
		if ((c = collect(c, c)) != '\0')
 | 
						|
			return(c);
 | 
						|
		goto pack;
 | 
						|
 | 
						|
	case '|':
 | 
						|
	case '&':
 | 
						|
	case ';':
 | 
						|
		if ((c1 = dual(c)) != '\0') {
 | 
						|
			startl = 1;
 | 
						|
			return(c1);
 | 
						|
		}
 | 
						|
		startl = 1;
 | 
						|
		return(c);
 | 
						|
	case '^':
 | 
						|
		startl = 1;
 | 
						|
		return('|');
 | 
						|
	case '>':
 | 
						|
	case '<':
 | 
						|
		diag(c);
 | 
						|
		return(c);
 | 
						|
 | 
						|
	case '\n':
 | 
						|
		nlseen++;
 | 
						|
		gethere();
 | 
						|
		startl = 1;
 | 
						|
		if (multiline || cf & CONTIN) {
 | 
						|
			if (talking && e.iop <= iostack)
 | 
						|
				prs(cprompt->value);
 | 
						|
			if (cf & CONTIN)
 | 
						|
				goto loop;
 | 
						|
		}
 | 
						|
		return(c);
 | 
						|
 | 
						|
	case '(':
 | 
						|
	case ')':
 | 
						|
		startl = 1;
 | 
						|
		return(c);
 | 
						|
	}
 | 
						|
 | 
						|
	unget(c);
 | 
						|
 | 
						|
pack:
 | 
						|
	while ((c = getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n"))
 | 
						|
		if (e.linep >= elinep)
 | 
						|
			err("word too long");
 | 
						|
		else
 | 
						|
			*e.linep++ = c;
 | 
						|
	unget(c);
 | 
						|
	if(any(c, "\"'`$"))
 | 
						|
		goto loop;
 | 
						|
	*e.linep++ = '\0';
 | 
						|
	if (atstart && (c = rlookup(line))!=0) {
 | 
						|
		startl = 1;
 | 
						|
		return(c);
 | 
						|
	}
 | 
						|
	yylval.cp = strsave(line, areanum);
 | 
						|
	return(WORD);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
collect(c, c1)
 | 
						|
register c, c1;
 | 
						|
{
 | 
						|
	char s[2];
 | 
						|
 | 
						|
	*e.linep++ = c;
 | 
						|
	while ((c = getc(c1)) != c1) {
 | 
						|
		if (c == 0) {
 | 
						|
			unget(c);
 | 
						|
			s[0] = c1;
 | 
						|
			s[1] = 0;
 | 
						|
			prs("no closing "); yyerror(s);
 | 
						|
			return(YYERRCODE);
 | 
						|
		}
 | 
						|
		if (talking && c == '\n' && e.iop <= iostack)
 | 
						|
			prs(cprompt->value);
 | 
						|
		*e.linep++ = c;
 | 
						|
	}
 | 
						|
	*e.linep++ = c;
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
dual(c)
 | 
						|
register c;
 | 
						|
{
 | 
						|
	char s[3];
 | 
						|
	register char *cp = s;
 | 
						|
 | 
						|
	*cp++ = c;
 | 
						|
	*cp++ = getc(0);
 | 
						|
	*cp = 0;
 | 
						|
	if ((c = rlookup(s)) == 0)
 | 
						|
		unget(*--cp);
 | 
						|
	return(c);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
diag(ec)
 | 
						|
register int ec;
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
 | 
						|
	c = getc(0);
 | 
						|
	if (c == '>' || c == '<') {
 | 
						|
		if (c != ec)
 | 
						|
			zzerr();
 | 
						|
		yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE;
 | 
						|
		c = getc(0);
 | 
						|
	} else
 | 
						|
		yylval.i = ec == '>'? IOWRITE: IOREAD;
 | 
						|
	if (c != '&' || yylval.i == IOHERE)
 | 
						|
		unget(c);
 | 
						|
	else
 | 
						|
		yylval.i |= IODUP;
 | 
						|
}
 | 
						|
 | 
						|
static char *
 | 
						|
tree(size)
 | 
						|
unsigned size;
 | 
						|
{
 | 
						|
	register char *t;
 | 
						|
 | 
						|
	if ((t = getcell(size)) == NULL) {
 | 
						|
		prs("command line too complicated\n");
 | 
						|
		fail();
 | 
						|
		/* NOTREACHED */
 | 
						|
	}
 | 
						|
	return(t);
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
/* ARGSUSED */
 | 
						|
void 
 | 
						|
printf(s)	/* yyparse calls it */
 | 
						|
char *s;
 | 
						|
{
 | 
						|
}
 | 
						|
 |