Module Name:    src
Committed By:   kre
Date:           Mon Jul 24 13:21:14 UTC 2017

Modified Files:
        src/bin/sh: arith_token.c arith_tokens.h arithmetic.c sh.1

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


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/bin/sh/arith_token.c
cvs rdiff -u -r1.2 -r1.3 src/bin/sh/arith_tokens.h
cvs rdiff -u -r1.3 -r1.4 src/bin/sh/arithmetic.c
cvs rdiff -u -r1.160 -r1.161 src/bin/sh/sh.1

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/arith_token.c
diff -u src/bin/sh/arith_token.c:1.5 src/bin/sh/arith_token.c:1.6
--- src/bin/sh/arith_token.c:1.5	Wed Jun  7 05:08:32 2017
+++ src/bin/sh/arith_token.c	Mon Jul 24 13:21:14 2017
@@ -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;
 	}

Index: src/bin/sh/arith_tokens.h
diff -u src/bin/sh/arith_tokens.h:1.2 src/bin/sh/arith_tokens.h:1.3
--- src/bin/sh/arith_tokens.h:1.2	Wed Jun  7 05:08:32 2017
+++ src/bin/sh/arith_tokens.h	Mon Jul 24 13:21:14 2017
@@ -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

Index: src/bin/sh/arithmetic.c
diff -u src/bin/sh/arithmetic.c:1.3 src/bin/sh/arithmetic.c:1.4
--- src/bin/sh/arithmetic.c:1.3	Wed Jun  7 05:08:32 2017
+++ src/bin/sh/arithmetic.c	Mon Jul 24 13:21:14 2017
@@ -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 *va
 		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 *va
 	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");

Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.160 src/bin/sh/sh.1:1.161
--- src/bin/sh/sh.1:1.160	Mon Jul 24 12:36:02 2017
+++ src/bin/sh/sh.1	Mon Jul 24 13:21:14 2017
@@ -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 err
 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.

Reply via email to