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

📄 dol.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * 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[] = "@(#)dol.c	8.1 (Berkeley) 5/31/93";#endif /* not lint */#include <sys/types.h>#include <fcntl.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 routines perform variable substitution and quoting via ' and ". * To this point these constructs have been preserved in the divided * input words.  Here we expand variables and turn quoting via ' and " into * QUOTE bits on characters (which prevent further interpretation). * If the `:q' modifier was applied during history expansion, then * some QUOTEing may have occurred already, so we dont "trim()" here. */static int Dpeekc, Dpeekrd;	/* Peeks for DgetC and Dreadc */static Char *Dcp, **Dvp;	/* Input vector for Dreadc */#define	DEOF	-1#define	unDgetC(c)	Dpeekc = c#define QUOTES		(_QF|_QB|_ESC)	/* \ ' " ` *//* * The following variables give the information about the current * $ expansion, recording the current word position, the remaining * words within this expansion, the count of remaining words, and the * information about any : modifier which is being applied. */#define MAXWLEN (BUFSIZ - 4)#define MAXMOD MAXWLEN		/* This cannot overflow	*/static Char *dolp;		/* Remaining chars from this word */static Char **dolnxt;		/* Further words */static int dolcnt;		/* Count of further words */static Char dolmod[MAXMOD];	/* : modifier character */static int dolnmod;		/* Number of modifiers */static int dolmcnt;		/* :gx -> 10000, else 1 */static int dolwcnt;		/* :wx -> 10000, else 1 */static void	 Dfix2 __P((Char **));static Char	*Dpack __P((Char *, Char *));static int	 Dword __P((void));static void	 dolerror __P((Char *));static int	 DgetC __P((int));static void	 Dgetdol __P((void));static void	 fixDolMod __P((void));static void	 setDolp __P((Char *));static void	 unDredc __P((int));static int	 Dredc __P((void));static void	 Dtestq __P((int));/* * Fix up the $ expansions and quotations in the * argument list to command t. */voidDfix(t)    register struct command *t;{    register Char **pp;    register Char *p;    if (noexec)	return;    /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */    for (pp = t->t_dcom; (p = *pp++) != NULL;)	for (; *p; p++) {	    if (cmap(*p, _DOL | QUOTES)) {	/* $, \, ', ", ` */		Dfix2(t->t_dcom);	/* found one */		blkfree(t->t_dcom);		t->t_dcom = gargv;		gargv = 0;		return;	    }	}}/* * $ substitute one word, for i/o redirection */Char   *Dfix1(cp)    register Char *cp;{    Char   *Dv[2];    if (noexec)	return (0);    Dv[0] = cp;    Dv[1] = NULL;    Dfix2(Dv);    if (gargc != 1) {	setname(vis_str(cp));	stderror(ERR_NAME | ERR_AMBIG);    }    cp = Strsave(gargv[0]);    blkfree(gargv), gargv = 0;    return (cp);}/* * Subroutine to do actual fixing after state initialization. */static voidDfix2(v)    Char  **v;{    ginit();			/* Initialize glob's area pointers */    Dvp = v;    Dcp = STRNULL;		/* Setup input vector for Dreadc */    unDgetC(0);    unDredc(0);			/* Clear out any old peeks (at error) */    dolp = 0;    dolcnt = 0;			/* Clear out residual $ expands (...) */    while (Dword())	continue;}/* * Pack up more characters in this word */static Char *Dpack(wbuf, wp)    Char   *wbuf, *wp;{    register int c;    register int i = MAXWLEN - (wp - wbuf);    for (;;) {	c = DgetC(DODOL);	if (c == '\\') {	    c = DgetC(0);	    if (c == DEOF) {		unDredc(c);		*wp = 0;		Gcat(STRNULL, wbuf);		return (NULL);	    }	    if (c == '\n')		c = ' ';	    else		c |= QUOTE;	}	if (c == DEOF) {	    unDredc(c);	    *wp = 0;	    Gcat(STRNULL, wbuf);	    return (NULL);	}	if (cmap(c, _SP | _NL | _QF | _QB)) {	/* sp \t\n'"` */	    unDgetC(c);	    if (cmap(c, QUOTES))		return (wp);	    *wp++ = 0;	    Gcat(STRNULL, wbuf);	    return (NULL);	}	if (--i <= 0)	    stderror(ERR_WTOOLONG);	*wp++ = c;    }}/* * Get a word.  This routine is analogous to the routine * word() in sh.lex.c for the main lexical input.  One difference * here is that we don't get a newline to terminate our expansion. * Rather, DgetC will return a DEOF when we hit the end-of-input. */static intDword(){    register int c, c1;    Char    wbuf[BUFSIZ];    register Char *wp = wbuf;    register int i = MAXWLEN;    register bool dolflg;    bool    sofar = 0, done = 0;    while (!done) {	done = 1;	c = DgetC(DODOL);	switch (c) {	case DEOF:	    if (sofar == 0)		return (0);	    /* finish this word and catch the code above the next time */	    unDredc(c);	    /* fall into ... */	case '\n':	    *wp = 0;	    Gcat(STRNULL, wbuf);	    return (1);	case ' ':	case '\t':	    done = 0;	    break;	case '`':	    /* We preserve ` quotations which are done yet later */	    *wp++ = c, --i;	case '\'':	case '"':	    /*	     * Note that DgetC never returns a QUOTES character from an	     * expansion, so only true input quotes will get us here or out.	     */	    c1 = c;	    dolflg = c1 == '"' ? DODOL : 0;	    for (;;) {		c = DgetC(dolflg);		if (c == c1)		    break;		if (c == '\n' || c == DEOF)		    stderror(ERR_UNMATCHED, c1);		if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE))		    --wp, ++i;		if (--i <= 0)		    stderror(ERR_WTOOLONG);		switch (c1) {		case '"':		    /*		     * Leave any `s alone for later. Other chars are all		     * quoted, thus `...` can tell it was within "...".		     */		    *wp++ = c == '`' ? '`' : c | QUOTE;		    break;		case '\'':		    /* Prevent all further interpretation */		    *wp++ = c | QUOTE;		    break;		case '`':		    /* Leave all text alone for later */		    *wp++ = c;		    break;		default:		    break;		}	    }	    if (c1 == '`')		*wp++ = '`' /* i--; eliminated */;	    sofar = 1;	    if ((wp = Dpack(wbuf, wp)) == NULL)		return (1);	    else {		i = MAXWLEN - (wp - wbuf);		done = 0;	    }	    break;	case '\\':	    c = DgetC(0);	/* No $ subst! */	    if (c == '\n' || c == DEOF) {		done = 0;		break;	    }	    c |= QUOTE;	    break;	default:	    break;	}	if (done) {	    unDgetC(c);	    sofar = 1;	    if ((wp = Dpack(wbuf, wp)) == NULL)		return (1);	    else {		i = MAXWLEN - (wp - wbuf);		done = 0;	    }	}    }    /* Really NOTREACHED */    return (0);}/* * Get a character, performing $ substitution unless flag is 0. * Any QUOTES character which is returned from a $ expansion is * QUOTEd so that it will not be recognized above. */static intDgetC(flag)    register int flag;{    register int c;top:    if ((c = Dpeekc) != '\0') {	Dpeekc = 0;	return (c);    }    if (lap) {	c = *lap++ & (QUOTE | TRIM);	if (c == 0) {	    lap = 0;	    goto top;	}quotspec:	if (cmap(c, QUOTES))	    return (c | QUOTE);	return (c);    }    if (dolp) {	if ((c = *dolp++ & (QUOTE | TRIM)) != '\0')	    goto quotspec;	if (dolcnt > 0) {	    setDolp(*dolnxt++);	    --dolcnt;	    return (' ');	}	dolp = 0;    }    if (dolcnt > 0) {	setDolp(*dolnxt++);	--dolcnt;	goto top;    }    c = Dredc();    if (c == '$' && flag) {	Dgetdol();	goto top;    }    return (c);}static Char *nulvec[] = {0};static struct varent nulargv = {nulvec, STRargv, { NULL, NULL, NULL }, 0};static voiddolerror(s)    Char   *s;{    setname(vis_str(s));    stderror(ERR_NAME | ERR_RANGE);}/* * Handle the multitudinous $ expansion forms. * Ugh. */static voidDgetdol(){    register Char *np;    register struct varent *vp = NULL;    Char    name[4 * MAXVARLEN + 1];    int     c, sc;    int     subscr = 0, lwb = 1, upb = 0;    bool    dimen = 0, bitset = 0;    char    tnp;    Char    wbuf[BUFSIZ];    static Char *dolbang = NULL;    dolnmod = dolmcnt = dolwcnt = 0;    c = sc = DgetC(0);    if (c == '{')	c = DgetC(0);		/* sc is { to take } later */    if ((c & TRIM) == '#')	dimen++, c = DgetC(0);	/* $# takes dimension */    else if (c == '?')	bitset++, c = DgetC(0);	/* $? tests existence */    switch (c) {    case '!':	if (dimen || bitset)	    stderror(ERR_SYNTAX);	if (backpid != 0) {	    if (dolbang) 		xfree((ptr_t) dolbang);	    setDolp(dolbang = putn(backpid));	}	goto eatbrac;    case '$':	if (dimen || bitset)	    stderror(ERR_SYNTAX);	setDolp(doldol);	goto eatbrac;    case '<' | QUOTE:	if (bitset)	    stderror(ERR_NOTALLOWED, "$?<");	if (dimen)	    stderror(ERR_NOTALLOWED, "$?#");	for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {	    *np = (unsigned char) tnp;	    if (np >= &wbuf[BUFSIZ - 1])		stderror(ERR_LTOOLONG);	    if (tnp == '\n')		break;	}	*np = 0;	/*	 * KLUDGE: dolmod is set here because it will cause setDolp to call	 * domod and thus to copy wbuf. Otherwise setDolp would use it	 * directly. If we saved it ourselves, no one would know when to free	 * it. The actual function of the 'q' causes filename expansion not to	 * be done on the interpolated value.	 */	dolmod[dolnmod++] = 'q';	dolmcnt = 10000;	setDolp(wbuf);	goto eatbrac;    case DEOF:    case '\n':	stderror(ERR_SYNTAX);	/* NOTREACHED */	break;    case '*':	(void) Strcpy(name, STRargv);	vp = adrof(STRargv);	subscr = -1;		/* Prevent eating [...] */	break;    default:	np = name;	if (Isdigit(c)) {	    if (dimen)		stderror(ERR_NOTALLOWED, "$#<num>");	    subscr = 0;	    do {		subscr = subscr * 10 + c - '0';		c = DgetC(0);	    } while (Isdigit(c));	    unDredc(c);	    if (subscr < 0) {		dolerror(vp->v_name);		return;	    }	    if (subscr == 0) {		if (bitset) {		    dolp = ffile ? STR1 : STR0;		    goto eatbrac;

⌨️ 快捷键说明

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