94c230f79cb11c80f098ac4d6a2f7f5cec8fb8ba
[platform/upstream/bash.git] / subst.c
1 /* subst.c -- The part of the shell that does parameter, command, and
2    globbing substitutions. */
3
4 /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
5
6    This file is part of GNU Bash, the Bourne Again SHell.
7
8    Bash is free software; you can redistribute it and/or modify it under
9    the terms of the GNU General Public License as published by the Free
10    Software Foundation; either version 2, or (at your option) any later
11    version.
12
13    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14    WARRANTY; without even the implied warranty of MERCHANTABILITY or
15    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16    for more details.
17
18    You should have received a copy of the GNU General Public License along
19    with Bash; see the file COPYING.  If not, write to the Free Software
20    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include "config.h"
23
24 #include "bashtypes.h"
25 #include <stdio.h>
26 #include <pwd.h>
27 #include <signal.h>
28 #include <errno.h>
29
30 #if defined (HAVE_UNISTD_H)
31 #  include <unistd.h>
32 #endif
33
34 #include "bashansi.h"
35 #include "posixstat.h"
36
37 #include "shell.h"
38 #include "flags.h"
39 #include "jobs.h"
40 #include "execute_cmd.h"
41 #include "filecntl.h"
42 #include "trap.h"
43 #include "pathexp.h"
44 #include "mailcheck.h"
45
46 #if !defined (HAVE_RESTARTABLE_SYSCALLS)        /* for getc_with_restart */
47 #include "input.h"
48 #endif
49
50 #include "builtins/getopt.h"
51 #include "builtins/common.h"
52
53 #include <tilde/tilde.h>
54 #include <glob/fnmatch.h>
55
56 #if !defined (errno)
57 extern int errno;
58 #endif /* !errno */
59
60 /* The size that strings change by. */
61 #define DEFAULT_INITIAL_ARRAY_SIZE 112
62 #define DEFAULT_ARRAY_SIZE 128
63
64 /* Variable types. */
65 #define VT_VARIABLE     0
66 #define VT_POSPARMS     1
67 #define VT_ARRAYVAR     2
68 #define VT_ARRAYMEMBER  3
69
70 /* Flags for quoted_strchr */
71 #define ST_BACKSL       0x01
72 #define ST_CTLESC       0x02
73
74 /* These defs make it easier to use the editor. */
75 #define LBRACE          '{'
76 #define RBRACE          '}'
77 #define LPAREN          '('
78 #define RPAREN          ')'
79
80 /* Process ID of the last command executed within command substitution. */
81 pid_t last_command_subst_pid = NO_PID;
82
83 /* Extern functions and variables from different files. */
84 extern int last_command_exit_value, interactive, interactive_shell;
85 extern int subshell_environment, startup_state;
86 extern int dollar_dollar_pid;
87 extern int posixly_correct;
88 extern char *this_command_name;
89 extern struct fd_bitmap *current_fds_to_close;
90 extern int wordexp_only;
91
92 extern void getopts_reset ();
93
94 /* Non-zero means to allow unmatched globbed filenames to expand to
95    a null file. */
96 int allow_null_glob_expansion;
97
98 /* Variables to keep track of which words in an expanded word list (the
99    output of expand_word_list_internal) are the result of globbing
100    expansions.  GLOB_ARGV_FLAGS is used by execute_cmd.c. */
101 char *glob_argv_flags;
102 static int glob_argv_flags_size;
103
104 static WORD_LIST expand_word_error, expand_word_fatal;
105 static char expand_param_error, expand_param_fatal;
106
107 static char *make_quoted_char ();
108 static void remove_quoted_nulls ();
109 static char *param_expand ();
110 static char *maybe_expand_string ();
111 static WORD_LIST *call_expand_word_internal ();
112 static WORD_LIST *expand_string_internal ();
113 static WORD_LIST *expand_word_internal (), *expand_word_list_internal ();
114 static WORD_LIST *expand_string_leave_quoted ();
115 static WORD_LIST *expand_string_for_rhs ();
116 static WORD_LIST *word_list_split ();
117 static WORD_LIST *quote_list (), *dequote_list ();
118 static char *quote_escapes ();
119 static WORD_LIST *list_quote_escapes ();
120 static int unquoted_substring (), unquoted_member ();
121 static int do_assignment_internal ();
122 static char *string_extract_verbatim (), *string_extract ();
123 static char *string_extract_double_quoted (), *string_extract_single_quoted ();
124 static char *string_list_dollar_at (), *string_list_dollar_star ();
125 static inline int skip_single_quoted (), skip_double_quoted ();
126 static char *extract_delimited_string ();
127 static char *extract_dollar_brace_string ();
128
129 /* **************************************************************** */
130 /*                                                                  */
131 /*                      Utility Functions                           */
132 /*                                                                  */
133 /* **************************************************************** */
134
135 /* Cons a new string from STRING starting at START and ending at END,
136    not including END. */
137 char *
138 substring (string, start, end)
139      char *string;
140      int start, end;
141 {
142   register int len;
143   register char *result;
144
145   len = end - start;
146   result = xmalloc (len + 1);
147   strncpy (result, string + start, len);
148   result[len] = '\0';
149   return (result);
150 }
151
152 static char *
153 quoted_substring (string, start, end)
154      char *string;
155      int start, end;
156 {
157   register int len, l;
158   register char *result, *s, *r;
159
160   len = end - start;
161
162   /* Move to string[start], skipping quoted characters. */
163   for (s = string, l = 0; *s && l < start; )
164     {
165       if (*s == CTLESC)
166         {
167           s++;
168           continue;
169         }
170       l++;
171       if (*s == 0)
172         break;
173     }
174
175   r = result = xmalloc (2*len + 1);      /* save room for quotes */
176
177   /* Copy LEN characters, including quote characters. */
178   s = string + l;
179   for (l = 0; l < len; s++)
180     {
181       if (*s == CTLESC)
182         *r++ = *s++;
183       *r++ = *s;
184       l++;
185       if (*s == 0)
186         break;
187     }
188   *r = '\0';
189   return result;
190 }
191
192 /* Find the first occurrence of character C in string S, obeying shell
193    quoting rules.  If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
194    characters are skipped.  If (FLAGS & ST_CTLESC) is non-zero, characters
195    escaped with CTLESC are skipped. */
196 static inline char *
197 quoted_strchr (s, c, flags)
198      char *s;
199      int c, flags;
200 {
201   register char *p;
202
203   for (p = s; *p; p++)
204     {
205       if (((flags & ST_BACKSL) && *p == '\\')
206             || ((flags & ST_CTLESC) && *p == CTLESC))
207         {
208           p++;
209           if (*p == '\0')
210             return ((char *)NULL);
211           continue;
212         }
213       else if (*p == c)
214         return p;
215     }
216   return ((char *)NULL);
217 }
218
219 /* Return 1 if CHARACTER appears in an unquoted portion of
220    STRING.  Return 0 otherwise. */
221 static int
222 unquoted_member (character, string)
223      int character;
224      char *string;
225 {
226   int sindex, c;
227
228   for (sindex = 0; c = string[sindex]; )
229     {
230       if (c == character)
231         return (1);
232
233       switch (c)
234         {
235         default:
236           sindex++;
237           break;
238
239         case '\\':
240           sindex++;
241           if (string[sindex])
242             sindex++;
243           break;
244
245         case '\'':
246           sindex = skip_single_quoted (string, ++sindex);
247           break;
248
249         case '"':
250           sindex = skip_double_quoted (string, ++sindex);
251           break;
252         }
253     }
254   return (0);
255 }
256
257 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
258 static int
259 unquoted_substring (substr, string)
260      char *substr, *string;
261 {
262   int sindex, c, sublen;
263
264   if (substr == 0 || *substr == '\0')
265     return (0);
266
267   sublen = strlen (substr);
268   for (sindex = 0; c = string[sindex]; )
269     {
270       if (STREQN (string + sindex, substr, sublen))
271         return (1);
272
273       switch (c)
274         {
275         case '\\':
276           sindex++;
277
278           if (string[sindex])
279             sindex++;
280           break;
281
282         case '\'':
283           sindex = skip_single_quoted (string, ++sindex);
284           break;
285
286         case '"':
287           sindex = skip_double_quoted (string, ++sindex);
288           break;
289
290         default:
291           sindex++;
292           break;
293         }
294     }
295   return (0);
296 }
297
298 /* Most of the substitutions must be done in parallel.  In order
299    to avoid using tons of unclear goto's, I have some functions
300    for manipulating malloc'ed strings.  They all take INDX, a
301    pointer to an integer which is the offset into the string
302    where manipulation is taking place.  They also take SIZE, a
303    pointer to an integer which is the current length of the
304    character array for this string. */
305
306 /* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
307    of space allocated to TARGET.  SOURCE can be NULL, in which
308    case nothing happens.  Gets rid of SOURCE by freeing it.
309    Returns TARGET in case the location has changed. */
310 inline char *
311 sub_append_string (source, target, indx, size)
312      char *source, *target;
313      int *indx, *size;
314 {
315   if (source)
316     {
317       int srclen, n;
318
319       srclen = STRLEN (source);
320       if (srclen >= (int)(*size - *indx))
321         {
322           n = srclen + *indx;
323           n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
324           target = xrealloc (target, (*size = n));
325         }
326
327       FASTCOPY (source, target + *indx, srclen);
328       *indx += srclen;
329       target[*indx] = '\0';
330
331       free (source);
332     }
333   return (target);
334 }
335
336 #if 0
337 /* UNUSED */
338 /* Append the textual representation of NUMBER to TARGET.
339    INDX and SIZE are as in SUB_APPEND_STRING. */
340 char *
341 sub_append_number (number, target, indx, size)
342      int number, *indx, *size;
343      char *target;
344 {
345   char *temp;
346
347   temp = itos (number);
348   return (sub_append_string (temp, target, indx, size));
349 }
350 #endif
351
352 /* Extract a substring from STRING, starting at SINDEX and ending with
353    one of the characters in CHARLIST.  Don't make the ending character
354    part of the string.  Leave SINDEX pointing at the ending character.
355    Understand about backslashes in the string.  If VARNAME is non-zero,
356    and array variables have been compiled into the shell, everything
357    between a `[' and a corresponding `]' is skipped over. */
358 static char *
359 string_extract (string, sindex, charlist, varname)
360      char *string, *charlist;
361      int *sindex, varname;
362 {
363   register int c, i;
364   char *temp;
365
366   for (i = *sindex; c = string[i]; i++)
367     {
368       if (c == '\\')
369         if (string[i + 1])
370           i++;
371         else
372           break;
373 #if defined (ARRAY_VARS)
374       else if (varname && c == '[')
375         {
376           int ni;
377           /* If this is an array subscript, skip over it and continue. */
378           ni = skipsubscript (string, i);
379           if (string[ni] == ']')
380             i = ni;
381         }
382 #endif
383       else if (MEMBER (c, charlist))
384           break;
385     }
386   c = i - *sindex;
387   temp = xmalloc (1 + c);
388   strncpy (temp, string + *sindex, c);
389   temp[c] = '\0';
390   *sindex = i;
391   return (temp);
392 }
393
394 /* Extract the contents of STRING as if it is enclosed in double quotes.
395    SINDEX, when passed in, is the offset of the character immediately
396    following the opening double quote; on exit, SINDEX is left pointing after
397    the closing double quote.  If STRIPDQ is non-zero, unquoted double
398    quotes are stripped and the string is terminated by a null byte.
399    Backslashes between the embedded double quotes are processed.  If STRIPDQ
400    is zero, an unquoted `"' terminates the string. */
401 static inline char *
402 string_extract_double_quoted (string, sindex, stripdq)
403      char *string;
404      int *sindex, stripdq;
405 {
406   int c, j, i, t;
407   char *temp, *ret;             /* The new string we return. */
408   int pass_next, backquote, si; /* State variables for the machine. */
409   int dquote;
410
411   pass_next = backquote = dquote = 0;
412   temp = xmalloc (1 + strlen (string) - *sindex);
413
414   for (j = 0, i = *sindex; c = string[i]; i++)
415     {
416       /* Process a character that was quoted by a backslash. */
417       if (pass_next)
418         {
419           /* Posix.2 sez:
420
421              ``The backslash shall retain its special meaning as an escape
422              character only when followed by one of the characters:
423                 $       `       "       \       <newline>''.
424
425              If STRIPDQ is zero, we handle the double quotes here and let
426              expand_word_internal handle the rest.  If STRIPDQ is non-zero,
427              we have already been through one round of backslash stripping,
428              and want to strip these backslashes only if DQUOTE is non-zero,
429              indicating that we are inside an embedded double-quoted string. */
430
431              /* If we are in an embedded quoted string, then don't strip
432                 backslashes before characters for which the backslash
433                 retains its special meaning, but remove backslashes in
434                 front of other characters.  If we are not in an
435                 embedded quoted string, don't strip backslashes at all.
436                 This mess is necessary because the string was already
437                 surrounded by double quotes (and sh has some really weird
438                 quoting rules).
439                 The returned string will be run through expansion as if
440                 it were double-quoted. */
441           if ((stripdq == 0 && c != '"') ||
442               (stripdq && ((dquote && strchr (slashify_in_quotes, c)) || dquote == 0)))
443             temp[j++] = '\\';
444           temp[j++] = c;
445           pass_next = 0;
446           continue;
447         }
448
449       /* A backslash protects the next character.  The code just above
450          handles preserving the backslash in front of any character but
451          a double quote. */
452       if (c == '\\')
453         {
454           pass_next++;
455           continue;
456         }
457
458       /* Inside backquotes, ``the portion of the quoted string from the
459          initial backquote and the characters up to the next backquote
460          that is not preceded by a backslash, having escape characters
461          removed, defines that command''. */
462       if (backquote)
463         {
464           if (c == '`')
465             backquote = 0;
466           temp[j++] = c;
467           continue;
468         }
469
470       if (c == '`')
471         {
472           temp[j++] = c;
473           backquote++;
474           continue;
475         }
476
477       /* Pass everything between `$(' and the matching `)' or a quoted
478          ${ ... } pair through according to the Posix.2 specification. */
479       if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
480         {
481           si = i + 2;
482           if (string[i + 1] == LPAREN)
483             ret = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
484           else
485             ret = extract_dollar_brace_string (string, &si, 1);
486
487           temp[j++] = '$';
488           temp[j++] = string[i + 1];
489
490           for (t = 0; ret[t]; t++, j++)
491             temp[j] = ret[t];
492           temp[j++] = string[si];
493
494           i = si;
495           free (ret);
496           continue;
497         }
498
499       /* Add any character but a double quote to the quoted string we're
500          accumulating. */
501       if (c != '"')
502         {
503           temp[j++] = c;
504           continue;
505         }
506
507       /* c == '"' */
508       if (stripdq)
509         {
510           dquote ^= 1;
511           continue;
512         }
513
514       break;
515     }
516   temp[j] = '\0';
517
518   /* Point to after the closing quote. */
519   if (c)
520     i++;
521   *sindex = i;
522
523   return (temp);
524 }
525
526 /* This should really be another option to string_extract_double_quoted. */
527 static inline int
528 skip_double_quoted (string, sind)
529      char *string;
530      int sind;
531 {
532   int c, j, i;
533   char *ret;
534   int pass_next, backquote, si;
535
536   pass_next = backquote = 0;
537
538   for (j = 0, i = sind; c = string[i]; i++)
539     {
540       if (pass_next)
541         {
542           pass_next = 0;
543           continue;
544         }
545       else if (c == '\\')
546         {
547           pass_next++;
548           continue;
549         }
550       else if (backquote)
551         {
552           if (c == '`')
553             backquote = 0;
554           continue;
555         }
556       else if (c == '`')
557         {
558           backquote++;
559           continue;
560         }
561       else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
562         {
563           si = i + 2;
564           if (string[i + 1] == LPAREN)
565             ret = extract_delimited_string (string, &si, "$(", "(", ")");
566           else
567             ret = extract_dollar_brace_string (string, &si, 0);
568
569           i = si;
570           free (ret);
571           continue;
572         }
573       else if (c != '"')
574         continue;
575       else
576         break;
577     }
578
579   if (c)
580     i++;
581
582   return (i);
583 }
584
585 /* Extract the contents of STRING as if it is enclosed in single quotes.
586    SINDEX, when passed in, is the offset of the character immediately
587    following the opening single quote; on exit, SINDEX is left pointing after
588    the closing single quote. */
589 static inline char *
590 string_extract_single_quoted (string, sindex)
591      char *string;
592      int *sindex;
593 {
594   register int i, j;
595   char *t;
596
597   for (i = *sindex; string[i] && string[i] != '\''; i++)
598     ;
599
600   j = i - *sindex;
601   t = xmalloc (1 + j);
602   strncpy (t, string + *sindex, j);
603   t[j] = '\0';
604
605   if (string[i])
606     i++;
607   *sindex = i;
608
609   return (t);
610 }
611
612 static inline int
613 skip_single_quoted (string, sind)
614      char *string;
615      int sind;
616 {
617   register int i;
618
619   for (i = sind; string[i] && string[i] != '\''; i++)
620     ;
621   if (string[i])
622     i++;
623   return i;
624 }
625
626 /* Just like string_extract, but doesn't hack backslashes or any of
627    that other stuff.  Obeys quoting.  Used to do splitting on $IFS. */
628 static char *
629 string_extract_verbatim (string, sindex, charlist)
630      char *string, *charlist;
631      int *sindex;
632 {
633   register int i = *sindex;
634   int c;
635   char *temp;
636
637   if (charlist[0] == '\'' && charlist[1] == '\0')
638     {
639       temp = string_extract_single_quoted (string, sindex);
640       --*sindex;        /* leave *sindex at separator character */
641       return temp;
642     }
643
644   for (i = *sindex; c = string[i]; i++)
645     {
646       if (c == CTLESC)
647         {
648           i++;
649           continue;
650         }
651
652       if (MEMBER (c, charlist))
653         break;
654     }
655
656   c = i - *sindex;
657   temp = xmalloc (1 + c);
658   strncpy (temp, string + *sindex, c);
659   temp[c] = '\0';
660   *sindex = i;
661
662   return (temp);
663 }
664
665 /* Extract the $( construct in STRING, and return a new string.
666    Start extracting at (SINDEX) as if we had just seen "$(".
667    Make (SINDEX) get the position of the matching ")". */
668 char *
669 extract_command_subst (string, sindex)
670      char *string;
671      int *sindex;
672 {
673   return (extract_delimited_string (string, sindex, "$(", "(", ")"));
674 }
675
676 /* Extract the $[ construct in STRING, and return a new string.
677    Start extracting at (SINDEX) as if we had just seen "$[".
678    Make (SINDEX) get the position of the matching "]". */
679 char *
680 extract_arithmetic_subst (string, sindex)
681      char *string;
682      int *sindex;
683 {
684   return (extract_delimited_string (string, sindex, "$[", "[", "]"));
685 }
686
687 #if defined (PROCESS_SUBSTITUTION)
688 /* Extract the <( or >( construct in STRING, and return a new string.
689    Start extracting at (SINDEX) as if we had just seen "<(".
690    Make (SINDEX) get the position of the matching ")". */ /*))*/
691 char *
692 extract_process_subst (string, starter, sindex)
693      char *string;
694      char *starter;
695      int *sindex;
696 {
697   return (extract_delimited_string (string, sindex, starter, "(", ")"));
698 }
699 #endif /* PROCESS_SUBSTITUTION */
700
701 #if defined (ARRAY_VARS)
702 char *
703 extract_array_assignment_list (string, sindex)
704      char *string;
705      int *sindex;
706 {
707   return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")"));
708 }
709 #endif
710
711 /* Extract and create a new string from the contents of STRING, a
712    character string delimited with OPENER and CLOSER.  SINDEX is
713    the address of an int describing the current offset in STRING;
714    it should point to just after the first OPENER found.  On exit,
715    SINDEX gets the position of the last character of the matching CLOSER.
716    If OPENER is more than a single character, ALT_OPENER, if non-null,
717    contains a character string that can also match CLOSER and thus
718    needs to be skipped. */
719 static char *
720 extract_delimited_string (string, sindex, opener, alt_opener, closer)
721      char *string;
722      int *sindex;
723      char *opener, *alt_opener, *closer;
724 {
725   int i, c, si;
726   char *t, *result;
727   int pass_character, nesting_level;
728   int len_closer, len_opener, len_alt_opener;
729
730   len_opener = STRLEN (opener);
731   len_alt_opener = STRLEN (alt_opener);
732   len_closer = STRLEN (closer);
733
734   pass_character = 0;
735
736   nesting_level = 1;
737   i = *sindex;
738
739   while (nesting_level)
740     {
741       c = string[i];
742
743       if (c == 0)
744         break;
745
746       if (pass_character)       /* previous char was backslash */
747         {
748           pass_character = 0;
749           i++;
750           continue;
751         }
752
753       if (c == CTLESC)
754         {
755           pass_character++;
756           i++;
757           continue;
758         }
759
760 #if 0
761       if (c == '\\' && delimiter == '"' &&
762               (member (string[i], slashify_in_quotes)))
763 #else
764       if (c == '\\')
765 #endif
766         {
767           pass_character++;
768           i++;
769           continue;
770         }
771
772       /* Process a nested OPENER. */
773       if (STREQN (string + i, opener, len_opener))
774         {
775           si = i + len_opener;
776           t = extract_delimited_string (string, &si, opener, alt_opener, closer);
777           i = si + 1;
778           FREE (t);
779           continue;
780         }
781
782       /* Process a nested ALT_OPENER */
783       if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
784         {
785           si = i + len_alt_opener;
786           t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer);
787           i = si + 1;
788           FREE (t);
789           continue;
790         }
791
792       /* If the current substring terminates the delimited string, decrement
793          the nesting level. */
794       if (STREQN (string + i, closer, len_closer))
795         {
796           i += len_closer - 1;  /* move to last char of the closer */
797           nesting_level--;
798           if (nesting_level == 0)
799             break;
800         }
801
802       /* Pass old-style command substitution through verbatim. */
803       if (c == '`')
804         {
805           si = i + 1;
806           t = string_extract (string, &si, "`", 0);
807           i = si + 1;
808           FREE (t);
809           continue;
810         }
811
812       /* Pass single-quoted strings through verbatim. */
813       if (c == '\'')
814         {
815           si = i + 1;
816           i = skip_single_quoted (string, si);
817           continue;
818         }
819
820       /* Pass embedded double-quoted strings through verbatim as well. */
821       if (c == '"')
822         {
823           si = i + 1;
824           i = skip_double_quoted (string, si);
825           continue;
826         }
827
828       i++;      /* move past this character, which was not special. */
829     }
830
831   if (c == 0 && nesting_level)
832     {
833       report_error ("bad substitution: no `%s' in %s", closer, string);
834       jump_to_top_level (DISCARD);
835     }
836
837   si = i - *sindex - len_closer + 1;
838   result = xmalloc (1 + si);
839   strncpy (result, string + *sindex, si);
840   result[si] = '\0';
841   *sindex = i;
842
843   return (result);
844 }
845
846 /* Extract a parameter expansion expression within ${ and } from STRING.
847    Obey the Posix.2 rules for finding the ending `}': count braces while
848    skipping over enclosed quoted strings and command substitutions.
849    SINDEX is the address of an int describing the current offset in STRING;
850    it should point to just after the first `{' found.  On exit, SINDEX
851    gets the position of the matching `}'.  QUOTED is non-zero if this
852    occurs inside double quotes. */
853 /* XXX -- this is very similar to extract_delimited_string -- XXX */
854 static char *
855 extract_dollar_brace_string (string, sindex, quoted)
856      char *string;
857      int *sindex, quoted;
858 {
859   register int i, c, l;
860   int pass_character, nesting_level, si;
861   char *result, *t;
862
863   pass_character = 0;
864
865   nesting_level = 1;
866
867   for (i = *sindex; (c = string[i]); i++)
868     {
869       if (pass_character)
870         {
871           pass_character = 0;
872           continue;
873         }
874
875       /* CTLESCs and backslashes quote the next character. */
876       if (c == CTLESC || c == '\\')
877         {
878           pass_character++;
879           continue;
880         }
881
882       if (string[i] == '$' && string[i+1] == LBRACE)
883         {
884           nesting_level++;
885           i++;
886           continue;
887         }
888
889       if (c == RBRACE)
890         {
891           nesting_level--;
892           if (nesting_level == 0)
893             break;
894           continue;
895         }
896
897       /* Pass the contents of old-style command substitutions through
898          verbatim. */
899       if (c == '`')
900         {
901           si = i + 1;
902           t = string_extract (string, &si, "`", 0);
903           i = si;
904           free (t);
905           continue;
906         }
907
908       /* Pass the contents of new-style command substitutions and
909          arithmetic substitutions through verbatim. */
910       if (string[i] == '$' && string[i+1] == LPAREN)
911         {
912           si = i + 2;
913           t = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
914           i = si;
915           free (t);
916           continue;
917         }
918
919       /* Pass the contents of single-quoted and double-quoted strings
920          through verbatim. */
921       if (c == '\'' || c == '"')
922         {
923           si = i + 1;
924           i = (c == '\'') ? skip_single_quoted (string, si)
925                           : skip_double_quoted (string, si);
926           /* skip_XXX_quoted leaves index one past close quote */
927           i--;
928           continue;
929         }
930     }
931
932   if (c == 0 && nesting_level)
933     {
934       report_error ("bad substitution: no ending `}' in %s", string);
935       jump_to_top_level (DISCARD);
936     }
937
938   l = i - *sindex;
939   result = xmalloc (1 + l);
940   strncpy (result, string + *sindex, l);
941   result[l] = '\0';
942   *sindex = i;
943
944   return (result);
945 }
946
947 /* Remove backslashes which are quoting backquotes from STRING.  Modifies
948    STRING, and returns a pointer to it. */
949 char *
950 de_backslash (string)
951      char *string;
952 {
953   register int i, l;
954
955   for (i = 0, l = strlen (string); i < l; i++)
956     if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
957                               string[i + 1] == '$'))
958       strcpy (string + i, string + i + 1);      /* XXX - should be memmove */
959   return (string);
960 }
961
962 #if 0
963 /*UNUSED*/
964 /* Replace instances of \! in a string with !. */
965 void
966 unquote_bang (string)
967      char *string;
968 {
969   register int i, j;
970   register char *temp;
971
972   temp = xmalloc (1 + strlen (string));
973
974   for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
975     {
976       if (string[i] == '\\' && string[i + 1] == '!')
977         {
978           temp[j] = '!';
979           i++;
980         }
981     }
982   strcpy (string, temp);
983   free (temp);
984 }
985 #endif
986
987 #if defined (READLINE)
988 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
989    an unclosed quoted string), or if the character at EINDEX is quoted
990    by a backslash. */
991 int
992 char_is_quoted (string, eindex)
993      char *string;
994      int eindex;
995 {
996   int i, pass_next, quoted;
997
998   for (i = pass_next = quoted = 0; i <= eindex; i++)
999     {
1000       if (pass_next)
1001         {
1002           pass_next = 0;
1003           if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
1004             return 1;
1005           continue;
1006         }
1007       else if (string[i] == '\'' || string[i] == '"')
1008         {
1009           i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
1010                                   : skip_double_quoted (string, ++i);
1011           if (i > eindex)
1012             return 1;
1013           i--;  /* the skip functions increment past the closing quote. */
1014         }
1015       else if (string[i] == '\\')
1016         {
1017           pass_next = 1;
1018           continue;
1019         }
1020     }
1021   return (0);
1022 }
1023
1024 int
1025 unclosed_pair (string, eindex, openstr)
1026      char *string;
1027      int eindex;
1028      char *openstr;
1029 {
1030   int i, pass_next, openc, olen;
1031
1032   olen = strlen (openstr);
1033   for (i = pass_next = openc = 0; i <= eindex; i++)
1034     {
1035       if (pass_next)
1036         {
1037           pass_next = 0;
1038           if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
1039             return 0;
1040           continue;
1041         }
1042       else if (STREQN (string + i, openstr, olen))
1043         {
1044           openc = 1 - openc;
1045           i += olen - 1;
1046         }
1047       else if (string[i] == '\'' || string[i] == '"')
1048         {
1049           i = (string[i] == '\'') ? skip_single_quoted (string, i)
1050                                   : skip_double_quoted (string, i);
1051           if (i > eindex)
1052             return 0;
1053         }
1054       else if (string[i] == '\\')
1055         {
1056           pass_next = 1;
1057           continue;
1058         }
1059     }
1060   return (openc);
1061 }
1062 #endif /* READLINE */
1063
1064 #if 0
1065 /* UNUSED */
1066 /* Extract the name of the variable to bind to from the assignment string. */
1067 char *
1068 assignment_name (string)
1069      char *string;
1070 {
1071   int offset;
1072   char *temp;
1073
1074   offset = assignment (string);
1075   if (offset == 0)
1076     return (char *)NULL;
1077   temp = xmalloc (offset + 1);
1078   strncpy (temp, string, offset);
1079   temp[offset] = '\0';
1080   return (temp);
1081 }
1082 #endif
1083
1084 /* **************************************************************** */
1085 /*                                                                  */
1086 /*     Functions to convert strings to WORD_LISTs and vice versa    */
1087 /*                                                                  */
1088 /* **************************************************************** */
1089
1090 /* Return a single string of all the words in LIST.  SEP is the separator
1091    to put between individual elements of LIST in the output string. */
1092 static char *
1093 string_list_internal (list, sep)
1094      WORD_LIST *list;
1095      char *sep;
1096 {
1097   register WORD_LIST *t;
1098   char *result, *r;
1099   int word_len, sep_len, result_size;
1100
1101   if (list == 0)
1102     return ((char *)NULL);
1103
1104   /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1105   sep_len = STRLEN (sep);
1106   result_size = 0;
1107
1108   for (t = list; t; t = t->next)
1109     {
1110       if (t != list)
1111         result_size += sep_len;
1112       result_size += strlen (t->word->word);
1113     }
1114
1115   r = result = xmalloc (result_size + 1);
1116
1117   for (t = list; t; t = t->next)
1118     {
1119       if (t != list && sep_len)
1120         {
1121           if (sep_len > 1)
1122             {
1123               FASTCOPY (sep, r, sep_len);
1124               r += sep_len;
1125             }
1126           else
1127             *r++ = sep[0];
1128         }
1129
1130       word_len = strlen (t->word->word);
1131       FASTCOPY (t->word->word, r, word_len);
1132       r += word_len;
1133     }
1134
1135   *r = '\0';
1136   return (result);
1137 }
1138
1139 /* Return a single string of all the words present in LIST, separating
1140    each word with a space. */
1141 char *
1142 string_list (list)
1143      WORD_LIST *list;
1144 {
1145   return (string_list_internal (list, " "));
1146 }
1147
1148 /* Return a single string of all the words present in LIST, obeying the
1149    quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1150    expansion [of $*] appears within a double quoted string, it expands
1151    to a single field with the value of each parameter separated by the
1152    first character of the IFS variable, or by a <space> if IFS is unset." */
1153 static char *
1154 string_list_dollar_star (list)
1155      WORD_LIST *list;
1156 {
1157   char *ifs, sep[2];
1158
1159   ifs = get_string_value ("IFS");
1160
1161   sep[0] = (ifs == 0) ? ' ' : *ifs;
1162   sep[1] = '\0';
1163
1164   return (string_list_internal (list, sep));
1165 }
1166
1167 /* Turn $@ into a string.  If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1168    is non-zero, the $@ appears within double quotes, and we should quote
1169    the list before converting it into a string.  If IFS is unset, and the
1170    word is not quoted, we just need to quote CTLESC and CTLNUL characters
1171    in the words in the list, because the default value of $IFS is
1172    <space><tab><newline>, IFS characters in the words in the list should
1173    also be split.  If IFS is null, and the word is not quoted, we need
1174    to quote the words in the list to preserve the positional parameters
1175    exactly. */
1176 static char *
1177 string_list_dollar_at (list, quoted)
1178      WORD_LIST *list;
1179      int quoted;
1180 {
1181   char *ifs, sep[2];
1182   WORD_LIST *tlist;
1183
1184   ifs = get_string_value ("IFS");
1185
1186   sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1187   sep[1] = '\0';
1188
1189   tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1190                 ? quote_list (list)
1191                 : list_quote_escapes (list);
1192   return (string_list_internal (tlist, sep));
1193 }
1194
1195 /* Return the list of words present in STRING.  Separate the string into
1196    words at any of the characters found in SEPARATORS.  If QUOTED is
1197    non-zero then word in the list will have its quoted flag set, otherwise
1198    the quoted flag is left as make_word () deemed fit.
1199
1200    This obeys the P1003.2 word splitting semantics.  If `separators' is
1201    exactly <space><tab><newline>, then the splitting algorithm is that of
1202    the Bourne shell, which treats any sequence of characters from `separators'
1203    as a delimiter.  If IFS is unset, which results in `separators' being set
1204    to "", no splitting occurs.  If separators has some other value, the
1205    following rules are applied (`IFS white space' means zero or more
1206    occurrences of <space>, <tab>, or <newline>, as long as those characters
1207    are in `separators'):
1208
1209         1) IFS white space is ignored at the start and the end of the
1210            string.
1211         2) Each occurrence of a character in `separators' that is not
1212            IFS white space, along with any adjacent occurrences of
1213            IFS white space delimits a field.
1214         3) Any nonzero-length sequence of IFS white space delimits a field.
1215    */
1216
1217 /* BEWARE!  list_string strips null arguments.  Don't call it twice and
1218    expect to have "" preserved! */
1219
1220 /* This performs word splitting and quoted null character removal on
1221    STRING. */
1222 #define issep(c)        (member ((c), separators))
1223
1224 WORD_LIST *
1225 list_string (string, separators, quoted)
1226      register char *string, *separators;
1227      int quoted;
1228 {
1229   WORD_LIST *result;
1230   WORD_DESC *t;
1231   char *current_word, *s;
1232   int sindex, sh_style_split;
1233
1234   if (!string || !*string)
1235     return ((WORD_LIST *)NULL);
1236
1237   sh_style_split =
1238     separators && *separators && (STREQ (separators, " \t\n"));
1239
1240   /* Remove sequences of whitespace at the beginning of STRING, as
1241      long as those characters appear in IFS.  Do not do this if
1242      STRING is quoted or if there are no separator characters. */
1243   if (!quoted || !separators || !*separators)
1244     {
1245       for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1246
1247       if (!*s)
1248         return ((WORD_LIST *)NULL);
1249
1250       string = s;
1251     }
1252
1253   /* OK, now STRING points to a word that does not begin with white space.
1254      The splitting algorithm is:
1255         extract a word, stopping at a separator
1256         skip sequences of spc, tab, or nl as long as they are separators
1257      This obeys the field splitting rules in Posix.2. */
1258   for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1259     {
1260       current_word = string_extract_verbatim (string, &sindex, separators);
1261       if (current_word == 0)
1262         break;
1263
1264       /* If we have a quoted empty string, add a quoted null argument.  We
1265          want to preserve the quoted null character iff this is a quoted
1266          empty string; otherwise the quoted null characters are removed
1267          below. */
1268       if (QUOTED_NULL (current_word))
1269         {
1270           t = make_bare_word ("");
1271           t->flags |= W_QUOTED;
1272           free (t->word);
1273           t->word = make_quoted_char ('\0');
1274           result = make_word_list (t, result);
1275         }
1276       else if (current_word[0] != '\0')
1277         {
1278           /* If we have something, then add it regardless.  However,
1279              perform quoted null character removal on the current word. */
1280           remove_quoted_nulls (current_word);
1281 #if 0
1282           result = make_word_list (make_word (current_word), result);
1283 #else
1284           result = add_string_to_list (current_word, result);
1285 #endif    
1286           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1287             result->word->flags |= W_QUOTED;
1288         }
1289
1290       /* If we're not doing sequences of separators in the traditional
1291          Bourne shell style, then add a quoted null argument. */
1292       else if (!sh_style_split && !spctabnl (string[sindex]))
1293         {
1294           t = make_bare_word ("");
1295           t->flags |= W_QUOTED;
1296           free (t->word);
1297           t->word = make_quoted_char ('\0');
1298           result = make_word_list (t, result);
1299         }
1300
1301       free (current_word);
1302
1303       /* Move past the current separator character. */
1304       if (string[sindex])
1305         sindex++;
1306
1307       /* Now skip sequences of space, tab, or newline characters if they are
1308          in the list of separators. */
1309       while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1310         sindex++;
1311     }
1312   return (REVERSE_LIST (result, WORD_LIST *));
1313 }
1314
1315 /* Parse a single word from STRING, using SEPARATORS to separate fields.
1316    ENDPTR is set to the first character after the word.  This is used by
1317    the `read' builtin.
1318    XXX - this function is very similar to list_string; they should be
1319          combined - XXX */
1320 char *
1321 get_word_from_string (stringp, separators, endptr)
1322      char **stringp, *separators, **endptr;
1323 {
1324   register char *s;
1325   char *current_word;
1326   int sindex, sh_style_split;
1327
1328   if (!stringp || !*stringp || !**stringp)
1329     return ((char *)NULL);
1330
1331   s = *stringp;
1332
1333   sh_style_split =
1334     separators && *separators && (STREQ (separators, " \t\n"));
1335
1336   /* Remove sequences of whitespace at the beginning of STRING, as
1337      long as those characters appear in IFS. */
1338   if (sh_style_split || !separators || !*separators)
1339     {
1340       for (; *s && spctabnl (*s) && issep (*s); s++);
1341
1342       /* If the string is nothing but whitespace, update it and return. */
1343       if (!*s)
1344         {
1345           *stringp = s;
1346           if (endptr)
1347             *endptr = s;
1348           return ((char *)NULL);
1349         }
1350     }
1351
1352   /* OK, S points to a word that does not begin with white space.
1353      Now extract a word, stopping at a separator, save a pointer to
1354      the first character after the word, then skip sequences of spc,
1355      tab, or nl as long as they are separators.
1356
1357      This obeys the field splitting rules in Posix.2. */
1358   sindex = 0;
1359   current_word = string_extract_verbatim (s, &sindex, separators);
1360
1361   /* Set ENDPTR to the first character after the end of the word. */
1362   if (endptr)
1363     *endptr = s + sindex;
1364
1365   /* Move past the current separator character. */
1366   if (s[sindex])
1367     sindex++;
1368
1369   /* Now skip sequences of space, tab, or newline characters if they are
1370      in the list of separators. */
1371   while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1372     sindex++;
1373
1374   /* Update STRING to point to the next field. */
1375   *stringp = s + sindex;
1376   return (current_word);
1377 }
1378
1379 /* Remove IFS white space at the end of STRING.  Start at the end
1380    of the string and walk backwards until the beginning of the string
1381    or we find a character that's not IFS white space and not CTLESC.
1382    Only let CTLESC escape a white space character if SAW_ESCAPE is
1383    non-zero.  */
1384 char *
1385 strip_trailing_ifs_whitespace (string, separators, saw_escape)
1386      char *string, *separators;
1387      int saw_escape;
1388 {
1389   char *s;
1390
1391   s = string + STRLEN (string) - 1;
1392   while (s > string && ((spctabnl (*s) && issep (*s)) ||
1393                         (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1394     s--;
1395   *++s = '\0';
1396   return string;
1397 }
1398
1399 #if defined (ARRAY_VARS)
1400 WORD_LIST *
1401 list_string_with_quotes (string)
1402      char *string;
1403 {
1404   WORD_LIST *list;
1405   char *token, *s;
1406   int c, i, tokstart, len;
1407
1408   for (s = string; s && *s && spctabnl (*s); s++)
1409     ;
1410   if (s == 0 || *s == 0)
1411     return ((WORD_LIST *)NULL);
1412
1413   tokstart = i = 0;
1414   list = (WORD_LIST *)NULL;
1415   while (1)
1416     {
1417       c = s[i];
1418       if (c == '\\')
1419         {
1420           i++;
1421           if (s[i])
1422             i++;
1423         }
1424       else if (c == '\'')
1425         i = skip_single_quoted (s, ++i);
1426       else if (c == '"')
1427         i = skip_double_quoted (s, ++i);
1428       else if (c == 0 || spctabnl (c))
1429         {
1430           /* We have found the end of a token.  Make a word out of it and
1431              add it to the word list. */
1432           len = i - tokstart;
1433           token = xmalloc (len + 1);
1434           strncpy (token, s + tokstart, len);
1435           token[len] = '\0';
1436 #if 0
1437           list = make_word_list (make_word (token), list);
1438 #else
1439           list = add_string_to_list (token, list);
1440 #endif
1441           free (token);
1442           while (spctabnl (s[i]))
1443             i++;
1444           if (s[i])
1445             tokstart = i;
1446           else
1447             break;
1448         }
1449       else
1450         i++;    /* normal character */
1451     }
1452   return (REVERSE_LIST (list, WORD_LIST *));
1453 }
1454 #endif /* ARRAY_VARS */
1455
1456 /********************************************************/
1457 /*                                                      */
1458 /*      Functions to perform assignment statements      */
1459 /*                                                      */
1460 /********************************************************/
1461
1462 #if defined (ARRAY_VARS)
1463 SHELL_VAR *
1464 do_array_element_assignment (name, value)
1465      char *name, *value;
1466 {
1467   char *t;
1468   int ind, ni;
1469   SHELL_VAR *entry;
1470
1471   t = strchr (name, '[');
1472   if (t == 0)
1473     return ((SHELL_VAR *)NULL);
1474   ind = t - name;
1475   ni = skipsubscript (name, ind);
1476   if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= ind + 1))
1477     {
1478       report_error ("%s: bad array subscript", name);
1479       return ((SHELL_VAR *)NULL);
1480     }
1481   *t++ = '\0';
1482   ind = array_expand_index (t, ni - ind);
1483   if (ind < 0)
1484     {
1485       t[-1] = '[';              /* restore original name */
1486       report_error ("%s: bad array subscript", name);
1487       return ((SHELL_VAR *)NULL);
1488     }
1489   entry = bind_array_variable (name, ind, value);
1490   t[-1] = '[';          /* restore original name */
1491   return (entry);
1492 }
1493 #endif /* ARRAY_VARS */
1494
1495 /* Given STRING, an assignment string, get the value of the right side
1496    of the `=', and bind it to the left side.  If EXPAND is true, then
1497    perform parameter expansion, command substitution, and arithmetic
1498    expansion on the right-hand side.  Perform tilde expansion in any
1499    case.  Do not perform word splitting on the result of expansion. */
1500 static int
1501 do_assignment_internal (string, expand)
1502      char *string;
1503      int expand;
1504 {
1505   int offset;
1506   char *name, *value;
1507   SHELL_VAR *entry;
1508 #if defined (ARRAY_VARS)
1509   char *t;
1510   int ni, assign_list = 0;
1511 #endif
1512
1513   offset = assignment (string);
1514   name = savestring (string);
1515   value = (char *)NULL;
1516
1517   if (name[offset] == '=')
1518     {
1519       char *temp;
1520
1521       name[offset] = 0;
1522       temp = name + offset + 1;
1523
1524 #if defined (ARRAY_VARS)
1525       if (expand && temp[0] == LPAREN && strchr (temp, RPAREN))
1526         {
1527           assign_list = ni = 1;
1528           value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")");
1529         }
1530       else
1531 #endif
1532
1533       /* Perform tilde expansion. */
1534       if (expand && temp[0])
1535         {
1536           temp = (strchr (temp, '~') && unquoted_member ('~', temp))
1537                         ? bash_tilde_expand (temp)
1538                         : savestring (temp);
1539
1540           value = maybe_expand_string (temp, 0, expand_string_unsplit);
1541           free (temp);
1542         }
1543       else
1544         value = savestring (temp);
1545     }
1546
1547   if (value == 0)
1548     {
1549       value = xmalloc (1);
1550       value[0] = '\0';
1551     }
1552
1553   if (echo_command_at_execute)
1554 #if defined (ARRAY_VARS)
1555     if (assign_list)
1556       fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
1557     else
1558 #endif
1559     fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1560
1561 #define ASSIGN_RETURN(r)        do { FREE (value); free (name); return (r); } while (0)
1562
1563 #if defined (ARRAY_VARS)
1564   if (t = strchr (name, '['))
1565     {
1566       if (assign_list)
1567         {
1568           report_error ("%s: cannot assign list to array member", name);
1569           ASSIGN_RETURN (0);
1570         }
1571       entry = do_array_element_assignment (name, value);
1572       if (entry == 0)
1573         ASSIGN_RETURN (0);
1574     }
1575   else if (assign_list)
1576     entry = assign_array_from_string (name, value);
1577   else
1578 #endif /* ARRAY_VARS */
1579   entry = bind_variable (name, value);
1580
1581   stupidly_hack_special_variables (name);
1582
1583   if (entry)
1584     entry->attributes &= ~att_invisible;
1585
1586   /* Return 1 if the assignment seems to have been performed correctly. */
1587   ASSIGN_RETURN (entry ? ((entry->attributes & att_readonly) == 0) : 0);
1588 }
1589
1590 /* Perform the assignment statement in STRING, and expand the
1591    right side by doing command and parameter expansion. */
1592 int
1593 do_assignment (string)
1594      char *string;
1595 {
1596   return do_assignment_internal (string, 1);
1597 }
1598
1599 /* Given STRING, an assignment string, get the value of the right side
1600    of the `=', and bind it to the left side.  Do not do command and
1601    parameter substitution on the right hand side. */
1602 int
1603 do_assignment_no_expand (string)
1604      char *string;
1605 {
1606   return do_assignment_internal (string, 0);
1607 }
1608
1609 /***************************************************
1610  *                                                 *
1611  *  Functions to manage the positional parameters  *
1612  *                                                 *
1613  ***************************************************/
1614
1615 /* Return the word list that corresponds to `$*'. */
1616 WORD_LIST *
1617 list_rest_of_args ()
1618 {
1619   register WORD_LIST *list, *args;
1620   int i;
1621
1622   /* Break out of the loop as soon as one of the dollar variables is null. */
1623   for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
1624     list = make_word_list (make_bare_word (dollar_vars[i]), list);
1625
1626   for (args = rest_of_args; args; args = args->next)
1627     list = make_word_list (make_bare_word (args->word->word), list);
1628
1629   return (REVERSE_LIST (list, WORD_LIST *));
1630 }
1631
1632 int
1633 number_of_args ()
1634 {
1635   register WORD_LIST *list;
1636   int n;
1637
1638   for (n = 0; n < 9 && dollar_vars[n+1]; n++)
1639     ;
1640   for (list = rest_of_args; list; list = list->next)
1641     n++;
1642   return n;
1643 }
1644
1645 /* Return the value of a positional parameter.  This handles values > 10. */
1646 char *
1647 get_dollar_var_value (ind)
1648      int ind;
1649 {
1650   char *temp;
1651   WORD_LIST *p;
1652
1653   if (ind < 10)
1654     temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
1655   else  /* We want something like ${11} */
1656     {
1657       ind -= 10;
1658       for (p = rest_of_args; p && ind--; p = p->next)
1659         ;
1660       temp = p ? savestring (p->word->word) : (char *)NULL;
1661     }
1662   return (temp);
1663 }
1664
1665 /* Make a single large string out of the dollar digit variables,
1666    and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
1667    case of "$*" with respect to IFS. */
1668 char *
1669 string_rest_of_args (dollar_star)
1670      int dollar_star;
1671 {
1672   register WORD_LIST *list;
1673   char *string;
1674
1675   list = list_rest_of_args ();
1676   string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1677   dispose_words (list);
1678   return (string);
1679 }
1680
1681 /* Return a string containing the positional parameters from START to
1682    END, inclusive.  If STRING[0] == '*', we obey the rules for $*,
1683    which only makes a difference if QUOTED is non-zero. */
1684 static char *
1685 pos_params (string, start, end, quoted)
1686      char *string;
1687      int start, end, quoted;
1688 {
1689   WORD_LIST *save, *params, *h, *t;
1690   char *ret;
1691   int i;
1692
1693   save = params = list_rest_of_args ();
1694   if (save == 0)
1695     return ((char *)NULL);
1696
1697   for (i = 1; params && i < start; i++)
1698     params = params->next;
1699   if (params == 0)
1700     return ((char *)NULL);
1701   for (h = t = params; params && i < end; i++)
1702     {
1703       t = params;
1704       params = params->next;
1705     }
1706
1707   t->next = (WORD_LIST *)NULL;
1708   if (string[0] == '*')
1709     ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h);
1710   else
1711     ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
1712   t->next = params;
1713
1714   dispose_words (save);
1715   return (ret);
1716 }
1717
1718 /******************************************************************/
1719 /*                                                                */
1720 /*      Functions to expand strings to strings or WORD_LISTs      */
1721 /*                                                                */
1722 /******************************************************************/
1723
1724 #if defined (PROCESS_SUBSTITUTION)
1725 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1726 #else
1727 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1728 #endif
1729
1730 /* If there are any characters in STRING that require full expansion,
1731    then call FUNC to expand STRING; otherwise just perform quote
1732    removal if necessary.  This returns a new string. */
1733 static char *
1734 maybe_expand_string (string, quoted, func)
1735      char *string;
1736      int quoted;
1737      WORD_LIST *(*func)();
1738 {
1739   WORD_LIST *list;
1740   int i, saw_quote;
1741   char *ret;
1742
1743   for (i = saw_quote = 0; string[i]; i++)
1744     {
1745       if (EXP_CHAR (string[i]))
1746         break;
1747       else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1748         saw_quote = 1;
1749     }
1750
1751   if (string[i])
1752     {
1753       list = (*func) (string, quoted);
1754       if (list)
1755         {
1756           ret = string_list (list);
1757           dispose_words (list);
1758         }
1759       else
1760         ret = (char *)NULL;
1761     }
1762   else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
1763     ret = string_quote_removal (string, quoted);
1764   else
1765     ret = savestring (string);
1766   return ret;
1767 }
1768
1769 static inline char *
1770 expand_string_to_string (string, quoted, func)
1771      char *string;
1772      int quoted;
1773      WORD_LIST *(*func)();
1774 {
1775   WORD_LIST *list;
1776   char *ret;
1777
1778   if (string == 0 || *string == '\0')
1779     return ((char *)NULL);
1780
1781   list = (*func) (string, quoted);
1782   if (list)
1783     {
1784       ret = string_list (list);
1785       dispose_words (list);
1786     }
1787   else
1788     ret = (char *)NULL;
1789
1790   return (ret);
1791 }
1792
1793 #if defined (COND_COMMAND)
1794 /* Just remove backslashes in STRING.  Returns a new string. */
1795 char *
1796 remove_backslashes (string)
1797      char *string;
1798 {
1799   char *r, *ret, *s;
1800
1801   r = ret = xmalloc (strlen (string) + 1);
1802   for (s = string; s && *s; )
1803     {
1804       if (*s == '\\')
1805         s++;
1806       if (*s == 0)
1807         break;
1808       *r++ = *s++;
1809     }
1810   *r = '\0';
1811   return ret;
1812 }
1813
1814 /* This needs better error handling. */
1815 /* Expand W for use as an argument to a unary or binary operator in a
1816    [[...]] expression.  If SPECIAL is nonzero, this is the rhs argument
1817    to the != or == operator, and should be treated as a pattern.  In
1818    this case, we quote the string specially for the globbing code.  The
1819    caller is responsible for removing the backslashes if the unquoted
1820    words is needed later. */   
1821 char *
1822 cond_expand_word (w, special)
1823      WORD_DESC *w;
1824      int special;
1825 {
1826   char *r, *p;
1827   WORD_LIST *l;
1828
1829   if (w->word == 0 || w->word[0] == '\0')
1830     return ((char *)NULL);
1831
1832   l = call_expand_word_internal (w, 0, (int *)0, (int *)0);
1833   if (l)
1834     {
1835       if (special == 0)
1836         {
1837           dequote_list (l);
1838           r = string_list (l);
1839         }
1840       else
1841         {
1842           p = string_list (l);
1843           r = quote_string_for_globbing (p, QGLOB_CVTNULL);
1844           free (p);
1845         }
1846       dispose_words (l);
1847     }
1848   else
1849     r = (char *)NULL;
1850
1851   return r;
1852 }
1853 #endif
1854
1855 /* Call expand_word_internal to expand W and handle error returns.
1856    A convenience function for functions that don't want to handle
1857    any errors or free any memory before aborting. */
1858 static WORD_LIST *
1859 call_expand_word_internal (w, q, c, e)
1860      WORD_DESC *w;
1861      int q, *c, *e;
1862 {
1863   WORD_LIST *result;
1864
1865   result = expand_word_internal (w, q, c, e);
1866   if (result == &expand_word_error)
1867     {
1868       /* By convention, each time this error is returned, w->word has
1869          already been freed. */
1870       w->word = (char *)NULL;
1871       jump_to_top_level (DISCARD);
1872       /* NOTREACHED */
1873     }
1874   else if (result == &expand_word_fatal)
1875     jump_to_top_level (FORCE_EOF);
1876     /* NOTREACHED */
1877   else
1878     return (result);
1879 }
1880
1881 /* Perform parameter expansion, command substitution, and arithmetic
1882    expansion on STRING, as if it were a word.  Leave the result quoted. */
1883 static WORD_LIST *
1884 expand_string_internal (string, quoted)
1885      char *string;
1886      int quoted;
1887 {
1888   WORD_DESC td;
1889   WORD_LIST *tresult;
1890
1891   if (string == 0 || *string == 0)
1892     return ((WORD_LIST *)NULL);
1893
1894   bzero ((char *)&td, sizeof (td));
1895   td.word = string;
1896   tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL);
1897   return (tresult);
1898 }
1899
1900 /* Expand STRING by performing parameter expansion, command substitution,
1901    and arithmetic expansion.  Dequote the resulting WORD_LIST before
1902    returning it, but do not perform word splitting.  The call to
1903    remove_quoted_nulls () is in here because word splitting normally
1904    takes care of quote removal. */
1905 WORD_LIST *
1906 expand_string_unsplit (string, quoted)
1907      char *string;
1908      int quoted;
1909 {
1910   WORD_LIST *value;
1911
1912   if (!string || !*string)
1913     return ((WORD_LIST *)NULL);
1914
1915   value = expand_string_internal (string, quoted);
1916   if (value)
1917     {
1918       if (value->word)
1919         remove_quoted_nulls (value->word->word);
1920       dequote_list (value);
1921     }
1922   return (value);
1923 }
1924
1925 /* Expand STRING just as if you were expanding a word, but do not dequote
1926    the resultant WORD_LIST.  This is called only from within this file,
1927    and is used to correctly preserve quoted characters when expanding
1928    things like ${1+"$@"}.  This does parameter expansion, command
1929    subsitution, arithmetic expansion, and word splitting. */
1930 static WORD_LIST *
1931 expand_string_leave_quoted (string, quoted)
1932      char *string;
1933      int quoted;
1934 {
1935   WORD_LIST *tlist;
1936   WORD_LIST *tresult;
1937
1938   if (string == 0 || *string == '\0')
1939     return ((WORD_LIST *)NULL);
1940
1941   tlist = expand_string_internal (string, quoted);
1942
1943   if (tlist)
1944     {
1945       tresult = word_list_split (tlist);
1946       dispose_words (tlist);
1947       return (tresult);
1948     }
1949   return ((WORD_LIST *)NULL);
1950 }
1951
1952 /* This does not perform word splitting or dequote the WORD_LIST
1953    it returns. */
1954 static WORD_LIST *
1955 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
1956      char *string;
1957      int quoted, *dollar_at_p, *has_dollar_at;
1958 {
1959   WORD_DESC td;
1960   WORD_LIST *tresult;
1961
1962   if (string == 0 || *string == '\0')
1963     return (WORD_LIST *)NULL;
1964
1965   bzero ((char *)&td, sizeof (td));
1966   td.word = string;
1967   tresult = call_expand_word_internal (&td, quoted, dollar_at_p, has_dollar_at);
1968   return (tresult);
1969 }
1970
1971 /* Expand STRING just as if you were expanding a word.  This also returns
1972    a list of words.  Note that filename globbing is *NOT* done for word
1973    or string expansion, just when the shell is expanding a command.  This
1974    does parameter expansion, command substitution, arithmetic expansion,
1975    and word splitting.  Dequote the resultant WORD_LIST before returning. */
1976 WORD_LIST *
1977 expand_string (string, quoted)
1978      char *string;
1979      int quoted;
1980 {
1981   WORD_LIST *result;
1982
1983   if (!string || !*string)
1984     return ((WORD_LIST *)NULL);
1985
1986   result = expand_string_leave_quoted (string, quoted);
1987   return (result ? dequote_list (result) : result);
1988 }
1989
1990 /***************************************************
1991  *                                                 *
1992  *      Functions to handle quoting chars          *
1993  *                                                 *
1994  ***************************************************/
1995
1996 /* Conventions:
1997
1998      A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
1999      The parser passes CTLNUL as CTLESC CTLNUL. */
2000
2001 /* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2002    This is necessary to make unquoted CTLESC and CTLNUL characters in the
2003    data stream pass through properly.
2004    Here we remove doubled CTLESC characters inside quoted strings before
2005    quoting the entire string, so we do not double the number of CTLESC
2006    characters. */
2007 static char *
2008 remove_quoted_escapes (string)
2009      char *string;
2010 {
2011   register char *s;
2012   int docopy;
2013   char *t, *t1;
2014
2015   if (string == NULL)
2016     return (string);
2017
2018   t1 = t = xmalloc (strlen (string) + 1);
2019   for (docopy = 0, s = string; *s; s++, t1++)
2020     {
2021       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2022         {
2023           s++;
2024           docopy = 1;
2025         }
2026       *t1 = *s;
2027     }
2028   *t1 = '\0';
2029   if (docopy)
2030     strcpy (string, t);
2031   free (t);
2032   return (string);
2033 }
2034
2035 /* Quote escape characters in string s, but no other characters.  This is
2036    used to protect CTLESC and CTLNUL in variable values from the rest of
2037    the word expansion process after the variable is expanded. */
2038 static char *
2039 quote_escapes (string)
2040      char *string;
2041 {
2042   register char *s, *t;
2043   char *result;
2044
2045   result = xmalloc ((strlen (string) * 2) + 1);
2046   for (s = string, t = result; *s; )
2047     {
2048       if (*s == CTLESC || *s == CTLNUL)
2049         *t++ = CTLESC;
2050       *t++ = *s++;
2051     }
2052   *t = '\0';
2053   return (result);
2054 }
2055
2056 static WORD_LIST *
2057 list_quote_escapes (list)
2058      WORD_LIST *list;
2059 {
2060   register WORD_LIST *w;
2061   char *t;
2062
2063   for (w = list; w; w = w->next)
2064     {
2065       t = w->word->word;
2066       w->word->word = quote_escapes (t);
2067       free (t);
2068     }
2069   return list;
2070 }
2071
2072 #ifdef INCLUDE_UNUSED
2073 static char *
2074 dequote_escapes (string)
2075      char *string;
2076 {
2077   register char *s, *t;
2078   char *result;
2079
2080   result = xmalloc (strlen (string) + 1);
2081   for (s = string, t = result; *s; )
2082     {
2083       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2084         {
2085           s++;
2086           if (*s == '\0')
2087             break;
2088         }
2089       *t++ = *s++;
2090     }
2091   *t = '\0';
2092   return result;
2093 }
2094 #endif
2095
2096 static WORD_LIST *
2097 dequote_list (list)
2098      WORD_LIST *list;
2099 {
2100   register char *s;
2101   register WORD_LIST *tlist;
2102
2103   for (tlist = list; tlist; tlist = tlist->next)
2104     {
2105       s = dequote_string (tlist->word->word);
2106       free (tlist->word->word);
2107       tlist->word->word = s;
2108     }
2109   return list;
2110 }
2111
2112 static char *
2113 make_quoted_char (c)
2114      int c;
2115 {
2116   char *temp;
2117
2118   temp = xmalloc (3);
2119   if (c == 0)
2120     {
2121       temp[0] = CTLNUL;
2122       temp[1] = '\0';
2123     }
2124   else
2125     {
2126       temp[0] = CTLESC;
2127       temp[1] = c;
2128       temp[2] = '\0';
2129     }
2130   return (temp);
2131 }
2132
2133 /* Quote STRING.  Return a new string. */
2134 char *
2135 quote_string (string)
2136      char *string;
2137 {
2138   register char *t;
2139   char *result;
2140
2141   if (*string == 0)
2142     {
2143       result = xmalloc (2);
2144       result[0] = CTLNUL;
2145       result[1] = '\0';
2146     }
2147   else
2148     {
2149       result = xmalloc ((strlen (string) * 2) + 1);
2150
2151       for (t = result; *string; )
2152         {
2153           *t++ = CTLESC;
2154           *t++ = *string++;
2155         }
2156       *t = '\0';
2157     }
2158   return (result);
2159 }
2160
2161 /* De-quoted quoted characters in STRING. */
2162 char *
2163 dequote_string (string)
2164      char *string;
2165 {
2166   register char *t;
2167   char *result;
2168
2169   result = xmalloc (strlen (string) + 1);
2170
2171   if (QUOTED_NULL (string))
2172     {
2173       result[0] = '\0';
2174       return (result);
2175     }
2176
2177   /* If no character in the string can be quoted, don't bother examining
2178      each character.  Just return a copy of the string passed to us. */
2179   if (strchr (string, CTLESC) == NULL)          /* XXX */
2180     {                                           /* XXX */
2181       strcpy (result, string);                  /* XXX */
2182       return (result);                          /* XXX */
2183     }
2184
2185   for (t = result; *string; string++, t++)
2186     {
2187       if (*string == CTLESC)
2188         {
2189           string++;
2190
2191           if (!*string)
2192             break;
2193         }
2194
2195       *t = *string;
2196     }
2197
2198   *t = '\0';
2199   return (result);
2200 }
2201
2202 /* Quote the entire WORD_LIST list. */
2203 static WORD_LIST *
2204 quote_list (list)
2205      WORD_LIST *list;
2206 {
2207   register WORD_LIST *w;
2208   char *t;
2209
2210   for (w = list; w; w = w->next)
2211     {
2212       t = w->word->word;
2213       w->word->word = quote_string (t);
2214       free (t);
2215       w->word->flags |= W_QUOTED;
2216     }
2217   return list;
2218 }
2219
2220 /* Perform quoted null character removal on STRING.  We don't allow any
2221    quoted null characters in the middle or at the ends of strings because
2222    of how expand_word_internal works.  remove_quoted_nulls () turns
2223    STRING into an empty string iff it only consists of a quoted null,
2224    and removes all unquoted CTLNUL characters. */
2225 /*
2226 #define remove_quoted_nulls(string) \
2227   do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
2228 */
2229 static void
2230 remove_quoted_nulls (string)
2231      char *string;
2232 {
2233   char *nstr, *s, *p;
2234
2235   nstr = savestring (string);
2236   nstr[0] = '\0';
2237   for (p = nstr, s = string; *s; s++)
2238     {
2239       if (*s == CTLESC)
2240         {
2241           *p++ = *s++;  /* CTLESC */
2242           if (*s == 0)
2243             break;
2244           *p++ = *s;    /* quoted char */
2245           continue;
2246         }
2247       if (*s == CTLNUL)
2248         continue;
2249       *p++ = *s;
2250     }
2251   *p = '\0';
2252   strcpy (string, nstr);
2253   free (nstr);
2254 }
2255
2256 /* Perform quoted null character removal on each element of LIST.
2257    This modifies LIST. */
2258 void
2259 word_list_remove_quoted_nulls (list)
2260      WORD_LIST *list;
2261 {
2262   register WORD_LIST *t;
2263
2264   for (t = list; t; t = t->next)
2265     remove_quoted_nulls (t->word->word);
2266 }
2267
2268 /* **************************************************************** */
2269 /*                                                                  */
2270 /*         Functions for Matching and Removing Patterns             */
2271 /*                                                                  */
2272 /* **************************************************************** */
2273
2274 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
2275    can have one of 4 values:
2276         RP_LONG_LEFT    remove longest matching portion at start of PARAM
2277         RP_SHORT_LEFT   remove shortest matching portion at start of PARAM
2278         RP_LONG_RIGHT   remove longest matching portion at end of PARAM
2279         RP_SHORT_RIGHT  remove shortest matching portion at end of PARAM
2280 */
2281
2282 #define RP_LONG_LEFT    1
2283 #define RP_SHORT_LEFT   2
2284 #define RP_LONG_RIGHT   3
2285 #define RP_SHORT_RIGHT  4
2286
2287 static char *
2288 remove_pattern (param, pattern, op)
2289      char *param, *pattern;
2290      int op;
2291 {
2292   register int len;
2293   register char *end;
2294   register char *p, *ret, c;
2295
2296   if (param == NULL || *param == '\0')
2297     return (param);
2298   if (pattern == NULL || *pattern == '\0')      /* minor optimization */
2299     return (savestring (param));
2300
2301   len = STRLEN (param);
2302   end = param + len;
2303
2304   switch (op)
2305     {
2306       case RP_LONG_LEFT:        /* remove longest match at start */
2307         for (p = end; p >= param; p--)
2308           {
2309             c = *p; *p = '\0';
2310             if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2311               {
2312                 *p = c;
2313                 return (savestring (p));
2314               }
2315             *p = c;
2316           }
2317         break;
2318
2319       case RP_SHORT_LEFT:       /* remove shortest match at start */
2320         for (p = param; p <= end; p++)
2321           {
2322             c = *p; *p = '\0';
2323             if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2324               {
2325                 *p = c;
2326                 return (savestring (p));
2327               }
2328             *p = c;
2329           }
2330         break;
2331
2332       case RP_LONG_RIGHT:       /* remove longest match at end */
2333         for (p = param; p <= end; p++)
2334           {
2335             if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2336               {
2337                 c = *p; *p = '\0';
2338                 ret = savestring (param);
2339                 *p = c;
2340                 return (ret);
2341               }
2342           }
2343         break;
2344
2345       case RP_SHORT_RIGHT:      /* remove shortest match at end */
2346         for (p = end; p >= param; p--)
2347           {
2348             if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2349               {
2350                 c = *p; *p = '\0';
2351                 ret = savestring (param);
2352                 *p = c;
2353                 return (ret);
2354               }
2355           }
2356         break;
2357     }
2358   return (savestring (param));  /* no match, return original string */
2359 }
2360
2361 /* Return 1 of the first character of STRING could match the first
2362    character of pattern PAT.  Used to avoid n2 calls to fnmatch(). */
2363 static int
2364 match_pattern_char (pat, string)
2365      char *pat, *string;
2366 {
2367   char c;
2368
2369   if (*string == 0)
2370     return (0);
2371
2372   switch (c = *pat++)
2373     {
2374     default:
2375       return (*string == c);
2376     case '\\':
2377       return (*string == *pat);
2378     case '?':
2379       return (*string == LPAREN ? 1 : (*string != '\0'));
2380     case '*':
2381       return (1);
2382     case '+':
2383     case '!':
2384     case '@':
2385       return (*string == LPAREN ? 1 : (*string == c));
2386     case '[':
2387       return (*string != '\0');
2388     }
2389 }
2390
2391 /* Match PAT anywhere in STRING and return the match boundaries.
2392    This returns 1 in case of a successful match, 0 otherwise.  SP
2393    and EP are pointers into the string where the match begins and
2394    ends, respectively.  MTYPE controls what kind of match is attempted.
2395    MATCH_BEG and MATCH_END anchor the match at the beginning and end
2396    of the string, respectively.  The longest match is returned. */
2397 static int
2398 match_pattern (string, pat, mtype, sp, ep)
2399      char *string, *pat;
2400      int mtype;
2401      char **sp, **ep;
2402 {
2403   int c;
2404   register char *p, *p1;
2405   char *end;
2406
2407   if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
2408     return (0);
2409
2410   end = string + STRLEN (string);
2411
2412   switch (mtype)
2413     {
2414     case MATCH_ANY:
2415       for (p = string; p <= end; p++)
2416         {
2417           if (match_pattern_char (pat, p))
2418             {
2419               for (p1 = end; p1 >= p; p1--)
2420                 {
2421                   c = *p1; *p1 = '\0';
2422                   if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0)
2423                     {
2424                       *p1 = c;
2425                       *sp = p;
2426                       *ep = p1;
2427                       return 1;
2428                     }
2429                   *p1 = c;
2430                 }
2431             }
2432         }
2433       return (0);
2434
2435     case MATCH_BEG:
2436       if (match_pattern_char (pat, string) == 0)
2437         return (0);
2438       for (p = end; p >= string; p--)
2439         {
2440           c = *p; *p = '\0';
2441           if (fnmatch (pat, string, FNMATCH_EXTFLAG) == 0)
2442             {
2443               *p = c;
2444               *sp = string;
2445               *ep = p;
2446               return 1;
2447             }
2448           *p = c;
2449         }
2450       return (0);
2451
2452     case MATCH_END:
2453       for (p = string; p <= end; p++)
2454         if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0)
2455           {
2456             *sp = p;
2457             *ep = end;
2458             return 1;
2459           }
2460       return (0);
2461     }
2462
2463   return (0);
2464 }
2465
2466 static int
2467 getpatspec (c, value)
2468      int c;
2469      char *value;
2470 {
2471   if (c == '#')
2472     return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
2473   else  /* c == '%' */
2474     return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
2475 }
2476
2477 /* Posix.2 says that the WORD should be run through tilde expansion,
2478    parameter expansion, command substitution and arithmetic expansion.
2479    This leaves the result quoted, so quote_string_for_globbing () has
2480    to be called to fix it up for fnmatch ().  If QUOTED is non-zero,
2481    it means that the entire expression was enclosed in double quotes.
2482    This means that quoting characters in the pattern do not make any
2483    special pattern characters quoted.  For example, the `*' in the
2484    following retains its special meaning: "${foo#'*'}". */
2485 static char *
2486 getpattern (value, quoted, expandpat)
2487      char *value;
2488      int quoted, expandpat;
2489 {
2490   char *pat, *tword;
2491   WORD_LIST *l;
2492   int i;
2493
2494   tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value);
2495
2496   /* expand_string_internal () leaves WORD quoted and does not perform
2497      word splitting. */
2498   if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
2499     {
2500       i = 0;
2501       pat = string_extract_double_quoted (tword, &i, 1);
2502       free (tword);
2503       tword = pat;
2504     }
2505
2506   /* There is a problem here:  how to handle single or double quotes in the
2507      pattern string when the whole expression is between double quotes? */
2508 #if 0
2509   l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL)
2510 #else
2511   l = *tword ? expand_string_for_rhs (tword,
2512                                       (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted,
2513                                       (int *)NULL, (int *)NULL)
2514 #endif
2515              : (WORD_LIST *)0;
2516   free (tword);
2517   pat = string_list (l);
2518   dispose_words (l);
2519   if (pat)
2520     {
2521       tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
2522       free (pat);
2523       pat = tword;
2524     }
2525   return (pat);
2526 }
2527
2528 /* Handle removing a pattern from a string as a result of ${name%[%]value}
2529    or ${name#[#]value}. */
2530 static char *
2531 parameter_brace_remove_pattern (value, temp, c, quoted)
2532      char *value, *temp;
2533      int c, quoted;
2534 {
2535   int patspec;
2536   char *pattern, *tword;
2537
2538   patspec = getpatspec (c, value);
2539   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2540     value++;
2541
2542   pattern = getpattern (value, quoted, 1);
2543
2544   tword = remove_pattern (temp, pattern, patspec);
2545
2546   FREE (pattern);
2547   return (tword);
2548 }
2549
2550 static char *
2551 list_remove_pattern (list, pattern, patspec, type, quoted)
2552      WORD_LIST *list;
2553      char *pattern;
2554      int patspec, type, quoted;
2555 {
2556   WORD_LIST *new, *l;
2557   WORD_DESC *w;
2558   char *tword;
2559
2560   for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
2561     {
2562       tword = remove_pattern (l->word->word, pattern, patspec);
2563       w = make_bare_word (tword);
2564       free (tword);
2565       new = make_word_list (w, new);
2566     }
2567
2568   l = REVERSE_LIST (new, WORD_LIST *);
2569   if (type == '*')
2570     tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
2571   else
2572     tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
2573
2574   dispose_words (l);
2575   return (tword);
2576 }
2577
2578 static char *
2579 parameter_list_remove_pattern (value, type, c, quoted)
2580      char *value;
2581      int type, c, quoted;
2582 {
2583   int patspec;
2584   char *pattern, *ret;
2585   WORD_LIST *list;
2586
2587   patspec = getpatspec (c, value);
2588   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2589     value++;
2590
2591   pattern = getpattern (value, quoted, 1);
2592
2593   list = list_rest_of_args ();
2594   ret = list_remove_pattern (list, pattern, patspec, type, quoted);
2595   dispose_words (list);
2596   FREE (pattern);
2597   return (ret);
2598 }
2599
2600 #if defined (ARRAY_VARS)
2601 static char *
2602 array_remove_pattern (value, aspec, aval, c, quoted)
2603      char *value, *aspec, *aval;        /* AVAL == evaluated ASPEC */
2604      int c, quoted;
2605 {
2606   SHELL_VAR *var;
2607   int len, patspec;
2608   char *ret, *t, *pattern;
2609   WORD_LIST *l;
2610
2611   var = array_variable_part (aspec, &t, &len);
2612   if (var == 0)
2613     return ((char *)NULL);
2614
2615   patspec = getpatspec (c, value);
2616   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2617     value++;
2618
2619   pattern = getpattern (value, quoted, 1);
2620
2621   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
2622     {
2623       if (array_p (var) == 0)
2624         {
2625           report_error ("%s: bad array subscript", aspec);
2626           FREE (pattern);
2627           return ((char *)NULL);
2628         }
2629       l = array_to_word_list (array_cell (var));
2630       if (l == 0)
2631         return ((char *)NULL);
2632       ret = list_remove_pattern (l, pattern, patspec, t[0], quoted);
2633       dispose_words (l);
2634     }
2635   else
2636     {
2637       ret = remove_pattern (aval, pattern, patspec);
2638       if (ret)
2639         {
2640           t = quote_escapes (ret);
2641           free (ret);
2642           ret = t;
2643         }
2644     }
2645
2646   FREE (pattern);
2647   return ret;
2648 }
2649 #endif /* ARRAY_VARS */
2650
2651 /*******************************************
2652  *                                         *
2653  *      Functions to expand WORD_DESCs     *
2654  *                                         *
2655  *******************************************/
2656
2657 /* Expand WORD, performing word splitting on the result.  This does
2658    parameter expansion, command substitution, arithmetic expansion,
2659    word splitting, and quote removal. */
2660
2661 WORD_LIST *
2662 expand_word (word, quoted)
2663      WORD_DESC *word;
2664      int quoted;
2665 {
2666   WORD_LIST *result, *tresult;
2667
2668   tresult = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
2669   result = word_list_split (tresult);
2670   dispose_words (tresult);
2671   return (result ? dequote_list (result) : result);
2672 }
2673
2674 /* Expand WORD, but do not perform word splitting on the result.  This
2675    does parameter expansion, command substitution, arithmetic expansion,
2676    and quote removal. */
2677 WORD_LIST *
2678 expand_word_no_split (word, quoted)
2679      WORD_DESC *word;
2680      int quoted;
2681 {
2682   WORD_LIST *result;
2683
2684   result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
2685   return (result ? dequote_list (result) : result);
2686 }
2687
2688 /* Perform shell expansions on WORD, but do not perform word splitting or
2689    quote removal on the result. */
2690 WORD_LIST *
2691 expand_word_leave_quoted (word, quoted)
2692      WORD_DESC *word;
2693      int quoted;
2694 {
2695   return (call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL));
2696 }
2697
2698 #if defined (PROCESS_SUBSTITUTION)
2699
2700 /*****************************************************************/
2701 /*                                                               */
2702 /*                  Hacking Process Substitution                 */
2703 /*                                                               */
2704 /*****************************************************************/
2705
2706 #if !defined (HAVE_DEV_FD)
2707 /* Named pipes must be removed explicitly with `unlink'.  This keeps a list
2708    of FIFOs the shell has open.  unlink_fifo_list will walk the list and
2709    unlink all of them. add_fifo_list adds the name of an open FIFO to the
2710    list.  NFIFO is a count of the number of FIFOs in the list. */
2711 #define FIFO_INCR 20
2712 extern char *mktemp ();
2713
2714 static char **fifo_list = (char **)NULL;
2715 static int nfifo;
2716 static int fifo_list_size;
2717
2718 static void
2719 add_fifo_list (pathname)
2720      char *pathname;
2721 {
2722   if (nfifo >= fifo_list_size - 1)
2723     {
2724       fifo_list_size += FIFO_INCR;
2725       fifo_list = (char **)xrealloc (fifo_list,
2726                                      fifo_list_size * sizeof (char *));
2727     }
2728
2729   fifo_list[nfifo++] = savestring (pathname);
2730 }
2731
2732 void
2733 unlink_fifo_list ()
2734 {
2735   if (nfifo == 0)
2736     return;
2737
2738   while (nfifo--)
2739     {
2740       unlink (fifo_list[nfifo]);
2741       free (fifo_list[nfifo]);
2742       fifo_list[nfifo] = (char *)NULL;
2743     }
2744   nfifo = 0;
2745 }
2746
2747 static char *
2748 make_named_pipe ()
2749 {
2750   char *tname;
2751
2752   tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
2753   if (mkfifo (tname, 0600) < 0)
2754     {
2755       free (tname);
2756       return ((char *)NULL);
2757     }
2758
2759   add_fifo_list (tname);
2760   return (tname);
2761 }
2762
2763 #else /* HAVE_DEV_FD */
2764
2765 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
2766    has open to children.  NFDS is a count of the number of bits currently
2767    set in DEV_FD_LIST.  TOTFDS is a count of the highest possible number
2768    of open files. */
2769 static char *dev_fd_list = (char *)NULL;
2770 static int nfds;
2771 static int totfds;      /* The highest possible number of open files. */
2772
2773 static void
2774 add_fifo_list (fd)
2775      int fd;
2776 {
2777   if (!dev_fd_list || fd >= totfds)
2778     {
2779       int ofds;
2780
2781       ofds = totfds;
2782       totfds = getdtablesize ();
2783       if (totfds < 0 || totfds > 256)
2784         totfds = 256;
2785       if (fd > totfds)
2786         totfds = fd + 2;
2787
2788       dev_fd_list = xrealloc (dev_fd_list, totfds);
2789       bzero (dev_fd_list + ofds, totfds - ofds);
2790     }
2791
2792   dev_fd_list[fd] = 1;
2793   nfds++;
2794 }
2795
2796 void
2797 unlink_fifo_list ()
2798 {
2799   register int i;
2800
2801   if (nfds == 0)
2802     return;
2803
2804   for (i = 0; nfds && i < totfds; i++)
2805     if (dev_fd_list[i])
2806       {
2807         close (i);
2808         dev_fd_list[i] = 0;
2809         nfds--;
2810       }
2811
2812   nfds = 0;
2813 }
2814
2815 #if defined (NOTDEF)
2816 print_dev_fd_list ()
2817 {
2818   register int i;
2819
2820   fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
2821   fflush (stderr);
2822
2823   for (i = 0; i < totfds; i++)
2824     {
2825       if (dev_fd_list[i])
2826         fprintf (stderr, " %d", i);
2827     }
2828   fprintf (stderr, "\n");
2829 }
2830 #endif /* NOTDEF */
2831
2832 static char *
2833 make_dev_fd_filename (fd)
2834      int fd;
2835 {
2836   char *ret;
2837
2838   ret = xmalloc (sizeof (DEV_FD_PREFIX) + 4);
2839   sprintf (ret, "%s%d", DEV_FD_PREFIX, fd);
2840   add_fifo_list (fd);
2841   return (ret);
2842 }
2843
2844 #endif /* HAVE_DEV_FD */
2845
2846 /* Return a filename that will open a connection to the process defined by
2847    executing STRING.  HAVE_DEV_FD, if defined, means open a pipe and return
2848    a filename in /dev/fd corresponding to a descriptor that is one of the
2849    ends of the pipe.  If not defined, we use named pipes on systems that have
2850    them.  Systems without /dev/fd and named pipes are out of luck.
2851
2852    OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
2853    use the read end of the pipe and dup that file descriptor to fd 0 in
2854    the child.  If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
2855    writing or use the write end of the pipe in the child, and dup that
2856    file descriptor to fd 1 in the child.  The parent does the opposite. */
2857
2858 static char *
2859 process_substitute (string, open_for_read_in_child)
2860      char *string;
2861      int open_for_read_in_child;
2862 {
2863   char *pathname;
2864   int fd, result;
2865   pid_t old_pid, pid;
2866 #if defined (HAVE_DEV_FD)
2867   int parent_pipe_fd, child_pipe_fd;
2868   int fildes[2];
2869 #endif /* HAVE_DEV_FD */
2870 #if defined (JOB_CONTROL)
2871   pid_t old_pipeline_pgrp;
2872 #endif
2873
2874   if (!string || !*string || wordexp_only)
2875     return ((char *)NULL);
2876
2877 #if !defined (HAVE_DEV_FD)
2878   pathname = make_named_pipe ();
2879 #else /* HAVE_DEV_FD */
2880   if (pipe (fildes) < 0)
2881     {
2882       sys_error ("cannot make pipe for process substitution");
2883       return ((char *)NULL);
2884     }
2885   /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
2886      the pipe in the parent, otherwise the read end. */
2887   parent_pipe_fd = fildes[open_for_read_in_child];
2888   child_pipe_fd = fildes[1 - open_for_read_in_child];
2889   /* Move the parent end of the pipe to some high file descriptor, to
2890      avoid clashes with FDs used by the script. */
2891   parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
2892
2893   pathname = make_dev_fd_filename (parent_pipe_fd);
2894 #endif /* HAVE_DEV_FD */
2895
2896   if (!pathname)
2897     {
2898       sys_error ("cannot make pipe for process substitution");
2899       return ((char *)NULL);
2900     }
2901
2902   old_pid = last_made_pid;
2903
2904 #if defined (JOB_CONTROL)
2905   old_pipeline_pgrp = pipeline_pgrp;
2906   pipeline_pgrp = shell_pgrp;
2907 #if 0
2908   cleanup_the_pipeline ();
2909 #else
2910   save_pipeline (1);
2911 #endif
2912 #endif /* JOB_CONTROL */
2913
2914   pid = make_child ((char *)NULL, 1);
2915   if (pid == 0)
2916     {
2917       reset_terminating_signals ();     /* XXX */
2918       /* Cancel traps, in trap.c. */
2919       restore_original_signals ();
2920       setup_async_signals ();
2921       subshell_environment = SUBSHELL_COMSUB;
2922     }
2923
2924 #if defined (JOB_CONTROL)
2925   set_sigchld_handler ();
2926   stop_making_children ();
2927   pipeline_pgrp = old_pipeline_pgrp;
2928 #endif /* JOB_CONTROL */
2929
2930   if (pid < 0)
2931     {
2932       sys_error ("cannot make child for process substitution");
2933       free (pathname);
2934 #if defined (HAVE_DEV_FD)
2935       close (parent_pipe_fd);
2936       close (child_pipe_fd);
2937 #endif /* HAVE_DEV_FD */
2938       return ((char *)NULL);
2939     }
2940
2941   if (pid > 0)
2942     {
2943 #if defined (JOB_CONTROL)
2944       restore_pipeline (1);
2945 #endif
2946
2947       last_made_pid = old_pid;
2948
2949 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2950       close_pgrp_pipe ();
2951 #endif /* JOB_CONTROL && PGRP_PIPE */
2952
2953 #if defined (HAVE_DEV_FD)
2954       close (child_pipe_fd);
2955 #endif /* HAVE_DEV_FD */
2956
2957       return (pathname);
2958     }
2959
2960   set_sigint_handler ();
2961
2962 #if defined (JOB_CONTROL)
2963   set_job_control (0);
2964 #endif /* JOB_CONTROL */
2965
2966 #if !defined (HAVE_DEV_FD)
2967   /* Open the named pipe in the child. */
2968   fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
2969   if (fd < 0)
2970     {
2971       sys_error ("cannot open named pipe %s for %s", pathname,
2972         open_for_read_in_child ? "reading" : "writing");
2973       exit (127);
2974     }
2975 #else /* HAVE_DEV_FD */
2976   fd = child_pipe_fd;
2977 #endif /* HAVE_DEV_FD */
2978
2979   if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
2980     {
2981       sys_error ("cannot duplicate named pipe %s as fd %d", pathname,
2982         open_for_read_in_child ? 0 : 1);
2983       exit (127);
2984     }
2985
2986   close (fd);
2987
2988   /* Need to close any files that this process has open to pipes inherited
2989      from its parent. */
2990   if (current_fds_to_close)
2991     {
2992       close_fd_bitmap (current_fds_to_close);
2993       current_fds_to_close = (struct fd_bitmap *)NULL;
2994     }
2995
2996 #if defined (HAVE_DEV_FD)
2997   /* Make sure we close the parent's end of the pipe and clear the slot
2998      in the fd list so it is not closed later, if reallocated by, for
2999      instance, pipe(2). */
3000   close (parent_pipe_fd);
3001   dev_fd_list[parent_pipe_fd] = 0;
3002 #endif /* HAVE_DEV_FD */
3003
3004   result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
3005
3006 #if !defined (HAVE_DEV_FD)
3007   /* Make sure we close the named pipe in the child before we exit. */
3008   close (open_for_read_in_child ? 0 : 1);
3009 #endif /* !HAVE_DEV_FD */
3010
3011   exit (result);
3012   /*NOTREACHED*/
3013 }
3014 #endif /* PROCESS_SUBSTITUTION */
3015
3016 /***********************************/
3017 /*                                 */
3018 /*      Command Substitution       */
3019 /*                                 */
3020 /***********************************/
3021
3022 static char *
3023 read_comsub (fd, quoted)
3024      int fd, quoted;
3025 {
3026   char *istring, buf[128], *bufp;
3027   int bufn, istring_index, istring_size, c;
3028
3029   istring = (char *)NULL;
3030   istring_index = istring_size = bufn = 0;
3031
3032   /* Read the output of the command through the pipe. */
3033   while (1)
3034     {
3035       if (fd < 0)
3036         break;
3037       if (--bufn <= 0)
3038         {
3039           while ((bufn = read (fd, buf, sizeof(buf))) < 0 && errno == EINTR)
3040             ;
3041           if (bufn <= 0) 
3042             break;
3043           bufp = buf;
3044         }
3045       c = *bufp++;
3046
3047       /* Add the character to ISTRING, possibly after resizing it. */
3048       RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
3049
3050       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
3051         istring[istring_index++] = CTLESC;
3052
3053       istring[istring_index++] = c;
3054     }
3055
3056   if (istring)
3057     istring[istring_index] = '\0';
3058
3059   /* If we read no output, just return now and save ourselves some
3060      trouble. */
3061   if (istring_index == 0)
3062     {
3063       FREE (istring);
3064       return (char *)NULL;
3065     }
3066
3067   /* Strip trailing newlines from the output of the command. */
3068   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
3069     {
3070       while (istring_index > 0)
3071         {
3072           if (istring[istring_index - 1] == '\n')
3073             {
3074               --istring_index;
3075
3076               /* If the newline was quoted, remove the quoting char. */
3077               if (istring[istring_index - 1] == CTLESC)
3078                 --istring_index;
3079             }
3080           else
3081             break;
3082         }
3083       istring[istring_index] = '\0';
3084     }
3085   else
3086     strip_trailing (istring, istring_index - 1, 1);
3087
3088   return istring;
3089 }
3090
3091 /* Perform command substitution on STRING.  This returns a string,
3092    possibly quoted. */
3093 static char *
3094 command_substitute (string, quoted)
3095      char *string;
3096      int quoted;
3097 {
3098   pid_t pid, old_pid, old_pipeline_pgrp;
3099   char *istring;
3100   int result, fildes[2];
3101
3102   istring = (char *)NULL;
3103
3104   /* Don't fork () if there is no need to.  In the case of no command to
3105      run, just return NULL. */
3106   if (!string || !*string || (string[0] == '\n' && !string[1]))
3107     return ((char *)NULL);
3108
3109   if (wordexp_only && read_but_dont_execute)
3110     {
3111       last_command_exit_value = 125;
3112       jump_to_top_level (EXITPROG);
3113     }
3114
3115   /* Pipe the output of executing STRING into the current shell. */
3116   if (pipe (fildes) < 0)
3117     {
3118       sys_error ("cannot make pipes for command substitution");
3119       goto error_exit;
3120     }
3121
3122   old_pid = last_made_pid;
3123 #if defined (JOB_CONTROL)
3124   old_pipeline_pgrp = pipeline_pgrp;
3125   pipeline_pgrp = shell_pgrp;
3126   cleanup_the_pipeline ();
3127 #endif
3128
3129   pid = make_child ((char *)NULL, 0);
3130   if (pid == 0)
3131     /* Reset the signal handlers in the child, but don't free the
3132        trap strings. */
3133     reset_signal_handlers ();
3134
3135 #if defined (JOB_CONTROL)
3136   set_sigchld_handler ();
3137   stop_making_children ();
3138   pipeline_pgrp = old_pipeline_pgrp;
3139 #endif /* JOB_CONTROL */
3140
3141   if (pid < 0)
3142     {
3143       sys_error ("cannot make child for command substitution");
3144     error_exit:
3145
3146       FREE (istring);
3147       close (fildes[0]);
3148       close (fildes[1]);
3149       return ((char *)NULL);
3150     }
3151
3152   if (pid == 0)
3153     {
3154       set_sigint_handler ();    /* XXX */
3155 #if defined (JOB_CONTROL)
3156       set_job_control (0);
3157 #endif
3158       if (dup2 (fildes[1], 1) < 0)
3159         {
3160           sys_error ("command_substitute: cannot duplicate pipe as fd 1");
3161           exit (EXECUTION_FAILURE);
3162         }
3163
3164       /* If standard output is closed in the parent shell
3165          (such as after `exec >&-'), file descriptor 1 will be
3166          the lowest available file descriptor, and end up in
3167          fildes[0].  This can happen for stdin and stderr as well,
3168          but stdout is more important -- it will cause no output
3169          to be generated from this command. */
3170       if ((fildes[1] != fileno (stdin)) &&
3171           (fildes[1] != fileno (stdout)) &&
3172           (fildes[1] != fileno (stderr)))
3173         close (fildes[1]);
3174
3175       if ((fildes[0] != fileno (stdin)) &&
3176           (fildes[0] != fileno (stdout)) &&
3177           (fildes[0] != fileno (stderr)))
3178         close (fildes[0]);
3179
3180       /* The currently executing shell is not interactive. */
3181       interactive = 0;
3182
3183       /* This is a subshell environment. */
3184       subshell_environment = SUBSHELL_COMSUB;
3185
3186       /* Command substitution does not inherit the -e flag. */
3187       exit_immediately_on_error = 0;
3188
3189       remove_quoted_escapes (string);
3190
3191       startup_state = 2;        /* see if we can avoid a fork */
3192       /* Give command substitution a place to jump back to on failure,
3193          so we don't go back up to main (). */
3194       result = setjmp (top_level);
3195
3196       if (result == EXITPROG)
3197         exit (last_command_exit_value);
3198       else if (result)
3199         exit (EXECUTION_FAILURE);
3200       else
3201         exit (parse_and_execute (string, "command substitution", SEVAL_NOHIST));
3202     }
3203   else
3204     {
3205 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
3206       close_pgrp_pipe ();
3207 #endif /* JOB_CONTROL && PGRP_PIPE */
3208
3209       close (fildes[1]);
3210
3211       istring = read_comsub (fildes[0], quoted);
3212
3213       close (fildes[0]);
3214
3215       last_command_exit_value = wait_for (pid);
3216       last_command_subst_pid = pid;
3217       last_made_pid = old_pid;
3218
3219 #if defined (JOB_CONTROL)
3220       /* If last_command_exit_value > 128, then the substituted command
3221          was terminated by a signal.  If that signal was SIGINT, then send
3222          SIGINT to ourselves.  This will break out of loops, for instance. */
3223       if (last_command_exit_value == (128 + SIGINT))
3224         kill (getpid (), SIGINT);
3225
3226       /* wait_for gives the terminal back to shell_pgrp.  If some other
3227          process group should have it, give it away to that group here.
3228          pipeline_pgrp is non-zero only while we are constructing a
3229          pipline, so what we are concerned about is whether or not that
3230          pipeline was started in the background.  A pipeline started in
3231          the background should never get the tty back here. */
3232 #if 0
3233       if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
3234 #else
3235       if (interactive && pipeline_pgrp != (pid_t)0 && subshell_environment != SUBSHELL_ASYNC)
3236 #endif
3237         give_terminal_to (pipeline_pgrp);
3238 #endif /* JOB_CONTROL */
3239
3240       return (istring);
3241     }
3242 }
3243
3244 /********************************************************
3245  *                                                      *
3246  *      Utility functions for parameter expansion       *
3247  *                                                      *
3248  ********************************************************/
3249
3250 /* Utility functions to manage arrays and their contents for expansion */
3251
3252 #if defined (ARRAY_VARS)
3253 int
3254 valid_array_reference (name)
3255      char *name;
3256 {
3257   char *t;
3258   int r, len;
3259
3260   t = strchr (name, '[');
3261   if (t)
3262     {
3263       *t = '\0';
3264       r = legal_identifier (name);
3265       *t = '[';
3266       if (r == 0)
3267         return 0;
3268       /* Check for a properly-terminated non-blank subscript. */
3269       len = skipsubscript (t, 0);
3270       if (t[len] != ']' || len == 1)
3271         return 0;
3272       for (r = 1; r < len; r++)
3273         if (whitespace (t[r]) == 0)
3274           return 1;
3275       return 0;
3276     }
3277   return 0;
3278 }
3279
3280 /* Expand the array index beginning at S and extending LEN characters. */
3281 int
3282 array_expand_index (s, len)
3283      char *s;
3284      int len;
3285 {
3286   char *exp, *t;
3287   int val, expok;
3288
3289   exp = xmalloc (len);
3290   strncpy (exp, s, len - 1);
3291   exp[len - 1] = '\0';
3292   t = maybe_expand_string (exp, 0, expand_string);
3293   this_command_name = (char *)NULL;
3294   val = evalexp (t, &expok);
3295   free (t);
3296   free (exp);
3297   if (expok == 0)
3298     jump_to_top_level (DISCARD);
3299   return val;
3300 }
3301
3302 /* Return the variable specified by S without any subscript.  If non-null,
3303    return the index of the start of the subscript in *SUBP.  If non-null,
3304    the length of the subscript is returned in *LENP. */
3305 SHELL_VAR *
3306 array_variable_part (s, subp, lenp)
3307      char *s, **subp;
3308      int *lenp;
3309 {
3310   char *t;
3311   int ind, ni;
3312   SHELL_VAR *var;
3313
3314   t = strchr (s, '[');
3315   ind = t - s;
3316   ni = skipsubscript (s, ind);
3317   if (ni <= ind + 1 || s[ni] != ']')
3318     {
3319       report_error ("%s: bad array subscript", s);
3320       return ((SHELL_VAR *)NULL);
3321     }
3322
3323   *t = '\0';
3324   var = find_variable (s);
3325   *t++ = '[';
3326
3327   if (subp)
3328     *subp = t;
3329   if (lenp)
3330     *lenp = ni - ind;
3331   return var;
3332 }
3333
3334 static char *
3335 array_value_internal (s, quoted, allow_all)
3336      char *s;
3337      int quoted, allow_all;
3338 {
3339   int len, ind;
3340   char *retval, *t, *temp;
3341   WORD_LIST *l, *list;
3342   SHELL_VAR *var;
3343
3344   var = array_variable_part (s, &t, &len);
3345
3346   if (var == 0)
3347     return (char *)NULL;
3348
3349   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3350     {
3351       if (array_p (var) == 0 || allow_all == 0)
3352         {
3353           report_error ("%s: bad array subscript", s);
3354           return ((char *)NULL);
3355         }
3356       l = array_to_word_list (array_cell (var));
3357       if (l == (WORD_LIST *)NULL)
3358         return ((char *) NULL);
3359
3360 #if 0
3361       if (t[0] == '*')          /* ${name[*]} */
3362         retval = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
3363       else                      /* ${name[@]} */
3364         retval = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3365 #else
3366       if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
3367         {
3368           temp = string_list_dollar_star (l);
3369           retval = quote_string (temp);
3370           free (temp);
3371         }
3372       else      /* ${name[@]} or unquoted ${name[*]} */
3373         retval = string_list_dollar_at (l, quoted);
3374 #endif
3375
3376       dispose_words (l);
3377     }
3378   else
3379     {
3380       ind = array_expand_index (t, len);
3381       if (ind < 0)
3382         {
3383           report_error ("%s: bad array subscript", var->name);
3384           return ((char *)NULL);
3385         }
3386       if (array_p (var) == 0)
3387         return (ind == 0 ? savestring (value_cell (var)) : (char *)NULL);
3388       retval = array_reference (array_cell (var), ind);
3389       if (retval)
3390         retval = quote_escapes (retval);
3391     }
3392
3393   return retval;
3394 }
3395
3396 static char *
3397 array_value (s, quoted)
3398      char *s;
3399      int quoted;
3400 {
3401   return (array_value_internal (s, quoted, 1));
3402 }
3403
3404 /* Return the value of the array indexing expression S as a single string.
3405    If ALLOW_ALL is 0, do not allow `@' and `*' subscripts.  This is used
3406    by other parts of the shell such as the arithmetic expression evaluator
3407    in expr.c. */
3408 char *
3409 get_array_value (s, allow_all)
3410      char *s;
3411      int allow_all;
3412 {
3413   return (array_value_internal (s, 0, allow_all));
3414 }
3415
3416 static int
3417 array_length_reference (s)
3418      char *s;
3419 {
3420   int ind, len;
3421   char *t;
3422   ARRAY *array;
3423   SHELL_VAR *var;
3424
3425   var = array_variable_part (s, &t, &len);
3426
3427   /* If unbound variables should generate an error, report one and return
3428      failure. */
3429   if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
3430     {
3431       ind = *--t;
3432       *t = '\0';
3433       report_error ("%s: unbound variable", s);
3434       *t++ = (char)ind;
3435       return (-1);
3436     }
3437   else if (var == 0)
3438     return 0;
3439   else if (array_p (var) == 0)
3440     return 1;
3441
3442   array = array_cell (var);
3443
3444   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3445     return (array_num_elements (array));
3446
3447   ind = array_expand_index (t, len);
3448   if (ind < 0)
3449     {
3450       report_error ("%s: bad array subscript", t);
3451       return (-1);
3452     }
3453   t = array_reference (array, ind);
3454   len = STRLEN (t);
3455
3456   return (len);
3457 }
3458 #endif /* ARRAY_VARS */
3459
3460 static int
3461 valid_brace_expansion_word (name, var_is_special)
3462      char *name;
3463      int var_is_special;
3464 {
3465   if (digit (*name) && all_digits (name))
3466     return 1;
3467   else if (var_is_special)
3468     return 1;
3469 #if defined (ARRAY_VARS)
3470   else if (valid_array_reference (name))
3471     return 1;
3472 #endif /* ARRAY_VARS */
3473   else if (legal_identifier (name))
3474     return 1;
3475   else
3476     return 0;
3477 }
3478
3479 /* Parameter expand NAME, and return a new string which is the expansion,
3480    or NULL if there was no expansion.
3481    VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
3482    the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
3483    NAME was found inside of a double-quoted expression. */
3484 static char *
3485 parameter_brace_expand_word (name, var_is_special, quoted)
3486      char *name;
3487      int var_is_special, quoted;
3488 {
3489   char *temp, *tt;
3490   int arg_index;
3491   SHELL_VAR *var;
3492   WORD_LIST *l;
3493
3494   /* Handle multiple digit arguments, as in ${11}. */
3495   if (digit (*name))
3496     {
3497       arg_index = atoi (name);
3498       temp = get_dollar_var_value (arg_index);
3499     }
3500   else if (var_is_special)      /* ${@} */
3501     {
3502       int sindex;
3503       tt = xmalloc (2 + strlen (name));
3504       tt[sindex = 0] = '$';
3505       strcpy (tt + 1, name);
3506 #if 0
3507       l = expand_string_leave_quoted (tt, quoted);
3508       free (tt);
3509       temp = string_list (l);
3510       dispose_words (l);
3511 #else
3512       temp = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
3513                            (int *)NULL, (int *)NULL, 0);
3514       free (tt);
3515 #endif
3516     }
3517 #if defined (ARRAY_VARS)
3518   else if (valid_array_reference (name))
3519     {
3520       temp = array_value (name, quoted);
3521     }
3522 #endif
3523   else if (var = find_variable (name))
3524     {
3525       if (var && invisible_p (var) == 0)
3526         {
3527 #if defined (ARRAY_VARS)
3528           temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
3529 #else
3530           temp = value_cell (var);
3531 #endif
3532
3533           if (temp)
3534             temp = quote_escapes (temp);
3535
3536           if (tempvar_p (var))
3537             dispose_variable (var);
3538         }
3539       else
3540         temp = (char *)NULL;
3541     }
3542   else
3543     temp = (char *)NULL;
3544
3545   return (temp);
3546 }
3547
3548 /* Expand an indirect reference to a variable: ${!NAME} expands to the
3549    value of the variable whose name is the value of NAME. */
3550 static char *
3551 parameter_brace_expand_indir (name, var_is_special, quoted)
3552      char *name;
3553      int var_is_special, quoted;
3554 {
3555   char *temp, *t;
3556
3557   t = parameter_brace_expand_word (name, var_is_special, quoted);
3558   if (t == 0)
3559     return (t);
3560   temp = parameter_brace_expand_word (t, t[0] == '@' && t[1] == '\0', quoted);
3561   free (t);
3562   return temp;
3563 }
3564
3565 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
3566    depending on the value of C, the separating character.  C can be one of
3567    "-", "+", or "=".  QUOTED is true if the entire brace expression occurs
3568    between double quotes. */
3569 static char *
3570 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
3571      char *name, *value;
3572      int c, quoted, *qdollaratp, *hasdollarat;
3573 {
3574   WORD_LIST *l;
3575   char *t, *t1, *temp;
3576   int hasdol;
3577
3578   temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
3579         ? bash_tilde_expand (value)
3580         : savestring (value);
3581
3582   /* If the entire expression is between double quotes, we want to treat
3583      the value as a double-quoted string, with the exception that we strip
3584      embedded unescaped double quotes. */
3585   if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *temp)
3586     {
3587       hasdol = 0;
3588       t = string_extract_double_quoted (temp, &hasdol, 1);
3589       free (temp);
3590       temp = t;
3591     }
3592
3593   hasdol = 0;
3594   /* XXX was 0 not quoted */
3595   l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
3596             : (WORD_LIST *)0;
3597   if (hasdollarat)
3598     *hasdollarat = hasdol || (l && l->next);
3599   free (temp);
3600   if (l)
3601     {
3602       /* The expansion of TEMP returned something.  We need to treat things
3603           slightly differently if HASDOL is non-zero. */
3604       temp = string_list (l);
3605       /* If l->next is not null, we know that TEMP contained "$@", since that
3606          is the only expansion that creates more than one word. */
3607       if ((hasdol && quoted) || l->next)
3608         *qdollaratp = 1;
3609       dispose_words (l);
3610     }
3611   else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
3612     {
3613       /* The brace expansion occurred between double quotes and there was
3614          a $@ in TEMP.  It does not matter if the $@ is quoted, as long as
3615          it does not expand to anything.  In this case, we want to return
3616          a quoted empty string. */
3617       temp = xmalloc (2);
3618       temp[0] = CTLNUL;
3619       temp[1] = '\0';
3620     }
3621   else
3622     temp = (char *)NULL;
3623
3624   if (c == '-' || c == '+')
3625     return (temp);
3626
3627   /* c == '=' */
3628   t = temp ? savestring (temp) : savestring ("");
3629   t1 = dequote_string (t);
3630   free (t);
3631   bind_variable (name, t1);
3632   free (t1);
3633   return (temp);
3634 }
3635
3636 /* Deal with the right hand side of a ${name:?value} expansion in the case
3637    that NAME is null or not set.  If VALUE is non-null it is expanded and
3638    used as the error message to print, otherwise a standard message is
3639    printed. */
3640 static void
3641 parameter_brace_expand_error (name, value)
3642      char *name, *value;
3643 {
3644   WORD_LIST *l;
3645   char *temp;
3646
3647   if (value && *value)
3648     {
3649       l = expand_string (value, 0);
3650       temp =  string_list (l);
3651       report_error ("%s: %s", name, temp ? temp : "");  /* XXX was value not "" */
3652       FREE (temp);
3653       dispose_words (l);
3654     }
3655   else
3656     report_error ("%s: parameter null or not set", name);
3657
3658   /* Free the data we have allocated during this expansion, since we
3659      are about to longjmp out. */
3660   free (name);
3661   FREE (value);
3662 }
3663
3664 /* Return 1 if NAME is something for which parameter_brace_expand_length is
3665    OK to do. */
3666 static int
3667 valid_length_expression (name)
3668      char *name;
3669 {
3670   return (!name[1] ||                                           /* ${#} */
3671           ((name[1] == '@' || name[1] == '*') && !name[2]) ||   /* ${#@}, ${#*} */
3672           (member (name[1], "-?$!#") && !name[2]) ||            /* ${#-}, etc. */
3673           (digit (name[1]) && all_digits (name + 1)) ||         /* ${#11} */
3674 #if defined (ARRAY_VARS)
3675           valid_array_reference (name + 1) ||                   /* ${#a[7]} */
3676 #endif
3677           legal_identifier (name + 1));                         /* ${#PS1} */
3678 }
3679
3680 /* Handle the parameter brace expansion that requires us to return the
3681    length of a parameter. */
3682 static int
3683 parameter_brace_expand_length (name)
3684      char *name;
3685 {
3686   char *t, *newname;
3687   int number;
3688   WORD_LIST *list;
3689 #if defined (ARRAY_VARS)
3690   SHELL_VAR *var;
3691 #endif
3692
3693   if (name[1] == '\0')                  /* ${#} */
3694     number = number_of_args ();
3695   else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0')       /* ${#@}, ${#*} */
3696     number = number_of_args ();
3697   else if (member (name[1], "-?$!#") && name[2] == '\0')
3698     {
3699       /* Take the lengths of some of the shell's special parameters. */
3700       switch (name[1])
3701         {
3702         case '-':
3703           t = which_set_flags ();
3704           break;
3705         case '?':
3706           t = itos (last_command_exit_value);
3707           break;
3708         case '$':
3709           t = itos (dollar_dollar_pid);
3710           break;
3711         case '!':
3712           if (last_asynchronous_pid == NO_PID)
3713             t = (char *)NULL;
3714           else
3715             t = itos ((int)last_asynchronous_pid);
3716           break;
3717         case '#':
3718           t = itos (number_of_args ());
3719           break;
3720         }
3721       number = STRLEN (t);
3722       FREE (t);
3723     }
3724 #if defined (ARRAY_VARS)
3725   else if (valid_array_reference (name + 1))
3726     number = array_length_reference (name + 1);
3727 #endif /* ARRAY_VARS */
3728   else
3729     {
3730       number = 0;
3731
3732       if (digit (name[1]))              /* ${#1} */
3733         {
3734           t = get_dollar_var_value (atoi (name + 1));
3735           number = STRLEN (t);
3736           FREE (t);
3737         }
3738 #if defined (ARRAY_VARS)
3739       else if ((var = find_variable (name + 1)) && array_p (var))
3740         {
3741           t = array_reference (array_cell (var), 0);
3742           number = STRLEN (t);
3743         }
3744 #endif
3745       else                              /* ${#PS1} */
3746         {
3747           newname = savestring (name);
3748           newname[0] = '$';
3749           list = expand_string (newname, Q_DOUBLE_QUOTES);
3750           t = list ? string_list (list) : (char *)NULL;
3751           free (newname);
3752           if (list)
3753             dispose_words (list);
3754
3755           number = STRLEN (t);
3756           FREE (t);
3757         }
3758     }
3759
3760   return (number);
3761 }
3762
3763 /* Verify and limit the start and end of the desired substring.  If
3764    VTYPE == 0, a regular shell variable is being used; if it is 1,
3765    then the positional parameters are being used; if it is 2, then
3766    VALUE is really a pointer to an array variable that should be used.
3767    Return value is 1 if both values were OK, 0 if there was a problem
3768    with an invalid expression, or -1 if the values were out of range. */
3769 static int
3770 verify_substring_values (value, substr, vtype, e1p, e2p)
3771      char *value, *substr;
3772      int vtype, *e1p, *e2p;
3773 {
3774   char *t, *temp1;
3775   int len, expok;
3776 #if defined (ARRAY_VARS)
3777  ARRAY *a;
3778 #endif
3779
3780   t = strchr (substr, ':');
3781   if (t)
3782     *t = '\0';
3783   temp1 = maybe_expand_string (substr, Q_DOUBLE_QUOTES, expand_string);
3784   *e1p = evalexp (temp1, &expok);
3785   free (temp1);
3786   if (expok == 0)
3787     return (0);
3788
3789   switch (vtype)
3790     {
3791     case VT_VARIABLE:
3792     case VT_ARRAYMEMBER:
3793       len = strlen (value);
3794       break;
3795     case VT_POSPARMS:
3796       len = number_of_args () + 1;
3797       break;
3798 #if defined (ARRAY_VARS)
3799     case VT_ARRAYVAR:
3800       a = (ARRAY *)value;
3801       len = array_num_elements (a) + 1;
3802       break;
3803 #endif
3804     }
3805
3806   if (*e1p < 0)         /* negative offsets count from end */
3807     *e1p += len;
3808
3809   if (*e1p >= len || *e1p < 0)
3810     return (-1);
3811
3812   if (t)
3813     {
3814       t++;
3815       temp1 = maybe_expand_string (t, Q_DOUBLE_QUOTES, expand_string);
3816       t[-1] = ':';
3817       *e2p = evalexp (temp1, &expok);
3818       free (temp1);
3819       if (expok == 0)
3820         return (0);
3821       if (*e2p < 0)
3822         {
3823           internal_error ("%s: substring expression < 0", t);
3824           return (0);
3825         }
3826       *e2p += *e1p;             /* want E2 chars starting at E1 */
3827       if (*e2p > len)
3828         *e2p = len;
3829     }
3830   else
3831     *e2p = len;
3832
3833   return (1);
3834 }
3835
3836 /* Return the type of variable specified by VARNAME (simple variable,
3837    positional param, or array variable).  Also return the value specified
3838    by VARNAME (value of a variable or a reference to an array element). */
3839 static int
3840 get_var_and_type (varname, value, varp, valp)
3841      char *varname, *value;
3842      SHELL_VAR **varp;
3843      char **valp;
3844 {
3845   int vtype;
3846   char *temp;
3847 #if defined (ARRAY_VARS)
3848   SHELL_VAR *v;
3849 #endif
3850
3851   vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';       /* VT_POSPARMS */
3852   *varp = (SHELL_VAR *)NULL;
3853
3854 #if defined (ARRAY_VARS)
3855   if (valid_array_reference (varname))
3856     {
3857       v = array_variable_part (varname, &temp, (int *)0);
3858       if (v && array_p (v))
3859         {
3860           if ((temp[0] == '@' || temp[0] == '*') && temp[1] == ']')
3861             {
3862               vtype = VT_ARRAYVAR;
3863               *valp = (char *)array_cell (v);
3864             }
3865           else
3866             {
3867               vtype = VT_ARRAYMEMBER;
3868               *valp = array_value (varname, 1);
3869             }
3870           *varp = v;
3871         }
3872       else
3873         return -1;
3874     }
3875   else if ((v = find_variable (varname)) && array_p (v))
3876     {
3877       vtype = VT_VARIABLE;
3878       *varp = v;
3879       *valp = array_reference (array_cell (v), 0);
3880     }
3881   else
3882 #endif
3883   *valp = value;
3884
3885   return vtype;
3886 }
3887
3888 /******************************************************/
3889 /*                                                    */
3890 /* Functions to extract substrings of variable values */
3891 /*                                                    */
3892 /******************************************************/
3893
3894 /* Process a variable substring expansion: ${name:e1[:e2]}.  If VARNAME
3895    is `@', use the positional parameters; otherwise, use the value of
3896    VARNAME.  If VARNAME is an array variable, use the array elements. */
3897
3898 static char *
3899 parameter_brace_substring (varname, value, substr, quoted)
3900      char *varname, *value, *substr;
3901      int quoted;
3902 {
3903   int e1, e2, vtype, r;
3904   char *temp, *val;
3905   SHELL_VAR *v;
3906
3907   if (value == 0)
3908     return ((char *)NULL);
3909
3910   this_command_name = varname;
3911
3912   vtype = get_var_and_type (varname, value, &v, &val);
3913   if (vtype == -1)
3914     return ((char *)NULL);
3915
3916   r = verify_substring_values (val, substr, vtype, &e1, &e2);
3917   if (r <= 0)
3918     {
3919       if (val && vtype == VT_ARRAYMEMBER)
3920         free (val);
3921       return ((r == 0) ? &expand_param_error : (char *)NULL);
3922     }
3923
3924   switch (vtype)
3925     {
3926     case VT_VARIABLE:
3927     case VT_ARRAYMEMBER:
3928       temp = quoted ? quoted_substring (value, e1, e2) : substring (value, e1, e2);
3929       break;
3930     case VT_POSPARMS:
3931       temp = pos_params (varname, e1, e2, quoted);
3932       break;
3933 #if defined (ARRAY_VARS)
3934     case VT_ARRAYVAR:
3935       temp = array_subrange (array_cell (v), e1, e2, quoted);
3936       break;
3937 #endif
3938     }
3939
3940   return temp;
3941 }
3942
3943 /****************************************************************/
3944 /*                                                              */
3945 /* Functions to perform pattern substitution on variable values */
3946 /*                                                              */
3947 /****************************************************************/
3948
3949 char *
3950 pat_subst (string, pat, rep, mflags)
3951      char *string, *pat, *rep;
3952      int mflags;
3953 {
3954   char *ret, *s, *e, *str;
3955   int rsize, rptr, l, replen, mtype;
3956
3957   ret = xmalloc (rsize = 64);
3958   ret[0] = '\0';
3959
3960   mtype = mflags & MATCH_TYPEMASK;
3961
3962   for (replen = STRLEN (rep), rptr = 0, str = string;;)
3963     {
3964       if (match_pattern (str, pat, mtype, &s, &e) == 0)
3965         break;
3966       l = s - str;
3967       RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
3968
3969       /* OK, now copy the leading unmatched portion of the string (from
3970          str to s) to ret starting at rptr (the current offset).  Then copy
3971          the replacement string at ret + rptr + (s - str).  Increment
3972          rptr (if necessary) and str and go on. */
3973       if (l)
3974         {
3975           strncpy (ret + rptr, str, l);
3976           rptr += l;
3977         }
3978       if (replen)
3979         {
3980           strncpy (ret + rptr, rep, replen);
3981           rptr += replen;
3982         }
3983       str = e;          /* e == end of match */
3984       if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
3985         break;
3986     }
3987
3988   /* Now copy the unmatched portion of the input string */
3989   if (*str)
3990     {
3991       RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
3992       strcpy (ret + rptr, str);
3993     }
3994   else
3995     ret[rptr] = '\0';
3996
3997   return ret;
3998 }
3999
4000 /* Do pattern match and replacement on the positional parameters. */
4001 static char *
4002 pos_params_pat_subst (string, pat, rep, mflags)
4003      char *string, *pat, *rep;
4004      int mflags;
4005 {
4006   WORD_LIST *save, *params;
4007   WORD_DESC *w;
4008   char *ret;
4009
4010   save = params = list_rest_of_args ();
4011   if (save == 0)
4012     return ((char *)NULL);
4013
4014   for ( ; params; params = params->next)
4015     {
4016       ret = pat_subst (params->word->word, pat, rep, mflags);
4017       w = make_bare_word (ret);
4018       dispose_word (params->word);
4019       params->word = w;
4020       FREE (ret);
4021     }
4022
4023   ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
4024   dispose_words (save);
4025
4026   return (ret);
4027 }
4028
4029 /* Perform pattern substitution on VALUE, which is the expansion of
4030    VARNAME.  PATSUB is an expression supplying the pattern to match
4031    and the string to substitute.  QUOTED is a flags word containing
4032    the type of quoting currently in effect. */
4033 static char *
4034 parameter_brace_patsub (varname, value, patsub, quoted)
4035      char *varname, *value, *patsub;
4036      int quoted;
4037 {
4038   int vtype, mflags;
4039   char *val, *temp, *pat, *rep, *p;
4040   SHELL_VAR *v;
4041
4042   if (value == 0)
4043     return ((char *)NULL);
4044
4045   this_command_name = varname;
4046
4047   vtype = get_var_and_type (varname, value, &v, &val);
4048   if (vtype == -1)
4049     return ((char *)NULL);
4050
4051   mflags = 0;
4052   if (*patsub == '/')
4053     {
4054       mflags |= MATCH_GLOBREP;
4055       patsub++;
4056     }
4057
4058   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4059     mflags |= MATCH_QUOTED;
4060
4061   if (rep = quoted_strchr (patsub, '/', ST_BACKSL))
4062     *rep++ = '\0';
4063   else
4064     rep = (char *)NULL;
4065
4066   if (rep && *rep == '\0')
4067     rep = (char *)NULL;
4068
4069   /* Expand PAT and REP for command, variable and parameter, arithmetic,
4070      and process substitution.  Also perform quote removal.  Do not
4071      perform word splitting or filename generation. */
4072 #if 0
4073   pat = maybe_expand_string (patsub, quoted, expand_string_unsplit);
4074 #else
4075   pat = maybe_expand_string (patsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit);
4076 #endif
4077   if (rep)
4078     {
4079       if ((mflags & MATCH_QUOTED) == 0)
4080         rep = maybe_expand_string (rep, quoted, expand_string_unsplit);
4081       else
4082         rep = expand_string_to_string (rep, quoted, expand_string_unsplit);
4083     }
4084
4085   p = pat;
4086   if (pat && pat[0] == '#')
4087     {
4088       mflags |= MATCH_BEG;
4089       p++;
4090     }
4091   else if (pat && pat[0] == '%')
4092     {
4093       mflags |= MATCH_END;
4094       p++;
4095     }
4096   else
4097     mflags |= MATCH_ANY;
4098
4099   /* OK, we now want to substitute REP for PAT in VAL.  If
4100      flags & MATCH_GLOBREP is non-zero, the substitution is done
4101      everywhere, otherwise only the first occurrence of PAT is
4102      replaced. */
4103   switch (vtype)
4104     {
4105     case VT_VARIABLE:
4106     case VT_ARRAYMEMBER:
4107       temp = pat_subst (val, p, rep, mflags);
4108       break;
4109     case VT_POSPARMS:
4110       temp = pos_params_pat_subst (val, p, rep, mflags);
4111       break;
4112 #if defined (ARRAY_VARS)
4113     case VT_ARRAYVAR:
4114       temp = array_pat_subst (array_cell (v), p, rep, mflags);
4115       break;
4116 #endif
4117     }
4118
4119   if (val && v && array_p (v) && vtype == VT_ARRAYMEMBER)
4120     free (val);
4121
4122   FREE (pat);
4123   FREE (rep);
4124
4125   return temp;
4126 }
4127
4128 /****************************************************************/
4129 /*                                                              */
4130 /*      Functions to perform parameter expansion on a string    */
4131 /*                                                              */
4132 /****************************************************************/
4133
4134 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
4135 static char *
4136 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
4137      char *string;
4138      int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
4139 {
4140   int check_nullness, var_is_set, var_is_null, var_is_special;
4141   int want_substring, want_indir, want_patsub;
4142   char *name, *value, *temp, *temp1;
4143   int t_index, sindex, c, number;
4144
4145   value = (char *)NULL;
4146   var_is_set = var_is_null = var_is_special = check_nullness = 0;
4147   want_substring = want_indir = want_patsub = 0;
4148
4149   sindex = *indexp;
4150   t_index = ++sindex;
4151   name = string_extract (string, &t_index, "#%:-=?+/}", 1);
4152
4153   /* If the name really consists of a special variable, then make sure
4154      that we have the entire name.  We don't allow indirect references
4155      to special variables except `#', `?', `@' and `*'. */
4156   if ((sindex == t_index &&
4157         (string[t_index] == '-' ||
4158          string[t_index] == '?' ||
4159          string[t_index] == '#')) ||
4160       (sindex == t_index - 1 && string[sindex] == '!' &&
4161         (string[t_index] == '#' ||
4162          string[t_index] == '?' ||
4163          string[t_index] == '@' ||
4164          string[t_index] == '*')))
4165     {
4166       t_index++;
4167       free (name);
4168       temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
4169       name = xmalloc (3 + (strlen (temp1)));
4170       *name = string[sindex];
4171       if (string[sindex] == '!')
4172         {
4173           /* indirect reference of $#, $?, $@, or $* */
4174           name[1] = string[sindex + 1];
4175           strcpy (name + 2, temp1);
4176         }
4177       else      
4178         strcpy (name + 1, temp1);
4179       free (temp1);
4180     }
4181   sindex = t_index;
4182
4183   /* Find out what character ended the variable name.  Then
4184      do the appropriate thing. */
4185   if (c = string[sindex])
4186     sindex++;
4187
4188   /* If c is followed by one of the valid parameter expansion
4189      characters, move past it as normal.  If not, assume that
4190      a substring specification is being given, and do not move
4191      past it. */
4192   if (c == ':' && member (string[sindex], "-=?+"))
4193     {
4194       check_nullness++;
4195       if (c = string[sindex])
4196         sindex++;
4197     }
4198   else if (c == ':' && string[sindex] != RBRACE)
4199     want_substring = 1;
4200   else if (c == '/' && string[sindex] != RBRACE)
4201     want_patsub = 1;
4202
4203   /* Catch the valid and invalid brace expressions that made it through the
4204      tests above. */
4205   /* ${#-} is a valid expansion and means to take the length of $-.
4206      Similarly for ${#?} and ${##}... */
4207   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4208         member (c, "-?#") && string[sindex] == RBRACE)
4209     {
4210       name = xrealloc (name, 3);
4211       name[1] = c;
4212       name[2] = '\0';
4213       c = string[sindex++];
4214     }
4215
4216   /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
4217   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4218         member (c, "%:=+/") && string[sindex] == RBRACE)
4219     {
4220       temp = (char *)NULL;
4221       goto bad_substitution;
4222     }
4223
4224   /* Indirect expansion begins with a `!'.  A valid indirect expansion is
4225      either a variable name, one of the positional parameters or a special
4226      variable that expands to one of the positional parameters. */
4227   want_indir = *name == '!' &&
4228     (legal_variable_starter (name[1]) || digit (name[1]) || member (name[1], "#?@*"));
4229
4230   /* Determine the value of this variable. */
4231
4232   /* Check for special variables, directly referenced. */
4233   if ((digit (*name) && all_digits (name)) ||
4234       (name[1] == '\0' && member (*name, "#-?$!@*")) ||
4235       (want_indir && name[2] == '\0' && member (name[1], "#?@*")))
4236     var_is_special++;
4237
4238   /* Check for special expansion things, like the length of a parameter */
4239   if (*name == '#' && name[1])
4240     {
4241       /* If we are not pointing at the character just after the
4242          closing brace, then we haven't gotten all of the name.
4243          Since it begins with a special character, this is a bad
4244          substitution.  Also check NAME for validity before trying
4245          to go on. */
4246       if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
4247         {
4248           temp = (char *)NULL;
4249           goto bad_substitution;
4250         }
4251
4252       number = parameter_brace_expand_length (name);
4253       free (name);
4254
4255       *indexp = sindex;
4256       return ((number < 0) ? &expand_param_error : itos (number));
4257     }
4258
4259   /* ${@} is identical to $@. */
4260   if (name[0] == '@' && name[1] == '\0')
4261     {
4262       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4263         *quoted_dollar_atp = 1;
4264
4265       if (contains_dollar_at)
4266         *contains_dollar_at = 1;
4267     }
4268
4269   /* Make sure that NAME is valid before trying to go on. */
4270   if (valid_brace_expansion_word (want_indir ? name + 1 : name,
4271                                         var_is_special) == 0)
4272     {
4273       temp = (char *)NULL;
4274       goto bad_substitution;
4275     }
4276
4277   if (want_indir)
4278     temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted);
4279   else
4280     temp = parameter_brace_expand_word (name, var_is_special, quoted);
4281
4282 #if defined (ARRAY_VARS)
4283 #if 0
4284   if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && valid_array_reference (name))
4285 #else
4286   if (valid_array_reference (name))
4287 #endif
4288     {
4289       temp1 = strchr (name, '[');
4290       if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4291         {
4292           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4293             *quoted_dollar_atp = 1;
4294           if (contains_dollar_at)
4295             *contains_dollar_at = 1;
4296         }       /* [ */
4297       /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4298          which should result in separate words even when IFS is unset. */
4299       if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4300         {
4301           if (contains_dollar_at)
4302             *contains_dollar_at = 1;
4303         }
4304     }
4305 #endif
4306
4307   var_is_set = temp != (char *)0;
4308   var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
4309
4310   /* Get the rest of the stuff inside the braces. */
4311   if (c && c != RBRACE)
4312     {
4313       /* Extract the contents of the ${ ... } expansion
4314          according to the Posix.2 rules. */
4315       value = extract_dollar_brace_string (string, &sindex, quoted);
4316       if (string[sindex] == RBRACE)
4317         sindex++;
4318       else
4319         goto bad_substitution;
4320     }
4321   else
4322     value = (char *)NULL;
4323
4324   *indexp = sindex;
4325
4326   /* If this is a substring spec, process it and add the result. */
4327   if (want_substring)
4328     {
4329       temp1 = parameter_brace_substring (name, temp, value, quoted);
4330       FREE (name);
4331       FREE (value);
4332       FREE (temp);
4333       return (temp1);
4334     }
4335   else if (want_patsub)
4336     {
4337       temp1 = parameter_brace_patsub (name, temp, value, quoted);
4338       FREE (name);
4339       FREE (value);
4340       FREE (temp);
4341       return (temp1);
4342     }
4343
4344   /* Do the right thing based on which character ended the variable name. */
4345   switch (c)
4346     {
4347     default:
4348     case '\0':
4349     bad_substitution:
4350       report_error ("%s: bad substitution", string ? string : "??");
4351       FREE (value);
4352       FREE (temp);
4353       free (name);
4354       return &expand_param_error;
4355
4356     case RBRACE:
4357       if (var_is_set == 0 && unbound_vars_is_error)
4358         {
4359           report_error ("%s: unbound variable", name);
4360           FREE (value);
4361           FREE (temp);
4362           free (name);
4363           last_command_exit_value = EXECUTION_FAILURE;
4364           return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4365         }
4366       break;
4367
4368     case '#':   /* ${param#[#]pattern} */
4369     case '%':   /* ${param%[%]pattern} */
4370       if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
4371         {
4372           FREE (value);
4373           break;
4374         }
4375       if ((name[0] == '@' || name[0] == '*') && name[1] == '\0')
4376         temp1 = parameter_list_remove_pattern (value, name[0], c, quoted);
4377 #if defined (ARRAY_VARS)
4378       else if (valid_array_reference (name))
4379         temp1 = array_remove_pattern (value, name, temp, c, quoted);
4380 #endif
4381       else
4382         temp1 = parameter_brace_remove_pattern (value, temp, c, quoted);
4383       free (temp);
4384       free (value);
4385       temp = temp1;
4386       break;
4387
4388     case '-':
4389     case '=':
4390     case '?':
4391     case '+':
4392       if (var_is_set && var_is_null == 0)
4393         {
4394           /* We don't want the value of the named variable for
4395              anything, just the value of the right hand side. */
4396           if (c == '+')
4397             {
4398               FREE (temp);
4399               if (value)
4400                 {
4401                   temp = parameter_brace_expand_rhs (name, value, c,
4402                                                      quoted,
4403                                                      quoted_dollar_atp,
4404                                                      contains_dollar_at);
4405                   free (value);
4406                 }
4407               else
4408                 temp = (char *)NULL;
4409             }
4410           else
4411             {
4412               FREE (value);
4413             }
4414           /* Otherwise do nothing; just use the value in TEMP. */
4415         }
4416       else      /* VAR not set or VAR is NULL. */
4417         {
4418           FREE (temp);
4419           temp = (char *)NULL;
4420           if (c == '=' && var_is_special)
4421             {
4422               report_error ("$%s: cannot assign in this way", name);
4423               free (name);
4424               free (value);
4425               return &expand_param_error;
4426             }
4427           else if (c == '?')
4428             {
4429               parameter_brace_expand_error (name, value);
4430               return (interactive ? &expand_param_error : &expand_param_fatal);
4431             }
4432           else if (c != '+')
4433             temp = parameter_brace_expand_rhs (name, value, c, quoted,
4434                                                quoted_dollar_atp,
4435                                                contains_dollar_at);
4436           free (value);
4437         }
4438       break;
4439     }
4440   free (name);
4441   return (temp);
4442 }
4443
4444 /* Expand a single ${xxx} expansion.  The braces are optional.  When
4445    the braces are used, parameter_brace_expand() does the work,
4446    possibly calling param_expand recursively. */
4447 static char *
4448 param_expand (string, sindex, quoted, expanded_something,
4449               contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
4450               pflags)
4451      char *string;
4452      int *sindex, quoted, *expanded_something, *contains_dollar_at;
4453      int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
4454 {
4455   char *temp, *temp1;
4456   int zindex, number, c, t_index, expok;
4457   SHELL_VAR *var;
4458   WORD_LIST *list, *tlist;
4459
4460   zindex = *sindex;
4461   c = string[++zindex];
4462
4463   temp = (char *)NULL;
4464
4465   /* Do simple cases first. Switch on what follows '$'. */
4466   switch (c)
4467     {
4468     /* $0 .. $9? */
4469     case '0':
4470     case '1':
4471     case '2':
4472     case '3':
4473     case '4':
4474     case '5':
4475     case '6':
4476     case '7':
4477     case '8':
4478     case '9':
4479       temp1 = dollar_vars[digit_value (c)];
4480       if (unbound_vars_is_error && temp1 == (char *)NULL)
4481         {
4482           report_error ("$%c: unbound variable", c);
4483           last_command_exit_value = EXECUTION_FAILURE;
4484           return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4485         }
4486       temp = temp1 ? savestring (temp1) : (char *)NULL;
4487       break;
4488
4489     /* $$ -- pid of the invoking shell. */
4490     case '$':
4491       temp = itos (dollar_dollar_pid);
4492       break;
4493
4494     /* $# -- number of positional parameters. */
4495     case '#':
4496       temp = itos (number_of_args ());
4497       break;
4498
4499     /* $? -- return value of the last synchronous command. */
4500     case '?':
4501       temp = itos (last_command_exit_value);
4502       break;
4503
4504     /* $- -- flags supplied to the shell on invocation or by `set'. */
4505     case '-':
4506       temp = which_set_flags ();
4507       break;
4508
4509       /* $! -- Pid of the last asynchronous command. */
4510     case '!':
4511       /* If no asynchronous pids have been created, expand to nothing.
4512          If `set -u' has been executed, and no async processes have
4513          been created, this is an expansion error. */
4514       if (last_asynchronous_pid == NO_PID)
4515         {
4516           if (expanded_something)
4517             *expanded_something = 0;
4518           temp = (char *)NULL;
4519           if (unbound_vars_is_error)
4520             {
4521               report_error ("$%c: unbound variable", c);
4522               last_command_exit_value = EXECUTION_FAILURE;
4523               return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4524             }
4525         }
4526       else
4527         temp = itos ((int)last_asynchronous_pid);
4528       break;
4529
4530     /* The only difference between this and $@ is when the arg is quoted. */
4531     case '*':           /* `$*' */
4532       list = list_rest_of_args ();
4533
4534       /* If there are no command-line arguments, this should just
4535          disappear if there are other characters in the expansion,
4536          even if it's quoted. */
4537       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
4538         temp = (char *)NULL;
4539       else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4540         {
4541           /* If we have "$*" we want to make a string of the positional
4542              parameters, separated by the first character of $IFS, and
4543              quote the whole string, including the separators.  If IFS
4544              is unset, the parameters are separated by ' '; if $IFS is
4545              null, the parameters are concatenated. */
4546           temp = string_list_dollar_star (list);
4547           temp1 = quote_string (temp);
4548           free (temp);
4549           temp = temp1;
4550         }
4551       else
4552         {
4553           /* If the $* is not quoted it is identical to $@ */
4554           temp = string_list_dollar_at (list, quoted);
4555           if (contains_dollar_at)
4556             *contains_dollar_at = 1;
4557         }
4558
4559       dispose_words (list);
4560       break;
4561
4562     /* When we have "$@" what we want is "$1" "$2" "$3" ... This
4563        means that we have to turn quoting off after we split into
4564        the individually quoted arguments so that the final split
4565        on the first character of $IFS is still done.  */
4566     case '@':           /* `$@' */
4567       list = list_rest_of_args ();
4568
4569       /* We want to flag the fact that we saw this.  We can't turn
4570          off quoting entirely, because other characters in the
4571          string might need it (consider "\"$@\""), but we need some
4572          way to signal that the final split on the first character
4573          of $IFS should be done, even though QUOTED is 1. */
4574       if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
4575         *quoted_dollar_at_p = 1;
4576       if (contains_dollar_at)
4577         *contains_dollar_at = 1;
4578
4579       /* We want to separate the positional parameters with the first
4580          character of $IFS in case $IFS is something other than a space.
4581          We also want to make sure that splitting is done no matter what --
4582          according to POSIX.2, this expands to a list of the positional
4583          parameters no matter what IFS is set to. */
4584       temp = string_list_dollar_at (list, quoted);
4585
4586       dispose_words (list);
4587       break;
4588
4589     case LBRACE:
4590       temp = parameter_brace_expand (string, &zindex, quoted,
4591                                      quoted_dollar_at_p,
4592                                      contains_dollar_at);
4593       if (temp == &expand_param_error || temp == &expand_param_fatal)
4594         return (temp);
4595
4596       /* XXX */
4597       /* quoted nulls should be removed if there is anything else
4598          in the string. */
4599       /* Note that we saw the quoted null so we can add one back at
4600          the end of this function if there are no other characters
4601          in the string, discard TEMP, and go on. */
4602       if (temp && QUOTED_NULL (temp))
4603         {
4604           if (had_quoted_null_p)
4605             *had_quoted_null_p = 1;
4606           free (temp);
4607           temp = (char *)NULL;
4608         }
4609
4610       goto return0;
4611
4612     /* Do command or arithmetic substitution. */
4613     case LPAREN:
4614       /* We have to extract the contents of this paren substitution. */
4615       t_index = zindex + 1;
4616       temp = extract_command_subst (string, &t_index);
4617       zindex = t_index;
4618
4619       /* For Posix.2-style `$(( ))' arithmetic substitution,
4620          extract the expression and pass it to the evaluator. */
4621       if (temp && *temp == LPAREN)
4622         {
4623           char *temp2;
4624           temp1 = temp + 1;
4625           temp2 = savestring (temp1);
4626           t_index = strlen (temp2) - 1;
4627
4628           if (temp2[t_index] != RPAREN)
4629             {
4630               free (temp2);
4631               goto comsub;
4632             }
4633
4634           /* Cut off ending `)' */
4635           temp2[t_index] = '\0';
4636
4637           /* Expand variables found inside the expression. */
4638           temp1 = maybe_expand_string (temp2, Q_DOUBLE_QUOTES, expand_string);
4639           free (temp2);
4640
4641 arithsub:
4642           /* No error messages. */
4643           this_command_name = (char *)NULL;
4644           number = evalexp (temp1, &expok);
4645           free (temp);
4646           free (temp1);
4647           if (expok == 0)
4648             {
4649               if (interactive_shell == 0 && posixly_correct)
4650                 {
4651                   last_command_exit_value = EXECUTION_FAILURE;
4652                   return (&expand_param_fatal);
4653                 }
4654               else
4655                 return (&expand_param_error);
4656             }
4657           temp = itos (number);
4658           break;
4659         }
4660
4661 comsub:
4662       temp1 = command_substitute (temp, quoted);
4663       FREE (temp);
4664       temp = temp1;
4665       break;
4666
4667     /* Do POSIX.2d9-style arithmetic substitution.  This will probably go
4668        away in a future bash release. */
4669     case '[':
4670       /* We have to extract the contents of this arithmetic substitution. */
4671       t_index = zindex + 1;
4672       temp = extract_arithmetic_subst (string, &t_index);
4673       zindex = t_index;
4674
4675        /* Do initial variable expansion. */
4676       temp1 = maybe_expand_string (temp, Q_DOUBLE_QUOTES, expand_string);
4677
4678       goto arithsub;
4679
4680     default:
4681       /* Find the variable in VARIABLE_LIST. */
4682       temp = (char *)NULL;
4683
4684       for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
4685         ;
4686       temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
4687
4688       /* If this isn't a variable name, then just output the `$'. */
4689       if (temp1 == 0 || *temp1 == '\0')
4690         {
4691           FREE (temp1);
4692           temp = xmalloc (2);
4693           temp[0] = '$';
4694           temp[1] = '\0';
4695           if (expanded_something)
4696             *expanded_something = 0;
4697           goto return0;
4698         }
4699
4700       /* If the variable exists, return its value cell. */
4701       var = find_variable (temp1);
4702
4703       if (var && invisible_p (var) == 0 && value_cell (var))
4704         {
4705 #if defined (ARRAY_VARS)
4706           if (array_p (var))
4707             {
4708               temp = array_reference (array_cell (var), 0);
4709               if (temp)
4710                 temp = quote_escapes (temp);
4711             }
4712           else
4713 #endif
4714           temp = quote_escapes (value_cell (var));
4715           free (temp1);
4716           if (tempvar_p (var))          /* XXX */
4717             {
4718               dispose_variable (var);   /* XXX */
4719               var = (SHELL_VAR *)NULL;
4720             }
4721           goto return0;
4722         }
4723
4724       temp = (char *)NULL;
4725
4726       if (unbound_vars_is_error)
4727         report_error ("%s: unbound variable", temp1);
4728       else
4729         {
4730           free (temp1);
4731           goto return0;
4732         }
4733
4734       free (temp1);
4735       last_command_exit_value = EXECUTION_FAILURE;
4736       return ((unbound_vars_is_error && interactive_shell == 0)
4737                 ? &expand_param_fatal
4738                 : &expand_param_error);
4739     }
4740
4741   if (string[zindex])
4742     zindex++;
4743
4744 return0:
4745   *sindex = zindex;
4746   return (temp);
4747 }
4748
4749 /* Make a word list which is the result of parameter and variable
4750    expansion, command substitution, arithmetic substitution, and
4751    quote removal of WORD.  Return a pointer to a WORD_LIST which is
4752    the result of the expansion.  If WORD contains a null word, the
4753    word list returned is also null.
4754
4755    QUOTED contains flag values defined in shell.h.
4756
4757    CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
4758    they point to an integer value which receives information about expansion.
4759    CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
4760    EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
4761    else zero.
4762
4763    This only does word splitting in the case of $@ expansion.  In that
4764    case, we split on ' '. */
4765
4766 /* Values for the local variable quoted_state. */
4767 #define UNQUOTED         0
4768 #define PARTIALLY_QUOTED 1
4769 #define WHOLLY_QUOTED    2
4770
4771 static WORD_LIST *
4772 expand_word_internal (word, quoted, contains_dollar_at, expanded_something)
4773      WORD_DESC *word;
4774      int quoted;
4775      int *contains_dollar_at;
4776      int *expanded_something;
4777 {
4778   WORD_LIST *list;
4779   WORD_DESC *tword;
4780   SHELL_VAR *var;
4781
4782   /* The intermediate string that we build while expanding. */
4783   char *istring;
4784
4785   /* The current size of the above object. */
4786   int istring_size;
4787
4788   /* Index into ISTRING. */
4789   int istring_index;
4790
4791   /* Temporary string storage. */
4792   char *temp, *temp1;
4793
4794   /* The text of WORD. */
4795   register char *string;
4796
4797   /* The index into STRING. */
4798   int sindex;
4799
4800   /* This gets 1 if we see a $@ while quoted. */
4801   int quoted_dollar_at;
4802
4803   /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
4804      whether WORD contains no quoting characters, a partially quoted
4805      string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
4806   int quoted_state;
4807
4808   int had_quoted_null;
4809   int has_dollar_at;
4810
4811   int expok;
4812
4813   register int c;               /* Current character. */
4814   int number;                   /* Temporary number value. */
4815   int t_index;                  /* For calls to string_extract_xxx. */
4816
4817   istring = xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
4818   istring[istring_index = 0] = '\0';
4819   quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
4820   quoted_state = UNQUOTED;
4821
4822   string = word->word;
4823   if (string == 0)
4824     goto finished_with_string;
4825
4826   if (contains_dollar_at)
4827     *contains_dollar_at = 0;
4828
4829   /* Begin the expansion. */
4830
4831   for (sindex = 0; ;)
4832     {
4833       c = string[sindex];
4834
4835       /* Case on toplevel character. */
4836       switch (c)
4837         {
4838         case '\0':
4839           goto finished_with_string;
4840
4841         case CTLESC:
4842           temp = xmalloc (3);
4843           temp[0] = CTLESC;
4844           temp[1] = c = string[++sindex];
4845           temp[2] = '\0';
4846
4847 dollar_add_string:
4848           if (string[sindex])
4849             sindex++;
4850
4851 add_string:
4852           if (temp)
4853             {
4854               istring = sub_append_string (temp, istring, &istring_index, &istring_size);
4855               temp = (char *)0;
4856             }
4857
4858           break;
4859
4860 #if defined (PROCESS_SUBSTITUTION)
4861           /* Process substitution. */
4862         case '<':
4863         case '>':
4864           {
4865             if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
4866               {
4867                 sindex--;
4868                 goto add_character;
4869               }
4870             else
4871               t_index = sindex + 1; /* skip past both '<' and LPAREN */
4872
4873             temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
4874             sindex = t_index;
4875
4876             /* If the process substitution specification is `<()', we want to
4877                open the pipe for writing in the child and produce output; if
4878                it is `>()', we want to open the pipe for reading in the child
4879                and consume input. */
4880             temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
4881
4882             FREE (temp1);
4883
4884             goto dollar_add_string;
4885           }
4886 #endif /* PROCESS_SUBSTITUTION */
4887
4888         case '$':
4889           if (expanded_something)
4890             *expanded_something = 1;
4891
4892           has_dollar_at = 0;
4893           temp = param_expand (string, &sindex, quoted, expanded_something,
4894                                &has_dollar_at, &quoted_dollar_at,
4895                                &had_quoted_null, 0);
4896
4897           if (temp == &expand_param_error || temp == &expand_param_fatal)
4898             {
4899               free (string);
4900               free (istring);
4901               return ((temp == &expand_param_error) ? &expand_word_error
4902                                                     : &expand_word_fatal);
4903             }
4904           if (contains_dollar_at && has_dollar_at)
4905             *contains_dollar_at = 1;
4906           goto add_string;
4907           break;
4908
4909         case '`':               /* Backquoted command substitution. */
4910           {
4911             sindex++;
4912
4913             if (expanded_something)
4914               *expanded_something = 1;
4915
4916             temp = string_extract (string, &sindex, "`", 0);
4917             de_backslash (temp);
4918             temp1 = command_substitute (temp, quoted);
4919             FREE (temp);
4920             temp = temp1;
4921             goto dollar_add_string;
4922           }
4923
4924         case '\\':
4925           if (string[sindex + 1] == '\n')
4926             {
4927               sindex += 2;
4928               continue;
4929             }
4930
4931           c = string[++sindex];
4932
4933           if (quoted & Q_HERE_DOCUMENT)
4934             temp1 = slashify_in_here_document;
4935           else if (quoted & Q_DOUBLE_QUOTES)
4936             temp1 = slashify_in_quotes;
4937           else
4938             temp1 = "";
4939
4940           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && member (c, temp1) == 0)
4941             {
4942               temp = xmalloc (3);
4943               temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
4944             }
4945           else
4946             /* This character is quoted, so add it in quoted mode. */
4947             temp = make_quoted_char (c);
4948
4949           if (c)
4950             sindex++;
4951           goto add_string;
4952
4953         case '"':
4954           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
4955             goto add_character;
4956
4957           t_index = ++sindex;
4958           temp = string_extract_double_quoted (string, &sindex, 0);
4959
4960           /* If the quotes surrounded the entire string, then the
4961              whole word was quoted. */
4962           quoted_state = (t_index == 1 && string[sindex] == '\0')
4963                             ? WHOLLY_QUOTED
4964                             : PARTIALLY_QUOTED;
4965
4966           if (temp && *temp)
4967             {
4968               tword = make_word (temp);         /* XXX */
4969               free (temp);
4970               temp = (char *)NULL;
4971
4972               has_dollar_at = 0;
4973               list = expand_word_internal (tword, Q_DOUBLE_QUOTES, &has_dollar_at, (int *)NULL);
4974
4975               if (list == &expand_word_error || list == &expand_word_fatal)
4976                 {
4977                   free (istring);
4978                   free (string);
4979                   /* expand_word_internal has already freed temp_word->word
4980                      for us because of the way it prints error messages. */
4981                   tword->word = (char *)NULL;
4982                   dispose_word (tword);
4983                   return list;
4984                 }
4985
4986               dispose_word (tword);
4987
4988               /* "$@" (a double-quoted dollar-at) expands into nothing,
4989                  not even a NULL word, when there are no positional
4990                  parameters. */
4991               if (list == 0 && has_dollar_at)
4992                 {
4993                   quoted_dollar_at++;
4994                   break;
4995                 }
4996
4997               /* If we get "$@", we know we have expanded something, so we
4998                  need to remember it for the final split on $IFS.  This is
4999                  a special case; it's the only case where a quoted string
5000                  can expand into more than one word.  It's going to come back
5001                  from the above call to expand_word_internal as a list with
5002                  a single word, in which all characters are quoted and
5003                  separated by blanks.  What we want to do is to turn it back
5004                  into a list for the next piece of code. */
5005               if (list)
5006                 dequote_list (list);
5007
5008               if (has_dollar_at)
5009                 {
5010                   quoted_dollar_at++;
5011                   if (contains_dollar_at)
5012                     *contains_dollar_at = 1;
5013                   if (expanded_something)
5014                     *expanded_something = 1;
5015                 }
5016             }
5017           else
5018             {
5019               /* What we have is "".  This is a minor optimization. */
5020               free (temp);
5021               list = (WORD_LIST *)NULL;
5022             }
5023
5024           /* The code above *might* return a list (consider the case of "$@",
5025              where it returns "$1", "$2", etc.).  We can't throw away the
5026              rest of the list, and we have to make sure each word gets added
5027              as quoted.  We test on tresult->next:  if it is non-NULL, we
5028              quote the whole list, save it to a string with string_list, and
5029              add that string. We don't need to quote the results of this
5030              (and it would be wrong, since that would quote the separators
5031              as well), so we go directly to add_string. */
5032           if (list)
5033             {
5034               if (list->next)
5035                 {
5036                   /* Testing quoted_dollar_at makes sure that "$@" is
5037                      split correctly when $IFS does not contain a space. */
5038                   temp = quoted_dollar_at
5039                                 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
5040                                 : string_list (quote_list (list));
5041                   dispose_words (list);
5042                   goto add_string;
5043                 }
5044               else
5045                 {
5046                   temp = savestring (list->word->word);
5047                   dispose_words (list);
5048 #if 1
5049                   /* If the string is not a quoted null string, we want
5050                      to remove any embedded unquoted CTLNUL characters.
5051                      We do not want to turn quoted null strings back into
5052                      the empty string, though.  We do this because we
5053                      want to remove any quoted nulls from expansions that
5054                      contain other characters.  For example, if we have
5055                      x"$*"y or "x$*y" and there are no positional parameters,
5056                      the $* should expand into nothing. */                   
5057                   if (QUOTED_NULL (temp) == 0)
5058                     remove_quoted_nulls (temp); /* XXX */
5059 #endif
5060                 }
5061             }
5062           else
5063             temp = (char *)NULL;
5064
5065           /* We do not want to add quoted nulls to strings that are only
5066              partially quoted; we can throw them away. */
5067           if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
5068             continue;
5069
5070         add_quoted_string:
5071
5072           if (temp)
5073             {
5074               temp1 = temp;
5075               temp = quote_string (temp);
5076               free (temp1);
5077             }
5078           else
5079             {
5080               /* Add NULL arg. */
5081               temp = xmalloc (2);
5082               temp[0] = CTLNUL;
5083               temp[1] = '\0';
5084             }
5085           goto add_string;
5086           /* break; */
5087
5088         case '\'':
5089           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
5090             goto add_character;
5091
5092           t_index = ++sindex;
5093           temp = string_extract_single_quoted (string, &sindex);
5094
5095           /* If the entire STRING was surrounded by single quotes,
5096              then the string is wholly quoted. */
5097           quoted_state = (t_index == 1 && string[sindex] == '\0')
5098                             ? WHOLLY_QUOTED
5099                             : PARTIALLY_QUOTED;
5100
5101           /* If all we had was '', it is a null expansion. */
5102           if (*temp == '\0')
5103             {
5104               free (temp);
5105               temp = (char *)NULL;
5106             }
5107           else
5108             remove_quoted_escapes (temp);
5109
5110           /* We do not want to add quoted nulls to strings that are only
5111              partially quoted; such nulls are discarded. */
5112           if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
5113             continue;
5114
5115           goto add_quoted_string;
5116           /* break; */
5117
5118         default:
5119           /* This is the fix for " $@ " */
5120           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5121             {
5122               temp = make_quoted_char (c);
5123               goto dollar_add_string;
5124             }
5125
5126         add_character:
5127           RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
5128                                   DEFAULT_ARRAY_SIZE);
5129           istring[istring_index++] = c;
5130           istring[istring_index] = '\0';
5131
5132           /* Next character. */
5133           sindex++;
5134         }
5135     }
5136
5137 finished_with_string:
5138   /* OK, we're ready to return.  If we have a quoted string, and
5139      quoted_dollar_at is not set, we do no splitting at all; otherwise
5140      we split on ' '.  The routines that call this will handle what to
5141      do if nothing has been expanded. */
5142
5143   /* Partially and wholly quoted strings which expand to the empty
5144      string are retained as an empty arguments.  Unquoted strings
5145      which expand to the empty string are discarded.  The single
5146      exception is the case of expanding "$@" when there are no
5147      positional parameters.  In that case, we discard the expansion. */
5148
5149   /* Because of how the code that handles "" and '' in partially
5150      quoted strings works, we need to make ISTRING into a QUOTED_NULL
5151      if we saw quoting characters, but the expansion was empty.
5152      "" and '' are tossed away before we get to this point when
5153      processing partially quoted strings.  This makes "" and $xxx""
5154      equivalent when xxx is unset.  We also look to see whether we
5155      saw a quoted null from a ${} expansion and add one back if we
5156      need to. */
5157
5158   /* If we expand to nothing and there were no single or double quotes
5159      in the word, we throw it away.  Otherwise, we return a NULL word.
5160      The single exception is for $@ surrounded by double quotes when
5161      there are no positional parameters.  In that case, we also throw
5162      the word away. */
5163
5164   if (*istring == '\0')
5165     {
5166       if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
5167         {
5168           istring[0] = CTLNUL;
5169           istring[1] = '\0';
5170           tword = make_bare_word (istring);
5171           list = make_word_list (tword, (WORD_LIST *)NULL);
5172           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5173             tword->flags |= W_QUOTED;
5174         }
5175       /* According to sh, ksh, and Posix.2, if a word expands into nothing
5176          and a double-quoted "$@" appears anywhere in it, then the entire
5177          word is removed. */
5178       else  if (quoted_state == UNQUOTED || quoted_dollar_at)
5179         list = (WORD_LIST *)NULL;
5180 #if 0
5181       else
5182         {
5183           tword = make_bare_word (istring);
5184           list = make_word_list (tword, (WORD_LIST *)NULL);
5185           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5186             tword->flags |= W_QUOTED;
5187         }
5188 #endif
5189     }
5190   else if (word->flags & W_NOSPLIT)
5191     {
5192       tword = make_bare_word (istring);
5193       list = make_word_list (tword, (WORD_LIST *)NULL);
5194       if (word->flags & W_ASSIGNMENT)
5195         tword->flags |= W_ASSIGNMENT;   /* XXX */
5196       if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5197         tword->flags |= W_QUOTED;
5198     }
5199   else
5200     {
5201       char *ifs_chars;
5202
5203       if (quoted_dollar_at || has_dollar_at)
5204         {
5205           var = find_variable ("IFS");
5206           ifs_chars = var ? value_cell (var) : " \t\n";
5207         }
5208       else
5209         ifs_chars = (char *)NULL;
5210
5211       /* If we have $@, we need to split the results no matter what.  If
5212          IFS is unset or NULL, string_list_dollar_at has separated the
5213          positional parameters with a space, so we split on space (we have
5214          set ifs_chars to " \t\n" above if ifs is unset).  If IFS is set,
5215          string_list_dollar_at has separated the positional parameters
5216          with the first character of $IFS, so we split on $IFS. */
5217       if (has_dollar_at && ifs_chars)
5218         list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
5219       else
5220         {
5221           tword = make_bare_word (istring);
5222           list = make_word_list (tword, (WORD_LIST *)NULL);
5223           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
5224             tword->flags |= W_QUOTED;
5225           if (word->flags & W_ASSIGNMENT)
5226             tword->flags |= W_ASSIGNMENT;
5227         }
5228     }
5229
5230   free (istring);
5231   return (list);
5232 }
5233
5234 /* **************************************************************** */
5235 /*                                                                  */
5236 /*                 Functions for Quote Removal                      */
5237 /*                                                                  */
5238 /* **************************************************************** */
5239
5240 /* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
5241    backslash quoting rules for within double quotes. */
5242 char *
5243 string_quote_removal (string, quoted)
5244      char *string;
5245      int quoted;
5246 {
5247   char *r, *result_string, *temp;
5248   int sindex, tindex, c, dquote;
5249
5250   /* The result can be no longer than the original string. */
5251   r = result_string = xmalloc (strlen (string) + 1);
5252
5253   for (dquote = sindex = 0; c = string[sindex];)
5254     {
5255       switch (c)
5256         {
5257         case '\\':
5258           c = string[++sindex];
5259           if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && member (c, slashify_in_quotes) == 0)
5260             *r++ = '\\';
5261           /* FALLTHROUGH */
5262
5263         default:
5264           *r++ = c;
5265           sindex++;
5266           break;
5267
5268         case '\'':
5269           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
5270             {
5271               *r++ = c;
5272               sindex++;
5273               break;
5274             }
5275           tindex = sindex + 1;
5276           temp = string_extract_single_quoted (string, &tindex);
5277           if (temp)
5278             {
5279               strcpy (r, temp);
5280               r += strlen (r);
5281               free (temp);
5282             }
5283           sindex = tindex;
5284           break;
5285
5286         case '"':
5287           dquote = 1 - dquote;
5288           sindex++;
5289           break;
5290         }
5291     }
5292     *r = '\0';
5293     return (result_string);
5294 }
5295
5296 #if 0
5297 /* UNUSED */
5298 /* Perform quote removal on word WORD.  This allocates and returns a new
5299    WORD_DESC *. */
5300 WORD_DESC *
5301 word_quote_removal (word, quoted)
5302      WORD_DESC *word;
5303      int quoted;
5304 {
5305   WORD_DESC *w;
5306   char *t;
5307
5308   t = string_quote_removal (word->word, quoted);
5309   w = make_bare_word (t);
5310   free (t);
5311   return (w);
5312 }
5313
5314 /* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
5315    the members of the list are treated as if they are surrounded by
5316    double quotes.  Return a new list, or NULL if LIST is NULL. */
5317 WORD_LIST *
5318 word_list_quote_removal (list, quoted)
5319      WORD_LIST *list;
5320      int quoted;
5321 {
5322   WORD_LIST *result, *t, *tresult;
5323
5324   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5325     {
5326       tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
5327       tresult->word = word_quote_removal (t->word, quoted);
5328       tresult->next = (WORD_LIST *)NULL;
5329       result = (WORD_LIST *) list_append (result, tresult);
5330     }
5331   return (result);
5332 }
5333 #endif
5334
5335 /*******************************************
5336  *                                         *
5337  *    Functions to perform word splitting  *
5338  *                                         *
5339  *******************************************/
5340
5341 /* This splits a single word into a WORD LIST on $IFS, but only if the word
5342    is not quoted.  list_string () performs quote removal for us, even if we
5343    don't do any splitting. */
5344 WORD_LIST *
5345 word_split (w)
5346      WORD_DESC *w;
5347 {
5348   WORD_LIST *result;
5349   SHELL_VAR *ifs;
5350   char *ifs_chars;
5351
5352   if (w)
5353     {
5354       ifs = find_variable ("IFS");
5355       /* If IFS is unset, it defaults to " \t\n". */
5356       ifs_chars = ifs ? value_cell (ifs) : " \t\n";
5357
5358       if ((w->flags & W_QUOTED) || !ifs_chars)
5359         ifs_chars = "";
5360
5361       result = list_string (w->word, ifs_chars, w->flags & W_QUOTED);
5362
5363       if (ifs && tempvar_p (ifs))       /* XXX */
5364         dispose_variable (ifs);         /* XXX */
5365     }
5366   else
5367     result = (WORD_LIST *)NULL;
5368
5369   return (result);
5370 }
5371
5372 /* Perform word splitting on LIST and return the RESULT.  It is possible
5373    to return (WORD_LIST *)NULL. */
5374 static WORD_LIST *
5375 word_list_split (list)
5376      WORD_LIST *list;
5377 {
5378   WORD_LIST *result, *t, *tresult;
5379
5380   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5381     {
5382       tresult = word_split (t->word);
5383       result = (WORD_LIST *) list_append (result, tresult);
5384     }
5385   return (result);
5386 }
5387
5388 /**************************************************
5389  *                                                *
5390  *    Functions to expand an entire WORD_LIST     *
5391  *                                                *
5392  **************************************************/
5393
5394 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
5395    ELIST, and set ELIST to the new list. */
5396 #define PREPEND_LIST(nlist, elist) \
5397         do { nlist->next = elist; elist = nlist; } while (0)
5398
5399 static WORD_LIST *varlist = (WORD_LIST *)NULL;
5400
5401 /* Separate out any initial variable assignments from TLIST.  If set -k has
5402    been executed, remove all assignment statements from TLIST.  Initial
5403    variable assignments and other environment assignments are placed
5404    on VARLIST. */
5405 static WORD_LIST *
5406 separate_out_assignments (tlist)
5407      WORD_LIST *tlist;
5408 {
5409   register WORD_LIST *vp, *lp;
5410
5411   if (!tlist)
5412     return ((WORD_LIST *)NULL);
5413
5414   varlist = (WORD_LIST *)NULL;
5415   vp = lp = tlist;
5416
5417   /* Separate out variable assignments at the start of the command.
5418      Loop invariant: vp->next == lp
5419      Loop postcondition:
5420         lp = list of words left after assignment statements skipped
5421         tlist = original list of words
5422   */
5423   while (lp && (lp->word->flags & W_ASSIGNMENT))
5424     {
5425       vp = lp;
5426       lp = lp->next;
5427     }
5428
5429   /* If lp != tlist, we have some initial assignment statements. */
5430   /* We make VARLIST point to the list of assignment words and
5431      TLIST point to the remaining words.  */
5432   if (lp != tlist)
5433     {
5434       varlist = tlist;
5435       /* ASSERT(vp->next == lp); */
5436       vp->next = (WORD_LIST *)NULL;     /* terminate variable list */
5437       tlist = lp;                       /* remainder of word list */
5438     }
5439
5440   /* vp == end of variable list */
5441   /* tlist == remainder of original word list without variable assignments */
5442   if (!tlist)
5443     /* All the words in tlist were assignment statements */
5444     return ((WORD_LIST *)NULL);
5445
5446   /* ASSERT(tlist != NULL); */
5447   /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
5448
5449   /* If the -k option is in effect, we need to go through the remaining
5450      words, separate out the assignment words, and place them on VARLIST. */
5451   if (place_keywords_in_env)
5452     {
5453       WORD_LIST *tp;    /* tp == running pointer into tlist */
5454
5455       tp = tlist;
5456       lp = tlist->next;
5457
5458       /* Loop Invariant: tp->next == lp */
5459       /* Loop postcondition: tlist == word list without assignment statements */
5460       while (lp)
5461         {
5462           if (lp->word->flags & W_ASSIGNMENT)
5463             {
5464               /* Found an assignment statement, add this word to end of
5465                  varlist (vp). */
5466               if (!varlist)
5467                 varlist = vp = lp;
5468               else
5469                 {
5470                   vp->next = lp;
5471                   vp = lp;
5472                 }
5473
5474               /* Remove the word pointed to by LP from TLIST. */
5475               tp->next = lp->next;
5476               /* ASSERT(vp == lp); */
5477               lp->next = (WORD_LIST *)NULL;
5478               lp = tp->next;
5479             }
5480           else
5481             {
5482               tp = lp;
5483               lp = lp->next;
5484             }
5485         }
5486     }
5487   return (tlist);
5488 }
5489
5490 #define WEXP_VARASSIGN  0x001
5491 #define WEXP_BRACEEXP   0x002
5492 #define WEXP_TILDEEXP   0x004
5493 #define WEXP_PARAMEXP   0x008
5494 #define WEXP_PATHEXP    0x010
5495
5496 /* All of the expansions, including variable assignments at the start of
5497    the list. */
5498 #define WEXP_ALL        (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
5499
5500 /* All of the expansions except variable assignments at the start of
5501    the list. */
5502 #define WEXP_NOVARS     (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
5503
5504 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
5505    expansion, command substitution, arithmetic expansion, word splitting, and
5506    quote removal. */
5507 #define WEXP_SHELLEXP   (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
5508
5509 /* Take the list of words in LIST and do the various substitutions.  Return
5510    a new list of words which is the expanded list, and without things like
5511    variable assignments. */
5512
5513 WORD_LIST *
5514 expand_words (list)
5515      WORD_LIST *list;
5516 {
5517   return (expand_word_list_internal (list, WEXP_ALL));
5518 }
5519
5520 /* Same as expand_words (), but doesn't hack variable or environment
5521    variables. */
5522 WORD_LIST *
5523 expand_words_no_vars (list)
5524      WORD_LIST *list;
5525 {
5526   return (expand_word_list_internal (list, WEXP_NOVARS));
5527 }
5528
5529 WORD_LIST *
5530 expand_words_shellexp (list)
5531      WORD_LIST *list;
5532 {
5533   return (expand_word_list_internal (list, WEXP_SHELLEXP));
5534 }
5535
5536 static WORD_LIST *
5537 glob_expand_word_list (tlist, eflags)
5538      WORD_LIST *tlist;
5539      int eflags;
5540 {
5541   char **glob_array, *temp_string;
5542   register int glob_index;
5543   WORD_LIST *glob_list, *output_list, *disposables, *next;
5544   WORD_DESC *tword;
5545
5546   output_list = disposables = (WORD_LIST *)NULL;
5547   glob_array = (char **)NULL;
5548   while (tlist)
5549     {
5550       /* For each word, either globbing is attempted or the word is
5551          added to orig_list.  If globbing succeeds, the results are
5552          added to orig_list and the word (tlist) is added to the list
5553          of disposable words.  If globbing fails and failed glob
5554          expansions are left unchanged (the shell default), the
5555          original word is added to orig_list.  If globbing fails and
5556          failed glob expansions are removed, the original word is
5557          added to the list of disposable words.  orig_list ends up
5558          in reverse order and requires a call to reverse_list to
5559          be set right.  After all words are examined, the disposable
5560          words are freed. */
5561       next = tlist->next;
5562
5563       /* If the word isn't an assignment and contains an unquoted
5564          pattern matching character, then glob it. */
5565       if ((tlist->word->flags & W_ASSIGNMENT) == 0 &&
5566           unquoted_glob_pattern_p (tlist->word->word))
5567         {
5568           glob_array = shell_glob_filename (tlist->word->word);
5569
5570           /* Handle error cases.
5571              I don't think we should report errors like "No such file
5572              or directory".  However, I would like to report errors
5573              like "Read failed". */
5574
5575           if (GLOB_FAILED (glob_array))
5576             {
5577               glob_array = (char **) xmalloc (sizeof (char *));
5578               glob_array[0] = (char *)NULL;
5579             }
5580
5581           /* Dequote the current word in case we have to use it. */
5582           if (glob_array[0] == NULL)
5583             {
5584               temp_string = dequote_string (tlist->word->word);
5585               free (tlist->word->word);
5586               tlist->word->word = temp_string;
5587             }
5588
5589           /* Make the array into a word list. */
5590           glob_list = (WORD_LIST *)NULL;
5591           for (glob_index = 0; glob_array[glob_index]; glob_index++)
5592             {
5593               tword = make_bare_word (glob_array[glob_index]);
5594               tword->flags |= W_GLOBEXP;        /* XXX */
5595               glob_list = make_word_list (tword, glob_list);
5596             }
5597
5598           if (glob_list)
5599             {
5600               output_list = (WORD_LIST *)list_append (glob_list, output_list);
5601               PREPEND_LIST (tlist, disposables);
5602             }
5603           else if (allow_null_glob_expansion == 0)
5604             {
5605               /* Failed glob expressions are left unchanged. */
5606               PREPEND_LIST (tlist, output_list);
5607             }
5608           else
5609             {
5610               /* Failed glob expressions are removed. */
5611               PREPEND_LIST (tlist, disposables);
5612             }
5613         }
5614       else
5615         {
5616           /* Dequote the string. */
5617           temp_string = dequote_string (tlist->word->word);
5618           free (tlist->word->word);
5619           tlist->word->word = temp_string;
5620           PREPEND_LIST (tlist, output_list);
5621         }
5622
5623       free_array (glob_array);
5624       glob_array = (char **)NULL;
5625
5626       tlist = next;
5627     }
5628
5629   if (disposables)
5630     dispose_words (disposables);
5631
5632   if (output_list)
5633     output_list = REVERSE_LIST (output_list, WORD_LIST *);
5634
5635   return (output_list);
5636 }
5637
5638 #if defined (BRACE_EXPANSION)
5639 static WORD_LIST *
5640 brace_expand_word_list (tlist, eflags)
5641      WORD_LIST *tlist;
5642      int eflags;
5643 {
5644   register char **expansions;
5645   char *temp_string;
5646   WORD_LIST *disposables, *output_list, *next;
5647   WORD_DESC *w;
5648   int eindex;
5649
5650   for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
5651     {
5652       next = tlist->next;
5653
5654       /* Only do brace expansion if the word has a brace character.  If
5655          not, just add the word list element to BRACES and continue.  In
5656          the common case, at least when running shell scripts, this will
5657          degenerate to a bunch of calls to `strchr', and then what is
5658          basically a reversal of TLIST into BRACES, which is corrected
5659          by a call to reverse_list () on BRACES when the end of TLIST
5660          is reached. */
5661       if (strchr (tlist->word->word, LBRACE))
5662         {
5663           expansions = brace_expand (tlist->word->word);
5664
5665           for (eindex = 0; temp_string = expansions[eindex]; eindex++)
5666             {
5667               w = make_word (temp_string);
5668               /* If brace expansion didn't change the word, preserve
5669                  the flags.  We may want to preserve the flags
5670                  unconditionally someday -- XXX */
5671               if (STREQ (temp_string, tlist->word->word))
5672                 w->flags = tlist->word->flags;
5673               output_list = make_word_list (w, output_list);
5674               free (expansions[eindex]);
5675             }
5676           free (expansions);
5677
5678           /* Add TLIST to the list of words to be freed after brace
5679              expansion has been performed. */
5680           PREPEND_LIST (tlist, disposables);
5681         }
5682       else
5683         PREPEND_LIST (tlist, output_list);
5684     }
5685
5686   if (disposables)
5687     dispose_words (disposables);
5688
5689   if (output_list)
5690     output_list = REVERSE_LIST (output_list, WORD_LIST *);
5691
5692   return (output_list);
5693 }
5694 #endif
5695
5696 static WORD_LIST *
5697 shell_expand_word_list (tlist, eflags)
5698      WORD_LIST *tlist;
5699      int eflags;
5700 {
5701   WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
5702   int expanded_something, has_dollar_at;
5703   char *temp_string;
5704
5705   /* We do tilde expansion all the time.  This is what 1003.2 says. */
5706   new_list = (WORD_LIST *)NULL;
5707   for (orig_list = tlist; tlist; tlist = next)
5708     {
5709       temp_string = tlist->word->word;
5710
5711       next = tlist->next;
5712
5713       /* Posix.2 section 3.6.1 says that tildes following `=' in words
5714          which are not assignment statements are not expanded.  We do
5715          this only if POSIXLY_CORRECT is enabled.  Essentially, we do
5716          tilde expansion on unquoted assignment statements (flags include
5717          W_ASSIGNMENT but not W_QUOTED). */
5718       if (temp_string[0] == '~' ||
5719             (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
5720              posixly_correct == 0 &&
5721              strchr (temp_string, '~') &&
5722              (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string))))
5723         {
5724           tlist->word->word = bash_tilde_expand (temp_string);
5725           free (temp_string);
5726         }
5727
5728       expanded_something = 0;
5729       expanded = expand_word_internal
5730         (tlist->word, 0, &has_dollar_at, &expanded_something);
5731
5732       if (expanded == &expand_word_error || expanded == &expand_word_fatal)
5733         {
5734           /* By convention, each time this error is returned,
5735              tlist->word->word has already been freed. */
5736           tlist->word->word = (char *)NULL;
5737
5738           /* Dispose our copy of the original list. */
5739           dispose_words (orig_list);
5740           /* Dispose the new list we're building. */
5741           dispose_words (new_list);
5742
5743           if (expanded == &expand_word_error)
5744             jump_to_top_level (DISCARD);
5745           else
5746             jump_to_top_level (FORCE_EOF);
5747         }
5748
5749       /* Don't split words marked W_NOSPLIT. */
5750       if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
5751         {
5752           temp_list = word_list_split (expanded);
5753           dispose_words (expanded);
5754         }
5755       else
5756         {
5757           /* If no parameter expansion, command substitution, process
5758              substitution, or arithmetic substitution took place, then
5759              do not do word splitting.  We still have to remove quoted
5760              null characters from the result. */
5761           word_list_remove_quoted_nulls (expanded);
5762           temp_list = expanded;
5763         }
5764
5765       expanded = REVERSE_LIST (temp_list, WORD_LIST *);
5766       new_list = (WORD_LIST *)list_append (expanded, new_list);
5767     }
5768
5769   if (orig_list)  
5770     dispose_words (orig_list);
5771
5772   if (new_list)
5773     new_list = REVERSE_LIST (new_list, WORD_LIST *);
5774
5775   return (new_list);
5776 }
5777
5778 /* The workhorse for expand_words () and expand_words_no_vars ().
5779    First arg is LIST, a WORD_LIST of words.
5780    Second arg DO_VARS is non-zero if you want to do environment and
5781    variable assignments, else zero.
5782
5783    This does all of the substitutions: brace expansion, tilde expansion,
5784    parameter expansion, command substitution, arithmetic expansion,
5785    process substitution, word splitting, and pathname expansion, according
5786    to the bits set in EFLAGS.  Words with the W_QUOTED or W_NOSPLIT bits
5787    set, or for which no expansion is done, do not undergo word splitting.
5788    Words with the W_ASSIGNMENT bit set do not undergo pathname expansion. */
5789 static WORD_LIST *
5790 expand_word_list_internal (list, eflags)
5791      WORD_LIST *list;
5792      int eflags;
5793 {
5794   WORD_LIST *new_list, *temp_list;
5795   int tint;
5796
5797   if (list == 0)
5798     return ((WORD_LIST *)NULL);
5799
5800   new_list = copy_word_list (list);
5801
5802   if (eflags & WEXP_VARASSIGN)
5803     {
5804       new_list = separate_out_assignments (new_list);
5805       if (new_list == 0)
5806         {
5807           if (varlist)
5808             {
5809               /* All the words were variable assignments, so they are placed
5810                  into the shell's environment. */
5811               for (temp_list = varlist; temp_list; temp_list = temp_list->next)
5812                 {
5813                   this_command_name = (char *)NULL;     /* no arithmetic errors */
5814                   tint = do_assignment (temp_list->word->word);
5815                   /* Variable assignment errors in non-interactive shells
5816                      running in Posix.2 mode cause the shell to exit. */
5817                   if (tint == 0 && interactive_shell == 0 && posixly_correct)
5818                     {
5819                       last_command_exit_value = EXECUTION_FAILURE;
5820                       jump_to_top_level (FORCE_EOF);
5821                     }
5822                 }
5823               dispose_words (varlist);
5824               varlist = (WORD_LIST *)NULL;
5825             }
5826           return ((WORD_LIST *)NULL);
5827         }
5828     }
5829
5830   /* Begin expanding the words that remain.  The expansions take place on
5831      things that aren't really variable assignments. */
5832
5833 #if defined (BRACE_EXPANSION)
5834   /* Do brace expansion on this word if there are any brace characters
5835      in the string. */
5836   if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
5837     new_list = brace_expand_word_list (new_list, eflags);
5838 #endif /* BRACE_EXPANSION */
5839
5840   /* Perform the `normal' shell expansions: tilde expansion, parameter and
5841      variable substitution, command substitution, arithmetic expansion,
5842      and word splitting. */
5843   new_list = shell_expand_word_list (new_list, eflags);
5844
5845   /* Okay, we're almost done.  Now let's just do some filename
5846      globbing. */
5847   if (new_list)
5848     {
5849       if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
5850         /* Glob expand the word list unless globbing has been disabled. */
5851         new_list = glob_expand_word_list (new_list, eflags);
5852       else
5853         /* Dequote the words, because we're not performing globbing. */
5854         new_list = dequote_list (new_list);
5855     }
5856
5857   if ((eflags & WEXP_VARASSIGN) && varlist)
5858     {
5859       Function *assign_func;
5860
5861       /* If the remainder of the words expand to nothing, Posix.2 requires
5862          that the variable and environment assignments affect the shell's
5863          environment. */
5864       assign_func = new_list ? assign_in_env : do_assignment;
5865
5866       for (temp_list = varlist; temp_list; temp_list = temp_list->next)
5867         {
5868           this_command_name = (char *)NULL;
5869           tint = (*assign_func) (temp_list->word->word);
5870           /* Variable assignment errors in non-interactive shells running
5871              in Posix.2 mode cause the shell to exit. */
5872           if (tint == 0 && assign_func == do_assignment &&
5873                 interactive_shell == 0 && posixly_correct)
5874             {
5875               last_command_exit_value = EXECUTION_FAILURE;
5876               jump_to_top_level (FORCE_EOF);
5877             }
5878         }
5879
5880       dispose_words (varlist);
5881       varlist = (WORD_LIST *)NULL;
5882     }
5883
5884 #if 0
5885   tint = list_length (new_list) + 1;
5886   RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
5887   for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
5888     glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
5889   glob_argv_flags[tint] = '\0';
5890 #endif
5891
5892   return (new_list);
5893 }