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