xref: /titanic_50/usr/src/cmd/csh/sh.lex.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
11*7c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley Software License Agreement
12*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <unistd.h>	/* for lseek prototype */
18*7c478bd9Sstevel@tonic-gate #include "sh.h"
19*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
20*7c478bd9Sstevel@tonic-gate #include <sys/filio.h>
21*7c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
22*7c478bd9Sstevel@tonic-gate #define RAW 	O_RAW
23*7c478bd9Sstevel@tonic-gate /*
24*7c478bd9Sstevel@tonic-gate  * C shell
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * These lexical routines read input and form lists of words.
29*7c478bd9Sstevel@tonic-gate  * There is some involved processing here, because of the complications
30*7c478bd9Sstevel@tonic-gate  * of input buffering, and especially because of history substitution.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate tchar *word();
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /*
36*7c478bd9Sstevel@tonic-gate  * Peekc is a peek characer for getC, peekread for readc.
37*7c478bd9Sstevel@tonic-gate  * There is a subtlety here in many places... history routines
38*7c478bd9Sstevel@tonic-gate  * will read ahead and then insert stuff into the input stream.
39*7c478bd9Sstevel@tonic-gate  * If they push back a character then they must push it behind
40*7c478bd9Sstevel@tonic-gate  * the text substituted by the history substitution.  On the other
41*7c478bd9Sstevel@tonic-gate  * hand in several places we need 2 peek characters.  To make this
42*7c478bd9Sstevel@tonic-gate  * all work, the history routines read with getC, and make use both
43*7c478bd9Sstevel@tonic-gate  * of ungetC and unreadc.  The key observation is that the state
44*7c478bd9Sstevel@tonic-gate  * of getC at the call of a history reference is such that calls
45*7c478bd9Sstevel@tonic-gate  * to getC from the history routines will always yield calls of
46*7c478bd9Sstevel@tonic-gate  * readc, unless this peeking is involved.  That is to say that during
47*7c478bd9Sstevel@tonic-gate  * getexcl the variables lap, exclp, and exclnxt are all zero.
48*7c478bd9Sstevel@tonic-gate  *
49*7c478bd9Sstevel@tonic-gate  * Getdol invokes history substitution, hence the extra peek, peekd,
50*7c478bd9Sstevel@tonic-gate  * which it can ungetD to be before history substitutions.
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate tchar peekc, peekd;
53*7c478bd9Sstevel@tonic-gate tchar peekread;
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate tchar *exclp;			/* (Tail of) current word from ! subst */
56*7c478bd9Sstevel@tonic-gate struct	wordent *exclnxt;	/* The rest of the ! subst words */
57*7c478bd9Sstevel@tonic-gate int	exclc;			/* Count of remainig words in ! subst */
58*7c478bd9Sstevel@tonic-gate tchar *alvecp;		/* "Globp" for alias resubstitution */
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*
61*7c478bd9Sstevel@tonic-gate  * Lex returns to its caller not only a wordlist (as a "var" parameter)
62*7c478bd9Sstevel@tonic-gate  * but also whether a history substitution occurred.  This is used in
63*7c478bd9Sstevel@tonic-gate  * the main (process) routine to determine whether to echo, and also
64*7c478bd9Sstevel@tonic-gate  * when called by the alias routine to determine whether to keep the
65*7c478bd9Sstevel@tonic-gate  * argument list.
66*7c478bd9Sstevel@tonic-gate  */
67*7c478bd9Sstevel@tonic-gate bool	hadhist;
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate tchar getCtmp;
70*7c478bd9Sstevel@tonic-gate #define getC(f)		((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f))
71*7c478bd9Sstevel@tonic-gate #define	ungetC(c)	peekc = c
72*7c478bd9Sstevel@tonic-gate #define	ungetD(c)	peekd = c
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate lex(hp)
75*7c478bd9Sstevel@tonic-gate 	register struct wordent *hp;
76*7c478bd9Sstevel@tonic-gate {
77*7c478bd9Sstevel@tonic-gate 	register struct wordent *wdp;
78*7c478bd9Sstevel@tonic-gate 	int c;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate #ifdef TRACE
81*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- lex()\n");
82*7c478bd9Sstevel@tonic-gate #endif
83*7c478bd9Sstevel@tonic-gate 	lineloc = btell();
84*7c478bd9Sstevel@tonic-gate 	hp->next = hp->prev = hp;
85*7c478bd9Sstevel@tonic-gate 	hp->word = S_ /*""*/;
86*7c478bd9Sstevel@tonic-gate 	alvecp = 0, hadhist = 0;
87*7c478bd9Sstevel@tonic-gate 	do
88*7c478bd9Sstevel@tonic-gate 		c = readc(0);
89*7c478bd9Sstevel@tonic-gate 	while (issp(c));
90*7c478bd9Sstevel@tonic-gate 	/* make sure history is enabled */
91*7c478bd9Sstevel@tonic-gate 	if (HIST && c == HISTSUB && intty)
92*7c478bd9Sstevel@tonic-gate 		/* ^lef^rit	from tty is short !:s^lef^rit */
93*7c478bd9Sstevel@tonic-gate 		getexcl(c);
94*7c478bd9Sstevel@tonic-gate 	else
95*7c478bd9Sstevel@tonic-gate 		unreadc(c);
96*7c478bd9Sstevel@tonic-gate 	wdp = hp;
97*7c478bd9Sstevel@tonic-gate 	/*
98*7c478bd9Sstevel@tonic-gate 	 * The following loop is written so that the links needed
99*7c478bd9Sstevel@tonic-gate 	 * by freelex will be ready and rarin to go even if it is
100*7c478bd9Sstevel@tonic-gate 	 * interrupted.
101*7c478bd9Sstevel@tonic-gate 	 */
102*7c478bd9Sstevel@tonic-gate 	do {
103*7c478bd9Sstevel@tonic-gate 		register struct wordent *new = (struct wordent *) xalloc(sizeof *wdp);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 		new->word = 0;
106*7c478bd9Sstevel@tonic-gate 		new->prev = wdp;
107*7c478bd9Sstevel@tonic-gate 		new->next = hp;
108*7c478bd9Sstevel@tonic-gate 		wdp->next = new;
109*7c478bd9Sstevel@tonic-gate 		wdp = new;
110*7c478bd9Sstevel@tonic-gate 		wdp->word = word();
111*7c478bd9Sstevel@tonic-gate 	} while (wdp->word[0] != '\n');
112*7c478bd9Sstevel@tonic-gate #ifdef TRACE
113*7c478bd9Sstevel@tonic-gate 	tprintf("Exiting lex()\n");
114*7c478bd9Sstevel@tonic-gate #endif
115*7c478bd9Sstevel@tonic-gate 	hp->prev = wdp;
116*7c478bd9Sstevel@tonic-gate 	return (hadhist);
117*7c478bd9Sstevel@tonic-gate }
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate prlex(sp0)
120*7c478bd9Sstevel@tonic-gate 	struct wordent *sp0;
121*7c478bd9Sstevel@tonic-gate {
122*7c478bd9Sstevel@tonic-gate 	register struct wordent *sp = sp0->next;
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate #ifdef TRACE
125*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- prlex()\n");
126*7c478bd9Sstevel@tonic-gate #endif
127*7c478bd9Sstevel@tonic-gate 	for (;;) {
128*7c478bd9Sstevel@tonic-gate 		printf("%t", sp->word);
129*7c478bd9Sstevel@tonic-gate 		sp = sp->next;
130*7c478bd9Sstevel@tonic-gate 		if (sp == sp0)
131*7c478bd9Sstevel@tonic-gate 			break;
132*7c478bd9Sstevel@tonic-gate 		if (sp->word[0] != '\n')
133*7c478bd9Sstevel@tonic-gate 			Putchar(' ');
134*7c478bd9Sstevel@tonic-gate 	}
135*7c478bd9Sstevel@tonic-gate }
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate copylex(hp, fp)
138*7c478bd9Sstevel@tonic-gate 	register struct wordent *hp;
139*7c478bd9Sstevel@tonic-gate 	register struct wordent *fp;
140*7c478bd9Sstevel@tonic-gate {
141*7c478bd9Sstevel@tonic-gate 	register struct wordent *wdp;
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate #ifdef TRACE
144*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- copylex()\n");
145*7c478bd9Sstevel@tonic-gate #endif
146*7c478bd9Sstevel@tonic-gate 	wdp = hp;
147*7c478bd9Sstevel@tonic-gate 	fp = fp->next;
148*7c478bd9Sstevel@tonic-gate 	do {
149*7c478bd9Sstevel@tonic-gate 		register struct wordent *new = (struct wordent *) xalloc(sizeof *wdp);
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 		new->prev = wdp;
152*7c478bd9Sstevel@tonic-gate 		new->next = hp;
153*7c478bd9Sstevel@tonic-gate 		wdp->next = new;
154*7c478bd9Sstevel@tonic-gate 		wdp = new;
155*7c478bd9Sstevel@tonic-gate 		wdp->word = savestr(fp->word);
156*7c478bd9Sstevel@tonic-gate 		fp = fp->next;
157*7c478bd9Sstevel@tonic-gate 	} while (wdp->word[0] != '\n');
158*7c478bd9Sstevel@tonic-gate 	hp->prev = wdp;
159*7c478bd9Sstevel@tonic-gate }
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate freelex(vp)
162*7c478bd9Sstevel@tonic-gate 	register struct wordent *vp;
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate 	register struct wordent *fp;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate #ifdef TRACE
167*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- freelex()\n");
168*7c478bd9Sstevel@tonic-gate #endif
169*7c478bd9Sstevel@tonic-gate 	while (vp->next != vp) {
170*7c478bd9Sstevel@tonic-gate 		fp = vp->next;
171*7c478bd9Sstevel@tonic-gate 		vp->next = fp->next;
172*7c478bd9Sstevel@tonic-gate 		XFREE(fp->word)
173*7c478bd9Sstevel@tonic-gate 		XFREE( (char *)fp)
174*7c478bd9Sstevel@tonic-gate 	}
175*7c478bd9Sstevel@tonic-gate 	vp->prev = vp;
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate tchar *
179*7c478bd9Sstevel@tonic-gate word()
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	register tchar c, c1;
182*7c478bd9Sstevel@tonic-gate 	register tchar *wp;
183*7c478bd9Sstevel@tonic-gate 	tchar wbuf[BUFSIZ];
184*7c478bd9Sstevel@tonic-gate 	register bool dolflg;
185*7c478bd9Sstevel@tonic-gate 	register int i;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate #ifdef TRACE
188*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- word()\n");
189*7c478bd9Sstevel@tonic-gate #endif
190*7c478bd9Sstevel@tonic-gate 	wp = wbuf;
191*7c478bd9Sstevel@tonic-gate 	i = BUFSIZ - 4;
192*7c478bd9Sstevel@tonic-gate loop:
193*7c478bd9Sstevel@tonic-gate 	while (issp(c = getC(DOALL)))
194*7c478bd9Sstevel@tonic-gate 		;
195*7c478bd9Sstevel@tonic-gate 	if (cmap(c, _META|_ESC)||isauxsp(c))
196*7c478bd9Sstevel@tonic-gate 		switch (c) {
197*7c478bd9Sstevel@tonic-gate 		case '&':
198*7c478bd9Sstevel@tonic-gate 		case '|':
199*7c478bd9Sstevel@tonic-gate 		case '<':
200*7c478bd9Sstevel@tonic-gate 		case '>':
201*7c478bd9Sstevel@tonic-gate 			*wp++ = c;
202*7c478bd9Sstevel@tonic-gate 			c1 = getC(DOALL);
203*7c478bd9Sstevel@tonic-gate 			if (c1 == c)
204*7c478bd9Sstevel@tonic-gate 				*wp++ = c1;
205*7c478bd9Sstevel@tonic-gate 			else
206*7c478bd9Sstevel@tonic-gate 				ungetC(c1);
207*7c478bd9Sstevel@tonic-gate 			goto ret;
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 		case '#':
210*7c478bd9Sstevel@tonic-gate 			if (intty)
211*7c478bd9Sstevel@tonic-gate 				break;
212*7c478bd9Sstevel@tonic-gate 			c = 0;
213*7c478bd9Sstevel@tonic-gate 			do {
214*7c478bd9Sstevel@tonic-gate 				c1 = c;
215*7c478bd9Sstevel@tonic-gate 				c = getC(0);
216*7c478bd9Sstevel@tonic-gate 			} while (c != '\n');
217*7c478bd9Sstevel@tonic-gate 			if (c1 == '\\')
218*7c478bd9Sstevel@tonic-gate 				goto loop;
219*7c478bd9Sstevel@tonic-gate 			/* fall into ... */
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 		case ';':
222*7c478bd9Sstevel@tonic-gate 		case '(':
223*7c478bd9Sstevel@tonic-gate 		case ')':
224*7c478bd9Sstevel@tonic-gate 		case '\n':
225*7c478bd9Sstevel@tonic-gate 			*wp++ = c;
226*7c478bd9Sstevel@tonic-gate 			goto ret;
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 		case '\\':
229*7c478bd9Sstevel@tonic-gate 			c = getC(0);
230*7c478bd9Sstevel@tonic-gate 			if (c == '\n') {
231*7c478bd9Sstevel@tonic-gate 				if (onelflg == 1)
232*7c478bd9Sstevel@tonic-gate 					onelflg = 2;
233*7c478bd9Sstevel@tonic-gate 				goto loop;
234*7c478bd9Sstevel@tonic-gate 			}
235*7c478bd9Sstevel@tonic-gate 			if (c != HIST)
236*7c478bd9Sstevel@tonic-gate 				*wp++ = '\\', --i;
237*7c478bd9Sstevel@tonic-gate 			c |= QUOTE;
238*7c478bd9Sstevel@tonic-gate 		}
239*7c478bd9Sstevel@tonic-gate 	c1 = 0;
240*7c478bd9Sstevel@tonic-gate 	dolflg = DOALL;
241*7c478bd9Sstevel@tonic-gate 	for (;;) {
242*7c478bd9Sstevel@tonic-gate 		if (c1) {
243*7c478bd9Sstevel@tonic-gate 			if (c == c1) {
244*7c478bd9Sstevel@tonic-gate 				c1 = 0;
245*7c478bd9Sstevel@tonic-gate 				dolflg = DOALL;
246*7c478bd9Sstevel@tonic-gate 			} else if (c == '\\') {
247*7c478bd9Sstevel@tonic-gate 				c = getC(0);
248*7c478bd9Sstevel@tonic-gate 				if (c == HIST)
249*7c478bd9Sstevel@tonic-gate 					c |= QUOTE;
250*7c478bd9Sstevel@tonic-gate 				else {
251*7c478bd9Sstevel@tonic-gate 					if (c == '\n')
252*7c478bd9Sstevel@tonic-gate 						/*
253*7c478bd9Sstevel@tonic-gate 						if (c1 == '`')
254*7c478bd9Sstevel@tonic-gate 							c = ' ';
255*7c478bd9Sstevel@tonic-gate 						else
256*7c478bd9Sstevel@tonic-gate 						*/
257*7c478bd9Sstevel@tonic-gate 							c |= QUOTE;
258*7c478bd9Sstevel@tonic-gate 					ungetC(c);
259*7c478bd9Sstevel@tonic-gate 					c = '\\';
260*7c478bd9Sstevel@tonic-gate 				}
261*7c478bd9Sstevel@tonic-gate 			} else if (c == '\n') {
262*7c478bd9Sstevel@tonic-gate 				seterrc(gettext("Unmatched "), c1);
263*7c478bd9Sstevel@tonic-gate 				ungetC(c);
264*7c478bd9Sstevel@tonic-gate 				break;
265*7c478bd9Sstevel@tonic-gate 			}
266*7c478bd9Sstevel@tonic-gate 		} else if (cmap(c, _META|_Q|_Q1|_ESC)||isauxsp(c)) {
267*7c478bd9Sstevel@tonic-gate 			if (c == '\\') {
268*7c478bd9Sstevel@tonic-gate 				c = getC(0);
269*7c478bd9Sstevel@tonic-gate 				if (c == '\n') {
270*7c478bd9Sstevel@tonic-gate 					if (onelflg == 1)
271*7c478bd9Sstevel@tonic-gate 						onelflg = 2;
272*7c478bd9Sstevel@tonic-gate 					break;
273*7c478bd9Sstevel@tonic-gate 				}
274*7c478bd9Sstevel@tonic-gate 				if (c != HIST)
275*7c478bd9Sstevel@tonic-gate 					*wp++ = '\\', --i;
276*7c478bd9Sstevel@tonic-gate 				c |= QUOTE;
277*7c478bd9Sstevel@tonic-gate 			} else if (cmap(c, _Q|_Q1)) {		/* '"` */
278*7c478bd9Sstevel@tonic-gate 				c1 = c;
279*7c478bd9Sstevel@tonic-gate 				dolflg = c == '"' ? DOALL : DOEXCL;
280*7c478bd9Sstevel@tonic-gate 			} else if (c != '#' || !intty) {
281*7c478bd9Sstevel@tonic-gate 				ungetC(c);
282*7c478bd9Sstevel@tonic-gate 				break;
283*7c478bd9Sstevel@tonic-gate 			}
284*7c478bd9Sstevel@tonic-gate 		}
285*7c478bd9Sstevel@tonic-gate 		if (--i > 0) {
286*7c478bd9Sstevel@tonic-gate 			*wp++ = c;
287*7c478bd9Sstevel@tonic-gate 			c = getC(dolflg);
288*7c478bd9Sstevel@tonic-gate 		} else {
289*7c478bd9Sstevel@tonic-gate 			seterr("Word too long");
290*7c478bd9Sstevel@tonic-gate 			wp = &wbuf[1];
291*7c478bd9Sstevel@tonic-gate 			break;
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 	}
294*7c478bd9Sstevel@tonic-gate ret:
295*7c478bd9Sstevel@tonic-gate 	*wp = 0;
296*7c478bd9Sstevel@tonic-gate #ifdef TRACE
297*7c478bd9Sstevel@tonic-gate 	tprintf("word() returning:%t\n", wbuf);
298*7c478bd9Sstevel@tonic-gate #endif
299*7c478bd9Sstevel@tonic-gate 	return (savestr(wbuf));
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate getC1(flag)
303*7c478bd9Sstevel@tonic-gate 	register int flag;
304*7c478bd9Sstevel@tonic-gate {
305*7c478bd9Sstevel@tonic-gate 	register tchar c;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate top:
308*7c478bd9Sstevel@tonic-gate 	if (c = peekc) {
309*7c478bd9Sstevel@tonic-gate 		peekc = 0;
310*7c478bd9Sstevel@tonic-gate 		return (c);
311*7c478bd9Sstevel@tonic-gate 	}
312*7c478bd9Sstevel@tonic-gate 	if (lap) {
313*7c478bd9Sstevel@tonic-gate 		if ((c = *lap++) == 0)
314*7c478bd9Sstevel@tonic-gate 			lap = 0;
315*7c478bd9Sstevel@tonic-gate 		else {
316*7c478bd9Sstevel@tonic-gate 			/*
317*7c478bd9Sstevel@tonic-gate 			 *	don't quote things if there was an error (err!=0)
318*7c478bd9Sstevel@tonic-gate 			 * 	the input is original, not from a substitution and
319*7c478bd9Sstevel@tonic-gate 			 *	therefore should not be quoted
320*7c478bd9Sstevel@tonic-gate 			 */
321*7c478bd9Sstevel@tonic-gate 			if (!err && cmap(c, _META|_Q|_Q1)||isauxsp(c))
322*7c478bd9Sstevel@tonic-gate 				c |= QUOTE;
323*7c478bd9Sstevel@tonic-gate 			return (c);
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 	}
326*7c478bd9Sstevel@tonic-gate 	if (c = peekd) {
327*7c478bd9Sstevel@tonic-gate 		peekd = 0;
328*7c478bd9Sstevel@tonic-gate 		return (c);
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate 	if (exclp) {
331*7c478bd9Sstevel@tonic-gate 		if (c = *exclp++)
332*7c478bd9Sstevel@tonic-gate 			return (c);
333*7c478bd9Sstevel@tonic-gate 		if (exclnxt && --exclc >= 0) {
334*7c478bd9Sstevel@tonic-gate 			exclnxt = exclnxt->next;
335*7c478bd9Sstevel@tonic-gate 			setexclp(exclnxt->word);
336*7c478bd9Sstevel@tonic-gate 			return (' ');
337*7c478bd9Sstevel@tonic-gate 		}
338*7c478bd9Sstevel@tonic-gate 		exclp = 0;
339*7c478bd9Sstevel@tonic-gate 		exclnxt = 0;
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 	if (exclnxt) {
342*7c478bd9Sstevel@tonic-gate 		exclnxt = exclnxt->next;
343*7c478bd9Sstevel@tonic-gate 		if (--exclc < 0)
344*7c478bd9Sstevel@tonic-gate 			exclnxt = 0;
345*7c478bd9Sstevel@tonic-gate 		else
346*7c478bd9Sstevel@tonic-gate 			setexclp(exclnxt->word);
347*7c478bd9Sstevel@tonic-gate 		goto top;
348*7c478bd9Sstevel@tonic-gate 	}
349*7c478bd9Sstevel@tonic-gate 	c = readc(0);
350*7c478bd9Sstevel@tonic-gate 	if (c == '$' && (flag & DODOL)) {
351*7c478bd9Sstevel@tonic-gate 		getdol();
352*7c478bd9Sstevel@tonic-gate 		goto top;
353*7c478bd9Sstevel@tonic-gate 	}
354*7c478bd9Sstevel@tonic-gate 	if (c == HIST && (flag & DOEXCL)) {
355*7c478bd9Sstevel@tonic-gate 		getexcl(0);
356*7c478bd9Sstevel@tonic-gate 		goto top;
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 	return (c);
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate getdol()
362*7c478bd9Sstevel@tonic-gate {
363*7c478bd9Sstevel@tonic-gate 	register tchar *np, *p;
364*7c478bd9Sstevel@tonic-gate 	tchar name[MAX_VREF_LEN];
365*7c478bd9Sstevel@tonic-gate 	register int c;
366*7c478bd9Sstevel@tonic-gate 	int sc;
367*7c478bd9Sstevel@tonic-gate 	bool special = 0;
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate #ifdef TRACE
370*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getdol()\n");
371*7c478bd9Sstevel@tonic-gate #endif
372*7c478bd9Sstevel@tonic-gate 	np = name, *np++ = '$';
373*7c478bd9Sstevel@tonic-gate 	c = sc = getC(DOEXCL);
374*7c478bd9Sstevel@tonic-gate 	if (isspnl(c)) {
375*7c478bd9Sstevel@tonic-gate 		ungetD(c);
376*7c478bd9Sstevel@tonic-gate 		ungetC('$' | QUOTE);
377*7c478bd9Sstevel@tonic-gate 		return;
378*7c478bd9Sstevel@tonic-gate 	}
379*7c478bd9Sstevel@tonic-gate 	if (c == '{')
380*7c478bd9Sstevel@tonic-gate 		*np++ = c, c = getC(DOEXCL);
381*7c478bd9Sstevel@tonic-gate 	if (c == '#' || c == '?')
382*7c478bd9Sstevel@tonic-gate 		special++, *np++ = c, c = getC(DOEXCL);
383*7c478bd9Sstevel@tonic-gate 	*np++ = c;
384*7c478bd9Sstevel@tonic-gate 	switch (c) {
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	case '<':
387*7c478bd9Sstevel@tonic-gate 	case '$':
388*7c478bd9Sstevel@tonic-gate 	case '*':
389*7c478bd9Sstevel@tonic-gate 		if (special)
390*7c478bd9Sstevel@tonic-gate 			goto vsyn;
391*7c478bd9Sstevel@tonic-gate 		goto ret;
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	case '\n':
394*7c478bd9Sstevel@tonic-gate 		ungetD(c);
395*7c478bd9Sstevel@tonic-gate 		np--;
396*7c478bd9Sstevel@tonic-gate 		goto vsyn;
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	default:
399*7c478bd9Sstevel@tonic-gate 		p = np;
400*7c478bd9Sstevel@tonic-gate 		if (digit(c)) {
401*7c478bd9Sstevel@tonic-gate 			/* make sure the variable names are MAX_VAR_LEN chars or less */
402*7c478bd9Sstevel@tonic-gate 			while (digit(c = getC(DOEXCL)) && (np-p) < MAX_VAR_LEN) {
403*7c478bd9Sstevel@tonic-gate 				*np++ = c;
404*7c478bd9Sstevel@tonic-gate 			}
405*7c478bd9Sstevel@tonic-gate 		} else if (letter(c)) {
406*7c478bd9Sstevel@tonic-gate 			while ((letter(c = getC(DOEXCL)) || digit(c)) &&
407*7c478bd9Sstevel@tonic-gate 				(np-p) < MAX_VAR_LEN ) {
408*7c478bd9Sstevel@tonic-gate 				*np++ = c;
409*7c478bd9Sstevel@tonic-gate 			}
410*7c478bd9Sstevel@tonic-gate 		}
411*7c478bd9Sstevel@tonic-gate 		else
412*7c478bd9Sstevel@tonic-gate 			goto vsyn;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 		if( (np - p) > MAX_VAR_LEN )
415*7c478bd9Sstevel@tonic-gate 		{
416*7c478bd9Sstevel@tonic-gate 			seterr("Variable name too long");
417*7c478bd9Sstevel@tonic-gate 			goto ret;
418*7c478bd9Sstevel@tonic-gate 		}
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 	if (c == '[') {
421*7c478bd9Sstevel@tonic-gate 		*np++ = c;
422*7c478bd9Sstevel@tonic-gate 		do {
423*7c478bd9Sstevel@tonic-gate 			c = getC(DOEXCL);
424*7c478bd9Sstevel@tonic-gate 			if (c == '\n') {
425*7c478bd9Sstevel@tonic-gate 				ungetD(c);
426*7c478bd9Sstevel@tonic-gate 				np--;
427*7c478bd9Sstevel@tonic-gate 				goto vsyn;
428*7c478bd9Sstevel@tonic-gate 			}
429*7c478bd9Sstevel@tonic-gate 			/* need to leave space for possible modifiers */
430*7c478bd9Sstevel@tonic-gate 			if (np >= &name[MAX_VREF_LEN - 8])
431*7c478bd9Sstevel@tonic-gate 			{
432*7c478bd9Sstevel@tonic-gate 				seterr("Variable reference too long");
433*7c478bd9Sstevel@tonic-gate 				goto ret;
434*7c478bd9Sstevel@tonic-gate 			}
435*7c478bd9Sstevel@tonic-gate 			*np++ = c;
436*7c478bd9Sstevel@tonic-gate 		} while (c != ']');
437*7c478bd9Sstevel@tonic-gate 		c = getC(DOEXCL);
438*7c478bd9Sstevel@tonic-gate 	}
439*7c478bd9Sstevel@tonic-gate 	if (c == ':') {
440*7c478bd9Sstevel@tonic-gate 		*np++ = c, c = getC(DOEXCL);
441*7c478bd9Sstevel@tonic-gate 		if (c == 'g')
442*7c478bd9Sstevel@tonic-gate 			*np++ = c, c = getC(DOEXCL);
443*7c478bd9Sstevel@tonic-gate 		*np++ = c;
444*7c478bd9Sstevel@tonic-gate 		if (!any(c, S_htrqxe))
445*7c478bd9Sstevel@tonic-gate 			goto vsyn;
446*7c478bd9Sstevel@tonic-gate 	} else
447*7c478bd9Sstevel@tonic-gate 		ungetD(c);
448*7c478bd9Sstevel@tonic-gate 	if (sc == '{') {
449*7c478bd9Sstevel@tonic-gate 		c = getC(DOEXCL);
450*7c478bd9Sstevel@tonic-gate 		if (c != '}') {
451*7c478bd9Sstevel@tonic-gate 			ungetC(c);
452*7c478bd9Sstevel@tonic-gate 			goto vsyn;
453*7c478bd9Sstevel@tonic-gate 		}
454*7c478bd9Sstevel@tonic-gate 		*np++ = c;
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate ret:
457*7c478bd9Sstevel@tonic-gate 	*np = 0;
458*7c478bd9Sstevel@tonic-gate 	addla(name);
459*7c478bd9Sstevel@tonic-gate 	return;
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate vsyn:
462*7c478bd9Sstevel@tonic-gate 	seterr("Variable syntax");
463*7c478bd9Sstevel@tonic-gate 	goto ret;
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate addla(cp)
467*7c478bd9Sstevel@tonic-gate 	tchar *cp;
468*7c478bd9Sstevel@tonic-gate {
469*7c478bd9Sstevel@tonic-gate 	tchar *buf;
470*7c478bd9Sstevel@tonic-gate 	int len = 0;
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate #ifdef TRACE
473*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- addla()\n");
474*7c478bd9Sstevel@tonic-gate #endif
475*7c478bd9Sstevel@tonic-gate 	if (lap) {
476*7c478bd9Sstevel@tonic-gate 		len = strlen_(lap);
477*7c478bd9Sstevel@tonic-gate 		buf = xalloc((len+1) * sizeof (tchar));
478*7c478bd9Sstevel@tonic-gate 		(void) strcpy_(buf, lap);
479*7c478bd9Sstevel@tonic-gate 	}
480*7c478bd9Sstevel@tonic-gate 	len += strlen_(cp);
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	/* len+5 is allow 4 additional charecters just to be safe */
483*7c478bd9Sstevel@tonic-gate 	labuf = xrealloc(labuf, (len+5) * sizeof (tchar));
484*7c478bd9Sstevel@tonic-gate 	(void) strcpy_(labuf, cp);
485*7c478bd9Sstevel@tonic-gate 	if (lap) {
486*7c478bd9Sstevel@tonic-gate 		(void) strcat_(labuf, buf);
487*7c478bd9Sstevel@tonic-gate 		free(buf);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 	lap = labuf;
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate tchar	lhsb[32];
493*7c478bd9Sstevel@tonic-gate tchar	slhs[32];
494*7c478bd9Sstevel@tonic-gate tchar	rhsb[64];
495*7c478bd9Sstevel@tonic-gate int	quesarg;
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate getexcl(sc)
498*7c478bd9Sstevel@tonic-gate 	tchar sc;
499*7c478bd9Sstevel@tonic-gate {
500*7c478bd9Sstevel@tonic-gate 	register struct wordent *hp, *ip;
501*7c478bd9Sstevel@tonic-gate 	int left, right, dol;
502*7c478bd9Sstevel@tonic-gate 	register int c;
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate #ifdef TRACE
505*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getexcl()\n");
506*7c478bd9Sstevel@tonic-gate #endif
507*7c478bd9Sstevel@tonic-gate 	if (sc == 0) {
508*7c478bd9Sstevel@tonic-gate 		sc = getC(0);
509*7c478bd9Sstevel@tonic-gate 		if (sc != '{') {
510*7c478bd9Sstevel@tonic-gate 			ungetC(sc);
511*7c478bd9Sstevel@tonic-gate 			sc = 0;
512*7c478bd9Sstevel@tonic-gate 		}
513*7c478bd9Sstevel@tonic-gate 	}
514*7c478bd9Sstevel@tonic-gate 	quesarg = -1;
515*7c478bd9Sstevel@tonic-gate 	lastev = eventno;
516*7c478bd9Sstevel@tonic-gate 	hp = gethent(sc);
517*7c478bd9Sstevel@tonic-gate 	if (hp == 0)
518*7c478bd9Sstevel@tonic-gate 		return;
519*7c478bd9Sstevel@tonic-gate 	hadhist = 1;
520*7c478bd9Sstevel@tonic-gate 	dol = 0;
521*7c478bd9Sstevel@tonic-gate 	if (hp == alhistp)
522*7c478bd9Sstevel@tonic-gate 		for (ip = hp->next->next; ip != alhistt; ip = ip->next)
523*7c478bd9Sstevel@tonic-gate 			dol++;
524*7c478bd9Sstevel@tonic-gate 	else
525*7c478bd9Sstevel@tonic-gate 		for (ip = hp->next->next; ip != hp->prev; ip = ip->next)
526*7c478bd9Sstevel@tonic-gate 			dol++;
527*7c478bd9Sstevel@tonic-gate 	left = 0, right = dol;
528*7c478bd9Sstevel@tonic-gate 	if (sc == HISTSUB) {
529*7c478bd9Sstevel@tonic-gate 		ungetC('s'), unreadc(HISTSUB), c = ':';
530*7c478bd9Sstevel@tonic-gate 		goto subst;
531*7c478bd9Sstevel@tonic-gate 	}
532*7c478bd9Sstevel@tonic-gate 	c = getC(0);
533*7c478bd9Sstevel@tonic-gate 	/* if (!any(c, ":^$*-%")) */		/* change needed for char -> tchar */
534*7c478bd9Sstevel@tonic-gate 	if (! (c == ':' || c == '^' || c == '$' || c == '*' ||
535*7c478bd9Sstevel@tonic-gate 	       c == '-' || c == '%' ))
536*7c478bd9Sstevel@tonic-gate 		goto subst;
537*7c478bd9Sstevel@tonic-gate 	left = right = -1;
538*7c478bd9Sstevel@tonic-gate 	if (c == ':') {
539*7c478bd9Sstevel@tonic-gate 		c = getC(0);
540*7c478bd9Sstevel@tonic-gate 		unreadc(c);
541*7c478bd9Sstevel@tonic-gate 		if (letter(c) || c == '&') {
542*7c478bd9Sstevel@tonic-gate 			c = ':';
543*7c478bd9Sstevel@tonic-gate 			left = 0, right = dol;
544*7c478bd9Sstevel@tonic-gate 			goto subst;
545*7c478bd9Sstevel@tonic-gate 		}
546*7c478bd9Sstevel@tonic-gate 	} else
547*7c478bd9Sstevel@tonic-gate 		ungetC(c);
548*7c478bd9Sstevel@tonic-gate 	if (!getsel(&left, &right, dol))
549*7c478bd9Sstevel@tonic-gate 		return;
550*7c478bd9Sstevel@tonic-gate 	c = getC(0);
551*7c478bd9Sstevel@tonic-gate 	if (c == '*')
552*7c478bd9Sstevel@tonic-gate 		ungetC(c), c = '-';
553*7c478bd9Sstevel@tonic-gate 	if (c == '-') {
554*7c478bd9Sstevel@tonic-gate 		if (!getsel(&left, &right, dol))
555*7c478bd9Sstevel@tonic-gate 			return;
556*7c478bd9Sstevel@tonic-gate 		c = getC(0);
557*7c478bd9Sstevel@tonic-gate 	}
558*7c478bd9Sstevel@tonic-gate subst:
559*7c478bd9Sstevel@tonic-gate 	exclc = right - left + 1;
560*7c478bd9Sstevel@tonic-gate 	while (--left >= 0)
561*7c478bd9Sstevel@tonic-gate 		hp = hp->next;
562*7c478bd9Sstevel@tonic-gate 	if (sc == HISTSUB || c == ':') {
563*7c478bd9Sstevel@tonic-gate 		do {
564*7c478bd9Sstevel@tonic-gate 			hp = getsub(hp);
565*7c478bd9Sstevel@tonic-gate 			c = getC(0);
566*7c478bd9Sstevel@tonic-gate 		} while (c == ':');
567*7c478bd9Sstevel@tonic-gate 	}
568*7c478bd9Sstevel@tonic-gate 	unreadc(c);
569*7c478bd9Sstevel@tonic-gate 	if (sc == '{') {
570*7c478bd9Sstevel@tonic-gate 		c = getC(0);
571*7c478bd9Sstevel@tonic-gate 		if (c != '}')
572*7c478bd9Sstevel@tonic-gate 			seterr("Bad ! form");
573*7c478bd9Sstevel@tonic-gate 	}
574*7c478bd9Sstevel@tonic-gate 	exclnxt = hp;
575*7c478bd9Sstevel@tonic-gate }
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate struct wordent *
578*7c478bd9Sstevel@tonic-gate getsub(en)
579*7c478bd9Sstevel@tonic-gate 	struct wordent *en;
580*7c478bd9Sstevel@tonic-gate {
581*7c478bd9Sstevel@tonic-gate 	register tchar *cp;
582*7c478bd9Sstevel@tonic-gate 	int delim;
583*7c478bd9Sstevel@tonic-gate 	register int c;
584*7c478bd9Sstevel@tonic-gate 	int sc;
585*7c478bd9Sstevel@tonic-gate 	bool global = 0;
586*7c478bd9Sstevel@tonic-gate 	tchar orhsb[(sizeof rhsb)/(sizeof rhsb[0])];
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate #ifdef TRACE
589*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getsub()\n");
590*7c478bd9Sstevel@tonic-gate #endif
591*7c478bd9Sstevel@tonic-gate 	exclnxt = 0;
592*7c478bd9Sstevel@tonic-gate 	sc = c = getC(0);
593*7c478bd9Sstevel@tonic-gate 	if (c == 'g')
594*7c478bd9Sstevel@tonic-gate 		global++, c = getC(0);
595*7c478bd9Sstevel@tonic-gate 	switch (c) {
596*7c478bd9Sstevel@tonic-gate 
597*7c478bd9Sstevel@tonic-gate 	case 'p':
598*7c478bd9Sstevel@tonic-gate 		justpr++;
599*7c478bd9Sstevel@tonic-gate 		goto ret;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	case 'x':
602*7c478bd9Sstevel@tonic-gate 	case 'q':
603*7c478bd9Sstevel@tonic-gate 		global++;
604*7c478bd9Sstevel@tonic-gate 		/* fall into ... */
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	case 'h':
607*7c478bd9Sstevel@tonic-gate 	case 'r':
608*7c478bd9Sstevel@tonic-gate 	case 't':
609*7c478bd9Sstevel@tonic-gate 	case 'e':
610*7c478bd9Sstevel@tonic-gate 		break;
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 	case '&':
613*7c478bd9Sstevel@tonic-gate 		if (slhs[0] == 0) {
614*7c478bd9Sstevel@tonic-gate 			seterr("No prev sub");
615*7c478bd9Sstevel@tonic-gate 			goto ret;
616*7c478bd9Sstevel@tonic-gate 		}
617*7c478bd9Sstevel@tonic-gate 		(void) strcpy_(lhsb, slhs);
618*7c478bd9Sstevel@tonic-gate 		break;
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate /*
621*7c478bd9Sstevel@tonic-gate 	case '~':
622*7c478bd9Sstevel@tonic-gate 		if (lhsb[0] == 0)
623*7c478bd9Sstevel@tonic-gate 			goto badlhs;
624*7c478bd9Sstevel@tonic-gate 		break;
625*7c478bd9Sstevel@tonic-gate */
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 	case 's':
628*7c478bd9Sstevel@tonic-gate 		delim = getC(0);
629*7c478bd9Sstevel@tonic-gate 		if (alnum(delim) || isspnl(delim)){
630*7c478bd9Sstevel@tonic-gate 			unreadc(delim);
631*7c478bd9Sstevel@tonic-gate bads:
632*7c478bd9Sstevel@tonic-gate 			lhsb[0] = 0;
633*7c478bd9Sstevel@tonic-gate 			seterr("Bad substitute");
634*7c478bd9Sstevel@tonic-gate 			goto ret;
635*7c478bd9Sstevel@tonic-gate 		}
636*7c478bd9Sstevel@tonic-gate 		cp = lhsb;
637*7c478bd9Sstevel@tonic-gate 		for (;;) {
638*7c478bd9Sstevel@tonic-gate 			c = getC(0);
639*7c478bd9Sstevel@tonic-gate 			if (c == '\n') {
640*7c478bd9Sstevel@tonic-gate 				unreadc(c);
641*7c478bd9Sstevel@tonic-gate 				break;
642*7c478bd9Sstevel@tonic-gate 			}
643*7c478bd9Sstevel@tonic-gate 			if (c == delim)
644*7c478bd9Sstevel@tonic-gate 				break;
645*7c478bd9Sstevel@tonic-gate 			if (cp > &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2])
646*7c478bd9Sstevel@tonic-gate 				goto bads;
647*7c478bd9Sstevel@tonic-gate 			if (c == '\\') {
648*7c478bd9Sstevel@tonic-gate 				c = getC(0);
649*7c478bd9Sstevel@tonic-gate 				if (c != delim && c != '\\')
650*7c478bd9Sstevel@tonic-gate 					*cp++ = '\\';
651*7c478bd9Sstevel@tonic-gate 			}
652*7c478bd9Sstevel@tonic-gate 			*cp++ = c;
653*7c478bd9Sstevel@tonic-gate 		}
654*7c478bd9Sstevel@tonic-gate 		if (cp != lhsb)
655*7c478bd9Sstevel@tonic-gate 			*cp++ = 0;
656*7c478bd9Sstevel@tonic-gate 		else if (lhsb[0] == 0) {
657*7c478bd9Sstevel@tonic-gate /*badlhs:*/
658*7c478bd9Sstevel@tonic-gate 			seterr("No prev lhs");
659*7c478bd9Sstevel@tonic-gate 			goto ret;
660*7c478bd9Sstevel@tonic-gate 		}
661*7c478bd9Sstevel@tonic-gate 		cp = rhsb;
662*7c478bd9Sstevel@tonic-gate 		(void) strcpy_(orhsb, cp);
663*7c478bd9Sstevel@tonic-gate 		for (;;) {
664*7c478bd9Sstevel@tonic-gate 			c = getC(0);
665*7c478bd9Sstevel@tonic-gate 			if (c == '\n') {
666*7c478bd9Sstevel@tonic-gate 				unreadc(c);
667*7c478bd9Sstevel@tonic-gate 				break;
668*7c478bd9Sstevel@tonic-gate 			}
669*7c478bd9Sstevel@tonic-gate 			if (c == delim)
670*7c478bd9Sstevel@tonic-gate 				break;
671*7c478bd9Sstevel@tonic-gate /*
672*7c478bd9Sstevel@tonic-gate 			if (c == '~') {
673*7c478bd9Sstevel@tonic-gate 				if (&cp[strlen_(orhsb)]
674*7c478bd9Sstevel@tonic-gate 				> &rhsb[(sizeof rhsb)/(sizeof rhsb[0]) - 2])
675*7c478bd9Sstevel@tonic-gate 					goto toorhs;
676*7c478bd9Sstevel@tonic-gate 				(void) strcpy_(cp, orhsb);
677*7c478bd9Sstevel@tonic-gate 				cp = strend(cp);
678*7c478bd9Sstevel@tonic-gate 				continue;
679*7c478bd9Sstevel@tonic-gate 			}
680*7c478bd9Sstevel@tonic-gate */
681*7c478bd9Sstevel@tonic-gate 			if (cp > &rhsb[(sizeof rhsb)/(sizeof rhsb[0]) - 2]) {
682*7c478bd9Sstevel@tonic-gate /*toorhs:*/
683*7c478bd9Sstevel@tonic-gate 				seterr("Rhs too long");
684*7c478bd9Sstevel@tonic-gate 				goto ret;
685*7c478bd9Sstevel@tonic-gate 			}
686*7c478bd9Sstevel@tonic-gate 			if (c == '\\') {
687*7c478bd9Sstevel@tonic-gate 				c = getC(0);
688*7c478bd9Sstevel@tonic-gate 				if (c != delim /* && c != '~' */)
689*7c478bd9Sstevel@tonic-gate 					*cp++ = '\\';
690*7c478bd9Sstevel@tonic-gate 			}
691*7c478bd9Sstevel@tonic-gate 			*cp++ = c;
692*7c478bd9Sstevel@tonic-gate 		}
693*7c478bd9Sstevel@tonic-gate 		*cp++ = 0;
694*7c478bd9Sstevel@tonic-gate 		break;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	default:
697*7c478bd9Sstevel@tonic-gate 		if (c == '\n')
698*7c478bd9Sstevel@tonic-gate 			unreadc(c);
699*7c478bd9Sstevel@tonic-gate 		seterrc(gettext("Bad ! modifier: "), c);
700*7c478bd9Sstevel@tonic-gate 		goto ret;
701*7c478bd9Sstevel@tonic-gate 	}
702*7c478bd9Sstevel@tonic-gate 	(void) strcpy_(slhs, lhsb);
703*7c478bd9Sstevel@tonic-gate 	if (exclc)
704*7c478bd9Sstevel@tonic-gate 		en = dosub(sc, en, global);
705*7c478bd9Sstevel@tonic-gate ret:
706*7c478bd9Sstevel@tonic-gate 	return (en);
707*7c478bd9Sstevel@tonic-gate }
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate struct wordent *
710*7c478bd9Sstevel@tonic-gate dosub(sc, en, global)
711*7c478bd9Sstevel@tonic-gate 	int sc;
712*7c478bd9Sstevel@tonic-gate 	struct wordent *en;
713*7c478bd9Sstevel@tonic-gate 	bool global;
714*7c478bd9Sstevel@tonic-gate {
715*7c478bd9Sstevel@tonic-gate 	struct wordent lex;
716*7c478bd9Sstevel@tonic-gate 	bool didsub = 0;
717*7c478bd9Sstevel@tonic-gate 	struct wordent *hp = &lex;
718*7c478bd9Sstevel@tonic-gate 	register struct wordent *wdp;
719*7c478bd9Sstevel@tonic-gate 	register int i = exclc;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate #ifdef TRACE
722*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dosub()\n");
723*7c478bd9Sstevel@tonic-gate #endif
724*7c478bd9Sstevel@tonic-gate 	wdp = hp;
725*7c478bd9Sstevel@tonic-gate 	while (--i >= 0) {
726*7c478bd9Sstevel@tonic-gate 		register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
727*7c478bd9Sstevel@tonic-gate 
728*7c478bd9Sstevel@tonic-gate 		new->prev = wdp;
729*7c478bd9Sstevel@tonic-gate 		new->next = hp;
730*7c478bd9Sstevel@tonic-gate 		wdp->next = new;
731*7c478bd9Sstevel@tonic-gate 		wdp = new;
732*7c478bd9Sstevel@tonic-gate 		en = en->next;
733*7c478bd9Sstevel@tonic-gate 		wdp->word = global || didsub == 0 ?
734*7c478bd9Sstevel@tonic-gate 		    subword(en->word, sc, &didsub) : savestr(en->word);
735*7c478bd9Sstevel@tonic-gate 	}
736*7c478bd9Sstevel@tonic-gate 	if (didsub == 0)
737*7c478bd9Sstevel@tonic-gate 		seterr("Modifier failed");
738*7c478bd9Sstevel@tonic-gate 	hp->prev = wdp;
739*7c478bd9Sstevel@tonic-gate 	return (&enthist(-1000, &lex, 0)->Hlex);
740*7c478bd9Sstevel@tonic-gate }
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate tchar *
743*7c478bd9Sstevel@tonic-gate subword(cp, type, adid)
744*7c478bd9Sstevel@tonic-gate 	tchar *cp;
745*7c478bd9Sstevel@tonic-gate 	int type;
746*7c478bd9Sstevel@tonic-gate 	bool *adid;
747*7c478bd9Sstevel@tonic-gate {
748*7c478bd9Sstevel@tonic-gate 	tchar wbuf[BUFSIZ];
749*7c478bd9Sstevel@tonic-gate 	register tchar *wp, *mp, *np;
750*7c478bd9Sstevel@tonic-gate 	register int i;
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate #ifdef TRACE
753*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- subword()\n");
754*7c478bd9Sstevel@tonic-gate #endif
755*7c478bd9Sstevel@tonic-gate 	switch (type) {
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate 	case 'r':
758*7c478bd9Sstevel@tonic-gate 	case 'e':
759*7c478bd9Sstevel@tonic-gate 	case 'h':
760*7c478bd9Sstevel@tonic-gate 	case 't':
761*7c478bd9Sstevel@tonic-gate 	case 'q':
762*7c478bd9Sstevel@tonic-gate 	case 'x':
763*7c478bd9Sstevel@tonic-gate 		wp = domod(cp, type);
764*7c478bd9Sstevel@tonic-gate 		if (wp == 0)
765*7c478bd9Sstevel@tonic-gate 			return (savestr(cp));
766*7c478bd9Sstevel@tonic-gate 		*adid = 1;
767*7c478bd9Sstevel@tonic-gate 		return (wp);
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 	default:
770*7c478bd9Sstevel@tonic-gate 		wp = wbuf;
771*7c478bd9Sstevel@tonic-gate 		i = BUFSIZ - 4;
772*7c478bd9Sstevel@tonic-gate 		for (mp = cp; *mp; mp++)
773*7c478bd9Sstevel@tonic-gate 			if (matchs(mp, lhsb)) {
774*7c478bd9Sstevel@tonic-gate 				for (np = cp; np < mp;)
775*7c478bd9Sstevel@tonic-gate 					*wp++ = *np++, --i;
776*7c478bd9Sstevel@tonic-gate 				for (np = rhsb; *np; np++) switch (*np) {
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 				case '\\':
779*7c478bd9Sstevel@tonic-gate 					if (np[1] == '&')
780*7c478bd9Sstevel@tonic-gate 						np++;
781*7c478bd9Sstevel@tonic-gate 					/* fall into ... */
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 				default:
784*7c478bd9Sstevel@tonic-gate 					if (--i < 0)
785*7c478bd9Sstevel@tonic-gate 						goto ovflo;
786*7c478bd9Sstevel@tonic-gate 					*wp++ = *np;
787*7c478bd9Sstevel@tonic-gate 					continue;
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 				case '&':
790*7c478bd9Sstevel@tonic-gate 					i -= strlen_(lhsb);
791*7c478bd9Sstevel@tonic-gate 					if (i < 0)
792*7c478bd9Sstevel@tonic-gate 						goto ovflo;
793*7c478bd9Sstevel@tonic-gate 					*wp = 0;
794*7c478bd9Sstevel@tonic-gate 					(void) strcat_(wp, lhsb);
795*7c478bd9Sstevel@tonic-gate 					wp = strend(wp);
796*7c478bd9Sstevel@tonic-gate 					continue;
797*7c478bd9Sstevel@tonic-gate 				}
798*7c478bd9Sstevel@tonic-gate 				mp += strlen_(lhsb);
799*7c478bd9Sstevel@tonic-gate 				i -= strlen_(mp);
800*7c478bd9Sstevel@tonic-gate 				if (i < 0) {
801*7c478bd9Sstevel@tonic-gate ovflo:
802*7c478bd9Sstevel@tonic-gate 					seterr("Subst buf ovflo");
803*7c478bd9Sstevel@tonic-gate 					return (S_ /*""*/);
804*7c478bd9Sstevel@tonic-gate 				}
805*7c478bd9Sstevel@tonic-gate 				*wp = 0;
806*7c478bd9Sstevel@tonic-gate 				(void) strcat_(wp, mp);
807*7c478bd9Sstevel@tonic-gate 				*adid = 1;
808*7c478bd9Sstevel@tonic-gate 				return (savestr(wbuf));
809*7c478bd9Sstevel@tonic-gate 			}
810*7c478bd9Sstevel@tonic-gate 		return (savestr(cp));
811*7c478bd9Sstevel@tonic-gate 	}
812*7c478bd9Sstevel@tonic-gate }
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate tchar *
815*7c478bd9Sstevel@tonic-gate domod(cp, type)
816*7c478bd9Sstevel@tonic-gate 	tchar *cp;
817*7c478bd9Sstevel@tonic-gate 	int type;
818*7c478bd9Sstevel@tonic-gate {
819*7c478bd9Sstevel@tonic-gate 	register tchar *wp, *xp;
820*7c478bd9Sstevel@tonic-gate 	register int c;
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate #ifdef TRACE
823*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- domod()\n");
824*7c478bd9Sstevel@tonic-gate #endif
825*7c478bd9Sstevel@tonic-gate 	switch (type) {
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	case 'x':
828*7c478bd9Sstevel@tonic-gate 	case 'q':
829*7c478bd9Sstevel@tonic-gate 		wp = savestr(cp);
830*7c478bd9Sstevel@tonic-gate 		for (xp = wp; c = *xp; xp++)
831*7c478bd9Sstevel@tonic-gate 			if (!issp(c) || type == 'q')
832*7c478bd9Sstevel@tonic-gate 				*xp |= QUOTE;
833*7c478bd9Sstevel@tonic-gate 		return (wp);
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 	case 'h':
836*7c478bd9Sstevel@tonic-gate 	case 't':
837*7c478bd9Sstevel@tonic-gate 		if (!any('/', cp))
838*7c478bd9Sstevel@tonic-gate 			return (type == 't' ? savestr(cp) : 0);
839*7c478bd9Sstevel@tonic-gate 		wp = strend(cp);
840*7c478bd9Sstevel@tonic-gate 		while (*--wp != '/')
841*7c478bd9Sstevel@tonic-gate 			continue;
842*7c478bd9Sstevel@tonic-gate 		if (type == 'h')
843*7c478bd9Sstevel@tonic-gate 			xp = savestr(cp), xp[wp - cp] = 0;
844*7c478bd9Sstevel@tonic-gate 		else
845*7c478bd9Sstevel@tonic-gate 			xp = savestr(wp + 1);
846*7c478bd9Sstevel@tonic-gate 		return (xp);
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate 	case 'e':
849*7c478bd9Sstevel@tonic-gate 	case 'r':
850*7c478bd9Sstevel@tonic-gate 		wp = strend(cp);
851*7c478bd9Sstevel@tonic-gate 		for (wp--; wp >= cp && *wp != '/'; wp--)
852*7c478bd9Sstevel@tonic-gate 			if (*wp == '.') {
853*7c478bd9Sstevel@tonic-gate 				if (type == 'e')
854*7c478bd9Sstevel@tonic-gate 					xp = savestr(wp + 1);
855*7c478bd9Sstevel@tonic-gate 				else
856*7c478bd9Sstevel@tonic-gate 					xp = savestr(cp), xp[wp - cp] = 0;
857*7c478bd9Sstevel@tonic-gate 				return (xp);
858*7c478bd9Sstevel@tonic-gate 			}
859*7c478bd9Sstevel@tonic-gate 		return (savestr(type == 'e' ? S_ /*""*/ : cp));
860*7c478bd9Sstevel@tonic-gate 	}
861*7c478bd9Sstevel@tonic-gate 	return (0);
862*7c478bd9Sstevel@tonic-gate }
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate matchs(str, pat)
865*7c478bd9Sstevel@tonic-gate 	register tchar *str, *pat;
866*7c478bd9Sstevel@tonic-gate {
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate #ifdef TRACE
869*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- matchs()\n");
870*7c478bd9Sstevel@tonic-gate #endif
871*7c478bd9Sstevel@tonic-gate 	while (*str && *pat && *str == *pat)
872*7c478bd9Sstevel@tonic-gate 		str++, pat++;
873*7c478bd9Sstevel@tonic-gate 	return (*pat == 0);
874*7c478bd9Sstevel@tonic-gate }
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate getsel(al, ar, dol)
877*7c478bd9Sstevel@tonic-gate 	register int *al, *ar;
878*7c478bd9Sstevel@tonic-gate 	int dol;
879*7c478bd9Sstevel@tonic-gate {
880*7c478bd9Sstevel@tonic-gate 	register int c = getC(0);
881*7c478bd9Sstevel@tonic-gate 	register int i;
882*7c478bd9Sstevel@tonic-gate 	bool first = *al < 0;
883*7c478bd9Sstevel@tonic-gate 
884*7c478bd9Sstevel@tonic-gate #ifdef TRACE
885*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getsel()\n");
886*7c478bd9Sstevel@tonic-gate #endif
887*7c478bd9Sstevel@tonic-gate 	switch (c) {
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 	case '%':
890*7c478bd9Sstevel@tonic-gate 		if (quesarg == -1)
891*7c478bd9Sstevel@tonic-gate 			goto bad;
892*7c478bd9Sstevel@tonic-gate 		if (*al < 0)
893*7c478bd9Sstevel@tonic-gate 			*al = quesarg;
894*7c478bd9Sstevel@tonic-gate 		*ar = quesarg;
895*7c478bd9Sstevel@tonic-gate 		break;
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate 	case '-':
898*7c478bd9Sstevel@tonic-gate 		if (*al < 0) {
899*7c478bd9Sstevel@tonic-gate 			*al = 0;
900*7c478bd9Sstevel@tonic-gate 			*ar = dol - 1;
901*7c478bd9Sstevel@tonic-gate 			unreadc(c);
902*7c478bd9Sstevel@tonic-gate 		}
903*7c478bd9Sstevel@tonic-gate 		return (1);
904*7c478bd9Sstevel@tonic-gate 
905*7c478bd9Sstevel@tonic-gate 	case '^':
906*7c478bd9Sstevel@tonic-gate 		if (*al < 0)
907*7c478bd9Sstevel@tonic-gate 			*al = 1;
908*7c478bd9Sstevel@tonic-gate 		*ar = 1;
909*7c478bd9Sstevel@tonic-gate 		break;
910*7c478bd9Sstevel@tonic-gate 
911*7c478bd9Sstevel@tonic-gate 	case '$':
912*7c478bd9Sstevel@tonic-gate 		if (*al < 0)
913*7c478bd9Sstevel@tonic-gate 			*al = dol;
914*7c478bd9Sstevel@tonic-gate 		*ar = dol;
915*7c478bd9Sstevel@tonic-gate 		break;
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate 	case '*':
918*7c478bd9Sstevel@tonic-gate 		if (*al < 0)
919*7c478bd9Sstevel@tonic-gate 			*al = 1;
920*7c478bd9Sstevel@tonic-gate 		*ar = dol;
921*7c478bd9Sstevel@tonic-gate 		if (*ar < *al) {
922*7c478bd9Sstevel@tonic-gate 			*ar = 0;
923*7c478bd9Sstevel@tonic-gate 			*al = 1;
924*7c478bd9Sstevel@tonic-gate 			return (1);
925*7c478bd9Sstevel@tonic-gate 		}
926*7c478bd9Sstevel@tonic-gate 		break;
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	default:
929*7c478bd9Sstevel@tonic-gate 		if (digit(c)) {
930*7c478bd9Sstevel@tonic-gate 			i = 0;
931*7c478bd9Sstevel@tonic-gate 			while (digit(c)) {
932*7c478bd9Sstevel@tonic-gate 				i = i * 10 + c - '0';
933*7c478bd9Sstevel@tonic-gate 				c = getC(0);
934*7c478bd9Sstevel@tonic-gate 			}
935*7c478bd9Sstevel@tonic-gate 			if (i < 0)
936*7c478bd9Sstevel@tonic-gate 				i = dol + 1;
937*7c478bd9Sstevel@tonic-gate 			if (*al < 0)
938*7c478bd9Sstevel@tonic-gate 				*al = i;
939*7c478bd9Sstevel@tonic-gate 			*ar = i;
940*7c478bd9Sstevel@tonic-gate 		} else
941*7c478bd9Sstevel@tonic-gate 			if (*al < 0)
942*7c478bd9Sstevel@tonic-gate 				*al = 0, *ar = dol;
943*7c478bd9Sstevel@tonic-gate 			else
944*7c478bd9Sstevel@tonic-gate 				*ar = dol - 1;
945*7c478bd9Sstevel@tonic-gate 		unreadc(c);
946*7c478bd9Sstevel@tonic-gate 		break;
947*7c478bd9Sstevel@tonic-gate 	}
948*7c478bd9Sstevel@tonic-gate 	if (first) {
949*7c478bd9Sstevel@tonic-gate 		c = getC(0);
950*7c478bd9Sstevel@tonic-gate 		unreadc(c);
951*7c478bd9Sstevel@tonic-gate 		/* if (any(c, "-$*")) */	/* char -> tchar */
952*7c478bd9Sstevel@tonic-gate 		if (c == '-' || c == '$' || c == '*')
953*7c478bd9Sstevel@tonic-gate 			return (1);
954*7c478bd9Sstevel@tonic-gate 	}
955*7c478bd9Sstevel@tonic-gate 	if (*al > *ar || *ar > dol) {
956*7c478bd9Sstevel@tonic-gate bad:
957*7c478bd9Sstevel@tonic-gate 		seterr("Bad ! arg selector");
958*7c478bd9Sstevel@tonic-gate 		return (0);
959*7c478bd9Sstevel@tonic-gate 	}
960*7c478bd9Sstevel@tonic-gate 	return (1);
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate }
963*7c478bd9Sstevel@tonic-gate 
964*7c478bd9Sstevel@tonic-gate struct wordent *
965*7c478bd9Sstevel@tonic-gate gethent(sc)
966*7c478bd9Sstevel@tonic-gate 	int sc;
967*7c478bd9Sstevel@tonic-gate {
968*7c478bd9Sstevel@tonic-gate 	register struct Hist *hp;
969*7c478bd9Sstevel@tonic-gate 	register tchar *np;
970*7c478bd9Sstevel@tonic-gate 	register int c;
971*7c478bd9Sstevel@tonic-gate 	int event;
972*7c478bd9Sstevel@tonic-gate 	bool back = 0;
973*7c478bd9Sstevel@tonic-gate 
974*7c478bd9Sstevel@tonic-gate #ifdef TRACE
975*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- gethent()\n");
976*7c478bd9Sstevel@tonic-gate #endif
977*7c478bd9Sstevel@tonic-gate 	c = sc == HISTSUB ? HIST : getC(0);
978*7c478bd9Sstevel@tonic-gate 	if (c == HIST) {
979*7c478bd9Sstevel@tonic-gate 		if (alhistp)
980*7c478bd9Sstevel@tonic-gate 			return (alhistp);
981*7c478bd9Sstevel@tonic-gate 		event = eventno;
982*7c478bd9Sstevel@tonic-gate 		goto skip;
983*7c478bd9Sstevel@tonic-gate 	}
984*7c478bd9Sstevel@tonic-gate 	switch (c) {
985*7c478bd9Sstevel@tonic-gate 
986*7c478bd9Sstevel@tonic-gate 	case ':':
987*7c478bd9Sstevel@tonic-gate 	case '^':
988*7c478bd9Sstevel@tonic-gate 	case '$':
989*7c478bd9Sstevel@tonic-gate 	case '*':
990*7c478bd9Sstevel@tonic-gate 	case '%':
991*7c478bd9Sstevel@tonic-gate 		ungetC(c);
992*7c478bd9Sstevel@tonic-gate 		if (lastev == eventno && alhistp)
993*7c478bd9Sstevel@tonic-gate 			return (alhistp);
994*7c478bd9Sstevel@tonic-gate 		event = lastev;
995*7c478bd9Sstevel@tonic-gate 		break;
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate 	case '-':
998*7c478bd9Sstevel@tonic-gate 		back = 1;
999*7c478bd9Sstevel@tonic-gate 		c = getC(0);
1000*7c478bd9Sstevel@tonic-gate 		goto number;
1001*7c478bd9Sstevel@tonic-gate 
1002*7c478bd9Sstevel@tonic-gate 	case '#':			/* !# is command being typed in (mrh) */
1003*7c478bd9Sstevel@tonic-gate 		return(&paraml);
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate 	default:
1006*7c478bd9Sstevel@tonic-gate 		/*if (any(c, "(=~")) {*/
1007*7c478bd9Sstevel@tonic-gate 		if (c == '(' || c == '=' || c == '~') {
1008*7c478bd9Sstevel@tonic-gate 			unreadc(c);
1009*7c478bd9Sstevel@tonic-gate 			ungetC(HIST);
1010*7c478bd9Sstevel@tonic-gate 			return (0);
1011*7c478bd9Sstevel@tonic-gate 		}
1012*7c478bd9Sstevel@tonic-gate 		if (digit(c))
1013*7c478bd9Sstevel@tonic-gate 			goto number;
1014*7c478bd9Sstevel@tonic-gate 		np = lhsb;
1015*7c478bd9Sstevel@tonic-gate 		/* while (!any(c, ": \t\\\n}")) { */
1016*7c478bd9Sstevel@tonic-gate 		while (! (c == ':' || c == '\\' || isspnl(c) || c == '}')) {
1017*7c478bd9Sstevel@tonic-gate 			if (np < &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2])
1018*7c478bd9Sstevel@tonic-gate 				*np++ = c;
1019*7c478bd9Sstevel@tonic-gate 			c = getC(0);
1020*7c478bd9Sstevel@tonic-gate 		}
1021*7c478bd9Sstevel@tonic-gate 		unreadc(c);
1022*7c478bd9Sstevel@tonic-gate 		if (np == lhsb) {
1023*7c478bd9Sstevel@tonic-gate 			ungetC(HIST);
1024*7c478bd9Sstevel@tonic-gate 			return (0);
1025*7c478bd9Sstevel@tonic-gate 		}
1026*7c478bd9Sstevel@tonic-gate 		*np++ = 0;
1027*7c478bd9Sstevel@tonic-gate 		hp = findev(lhsb, 0);
1028*7c478bd9Sstevel@tonic-gate 		if (hp)
1029*7c478bd9Sstevel@tonic-gate 			lastev = hp->Hnum;
1030*7c478bd9Sstevel@tonic-gate 		return (&hp->Hlex);
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate 	case '?':
1033*7c478bd9Sstevel@tonic-gate 		np = lhsb;
1034*7c478bd9Sstevel@tonic-gate 		for (;;) {
1035*7c478bd9Sstevel@tonic-gate 			c = getC(0);
1036*7c478bd9Sstevel@tonic-gate 			if (c == '\n') {
1037*7c478bd9Sstevel@tonic-gate 				unreadc(c);
1038*7c478bd9Sstevel@tonic-gate 				break;
1039*7c478bd9Sstevel@tonic-gate 			}
1040*7c478bd9Sstevel@tonic-gate 			if (c == '?')
1041*7c478bd9Sstevel@tonic-gate 				break;
1042*7c478bd9Sstevel@tonic-gate 			if (np < &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2])
1043*7c478bd9Sstevel@tonic-gate 				*np++ = c;
1044*7c478bd9Sstevel@tonic-gate 		}
1045*7c478bd9Sstevel@tonic-gate 		if (np == lhsb) {
1046*7c478bd9Sstevel@tonic-gate 			if (lhsb[0] == 0) {
1047*7c478bd9Sstevel@tonic-gate 				seterr("No prev search");
1048*7c478bd9Sstevel@tonic-gate 				return (0);
1049*7c478bd9Sstevel@tonic-gate 			}
1050*7c478bd9Sstevel@tonic-gate 		} else
1051*7c478bd9Sstevel@tonic-gate 			*np++ = 0;
1052*7c478bd9Sstevel@tonic-gate 		hp = findev(lhsb, 1);
1053*7c478bd9Sstevel@tonic-gate 		if (hp)
1054*7c478bd9Sstevel@tonic-gate 			lastev = hp->Hnum;
1055*7c478bd9Sstevel@tonic-gate 		return (&hp->Hlex);
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 	number:
1058*7c478bd9Sstevel@tonic-gate 		event = 0;
1059*7c478bd9Sstevel@tonic-gate 		while (digit(c)) {
1060*7c478bd9Sstevel@tonic-gate 			event = event * 10 + c - '0';
1061*7c478bd9Sstevel@tonic-gate 			c = getC(0);
1062*7c478bd9Sstevel@tonic-gate 		}
1063*7c478bd9Sstevel@tonic-gate 		if (back)
1064*7c478bd9Sstevel@tonic-gate 			event = eventno + (alhistp == 0) - (event ? event : 0);
1065*7c478bd9Sstevel@tonic-gate 		unreadc(c);
1066*7c478bd9Sstevel@tonic-gate 		break;
1067*7c478bd9Sstevel@tonic-gate 	}
1068*7c478bd9Sstevel@tonic-gate skip:
1069*7c478bd9Sstevel@tonic-gate 	for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
1070*7c478bd9Sstevel@tonic-gate 		if (hp->Hnum == event) {
1071*7c478bd9Sstevel@tonic-gate 			hp->Href = eventno;
1072*7c478bd9Sstevel@tonic-gate 			lastev = hp->Hnum;
1073*7c478bd9Sstevel@tonic-gate 			return (&hp->Hlex);
1074*7c478bd9Sstevel@tonic-gate 		}
1075*7c478bd9Sstevel@tonic-gate 	np = putn(event);
1076*7c478bd9Sstevel@tonic-gate 	noev(np);
1077*7c478bd9Sstevel@tonic-gate 	return (0);
1078*7c478bd9Sstevel@tonic-gate }
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate struct Hist *
1081*7c478bd9Sstevel@tonic-gate findev(cp, anyarg)
1082*7c478bd9Sstevel@tonic-gate 	tchar *cp;
1083*7c478bd9Sstevel@tonic-gate 	bool anyarg;
1084*7c478bd9Sstevel@tonic-gate {
1085*7c478bd9Sstevel@tonic-gate 	register struct Hist *hp;
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate #ifdef TRACE
1088*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- findev()\n");
1089*7c478bd9Sstevel@tonic-gate #endif
1090*7c478bd9Sstevel@tonic-gate 	for (hp = Histlist.Hnext; hp; hp = hp->Hnext) {
1091*7c478bd9Sstevel@tonic-gate 	 tchar *dp;
1092*7c478bd9Sstevel@tonic-gate 		register tchar *p, *q;
1093*7c478bd9Sstevel@tonic-gate 		register struct wordent *lp = hp->Hlex.next;
1094*7c478bd9Sstevel@tonic-gate 		int argno = 0;
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate 		if (lp->word[0] == '\n')
1097*7c478bd9Sstevel@tonic-gate 			continue;
1098*7c478bd9Sstevel@tonic-gate 		if (!anyarg) {
1099*7c478bd9Sstevel@tonic-gate 			p = cp;
1100*7c478bd9Sstevel@tonic-gate 			q = lp->word;
1101*7c478bd9Sstevel@tonic-gate 			do
1102*7c478bd9Sstevel@tonic-gate 				if (!*p)
1103*7c478bd9Sstevel@tonic-gate 					return (hp);
1104*7c478bd9Sstevel@tonic-gate 			while (*p++ == *q++);
1105*7c478bd9Sstevel@tonic-gate 			continue;
1106*7c478bd9Sstevel@tonic-gate 		}
1107*7c478bd9Sstevel@tonic-gate 		do {
1108*7c478bd9Sstevel@tonic-gate 			for (dp = lp->word; *dp; dp++) {
1109*7c478bd9Sstevel@tonic-gate 				p = cp;
1110*7c478bd9Sstevel@tonic-gate 				q = dp;
1111*7c478bd9Sstevel@tonic-gate 				do
1112*7c478bd9Sstevel@tonic-gate 					if (!*p) {
1113*7c478bd9Sstevel@tonic-gate 						quesarg = argno;
1114*7c478bd9Sstevel@tonic-gate 						return (hp);
1115*7c478bd9Sstevel@tonic-gate 					}
1116*7c478bd9Sstevel@tonic-gate 				while (*p++ == *q++);
1117*7c478bd9Sstevel@tonic-gate 			}
1118*7c478bd9Sstevel@tonic-gate 			lp = lp->next;
1119*7c478bd9Sstevel@tonic-gate 			argno++;
1120*7c478bd9Sstevel@tonic-gate 		} while (lp->word[0] != '\n');
1121*7c478bd9Sstevel@tonic-gate 	}
1122*7c478bd9Sstevel@tonic-gate 	noev(cp);
1123*7c478bd9Sstevel@tonic-gate 	return (0);
1124*7c478bd9Sstevel@tonic-gate }
1125*7c478bd9Sstevel@tonic-gate 
1126*7c478bd9Sstevel@tonic-gate noev(cp)
1127*7c478bd9Sstevel@tonic-gate 	tchar *cp;
1128*7c478bd9Sstevel@tonic-gate {
1129*7c478bd9Sstevel@tonic-gate 
1130*7c478bd9Sstevel@tonic-gate #ifdef TRACE
1131*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- noev()\n");
1132*7c478bd9Sstevel@tonic-gate #endif
1133*7c478bd9Sstevel@tonic-gate 	seterr2(cp, ": Event not found");
1134*7c478bd9Sstevel@tonic-gate }
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate setexclp(cp)
1137*7c478bd9Sstevel@tonic-gate 	register tchar *cp;
1138*7c478bd9Sstevel@tonic-gate {
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate #ifdef TRACE
1141*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- setexclp()\n");
1142*7c478bd9Sstevel@tonic-gate #endif
1143*7c478bd9Sstevel@tonic-gate 	if (cp && cp[0] == '\n')
1144*7c478bd9Sstevel@tonic-gate 		return;
1145*7c478bd9Sstevel@tonic-gate 	exclp = cp;
1146*7c478bd9Sstevel@tonic-gate }
1147*7c478bd9Sstevel@tonic-gate 
1148*7c478bd9Sstevel@tonic-gate unreadc(c)
1149*7c478bd9Sstevel@tonic-gate 	tchar c;
1150*7c478bd9Sstevel@tonic-gate {
1151*7c478bd9Sstevel@tonic-gate 
1152*7c478bd9Sstevel@tonic-gate 	peekread = c;
1153*7c478bd9Sstevel@tonic-gate }
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate readc(wanteof)
1156*7c478bd9Sstevel@tonic-gate 	bool wanteof;
1157*7c478bd9Sstevel@tonic-gate {
1158*7c478bd9Sstevel@tonic-gate 	register int c;
1159*7c478bd9Sstevel@tonic-gate 	static sincereal;
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 	if (c = peekread) {
1162*7c478bd9Sstevel@tonic-gate 		peekread = 0;
1163*7c478bd9Sstevel@tonic-gate 		return (c);
1164*7c478bd9Sstevel@tonic-gate 	}
1165*7c478bd9Sstevel@tonic-gate top:
1166*7c478bd9Sstevel@tonic-gate 	if (alvecp) {
1167*7c478bd9Sstevel@tonic-gate 		if (c = *alvecp++)
1168*7c478bd9Sstevel@tonic-gate 			return (c);
1169*7c478bd9Sstevel@tonic-gate 		if (*alvec) {
1170*7c478bd9Sstevel@tonic-gate 			alvecp = *alvec++;
1171*7c478bd9Sstevel@tonic-gate 			return (' ');
1172*7c478bd9Sstevel@tonic-gate 		}
1173*7c478bd9Sstevel@tonic-gate 	}
1174*7c478bd9Sstevel@tonic-gate 	if (alvec) {
1175*7c478bd9Sstevel@tonic-gate 		if (alvecp = *alvec) {
1176*7c478bd9Sstevel@tonic-gate 			alvec++;
1177*7c478bd9Sstevel@tonic-gate 			goto top;
1178*7c478bd9Sstevel@tonic-gate 		}
1179*7c478bd9Sstevel@tonic-gate 		/* Infinite source! */
1180*7c478bd9Sstevel@tonic-gate 		return ('\n');
1181*7c478bd9Sstevel@tonic-gate 	}
1182*7c478bd9Sstevel@tonic-gate 	if (evalp) {
1183*7c478bd9Sstevel@tonic-gate 		if (c = *evalp++)
1184*7c478bd9Sstevel@tonic-gate 			return (c);
1185*7c478bd9Sstevel@tonic-gate 		if (*evalvec) {
1186*7c478bd9Sstevel@tonic-gate 			evalp = *evalvec++;
1187*7c478bd9Sstevel@tonic-gate 			return (' ');
1188*7c478bd9Sstevel@tonic-gate 		}
1189*7c478bd9Sstevel@tonic-gate 		evalp = 0;
1190*7c478bd9Sstevel@tonic-gate 	}
1191*7c478bd9Sstevel@tonic-gate 	if (evalvec) {
1192*7c478bd9Sstevel@tonic-gate 		if (evalvec ==  (tchar **)1) {
1193*7c478bd9Sstevel@tonic-gate 			doneinp = 1;
1194*7c478bd9Sstevel@tonic-gate 			reset();
1195*7c478bd9Sstevel@tonic-gate 		}
1196*7c478bd9Sstevel@tonic-gate 		if (evalp = *evalvec) {
1197*7c478bd9Sstevel@tonic-gate 			evalvec++;
1198*7c478bd9Sstevel@tonic-gate 			goto top;
1199*7c478bd9Sstevel@tonic-gate 		}
1200*7c478bd9Sstevel@tonic-gate 		evalvec =  (tchar **)1;
1201*7c478bd9Sstevel@tonic-gate 		return ('\n');
1202*7c478bd9Sstevel@tonic-gate 	}
1203*7c478bd9Sstevel@tonic-gate 	do {
1204*7c478bd9Sstevel@tonic-gate 		if (arginp ==  (tchar *) 1 || onelflg == 1) {
1205*7c478bd9Sstevel@tonic-gate 			if (wanteof)
1206*7c478bd9Sstevel@tonic-gate 				return (-1);
1207*7c478bd9Sstevel@tonic-gate 			exitstat();
1208*7c478bd9Sstevel@tonic-gate 		}
1209*7c478bd9Sstevel@tonic-gate 		if (arginp) {
1210*7c478bd9Sstevel@tonic-gate 			if ((c = *arginp++) == 0) {
1211*7c478bd9Sstevel@tonic-gate 				arginp =  (tchar *) 1;
1212*7c478bd9Sstevel@tonic-gate 				return ('\n');
1213*7c478bd9Sstevel@tonic-gate 			}
1214*7c478bd9Sstevel@tonic-gate 			return (c);
1215*7c478bd9Sstevel@tonic-gate 		}
1216*7c478bd9Sstevel@tonic-gate reread:
1217*7c478bd9Sstevel@tonic-gate 		c = bgetc();
1218*7c478bd9Sstevel@tonic-gate 		if (c < 0) {
1219*7c478bd9Sstevel@tonic-gate 			struct sgttyb tty;
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate 			if (wanteof)
1222*7c478bd9Sstevel@tonic-gate 				return (-1);
1223*7c478bd9Sstevel@tonic-gate 			/* was isatty but raw with ignoreeof yields problems */
1224*7c478bd9Sstevel@tonic-gate 			if (ioctl(SHIN, TIOCGETP,  (char *)&tty) == 0 &&
1225*7c478bd9Sstevel@tonic-gate 			    (tty.sg_flags & RAW) == 0) {
1226*7c478bd9Sstevel@tonic-gate 				/* was 'short' for FILEC */
1227*7c478bd9Sstevel@tonic-gate 				int ctpgrp;
1228*7c478bd9Sstevel@tonic-gate 
1229*7c478bd9Sstevel@tonic-gate 				if (++sincereal > 25)
1230*7c478bd9Sstevel@tonic-gate 					goto oops;
1231*7c478bd9Sstevel@tonic-gate 				if (tpgrp != -1 &&
1232*7c478bd9Sstevel@tonic-gate 				    ioctl(FSHTTY, TIOCGPGRP,  (char *)&ctpgrp) == 0 &&
1233*7c478bd9Sstevel@tonic-gate 				    tpgrp != ctpgrp) {
1234*7c478bd9Sstevel@tonic-gate 					(void) ioctl(FSHTTY, TIOCSPGRP,
1235*7c478bd9Sstevel@tonic-gate 						 (char *)&tpgrp);
1236*7c478bd9Sstevel@tonic-gate 					(void) killpg(ctpgrp, SIGHUP);
1237*7c478bd9Sstevel@tonic-gate printf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp);
1238*7c478bd9Sstevel@tonic-gate 					goto reread;
1239*7c478bd9Sstevel@tonic-gate 				}
1240*7c478bd9Sstevel@tonic-gate 				if (adrof(S_ignoreeof/*"ignoreeof"*/)) {
1241*7c478bd9Sstevel@tonic-gate 					if (loginsh)
1242*7c478bd9Sstevel@tonic-gate 						printf("\nUse \"logout\" to logout.\n");
1243*7c478bd9Sstevel@tonic-gate 					else
1244*7c478bd9Sstevel@tonic-gate 						printf("\nUse \"exit\" to leave csh.\n");
1245*7c478bd9Sstevel@tonic-gate 					reset();
1246*7c478bd9Sstevel@tonic-gate 				}
1247*7c478bd9Sstevel@tonic-gate 				if (chkstop == 0) {
1248*7c478bd9Sstevel@tonic-gate 					panystop(1);
1249*7c478bd9Sstevel@tonic-gate 				}
1250*7c478bd9Sstevel@tonic-gate 			}
1251*7c478bd9Sstevel@tonic-gate oops:
1252*7c478bd9Sstevel@tonic-gate 			doneinp = 1;
1253*7c478bd9Sstevel@tonic-gate 			reset();
1254*7c478bd9Sstevel@tonic-gate 		}
1255*7c478bd9Sstevel@tonic-gate 		sincereal = 0;
1256*7c478bd9Sstevel@tonic-gate 		if (c == '\n' && onelflg)
1257*7c478bd9Sstevel@tonic-gate 			onelflg--;
1258*7c478bd9Sstevel@tonic-gate 	} while (c == 0);
1259*7c478bd9Sstevel@tonic-gate 	return (c);
1260*7c478bd9Sstevel@tonic-gate }
1261*7c478bd9Sstevel@tonic-gate 
1262*7c478bd9Sstevel@tonic-gate bgetc()
1263*7c478bd9Sstevel@tonic-gate {
1264*7c478bd9Sstevel@tonic-gate 	register int buf, off, c;
1265*7c478bd9Sstevel@tonic-gate #ifdef FILEC
1266*7c478bd9Sstevel@tonic-gate 	tchar ttyline[BUFSIZ];
1267*7c478bd9Sstevel@tonic-gate 	register int numleft = 0, roomleft;
1268*7c478bd9Sstevel@tonic-gate #endif
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate #ifdef TELL
1271*7c478bd9Sstevel@tonic-gate 	if (cantell) {
1272*7c478bd9Sstevel@tonic-gate 		if (fseekp < fbobp || fseekp > feobp) {
1273*7c478bd9Sstevel@tonic-gate 			fbobp = feobp = fseekp;
1274*7c478bd9Sstevel@tonic-gate 			(void) lseek(SHIN, fseekp, 0);
1275*7c478bd9Sstevel@tonic-gate 		}
1276*7c478bd9Sstevel@tonic-gate 		if (fseekp == feobp) {
1277*7c478bd9Sstevel@tonic-gate 			fbobp = feobp;
1278*7c478bd9Sstevel@tonic-gate 			do
1279*7c478bd9Sstevel@tonic-gate 				c = read_(SHIN, fbuf[0], BUFSIZ);
1280*7c478bd9Sstevel@tonic-gate 			while (c < 0 && errno == EINTR);
1281*7c478bd9Sstevel@tonic-gate 			if (c <= 0)
1282*7c478bd9Sstevel@tonic-gate 				return (-1);
1283*7c478bd9Sstevel@tonic-gate 			feobp += c;
1284*7c478bd9Sstevel@tonic-gate 		}
1285*7c478bd9Sstevel@tonic-gate 		c = fbuf[0][fseekp - fbobp];
1286*7c478bd9Sstevel@tonic-gate 		fseekp++;
1287*7c478bd9Sstevel@tonic-gate 		return (c);
1288*7c478bd9Sstevel@tonic-gate 	}
1289*7c478bd9Sstevel@tonic-gate #endif
1290*7c478bd9Sstevel@tonic-gate again:
1291*7c478bd9Sstevel@tonic-gate 	buf = (int) fseekp / BUFSIZ;
1292*7c478bd9Sstevel@tonic-gate 	if (buf >= fblocks) {
1293*7c478bd9Sstevel@tonic-gate 		register tchar **nfbuf =
1294*7c478bd9Sstevel@tonic-gate 			 (tchar **) calloc((unsigned) (fblocks + 2),
1295*7c478bd9Sstevel@tonic-gate 				sizeof  (tchar **));
1296*7c478bd9Sstevel@tonic-gate 
1297*7c478bd9Sstevel@tonic-gate 		if (fbuf) {
1298*7c478bd9Sstevel@tonic-gate 			(void) blkcpy(nfbuf, fbuf);
1299*7c478bd9Sstevel@tonic-gate 			xfree( (char *)fbuf);
1300*7c478bd9Sstevel@tonic-gate 		}
1301*7c478bd9Sstevel@tonic-gate 		fbuf = nfbuf;
1302*7c478bd9Sstevel@tonic-gate 		fbuf[fblocks] = (tchar *)calloc(BUFSIZ, sizeof (tchar));
1303*7c478bd9Sstevel@tonic-gate 		fblocks++;
1304*7c478bd9Sstevel@tonic-gate 		goto again;
1305*7c478bd9Sstevel@tonic-gate 	}
1306*7c478bd9Sstevel@tonic-gate 	if (fseekp >= feobp) {
1307*7c478bd9Sstevel@tonic-gate 		buf = (int) feobp / BUFSIZ;
1308*7c478bd9Sstevel@tonic-gate 		off = (int) feobp % BUFSIZ;
1309*7c478bd9Sstevel@tonic-gate #ifndef FILEC
1310*7c478bd9Sstevel@tonic-gate 		for (;;) {
1311*7c478bd9Sstevel@tonic-gate 			c = read_(SHIN, fbuf[buf] + off, BUFSIZ - off);
1312*7c478bd9Sstevel@tonic-gate #else
1313*7c478bd9Sstevel@tonic-gate 		roomleft = BUFSIZ - off;
1314*7c478bd9Sstevel@tonic-gate 		for (;;) {
1315*7c478bd9Sstevel@tonic-gate 			if (filec && intty) {
1316*7c478bd9Sstevel@tonic-gate 				c = numleft ? numleft : tenex(ttyline, BUFSIZ);
1317*7c478bd9Sstevel@tonic-gate 				if (c > roomleft) {
1318*7c478bd9Sstevel@tonic-gate 					/* start with fresh buffer */
1319*7c478bd9Sstevel@tonic-gate 					feobp = fseekp = fblocks * BUFSIZ;
1320*7c478bd9Sstevel@tonic-gate 					numleft = c;
1321*7c478bd9Sstevel@tonic-gate 					goto again;
1322*7c478bd9Sstevel@tonic-gate 				}
1323*7c478bd9Sstevel@tonic-gate 				if (c > 0)
1324*7c478bd9Sstevel@tonic-gate 					copy(fbuf[buf] + off, ttyline, c*sizeof(tchar));
1325*7c478bd9Sstevel@tonic-gate 				numleft = 0;
1326*7c478bd9Sstevel@tonic-gate 			} else
1327*7c478bd9Sstevel@tonic-gate 				c = read_(SHIN, fbuf[buf] + off, roomleft);
1328*7c478bd9Sstevel@tonic-gate #endif
1329*7c478bd9Sstevel@tonic-gate 			if (c >= 0)
1330*7c478bd9Sstevel@tonic-gate 				break;
1331*7c478bd9Sstevel@tonic-gate 			if (errno == EWOULDBLOCK) {
1332*7c478bd9Sstevel@tonic-gate 				int off = 0;
1333*7c478bd9Sstevel@tonic-gate 
1334*7c478bd9Sstevel@tonic-gate 				(void) ioctl(SHIN, FIONBIO,  (char *)&off);
1335*7c478bd9Sstevel@tonic-gate 			} else if (errno != EINTR)
1336*7c478bd9Sstevel@tonic-gate 				break;
1337*7c478bd9Sstevel@tonic-gate 		}
1338*7c478bd9Sstevel@tonic-gate 		if (c <= 0)
1339*7c478bd9Sstevel@tonic-gate 			return (-1);
1340*7c478bd9Sstevel@tonic-gate 		feobp += c;
1341*7c478bd9Sstevel@tonic-gate #ifndef FILEC
1342*7c478bd9Sstevel@tonic-gate 		goto again;
1343*7c478bd9Sstevel@tonic-gate #else
1344*7c478bd9Sstevel@tonic-gate 		if (filec && !intty)
1345*7c478bd9Sstevel@tonic-gate 			goto again;
1346*7c478bd9Sstevel@tonic-gate #endif
1347*7c478bd9Sstevel@tonic-gate 	}
1348*7c478bd9Sstevel@tonic-gate 	c = fbuf[buf][(int) fseekp % BUFSIZ];
1349*7c478bd9Sstevel@tonic-gate 	fseekp++;
1350*7c478bd9Sstevel@tonic-gate 	return (c);
1351*7c478bd9Sstevel@tonic-gate }
1352*7c478bd9Sstevel@tonic-gate 
1353*7c478bd9Sstevel@tonic-gate bfree()
1354*7c478bd9Sstevel@tonic-gate {
1355*7c478bd9Sstevel@tonic-gate 	register int sb, i;
1356*7c478bd9Sstevel@tonic-gate 
1357*7c478bd9Sstevel@tonic-gate #ifdef TELL
1358*7c478bd9Sstevel@tonic-gate 	if (cantell)
1359*7c478bd9Sstevel@tonic-gate 		return;
1360*7c478bd9Sstevel@tonic-gate #endif
1361*7c478bd9Sstevel@tonic-gate 	if (whyles)
1362*7c478bd9Sstevel@tonic-gate 		return;
1363*7c478bd9Sstevel@tonic-gate 	sb = (int) (fseekp - 1) / BUFSIZ;
1364*7c478bd9Sstevel@tonic-gate 	if (sb > 0) {
1365*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < sb; i++)
1366*7c478bd9Sstevel@tonic-gate 			xfree(fbuf[i]);
1367*7c478bd9Sstevel@tonic-gate 		(void) blkcpy(fbuf, &fbuf[sb]);
1368*7c478bd9Sstevel@tonic-gate 		fseekp -= BUFSIZ * sb;
1369*7c478bd9Sstevel@tonic-gate 		feobp -= BUFSIZ * sb;
1370*7c478bd9Sstevel@tonic-gate 		fblocks -= sb;
1371*7c478bd9Sstevel@tonic-gate 	}
1372*7c478bd9Sstevel@tonic-gate }
1373*7c478bd9Sstevel@tonic-gate 
1374*7c478bd9Sstevel@tonic-gate bseek(l)
1375*7c478bd9Sstevel@tonic-gate 	off_t l;
1376*7c478bd9Sstevel@tonic-gate {
1377*7c478bd9Sstevel@tonic-gate 	register struct whyle *wp;
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 	fseekp = l;
1380*7c478bd9Sstevel@tonic-gate #ifdef TELL
1381*7c478bd9Sstevel@tonic-gate 	if (!cantell) {
1382*7c478bd9Sstevel@tonic-gate #endif
1383*7c478bd9Sstevel@tonic-gate 		if (!whyles)
1384*7c478bd9Sstevel@tonic-gate 			return;
1385*7c478bd9Sstevel@tonic-gate 		for (wp = whyles; wp->w_next; wp = wp->w_next)
1386*7c478bd9Sstevel@tonic-gate 			continue;
1387*7c478bd9Sstevel@tonic-gate 		if (wp->w_start > l)
1388*7c478bd9Sstevel@tonic-gate 			l = wp->w_start;
1389*7c478bd9Sstevel@tonic-gate #ifdef TELL
1390*7c478bd9Sstevel@tonic-gate 	}
1391*7c478bd9Sstevel@tonic-gate #endif
1392*7c478bd9Sstevel@tonic-gate }
1393*7c478bd9Sstevel@tonic-gate 
1394*7c478bd9Sstevel@tonic-gate /* any similarity to bell telephone is purely accidental */
1395*7c478bd9Sstevel@tonic-gate #ifndef btell
1396*7c478bd9Sstevel@tonic-gate off_t
1397*7c478bd9Sstevel@tonic-gate btell()
1398*7c478bd9Sstevel@tonic-gate {
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate 	return (fseekp);
1401*7c478bd9Sstevel@tonic-gate }
1402*7c478bd9Sstevel@tonic-gate #endif
1403*7c478bd9Sstevel@tonic-gate 
1404*7c478bd9Sstevel@tonic-gate btoeof()
1405*7c478bd9Sstevel@tonic-gate {
1406*7c478bd9Sstevel@tonic-gate 
1407*7c478bd9Sstevel@tonic-gate 	(void) lseek(SHIN, (off_t)0, 2);
1408*7c478bd9Sstevel@tonic-gate 	fseekp = feobp;
1409*7c478bd9Sstevel@tonic-gate 	wfree();
1410*7c478bd9Sstevel@tonic-gate 	bfree();
1411*7c478bd9Sstevel@tonic-gate }
1412*7c478bd9Sstevel@tonic-gate 
1413*7c478bd9Sstevel@tonic-gate #ifdef TELL
1414*7c478bd9Sstevel@tonic-gate settell()
1415*7c478bd9Sstevel@tonic-gate {
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 	cantell = 0;
1418*7c478bd9Sstevel@tonic-gate 	if (arginp || onelflg || intty)
1419*7c478bd9Sstevel@tonic-gate 		return;
1420*7c478bd9Sstevel@tonic-gate 	if (lseek(SHIN, (off_t)0, 1) < 0 || errno == ESPIPE)
1421*7c478bd9Sstevel@tonic-gate 		return;
1422*7c478bd9Sstevel@tonic-gate 	fbuf =  (tchar **) calloc(2, sizeof  (tchar **));
1423*7c478bd9Sstevel@tonic-gate 	fblocks = 1;
1424*7c478bd9Sstevel@tonic-gate 	fbuf[0] = (tchar *)calloc(BUFSIZ, sizeof (tchar));
1425*7c478bd9Sstevel@tonic-gate 	fseekp = fbobp = feobp = lseek(SHIN, (off_t)0, 1);
1426*7c478bd9Sstevel@tonic-gate 	cantell = 1;
1427*7c478bd9Sstevel@tonic-gate }
1428*7c478bd9Sstevel@tonic-gate #endif
1429*7c478bd9Sstevel@tonic-gate 
1430