Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Add support for ++ and -- (pre & post) and ', ' to ari...



details:   https://anonhg.NetBSD.org/src/rev/035f6fb6d658
branches:  trunk
changeset: 825599:035f6fb6d658
user:      kre <kre%NetBSD.org@localhost>
date:      Mon Jul 24 13:21:14 2017 +0000

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

diffstat:

 bin/sh/arith_token.c  |  21 ++++++++++++++-----
 bin/sh/arith_tokens.h |   5 +++-
 bin/sh/arithmetic.c   |  52 ++++++++++++++++++++++++++++++++++++++++++++------
 bin/sh/sh.1           |  27 ++++++++++++++++++-------
 4 files changed, 83 insertions(+), 22 deletions(-)

diffs (224 lines):

diff -r 4ca9e0c8ae54 -r 035f6fb6d658 bin/sh/arith_token.c
--- a/bin/sh/arith_token.c      Mon Jul 24 12:36:02 2017 +0000
+++ b/bin/sh/arith_token.c      Mon Jul 24 13:21:14 2017 +0000
@@ -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 @@
                        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 @@
                case ':':
                        token = ARITH_COLON;
                        break;
+               case ',':
+                       token = ARITH_COMMA;
+                       break;
                }
                break;
        }
diff -r 4ca9e0c8ae54 -r 035f6fb6d658 bin/sh/arith_tokens.h
--- a/bin/sh/arith_tokens.h     Mon Jul 24 12:36:02 2017 +0000
+++ b/bin/sh/arith_tokens.h     Mon Jul 24 13:21:14 2017 +0000
@@ -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
diff -r 4ca9e0c8ae54 -r 035f6fb6d658 bin/sh/arithmetic.c
--- a/bin/sh/arithmetic.c       Mon Jul 24 12:36:02 2017 +0000
+++ b/bin/sh/arithmetic.c       Mon Jul 24 13:21:14 2017 +0000
@@ -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 @@
        }
 }
 
-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 @@
                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 @@
        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 @@
        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_buf = arith_startbuf = s;
 
-       result = assignment(arith_token(), 0);
+       result = comma_list(arith_token(), 0);
 
        if (last_token)
                arith_err("expecting end of expression");
diff -r 4ca9e0c8ae54 -r 035f6fb6d658 bin/sh/sh.1
--- a/bin/sh/sh.1       Mon Jul 24 12:36:02 2017 +0000
+++ b/bin/sh/sh.1       Mon Jul 24 13:21:14 2017 +0000
@@ -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 @@
 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.



Home | Main Index | Thread Index | Old Index