Annotation of lucent/sys/src/cmd/rc/glob.c, revision 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.