Index: bin/sh/arith_yacc.h =================================================================== --- bin/sh/arith_yacc.h +++ bin/sh/arith_yacc.h @@ -90,4 +90,5 @@ extern union yystype yylval; +arith_t strtoarith_t(const char *restrict nptr, char **restrict endptr); int yylex(void); Index: bin/sh/arith_yacc.c =================================================================== --- bin/sh/arith_yacc.c +++ bin/sh/arith_yacc.c @@ -104,7 +104,7 @@ if (str == NULL || *str == '\0') str = "0"; errno = 0; - result = strtoarith_t(str, &p, 0); + result = strtoarith_t(str, &p); if (errno != 0 || *p != '\0') yyerror("variable conversion error"); return result; Index: bin/sh/arith_yylex.c =================================================================== --- bin/sh/arith_yylex.c +++ bin/sh/arith_yylex.c @@ -35,6 +35,8 @@ #include __FBSDID("$FreeBSD$"); +#include +#include #include #include #include @@ -50,6 +52,32 @@ #error Arithmetic tokens are out of order. #endif +arith_t +strtoarith_t(const char *restrict nptr, char **restrict endptr) +{ + arith_t val; + + while (isspace((unsigned char)*nptr)) + nptr++; + switch (*nptr) { + case '-': + return strtoimax(nptr, endptr, 0); + case '0': + return (arith_t)strtoumax(nptr, endptr, 0); + default: + val = (arith_t)strtoumax(nptr, endptr, 0); + if (val >= 0) + return val; + else if (val == ARITH_MIN) { + errno = ERANGE; + return ARITH_MIN; + } else { + errno = ERANGE; + return ARITH_MAX; + } + } +} + int yylex(void) { @@ -78,7 +106,7 @@ case '7': case '8': case '9': - yylval.val = strtoarith_t(buf, &end, 0); + yylval.val = strtoarith_t(buf, &end); arith_buf = end; return ARITH_NUM; case 'A': Index: bin/sh/shell.h =================================================================== --- bin/sh/shell.h +++ bin/sh/shell.h @@ -59,7 +59,6 @@ */ typedef intmax_t arith_t; #define ARITH_FORMAT_STR "%" PRIdMAX -#define strtoarith_t(nptr, endptr, base) (intmax_t)strtoumax(nptr, endptr, base) #define ARITH_MIN INTMAX_MIN #define ARITH_MAX INTMAX_MAX Index: bin/sh/tests/expansion/Makefile =================================================================== --- bin/sh/tests/expansion/Makefile +++ bin/sh/tests/expansion/Makefile @@ -22,6 +22,8 @@ ${PACKAGE}FILES+= arith13.0 ${PACKAGE}FILES+= arith14.0 ${PACKAGE}FILES+= arith15.0 +${PACKAGE}FILES+= arith16.0 +${PACKAGE}FILES+= arith17.0 ${PACKAGE}FILES+= assign1.0 ${PACKAGE}FILES+= cmdsubst1.0 ${PACKAGE}FILES+= cmdsubst2.0 Index: bin/sh/tests/expansion/arith16.0 =================================================================== --- bin/sh/tests/expansion/arith16.0 +++ bin/sh/tests/expansion/arith16.0 @@ -0,0 +1,26 @@ +# $FreeBSD$ + +failures=0 + +for x in \ + 0x10000000000000000 \ + -0x8000000000000001 \ + 0xfffffffffffffffffffffffffffffffff \ + -0xfffffffffffffffffffffffffffffffff \ + 02000000000000000000000 \ + 9223372036854775808 \ + 9223372036854775809 \ + -9223372036854775809 \ + 9999999999999999999999999 \ + -9999999999999999999999999 +do + msg=$({ + v=$((x)) || : + } 3>&1 >&2 2>&3 3>&-) + r=$? + if [ "$r" = 0 ] || [ -z "$msg" ]; then + printf 'Failed: %s\n' "$x" + : $((failures += 1)) + fi +done +exit $((failures > 0)) Index: bin/sh/tests/expansion/arith17.0 =================================================================== --- bin/sh/tests/expansion/arith17.0 +++ bin/sh/tests/expansion/arith17.0 @@ -0,0 +1,3 @@ +# $FreeBSD$ + +[ $((9223372036854775809)) -gt 0 ]