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