17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <regexp.h>
49a747e4fSDavid du Colombier #include <String.h>
57dd7cddfSDavid du Colombier #include "glob.h"
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier /*
89a747e4fSDavid du Colombier * I wrote this glob so that there would be no limit
99a747e4fSDavid du Colombier * on element or path size. The one in rc is probably
109a747e4fSDavid du Colombier * better, certainly faster. - presotto
117dd7cddfSDavid du Colombier */
127dd7cddfSDavid du Colombier
139a747e4fSDavid du Colombier static Glob*
globnew(void)149a747e4fSDavid du Colombier globnew(void)
157dd7cddfSDavid du Colombier {
169a747e4fSDavid du Colombier Glob *g;
177dd7cddfSDavid du Colombier
189a747e4fSDavid du Colombier g = mallocz(sizeof(*g), 1);
199a747e4fSDavid du Colombier if(g == nil)
209a747e4fSDavid du Colombier sysfatal("globnew: %r");
219a747e4fSDavid du Colombier return g;
227dd7cddfSDavid du Colombier }
237dd7cddfSDavid du Colombier
249a747e4fSDavid du Colombier static void
globfree1(Glob * g)25*b27b55e2SDavid du Colombier globfree1(Glob *g)
26*b27b55e2SDavid du Colombier {
27*b27b55e2SDavid du Colombier s_free(g->glob);
28*b27b55e2SDavid du Colombier free(g);
29*b27b55e2SDavid du Colombier }
30*b27b55e2SDavid du Colombier
31*b27b55e2SDavid du Colombier static void
globfree(Glob * g)327dd7cddfSDavid du Colombier globfree(Glob *g)
337dd7cddfSDavid du Colombier {
347dd7cddfSDavid du Colombier Glob *next;
357dd7cddfSDavid du Colombier
369a747e4fSDavid du Colombier for(; g != nil; g = next){
377dd7cddfSDavid du Colombier next = g->next;
38*b27b55e2SDavid du Colombier globfree1(g);
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier }
417dd7cddfSDavid du Colombier
429a747e4fSDavid du Colombier static Globlist*
globlistnew(char * x)439a747e4fSDavid du Colombier globlistnew(char *x)
449a747e4fSDavid du Colombier {
459a747e4fSDavid du Colombier Globlist *gl;
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier gl = mallocz(sizeof *gl, 1);
489a747e4fSDavid du Colombier if(gl == nil)
499a747e4fSDavid du Colombier sysfatal("globlistnew: %r");
509a747e4fSDavid du Colombier gl->first = globnew();
519a747e4fSDavid du Colombier gl->first->glob = s_copy(x);
529a747e4fSDavid du Colombier gl->l = &gl->first->next;
539a747e4fSDavid du Colombier return gl;
549a747e4fSDavid du Colombier }
559a747e4fSDavid du Colombier
567dd7cddfSDavid du Colombier void
globlistfree(Globlist * gl)579a747e4fSDavid du Colombier globlistfree(Globlist *gl)
587dd7cddfSDavid du Colombier {
599a747e4fSDavid du Colombier if(gl == nil)
609a747e4fSDavid du Colombier return;
619a747e4fSDavid du Colombier globfree(gl->first);
629a747e4fSDavid du Colombier free(gl);
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier
659a747e4fSDavid du Colombier void
globadd(Globlist * gl,char * dir,char * file)669a747e4fSDavid du Colombier globadd(Globlist *gl, char *dir, char *file)
677dd7cddfSDavid du Colombier {
689a747e4fSDavid du Colombier Glob *g;
697dd7cddfSDavid du Colombier
709a747e4fSDavid du Colombier g = globnew();
719a747e4fSDavid du Colombier g->glob = s_copy(dir);
729a747e4fSDavid du Colombier if(strcmp(dir, "/") != 0 && *dir != 0)
739a747e4fSDavid du Colombier s_append(g->glob, "/");
749a747e4fSDavid du Colombier s_append(g->glob, file);
759a747e4fSDavid du Colombier *(gl->l) = g;
769a747e4fSDavid du Colombier gl->l = &(g->next);
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier static void
globdir(Globlist * gl,char * dir,Reprog * re)809a747e4fSDavid du Colombier globdir(Globlist *gl, char *dir, Reprog *re)
817dd7cddfSDavid du Colombier {
829a747e4fSDavid du Colombier Dir *d;
839a747e4fSDavid du Colombier int i, n, fd;
847dd7cddfSDavid du Colombier
859a747e4fSDavid du Colombier if(*dir == 0)
869a747e4fSDavid du Colombier fd = open(".", OREAD);
879a747e4fSDavid du Colombier else
889a747e4fSDavid du Colombier fd = open(dir, OREAD);
899a747e4fSDavid du Colombier if(fd < 0)
909a747e4fSDavid du Colombier return;
919a747e4fSDavid du Colombier n = dirreadall(fd, &d);
929a747e4fSDavid du Colombier if(n == 0)
939a747e4fSDavid du Colombier return;
949a747e4fSDavid du Colombier close(fd);
959a747e4fSDavid du Colombier for(i = 0; i < n; i++)
969a747e4fSDavid du Colombier if(regexec(re, d[i].name, nil, 0))
979a747e4fSDavid du Colombier globadd(gl, dir, d[i].name);
989a747e4fSDavid du Colombier free(d);
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier static void
globdot(Globlist * gl,char * dir)1029a747e4fSDavid du Colombier globdot(Globlist *gl, char *dir)
1037dd7cddfSDavid du Colombier {
1049a747e4fSDavid du Colombier Dir *d;
1057dd7cddfSDavid du Colombier
1069a747e4fSDavid du Colombier if(*dir == 0){
1079a747e4fSDavid du Colombier globadd(gl, "", ".");
1087dd7cddfSDavid du Colombier return;
1097dd7cddfSDavid du Colombier }
1109a747e4fSDavid du Colombier d = dirstat(dir);
1119a747e4fSDavid du Colombier if(d == nil)
1129a747e4fSDavid du Colombier return;
1139a747e4fSDavid du Colombier if(d->qid.type & QTDIR)
1149a747e4fSDavid du Colombier globadd(gl, dir, ".");
1159a747e4fSDavid du Colombier free(d);
1169a747e4fSDavid du Colombier }
1179a747e4fSDavid du Colombier
1189a747e4fSDavid du Colombier static void
globnext(Globlist * gl,char * pattern)1199a747e4fSDavid du Colombier globnext(Globlist *gl, char *pattern)
1209a747e4fSDavid du Colombier {
1219a747e4fSDavid du Colombier String *np;
1229a747e4fSDavid du Colombier Glob *g, *inlist;
1239a747e4fSDavid du Colombier Reprog *re;
1249a747e4fSDavid du Colombier int c;
1259a747e4fSDavid du Colombier
1269a747e4fSDavid du Colombier /* nothing left */
1279a747e4fSDavid du Colombier if(*pattern == 0)
1289a747e4fSDavid du Colombier return;
1299a747e4fSDavid du Colombier
1309a747e4fSDavid du Colombier inlist = gl->first;
1319a747e4fSDavid du Colombier gl->first = nil;
1329a747e4fSDavid du Colombier gl->l = &gl->first;
1339a747e4fSDavid du Colombier
1349a747e4fSDavid du Colombier /* pick off next pattern and turn into a reg exp */
1359a747e4fSDavid du Colombier np = s_new();
1369a747e4fSDavid du Colombier s_putc(np, '^');
1379a747e4fSDavid du Colombier for(; c = *pattern; pattern++){
1389a747e4fSDavid du Colombier if(c == '/'){
1399a747e4fSDavid du Colombier pattern++;
1407dd7cddfSDavid du Colombier break;
1417dd7cddfSDavid du Colombier }
1429a747e4fSDavid du Colombier switch(c){
1439a747e4fSDavid du Colombier case '|':
1449a747e4fSDavid du Colombier case '+':
1459a747e4fSDavid du Colombier case '.':
1469a747e4fSDavid du Colombier case '^':
1479a747e4fSDavid du Colombier case '$':
1489a747e4fSDavid du Colombier case '(':
1499a747e4fSDavid du Colombier case ')':
1509a747e4fSDavid du Colombier s_putc(np, '\\');
1519a747e4fSDavid du Colombier s_putc(np, c);
1529a747e4fSDavid du Colombier break;
1539a747e4fSDavid du Colombier case '?':
1549a747e4fSDavid du Colombier s_putc(np, '.');
1557dd7cddfSDavid du Colombier break;
1567dd7cddfSDavid du Colombier case '*':
1579a747e4fSDavid du Colombier s_putc(np, '.');
1589a747e4fSDavid du Colombier s_putc(np, '*');
1597dd7cddfSDavid du Colombier break;
1609a747e4fSDavid du Colombier default:
1619a747e4fSDavid du Colombier s_putc(np, c);
1627dd7cddfSDavid du Colombier break;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier }
1659a747e4fSDavid du Colombier s_putc(np, '$');
1669a747e4fSDavid du Colombier s_terminate(np);
1679a747e4fSDavid du Colombier if(strcmp(s_to_c(np), "^\\.$") == 0){
1689a747e4fSDavid du Colombier /* anything that's a directory works */
1699a747e4fSDavid du Colombier for(g = inlist; g != nil; g = g->next)
1709a747e4fSDavid du Colombier globdot(gl, s_to_c(g->glob));
1719a747e4fSDavid du Colombier } else {
1729a747e4fSDavid du Colombier re = regcomp(s_to_c(np));
1739a747e4fSDavid du Colombier
1749a747e4fSDavid du Colombier /* run input list as directories */
1759a747e4fSDavid du Colombier for(g = inlist; g != nil; g = g->next)
1769a747e4fSDavid du Colombier globdir(gl, s_to_c(g->glob), re);
1779a747e4fSDavid du Colombier free(re);
1789a747e4fSDavid du Colombier }
1799a747e4fSDavid du Colombier s_free(np);
1809a747e4fSDavid du Colombier globfree(inlist);
1819a747e4fSDavid du Colombier
1829a747e4fSDavid du Colombier if(gl->first != nil)
1839a747e4fSDavid du Colombier globnext(gl, pattern);
1849a747e4fSDavid du Colombier }
1859a747e4fSDavid du Colombier
186*b27b55e2SDavid du Colombier char *
globiter(Globlist * gl)187*b27b55e2SDavid du Colombier globiter(Globlist *gl)
188*b27b55e2SDavid du Colombier {
189*b27b55e2SDavid du Colombier Glob *g;
190*b27b55e2SDavid du Colombier char *s;
191*b27b55e2SDavid du Colombier
192*b27b55e2SDavid du Colombier if(gl->first == nil)
193*b27b55e2SDavid du Colombier return nil;
194*b27b55e2SDavid du Colombier g = gl->first;
195*b27b55e2SDavid du Colombier gl->first = g->next;
196*b27b55e2SDavid du Colombier if(gl->first == nil)
197*b27b55e2SDavid du Colombier gl->l = &gl->first;
198*b27b55e2SDavid du Colombier s = strdup(s_to_c(g->glob));
199*b27b55e2SDavid du Colombier if(s == nil)
200*b27b55e2SDavid du Colombier sysfatal("globiter: %r");
201*b27b55e2SDavid du Colombier globfree1(g);
202*b27b55e2SDavid du Colombier return s;
203*b27b55e2SDavid du Colombier }
204*b27b55e2SDavid du Colombier
2059a747e4fSDavid du Colombier Globlist*
glob(char * pattern)2069a747e4fSDavid du Colombier glob(char *pattern)
2079a747e4fSDavid du Colombier {
2089a747e4fSDavid du Colombier Globlist *gl;
2099a747e4fSDavid du Colombier
2109a747e4fSDavid du Colombier if(pattern == nil || *pattern == 0)
2119a747e4fSDavid du Colombier return nil;
2129a747e4fSDavid du Colombier if(*pattern == '/'){
2139a747e4fSDavid du Colombier pattern++;
2149a747e4fSDavid du Colombier gl = globlistnew("/");
2159a747e4fSDavid du Colombier } else
2169a747e4fSDavid du Colombier gl = globlistnew("");
2179a747e4fSDavid du Colombier globnext(gl, pattern);
2189a747e4fSDavid du Colombier return gl;
2197dd7cddfSDavid du Colombier }
220