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

📄 eval.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 3 页
字号:
			 * word is generated if $# is 0 (unless there is			 * other stuff inside the quotes).			 */			type = XBASE;			if (f&DOBLANK) {				doblank--;				/* not really correct: x=; "$x$@" should				 * generate a null argument and				 * set A; "${@:+}" shouldn't.				 */				if (dp == Xstring(ds, dp))					word = IFS_WS;			}			continue;		  case XSUB:			if ((c = *x.str++) == 0) {				type = XBASE;				if (f&DOBLANK)					doblank--;				continue;			}			break;		  case XARGSEP:			type = XARG;			quote = 1;		  case XARG:			if ((c = *x.str++) == '\0') {				/* force null words to be created so				 * set -- '' 2 ''; foo "$@" will do				 * the right thing				 */				if (quote && x.split)					word = IFS_WORD;				if ((x.str = *x.u.strv++) == NULL) {					type = XBASE;					if (f&DOBLANK)						doblank--;					continue;				}				c = ifs0;				if (c == 0) {					if (quote && !x.split)						continue;					c = ' ';				}				if (quote && x.split) {					/* terminate word for "$@" */					type = XARGSEP;					quote = 0;				}			}			break;		  case XCOM:			if (newlines) {		/* Spit out saved nl's */				c = '\n';				--newlines;			} else {				while ((c = shf_getc(x.u.shf)) == 0 || c == '\n')				    if (c == '\n')					    newlines++;	/* Save newlines */				if (newlines && c != EOF) {					shf_ungetc(c, x.u.shf);					c = '\n';					--newlines;				}			}			if (c == EOF) {				newlines = 0;				shf_close(x.u.shf);				if (x.split)					subst_exstat = waitlast();				type = XBASE;				if (f&DOBLANK)					doblank--;				continue;			}			break;		}		/* check for end of word or IFS separation */		if (c == 0 || (!quote && (f & DOBLANK) && doblank && !make_magic			       && ctype(c, C_IFS)))		{			/* How words are broken up:			 *		   |       value of c			 *	  word	   |	ws	nws	0			 *	-----------------------------------			 *	IFS_WORD	w/WS	w/NWS	w			 *	IFS_WS		-/WS	w/NWS	-			 *	IFS_NWS		-/NWS	w/NWS	w			 *   (w means generate a word)			 * Note that IFS_NWS/0 generates a word (at&t ksh			 * doesn't do this, but POSIX does).			 */			if (word == IFS_WORD			    || (!ctype(c, C_IFSWS) && (c || word == IFS_NWS)))			{				char *p;				*dp++ = '\0';				p = Xclose(ds, dp);#ifdef BRACE_EXPAND				if (fdo & DOBRACE_)					/* also does globbing */					alt_expand(wp, p, p,						   p + Xlength(ds, (dp - 1)),						   fdo | (f & DOMARKDIRS));				else#endif /* BRACE_EXPAND */				if (fdo & DOGLOB)					glob(p, wp, f & DOMARKDIRS);				else if ((f & DOPAT) || !(fdo & DOMAGIC_))					XPput(*wp, p);				else					XPput(*wp, debunk(p, p));				fdo = 0;				saw_eq = 0;				tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0;				if (c != 0)					Xinit(ds, dp, 128, ATEMP);			}			if (c == 0)				return;			if (word != IFS_NWS)				word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS;		} else {			/* age tilde_ok info - ~ code tests second bit */			tilde_ok <<= 1;			/* mark any special second pass chars */			if (!quote)				switch (c) {				  case '[':				  case NOT:				  case '-':				  case ']':					/* For character classes - doesn't hurt					 * to have magic !,-,]'s outside of					 * [...] expressions.					 */					if (f & (DOPAT | DOGLOB)) {						fdo |= DOMAGIC_;						if (c == '[')							fdo |= f & DOGLOB;						*dp++ = MAGIC;					}					break;				  case '*':				  case '?':					if (f & (DOPAT | DOGLOB)) {						fdo |= DOMAGIC_ | (f & DOGLOB);						*dp++ = MAGIC;					}					break;#ifdef BRACE_EXPAND				  case OBRACE:				  case ',':				  case CBRACE:					if ((f & DOBRACE_) && (c == OBRACE						|| (fdo & DOBRACE_)))					{						fdo |= DOBRACE_|DOMAGIC_;						*dp++ = MAGIC;					}					break;#endif /* BRACE_EXPAND */				  case '=':					/* Note first unquoted = for ~ */					if (!(f & DOTEMP_) && !saw_eq) {						saw_eq = 1;						tilde_ok = 1;					}					break;				  case PATHSEP: /* : */					/* Note unquoted : for ~ */					if (!(f & DOTEMP_) && (f & DOASNTILDE))						tilde_ok = 1;					break;				  case '~':					/* tilde_ok is reset whenever					 * any of ' " $( $(( ${ } are seen.					 * Note that tilde_ok must be preserved					 * through the sequence ${A=a=}~					 */					if (type == XBASE					    && (f & (DOTILDE|DOASNTILDE))					    && (tilde_ok & 2))					{						char *p, *dp_x;						dp_x = dp;						p = maybe_expand_tilde(sp,							&ds, &dp_x,							f & DOASNTILDE);						if (p) {							if (dp != dp_x)								word = IFS_WORD;							dp = dp_x;							sp = p;							continue;						}					}					break;				}			else				quote &= ~2; /* undo temporary */			if (make_magic) {				make_magic = 0;				fdo |= DOMAGIC_ | (f & DOGLOB);				*dp++ = MAGIC;			} else if (ISMAGIC(c)) {				fdo |= DOMAGIC_;				*dp++ = MAGIC;			}			*dp++ = c; /* save output char */			word = IFS_WORD;		}	}}/* * Prepare to generate the string returned by ${} substitution. */static intvarsub(xp, sp, word, stypep, slenp)	Expand *xp;	char *sp;	char *word;	int *stypep;	/* becomes qualifier type */	int *slenp;	/* " " len (=, :=, etc.) valid iff *stypep != 0 */{	int c;	int state;	/* next state: XBASE, XARG, XSUB, XNULLSUB */	int stype;	/* substitution type */	int slen;	char *p;	struct tbl *vp;	if (sp[0] == '\0')	/* Bad variable name */		return -1;	xp->var = (struct tbl *) 0;	/* ${#var}, string length or array size */	if (sp[0] == '#' && (c = sp[1]) != '\0') {		int zero_ok = 0;		/* Can't have any modifiers for ${#...} */		if (*word != CSUBST)			return -1;		sp++;		/* Check for size of array */		if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') {			int n = 0;			int max = 0;			vp = global(arrayname(sp));			if (vp->flag & (ISSET|ARRAY))				zero_ok = 1;			for (; vp; vp = vp->u.array)				if (vp->flag & ISSET) {					max = vp->index + 1;					n++;				}			c = n; /* ksh88/ksh93 go for number, not max index */		} else if (c == '*' || c == '@')			c = e->loc->argc;		else {			p = str_val(global(sp));			zero_ok = p != null;			c = strlen(p);		}		if (Flag(FNOUNSET) && c == 0 && !zero_ok)			errorf("%s: parameter not set", sp);		*stypep = 0; /* unqualified variable/string substitution */		xp->str = str_save(ulton((unsigned long)c, 10), ATEMP);		return XSUB;	}	/* Check for qualifiers in word part */	stype = 0;	c = word[slen = 0] == CHAR ? word[1] : 0;	if (c == ':') {		slen += 2;		stype = 0x80;		c = word[slen + 0] == CHAR ? word[slen + 1] : 0;	}	if (ctype(c, C_SUBOP1)) {		slen += 2;		stype |= c;	} else if (ctype(c, C_SUBOP2)) { /* Note: ksh88 allows :%, :%%, etc */		slen += 2;		stype = c;		if (word[slen + 0] == CHAR && c == word[slen + 1]) {			stype |= 0x80;			slen += 2;		}	} else if (stype)	/* : is not ok */		return -1;	if (!stype && *word != CSUBST)		return -1;	*stypep = stype;	*slenp = slen;	c = sp[0];	if (c == '*' || c == '@') {		switch (stype & 0x7f) {		  case '=':	/* can't assign to a vector */		  case '%':	/* can't trim a vector (yet) */		  case '#':			return -1;		}		if (e->loc->argc == 0) {			xp->str = null;			state = c == '@' ? XNULLSUB : XSUB;		} else {			xp->u.strv = (const char **) e->loc->argv + 1;			xp->str = *xp->u.strv++;			xp->split = c == '@'; /* $@ */			state = XARG;		}	} else {		if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') {			XPtrV wv;			switch (stype & 0x7f) {			  case '=':	/* can't assign to a vector */			  case '%':	/* can't trim a vector (yet) */			  case '#':				return -1;			}			XPinit(wv, 32);			vp = global(arrayname(sp));			for (; vp; vp = vp->u.array) {				if (!(vp->flag&ISSET))					continue;				XPput(wv, str_val(vp));			}			if (XPsize(wv) == 0) {				xp->str = null;				state = p[1] == '@' ? XNULLSUB : XSUB;				XPfree(wv);			} else {				XPput(wv, 0);				xp->u.strv = (const char **) XPptrv(wv);				xp->str = *xp->u.strv++;				xp->split = p[1] == '@'; /* ${foo[@]} */				state = XARG;			}		} else {			/* Can't assign things like $! or $1 */			if ((stype & 0x7f) == '='			    && (ctype(*sp, C_VAR1) || digit(*sp)))				return -1;			xp->var = global(sp);			xp->str = str_val(xp->var);			state = XSUB;		}	}	c = stype&0x7f;	/* test the compiler's code generator */	if (ctype(c, C_SUBOP2) ||	    (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */	     c == '=' || c == '-' || c == '?' : c == '+'))		state = XBASE;	/* expand word instead of variable value */	if (Flag(FNOUNSET) && xp->str == null	    && (ctype(c, C_SUBOP2) || (state != XBASE && c != '+')))		errorf("%s: parameter not set", sp);	return state;}/* * Run the command in $(...) and read its output. */static intcomsub(xp, cp)	register Expand *xp;	char *cp;{	Source *s, *sold;	register struct op *t;	struct shf *shf;	s = pushs(SSTRING, ATEMP);	s->start = s->str = cp;	sold = source;	t = compile(s);	source = sold;	if (t == NULL)		return XBASE;	if (t != NULL && t->type == TCOM && /* $(<file) */	    *t->args == NULL && *t->vars == NULL && t->ioact != NULL) {		register struct ioword *io = *t->ioact;		char *name;		if ((io->flag&IOTYPE) != IOREAD)			errorf("funny $() command: %s",				snptreef((char *) 0, 32, "%R", io));		shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0,			SHF_MAPHI|SHF_CLEXEC);		if (shf == NULL)			errorf("%s: cannot open $() input", name);		xp->split = 0;	/* no waitlast() */	} else {		int ofd1, pv[2];		openpipe(pv);		shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0);		ofd1 = savefd(1, 0);	/* fd 1 may be closed... */		ksh_dup2(pv[1], 1, FALSE);		close(pv[1]);		execute(t, XFORK|XXCOM|XPIPEO);		restfd(1, ofd1);		startlast();		xp->split = 1;	/* waitlast() */	}	xp->u.shf = shf;	return XCOM;}/* * perform #pattern and %pattern substitution in ${} */static char *trimsub(str, pat, how)	register char *str;	char *pat;	int how;{	register char *end = strchr(str, 0);	register char *p, c;	switch (how&0xff) {	/* UCHAR_MAX maybe? */	  case '#':		/* shortest at begining */		for (p = str; p <= end; p++) {			c = *p; *p = '\0';			if (gmatch(str, pat, FALSE)) {				*p = c;				return p;			}			*p = c;		}		break;	  case '#'|0x80:	/* longest match at begining */		for (p = end; p >= str; p--) {			c = *p; *p = '\0';			if (gmatch(str, pat, FALSE)) {				*p = c;				return p;			}			*p = c;		}		break;

⌨️ 快捷键说明

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