Add support for ++ and -- (pre & post) and ',' to arithmetic.

This commit is contained in:
kre 2017-07-24 13:21:14 +00:00
parent a304c3b3a5
commit e79133b55e
4 changed files with 83 additions and 22 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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");

View File

@ -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.