sh.lex.c revision 100616
1100616Smp/* $Header: /src/pub/tcsh/sh.lex.c,v 3.56 2002/07/08 20:57:32 christos Exp $ */ 259243Sobrien/* 359243Sobrien * sh.lex.c: Lexical analysis into tokens 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35100616SmpRCSID("$Id: sh.lex.c,v 3.56 2002/07/08 20:57:32 christos Exp $") 3659243Sobrien 3759243Sobrien#include "ed.h" 3859243Sobrien/* #define DEBUG_INP */ 3959243Sobrien/* #define DEBUG_SEEK */ 4059243Sobrien 4159243Sobrien/* 4259243Sobrien * C shell 4359243Sobrien */ 4459243Sobrien 4559243Sobrien/* 4659243Sobrien * These lexical routines read input and form lists of words. 4759243Sobrien * There is some involved processing here, because of the complications 4859243Sobrien * of input buffering, and especially because of history substitution. 4959243Sobrien */ 5059243Sobrienstatic Char *word __P((void)); 5159243Sobrienstatic int getC1 __P((int)); 5259243Sobrienstatic void getdol __P((void)); 5359243Sobrienstatic void getexcl __P((int)); 5459243Sobrienstatic struct Hist *findev __P((Char *, bool)); 5559243Sobrienstatic void setexclp __P((Char *)); 5659243Sobrienstatic int bgetc __P((void)); 5759243Sobrienstatic void balloc __P((int)); 5859243Sobrienstatic void bfree __P((void)); 5959243Sobrienstatic struct wordent *gethent __P((int)); 6059243Sobrienstatic int matchs __P((Char *, Char *)); 6159243Sobrienstatic int getsel __P((int *, int *, int)); 6259243Sobrienstatic struct wordent *getsub __P((struct wordent *)); 6359243Sobrienstatic Char *subword __P((Char *, int, bool *)); 6459243Sobrienstatic struct wordent *dosub __P((int, struct wordent *, bool)); 6559243Sobrien 6659243Sobrien/* 6759243Sobrien * Peekc is a peek character for getC, peekread for readc. 6859243Sobrien * There is a subtlety here in many places... history routines 6959243Sobrien * will read ahead and then insert stuff into the input stream. 7059243Sobrien * If they push back a character then they must push it behind 7159243Sobrien * the text substituted by the history substitution. On the other 7259243Sobrien * hand in several places we need 2 peek characters. To make this 7359243Sobrien * all work, the history routines read with getC, and make use both 7459243Sobrien * of ungetC and unreadc. The key observation is that the state 7559243Sobrien * of getC at the call of a history reference is such that calls 7659243Sobrien * to getC from the history routines will always yield calls of 7759243Sobrien * readc, unless this peeking is involved. That is to say that during 7859243Sobrien * getexcl the variables lap, exclp, and exclnxt are all zero. 7959243Sobrien * 8059243Sobrien * Getdol invokes history substitution, hence the extra peek, peekd, 8159243Sobrien * which it can ungetD to be before history substitutions. 8259243Sobrien */ 8359243Sobrienstatic Char peekc = 0, peekd = 0; 8459243Sobrienstatic Char peekread = 0; 8559243Sobrien 8659243Sobrien/* (Tail of) current word from ! subst */ 8759243Sobrienstatic Char *exclp = NULL; 8859243Sobrien 8959243Sobrien/* The rest of the ! subst words */ 9059243Sobrienstatic struct wordent *exclnxt = NULL; 9159243Sobrien 9259243Sobrien/* Count of remaining words in ! subst */ 9359243Sobrienstatic int exclc = 0; 9459243Sobrien 9559243Sobrien/* "Globp" for alias resubstitution */ 9669408Sacheint aret = TCSH_F_SEEK; 9759243Sobrien 9859243Sobrien/* 9959243Sobrien * Labuf implements a general buffer for lookahead during lexical operations. 10059243Sobrien * Text which is to be placed in the input stream can be stuck here. 10159243Sobrien * We stick parsed ahead $ constructs during initial input, 10259243Sobrien * process id's from `$$', and modified variable values (from qualifiers 10359243Sobrien * during expansion in sh.dol.c) here. 10459243Sobrien */ 10559243Sobrienstatic Char labuf[BUFSIZE]; 10659243Sobrien 10759243Sobrien/* 10859243Sobrien * Lex returns to its caller not only a wordlist (as a "var" parameter) 10959243Sobrien * but also whether a history substitution occurred. This is used in 11059243Sobrien * the main (process) routine to determine whether to echo, and also 11159243Sobrien * when called by the alias routine to determine whether to keep the 11259243Sobrien * argument list. 11359243Sobrien */ 11459243Sobrienstatic bool hadhist = 0; 11559243Sobrien 11659243Sobrien/* 11759243Sobrien * Avoid alias expansion recursion via \!# 11859243Sobrien */ 11959243Sobrienint hleft; 12059243Sobrien 12159243SobrienChar histline[BUFSIZE + 2]; /* last line input */ 12259243Sobrien 12359243Sobrien /* The +2 is to fool hp's optimizer */ 12459243Sobrienbool histvalid = 0; /* is histline valid */ 12559243Sobrienstatic Char *histlinep = NULL; /* current pointer into histline */ 12659243Sobrien 12759243Sobrienstatic Char getCtmp; 12859243Sobrien 12959243Sobrien#define getC(f) (((getCtmp = peekc) != '\0') ? (peekc = 0, getCtmp) : getC1(f)) 13059243Sobrien#define ungetC(c) peekc = (Char) c 13159243Sobrien#define ungetD(c) peekd = (Char) c 13259243Sobrien 13359243Sobrien/* Use Htime to store timestamps picked up from history file for enthist() 13459243Sobrien * if reading saved history (sg) 13559243Sobrien */ 13659243Sobrientime_t Htime = (time_t)0; 13759243Sobrienstatic time_t a2time_t __P((Char *)); 13859243Sobrien 13959243Sobrien/* 14059243Sobrien * for history event processing 14159243Sobrien * in the command 'echo !?foo?:1 !$' we want the !$ to expand from the line 14259243Sobrien * 'foo' was found instead of the last command 14359243Sobrien */ 14459243Sobrienstatic int uselastevent = 1; 14559243Sobrien 14659243Sobrienint 14759243Sobrienlex(hp) 14859243Sobrien struct wordent *hp; 14959243Sobrien{ 15059243Sobrien struct wordent *wdp; 15159243Sobrien int c; 15259243Sobrien 15359243Sobrien 15459243Sobrien uselastevent = 1; 15559243Sobrien histvalid = 0; 15659243Sobrien histlinep = histline; 15759243Sobrien *histlinep = '\0'; 15859243Sobrien 15959243Sobrien btell(&lineloc); 16059243Sobrien hp->next = hp->prev = hp; 16159243Sobrien hp->word = STRNULL; 16259243Sobrien hadhist = 0; 16359243Sobrien do 16459243Sobrien c = readc(0); 16559243Sobrien while (c == ' ' || c == '\t'); 16659243Sobrien if (c == HISTSUB && intty) 16759243Sobrien /* ^lef^rit from tty is short !:s^lef^rit */ 16859243Sobrien getexcl(c); 16959243Sobrien else 17059243Sobrien unreadc(c); 17159243Sobrien wdp = hp; 17259243Sobrien /* 17359243Sobrien * The following loop is written so that the links needed by freelex will 17459243Sobrien * be ready and rarin to go even if it is interrupted. 17559243Sobrien */ 17659243Sobrien do { 17759243Sobrien struct wordent *new; 17859243Sobrien 17959243Sobrien new = (struct wordent *) xmalloc((size_t) sizeof(*wdp)); 18059243Sobrien new->word = STRNULL; 18159243Sobrien new->prev = wdp; 18259243Sobrien new->next = hp; 18359243Sobrien wdp->next = new; 18459243Sobrien hp->prev = new; 18559243Sobrien wdp = new; 18659243Sobrien wdp->word = word(); 18759243Sobrien } while (wdp->word[0] != '\n'); 18859243Sobrien if (histlinep < histline + BUFSIZE) { 18959243Sobrien *histlinep = '\0'; 19059243Sobrien if (histlinep > histline && histlinep[-1] == '\n') 19159243Sobrien histlinep[-1] = '\0'; 19259243Sobrien histvalid = 1; 19359243Sobrien } 19459243Sobrien else { 19559243Sobrien histline[BUFSIZE - 1] = '\0'; 19659243Sobrien } 19759243Sobrien 19859243Sobrien return (hadhist); 19959243Sobrien} 20059243Sobrien 20159243Sobrienstatic time_t 20259243Sobriena2time_t(word) 20359243Sobrien Char *word; 20459243Sobrien{ 20559243Sobrien /* Attempt to distinguish timestamps from other possible entries. 20659243Sobrien * Format: "+NNNNNNNNNN" (10 digits, left padded with ascii '0') */ 20759243Sobrien 20859243Sobrien time_t ret; 20959243Sobrien Char *s; 21059243Sobrien int ct; 21159243Sobrien 21259243Sobrien if (!word || *(s = word) != '+') 21359243Sobrien return (time_t)0; 21459243Sobrien 21559243Sobrien for (++s, ret = 0, ct = 0; *s; ++s, ++ct) 21659243Sobrien { 21759243Sobrien if (!isdigit((unsigned char)*s)) 21859243Sobrien return (time_t)0; 21959243Sobrien ret = ret * 10 + (time_t)((unsigned char)*s - '0'); 22059243Sobrien } 22159243Sobrien 22259243Sobrien if (ct != 10) 22359243Sobrien return (time_t)0; 22459243Sobrien 22559243Sobrien return ret; 22659243Sobrien} 22759243Sobrien 22859243Sobrienvoid 22959243Sobrienprlex(sp0) 23059243Sobrien struct wordent *sp0; 23159243Sobrien{ 23259243Sobrien struct wordent *sp = sp0->next; 23359243Sobrien 23459243Sobrien for (;;) { 23559243Sobrien xprintf("%S", sp->word); 23659243Sobrien sp = sp->next; 23759243Sobrien if (sp == sp0) 23859243Sobrien break; 23959243Sobrien if (sp->word[0] != '\n') 24059243Sobrien xputchar(' '); 24159243Sobrien } 24259243Sobrien} 24359243Sobrien 24459243Sobrienvoid 24559243Sobriencopylex(hp, fp) 24659243Sobrien struct wordent *hp; 24759243Sobrien struct wordent *fp; 24859243Sobrien{ 24959243Sobrien struct wordent *wdp; 25059243Sobrien 25159243Sobrien wdp = hp; 25259243Sobrien fp = fp->next; 25359243Sobrien do { 25459243Sobrien struct wordent *new; 25559243Sobrien 25659243Sobrien new = (struct wordent *) xmalloc((size_t) sizeof(*wdp)); 25759243Sobrien new->word = STRNULL; 25859243Sobrien new->prev = wdp; 25959243Sobrien new->next = hp; 26059243Sobrien wdp->next = new; 26159243Sobrien hp->prev = new; 26259243Sobrien wdp = new; 26359243Sobrien wdp->word = Strsave(fp->word); 26459243Sobrien fp = fp->next; 26559243Sobrien } while (wdp->word[0] != '\n'); 26659243Sobrien} 26759243Sobrien 26859243Sobrienvoid 26959243Sobrienfreelex(vp) 27059243Sobrien struct wordent *vp; 27159243Sobrien{ 27259243Sobrien struct wordent *fp; 27359243Sobrien 27459243Sobrien while (vp->next != vp) { 27559243Sobrien fp = vp->next; 27659243Sobrien vp->next = fp->next; 27759243Sobrien if (fp->word != STRNULL) 27859243Sobrien xfree((ptr_t) fp->word); 27959243Sobrien xfree((ptr_t) fp); 28059243Sobrien } 28159243Sobrien vp->prev = vp; 28259243Sobrien} 28359243Sobrien 28459243Sobrienstatic Char * 28559243Sobrienword() 28659243Sobrien{ 28759243Sobrien Char c, c1; 28859243Sobrien Char *wp; 28959243Sobrien Char wbuf[BUFSIZE]; 29059243Sobrien Char hbuf[12]; 29159243Sobrien int h; 29259243Sobrien bool dolflg; 29359243Sobrien int i; 29459415Sobrien#if defined(DSPMBYTE) 29559415Sobrien int mbytepos = 1; 29659415Sobrien#endif /* DSPMBYTE */ 29759243Sobrien 29859243Sobrien wp = wbuf; 29959243Sobrien i = BUFSIZE - 4; 30059243Sobrienloop: 30159243Sobrien while ((c = getC(DOALL)) == ' ' || c == '\t') 30259243Sobrien continue; 30359243Sobrien if (cmap(c, _META | _ESC)) 30459243Sobrien switch (c) { 30559243Sobrien case '&': 30659243Sobrien case '|': 30759243Sobrien case '<': 30859243Sobrien case '>': 30959243Sobrien *wp++ = c; 31059243Sobrien c1 = getC(DOALL); 31159243Sobrien if (c1 == c) 31259243Sobrien *wp++ = c1; 31359243Sobrien else 31459243Sobrien ungetC(c1); 31559243Sobrien goto ret; 31659243Sobrien 31759243Sobrien case '#': 31859243Sobrien if (intty) 31959243Sobrien break; 32059243Sobrien c = 0; 32159243Sobrien h = 0; 32259243Sobrien do { 32359243Sobrien c1 = c; 32459243Sobrien c = getC(0); 32559243Sobrien if (h < 12) 32659243Sobrien hbuf[h++] = c; 32759243Sobrien } while (c != '\n'); 32859243Sobrien hbuf[11] = '\0'; 32959243Sobrien Htime = a2time_t(hbuf); 33059243Sobrien if (c1 == '\\') 33159243Sobrien goto loop; 33259243Sobrien /*FALLTHROUGH*/ 33359243Sobrien 33459243Sobrien case ';': 33559243Sobrien case '(': 33659243Sobrien case ')': 33759243Sobrien case '\n': 33859243Sobrien *wp++ = c; 33959243Sobrien goto ret; 34059243Sobrien 34159243Sobrien case '\\': 34259243Sobrien c = getC(0); 34359243Sobrien if (c == '\n') { 34459243Sobrien if (onelflg == 1) 34559243Sobrien onelflg = 2; 34659243Sobrien goto loop; 34759243Sobrien } 34859243Sobrien if (c != HIST) 34959243Sobrien *wp++ = '\\', --i; 35059243Sobrien c |= QUOTE; 35159243Sobrien default: 35259243Sobrien break; 35359243Sobrien } 35459243Sobrien c1 = 0; 35559243Sobrien dolflg = DOALL; 35659243Sobrien for (;;) { 35759415Sobrien#if defined(DSPMBYTE) 35859415Sobrien if (mbytepos == 2) 35959415Sobrien mbytepos = 1; 36059415Sobrien else if (mbytepos == 1 && Ismbyte1(c) && 2 <= i) 36159415Sobrien mbytepos = 2; 36259415Sobrien else 36359415Sobrien#endif /* DSPMBYTE */ 36459243Sobrien if (c1) { 36559243Sobrien if (c == c1) { 36659243Sobrien c1 = 0; 36759243Sobrien dolflg = DOALL; 36859243Sobrien } 36959243Sobrien else if (c == '\\') { 37059243Sobrien c = getC(0); 37159243Sobrien/* 37259243Sobrien * PWP: this is dumb, but how all of the other shells work. If \ quotes 37359243Sobrien * a character OUTSIDE of a set of ''s, why shouldn't it quote EVERY 37459243Sobrien * following character INSIDE a set of ''s. 37559243Sobrien * 37659243Sobrien * Actually, all I really want to be able to say is 'foo\'bar' --> foo'bar 37759243Sobrien */ 37859243Sobrien if (c == HIST) 37959243Sobrien c |= QUOTE; 38059243Sobrien else { 38159243Sobrien if (bslash_quote && 38259243Sobrien ((c == '\'') || (c == '"') || 38359243Sobrien (c == '\\'))) { 38459243Sobrien c |= QUOTE; 38559243Sobrien } 38659243Sobrien else { 38759243Sobrien if (c == '\n') 38859243Sobrien /* 38959243Sobrien * if (c1 == '`') c = ' '; else 39059243Sobrien */ 39159243Sobrien c |= QUOTE; 39259243Sobrien ungetC(c); 39359243Sobrien c = '\\'; 39459243Sobrien } 39559243Sobrien } 39659243Sobrien } 39759243Sobrien else if (c == '\n') { 39859243Sobrien seterror(ERR_UNMATCHED, c1); 39959243Sobrien ungetC(c); 40059243Sobrien break; 40159243Sobrien } 40259243Sobrien } 40359243Sobrien else if (cmap(c, _META | _QF | _QB | _ESC)) { 40459243Sobrien if (c == '\\') { 40559243Sobrien c = getC(0); 40659243Sobrien if (c == '\n') { 40759243Sobrien if (onelflg == 1) 40859243Sobrien onelflg = 2; 40959243Sobrien break; 41059243Sobrien } 41159243Sobrien if (c != HIST) 41259243Sobrien *wp++ = '\\', --i; 41359243Sobrien c |= QUOTE; 41459243Sobrien } 41559243Sobrien else if (cmap(c, _QF | _QB)) { /* '"` */ 41659243Sobrien c1 = c; 41759243Sobrien dolflg = c == '"' ? DOALL : DOEXCL; 41859243Sobrien } 41959243Sobrien else if (c != '#' || !intty) { 42059243Sobrien ungetC(c); 42159243Sobrien break; 42259243Sobrien } 42359243Sobrien } 42459243Sobrien if (--i > 0) { 42559243Sobrien *wp++ = c; 42659243Sobrien c = getC(dolflg); 42759243Sobrien } 42859243Sobrien else { 42959243Sobrien seterror(ERR_WTOOLONG); 43059243Sobrien wp = &wbuf[1]; 43159243Sobrien break; 43259243Sobrien } 43359243Sobrien } 43459243Sobrienret: 43559243Sobrien *wp = 0; 43659243Sobrien return (Strsave(wbuf)); 43759243Sobrien} 43859243Sobrien 43959243Sobrienstatic int 44059243SobriengetC1(flag) 44159243Sobrien int flag; 44259243Sobrien{ 44359243Sobrien Char c; 44459243Sobrien 44559243Sobrien for (;;) { 44659243Sobrien if ((c = peekc) != 0) { 44759243Sobrien peekc = 0; 44859243Sobrien return (c); 44959243Sobrien } 45059243Sobrien if (lap) { 45159243Sobrien if ((c = *lap++) == 0) 45259243Sobrien lap = 0; 45359243Sobrien else { 45459243Sobrien if (cmap(c, _META | _QF | _QB)) 45559243Sobrien c |= QUOTE; 45659243Sobrien return (c); 45759243Sobrien } 45859243Sobrien } 45959243Sobrien if ((c = peekd) != 0) { 46059243Sobrien peekd = 0; 46159243Sobrien return (c); 46259243Sobrien } 46359243Sobrien if (exclp) { 46459243Sobrien if ((c = *exclp++) != 0) 46559243Sobrien return (c); 46659243Sobrien if (exclnxt && --exclc >= 0) { 46759243Sobrien exclnxt = exclnxt->next; 46859243Sobrien setexclp(exclnxt->word); 46959243Sobrien return (' '); 47059243Sobrien } 47159243Sobrien exclp = 0; 47259243Sobrien exclnxt = 0; 47359243Sobrien /* this will throw away the dummy history entries */ 47459243Sobrien savehist(NULL, 0); 47559243Sobrien 47659243Sobrien } 47759243Sobrien if (exclnxt) { 47859243Sobrien exclnxt = exclnxt->next; 47959243Sobrien if (--exclc < 0) 48059243Sobrien exclnxt = 0; 48159243Sobrien else 48259243Sobrien setexclp(exclnxt->word); 48359243Sobrien continue; 48459243Sobrien } 48559243Sobrien c = readc(0); 48659243Sobrien if (c == '$' && (flag & DODOL)) { 48759243Sobrien getdol(); 48859243Sobrien continue; 48959243Sobrien } 49059243Sobrien if (c == HIST && (flag & DOEXCL)) { 49159243Sobrien getexcl(0); 49259243Sobrien continue; 49359243Sobrien } 49459243Sobrien break; 49559243Sobrien } 49659243Sobrien return (c); 49759243Sobrien} 49859243Sobrien 49959243Sobrienstatic void 50059243Sobriengetdol() 50159243Sobrien{ 50259243Sobrien Char *np, *ep; 50359243Sobrien Char name[4 * MAXVARLEN + 1]; 50459243Sobrien int c; 50559243Sobrien int sc; 50659243Sobrien bool special = 0, toolong; 50759243Sobrien 50859243Sobrien np = name, *np++ = '$'; 50959243Sobrien c = sc = getC(DOEXCL); 51059243Sobrien if (any("\t \n", c)) { 51159243Sobrien ungetD(c); 51259243Sobrien ungetC('$' | QUOTE); 51359243Sobrien return; 51459243Sobrien } 51559243Sobrien if (c == '{') 51659243Sobrien *np++ = (Char) c, c = getC(DOEXCL); 51759243Sobrien if (c == '#' || c == '?' || c == '%') 51859243Sobrien special++, *np++ = (Char) c, c = getC(DOEXCL); 51959243Sobrien *np++ = (Char) c; 52059243Sobrien switch (c) { 52159243Sobrien 52259243Sobrien case '<': 52359243Sobrien case '$': 52459243Sobrien case '!': 52559243Sobrien if (special) 52659243Sobrien seterror(ERR_SPDOLLT); 52759243Sobrien *np = 0; 52859243Sobrien addla(name); 52959243Sobrien return; 53059243Sobrien 53159243Sobrien case '\n': 53259243Sobrien ungetD(c); 53359243Sobrien np--; 53459243Sobrien if (!special) 53559243Sobrien seterror(ERR_NEWLINE); 53659243Sobrien *np = 0; 53759243Sobrien addla(name); 53859243Sobrien return; 53959243Sobrien 54059243Sobrien case '*': 54159243Sobrien if (special) 54259243Sobrien seterror(ERR_SPSTAR); 54359243Sobrien *np = 0; 54459243Sobrien addla(name); 54559243Sobrien return; 54659243Sobrien 54759243Sobrien default: 54859243Sobrien toolong = 0; 54959243Sobrien if (Isdigit(c)) { 55059243Sobrien#ifdef notdef 55159243Sobrien /* let $?0 pass for now */ 55259243Sobrien if (special) { 55359243Sobrien seterror(ERR_DIGIT); 55459243Sobrien *np = 0; 55559243Sobrien addla(name); 55659243Sobrien return; 55759243Sobrien } 55859243Sobrien#endif 55959243Sobrien /* we know that np < &name[4] */ 56059243Sobrien ep = &np[MAXVARLEN]; 56159243Sobrien while ((c = getC(DOEXCL)) != 0) { 56259243Sobrien if (!Isdigit(c)) 56359243Sobrien break; 56459243Sobrien if (np < ep) 56559243Sobrien *np++ = (Char) c; 56659243Sobrien else 56759243Sobrien toolong = 1; 56859243Sobrien } 56959243Sobrien } 57059243Sobrien else if (letter(c)) { 57159243Sobrien /* we know that np < &name[4] */ 57259243Sobrien ep = &np[MAXVARLEN]; 57359243Sobrien toolong = 0; 57459243Sobrien while ((c = getC(DOEXCL)) != 0) { 57559243Sobrien /* Bugfix for ${v123x} from Chris Torek, DAS DEC-90. */ 57659243Sobrien if (!letter(c) && !Isdigit(c)) 57759243Sobrien break; 57859243Sobrien if (np < ep) 57959243Sobrien *np++ = (Char) c; 58059243Sobrien else 58159243Sobrien toolong = 1; 58259243Sobrien } 58359243Sobrien } 58459243Sobrien else { 58559243Sobrien if (!special) 58659243Sobrien seterror(ERR_VARILL); 58759243Sobrien else { 58859243Sobrien ungetD(c); 58959243Sobrien --np; 59059243Sobrien } 59159243Sobrien *np = 0; 59259243Sobrien addla(name); 59359243Sobrien return; 59459243Sobrien } 59559243Sobrien if (toolong) { 59659243Sobrien seterror(ERR_VARTOOLONG); 59759243Sobrien *np = 0; 59859243Sobrien addla(name); 59959243Sobrien return; 60059243Sobrien } 60159243Sobrien break; 60259243Sobrien } 60359243Sobrien if (c == '[') { 60459243Sobrien *np++ = (Char) c; 60559243Sobrien /* 60659243Sobrien * Name up to here is a max of MAXVARLEN + 8. 60759243Sobrien */ 60859243Sobrien ep = &np[2 * MAXVARLEN + 8]; 60959243Sobrien do { 61059243Sobrien /* 61159243Sobrien * Michael Greim: Allow $ expansion to take place in selector 61259243Sobrien * expressions. (limits the number of characters returned) 61359243Sobrien */ 61459243Sobrien c = getC(DOEXCL | DODOL); 61559243Sobrien if (c == '\n') { 61659243Sobrien ungetD(c); 61759243Sobrien np--; 61859243Sobrien seterror(ERR_NLINDEX); 61959243Sobrien *np = 0; 62059243Sobrien addla(name); 62159243Sobrien return; 62259243Sobrien } 62359243Sobrien if (np < ep) 62459243Sobrien *np++ = (Char) c; 62559243Sobrien } while (c != ']'); 62659243Sobrien *np = '\0'; 62759243Sobrien if (np >= ep) { 62859243Sobrien seterror(ERR_SELOVFL); 62959243Sobrien addla(name); 63059243Sobrien return; 63159243Sobrien } 63259243Sobrien c = getC(DOEXCL); 63359243Sobrien } 63459243Sobrien /* 63559243Sobrien * Name up to here is a max of 2 * MAXVARLEN + 8. 63659243Sobrien */ 63759243Sobrien if (c == ':') { 63859243Sobrien /* 63959243Sobrien * if the :g modifier is followed by a newline, then error right away! 64059243Sobrien * -strike 64159243Sobrien */ 64259243Sobrien 64359243Sobrien int gmodflag = 0, amodflag = 0; 64459243Sobrien 64559243Sobrien#ifndef COMPAT 64659243Sobrien do { 64759243Sobrien#endif /* COMPAT */ 64859243Sobrien *np++ = (Char) c, c = getC(DOEXCL); 64959243Sobrien if (c == 'g' || c == 'a') { 65059243Sobrien if (c == 'g') 65159243Sobrien gmodflag++; 65259243Sobrien else 65359243Sobrien amodflag++; 65459243Sobrien *np++ = (Char) c; c = getC(DOEXCL); 65559243Sobrien } 65659243Sobrien if ((c == 'g' && !gmodflag) || (c == 'a' && !amodflag)) { 65759243Sobrien if (c == 'g') 65859243Sobrien gmodflag++; 65959243Sobrien else 66059243Sobrien amodflag++; 66159243Sobrien *np++ = (Char) c; c = getC(DOEXCL); 66259243Sobrien } 66359243Sobrien *np++ = (Char) c; 66459243Sobrien /* scan s// [eichin:19910926.0512EST] */ 66559243Sobrien if (c == 's') { 66659243Sobrien int delimcnt = 2; 66759243Sobrien int delim = getC(0); 66859243Sobrien *np++ = (Char) delim; 66959243Sobrien 67059243Sobrien if (!delim || letter(delim) 67159243Sobrien || Isdigit(delim) || any(" \t\n", delim)) { 67259243Sobrien seterror(ERR_BADSUBST); 67359243Sobrien break; 67459243Sobrien } 67559243Sobrien while ((c = getC(0)) != (-1)) { 67659243Sobrien *np++ = (Char) c; 67759243Sobrien if(c == delim) delimcnt--; 67859243Sobrien if(!delimcnt) break; 67959243Sobrien } 68059243Sobrien if(delimcnt) { 68159243Sobrien seterror(ERR_BADSUBST); 68259243Sobrien break; 68359243Sobrien } 68459243Sobrien c = 's'; 68559243Sobrien } 68659243Sobrien if (!any("htrqxesul", c)) { 68759243Sobrien if ((amodflag || gmodflag) && c == '\n') 68859243Sobrien stderror(ERR_VARSYN); /* strike */ 68959243Sobrien seterror(ERR_BADMOD, c); 69059243Sobrien *np = 0; 69159243Sobrien addla(name); 69259243Sobrien return; 69359243Sobrien } 69459243Sobrien#ifndef COMPAT 69559243Sobrien } 69659243Sobrien while ((c = getC(DOEXCL)) == ':'); 69759243Sobrien ungetD(c); 69859243Sobrien#endif /* COMPAT */ 69959243Sobrien } 70059243Sobrien else 70159243Sobrien ungetD(c); 70259243Sobrien if (sc == '{') { 70359243Sobrien c = getC(DOEXCL); 70459243Sobrien if (c != '}') { 70559243Sobrien ungetD(c); 70659243Sobrien seterror(ERR_MISSING, '}'); 70759243Sobrien *np = 0; 70859243Sobrien addla(name); 70959243Sobrien return; 71059243Sobrien } 71159243Sobrien *np++ = (Char) c; 71259243Sobrien } 71359243Sobrien *np = 0; 71459243Sobrien addla(name); 71559243Sobrien return; 71659243Sobrien} 71759243Sobrien 71859243Sobrienvoid 71959243Sobrienaddla(cp) 72059243Sobrien Char *cp; 72159243Sobrien{ 72259243Sobrien Char buf[BUFSIZE]; 72359243Sobrien 72459243Sobrien if (Strlen(cp) + (lap ? Strlen(lap) : 0) >= 72559243Sobrien (sizeof(labuf) - 4) / sizeof(Char)) { 72659243Sobrien seterror(ERR_EXPOVFL); 72759243Sobrien return; 72859243Sobrien } 72959243Sobrien if (lap) 73059243Sobrien (void) Strcpy(buf, lap); 73159243Sobrien (void) Strcpy(labuf, cp); 73259243Sobrien if (lap) 73359243Sobrien (void) Strcat(labuf, buf); 73459243Sobrien lap = labuf; 73559243Sobrien} 73659243Sobrien 73759243Sobrienstatic Char lhsb[32]; 73859243Sobrienstatic Char slhs[32]; 73959243Sobrienstatic Char rhsb[64]; 74059243Sobrienstatic int quesarg; 74159243Sobrien 74259243Sobrienstatic void 74359243Sobriengetexcl(sc) 74459243Sobrien int sc; 74559243Sobrien{ 74659243Sobrien struct wordent *hp, *ip; 74759243Sobrien int left, right, dol; 74859243Sobrien int c; 74959243Sobrien 75059243Sobrien if (sc == 0) { 75159243Sobrien sc = getC(0); 75259243Sobrien if (sc != '{') { 75359243Sobrien ungetC(sc); 75459243Sobrien sc = 0; 75559243Sobrien } 75659243Sobrien } 75759243Sobrien quesarg = -1; 75859243Sobrien 75959243Sobrien if (uselastevent) { 76059243Sobrien uselastevent = 0; 76159243Sobrien lastev = eventno; 76259243Sobrien } 76359243Sobrien else 76459243Sobrien lastev = eventno; 76559243Sobrien hp = gethent(sc); 76659243Sobrien if (hp == 0) 76759243Sobrien return; 76859243Sobrien hadhist = 1; 76959243Sobrien dol = 0; 77059243Sobrien if (hp == alhistp) 77159243Sobrien for (ip = hp->next->next; ip != alhistt; ip = ip->next) 77259243Sobrien dol++; 77359243Sobrien else 77459243Sobrien for (ip = hp->next->next; ip != hp->prev; ip = ip->next) 77559243Sobrien dol++; 77659243Sobrien left = 0, right = dol; 77759243Sobrien if (sc == HISTSUB) { 77859243Sobrien ungetC('s'), unreadc(HISTSUB), c = ':'; 77959243Sobrien goto subst; 78059243Sobrien } 78159243Sobrien c = getC(0); 78259243Sobrien if (!any(":^$*-%", c)) 78359243Sobrien goto subst; 78459243Sobrien left = right = -1; 78559243Sobrien if (c == ':') { 78659243Sobrien c = getC(0); 78759243Sobrien unreadc(c); 78859243Sobrien if (letter(c) || c == '&') { 78959243Sobrien c = ':'; 79059243Sobrien left = 0, right = dol; 79159243Sobrien goto subst; 79259243Sobrien } 79359243Sobrien } 79459243Sobrien else 79559243Sobrien ungetC(c); 79659243Sobrien if (!getsel(&left, &right, dol)) 79759243Sobrien return; 79859243Sobrien c = getC(0); 79959243Sobrien if (c == '*') 80059243Sobrien ungetC(c), c = '-'; 80159243Sobrien if (c == '-') { 80259243Sobrien if (!getsel(&left, &right, dol)) 80359243Sobrien return; 80459243Sobrien c = getC(0); 80559243Sobrien } 80659243Sobriensubst: 80759243Sobrien exclc = right - left + 1; 80859243Sobrien while (--left >= 0) 80959243Sobrien hp = hp->next; 81059243Sobrien if (sc == HISTSUB || c == ':') { 81159243Sobrien do { 81259243Sobrien hp = getsub(hp); 81359243Sobrien c = getC(0); 81459243Sobrien } while (c == ':'); 81559243Sobrien } 81659243Sobrien unreadc(c); 81759243Sobrien if (sc == '{') { 81859243Sobrien c = getC(0); 81959243Sobrien if (c != '}') 82059243Sobrien seterror(ERR_BADBANG); 82159243Sobrien } 82259243Sobrien exclnxt = hp; 82359243Sobrien} 82459243Sobrien 82559243Sobrienstatic struct wordent * 82659243Sobriengetsub(en) 82759243Sobrien struct wordent *en; 82859243Sobrien{ 82959243Sobrien Char *cp; 83059243Sobrien int delim; 83159243Sobrien int c; 83259243Sobrien int sc; 83359243Sobrien bool global; 83459243Sobrien Char orhsb[sizeof(rhsb) / sizeof(Char)]; 83559243Sobrien 83659243Sobrien#ifndef COMPAT 83759243Sobrien do { 83859243Sobrien#endif /* COMPAT */ 83959243Sobrien exclnxt = 0; 84059243Sobrien global = 0; 84159243Sobrien sc = c = getC(0); 84259243Sobrien if (c == 'g' || c == 'a') { 84359243Sobrien global |= (c == 'g') ? 1 : 2; 84459243Sobrien sc = c = getC(0); 84559243Sobrien } 84659243Sobrien if (((c =='g') && !(global & 1)) || ((c == 'a') && !(global & 2))) { 84759243Sobrien global |= (c == 'g') ? 1 : 2; 84859243Sobrien sc = c = getC(0); 84959243Sobrien } 85059243Sobrien 85159243Sobrien switch (c) { 85259243Sobrien case 'p': 85359243Sobrien justpr++; 85459243Sobrien return (en); 85559243Sobrien 85659243Sobrien case 'x': 85759243Sobrien case 'q': 85859243Sobrien global |= 1; 85959243Sobrien /*FALLTHROUGH*/ 86059243Sobrien 86159243Sobrien case 'h': 86259243Sobrien case 'r': 86359243Sobrien case 't': 86459243Sobrien case 'e': 86559243Sobrien case 'u': 86659243Sobrien case 'l': 86759243Sobrien break; 86859243Sobrien 86959243Sobrien case '&': 87059243Sobrien if (slhs[0] == 0) { 87159243Sobrien seterror(ERR_NOSUBST); 87259243Sobrien return (en); 87359243Sobrien } 87459243Sobrien (void) Strcpy(lhsb, slhs); 87559243Sobrien break; 87659243Sobrien 87759243Sobrien#ifdef notdef 87859243Sobrien case '~': 87959243Sobrien if (lhsb[0] == 0) 88059243Sobrien goto badlhs; 88159243Sobrien break; 88259243Sobrien#endif 88359243Sobrien 88459243Sobrien case 's': 88559243Sobrien delim = getC(0); 88659243Sobrien if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) { 88759243Sobrien unreadc(delim); 88859243Sobrien lhsb[0] = 0; 88959243Sobrien seterror(ERR_BADSUBST); 89059243Sobrien return (en); 89159243Sobrien } 89259243Sobrien cp = lhsb; 89359243Sobrien for (;;) { 89459243Sobrien c = getC(0); 89559243Sobrien if (c == '\n') { 89659243Sobrien unreadc(c); 89759243Sobrien break; 89859243Sobrien } 89959243Sobrien if (c == delim) 90059243Sobrien break; 90159243Sobrien if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) { 90259243Sobrien lhsb[0] = 0; 90359243Sobrien seterror(ERR_BADSUBST); 90459243Sobrien return (en); 90559243Sobrien } 90659243Sobrien if (c == '\\') { 90759243Sobrien c = getC(0); 90859243Sobrien if (c != delim && c != '\\') 90959243Sobrien *cp++ = '\\'; 91059243Sobrien } 91159243Sobrien *cp++ = (Char) c; 91259243Sobrien } 91359243Sobrien if (cp != lhsb) 91459243Sobrien *cp++ = 0; 91559243Sobrien else if (lhsb[0] == 0) { 91659243Sobrien seterror(ERR_LHS); 91759243Sobrien return (en); 91859243Sobrien } 91959243Sobrien cp = rhsb; 92059243Sobrien (void) Strcpy(orhsb, cp); 92159243Sobrien for (;;) { 92259243Sobrien c = getC(0); 92359243Sobrien if (c == '\n') { 92459243Sobrien unreadc(c); 92559243Sobrien break; 92659243Sobrien } 92759243Sobrien if (c == delim) 92859243Sobrien break; 92959243Sobrien#ifdef notdef 93059243Sobrien if (c == '~') { 93159243Sobrien if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) / 93259243Sobrien sizeof(Char) - 2]) 93359243Sobrien goto toorhs; 93459243Sobrien (void) Strcpy(cp, orhsb); 93559243Sobrien cp = Strend(cp); 93659243Sobrien continue; 93759243Sobrien } 93859243Sobrien#endif 93959243Sobrien if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) { 94059243Sobrien seterror(ERR_RHSLONG); 94159243Sobrien return (en); 94259243Sobrien } 94359243Sobrien if (c == '\\') { 94459243Sobrien c = getC(0); 94559243Sobrien if (c != delim /* && c != '~' */ ) 94659243Sobrien *cp++ = '\\'; 94759243Sobrien } 94859243Sobrien *cp++ = (Char) c; 94959243Sobrien } 95059243Sobrien *cp++ = 0; 95159243Sobrien break; 95259243Sobrien 95359243Sobrien default: 95459243Sobrien if (c == '\n') 95559243Sobrien unreadc(c); 95659243Sobrien seterror(ERR_BADBANGMOD, c); 95759243Sobrien return (en); 95859243Sobrien } 95959243Sobrien (void) Strcpy(slhs, lhsb); 96059243Sobrien if (exclc) 96159243Sobrien en = dosub(sc, en, global); 96259243Sobrien#ifndef COMPAT 96359243Sobrien } 96459243Sobrien while ((c = getC(0)) == ':'); 96559243Sobrien unreadc(c); 96659243Sobrien#endif /* COMPAT */ 96759243Sobrien return (en); 96859243Sobrien} 96959243Sobrien 97059243Sobrien/* 97159243Sobrien * 97259243Sobrien * From Beto Appleton (beto@aixwiz.austin.ibm.com) 97359243Sobrien * 97459243Sobrien * when using history substitution, and the variable 97559243Sobrien * 'history' is set to a value higher than 1000, 97659243Sobrien * the shell might either freeze (hang) or core-dump. 97759243Sobrien * We raise the limit to 50000000 97859243Sobrien */ 97959243Sobrien 98059243Sobrien#define HIST_PURGE -50000000 98159243Sobrienstatic struct wordent * 98259243Sobriendosub(sc, en, global) 98359243Sobrien int sc; 98459243Sobrien struct wordent *en; 98559243Sobrien bool global; 98659243Sobrien{ 98759243Sobrien struct wordent lexi; 98859243Sobrien bool didsub = 0, didone = 0; 98959243Sobrien struct wordent *hp = &lexi; 99059243Sobrien struct wordent *wdp; 99159243Sobrien int i = exclc; 99259243Sobrien struct Hist *hst; 99359243Sobrien 99459243Sobrien wdp = hp; 99559243Sobrien while (--i >= 0) { 99659243Sobrien struct wordent *new = 99759243Sobrien (struct wordent *) xcalloc(1, sizeof *wdp); 99859243Sobrien 99959243Sobrien new->word = 0; 100059243Sobrien new->prev = wdp; 100159243Sobrien new->next = hp; 100259243Sobrien wdp->next = new; 100359243Sobrien wdp = new; 100459243Sobrien en = en->next; 100559243Sobrien if (en->word) { 100659243Sobrien Char *tword, *otword; 100759243Sobrien 100859243Sobrien if ((global & 1) || didsub == 0) { 100959243Sobrien tword = subword(en->word, sc, &didone); 101059243Sobrien if (didone) 101159243Sobrien didsub = 1; 101259243Sobrien if (global & 2) { 101359243Sobrien while (didone && tword != STRNULL) { 101459243Sobrien otword = tword; 101559243Sobrien tword = subword(otword, sc, &didone); 101659243Sobrien if (Strcmp(tword, otword) == 0) { 101759243Sobrien xfree((ptr_t) otword); 101859243Sobrien break; 101959243Sobrien } 102059243Sobrien else 102159243Sobrien xfree((ptr_t) otword); 102259243Sobrien } 102359243Sobrien } 102459243Sobrien } 102559243Sobrien else 102659243Sobrien tword = Strsave(en->word); 102759243Sobrien wdp->word = tword; 102859243Sobrien } 102959243Sobrien } 103059243Sobrien if (didsub == 0) 103159243Sobrien seterror(ERR_MODFAIL); 103259243Sobrien hp->prev = wdp; 103359243Sobrien /* 103459243Sobrien * ANSI mode HP/UX compiler chokes on 103559243Sobrien * return &enthist(HIST_PURGE, &lexi, 0)->Hlex; 103659243Sobrien */ 103759243Sobrien hst = enthist(HIST_PURGE, &lexi, 0, 0); 103859243Sobrien return &(hst->Hlex); 103959243Sobrien} 104059243Sobrien 104159243Sobrienstatic Char * 104259243Sobriensubword(cp, type, adid) 104359243Sobrien Char *cp; 104459243Sobrien int type; 104559243Sobrien bool *adid; 104659243Sobrien{ 104759243Sobrien Char wbuf[BUFSIZE]; 104859243Sobrien Char *wp, *mp, *np; 104959243Sobrien int i; 105059243Sobrien 105159243Sobrien *adid = 0; 105259243Sobrien switch (type) { 105359243Sobrien 105459243Sobrien case 'r': 105559243Sobrien case 'e': 105659243Sobrien case 'h': 105759243Sobrien case 't': 105859243Sobrien case 'q': 105959243Sobrien case 'x': 106059243Sobrien case 'u': 106159243Sobrien case 'l': 106259243Sobrien wp = domod(cp, type); 106359243Sobrien if (wp == 0) 106459243Sobrien return (Strsave(cp)); 106559243Sobrien *adid = 1; 106659243Sobrien return (wp); 106759243Sobrien 106859243Sobrien default: 106959243Sobrien wp = wbuf; 107059243Sobrien i = BUFSIZE - 4; 107159243Sobrien for (mp = cp; *mp; mp++) 107259243Sobrien if (matchs(mp, lhsb)) { 107359243Sobrien for (np = cp; np < mp;) 107459243Sobrien *wp++ = *np++, --i; 107559243Sobrien for (np = rhsb; *np; np++) 107659243Sobrien switch (*np) { 107759243Sobrien 107859243Sobrien case '\\': 107959243Sobrien if (np[1] == '&') 108059243Sobrien np++; 108159243Sobrien /* fall into ... */ 108259243Sobrien 108359243Sobrien default: 108459243Sobrien if (--i < 0) { 108559243Sobrien seterror(ERR_SUBOVFL); 108659243Sobrien return (STRNULL); 108759243Sobrien } 108859243Sobrien *wp++ = *np; 108959243Sobrien continue; 109059243Sobrien 109159243Sobrien case '&': 109259243Sobrien i -= Strlen(lhsb); 109359243Sobrien if (i < 0) { 109459243Sobrien seterror(ERR_SUBOVFL); 109559243Sobrien return (STRNULL); 109659243Sobrien } 109759243Sobrien *wp = 0; 109859243Sobrien (void) Strcat(wp, lhsb); 109959243Sobrien wp = Strend(wp); 110059243Sobrien continue; 110159243Sobrien } 110259243Sobrien mp += Strlen(lhsb); 110359243Sobrien i -= Strlen(mp); 110459243Sobrien if (i < 0) { 110559243Sobrien seterror(ERR_SUBOVFL); 110659243Sobrien return (STRNULL); 110759243Sobrien } 110859243Sobrien *wp = 0; 110959243Sobrien (void) Strcat(wp, mp); 111059243Sobrien *adid = 1; 111159243Sobrien return (Strsave(wbuf)); 111259243Sobrien } 111359243Sobrien return (Strsave(cp)); 111459243Sobrien } 111559243Sobrien} 111659243Sobrien 111759243SobrienChar * 111859243Sobriendomod(cp, type) 111959243Sobrien Char *cp; 112059243Sobrien int type; 112159243Sobrien{ 112259243Sobrien Char *wp, *xp; 112359243Sobrien int c; 112459243Sobrien 112559243Sobrien switch (type) { 112659243Sobrien 112759243Sobrien case 'x': 112859243Sobrien case 'q': 112959243Sobrien wp = Strsave(cp); 113059243Sobrien for (xp = wp; (c = *xp) != 0; xp++) 113159243Sobrien if ((c != ' ' && c != '\t') || type == 'q') 113259243Sobrien *xp |= QUOTE; 113359243Sobrien return (wp); 113459243Sobrien 113559243Sobrien case 'l': 113659243Sobrien wp = Strsave(cp); 113759243Sobrien for (cp = wp; *cp; cp++) 113859243Sobrien if (Isupper(*cp)) { 113959243Sobrien *cp = Tolower(*cp); 114059243Sobrien return wp; 114159243Sobrien } 114259243Sobrien return wp; 114359243Sobrien 114459243Sobrien case 'u': 114559243Sobrien wp = Strsave(cp); 114659243Sobrien for (cp = wp; *cp; cp++) 114759243Sobrien if (Islower(*cp)) { 114859243Sobrien *cp = Toupper(*cp); 114959243Sobrien return wp; 115059243Sobrien } 115159243Sobrien return wp; 115259243Sobrien 115359243Sobrien case 'h': 115459243Sobrien case 't': 115559243Sobrien if (!any(short2str(cp), '/')) 115659243Sobrien return (type == 't' ? Strsave(cp) : 0); 115759243Sobrien wp = Strend(cp); 115859243Sobrien while (*--wp != '/') 115959243Sobrien continue; 116059243Sobrien if (type == 'h') 116159243Sobrien xp = Strsave(cp), xp[wp - cp] = 0; 116259243Sobrien else 116359243Sobrien xp = Strsave(wp + 1); 116459243Sobrien return (xp); 116559243Sobrien 116659243Sobrien case 'e': 116759243Sobrien case 'r': 116859243Sobrien wp = Strend(cp); 116959243Sobrien for (wp--; wp >= cp && *wp != '/'; wp--) 117059243Sobrien if (*wp == '.') { 117159243Sobrien if (type == 'e') 117259243Sobrien xp = Strsave(wp + 1); 117359243Sobrien else 117459243Sobrien xp = Strsave(cp), xp[wp - cp] = 0; 117559243Sobrien return (xp); 117659243Sobrien } 117759243Sobrien return (Strsave(type == 'e' ? STRNULL : cp)); 117859243Sobrien default: 117959243Sobrien break; 118059243Sobrien } 118159243Sobrien return (0); 118259243Sobrien} 118359243Sobrien 118459243Sobrienstatic int 118559243Sobrienmatchs(str, pat) 118659243Sobrien Char *str, *pat; 118759243Sobrien{ 118859243Sobrien while (*str && *pat && *str == *pat) 118959243Sobrien str++, pat++; 119059243Sobrien return (*pat == 0); 119159243Sobrien} 119259243Sobrien 119359243Sobrienstatic int 119459243Sobriengetsel(al, ar, dol) 119559243Sobrien int *al, *ar; 119659243Sobrien int dol; 119759243Sobrien{ 119859243Sobrien int c = getC(0); 119959243Sobrien int i; 120059243Sobrien bool first = *al < 0; 120159243Sobrien 120259243Sobrien switch (c) { 120359243Sobrien 120459243Sobrien case '%': 120559243Sobrien if (quesarg == -1) { 120659243Sobrien seterror(ERR_BADBANGARG); 120759243Sobrien return (0); 120859243Sobrien } 120959243Sobrien if (*al < 0) 121059243Sobrien *al = quesarg; 121159243Sobrien *ar = quesarg; 121259243Sobrien break; 121359243Sobrien 121459243Sobrien case '-': 121559243Sobrien if (*al < 0) { 121659243Sobrien *al = 0; 121759243Sobrien *ar = dol - 1; 121859243Sobrien unreadc(c); 121959243Sobrien } 122059243Sobrien return (1); 122159243Sobrien 122259243Sobrien case '^': 122359243Sobrien if (*al < 0) 122459243Sobrien *al = 1; 122559243Sobrien *ar = 1; 122659243Sobrien break; 122759243Sobrien 122859243Sobrien case '$': 122959243Sobrien if (*al < 0) 123059243Sobrien *al = dol; 123159243Sobrien *ar = dol; 123259243Sobrien break; 123359243Sobrien 123459243Sobrien case '*': 123559243Sobrien if (*al < 0) 123659243Sobrien *al = 1; 123759243Sobrien *ar = dol; 123859243Sobrien if (*ar < *al) { 123959243Sobrien *ar = 0; 124059243Sobrien *al = 1; 124159243Sobrien return (1); 124259243Sobrien } 124359243Sobrien break; 124459243Sobrien 124559243Sobrien default: 124659243Sobrien if (Isdigit(c)) { 124759243Sobrien i = 0; 124859243Sobrien while (Isdigit(c)) { 124959243Sobrien i = i * 10 + c - '0'; 125059243Sobrien c = getC(0); 125159243Sobrien } 125259243Sobrien if (i < 0) 125359243Sobrien i = dol + 1; 125459243Sobrien if (*al < 0) 125559243Sobrien *al = i; 125659243Sobrien *ar = i; 125759243Sobrien } 125859243Sobrien else if (*al < 0) 125959243Sobrien *al = 0, *ar = dol; 126059243Sobrien else 126159243Sobrien *ar = dol - 1; 126259243Sobrien unreadc(c); 126359243Sobrien break; 126459243Sobrien } 126559243Sobrien if (first) { 126659243Sobrien c = getC(0); 126759243Sobrien unreadc(c); 126859243Sobrien if (any("-$*", c)) 126959243Sobrien return (1); 127059243Sobrien } 127159243Sobrien if (*al > *ar || *ar > dol) { 127259243Sobrien seterror(ERR_BADBANGARG); 127359243Sobrien return (0); 127459243Sobrien } 127559243Sobrien return (1); 127659243Sobrien 127759243Sobrien} 127859243Sobrien 127959243Sobrienstatic struct wordent * 128059243Sobriengethent(sc) 128159243Sobrien int sc; 128259243Sobrien{ 128359243Sobrien struct Hist *hp; 128459243Sobrien Char *np; 128559243Sobrien int c; 128659243Sobrien int event; 128759243Sobrien bool back = 0; 128859243Sobrien 128959243Sobrien c = sc == HISTSUB ? HIST : getC(0); 129059243Sobrien if (c == HIST) { 129159243Sobrien if (alhistp) 129259243Sobrien return (alhistp); 129359243Sobrien event = eventno; 129459243Sobrien } 129559243Sobrien else 129659243Sobrien switch (c) { 129759243Sobrien 129859243Sobrien case ':': 129959243Sobrien case '^': 130059243Sobrien case '$': 130159243Sobrien case '*': 130259243Sobrien case '%': 130359243Sobrien ungetC(c); 130459243Sobrien if (lastev == eventno && alhistp) 130559243Sobrien return (alhistp); 130659243Sobrien event = lastev; 130759243Sobrien break; 130859243Sobrien 130959243Sobrien case '#': /* !# is command being typed in (mrh) */ 131059243Sobrien if (--hleft == 0) { 131159243Sobrien seterror(ERR_HISTLOOP); 131259243Sobrien return (0); 131359243Sobrien } 131459243Sobrien else 131559243Sobrien return (¶ml); 131659243Sobrien /* NOTREACHED */ 131759243Sobrien 131859243Sobrien case '-': 131959243Sobrien back = 1; 132059243Sobrien c = getC(0); 132159243Sobrien /* FALLSTHROUGH */ 132259243Sobrien 132359243Sobrien default: 132459243Sobrien if (any("(=~", c)) { 132559243Sobrien unreadc(c); 132659243Sobrien ungetC(HIST); 132759243Sobrien return (0); 132859243Sobrien } 132959243Sobrien np = lhsb; 133059243Sobrien event = 0; 133159243Sobrien while (!cmap(c, _ESC | _META | _QF | _QB) && !any("^*-%${}:#", c)) { 133259243Sobrien if (event != -1 && Isdigit(c)) 133359243Sobrien event = event * 10 + c - '0'; 133459243Sobrien else 133559243Sobrien event = -1; 133659243Sobrien if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) 133759243Sobrien *np++ = (Char) c; 133859243Sobrien c = getC(0); 133959243Sobrien } 134059243Sobrien unreadc(c); 134159243Sobrien if (np == lhsb) { 134259243Sobrien ungetC(HIST); 134359243Sobrien return (0); 134459243Sobrien } 134559243Sobrien *np++ = 0; 134659243Sobrien if (event != -1) { 134759243Sobrien /* 134859243Sobrien * History had only digits 134959243Sobrien */ 135059243Sobrien if (back) 135159243Sobrien event = eventno + (alhistp == 0) - (event ? event : 0); 135259243Sobrien break; 135359243Sobrien } 135459243Sobrien if (back) { 135559243Sobrien event = sizeof(lhsb) / sizeof(lhsb[0]); 135659243Sobrien np = &lhsb[--event]; 135759243Sobrien *np-- = '\0'; 135859243Sobrien for (event--; np > lhsb; *np-- = lhsb[--event]) 135959243Sobrien continue; 136059243Sobrien *np = '-'; 136159243Sobrien } 136259243Sobrien hp = findev(lhsb, 0); 136359243Sobrien if (hp) 136459243Sobrien lastev = hp->Hnum; 136559243Sobrien return (&hp->Hlex); 136659243Sobrien 136759243Sobrien case '?': 136859243Sobrien np = lhsb; 136959243Sobrien for (;;) { 137059243Sobrien c = getC(0); 137159243Sobrien if (c == '\n') { 137259243Sobrien unreadc(c); 137359243Sobrien break; 137459243Sobrien } 137559243Sobrien if (c == '?') 137659243Sobrien break; 137759243Sobrien if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) 137859243Sobrien *np++ = (Char) c; 137959243Sobrien } 138059243Sobrien if (np == lhsb) { 138159243Sobrien if (lhsb[0] == 0) { 138259243Sobrien seterror(ERR_NOSEARCH); 138359243Sobrien return (0); 138459243Sobrien } 138559243Sobrien } 138659243Sobrien else 138759243Sobrien *np++ = 0; 138859243Sobrien hp = findev(lhsb, 1); 138959243Sobrien if (hp) 139059243Sobrien lastev = hp->Hnum; 139159243Sobrien return (&hp->Hlex); 139259243Sobrien } 139359243Sobrien 139459243Sobrien for (hp = Histlist.Hnext; hp; hp = hp->Hnext) 139559243Sobrien if (hp->Hnum == event) { 139659243Sobrien hp->Href = eventno; 139759243Sobrien lastev = hp->Hnum; 139859243Sobrien return (&hp->Hlex); 139959243Sobrien } 140059243Sobrien np = putn(event); 140159243Sobrien seterror(ERR_NOEVENT, short2str(np)); 140259243Sobrien return (0); 140359243Sobrien} 140459243Sobrien 140559243Sobrienstatic struct Hist * 140659243Sobrienfindev(cp, anyarg) 140759243Sobrien Char *cp; 140859243Sobrien bool anyarg; 140959243Sobrien{ 141059243Sobrien struct Hist *hp; 141159243Sobrien 141259243Sobrien for (hp = Histlist.Hnext; hp; hp = hp->Hnext) { 141359243Sobrien Char *dp; 141459243Sobrien Char *p, *q; 141559243Sobrien struct wordent *lp = hp->Hlex.next; 141659243Sobrien int argno = 0; 141759243Sobrien 141859243Sobrien /* 141959243Sobrien * The entries added by alias substitution don't have a newline but do 142059243Sobrien * have a negative event number. Savehist() trims off these entries, 142159243Sobrien * but it happens before alias expansion, too early to delete those 142259243Sobrien * from the previous command. 142359243Sobrien */ 142459243Sobrien if (hp->Hnum < 0) 142559243Sobrien continue; 142659243Sobrien if (lp->word[0] == '\n') 142759243Sobrien continue; 142859243Sobrien if (!anyarg) { 142959243Sobrien p = cp; 143059243Sobrien q = lp->word; 143159243Sobrien do 143259243Sobrien if (!*p) 143359243Sobrien return (hp); 143459243Sobrien while (*p++ == *q++); 143559243Sobrien continue; 143659243Sobrien } 143759243Sobrien do { 143859243Sobrien for (dp = lp->word; *dp; dp++) { 143959243Sobrien p = cp; 144059243Sobrien q = dp; 144159243Sobrien do 144259243Sobrien if (!*p) { 144359243Sobrien quesarg = argno; 144459243Sobrien return (hp); 144559243Sobrien } 144659243Sobrien while (*p++ == *q++); 144759243Sobrien } 144859243Sobrien lp = lp->next; 144959243Sobrien argno++; 145059243Sobrien } while (lp->word[0] != '\n'); 145159243Sobrien } 145259243Sobrien seterror(ERR_NOEVENT, short2str(cp)); 145359243Sobrien return (0); 145459243Sobrien} 145559243Sobrien 145659243Sobrien 145759243Sobrienstatic void 145859243Sobriensetexclp(cp) 145959243Sobrien Char *cp; 146059243Sobrien{ 146159243Sobrien if (cp && cp[0] == '\n') 146259243Sobrien return; 146359243Sobrien exclp = cp; 146459243Sobrien} 146559243Sobrien 146659243Sobrienvoid 146759243Sobrienunreadc(c) 146859243Sobrien int c; 146959243Sobrien{ 147059243Sobrien peekread = (Char) c; 147159243Sobrien} 147259243Sobrien 147359243Sobrienint 147459243Sobrienreadc(wanteof) 147559243Sobrien bool wanteof; 147659243Sobrien{ 147759243Sobrien int c; 147859243Sobrien static int sincereal; /* Number of real EOFs we've seen */ 147959243Sobrien Char *ptr; /* For STRignoreeof */ 148059243Sobrien int numeof = 0; /* Value of STRignoreeof */ 148159243Sobrien 148259243Sobrien#ifdef DEBUG_INP 148359243Sobrien xprintf("readc\n"); 148459243Sobrien#endif 148559243Sobrien if ((c = peekread) != 0) { 148659243Sobrien peekread = 0; 148759243Sobrien return (c); 148859243Sobrien } 148959243Sobrien 149059243Sobrien /* Compute the value of EOFs */ 149159243Sobrien if ((ptr = varval(STRignoreeof)) != STRNULL) { 149259243Sobrien while (*ptr) { 149359243Sobrien if (!Isdigit(*ptr)) { 149459243Sobrien numeof = 0; 149559243Sobrien break; 149659243Sobrien } 149759243Sobrien numeof = numeof * 10 + *ptr++ - '0'; 149859243Sobrien } 1499100616Smp if (numeof != 0) 1500100616Smp numeof++; 150159243Sobrien } 1502100616Smp if (numeof < 0) numeof = 26; /* Sanity check */ 150359243Sobrien 150459243Sobrientop: 150569408Sache aret = TCSH_F_SEEK; 150659243Sobrien if (alvecp) { 150759243Sobrien arun = 1; 150859243Sobrien#ifdef DEBUG_INP 150959243Sobrien xprintf("alvecp %c\n", *alvecp & 0xff); 151059243Sobrien#endif 151169408Sache aret = TCSH_A_SEEK; 151259243Sobrien if ((c = *alvecp++) != 0) 151359243Sobrien return (c); 151459243Sobrien if (alvec && *alvec) { 151559243Sobrien alvecp = *alvec++; 151659243Sobrien return (' '); 151759243Sobrien } 151859243Sobrien else { 151959243Sobrien alvecp = NULL; 152069408Sache aret = TCSH_F_SEEK; 152159243Sobrien return('\n'); 152259243Sobrien } 152359243Sobrien } 152459243Sobrien if (alvec) { 152559243Sobrien arun = 1; 152659243Sobrien if ((alvecp = *alvec) != 0) { 152759243Sobrien alvec++; 152859243Sobrien goto top; 152959243Sobrien } 153059243Sobrien /* Infinite source! */ 153159243Sobrien return ('\n'); 153259243Sobrien } 153359243Sobrien arun = 0; 153459243Sobrien if (evalp) { 153569408Sache aret = TCSH_E_SEEK; 153659243Sobrien if ((c = *evalp++) != 0) 153759243Sobrien return (c); 153859243Sobrien if (evalvec && *evalvec) { 153959243Sobrien evalp = *evalvec++; 154059243Sobrien return (' '); 154159243Sobrien } 154269408Sache aret = TCSH_F_SEEK; 154359243Sobrien evalp = 0; 154459243Sobrien } 154559243Sobrien if (evalvec) { 154659243Sobrien if (evalvec == INVPPTR) { 154759243Sobrien doneinp = 1; 154859243Sobrien reset(); 154959243Sobrien } 155059243Sobrien if ((evalp = *evalvec) != 0) { 155159243Sobrien evalvec++; 155259243Sobrien goto top; 155359243Sobrien } 155459243Sobrien evalvec = INVPPTR; 155559243Sobrien return ('\n'); 155659243Sobrien } 155759243Sobrien do { 155859243Sobrien if (arginp == INVPTR || onelflg == 1) { 155959243Sobrien if (wanteof) 156059243Sobrien return (-1); 156159243Sobrien exitstat(); 156259243Sobrien } 156359243Sobrien if (arginp) { 156459243Sobrien if ((c = *arginp++) == 0) { 156559243Sobrien arginp = INVPTR; 156659243Sobrien return ('\n'); 156759243Sobrien } 156859243Sobrien return (c); 156959243Sobrien } 157059243Sobrien#ifdef BSDJOBS 157159243Sobrienreread: 157259243Sobrien#endif /* BSDJOBS */ 157359243Sobrien c = bgetc(); 157459243Sobrien if (c < 0) { 157569408Sache#ifndef WINNT_NATIVE 157659243Sobrien# ifndef POSIX 157759243Sobrien# ifdef TERMIO 157859243Sobrien struct termio tty; 157959243Sobrien# else /* SGTTYB */ 158059243Sobrien struct sgttyb tty; 158159243Sobrien# endif /* TERMIO */ 158259243Sobrien# else /* POSIX */ 158359243Sobrien struct termios tty; 158459243Sobrien# endif /* POSIX */ 158569408Sache#endif /* !WINNT_NATIVE */ 158659243Sobrien if (wanteof) 158759243Sobrien return (-1); 158859243Sobrien /* was isatty but raw with ignoreeof yields problems */ 158969408Sache#ifndef WINNT_NATIVE 159059243Sobrien# ifndef POSIX 159159243Sobrien# ifdef TERMIO 159259243Sobrien if (ioctl(SHIN, TCGETA, (ioctl_t) & tty) == 0 && 159359243Sobrien (tty.c_lflag & ICANON)) 159459243Sobrien# else /* GSTTYB */ 159559243Sobrien if (ioctl(SHIN, TIOCGETP, (ioctl_t) & tty) == 0 && 159659243Sobrien (tty.sg_flags & RAW) == 0) 159759243Sobrien# endif /* TERMIO */ 159859243Sobrien# else /* POSIX */ 159959243Sobrien if (tcgetattr(SHIN, &tty) == 0 && 160059243Sobrien (tty.c_lflag & ICANON)) 160159243Sobrien# endif /* POSIX */ 160269408Sache#else /* WINNT_NATIVE */ 160359243Sobrien if (isatty(SHIN)) 160469408Sache#endif /* !WINNT_NATIVE */ 160559243Sobrien { 160659243Sobrien#ifdef BSDJOBS 160759243Sobrien int ctpgrp; 160859243Sobrien#endif /* BSDJOBS */ 160959243Sobrien 1610100616Smp if (numeof != 0 && ++sincereal >= numeof) /* Too many EOFs? Bye! */ 161159243Sobrien goto oops; 161259243Sobrien#ifdef BSDJOBS 161359243Sobrien if (tpgrp != -1 && 161459243Sobrien (ctpgrp = tcgetpgrp(FSHTTY)) != -1 && 161559243Sobrien tpgrp != ctpgrp) { 161659243Sobrien (void) tcsetpgrp(FSHTTY, tpgrp); 161759243Sobrien# ifdef _SEQUENT_ 161859243Sobrien if (ctpgrp) 161959243Sobrien# endif /* _SEQUENT */ 162059243Sobrien (void) killpg((pid_t) ctpgrp, SIGHUP); 162159243Sobrien# ifdef notdef 162259243Sobrien /* 162359243Sobrien * With the walking process group fix, this message 162459243Sobrien * is now obsolete. As the foreground process group 162559243Sobrien * changes, the shell needs to adjust. Well too bad. 162659243Sobrien */ 162759243Sobrien xprintf(CGETS(16, 1, "Reset tty pgrp from %d to %d\n"), 162859243Sobrien ctpgrp, tpgrp); 162959243Sobrien# endif /* notdef */ 163059243Sobrien goto reread; 163159243Sobrien } 163259243Sobrien#endif /* BSDJOBS */ 163359243Sobrien /* What follows is complicated EOF handling -- sterling@netcom.com */ 163459243Sobrien /* First, we check to see if we have ignoreeof set */ 163559243Sobrien if (adrof(STRignoreeof)) { 163659243Sobrien /* If so, we check for any stopped jobs only on the first EOF */ 163759243Sobrien if ((sincereal == 1) && (chkstop == 0)) { 163859243Sobrien panystop(1); 163959243Sobrien } 164059243Sobrien } else { 164159243Sobrien /* If we don't have ignoreeof set, always check for stopped jobs */ 164259243Sobrien if (chkstop == 0) { 164359243Sobrien panystop(1); 164459243Sobrien } 164559243Sobrien } 164659243Sobrien /* At this point, if there were stopped jobs, we would have already 164759243Sobrien * called reset(). If we got this far, assume we can print an 164859243Sobrien * exit/logout message if we ignoreeof, or just exit. 164959243Sobrien */ 165059243Sobrien if (adrof(STRignoreeof)) { 165159243Sobrien /* If so, tell the user to use exit or logout */ 165259243Sobrien if (loginsh) { 165359243Sobrien xprintf(CGETS(16, 2, 165459243Sobrien "\nUse \"logout\" to logout.\n")); 165559243Sobrien } else { 165659243Sobrien xprintf(CGETS(16, 3, 165759243Sobrien "\nUse \"exit\" to leave %s.\n"), 165859243Sobrien progname); 165959243Sobrien } 166059243Sobrien reset(); 166159243Sobrien } else { 166259243Sobrien /* If we don't have ignoreeof set, just fall through */ 166359243Sobrien ; /* EMPTY */ 166459243Sobrien } 166559243Sobrien } 166659243Sobrien oops: 166759243Sobrien doneinp = 1; 166859243Sobrien reset(); 166959243Sobrien } 167059243Sobrien sincereal = 0; 167159243Sobrien if (c == '\n' && onelflg) 167259243Sobrien onelflg--; 167359243Sobrien } while (c == 0); 167459243Sobrien if (histlinep < histline + BUFSIZE) 167559243Sobrien *histlinep++ = (Char) c; 167659243Sobrien return (c); 167759243Sobrien} 167859243Sobrien 167959243Sobrienstatic void 168059243Sobrienballoc(buf) 168159243Sobrien int buf; 168259243Sobrien{ 168359243Sobrien Char **nfbuf; 168459243Sobrien 168559243Sobrien while (buf >= fblocks) { 168659243Sobrien nfbuf = (Char **) xcalloc((size_t) (fblocks + 2), 168759243Sobrien sizeof(Char **)); 168859243Sobrien if (fbuf) { 168959243Sobrien (void) blkcpy(nfbuf, fbuf); 169059243Sobrien xfree((ptr_t) fbuf); 169159243Sobrien } 169259243Sobrien fbuf = nfbuf; 169359243Sobrien fbuf[fblocks] = (Char *) xcalloc(BUFSIZE, sizeof(Char)); 169459243Sobrien fblocks++; 169559243Sobrien } 169659243Sobrien} 169759243Sobrien 169859243Sobrienstatic int 169959243Sobrienbgetc() 170059243Sobrien{ 170159243Sobrien int c, off, buf; 170259243Sobrien int numleft = 0, roomleft; 170359243Sobrien char tbuf[BUFSIZE + 1]; 170459243Sobrien 170559243Sobrien if (cantell) { 170659243Sobrien if (fseekp < fbobp || fseekp > feobp) { 170759243Sobrien fbobp = feobp = fseekp; 170859243Sobrien (void) lseek(SHIN, fseekp, L_SET); 170959243Sobrien } 171059243Sobrien if (fseekp == feobp) { 171159243Sobrien int i; 171259243Sobrien 171359243Sobrien fbobp = feobp; 171459243Sobrien do 171559243Sobrien c = read(SHIN, tbuf, BUFSIZE); 171659243Sobrien while (c < 0 && errno == EINTR); 171759243Sobrien#ifdef convex 171859243Sobrien if (c < 0) 171959243Sobrien stderror(ERR_SYSTEM, progname, strerror(errno)); 172059243Sobrien#endif /* convex */ 172159243Sobrien if (c <= 0) 172259243Sobrien return (-1); 172359243Sobrien for (i = 0; i < c; i++) 172459243Sobrien fbuf[0][i] = (unsigned char) tbuf[i]; 172559243Sobrien feobp += c; 172659243Sobrien } 172769408Sache#ifndef WINNT_NATIVE 172859243Sobrien c = fbuf[0][fseekp - fbobp]; 172959243Sobrien fseekp++; 173059243Sobrien#else 173159243Sobrien do { 173259243Sobrien c = fbuf[0][fseekp - fbobp]; 173359243Sobrien fseekp++; 173459243Sobrien } while(c == '\r'); 173569408Sache#endif /* !WINNT_NATIVE */ 173659243Sobrien return (c); 173759243Sobrien } 173859243Sobrien 173959243Sobrien while (fseekp >= feobp) { 1740100616Smp if ((editing 1741100616Smp#if defined(FILEC) && defined(TIOCSTI) 1742100616Smp || filec 1743100616Smp#endif /* FILEC && TIOCSTI */ 1744100616Smp ) && intty) { /* then use twenex routine */ 174559243Sobrien fseekp = feobp; /* where else? */ 1746100616Smp#if defined(FILEC) && defined(TIOCSTI) 1747100616Smp if (!editing) 1748100616Smp c = numleft = tenex(InputBuf, BUFSIZE); 1749100616Smp else 1750100616Smp#endif /* FILEC && TIOCSTI */ 175159243Sobrien c = numleft = Inputl(); /* PWP: get a line */ 175259243Sobrien while (numleft > 0) { 175359243Sobrien off = (int) feobp % BUFSIZE; 175459243Sobrien buf = (int) feobp / BUFSIZE; 175559243Sobrien balloc(buf); 175659243Sobrien roomleft = BUFSIZE - off; 175759243Sobrien if (roomleft > numleft) 175859243Sobrien roomleft = numleft; 1759100616Smp (void) memmove((ptr_t) (fbuf[buf] + off), 1760100616Smp (ptr_t) (InputBuf + c - numleft), 1761100616Smp (size_t) (roomleft * sizeof(Char))); 176259243Sobrien numleft -= roomleft; 176359243Sobrien feobp += roomleft; 176459243Sobrien } 1765100616Smp } else { 176659243Sobrien off = (int) feobp % BUFSIZE; 176759243Sobrien buf = (int) feobp / BUFSIZE; 176859243Sobrien balloc(buf); 176959243Sobrien roomleft = BUFSIZE - off; 177059243Sobrien c = read(SHIN, tbuf, (size_t) roomleft); 177159243Sobrien if (c > 0) { 177259243Sobrien int i; 177359243Sobrien Char *ptr = fbuf[buf] + off; 177459243Sobrien 177559243Sobrien for (i = 0; i < c; i++) 177659243Sobrien ptr[i] = (unsigned char) tbuf[i]; 177759243Sobrien feobp += c; 177859243Sobrien } 177959243Sobrien } 178059243Sobrien if (c == 0 || (c < 0 && fixio(SHIN, errno) == -1)) 178159243Sobrien return (-1); 178259243Sobrien } 178369408Sache#ifndef WINNT_NATIVE 178459243Sobrien c = fbuf[(int) fseekp / BUFSIZE][(int) fseekp % BUFSIZE]; 178559243Sobrien fseekp++; 178659243Sobrien#else 178759243Sobrien do { 178859243Sobrien c = fbuf[(int) fseekp / BUFSIZE][(int) fseekp % BUFSIZE]; 178959243Sobrien fseekp++; 179059243Sobrien } while(c == '\r'); 179169408Sache#endif /* !WINNT_NATIVE */ 179259243Sobrien return (c); 179359243Sobrien} 179459243Sobrien 179559243Sobrienstatic void 179659243Sobrienbfree() 179759243Sobrien{ 179859243Sobrien int sb, i; 179959243Sobrien 180059243Sobrien if (cantell) 180159243Sobrien return; 180259243Sobrien if (whyles) 180359243Sobrien return; 180459243Sobrien sb = (int) (fseekp - 1) / BUFSIZE; 180559243Sobrien if (sb > 0) { 180659243Sobrien for (i = 0; i < sb; i++) 180759243Sobrien xfree((ptr_t) fbuf[i]); 180859243Sobrien (void) blkcpy(fbuf, &fbuf[sb]); 180959243Sobrien fseekp -= BUFSIZE * sb; 181059243Sobrien feobp -= BUFSIZE * sb; 181159243Sobrien fblocks -= sb; 181259243Sobrien } 181359243Sobrien} 181459243Sobrien 181559243Sobrienvoid 181659243Sobrienbseek(l) 181759243Sobrien struct Ain *l; 181859243Sobrien{ 181959243Sobrien switch (aret = l->type) { 182069408Sache case TCSH_E_SEEK: 182159243Sobrien evalvec = l->a_seek; 182259243Sobrien evalp = l->c_seek; 182359243Sobrien#ifdef DEBUG_SEEK 182459243Sobrien xprintf(CGETS(16, 4, "seek to eval %x %x\n"), evalvec, evalp); 182559243Sobrien#endif 182659243Sobrien return; 182769408Sache case TCSH_A_SEEK: 182859243Sobrien alvec = l->a_seek; 182959243Sobrien alvecp = l->c_seek; 183059243Sobrien#ifdef DEBUG_SEEK 183159243Sobrien xprintf(CGETS(16, 5, "seek to alias %x %x\n"), alvec, alvecp); 183259243Sobrien#endif 183359243Sobrien return; 183469408Sache case TCSH_F_SEEK: 183559243Sobrien#ifdef DEBUG_SEEK 183659243Sobrien xprintf(CGETS(16, 6, "seek to file %x\n"), fseekp); 183759243Sobrien#endif 183859243Sobrien fseekp = l->f_seek; 183959243Sobrien return; 184059243Sobrien default: 184159243Sobrien xprintf(CGETS(16, 7, "Bad seek type %d\n"), aret); 184259243Sobrien abort(); 184359243Sobrien } 184459243Sobrien} 184559243Sobrien 184659243Sobrien/* any similarity to bell telephone is purely accidental */ 184759243Sobrienvoid 184859243Sobrienbtell(l) 184959243Sobrienstruct Ain *l; 185059243Sobrien{ 185159243Sobrien switch (l->type = aret) { 185269408Sache case TCSH_E_SEEK: 185359243Sobrien l->a_seek = evalvec; 185459243Sobrien l->c_seek = evalp; 185559243Sobrien#ifdef DEBUG_SEEK 185659243Sobrien xprintf(CGETS(16, 8, "tell eval %x %x\n"), evalvec, evalp); 185759243Sobrien#endif 185859243Sobrien return; 185969408Sache case TCSH_A_SEEK: 186059243Sobrien l->a_seek = alvec; 186159243Sobrien l->c_seek = alvecp; 186259243Sobrien#ifdef DEBUG_SEEK 186359243Sobrien xprintf(CGETS(16, 9, "tell alias %x %x\n"), alvec, alvecp); 186459243Sobrien#endif 186559243Sobrien return; 186669408Sache case TCSH_F_SEEK: 186759243Sobrien /*SUPPRESS 112*/ 186859243Sobrien l->f_seek = fseekp; 186959243Sobrien l->a_seek = NULL; 187059243Sobrien#ifdef DEBUG_SEEK 187159243Sobrien xprintf(CGETS(16, 10, "tell file %x\n"), fseekp); 187259243Sobrien#endif 187359243Sobrien return; 187459243Sobrien default: 187559243Sobrien xprintf(CGETS(16, 7, "Bad seek type %d\n"), aret); 187659243Sobrien abort(); 187759243Sobrien } 187859243Sobrien} 187959243Sobrien 188059243Sobrienvoid 188159243Sobrienbtoeof() 188259243Sobrien{ 188359243Sobrien (void) lseek(SHIN, (off_t) 0, L_XTND); 188469408Sache aret = TCSH_F_SEEK; 188559243Sobrien fseekp = feobp; 188659243Sobrien alvec = NULL; 188759243Sobrien alvecp = NULL; 188859243Sobrien evalvec = NULL; 188959243Sobrien evalp = NULL; 189059243Sobrien wfree(); 189159243Sobrien bfree(); 189259243Sobrien} 189359243Sobrien 189459243Sobrienvoid 189559243Sobriensettell() 189659243Sobrien{ 189759243Sobrien off_t x; 189859243Sobrien cantell = 0; 189959243Sobrien if (arginp || onelflg || intty) 190059243Sobrien return; 190159243Sobrien if ((x = lseek(SHIN, (off_t) 0, L_INCR)) == -1) 190259243Sobrien return; 190359243Sobrien fbuf = (Char **) xcalloc(2, sizeof(Char **)); 190459243Sobrien fblocks = 1; 190559243Sobrien fbuf[0] = (Char *) xcalloc(BUFSIZE, sizeof(Char)); 190659243Sobrien fseekp = fbobp = feobp = x; 190759243Sobrien cantell = 1; 190859243Sobrien} 1909