standards/52972: /bin/sh arithmetic not POSIX compliant
Wartan Hachaturow
wart at tepkom.ru
Fri Aug 22 15:41:32 PDT 2003
The following reply was made to PR standards/52972; it has been noted by GNATS.
From: Wartan Hachaturow <wart at tepkom.ru>
To: Jens Schweikhardt <schweikh at schweikhardt.net>
Cc: GNATS Bug Followup <bug-followup at FreeBSD.org>, tjr at FreeBSD.org
Subject: Re: standards/52972: /bin/sh arithmetic not POSIX compliant
Date: Sat, 23 Aug 2003 02:27:21 +0400
--Kj7319i9nmIyA2yE
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
This version of patch (hopefully :) fixes the issues tjr pointed to,
and adds hexal and octal constants which are required by SUSv3.
I've even successfully built 5.1's world with it.
--
Regards, Wartan.
"Computers are not intelligent. They only think they are."
--Kj7319i9nmIyA2yE
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ash.patch"
diff -u ./FreeBSD_ASH_HEAD.orig/arith.h ./FreeBSD_ASH_HEAD/arith.h
--- ./FreeBSD_ASH_HEAD.orig/arith.h Thu Aug 7 14:17:27 2003
+++ ./FreeBSD_ASH_HEAD/arith.h Thu Aug 7 14:17:43 2003
@@ -31,8 +31,9 @@
* SUCH DAMAGE.
*
* @(#)arith.h 1.1 (Berkeley) 5/4/95
- * $FreeBSD: src/bin/sh/arith.h,v 1.6 2002/02/02 06:50:45 imp Exp $
+ * $FreeBSD: src/bin/sh/arith.h,v 1.5.2.1 2002/07/19 04:38:51 tjr Exp $
*/
+int arith_assign(char *, arith_t);
int arith(char *);
int expcmd(int , char **);
diff -u ./FreeBSD_ASH_HEAD.orig/arith.y ./FreeBSD_ASH_HEAD/arith.y
--- ./FreeBSD_ASH_HEAD.orig/arith.y Thu Aug 7 14:17:27 2003
+++ ./FreeBSD_ASH_HEAD/arith.y Fri Aug 22 16:23:05 2003
@@ -1,5 +1,65 @@
-%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+%{
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/sh/arith.y,v 1.10.2.2 2002/07/19 04:38:51 tjr Exp $");
+
+#include <limits.h>
+#include "shell.h"
+#include "var.h"
+%}
+%union {
+ arith_t l_value;
+ char* s_value;
+}
+%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+%token <s_value> ARITH_VAR
+
+%type <l_value> expr
+%right ARITH_ASSIGN
+%right ARITH_ADDASSIGN ARITH_SUBASSIGN
+%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
+%right ARITH_RSHASSIGN ARITH_LSHASSIGN
+%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
%left ARITH_OR
%left ARITH_AND
%left ARITH_BOR
@@ -18,7 +78,6 @@
}
;
-
expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
| expr ARITH_OR expr = { $$ = $1 ? $1 : $3 ? $3 : 0; }
| expr ARITH_AND expr = { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
@@ -51,62 +110,139 @@
| ARITH_SUB expr %prec ARITH_UNARYMINUS = { $$ = -($2); }
| ARITH_ADD expr %prec ARITH_UNARYPLUS = { $$ = $2; }
| ARITH_NUM
+ | ARITH_VAR {
+ char *p;
+ arith_t arith_val;
+ char *str_val;
+
+ if (lookupvar($1) == NULL)
+ setvarsafe($1, "0", 0);
+ str_val = lookupvar($1);
+ arith_val = strtoarith_t(str_val, &p, 0);
+ /*
+ * Conversion is successful only in case
+ * we've converted _all_ characters.
+ */
+ if (*p != '\0')
+ yyerror("variable conversion error");
+ $$ = arith_val;
+ }
+ | ARITH_VAR ARITH_ASSIGN expr {
+ if (arith_assign($1, $3) != 1)
+ yyerror("variable assignment error");
+ $$ = $3;
+ }
+ | ARITH_VAR ARITH_ADDASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) + $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_SUBASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) - $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_MULASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) * $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_DIVASSIGN expr {
+ arith_t value;
+
+ if ($3 == 0)
+ yyerror("division by zero");
+
+ value = atoarith_t(lookupvar($1)) / $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_REMASSIGN expr {
+ arith_t value;
+
+ if ($3 == 0)
+ yyerror("division by zero");
+
+ value = atoarith_t(lookupvar($1)) % $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_RSHASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) >> $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_LSHASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) << $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_BANDASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) & $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_BXORASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) ^ $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
+ | ARITH_VAR ARITH_BORASSIGN expr {
+ arith_t value;
+
+ value = atoarith_t(lookupvar($1)) | $3;
+ if (arith_assign($1, value) != 0)
+ yyerror("variable assignment error");
+ $$ = value;
+ }
;
%%
-/*-
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
-#endif
-#endif /* not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/arith.y,v 1.14 2003/05/01 16:58:56 obrien Exp $");
-
-#include "shell.h"
#include "error.h"
#include "output.h"
#include "memalloc.h"
+#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
+
char *arith_buf, *arith_startbuf;
extern void arith_lex_reset();
int yylex(void);
int yyparse(void);
+
+int
+arith_assign(char *name, arith_t value) {
+ char *str;
+ int ret;
+
+ str = (char *)ckmalloc(lstrlen(value));
+ sprintf(str, ARITH_FORMAT_STR, value);
+ ret = setvarsafe(name, str, 0);
+ free(str);
+ return ret;
+}
int
arith(char *s)
diff -u ./FreeBSD_ASH_HEAD.orig/arith_lex.l ./FreeBSD_ASH_HEAD/arith_lex.l
--- ./FreeBSD_ASH_HEAD.orig/arith_lex.l Thu Aug 7 14:17:27 2003
+++ ./FreeBSD_ASH_HEAD/arith_lex.l Fri Aug 22 16:30:51 2003
@@ -41,12 +41,14 @@
#endif
#endif /* not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/arith_lex.l,v 1.18 2003/05/01 16:58:56 obrien Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/arith_lex.l,v 1.14.2.2 2002/07/19 04:38:51 tjr Exp $");
+#include "shell.h"
#include "y.tab.h"
#include "error.h"
+#include "var.h"
+#include "memalloc.h"
-extern int yylval;
extern char *arith_buf, *arith_startbuf;
#undef YY_INPUT
#define YY_INPUT(buf,result,max) \
@@ -56,7 +58,36 @@
%%
[ \t\n] { ; }
-[0-9]+ { yylval = atol(yytext); return(ARITH_NUM); }
+
+0x[a-fA-F0-9]+ {
+ yylval.l_value = strtoarith_t(yytext, NULL, 16);
+ return(ARITH_NUM);
+ }
+
+0[0-7]+ {
+ yylval.l_value = strtoarith_t(yytext, NULL, 8);
+ return(ARITH_NUM);
+ }
+
+[0-9]+ {
+ yylval.l_value = strtoarith_t(yytext, NULL, 10);
+ return(ARITH_NUM);
+ }
+
+
+[A-Za-z][A-Za-z0-9_]* {
+ /*
+ * If variable doesn't exist, we should initialize
+ * it to zero.
+ */
+ char *temp;
+ if (lookupvar(yytext) == NULL)
+ setvarsafe(yytext, "0", 0);
+ temp = (char *)ckmalloc(strlen(yytext) + 1);
+ yylval.s_value = strcpy(temp, yytext);
+
+ return(ARITH_VAR);
+ }
"(" { return(ARITH_LPAREN); }
")" { return(ARITH_RPAREN); }
"||" { return(ARITH_OR); }
@@ -79,6 +110,17 @@
"-" { return(ARITH_SUB); }
"~" { return(ARITH_BNOT); }
"!" { return(ARITH_NOT); }
+"=" { return(ARITH_ASSIGN); }
+"+=" { return(ARITH_ADDASSIGN); }
+"-=" { return(ARITH_SUBASSIGN); }
+"*=" { return(ARITH_MULASSIGN); }
+"/=" { return(ARITH_DIVASSIGN); }
+"%=" { return(ARITH_REMASSIGN); }
+">>=" { return(ARITH_RSHASSIGN); }
+"<<=" { return(ARITH_LSHASSIGN); }
+"&=" { return(ARITH_BANDASSIGN); }
+"^=" { return(ARITH_BXORASSIGN); }
+"|=" { return(ARITH_BORASSIGN); }
. { error("arith: syntax error: \"%s\"\n", arith_startbuf); }
%%
Common subdirectories: ./FreeBSD_ASH_HEAD.orig/bltin and ./FreeBSD_ASH_HEAD/bltin
Common subdirectories: ./FreeBSD_ASH_HEAD.orig/funcs and ./FreeBSD_ASH_HEAD/funcs
diff -u ./FreeBSD_ASH_HEAD.orig/shell.h ./FreeBSD_ASH_HEAD/shell.h
--- ./FreeBSD_ASH_HEAD.orig/shell.h Thu Aug 7 14:17:27 2003
+++ ./FreeBSD_ASH_HEAD/shell.h Fri Aug 22 16:29:39 2003
@@ -51,6 +51,14 @@
#define JOBS 1
/* #define DEBUG 1 */
+/*
+ * Type of used arithmetics. SUSv3 requires us to have at least signed long.
+ */
+typedef long arith_t;
+#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
+#define atoarith_t(arg) strtol(arg, NULL, 0)
+#define ARITH_FORMAT_STR "%ld"
+
typedef void *pointer;
#define STATIC static
#define MKINIT /* empty */
--Kj7319i9nmIyA2yE--
More information about the freebsd-standards
mailing list