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
|
* Copyright (c) 2002
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
#ifndef lint
|
#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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -212,13 +212,19 @@ arith_token(void)
|
||||||
goto checkeq;
|
goto checkeq;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
if (buf[1] == '+')
|
if (buf[1] == '+') {
|
||||||
error("arithmetic: ++ operator unsupported");
|
buf++;
|
||||||
|
token = ARITH_INCR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
token = ARITH_ADD;
|
token = ARITH_ADD;
|
||||||
goto checkeq;
|
goto checkeq;
|
||||||
case '-':
|
case '-':
|
||||||
if (buf[1] == '-')
|
if (buf[1] == '-') {
|
||||||
error("arithmetic: -- operator unsupported");
|
buf++;
|
||||||
|
token = ARITH_DECR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
token = ARITH_SUB;
|
token = ARITH_SUB;
|
||||||
goto checkeq;
|
goto checkeq;
|
||||||
case '~':
|
case '~':
|
||||||
|
@ -234,6 +240,9 @@ arith_token(void)
|
||||||
case ':':
|
case ':':
|
||||||
token = ARITH_COLON;
|
token = ARITH_COLON;
|
||||||
break;
|
break;
|
||||||
|
case ',':
|
||||||
|
token = ARITH_COMMA;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
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
|
* Copyright (c) 1993
|
||||||
|
@ -98,6 +98,9 @@
|
||||||
#define ARITH_BNOT 36
|
#define ARITH_BNOT 36
|
||||||
#define ARITH_QMARK 37
|
#define ARITH_QMARK 37
|
||||||
#define ARITH_COLON 38
|
#define ARITH_COLON 38
|
||||||
|
#define ARITH_INCR 39
|
||||||
|
#define ARITH_DECR 40
|
||||||
|
#define ARITH_COMMA 41
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals shared between arith parser, and lexer
|
* 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
|
* Copyright (c) 1993
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
#ifndef lint
|
#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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <limits.h>
|
#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
|
static intmax_t
|
||||||
primary(int token, union a_token_val *val, int op, int noeval)
|
primary(int token, union a_token_val *val, int op, int noeval)
|
||||||
{
|
{
|
||||||
intmax_t result;
|
intmax_t result;
|
||||||
|
char sresult[DIGITS(result) + 1];
|
||||||
|
|
||||||
VTRACE(DBG_ARITH, ("Arith primary: token %d op %d%s\n",
|
VTRACE(DBG_ARITH, ("Arith primary: token %d op %d%s\n",
|
||||||
token, op, noeval ? " noeval" : ""));
|
token, op, noeval ? " noeval" : ""));
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case ARITH_LPAREN:
|
case ARITH_LPAREN:
|
||||||
result = assignment(op, noeval);
|
result = comma_list(op, noeval);
|
||||||
if (last_token != ARITH_RPAREN)
|
if (last_token != ARITH_RPAREN)
|
||||||
arith_err("expecting ')'");
|
arith_err("expecting ')'");
|
||||||
last_token = arith_token();
|
last_token = arith_token();
|
||||||
|
@ -213,8 +215,18 @@ primary(int token, union a_token_val *val, int op, int noeval)
|
||||||
last_token = op;
|
last_token = op;
|
||||||
return val->val;
|
return val->val;
|
||||||
case ARITH_VAR:
|
case ARITH_VAR:
|
||||||
last_token = op;
|
result = noeval ? val->val : arith_lookupvarint(val->name);
|
||||||
return 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:
|
case ARITH_ADD:
|
||||||
*val = a_t_val;
|
*val = a_t_val;
|
||||||
return primary(op, val, arith_token(), noeval);
|
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:
|
case ARITH_BNOT:
|
||||||
*val = a_t_val;
|
*val = a_t_val;
|
||||||
return ~primary(op, val, arith_token(), noeval);
|
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:
|
default:
|
||||||
arith_err("expecting primary");
|
arith_err("expecting primary");
|
||||||
}
|
}
|
||||||
|
@ -374,6 +398,20 @@ assignment(int var, int noeval)
|
||||||
return result;
|
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
|
intmax_t
|
||||||
arith(const char *s, int lno)
|
arith(const char *s, int lno)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +443,7 @@ arith(const char *s, int lno)
|
||||||
|
|
||||||
arith_buf = arith_startbuf = s;
|
arith_buf = arith_startbuf = s;
|
||||||
|
|
||||||
result = assignment(arith_token(), 0);
|
result = comma_list(arith_token(), 0);
|
||||||
|
|
||||||
if (last_token)
|
if (last_token)
|
||||||
arith_err("expecting end of expression");
|
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
|
.\" Copyright (c) 1991, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" 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.
|
Referencing the value of a variable which is not numeric is an error.
|
||||||
.Pp
|
.Pp
|
||||||
All of the C expression operators applicable to integers are supported,
|
All of the C expression operators applicable to integers are supported,
|
||||||
and operate as they would in a C expression, except the unary
|
and operate as they would in a C expression.
|
||||||
.Dq ++
|
Use white space, or parentheses, to disambiguate confusing syntax,
|
||||||
and
|
otherwise, as in C, the longest sequence of consecutive characters
|
||||||
.Dq --
|
which make a valid token (operator, variable name, or number) is taken
|
||||||
operators (in both prefix and postfix forms) and the
|
to be that token, even if the token designated cannot be used
|
||||||
.Dq \&,
|
and a different interpretation could produce a successful parse.
|
||||||
(comma) operator, which are currently not supported.
|
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
|
.Pp
|
||||||
It should not be necessary to state that the C operators which
|
It should not be necessary to state that the C operators which
|
||||||
operate on, or produce, pointer types, are not supported.
|
operate on, or produce, pointer types, are not supported.
|
||||||
|
|
Loading…
Reference in New Issue