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;
 | |
| {
 | |
| }
 | |
| 
 | 
