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

📄 eval.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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[] = "@(#)eval.c	5.3 (Berkeley) 4/12/91";#endif /* not lint *//* * Evaluate a command. */#include "shell.h"#include "nodes.h"#include "syntax.h"#include "expand.h"#include "parser.h"#include "jobs.h"#include "eval.h"#include "builtins.h"#include "options.h"#include "exec.h"#include "redir.h"#include "input.h"#include "output.h"#include "trap.h"#include "var.h"#include "memalloc.h"#include "error.h"#include "mystring.h"#include <sys/types.h>#include <signal.h>/* flags in argument to evaltree */#define EV_EXIT 01		/* exit after evaluating tree */#define EV_TESTED 02		/* exit status is checked; ignore -e flag */#define EV_BACKCMD 04		/* command executing within back quotes *//* reasons for skipping commands (see comment on breakcmd routine) */#define SKIPBREAK 1#define SKIPCONT 2#define SKIPFUNC 3MKINIT int evalskip;		/* set if we are skipping commands */STATIC int skipcount;		/* number of levels to skip */MKINIT int loopnest;		/* current loop nesting level */int funcnest;			/* depth of function calls */char *commandname;struct strlist *cmdenviron;int exitstatus;			/* exit status of last command */#ifdef __STDC__STATIC void evalloop(union node *);STATIC void evalfor(union node *);STATIC void evalcase(union node *, int);STATIC void evalsubshell(union node *, int);STATIC void expredir(union node *);STATIC void evalpipe(union node *);STATIC void evalcommand(union node *, int, struct backcmd *);STATIC void prehash(union node *);#elseSTATIC void evalloop();STATIC void evalfor();STATIC void evalcase();STATIC void evalsubshell();STATIC void expredir();STATIC void evalpipe();STATIC void evalcommand();STATIC void prehash();#endif/* * Called to reset things after an exception. */#ifdef mkinitINCLUDE "eval.h"RESET {	evalskip = 0;	loopnest = 0;	funcnest = 0;}SHELLPROC {	exitstatus = 0;}#endif/* * The eval commmand. */evalcmd(argc, argv)  	char **argv; {        char *p;        char *concat;        char **ap;        if (argc > 1) {                p = argv[1];                if (argc > 2) {                        STARTSTACKSTR(concat);                        ap = argv + 2;                        for (;;) {                                while (*p)                                        STPUTC(*p++, concat);                                if ((p = *ap++) == NULL)                                        break;                                STPUTC(' ', concat);                        }                        STPUTC('\0', concat);                        p = grabstackstr(concat);                }                evalstring(p);        }        return exitstatus;}/* * Execute a command or commands contained in a string. */voidevalstring(s)	char *s;	{	union node *n;	struct stackmark smark;	setstackmark(&smark);	setinputstring(s, 1);	while ((n = parsecmd(0)) != NEOF) {		evaltree(n, 0);		popstackmark(&smark);	}	popfile();	popstackmark(&smark);}/* * Evaluate a parse tree.  The value is left in the global variable * exitstatus. */voidevaltree(n, flags)	union node *n;	{	if (n == NULL) {		TRACE(("evaltree(NULL) called\n"));		return;	}	TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));	switch (n->type) {	case NSEMI:		evaltree(n->nbinary.ch1, 0);		if (evalskip)			goto out;		evaltree(n->nbinary.ch2, flags);		break;	case NAND:		evaltree(n->nbinary.ch1, EV_TESTED);		if (evalskip || exitstatus != 0)			goto out;		evaltree(n->nbinary.ch2, flags);		break;	case NOR:		evaltree(n->nbinary.ch1, EV_TESTED);		if (evalskip || exitstatus == 0)			goto out;		evaltree(n->nbinary.ch2, flags);		break;	case NREDIR:		expredir(n->nredir.redirect);		redirect(n->nredir.redirect, REDIR_PUSH);		evaltree(n->nredir.n, flags);		popredir();		break;	case NSUBSHELL:		evalsubshell(n, flags);		break;	case NBACKGND:		evalsubshell(n, flags);		break;	case NIF: {		int status = 0; 		evaltree(n->nif.test, EV_TESTED);		if (evalskip)			goto out;		if (exitstatus == 0) {			evaltree(n->nif.ifpart, flags);			status = exitstatus;		} else if (n->nif.elsepart) {			evaltree(n->nif.elsepart, flags);			status = exitstatus;		}		exitstatus = status;		break;	}	case NWHILE:	case NUNTIL:		evalloop(n);		break;	case NFOR:		evalfor(n);		break;	case NCASE:		evalcase(n, flags);		break;	case NDEFUN:		defun(n->narg.text, n->narg.next);		exitstatus = 0;		break;	case NPIPE:		evalpipe(n);		break;	case NCMD:		evalcommand(n, flags, (struct backcmd *)NULL);		break;	default:		out1fmt("Node type = %d\n", n->type);		flushout(&output);		break;	}out:	if (pendingsigs)		dotrap();	if ((flags & EV_EXIT) || (eflag && exitstatus && !(flags & EV_TESTED)))		exitshell(exitstatus);}STATIC voidevalloop(n)	union node *n;	{	int status;	loopnest++;	status = 0;	for (;;) {		evaltree(n->nbinary.ch1, EV_TESTED);		if (evalskip) {skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {				evalskip = 0;				continue;			}			if (evalskip == SKIPBREAK && --skipcount <= 0)				evalskip = 0;			break;		}		if (n->type == NWHILE) {			if (exitstatus != 0)				break;		} else {			if (exitstatus == 0)				break;		}		evaltree(n->nbinary.ch2, 0);		status = exitstatus;		if (evalskip)			goto skipping;	}	loopnest--;	exitstatus = status;}STATIC voidevalfor(n)	union node *n;	{	struct arglist arglist;	union node *argp;	struct strlist *sp;	struct stackmark smark;	setstackmark(&smark);	arglist.lastp = &arglist.list;	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {		expandarg(argp, &arglist, 1);		if (evalskip)			goto out;	}	*arglist.lastp = NULL;	exitstatus = 0;	loopnest++;	for (sp = arglist.list ; sp ; sp = sp->next) {		setvar(n->nfor.var, sp->text, 0);		evaltree(n->nfor.body, 0);		if (evalskip) {			if (evalskip == SKIPCONT && --skipcount <= 0) {				evalskip = 0;				continue;			}			if (evalskip == SKIPBREAK && --skipcount <= 0)				evalskip = 0;			break;		}	}	loopnest--;out:	popstackmark(&smark);}STATIC voidevalcase(n, flags)	union node *n;	{	union node *cp;	union node *patp;	struct arglist arglist;	struct stackmark smark;	setstackmark(&smark);	arglist.lastp = &arglist.list;	expandarg(n->ncase.expr, &arglist, 0);	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {			if (casematch(patp, arglist.list->text)) {				if (evalskip == 0) {					evaltree(cp->nclist.body, flags);				}				goto out;			}		}	}out:	popstackmark(&smark);}/* * Kick off a subshell to evaluate a tree. */STATIC voidevalsubshell(n, flags)	union node *n;	{	struct job *jp;	int backgnd = (n->type == NBACKGND);	expredir(n->nredir.redirect);	jp = makejob(n, 1);	if (forkshell(jp, n, backgnd) == 0) {		if (backgnd)			flags &=~ EV_TESTED;		redirect(n->nredir.redirect, 0);		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */	}	if (! backgnd) {		INTOFF;		exitstatus = waitforjob(jp);		INTON;	}}/* * Compute the names of the files in a redirection list. */STATIC voidexpredir(n)	union node *n;	{	register union node *redir;	for (redir = n ; redir ; redir = redir->nfile.next) {		if (redir->type == NFROM		 || redir->type == NTO		 || redir->type == NAPPEND) {			struct arglist fn;			fn.lastp = &fn.list;			expandarg(redir->nfile.fname, &fn, 0);			redir->nfile.expfname = fn.list->text;		}	}}/* * Evaluate a pipeline.  All the processes in the pipeline are children * of the process creating the pipeline.  (This differs from some versions * of the shell, which make the last process in a pipeline the parent * of all the rest.) */STATIC voidevalpipe(n)	union node *n;	{	struct job *jp;	struct nodelist *lp;	int pipelen;	int prevfd;	int pip[2];	TRACE(("evalpipe(0x%x) called\n", (int)n));	pipelen = 0;	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)		pipelen++;	INTOFF;	jp = makejob(n, pipelen);	prevfd = -1;	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {		prehash(lp->n);		pip[1] = -1;

⌨️ 快捷键说明

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