sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit abdd0671f7d69dd4d48e2c692eb26bc658161763
parent f6552e36691c27c147aaafe3be9eb6011eef728f
Author: FRIGN <dev@frign.de>
Date:   Sun, 16 Nov 2014 20:29:29 +0100

Refactor expr.c

Diffstat:
Mexpr.c | 104++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 58 insertions(+), 46 deletions(-)

diff --git a/expr.c b/expr.c @@ -23,17 +23,16 @@ static Val match(Val, Val); static void num(Val); static int valcmp(Val, Val); static char *valstr(Val, char*, size_t); -static int yylex(void); -static int yyparse(int); +static int lex(char *); +static int parse(char **, int); -static char **args; static size_t intlen; -static Val yylval; +static Val lastval; static void ezero(intmax_t n) { - if(n == 0) + if (n == 0) enprintf(2, "division by zero\n"); } @@ -61,7 +60,7 @@ doop(int *ops, int **otop, Val *vals, Val **vtop) case '|': if (a.s && *a.s) ret = (Val){ a.s, 0 }; - else if (!a.s && a.n) + else if (!a.s && a.n) ret = (Val){ NULL, a.n }; else if (b.s && *b.s) ret = (Val){ b.s, 0 }; @@ -159,17 +158,14 @@ valstr(Val val, char *buf, size_t bufsiz) } static int -yylex(void) +lex(char *p) { intmax_t d; - char *q, *p, *ops = "|&=><+-*/%():"; - - if (!(p = *args++)) - return 0; + char *q, *ops = "|&=><+-*/%():"; d = strtoimax(p, &q, 10); if (*p && !*q) { - yylval = (Val){ NULL, d }; + lastval = (Val){ NULL, d }; return VAL; } @@ -183,17 +179,18 @@ yylex(void) if (strcmp(p, "!=") == 0) return NE; - yylval = (Val){ p, 0 }; + lastval = (Val){ p, 0 }; return VAL; } static int -yyparse(int argc) +parse(char **expr, int exprlen) { - Val vals[argc], *vtop = vals; - int ops [argc], *otop = ops; - int type, last = 0; + Val val[exprlen], *valp = val; + int op[exprlen], *opp = op; + int i, type, lasttype = 0; char prec[] = { + [ 0 ] = 0, [VAL] = 0, ['|'] = 1, ['&'] = 2, ['='] = 3, ['>'] = 3, [GE] = 3, ['<'] = 3, [LE] = 3, [NE] = 3, @@ -202,55 +199,70 @@ yyparse(int argc) [':'] = 6, }; - while((type = yylex())) { + for (i = 0; i < exprlen; i++) { + type = lex(expr[i]); + switch (type) { - case VAL: *vtop++ = yylval; break; - case '(': *otop++ = '(' ; break; + case VAL: + *valp++ = lastval; + break; + case '(': + *opp++ = '('; + break; case ')': - if (last == '(') + if (lasttype == '(') enprintf(2, "syntax error: empty ( )\n"); - while(otop > ops && otop[-1] != '(') - doop(ops, &otop, vals, &vtop); - if (otop == ops) + while (opp > op && opp[-1] != '(') + doop(op, &opp, val, &valp); + if (opp == op) enprintf(2, "syntax error: extra )\n"); - otop--; + opp--; break; default : - if (prec[last]) + if (prec[lasttype]) enprintf(2, "syntax error: extra operator\n"); - while (otop > ops && prec[otop[-1]] >= prec[type]) - doop(ops, &otop, vals, &vtop); - *otop++ = type; + while (opp > op && prec[opp[-1]] >= prec[type]) + doop(op, &opp, val, &valp); + *opp++ = type; break; } - last = type; + lasttype = type; } - while(otop > ops) - doop(ops, &otop, vals, &vtop); + while (opp > op) + doop(op, &opp, val, &valp); - if (vtop == vals) + if (valp == val) enprintf(2, "syntax error: missing expression\n"); - if (vtop - vals > 1) + if (valp - val > 1) enprintf(2, "syntax error: extra expression\n"); - vtop--; - if (vtop->s) - printf("%s\n", vtop->s); + valp--; + if (valp->s) + printf("%s\n", valp->s); else - printf("%"PRIdMAX"\n", vtop->n); + printf("%"PRIdMAX"\n", valp->n); - return (vtop->s && *vtop->s) || vtop->n; + return (valp->s && *valp->s) || valp->n; +} + +static void +usage(void) +{ + eprintf("usage: %s EXPRESSION\n", argv0); } int -main(int argc, char **argv) +main(int argc, char *argv[]) { - if (!(intlen = snprintf(NULL, 0, "%"PRIdMAX, INTMAX_MIN) + 1)) - enprintf(3, "failed to get max digits\n"); + intmax_t n = INTMAX_MIN; + + /* Get the maximum number of digits (+ sign) */ + for (intlen = (n < 0); n; n /= 10, ++intlen); - args = argv + 1; - if (*args && !strcmp("--", *args)) - ++args; + ARGBEGIN { + default: + usage(); + } ARGEND; - return !yyparse(argc); + return !parse(argv, argc); }