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