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

📄 edit.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (x_basename(words[i] + prefix_len, (char *) 0)							> prefix_len)				break;		/* All in same directory? */		if (i == nwords) {			while (prefix_len > 0			       && !ISDIRSEP(words[0][prefix_len - 1]))				prefix_len--;			use_copy = 1;			XPinit(l, nwords + 1);			for (i = 0; i < nwords; i++)				XPput(l, words[i] + prefix_len);			XPput(l, (char *) 0);		}	}	/*	 * Enumerate expansions	 */	x_putc('\r');	x_putc('\n');	pr_menu(use_copy ? (char **) XPptrv(l) : words);	if (use_copy)		XPfree(l); /* not x_free_words() */}/* *  Do file globbing: *	- appends * to (copy of) str if no globbing chars found *	- does expansion, checks for no match, etc. *	- sets *wordsp to array of matching strings *	- returns number of matching strings */static intx_file_glob(flags, str, slen, wordsp)	int flags;	const char *str;	int slen;	char ***wordsp;{	char *toglob;	char **words;	int nwords;	XPtrV w;	struct source *s, *sold;	if (slen < 0)		return 0;	toglob = add_glob(str, slen);	/*	 * Convert "foo*" (toglob) to an array of strings (words)	 */	sold = source;	s = pushs(SWSTR, ATEMP);	s->start = s->str = toglob;	source = s;	if (yylex(ONEWORD) != LWORD) {		source = sold;		internal_errorf(0, "fileglob: substitute error");		return 0;	}	source = sold;	XPinit(w, 32);	expand(yylval.cp, &w, DOGLOB|DOTILDE|DOMARKDIRS);	XPput(w, NULL);	words = (char **) XPclose(w);	for (nwords = 0; words[nwords]; nwords++)		;	if (nwords == 1) {		struct stat statb;		/* Check if globbing failed (returned glob pattern),		 * but be careful (E.g. toglob == "ab*" when the file		 * "ab*" exists is not an error).		 * Also, check for empty result - happens if we tried		 * to glob something which evaluated to an empty		 * string (e.g., "$FOO" when there is no FOO, etc).		 */		if ((strcmp(words[0], toglob) == 0		     && stat(words[0], &statb) < 0)		    || words[0][0] == '\0')		{			x_free_words(nwords, words);			nwords = 0;		}	}	afree(toglob, ATEMP);	*wordsp = nwords ? words : (char **) 0;	return nwords;}/* Data structure used in x_command_glob() */struct path_order_info {	char *word;	int base;	int path_order;};/* Compare routine used in x_command_glob() */static intpath_order_cmp(aa, bb)	const void *aa;	const void *bb;{	const struct path_order_info *a = (const struct path_order_info *) aa;	const struct path_order_info *b = (const struct path_order_info *) bb;	int t;	t = FILECMP(a->word + a->base, b->word + b->base);	return t ? t : a->path_order - b->path_order;}static intx_command_glob(flags, str, slen, wordsp)	int flags;	const char *str;	int slen;	char ***wordsp;{	char *toglob;	char *pat;	char *fpath;	int nwords;	XPtrV w;	struct block *l;	if (slen < 0)		return 0;	toglob = add_glob(str, slen);	/* Convert "foo*" (toglob) to a pattern for future use */	pat = evalstr(toglob, DOPAT|DOTILDE);	afree(toglob, ATEMP);	XPinit(w, 32);	glob_table(pat, &w, &keywords);	glob_table(pat, &w, &aliases);	glob_table(pat, &w, &builtins);	for (l = e->loc; l; l = l->next)		glob_table(pat, &w, &l->funs);	glob_path(flags, pat, &w, path);	if ((fpath = str_val(global("FPATH"))) != null)		glob_path(flags, pat, &w, fpath);	nwords = XPsize(w);	if (!nwords) {		*wordsp = (char **) 0;		XPfree(w);		return 0;	}	/* Sort entries */	if (flags & XCF_FULLPATH) {		/* Sort by basename, then path order */		struct path_order_info *info;		struct path_order_info *last_info = 0;		char **words = (char **) XPptrv(w);		int path_order = 0;		int i;		info = (struct path_order_info *)			alloc(sizeof(struct path_order_info) * nwords, ATEMP);		for (i = 0; i < nwords; i++) {			info[i].word = words[i];			info[i].base = x_basename(words[i], (char *) 0);			if (!last_info || info[i].base != last_info->base			    || FILENCMP(words[i],					last_info->word, info[i].base) != 0)			{				last_info = &info[i];				path_order++;			}			info[i].path_order = path_order;		}		qsort(info, nwords, sizeof(struct path_order_info),			path_order_cmp);		for (i = 0; i < nwords; i++)			words[i] = info[i].word;		afree((void *) info, ATEMP);	} else {		/* Sort and remove duplicate entries */		char **words = (char **) XPptrv(w);		int i, j;		qsortp(XPptrv(w), (size_t) nwords, xstrcmp);		for (i = j = 0; i < nwords - 1; i++) {			if (strcmp(words[i], words[i + 1]))				words[j++] = words[i];			else				afree(words[i], ATEMP);		}		words[j++] = words[i];		nwords = j;		w.cur = (void **) &words[j];	}	XPput(w, NULL);	*wordsp = (char **) XPclose(w);	return nwords;}#define IS_WORDC(c)	!(ctype(c, C_LEX1) || (c) == '\'' || (c) == '"')static intx_locate_word(buf, buflen, pos, startp, is_commandp)	const char *buf;	int buflen;	int pos;	int *startp;	int *is_commandp;{	int p;	int start, end;	/* Bad call?  Probably should report error */	if (pos < 0 || pos > buflen) {		*startp = pos;		*is_commandp = 0;		return 0;	}	/* The case where pos == buflen happens to take care of itself... */	start = pos;	/* Keep going backwards to start of word (has effect of allowing	 * one blank after the end of a word)	 */	for (; start > 0 && IS_WORDC(buf[start - 1]); start--)		;	/* Go forwards to end of word */	for (end = start; end < buflen && IS_WORDC(buf[end]); end++)		;	if (is_commandp) {		int iscmd;		/* Figure out if this is a command */		for (p = start - 1; p >= 0 && isspace(buf[p]); p--)			;		iscmd = p < 0 || strchr(";|&()", buf[p]);		if (iscmd) {			/* If command has a /, path, etc. is not searched;			 * only current directory is searched, which is just			 * like file globbing.			 */			for (p = start; p < end; p++)				if (ISDIRSEP(buf[p]))					break;			iscmd = p == end;		}		*is_commandp = iscmd;	}	*startp = start;	return end - start;}intx_cf_glob(flags, buf, buflen, pos, startp, endp, wordsp, is_commandp)	int flags;	const char *buf;	int buflen;	int pos;	int *startp;	int *endp;	char ***wordsp;	int *is_commandp;{	int len;	int nwords;	char **words;	int is_command;	len = x_locate_word(buf, buflen, pos, startp, &is_command);	if (!(flags & XCF_COMMAND))		is_command = 0;	/* Don't do command globing on zero length strings - it takes too	 * long and isn't very useful.  File globs are more likely to be	 * useful, so allow these.	 */	if (len == 0 && is_command)		return 0;	nwords = (is_command ? x_command_glob : x_file_glob)(flags,				    buf + *startp, len, &words);	if (nwords == 0) {		*wordsp = (char **) 0;		return 0;	}	if (is_commandp)		*is_commandp = is_command;	*wordsp = words;	*endp = *startp + len;	return nwords;}/* Given a string, copy it and possibly add a '*' to the end.  The * new string is returned. */static char *add_glob(str, slen)	const char *str;	int slen;{	char *toglob;	char *s;	bool_t saw_slash = FALSE;	if (slen < 0)		return (char *) 0;	toglob = str_nsave(str, slen + 1, ATEMP); /* + 1 for "*" */	toglob[slen] = '\0';	/*	 * If the pathname contains a wildcard (an unquoted '*',	 * '?', or '[') or parameter expansion ('$'), or a ~username	 * with no trailing slash, then it is globbed based on that	 * value (i.e., without the appended '*').	 */	for (s = toglob; *s; s++) {		if (*s == '\\' && s[1])			s++;		else if (*s == '*' || *s == '[' || *s == '?' || *s == '$'			 || (s[1] == '(' /*)*/ && strchr("*+?@!", *s)))			break;		else if (ISDIRSEP(*s))			saw_slash = TRUE;	}	if (!*s && (*toglob != '~' || saw_slash)) {		toglob[slen] = '*';		toglob[slen + 1] = '\0';	}	return toglob;}/* * Find longest common prefix */intx_longest_prefix(nwords, words)	int nwords;	char *const *words;{	int i, j;	int prefix_len;	char *p;	if (nwords <= 0)		return 0;	prefix_len = strlen(words[0]);	for (i = 1; i < nwords; i++)		for (j = 0, p = words[i]; j < prefix_len; j++)			if (FILECHCONV(p[j]) != FILECHCONV(words[0][j])) {				prefix_len = j;				break;			}	return prefix_len;}voidx_free_words(nwords, words)	int nwords;	char **words;{	int i;	for (i = 0; i < nwords; i++)		if (words[i])			afree(words[i], ATEMP);	afree(words, ATEMP);}/* Return the offset of the basename of string s (which ends at se - need not * be null terminated).  Trailing slashes are ignored.  If s is just a slash, * then the offset is 0 (actually, length - 1). *	s		Return *	/etc		1 *	/etc/		1 *	/etc//		1 *	/etc/fo		5 *	foo		0 *	///		2 *			0 */intx_basename(s, se)	const char *s;	const char *se;{	const char *p;	if (se == (char *) 0)		se = s + strlen(s);	if (s == se)		return 0;	/* Skip trailing slashes */	for (p = se - 1; p > s && ISDIRSEP(*p); p--)		;	for (; p > s && !ISDIRSEP(*p); p--)		;	if (ISDIRSEP(*p) && p + 1 < se)		p++;	return p - s;}/* *  Apply pattern matching to a table: all table entries that match a pattern * are added to wp. */static voidglob_table(pat, wp, tp)	const char *pat;	XPtrV *wp;	struct table *tp;{	struct tstate ts;	struct tbl *te;	for (twalk(&ts, tp); (te = tnext(&ts)); ) {		if (gmatch(te->name, pat, FALSE))			XPput(*wp, str_save(te->name, ATEMP));	}}static voidglob_path(flags, pat, wp, path)	int flags;	const char *pat;	XPtrV *wp;	const char *path;{	const char *sp, *p;	char *xp;	int pathlen;	int patlen;	int oldsize, newsize, i, j;	char **words;	XString xs;	patlen = strlen(pat) + 1;	sp = path;	Xinit(xs, xp, patlen + 128, ATEMP);	while (sp) {		xp = Xstring(xs, xp);		if (!(p = strchr(sp, PATHSEP)))			p = sp + strlen(sp);		pathlen = p - sp;		if (pathlen) {			/* Copy sp into xp, stuffing any MAGIC characters			 * on the way			 */			const char *s = sp;			XcheckN(xs, xp, pathlen * 2);			while (s < p) {				if (ISMAGIC(*s))					*xp++ = MAGIC;				*xp++ = *s++;			}			*xp++ = DIRSEP;			pathlen++;		}		sp = p;		XcheckN(xs, xp, patlen);		memcpy(xp, pat, patlen);		oldsize = XPsize(*wp);		glob_str(Xstring(xs, xp), wp, 0);		newsize = XPsize(*wp);		/* Check that each match is executable... */		words = (char **) XPptrv(*wp);		for (i = j = oldsize; i < newsize; i++) {			if (search_access(words[i], X_OK, (int *) 0) >= 0) {				words[j] = words[i];				if (!(flags & XCF_FULLPATH))					memmove(words[j], words[j] + pathlen,						strlen(words[j] + pathlen) + 1);				j++;			} else				afree(words[i], ATEMP);		}		wp->cur = (void **) &words[j];		if (!*sp++)			break;	}	Xfree(xs, xp);}#endif /* EDIT */

⌨️ 快捷键说明

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