diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2005-02-02 07:53:02 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2005-02-02 07:53:02 +0000 |
commit | 54ee15db00e783ca1052eedeb6b38b4484b6011f (patch) | |
tree | bf4d8074308cb316ade912a58910777671d1b708 | |
parent | 8611e25a7ef3067db40e9ec505220aa05c19a973 (diff) |
Introduce POSIX hex and octal (0x... and 0...) constants in arithmetic
expressions. Work by Matthias Kilian, based on an old diff by myself.
Note: MAKEDEV should be updated. Tested by many, thanks.
ok millert@ deraadt@
-rw-r--r-- | bin/ksh/c_ksh.c | 4 | ||||
-rw-r--r-- | bin/ksh/c_sh.c | 4 | ||||
-rw-r--r-- | bin/ksh/c_test.c | 6 | ||||
-rw-r--r-- | bin/ksh/c_ulimit.c | 4 | ||||
-rw-r--r-- | bin/ksh/eval.c | 4 | ||||
-rw-r--r-- | bin/ksh/expr.c | 26 | ||||
-rw-r--r-- | bin/ksh/ksh.1 | 15 | ||||
-rw-r--r-- | bin/ksh/ksh.1tbl | 15 | ||||
-rw-r--r-- | bin/ksh/proto.h | 10 | ||||
-rw-r--r-- | bin/ksh/sh.1 | 15 | ||||
-rw-r--r-- | bin/ksh/sh.1tbl | 15 | ||||
-rw-r--r-- | bin/ksh/var.c | 30 |
12 files changed, 107 insertions, 41 deletions
diff --git a/bin/ksh/c_ksh.c b/bin/ksh/c_ksh.c index 44458db0f57..6bfbffbef93 100644 --- a/bin/ksh/c_ksh.c +++ b/bin/ksh/c_ksh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_ksh.c,v 1.24 2004/12/22 17:14:34 millert Exp $ */ +/* $OpenBSD: c_ksh.c,v 1.25 2005/02/02 07:53:01 otto Exp $ */ /* * built-in Korn commands: c_* @@ -1012,7 +1012,7 @@ c_let(char **wp) bi_errorf("no arguments"); else for (wp++; *wp; wp++) - if (!evaluate(*wp, &val, KSH_RETURN_ERROR)) { + if (!evaluate(*wp, &val, KSH_RETURN_ERROR, true)) { rv = 2; /* distinguish error from zero result */ break; } else diff --git a/bin/ksh/c_sh.c b/bin/ksh/c_sh.c index b76cc0af525..05ec4b9c620 100644 --- a/bin/ksh/c_sh.c +++ b/bin/ksh/c_sh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_sh.c,v 1.27 2004/12/28 21:11:21 jsg Exp $ */ +/* $OpenBSD: c_sh.c,v 1.28 2005/02/02 07:53:01 otto Exp $ */ /* * built-in Bourne commands @@ -31,7 +31,7 @@ c_shift(char **wp) arg = wp[builtin_opt.optind]; if (arg) { - evaluate(arg, &val, KSH_UNWIND_ERROR); + evaluate(arg, &val, KSH_UNWIND_ERROR, false); n = val; } else n = 1; diff --git a/bin/ksh/c_test.c b/bin/ksh/c_test.c index 227dfa6d250..2023d51be60 100644 --- a/bin/ksh/c_test.c +++ b/bin/ksh/c_test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_test.c,v 1.14 2004/12/22 17:14:34 millert Exp $ */ +/* $OpenBSD: c_test.c,v 1.15 2005/02/02 07:53:01 otto Exp $ */ /* * test(1); version 7-like -- author Erik Baalbergen @@ -308,8 +308,8 @@ test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2, { long v1, v2; - if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR) - || !evaluate(opnd2, &v2, KSH_RETURN_ERROR)) + if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) + || !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) { /* error already printed.. */ te->flags |= TEF_ERROR; diff --git a/bin/ksh/c_ulimit.c b/bin/ksh/c_ulimit.c index 96a1180060d..5bf0f19b5f6 100644 --- a/bin/ksh/c_ulimit.c +++ b/bin/ksh/c_ulimit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_ulimit.c,v 1.12 2004/12/20 11:34:26 otto Exp $ */ +/* $OpenBSD: c_ulimit.c,v 1.13 2005/02/02 07:53:01 otto Exp $ */ /* ulimit -- handle "ulimit" builtin @@ -104,7 +104,7 @@ c_ulimit(char **wp) else { long rval; - if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR)) + if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR, false)) return 1; /* Avoid problems caused by typos that * evaluate misses due to evaluating unset diff --git a/bin/ksh/eval.c b/bin/ksh/eval.c index 7fd78bd586a..3b560d060c5 100644 --- a/bin/ksh/eval.c +++ b/bin/ksh/eval.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eval.c,v 1.24 2004/12/22 18:52:37 millert Exp $ */ +/* $OpenBSD: eval.c,v 1.25 2005/02/02 07:53:01 otto Exp $ */ /* * Expansion - quoting, separation, substitution, globbing @@ -248,7 +248,7 @@ expand(char *cp, /* input word */ v.type = 10; /* not default */ v.name[0] = '\0'; v_evaluate(&v, substitute(sp, 0), - KSH_UNWIND_ERROR); + KSH_UNWIND_ERROR, true); sp = strchr(sp, 0) + 1; for (p = str_val(&v); *p; ) { Xcheck(ds, dp); diff --git a/bin/ksh/expr.c b/bin/ksh/expr.c index 34c8901cc83..8b0b4e71019 100644 --- a/bin/ksh/expr.c +++ b/bin/ksh/expr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: expr.c,v 1.16 2004/12/22 18:57:28 otto Exp $ */ +/* $OpenBSD: expr.c,v 1.17 2005/02/02 07:53:01 otto Exp $ */ /* * Korn expression evaluation @@ -119,6 +119,9 @@ struct expr_state { const char *tokp; /* lexical position */ enum token tok; /* token from token() */ int noassign; /* don't do assigns (for ?:,&&,||) */ + bool arith; /* true if evaluating an $(()) + * expression + */ struct tbl *val; /* value from token() */ struct tbl *evaling; /* variable that is being recursively * expanded (EXPRINEVAL flag set) @@ -141,14 +144,14 @@ static struct tbl *intvar(Expr_state *, struct tbl *); * parse and evaluate expression */ int -evaluate(const char *expr, long int *rval, int error_ok) +evaluate(const char *expr, long int *rval, int error_ok, bool arith) { struct tbl v; int ret; v.flag = DEFINED|INTEGER; v.type = 0; - ret = v_evaluate(&v, expr, error_ok); + ret = v_evaluate(&v, expr, error_ok, arith); *rval = v.val.i; return ret; } @@ -157,7 +160,8 @@ evaluate(const char *expr, long int *rval, int error_ok) * parse and evaluate expression, storing result in vp. */ int -v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok) +v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok, + bool arith) { struct tbl *v; Expr_state curstate; @@ -167,6 +171,7 @@ v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok) /* save state to allow recursive calls */ curstate.expression = curstate.tokp = expr; curstate.noassign = 0; + curstate.arith = arith; curstate.evaling = (struct tbl *) 0; newenv(E_ERRH); @@ -198,7 +203,7 @@ v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok) evalerr(es, ET_UNEXPECTED, (char *) 0); if (vp->flag & INTEGER) - setint_v(vp, v); + setint_v(vp, v, es->arith); else /* can fail if readonly */ setstr(vp, str_val(v), error_ok); @@ -214,6 +219,7 @@ evalerr(Expr_state *es, enum error_type type, const char *str) char tbuf[2]; const char *s; + es->arith = false; switch (type) { case ET_UNEXPECTED: switch (es->tok) { @@ -433,7 +439,7 @@ evalexpr(Expr_state *es, enum prec prec) if (IS_ASSIGNOP(op)) { vr->val.i = res; if (vasn->flag & INTEGER) - setint_v(vasn, vr); + setint_v(vasn, vr, es->arith); else setint(vasn, res); vl = vr; @@ -491,7 +497,7 @@ token(Expr_state *es) es->val->flag &= ~INTEGER; es->val->type = 0; es->val->val.s = tvar; - if (setint_v(es->val, es->val) == NULL) + if (setint_v(es->val, es->val, es->arith) == NULL) evalerr(es, ET_BADLIT, tvar); afree(tvar, ATEMP); es->tok = LIT; @@ -524,7 +530,7 @@ do_ppmm(Expr_state *es, enum token op, struct tbl *vasn, bool is_prefix) vl = intvar(es, vasn); oval = op == O_PLUSPLUS ? vl->val.i++ : vl->val.i--; if (vasn->flag & INTEGER) - setint_v(vasn, vl); + setint_v(vasn, vl, es->arith); else setint(vasn, vl->val.i); if (!is_prefix) /* undo the inc/dec */ @@ -568,12 +574,12 @@ intvar(Expr_state *es, struct tbl *vp) return vp; vq = tempvar(); - if (setint_v(vq, vp) == NULL) { + if (setint_v(vq, vp, es->arith) == NULL) { if (vp->flag & EXPRINEVAL) evalerr(es, ET_RECURSIVE, vp->name); es->evaling = vp; vp->flag |= EXPRINEVAL; - v_evaluate(vq, str_val(vp), KSH_UNWIND_ERROR); + v_evaluate(vq, str_val(vp), KSH_UNWIND_ERROR, es->arith); vp->flag &= ~EXPRINEVAL; es->evaling = (struct tbl *) 0; } diff --git a/bin/ksh/ksh.1 b/bin/ksh/ksh.1 index 8f5e9dfedcd..32180f9cff5 100644 --- a/bin/ksh/ksh.1 +++ b/bin/ksh/ksh.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ksh.1,v 1.88 2005/01/19 19:32:02 jmc Exp $ +.\" $OpenBSD: ksh.1,v 1.89 2005/02/02 07:53:01 otto Exp $ .\" .\" Public Domain .\" @@ -2138,6 +2138,19 @@ where is a decimal integer specifying the base, and .Ar number is a number in the specified base. +Additionally, +integers may be prefixed with +.Sq 0X +or +.Sq 0x +(specifying base 16) +or +.Sq 0 +(base 8) +in all forms of arithmetic expressions, +except as numeric arguments to the +.Ic test +command. .Pp The operators are evaluated as follows: .Bl -tag -width Ds -offset indent diff --git a/bin/ksh/ksh.1tbl b/bin/ksh/ksh.1tbl index 63f594c1407..0848d48675d 100644 --- a/bin/ksh/ksh.1tbl +++ b/bin/ksh/ksh.1tbl @@ -1,4 +1,4 @@ -.\" $OpenBSD: ksh.1tbl,v 1.88 2005/01/19 19:32:02 jmc Exp $ +.\" $OpenBSD: ksh.1tbl,v 1.89 2005/02/02 07:53:01 otto Exp $ .\" .\" Public Domain .\" @@ -2138,6 +2138,19 @@ where is a decimal integer specifying the base, and .Ar number is a number in the specified base. +Additionally, +integers may be prefixed with +.Sq 0X +or +.Sq 0x +(specifying base 16) +or +.Sq 0 +(base 8) +in all forms of arithmetic expressions, +except as numeric arguments to the +.Ic test +command. .Pp The operators are evaluated as follows: .Bl -tag -width Ds -offset indent diff --git a/bin/ksh/proto.h b/bin/ksh/proto.h index fb49c7bd71f..e7d3276cdd2 100644 --- a/bin/ksh/proto.h +++ b/bin/ksh/proto.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proto.h,v 1.24 2004/12/22 19:02:13 millert Exp $ */ +/* $OpenBSD: proto.h,v 1.25 2005/02/02 07:53:01 otto Exp $ */ /* * prototypes for PD-KSH @@ -77,8 +77,8 @@ int search_access(const char *, int, int *); int pr_menu(char *const *); int pr_list(char *const *); /* expr.c */ -int evaluate(const char *, long *, int); -int v_evaluate(struct tbl *, const char *, volatile int); +int evaluate(const char *, long *, int, bool); +int v_evaluate(struct tbl *, const char *, volatile int, bool); /* history.c */ void init_histvec(void); void hist_init(Source *); @@ -247,9 +247,9 @@ struct tbl * local(const char *, bool); char * str_val(struct tbl *); long intval(struct tbl *); int setstr(struct tbl *, const char *, int); -struct tbl *setint_v(struct tbl *, struct tbl *); +struct tbl *setint_v(struct tbl *, struct tbl *, bool); void setint(struct tbl *, long); -int getint(struct tbl *, long *); +int getint(struct tbl *, long *, bool); struct tbl * typeset(const char *, Tflag, Tflag, int, int); void unset(struct tbl *, int); char * skip_varname(const char *, int); diff --git a/bin/ksh/sh.1 b/bin/ksh/sh.1 index 0125a6bfbb8..24682940c02 100644 --- a/bin/ksh/sh.1 +++ b/bin/ksh/sh.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sh.1,v 1.60 2005/01/21 15:15:55 otto Exp $ +.\" $OpenBSD: sh.1,v 1.61 2005/02/02 07:53:01 otto Exp $ .\" .\" Public Domain .\" @@ -1690,6 +1690,19 @@ where is a decimal integer specifying the base, and .Ar number is a number in the specified base. +Additionally, +integers may be prefixed with +.Sq 0X +or +.Sq 0x +(specifying base 16) +or +.Sq 0 +(base 8) +in all forms of arithmetic expressions, +except as numeric arguments to the +.Ic test +command. .Pp The operators are evaluated as follows: .Bl -tag -width Ds -offset indent diff --git a/bin/ksh/sh.1tbl b/bin/ksh/sh.1tbl index 7cb1725b1c5..894273bce89 100644 --- a/bin/ksh/sh.1tbl +++ b/bin/ksh/sh.1tbl @@ -1,4 +1,4 @@ -.\" $OpenBSD: sh.1tbl,v 1.60 2005/01/21 15:15:55 otto Exp $ +.\" $OpenBSD: sh.1tbl,v 1.61 2005/02/02 07:53:01 otto Exp $ .\" .\" Public Domain .\" @@ -1690,6 +1690,19 @@ where is a decimal integer specifying the base, and .Ar number is a number in the specified base. +Additionally, +integers may be prefixed with +.Sq 0X +or +.Sq 0x +(specifying base 16) +or +.Sq 0 +(base 8) +in all forms of arithmetic expressions, +except as numeric arguments to the +.Ic test +command. .Pp The operators are evaluated as follows: .Bl -tag -width Ds -offset indent diff --git a/bin/ksh/var.c b/bin/ksh/var.c index 88c51a77613..95d9c133508 100644 --- a/bin/ksh/var.c +++ b/bin/ksh/var.c @@ -1,4 +1,4 @@ -/* $OpenBSD: var.c,v 1.22 2004/12/22 17:14:34 millert Exp $ */ +/* $OpenBSD: var.c,v 1.23 2005/02/02 07:53:01 otto Exp $ */ #include "sh.h" #include <time.h> @@ -123,9 +123,7 @@ initvar(void) * non-zero if this is an array, sets *valp to the array index, returns * the basename of the array. */ -const char *array_index_calc(const char *n, bool *arrayp, int *valp); - -const char * +static const char * array_index_calc(const char *n, bool *arrayp, int *valp) { const char *p; @@ -143,7 +141,7 @@ array_index_calc(const char *n, bool *arrayp, int *valp) sub = substitute(tmp, 0); afree(tmp, ATEMP); n = str_nsave(n, p - n, ATEMP); - evaluate(sub, &rval, KSH_UNWIND_ERROR); + evaluate(sub, &rval, KSH_UNWIND_ERROR, true); if (rval < 0 || rval > ARRAYMAX) errorf("%s: subscript out of range", n); *valp = rval; @@ -335,7 +333,7 @@ intval(struct tbl *vp) long num; int base; - base = getint(vp, &num); + base = getint(vp, &num, false); if (base == -1) /* XXX check calls - is error here ok by POSIX? */ errorf("%s: bad number", str_val(vp)); @@ -374,9 +372,10 @@ setstr(struct tbl *vq, const char *s, int error_ok) vq->val.s = str_save(s, vq->areap); vq->flag |= ALLOC; } - } else /* integer dest */ - if (!v_evaluate(vq, s, error_ok)) + } else { /* integer dest */ + if (!v_evaluate(vq, s, error_ok, true)) return 0; + } vq->flag |= ISSET; if ((vq->flag&SPECIAL)) setspec(vq); @@ -403,7 +402,7 @@ setint(struct tbl *vq, long int n) } int -getint(struct tbl *vp, long int *nump) +getint(struct tbl *vp, long int *nump, bool arith) { char *s; int c; @@ -426,6 +425,15 @@ getint(struct tbl *vp, long int *nump) base = 10; num = 0; neg = 0; + if (arith && *s == '0' && *(s+1)) { + s++; + if (*s == 'x' || *s == 'X') { + s++; + base = 16; + } else + base = 8; + have_base++; + } for (c = *s++; c ; c = *s++) { if (c == '-') { neg++; @@ -460,12 +468,12 @@ getint(struct tbl *vp, long int *nump) * (vq and vp may be the same) */ struct tbl * -setint_v(struct tbl *vq, struct tbl *vp) +setint_v(struct tbl *vq, struct tbl *vp, bool arith) { int base; long num; - if ((base = getint(vp, &num)) == -1) + if ((base = getint(vp, &num, arith)) == -1) return NULL; if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) { vq->flag &= ~ALLOC; |