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

📄 glob.c

📁 早期freebsd实现
💻 C
字号:
/* glob.c: rc's (ugly) globber. This code is not elegant, but it works */#include <sys/types.h>#include <sys/stat.h>#include "rc.h"#include <dirent.h>static List *dmatch(char *, char *, char *);static List *doglob(char *, char *);static List *lglob(List *, char *, char *, size_t);static List *sort(List *);/*   Matches a list of words s against a list of patterns p. Returns true iff   a pattern in p matches a word in s. () matches (), but otherwise null   patterns match nothing.*/extern bool lmatch(List *s, List *p) {	List *q;	int i;	bool okay;	if (s == NULL) {		if (p == NULL) /* null matches null */			return TRUE;		for (; p != NULL; p = p->n) { /* one or more stars match null */			if (*p->w != '\0') { /* the null string is a special case; it does *not* match () */				okay = TRUE;				for (i = 0; p->w[i] != '\0'; i++)					if (p->w[i] != '*' || p->m[i] != 1) {						okay = FALSE;						break;					}				if (okay)					return TRUE;			}		}		return FALSE;	}	for (; s != NULL; s = s->n)		for (q = p; q != NULL; q = q->n)			if (match(q->w, q->m, s->w))				return TRUE;	return FALSE;}/*   Globs a list; checks to see if each element in the list has a metacharacter. If it   does, it is globbed, and the output is sorted.*/extern List *glob(List *s) {	List *top, *r;	bool meta;	for (r = s, meta = FALSE; r != NULL; r = r->n)		if (r->m != NULL)			meta = TRUE;	if (!meta)		return s; /* don't copy lists with no metacharacters in them */	for (top = r = NULL; s != NULL; s = s->n) {		if (s->m == NULL) { /* no metacharacters; just tack on to the return list */			if (top == NULL)				top = r = nnew(List);			else				r = r->n = nnew(List);			r->w = s->w;		} else {			if (top == NULL)				top = r = sort(doglob(s->w, s->m));			else				r->n = sort(doglob(s->w, s->m));			while (r->n != NULL)				r = r->n;		}	}	r->n = NULL;	return top;}/* Matches a pattern p against the contents of directory d */static List *dmatch(char *d, char *p, char *m) {	bool matched = FALSE;	List *top, *r;	static DIR *dirp;	static struct dirent *dp;	static struct stat s;	/* prototypes for XXXdir functions. comment out if necessary */	extern DIR *opendir(const char *);	extern struct dirent *readdir(DIR *);	/*extern int closedir(DIR *);*/	top = r = NULL;	/* opendir succeeds on regular files on some systems, so the stat() call is necessary (sigh) */	if (stat(d, &s) < 0 || (s.st_mode & S_IFMT) != S_IFDIR || (dirp = opendir(d)) == NULL)		return NULL;	while ((dp = readdir(dirp)) != NULL)		if ((*dp->d_name != '.' || *p == '.') && match(p, m, dp->d_name)) { /* match ^. explicitly */			matched = TRUE;			if (top == NULL)				top = r = nnew(List);			else				r = r->n = nnew(List);			r->w = ncpy(dp->d_name);			r->m = NULL;		}	closedir(dirp);	if (!matched)		return NULL;	r->n = NULL;	return top;}/*   lglob() globs a pattern agains a list of directory roots. e.g., (/tmp /usr /bin) "*"   will return a list with all the files in /tmp, /usr, and /bin. NULL on no match.   slashcount indicates the number of slashes to stick between the directory and the   matched name. e.g., for matching ////tmp/////foo**/static List *lglob(List *s, char *p, char *m, size_t slashcount) {	List *q, *r, *top, foo;	static List slash;	static size_t slashsize = 0;	if (slashcount + 1 > slashsize) {		slash.w = ealloc(slashcount + 1);		slashsize = slashcount;	}	slash.w[slashcount] = '\0';	while (slashcount > 0)		slash.w[--slashcount] = '/';	for (top = r = NULL; s != NULL; s = s->n) {		q = dmatch(s->w, p, m);		if (q != NULL) {			foo.w = s->w;			foo.m = NULL;			foo.n = NULL;			if (!(s->w[0] == '/' && s->w[1] == '\0')) /* need to separate */				q = concat(&slash, q);		  /* dir/name with slash */			q = concat(&foo, q);			if (r == NULL)				top = r = q;			else				r->n = q;			while (r->n != NULL)				r = r->n;		}	}	return top;}/*   Doglob globs a pathname in pattern form against a unix path. Returns the original   pattern (cleaned of metacharacters) on failure, or the globbed string(s).*/static List *doglob(char *w, char *m) {	static char *dir = NULL, *pattern = NULL, *metadir = NULL, *metapattern = NULL;	static size_t dsize = 0;	char *d, *p, *md, *mp;	size_t psize;	char *s = w;	List firstdir;	List *matched;	if ((psize = strlen(w) + 1) > dsize || dir == NULL) {		efree(dir); efree(pattern); efree(metadir); efree(metapattern);		dir = ealloc(psize);		pattern = ealloc(psize);		metadir = ealloc(psize);		metapattern = ealloc(psize);		dsize = psize;	}	d = dir;	p = pattern;	md = metadir;	mp = metapattern;	if (*s == '/')		while (*s == '/')			*d++ = *s++, *md++ = *m++;	else		while (*s != '/' && *s != '\0')			*d++ = *s++, *md++ = *m++; /* get first directory component */	*d = '\0';	/*	   Special case: no slashes in the pattern, i.e., open the current directory.	   Remember that w cannot consist of slashes alone (the other way *s could be	   zero) since doglob gets called iff there's a metacharacter to be matched	*/	if (*s == '\0') {		matched = dmatch(".", dir, metadir);		goto end;	}	if (*w == '/') {		firstdir.w = dir;		firstdir.m = metadir;		firstdir.n = NULL;		matched = &firstdir;	} else {		/*		   we must glob against current directory,		   since the first character is not a slash.		*/		matched = dmatch(".", dir, metadir);	}	do {		size_t slashcount;		SIGCHK;		for (slashcount = 0; *s == '/'; s++, m++)			slashcount++; /* skip slashes */		while (*s != '/' && *s != '\0')			*p++ = *s++, *mp++ = *m++; /* get pattern */		*p = '\0';		matched = lglob(matched, pattern, metapattern, slashcount);		p = pattern, mp = metapattern;	} while (*s != '\0');end:	if (matched == NULL) {		matched = nnew(List);		matched->w = w;		matched->m = NULL;		matched->n = NULL;	}	return matched;}static List *sort(List *s) {	size_t nel = listnel(s);	if (nel > 1) {		char **a;		List *t;		qsort(a = list2array(s, FALSE), nel, sizeof(char *), starstrcmp);		for (t = s; t != NULL; t = t->n)			t->w = *a++;	}	return s;}

⌨️ 快捷键说明

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