On 6/24/11 1:18 PM, Rui Santos wrote:

> Try this script:
> #!/bin/bash
> 
> declare -ax array
> array[$(( $( echo -n 1001 ) - 1001 ))]=1
> 
> this will issue an error: line 6: 1001: command not found
> 
> If however the script is turned into:
> #!/bin/bash
> 
> declare -ax array
> array[$(( `echo -n 1001` - 1001 ))]=1
> 
> it works perfectly.
> 
> The first script will run without any problems on bash-4.1-9
> However if, on bash 4.2-10 (where the 1st script fails), you have a script
> like:
> #!/bin/bash
> echo $(( $( echo -n 1001 ) - 1001 ))
> 
> it also works fine.
> strange...

Yes.  It's a case of not saving and restoring enough state across possibly-
recursive calls to the shell parser.  (The assignment statement is the key
in this case.)

> So, I compared subst.c files from bash-4.1-9 and bash-4.2-10 and was able
> to build a patch that it seems to make it work.
> So to all you Bash guru's, can this patch be applied with no extra
> consequences ?

No.  The code is in there for a reason.  It's part of the fix for Posix
interpretation 217 (http://austingroupbugs.net/view.php?id=217).

The right fix is to save and restore the right shell context around
recursive calls to the parser.  The attached patch does that, and the
result passes the rest of the test suite (which obviously needs to be
augmented).

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU    c...@case.edu    http://cnswww.cns.cwru.edu/~chet/
*** ../bash-4.2-patched/parse.y 2011-02-26 19:19:05.000000000 -0500
--- parse.y     2011-06-24 20:08:22.000000000 -0400
***************
*** 3843,3846 ****
--- 3849,3853 ----
  {
    sh_parser_state_t ps;
+   sh_input_line_state_t ls;
    int orig_ind, nc, sflags;
    char *ret, *s, *ep, *ostring;
***************
*** 3850,3857 ****
--- 3857,3866 ----
    ostring = string;
  
+ /*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", 
shell_input_line_size, shell_input_line);*/
    sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
    if (flags & SX_NOLONGJMP)
      sflags |= SEVAL_NOLONGJMP;
    save_parser_state (&ps);
+   save_input_line_state (&ls);
  
    /*(*/
***************
*** 3862,3865 ****
--- 3871,3876 ----
    restore_parser_state (&ps);
    reset_parser ();
+   /* reset_parser clears shell_input_line and associated variables */
+   restore_input_line_state (&ls);
    if (interactive)
      token_to_read = 0;
***************
*** 5909,5912 ****
--- 5920,5929 ----
    ps->echo_input_at_read = echo_input_at_read;
  
+   ps->token = token;
+   ps->token_buffer_size = token_buffer_size;
+   /* Force reallocation on next call to read_token_word */
+   token = 0;
+   token_buffer_size = 0;
+ 
    return (ps);
  }
***************
*** 5950,5953 ****
--- 5967,6006 ----
    expand_aliases = ps->expand_aliases;
    echo_input_at_read = ps->echo_input_at_read;
+ 
+   FREE (token);
+   token = ps->token;
+   token_buffer_size = ps->token_buffer_size;
+ }
+ 
+ sh_input_line_state_t *
+ save_input_line_state (ls)
+      sh_input_line_state_t *ls;
+ {
+   if (ls == 0)
+     ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
+   if (ls == 0)
+     return ((sh_input_line_state_t *)NULL);
+ 
+   ls->input_line = shell_input_line;
+   ls->input_line_size = shell_input_line_size;
+   ls->input_line_len = shell_input_line_len;
+   ls->input_line_index = shell_input_line_index;
+ 
+   /* force reallocation */
+   shell_input_line = 0;
+   shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
+ }
+ 
+ void
+ restore_input_line_state (ls)
+      sh_input_line_state_t *ls;
+ {
+   FREE (shell_input_line);
+   shell_input_line = ls->input_line;
+   shell_input_line_size = ls->input_line_size;
+   shell_input_line_len = ls->input_line_len;
+   shell_input_line_index = ls->input_line_index;
+ 
+   set_line_mbstate ();
  }
  
*** ../bash-4.2-patched/shell.h 2011-01-06 22:16:55.000000000 -0500
--- shell.h     2011-06-24 19:12:25.000000000 -0400
***************
*** 137,140 ****
--- 139,145 ----
    int *token_state;
  
+   char *token;
+   int token_buffer_size;
+ 
    /* input line state -- line number saved elsewhere */
    int input_line_terminator;
***************
*** 167,171 ****
--- 172,186 ----
  } sh_parser_state_t;
  
+ typedef struct _sh_input_line_state_t {
+   char *input_line;
+   int input_line_index;
+   int input_line_size;
+   int input_line_len;
+ } sh_input_line_state_t;
+ 
  /* Let's try declaring these here. */
  extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *));
  extern void restore_parser_state __P((sh_parser_state_t *));
+ 
+ extern sh_input_line_state_t *save_input_line_state 
__P((sh_input_line_state_t *));
+ extern void restore_input_line_state __P((sh_input_line_state_t *));

Reply via email to