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