Add support for ++ and -- (pre & post) and ',' to arithmetic.
This commit is contained in:
parent
a304c3b3a5
commit
e79133b55e
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: arith_token.c,v 1.5 2017/06/07 05:08:32 kre Exp $ */
|
||||
/* $NetBSD: arith_token.c,v 1.6 2017/07/24 13:21:14 kre Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002
|
||||
|
@ -39,7 +39,7 @@
|
|||
#include <sys/cdefs.h>
|
||||
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: arith_token.c,v 1.5 2017/06/07 05:08:32 kre Exp $");
|
||||
__RCSID("$NetBSD: arith_token.c,v 1.6 2017/07/24 13:21:14 kre Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
@ -212,13 +212,19 @@ arith_token(void)
|
|||
goto checkeq;
|
||||
|
||||
case '+':
|
||||
if (buf[1] == '+')
|
||||
error("arithmetic: ++ operator unsupported");
|
||||
if (buf[1] == '+') {
|
||||
buf++;
|
||||
token = ARITH_INCR;
|
||||
break;
|
||||
}
|
||||
token = ARITH_ADD;
|
||||
goto checkeq;
|
||||
case '-':
|
||||
if (buf[1] == '-')
|
||||
error("arithmetic: -- operator unsupported");
|
||||
if (buf[1] == '-') {
|
||||
buf++;
|
||||
token = ARITH_DECR;
|
||||
break;
|
||||
}
|
||||
token = ARITH_SUB;
|
||||
goto checkeq;
|
||||
case '~':
|
||||
|
@ -234,6 +240,9 @@ arith_token(void)
|
|||
case ':':
|
||||
token = ARITH_COLON;
|
||||
break;
|
||||
case ',':
|
||||
token = ARITH_COMMA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: arith_tokens.h,v 1.2 2017/06/07 05:08:32 kre Exp $ */
|
||||
/* $NetBSD: arith_tokens.h,v 1.3 2017/07/24 13:21:14 kre Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
|
@ -98,6 +98,9 @@
|
|||
#define ARITH_BNOT 36
|
||||
#define ARITH_QMARK 37
|
||||
#define ARITH_COLON 38
|
||||
#define ARITH_INCR 39
|
||||
#define ARITH_DECR 40
|
||||
#define ARITH_COMMA 41
|
||||
|
||||
/*
|
||||
* Globals shared between arith parser, and lexer
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: arithmetic.c,v 1.3 2017/06/07 05:08:32 kre Exp $ */
|
||||
/* $NetBSD: arithmetic.c,v 1.4 2017/07/24 13:21:14 kre Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
|
@ -39,7 +39,7 @@
|
|||
#include <sys/cdefs.h>
|
||||
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: arithmetic.c,v 1.3 2017/06/07 05:08:32 kre Exp $");
|
||||
__RCSID("$NetBSD: arithmetic.c,v 1.4 2017/07/24 13:21:14 kre Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <limits.h>
|
||||
|
@ -192,19 +192,21 @@ do_binop(int op, intmax_t a, intmax_t b)
|
|||
}
|
||||
}
|
||||
|
||||
static intmax_t assignment(int var, int noeval);
|
||||
static intmax_t assignment(int, int);
|
||||
static intmax_t comma_list(int, int);
|
||||
|
||||
static intmax_t
|
||||
primary(int token, union a_token_val *val, int op, int noeval)
|
||||
{
|
||||
intmax_t result;
|
||||
char sresult[DIGITS(result) + 1];
|
||||
|
||||
VTRACE(DBG_ARITH, ("Arith primary: token %d op %d%s\n",
|
||||
token, op, noeval ? " noeval" : ""));
|
||||
|
||||
switch (token) {
|
||||
case ARITH_LPAREN:
|
||||
result = assignment(op, noeval);
|
||||
result = comma_list(op, noeval);
|
||||
if (last_token != ARITH_RPAREN)
|
||||
arith_err("expecting ')'");
|
||||
last_token = arith_token();
|
||||
|
@ -213,8 +215,18 @@ primary(int token, union a_token_val *val, int op, int noeval)
|
|||
last_token = op;
|
||||
return val->val;
|
||||
case ARITH_VAR:
|
||||
last_token = op;
|
||||
return noeval ? val->val : arith_lookupvarint(val->name);
|
||||
result = noeval ? val->val : arith_lookupvarint(val->name);
|
||||
if (op == ARITH_INCR || op == ARITH_DECR) {
|
||||
last_token = arith_token();
|
||||
if (noeval)
|
||||
return val->val;
|
||||
|
||||
snprintf(sresult, sizeof(sresult), ARITH_FORMAT_STR,
|
||||
result + (op == ARITH_INCR ? 1 : -1));
|
||||
setvar(val->name, sresult, 0);
|
||||
} else
|
||||
last_token = op;
|
||||
return result;
|
||||
case ARITH_ADD:
|
||||
*val = a_t_val;
|
||||
return primary(op, val, arith_token(), noeval);
|
||||
|
@ -227,6 +239,18 @@ primary(int token, union a_token_val *val, int op, int noeval)
|
|||
case ARITH_BNOT:
|
||||
*val = a_t_val;
|
||||
return ~primary(op, val, arith_token(), noeval);
|
||||
case ARITH_INCR:
|
||||
case ARITH_DECR:
|
||||
if (op != ARITH_VAR)
|
||||
arith_err("incr/decr require var name");
|
||||
last_token = arith_token();
|
||||
if (noeval)
|
||||
return val->val;
|
||||
result = arith_lookupvarint(a_t_val.name);
|
||||
snprintf(sresult, sizeof(sresult), ARITH_FORMAT_STR,
|
||||
result += (token == ARITH_INCR ? 1 : -1));
|
||||
setvar(a_t_val.name, sresult, 0);
|
||||
return result;
|
||||
default:
|
||||
arith_err("expecting primary");
|
||||
}
|
||||
|
@ -374,6 +398,20 @@ assignment(int var, int noeval)
|
|||
return result;
|
||||
}
|
||||
|
||||
static intmax_t
|
||||
comma_list(int token, int noeval)
|
||||
{
|
||||
intmax_t result = assignment(token, noeval);
|
||||
|
||||
while (last_token == ARITH_COMMA) {
|
||||
VTRACE(DBG_ARITH, ("Arith: comma discarding %jd%s\n", result,
|
||||
noeval ? " noeval" : ""));
|
||||
result = assignment(arith_token(), noeval);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
intmax_t
|
||||
arith(const char *s, int lno)
|
||||
{
|
||||
|
@ -405,7 +443,7 @@ arith(const char *s, int lno)
|
|||
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
result = assignment(arith_token(), 0);
|
||||
result = comma_list(arith_token(), 0);
|
||||
|
||||
if (last_token)
|
||||
arith_err("expecting end of expression");
|
||||
|
|
27
bin/sh/sh.1
27
bin/sh/sh.1
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: sh.1,v 1.160 2017/07/24 12:36:02 kre Exp $
|
||||
.\" $NetBSD: sh.1,v 1.161 2017/07/24 13:21:14 kre Exp $
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
|
@ -1528,13 +1528,24 @@ string, which might result in syntax errors.
|
|||
Referencing the value of a variable which is not numeric is an error.
|
||||
.Pp
|
||||
All of the C expression operators applicable to integers are supported,
|
||||
and operate as they would in a C expression, except the unary
|
||||
.Dq ++
|
||||
and
|
||||
.Dq --
|
||||
operators (in both prefix and postfix forms) and the
|
||||
.Dq \&,
|
||||
(comma) operator, which are currently not supported.
|
||||
and operate as they would in a C expression.
|
||||
Use white space, or parentheses, to disambiguate confusing syntax,
|
||||
otherwise, as in C, the longest sequence of consecutive characters
|
||||
which make a valid token (operator, variable name, or number) is taken
|
||||
to be that token, even if the token designated cannot be used
|
||||
and a different interpretation could produce a successful parse.
|
||||
This means, as an example, that
|
||||
.Dq a+++++b
|
||||
is parsed as the gibberish sequence
|
||||
.Dq "a ++ ++ + b" ,
|
||||
rather than as the valid alternative
|
||||
.Dq "a ++ + ++ b" .
|
||||
Similarly, separate the
|
||||
.Sq \&,
|
||||
operator from numbers with white space to avoid the possibility
|
||||
of confusion with the decimal indicator in some locales (though
|
||||
fractional, or floating-point, numbers are not supported in this
|
||||
implementation.)
|
||||
.Pp
|
||||
It should not be necessary to state that the C operators which
|
||||
operate on, or produce, pointer types, are not supported.
|
||||
|
|
Loading…
Reference in New Issue