summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2005-02-02 07:53:02 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2005-02-02 07:53:02 +0000
commit54ee15db00e783ca1052eedeb6b38b4484b6011f (patch)
treebf4d8074308cb316ade912a58910777671d1b708
parent8611e25a7ef3067db40e9ec505220aa05c19a973 (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.c4
-rw-r--r--bin/ksh/c_sh.c4
-rw-r--r--bin/ksh/c_test.c6
-rw-r--r--bin/ksh/c_ulimit.c4
-rw-r--r--bin/ksh/eval.c4
-rw-r--r--bin/ksh/expr.c26
-rw-r--r--bin/ksh/ksh.115
-rw-r--r--bin/ksh/ksh.1tbl15
-rw-r--r--bin/ksh/proto.h10
-rw-r--r--bin/ksh/sh.115
-rw-r--r--bin/ksh/sh.1tbl15
-rw-r--r--bin/ksh/var.c30
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;