bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Arithmetic assignment to array element broken


From: Joe Burpee
Subject: Arithmetic assignment to array element broken
Date: Tue, 25 Dec 2001 10:07:40 -0500

Configuration Information [Automatically generated, do not change]:
Machine: i586
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i586' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i586-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib -g -O2
uname output: Linux jeep1.burkby.com 2.4.9-6 #1 Thu Oct 18 09:47:34 EDT 2001 
i586 unknown
Machine Type: i586-pc-linux-gnu

Bash Version: 2.05a
Patch Level: 0
Release Status: release


Description:

Arithmetic assignment $((X=Y)) uses bind_int_variable.  This seems to be
wrong since the rhs has no need for re-evaluation.  Also the lhs does
not permit array element lvalues $((X[I]=Y)), etc.  (Hence it also
creates extra vars with names like "X[I]".)

This breaks other things.  E.g.
        for ((X[I]=1; X[I]<9; X[I]++))
is doubly broken.

I attempted a patch (below) using the routine for substitute ${X=Y}
which seems to be the general form borrowed by simple X=Y.

Works for me, but I've no doubt missed something.  Anyway, apologies for
kludginess; this stuff is new to me.


Repeat-By:

$ Arr=(0 1 2)
$ set|grep ^Arr
Arr=([0]="0" [1]="1" [2]="2")
$ echo $((++Arr[2]))
3
$ set|grep ^Arr
Arr=([0]="0" [1]="1" [2]="2")
Arr[2]=3


Fix:

--- bash-2.05a/expr.c.orig      Mon Oct 15 14:19:21 2001
+++ bash-2.05a/expr.c   Tue Dec 25 08:47:37 2001
@@ -383,7 +383,7 @@
 expassign ()
 {
   register long        value;
-  char *lhs, *rhs;
+  char *lhs;
 
   value = expcond ();
   if (curtok == EQ || curtok == OP_ASSIGN)
@@ -448,10 +448,8 @@
          value = lvalue;
        }
 
-      rhs = itos (value);
       if (noeval == 0)
-       (void)bind_int_variable (lhs, rhs);
-      free (rhs);
+             do_assignment_value (lhs, value);
       free (lhs);
       FREE (tokstr);
       tokstr = (char *)NULL;           /* For freeing on errors. */
@@ -784,7 +782,6 @@
 exp0 ()
 {
   register long val = 0, v2;
-  char *vincdec;
   int stok;
 
   /* XXX - might need additional logic here to decide whether or not
@@ -798,10 +795,8 @@
        evalerror ("identifier expected after pre-increment or
pre-decrement");
 
       v2 = tokval + ((stok == PREINC) ? 1 : -1);
-      vincdec = itos (v2);
       if (noeval == 0)
-       (void)bind_int_variable (tokstr, vincdec);
-      free (vincdec);
+             do_assignment_value (tokstr, v2);
       val = v2;
 
       curtok = NUM;    /* make sure --x=7 is flagged as an error */
@@ -836,10 +831,8 @@
        {
          /* post-increment or post-decrement */
          v2 = val + ((*tp == '+') ? 1 : -1);
-         vincdec = itos (v2);
          if (noeval == 0)
-           (void)bind_int_variable (tokstr, vincdec);
-         free (vincdec);
+             do_assignment_value (tokstr, v2);
          tp += 2;
          curtok = NUM; /* make sure x++=7 is flagged as an error */
        }
@@ -1113,6 +1106,26 @@
     }
   return (val);
 }
+
+/* Use ${X=Y} substitution assignment code for $((X=Y)), etc. */
+int
+do_assignment_value (lhs, value)
+  char *lhs;
+  register long value;
+{
+  char *str, *rhs; /* revert to string "lhs=rhs" */
+  int i;
+  
+  rhs = itos (value);
+  i = strlen (lhs);
+  str = (char *)xmalloc (i + 1 + strlen(rhs) + 1);
+  strcpy (str, lhs);
+  str[i++] = '=';
+  strcpy (str + i, rhs);
+  free (rhs);
+  do_assignment_no_expand (str); /* includes subscripted lhs */
+  free (str);
+  }    
 
 #if defined (EXPR_TEST)
 void *




reply via email to

[Prev in Thread] Current Thread [Next in Thread]