Introduction
Introduction Statistics Contact Development Disclaimer Help
expr: treat expressions as strs until evaluation - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
commit e50d533d598dbe284e225e2ee52ed5f76a6e6f6a
parent 7d5b113423ae72b2edbd8433871ad8a819bfadca
Author: Randy Palamar <[email protected]>
Date: Sun, 7 Jan 2024 11:02:17 -0700
expr: treat expressions as strs until evaluation
Comparison operations (>, <, =, etc.) and matching operations must
operate originally provided string not one that has gone back and
forth through string formatting. This caused operations such as
the following to give incorrect results:
./expr 00003 : '.*'
Before: 1
After: 5
This commit fixes that issue.
Diffstat:
M expr.c | 73 +++++++++++------------------…
1 file changed, 25 insertions(+), 48 deletions(-)
---
diff --git a/expr.c b/expr.c
@@ -18,11 +18,13 @@ struct val {
};
static void
-enan(struct val *v)
+tonum(struct val *v)
{
- if (!v->str)
- return;
- enprintf(2, "syntax error: expected integer, got %s\n", v->str);
+ const char *errstr;
+ long long d = strtonum(v->str, LLONG_MIN, LLONG_MAX, &errstr);
+ if (errstr)
+ enprintf(2, "error: expected integer, got %s\n", v->str);
+ v->num = d;
}
static void
@@ -37,16 +39,14 @@ static int
valcmp(struct val *a, struct val *b)
{
int ret;
- char buf[BUFSIZ];
-
- if (!a->str && !b->str) {
- ret = (a->num > b->num) - (a->num < b->num);
- } else if (a->str && !b->str) {
- snprintf(buf, sizeof(buf), "%lld", b->num);
- ret = strcmp(a->str, buf);
- } else if (!a->str && b->str) {
- snprintf(buf, sizeof(buf), "%lld", a->num);
- ret = strcmp(buf, b->str);
+ const char *err1, *err2;
+ long long d1, d2;
+
+ d1 = strtonum(a->str, LLONG_MIN, LLONG_MAX, &err1);
+ d2 = strtonum(b->str, LLONG_MIN, LLONG_MAX, &err2);
+
+ if (!err1 && !err2) {
+ ret = (d1 > d2) - (d1 < d2);
} else {
ret = strcmp(a->str, b->str);
}
@@ -61,24 +61,10 @@ match(struct val *vstr, struct val *vregx, struct val *ret)
regmatch_t matches[2];
long long d;
size_t anchlen;
- char strbuf[BUFSIZ], regxbuf[BUFSIZ],
- *s, *p, *anchreg, *str, *regx;
+ char *s, *p, *anchreg;
+ char *str = vstr->str, *regx = vregx->str;
const char *errstr;
- if (!vstr->str) {
- snprintf(strbuf, sizeof(strbuf), "%lld", vstr->num);
- str = strbuf;
- } else {
- str = vstr->str;
- }
-
- if (!vregx->str) {
- snprintf(regxbuf, sizeof(regxbuf), "%lld", vregx->num);
- regx = regxbuf;
- } else {
- regx = vregx->str;
- }
-
/* anchored regex */
anchlen = strlen(regx) + 1 + 1;
anchreg = emalloc(anchlen);
@@ -152,11 +138,11 @@ doop(int *ophead, int *opp, struct val *valhead, struct v…
case LE : ret.num = (valcmp(a, b) <= 0); break;
case NE : ret.num = (valcmp(a, b) != 0); break;
- case '+': enan(a); enan(b); ret.num = a->num + b->num; break;
- case '-': enan(a); enan(b); ret.num = a->num - b->num; break;
- case '*': enan(a); enan(b); ret.num = a->num * b->num; break;
- case '/': enan(a); enan(b); ezero(b); ret.num = a->num / b->num; break;
- case '%': enan(a); enan(b); ezero(b); ret.num = a->num % b->num; break;
+ case '+': tonum(a); tonum(b); ret.num = a->num + b->num; bre…
+ case '-': tonum(a); tonum(b); ret.num = a->num - b->num; bre…
+ case '*': tonum(a); tonum(b); ret.num = a->num * b->num; bre…
+ case '/': tonum(a); tonum(b); ezero(b); ret.num = a->num / b->num; bre…
+ case '%': tonum(a); tonum(b); ezero(b); ret.num = a->num % b->num; bre…
case ':': match(a, b, &ret); break;
}
@@ -167,25 +153,15 @@ doop(int *ophead, int *opp, struct val *valhead, struct v…
static int
lex(char *s, struct val *v)
{
- long long d;
int type = VAL;
char *ops = "|&=><+-*/%():";
- const char *errstr;
-
- d = strtonum(s, LLONG_MIN, LLONG_MAX, &errstr);
- if (!errstr) {
- /* integer */
- v->num = d;
- } else if (s[0] && strchr(ops, s[0]) && !s[1]) {
+ if (s[0] && strchr(ops, s[0]) && !s[1]) {
/* one-char operand */
type = s[0];
} else if (s[0] && strchr("><!", s[0]) && s[1] == '=' && !s[2]) {
/* two-char operand */
type = (s[0] == '>') ? GE : (s[0] == '<') ? LE : NE;
- } else {
- /* string */
- v->str = s;
}
return type;
@@ -211,8 +187,9 @@ parse(char *expr[], int numexpr)
for (; *expr; expr++) {
switch ((type = lex(*expr, &v))) {
case VAL:
- valp->str = v.str;
- valp->num = v.num;
+ /* treatment of *expr is not known until
+ * doop(); treat as a string for now */
+ valp->str = *expr;
valp++;
break;
case '(':
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.