Introduction
Introduction Statistics Contact Development Disclaimer Help
glob.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
glob.c (4540B)
---
1 #include "rc.h"
2 #include "exec.h"
3 #include "fns.h"
4 char *globname;
5 struct word *globv;
6 /*
7 * delete all the GLOB marks from s, in place
8 */
9
10 void
11 deglob(char *s)
12 {
13 char *t = s;
14 do{
15 if(*t==GLOB)
16 t++;
17 *s++=*t;
18 }while(*t++);
19 }
20
21 int
22 globcmp(const void *s, const void *t)
23 {
24 return strcmp(*(char**)s, *(char**)t);
25 }
26
27 void
28 globsort(word *left, word *right)
29 {
30 char **list;
31 word *a;
32 int n = 0;
33 for(a = left;a!=right;a = a->next) n++;
34 list = (char **)emalloc(n*sizeof(char *));
35 for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word;
36 qsort((void *)list, n, sizeof(void *), globcmp);
37 for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n];
38 efree((char *)list);
39 }
40 /*
41 * Push names prefixed by globname and suffixed by a match of p onto the…
42 * namep points to the end of the prefix in globname.
43 */
44
45 void
46 globdir(char *p, char *namep)
47 {
48 char *t, *newp;
49 int f;
50 /* scan the pattern looking for a component with a metacharacter…
51 if(*p=='\0'){
52 globv = newword(globname, globv);
53 return;
54 }
55 t = namep;
56 newp = p;
57 while(*newp){
58 if(*newp==GLOB)
59 break;
60 *t=*newp++;
61 if(*t++=='/'){
62 namep = t;
63 p = newp;
64 }
65 }
66 /* If we ran out of pattern, append the name if accessible */
67 if(*newp=='\0'){
68 *t='\0';
69 if(access(globname, 0)==0)
70 globv = newword(globname, globv);
71 return;
72 }
73 /* read the directory and recur for any entry that matches */
74 *namep='\0';
75 if((f = Opendir(globname[0]?globname:"."))<0) return;
76 while(*newp!='/' && *newp!='\0') newp++;
77 while(Readdir(f, namep, *newp=='/')){
78 if(matchfn(namep, p)){
79 for(t = namep;*t;t++);
80 globdir(newp, t);
81 }
82 }
83 Closedir(f);
84 }
85 /*
86 * Push all file names matched by p on the current thread's stack.
87 * If there are no matches, the list consists of p.
88 */
89
90 void
91 glob(char *p)
92 {
93 word *svglobv = globv;
94 int globlen = Globsize(p);
95 if(!globlen){
96 deglob(p);
97 globv = newword(p, globv);
98 return;
99 }
100 globname = emalloc(globlen);
101 globname[0]='\0';
102 globdir(p, globname);
103 efree(globname);
104 if(svglobv==globv){
105 deglob(p);
106 globv = newword(p, globv);
107 }
108 else
109 globsort(globv, svglobv);
110 }
111 /*
112 * Do p and q point at equal utf codes
113 */
114
115 int
116 equtf(char *p, char *q)
117 {
118 if(*p!=*q)
119 return 0;
120 if(twobyte(*p)) return p[1]==q[1];
121 if(threebyte(*p)){
122 if(p[1]!=q[1])
123 return 0;
124 if(p[1]=='\0')
125 return 1; /* broken code at end of string…
126 return p[2]==q[2];
127 }
128 return 1;
129 }
130 /*
131 * Return a pointer to the next utf code in the string,
132 * not jumping past nuls in broken utf codes!
133 */
134
135 char*
136 nextutf(char *p)
137 {
138 if(twobyte(*p)) return p[1]=='\0'?p+1:p+2;
139 if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3;
140 return p+1;
141 }
142 /*
143 * Convert the utf code at *p to a unicode value
144 */
145
146 int
147 unicode(char *p)
148 {
149 int u=*p&0xff;
150 if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f);
151 if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f);
152 return u;
153 }
154 /*
155 * Does the string s match the pattern p
156 * . and .. are only matched by patterns starting with .
157 * * matches any sequence of characters
158 * ? matches any single character
159 * [...] matches the enclosed list of characters
160 */
161
162 int
163 matchfn(char *s, char *p)
164 {
165 if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!…
166 return 0;
167 return match(s, p, '/');
168 }
169
170 int
171 match(char *s, char *p, int stop)
172 {
173 int compl, hit, lo, hi, t, c;
174 for(;*p!=stop && *p!='\0';s = nextutf(s),p = nextutf(p)){
175 if(*p!=GLOB){
176 if(!equtf(p, s)) return 0;
177 }
178 else switch(*++p){
179 case GLOB:
180 if(*s!=GLOB)
181 return 0;
182 break;
183 case '*':
184 for(;;){
185 if(match(s, nextutf(p), stop)) return 1;
186 if(!*s)
187 break;
188 s = nextutf(s);
189 }
190 return 0;
191 case '?':
192 if(*s=='\0')
193 return 0;
194 break;
195 case '[':
196 if(*s=='\0')
197 return 0;
198 c = unicode(s);
199 p++;
200 compl=*p=='~';
201 if(compl)
202 p++;
203 hit = 0;
204 while(*p!=']'){
205 if(*p=='\0')
206 return 0; /* synt…
207 lo = unicode(p);
208 p = nextutf(p);
209 if(*p!='-')
210 hi = lo;
211 else{
212 p++;
213 if(*p=='\0')
214 return 0; /* synt…
215 hi = unicode(p);
216 p = nextutf(p);
217 if(hi<lo){ t = lo; lo = hi; hi =…
218 }
219 if(lo<=c && c<=hi)
220 hit = 1;
221 }
222 if(compl)
223 hit=!hit;
224 if(!hit)
225 return 0;
226 break;
227 }
228 }
229 return *s=='\0';
230 }
231
232 void
233 globlist1(word *gl)
234 {
235 if(gl){
236 globlist1(gl->next);
237 glob(gl->word);
238 }
239 }
240
241 void
242 globlist(void)
243 {
244 word *a;
245 globv = 0;
246 globlist1(runq->argv->words);
247 poplist();
248 pushlist();
249 if(globv){
250 for(a = globv;a->next;a = a->next);
251 a->next = runq->argv->words;
252 runq->argv->words = globv;
253 }
254 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.