diff options
| -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;  } | 
