13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "fns.h"
43e12c5d1SDavid du Colombier char *globname;
53e12c5d1SDavid du Colombier struct word *globv;
63e12c5d1SDavid du Colombier /*
73e12c5d1SDavid du Colombier * delete all the GLOB marks from s, in place
83e12c5d1SDavid du Colombier */
9dc5a79c1SDavid du Colombier
10dc5a79c1SDavid du Colombier void
deglob(void * as)11276e7d6dSDavid du Colombier deglob(void *as)
123e12c5d1SDavid du Colombier {
13276e7d6dSDavid du Colombier char *s = as;
143e12c5d1SDavid du Colombier char *t = s;
153e12c5d1SDavid du Colombier do{
16dc5a79c1SDavid du Colombier if(*t==GLOB)
17dc5a79c1SDavid du Colombier t++;
183e12c5d1SDavid du Colombier *s++=*t;
193e12c5d1SDavid du Colombier }while(*t++);
203e12c5d1SDavid du Colombier }
21dc5a79c1SDavid du Colombier
22dc5a79c1SDavid du Colombier int
globcmp(const void * s,const void * t)23dc5a79c1SDavid du Colombier globcmp(const void *s, const void *t)
243e12c5d1SDavid du Colombier {
257dd7cddfSDavid du Colombier return strcmp(*(char**)s, *(char**)t);
263e12c5d1SDavid du Colombier }
27dc5a79c1SDavid du Colombier
28dc5a79c1SDavid du Colombier void
globsort(word * left,word * right)29dc5a79c1SDavid du Colombier globsort(word *left, word *right)
303e12c5d1SDavid du Colombier {
313e12c5d1SDavid du Colombier char **list;
323e12c5d1SDavid du Colombier word *a;
333e12c5d1SDavid du Colombier int n = 0;
3499eb86a7SDavid du Colombier for(a = left;a!=right;a = a->next) n++;
353e12c5d1SDavid du Colombier list = (char **)emalloc(n*sizeof(char *));
3699eb86a7SDavid du Colombier for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word;
37dc5a79c1SDavid du Colombier qsort((void *)list, n, sizeof(void *), globcmp);
3899eb86a7SDavid du Colombier for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n];
393e12c5d1SDavid du Colombier efree((char *)list);
403e12c5d1SDavid du Colombier }
413e12c5d1SDavid du Colombier /*
423e12c5d1SDavid du Colombier * Push names prefixed by globname and suffixed by a match of p onto the astack.
433e12c5d1SDavid du Colombier * namep points to the end of the prefix in globname.
443e12c5d1SDavid du Colombier */
45dc5a79c1SDavid du Colombier
46dc5a79c1SDavid du Colombier void
globdir(uchar * p,uchar * namep)47276e7d6dSDavid du Colombier globdir(uchar *p, uchar *namep)
483e12c5d1SDavid du Colombier {
49276e7d6dSDavid du Colombier uchar *t, *newp;
503e12c5d1SDavid du Colombier int f;
513e12c5d1SDavid du Colombier /* scan the pattern looking for a component with a metacharacter in it */
523e12c5d1SDavid du Colombier if(*p=='\0'){
533e12c5d1SDavid du Colombier globv = newword(globname, globv);
543e12c5d1SDavid du Colombier return;
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier t = namep;
573e12c5d1SDavid du Colombier newp = p;
583e12c5d1SDavid du Colombier while(*newp){
593e12c5d1SDavid du Colombier if(*newp==GLOB)
603e12c5d1SDavid du Colombier break;
613e12c5d1SDavid du Colombier *t=*newp++;
623e12c5d1SDavid du Colombier if(*t++=='/'){
633e12c5d1SDavid du Colombier namep = t;
643e12c5d1SDavid du Colombier p = newp;
653e12c5d1SDavid du Colombier }
663e12c5d1SDavid du Colombier }
673e12c5d1SDavid du Colombier /* If we ran out of pattern, append the name if accessible */
683e12c5d1SDavid du Colombier if(*newp=='\0'){
693e12c5d1SDavid du Colombier *t='\0';
703e12c5d1SDavid du Colombier if(access(globname, 0)==0)
713e12c5d1SDavid du Colombier globv = newword(globname, globv);
723e12c5d1SDavid du Colombier return;
733e12c5d1SDavid du Colombier }
743e12c5d1SDavid du Colombier /* read the directory and recur for any entry that matches */
753e12c5d1SDavid du Colombier *namep='\0';
7699eb86a7SDavid du Colombier if((f = Opendir(globname[0]?globname:"."))<0) return;
7799eb86a7SDavid du Colombier while(*newp!='/' && *newp!='\0') newp++;
786b6b9ac8SDavid du Colombier while(Readdir(f, namep, *newp=='/')){
793e12c5d1SDavid du Colombier if(matchfn(namep, p)){
8099eb86a7SDavid du Colombier for(t = namep;*t;t++);
813e12c5d1SDavid du Colombier globdir(newp, t);
823e12c5d1SDavid du Colombier }
833e12c5d1SDavid du Colombier }
843e12c5d1SDavid du Colombier Closedir(f);
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier /*
873e12c5d1SDavid du Colombier * Push all file names matched by p on the current thread's stack.
883e12c5d1SDavid du Colombier * If there are no matches, the list consists of p.
893e12c5d1SDavid du Colombier */
90dc5a79c1SDavid du Colombier
91dc5a79c1SDavid du Colombier void
glob(void * ap)92276e7d6dSDavid du Colombier glob(void *ap)
933e12c5d1SDavid du Colombier {
94276e7d6dSDavid du Colombier uchar *p = ap;
953e12c5d1SDavid du Colombier word *svglobv = globv;
96276e7d6dSDavid du Colombier int globlen = Globsize(ap);
97276e7d6dSDavid du Colombier
983e12c5d1SDavid du Colombier if(!globlen){
993e12c5d1SDavid du Colombier deglob(p);
100276e7d6dSDavid du Colombier globv = newword((char *)p, globv);
1013e12c5d1SDavid du Colombier return;
1023e12c5d1SDavid du Colombier }
1033e12c5d1SDavid du Colombier globname = emalloc(globlen);
1043e12c5d1SDavid du Colombier globname[0]='\0';
105276e7d6dSDavid du Colombier globdir(p, (uchar *)globname);
1063e12c5d1SDavid du Colombier efree(globname);
1073e12c5d1SDavid du Colombier if(svglobv==globv){
1083e12c5d1SDavid du Colombier deglob(p);
109276e7d6dSDavid du Colombier globv = newword((char *)p, globv);
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier else
1123e12c5d1SDavid du Colombier globsort(globv, svglobv);
1133e12c5d1SDavid du Colombier }
114*82726826SDavid du Colombier
1153e12c5d1SDavid du Colombier /*
1163e12c5d1SDavid du Colombier * Do p and q point at equal utf codes
1173e12c5d1SDavid du Colombier */
118dc5a79c1SDavid du Colombier int
equtf(uchar * p,uchar * q)119276e7d6dSDavid du Colombier equtf(uchar *p, uchar *q)
120dc5a79c1SDavid du Colombier {
121*82726826SDavid du Colombier Rune pr, qr;
122dc5a79c1SDavid du Colombier if(*p!=*q)
123dc5a79c1SDavid du Colombier return 0;
124*82726826SDavid du Colombier
125*82726826SDavid du Colombier chartorune(&pr, (char*)p);
126*82726826SDavid du Colombier chartorune(&qr, (char*)q);
127*82726826SDavid du Colombier return pr == qr;
1283e12c5d1SDavid du Colombier }
129*82726826SDavid du Colombier
1303e12c5d1SDavid du Colombier /*
1313e12c5d1SDavid du Colombier * Return a pointer to the next utf code in the string,
1323e12c5d1SDavid du Colombier * not jumping past nuls in broken utf codes!
1333e12c5d1SDavid du Colombier */
134dc5a79c1SDavid du Colombier
135276e7d6dSDavid du Colombier uchar*
nextutf(uchar * p)136276e7d6dSDavid du Colombier nextutf(uchar *p)
137dc5a79c1SDavid du Colombier {
138*82726826SDavid du Colombier Rune dummy;
139*82726826SDavid du Colombier return p + chartorune(&dummy, (char*)p);
1403e12c5d1SDavid du Colombier }
141*82726826SDavid du Colombier
1423e12c5d1SDavid du Colombier /*
1433e12c5d1SDavid du Colombier * Convert the utf code at *p to a unicode value
1443e12c5d1SDavid du Colombier */
145dc5a79c1SDavid du Colombier
146dc5a79c1SDavid du Colombier int
unicode(uchar * p)147276e7d6dSDavid du Colombier unicode(uchar *p)
148dc5a79c1SDavid du Colombier {
149*82726826SDavid du Colombier Rune r;
150276e7d6dSDavid du Colombier
151*82726826SDavid du Colombier chartorune(&r, (char*)p);
152*82726826SDavid du Colombier return r;
1533e12c5d1SDavid du Colombier }
154*82726826SDavid du Colombier
1553e12c5d1SDavid du Colombier /*
1563e12c5d1SDavid du Colombier * Does the string s match the pattern p
1573e12c5d1SDavid du Colombier * . and .. are only matched by patterns starting with .
1583e12c5d1SDavid du Colombier * * matches any sequence of characters
1593e12c5d1SDavid du Colombier * ? matches any single character
1603e12c5d1SDavid du Colombier * [...] matches the enclosed list of characters
1613e12c5d1SDavid du Colombier */
162dc5a79c1SDavid du Colombier
163dc5a79c1SDavid du Colombier int
matchfn(void * as,void * ap)164276e7d6dSDavid du Colombier matchfn(void *as, void *ap)
1653e12c5d1SDavid du Colombier {
166276e7d6dSDavid du Colombier uchar *s = as, *p = ap;
167276e7d6dSDavid du Colombier
1683e12c5d1SDavid du Colombier if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.')
1693e12c5d1SDavid du Colombier return 0;
1703e12c5d1SDavid du Colombier return match(s, p, '/');
1713e12c5d1SDavid du Colombier }
172dc5a79c1SDavid du Colombier
173dc5a79c1SDavid du Colombier int
match(void * as,void * ap,int stop)174276e7d6dSDavid du Colombier match(void *as, void *ap, int stop)
1753e12c5d1SDavid du Colombier {
1763e12c5d1SDavid du Colombier int compl, hit, lo, hi, t, c;
177276e7d6dSDavid du Colombier uchar *s = as, *p = ap;
178276e7d6dSDavid du Colombier
1793e12c5d1SDavid du Colombier for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){
1803e12c5d1SDavid du Colombier if(*p!=GLOB){
1813e12c5d1SDavid du Colombier if(!equtf(p, s)) return 0;
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier else switch(*++p){
1843e12c5d1SDavid du Colombier case GLOB:
185dc5a79c1SDavid du Colombier if(*s!=GLOB)
186dc5a79c1SDavid du Colombier return 0;
1873e12c5d1SDavid du Colombier break;
1883e12c5d1SDavid du Colombier case '*':
1893e12c5d1SDavid du Colombier for(;;){
1903e12c5d1SDavid du Colombier if(match(s, nextutf(p), stop)) return 1;
191dc5a79c1SDavid du Colombier if(!*s)
192dc5a79c1SDavid du Colombier break;
1933e12c5d1SDavid du Colombier s = nextutf(s);
1943e12c5d1SDavid du Colombier }
1953e12c5d1SDavid du Colombier return 0;
1963e12c5d1SDavid du Colombier case '?':
197dc5a79c1SDavid du Colombier if(*s=='\0')
198dc5a79c1SDavid du Colombier return 0;
1993e12c5d1SDavid du Colombier break;
2003e12c5d1SDavid du Colombier case '[':
201dc5a79c1SDavid du Colombier if(*s=='\0')
202dc5a79c1SDavid du Colombier return 0;
2033e12c5d1SDavid du Colombier c = unicode(s);
2043e12c5d1SDavid du Colombier p++;
2053e12c5d1SDavid du Colombier compl=*p=='~';
206dc5a79c1SDavid du Colombier if(compl)
207dc5a79c1SDavid du Colombier p++;
2083e12c5d1SDavid du Colombier hit = 0;
2093e12c5d1SDavid du Colombier while(*p!=']'){
210dc5a79c1SDavid du Colombier if(*p=='\0')
211dc5a79c1SDavid du Colombier return 0; /* syntax error */
2123e12c5d1SDavid du Colombier lo = unicode(p);
2133e12c5d1SDavid du Colombier p = nextutf(p);
214dc5a79c1SDavid du Colombier if(*p!='-')
215dc5a79c1SDavid du Colombier hi = lo;
2163e12c5d1SDavid du Colombier else{
2173e12c5d1SDavid du Colombier p++;
218dc5a79c1SDavid du Colombier if(*p=='\0')
219dc5a79c1SDavid du Colombier return 0; /* syntax error */
2203e12c5d1SDavid du Colombier hi = unicode(p);
2213e12c5d1SDavid du Colombier p = nextutf(p);
2223e12c5d1SDavid du Colombier if(hi<lo){ t = lo; lo = hi; hi = t; }
2233e12c5d1SDavid du Colombier }
224dc5a79c1SDavid du Colombier if(lo<=c && c<=hi)
225dc5a79c1SDavid du Colombier hit = 1;
2263e12c5d1SDavid du Colombier }
227dc5a79c1SDavid du Colombier if(compl)
228dc5a79c1SDavid du Colombier hit=!hit;
229dc5a79c1SDavid du Colombier if(!hit)
230dc5a79c1SDavid du Colombier return 0;
2313e12c5d1SDavid du Colombier break;
2323e12c5d1SDavid du Colombier }
2333e12c5d1SDavid du Colombier }
2343e12c5d1SDavid du Colombier return *s=='\0';
2353e12c5d1SDavid du Colombier }
236dc5a79c1SDavid du Colombier
237dc5a79c1SDavid du Colombier void
globlist1(word * gl)238dc5a79c1SDavid du Colombier globlist1(word *gl)
2393e12c5d1SDavid du Colombier {
2403e12c5d1SDavid du Colombier if(gl){
2413e12c5d1SDavid du Colombier globlist1(gl->next);
2423e12c5d1SDavid du Colombier glob(gl->word);
2433e12c5d1SDavid du Colombier }
2443e12c5d1SDavid du Colombier }
245dc5a79c1SDavid du Colombier
246dc5a79c1SDavid du Colombier void
globlist(void)247dc5a79c1SDavid du Colombier globlist(void)
248dc5a79c1SDavid du Colombier {
2493e12c5d1SDavid du Colombier word *a;
2503e12c5d1SDavid du Colombier globv = 0;
2513e12c5d1SDavid du Colombier globlist1(runq->argv->words);
2523e12c5d1SDavid du Colombier poplist();
2533e12c5d1SDavid du Colombier pushlist();
2543e12c5d1SDavid du Colombier if(globv){
2553e12c5d1SDavid du Colombier for(a = globv;a->next;a = a->next);
2563e12c5d1SDavid du Colombier a->next = runq->argv->words;
2573e12c5d1SDavid du Colombier runq->argv->words = globv;
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier }
260