Annotation of lucent/sys/src/cmd/rc/glob.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.