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

📄 func.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[] = "@(#)func.c	8.1 (Berkeley) 5/31/93";#endif /* not lint */#include <sys/types.h>#include <sys/stat.h>#include <signal.h>#include <locale.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"#include "pathnames.h"extern char **environ;static int zlast = -1;static void	islogin __P((void));static void	reexecute __P((struct command *));static void	preread __P((void));static void	doagain __P((void));static void	search __P((int, int, Char *));static int	getword __P((Char *));static int	keyword __P((Char *));static void	toend __P((void));static void	xecho __P((int, Char **));static void	Unsetenv __P((Char *));struct biltins *isbfunc(t)    struct command *t;{    register Char *cp = t->t_dcom[0];    register struct biltins *bp, *bp1, *bp2;    static struct biltins label = {"", dozip, 0, 0};    static struct biltins foregnd = {"%job", dofg1, 0, 0};    static struct biltins backgnd = {"%job &", dobg1, 0, 0};    if (lastchr(cp) == ':') {	label.bname = short2str(cp);	return (&label);    }    if (*cp == '%') {	if (t->t_dflg & F_AMPERSAND) {	    t->t_dflg &= ~F_AMPERSAND;	    backgnd.bname = short2str(cp);	    return (&backgnd);	}	foregnd.bname = short2str(cp);	return (&foregnd);    }    /*     * Binary search Bp1 is the beginning of the current search range. Bp2 is     * one past the end.     */    for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {	register i;	bp = bp1 + ((bp2 - bp1) >> 1);	if ((i = *cp - *bp->bname) == 0 &&	    (i = Strcmp(cp, str2short(bp->bname))) == 0)	    return bp;	if (i < 0)	    bp2 = bp;	else	    bp1 = bp + 1;    }    return (0);}voidfunc(t, bp)    register struct command *t;    register struct biltins *bp;{    int     i;    xechoit(t->t_dcom);    setname(bp->bname);    i = blklen(t->t_dcom) - 1;    if (i < bp->minargs)	stderror(ERR_NAME | ERR_TOOFEW);    if (i > bp->maxargs)	stderror(ERR_NAME | ERR_TOOMANY);    (*bp->bfunct) (t->t_dcom, t);}void/*ARGSUSED*/doonintr(v, t)    Char **v;    struct command *t;{    register Char *cp;    register Char *vv = v[1];    if (parintr == SIG_IGN)	return;    if (setintr && intty)	stderror(ERR_NAME | ERR_TERMINAL);    cp = gointr;    gointr = 0;    xfree((ptr_t) cp);    if (vv == 0) {	if (setintr)	    (void) sigblock(sigmask(SIGINT));	else	    (void) signal(SIGINT, SIG_DFL);	gointr = 0;    }    else if (eq((vv = strip(vv)), STRminus)) {	(void) signal(SIGINT, SIG_IGN);	gointr = Strsave(STRminus);    }    else {	gointr = Strsave(vv);	(void) signal(SIGINT, pintr);    }}void/*ARGSUSED*/donohup(v, t)    Char **v;    struct command *t;{    if (intty)	stderror(ERR_NAME | ERR_TERMINAL);    if (setintr == 0) {	(void) signal(SIGHUP, SIG_IGN);    }}void/*ARGSUSED*/dozip(v, t)    Char **v;    struct command *t;{    ;}voidprvars(){    plist(&shvhed);}void/*ARGSUSED*/doalias(v, t)    Char **v;    struct command *t;{    register struct varent *vp;    register Char *p;    v++;    p = *v++;    if (p == 0)	plist(&aliases);    else if (*v == 0) {	vp = adrof1(strip(p), &aliases);	if (vp) {	    blkpr(cshout, vp->vec);	    fputc('\n', cshout);	}    }    else {	if (eq(p, STRalias) || eq(p, STRunalias)) {	    setname(vis_str(p));	    stderror(ERR_NAME | ERR_DANGER);	}	set1(strip(p), saveblk(v), &aliases);    }}void/*ARGSUSED*/unalias(v, t)    Char **v;    struct command *t;{    unset1(v, &aliases);}void/*ARGSUSED*/dologout(v, t)    Char **v;    struct command *t;{    islogin();    goodbye();}void/*ARGSUSED*/dologin(v, t)    Char **v;    struct command *t;{    islogin();    rechist();    (void) signal(SIGTERM, parterm);    (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL);    untty();    xexit(1);}static voidislogin(){    if (chkstop == 0 && setintr)	panystop(0);    if (loginsh)	return;    stderror(ERR_NOTLOGIN);}voiddoif(v, kp)    Char  **v;    struct command *kp;{    register int i;    register Char **vv;    v++;    i = expr(&v);    vv = v;    if (*vv == NULL)	stderror(ERR_NAME | ERR_EMPTYIF);    if (eq(*vv, STRthen)) {	if (*++vv)	    stderror(ERR_NAME | ERR_IMPRTHEN);	setname(vis_str(STRthen));	/*	 * If expression was zero, then scan to else, otherwise just fall into	 * following code.	 */	if (!i)	    search(T_IF, 0, NULL);	return;    }    /*     * Simple command attached to this if. Left shift the node in this tree,     * munging it so we can reexecute it.     */    if (i) {	lshift(kp->t_dcom, vv - kp->t_dcom);	reexecute(kp);	donefds();    }}/* * Reexecute a command, being careful not * to redo i/o redirection, which is already set up. */static voidreexecute(kp)    register struct command *kp;{    kp->t_dflg &= F_SAVE;    kp->t_dflg |= F_REPEAT;    /*     * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set     * pgrp's as the jobs would then have no way to get the tty (we can't give     * it to them, and our parent wouldn't know their pgrp, etc.     */    execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);}void/*ARGSUSED*/doelse(v, t)    Char **v;    struct command *t;{    search(T_ELSE, 0, NULL);}void/*ARGSUSED*/dogoto(v, t)    Char **v;    struct command *t;{    Char   *lp;    gotolab(lp = globone(v[1], G_ERROR));    xfree((ptr_t) lp);}voidgotolab(lab)    Char *lab;{    register struct whyle *wp;    /*     * While we still can, locate any unknown ends of existing loops. This     * obscure code is the WORST result of the fact that we don't really parse.     */    zlast = T_GOTO;    for (wp = whyles; wp; wp = wp->w_next)	if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {	    search(T_BREAK, 0, NULL);	    btell(&wp->w_end);	}	else	    bseek(&wp->w_end);    search(T_GOTO, 0, lab);    /*     * Eliminate loops which were exited.     */    wfree();}void/*ARGSUSED*/doswitch(v, t)    Char **v;    struct command *t;{    register Char *cp, *lp;    v++;    if (!*v || *(*v++) != '(')	stderror(ERR_SYNTAX);    cp = **v == ')' ? STRNULL : *v++;    if (*(*v++) != ')')	v--;    if (*v)	stderror(ERR_SYNTAX);    search(T_SWITCH, 0, lp = globone(cp, G_ERROR));    xfree((ptr_t) lp);}void/*ARGSUSED*/dobreak(v, t)    Char **v;    struct command *t;{    if (whyles)	toend();    else	stderror(ERR_NAME | ERR_NOTWHILE);}void/*ARGSUSED*/doexit(v, t)    Char **v;    struct command *t;{    if (chkstop == 0 && (intty || intact) && evalvec == 0)	panystop(0);    /*     * Don't DEMAND parentheses here either.     */    v++;    if (*v) {	set(STRstatus, putn(expr(&v)));	if (*v)	    stderror(ERR_NAME | ERR_EXPRESSION);    }    btoeof();    if (intty)	(void) close(SHIN);}void/*ARGSUSED*/doforeach(v, t)    Char **v;    struct command *t;{    register Char *cp, *sp;    register struct whyle *nwp;    v++;    sp = cp = strip(*v);    if (!letter(*sp))	stderror(ERR_NAME | ERR_VARBEGIN);    while (*cp && alnum(*cp))	cp++;    if (*cp)	stderror(ERR_NAME | ERR_VARALNUM);    if ((cp - sp) > MAXVARLEN)	stderror(ERR_NAME | ERR_VARTOOLONG);    cp = *v++;    if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')	stderror(ERR_NAME | ERR_NOPAREN);    v++;    gflag = 0, tglob(v);    v = globall(v);    if (v == 0)	stderror(ERR_NAME | ERR_NOMATCH);    nwp = (struct whyle *) xcalloc(1, sizeof *nwp);    nwp->w_fe = nwp->w_fe0 = v;    gargv = 0;    btell(&nwp->w_start);    nwp->w_fename = Strsave(cp);    nwp->w_next = whyles;    nwp->w_end.type = F_SEEK;    whyles = nwp;    /*     * Pre-read the loop so as to be more comprehensible to a terminal user.     */    zlast = T_FOREACH;    if (intty)	preread();    doagain();}void/*ARGSUSED*/dowhile(v, t)    Char **v;    struct command *t;{    register int status;    register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&    whyles->w_fename == 0;    v++;    /*     * Implement prereading here also, taking care not to evaluate the     * expression before the loop has been read up from a terminal.     */    if (intty && !again)	status = !exp0(&v, 1);    else	status = !expr(&v);    if (*v)	stderror(ERR_NAME | ERR_EXPRESSION);    if (!again) {	register struct whyle *nwp =	(struct whyle *) xcalloc(1, sizeof(*nwp));	nwp->w_start = lineloc;	nwp->w_end.type = F_SEEK;	nwp->w_end.f_seek = 0;	nwp->w_next = whyles;	whyles = nwp;	zlast = T_WHILE;	if (intty) {	    /*	     * The tty preread	     */	    preread();	    doagain();	    return;	}    }    if (status)	/* We ain't gonna loop no more, no more! */	toend();}static voidpreread(){    whyles->w_end.type = I_SEEK;    if (setintr)	(void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));    search(T_BREAK, 0, NULL);		/* read the expression in */    if (setintr)	(void) sigblock(sigmask(SIGINT));    btell(&whyles->w_end);}void/*ARGSUSED*/doend(v, t)    Char **v;    struct command *t;{    if (!whyles)	stderror(ERR_NAME | ERR_NOTWHILE);    btell(&whyles->w_end);    doagain();}void/*ARGSUSED*/docontin(v, t)    Char **v;    struct command *t;{    if (!whyles)	stderror(ERR_NAME | ERR_NOTWHILE);    doagain();}static voiddoagain(){    /* Repeating a while is simple */    if (whyles->w_fename == 0) {	bseek(&whyles->w_start);	return;    }    /*     * The foreach variable list actually has a spurious word ")" at the end of     * the w_fe list.  Thus we are at the of the list if one word beyond this     * is 0.     */    if (!whyles->w_fe[1]) {	dobreak(NULL, NULL);	return;    }    set(whyles->w_fename, Strsave(*whyles->w_fe++));    bseek(&whyles->w_start);}voiddorepeat(v, kp)    Char  **v;    struct command *kp;{    register int i;    register sigset_t omask = 0;    i = getn(v[1]);    if (setintr)	omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);    lshift(v, 2);    while (i > 0) {	if (setintr)	    (void) sigsetmask(omask);	reexecute(kp);	--i;    }    donefds();    if (setintr)	(void) sigsetmask(omask);}void/*ARGSUSED*/doswbrk(v, t)    Char **v;    struct command *t;{    search(T_BRKSW, 0, NULL);}intsrchx(cp)    register Char *cp;{    register struct srch *sp, *sp1, *sp2;    register i;    /*     * Binary search Sp1 is the beginning of the current search range. Sp2 is     * one past the end.     */    for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {	sp = sp1 + ((sp2 - sp1) >> 1);	if ((i = *cp - *sp->s_name) == 0 &&	    (i = Strcmp(cp, str2short(sp->s_name))) == 0)	    return sp->s_value;	if (i < 0)	    sp2 = sp;	else	    sp1 = sp + 1;    }    return (-1);}static Char Stype;static Char *Sgoal;/*VARARGS2*/static voidsearch(type, level, goal)    int     type;    register int level;    Char   *goal;{    Char    wordbuf[BUFSIZ];    register Char *aword = wordbuf;    register Char *cp;    Stype = type;    Sgoal = goal;    if (type == T_GOTO) {	struct Ain a;	a.type = F_SEEK;	a.f_seek = 0;	bseek(&a);    }    do {	if (intty && fseekp == feobp && aret == F_SEEK)	    (void) fprintf(cshout, "? "), (void) fflush(cshout);	aword[0] = 0;	(void) getword(aword);	switch (srchx(aword)) {	case T_ELSE:	    if (level == 0 && type == T_IF)		return;	    break;	case T_IF:	    while (getword(aword))		continue;	    if ((type == T_IF || type == T_ELSE) &&		eq(aword, STRthen))		level++;	    break;	case T_ENDIF:	    if (type == T_IF || type == T_ELSE)		level--;	    break;	case T_FOREACH:	case T_WHILE:	    if (type == T_BREAK)		level++;	    break;	case T_END:	    if (type == T_BREAK)		level--;	    break;	case T_SWITCH:	    if (type == T_SWITCH || type == T_BRKSW)		level++;	    break;	case T_ENDSW:	    if (type == T_SWITCH || type == T_BRKSW)		level--;	    break;	case T_LABEL:	    if (type == T_GOTO && getword(aword) && eq(aword, goal))		level = -1;	    break;	default:	    if (type != T_GOTO && (type != T_SWITCH || level != 0))		break;	    if (lastchr(aword) != ':')		break;	    aword[Strlen(aword) - 1] = 0;	    if ((type == T_GOTO && eq(aword, goal)) ||		(type == T_SWITCH && eq(aword, STRdefault)))		level = -1;	    break;	case T_CASE:	    if (type != T_SWITCH || level != 0)		break;	    (void) getword(aword);	    if (lastchr(aword) == ':')		aword[Strlen(aword) - 1] = 0;	    cp = strip(Dfix1(aword));	    if (Gmatch(goal, cp))		level = -1;	    xfree((ptr_t) cp);	    break;	case T_DEFAULT:	    if (type == T_SWITCH && level == 0)		level = -1;	    break;	}	(void) getword(NULL);    } while (level >= 0);}static intgetword(wp)    register Char *wp;{    register int found = 0;    register int c, d;    int     kwd = 0;    Char   *owp = wp;    c = readc(1);    d = 0;    do {	while (c == ' ' || c == '\t')	    c = readc(1);	if (c == '#')	    do		c = readc(1);	    while (c >= 0 && c != '\n');	if (c < 0)	    goto past;	if (c == '\n') {	    if (wp)		break;	    return (0);	}	unreadc(c);	found = 1;	do {	    c = readc(1);	    if (c == '\\' && (c = readc(1)) == '\n')

⌨️ 快捷键说明

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