standards/52972: /bin/sh arithmetic not POSIX compliant
Wartan Hachaturow
wart at tepkom.ru
Thu Jul 3 13:40:17 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>
Subject: Re: standards/52972: /bin/sh arithmetic not POSIX compliant
Date: Fri, 4 Jul 2003 00:35:55 +0400
--jRHKVT23PllUwdXP
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Thu, Jul 03, 2003 at 09:40:06PM +0200, Jens Schweikhardt wrote:
> Thanks for taking up the grunt work and implementing this. This is more
> than I hoped for!
Someone should have made it :)
> + It appears this is a patch against RELENG_4; is this true? If yes, a
> patch against HEAD is needed.
Well, it was against RELENG_5_1. But the attached one is against HEAD
(though it have some remniscents like rcs ids from 5_1).
Looks like nothing has changed in ash since 5_1, initial patch applied
flawlessly.
> + There are many lines with whitespace at end-of-line which you should
> remove. Can you instruct your editor to make these visible?
Ok, looks like I've removed them now. ":set list" was of a great help :)
> + Reversing comparisons against constant values like in
> if (NULL == lookupvar($1))
> look like a style(9) violation.
I heard somewhere that it's treated as a good habit, and was in process
of getting myself used to that kind of comparison (like you may have
noticed, I mixed both ways :). But if it's against style(9), I'll
drop it. (My internal nature was against it, anyway :).
> PS: 11k is not really a big patch. Nobody would mind if you send your
> improved patch to the GNATS db. URLs with patches tend to become
> stale very soon.
Ok, improved one is attached.
--
Regards, Wartan.
"Computers are not intelligent. They only think they are."
--jRHKVT23PllUwdXP
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ash.patch.2"
diff -u ./FreeBSD_ASH_HEAD.orig/arith.h ./FreeBSD_ASH_HEAD/arith.h
--- ./FreeBSD_ASH_HEAD.orig/arith.h Fri Jul 4 00:16:21 2003
+++ ./FreeBSD_ASH_HEAD/arith.h Thu Jul 3 23:52:01 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 Fri Jul 4 00:16:21 2003
+++ ./FreeBSD_ASH_HEAD/arith.y Fri Jul 4 00:09:27 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
+static const char rcsid[] =
+ "$FreeBSD: src/bin/sh/arith.y,v 1.10.2.2 2002/07/19 04:38:51 tjr Exp $";
+#endif /* not lint */
+
+#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 (strncmp(p, "\0", 1) != 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));
+ snprintf(str, sizeof(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 Fri Jul 4 00:16:21 2003
+++ ./FreeBSD_ASH_HEAD/arith_lex.l Fri Jul 4 00:05:44 2003
@@ -39,14 +39,16 @@
#if 0
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
#endif
+static const char rcsid[] =
+ "$FreeBSD: src/bin/sh/arith_lex.l,v 1.14.2.2 2002/07/19 04:38:51 tjr Exp $";
#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 $");
+#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,13 +58,25 @@
%%
[ \t\n] { ; }
-[0-9]+ { yylval = atol(yytext); return(ARITH_NUM); }
+[0-9]+ { yylval.l_value = atol(yytext); 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 = strncpy(temp, yytext, sizeof(temp));
+
+ return(ARITH_VAR);
+ }
"(" { return(ARITH_LPAREN); }
")" { return(ARITH_RPAREN); }
"||" { return(ARITH_OR); }
"&&" { return(ARITH_AND); }
"|" { return(ARITH_BOR); }
-"^" { return(ARITH_BXOR); }
+"^" { return(ARITH_BXOR); }
"&" { return(ARITH_BAND); }
"==" { return(ARITH_EQ); }
"!=" { return(ARITH_NE); }
@@ -79,6 +93,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 Fri Jul 4 00:16:21 2003
+++ ./FreeBSD_ASH_HEAD/shell.h Thu Jul 3 23:52:15 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) atol(arg)
+#define ARITH_FORMAT_STR "%ld"
+
typedef void *pointer;
#define STATIC static
#define MKINIT /* empty */
--jRHKVT23PllUwdXP--
More information about the freebsd-standards
mailing list