1 f08fdedc 2003-11-23 devnull #include "rc.h"
2 f08fdedc 2003-11-23 devnull #include "exec.h"
3 f08fdedc 2003-11-23 devnull #include "fns.h"
4 f08fdedc 2003-11-23 devnull char *globname;
5 f08fdedc 2003-11-23 devnull struct word *globv;
7 f08fdedc 2003-11-23 devnull * delete all the GLOB marks from s, in place
11 c8f53842 2007-03-26 devnull deglob(char *s)
13 c8f53842 2007-03-26 devnull char *t = s;
15 c8f53842 2007-03-26 devnull if(*t==GLOB)
18 f08fdedc 2003-11-23 devnull }while(*t++);
22 c8f53842 2007-03-26 devnull globcmp(const void *s, const void *t)
24 f08fdedc 2003-11-23 devnull return strcmp(*(char**)s, *(char**)t);
28 c8f53842 2007-03-26 devnull globsort(word *left, word *right)
30 f08fdedc 2003-11-23 devnull char **list;
32 c8f53842 2007-03-26 devnull int n = 0;
33 c8f53842 2007-03-26 devnull for(a = left;a!=right;a = a->next) n++;
34 c8f53842 2007-03-26 devnull list = (char **)emalloc(n*sizeof(char *));
35 c8f53842 2007-03-26 devnull for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word;
36 c8f53842 2007-03-26 devnull qsort((void *)list, n, sizeof(void *), globcmp);
37 c8f53842 2007-03-26 devnull for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n];
38 f08fdedc 2003-11-23 devnull efree((char *)list);
41 f08fdedc 2003-11-23 devnull * Push names prefixed by globname and suffixed by a match of p onto the astack.
42 f08fdedc 2003-11-23 devnull * namep points to the end of the prefix in globname.
46 c8f53842 2007-03-26 devnull globdir(char *p, char *namep)
48 f08fdedc 2003-11-23 devnull char *t, *newp;
50 f08fdedc 2003-11-23 devnull /* scan the pattern looking for a component with a metacharacter in it */
51 f08fdedc 2003-11-23 devnull if(*p=='\0'){
52 c8f53842 2007-03-26 devnull globv = newword(globname, globv);
55 c8f53842 2007-03-26 devnull t = namep;
56 c8f53842 2007-03-26 devnull newp = p;
57 f08fdedc 2003-11-23 devnull while(*newp){
58 f08fdedc 2003-11-23 devnull if(*newp==GLOB)
60 f08fdedc 2003-11-23 devnull *t=*newp++;
61 f08fdedc 2003-11-23 devnull if(*t++=='/'){
62 c8f53842 2007-03-26 devnull namep = t;
63 c8f53842 2007-03-26 devnull p = newp;
66 f08fdedc 2003-11-23 devnull /* If we ran out of pattern, append the name if accessible */
67 f08fdedc 2003-11-23 devnull if(*newp=='\0'){
69 f08fdedc 2003-11-23 devnull if(access(globname, 0)==0)
70 c8f53842 2007-03-26 devnull globv = newword(globname, globv);
73 f08fdedc 2003-11-23 devnull /* read the directory and recur for any entry that matches */
74 f08fdedc 2003-11-23 devnull *namep='\0';
75 c8f53842 2007-03-26 devnull if((f = Opendir(globname[0]?globname:"."))<0) return;
76 f08fdedc 2003-11-23 devnull while(*newp!='/' && *newp!='\0') newp++;
77 c8f53842 2007-03-26 devnull while(Readdir(f, namep, *newp=='/')){
78 f08fdedc 2003-11-23 devnull if(matchfn(namep, p)){
79 c8f53842 2007-03-26 devnull for(t = namep;*t;t++);
80 f08fdedc 2003-11-23 devnull globdir(newp, t);
83 f08fdedc 2003-11-23 devnull Closedir(f);
86 f08fdedc 2003-11-23 devnull * Push all file names matched by p on the current thread's stack.
87 f08fdedc 2003-11-23 devnull * If there are no matches, the list consists of p.
91 c8f53842 2007-03-26 devnull glob(char *p)
93 c8f53842 2007-03-26 devnull word *svglobv = globv;
94 c8f53842 2007-03-26 devnull int globlen = Globsize(p);
95 f08fdedc 2003-11-23 devnull if(!globlen){
96 f08fdedc 2003-11-23 devnull deglob(p);
97 c8f53842 2007-03-26 devnull globv = newword(p, globv);
100 c8f53842 2007-03-26 devnull globname = emalloc(globlen);
101 f08fdedc 2003-11-23 devnull globname[0]='\0';
102 f08fdedc 2003-11-23 devnull globdir(p, globname);
103 f08fdedc 2003-11-23 devnull efree(globname);
104 f08fdedc 2003-11-23 devnull if(svglobv==globv){
105 f08fdedc 2003-11-23 devnull deglob(p);
106 c8f53842 2007-03-26 devnull globv = newword(p, globv);
109 f08fdedc 2003-11-23 devnull globsort(globv, svglobv);
112 f08fdedc 2003-11-23 devnull * Do p and q point at equal utf codes
116 c8f53842 2007-03-26 devnull equtf(char *p, char *q)
118 c8f53842 2007-03-26 devnull if(*p!=*q)
119 c8f53842 2007-03-26 devnull return 0;
120 f08fdedc 2003-11-23 devnull if(twobyte(*p)) return p[1]==q[1];
121 f08fdedc 2003-11-23 devnull if(threebyte(*p)){
122 c8f53842 2007-03-26 devnull if(p[1]!=q[1])
123 c8f53842 2007-03-26 devnull return 0;
124 c8f53842 2007-03-26 devnull if(p[1]=='\0')
125 c8f53842 2007-03-26 devnull return 1; /* broken code at end of string! */
126 f08fdedc 2003-11-23 devnull return p[2]==q[2];
128 0786c964 2011-01-02 rsc if(fourbyte(*p)){
129 0786c964 2011-01-02 rsc if(p[1]!=q[1])
131 0786c964 2011-01-02 rsc if(p[1]=='\0')
133 0786c964 2011-01-02 rsc if(p[2]!=q[2])
135 0786c964 2011-01-02 rsc if(p[2]=='\0')
137 0786c964 2011-01-02 rsc return p[3]==q[3];
139 f08fdedc 2003-11-23 devnull return 1;
142 f08fdedc 2003-11-23 devnull * Return a pointer to the next utf code in the string,
143 f08fdedc 2003-11-23 devnull * not jumping past nuls in broken utf codes!
147 c8f53842 2007-03-26 devnull nextutf(char *p)
149 f08fdedc 2003-11-23 devnull if(twobyte(*p)) return p[1]=='\0'?p+1:p+2;
150 f08fdedc 2003-11-23 devnull if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3;
151 0786c964 2011-01-02 rsc if(fourbyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p[3]=='\0'?p+3:p+4;
152 f08fdedc 2003-11-23 devnull return p+1;
155 f08fdedc 2003-11-23 devnull * Convert the utf code at *p to a unicode value
159 c8f53842 2007-03-26 devnull unicode(char *p)
161 f08fdedc 2003-11-23 devnull int u=*p&0xff;
162 f08fdedc 2003-11-23 devnull if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f);
163 f08fdedc 2003-11-23 devnull if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f);
164 0786c964 2011-01-02 rsc if(fourbyte(u)) return (u<<18)|((p[1]&0x3f)<<12)|((p[2]&0x3f)<<6)|(p[3]&0x3f);
165 f08fdedc 2003-11-23 devnull return u;
168 f08fdedc 2003-11-23 devnull * Does the string s match the pattern p
169 f08fdedc 2003-11-23 devnull * . and .. are only matched by patterns starting with .
170 f08fdedc 2003-11-23 devnull * * matches any sequence of characters
171 f08fdedc 2003-11-23 devnull * ? matches any single character
172 f08fdedc 2003-11-23 devnull * [...] matches the enclosed list of characters
176 c8f53842 2007-03-26 devnull matchfn(char *s, char *p)
178 f08fdedc 2003-11-23 devnull if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.')
179 f08fdedc 2003-11-23 devnull return 0;
180 f08fdedc 2003-11-23 devnull return match(s, p, '/');
184 c8f53842 2007-03-26 devnull match(char *s, char *p, int stop)
186 f08fdedc 2003-11-23 devnull int compl, hit, lo, hi, t, c;
187 c8f53842 2007-03-26 devnull for(;*p!=stop && *p!='\0';s = nextutf(s),p = nextutf(p)){
188 f08fdedc 2003-11-23 devnull if(*p!=GLOB){
189 f08fdedc 2003-11-23 devnull if(!equtf(p, s)) return 0;
191 f08fdedc 2003-11-23 devnull else switch(*++p){
192 f08fdedc 2003-11-23 devnull case GLOB:
193 c8f53842 2007-03-26 devnull if(*s!=GLOB)
194 c8f53842 2007-03-26 devnull return 0;
196 f08fdedc 2003-11-23 devnull case '*':
197 f08fdedc 2003-11-23 devnull for(;;){
198 f08fdedc 2003-11-23 devnull if(match(s, nextutf(p), stop)) return 1;
201 c8f53842 2007-03-26 devnull s = nextutf(s);
203 f08fdedc 2003-11-23 devnull return 0;
204 f08fdedc 2003-11-23 devnull case '?':
205 c8f53842 2007-03-26 devnull if(*s=='\0')
206 c8f53842 2007-03-26 devnull return 0;
208 f08fdedc 2003-11-23 devnull case '[':
209 c8f53842 2007-03-26 devnull if(*s=='\0')
210 c8f53842 2007-03-26 devnull return 0;
211 c8f53842 2007-03-26 devnull c = unicode(s);
213 f08fdedc 2003-11-23 devnull compl=*p=='~';
214 c8f53842 2007-03-26 devnull if(compl)
216 c8f53842 2007-03-26 devnull hit = 0;
217 f08fdedc 2003-11-23 devnull while(*p!=']'){
218 c8f53842 2007-03-26 devnull if(*p=='\0')
219 c8f53842 2007-03-26 devnull return 0; /* syntax error */
220 c8f53842 2007-03-26 devnull lo = unicode(p);
221 c8f53842 2007-03-26 devnull p = nextutf(p);
222 c8f53842 2007-03-26 devnull if(*p!='-')
223 c8f53842 2007-03-26 devnull hi = lo;
226 c8f53842 2007-03-26 devnull if(*p=='\0')
227 c8f53842 2007-03-26 devnull return 0; /* syntax error */
228 c8f53842 2007-03-26 devnull hi = unicode(p);
229 c8f53842 2007-03-26 devnull p = nextutf(p);
230 c8f53842 2007-03-26 devnull if(hi<lo){ t = lo; lo = hi; hi = t; }
232 c8f53842 2007-03-26 devnull if(lo<=c && c<=hi)
233 c8f53842 2007-03-26 devnull hit = 1;
235 c8f53842 2007-03-26 devnull if(compl)
236 c8f53842 2007-03-26 devnull hit=!hit;
237 c8f53842 2007-03-26 devnull if(!hit)
238 c8f53842 2007-03-26 devnull return 0;
242 f08fdedc 2003-11-23 devnull return *s=='\0';
246 c8f53842 2007-03-26 devnull globlist1(word *gl)
249 f08fdedc 2003-11-23 devnull globlist1(gl->next);
250 f08fdedc 2003-11-23 devnull glob(gl->word);
255 c8f53842 2007-03-26 devnull globlist(void)
257 f08fdedc 2003-11-23 devnull word *a;
258 c8f53842 2007-03-26 devnull globv = 0;
259 f08fdedc 2003-11-23 devnull globlist1(runq->argv->words);
260 f08fdedc 2003-11-23 devnull poplist();
261 f08fdedc 2003-11-23 devnull pushlist();
262 f08fdedc 2003-11-23 devnull if(globv){
263 c8f53842 2007-03-26 devnull for(a = globv;a->next;a = a->next);
264 c8f53842 2007-03-26 devnull a->next = runq->argv->words;
265 c8f53842 2007-03-26 devnull runq->argv->words = globv;