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