1*3e12c5d1SDavid du Colombier #include "rc.h" 2*3e12c5d1SDavid du Colombier #include "exec.h" 3*3e12c5d1SDavid du Colombier #include "fns.h" 4*3e12c5d1SDavid du Colombier char *globname; 5*3e12c5d1SDavid du Colombier struct word *globv; 6*3e12c5d1SDavid du Colombier /* 7*3e12c5d1SDavid du Colombier * delete all the GLOB marks from s, in place 8*3e12c5d1SDavid du Colombier */ 9*3e12c5d1SDavid du Colombier void deglob(char *s) 10*3e12c5d1SDavid du Colombier { 11*3e12c5d1SDavid du Colombier char *t=s; 12*3e12c5d1SDavid du Colombier do{ 13*3e12c5d1SDavid du Colombier if(*t==GLOB) t++; 14*3e12c5d1SDavid du Colombier *s++=*t; 15*3e12c5d1SDavid du Colombier }while(*t++); 16*3e12c5d1SDavid du Colombier } 17*3e12c5d1SDavid du Colombier int globcmp(char **s, char **t) 18*3e12c5d1SDavid du Colombier { 19*3e12c5d1SDavid du Colombier return strcmp(*s, *t); 20*3e12c5d1SDavid du Colombier } 21*3e12c5d1SDavid du Colombier void globsort(word *left, word *right) 22*3e12c5d1SDavid du Colombier { 23*3e12c5d1SDavid du Colombier char **list; 24*3e12c5d1SDavid du Colombier word *a; 25*3e12c5d1SDavid du Colombier int n=0; 26*3e12c5d1SDavid du Colombier for(a=left;a!=right;a=a->next) n++; 27*3e12c5d1SDavid du Colombier list=(char **)emalloc(n*sizeof(char *)); 28*3e12c5d1SDavid du Colombier for(a=left,n=0;a!=right;a=a->next,n++) list[n]=a->word; 29*3e12c5d1SDavid du Colombier qsort((char *)list, n, sizeof(char *), globcmp); 30*3e12c5d1SDavid du Colombier for(a=left,n=0;a!=right;a=a->next,n++) a->word=list[n]; 31*3e12c5d1SDavid du Colombier efree((char *)list); 32*3e12c5d1SDavid du Colombier } 33*3e12c5d1SDavid du Colombier /* 34*3e12c5d1SDavid du Colombier * Push names prefixed by globname and suffixed by a match of p onto the astack. 35*3e12c5d1SDavid du Colombier * namep points to the end of the prefix in globname. 36*3e12c5d1SDavid du Colombier */ 37*3e12c5d1SDavid du Colombier void globdir(char *p, char *namep) 38*3e12c5d1SDavid du Colombier { 39*3e12c5d1SDavid du Colombier char *t, *newp; 40*3e12c5d1SDavid du Colombier int f; 41*3e12c5d1SDavid du Colombier /* scan the pattern looking for a component with a metacharacter in it */ 42*3e12c5d1SDavid du Colombier if(*p=='\0'){ 43*3e12c5d1SDavid du Colombier globv=newword(globname, globv); 44*3e12c5d1SDavid du Colombier return; 45*3e12c5d1SDavid du Colombier } 46*3e12c5d1SDavid du Colombier t=namep; 47*3e12c5d1SDavid du Colombier newp=p; 48*3e12c5d1SDavid du Colombier while(*newp){ 49*3e12c5d1SDavid du Colombier if(*newp==GLOB) 50*3e12c5d1SDavid du Colombier break; 51*3e12c5d1SDavid du Colombier *t=*newp++; 52*3e12c5d1SDavid du Colombier if(*t++=='/'){ 53*3e12c5d1SDavid du Colombier namep=t; 54*3e12c5d1SDavid du Colombier p=newp; 55*3e12c5d1SDavid du Colombier } 56*3e12c5d1SDavid du Colombier } 57*3e12c5d1SDavid du Colombier /* If we ran out of pattern, append the name if accessible */ 58*3e12c5d1SDavid du Colombier if(*newp=='\0'){ 59*3e12c5d1SDavid du Colombier *t='\0'; 60*3e12c5d1SDavid du Colombier if(access(globname, 0)==0) 61*3e12c5d1SDavid du Colombier globv=newword(globname, globv); 62*3e12c5d1SDavid du Colombier return; 63*3e12c5d1SDavid du Colombier } 64*3e12c5d1SDavid du Colombier /* read the directory and recur for any entry that matches */ 65*3e12c5d1SDavid du Colombier *namep='\0'; 66*3e12c5d1SDavid du Colombier if((f=Opendir(globname[0]?globname:"."))<0) return; 67*3e12c5d1SDavid du Colombier while(*newp!='/' && *newp!='\0') newp++; 68*3e12c5d1SDavid du Colombier while(Readdir(f, namep)){ 69*3e12c5d1SDavid du Colombier if(matchfn(namep, p)){ 70*3e12c5d1SDavid du Colombier for(t=namep;*t;t++); 71*3e12c5d1SDavid du Colombier globdir(newp, t); 72*3e12c5d1SDavid du Colombier } 73*3e12c5d1SDavid du Colombier } 74*3e12c5d1SDavid du Colombier Closedir(f); 75*3e12c5d1SDavid du Colombier } 76*3e12c5d1SDavid du Colombier /* 77*3e12c5d1SDavid du Colombier * Push all file names matched by p on the current thread's stack. 78*3e12c5d1SDavid du Colombier * If there are no matches, the list consists of p. 79*3e12c5d1SDavid du Colombier */ 80*3e12c5d1SDavid du Colombier void glob(char *p) 81*3e12c5d1SDavid du Colombier { 82*3e12c5d1SDavid du Colombier word *svglobv=globv; 83*3e12c5d1SDavid du Colombier int globlen=Globsize(p); 84*3e12c5d1SDavid du Colombier if(!globlen){ 85*3e12c5d1SDavid du Colombier deglob(p); 86*3e12c5d1SDavid du Colombier globv=newword(p, globv); 87*3e12c5d1SDavid du Colombier return; 88*3e12c5d1SDavid du Colombier } 89*3e12c5d1SDavid du Colombier globname=emalloc(globlen); 90*3e12c5d1SDavid du Colombier globname[0]='\0'; 91*3e12c5d1SDavid du Colombier globdir(p, globname); 92*3e12c5d1SDavid du Colombier efree(globname); 93*3e12c5d1SDavid du Colombier if(svglobv==globv){ 94*3e12c5d1SDavid du Colombier deglob(p); 95*3e12c5d1SDavid du Colombier globv=newword(p, globv); 96*3e12c5d1SDavid du Colombier } 97*3e12c5d1SDavid du Colombier else 98*3e12c5d1SDavid du Colombier globsort(globv, svglobv); 99*3e12c5d1SDavid du Colombier } 100*3e12c5d1SDavid du Colombier /* 101*3e12c5d1SDavid du Colombier * Do p and q point at equal utf codes 102*3e12c5d1SDavid du Colombier */ 103*3e12c5d1SDavid du Colombier int equtf(char *p, char *q){ 104*3e12c5d1SDavid du Colombier if(*p!=*q) return 0; 105*3e12c5d1SDavid du Colombier if(twobyte(*p)) return p[1]==q[1]; 106*3e12c5d1SDavid du Colombier if(threebyte(*p)){ 107*3e12c5d1SDavid du Colombier if(p[1]!=q[1]) return 0; 108*3e12c5d1SDavid du Colombier if(p[1]=='\0') return 1; /* broken code at end of string! */ 109*3e12c5d1SDavid du Colombier return p[2]==q[2]; 110*3e12c5d1SDavid du Colombier } 111*3e12c5d1SDavid du Colombier return 1; 112*3e12c5d1SDavid du Colombier } 113*3e12c5d1SDavid du Colombier /* 114*3e12c5d1SDavid du Colombier * Return a pointer to the next utf code in the string, 115*3e12c5d1SDavid du Colombier * not jumping past nuls in broken utf codes! 116*3e12c5d1SDavid du Colombier */ 117*3e12c5d1SDavid du Colombier char *nextutf(char *p){ 118*3e12c5d1SDavid du Colombier int u=*p&0xff; 119*3e12c5d1SDavid du Colombier if(twobyte(*p)) return p[1]=='\0'?p+1:p+2; 120*3e12c5d1SDavid du Colombier if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3; 121*3e12c5d1SDavid du Colombier return p+1; 122*3e12c5d1SDavid du Colombier } 123*3e12c5d1SDavid du Colombier /* 124*3e12c5d1SDavid du Colombier * Convert the utf code at *p to a unicode value 125*3e12c5d1SDavid du Colombier */ 126*3e12c5d1SDavid du Colombier int unicode(char *p){ 127*3e12c5d1SDavid du Colombier int u=*p&0xff, v; 128*3e12c5d1SDavid du Colombier if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f); 129*3e12c5d1SDavid du Colombier if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f); 130*3e12c5d1SDavid du Colombier return u; 131*3e12c5d1SDavid du Colombier } 132*3e12c5d1SDavid du Colombier /* 133*3e12c5d1SDavid du Colombier * Does the string s match the pattern p 134*3e12c5d1SDavid du Colombier * . and .. are only matched by patterns starting with . 135*3e12c5d1SDavid du Colombier * * matches any sequence of characters 136*3e12c5d1SDavid du Colombier * ? matches any single character 137*3e12c5d1SDavid du Colombier * [...] matches the enclosed list of characters 138*3e12c5d1SDavid du Colombier */ 139*3e12c5d1SDavid du Colombier int matchfn(char *s, char *p) 140*3e12c5d1SDavid du Colombier { 141*3e12c5d1SDavid du Colombier if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.') 142*3e12c5d1SDavid du Colombier return 0; 143*3e12c5d1SDavid du Colombier return match(s, p, '/'); 144*3e12c5d1SDavid du Colombier } 145*3e12c5d1SDavid du Colombier int match(char *s, char *p, int stop) 146*3e12c5d1SDavid du Colombier { 147*3e12c5d1SDavid du Colombier int compl, hit, lo, hi, t, c; 148*3e12c5d1SDavid du Colombier for(;*p!=stop && *p!='\0';s=nextutf(s),p=nextutf(p)){ 149*3e12c5d1SDavid du Colombier if(*p!=GLOB){ 150*3e12c5d1SDavid du Colombier if(!equtf(p, s)) return 0; 151*3e12c5d1SDavid du Colombier } 152*3e12c5d1SDavid du Colombier else switch(*++p){ 153*3e12c5d1SDavid du Colombier case GLOB: 154*3e12c5d1SDavid du Colombier if(*s!=GLOB) return 0; 155*3e12c5d1SDavid du Colombier break; 156*3e12c5d1SDavid du Colombier case '*': 157*3e12c5d1SDavid du Colombier for(;;){ 158*3e12c5d1SDavid du Colombier if(match(s, nextutf(p), stop)) return 1; 159*3e12c5d1SDavid du Colombier if(!*s) break; 160*3e12c5d1SDavid du Colombier s=nextutf(s); 161*3e12c5d1SDavid du Colombier } 162*3e12c5d1SDavid du Colombier return 0; 163*3e12c5d1SDavid du Colombier case '?': 164*3e12c5d1SDavid du Colombier if(*s=='\0') return 0; 165*3e12c5d1SDavid du Colombier break; 166*3e12c5d1SDavid du Colombier case '[': 167*3e12c5d1SDavid du Colombier if(*s=='\0') return 0; 168*3e12c5d1SDavid du Colombier c=unicode(s); 169*3e12c5d1SDavid du Colombier p++; 170*3e12c5d1SDavid du Colombier compl=*p=='~'; 171*3e12c5d1SDavid du Colombier if(compl) p++; 172*3e12c5d1SDavid du Colombier hit=0; 173*3e12c5d1SDavid du Colombier while(*p!=']'){ 174*3e12c5d1SDavid du Colombier if(*p=='\0') return 0; /* syntax error */ 175*3e12c5d1SDavid du Colombier lo=unicode(p); 176*3e12c5d1SDavid du Colombier p=nextutf(p); 177*3e12c5d1SDavid du Colombier if(*p!='-') hi=lo; 178*3e12c5d1SDavid du Colombier else{ 179*3e12c5d1SDavid du Colombier p++; 180*3e12c5d1SDavid du Colombier if(*p=='\0') return 0; /* syntax error */ 181*3e12c5d1SDavid du Colombier hi=unicode(p); 182*3e12c5d1SDavid du Colombier p=nextutf(p); 183*3e12c5d1SDavid du Colombier if(hi<lo){ t=lo; lo=hi; hi=t; } 184*3e12c5d1SDavid du Colombier } 185*3e12c5d1SDavid du Colombier if(lo<=c && c<=hi) hit=1; 186*3e12c5d1SDavid du Colombier } 187*3e12c5d1SDavid du Colombier if(compl) hit=!hit; 188*3e12c5d1SDavid du Colombier if(!hit) return 0; 189*3e12c5d1SDavid du Colombier break; 190*3e12c5d1SDavid du Colombier } 191*3e12c5d1SDavid du Colombier } 192*3e12c5d1SDavid du Colombier return *s=='\0'; 193*3e12c5d1SDavid du Colombier } 194*3e12c5d1SDavid du Colombier void globlist1(word *gl) 195*3e12c5d1SDavid du Colombier { 196*3e12c5d1SDavid du Colombier if(gl){ 197*3e12c5d1SDavid du Colombier globlist1(gl->next); 198*3e12c5d1SDavid du Colombier glob(gl->word); 199*3e12c5d1SDavid du Colombier } 200*3e12c5d1SDavid du Colombier } 201*3e12c5d1SDavid du Colombier void globlist(void){ 202*3e12c5d1SDavid du Colombier word *a; 203*3e12c5d1SDavid du Colombier globv=0; 204*3e12c5d1SDavid du Colombier globlist1(runq->argv->words); 205*3e12c5d1SDavid du Colombier poplist(); 206*3e12c5d1SDavid du Colombier pushlist(); 207*3e12c5d1SDavid du Colombier if(globv){ 208*3e12c5d1SDavid du Colombier for(a=globv;a->next;a=a->next); 209*3e12c5d1SDavid du Colombier a->next=runq->argv->words; 210*3e12c5d1SDavid du Colombier runq->argv->words=globv; 211*3e12c5d1SDavid du Colombier } 212*3e12c5d1SDavid du Colombier } 213