sh.set.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 750 行

C
750
字号
#ifndef lintstatic  char    *sccsid = "@(#)sh.set.c	4.2  (ULTRIX)        8/13/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1988 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/#include <limits.h>#include "sh.h"#include "sh.local.h"/* * C Shell * Modification History * * 005 - Bob Fontaine	- Fri Jun 22 09:53:01 EDT 1990 *	 Changed call to internal printf routine to csh_printf to avoid *	 confusion with stdio library routine. * * 004 - Bob Fontaine   - Thu May 24 14:07:57 EDT 1990 * 	 If the user sets $home to a path that does not begin with a '/', *	 inform him/her that fact and warn that future actions may be  *	 unpredictable.	 Fix for QAR #2622 * * 003 - Gary A. Gaudet - Tue Jan  2 12:01:30 EST 1990 *	added limits.h *	cleanup some INT_MIN code *	added some (castings) * * 02 20-Sep-88 Al Delorey (afd) *	removed some old tcsh code (using dcsh form now). * * 01 Sat Aug 13 15:28:57 EDT 1988, Gary A. Gaudet *	merging mips & ultrix for 8 bit clean and bug fixes */doset(v)	register char **v;{	register char *p;	char *vp, op,*rnf;	char **vecp;	bool hadsub;	int subscr;	char *errstr = "Syntax error";#define oops(reason)    { errstr = reason; goto setsyn; }	v++;	p = *v++;	if (p == 0) {		prvars();		return;	}	do {		hadsub = 0;		/*		GT01:		Any variable being set with the set command		must start with an alphabetic.		*/		if (!letter(*p))			oops("Syntax error: name needs leading alphabetic");		for (vp = p; alnum(*p); p++)			continue;		if (vp == p || !letter(*vp))			oops("Syntax error: name contains bad character");		if (*p == '[') {			hadsub++;			p = getinx(p, &subscr);		}		if (op = *p) {			*p++ = 0;			if (*p == 0 && *v && **v == '(')				p = *v++;		} else if (*v && eq(*v, "=")) {			op = '=', v++;			if (*v)				p = *v++;		}		if (op && op != '=')setsyn:			bferr(errstr);		if (eq(p, "(")) {			register char **e = v;			if (hadsub)				goto setsyn;			for (;;) {				if (!*e)					bferr("Missing )");				if (**e == ')')					break;				e++;			}			p = *e;			*e = 0;			vecp = saveblk(v);			set1(vp, vecp, &shvhed);			*e = p;			v = e + 1;		} else if (hadsub) 			asx(vp, subscr, savestr(p));		else {			set(vp, savestr(p));			if (eq(vp, "home") && *p != '/')	/* 004 RNF */	oops("Warning: home is not set to an absolute path name");			}		if (eq(vp, "path")) {			exportpath(adrof("path")->vec);			dohash();		} else if (eq(vp, "histchars")) {			register char *p = value("histchars");			HIST = *p++;			HISTSUB = *p;		} else if (eq(vp, "user")) {			setenv("USER", value(vp));		} else if (eq(vp, "term")) {			setenv("TERM", value(vp));		} else if (eq(vp, "home")) {				setenv("HOME", value(vp));		}	} while (p = *v++);}char *getinx(cp, ip)	register char *cp;	register int *ip;{	*ip = 0;	*cp++ = 0;	while (*cp && digit(*cp))		*ip = *ip * 10 + *cp++ - '0';	if (*cp++ != ']')		bferr("Subscript error");	return (cp);}asx(vp, subscr, p)	char *vp;	int subscr;	char *p;{	register struct varent *v = getvx(vp, subscr);	xfree(v->vec[subscr - 1]);	v->vec[subscr - 1] = globone(p);}struct varent *getvx(vp, subscr)	char *vp;{	register struct varent *v = adrof(vp);	if (v == 0)		udvar(vp);	if (subscr < 1 || subscr > blklen(v->vec))		bferr("Subscript out of range");	return (v);}char	plusplus[2] = { '1', 0 };dolet(v)	char **v;{	register char *p;	char *vp, c, op;	bool hadsub;	int subscr;	v++;	p = *v++;	if (p == 0) {		prvars();		return;	}	do {		hadsub = 0;		for (vp = p; alnum(*p); p++)			continue;		if (vp == p || !letter(*vp))			goto letsyn;		if (*p == '[') {			hadsub++;			p = getinx(p, &subscr);		}		if (*p == 0 && *v)			p = *v++;		if (op = *p)			*p++ = 0;		else			goto letsyn;		vp = savestr(vp);		if (op == '=') {			c = '=';			p = xset(p, &v);		} else {			c = *p++;			if (any(c, "+-")) {				if (c != op || *p)					goto letsyn;				p = plusplus;			} else {				if (any(op, "<>")) {					if (c != op)						goto letsyn;					c = *p++;letsyn:					bferr("Syntax error");				}				if (c != '=')					goto letsyn;				p = xset(p, &v);			}		}		if (op == '=')			if (hadsub)				asx(vp, subscr, p);			else				set(vp, p);		else			if (hadsub)#ifndef V6				/* avoid bug in vax CC */				{					struct varent *gv = getvx(vp, subscr);					asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));				}#else				asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p));#endif			else				set(vp, operate(op, value(vp), p));		if (eq(vp, "path")) {			exportpath(adrof("path")->vec);			dohash();		}		XFREE(vp)		if (c != '=')			XFREE(p)	} while (p = *v++);}char *xset(cp, vp)	char *cp, ***vp;{	register char *dp;	if (*cp) {		dp = savestr(cp);		--(*vp);		xfree(**vp);		**vp = dp;	}	return (putn(exp(vp)));}char *operate(op, vp, p)	char op, *vp, *p;{	char opr[2];	char *vec[5];	register char **v = vec;	char **vecp = v;	register int i;	if (op != '=') {		if (*vp)			*v++ = vp;		opr[0] = op;		opr[1] = 0;		*v++ = opr;		if (op == '<' || op == '>')			*v++ = opr;	}	*v++ = p;	*v++ = 0;	i = exp(&vecp);	if (*vecp)		bferr("Expression syntax");	return (putn(i));}static	char *putp; char *putn(n)	register int n;{	static char number[15];	putp = number;	if (n < 0) {		*putp++ = '-';		if (n != INT_MIN) {	/* 003 - GAG */			 putn1 (-n);		} else {			putn1 (-(n/10));			*putp++ = n % 10 + '0';		}	} else {		putn1(n);	}	*putp = 0;	return (savestr(number));}putn1(n)	register int n;{	if (n > 9)		putn1(n / 10);	*putp++ = n % 10 + '0';}getn(cp)	register char *cp;{	register int n;	int sign;	sign = 0;	if (cp[0] == '+' && cp[1])		cp++;	if (*cp == '-') {		sign++;		cp++;		if (!digit(*cp))			goto badnum;	}	n = 0;	while (digit(*cp))		n = n * 10 + *cp++ - '0';	if (*cp)		goto badnum;	return (sign ? -n : n);badnum:	bferr("Badly formed number");	return (0);}char *value1(var, head)	char *var;	struct varent *head;{	register struct varent *vp;	vp = adrof1(var, head);	return (vp == 0 || vp->vec[0] == 0 ? "" : vp->vec[0]);}struct varent *madrof(pat, vp)	char *pat;	register struct varent *vp;{	register struct varent *vp1;	for (; vp; vp = vp->v_right) {		if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))			return vp1;		if (Gmatch(vp->v_name, pat))			return vp;	}	return vp;}struct varent *adrof1(name, v)	register char *name;	register struct varent *v;{	register cmp;	v = v->v_left;	while (v && ((cmp = *name - *v->v_name) ||		     (cmp = strcmp(name, v->v_name))))		if (cmp < 0)			v = v->v_left;		else			v = v->v_right;	return v;}/* * The caller is responsible for putting value in a safe place */set(var, val)	char *var, *val;{	register char **vec = (char **) xalloc((unsigned)(2 * sizeof (char **)));	vec[0] = onlyread(val) ? savestr(val) : val;	vec[1] = 0;	set1(var, vec, &shvhed);}set1(var, vec, head)	char *var, **vec;	struct varent *head;{	register char **oldv = vec;	gflag = 0; tglob(oldv);	if (gflag) {		vec = glob(oldv);		if (vec == 0) {			bferr("No match");			blkfree(oldv);			return;		}		blkfree(oldv);		gargv = 0;	}	setq(var, vec, head);}setq(name, vec, p)	char *name, **vec;	register struct varent *p;{	register struct varent *c;	register f;	f = 0;			/* tree hangs off the header's left link */	while (c = p->v_link[f]) {		if ((f = *name - *c->v_name) == 0 &&		    (f = strcmp(name, c->v_name)) == 0) {			blkfree(c->vec);			goto found;		}		p = c;		f = f > 0;	}	p->v_link[f] = c = (struct varent *)xalloc((unsigned)sizeof (struct varent));	c->v_name = savestr(name);	c->v_bal = 0;	c->v_left = c->v_right = 0;	c->v_parent = p;	balance(p, f, 0);found:	trim(c->vec = vec);}unset(v)	char *v[];{	unset1(v, &shvhed);	if (adrof("histchars") == 0) {		HIST = '!';		HISTSUB = '^';	}}unset1(v, head)	register char *v[];	struct varent *head;{	register struct varent *vp;	register int cnt;	while (*++v) {		cnt = 0;		while (vp = madrof(*v, head->v_left))			unsetv1(vp), cnt++;		if (cnt == 0)			setname(*v);	}}unsetv(var)	char *var;{	register struct varent *vp;	if ((vp = adrof1(var, &shvhed)) == 0)		udvar(var);	unsetv1(vp);}unsetv1(p)	register struct varent *p;{	register struct varent *c, *pp;	register f;	/*	 * Free associated memory first to avoid complications.	 */	blkfree(p->vec);	XFREE(p->v_name);	/*	 * If p is missing one child, then we can move the other	 * into where p is.  Otherwise, we find the predecessor	 * of p, which is guaranteed to have no right child, copy	 * it into p, and move it's left child into it.	 */	if (p->v_right == 0)		c = p->v_left;	else if (p->v_left == 0)		c = p->v_right;	else {		for (c = p->v_left; c->v_right; c = c->v_right)			;		p->v_name = c->v_name;		p->vec = c->vec;		p = c;		c = p->v_left;	}	/*	 * Move c into where p is.	 */	pp = p->v_parent;	f = pp->v_right == p;	if (pp->v_link[f] = c)		c->v_parent = pp;	/*	 * Free the deleted node, and rebalance.	 */	XFREE((char *)p);	balance(pp, f, 1);}setNS(cp)	char *cp;{	set(cp, "");}shift(v)	register char **v;{	register struct varent *argv;	register char *name;	v++;	name = *v;	if (name == 0)		name = "argv";	else		(void) strip(name);	argv = adrof(name);	if (argv == 0)		udvar(name);	if (argv->vec[0] == 0)		bferr("No more words");	lshift(argv->vec, 1);}exportpath(val)char **val;{	char exppath[BUFSIZ];	exppath[0] = 0;	if (val)		while (*val) {			if (strlen(*val) + strlen(exppath) + 2 > BUFSIZ) {				csh_printf("Warning: ridiculously long PATH truncated\n"); /* 005 RNF */				break;			}			(void) strcat(exppath, *val++);			if (*val == 0 || eq(*val, ")"))				break;			(void) strcat(exppath, ":");		}	setenv("PATH", exppath);}	/* macros to do single rotations on node p */#define rright(p) (\	t = (p)->v_left,\	(t)->v_parent = (p)->v_parent,\	((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\	(t->v_right = (p))->v_parent = t,\	(p) = t)#define rleft(p) (\	t = (p)->v_right,\	(t)->v_parent = (p)->v_parent,\	((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\	(t->v_left = (p))->v_parent = t,\	(p) = t)/* * Rebalance a tree, starting at p and up. * F == 0 means we've come from p's left child. * D == 1 means we've just done a delete, otherwise an insert. */balance(p, f, d)	register struct varent *p;	register f;{	register struct varent *pp;	register struct varent *t;		/* used by the rotate macros */	register ff;	/*	 * Ok, from here on, p is the node we're operating on;	 * pp is it's parent; f is the branch of p from which we have come;	 * ff is the branch of pp which is p.	 */	for (; pp = p->v_parent; p = pp, f = ff) {		ff = pp->v_right == p;		if (f ^ d) {		/* right heavy */			switch (p->v_bal) {			case -1:		/* was left heavy */				p->v_bal = 0;				break;			case 0:			/* was balanced */				p->v_bal = 1;				break;			case 1:			/* was already right heavy */				switch (p->v_right->v_bal) {				case 1:			/* sigle rotate */					pp->v_link[ff] = rleft(p);					p->v_left->v_bal = 0;					p->v_bal = 0;					break;				case 0:			/* single rotate */					pp->v_link[ff] = rleft(p);					p->v_left->v_bal = 1;					p->v_bal = -1;					break;				case -1:		/* double rotate */					rright(p->v_right);					pp->v_link[ff] = rleft(p);					p->v_left->v_bal =						p->v_bal < 1 ? 0 : -1;					p->v_right->v_bal =						p->v_bal > -1 ? 0 : 1;					p->v_bal = 0;					break;				}				break;			}		} else {		/* left heavy */			switch (p->v_bal) {			case 1:			/* was right heavy */				p->v_bal = 0;				break;			case 0:			/* was balanced */				p->v_bal = -1;				break;			case -1:		/* was already left heavy */				switch (p->v_left->v_bal) {				case -1:		/* single rotate */					pp->v_link[ff] = rright(p);					p->v_right->v_bal = 0;					p->v_bal = 0;					break;				case 0:			/* signle rotate */					pp->v_link[ff] = rright(p);					p->v_right->v_bal = -1;					p->v_bal = 1;					break;				case 1:			/* double rotate */					rleft(p->v_left);					pp->v_link[ff] = rright(p);					p->v_left->v_bal =						p->v_bal < 1 ? 0 : -1;					p->v_right->v_bal =						p->v_bal > -1 ? 0 : 1;					p->v_bal = 0;					break;				}				break;			}		}		/*		 * If from insert, then we terminate when p is balanced.		 * If from delete, then we terminate when p is unbalanced.		 */		if ((p->v_bal == 0) ^ d)			break;	}}plist(p)	register struct varent *p;{	register struct varent *c;	register len;	if (setintr)		(void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));	for (;;) {		while (p->v_left)			p = p->v_left;	x:		if (p->v_parent == 0)		/* is it the header? */			return;		len = blklen(p->vec);		csh_printf(p->v_name);		/* 005 RNF */		putchar('\t');		if (len != 1)			putchar('(');		blkpr(p->vec);		if (len != 1)			putchar(')');		putchar('\n');		if (p->v_right) {			p = p->v_right;			continue;		}		do {			c = p;			p = p->v_parent;		} while (p->v_right == c);		goto x;	}}

⌨️ 快捷键说明

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