diff options
author | Nicholas <nbnoll@eml.cc> | 2021-11-15 15:08:03 -0800 |
---|---|---|
committer | Nicholas <nbnoll@eml.cc> | 2021-11-15 15:08:14 -0800 |
commit | e9ff1c6fbbbac9ece2604876ab589ac282360446 (patch) | |
tree | 1e1378a1cb37ca4e751d8140eeed99db7ccc4ce7 /src/cmd/rc/glob.c | |
parent | 27d656be97f1544d7535d8c144ff28b9214aed97 (diff) |
Feat: added if/else branching and switch statement
Unsure about my modification to the language. I found the parsing of the
case body within switches to be odd - specifically that it parses
liberally and then checks that it has case -> cmd structuring while it
walks the code. This means the language is more permissive than the
semantics. I modified it to be more explicit, but at the cost of having
to end each case statement with a semicolon. I wanted a colon, but this
is a valid word character and thus will be lexed as part of the word.
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; +} |