9f314eece51465c1ed801cafad6425291888b39e
[hdw-linux/hdw-linux.git] / packages / base / bash / official_fixes.patch
1 diff -Naur bash-3.0.orig/array.c bash-3.0/array.c
2 --- bash-3.0.orig/array.c       2004-05-06 12:24:13.000000000 +0000
3 +++ bash-3.0/array.c    2005-01-08 05:40:02.059798512 +0000
4 @@ -451,7 +451,7 @@
5                          */
6                         array_dispose_element(new);
7                         free(element_value(ae));
8 -                       ae->value = savestring(v);
9 +                       ae->value = v ? savestring(v) : (char *)NULL;
10                         return(0);
11                 } else if (element_index(ae) > i) {
12                         ADD_BEFORE(ae, new);
13 diff -Naur bash-3.0.orig/arrayfunc.c bash-3.0/arrayfunc.c
14 --- bash-3.0.orig/arrayfunc.c   2003-12-19 05:03:09.000000000 +0000
15 +++ bash-3.0/arrayfunc.c        2005-01-08 05:40:01.679856272 +0000
16 @@ -611,7 +611,7 @@
17    var = find_variable (t);
18  
19    free (t);
20 -  return var;
21 +  return (var == 0 || invisible_p (var)) ? (SHELL_VAR *)0 : var;
22  }
23  
24  /* Return a string containing the elements in the array and subscript
25 diff -Naur bash-3.0.orig/bashline.c bash-3.0/bashline.c
26 --- bash-3.0.orig/bashline.c    2004-07-06 03:22:12.000000000 +0000
27 +++ bash-3.0/bashline.c 2005-01-08 05:40:42.016724136 +0000
28 @@ -100,6 +100,7 @@
29  #endif
30  
31  /* Helper functions for Readline. */
32 +static int bash_directory_expansion __P((char **));
33  static int bash_directory_completion_hook __P((char **));
34  static int filename_completion_ignore __P((char **));
35  static int bash_push_line __P((void));
36 @@ -292,7 +293,7 @@
37        /* See if we have anything to do. */
38        at = strchr (rl_completer_word_break_characters, '@');
39        if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0))
40 -        return;
41 +        return old_value;
42  
43        /* We have something to do.  Do it. */
44        nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off);
45 @@ -1406,10 +1407,19 @@
46              filename. */
47           if (*hint_text == '~')
48             {
49 -             int l, tl, vl;
50 +             int l, tl, vl, dl;
51 +             char *rd;
52               vl = strlen (val);
53               tl = strlen (hint_text);
54 +#if 0
55               l = vl - hint_len;        /* # of chars added */
56 +#else
57 +             rd = savestring (filename_hint);
58 +             bash_directory_expansion (&rd);
59 +             dl = strlen (rd);
60 +             l = vl - dl;              /* # of chars added */
61 +             free (rd);
62 +#endif
63               temp = (char *)xmalloc (l + 2 + tl);
64               strcpy (temp, hint_text);
65               strcpy (temp + tl, val + vl - l);
66 @@ -2187,6 +2197,27 @@
67    return 0;
68  }
69  
70 +/* Simulate the expansions that will be performed by
71 +   rl_filename_completion_function.  This must be called with the address of
72 +   a pointer to malloc'd memory. */
73 +static int
74 +bash_directory_expansion (dirname)
75 +     char **dirname;
76 +{
77 +  char *d;
78 +
79 +  d = savestring (*dirname);
80 +
81 +  if (rl_directory_rewrite_hook)
82 +    (*rl_directory_rewrite_hook) (&d);
83 +
84 +  if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
85 +    {
86 +      free (*dirname);
87 +      *dirname = d;
88 +    }
89 +}
90 +  
91  /* Handle symbolic link references and other directory name
92     expansions while hacking completion. */
93  static int
94 @@ -2513,7 +2544,7 @@
95    static char **matches = (char **)NULL;
96    static int ind;
97    int glen;
98 -  char *ret;
99 +  char *ret, *ttext;
100  
101    if (state == 0)
102      {
103 @@ -2523,17 +2554,22 @@
104         FREE (globorig);
105        FREE (globtext);
106  
107 +      ttext = bash_tilde_expand (text, 0);
108 +
109        if (rl_explicit_arg)
110         {
111 -         globorig = savestring (text);
112 -         glen = strlen (text);
113 +         globorig = savestring (ttext);
114 +         glen = strlen (ttext);
115           globtext = (char *)xmalloc (glen + 2);
116 -         strcpy (globtext, text);
117 +         strcpy (globtext, ttext);
118           globtext[glen] = '*';
119           globtext[glen+1] = '\0';
120         }
121        else
122 -        globtext = globorig = savestring (text);
123 +        globtext = globorig = savestring (ttext);
124 +
125 +      if (ttext != text)
126 +       free (ttext);
127  
128        matches = shell_glob_filename (globtext);
129        if (GLOB_FAILED (matches))
130 diff -Naur bash-3.0.orig/braces.c bash-3.0/braces.c
131 --- bash-3.0.orig/braces.c      2003-12-04 16:09:52.000000000 +0000
132 +++ bash-3.0/braces.c   2005-01-08 05:40:50.317462232 +0000
133 @@ -340,8 +340,8 @@
134    
135    if (lhs_t == ST_CHAR)
136      {
137 -      lhs_v = lhs[0];
138 -      rhs_v = rhs[0];
139 +      lhs_v = (unsigned char)lhs[0];
140 +      rhs_v = (unsigned char)rhs[0];
141      }
142    else
143      {
144 @@ -402,6 +402,8 @@
145         {
146           pass_next = 1;
147           i++;
148 +         if (quoted == 0)
149 +           level++;
150           continue;
151         }
152  #endif
153 diff -Naur bash-3.0.orig/builtins/trap.def bash-3.0/builtins/trap.def
154 --- bash-3.0.orig/builtins/trap.def     2004-05-28 02:26:19.000000000 +0000
155 +++ bash-3.0/builtins/trap.def  2005-01-08 05:40:04.443436144 +0000
156 @@ -23,7 +23,7 @@
157  
158  $BUILTIN trap
159  $FUNCTION trap_builtin
160 -$SHORT_DOC trap [-lp] [[arg] signal_spec ...]
161 +$SHORT_DOC trap [-lp] [arg signal_spec ...]
162  The command ARG is to be read and executed when the shell receives
163  signal(s) SIGNAL_SPEC.  If ARG is absent (and a single SIGNAL_SPEC
164  is supplied) or `-', each specified signal is reset to its original
165 @@ -87,7 +87,7 @@
166  trap_builtin (list)
167       WORD_LIST *list;
168  {
169 -  int list_signal_names, display, result, opt;
170 +  int list_signal_names, display, result, opt, first_signal;
171  
172    list_signal_names = display = 0;
173    result = EXECUTION_SUCCESS;
174 @@ -118,14 +118,19 @@
175    else
176      {
177        char *first_arg;
178 -      int operation, sig;
179 +      int operation, sig, first_signal;
180  
181        operation = SET;
182        first_arg = list->word->word;
183 +      first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
184 +
185 +      /* Backwards compatibility */
186 +      if (first_signal)
187 +       operation = REVERT;
188        /* When in posix mode, the historical behavior of looking for a
189          missing first argument is disabled.  To revert to the original
190          signal handling disposition, use `-' as the first argument. */
191 -      if (posixly_correct == 0 && first_arg && *first_arg &&
192 +      else if (posixly_correct == 0 && first_arg && *first_arg &&
193                 (*first_arg != '-' || first_arg[1]) &&
194                 signal_object_p (first_arg, opt) && list->next == 0)
195         operation = REVERT;
196 diff -Naur bash-3.0.orig/doc/bashref.texi bash-3.0/doc/bashref.texi
197 --- bash-3.0.orig/doc/bashref.texi      2004-06-26 18:26:07.000000000 +0000
198 +++ bash-3.0/doc/bashref.texi   2005-01-08 05:40:04.494428392 +0000
199 @@ -5953,7 +5953,8 @@
200  @item
201  The @code{trap} builtin doesn't check the first argument for a possible
202  signal specification and revert the signal handling to the original
203 -disposition if it is.  If users want to reset the handler for a given
204 +disposition if it is, unless that argument consists solely of digits and
205 +is a valid signal number.  If users want to reset the handler for a given
206  signal to the original disposition, they should use @samp{-} as the
207  first argument.
208  
209 diff -Naur bash-3.0.orig/general.c bash-3.0/general.c
210 --- bash-3.0.orig/general.c     2004-04-15 03:20:13.000000000 +0000
211 +++ bash-3.0/general.c  2005-01-08 05:40:51.913219640 +0000
212 @@ -267,7 +267,7 @@
213    c = string[indx = 0];
214  
215  #if defined (ARRAY_VARS)
216 -  if ((legal_variable_starter (c) == 0) && (flags && c != '[')) /* ] */
217 +  if ((legal_variable_starter (c) == 0) && (flags == 0 || c != '[')) /* ] */
218  #else
219    if (legal_variable_starter (c) == 0)
220  #endif
221 diff -Naur bash-3.0.orig/include/shmbutil.h bash-3.0/include/shmbutil.h
222 --- bash-3.0.orig/include/shmbutil.h    2004-04-19 13:59:42.000000000 +0000
223 +++ bash-3.0/include/shmbutil.h 2005-01-08 05:40:05.724241432 +0000
224 @@ -31,6 +31,8 @@
225  extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
226  extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
227  
228 +extern size_t mbstrlen __P((const char *));
229 +
230  extern char *xstrchr __P((const char *, int));
231  
232  #ifndef MB_INVALIDCH
233 @@ -38,6 +40,9 @@
234  #define MB_NULLWCH(x)          ((x) == 0)
235  #endif
236  
237 +#define MBSLEN(s)      (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0)
238 +#define MB_STRLEN(s)   ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s))
239 +
240  #else /* !HANDLE_MULTIBYTE */
241  
242  #undef MB_LEN_MAX
243 @@ -54,6 +59,8 @@
244  #define MB_NULLWCH(x)          (0)
245  #endif
246  
247 +#define MB_STRLEN(s)           (STRLEN(s))
248 +
249  #endif /* !HANDLE_MULTIBYTE */
250  
251  /* Declare and initialize a multibyte state.  Call must be terminated
252 diff -Naur bash-3.0.orig/jobs.c bash-3.0/jobs.c
253 --- bash-3.0.orig/jobs.c        2004-04-23 20:28:25.000000000 +0000
254 +++ bash-3.0/jobs.c     2005-01-08 05:40:40.567944384 +0000
255 @@ -1778,8 +1778,13 @@
256    if (pipefail_opt)
257      {
258        fail = 0;
259 -      for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
260 -        if (p->status != EXECUTION_SUCCESS) fail = p->status;
261 +      p = jobs[job]->pipe;
262 +      do
263 +       {
264 +         if (p->status != EXECUTION_SUCCESS) fail = p->status;
265 +         p = p->next;
266 +       }
267 +      while (p != jobs[job]->pipe);
268        return fail;
269      }
270  
271 diff -Naur bash-3.0.orig/lib/readline/display.c bash-3.0/lib/readline/display.c
272 --- bash-3.0.orig/lib/readline/display.c        2004-05-28 02:57:51.000000000 +0000
273 +++ bash-3.0/lib/readline/display.c     2005-01-08 05:40:08.574808080 +0000
274 @@ -201,7 +201,7 @@
275       int *lp, *lip, *niflp, *vlp;
276  {
277    char *r, *ret, *p;
278 -  int l, rl, last, ignoring, ninvis, invfl, ind, pind, physchars;
279 +  int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
280  
281    /* Short-circuit if we can. */
282    if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
283 @@ -222,6 +222,7 @@
284    r = ret = (char *)xmalloc (l + 1);
285  
286    invfl = 0;   /* invisible chars in first line of prompt */
287 +  invflset = 0;        /* we only want to set invfl once */
288  
289    for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
290      {
291 @@ -249,7 +250,10 @@
292               while (l--)
293                 *r++ = *p++;
294               if (!ignoring)
295 -               rl += ind - pind;
296 +               {
297 +                 rl += ind - pind;
298 +                 physchars += _rl_col_width (pmt, pind, ind);
299 +               }
300               else
301                 ninvis += ind - pind;
302               p--;                      /* compensate for later increment */
303 @@ -259,16 +263,19 @@
304             {
305               *r++ = *p;
306               if (!ignoring)
307 -               rl++;                   /* visible length byte counter */
308 +               {
309 +                 rl++;                 /* visible length byte counter */
310 +                 physchars++;
311 +               }
312               else
313                 ninvis++;               /* invisible chars byte counter */
314             }
315  
316 -         if (rl >= _rl_screenwidth)
317 -           invfl = ninvis;
318 -
319 -         if (ignoring == 0)
320 -           physchars++;
321 +         if (invflset == 0 && rl >= _rl_screenwidth)
322 +           {
323 +             invfl = ninvis;
324 +             invflset = 1;
325 +           }
326         }
327      }
328  
329 @@ -351,14 +358,14 @@
330        local_prompt = expand_prompt (p, &prompt_visible_length,
331                                        &prompt_last_invisible,
332                                        (int *)NULL,
333 -                                      (int *)NULL);
334 +                                      &prompt_physical_chars);
335        c = *t; *t = '\0';
336        /* The portion of the prompt string up to and including the
337          final newline is now null-terminated. */
338        local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
339                                                    (int *)NULL,
340                                                    &prompt_invis_chars_first_line,
341 -                                                  &prompt_physical_chars);
342 +                                                  (int *)NULL);
343        *t = c;
344        return (prompt_prefix_length);
345      }
346 @@ -417,7 +424,7 @@
347    register int in, out, c, linenum, cursor_linenum;
348    register char *line;
349    int c_pos, inv_botlin, lb_botlin, lb_linenum;
350 -  int newlines, lpos, temp, modmark;
351 +  int newlines, lpos, temp, modmark, n0, num;
352    char *prompt_this_line;
353  #if defined (HANDLE_MULTIBYTE)
354    wchar_t wc;
355 @@ -573,6 +580,7 @@
356  
357  #if defined (HANDLE_MULTIBYTE)
358    memset (_rl_wrapped_line, 0, vis_lbsize);
359 +  num = 0;
360  #endif
361  
362    /* prompt_invis_chars_first_line is the number of invisible characters in
363 @@ -591,13 +599,32 @@
364           probably too much work for the benefit gained.  How many people have
365           prompts that exceed two physical lines?
366           Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
367 +#if defined (HANDLE_MULTIBYTE)
368 +      n0 = num;
369 +      temp = local_prompt ? strlen (local_prompt) : 0;
370 +      while (num < temp)
371 +       {
372 +         if (_rl_col_width  (local_prompt, n0, num) > _rl_screenwidth)
373 +           {
374 +             num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
375 +             break;
376 +           }
377 +         num++;
378 +       }
379 +      temp = num +
380 +#else
381        temp = ((newlines + 1) * _rl_screenwidth) +
382 +#endif /* !HANDLE_MULTIBYTE */
383               ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
384                                                             : ((newlines == 1) ? wrap_offset : 0))
385                                          : ((newlines == 0) ? wrap_offset :0));
386               
387        inv_lbreaks[++newlines] = temp;
388 +#if defined (HANDLE_MULTIBYTE)
389 +      lpos -= _rl_col_width (local_prompt, n0, num);
390 +#else
391        lpos -= _rl_screenwidth;
392 +#endif
393      }
394  
395    prompt_last_screen_line = newlines;
396 diff -Naur bash-3.0.orig/lib/readline/mbutil.c bash-3.0/lib/readline/mbutil.c
397 --- bash-3.0.orig/lib/readline/mbutil.c 2004-01-14 14:44:52.000000000 +0000
398 +++ bash-3.0/lib/readline/mbutil.c      2005-01-08 05:40:39.252144416 +0000
399 @@ -126,11 +126,11 @@
400    if (find_non_zero)
401      {
402        tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
403 -      while (wcwidth (wc) == 0)
404 +      while (tmp > 0 && wcwidth (wc) == 0)
405         {
406           point += tmp;
407           tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
408 -         if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2))
409 +         if (MB_NULLWCH (tmp) || MB_INVALIDCH (tmp))
410             break;
411         }
412      }
413 diff -Naur bash-3.0.orig/lib/readline/misc.c bash-3.0/lib/readline/misc.c
414 --- bash-3.0.orig/lib/readline/misc.c   2004-07-07 12:56:32.000000000 +0000
415 +++ bash-3.0/lib/readline/misc.c        2005-01-08 05:40:07.040041400 +0000
416 @@ -276,12 +276,6 @@
417        _rl_saved_line_for_history->line = savestring (rl_line_buffer);
418        _rl_saved_line_for_history->data = (char *)rl_undo_list;
419      }
420 -  else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0)
421 -    {
422 -      free (_rl_saved_line_for_history->line);
423 -      _rl_saved_line_for_history->line = savestring (rl_line_buffer);
424 -      _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */
425 -    }
426  
427    return 0;
428  }
429 diff -Naur bash-3.0.orig/lib/readline/vi_mode.c bash-3.0/lib/readline/vi_mode.c
430 --- bash-3.0.orig/lib/readline/vi_mode.c        2004-07-13 18:08:27.000000000 +0000
431 +++ bash-3.0/lib/readline/vi_mode.c     2005-01-08 05:40:25.349257976 +0000
432 @@ -272,10 +272,12 @@
433    switch (key)
434      {
435      case '?':
436 +      _rl_free_saved_history_line ();
437        rl_noninc_forward_search (count, key);
438        break;
439  
440      case '/':
441 +      _rl_free_saved_history_line ();
442        rl_noninc_reverse_search (count, key);
443        break;
444  
445 @@ -690,7 +692,7 @@
446  {
447    wchar_t wc;
448    char mb[MB_LEN_MAX+1];
449 -  int mblen;
450 +  int mblen, p;
451    mbstate_t ps;
452  
453    memset (&ps, 0, sizeof (mbstate_t));
454 @@ -713,11 +715,14 @@
455        /* Vi is kind of strange here. */
456        if (wc)
457         {
458 +         p = rl_point;
459           mblen = wcrtomb (mb, wc, &ps);
460           if (mblen >= 0)
461             mb[mblen] = '\0';
462           rl_begin_undo_group ();
463 -         rl_delete (1, 0);
464 +         rl_vi_delete (1, 0);
465 +         if (rl_point < p)     /* Did we retreat at EOL? */
466 +           rl_point++; /* XXX - should we advance more than 1 for mbchar? */
467           rl_insert_text (mb);
468           rl_end_undo_group ();
469           rl_vi_check ();
470 @@ -1310,12 +1315,16 @@
471        rl_vi_delete (1, c);
472  #if defined (HANDLE_MULTIBYTE)
473        if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
474 -       while (_rl_insert_char (1, c))
475 -         {
476 -           RL_SETSTATE (RL_STATE_MOREINPUT);
477 -           c = rl_read_key ();
478 -           RL_UNSETSTATE (RL_STATE_MOREINPUT);
479 -         }
480 +       {
481 +         if (rl_point < p)             /* Did we retreat at EOL? */
482 +           rl_point++;
483 +         while (_rl_insert_char (1, c))
484 +           {
485 +             RL_SETSTATE (RL_STATE_MOREINPUT);
486 +             c = rl_read_key ();
487 +             RL_UNSETSTATE (RL_STATE_MOREINPUT);
488 +           }
489 +       }
490        else
491  #endif
492         {
493 diff -Naur bash-3.0.orig/patchlevel.h bash-3.0/patchlevel.h
494 --- bash-3.0.orig/patchlevel.h  2001-08-22 12:05:39.000000000 +0000
495 +++ bash-3.0/patchlevel.h       2005-01-08 05:40:53.584965496 +0000
496 @@ -25,6 +25,6 @@
497     regexp `^#define[   ]*PATCHLEVEL', since that's what support/mkversion.sh
498     looks for to find the patch level (for the sccs version string). */
499  
500 -#define PATCHLEVEL 0
501 +#define PATCHLEVEL 16
502  
503  #endif /* _PATCHLEVEL_H_ */
504 diff -Naur bash-3.0.orig/pcomplete.c bash-3.0/pcomplete.c
505 --- bash-3.0.orig/pcomplete.c   2004-01-08 15:36:17.000000000 +0000
506 +++ bash-3.0/pcomplete.c        2005-01-08 05:40:02.049800032 +0000
507 @@ -863,6 +863,8 @@
508    if (array_p (v) == 0)
509      v = convert_var_to_array (v);
510    v = assign_array_var_from_word_list (v, lwords);
511 +
512 +  VUNSETATTR (v, att_invisible);
513    return v;
514  }
515  #endif /* ARRAY_VARS */
516 @@ -1022,6 +1024,8 @@
517    if (array_p (v) == 0)
518      v = convert_var_to_array (v);
519  
520 +  VUNSETATTR (v, att_invisible);
521 +
522    a = array_cell (v);
523    if (a == 0 || array_empty (a))
524      sl = (STRINGLIST *)NULL;
525 diff -Naur bash-3.0.orig/subst.c bash-3.0/subst.c
526 --- bash-3.0.orig/subst.c       2004-07-04 17:56:13.000000000 +0000
527 +++ bash-3.0/subst.c    2005-01-08 05:40:53.574967016 +0000
528 @@ -4691,6 +4691,26 @@
529           legal_identifier (name + 1));                         /* ${#PS1} */
530  }
531  
532 +#if defined (HANDLE_MULTIBYTE)
533 +size_t
534 +mbstrlen (s)
535 +     const char *s;
536 +{
537 +  size_t clen, nc;
538 +  mbstate_t mbs;
539 +
540 +  nc = 0;
541 +  memset (&mbs, 0, sizeof (mbs));
542 +  while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0 && (MB_INVALIDCH(clen) == 0))
543 +    {
544 +      s += clen;
545 +      nc++;
546 +    }
547 +  return nc;
548 +}
549 +#endif
550 +      
551 +
552  /* Handle the parameter brace expansion that requires us to return the
553     length of a parameter. */
554  static intmax_t
555 @@ -4746,14 +4766,14 @@
556        if (legal_number (name + 1, &arg_index))         /* ${#1} */
557         {
558           t = get_dollar_var_value (arg_index);
559 -         number = STRLEN (t);
560 +         number = MB_STRLEN (t);
561           FREE (t);
562         }
563  #if defined (ARRAY_VARS)
564 -      else if ((var = find_variable (name + 1)) && array_p (var))
565 +      else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && array_p (var))
566         {
567           t = array_reference (array_cell (var), 0);
568 -         number = STRLEN (t);
569 +         number = MB_STRLEN (t);
570         }
571  #endif
572        else                             /* ${#PS1} */
573 @@ -4766,7 +4786,7 @@
574           if (list)
575             dispose_words (list);
576  
577 -         number = STRLEN (t);
578 +         number = MB_STRLEN (t);
579           FREE (t);
580         }
581      }
582 @@ -4871,7 +4891,7 @@
583      {
584      case VT_VARIABLE:
585      case VT_ARRAYMEMBER:
586 -      len = strlen (value);
587 +      len = MB_STRLEN (value);
588        break;
589      case VT_POSPARMS:
590        len = number_of_args () + 1;
591 @@ -4879,8 +4899,9 @@
592  #if defined (ARRAY_VARS)
593      case VT_ARRAYVAR:
594        a = (ARRAY *)value;
595 -      /* For arrays, the first value deals with array indices. */
596 -      len = array_max_index (a);       /* arrays index from 0 to n - 1 */
597 +      /* For arrays, the first value deals with array indices.  Negative
598 +        offsets count from one past the array's maximum index. */
599 +      len = array_max_index (a) + (*e1p < 0);  /* arrays index from 0 to n - 1 */
600        break;
601  #endif
602      }
603 @@ -4891,7 +4912,7 @@
604    if (*e1p < 0)                /* negative offsets count from end */
605      *e1p += len;
606  
607 -  if (*e1p >= len || *e1p < 0)
608 +  if (*e1p > len || *e1p < 0)
609      return (-1);
610  
611  #if defined (ARRAY_VARS)
612 @@ -4982,7 +5003,7 @@
613        else
614         return -1;
615      }
616 -  else if ((v = find_variable (varname)) && array_p (v))
617 +  else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v))
618      {
619        vtype = VT_ARRAYMEMBER;
620        *varp = v;
621 diff -Naur bash-3.0.orig/tests/array.right bash-3.0/tests/array.right
622 --- bash-3.0.orig/tests/array.right     2003-10-05 03:25:10.000000000 +0000
623 +++ bash-3.0/tests/array.right  2005-01-08 05:40:53.582965800 +0000
624 @@ -170,8 +170,8 @@
625  three five seven
626  positive offset - expect five seven
627  five seven
628 -negative offset - expect five seven
629 -five seven
630 +negative offset to unset element - expect seven
631 +seven
632  positive offset 2 - expect seven
633  seven
634  negative offset 2 - expect seven
635 diff -Naur bash-3.0.orig/tests/array.tests bash-3.0/tests/array.tests
636 --- bash-3.0.orig/tests/array.tests     2003-10-05 03:25:00.000000000 +0000
637 +++ bash-3.0/tests/array.tests  2005-01-08 05:40:53.580966104 +0000
638 @@ -322,7 +322,7 @@
639  
640  echo positive offset - expect five seven
641  echo ${av[@]:5:2}
642 -echo negative offset - expect five seven
643 +echo negative offset to unset element - expect seven
644  echo ${av[@]: -2:2}
645  
646  echo positive offset 2 - expect seven
647 diff -Naur bash-3.0.orig/tests/dbg-support.tests bash-3.0/tests/dbg-support.tests
648 --- bash-3.0.orig/tests/dbg-support.tests       2003-03-25 20:33:03.000000000 +0000
649 +++ bash-3.0/tests/dbg-support.tests    2005-01-08 05:40:02.065797600 +0000
650 @@ -62,8 +62,8 @@
651  trap 'print_debug_trap $LINENO' DEBUG
652  trap 'print_return_trap $LINENO' RETURN
653  
654 -# Funcname is now an array. Vanilla Bash 2.05 doesn't have FUNCNAME array.
655 -echo "FUNCNAME" ${FUNCNAME[0]}
656 +# Funcname is now an array, but you still can't see it outside a function
657 +echo "FUNCNAME" ${FUNCNAME[0]:-main}
658  
659  # We should trace into the below. 
660  # Start easy with a simple function.
661 diff -Naur bash-3.0.orig/tests/errors.right bash-3.0/tests/errors.right
662 --- bash-3.0.orig/tests/errors.right    2004-05-28 02:26:03.000000000 +0000
663 +++ bash-3.0/tests/errors.right 2005-01-08 05:40:04.502427176 +0000
664 @@ -85,7 +85,7 @@
665  ./errors.tests: line 213: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
666  ./errors.tests: line 216: trap: NOSIG: invalid signal specification
667  ./errors.tests: line 219: trap: -s: invalid option
668 -trap: usage: trap [-lp] [[arg] signal_spec ...]
669 +trap: usage: trap [-lp] [arg signal_spec ...]
670  ./errors.tests: line 225: return: can only `return' from a function or sourced script
671  ./errors.tests: line 229: break: 0: loop count out of range
672  ./errors.tests: line 233: continue: 0: loop count out of range
673 diff -Naur bash-3.0.orig/variables.c bash-3.0/variables.c
674 --- bash-3.0.orig/variables.c   2004-07-04 17:57:26.000000000 +0000
675 +++ bash-3.0/variables.c        2005-01-08 05:40:01.842831496 +0000
676 @@ -1419,11 +1419,11 @@
677    v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
678  
679  #  if defined (DEBUGGER)
680 -  v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, (att_invisible|att_noassign));
681 -  v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, (att_invisible|att_noassign));
682 +  v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign);
683 +  v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign);
684  #  endif /* DEBUGGER */
685 -  v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, (att_invisible|att_noassign));
686 -  v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, (att_invisible|att_noassign));
687 +  v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign);
688 +  v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign);
689  #endif
690  
691    v = init_funcname_var ();
692 @@ -1599,7 +1599,10 @@
693    /* local foo; local foo;  is a no-op. */
694    old_var = find_variable (name);
695    if (old_var && local_p (old_var) && old_var->context == variable_context)
696 -    return (old_var);
697 +    {
698 +      VUNSETATTR (old_var, att_invisible);
699 +      return (old_var);
700 +    }
701  
702    was_tmpvar = old_var && tempvar_p (old_var);
703    if (was_tmpvar)