diff --git a/src/modal.c b/src/modal.c index d7a2880..7cf6066 100644 --- a/src/modal.c +++ b/src/modal.c @@ -30,43 +30,6 @@ walk(char *s) return s; } -static int -bind(int id, char *b) -{ - if(regs[id]) { - char *a = regs[id], *aa = walk(a), *bb = walk(b); - while(a < aa && b < bb) - if(*a++ != *b++) return 0; - } else if(id == ':') { - char *bb = walk(b); - if(*b == '(') b++, --bb; - while(b < bb) putc(*(b++), stdout); - } else - regs[id] = b; - return 1; -} - -static char * -match(char *p, Rule *r) -{ - int i; - char c, *a = r->a, *b = p; - for(i = 0x21; i < 0x7f; i++) - if((char)i != ':') - regs[i] = 0; - while((c = *a)) { - if(c == '?') { - if(!bind(*(++a), b)) return NULL; - a++, b = walk(b); - continue; - } - if(*a != *b) return NULL; - a++, b++; - } - c = *b; - return spacer(c) ? b : NULL; -} - static char * plode(char *s) { @@ -93,7 +56,23 @@ plode(char *s) } static int -commit(char r) +bind_reg(int r, char *b) +{ + if(regs[r]) { + char *a = regs[r], *aa = walk(a), *bb = walk(b); + while(a < aa && b < bb) + if(*a++ != *b++) return 0; + } else if(r == ':') { + char *bb = walk(b); + if(*b == '(') b++, --bb; + while(b < bb) putc(*(b++), stdout); + } else + regs[r] = b; + return 1; +} + +static int +write_reg(char r) { char *s = regs[(int)r]; if(r == '*') @@ -107,8 +86,29 @@ commit(char r) return 1; } +static char * +match_rule(char *p, Rule *r) +{ + int i; + char c, *a = r->a, *b = p; + for(i = 0x21; i < 0x7f; i++) + if((char)i != ':') + regs[i] = 0; + while((c = *a)) { + if(c == '?') { + if(!bind_reg(*(++a), b)) return NULL; + a++, b = walk(b); + continue; + } + if(*a != *b) return NULL; + a++, b++; + } + c = *b; + return spacer(c) ? b : NULL; +} + static int -save(int rule, char *s) +commit_rule(int rule, char *s) { while((*outp_++ = *s++)) ; @@ -133,6 +133,19 @@ parse_rule(char *s) return d; } +static int +add_rule(char *p) +{ + char c; + Rule *r = &rules[rules_len++]; + p += 2; + while((c = *p) && c <= ' ') p++; + r->a = parse_rule(p), p = walk(p); + while((c = *p) && c <= ' ') p++; + r->b = parse_rule(p), p = walk(p); + return commit_rule(-1, p); +} + static int rewrite(void) { @@ -140,30 +153,22 @@ rewrite(void) while((c = *p) && c <= ' ') p++; while((c = *p)) { int i; - if(p[0] == '<' && p[1] == '>') { - Rule *r = &rules[rules_len++]; - p += 2; - while((c = *p) && c <= ' ') p++; - r->a = parse_rule(p), p = walk(p); - while((c = *p) && c <= ' ') p++; - r->b = parse_rule(p), p = walk(p); - return save(-1, p); - } + if(p[0] == '<' && p[1] == '>') return add_rule(p); if(p != o) c_ = *(p - 1); if(p == o || spacer(c_)) { for(i = 0; i < rules_len; i++) { Rule *r = &rules[i]; - char *res = match(p, r); + char *res = match_rule(p, r); if(res != NULL) { char cc, *b = r->b; if(!*b && last == ' ') outp_--; while((cc = *b++)) { if(cc == '?') - commit(*b++); + write_reg(*b++); else *outp_++ = cc; } - return save(i, res); + return commit_rule(i, res); } } }