10Sstevel@tonic-gate /*
2*2182Schin * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
70Sstevel@tonic-gate /* All Rights Reserved */
80Sstevel@tonic-gate
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
110Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
120Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
130Sstevel@tonic-gate */
140Sstevel@tonic-gate
150Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
160Sstevel@tonic-gate
170Sstevel@tonic-gate #include <unistd.h> /* for lseek prototype */
180Sstevel@tonic-gate #include "sh.h"
190Sstevel@tonic-gate #include "sh.tconst.h"
200Sstevel@tonic-gate #include <sys/filio.h>
210Sstevel@tonic-gate #include <sys/ttold.h>
22559Snakanon #define RAW O_RAW
230Sstevel@tonic-gate /*
240Sstevel@tonic-gate * C shell
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * These lexical routines read input and form lists of words.
290Sstevel@tonic-gate * There is some involved processing here, because of the complications
300Sstevel@tonic-gate * of input buffering, and especially because of history substitution.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
33356Smuffin tchar *word(void);
34356Smuffin tchar getC1(int);
35356Smuffin tchar *subword(tchar *, int, bool *);
36356Smuffin void getdol(void);
37356Smuffin void addla(tchar *);
38356Smuffin void getexcl(tchar);
39356Smuffin void noev(tchar *);
40356Smuffin void setexclp(tchar *);
41356Smuffin void unreadc(tchar);
42356Smuffin int readc(bool);
43356Smuffin struct wordent *dosub(int, struct wordent *, bool);
44356Smuffin struct Hist *findev(tchar *, bool);
45356Smuffin struct wordent *gethent(int);
46356Smuffin struct wordent *getsub(struct wordent *);
470Sstevel@tonic-gate
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate * Peekc is a peek characer for getC, peekread for readc.
500Sstevel@tonic-gate * There is a subtlety here in many places... history routines
510Sstevel@tonic-gate * will read ahead and then insert stuff into the input stream.
520Sstevel@tonic-gate * If they push back a character then they must push it behind
530Sstevel@tonic-gate * the text substituted by the history substitution. On the other
540Sstevel@tonic-gate * hand in several places we need 2 peek characters. To make this
550Sstevel@tonic-gate * all work, the history routines read with getC, and make use both
560Sstevel@tonic-gate * of ungetC and unreadc. The key observation is that the state
570Sstevel@tonic-gate * of getC at the call of a history reference is such that calls
580Sstevel@tonic-gate * to getC from the history routines will always yield calls of
590Sstevel@tonic-gate * readc, unless this peeking is involved. That is to say that during
600Sstevel@tonic-gate * getexcl the variables lap, exclp, and exclnxt are all zero.
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * Getdol invokes history substitution, hence the extra peek, peekd,
630Sstevel@tonic-gate * which it can ungetD to be before history substitutions.
640Sstevel@tonic-gate */
650Sstevel@tonic-gate tchar peekc, peekd;
660Sstevel@tonic-gate tchar peekread;
670Sstevel@tonic-gate
680Sstevel@tonic-gate tchar *exclp; /* (Tail of) current word from ! subst */
690Sstevel@tonic-gate struct wordent *exclnxt; /* The rest of the ! subst words */
700Sstevel@tonic-gate int exclc; /* Count of remainig words in ! subst */
710Sstevel@tonic-gate tchar *alvecp; /* "Globp" for alias resubstitution */
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * Lex returns to its caller not only a wordlist (as a "var" parameter)
750Sstevel@tonic-gate * but also whether a history substitution occurred. This is used in
760Sstevel@tonic-gate * the main (process) routine to determine whether to echo, and also
770Sstevel@tonic-gate * when called by the alias routine to determine whether to keep the
780Sstevel@tonic-gate * argument list.
790Sstevel@tonic-gate */
800Sstevel@tonic-gate bool hadhist;
810Sstevel@tonic-gate
820Sstevel@tonic-gate tchar getCtmp;
83559Snakanon #define getC(f) ((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f))
840Sstevel@tonic-gate #define ungetC(c) peekc = c
850Sstevel@tonic-gate #define ungetD(c) peekd = c
860Sstevel@tonic-gate
87356Smuffin bool
lex(struct wordent * hp)88356Smuffin lex(struct wordent *hp)
890Sstevel@tonic-gate {
90356Smuffin struct wordent *wdp;
910Sstevel@tonic-gate int c;
920Sstevel@tonic-gate
930Sstevel@tonic-gate #ifdef TRACE
940Sstevel@tonic-gate tprintf("TRACE- lex()\n");
950Sstevel@tonic-gate #endif
960Sstevel@tonic-gate lineloc = btell();
970Sstevel@tonic-gate hp->next = hp->prev = hp;
98559Snakanon hp->word = S_ /* "" */;
990Sstevel@tonic-gate alvecp = 0, hadhist = 0;
1000Sstevel@tonic-gate do
1010Sstevel@tonic-gate c = readc(0);
1020Sstevel@tonic-gate while (issp(c));
1030Sstevel@tonic-gate /* make sure history is enabled */
1040Sstevel@tonic-gate if (HIST && c == HISTSUB && intty)
1050Sstevel@tonic-gate /* ^lef^rit from tty is short !:s^lef^rit */
1060Sstevel@tonic-gate getexcl(c);
1070Sstevel@tonic-gate else
1080Sstevel@tonic-gate unreadc(c);
1090Sstevel@tonic-gate wdp = hp;
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * The following loop is written so that the links needed
1120Sstevel@tonic-gate * by freelex will be ready and rarin to go even if it is
1130Sstevel@tonic-gate * interrupted.
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate do {
116559Snakanon struct wordent *new = (struct wordent *)xalloc(sizeof *wdp);
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate new->word = 0;
1190Sstevel@tonic-gate new->prev = wdp;
1200Sstevel@tonic-gate new->next = hp;
1210Sstevel@tonic-gate wdp->next = new;
1220Sstevel@tonic-gate wdp = new;
1230Sstevel@tonic-gate wdp->word = word();
1240Sstevel@tonic-gate } while (wdp->word[0] != '\n');
1250Sstevel@tonic-gate #ifdef TRACE
1260Sstevel@tonic-gate tprintf("Exiting lex()\n");
1270Sstevel@tonic-gate #endif
1280Sstevel@tonic-gate hp->prev = wdp;
1290Sstevel@tonic-gate return (hadhist);
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate
132356Smuffin void
prlex(struct wordent * sp0)133356Smuffin prlex(struct wordent *sp0)
1340Sstevel@tonic-gate {
135356Smuffin struct wordent *sp = sp0->next;
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate #ifdef TRACE
1380Sstevel@tonic-gate tprintf("TRACE- prlex()\n");
1390Sstevel@tonic-gate #endif
1400Sstevel@tonic-gate for (;;) {
1410Sstevel@tonic-gate printf("%t", sp->word);
1420Sstevel@tonic-gate sp = sp->next;
1430Sstevel@tonic-gate if (sp == sp0)
1440Sstevel@tonic-gate break;
1450Sstevel@tonic-gate if (sp->word[0] != '\n')
1460Sstevel@tonic-gate Putchar(' ');
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate
150356Smuffin void
copylex(struct wordent * hp,struct wordent * fp)151356Smuffin copylex(struct wordent *hp, struct wordent *fp)
1520Sstevel@tonic-gate {
153356Smuffin struct wordent *wdp;
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate #ifdef TRACE
1560Sstevel@tonic-gate tprintf("TRACE- copylex()\n");
1570Sstevel@tonic-gate #endif
1580Sstevel@tonic-gate wdp = hp;
1590Sstevel@tonic-gate fp = fp->next;
1600Sstevel@tonic-gate do {
161559Snakanon struct wordent *new = (struct wordent *)xalloc(sizeof *wdp);
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate new->prev = wdp;
1640Sstevel@tonic-gate new->next = hp;
1650Sstevel@tonic-gate wdp->next = new;
1660Sstevel@tonic-gate wdp = new;
1670Sstevel@tonic-gate wdp->word = savestr(fp->word);
1680Sstevel@tonic-gate fp = fp->next;
1690Sstevel@tonic-gate } while (wdp->word[0] != '\n');
1700Sstevel@tonic-gate hp->prev = wdp;
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate
173356Smuffin void
freelex(struct wordent * vp)174356Smuffin freelex(struct wordent *vp)
1750Sstevel@tonic-gate {
176356Smuffin struct wordent *fp;
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate #ifdef TRACE
1790Sstevel@tonic-gate tprintf("TRACE- freelex()\n");
1800Sstevel@tonic-gate #endif
1810Sstevel@tonic-gate while (vp->next != vp) {
1820Sstevel@tonic-gate fp = vp->next;
1830Sstevel@tonic-gate vp->next = fp->next;
184559Snakanon xfree(fp->word);
185559Snakanon xfree(fp);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate vp->prev = vp;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate tchar *
word(void)191356Smuffin word(void)
1920Sstevel@tonic-gate {
193356Smuffin tchar c, c1;
194356Smuffin tchar *wp;
1950Sstevel@tonic-gate tchar wbuf[BUFSIZ];
196356Smuffin bool dolflg;
197356Smuffin int i;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate #ifdef TRACE
2000Sstevel@tonic-gate tprintf("TRACE- word()\n");
2010Sstevel@tonic-gate #endif
2020Sstevel@tonic-gate wp = wbuf;
2030Sstevel@tonic-gate i = BUFSIZ - 4;
2040Sstevel@tonic-gate loop:
2050Sstevel@tonic-gate while (issp(c = getC(DOALL)))
2060Sstevel@tonic-gate ;
2070Sstevel@tonic-gate if (cmap(c, _META|_ESC)||isauxsp(c))
2080Sstevel@tonic-gate switch (c) {
2090Sstevel@tonic-gate case '&':
2100Sstevel@tonic-gate case '|':
2110Sstevel@tonic-gate case '<':
2120Sstevel@tonic-gate case '>':
2130Sstevel@tonic-gate *wp++ = c;
2140Sstevel@tonic-gate c1 = getC(DOALL);
2150Sstevel@tonic-gate if (c1 == c)
2160Sstevel@tonic-gate *wp++ = c1;
2170Sstevel@tonic-gate else
2180Sstevel@tonic-gate ungetC(c1);
2190Sstevel@tonic-gate goto ret;
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate case '#':
2220Sstevel@tonic-gate if (intty)
2230Sstevel@tonic-gate break;
2240Sstevel@tonic-gate c = 0;
2250Sstevel@tonic-gate do {
2260Sstevel@tonic-gate c1 = c;
2270Sstevel@tonic-gate c = getC(0);
2280Sstevel@tonic-gate } while (c != '\n');
2290Sstevel@tonic-gate if (c1 == '\\')
2300Sstevel@tonic-gate goto loop;
2310Sstevel@tonic-gate /* fall into ... */
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate case ';':
2340Sstevel@tonic-gate case '(':
2350Sstevel@tonic-gate case ')':
2360Sstevel@tonic-gate case '\n':
2370Sstevel@tonic-gate *wp++ = c;
2380Sstevel@tonic-gate goto ret;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate case '\\':
2410Sstevel@tonic-gate c = getC(0);
2420Sstevel@tonic-gate if (c == '\n') {
2430Sstevel@tonic-gate if (onelflg == 1)
2440Sstevel@tonic-gate onelflg = 2;
2450Sstevel@tonic-gate goto loop;
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate if (c != HIST)
2480Sstevel@tonic-gate *wp++ = '\\', --i;
2490Sstevel@tonic-gate c |= QUOTE;
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate c1 = 0;
2520Sstevel@tonic-gate dolflg = DOALL;
2530Sstevel@tonic-gate for (;;) {
2540Sstevel@tonic-gate if (c1) {
2550Sstevel@tonic-gate if (c == c1) {
2560Sstevel@tonic-gate c1 = 0;
2570Sstevel@tonic-gate dolflg = DOALL;
2580Sstevel@tonic-gate } else if (c == '\\') {
2590Sstevel@tonic-gate c = getC(0);
2600Sstevel@tonic-gate if (c == HIST)
2610Sstevel@tonic-gate c |= QUOTE;
2620Sstevel@tonic-gate else {
2630Sstevel@tonic-gate if (c == '\n')
264559Snakanon #if 0
2650Sstevel@tonic-gate if (c1 == '`')
2660Sstevel@tonic-gate c = ' ';
2670Sstevel@tonic-gate else
268559Snakanon #endif
2690Sstevel@tonic-gate c |= QUOTE;
2700Sstevel@tonic-gate ungetC(c);
2710Sstevel@tonic-gate c = '\\';
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate } else if (c == '\n') {
2740Sstevel@tonic-gate seterrc(gettext("Unmatched "), c1);
2750Sstevel@tonic-gate ungetC(c);
2760Sstevel@tonic-gate break;
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate } else if (cmap(c, _META|_Q|_Q1|_ESC)||isauxsp(c)) {
2790Sstevel@tonic-gate if (c == '\\') {
2800Sstevel@tonic-gate c = getC(0);
2810Sstevel@tonic-gate if (c == '\n') {
2820Sstevel@tonic-gate if (onelflg == 1)
2830Sstevel@tonic-gate onelflg = 2;
2840Sstevel@tonic-gate break;
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate if (c != HIST)
2870Sstevel@tonic-gate *wp++ = '\\', --i;
2880Sstevel@tonic-gate c |= QUOTE;
2890Sstevel@tonic-gate } else if (cmap(c, _Q|_Q1)) { /* '"` */
2900Sstevel@tonic-gate c1 = c;
2910Sstevel@tonic-gate dolflg = c == '"' ? DOALL : DOEXCL;
2920Sstevel@tonic-gate } else if (c != '#' || !intty) {
2930Sstevel@tonic-gate ungetC(c);
2940Sstevel@tonic-gate break;
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate if (--i > 0) {
2980Sstevel@tonic-gate *wp++ = c;
2990Sstevel@tonic-gate c = getC(dolflg);
3000Sstevel@tonic-gate } else {
3010Sstevel@tonic-gate seterr("Word too long");
3020Sstevel@tonic-gate wp = &wbuf[1];
3030Sstevel@tonic-gate break;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate ret:
3070Sstevel@tonic-gate *wp = 0;
3080Sstevel@tonic-gate #ifdef TRACE
3090Sstevel@tonic-gate tprintf("word() returning:%t\n", wbuf);
3100Sstevel@tonic-gate #endif
3110Sstevel@tonic-gate return (savestr(wbuf));
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate
314356Smuffin tchar
getC1(int flag)315356Smuffin getC1(int flag)
3160Sstevel@tonic-gate {
317356Smuffin tchar c;
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate top:
3200Sstevel@tonic-gate if (c = peekc) {
3210Sstevel@tonic-gate peekc = 0;
3220Sstevel@tonic-gate return (c);
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate if (lap) {
3250Sstevel@tonic-gate if ((c = *lap++) == 0)
3260Sstevel@tonic-gate lap = 0;
3270Sstevel@tonic-gate else {
3280Sstevel@tonic-gate /*
329559Snakanon * don't quote things if there was an error (err!=0)
330559Snakanon * the input is original, not from a substitution and
331559Snakanon * therefore should not be quoted
3320Sstevel@tonic-gate */
3330Sstevel@tonic-gate if (!err && cmap(c, _META|_Q|_Q1)||isauxsp(c))
3340Sstevel@tonic-gate c |= QUOTE;
3350Sstevel@tonic-gate return (c);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate if (c = peekd) {
3390Sstevel@tonic-gate peekd = 0;
3400Sstevel@tonic-gate return (c);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate if (exclp) {
3430Sstevel@tonic-gate if (c = *exclp++)
3440Sstevel@tonic-gate return (c);
3450Sstevel@tonic-gate if (exclnxt && --exclc >= 0) {
3460Sstevel@tonic-gate exclnxt = exclnxt->next;
3470Sstevel@tonic-gate setexclp(exclnxt->word);
3480Sstevel@tonic-gate return (' ');
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate exclp = 0;
3510Sstevel@tonic-gate exclnxt = 0;
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate if (exclnxt) {
3540Sstevel@tonic-gate exclnxt = exclnxt->next;
3550Sstevel@tonic-gate if (--exclc < 0)
3560Sstevel@tonic-gate exclnxt = 0;
3570Sstevel@tonic-gate else
3580Sstevel@tonic-gate setexclp(exclnxt->word);
3590Sstevel@tonic-gate goto top;
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate c = readc(0);
3620Sstevel@tonic-gate if (c == '$' && (flag & DODOL)) {
3630Sstevel@tonic-gate getdol();
3640Sstevel@tonic-gate goto top;
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate if (c == HIST && (flag & DOEXCL)) {
3670Sstevel@tonic-gate getexcl(0);
3680Sstevel@tonic-gate goto top;
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate return (c);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate
373356Smuffin void
getdol(void)374356Smuffin getdol(void)
3750Sstevel@tonic-gate {
376356Smuffin tchar *np, *p;
3770Sstevel@tonic-gate tchar name[MAX_VREF_LEN];
378356Smuffin int c;
3790Sstevel@tonic-gate int sc;
3800Sstevel@tonic-gate bool special = 0;
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate #ifdef TRACE
3830Sstevel@tonic-gate tprintf("TRACE- getdol()\n");
3840Sstevel@tonic-gate #endif
3850Sstevel@tonic-gate np = name, *np++ = '$';
3860Sstevel@tonic-gate c = sc = getC(DOEXCL);
3870Sstevel@tonic-gate if (isspnl(c)) {
3880Sstevel@tonic-gate ungetD(c);
3890Sstevel@tonic-gate ungetC('$' | QUOTE);
3900Sstevel@tonic-gate return;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate if (c == '{')
3930Sstevel@tonic-gate *np++ = c, c = getC(DOEXCL);
3940Sstevel@tonic-gate if (c == '#' || c == '?')
3950Sstevel@tonic-gate special++, *np++ = c, c = getC(DOEXCL);
3960Sstevel@tonic-gate *np++ = c;
3970Sstevel@tonic-gate switch (c) {
398559Snakanon
3990Sstevel@tonic-gate case '<':
4000Sstevel@tonic-gate case '$':
4010Sstevel@tonic-gate case '*':
4020Sstevel@tonic-gate if (special)
4030Sstevel@tonic-gate goto vsyn;
4040Sstevel@tonic-gate goto ret;
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate case '\n':
4070Sstevel@tonic-gate ungetD(c);
4080Sstevel@tonic-gate np--;
4090Sstevel@tonic-gate goto vsyn;
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate default:
4120Sstevel@tonic-gate p = np;
4130Sstevel@tonic-gate if (digit(c)) {
4140Sstevel@tonic-gate /* make sure the variable names are MAX_VAR_LEN chars or less */
415559Snakanon while (digit(c = getC(DOEXCL)) && (np - p) < MAX_VAR_LEN) {
4160Sstevel@tonic-gate *np++ = c;
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate } else if (letter(c)) {
4190Sstevel@tonic-gate while ((letter(c = getC(DOEXCL)) || digit(c)) &&
420559Snakanon (np - p) < MAX_VAR_LEN) {
4210Sstevel@tonic-gate *np++ = c;
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate else
4250Sstevel@tonic-gate goto vsyn;
4260Sstevel@tonic-gate
427559Snakanon if ((np - p) > MAX_VAR_LEN)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate seterr("Variable name too long");
4300Sstevel@tonic-gate goto ret;
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate if (c == '[') {
4340Sstevel@tonic-gate *np++ = c;
4350Sstevel@tonic-gate do {
4360Sstevel@tonic-gate c = getC(DOEXCL);
4370Sstevel@tonic-gate if (c == '\n') {
4380Sstevel@tonic-gate ungetD(c);
4390Sstevel@tonic-gate np--;
4400Sstevel@tonic-gate goto vsyn;
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate /* need to leave space for possible modifiers */
4430Sstevel@tonic-gate if (np >= &name[MAX_VREF_LEN - 8])
4440Sstevel@tonic-gate {
4450Sstevel@tonic-gate seterr("Variable reference too long");
4460Sstevel@tonic-gate goto ret;
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate *np++ = c;
4490Sstevel@tonic-gate } while (c != ']');
4500Sstevel@tonic-gate c = getC(DOEXCL);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate if (c == ':') {
4530Sstevel@tonic-gate *np++ = c, c = getC(DOEXCL);
4540Sstevel@tonic-gate if (c == 'g')
4550Sstevel@tonic-gate *np++ = c, c = getC(DOEXCL);
4560Sstevel@tonic-gate *np++ = c;
4570Sstevel@tonic-gate if (!any(c, S_htrqxe))
4580Sstevel@tonic-gate goto vsyn;
4590Sstevel@tonic-gate } else
4600Sstevel@tonic-gate ungetD(c);
4610Sstevel@tonic-gate if (sc == '{') {
4620Sstevel@tonic-gate c = getC(DOEXCL);
4630Sstevel@tonic-gate if (c != '}') {
4640Sstevel@tonic-gate ungetC(c);
4650Sstevel@tonic-gate goto vsyn;
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate *np++ = c;
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate ret:
4700Sstevel@tonic-gate *np = 0;
4710Sstevel@tonic-gate addla(name);
4720Sstevel@tonic-gate return;
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate vsyn:
4750Sstevel@tonic-gate seterr("Variable syntax");
4760Sstevel@tonic-gate goto ret;
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
479356Smuffin void
addla(tchar * cp)480356Smuffin addla(tchar *cp)
4810Sstevel@tonic-gate {
4820Sstevel@tonic-gate tchar *buf;
4830Sstevel@tonic-gate int len = 0;
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate #ifdef TRACE
4860Sstevel@tonic-gate tprintf("TRACE- addla()\n");
4870Sstevel@tonic-gate #endif
4880Sstevel@tonic-gate if (lap) {
4890Sstevel@tonic-gate len = strlen_(lap);
4900Sstevel@tonic-gate buf = xalloc((len+1) * sizeof (tchar));
4910Sstevel@tonic-gate (void) strcpy_(buf, lap);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate len += strlen_(cp);
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate /* len+5 is allow 4 additional charecters just to be safe */
4960Sstevel@tonic-gate labuf = xrealloc(labuf, (len+5) * sizeof (tchar));
4970Sstevel@tonic-gate (void) strcpy_(labuf, cp);
4980Sstevel@tonic-gate if (lap) {
4990Sstevel@tonic-gate (void) strcat_(labuf, buf);
500559Snakanon xfree(buf);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate lap = labuf;
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate
505*2182Schin tchar lhsb[256];
506*2182Schin tchar slhs[256];
507*2182Schin tchar rhsb[512];
5080Sstevel@tonic-gate int quesarg;
5090Sstevel@tonic-gate
510356Smuffin void
getexcl(tchar sc)511356Smuffin getexcl(tchar sc)
5120Sstevel@tonic-gate {
513356Smuffin struct wordent *hp, *ip;
5140Sstevel@tonic-gate int left, right, dol;
515356Smuffin int c;
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate #ifdef TRACE
5180Sstevel@tonic-gate tprintf("TRACE- getexcl()\n");
5190Sstevel@tonic-gate #endif
5200Sstevel@tonic-gate if (sc == 0) {
5210Sstevel@tonic-gate sc = getC(0);
5220Sstevel@tonic-gate if (sc != '{') {
5230Sstevel@tonic-gate ungetC(sc);
5240Sstevel@tonic-gate sc = 0;
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate quesarg = -1;
5280Sstevel@tonic-gate lastev = eventno;
5290Sstevel@tonic-gate hp = gethent(sc);
5300Sstevel@tonic-gate if (hp == 0)
5310Sstevel@tonic-gate return;
5320Sstevel@tonic-gate hadhist = 1;
5330Sstevel@tonic-gate dol = 0;
5340Sstevel@tonic-gate if (hp == alhistp)
5350Sstevel@tonic-gate for (ip = hp->next->next; ip != alhistt; ip = ip->next)
5360Sstevel@tonic-gate dol++;
5370Sstevel@tonic-gate else
5380Sstevel@tonic-gate for (ip = hp->next->next; ip != hp->prev; ip = ip->next)
5390Sstevel@tonic-gate dol++;
5400Sstevel@tonic-gate left = 0, right = dol;
5410Sstevel@tonic-gate if (sc == HISTSUB) {
5420Sstevel@tonic-gate ungetC('s'), unreadc(HISTSUB), c = ':';
5430Sstevel@tonic-gate goto subst;
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate c = getC(0);
546559Snakanon /* if (!any(c, ":^$*-%")) */ /* change needed for char -> tchar */
5470Sstevel@tonic-gate if (! (c == ':' || c == '^' || c == '$' || c == '*' ||
548559Snakanon c == '-' || c == '%'))
5490Sstevel@tonic-gate goto subst;
5500Sstevel@tonic-gate left = right = -1;
5510Sstevel@tonic-gate if (c == ':') {
5520Sstevel@tonic-gate c = getC(0);
5530Sstevel@tonic-gate unreadc(c);
5540Sstevel@tonic-gate if (letter(c) || c == '&') {
5550Sstevel@tonic-gate c = ':';
5560Sstevel@tonic-gate left = 0, right = dol;
5570Sstevel@tonic-gate goto subst;
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate } else
5600Sstevel@tonic-gate ungetC(c);
5610Sstevel@tonic-gate if (!getsel(&left, &right, dol))
5620Sstevel@tonic-gate return;
5630Sstevel@tonic-gate c = getC(0);
5640Sstevel@tonic-gate if (c == '*')
5650Sstevel@tonic-gate ungetC(c), c = '-';
5660Sstevel@tonic-gate if (c == '-') {
5670Sstevel@tonic-gate if (!getsel(&left, &right, dol))
5680Sstevel@tonic-gate return;
5690Sstevel@tonic-gate c = getC(0);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate subst:
5720Sstevel@tonic-gate exclc = right - left + 1;
5730Sstevel@tonic-gate while (--left >= 0)
5740Sstevel@tonic-gate hp = hp->next;
5750Sstevel@tonic-gate if (sc == HISTSUB || c == ':') {
5760Sstevel@tonic-gate do {
5770Sstevel@tonic-gate hp = getsub(hp);
5780Sstevel@tonic-gate c = getC(0);
5790Sstevel@tonic-gate } while (c == ':');
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate unreadc(c);
5820Sstevel@tonic-gate if (sc == '{') {
5830Sstevel@tonic-gate c = getC(0);
5840Sstevel@tonic-gate if (c != '}')
5850Sstevel@tonic-gate seterr("Bad ! form");
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate exclnxt = hp;
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate struct wordent *
getsub(struct wordent * en)591356Smuffin getsub(struct wordent *en)
5920Sstevel@tonic-gate {
593356Smuffin tchar *cp;
5940Sstevel@tonic-gate int delim;
595356Smuffin int c;
5960Sstevel@tonic-gate int sc;
5970Sstevel@tonic-gate bool global = 0;
5980Sstevel@tonic-gate tchar orhsb[(sizeof rhsb)/(sizeof rhsb[0])];
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate #ifdef TRACE
6010Sstevel@tonic-gate tprintf("TRACE- getsub()\n");
6020Sstevel@tonic-gate #endif
6030Sstevel@tonic-gate exclnxt = 0;
6040Sstevel@tonic-gate sc = c = getC(0);
6050Sstevel@tonic-gate if (c == 'g')
6060Sstevel@tonic-gate global++, c = getC(0);
6070Sstevel@tonic-gate switch (c) {
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate case 'p':
6100Sstevel@tonic-gate justpr++;
6110Sstevel@tonic-gate goto ret;
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate case 'x':
6140Sstevel@tonic-gate case 'q':
6150Sstevel@tonic-gate global++;
6160Sstevel@tonic-gate /* fall into ... */
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate case 'h':
6190Sstevel@tonic-gate case 'r':
6200Sstevel@tonic-gate case 't':
6210Sstevel@tonic-gate case 'e':
6220Sstevel@tonic-gate break;
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate case '&':
6250Sstevel@tonic-gate if (slhs[0] == 0) {
6260Sstevel@tonic-gate seterr("No prev sub");
6270Sstevel@tonic-gate goto ret;
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate (void) strcpy_(lhsb, slhs);
6300Sstevel@tonic-gate break;
6310Sstevel@tonic-gate
632559Snakanon #if 0
6330Sstevel@tonic-gate case '~':
6340Sstevel@tonic-gate if (lhsb[0] == 0)
6350Sstevel@tonic-gate goto badlhs;
6360Sstevel@tonic-gate break;
637559Snakanon #endif
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate case 's':
6400Sstevel@tonic-gate delim = getC(0);
641559Snakanon if (alnum(delim) || isspnl(delim)) {
6420Sstevel@tonic-gate unreadc(delim);
6430Sstevel@tonic-gate bads:
6440Sstevel@tonic-gate lhsb[0] = 0;
6450Sstevel@tonic-gate seterr("Bad substitute");
6460Sstevel@tonic-gate goto ret;
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate cp = lhsb;
6490Sstevel@tonic-gate for (;;) {
6500Sstevel@tonic-gate c = getC(0);
6510Sstevel@tonic-gate if (c == '\n') {
6520Sstevel@tonic-gate unreadc(c);
6530Sstevel@tonic-gate break;
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate if (c == delim)
6560Sstevel@tonic-gate break;
6570Sstevel@tonic-gate if (cp > &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2])
6580Sstevel@tonic-gate goto bads;
6590Sstevel@tonic-gate if (c == '\\') {
6600Sstevel@tonic-gate c = getC(0);
6610Sstevel@tonic-gate if (c != delim && c != '\\')
6620Sstevel@tonic-gate *cp++ = '\\';
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate *cp++ = c;
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate if (cp != lhsb)
6670Sstevel@tonic-gate *cp++ = 0;
6680Sstevel@tonic-gate else if (lhsb[0] == 0) {
669559Snakanon /* badlhs: */
6700Sstevel@tonic-gate seterr("No prev lhs");
6710Sstevel@tonic-gate goto ret;
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate cp = rhsb;
6740Sstevel@tonic-gate (void) strcpy_(orhsb, cp);
6750Sstevel@tonic-gate for (;;) {
6760Sstevel@tonic-gate c = getC(0);
6770Sstevel@tonic-gate if (c == '\n') {
6780Sstevel@tonic-gate unreadc(c);
6790Sstevel@tonic-gate break;
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate if (c == delim)
6820Sstevel@tonic-gate break;
683559Snakanon #if 0
6840Sstevel@tonic-gate if (c == '~') {
685559Snakanon if (&cp[strlen_(orhsb)]
6860Sstevel@tonic-gate > &rhsb[(sizeof rhsb)/(sizeof rhsb[0]) - 2])
6870Sstevel@tonic-gate goto toorhs;
6880Sstevel@tonic-gate (void) strcpy_(cp, orhsb);
6890Sstevel@tonic-gate cp = strend(cp);
6900Sstevel@tonic-gate continue;
6910Sstevel@tonic-gate }
692559Snakanon #endif
6930Sstevel@tonic-gate if (cp > &rhsb[(sizeof rhsb)/(sizeof rhsb[0]) - 2]) {
694559Snakanon /* toorhs: */
6950Sstevel@tonic-gate seterr("Rhs too long");
6960Sstevel@tonic-gate goto ret;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate if (c == '\\') {
6990Sstevel@tonic-gate c = getC(0);
7000Sstevel@tonic-gate if (c != delim /* && c != '~' */)
7010Sstevel@tonic-gate *cp++ = '\\';
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate *cp++ = c;
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate *cp++ = 0;
7060Sstevel@tonic-gate break;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate default:
7090Sstevel@tonic-gate if (c == '\n')
7100Sstevel@tonic-gate unreadc(c);
7110Sstevel@tonic-gate seterrc(gettext("Bad ! modifier: "), c);
7120Sstevel@tonic-gate goto ret;
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate (void) strcpy_(slhs, lhsb);
7150Sstevel@tonic-gate if (exclc)
7160Sstevel@tonic-gate en = dosub(sc, en, global);
7170Sstevel@tonic-gate ret:
7180Sstevel@tonic-gate return (en);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate struct wordent *
dosub(int sc,struct wordent * en,bool global)722356Smuffin dosub(int sc, struct wordent *en, bool global)
7230Sstevel@tonic-gate {
7240Sstevel@tonic-gate struct wordent lex;
7250Sstevel@tonic-gate bool didsub = 0;
7260Sstevel@tonic-gate struct wordent *hp = &lex;
727356Smuffin struct wordent *wdp;
728356Smuffin int i = exclc;
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate #ifdef TRACE
7310Sstevel@tonic-gate tprintf("TRACE- dosub()\n");
7320Sstevel@tonic-gate #endif
7330Sstevel@tonic-gate wdp = hp;
7340Sstevel@tonic-gate while (--i >= 0) {
735559Snakanon struct wordent *new = (struct wordent *)xcalloc(1, sizeof *wdp);
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate new->prev = wdp;
7380Sstevel@tonic-gate new->next = hp;
7390Sstevel@tonic-gate wdp->next = new;
7400Sstevel@tonic-gate wdp = new;
7410Sstevel@tonic-gate en = en->next;
7420Sstevel@tonic-gate wdp->word = global || didsub == 0 ?
7430Sstevel@tonic-gate subword(en->word, sc, &didsub) : savestr(en->word);
7440Sstevel@tonic-gate }
7450Sstevel@tonic-gate if (didsub == 0)
7460Sstevel@tonic-gate seterr("Modifier failed");
7470Sstevel@tonic-gate hp->prev = wdp;
7480Sstevel@tonic-gate return (&enthist(-1000, &lex, 0)->Hlex);
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate tchar *
subword(tchar * cp,int type,bool * adid)752356Smuffin subword(tchar *cp, int type, bool *adid)
7530Sstevel@tonic-gate {
7540Sstevel@tonic-gate tchar wbuf[BUFSIZ];
755356Smuffin tchar *wp, *mp, *np;
756356Smuffin int i;
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate #ifdef TRACE
7590Sstevel@tonic-gate tprintf("TRACE- subword()\n");
7600Sstevel@tonic-gate #endif
7610Sstevel@tonic-gate switch (type) {
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate case 'r':
7640Sstevel@tonic-gate case 'e':
7650Sstevel@tonic-gate case 'h':
7660Sstevel@tonic-gate case 't':
7670Sstevel@tonic-gate case 'q':
7680Sstevel@tonic-gate case 'x':
7690Sstevel@tonic-gate wp = domod(cp, type);
7700Sstevel@tonic-gate if (wp == 0)
7710Sstevel@tonic-gate return (savestr(cp));
7720Sstevel@tonic-gate *adid = 1;
7730Sstevel@tonic-gate return (wp);
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate default:
7760Sstevel@tonic-gate wp = wbuf;
7770Sstevel@tonic-gate i = BUFSIZ - 4;
7780Sstevel@tonic-gate for (mp = cp; *mp; mp++)
7790Sstevel@tonic-gate if (matchs(mp, lhsb)) {
780559Snakanon for (np = cp; np < mp; )
7810Sstevel@tonic-gate *wp++ = *np++, --i;
7820Sstevel@tonic-gate for (np = rhsb; *np; np++) switch (*np) {
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate case '\\':
7850Sstevel@tonic-gate if (np[1] == '&')
7860Sstevel@tonic-gate np++;
7870Sstevel@tonic-gate /* fall into ... */
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate default:
7900Sstevel@tonic-gate if (--i < 0)
7910Sstevel@tonic-gate goto ovflo;
7920Sstevel@tonic-gate *wp++ = *np;
7930Sstevel@tonic-gate continue;
7940Sstevel@tonic-gate
7950Sstevel@tonic-gate case '&':
7960Sstevel@tonic-gate i -= strlen_(lhsb);
7970Sstevel@tonic-gate if (i < 0)
7980Sstevel@tonic-gate goto ovflo;
7990Sstevel@tonic-gate *wp = 0;
8000Sstevel@tonic-gate (void) strcat_(wp, lhsb);
8010Sstevel@tonic-gate wp = strend(wp);
8020Sstevel@tonic-gate continue;
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate mp += strlen_(lhsb);
8050Sstevel@tonic-gate i -= strlen_(mp);
8060Sstevel@tonic-gate if (i < 0) {
8070Sstevel@tonic-gate ovflo:
8080Sstevel@tonic-gate seterr("Subst buf ovflo");
809559Snakanon return (S_ /* "" */);
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate *wp = 0;
8120Sstevel@tonic-gate (void) strcat_(wp, mp);
8130Sstevel@tonic-gate *adid = 1;
8140Sstevel@tonic-gate return (savestr(wbuf));
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate return (savestr(cp));
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate }
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate tchar *
domod(tchar * cp,int type)821356Smuffin domod(tchar *cp, int type)
8220Sstevel@tonic-gate {
823356Smuffin tchar *wp, *xp;
824356Smuffin int c;
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate #ifdef TRACE
8270Sstevel@tonic-gate tprintf("TRACE- domod()\n");
8280Sstevel@tonic-gate #endif
8290Sstevel@tonic-gate switch (type) {
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate case 'x':
8320Sstevel@tonic-gate case 'q':
8330Sstevel@tonic-gate wp = savestr(cp);
8340Sstevel@tonic-gate for (xp = wp; c = *xp; xp++)
8350Sstevel@tonic-gate if (!issp(c) || type == 'q')
8360Sstevel@tonic-gate *xp |= QUOTE;
8370Sstevel@tonic-gate return (wp);
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate case 'h':
8400Sstevel@tonic-gate case 't':
8410Sstevel@tonic-gate if (!any('/', cp))
8420Sstevel@tonic-gate return (type == 't' ? savestr(cp) : 0);
8430Sstevel@tonic-gate wp = strend(cp);
8440Sstevel@tonic-gate while (*--wp != '/')
8450Sstevel@tonic-gate continue;
8460Sstevel@tonic-gate if (type == 'h')
8470Sstevel@tonic-gate xp = savestr(cp), xp[wp - cp] = 0;
8480Sstevel@tonic-gate else
8490Sstevel@tonic-gate xp = savestr(wp + 1);
8500Sstevel@tonic-gate return (xp);
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate case 'e':
8530Sstevel@tonic-gate case 'r':
8540Sstevel@tonic-gate wp = strend(cp);
8550Sstevel@tonic-gate for (wp--; wp >= cp && *wp != '/'; wp--)
8560Sstevel@tonic-gate if (*wp == '.') {
8570Sstevel@tonic-gate if (type == 'e')
8580Sstevel@tonic-gate xp = savestr(wp + 1);
8590Sstevel@tonic-gate else
8600Sstevel@tonic-gate xp = savestr(cp), xp[wp - cp] = 0;
8610Sstevel@tonic-gate return (xp);
8620Sstevel@tonic-gate }
863559Snakanon return (savestr(type == 'e' ? S_ /* "" */ : cp));
8640Sstevel@tonic-gate }
8650Sstevel@tonic-gate return (0);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate
868356Smuffin int
matchs(tchar * str,tchar * pat)869356Smuffin matchs(tchar *str, tchar *pat)
8700Sstevel@tonic-gate {
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate #ifdef TRACE
8730Sstevel@tonic-gate tprintf("TRACE- matchs()\n");
8740Sstevel@tonic-gate #endif
8750Sstevel@tonic-gate while (*str && *pat && *str == *pat)
8760Sstevel@tonic-gate str++, pat++;
8770Sstevel@tonic-gate return (*pat == 0);
8780Sstevel@tonic-gate }
8790Sstevel@tonic-gate
880356Smuffin int
getsel(int * al,int * ar,int dol)881356Smuffin getsel(int *al, int *ar, int dol)
8820Sstevel@tonic-gate {
883356Smuffin int c = getC(0);
884356Smuffin int i;
8850Sstevel@tonic-gate bool first = *al < 0;
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate #ifdef TRACE
8880Sstevel@tonic-gate tprintf("TRACE- getsel()\n");
8890Sstevel@tonic-gate #endif
8900Sstevel@tonic-gate switch (c) {
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate case '%':
8930Sstevel@tonic-gate if (quesarg == -1)
8940Sstevel@tonic-gate goto bad;
8950Sstevel@tonic-gate if (*al < 0)
8960Sstevel@tonic-gate *al = quesarg;
8970Sstevel@tonic-gate *ar = quesarg;
8980Sstevel@tonic-gate break;
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate case '-':
9010Sstevel@tonic-gate if (*al < 0) {
9020Sstevel@tonic-gate *al = 0;
9030Sstevel@tonic-gate *ar = dol - 1;
9040Sstevel@tonic-gate unreadc(c);
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate return (1);
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate case '^':
9090Sstevel@tonic-gate if (*al < 0)
9100Sstevel@tonic-gate *al = 1;
9110Sstevel@tonic-gate *ar = 1;
9120Sstevel@tonic-gate break;
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate case '$':
9150Sstevel@tonic-gate if (*al < 0)
9160Sstevel@tonic-gate *al = dol;
9170Sstevel@tonic-gate *ar = dol;
9180Sstevel@tonic-gate break;
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate case '*':
9210Sstevel@tonic-gate if (*al < 0)
9220Sstevel@tonic-gate *al = 1;
9230Sstevel@tonic-gate *ar = dol;
9240Sstevel@tonic-gate if (*ar < *al) {
9250Sstevel@tonic-gate *ar = 0;
9260Sstevel@tonic-gate *al = 1;
9270Sstevel@tonic-gate return (1);
9280Sstevel@tonic-gate }
9290Sstevel@tonic-gate break;
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate default:
9320Sstevel@tonic-gate if (digit(c)) {
9330Sstevel@tonic-gate i = 0;
9340Sstevel@tonic-gate while (digit(c)) {
9350Sstevel@tonic-gate i = i * 10 + c - '0';
9360Sstevel@tonic-gate c = getC(0);
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate if (i < 0)
9390Sstevel@tonic-gate i = dol + 1;
9400Sstevel@tonic-gate if (*al < 0)
9410Sstevel@tonic-gate *al = i;
9420Sstevel@tonic-gate *ar = i;
9430Sstevel@tonic-gate } else
9440Sstevel@tonic-gate if (*al < 0)
9450Sstevel@tonic-gate *al = 0, *ar = dol;
9460Sstevel@tonic-gate else
9470Sstevel@tonic-gate *ar = dol - 1;
9480Sstevel@tonic-gate unreadc(c);
9490Sstevel@tonic-gate break;
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate if (first) {
9520Sstevel@tonic-gate c = getC(0);
9530Sstevel@tonic-gate unreadc(c);
9540Sstevel@tonic-gate /* if (any(c, "-$*")) */ /* char -> tchar */
9550Sstevel@tonic-gate if (c == '-' || c == '$' || c == '*')
9560Sstevel@tonic-gate return (1);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate if (*al > *ar || *ar > dol) {
9590Sstevel@tonic-gate bad:
9600Sstevel@tonic-gate seterr("Bad ! arg selector");
9610Sstevel@tonic-gate return (0);
9620Sstevel@tonic-gate }
9630Sstevel@tonic-gate return (1);
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate struct wordent *
gethent(int sc)968356Smuffin gethent(int sc)
9690Sstevel@tonic-gate {
970356Smuffin struct Hist *hp;
971356Smuffin tchar *np;
972356Smuffin int c;
9730Sstevel@tonic-gate int event;
9740Sstevel@tonic-gate bool back = 0;
9750Sstevel@tonic-gate
9760Sstevel@tonic-gate #ifdef TRACE
9770Sstevel@tonic-gate tprintf("TRACE- gethent()\n");
9780Sstevel@tonic-gate #endif
9790Sstevel@tonic-gate c = sc == HISTSUB ? HIST : getC(0);
9800Sstevel@tonic-gate if (c == HIST) {
9810Sstevel@tonic-gate if (alhistp)
9820Sstevel@tonic-gate return (alhistp);
9830Sstevel@tonic-gate event = eventno;
9840Sstevel@tonic-gate goto skip;
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate switch (c) {
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate case ':':
9890Sstevel@tonic-gate case '^':
9900Sstevel@tonic-gate case '$':
9910Sstevel@tonic-gate case '*':
9920Sstevel@tonic-gate case '%':
9930Sstevel@tonic-gate ungetC(c);
9940Sstevel@tonic-gate if (lastev == eventno && alhistp)
9950Sstevel@tonic-gate return (alhistp);
9960Sstevel@tonic-gate event = lastev;
9970Sstevel@tonic-gate break;
9980Sstevel@tonic-gate
9990Sstevel@tonic-gate case '-':
10000Sstevel@tonic-gate back = 1;
10010Sstevel@tonic-gate c = getC(0);
10020Sstevel@tonic-gate goto number;
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate case '#': /* !# is command being typed in (mrh) */
1005559Snakanon return (¶ml);
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate default:
1008559Snakanon /* if (any(c, "(=~")) { */
10090Sstevel@tonic-gate if (c == '(' || c == '=' || c == '~') {
10100Sstevel@tonic-gate unreadc(c);
10110Sstevel@tonic-gate ungetC(HIST);
10120Sstevel@tonic-gate return (0);
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate if (digit(c))
10150Sstevel@tonic-gate goto number;
10160Sstevel@tonic-gate np = lhsb;
10170Sstevel@tonic-gate /* while (!any(c, ": \t\\\n}")) { */
10180Sstevel@tonic-gate while (! (c == ':' || c == '\\' || isspnl(c) || c == '}')) {
10190Sstevel@tonic-gate if (np < &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2])
10200Sstevel@tonic-gate *np++ = c;
10210Sstevel@tonic-gate c = getC(0);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate unreadc(c);
10240Sstevel@tonic-gate if (np == lhsb) {
10250Sstevel@tonic-gate ungetC(HIST);
10260Sstevel@tonic-gate return (0);
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate *np++ = 0;
10290Sstevel@tonic-gate hp = findev(lhsb, 0);
10300Sstevel@tonic-gate if (hp)
10310Sstevel@tonic-gate lastev = hp->Hnum;
10320Sstevel@tonic-gate return (&hp->Hlex);
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate case '?':
10350Sstevel@tonic-gate np = lhsb;
10360Sstevel@tonic-gate for (;;) {
10370Sstevel@tonic-gate c = getC(0);
10380Sstevel@tonic-gate if (c == '\n') {
10390Sstevel@tonic-gate unreadc(c);
10400Sstevel@tonic-gate break;
10410Sstevel@tonic-gate }
10420Sstevel@tonic-gate if (c == '?')
10430Sstevel@tonic-gate break;
10440Sstevel@tonic-gate if (np < &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2])
10450Sstevel@tonic-gate *np++ = c;
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate if (np == lhsb) {
10480Sstevel@tonic-gate if (lhsb[0] == 0) {
10490Sstevel@tonic-gate seterr("No prev search");
10500Sstevel@tonic-gate return (0);
10510Sstevel@tonic-gate }
10520Sstevel@tonic-gate } else
10530Sstevel@tonic-gate *np++ = 0;
10540Sstevel@tonic-gate hp = findev(lhsb, 1);
10550Sstevel@tonic-gate if (hp)
10560Sstevel@tonic-gate lastev = hp->Hnum;
10570Sstevel@tonic-gate return (&hp->Hlex);
10580Sstevel@tonic-gate
10590Sstevel@tonic-gate number:
10600Sstevel@tonic-gate event = 0;
10610Sstevel@tonic-gate while (digit(c)) {
10620Sstevel@tonic-gate event = event * 10 + c - '0';
10630Sstevel@tonic-gate c = getC(0);
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate if (back)
10660Sstevel@tonic-gate event = eventno + (alhistp == 0) - (event ? event : 0);
10670Sstevel@tonic-gate unreadc(c);
10680Sstevel@tonic-gate break;
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate skip:
10710Sstevel@tonic-gate for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
10720Sstevel@tonic-gate if (hp->Hnum == event) {
10730Sstevel@tonic-gate hp->Href = eventno;
10740Sstevel@tonic-gate lastev = hp->Hnum;
10750Sstevel@tonic-gate return (&hp->Hlex);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate np = putn(event);
10780Sstevel@tonic-gate noev(np);
10790Sstevel@tonic-gate return (0);
10800Sstevel@tonic-gate }
10810Sstevel@tonic-gate
10820Sstevel@tonic-gate struct Hist *
findev(tchar * cp,bool anyarg)1083356Smuffin findev(tchar *cp, bool anyarg)
10840Sstevel@tonic-gate {
1085356Smuffin struct Hist *hp;
10860Sstevel@tonic-gate
10870Sstevel@tonic-gate #ifdef TRACE
10880Sstevel@tonic-gate tprintf("TRACE- findev()\n");
10890Sstevel@tonic-gate #endif
10900Sstevel@tonic-gate for (hp = Histlist.Hnext; hp; hp = hp->Hnext) {
1091356Smuffin tchar *dp;
1092356Smuffin tchar *p, *q;
1093356Smuffin struct wordent *lp = hp->Hlex.next;
10940Sstevel@tonic-gate int argno = 0;
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate if (lp->word[0] == '\n')
10970Sstevel@tonic-gate continue;
10980Sstevel@tonic-gate if (!anyarg) {
10990Sstevel@tonic-gate p = cp;
11000Sstevel@tonic-gate q = lp->word;
11010Sstevel@tonic-gate do
11020Sstevel@tonic-gate if (!*p)
11030Sstevel@tonic-gate return (hp);
11040Sstevel@tonic-gate while (*p++ == *q++);
11050Sstevel@tonic-gate continue;
11060Sstevel@tonic-gate }
11070Sstevel@tonic-gate do {
11080Sstevel@tonic-gate for (dp = lp->word; *dp; dp++) {
11090Sstevel@tonic-gate p = cp;
11100Sstevel@tonic-gate q = dp;
11110Sstevel@tonic-gate do
11120Sstevel@tonic-gate if (!*p) {
11130Sstevel@tonic-gate quesarg = argno;
11140Sstevel@tonic-gate return (hp);
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate while (*p++ == *q++);
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate lp = lp->next;
11190Sstevel@tonic-gate argno++;
11200Sstevel@tonic-gate } while (lp->word[0] != '\n');
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate noev(cp);
11230Sstevel@tonic-gate return (0);
11240Sstevel@tonic-gate }
11250Sstevel@tonic-gate
1126356Smuffin void
noev(tchar * cp)1127356Smuffin noev(tchar *cp)
11280Sstevel@tonic-gate {
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate #ifdef TRACE
11310Sstevel@tonic-gate tprintf("TRACE- noev()\n");
11320Sstevel@tonic-gate #endif
11330Sstevel@tonic-gate seterr2(cp, ": Event not found");
11340Sstevel@tonic-gate }
11350Sstevel@tonic-gate
1136356Smuffin void
setexclp(tchar * cp)1137356Smuffin setexclp(tchar *cp)
11380Sstevel@tonic-gate {
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate #ifdef TRACE
11410Sstevel@tonic-gate tprintf("TRACE- setexclp()\n");
11420Sstevel@tonic-gate #endif
11430Sstevel@tonic-gate if (cp && cp[0] == '\n')
11440Sstevel@tonic-gate return;
11450Sstevel@tonic-gate exclp = cp;
11460Sstevel@tonic-gate }
11470Sstevel@tonic-gate
1148356Smuffin void
unreadc(tchar c)1149356Smuffin unreadc(tchar c)
11500Sstevel@tonic-gate {
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate peekread = c;
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate
1155356Smuffin int
readc(bool wanteof)1156356Smuffin readc(bool wanteof)
11570Sstevel@tonic-gate {
1158356Smuffin int c;
1159356Smuffin static int sincereal;
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate if (c = peekread) {
11620Sstevel@tonic-gate peekread = 0;
11630Sstevel@tonic-gate return (c);
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate top:
11660Sstevel@tonic-gate if (alvecp) {
11670Sstevel@tonic-gate if (c = *alvecp++)
11680Sstevel@tonic-gate return (c);
11690Sstevel@tonic-gate if (*alvec) {
11700Sstevel@tonic-gate alvecp = *alvec++;
11710Sstevel@tonic-gate return (' ');
11720Sstevel@tonic-gate }
11730Sstevel@tonic-gate }
11740Sstevel@tonic-gate if (alvec) {
11750Sstevel@tonic-gate if (alvecp = *alvec) {
11760Sstevel@tonic-gate alvec++;
11770Sstevel@tonic-gate goto top;
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate /* Infinite source! */
11800Sstevel@tonic-gate return ('\n');
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate if (evalp) {
11830Sstevel@tonic-gate if (c = *evalp++)
11840Sstevel@tonic-gate return (c);
11850Sstevel@tonic-gate if (*evalvec) {
11860Sstevel@tonic-gate evalp = *evalvec++;
11870Sstevel@tonic-gate return (' ');
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate evalp = 0;
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate if (evalvec) {
11920Sstevel@tonic-gate if (evalvec == (tchar **)1) {
11930Sstevel@tonic-gate doneinp = 1;
11940Sstevel@tonic-gate reset();
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate if (evalp = *evalvec) {
11970Sstevel@tonic-gate evalvec++;
11980Sstevel@tonic-gate goto top;
11990Sstevel@tonic-gate }
12000Sstevel@tonic-gate evalvec = (tchar **)1;
12010Sstevel@tonic-gate return ('\n');
12020Sstevel@tonic-gate }
12030Sstevel@tonic-gate do {
12040Sstevel@tonic-gate if (arginp == (tchar *) 1 || onelflg == 1) {
12050Sstevel@tonic-gate if (wanteof)
12060Sstevel@tonic-gate return (-1);
12070Sstevel@tonic-gate exitstat();
12080Sstevel@tonic-gate }
12090Sstevel@tonic-gate if (arginp) {
12100Sstevel@tonic-gate if ((c = *arginp++) == 0) {
12110Sstevel@tonic-gate arginp = (tchar *) 1;
12120Sstevel@tonic-gate return ('\n');
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate return (c);
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate reread:
12170Sstevel@tonic-gate c = bgetc();
12180Sstevel@tonic-gate if (c < 0) {
12190Sstevel@tonic-gate struct sgttyb tty;
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate if (wanteof)
12220Sstevel@tonic-gate return (-1);
12230Sstevel@tonic-gate /* was isatty but raw with ignoreeof yields problems */
12240Sstevel@tonic-gate if (ioctl(SHIN, TIOCGETP, (char *)&tty) == 0 &&
12250Sstevel@tonic-gate (tty.sg_flags & RAW) == 0) {
12260Sstevel@tonic-gate /* was 'short' for FILEC */
12270Sstevel@tonic-gate int ctpgrp;
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate if (++sincereal > 25)
12300Sstevel@tonic-gate goto oops;
12310Sstevel@tonic-gate if (tpgrp != -1 &&
1232559Snakanon ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp) == 0 &&
12330Sstevel@tonic-gate tpgrp != ctpgrp) {
12340Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP,
1235559Snakanon (char *)&tpgrp);
12360Sstevel@tonic-gate (void) killpg(ctpgrp, SIGHUP);
12370Sstevel@tonic-gate printf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp);
12380Sstevel@tonic-gate goto reread;
12390Sstevel@tonic-gate }
1240559Snakanon if (adrof(S_ignoreeof /* "ignoreeof" */)) {
12410Sstevel@tonic-gate if (loginsh)
1242559Snakanon printf("\nUse \"logout\" to logout.\n");
12430Sstevel@tonic-gate else
1244559Snakanon printf("\nUse \"exit\" to leave csh.\n");
12450Sstevel@tonic-gate reset();
12460Sstevel@tonic-gate }
12470Sstevel@tonic-gate if (chkstop == 0) {
12480Sstevel@tonic-gate panystop(1);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate }
12510Sstevel@tonic-gate oops:
12520Sstevel@tonic-gate doneinp = 1;
12530Sstevel@tonic-gate reset();
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate sincereal = 0;
12560Sstevel@tonic-gate if (c == '\n' && onelflg)
12570Sstevel@tonic-gate onelflg--;
12580Sstevel@tonic-gate } while (c == 0);
12590Sstevel@tonic-gate return (c);
12600Sstevel@tonic-gate }
12610Sstevel@tonic-gate
1262559Snakanon static void
expand_fbuf(void)1263559Snakanon expand_fbuf(void)
1264559Snakanon {
1265559Snakanon tchar **nfbuf =
1266559Snakanon (tchar **)xcalloc((unsigned)(fblocks + 2), sizeof (tchar **));
1267559Snakanon
1268559Snakanon if (fbuf) {
1269559Snakanon (void) blkcpy(nfbuf, fbuf);
1270559Snakanon xfree((char *)fbuf);
1271559Snakanon }
1272559Snakanon fbuf = nfbuf;
1273559Snakanon fbuf[fblocks] = (tchar *)xcalloc(BUFSIZ + MB_LEN_MAX,
1274559Snakanon sizeof (tchar));
1275559Snakanon fblocks++;
1276559Snakanon }
1277559Snakanon
1278356Smuffin int
bgetc(void)1279356Smuffin bgetc(void)
12800Sstevel@tonic-gate {
1281356Smuffin int buf, off, c;
12820Sstevel@tonic-gate #ifdef FILEC
1283559Snakanon tchar ttyline[BUFSIZ + MB_LEN_MAX]; /* read_() can return extra bytes */
1284559Snakanon int roomleft;
12850Sstevel@tonic-gate #endif
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate #ifdef TELL
12880Sstevel@tonic-gate if (cantell) {
12890Sstevel@tonic-gate if (fseekp < fbobp || fseekp > feobp) {
12900Sstevel@tonic-gate fbobp = feobp = fseekp;
12910Sstevel@tonic-gate (void) lseek(SHIN, fseekp, 0);
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate if (fseekp == feobp) {
12940Sstevel@tonic-gate fbobp = feobp;
12950Sstevel@tonic-gate do
12960Sstevel@tonic-gate c = read_(SHIN, fbuf[0], BUFSIZ);
12970Sstevel@tonic-gate while (c < 0 && errno == EINTR);
12980Sstevel@tonic-gate if (c <= 0)
12990Sstevel@tonic-gate return (-1);
13000Sstevel@tonic-gate feobp += c;
13010Sstevel@tonic-gate }
13020Sstevel@tonic-gate c = fbuf[0][fseekp - fbobp];
13030Sstevel@tonic-gate fseekp++;
13040Sstevel@tonic-gate return (c);
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate #endif
13070Sstevel@tonic-gate again:
1308559Snakanon buf = (int)fseekp / BUFSIZ;
13090Sstevel@tonic-gate if (buf >= fblocks) {
1310559Snakanon expand_fbuf();
13110Sstevel@tonic-gate goto again;
13120Sstevel@tonic-gate }
13130Sstevel@tonic-gate if (fseekp >= feobp) {
1314559Snakanon buf = (int)feobp / BUFSIZ;
1315559Snakanon off = (int)feobp % BUFSIZ;
13160Sstevel@tonic-gate #ifndef FILEC
13170Sstevel@tonic-gate for (;;) {
13180Sstevel@tonic-gate c = read_(SHIN, fbuf[buf] + off, BUFSIZ - off);
13190Sstevel@tonic-gate #else
13200Sstevel@tonic-gate roomleft = BUFSIZ - off;
13210Sstevel@tonic-gate for (;;) {
13220Sstevel@tonic-gate if (filec && intty) {
1323559Snakanon c = tenex(ttyline, BUFSIZ);
13240Sstevel@tonic-gate if (c > roomleft) {
1325559Snakanon expand_fbuf();
1326559Snakanon copy(fbuf[buf] + off, ttyline,
1327559Snakanon roomleft * sizeof (tchar));
1328559Snakanon copy(fbuf[buf + 1], ttyline + roomleft,
1329559Snakanon (c - roomleft) * sizeof (tchar));
1330559Snakanon } else if (c > 0) {
1331559Snakanon copy(fbuf[buf] + off, ttyline,
1332559Snakanon c * sizeof (tchar));
13330Sstevel@tonic-gate }
1334559Snakanon } else {
13350Sstevel@tonic-gate c = read_(SHIN, fbuf[buf] + off, roomleft);
1336559Snakanon if (c > roomleft) {
1337559Snakanon expand_fbuf();
1338559Snakanon copy(fbuf[buf + 1],
1339559Snakanon fbuf[buf] + off + roomleft,
1340559Snakanon (c - roomleft) * sizeof (tchar));
1341559Snakanon }
1342559Snakanon }
13430Sstevel@tonic-gate #endif
13440Sstevel@tonic-gate if (c >= 0)
13450Sstevel@tonic-gate break;
13460Sstevel@tonic-gate if (errno == EWOULDBLOCK) {
13470Sstevel@tonic-gate int off = 0;
13480Sstevel@tonic-gate
13490Sstevel@tonic-gate (void) ioctl(SHIN, FIONBIO, (char *)&off);
13500Sstevel@tonic-gate } else if (errno != EINTR)
13510Sstevel@tonic-gate break;
13520Sstevel@tonic-gate }
13530Sstevel@tonic-gate if (c <= 0)
13540Sstevel@tonic-gate return (-1);
13550Sstevel@tonic-gate feobp += c;
13560Sstevel@tonic-gate #ifndef FILEC
13570Sstevel@tonic-gate goto again;
13580Sstevel@tonic-gate #else
13590Sstevel@tonic-gate if (filec && !intty)
13600Sstevel@tonic-gate goto again;
13610Sstevel@tonic-gate #endif
13620Sstevel@tonic-gate }
1363559Snakanon c = fbuf[buf][(int)fseekp % BUFSIZ];
13640Sstevel@tonic-gate fseekp++;
13650Sstevel@tonic-gate return (c);
13660Sstevel@tonic-gate }
13670Sstevel@tonic-gate
1368559Snakanon void
1369356Smuffin bfree(void)
13700Sstevel@tonic-gate {
1371356Smuffin int sb, i;
13720Sstevel@tonic-gate
13730Sstevel@tonic-gate #ifdef TELL
13740Sstevel@tonic-gate if (cantell)
13750Sstevel@tonic-gate return;
13760Sstevel@tonic-gate #endif
13770Sstevel@tonic-gate if (whyles)
13780Sstevel@tonic-gate return;
1379559Snakanon sb = (int)(fseekp - 1) / BUFSIZ;
13800Sstevel@tonic-gate if (sb > 0) {
13810Sstevel@tonic-gate for (i = 0; i < sb; i++)
13820Sstevel@tonic-gate xfree(fbuf[i]);
13830Sstevel@tonic-gate (void) blkcpy(fbuf, &fbuf[sb]);
13840Sstevel@tonic-gate fseekp -= BUFSIZ * sb;
13850Sstevel@tonic-gate feobp -= BUFSIZ * sb;
13860Sstevel@tonic-gate fblocks -= sb;
13870Sstevel@tonic-gate }
13880Sstevel@tonic-gate }
13890Sstevel@tonic-gate
1390356Smuffin void
1391356Smuffin bseek(off_t l)
13920Sstevel@tonic-gate {
1393356Smuffin struct whyle *wp;
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate fseekp = l;
13960Sstevel@tonic-gate #ifdef TELL
13970Sstevel@tonic-gate if (!cantell) {
13980Sstevel@tonic-gate #endif
13990Sstevel@tonic-gate if (!whyles)
14000Sstevel@tonic-gate return;
14010Sstevel@tonic-gate for (wp = whyles; wp->w_next; wp = wp->w_next)
14020Sstevel@tonic-gate continue;
14030Sstevel@tonic-gate if (wp->w_start > l)
14040Sstevel@tonic-gate l = wp->w_start;
14050Sstevel@tonic-gate #ifdef TELL
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate #endif
14080Sstevel@tonic-gate }
14090Sstevel@tonic-gate
14100Sstevel@tonic-gate /* any similarity to bell telephone is purely accidental */
14110Sstevel@tonic-gate #ifndef btell
14120Sstevel@tonic-gate off_t
1413356Smuffin btell(void)
14140Sstevel@tonic-gate {
14150Sstevel@tonic-gate
14160Sstevel@tonic-gate return (fseekp);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate #endif
14190Sstevel@tonic-gate
1420356Smuffin void
1421356Smuffin btoeof(void)
14220Sstevel@tonic-gate {
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate (void) lseek(SHIN, (off_t)0, 2);
14250Sstevel@tonic-gate fseekp = feobp;
14260Sstevel@tonic-gate wfree();
14270Sstevel@tonic-gate bfree();
14280Sstevel@tonic-gate }
14290Sstevel@tonic-gate
14300Sstevel@tonic-gate #ifdef TELL
1431356Smuffin void
1432356Smuffin settell(void)
14330Sstevel@tonic-gate {
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate cantell = 0;
14360Sstevel@tonic-gate if (arginp || onelflg || intty)
14370Sstevel@tonic-gate return;
14380Sstevel@tonic-gate if (lseek(SHIN, (off_t)0, 1) < 0 || errno == ESPIPE)
14390Sstevel@tonic-gate return;
1440559Snakanon fbuf = (tchar **)xcalloc(2, sizeof (tchar **));
14410Sstevel@tonic-gate fblocks = 1;
1442559Snakanon fbuf[0] = (tchar *)xcalloc(BUFSIZ + MB_LEN_MAX, sizeof (tchar));
14430Sstevel@tonic-gate fseekp = fbobp = feobp = lseek(SHIN, (off_t)0, 1);
14440Sstevel@tonic-gate cantell = 1;
14450Sstevel@tonic-gate }
14460Sstevel@tonic-gate #endif
1447