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 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 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 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; 34*99eb86a7SDavid du Colombier for(a = left;a!=right;a = a->next) n++; 353e12c5d1SDavid du Colombier list = (char **)emalloc(n*sizeof(char *)); 36*99eb86a7SDavid 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); 38*99eb86a7SDavid 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 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'; 76*99eb86a7SDavid du Colombier if((f = Opendir(globname[0]?globname:"."))<0) return; 77*99eb86a7SDavid du Colombier while(*newp!='/' && *newp!='\0') newp++; 786b6b9ac8SDavid du Colombier while(Readdir(f, namep, *newp=='/')){ 793e12c5d1SDavid du Colombier if(matchfn(namep, p)){ 80*99eb86a7SDavid 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 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 } 1143e12c5d1SDavid du Colombier /* 1153e12c5d1SDavid du Colombier * Do p and q point at equal utf codes 1163e12c5d1SDavid du Colombier */ 117dc5a79c1SDavid du Colombier 118dc5a79c1SDavid du Colombier int 119276e7d6dSDavid du Colombier equtf(uchar *p, uchar *q) 120dc5a79c1SDavid du Colombier { 121dc5a79c1SDavid du Colombier if(*p!=*q) 122dc5a79c1SDavid du Colombier return 0; 123*99eb86a7SDavid du Colombier if(twobyte(*p)) return p[1]==q[1]; 1243e12c5d1SDavid du Colombier if(threebyte(*p)){ 125dc5a79c1SDavid du Colombier if(p[1]!=q[1]) 126dc5a79c1SDavid du Colombier return 0; 127dc5a79c1SDavid du Colombier if(p[1]=='\0') 128dc5a79c1SDavid du Colombier return 1; /* broken code at end of string! */ 1293e12c5d1SDavid du Colombier return p[2]==q[2]; 1303e12c5d1SDavid du Colombier } 1313e12c5d1SDavid du Colombier return 1; 1323e12c5d1SDavid du Colombier } 1333e12c5d1SDavid du Colombier /* 1343e12c5d1SDavid du Colombier * Return a pointer to the next utf code in the string, 1353e12c5d1SDavid du Colombier * not jumping past nuls in broken utf codes! 1363e12c5d1SDavid du Colombier */ 137dc5a79c1SDavid du Colombier 138276e7d6dSDavid du Colombier uchar* 139276e7d6dSDavid du Colombier nextutf(uchar *p) 140dc5a79c1SDavid du Colombier { 141*99eb86a7SDavid du Colombier if(twobyte(*p)) return p[1]=='\0'?p+1:p+2; 142*99eb86a7SDavid du Colombier if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3; 1433e12c5d1SDavid du Colombier return p+1; 1443e12c5d1SDavid du Colombier } 1453e12c5d1SDavid du Colombier /* 1463e12c5d1SDavid du Colombier * Convert the utf code at *p to a unicode value 1473e12c5d1SDavid du Colombier */ 148dc5a79c1SDavid du Colombier 149dc5a79c1SDavid du Colombier int 150276e7d6dSDavid du Colombier unicode(uchar *p) 151dc5a79c1SDavid du Colombier { 152276e7d6dSDavid du Colombier int u = *p; 153276e7d6dSDavid du Colombier 154276e7d6dSDavid du Colombier if(twobyte(u)) 155276e7d6dSDavid du Colombier return ((u&0x1f)<<6)|(p[1]&0x3f); 156276e7d6dSDavid du Colombier if(threebyte(u)) 157276e7d6dSDavid du Colombier return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f); 1583e12c5d1SDavid du Colombier return u; 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier /* 1613e12c5d1SDavid du Colombier * Does the string s match the pattern p 1623e12c5d1SDavid du Colombier * . and .. are only matched by patterns starting with . 1633e12c5d1SDavid du Colombier * * matches any sequence of characters 1643e12c5d1SDavid du Colombier * ? matches any single character 1653e12c5d1SDavid du Colombier * [...] matches the enclosed list of characters 1663e12c5d1SDavid du Colombier */ 167dc5a79c1SDavid du Colombier 168dc5a79c1SDavid du Colombier int 169276e7d6dSDavid du Colombier matchfn(void *as, void *ap) 1703e12c5d1SDavid du Colombier { 171276e7d6dSDavid du Colombier uchar *s = as, *p = ap; 172276e7d6dSDavid du Colombier 1733e12c5d1SDavid du Colombier if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.') 1743e12c5d1SDavid du Colombier return 0; 1753e12c5d1SDavid du Colombier return match(s, p, '/'); 1763e12c5d1SDavid du Colombier } 177dc5a79c1SDavid du Colombier 178dc5a79c1SDavid du Colombier int 179276e7d6dSDavid du Colombier match(void *as, void *ap, int stop) 1803e12c5d1SDavid du Colombier { 1813e12c5d1SDavid du Colombier int compl, hit, lo, hi, t, c; 182276e7d6dSDavid du Colombier uchar *s = as, *p = ap; 183276e7d6dSDavid du Colombier 1843e12c5d1SDavid du Colombier for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){ 1853e12c5d1SDavid du Colombier if(*p!=GLOB){ 1863e12c5d1SDavid du Colombier if(!equtf(p, s)) return 0; 1873e12c5d1SDavid du Colombier } 1883e12c5d1SDavid du Colombier else switch(*++p){ 1893e12c5d1SDavid du Colombier case GLOB: 190dc5a79c1SDavid du Colombier if(*s!=GLOB) 191dc5a79c1SDavid du Colombier return 0; 1923e12c5d1SDavid du Colombier break; 1933e12c5d1SDavid du Colombier case '*': 1943e12c5d1SDavid du Colombier for(;;){ 1953e12c5d1SDavid du Colombier if(match(s, nextutf(p), stop)) return 1; 196dc5a79c1SDavid du Colombier if(!*s) 197dc5a79c1SDavid du Colombier break; 1983e12c5d1SDavid du Colombier s = nextutf(s); 1993e12c5d1SDavid du Colombier } 2003e12c5d1SDavid du Colombier return 0; 2013e12c5d1SDavid du Colombier case '?': 202dc5a79c1SDavid du Colombier if(*s=='\0') 203dc5a79c1SDavid du Colombier return 0; 2043e12c5d1SDavid du Colombier break; 2053e12c5d1SDavid du Colombier case '[': 206dc5a79c1SDavid du Colombier if(*s=='\0') 207dc5a79c1SDavid du Colombier return 0; 2083e12c5d1SDavid du Colombier c = unicode(s); 2093e12c5d1SDavid du Colombier p++; 2103e12c5d1SDavid du Colombier compl=*p=='~'; 211dc5a79c1SDavid du Colombier if(compl) 212dc5a79c1SDavid du Colombier p++; 2133e12c5d1SDavid du Colombier hit = 0; 2143e12c5d1SDavid du Colombier while(*p!=']'){ 215dc5a79c1SDavid du Colombier if(*p=='\0') 216dc5a79c1SDavid du Colombier return 0; /* syntax error */ 2173e12c5d1SDavid du Colombier lo = unicode(p); 2183e12c5d1SDavid du Colombier p = nextutf(p); 219dc5a79c1SDavid du Colombier if(*p!='-') 220dc5a79c1SDavid du Colombier hi = lo; 2213e12c5d1SDavid du Colombier else{ 2223e12c5d1SDavid du Colombier p++; 223dc5a79c1SDavid du Colombier if(*p=='\0') 224dc5a79c1SDavid du Colombier return 0; /* syntax error */ 2253e12c5d1SDavid du Colombier hi = unicode(p); 2263e12c5d1SDavid du Colombier p = nextutf(p); 2273e12c5d1SDavid du Colombier if(hi<lo){ t = lo; lo = hi; hi = t; } 2283e12c5d1SDavid du Colombier } 229dc5a79c1SDavid du Colombier if(lo<=c && c<=hi) 230dc5a79c1SDavid du Colombier hit = 1; 2313e12c5d1SDavid du Colombier } 232dc5a79c1SDavid du Colombier if(compl) 233dc5a79c1SDavid du Colombier hit=!hit; 234dc5a79c1SDavid du Colombier if(!hit) 235dc5a79c1SDavid du Colombier return 0; 2363e12c5d1SDavid du Colombier break; 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier } 2393e12c5d1SDavid du Colombier return *s=='\0'; 2403e12c5d1SDavid du Colombier } 241dc5a79c1SDavid du Colombier 242dc5a79c1SDavid du Colombier void 243dc5a79c1SDavid du Colombier globlist1(word *gl) 2443e12c5d1SDavid du Colombier { 2453e12c5d1SDavid du Colombier if(gl){ 2463e12c5d1SDavid du Colombier globlist1(gl->next); 2473e12c5d1SDavid du Colombier glob(gl->word); 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier } 250dc5a79c1SDavid du Colombier 251dc5a79c1SDavid du Colombier void 252dc5a79c1SDavid du Colombier globlist(void) 253dc5a79c1SDavid du Colombier { 2543e12c5d1SDavid du Colombier word *a; 2553e12c5d1SDavid du Colombier globv = 0; 2563e12c5d1SDavid du Colombier globlist1(runq->argv->words); 2573e12c5d1SDavid du Colombier poplist(); 2583e12c5d1SDavid du Colombier pushlist(); 2593e12c5d1SDavid du Colombier if(globv){ 2603e12c5d1SDavid du Colombier for(a = globv;a->next;a = a->next); 2613e12c5d1SDavid du Colombier a->next = runq->argv->words; 2623e12c5d1SDavid du Colombier runq->argv->words = globv; 2633e12c5d1SDavid du Colombier } 2643e12c5d1SDavid du Colombier } 265