⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lex.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * Copyright (c) 1980, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)lex.c	8.1 (Berkeley) 5/31/93";#endif /* not lint */#include <sys/types.h>#include <sys/ioctl.h>#include <termios.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#if __STDC__# include <stdarg.h>#else# include <varargs.h>#endif#include "csh.h"#include "extern.h"/* * These lexical routines read input and form lists of words. * There is some involved processing here, because of the complications * of input buffering, and especially because of history substitution. */static Char	*word __P((void));static int	 getC1 __P((int));static void	 getdol __P((void));static void	 getexcl __P((int));static struct Hist		*findev __P((Char *, bool));static void	 setexclp __P((Char *));static int	 bgetc __P((void));static void	 bfree __P((void));static struct wordent		*gethent __P((int));static int	 matchs __P((Char *, Char *));static int	 getsel __P((int *, int *, int));static struct wordent		*getsub __P((struct wordent *));static Char	*subword __P((Char *, int, bool *));static struct wordent		*dosub __P((int, struct wordent *, bool));/* * Peekc is a peek character for getC, peekread for readc. * There is a subtlety here in many places... history routines * will read ahead and then insert stuff into the input stream. * If they push back a character then they must push it behind * the text substituted by the history substitution.  On the other * hand in several places we need 2 peek characters.  To make this * all work, the history routines read with getC, and make use both * of ungetC and unreadc.  The key observation is that the state * of getC at the call of a history reference is such that calls * to getC from the history routines will always yield calls of * readc, unless this peeking is involved.  That is to say that during * getexcl the variables lap, exclp, and exclnxt are all zero. * * Getdol invokes history substitution, hence the extra peek, peekd, * which it can ungetD to be before history substitutions. */static Char peekc = 0, peekd = 0;static Char peekread = 0;/* (Tail of) current word from ! subst */static Char *exclp = NULL;/* The rest of the ! subst words */static struct wordent *exclnxt = NULL;/* Count of remaining words in ! subst */static int exclc = 0;/* "Globp" for alias resubstitution */Char *alvecp = NULL;int aret = F_SEEK;/* * Labuf implements a general buffer for lookahead during lexical operations. * Text which is to be placed in the input stream can be stuck here. * We stick parsed ahead $ constructs during initial input, * process id's from `$$', and modified variable values (from qualifiers * during expansion in sh.dol.c) here. */static Char labuf[BUFSIZ];/* * Lex returns to its caller not only a wordlist (as a "var" parameter) * but also whether a history substitution occurred.  This is used in * the main (process) routine to determine whether to echo, and also * when called by the alias routine to determine whether to keep the * argument list. */static bool hadhist = 0;/* * Avoid alias expansion recursion via \!# */int     hleft;static Char getCtmp;#define getC(f)		((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f))#define	ungetC(c)	peekc = c#define	ungetD(c)	peekd = cintlex(hp)    register struct wordent *hp;{    register struct wordent *wdp;    int     c;    btell(&lineloc);    hp->next = hp->prev = hp;    hp->word = STRNULL;    hadhist = 0;    do	c = readc(0);    while (c == ' ' || c == '\t');    if (c == HISTSUB && intty)	/* ^lef^rit	from tty is short !:s^lef^rit */	getexcl(c);    else	unreadc(c);    wdp = hp;    /*     * The following loop is written so that the links needed by freelex will     * be ready and rarin to go even if it is interrupted.     */    do {	register struct wordent *new;	new = (struct wordent *) xmalloc((size_t) sizeof(*wdp));	new->word = 0;	new->prev = wdp;	new->next = hp;	wdp->next = new;	wdp = new;	wdp->word = word();    } while (wdp->word[0] != '\n');    hp->prev = wdp;    return (hadhist);}voidprlex(fp, sp0)    FILE *fp;    struct wordent *sp0;{    register struct wordent *sp = sp0->next;    for (;;) {	(void) fprintf(fp, "%s", vis_str(sp->word));	sp = sp->next;	if (sp == sp0)	    break;	if (sp->word[0] != '\n')	    (void) fputc(' ', fp);    }}voidcopylex(hp, fp)    register struct wordent *hp;    register struct wordent *fp;{    register struct wordent *wdp;    wdp = hp;    fp = fp->next;    do {	register struct wordent *new;	new = (struct wordent *) xmalloc((size_t) sizeof(*wdp));	new->prev = wdp;	new->next = hp;	wdp->next = new;	wdp = new;	wdp->word = Strsave(fp->word);	fp = fp->next;    } while (wdp->word[0] != '\n');    hp->prev = wdp;}voidfreelex(vp)    register struct wordent *vp;{    register struct wordent *fp;    while (vp->next != vp) {	fp = vp->next;	vp->next = fp->next;	xfree((ptr_t) fp->word);	xfree((ptr_t) fp);    }    vp->prev = vp;}static Char *word(){    register Char c, c1;    register Char *wp;    Char    wbuf[BUFSIZ];    register bool dolflg;    register int i;    wp = wbuf;    i = BUFSIZ - 4;loop:    while ((c = getC(DOALL)) == ' ' || c == '\t')	continue;    if (cmap(c, _META | _ESC))	switch (c) {	case '&':	case '|':	case '<':	case '>':	    *wp++ = c;	    c1 = getC(DOALL);	    if (c1 == c)		*wp++ = c1;	    else		ungetC(c1);	    goto ret;	case '#':	    if (intty)		break;	    c = 0;	    do {		c1 = c;		c = getC(0);	    } while (c != '\n');	    if (c1 == '\\')		goto loop;	    /* fall into ... */	case ';':	case '(':	case ')':	case '\n':	    *wp++ = c;	    goto ret;	case '\\':	    c = getC(0);	    if (c == '\n') {		if (onelflg == 1)		    onelflg = 2;		goto loop;	    }	    if (c != HIST)		*wp++ = '\\', --i;	    c |= QUOTE;	}    c1 = 0;    dolflg = DOALL;    for (;;) {	if (c1) {	    if (c == c1) {		c1 = 0;		dolflg = DOALL;	    }	    else if (c == '\\') {		c = getC(0);		if (c == HIST)		    c |= QUOTE;		else {		    if (c == '\n')			/*			 * if (c1 == '`') c = ' '; else			 */			c |= QUOTE;		    ungetC(c);		    c = '\\';		}	    }	    else if (c == '\n') {		seterror(ERR_UNMATCHED, c1);		ungetC(c);		break;	    }	}	else if (cmap(c, _META | _QF | _QB | _ESC)) {	    if (c == '\\') {		c = getC(0);		if (c == '\n') {		    if (onelflg == 1)			onelflg = 2;		    break;		}		if (c != HIST)		    *wp++ = '\\', --i;		c |= QUOTE;	    }	    else if (cmap(c, _QF | _QB)) {	/* '"` */		c1 = c;		dolflg = c == '"' ? DOALL : DOEXCL;	    }	    else if (c != '#' || !intty) {		ungetC(c);		break;	    }	}	if (--i > 0) {	    *wp++ = c;	    c = getC(dolflg);	}	else {	    seterror(ERR_WTOOLONG);	    wp = &wbuf[1];	    break;	}    }ret:    *wp = 0;    return (Strsave(wbuf));}static intgetC1(flag)    register int flag;{    register Char c;    while (1) {	if ((c = peekc) != '\0') {	    peekc = 0;	    return (c);	}	if (lap) {	    if ((c = *lap++) == 0)		lap = 0;	    else {		if (cmap(c, _META | _QF | _QB))		    c |= QUOTE;		return (c);	    }	}	if ((c = peekd) != '\0') {	    peekd = 0;	    return (c);	}	if (exclp) {	    if ((c = *exclp++) != '\0')		return (c);	    if (exclnxt && --exclc >= 0) {		exclnxt = exclnxt->next;		setexclp(exclnxt->word);		return (' ');	    }	    exclp = 0;	    exclnxt = 0;	}	if (exclnxt) {	    exclnxt = exclnxt->next;	    if (--exclc < 0)		exclnxt = 0;	    else		setexclp(exclnxt->word);	    continue;	}	c = readc(0);	if (c == '$' && (flag & DODOL)) {	    getdol();	    continue;	}	if (c == HIST && (flag & DOEXCL)) {	    getexcl(0);	    continue;	}	break;    }    return (c);}static voidgetdol(){    register Char *np, *ep;    Char    name[4 * MAXVARLEN + 1];    register int c;    int     sc;    bool    special = 0, toolong;    np = name, *np++ = '$';    c = sc = getC(DOEXCL);    if (any("\t \n", c)) {	ungetD(c);	ungetC('$' | QUOTE);	return;    }    if (c == '{')	*np++ = c, c = getC(DOEXCL);    if (c == '#' || c == '?')	special++, *np++ = c, c = getC(DOEXCL);    *np++ = c;    switch (c) {    case '<':    case '$':    case '!':	if (special)	    seterror(ERR_SPDOLLT);	*np = 0;	addla(name);	return;    case '\n':	ungetD(c);	np--;	seterror(ERR_NEWLINE);	*np = 0;	addla(name);	return;    case '*':	if (special)	    seterror(ERR_SPSTAR);	*np = 0;	addla(name);	return;    default:	toolong = 0;	if (Isdigit(c)) {#ifdef notdef	    /* let $?0 pass for now */	    if (special) {		seterror(ERR_DIGIT);		*np = 0;		addla(name);		return;	    }#endif	    /* we know that np < &name[4] */	    ep = &np[MAXVARLEN];	    while ((c = getC(DOEXCL)) != '\0'){		if (!Isdigit(c))		    break;		if (np < ep)		    *np++ = c;		else		    toolong = 1;	    }	}	else if (letter(c)) {	    /* we know that np < &name[4] */	    ep = &np[MAXVARLEN];	    toolong = 0;	    while ((c = getC(DOEXCL)) != '\0') {		/* Bugfix for ${v123x} from Chris Torek, DAS DEC-90. */		if (!letter(c) && !Isdigit(c))		    break;		if (np < ep)		    *np++ = c;		else		    toolong = 1;	    }	}	else {	    *np = 0;	    seterror(ERR_VARILL);	    addla(name);	    return;	}	if (toolong) {	    seterror(ERR_VARTOOLONG);	    *np = 0;	    addla(name);	    return;	}	break;    }    if (c == '[') {	*np++ = c;	/*	 * Name up to here is a max of MAXVARLEN + 8.	 */	ep = &np[2 * MAXVARLEN + 8];	do {	    /*	     * Michael Greim: Allow $ expansion to take place in selector	     * expressions. (limits the number of characters returned)	     */	    c = getC(DOEXCL | DODOL);	    if (c == '\n') {		ungetD(c);		np--;		seterror(ERR_NLINDEX);		*np = 0;		addla(name);		return;	    }	    if (np < ep)		*np++ = c;	} while (c != ']');	*np = '\0';	if (np >= ep) {	    seterror(ERR_SELOVFL);	    addla(name);	    return;	}	c = getC(DOEXCL);    }    /*     * Name up to here is a max of 2 * MAXVARLEN + 8.     */    if (c == ':') {	/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -