diff options
author | Szabolcs Nagy <nsz@port70.net> | 2014-07-29 19:39:19 +0200 |
---|---|---|
committer | Szabolcs Nagy <nsz@port70.net> | 2014-07-29 19:39:19 +0200 |
commit | a126188f864f439e5243d75601f179ea72a7b4e7 (patch) | |
tree | 800ff43a9c612e0af1ca49e51ccf49cd7c2c0457 | |
parent | e4dd0ab83cc191ba4e7d6e10328c30280d267ed9 (diff) | |
download | musl-a126188f864f439e5243d75601f179ea72a7b4e7.tar.gz musl-a126188f864f439e5243d75601f179ea72a7b4e7.tar.bz2 musl-a126188f864f439e5243d75601f179ea72a7b4e7.tar.xz musl-a126188f864f439e5243d75601f179ea72a7b4e7.zip |
tweaks to plural rules evaluator
const parsing, depth accounting and failure handling was changed
a bit so the generated code is slightly smaller.
-rw-r--r-- | src/locale/pleval.c | 98 |
1 files changed, 44 insertions, 54 deletions
diff --git a/src/locale/pleval.c b/src/locale/pleval.c index 47aefc34..03370bcf 100644 --- a/src/locale/pleval.c +++ b/src/locale/pleval.c @@ -33,15 +33,10 @@ static const char *skipspace(const char *s) return s; } -static unsigned long evalconst(struct st *st) +static unsigned long fail(struct st *st) { - char *e; - unsigned long n; - n = strtoul(st->s, &e, 10); - if (!isdigit(*st->s) || e == st->s || n == -1) - st->err = 1; - st->s = skipspace(e); - return n; + st->err = 1; + return 0; } static unsigned long evalexpr(struct st *st, int d); @@ -49,47 +44,47 @@ static unsigned long evalexpr(struct st *st, int d); static unsigned long evalterm(struct st *st, int d) { unsigned long a; - if (d <= 0) { - st->err = 1; - return 0; - } + char *e; + if (--d < 0) return fail(st); st->s = skipspace(st->s); - if (*st->s == '!') { - st->s++; - return !evalterm(st, d-1); + if (isdigit(*st->s)) { + a = strtoul(st->s, &e, 10); + if (e == st->s || a == -1) return fail(st); + st->s = skipspace(e); + return a; + } + if (*st->s == 'n') { + st->s = skipspace(st->s + 1); + return st->n; } if (*st->s == '(') { st->s++; - a = evalexpr(st, d-1); - if (*st->s != ')') { - st->err = 1; - return 0; - } + a = evalexpr(st, d); + if (*st->s != ')') return fail(st); st->s = skipspace(st->s + 1); return a; } - if (*st->s == 'n') { - st->s = skipspace(st->s + 1); - return st->n; + if (*st->s == '!') { + st->s++; + return !evalterm(st, d); } - return evalconst(st); + return fail(st); } static unsigned long evalmul(struct st *st, int d) { - unsigned long b, a = evalterm(st, d-1); + unsigned long b, a = evalterm(st, d); int op; for (;;) { op = *st->s; if (op != '*' && op != '/' && op != '%') return a; st->s++; - b = evalterm(st, d-1); + b = evalterm(st, d); if (op == '*') { a *= b; } else if (!b) { - st->err = 1; - return 0; + return fail(st); } else if (op == '%') { a %= b; } else { @@ -101,19 +96,19 @@ static unsigned long evalmul(struct st *st, int d) static unsigned long evaladd(struct st *st, int d) { unsigned long a = 0; - int add = 1; + int sub = 0; for (;;) { - a += (add?1:-1) * evalmul(st, d-1); + a += (sub ? -1 : 1) * evalmul(st, d); if (*st->s != '+' && *st->s != '-') return a; - add = *st->s == '+'; + sub = *st->s == '-'; st->s++; } } static unsigned long evalrel(struct st *st, int d) { - unsigned long b, a = evaladd(st, d-1); + unsigned long b, a = evaladd(st, d); int less, eq; for (;;) { if (*st->s != '<' && *st->s != '>') @@ -121,65 +116,60 @@ static unsigned long evalrel(struct st *st, int d) less = st->s[0] == '<'; eq = st->s[1] == '='; st->s += 1 + eq; - b = evaladd(st, d-1); + b = evaladd(st, d); a = (less ? a < b : a > b) || (eq && a == b); } } static unsigned long evaleq(struct st *st, int d) { - unsigned long a = evalrel(st, d-1); - int neg; + unsigned long a = evalrel(st, d); + int c; for (;;) { - if ((st->s[0] != '=' && st->s[0] != '!') || st->s[1] != '=') + c = st->s[0]; + if ((c != '=' && c != '!') || st->s[1] != '=') return a; - neg = st->s[0] == '!'; st->s += 2; - a = evalrel(st, d-1) == a; - a ^= neg; + a = (evalrel(st, d) == a) ^ (c == '!'); } } static unsigned long evaland(struct st *st, int d) { - unsigned long a = evaleq(st, d-1); + unsigned long a = evaleq(st, d); for (;;) { if (st->s[0] != '&' || st->s[1] != '&') return a; st->s += 2; - a = evaleq(st, d-1) && a; + a = evaleq(st, d) && a; } } static unsigned long evalor(struct st *st, int d) { - unsigned long a = evaland(st, d-1); + unsigned long a = evaland(st, d); for (;;) { if (st->s[0] != '|' || st->s[1] != '|') return a; st->s += 2; - a = evaland(st, d-1) || a; + a = evaland(st, d) || a; } } static unsigned long evalexpr(struct st *st, int d) { unsigned long a1, a2, a3; - if (d <= 0) { - st->err = 1; - return 0; - } - a1 = evalor(st, d-1); + if (--d < 0) + return fail(st); + a1 = evalor(st, d-6); if (*st->s != '?') return a1; st->s++; - a2 = evalexpr(st, d-1); - if (*st->s != ':') { - st->err = 1; - return 0; - } + a2 = evalexpr(st, d); + if (*st->s != ':') + return fail(st); st->s++; - a3 = evalexpr(st, d-1); + a3 = evalexpr(st, d); return a1 ? a2 : a3; } |