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

📄 eval.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 3 页
字号:
	  case '%':		/* shortest match at end */		for (p = end; p >= str; p--) {			if (gmatch(p, pat, FALSE))				return str_nsave(str, p - str, ATEMP);		}		break;	  case '%'|0x80:	/* longest match at end */		for (p = str; p <= end; p++) {			if (gmatch(p, pat, FALSE))				return str_nsave(str, p - str, ATEMP);		}		break;	}	return str;		/* no match, return string */}/* * glob * Name derived from V6's /etc/glob, the program that expanded filenames. *//* XXX cp not const 'cause slashes are temporarily replaced with nulls... */static voidglob(cp, wp, markdirs)	char *cp;	register XPtrV *wp;	int markdirs;{	int oldsize = XPsize(*wp);	if (glob_str(cp, wp, markdirs) == 0)		XPput(*wp, debunk(cp, cp));	else		qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize),			xstrcmp);}#define GF_NONE		0#define GF_EXCHECK	BIT(0)		/* do existance check on file */#define GF_GLOBBED	BIT(1)		/* some globbing has been done */#define GF_MARKDIR	BIT(2)		/* add trailing / to directories *//* Apply file globbing to cp and store the matching files in wp.  Returns * the number of matches found. */intglob_str(cp, wp, markdirs)	char *cp;	XPtrV *wp;	int markdirs;{	int oldsize = XPsize(*wp);	XString xs;	char *xp;	Xinit(xs, xp, 256, ATEMP);	globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE);	Xfree(xs, xp);	return XPsize(*wp) - oldsize;}static voidglobit(xs, xpp, sp, wp, check)	XString *xs;		/* dest string */	char **xpp;		/* ptr to dest end */	char *sp;		/* source path */	register XPtrV *wp;	/* output list */	int check;		/* GF_* flags */{	register char *np;	/* next source component */	char *xp = *xpp;	char *se;	char odirsep;	/* This to allow long expansions to be interrupted */	intrcheck();	if (sp == NULL) {	/* end of source path */		/* We only need to check if the file exists if a pattern		 * is followed by a non-pattern (eg, foo*x/bar; no check		 * is needed for foo* since the match must exist) or if		 * any patterns were expanded and the markdirs option is set.		 * Symlinks make things a bit tricky...		 */		if ((check & GF_EXCHECK)		    || ((check & GF_MARKDIR) && (check & GF_GLOBBED)))		{#define stat_check()	(stat_done ? stat_done : \			    (stat_done = stat(Xstring(*xs, xp), &statb) < 0 \				? -1 : 1))			struct stat lstatb, statb;			int stat_done = 0;	 /* -1: failed, 1 ok */			if (lstat(Xstring(*xs, xp), &lstatb) < 0)				return;			/* special case for systems which strip trailing			 * slashes from regular files (eg, /etc/passwd/).			 * SunOS 4.1.3 does this...			 */			if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp)			    && ISDIRSEP(xp[-1]) && !S_ISDIR(lstatb.st_mode)#ifdef S_ISLNK			    && (!S_ISLNK(lstatb.st_mode)				|| stat_check() < 0				|| !S_ISDIR(statb.st_mode))#endif /* S_ISLNK */				)				return;			/* Possibly tack on a trailing / if there isn't already			 * one and if the file is a directory or a symlink to a			 * directory			 */			if (((check & GF_MARKDIR) && (check & GF_GLOBBED))			    && xp > Xstring(*xs, xp) && !ISDIRSEP(xp[-1])			    && (S_ISDIR(lstatb.st_mode)#ifdef S_ISLNK				|| (S_ISLNK(lstatb.st_mode)				    && stat_check() > 0				    && S_ISDIR(statb.st_mode))#endif /* S_ISLNK */				    ))			{				*xp++ = DIRSEP;				*xp = '\0';			}		}#ifdef OS2 /* Done this way to avoid bug in gcc 2.7.2... */    /* Ugly kludge required for command     * completion - see how search_access()     * is implemented for OS/2...     */# define KLUDGE_VAL	4#else /* OS2 */# define KLUDGE_VAL	0#endif /* OS2 */		XPput(*wp, str_nsave(Xstring(*xs, xp), Xlength(*xs, xp)			+ KLUDGE_VAL, ATEMP));		return;	}	if (xp > Xstring(*xs, xp))		*xp++ = DIRSEP;	while (ISDIRSEP(*sp)) {		Xcheck(*xs, xp);		*xp++ = *sp++;	}	np = ksh_strchr_dirsep(sp);	if (np != NULL) {		se = np;		odirsep = *np;	/* don't assume DIRSEP, can be multiple kinds */		*np++ = '\0';	} else {		odirsep = '\0'; /* keep gcc quiet */		se = sp + strlen(sp);	}	/* Check if sp needs globbing - done to avoid pattern checks for strings	 * containing MAGIC characters, open ['s without the matching close ],	 * etc. (otherwise opendir() will be called which may fail because the	 * directory isn't readable - if no globbing is needed, only execute	 * permission should be required (as per POSIX)).	 */	if (!has_globbing(sp, se)) {		XcheckN(*xs, xp, se - sp + 1);		debunk(xp, sp);		xp += strlen(xp);		*xpp = xp;		globit(xs, xpp, np, wp, check);	} else {		DIR *dirp;		struct dirent *d;		char *name;		int len;		int prefix_len;		/* xp = *xpp;	   copy_non_glob() may have re-alloc'd xs */		*xp = '\0';		prefix_len = Xlength(*xs, xp);		dirp = ksh_opendir(prefix_len ? Xstring(*xs, xp) : ".");		if (dirp == NULL)			goto Nodir;		while ((d = readdir(dirp)) != NULL) {			name = d->d_name;			if (name[0] == '.' &&			    (name[1] == 0 || (name[1] == '.' && name[2] == 0)))				continue; /* always ignore . and .. */			if ((*name == '.' && *sp != '.')			    || !gmatch(name, sp, TRUE))				continue;			len = NLENGTH(d) + 1;			XcheckN(*xs, xp, len);			memcpy(xp, name, len);			*xpp = xp + len - 1;			globit(xs, xpp, np, wp,				(check & GF_MARKDIR) | GF_GLOBBED				| (np ? GF_EXCHECK : GF_NONE));			xp = Xstring(*xs, xp) + prefix_len;		}		closedir(dirp);	  Nodir:;	}	if (np != NULL)		*--np = odirsep;}#if 0/* Check if p contains something that needs globbing; if it does, 0 is * returned; if not, p is copied into xs/xp after stripping any MAGICs */static int	copy_non_glob ARGS((XString *xs, char **xpp, char *p));static intcopy_non_glob(xs, xpp, p)	XString *xs;	char **xpp;	char *p;{	char *xp;	int len = strlen(p);	XcheckN(*xs, *xpp, len);	xp = *xpp;	for (; *p; p++) {		if (ISMAGIC(*p)) {			int c = *++p;			if (c == '*' || c == '?')				return 0;			if (*p == '[') {				char *q = p + 1;				if (ISMAGIC(*q) && q[1] == NOT)					q += 2;				if (ISMAGIC(*q) && q[1] == ']')					q += 2;				for (; *q; q++)					if (ISMAGIC(*q) && *++q == ']')						return 0;				/* pass a literal [ through */			}			/* must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, etc. */		}		*xp++ = *p;	}	*xp = '\0';	*xpp = xp;	return 1;}#endif /* 0 *//* remove MAGIC from string */char *debunk(dp, sp)	char *dp;	const char *sp;{	char *d, *s;	if ((s = strchr(sp, MAGIC))) {		memcpy(dp, sp, s - sp);		for (d = dp + (s - sp); *s; s++)			if (!ISMAGIC(*s) || !(*++s & 0x80)			    || !strchr("*+?@! ", *s & 0x7f))				*d++ = *s;			else {				/* extended pattern operators: *+?@! */				if ((*s & 0x7f) != ' ')					*d++ = *s & 0x7f;				*d++ = '(';			}		*d = '\0';	} else if (dp != sp)		strcpy(dp, sp);	return dp;}/* Check if p is an unquoted name, possibly followed by a / or :.  If so * puts the expanded version in *dcp,dp and returns a pointer in p just * past the name, otherwise returns 0. */static char *maybe_expand_tilde(p, dsp, dpp, isassign)	char *p;	XString *dsp;	char **dpp;	int isassign;{	XString ts;	char *dp = *dpp;	char *tp, *r;	Xinit(ts, tp, 16, ATEMP);	/* : only for DOASNTILDE form */	while (p[0] == CHAR && !ISDIRSEP(p[1])	       && (!isassign || p[1] != PATHSEP))	{		Xcheck(ts, tp);		*tp++ = p[1];		p += 2;	}	*tp = '\0';	r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? tilde(Xstring(ts, tp)) : (char *) 0;	Xfree(ts, tp);	if (r) {		while (*r) {			Xcheck(*dsp, dp);			if (ISMAGIC(*r))				*dp++ = MAGIC;			*dp++ = *r++;		}		*dpp = dp;		r = p;	}	return r;}/* * tilde expansion * * based on a version by Arnold Robbins */static char *tilde(cp)	char *cp;{	char *dp;	if (cp[0] == '\0')		dp = str_val(global("HOME"));	else if (cp[0] == '+' && cp[1] == '\0')		dp = str_val(global("PWD"));	else if (cp[0] == '-' && cp[1] == '\0')		dp = str_val(global("OLDPWD"));	else		dp = homedir(cp);	/* If HOME, PWD or OLDPWD are not set, don't expand ~ */	if (dp == null)		dp = (char *) 0;	return dp;}/* * map userid to user's home directory. * note that 4.3's getpw adds more than 6K to the shell, * and the YP version probably adds much more. * we might consider our own version of getpwnam() to keep the size down. */static char *homedir(name)	char *name;{	register struct tbl *ap;	ap = tenter(&homedirs, name, hash(name));	if (!(ap->flag & ISSET)) {#ifdef OS2		/* No usernames in OS2 - punt */		return NULL;#else /* OS2 */		struct passwd *pw;		pw = getpwnam(name);		if (pw == NULL)			return NULL;		ap->val.s = str_save(pw->pw_dir, APERM);		ap->flag |= DEFINED|ISSET|ALLOC;#endif /* OS2 */	}	return ap->val.s;}#ifdef BRACE_EXPANDstatic voidalt_expand(wp, start, exp_start, end, fdo)	XPtrV *wp;	char *start, *exp_start;	char *end;	int fdo;{	int UNINITIALIZED(count);	char *brace_start, *brace_end, *UNINITIALIZED(comma);	char *field_start;	char *p;	/* search for open brace */	for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != OBRACE; p += 2)		;	brace_start = p;	/* find matching close brace, if any */	if (p) {		comma = (char *) 0;		count = 1;		for (p += 2; *p && count; p++) {			if (ISMAGIC(*p)) {				if (*++p == OBRACE)					count++;				else if (*p == CBRACE)					--count;				else if (*p == ',' && count == 1)					comma = p;			}		}	}	/* no valid expansions... */	if (!p || count != 0) {		/* Note that given a{{b,c} we do not expand anything (this is		 * what at&t ksh does.  This may be changed to do the {b,c}		 * expansion. }		 */		if (fdo & DOGLOB)			glob(start, wp, fdo & DOMARKDIRS);		else			XPput(*wp, debunk(start, start));		return;	}	brace_end = p;	if (!comma) {		alt_expand(wp, start, brace_end, end, fdo);		return;	}	/* expand expression */	field_start = brace_start + 2;	count = 1;	for (p = brace_start + 2; p != brace_end; p++) {		if (ISMAGIC(*p)) {			if (*++p == OBRACE)				count++;			else if ((*p == CBRACE && --count == 0)				 || (*p == ',' && count == 1))			{				char *new;				int l1, l2, l3;				l1 = brace_start - start;				l2 = (p - 1) - field_start;				l3 = end - brace_end;				new = (char *) alloc(l1 + l2 + l3 + 1, ATEMP);				memcpy(new, start, l1);				memcpy(new + l1, field_start, l2);				memcpy(new + l1 + l2, brace_end, l3);				new[l1 + l2 + l3] = '\0';				alt_expand(wp, new, new + l1,					   new + l1 + l2 + l3, fdo);				field_start = p + 1;			}		}	}	return;}#endif /* BRACE_EXPAND */

⌨️ 快捷键说明

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