glob.c

来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 220 行

C
220
字号
#include <u.h>#include <libc.h>#include <regexp.h>#include <String.h>#include "glob.h"/* *  I wrote this glob so that there would be no limit *  on element or path size.  The one in rc is probably *  better, certainly faster. - presotto */static Glob*globnew(void){	Glob *g;	g = mallocz(sizeof(*g), 1);	if(g == nil)		sysfatal("globnew: %r");	return g;}static voidglobfree1(Glob *g){	s_free(g->glob);	free(g);}static voidglobfree(Glob *g){	Glob *next;	for(; g != nil; g = next){		next = g->next;		globfree1(g);	}}static Globlist*globlistnew(char *x){	Globlist *gl;	gl = mallocz(sizeof *gl, 1);	if(gl == nil)		sysfatal("globlistnew: %r");	gl->first = globnew();	gl->first->glob = s_copy(x);	gl->l = &gl->first->next;	return gl;}voidgloblistfree(Globlist *gl){	if(gl == nil)		return;	globfree(gl->first);	free(gl);}voidglobadd(Globlist *gl, char *dir, char *file){	Glob *g;	g = globnew();	g->glob = s_copy(dir);	if(strcmp(dir, "/") != 0 && *dir != 0)		s_append(g->glob, "/");	s_append(g->glob, file);	*(gl->l) = g;	gl->l = &(g->next); }static voidglobdir(Globlist *gl, char *dir, Reprog *re){	Dir *d;	int i, n, fd;	if(*dir == 0)		fd = open(".", OREAD);	else		fd = open(dir, OREAD);	if(fd < 0)		return;	n = dirreadall(fd, &d);	if(n == 0)		return;	close(fd);	for(i = 0; i < n; i++)		if(regexec(re, d[i].name, nil, 0))			globadd(gl, dir, d[i].name);	free(d);}static voidglobdot(Globlist *gl, char *dir){	Dir *d;	if(*dir == 0){		globadd(gl, "", ".");		return;	}	d = dirstat(dir);	if(d == nil)		return;	if(d->qid.type & QTDIR)		globadd(gl, dir, ".");	free(d);}static voidglobnext(Globlist *gl, char *pattern){	String *np;	Glob *g, *inlist;	Reprog *re;	int c;	/* nothing left */	if(*pattern == 0)		return;	inlist = gl->first;	gl->first = nil;	gl->l = &gl->first;	/* pick off next pattern and turn into a reg exp */	np = s_new();	s_putc(np, '^');	for(; c = *pattern; pattern++){		if(c == '/'){			pattern++;			break;		}		switch(c){		case '|':		case '+':		case '.':		case '^':		case '$':		case '(':		case ')':			s_putc(np, '\\');			s_putc(np, c);			break;		case '?':			s_putc(np, '.');			break;		case '*':			s_putc(np, '.');			s_putc(np, '*');			break;		default:			s_putc(np, c);			break;		}	}	s_putc(np, '$');	s_terminate(np);	if(strcmp(s_to_c(np), "^\\.$") == 0){		/* anything that's a directory works */		for(g = inlist; g != nil; g = g->next)			globdot(gl, s_to_c(g->glob));	} else {		re = regcomp(s_to_c(np));		/* run input list as directories */		for(g = inlist; g != nil; g = g->next)			globdir(gl, s_to_c(g->glob), re);		free(re);	}	s_free(np);	globfree(inlist);	if(gl->first != nil)		globnext(gl, pattern);}char *globiter(Globlist *gl){	Glob *g;	char *s;	if(gl->first == nil)		return nil;	g = gl->first;	gl->first = g->next;	if(gl->first == nil)		gl->l = &gl->first;	s = strdup(s_to_c(g->glob));	if(s == nil)		sysfatal("globiter: %r");	globfree1(g);	return s;}Globlist*glob(char *pattern){	Globlist *gl;	if(pattern == nil || *pattern == 0)		return nil;	if(*pattern == '/'){		pattern++;		gl = globlistnew("/");	} else		gl = globlistnew("");	globnext(gl, pattern);	return gl;}

⌨️ 快捷键说明

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