diff options
Diffstat (limited to 'src/cmd/rc/glob.c')
-rw-r--r-- | src/cmd/rc/glob.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/cmd/rc/glob.c b/src/cmd/rc/glob.c new file mode 100644 index 0000000..9d88b59 --- /dev/null +++ b/src/cmd/rc/glob.c @@ -0,0 +1,82 @@ +#include "rc.h" + +/* removes glob marks in place */ +void +deglob(char *s) +{ + char *t = s; + do{ + if(*t==GLOB) + t++; + *s++=*t; + }while(*t++); +} + +int +match(char *s, char *p, int stop) +{ + rune rs, rp, lo, hi; + int neg, hit; + + utf8·decode(p, &rp), utf8·decode(s, &rs); + for(; *p && *p != stop; s+=utf8·decode(s,&rs),p+=utf8·decode(p,&rp)){ + /* fast path: normal character */ + if(*p != GLOB){ + if(rp != rs) + return 0; + continue; + } + + /* unglob */ + switch(*++p){ + case GLOB: + if(*s != GLOB) + return 0; + break; + case '*': + for(;;){ + p += utf8·decode(p, &rp); + if(match(s, p, stop)) + return 1; + s += utf8·decode(s, &rs); + } + return 0; + + case '?': + if(*s == 0) + return 0; + break; + + case '[': + if(*s==0) + return 0; + if((neg=*++p=='~')) + p++; + hit = 0; + while(*p != ']'){ + if(*p==0) + return 0; /* syntax error */ + p += utf8·decode(p, &lo); + if(*p != '-') + hi = lo; + else{ + if(*++p == 0) + return 0; /* syntax error */ + p += utf8·decode(p, &hi); + if(hi < lo) + rp=lo, lo=hi, hi=rp; + } + + if(lo <= rs && rs <= hi) + hit = 1; + } + if(neg) + hit=!hit; + if(!hit) + return 0; + break; + } + } + + return *s == 0; +} |