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

📄 eval.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Expansion - quoting, separation, substitution, globbing */#include "sh.h"#include <pwd.h>#include "ksh_dir.h"#include "ksh_stat.h"/* * string expansion * * first pass: quoting, IFS separation, ~, ${}, $() and $(()) substitution. * second pass: alternation ({,}), filename expansion (*?[]). *//* expansion generator state */typedef struct Expand {	/* int  type; */	/* see expand() */	const char *str;	/* string */	union {		const char **strv;/* string[] */		struct shf *shf;/* file */	} u;			/* source */	struct tbl *var;	/* variable in ${var..} */	short	split;		/* split "$@" / call waitlast $() */} Expand;#define	XBASE		0	/* scanning original */#define	XSUB		1	/* expanding ${} string */#define	XARGSEP		2	/* ifs0 between "$*" */#define	XARG		3	/* expanding $*, $@ */#define	XCOM		4	/* expanding $() */#define XNULLSUB	5	/* "$@" when $# is 0 (don't generate word) *//* States used for field splitting */#define IFS_WORD	0	/* word has chars (or quotes) */#define IFS_WS		1	/* have seen IFS white-space */#define IFS_NWS		2	/* have seen IFS non-white-space */static	int	varsub ARGS((Expand *xp, char *sp, char *word, int *stypep, int *slenp));static	int	comsub ARGS((Expand *xp, char *cp));static	char   *trimsub ARGS((char *str, char *pat, int how));static	void	glob ARGS((char *cp, XPtrV *wp, int markdirs));static	void	globit ARGS((XString *xs, char **xpp, char *sp, XPtrV *wp,			     int check));static char	*maybe_expand_tilde ARGS((char *p, XString *dsp, char **dpp,					  int isassign));static	char   *tilde ARGS((char *acp));static	char   *homedir ARGS((char *name));#ifdef BRACE_EXPANDstatic void	alt_expand ARGS((XPtrV *wp, char *start, char *exp_start,				 char *end, int fdo));#endif/* compile and expand word */char *substitute(cp, f)	const char *cp;	int f;{	struct source *s, *sold;	sold = source;	s = pushs(SWSTR, ATEMP);	s->start = s->str = cp;	source = s;	if (yylex(ONEWORD) != LWORD)		internal_errorf(1, "substitute");	source = sold;	afree(s, ATEMP);	return evalstr(yylval.cp, f);}/* * expand arg-list */char **eval(ap, f)	register char **ap;	int f;{	XPtrV w;	if (*ap == NULL)		return ap;	XPinit(w, 32);	XPput(w, NULL);		/* space for shell name */#ifdef	SHARPBANG	XPput(w, NULL);		/* and space for one arg */#endif	while (*ap != NULL)		expand(*ap++, &w, f);	XPput(w, NULL);#ifdef	SHARPBANG	return (char **) XPclose(w) + 2;#else	return (char **) XPclose(w) + 1;#endif}/* * expand string */char *evalstr(cp, f)	char *cp;	int f;{	XPtrV w;	XPinit(w, 1);	expand(cp, &w, f);	cp = (XPsize(w) == 0) ? null : (char*) *XPptrv(w);	XPfree(w);	return cp;}/* * expand string - return only one component * used from iosetup to expand redirection files */char *evalonestr(cp, f)	register char *cp;	int f;{	XPtrV w;	XPinit(w, 1);	expand(cp, &w, f);	switch (XPsize(w)) {	case 0:		cp = null;		break;	case 1:		cp = (char*) *XPptrv(w);		break;	default:		cp = evalstr(cp, f&~DOGLOB);		break;	}	XPfree(w);	return cp;}/* for nested substitution: ${var:=$var2} */typedef struct SubType {	short	stype;		/* [=+-?%#] action after expanded word */	short	base;		/* begin position of expanded word */	short	f;		/* saved value of f (DOPAT, etc) */	struct tbl *var;	/* variable for ${var..} */	short	quote;		/* saved value of quote (for ${..[%#]..}) */	struct SubType *prev;	/* old type */	struct SubType *next;	/* poped type (to avoid re-allocating) */} SubType;voidexpand(cp, wp, f)	char *cp;		/* input word */	register XPtrV *wp;	/* output words */	int f;			/* DO* flags */{	register int UNINITIALIZED(c);	register int type;	/* expansion type */	register int quote = 0;	/* quoted */	XString ds;		/* destination string */	register char *dp, *sp;	/* dest., source */	int fdo, word;		/* second pass flags; have word */	int doblank;		/* field spliting of parameter/command subst */	Expand x;		/* expansion variables */	SubType st_head, *st;	int UNINITIALIZED(newlines); /* For trailing newlines in COMSUB */	int saw_eq, tilde_ok;	int make_magic;	if (cp == NULL)		internal_errorf(1, "expand(NULL)");	/* for alias, readonly, set, typeset commands */	if ((f & DOVACHECK) && is_wdvarassign(cp)) {		f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE);		f |= DOASNTILDE;	}	if (Flag(FNOGLOB))		f &= ~DOGLOB;	if (Flag(FMARKDIRS))		f |= DOMARKDIRS;#ifdef BRACE_EXPAND	if (Flag(FBRACEEXPAND) && (f & DOGLOB))		f |= DOBRACE_;#endif /* BRACE_EXPAND */	Xinit(ds, dp, 128, ATEMP);	/* init dest. string */	type = XBASE;	sp = cp;	fdo = 0;	saw_eq = 0;	tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; /* must be 1/0 */	doblank = 0;	make_magic = 0;	word = (f&DOBLANK) ? IFS_WS : IFS_WORD;	st_head.next = (SubType *) 0;	st = &st_head;	while (1) {		Xcheck(ds, dp);		switch (type) {		  case XBASE:	/* original prefixed string */			c = *sp++;			switch (c) {			  case EOS:				c = 0;				break;			  case CHAR:				c = *sp++;				break;			  case QCHAR:				quote |= 2; /* temporary quote */				c = *sp++;				break;			  case OQUOTE:				word = IFS_WORD;				tilde_ok = 0;				quote = 1;				continue;			  case CQUOTE:				quote = 0;				continue;			  case COMSUB:				tilde_ok = 0;				if (f & DONTRUNCOMMAND) {					word = IFS_WORD;					*dp++ = '$'; *dp++ = '(';					while (*sp != '\0') {						Xcheck(ds, dp);						*dp++ = *sp++;					}					*dp++ = ')';				} else {					type = comsub(&x, sp);					if (type == XCOM && (f&DOBLANK))						doblank++;					sp = strchr(sp, 0) + 1;					newlines = 0;				}				continue;			  case EXPRSUB:				word = IFS_WORD;				tilde_ok = 0;				if (f & DONTRUNCOMMAND) {					*dp++ = '$'; *dp++ = '('; *dp++ = '(';					while (*sp != '\0') {						Xcheck(ds, dp);						*dp++ = *sp++;					}					*dp++ = ')'; *dp++ = ')';				} else {					struct tbl v;					char *p;					v.flag = DEFINED|ISSET|INTEGER;					v.type = 10; /* not default */					v.name[0] = '\0';					v_evaluate(&v, substitute(sp, 0),						KSH_UNWIND_ERROR);					sp = strchr(sp, 0) + 1;					for (p = str_val(&v); *p; ) {						Xcheck(ds, dp);						*dp++ = *p++;					}				}				continue;			  case OSUBST: /* ${{#}var{:}[=+-?#%]word} */			  /* format is:			   *   OSUBST [{x] plain-variable-part \0			   *     compiled-word-part CSUBST [}x]			   * This is were all syntax checking gets done...			   */			  {				char *varname = ++sp; /* skip the { or x (}) */				int stype;				int slen;				sp = strchr(sp, '\0') + 1; /* skip variable */				type = varsub(&x, varname, sp, &stype, &slen);				if (type < 0) {					char endc;					char *str, *end;					end = (char *) wdscan(sp, CSUBST);					/* ({) the } or x is already skipped */					endc = *end;					*end = EOS;					str = snptreef((char *) 0, 64, "%S",							varname - 1);					*end = endc;					errorf("%s: bad substitution", str);				}				if (f&DOBLANK)					doblank++;				tilde_ok = 0;				if (type == XBASE) {	/* expand? */					if (!st->next) {						SubType *newst;						newst = (SubType *) alloc(							sizeof(SubType), ATEMP);						newst->next = (SubType *) 0;						newst->prev = st;						st->next = newst;					}					st = st->next;					st->stype = stype;					st->base = Xsavepos(ds, dp);					st->f = f;					st->var = x.var;					st->quote = quote;					/* skip qualifier(s) */					if (stype)						sp += slen;					switch (stype & 0x7f) {					  case '#':					  case '%':						/* ! DOBLANK,DOBRACE_,DOTILDE */						f = DOPAT | (f&DONTRUNCOMMAND)						    | DOTEMP_;						quote = 0;						/* Prepend open pattern (so |						 * in a trim will work as						 * expected)						 */						*dp++ = MAGIC;						*dp++ = '@' + 0x80;						break;					  case '=':						/* Enabling tilde expansion						 * after :'s here is						 * non-standard ksh, but is						 * consistent with rules for						 * other assignments.  Not						 * sure what POSIX thinks of						 * this.						 * Not doing tilde expansion						 * for integer variables is a						 * non-POSIX thing - makes						 * sense though, since ~ is						 * a arithmetic operator.						 */						if (!(x.var->flag & INTEGER))							f |= DOASNTILDE|DOTILDE;						f |= DOTEMP_;						/* These will be done after the						 * value has been assigned.						 */						f &= ~(DOBLANK|DOGLOB|DOBRACE_);						tilde_ok = 1;						break;					  case '?':						f &= ~DOBLANK;						f |= DOTEMP_;						/* fall through */					  default:						/* Enable tilde expansion */						tilde_ok = 1;						f |= DOTILDE;					}				} else					/* skip word */					sp = (char *) wdscan(sp, CSUBST);				continue;			  }			  case CSUBST: /* only get here if expanding word */				sp++; /* ({) skip the } or x */				tilde_ok = 0;	/* in case of ${unset:-} */				*dp = '\0';				quote = st->quote;				f = st->f;				if (f&DOBLANK)					doblank--;				switch (st->stype&0x7f) {				  case '#':				  case '%':					/* Append end-pattern */					*dp++ = MAGIC; *dp++ = ')'; *dp = '\0';					dp = Xrestpos(ds, dp, st->base);					/* Must use st->var since calling					 * global would break things					 * like x[i+=1].					 */					x.str = trimsub(str_val(st->var),						dp, st->stype);					type = XSUB;					if (f&DOBLANK)						doblank++;					st = st->prev;					continue;				  case '=':					/* Restore our position and substitute					 * the value of st->var (may not be					 * the assigned value in the presence					 * of integer/right-adj/etc attributes).					 */					dp = Xrestpos(ds, dp, st->base);					/* Must use st->var since calling					 * global would cause with things					 * like x[i+=1] to be evaluated twice.					 */					/* Note: not exported by FEXPORT					 * in at&t ksh.					 */					/* XXX POSIX says readonly is only					 * fatal for special builtins (setstr					 * does readonly check).					 */					setstr(st->var, debunk(						(char *) alloc(strlen(dp) + 1,							ATEMP), dp),						KSH_UNWIND_ERROR);					x.str = str_val(st->var);					type = XSUB;					if (f&DOBLANK)						doblank++;					st = st->prev;					continue;				  case '?':				    {					char *s = Xrestpos(ds, dp, st->base);					errorf("%s: %s", st->var->name,					    dp == s ? 					      "parameter null or not set"					    : (debunk(s, s), s));				    }				}				st = st->prev;				type = XBASE;				continue;			  case OPAT: /* open pattern: *(foo|bar) */				/* Next char is the type of pattern */				make_magic = 1;				c = *sp++ + 0x80;				break;			  case SPAT: /* pattern seperator (|) */				make_magic = 1;				c = '|';				break;			  case CPAT: /* close pattern */				make_magic = 1;				c = /*(*/ ')';				break;			}			break;		  case XNULLSUB:			/* Special case for "$@" (and "${foo[@]}") - no

⌨️ 快捷键说明

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