78f217cabb2a045f6444d07ff56f9deddd1ab5a3
[platform/upstream/bash.git] / subst.c
1 /* subst.c -- The part of the shell that does parameter, command, arithmetic,
2    and 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-2009 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
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation, either version 3 of the License, or
14    (at your option) any later version.
15
16    Bash is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "config.h"
26
27 #include "bashtypes.h"
28 #include <stdio.h>
29 #include "chartypes.h"
30 #if defined (HAVE_PWD_H)
31 #  include <pwd.h>
32 #endif
33 #include <signal.h>
34 #include <errno.h>
35
36 #if defined (HAVE_UNISTD_H)
37 #  include <unistd.h>
38 #endif
39
40 #include "bashansi.h"
41 #include "posixstat.h"
42 #include "bashintl.h"
43
44 #include "shell.h"
45 #include "flags.h"
46 #include "jobs.h"
47 #include "execute_cmd.h"
48 #include "filecntl.h"
49 #include "trap.h"
50 #include "pathexp.h"
51 #include "mailcheck.h"
52
53 #include "shmbutil.h"
54
55 #include "builtins/getopt.h"
56 #include "builtins/common.h"
57
58 #include "builtins/builtext.h"
59
60 #include <tilde/tilde.h>
61 #include <glob/strmatch.h>
62
63 #if !defined (errno)
64 extern int errno;
65 #endif /* !errno */
66
67 /* The size that strings change by. */
68 #define DEFAULT_INITIAL_ARRAY_SIZE 112
69 #define DEFAULT_ARRAY_SIZE 128
70
71 /* Variable types. */
72 #define VT_VARIABLE     0
73 #define VT_POSPARMS     1
74 #define VT_ARRAYVAR     2
75 #define VT_ARRAYMEMBER  3
76 #define VT_ASSOCVAR     4
77
78 #define VT_STARSUB      128     /* $* or ${array[*]} -- used to split */
79
80 /* Flags for quoted_strchr */
81 #define ST_BACKSL       0x01
82 #define ST_CTLESC       0x02
83 #define ST_SQUOTE       0x04    /* unused yet */
84 #define ST_DQUOTE       0x08    /* unused yet */
85
86 /* Flags for the `pflags' argument to param_expand() */
87 #define PF_NOCOMSUB     0x01    /* Do not perform command substitution */
88 #define PF_IGNUNBOUND   0x02    /* ignore unbound vars even if -u set */
89
90 /* These defs make it easier to use the editor. */
91 #define LBRACE          '{'
92 #define RBRACE          '}'
93 #define LPAREN          '('
94 #define RPAREN          ')'
95
96 /* Evaluates to 1 if C is one of the shell's special parameters whose length
97    can be taken, but is also one of the special expansion characters. */
98 #define VALID_SPECIAL_LENGTH_PARAM(c) \
99   ((c) == '-' || (c) == '?' || (c) == '#')
100
101 /* Evaluates to 1 if C is one of the shell's special parameters for which an
102    indirect variable reference may be made. */
103 #define VALID_INDIR_PARAM(c) \
104   ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
105
106 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
107    in ${parameter[:]OPword}. */
108 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
109
110 /* Evaluates to 1 if this is one of the shell's special variables. */
111 #define SPECIAL_VAR(name, wi) \
112  ((DIGIT (*name) && all_digits (name)) || \
113       (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
114       (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
115
116 /* An expansion function that takes a string and a quoted flag and returns
117    a WORD_LIST *.  Used as the type of the third argument to
118    expand_string_if_necessary(). */
119 typedef WORD_LIST *EXPFUNC __P((char *, int));
120
121 /* Process ID of the last command executed within command substitution. */
122 pid_t last_command_subst_pid = NO_PID;
123 pid_t current_command_subst_pid = NO_PID;
124
125 /* Variables used to keep track of the characters in IFS. */
126 SHELL_VAR *ifs_var;
127 char *ifs_value;
128 unsigned char ifs_cmap[UCHAR_MAX + 1];
129
130 #if defined (HANDLE_MULTIBYTE)
131 unsigned char ifs_firstc[MB_LEN_MAX];
132 size_t ifs_firstc_len;
133 #else
134 unsigned char ifs_firstc;
135 #endif
136
137 int assigning_in_environment;
138
139 /* Extern functions and variables from different files. */
140 extern int last_command_exit_value, last_command_exit_signal;
141 extern int subshell_environment;
142 extern int subshell_level, parse_and_execute_level;
143 extern int eof_encountered;
144 extern int return_catch_flag, return_catch_value;
145 extern pid_t dollar_dollar_pid;
146 extern int posixly_correct;
147 extern char *this_command_name;
148 extern struct fd_bitmap *current_fds_to_close;
149 extern int wordexp_only;
150 extern int expanding_redir;
151 extern int tempenv_assign_error;
152
153 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
154 extern wchar_t *wcsdup __P((const wchar_t *));
155 #endif
156
157 /* Non-zero means to allow unmatched globbed filenames to expand to
158    a null file. */
159 int allow_null_glob_expansion;
160
161 /* Non-zero means to throw an error when globbing fails to match anything. */
162 int fail_glob_expansion;
163
164 #if 0
165 /* Variables to keep track of which words in an expanded word list (the
166    output of expand_word_list_internal) are the result of globbing
167    expansions.  GLOB_ARGV_FLAGS is used by execute_cmd.c.
168    (CURRENTLY UNUSED). */
169 char *glob_argv_flags;
170 static int glob_argv_flags_size;
171 #endif
172
173 static WORD_LIST expand_word_error, expand_word_fatal;
174 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
175 static char expand_param_error, expand_param_fatal;
176 static char extract_string_error, extract_string_fatal;
177
178 /* Tell the expansion functions to not longjmp back to top_level on fatal
179    errors.  Enabled when doing completion and prompt string expansion. */
180 static int no_longjmp_on_fatal_error = 0;
181
182 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
183    $* on $IFS, primarily when doing assignment statements. */
184 static int expand_no_split_dollar_star = 0;
185
186 /* Used to hold a list of variable assignments preceding a command.  Global
187    so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
188    SIGCHLD trap. */
189 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
190
191 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
192    without any leading variable assignments. */
193 static WORD_LIST *garglist = (WORD_LIST *)NULL;
194
195 static char *quoted_substring __P((char *, int, int));
196 static int quoted_strlen __P((char *));
197 static char *quoted_strchr __P((char *, int, int));
198
199 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
200 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
201 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
202 static WORD_LIST *expand_string_internal __P((char *, int));
203 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
204 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
205
206 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
207 static char *make_quoted_char __P((int));
208 static WORD_LIST *quote_list __P((WORD_LIST *));
209
210 static int unquoted_substring __P((char *, char *));
211 static int unquoted_member __P((int, char *));
212
213 #if defined (ARRAY_VARS)
214 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
215 #endif
216 static int do_assignment_internal __P((const WORD_DESC *, int));
217
218 static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
219 static char *string_extract __P((char *, int *, char *, int));
220 static char *string_extract_double_quoted __P((char *, int *, int));
221 static inline char *string_extract_single_quoted __P((char *, int *));
222 static inline int skip_single_quoted __P((const char *, size_t, int));
223 static int skip_double_quoted __P((char *, size_t, int));
224 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
225 static char *extract_dollar_brace_string __P((char *, int *, int, int));
226 static int skip_matched_pair __P((const char *, int, int, int, int));
227
228 static char *pos_params __P((char *, int, int, int));
229
230 static unsigned char *mb_getcharlens __P((char *, int));
231
232 static char *remove_upattern __P((char *, char *, int));
233 #if defined (HANDLE_MULTIBYTE) 
234 static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
235 #endif
236 static char *remove_pattern __P((char *, char *, int));
237
238 static int match_pattern_char __P((char *, char *));
239 static int match_upattern __P((char *, char *, int, char **, char **));
240 #if defined (HANDLE_MULTIBYTE)
241 static int match_pattern_wchar __P((wchar_t *, wchar_t *));
242 static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
243 #endif
244 static int match_pattern __P((char *, char *, int, char **, char **));
245 static int getpatspec __P((int, char *));
246 static char *getpattern __P((char *, int, int));
247 static char *variable_remove_pattern __P((char *, char *, int, int));
248 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
249 static char *parameter_list_remove_pattern __P((int, char *, int, int));
250 #ifdef ARRAY_VARS
251 static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int));
252 #endif
253 static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
254
255 static char *process_substitute __P((char *, int));
256
257 static char *read_comsub __P((int, int, int *));
258
259 #ifdef ARRAY_VARS
260 static arrayind_t array_length_reference __P((char *));
261 #endif
262
263 static int valid_brace_expansion_word __P((char *, int));
264 static int chk_atstar __P((char *, int, int *, int *));
265 static int chk_arithsub __P((const char *, int));
266
267 static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
268 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
269 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
270 static void parameter_brace_expand_error __P((char *, char *));
271
272 static int valid_length_expression __P((char *));
273 static intmax_t parameter_brace_expand_length __P((char *));
274
275 static char *skiparith __P((char *, int));
276 static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
277 static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
278 static char *mb_substring __P((char *, int, int));
279 static char *parameter_brace_substring __P((char *, char *, char *, int));
280
281 static char *pos_params_pat_subst __P((char *, char *, char *, int));
282
283 static char *parameter_brace_patsub __P((char *, char *, char *, int));
284
285 static char *pos_params_casemod __P((char *, char *, int, int));
286 static char *parameter_brace_casemod __P((char *, char *, int, char *, int));
287
288 static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
289 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
290
291 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
292
293 static WORD_LIST *word_list_split __P((WORD_LIST *));
294
295 static void exp_jump_to_top_level __P((int));
296
297 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
298 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
299 #ifdef BRACE_EXPANSION
300 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
301 #endif
302 #if defined (ARRAY_VARS)
303 static int make_internal_declare __P((char *, char *));
304 #endif
305 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
306 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
307
308 /* **************************************************************** */
309 /*                                                                  */
310 /*                      Utility Functions                           */
311 /*                                                                  */
312 /* **************************************************************** */
313
314 #ifdef INCLUDE_UNUSED
315 static char *
316 quoted_substring (string, start, end)
317      char *string;
318      int start, end;
319 {
320   register int len, l;
321   register char *result, *s, *r;
322
323   len = end - start;
324
325   /* Move to string[start], skipping quoted characters. */
326   for (s = string, l = 0; *s && l < start; )
327     {
328       if (*s == CTLESC)
329         {
330           s++;
331           continue;
332         }
333       l++;
334       if (*s == 0)
335         break;
336     }
337
338   r = result = (char *)xmalloc (2*len + 1);      /* save room for quotes */
339
340   /* Copy LEN characters, including quote characters. */
341   s = string + l;
342   for (l = 0; l < len; s++)
343     {
344       if (*s == CTLESC)
345         *r++ = *s++;
346       *r++ = *s;
347       l++;
348       if (*s == 0)
349         break;
350     }
351   *r = '\0';
352   return result;
353 }
354 #endif
355
356 #ifdef INCLUDE_UNUSED
357 /* Return the length of S, skipping over quoted characters */
358 static int
359 quoted_strlen (s)
360      char *s;
361 {
362   register char *p;
363   int i;
364
365   i = 0;
366   for (p = s; *p; p++)
367     {
368       if (*p == CTLESC)
369         {
370           p++;
371           if (*p == 0)
372             return (i + 1);
373         }
374       i++;
375     }
376
377   return i;
378 }
379 #endif
380
381 /* Find the first occurrence of character C in string S, obeying shell
382    quoting rules.  If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
383    characters are skipped.  If (FLAGS & ST_CTLESC) is non-zero, characters
384    escaped with CTLESC are skipped. */
385 static char *
386 quoted_strchr (s, c, flags)
387      char *s;
388      int c, flags;
389 {
390   register char *p;
391
392   for (p = s; *p; p++)
393     {
394       if (((flags & ST_BACKSL) && *p == '\\')
395             || ((flags & ST_CTLESC) && *p == CTLESC))
396         {
397           p++;
398           if (*p == '\0')
399             return ((char *)NULL);
400           continue;
401         }
402       else if (*p == c)
403         return p;
404     }
405   return ((char *)NULL);
406 }
407
408 /* Return 1 if CHARACTER appears in an unquoted portion of
409    STRING.  Return 0 otherwise.  CHARACTER must be a single-byte character. */
410 static int
411 unquoted_member (character, string)
412      int character;
413      char *string;
414 {
415   size_t slen;
416   int sindex, c;
417   DECLARE_MBSTATE;
418
419   slen = strlen (string);
420   sindex = 0;
421   while (c = string[sindex])
422     {
423       if (c == character)
424         return (1);
425
426       switch (c)
427         {
428         default:
429           ADVANCE_CHAR (string, slen, sindex);
430           break;
431
432         case '\\':
433           sindex++;
434           if (string[sindex])
435             ADVANCE_CHAR (string, slen, sindex);
436           break;
437
438         case '\'':
439           sindex = skip_single_quoted (string, slen, ++sindex);
440           break;
441
442         case '"':
443           sindex = skip_double_quoted (string, slen, ++sindex);
444           break;
445         }
446     }
447   return (0);
448 }
449
450 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
451 static int
452 unquoted_substring (substr, string)
453      char *substr, *string;
454 {
455   size_t slen;
456   int sindex, c, sublen;
457   DECLARE_MBSTATE;
458
459   if (substr == 0 || *substr == '\0')
460     return (0);
461
462   slen = strlen (string);
463   sublen = strlen (substr);
464   for (sindex = 0; c = string[sindex]; )
465     {
466       if (STREQN (string + sindex, substr, sublen))
467         return (1);
468
469       switch (c)
470         {
471         case '\\':
472           sindex++;
473
474           if (string[sindex])
475             ADVANCE_CHAR (string, slen, sindex);
476           break;
477
478         case '\'':
479           sindex = skip_single_quoted (string, slen, ++sindex);
480           break;
481
482         case '"':
483           sindex = skip_double_quoted (string, slen, ++sindex);
484           break;
485
486         default:
487           ADVANCE_CHAR (string, slen, sindex);
488           break;
489         }
490     }
491   return (0);
492 }
493
494 /* Most of the substitutions must be done in parallel.  In order
495    to avoid using tons of unclear goto's, I have some functions
496    for manipulating malloc'ed strings.  They all take INDX, a
497    pointer to an integer which is the offset into the string
498    where manipulation is taking place.  They also take SIZE, a
499    pointer to an integer which is the current length of the
500    character array for this string. */
501
502 /* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
503    of space allocated to TARGET.  SOURCE can be NULL, in which
504    case nothing happens.  Gets rid of SOURCE by freeing it.
505    Returns TARGET in case the location has changed. */
506 INLINE char *
507 sub_append_string (source, target, indx, size)
508      char *source, *target;
509      int *indx, *size;
510 {
511   if (source)
512     {
513       int srclen, n;
514
515       srclen = STRLEN (source);
516       if (srclen >= (int)(*size - *indx))
517         {
518           n = srclen + *indx;
519           n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
520           target = (char *)xrealloc (target, (*size = n));
521         }
522
523       FASTCOPY (source, target + *indx, srclen);
524       *indx += srclen;
525       target[*indx] = '\0';
526
527       free (source);
528     }
529   return (target);
530 }
531
532 #if 0
533 /* UNUSED */
534 /* Append the textual representation of NUMBER to TARGET.
535    INDX and SIZE are as in SUB_APPEND_STRING. */
536 char *
537 sub_append_number (number, target, indx, size)
538      intmax_t number;
539      int *indx, *size;
540      char *target;
541 {
542   char *temp;
543
544   temp = itos (number);
545   return (sub_append_string (temp, target, indx, size));
546 }
547 #endif
548
549 /* Extract a substring from STRING, starting at SINDEX and ending with
550    one of the characters in CHARLIST.  Don't make the ending character
551    part of the string.  Leave SINDEX pointing at the ending character.
552    Understand about backslashes in the string.  If (flags & SX_VARNAME)
553    is non-zero, and array variables have been compiled into the shell,
554    everything between a `[' and a corresponding `]' is skipped over.
555    If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
556    update SINDEX.  If (flags & SX_REQMATCH) is non-zero, the string must
557    contain a closing character from CHARLIST. */
558 static char *
559 string_extract (string, sindex, charlist, flags)
560      char *string;
561      int *sindex;
562      char *charlist;
563      int flags;
564 {
565   register int c, i;
566   int found;
567   size_t slen;
568   char *temp;
569   DECLARE_MBSTATE;
570
571   slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
572   i = *sindex;
573   found = 0;
574   while (c = string[i])
575     {
576       if (c == '\\')
577         {
578           if (string[i + 1])
579             i++;
580           else
581             break;
582         }
583 #if defined (ARRAY_VARS)
584       else if ((flags & SX_VARNAME) && c == '[')
585         {
586           int ni;
587           /* If this is an array subscript, skip over it and continue. */
588           ni = skipsubscript (string, i);
589           if (string[ni] == ']')
590             i = ni;
591         }
592 #endif
593       else if (MEMBER (c, charlist))
594         {
595           found = 1;
596           break;
597         }
598
599       ADVANCE_CHAR (string, slen, i);
600     }
601
602   /* If we had to have a matching delimiter and didn't find one, return an
603      error and let the caller deal with it. */
604   if ((flags & SX_REQMATCH) && found == 0)
605     {
606       *sindex = i;
607       return (&extract_string_error);
608     }
609   
610   temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
611   *sindex = i;
612   
613   return (temp);
614 }
615
616 /* Extract the contents of STRING as if it is enclosed in double quotes.
617    SINDEX, when passed in, is the offset of the character immediately
618    following the opening double quote; on exit, SINDEX is left pointing after
619    the closing double quote.  If STRIPDQ is non-zero, unquoted double
620    quotes are stripped and the string is terminated by a null byte.
621    Backslashes between the embedded double quotes are processed.  If STRIPDQ
622    is zero, an unquoted `"' terminates the string. */
623 static char *
624 string_extract_double_quoted (string, sindex, stripdq)
625      char *string;
626      int *sindex, stripdq;
627 {
628   size_t slen;
629   char *send;
630   int j, i, t;
631   unsigned char c;
632   char *temp, *ret;             /* The new string we return. */
633   int pass_next, backquote, si; /* State variables for the machine. */
634   int dquote;
635   DECLARE_MBSTATE;
636
637   slen = strlen (string + *sindex) + *sindex;
638   send = string + slen;
639
640   pass_next = backquote = dquote = 0;
641   temp = (char *)xmalloc (1 + slen - *sindex);
642
643   j = 0;
644   i = *sindex;
645   while (c = string[i])
646     {
647       /* Process a character that was quoted by a backslash. */
648       if (pass_next)
649         {
650           /* Posix.2 sez:
651
652              ``The backslash shall retain its special meaning as an escape
653              character only when followed by one of the characters:
654                 $       `       "       \       <newline>''.
655
656              If STRIPDQ is zero, we handle the double quotes here and let
657              expand_word_internal handle the rest.  If STRIPDQ is non-zero,
658              we have already been through one round of backslash stripping,
659              and want to strip these backslashes only if DQUOTE is non-zero,
660              indicating that we are inside an embedded double-quoted string. */
661
662              /* If we are in an embedded quoted string, then don't strip
663                 backslashes before characters for which the backslash
664                 retains its special meaning, but remove backslashes in
665                 front of other characters.  If we are not in an
666                 embedded quoted string, don't strip backslashes at all.
667                 This mess is necessary because the string was already
668                 surrounded by double quotes (and sh has some really weird
669                 quoting rules).
670                 The returned string will be run through expansion as if
671                 it were double-quoted. */
672           if ((stripdq == 0 && c != '"') ||
673               (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
674             temp[j++] = '\\';
675           pass_next = 0;
676
677 add_one_character:
678           COPY_CHAR_I (temp, j, string, send, i);
679           continue;
680         }
681
682       /* A backslash protects the next character.  The code just above
683          handles preserving the backslash in front of any character but
684          a double quote. */
685       if (c == '\\')
686         {
687           pass_next++;
688           i++;
689           continue;
690         }
691
692       /* Inside backquotes, ``the portion of the quoted string from the
693          initial backquote and the characters up to the next backquote
694          that is not preceded by a backslash, having escape characters
695          removed, defines that command''. */
696       if (backquote)
697         {
698           if (c == '`')
699             backquote = 0;
700           temp[j++] = c;
701           i++;
702           continue;
703         }
704
705       if (c == '`')
706         {
707           temp[j++] = c;
708           backquote++;
709           i++;
710           continue;
711         }
712
713       /* Pass everything between `$(' and the matching `)' or a quoted
714          ${ ... } pair through according to the Posix.2 specification. */
715       if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
716         {
717           int free_ret = 1;
718
719           si = i + 2;
720           if (string[i + 1] == LPAREN)
721             ret = extract_command_subst (string, &si, 0);
722           else
723             ret = extract_dollar_brace_string (string, &si, 1, 0);
724
725           temp[j++] = '$';
726           temp[j++] = string[i + 1];
727
728           /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
729              is set. */
730           if (ret == 0 && no_longjmp_on_fatal_error)
731             {
732               free_ret = 0;
733               ret = string + i + 2;
734             }
735
736           for (t = 0; ret[t]; t++, j++)
737             temp[j] = ret[t];
738           temp[j] = string[si];
739
740           if (string[si])
741             {
742               j++;
743               i = si + 1;
744             }
745           else
746             i = si;
747
748           if (free_ret)
749             free (ret);
750           continue;
751         }
752
753       /* Add any character but a double quote to the quoted string we're
754          accumulating. */
755       if (c != '"')
756         goto add_one_character;
757
758       /* c == '"' */
759       if (stripdq)
760         {
761           dquote ^= 1;
762           i++;
763           continue;
764         }
765
766       break;
767     }
768   temp[j] = '\0';
769
770   /* Point to after the closing quote. */
771   if (c)
772     i++;
773   *sindex = i;
774
775   return (temp);
776 }
777
778 /* This should really be another option to string_extract_double_quoted. */
779 static int
780 skip_double_quoted (string, slen, sind)
781      char *string;
782      size_t slen;
783      int sind;
784 {
785   int c, i;
786   char *ret;
787   int pass_next, backquote, si;
788   DECLARE_MBSTATE;
789
790   pass_next = backquote = 0;
791   i = sind;
792   while (c = string[i])
793     {
794       if (pass_next)
795         {
796           pass_next = 0;
797           ADVANCE_CHAR (string, slen, i);
798           continue;
799         }
800       else if (c == '\\')
801         {
802           pass_next++;
803           i++;
804           continue;
805         }
806       else if (backquote)
807         {
808           if (c == '`')
809             backquote = 0;
810           ADVANCE_CHAR (string, slen, i);
811           continue;
812         }
813       else if (c == '`')
814         {
815           backquote++;
816           i++;
817           continue;
818         }
819       else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
820         {
821           si = i + 2;
822           if (string[i + 1] == LPAREN)
823             ret = extract_command_subst (string, &si, SX_NOALLOC);
824           else
825             ret = extract_dollar_brace_string (string, &si, 1, SX_NOALLOC);
826
827           i = si + 1;
828           continue;
829         }
830       else if (c != '"')
831         {
832           ADVANCE_CHAR (string, slen, i);
833           continue;
834         }
835       else
836         break;
837     }
838
839   if (c)
840     i++;
841
842   return (i);
843 }
844
845 /* Extract the contents of STRING as if it is enclosed in single quotes.
846    SINDEX, when passed in, is the offset of the character immediately
847    following the opening single quote; on exit, SINDEX is left pointing after
848    the closing single quote. */
849 static inline char *
850 string_extract_single_quoted (string, sindex)
851      char *string;
852      int *sindex;
853 {
854   register int i;
855   size_t slen;
856   char *t;
857   DECLARE_MBSTATE;
858
859   /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
860   slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
861   i = *sindex;
862   while (string[i] && string[i] != '\'')
863     ADVANCE_CHAR (string, slen, i);
864
865   t = substring (string, *sindex, i);
866
867   if (string[i])
868     i++;
869   *sindex = i;
870
871   return (t);
872 }
873
874 static inline int
875 skip_single_quoted (string, slen, sind)
876      const char *string;
877      size_t slen;
878      int sind;
879 {
880   register int c;
881   DECLARE_MBSTATE;
882
883   c = sind;
884   while (string[c] && string[c] != '\'')
885     ADVANCE_CHAR (string, slen, c);
886
887   if (string[c])
888     c++;
889   return c;
890 }
891
892 /* Just like string_extract, but doesn't hack backslashes or any of
893    that other stuff.  Obeys CTLESC quoting.  Used to do splitting on $IFS. */
894 static char *
895 string_extract_verbatim (string, slen, sindex, charlist, flags)
896      char *string;
897      size_t slen;
898      int *sindex;
899      char *charlist;
900      int flags;
901 {
902   register int i = *sindex;
903 #if defined (HANDLE_MULTIBYTE)
904   size_t clen;
905   wchar_t *wcharlist;
906 #endif
907   int c;
908   char *temp;
909   DECLARE_MBSTATE;
910
911   if (charlist[0] == '\'' && charlist[1] == '\0')
912     {
913       temp = string_extract_single_quoted (string, sindex);
914       --*sindex;        /* leave *sindex at separator character */
915       return temp;
916     }
917
918   i = *sindex;
919 #if 0
920   /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
921      this only if MB_CUR_MAX > 1. */
922   slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
923 #endif
924 #if defined (HANDLE_MULTIBYTE)
925   clen = strlen (charlist);
926   wcharlist = 0;
927 #endif
928   while (c = string[i])
929     {
930 #if defined (HANDLE_MULTIBYTE)
931       size_t mblength;
932 #endif
933       if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
934         {
935           i += 2;
936           continue;
937         }
938       /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
939          through, to protect the CTLNULs from later calls to
940          remove_quoted_nulls. */
941       else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
942         {
943           i += 2;
944           continue;
945         }
946
947 #if defined (HANDLE_MULTIBYTE)
948       mblength = MBLEN (string + i, slen - i);
949       if (mblength > 1)
950         {
951           wchar_t wc;
952           mblength = mbtowc (&wc, string + i, slen - i);
953           if (MB_INVALIDCH (mblength))
954             {
955               if (MEMBER (c, charlist))
956                 break;
957             }
958           else
959             {
960               if (wcharlist == 0)
961                 {
962                   size_t len;
963                   len = mbstowcs (wcharlist, charlist, 0);
964                   if (len == -1)
965                     len = 0;
966                   wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
967                   mbstowcs (wcharlist, charlist, len + 1);
968                 }
969
970               if (wcschr (wcharlist, wc))
971                 break;
972             }
973         }
974       else              
975 #endif
976       if (MEMBER (c, charlist))
977         break;
978
979       ADVANCE_CHAR (string, slen, i);
980     }
981
982 #if defined (HANDLE_MULTIBYTE)
983   FREE (wcharlist);
984 #endif
985
986   temp = substring (string, *sindex, i);
987   *sindex = i;
988
989   return (temp);
990 }
991
992 /* Extract the $( construct in STRING, and return a new string.
993    Start extracting at (SINDEX) as if we had just seen "$(".
994    Make (SINDEX) get the position of the matching ")". )
995    XFLAGS is additional flags to pass to other extraction functions, */
996 char *
997 extract_command_subst (string, sindex, xflags)
998      char *string;
999      int *sindex;
1000      int xflags;
1001 {
1002   if (string[*sindex] == '(')   /*)*/
1003     return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
1004   else
1005     {
1006       xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1007       return (xparse_dolparen (string, string+*sindex, sindex, xflags));
1008     }
1009 }
1010
1011 /* Extract the $[ construct in STRING, and return a new string. (])
1012    Start extracting at (SINDEX) as if we had just seen "$[".
1013    Make (SINDEX) get the position of the matching "]". */
1014 char *
1015 extract_arithmetic_subst (string, sindex)
1016      char *string;
1017      int *sindex;
1018 {
1019   return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
1020 }
1021
1022 #if defined (PROCESS_SUBSTITUTION)
1023 /* Extract the <( or >( construct in STRING, and return a new string.
1024    Start extracting at (SINDEX) as if we had just seen "<(".
1025    Make (SINDEX) get the position of the matching ")". */ /*))*/
1026 char *
1027 extract_process_subst (string, starter, sindex)
1028      char *string;
1029      char *starter;
1030      int *sindex;
1031 {
1032   return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1033 }
1034 #endif /* PROCESS_SUBSTITUTION */
1035
1036 #if defined (ARRAY_VARS)
1037 /* This can be fooled by unquoted right parens in the passed string. If
1038    each caller verifies that the last character in STRING is a right paren,
1039    we don't even need to call extract_delimited_string. */
1040 char *
1041 extract_array_assignment_list (string, sindex)
1042      char *string;
1043      int *sindex;
1044 {
1045   int slen;
1046   char *ret;
1047
1048   slen = strlen (string);       /* ( */
1049   if (string[slen - 1] == ')')
1050    {
1051       ret = substring (string, *sindex, slen - 1);
1052       *sindex = slen - 1;
1053       return ret;
1054     }
1055   return 0;  
1056 }
1057 #endif
1058
1059 /* Extract and create a new string from the contents of STRING, a
1060    character string delimited with OPENER and CLOSER.  SINDEX is
1061    the address of an int describing the current offset in STRING;
1062    it should point to just after the first OPENER found.  On exit,
1063    SINDEX gets the position of the last character of the matching CLOSER.
1064    If OPENER is more than a single character, ALT_OPENER, if non-null,
1065    contains a character string that can also match CLOSER and thus
1066    needs to be skipped. */
1067 static char *
1068 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1069      char *string;
1070      int *sindex;
1071      char *opener, *alt_opener, *closer;
1072      int flags;
1073 {
1074   int i, c, si;
1075   size_t slen;
1076   char *t, *result;
1077   int pass_character, nesting_level, in_comment;
1078   int len_closer, len_opener, len_alt_opener;
1079   DECLARE_MBSTATE;
1080
1081   slen = strlen (string + *sindex) + *sindex;
1082   len_opener = STRLEN (opener);
1083   len_alt_opener = STRLEN (alt_opener);
1084   len_closer = STRLEN (closer);
1085
1086   pass_character = in_comment = 0;
1087
1088   nesting_level = 1;
1089   i = *sindex;
1090
1091   while (nesting_level)
1092     {
1093       c = string[i];
1094
1095       if (c == 0)
1096         break;
1097
1098       if (in_comment)
1099         {
1100           if (c == '\n')
1101             in_comment = 0;
1102           ADVANCE_CHAR (string, slen, i);
1103           continue;
1104         }
1105
1106       if (pass_character)       /* previous char was backslash */
1107         {
1108           pass_character = 0;
1109           ADVANCE_CHAR (string, slen, i);
1110           continue;
1111         }
1112
1113       /* Not exactly right yet; should handle shell metacharacters and
1114          multibyte characters, too. */
1115       if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
1116         {
1117           in_comment = 1;
1118           ADVANCE_CHAR (string, slen, i);
1119           continue;
1120         }
1121         
1122       if (c == CTLESC || c == '\\')
1123         {
1124           pass_character++;
1125           i++;
1126           continue;
1127         }
1128
1129       /* Process a nested OPENER. */
1130       if (STREQN (string + i, opener, len_opener))
1131         {
1132           si = i + len_opener;
1133           t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
1134           i = si + 1;
1135           continue;
1136         }
1137
1138       /* Process a nested ALT_OPENER */
1139       if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1140         {
1141           si = i + len_alt_opener;
1142           t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
1143           i = si + 1;
1144           continue;
1145         }
1146
1147       /* If the current substring terminates the delimited string, decrement
1148          the nesting level. */
1149       if (STREQN (string + i, closer, len_closer))
1150         {
1151           i += len_closer - 1;  /* move to last byte of the closer */
1152           nesting_level--;
1153           if (nesting_level == 0)
1154             break;
1155         }
1156
1157       /* Pass old-style command substitution through verbatim. */
1158       if (c == '`')
1159         {
1160           si = i + 1;
1161           t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1162           i = si + 1;
1163           continue;
1164         }
1165
1166       /* Pass single-quoted and double-quoted strings through verbatim. */
1167       if (c == '\'' || c == '"')
1168         {
1169           si = i + 1;
1170           i = (c == '\'') ? skip_single_quoted (string, slen, si)
1171                           : skip_double_quoted (string, slen, si);
1172           continue;
1173         }
1174
1175       /* move past this character, which was not special. */
1176       ADVANCE_CHAR (string, slen, i);
1177     }
1178
1179   if (c == 0 && nesting_level)
1180     {
1181       if (no_longjmp_on_fatal_error == 0)
1182         {
1183           report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1184           last_command_exit_value = EXECUTION_FAILURE;
1185           exp_jump_to_top_level (DISCARD);
1186         }
1187       else
1188         {
1189           *sindex = i;
1190           return (char *)NULL;
1191         }
1192     }
1193
1194   si = i - *sindex - len_closer + 1;
1195   if (flags & SX_NOALLOC)
1196     result = (char *)NULL;
1197   else    
1198     {
1199       result = (char *)xmalloc (1 + si);
1200       strncpy (result, string + *sindex, si);
1201       result[si] = '\0';
1202     }
1203   *sindex = i;
1204
1205   return (result);
1206 }
1207
1208 /* Extract a parameter expansion expression within ${ and } from STRING.
1209    Obey the Posix.2 rules for finding the ending `}': count braces while
1210    skipping over enclosed quoted strings and command substitutions.
1211    SINDEX is the address of an int describing the current offset in STRING;
1212    it should point to just after the first `{' found.  On exit, SINDEX
1213    gets the position of the matching `}'.  QUOTED is non-zero if this
1214    occurs inside double quotes. */
1215 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1216 static char *
1217 extract_dollar_brace_string (string, sindex, quoted, flags)
1218      char *string;
1219      int *sindex, quoted, flags;
1220 {
1221   register int i, c;
1222   size_t slen;
1223   int pass_character, nesting_level, si;
1224   char *result, *t;
1225   DECLARE_MBSTATE;
1226
1227   pass_character = 0;
1228   nesting_level = 1;
1229   slen = strlen (string + *sindex) + *sindex;
1230
1231   i = *sindex;
1232   while (c = string[i])
1233     {
1234       if (pass_character)
1235         {
1236           pass_character = 0;
1237           ADVANCE_CHAR (string, slen, i);
1238           continue;
1239         }
1240
1241       /* CTLESCs and backslashes quote the next character. */
1242       if (c == CTLESC || c == '\\')
1243         {
1244           pass_character++;
1245           i++;
1246           continue;
1247         }
1248
1249       if (string[i] == '$' && string[i+1] == LBRACE)
1250         {
1251           nesting_level++;
1252           i += 2;
1253           continue;
1254         }
1255
1256       if (c == RBRACE)
1257         {
1258           nesting_level--;
1259           if (nesting_level == 0)
1260             break;
1261           i++;
1262           continue;
1263         }
1264
1265       /* Pass the contents of old-style command substitutions through
1266          verbatim. */
1267       if (c == '`')
1268         {
1269           si = i + 1;
1270           t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1271           i = si + 1;
1272           continue;
1273         }
1274
1275       /* Pass the contents of new-style command substitutions and
1276          arithmetic substitutions through verbatim. */
1277       if (string[i] == '$' && string[i+1] == LPAREN)
1278         {
1279           si = i + 2;
1280           t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1281           i = si + 1;
1282           continue;
1283         }
1284
1285       /* Pass the contents of single-quoted and double-quoted strings
1286          through verbatim. */
1287       if (c == '\'' || c == '"')
1288         {
1289           si = i + 1;
1290           i = (c == '\'') ? skip_single_quoted (string, slen, si)
1291                           : skip_double_quoted (string, slen, si);
1292           /* skip_XXX_quoted leaves index one past close quote */
1293           continue;
1294         }
1295
1296       /* move past this character, which was not special. */
1297       ADVANCE_CHAR (string, slen, i);
1298     }
1299
1300   if (c == 0 && nesting_level)
1301     {
1302       if (no_longjmp_on_fatal_error == 0)
1303         {                       /* { */
1304           report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1305           last_command_exit_value = EXECUTION_FAILURE;
1306           exp_jump_to_top_level (DISCARD);
1307         }
1308       else
1309         {
1310           *sindex = i;
1311           return ((char *)NULL);
1312         }
1313     }
1314
1315   result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1316   *sindex = i;
1317
1318   return (result);
1319 }
1320
1321 /* Remove backslashes which are quoting backquotes from STRING.  Modifies
1322    STRING, and returns a pointer to it. */
1323 char *
1324 de_backslash (string)
1325      char *string;
1326 {
1327   register size_t slen;
1328   register int i, j, prev_i;
1329   DECLARE_MBSTATE;
1330
1331   slen = strlen (string);
1332   i = j = 0;
1333
1334   /* Loop copying string[i] to string[j], i >= j. */
1335   while (i < slen)
1336     {
1337       if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1338                               string[i + 1] == '$'))
1339         i++;
1340       prev_i = i;
1341       ADVANCE_CHAR (string, slen, i);
1342       if (j < prev_i)
1343         do string[j++] = string[prev_i++]; while (prev_i < i);
1344       else
1345         j = i;
1346     }
1347   string[j] = '\0';
1348
1349   return (string);
1350 }
1351
1352 #if 0
1353 /*UNUSED*/
1354 /* Replace instances of \! in a string with !. */
1355 void
1356 unquote_bang (string)
1357      char *string;
1358 {
1359   register int i, j;
1360   register char *temp;
1361
1362   temp = (char *)xmalloc (1 + strlen (string));
1363
1364   for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1365     {
1366       if (string[i] == '\\' && string[i + 1] == '!')
1367         {
1368           temp[j] = '!';
1369           i++;
1370         }
1371     }
1372   strcpy (string, temp);
1373   free (temp);
1374 }
1375 #endif
1376
1377 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1378
1379 /* This function assumes s[i] == open; returns with s[ret] == close; used to
1380    parse array subscripts.  FLAGS currently unused. */
1381 static int
1382 skip_matched_pair (string, start, open, close, flags)
1383      const char *string;
1384      int start, open, close, flags;
1385 {
1386   int i, pass_next, backq, si, c, count;
1387   size_t slen;
1388   char *temp, *ss;
1389   DECLARE_MBSTATE;
1390
1391   slen = strlen (string + start) + start;
1392   no_longjmp_on_fatal_error = 1;
1393
1394   i = start + 1;                /* skip over leading bracket */
1395   count = 1;
1396   pass_next = backq = 0;
1397   ss = (char *)string;
1398   while (c = string[i])
1399     {
1400       if (pass_next)
1401         {
1402           pass_next = 0;
1403           if (c == 0)
1404             CQ_RETURN(i);
1405           ADVANCE_CHAR (string, slen, i);
1406           continue;
1407         }
1408       else if (c == '\\')
1409         {
1410           pass_next = 1;
1411           i++;
1412           continue;
1413         }
1414       else if (backq)
1415         {
1416           if (c == '`')
1417             backq = 0;
1418           ADVANCE_CHAR (string, slen, i);
1419           continue;
1420         }
1421       else if (c == '`')
1422         {
1423           backq = 1;
1424           i++;
1425           continue;
1426         }
1427       else if (c == open)
1428         {
1429           count++;
1430           i++;
1431           continue;
1432         }
1433       else if (c == close)
1434         {
1435           count--;
1436           if (count == 0)
1437             break;
1438           i++;
1439           continue;
1440         }
1441       else if (c == '\'' || c == '"')
1442         {
1443           i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
1444                           : skip_double_quoted (ss, slen, ++i);
1445           /* no increment, the skip functions increment past the closing quote. */
1446         }
1447       else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1448         {
1449           si = i + 2;
1450           if (string[si] == '\0')
1451             CQ_RETURN(si);
1452
1453           if (string[i+1] == LPAREN)
1454             temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1455           else
1456             temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
1457           i = si;
1458           if (string[i] == '\0')        /* don't increment i past EOS in loop */
1459             break;
1460           i++;
1461           continue;
1462         }
1463       else
1464         ADVANCE_CHAR (string, slen, i);
1465     }
1466
1467   CQ_RETURN(i);
1468 }
1469
1470 #if defined (ARRAY_VARS)
1471 int
1472 skipsubscript (string, start)
1473      const char *string;
1474      int start;
1475 {
1476   return (skip_matched_pair (string, start, '[', ']', 0));
1477 }
1478 #endif
1479
1480 /* Skip characters in STRING until we find a character in DELIMS, and return
1481    the index of that character.  START is the index into string at which we
1482    begin.  This is similar in spirit to strpbrk, but it returns an index into
1483    STRING and takes a starting index.  This little piece of code knows quite
1484    a lot of shell syntax.  It's very similar to skip_double_quoted and other
1485    functions of that ilk. */
1486 int
1487 skip_to_delim (string, start, delims, flags)
1488      char *string;
1489      int start;
1490      char *delims;
1491      int flags;
1492 {
1493   int i, pass_next, backq, si, c, invert;
1494   size_t slen;
1495   char *temp;
1496   DECLARE_MBSTATE;
1497
1498   slen = strlen (string + start) + start;
1499   if (flags & SD_NOJMP)
1500     no_longjmp_on_fatal_error = 1;
1501   invert = (flags & SD_INVERT);
1502
1503   i = start;
1504   pass_next = backq = 0;
1505   while (c = string[i])
1506     {
1507       if (pass_next)
1508         {
1509           pass_next = 0;
1510           if (c == 0)
1511             CQ_RETURN(i);
1512           ADVANCE_CHAR (string, slen, i);
1513           continue;
1514         }
1515       else if (c == '\\')
1516         {
1517           pass_next = 1;
1518           i++;
1519           continue;
1520         }
1521       else if (backq)
1522         {
1523           if (c == '`')
1524             backq = 0;
1525           ADVANCE_CHAR (string, slen, i);
1526           continue;
1527         }
1528       else if (c == '`')
1529         {
1530           backq = 1;
1531           i++;
1532           continue;
1533         }
1534       else if (invert == 0 && member (c, delims))
1535         break;
1536       else if (c == '\'' || c == '"')
1537         {
1538           i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1539                           : skip_double_quoted (string, slen, ++i);
1540           /* no increment, the skip functions increment past the closing quote. */
1541         }
1542       else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1543         {
1544           si = i + 2;
1545           if (string[si] == '\0')
1546             CQ_RETURN(si);
1547
1548           if (string[i+1] == LPAREN)
1549             temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1550           else
1551             temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
1552           i = si;
1553           if (string[i] == '\0')        /* don't increment i past EOS in loop */
1554             break;
1555           i++;
1556           continue;
1557         }
1558       else if (invert && (member (c, delims) == 0))
1559         break;
1560       else
1561         ADVANCE_CHAR (string, slen, i);
1562     }
1563
1564   CQ_RETURN(i);
1565 }
1566
1567 #if defined (READLINE)
1568 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1569    an unclosed quoted string), or if the character at EINDEX is quoted
1570    by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1571    single and double-quoted string parsing functions should not return an
1572    error if there are unclosed quotes or braces.  The characters that this
1573    recognizes need to be the same as the contents of
1574    rl_completer_quote_characters. */
1575
1576 int
1577 char_is_quoted (string, eindex)
1578      char *string;
1579      int eindex;
1580 {
1581   int i, pass_next, c;
1582   size_t slen;
1583   DECLARE_MBSTATE;
1584
1585   slen = strlen (string);
1586   no_longjmp_on_fatal_error = 1;
1587   i = pass_next = 0;
1588   while (i <= eindex)
1589     {
1590       c = string[i];
1591
1592       if (pass_next)
1593         {
1594           pass_next = 0;
1595           if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
1596             CQ_RETURN(1);
1597           ADVANCE_CHAR (string, slen, i);
1598           continue;
1599         }
1600       else if (c == '\\')
1601         {
1602           pass_next = 1;
1603           i++;
1604           continue;
1605         }
1606       else if (c == '\'' || c == '"')
1607         {
1608           i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1609                           : skip_double_quoted (string, slen, ++i);
1610           if (i > eindex)
1611             CQ_RETURN(1);
1612           /* no increment, the skip_xxx functions go one past end */
1613         }
1614       else
1615         ADVANCE_CHAR (string, slen, i);
1616     }
1617
1618   CQ_RETURN(0);
1619 }
1620
1621 int
1622 unclosed_pair (string, eindex, openstr)
1623      char *string;
1624      int eindex;
1625      char *openstr;
1626 {
1627   int i, pass_next, openc, olen;
1628   size_t slen;
1629   DECLARE_MBSTATE;
1630
1631   slen = strlen (string);
1632   olen = strlen (openstr);
1633   i = pass_next = openc = 0;
1634   while (i <= eindex)
1635     {
1636       if (pass_next)
1637         {
1638           pass_next = 0;
1639           if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
1640             return 0;
1641           ADVANCE_CHAR (string, slen, i);
1642           continue;
1643         }
1644       else if (string[i] == '\\')
1645         {
1646           pass_next = 1;
1647           i++;
1648           continue;
1649         }
1650       else if (STREQN (string + i, openstr, olen))
1651         {
1652           openc = 1 - openc;
1653           i += olen;
1654         }
1655       else if (string[i] == '\'' || string[i] == '"')
1656         {
1657           i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1658                                   : skip_double_quoted (string, slen, i);
1659           if (i > eindex)
1660             return 0;
1661         }
1662       else
1663         ADVANCE_CHAR (string, slen, i);
1664     }
1665   return (openc);
1666 }
1667
1668 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1669    individual words.  If DELIMS is NULL, the current value of $IFS is used
1670    to split the string, and the function follows the shell field splitting
1671    rules.  SENTINEL is an index to look for.  NWP, if non-NULL,
1672    gets the number of words in the returned list.  CWP, if non-NULL, gets
1673    the index of the word containing SENTINEL.  Non-whitespace chars in
1674    DELIMS delimit separate fields. */
1675 WORD_LIST *
1676 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1677      char *string;
1678      int slen;
1679      char *delims;
1680      int sentinel;
1681      int *nwp, *cwp;
1682 {
1683   int ts, te, i, nw, cw, ifs_split;
1684   char *token, *d, *d2;
1685   WORD_LIST *ret, *tl;
1686
1687   if (string == 0 || *string == '\0')
1688     {
1689       if (nwp)
1690         *nwp = 0;
1691       if (cwp)
1692         *cwp = 0;       
1693       return ((WORD_LIST *)NULL);
1694     }
1695
1696   d = (delims == 0) ? ifs_value : delims;
1697   ifs_split = delims == 0;
1698
1699   /* Make d2 the non-whitespace characters in delims */
1700   d2 = 0;
1701   if (delims)
1702     {
1703       size_t slength;
1704 #if defined (HANDLE_MULTIBYTE)
1705       size_t mblength = 1;
1706 #endif
1707       DECLARE_MBSTATE;
1708
1709       slength = strlen (delims);
1710       d2 = (char *)xmalloc (slength + 1);
1711       i = ts = 0;
1712       while (delims[i])
1713         {
1714 #if defined (HANDLE_MULTIBYTE)
1715           mbstate_t state_bak;
1716           state_bak = state;
1717           mblength = MBRLEN (delims + i, slength, &state);
1718           if (MB_INVALIDCH (mblength))
1719             state = state_bak;
1720           else if (mblength > 1)
1721             {
1722               memcpy (d2 + ts, delims + i, mblength);
1723               ts += mblength;
1724               i += mblength;
1725               slength -= mblength;
1726               continue;
1727             }
1728 #endif
1729           if (whitespace (delims[i]) == 0)
1730             d2[ts++] = delims[i];
1731
1732           i++;
1733           slength--;
1734         }
1735       d2[ts] = '\0';
1736     }
1737
1738   ret = (WORD_LIST *)NULL;
1739
1740   /* Remove sequences of whitspace characters at the start of the string, as
1741      long as those characters are delimiters. */
1742   for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1743     ;
1744   if (string[i] == '\0')
1745     return (ret);
1746
1747   ts = i;
1748   nw = 0;
1749   cw = -1;
1750   while (1)
1751     {
1752       te = skip_to_delim (string, ts, d, SD_NOJMP);
1753
1754       /* If we have a non-whitespace delimiter character, use it to make a
1755          separate field.  This is just about what $IFS splitting does and
1756          is closer to the behavior of the shell parser. */
1757       if (ts == te && d2 && member (string[ts], d2))
1758         {
1759           te = ts + 1;
1760           /* If we're using IFS splitting, the non-whitespace delimiter char
1761              and any additional IFS whitespace delimits a field. */
1762           if (ifs_split)
1763             while (member (string[te], d) && spctabnl (string[te]))
1764               te++;
1765           else
1766             while (member (string[te], d2))
1767               te++;
1768         }
1769
1770       token = substring (string, ts, te);
1771
1772       ret = add_string_to_list (token, ret);
1773       free (token);
1774       nw++;
1775
1776       if (sentinel >= ts && sentinel <= te)
1777         cw = nw;
1778
1779       /* If the cursor is at whitespace just before word start, set the
1780          sentinel word to the current word. */
1781       if (cwp && cw == -1 && sentinel == ts-1)
1782         cw = nw;
1783
1784       /* If the cursor is at whitespace between two words, make a new, empty
1785          word, add it before (well, after, since the list is in reverse order)
1786          the word we just added, and set the current word to that one. */
1787       if (cwp && cw == -1 && sentinel < ts)
1788         {
1789           tl = make_word_list (make_word (""), ret->next);
1790           ret->next = tl;
1791           cw = nw;
1792           nw++;
1793         }
1794
1795       if (string[te] == 0)
1796         break;
1797
1798       i = te;
1799       while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
1800         i++;
1801
1802       if (string[i])
1803         ts = i;
1804       else
1805         break;
1806     }
1807
1808   /* Special case for SENTINEL at the end of STRING.  If we haven't found
1809      the word containing SENTINEL yet, and the index we're looking for is at
1810      the end of STRING, add an additional null argument and set the current
1811      word pointer to that. */
1812   if (cwp && cw == -1 && sentinel >= slen)
1813     {
1814       if (whitespace (string[sentinel - 1]))
1815         {
1816           token = "";
1817           ret = add_string_to_list (token, ret);
1818           nw++;
1819         }
1820       cw = nw;
1821     }
1822
1823   if (nwp)
1824     *nwp = nw;
1825   if (cwp)
1826     *cwp = cw;
1827
1828   return (REVERSE_LIST (ret, WORD_LIST *));
1829 }
1830 #endif /* READLINE */
1831
1832 #if 0
1833 /* UNUSED */
1834 /* Extract the name of the variable to bind to from the assignment string. */
1835 char *
1836 assignment_name (string)
1837      char *string;
1838 {
1839   int offset;
1840   char *temp;
1841
1842   offset = assignment (string, 0);
1843   if (offset == 0)
1844     return (char *)NULL;
1845   temp = substring (string, 0, offset);
1846   return (temp);
1847 }
1848 #endif
1849
1850 /* **************************************************************** */
1851 /*                                                                  */
1852 /*     Functions to convert strings to WORD_LISTs and vice versa    */
1853 /*                                                                  */
1854 /* **************************************************************** */
1855
1856 /* Return a single string of all the words in LIST.  SEP is the separator
1857    to put between individual elements of LIST in the output string. */
1858 char *
1859 string_list_internal (list, sep)
1860      WORD_LIST *list;
1861      char *sep;
1862 {
1863   register WORD_LIST *t;
1864   char *result, *r;
1865   int word_len, sep_len, result_size;
1866
1867   if (list == 0)
1868     return ((char *)NULL);
1869
1870   /* Short-circuit quickly if we don't need to separate anything. */
1871   if (list->next == 0)
1872     return (savestring (list->word->word));
1873
1874   /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1875   sep_len = STRLEN (sep);
1876   result_size = 0;
1877
1878   for (t = list; t; t = t->next)
1879     {
1880       if (t != list)
1881         result_size += sep_len;
1882       result_size += strlen (t->word->word);
1883     }
1884
1885   r = result = (char *)xmalloc (result_size + 1);
1886
1887   for (t = list; t; t = t->next)
1888     {
1889       if (t != list && sep_len)
1890         {
1891           if (sep_len > 1)
1892             {
1893               FASTCOPY (sep, r, sep_len);
1894               r += sep_len;
1895             }
1896           else
1897             *r++ = sep[0];
1898         }
1899
1900       word_len = strlen (t->word->word);
1901       FASTCOPY (t->word->word, r, word_len);
1902       r += word_len;
1903     }
1904
1905   *r = '\0';
1906   return (result);
1907 }
1908
1909 /* Return a single string of all the words present in LIST, separating
1910    each word with a space. */
1911 char *
1912 string_list (list)
1913      WORD_LIST *list;
1914 {
1915   return (string_list_internal (list, " "));
1916 }
1917
1918 /* An external interface that can be used by the rest of the shell to
1919    obtain a string containing the first character in $IFS.  Handles all
1920    the multibyte complications.  If LENP is non-null, it is set to the
1921    length of the returned string. */
1922 char *
1923 ifs_firstchar (lenp)
1924      int *lenp;
1925 {
1926   char *ret;
1927   int len;
1928
1929   ret = xmalloc (MB_LEN_MAX + 1);
1930 #if defined (HANDLE_MULTIBYTE)
1931   if (ifs_firstc_len == 1)
1932     {
1933       ret[0] = ifs_firstc[0];
1934       ret[1] = '\0';
1935       len = ret[0] ? 1 : 0;
1936     }
1937   else
1938     {
1939       memcpy (ret, ifs_firstc, ifs_firstc_len);
1940       ret[len = ifs_firstc_len] = '\0';
1941     }
1942 #else
1943   ret[0] = ifs_firstc;
1944   ret[1] = '\0';
1945   len = ret[0] ? 0 : 1;
1946 #endif
1947
1948   if (lenp)
1949     *lenp = len;
1950
1951   return ret;
1952 }
1953
1954 /* Return a single string of all the words present in LIST, obeying the
1955    quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1956    expansion [of $*] appears within a double quoted string, it expands
1957    to a single field with the value of each parameter separated by the
1958    first character of the IFS variable, or by a <space> if IFS is unset." */
1959 char *
1960 string_list_dollar_star (list)
1961      WORD_LIST *list;
1962 {
1963   char *ret;
1964 #if defined (HANDLE_MULTIBYTE)
1965 #  if defined (__GNUC__)
1966   char sep[MB_CUR_MAX + 1];
1967 #  else
1968   char *sep = 0;
1969 #  endif
1970 #else
1971   char sep[2];
1972 #endif
1973
1974 #if defined (HANDLE_MULTIBYTE)
1975 #  if !defined (__GNUC__)
1976   sep = (char *)xmalloc (MB_CUR_MAX + 1);
1977 #  endif /* !__GNUC__ */
1978   if (ifs_firstc_len == 1)
1979     {
1980       sep[0] = ifs_firstc[0];
1981       sep[1] = '\0';
1982     }
1983   else
1984     {
1985       memcpy (sep, ifs_firstc, ifs_firstc_len);
1986       sep[ifs_firstc_len] = '\0';
1987     }
1988 #else
1989   sep[0] = ifs_firstc;
1990   sep[1] = '\0';
1991 #endif
1992
1993   ret = string_list_internal (list, sep);
1994 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1995   free (sep);
1996 #endif
1997   return ret;
1998 }
1999
2000 /* Turn $@ into a string.  If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2001    is non-zero, the $@ appears within double quotes, and we should quote
2002    the list before converting it into a string.  If IFS is unset, and the
2003    word is not quoted, we just need to quote CTLESC and CTLNUL characters
2004    in the words in the list, because the default value of $IFS is
2005    <space><tab><newline>, IFS characters in the words in the list should
2006    also be split.  If IFS is null, and the word is not quoted, we need
2007    to quote the words in the list to preserve the positional parameters
2008    exactly. */
2009 char *
2010 string_list_dollar_at (list, quoted)
2011      WORD_LIST *list;
2012      int quoted;
2013 {
2014   char *ifs, *ret;
2015 #if defined (HANDLE_MULTIBYTE)
2016 #  if defined (__GNUC__)
2017   char sep[MB_CUR_MAX + 1];
2018 #  else
2019   char *sep = 0;
2020 #  endif /* !__GNUC__ */
2021 #else
2022   char sep[2];
2023 #endif
2024   WORD_LIST *tlist;
2025
2026   /* XXX this could just be ifs = ifs_value; */
2027   ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
2028
2029 #if defined (HANDLE_MULTIBYTE)
2030 #  if !defined (__GNUC__)
2031   sep = (char *)xmalloc (MB_CUR_MAX + 1);
2032 #  endif /* !__GNUC__ */
2033   if (ifs && *ifs)
2034     {
2035       if (ifs_firstc_len == 1)
2036         {
2037           sep[0] = ifs_firstc[0];
2038           sep[1] = '\0';
2039         }
2040       else
2041         {
2042           memcpy (sep, ifs_firstc, ifs_firstc_len);
2043           sep[ifs_firstc_len] = '\0';
2044         }
2045     }
2046   else
2047     {
2048       sep[0] = ' ';
2049       sep[1] = '\0';
2050     }
2051 #else
2052   sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
2053   sep[1] = '\0';
2054 #endif
2055
2056   /* XXX -- why call quote_list if ifs == 0?  we can get away without doing
2057      it now that quote_escapes quotes spaces */
2058 #if 0
2059   tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
2060 #else
2061   tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2062 #endif
2063                 ? quote_list (list)
2064                 : list_quote_escapes (list);
2065
2066   ret = string_list_internal (tlist, sep);
2067 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2068   free (sep);
2069 #endif
2070   return ret;
2071 }
2072
2073 /* Turn the positional paramters into a string, understanding quoting and
2074    the various subtleties of using the first character of $IFS as the
2075    separator.  Calls string_list_dollar_at, string_list_dollar_star, and
2076    string_list as appropriate. */
2077 char *
2078 string_list_pos_params (pchar, list, quoted)
2079      int pchar;
2080      WORD_LIST *list;
2081      int quoted;
2082 {
2083   char *ret;
2084   WORD_LIST *tlist;
2085
2086   if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
2087     {
2088       tlist = quote_list (list);
2089       word_list_remove_quoted_nulls (tlist);
2090       ret = string_list_dollar_star (tlist);
2091     }
2092   else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
2093     {
2094       tlist = quote_list (list);
2095       word_list_remove_quoted_nulls (tlist);
2096       ret = string_list (tlist);
2097     }
2098   else if (pchar == '*')
2099     {
2100       /* Even when unquoted, string_list_dollar_star does the right thing
2101          making sure that the first character of $IFS is used as the
2102          separator. */
2103       ret = string_list_dollar_star (list);
2104     }
2105   else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
2106     /* We use string_list_dollar_at, but only if the string is quoted, since
2107        that quotes the escapes if it's not, which we don't want.  We could
2108        use string_list (the old code did), but that doesn't do the right
2109        thing if the first character of $IFS is not a space.  We use
2110        string_list_dollar_star if the string is unquoted so we make sure that
2111        the elements of $@ are separated by the first character of $IFS for
2112        later splitting. */
2113     ret = string_list_dollar_at (list, quoted);
2114   else if (pchar == '@')
2115     ret = string_list_dollar_star (list);
2116   else
2117     ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
2118
2119   return ret;
2120 }
2121
2122 /* Return the list of words present in STRING.  Separate the string into
2123    words at any of the characters found in SEPARATORS.  If QUOTED is
2124    non-zero then word in the list will have its quoted flag set, otherwise
2125    the quoted flag is left as make_word () deemed fit.
2126
2127    This obeys the P1003.2 word splitting semantics.  If `separators' is
2128    exactly <space><tab><newline>, then the splitting algorithm is that of
2129    the Bourne shell, which treats any sequence of characters from `separators'
2130    as a delimiter.  If IFS is unset, which results in `separators' being set
2131    to "", no splitting occurs.  If separators has some other value, the
2132    following rules are applied (`IFS white space' means zero or more
2133    occurrences of <space>, <tab>, or <newline>, as long as those characters
2134    are in `separators'):
2135
2136         1) IFS white space is ignored at the start and the end of the
2137            string.
2138         2) Each occurrence of a character in `separators' that is not
2139            IFS white space, along with any adjacent occurrences of
2140            IFS white space delimits a field.
2141         3) Any nonzero-length sequence of IFS white space delimits a field.
2142    */
2143
2144 /* BEWARE!  list_string strips null arguments.  Don't call it twice and
2145    expect to have "" preserved! */
2146
2147 /* This performs word splitting and quoted null character removal on
2148    STRING. */
2149 #define issep(c) \
2150         (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2151                                               : (c) == (separators)[0]) \
2152                            : 0)
2153
2154 WORD_LIST *
2155 list_string (string, separators, quoted)
2156      register char *string, *separators;
2157      int quoted;
2158 {
2159   WORD_LIST *result;
2160   WORD_DESC *t;
2161   char *current_word, *s;
2162   int sindex, sh_style_split, whitesep, xflags;
2163   size_t slen;
2164
2165   if (!string || !*string)
2166     return ((WORD_LIST *)NULL);
2167
2168   sh_style_split = separators && separators[0] == ' ' &&
2169                                  separators[1] == '\t' &&
2170                                  separators[2] == '\n' &&
2171                                  separators[3] == '\0';
2172   for (xflags = 0, s = ifs_value; s && *s; s++)
2173     {
2174       if (*s == CTLESC) xflags |= SX_NOCTLESC;
2175       else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2176     }
2177
2178   slen = 0;
2179   /* Remove sequences of whitespace at the beginning of STRING, as
2180      long as those characters appear in IFS.  Do not do this if
2181      STRING is quoted or if there are no separator characters. */
2182   if (!quoted || !separators || !*separators)
2183     {
2184       for (s = string; *s && spctabnl (*s) && issep (*s); s++);
2185
2186       if (!*s)
2187         return ((WORD_LIST *)NULL);
2188
2189       string = s;
2190     }
2191
2192   /* OK, now STRING points to a word that does not begin with white space.
2193      The splitting algorithm is:
2194         extract a word, stopping at a separator
2195         skip sequences of spc, tab, or nl as long as they are separators
2196      This obeys the field splitting rules in Posix.2. */
2197   slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
2198   for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
2199     {
2200       /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2201          unless multibyte chars are possible. */
2202       current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
2203       if (current_word == 0)
2204         break;
2205
2206       /* If we have a quoted empty string, add a quoted null argument.  We
2207          want to preserve the quoted null character iff this is a quoted
2208          empty string; otherwise the quoted null characters are removed
2209          below. */
2210       if (QUOTED_NULL (current_word))
2211         {
2212           t = alloc_word_desc ();
2213           t->word = make_quoted_char ('\0');
2214           t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2215           result = make_word_list (t, result);
2216         }
2217       else if (current_word[0] != '\0')
2218         {
2219           /* If we have something, then add it regardless.  However,
2220              perform quoted null character removal on the current word. */
2221           remove_quoted_nulls (current_word);
2222           result = add_string_to_list (current_word, result);
2223           result->word->flags &= ~W_HASQUOTEDNULL;      /* just to be sure */
2224           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2225             result->word->flags |= W_QUOTED;
2226         }
2227
2228       /* If we're not doing sequences of separators in the traditional
2229          Bourne shell style, then add a quoted null argument. */
2230       else if (!sh_style_split && !spctabnl (string[sindex]))
2231         {
2232           t = alloc_word_desc ();
2233           t->word = make_quoted_char ('\0');
2234           t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2235           result = make_word_list (t, result);
2236         }
2237
2238       free (current_word);
2239
2240       /* Note whether or not the separator is IFS whitespace, used later. */
2241       whitesep = string[sindex] && spctabnl (string[sindex]);
2242
2243       /* Move past the current separator character. */
2244       if (string[sindex])
2245         {
2246           DECLARE_MBSTATE;
2247           ADVANCE_CHAR (string, slen, sindex);
2248         }
2249
2250       /* Now skip sequences of space, tab, or newline characters if they are
2251          in the list of separators. */
2252       while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2253         sindex++;
2254
2255       /* If the first separator was IFS whitespace and the current character
2256          is a non-whitespace IFS character, it should be part of the current
2257          field delimiter, not a separate delimiter that would result in an
2258          empty field.  Look at POSIX.2, 3.6.5, (3)(b). */
2259       if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2260         {
2261           sindex++;
2262           /* An IFS character that is not IFS white space, along with any
2263              adjacent IFS white space, shall delimit a field. (SUSv3) */
2264           while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2265             sindex++;
2266         }
2267     }
2268   return (REVERSE_LIST (result, WORD_LIST *));
2269 }
2270
2271 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2272    ENDPTR is set to the first character after the word.  This is used by
2273    the `read' builtin.  This is never called with SEPARATORS != $IFS;
2274    it should be simplified.
2275
2276    XXX - this function is very similar to list_string; they should be
2277          combined - XXX */
2278 char *
2279 get_word_from_string (stringp, separators, endptr)
2280      char **stringp, *separators, **endptr;
2281 {
2282   register char *s;
2283   char *current_word;
2284   int sindex, sh_style_split, whitesep, xflags;
2285   size_t slen;
2286
2287   if (!stringp || !*stringp || !**stringp)
2288     return ((char *)NULL);
2289
2290   sh_style_split = separators && separators[0] == ' ' &&
2291                                  separators[1] == '\t' &&
2292                                  separators[2] == '\n' &&
2293                                  separators[3] == '\0';
2294   for (xflags = 0, s = ifs_value; s && *s; s++)
2295     {
2296       if (*s == CTLESC) xflags |= SX_NOCTLESC;
2297       if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2298     }
2299
2300   s = *stringp;
2301   slen = 0;
2302
2303   /* Remove sequences of whitespace at the beginning of STRING, as
2304      long as those characters appear in IFS. */
2305   if (sh_style_split || !separators || !*separators)
2306     {
2307       for (; *s && spctabnl (*s) && isifs (*s); s++);
2308
2309       /* If the string is nothing but whitespace, update it and return. */
2310       if (!*s)
2311         {
2312           *stringp = s;
2313           if (endptr)
2314             *endptr = s;
2315           return ((char *)NULL);
2316         }
2317     }
2318
2319   /* OK, S points to a word that does not begin with white space.
2320      Now extract a word, stopping at a separator, save a pointer to
2321      the first character after the word, then skip sequences of spc,
2322      tab, or nl as long as they are separators.
2323
2324      This obeys the field splitting rules in Posix.2. */
2325   sindex = 0;
2326   /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2327      unless multibyte chars are possible. */
2328   slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2329   current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
2330
2331   /* Set ENDPTR to the first character after the end of the word. */
2332   if (endptr)
2333     *endptr = s + sindex;
2334
2335   /* Note whether or not the separator is IFS whitespace, used later. */
2336   whitesep = s[sindex] && spctabnl (s[sindex]);
2337
2338   /* Move past the current separator character. */
2339   if (s[sindex])
2340     {
2341       DECLARE_MBSTATE;
2342       ADVANCE_CHAR (s, slen, sindex);
2343     }
2344
2345   /* Now skip sequences of space, tab, or newline characters if they are
2346      in the list of separators. */
2347   while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2348     sindex++;
2349
2350   /* If the first separator was IFS whitespace and the current character is
2351      a non-whitespace IFS character, it should be part of the current field
2352      delimiter, not a separate delimiter that would result in an empty field.
2353      Look at POSIX.2, 3.6.5, (3)(b). */
2354   if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2355     {
2356       sindex++;
2357       /* An IFS character that is not IFS white space, along with any adjacent
2358          IFS white space, shall delimit a field. */
2359       while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2360         sindex++;
2361     }
2362
2363   /* Update STRING to point to the next field. */
2364   *stringp = s + sindex;
2365   return (current_word);
2366 }
2367
2368 /* Remove IFS white space at the end of STRING.  Start at the end
2369    of the string and walk backwards until the beginning of the string
2370    or we find a character that's not IFS white space and not CTLESC.
2371    Only let CTLESC escape a white space character if SAW_ESCAPE is
2372    non-zero.  */
2373 char *
2374 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2375      char *string, *separators;
2376      int saw_escape;
2377 {
2378   char *s;
2379
2380   s = string + STRLEN (string) - 1;
2381   while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2382                         (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2383     s--;
2384   *++s = '\0';
2385   return string;
2386 }
2387
2388 #if 0
2389 /* UNUSED */
2390 /* Split STRING into words at whitespace.  Obeys shell-style quoting with
2391    backslashes, single and double quotes. */
2392 WORD_LIST *
2393 list_string_with_quotes (string)
2394      char *string;
2395 {
2396   WORD_LIST *list;
2397   char *token, *s;
2398   size_t s_len;
2399   int c, i, tokstart, len;
2400
2401   for (s = string; s && *s && spctabnl (*s); s++)
2402     ;
2403   if (s == 0 || *s == 0)
2404     return ((WORD_LIST *)NULL);
2405
2406   s_len = strlen (s);
2407   tokstart = i = 0;
2408   list = (WORD_LIST *)NULL;
2409   while (1)
2410     {
2411       c = s[i];
2412       if (c == '\\')
2413         {
2414           i++;
2415           if (s[i])
2416             i++;
2417         }
2418       else if (c == '\'')
2419         i = skip_single_quoted (s, s_len, ++i);
2420       else if (c == '"')
2421         i = skip_double_quoted (s, s_len, ++i);
2422       else if (c == 0 || spctabnl (c))
2423         {
2424           /* We have found the end of a token.  Make a word out of it and
2425              add it to the word list. */
2426           token = substring (s, tokstart, i);
2427           list = add_string_to_list (token, list);
2428           free (token);
2429           while (spctabnl (s[i]))
2430             i++;
2431           if (s[i])
2432             tokstart = i;
2433           else
2434             break;
2435         }
2436       else
2437         i++;    /* normal character */
2438     }
2439   return (REVERSE_LIST (list, WORD_LIST *));
2440 }
2441 #endif
2442
2443 /********************************************************/
2444 /*                                                      */
2445 /*      Functions to perform assignment statements      */
2446 /*                                                      */
2447 /********************************************************/
2448
2449 #if defined (ARRAY_VARS)
2450 static SHELL_VAR *
2451 do_compound_assignment (name, value, flags)
2452      char *name, *value;
2453      int flags;
2454 {
2455   SHELL_VAR *v;
2456   int mklocal, mkassoc;
2457   WORD_LIST *list;
2458
2459   mklocal = flags & ASS_MKLOCAL;
2460   mkassoc = flags & ASS_MKASSOC;
2461
2462   if (mklocal && variable_context)
2463     {
2464       v = find_variable (name);
2465       list = expand_compound_array_assignment (v, value, flags);
2466       if (mkassoc)
2467         v = make_local_assoc_variable (name);
2468       else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
2469         v = make_local_array_variable (name);
2470       assign_compound_array_list (v, list, flags);
2471     }
2472   else
2473     v = assign_array_from_string (name, value, flags);
2474
2475   return (v);
2476 }
2477 #endif
2478
2479 /* Given STRING, an assignment string, get the value of the right side
2480    of the `=', and bind it to the left side.  If EXPAND is true, then
2481    perform parameter expansion, command substitution, and arithmetic
2482    expansion on the right-hand side.  Perform tilde expansion in any
2483    case.  Do not perform word splitting on the result of expansion. */
2484 static int
2485 do_assignment_internal (word, expand)
2486      const WORD_DESC *word;
2487      int expand;
2488 {
2489   int offset, tlen, appendop, assign_list, aflags, retval;
2490   char *name, *value;
2491   SHELL_VAR *entry;
2492 #if defined (ARRAY_VARS)
2493   char *t;
2494   int ni;
2495 #endif
2496   const char *string;
2497
2498   if (word == 0 || word->word == 0)
2499     return 0;
2500
2501   appendop = assign_list = aflags = 0;
2502   string = word->word;
2503   offset = assignment (string, 0);
2504   name = savestring (string);
2505   value = (char *)NULL;
2506
2507   if (name[offset] == '=')
2508     {
2509       char *temp;
2510
2511       if (name[offset - 1] == '+')
2512         {
2513           appendop = 1;
2514           name[offset - 1] = '\0';
2515         }
2516
2517       name[offset] = 0;         /* might need this set later */
2518       temp = name + offset + 1;
2519       tlen = STRLEN (temp);
2520
2521 #if defined (ARRAY_VARS)
2522       if (expand && (word->flags & W_COMPASSIGN))
2523         {
2524           assign_list = ni = 1;
2525           value = extract_array_assignment_list (temp, &ni);
2526         }
2527       else
2528 #endif
2529
2530       if (expand && temp[0])
2531         value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2532       else
2533         value = savestring (temp);
2534     }
2535
2536   if (value == 0)
2537     {
2538       value = (char *)xmalloc (1);
2539       value[0] = '\0';
2540     }
2541
2542   if (echo_command_at_execute)
2543     {
2544       if (appendop)
2545         name[offset - 1] = '+';
2546       xtrace_print_assignment (name, value, assign_list, 1);
2547       if (appendop)
2548         name[offset - 1] = '\0';
2549     }
2550
2551 #define ASSIGN_RETURN(r)        do { FREE (value); free (name); return (r); } while (0)
2552
2553   if (appendop)
2554     aflags |= ASS_APPEND;
2555
2556 #if defined (ARRAY_VARS)
2557   if (t = xstrchr (name, '['))  /*]*/
2558     {
2559       if (assign_list)
2560         {
2561           report_error (_("%s: cannot assign list to array member"), name);
2562           ASSIGN_RETURN (0);
2563         }
2564       entry = assign_array_element (name, value, aflags);
2565       if (entry == 0)
2566         ASSIGN_RETURN (0);
2567     }
2568   else if (assign_list)
2569     {
2570       if (word->flags & W_ASSIGNARG)
2571         aflags |= ASS_MKLOCAL;
2572       if (word->flags & W_ASSIGNASSOC)
2573         aflags |= ASS_MKASSOC;
2574       entry = do_compound_assignment (name, value, aflags);
2575     }
2576   else
2577 #endif /* ARRAY_VARS */
2578   entry = bind_variable (name, value, aflags);
2579
2580   stupidly_hack_special_variables (name);
2581
2582 #if 1
2583   /* Return 1 if the assignment seems to have been performed correctly. */
2584   if (entry == 0 || readonly_p (entry))
2585     retval = 0;         /* assignment failure */
2586   else if (noassign_p (entry))
2587     {
2588       last_command_exit_value = EXECUTION_FAILURE;
2589       retval = 1;       /* error status, but not assignment failure */
2590     }
2591   else
2592     retval = 1;
2593
2594   if (entry && retval != 0 && noassign_p (entry) == 0)
2595     VUNSETATTR (entry, att_invisible);
2596
2597   ASSIGN_RETURN (retval);
2598 #else
2599   if (entry)
2600     VUNSETATTR (entry, att_invisible);
2601
2602   ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2603 #endif
2604 }
2605
2606 /* Perform the assignment statement in STRING, and expand the
2607    right side by doing tilde, command and parameter expansion. */
2608 int
2609 do_assignment (string)
2610      char *string;
2611 {
2612   WORD_DESC td;
2613
2614   td.flags = W_ASSIGNMENT;
2615   td.word = string;
2616
2617   return do_assignment_internal (&td, 1);
2618 }
2619
2620 int
2621 do_word_assignment (word)
2622      WORD_DESC *word;
2623 {
2624   return do_assignment_internal (word, 1);
2625 }
2626
2627 /* Given STRING, an assignment string, get the value of the right side
2628    of the `=', and bind it to the left side.  Do not perform any word
2629    expansions on the right hand side. */
2630 int
2631 do_assignment_no_expand (string)
2632      char *string;
2633 {
2634   WORD_DESC td;
2635
2636   td.flags = W_ASSIGNMENT;
2637   td.word = string;
2638
2639   return (do_assignment_internal (&td, 0));
2640 }
2641
2642 /***************************************************
2643  *                                                 *
2644  *  Functions to manage the positional parameters  *
2645  *                                                 *
2646  ***************************************************/
2647
2648 /* Return the word list that corresponds to `$*'. */
2649 WORD_LIST *
2650 list_rest_of_args ()
2651 {
2652   register WORD_LIST *list, *args;
2653   int i;
2654
2655   /* Break out of the loop as soon as one of the dollar variables is null. */
2656   for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2657     list = make_word_list (make_bare_word (dollar_vars[i]), list);
2658
2659   for (args = rest_of_args; args; args = args->next)
2660     list = make_word_list (make_bare_word (args->word->word), list);
2661
2662   return (REVERSE_LIST (list, WORD_LIST *));
2663 }
2664
2665 int
2666 number_of_args ()
2667 {
2668   register WORD_LIST *list;
2669   int n;
2670
2671   for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2672     ;
2673   for (list = rest_of_args; list; list = list->next)
2674     n++;
2675   return n;
2676 }
2677
2678 /* Return the value of a positional parameter.  This handles values > 10. */
2679 char *
2680 get_dollar_var_value (ind)
2681      intmax_t ind;
2682 {
2683   char *temp;
2684   WORD_LIST *p;
2685
2686   if (ind < 10)
2687     temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2688   else  /* We want something like ${11} */
2689     {
2690       ind -= 10;
2691       for (p = rest_of_args; p && ind--; p = p->next)
2692         ;
2693       temp = p ? savestring (p->word->word) : (char *)NULL;
2694     }
2695   return (temp);
2696 }
2697
2698 /* Make a single large string out of the dollar digit variables,
2699    and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
2700    case of "$*" with respect to IFS. */
2701 char *
2702 string_rest_of_args (dollar_star)
2703      int dollar_star;
2704 {
2705   register WORD_LIST *list;
2706   char *string;
2707
2708   list = list_rest_of_args ();
2709   string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2710   dispose_words (list);
2711   return (string);
2712 }
2713
2714 /* Return a string containing the positional parameters from START to
2715    END, inclusive.  If STRING[0] == '*', we obey the rules for $*,
2716    which only makes a difference if QUOTED is non-zero.  If QUOTED includes
2717    Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2718    no quoting chars are added. */
2719 static char *
2720 pos_params (string, start, end, quoted)
2721      char *string;
2722      int start, end, quoted;
2723 {
2724   WORD_LIST *save, *params, *h, *t;
2725   char *ret;
2726   int i;
2727
2728   /* see if we can short-circuit.  if start == end, we want 0 parameters. */
2729   if (start == end)
2730     return ((char *)NULL);
2731
2732   save = params = list_rest_of_args ();
2733   if (save == 0)
2734     return ((char *)NULL);
2735
2736   if (start == 0)               /* handle ${@:0[:x]} specially */
2737     {
2738       t = make_word_list (make_word (dollar_vars[0]), params);
2739       save = params = t;
2740     }
2741
2742   for (i = 1; params && i < start; i++)
2743     params = params->next;
2744   if (params == 0)
2745     return ((char *)NULL);
2746   for (h = t = params; params && i < end; i++)
2747     {
2748       t = params;
2749       params = params->next;
2750     }
2751
2752   t->next = (WORD_LIST *)NULL;
2753
2754   ret = string_list_pos_params (string[0], h, quoted);
2755
2756   if (t != params)
2757     t->next = params;
2758
2759   dispose_words (save);
2760   return (ret);
2761 }
2762
2763 /******************************************************************/
2764 /*                                                                */
2765 /*      Functions to expand strings to strings or WORD_LISTs      */
2766 /*                                                                */
2767 /******************************************************************/
2768
2769 #if defined (PROCESS_SUBSTITUTION)
2770 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
2771 #else
2772 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
2773 #endif
2774
2775 /* If there are any characters in STRING that require full expansion,
2776    then call FUNC to expand STRING; otherwise just perform quote
2777    removal if necessary.  This returns a new string. */
2778 static char *
2779 expand_string_if_necessary (string, quoted, func)
2780      char *string;
2781      int quoted;
2782      EXPFUNC *func;
2783 {
2784   WORD_LIST *list;
2785   size_t slen;
2786   int i, saw_quote;
2787   char *ret;
2788   DECLARE_MBSTATE;
2789
2790   /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
2791   slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
2792   i = saw_quote = 0;
2793   while (string[i])
2794     {
2795       if (EXP_CHAR (string[i]))
2796         break;
2797       else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2798         saw_quote = 1;
2799       ADVANCE_CHAR (string, slen, i);
2800     }
2801
2802   if (string[i])
2803     {
2804       list = (*func) (string, quoted);
2805       if (list)
2806         {
2807           ret = string_list (list);
2808           dispose_words (list);
2809         }
2810       else
2811         ret = (char *)NULL;
2812     }
2813   else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2814     ret = string_quote_removal (string, quoted);
2815   else
2816     ret = savestring (string);
2817
2818   return ret;
2819 }
2820
2821 static inline char *
2822 expand_string_to_string_internal (string, quoted, func)
2823      char *string;
2824      int quoted;
2825      EXPFUNC *func;
2826 {
2827   WORD_LIST *list;
2828   char *ret;
2829
2830   if (string == 0 || *string == '\0')
2831     return ((char *)NULL);
2832
2833   list = (*func) (string, quoted);
2834   if (list)
2835     {
2836       ret = string_list (list);
2837       dispose_words (list);
2838     }
2839   else
2840     ret = (char *)NULL;
2841
2842   return (ret);
2843 }
2844
2845 char *
2846 expand_string_to_string (string, quoted)
2847      char *string;
2848      int quoted;
2849 {
2850   return (expand_string_to_string_internal (string, quoted, expand_string));
2851 }
2852
2853 char *
2854 expand_string_unsplit_to_string (string, quoted)
2855      char *string;
2856      int quoted;
2857 {
2858   return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2859 }
2860
2861 char *
2862 expand_assignment_string_to_string (string, quoted)
2863      char *string;
2864      int quoted;
2865 {
2866   return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
2867 }
2868
2869 char *
2870 expand_arith_string (string, quoted)
2871      char *string;
2872      int quoted;
2873 {
2874   return (expand_string_if_necessary (string, quoted, expand_string));
2875 }
2876
2877 #if defined (COND_COMMAND)
2878 /* Just remove backslashes in STRING.  Returns a new string. */
2879 char *
2880 remove_backslashes (string)
2881      char *string;
2882 {
2883   char *r, *ret, *s;
2884
2885   r = ret = (char *)xmalloc (strlen (string) + 1);
2886   for (s = string; s && *s; )
2887     {
2888       if (*s == '\\')
2889         s++;
2890       if (*s == 0)
2891         break;
2892       *r++ = *s++;
2893     }
2894   *r = '\0';
2895   return ret;
2896 }
2897
2898 /* This needs better error handling. */
2899 /* Expand W for use as an argument to a unary or binary operator in a
2900    [[...]] expression.  If SPECIAL is 1, this is the rhs argument
2901    to the != or == operator, and should be treated as a pattern.  In
2902    this case, we quote the string specially for the globbing code.  If
2903    SPECIAL is 2, this is an rhs argument for the =~ operator, and should
2904    be quoted appropriately for regcomp/regexec.  The caller is responsible
2905    for removing the backslashes if the unquoted word is needed later. */   
2906 char *
2907 cond_expand_word (w, special)
2908      WORD_DESC *w;
2909      int special;
2910 {
2911   char *r, *p;
2912   WORD_LIST *l;
2913   int qflags;
2914
2915   if (w->word == 0 || w->word[0] == '\0')
2916     return ((char *)NULL);
2917
2918   l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2919   if (l)
2920     {
2921       if (special == 0)
2922         {
2923           dequote_list (l);
2924           r = string_list (l);
2925         }
2926       else
2927         {
2928           qflags = QGLOB_CVTNULL;
2929           if (special == 2)
2930             qflags |= QGLOB_REGEXP;
2931           p = string_list (l);
2932           r = quote_string_for_globbing (p, qflags);
2933           free (p);
2934         }
2935       dispose_words (l);
2936     }
2937   else
2938     r = (char *)NULL;
2939
2940   return r;
2941 }
2942 #endif
2943
2944 /* Call expand_word_internal to expand W and handle error returns.
2945    A convenience function for functions that don't want to handle
2946    any errors or free any memory before aborting. */
2947 static WORD_LIST *
2948 call_expand_word_internal (w, q, i, c, e)
2949      WORD_DESC *w;
2950      int q, i, *c, *e;
2951 {
2952   WORD_LIST *result;
2953
2954   result = expand_word_internal (w, q, i, c, e);
2955   if (result == &expand_word_error || result == &expand_word_fatal)
2956     {
2957       /* By convention, each time this error is returned, w->word has
2958          already been freed (it sometimes may not be in the fatal case,
2959          but that doesn't result in a memory leak because we're going
2960          to exit in most cases). */
2961       w->word = (char *)NULL;
2962       last_command_exit_value = EXECUTION_FAILURE;
2963       exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2964       /* NOTREACHED */
2965     }
2966   else
2967     return (result);
2968 }
2969
2970 /* Perform parameter expansion, command substitution, and arithmetic
2971    expansion on STRING, as if it were a word.  Leave the result quoted. */
2972 static WORD_LIST *
2973 expand_string_internal (string, quoted)
2974      char *string;
2975      int quoted;
2976 {
2977   WORD_DESC td;
2978   WORD_LIST *tresult;
2979
2980   if (string == 0 || *string == 0)
2981     return ((WORD_LIST *)NULL);
2982
2983   td.flags = 0;
2984   td.word = savestring (string);
2985
2986   tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2987
2988   FREE (td.word);
2989   return (tresult);
2990 }
2991
2992 /* Expand STRING by performing parameter expansion, command substitution,
2993    and arithmetic expansion.  Dequote the resulting WORD_LIST before
2994    returning it, but do not perform word splitting.  The call to
2995    remove_quoted_nulls () is in here because word splitting normally
2996    takes care of quote removal. */
2997 WORD_LIST *
2998 expand_string_unsplit (string, quoted)
2999      char *string;
3000      int quoted;
3001 {
3002   WORD_LIST *value;
3003
3004   if (string == 0 || *string == '\0')
3005     return ((WORD_LIST *)NULL);
3006
3007   expand_no_split_dollar_star = 1;
3008   value = expand_string_internal (string, quoted);
3009   expand_no_split_dollar_star = 0;
3010
3011   if (value)
3012     {
3013       if (value->word)
3014         {
3015           remove_quoted_nulls (value->word->word);
3016           value->word->flags &= ~W_HASQUOTEDNULL;
3017         }
3018       dequote_list (value);
3019     }
3020   return (value);
3021 }
3022
3023 /* Expand the rhs of an assignment statement */
3024 WORD_LIST *
3025 expand_string_assignment (string, quoted)
3026      char *string;
3027      int quoted;
3028 {
3029   WORD_DESC td;
3030   WORD_LIST *value;
3031
3032   if (string == 0 || *string == '\0')
3033     return ((WORD_LIST *)NULL);
3034
3035   expand_no_split_dollar_star = 1;
3036
3037   td.flags = W_ASSIGNRHS;
3038   td.word = savestring (string);
3039   value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3040   FREE (td.word);
3041
3042   expand_no_split_dollar_star = 0;
3043
3044   if (value)
3045     {
3046       if (value->word)
3047         {
3048           remove_quoted_nulls (value->word->word);
3049           value->word->flags &= ~W_HASQUOTEDNULL;
3050         }
3051       dequote_list (value);
3052     }
3053   return (value);
3054 }
3055
3056
3057 /* Expand one of the PS? prompt strings. This is a sort of combination of
3058    expand_string_unsplit and expand_string_internal, but returns the
3059    passed string when an error occurs.  Might want to trap other calls
3060    to jump_to_top_level here so we don't endlessly loop. */
3061 WORD_LIST *
3062 expand_prompt_string (string, quoted, wflags)
3063      char *string;
3064      int quoted;
3065      int wflags;
3066 {
3067   WORD_LIST *value;
3068   WORD_DESC td;
3069
3070   if (string == 0 || *string == 0)
3071     return ((WORD_LIST *)NULL);
3072
3073   td.flags = wflags;
3074   td.word = savestring (string);
3075
3076   no_longjmp_on_fatal_error = 1;
3077   value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3078   no_longjmp_on_fatal_error = 0;
3079
3080   if (value == &expand_word_error || value == &expand_word_fatal)
3081     {
3082       value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
3083       return value;
3084     }
3085   FREE (td.word);
3086   if (value)
3087     {
3088       if (value->word)
3089         {
3090           remove_quoted_nulls (value->word->word);
3091           value->word->flags &= ~W_HASQUOTEDNULL;
3092         }
3093       dequote_list (value);
3094     }
3095   return (value);
3096 }
3097
3098 /* Expand STRING just as if you were expanding a word, but do not dequote
3099    the resultant WORD_LIST.  This is called only from within this file,
3100    and is used to correctly preserve quoted characters when expanding
3101    things like ${1+"$@"}.  This does parameter expansion, command
3102    substitution, arithmetic expansion, and word splitting. */
3103 static WORD_LIST *
3104 expand_string_leave_quoted (string, quoted)
3105      char *string;
3106      int quoted;
3107 {
3108   WORD_LIST *tlist;
3109   WORD_LIST *tresult;
3110
3111   if (string == 0 || *string == '\0')
3112     return ((WORD_LIST *)NULL);
3113
3114   tlist = expand_string_internal (string, quoted);
3115
3116   if (tlist)
3117     {
3118       tresult = word_list_split (tlist);
3119       dispose_words (tlist);
3120       return (tresult);
3121     }
3122   return ((WORD_LIST *)NULL);
3123 }
3124
3125 /* This does not perform word splitting or dequote the WORD_LIST
3126    it returns. */
3127 static WORD_LIST *
3128 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
3129      char *string;
3130      int quoted, *dollar_at_p, *has_dollar_at;
3131 {
3132   WORD_DESC td;
3133   WORD_LIST *tresult;
3134
3135   if (string == 0 || *string == '\0')
3136     return (WORD_LIST *)NULL;
3137
3138   td.flags = 0;
3139   td.word = string;
3140   tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
3141   return (tresult);
3142 }
3143
3144 /* Expand STRING just as if you were expanding a word.  This also returns
3145    a list of words.  Note that filename globbing is *NOT* done for word
3146    or string expansion, just when the shell is expanding a command.  This
3147    does parameter expansion, command substitution, arithmetic expansion,
3148    and word splitting.  Dequote the resultant WORD_LIST before returning. */
3149 WORD_LIST *
3150 expand_string (string, quoted)
3151      char *string;
3152      int quoted;
3153 {
3154   WORD_LIST *result;
3155
3156   if (string == 0 || *string == '\0')
3157     return ((WORD_LIST *)NULL);
3158
3159   result = expand_string_leave_quoted (string, quoted);
3160   return (result ? dequote_list (result) : result);
3161 }
3162
3163 /***************************************************
3164  *                                                 *
3165  *      Functions to handle quoting chars          *
3166  *                                                 *
3167  ***************************************************/
3168
3169 /* Conventions:
3170
3171      A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
3172      The parser passes CTLNUL as CTLESC CTLNUL. */
3173
3174 /* Quote escape characters in string s, but no other characters.  This is
3175    used to protect CTLESC and CTLNUL in variable values from the rest of
3176    the word expansion process after the variable is expanded (word splitting
3177    and filename generation).  If IFS is null, we quote spaces as well, just
3178    in case we split on spaces later (in the case of unquoted $@, we will
3179    eventually attempt to split the entire word on spaces).  Corresponding
3180    code exists in dequote_escapes.  Even if we don't end up splitting on
3181    spaces, quoting spaces is not a problem.  This should never be called on
3182    a string that is quoted with single or double quotes or part of a here
3183    document (effectively double-quoted). */
3184 char *
3185 quote_escapes (string)
3186      char *string;
3187 {
3188   register char *s, *t;
3189   size_t slen;
3190   char *result, *send;
3191   int quote_spaces, skip_ctlesc, skip_ctlnul;
3192   DECLARE_MBSTATE; 
3193
3194   slen = strlen (string);
3195   send = string + slen;
3196
3197   quote_spaces = (ifs_value && *ifs_value == 0);
3198
3199   for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
3200     skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
3201
3202   t = result = (char *)xmalloc ((slen * 2) + 1);
3203   s = string;
3204
3205   while (*s)
3206     {
3207       if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
3208         *t++ = CTLESC;
3209       COPY_CHAR_P (t, s, send);
3210     }
3211   *t = '\0';
3212   return (result);
3213 }
3214
3215 static WORD_LIST *
3216 list_quote_escapes (list)
3217      WORD_LIST *list;
3218 {
3219   register WORD_LIST *w;
3220   char *t;
3221
3222   for (w = list; w; w = w->next)
3223     {
3224       t = w->word->word;
3225       w->word->word = quote_escapes (t);
3226       free (t);
3227     }
3228   return list;
3229 }
3230
3231 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
3232
3233    The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
3234    This is necessary to make unquoted CTLESC and CTLNUL characters in the
3235    data stream pass through properly.
3236
3237    We need to remove doubled CTLESC characters inside quoted strings before
3238    quoting the entire string, so we do not double the number of CTLESC
3239    characters.
3240
3241    Also used by parts of the pattern substitution code. */
3242 char *
3243 dequote_escapes (string)
3244      char *string;
3245 {
3246   register char *s, *t, *s1;
3247   size_t slen;
3248   char *result, *send;
3249   int quote_spaces;
3250   DECLARE_MBSTATE;
3251
3252   if (string == 0)
3253     return string;
3254
3255   slen = strlen (string);
3256   send = string + slen;
3257
3258   t = result = (char *)xmalloc (slen + 1);
3259
3260   if (strchr (string, CTLESC) == 0)
3261     return (strcpy (result, string));
3262
3263   quote_spaces = (ifs_value && *ifs_value == 0);
3264
3265   s = string;
3266   while (*s)
3267     {
3268       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
3269         {
3270           s++;
3271           if (*s == '\0')
3272             break;
3273         }
3274       COPY_CHAR_P (t, s, send);
3275     }
3276   *t = '\0';
3277   return result;
3278 }
3279
3280 /* Return a new string with the quoted representation of character C.
3281    This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3282    set in any resultant WORD_DESC where this value is the word. */
3283 static char *
3284 make_quoted_char (c)
3285      int c;
3286 {
3287   char *temp;
3288
3289   temp = (char *)xmalloc (3);
3290   if (c == 0)
3291     {
3292       temp[0] = CTLNUL;
3293       temp[1] = '\0';
3294     }
3295   else
3296     {
3297       temp[0] = CTLESC;
3298       temp[1] = c;
3299       temp[2] = '\0';
3300     }
3301   return (temp);
3302 }
3303
3304 /* Quote STRING, returning a new string.  This turns "" into QUOTED_NULL, so
3305    the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3306    this value is the word. */
3307 char *
3308 quote_string (string)
3309      char *string;
3310 {
3311   register char *t;
3312   size_t slen;
3313   char *result, *send;
3314
3315   if (*string == 0)
3316     {
3317       result = (char *)xmalloc (2);
3318       result[0] = CTLNUL;
3319       result[1] = '\0';
3320     }
3321   else
3322     {
3323       DECLARE_MBSTATE;
3324
3325       slen = strlen (string);
3326       send = string + slen;
3327
3328       result = (char *)xmalloc ((slen * 2) + 1);
3329
3330       for (t = result; string < send; )
3331         {
3332           *t++ = CTLESC;
3333           COPY_CHAR_P (t, string, send);
3334         }
3335       *t = '\0';
3336     }
3337   return (result);
3338 }
3339
3340 /* De-quote quoted characters in STRING. */
3341 char *
3342 dequote_string (string)
3343      char *string;
3344 {
3345   register char *s, *t;
3346   size_t slen;
3347   char *result, *send;
3348   DECLARE_MBSTATE;
3349
3350   slen = strlen (string);
3351
3352   t = result = (char *)xmalloc (slen + 1);
3353
3354   if (QUOTED_NULL (string))
3355     {
3356       result[0] = '\0';
3357       return (result);
3358     }
3359
3360   /* If no character in the string can be quoted, don't bother examining
3361      each character.  Just return a copy of the string passed to us. */
3362   if (strchr (string, CTLESC) == NULL)
3363     return (strcpy (result, string));
3364
3365   send = string + slen;
3366   s = string;
3367   while (*s)
3368     {
3369       if (*s == CTLESC)
3370         {
3371           s++;
3372           if (*s == '\0')
3373             break;
3374         }
3375       COPY_CHAR_P (t, s, send);
3376     }
3377
3378   *t = '\0';
3379   return (result);
3380 }
3381
3382 /* Quote the entire WORD_LIST list. */
3383 static WORD_LIST *
3384 quote_list (list)
3385      WORD_LIST *list;
3386 {
3387   register WORD_LIST *w;
3388   char *t;
3389
3390   for (w = list; w; w = w->next)
3391     {
3392       t = w->word->word;
3393       w->word->word = quote_string (t);
3394       if (*t == 0)
3395         w->word->flags |= W_HASQUOTEDNULL;      /* XXX - turn on W_HASQUOTEDNULL here? */
3396       w->word->flags |= W_QUOTED;
3397       free (t);
3398     }
3399   return list;
3400 }
3401
3402 /* De-quote quoted characters in each word in LIST. */
3403 WORD_LIST *
3404 dequote_list (list)
3405      WORD_LIST *list;
3406 {
3407   register char *s;
3408   register WORD_LIST *tlist;
3409
3410   for (tlist = list; tlist; tlist = tlist->next)
3411     {
3412       s = dequote_string (tlist->word->word);
3413       if (QUOTED_NULL (tlist->word->word))
3414         tlist->word->flags &= ~W_HASQUOTEDNULL;
3415       free (tlist->word->word);
3416       tlist->word->word = s;
3417     }
3418   return list;
3419 }
3420
3421 /* Remove CTLESC protecting a CTLESC or CTLNUL in place.  Return the passed
3422    string. */
3423 char *
3424 remove_quoted_escapes (string)
3425      char *string;
3426 {
3427   char *t;
3428
3429   if (string)
3430     {
3431       t = dequote_escapes (string);
3432       strcpy (string, t);
3433       free (t);
3434     }
3435
3436   return (string);
3437 }
3438
3439 /* Perform quoted null character removal on STRING.  We don't allow any
3440    quoted null characters in the middle or at the ends of strings because
3441    of how expand_word_internal works.  remove_quoted_nulls () turns
3442    STRING into an empty string iff it only consists of a quoted null,
3443    and removes all unquoted CTLNUL characters. */
3444 char *
3445 remove_quoted_nulls (string)
3446      char *string;
3447 {
3448   register size_t slen;
3449   register int i, j, prev_i;
3450   DECLARE_MBSTATE;
3451
3452   if (strchr (string, CTLNUL) == 0)             /* XXX */
3453     return string;                              /* XXX */
3454
3455   slen = strlen (string);
3456   i = j = 0;
3457
3458   while (i < slen)
3459     {
3460       if (string[i] == CTLESC)
3461         {
3462           /* Old code had j++, but we cannot assume that i == j at this
3463              point -- what if a CTLNUL has already been removed from the
3464              string?  We don't want to drop the CTLESC or recopy characters
3465              that we've already copied down. */
3466           i++; string[j++] = CTLESC;
3467           if (i == slen)
3468             break;
3469         }
3470       else if (string[i] == CTLNUL)
3471         i++;
3472
3473       prev_i = i;
3474       ADVANCE_CHAR (string, slen, i);
3475       if (j < prev_i)
3476         {
3477           do string[j++] = string[prev_i++]; while (prev_i < i);
3478         }
3479       else
3480         j = i;
3481     }
3482   string[j] = '\0';
3483
3484   return (string);
3485 }
3486
3487 /* Perform quoted null character removal on each element of LIST.
3488    This modifies LIST. */
3489 void
3490 word_list_remove_quoted_nulls (list)
3491      WORD_LIST *list;
3492 {
3493   register WORD_LIST *t;
3494
3495   for (t = list; t; t = t->next)
3496     {
3497       remove_quoted_nulls (t->word->word);
3498       t->word->flags &= ~W_HASQUOTEDNULL;
3499     }
3500 }
3501
3502 /* **************************************************************** */
3503 /*                                                                  */
3504 /*         Functions for Matching and Removing Patterns             */
3505 /*                                                                  */
3506 /* **************************************************************** */
3507
3508 #if defined (HANDLE_MULTIBYTE)
3509 #if 0 /* Currently unused */
3510 static unsigned char *
3511 mb_getcharlens (string, len)
3512      char *string;
3513      int len;
3514 {
3515   int i, offset, last;
3516   unsigned char *ret;
3517   char *p;
3518   DECLARE_MBSTATE;
3519
3520   i = offset = 0;
3521   last = 0;
3522   ret = (unsigned char *)xmalloc (len);
3523   memset (ret, 0, len);
3524   while (string[last])
3525     {
3526       ADVANCE_CHAR (string, len, offset);
3527       ret[last] = offset - last;
3528       last = offset;
3529     }
3530   return ret;
3531 }
3532 #endif
3533 #endif
3534
3535 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3536    can have one of 4 values:
3537         RP_LONG_LEFT    remove longest matching portion at start of PARAM
3538         RP_SHORT_LEFT   remove shortest matching portion at start of PARAM
3539         RP_LONG_RIGHT   remove longest matching portion at end of PARAM
3540         RP_SHORT_RIGHT  remove shortest matching portion at end of PARAM
3541 */
3542
3543 #define RP_LONG_LEFT    1
3544 #define RP_SHORT_LEFT   2
3545 #define RP_LONG_RIGHT   3
3546 #define RP_SHORT_RIGHT  4
3547
3548 static char *
3549 remove_upattern (param, pattern, op)
3550      char *param, *pattern;
3551      int op;
3552 {
3553   register int len;
3554   register char *end;
3555   register char *p, *ret, c;
3556
3557   len = STRLEN (param);
3558   end = param + len;
3559
3560   switch (op)
3561     {
3562       case RP_LONG_LEFT:        /* remove longest match at start */
3563         for (p = end; p >= param; p--)
3564           {
3565             c = *p; *p = '\0';
3566             if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3567               {
3568                 *p = c;
3569                 return (savestring (p));
3570               }
3571             *p = c;
3572
3573           }
3574         break;
3575
3576       case RP_SHORT_LEFT:       /* remove shortest match at start */
3577         for (p = param; p <= end; p++)
3578           {
3579             c = *p; *p = '\0';
3580             if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3581               {
3582                 *p = c;
3583                 return (savestring (p));
3584               }
3585             *p = c;
3586           }
3587         break;
3588
3589       case RP_LONG_RIGHT:       /* remove longest match at end */
3590         for (p = param; p <= end; p++)
3591           {
3592             if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3593               {
3594                 c = *p; *p = '\0';
3595                 ret = savestring (param);
3596                 *p = c;
3597                 return (ret);
3598               }
3599           }
3600         break;
3601
3602       case RP_SHORT_RIGHT:      /* remove shortest match at end */
3603         for (p = end; p >= param; p--)
3604           {
3605             if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3606               {
3607                 c = *p; *p = '\0';
3608                 ret = savestring (param);
3609                 *p = c;
3610                 return (ret);
3611               }
3612           }
3613         break;
3614     }
3615
3616   return (savestring (param));  /* no match, return original string */
3617 }
3618
3619 #if defined (HANDLE_MULTIBYTE)
3620 static wchar_t *
3621 remove_wpattern (wparam, wstrlen, wpattern, op)
3622      wchar_t *wparam;
3623      size_t wstrlen;
3624      wchar_t *wpattern;
3625      int op;
3626 {
3627   wchar_t wc, *ret;
3628   int n;
3629
3630   switch (op)
3631     {
3632       case RP_LONG_LEFT:        /* remove longest match at start */
3633         for (n = wstrlen; n >= 0; n--)
3634           {
3635             wc = wparam[n]; wparam[n] = L'\0';
3636             if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3637               {
3638                 wparam[n] = wc;
3639                 return (wcsdup (wparam + n));
3640               }
3641             wparam[n] = wc;
3642           }
3643         break;
3644
3645       case RP_SHORT_LEFT:       /* remove shortest match at start */
3646         for (n = 0; n <= wstrlen; n++)
3647           {
3648             wc = wparam[n]; wparam[n] = L'\0';
3649             if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3650               {
3651                 wparam[n] = wc;
3652                 return (wcsdup (wparam + n));
3653               }
3654             wparam[n] = wc;
3655           }
3656         break;
3657
3658       case RP_LONG_RIGHT:       /* remove longest match at end */
3659         for (n = 0; n <= wstrlen; n++)
3660           {
3661             if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3662               {
3663                 wc = wparam[n]; wparam[n] = L'\0';
3664                 ret = wcsdup (wparam);
3665                 wparam[n] = wc;
3666                 return (ret);
3667               }
3668           }
3669         break;
3670
3671       case RP_SHORT_RIGHT:      /* remove shortest match at end */
3672         for (n = wstrlen; n >= 0; n--)
3673           {
3674             if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3675               {
3676                 wc = wparam[n]; wparam[n] = L'\0';
3677                 ret = wcsdup (wparam);
3678                 wparam[n] = wc;
3679                 return (ret);
3680               }
3681           }
3682         break;
3683     }
3684
3685   return (wcsdup (wparam));     /* no match, return original string */
3686 }
3687 #endif /* HANDLE_MULTIBYTE */
3688
3689 static char *
3690 remove_pattern (param, pattern, op)
3691      char *param, *pattern;
3692      int op;
3693 {
3694   if (param == NULL)
3695     return (param);
3696   if (*param == '\0' || pattern == NULL || *pattern == '\0')    /* minor optimization */
3697     return (savestring (param));
3698
3699 #if defined (HANDLE_MULTIBYTE)
3700   if (MB_CUR_MAX > 1)
3701     {
3702       wchar_t *ret, *oret;
3703       size_t n;
3704       wchar_t *wparam, *wpattern;
3705       mbstate_t ps;
3706       char *xret;
3707
3708       n = xdupmbstowcs (&wpattern, NULL, pattern);
3709       if (n == (size_t)-1)
3710         return (remove_upattern (param, pattern, op));
3711       n = xdupmbstowcs (&wparam, NULL, param);
3712       if (n == (size_t)-1)
3713         {
3714           free (wpattern);
3715           return (remove_upattern (param, pattern, op));
3716         }
3717       oret = ret = remove_wpattern (wparam, n, wpattern, op);
3718
3719       free (wparam);
3720       free (wpattern);
3721
3722       n = strlen (param);
3723       xret = (char *)xmalloc (n + 1);
3724       memset (&ps, '\0', sizeof (mbstate_t));
3725       n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3726       xret[n] = '\0';           /* just to make sure */
3727       free (oret);
3728       return xret;      
3729     }
3730   else
3731 #endif
3732     return (remove_upattern (param, pattern, op));
3733 }
3734
3735 /* Return 1 of the first character of STRING could match the first
3736    character of pattern PAT.  Used to avoid n2 calls to strmatch(). */
3737 static int
3738 match_pattern_char (pat, string)
3739      char *pat, *string;
3740 {
3741   char c;
3742
3743   if (*string == 0)
3744     return (0);
3745
3746   switch (c = *pat++)
3747     {
3748     default:
3749       return (*string == c);
3750     case '\\':
3751       return (*string == *pat);
3752     case '?':
3753       return (*pat == LPAREN ? 1 : (*string != '\0'));
3754     case '*':
3755       return (1);
3756     case '+':
3757     case '!':
3758     case '@':
3759       return (*pat == LPAREN ? 1 : (*string == c));
3760     case '[':
3761       return (*string != '\0');
3762     }
3763 }
3764
3765 /* Match PAT anywhere in STRING and return the match boundaries.
3766    This returns 1 in case of a successful match, 0 otherwise.  SP
3767    and EP are pointers into the string where the match begins and
3768    ends, respectively.  MTYPE controls what kind of match is attempted.
3769    MATCH_BEG and MATCH_END anchor the match at the beginning and end
3770    of the string, respectively.  The longest match is returned. */
3771 static int
3772 match_upattern (string, pat, mtype, sp, ep)
3773      char *string, *pat;
3774      int mtype;
3775      char **sp, **ep;
3776 {
3777   int c, len;
3778   register char *p, *p1, *npat;
3779   char *end;
3780
3781   /* If the pattern doesn't match anywhere in the string, go ahead and
3782      short-circuit right away.  A minor optimization, saves a bunch of
3783      unnecessary calls to strmatch (up to N calls for a string of N
3784      characters) if the match is unsuccessful.  To preserve the semantics
3785      of the substring matches below, we make sure that the pattern has
3786      `*' as first and last character, making a new pattern if necessary. */
3787   /* XXX - check this later if I ever implement `**' with special meaning,
3788      since this will potentially result in `**' at the beginning or end */
3789   len = STRLEN (pat);
3790   if (pat[0] != '*' || (pat[0] == '*' && pat[1] == '(' && extended_glob) || pat[len - 1] != '*')        /*)*/
3791     {
3792       p = npat = (char *)xmalloc (len + 3);
3793       p1 = pat;
3794       if (*p1 != '*' || (*p1 == '*' && p1[1] == '(' && extended_glob))  /*)*/
3795         *p++ = '*';
3796       while (*p1)
3797         *p++ = *p1++;
3798       if (p1[-1] != '*' || p[-2] == '\\')
3799         *p++ = '*';
3800       *p = '\0';
3801     }
3802   else
3803     npat = pat;
3804   c = strmatch (npat, string, FNMATCH_EXTFLAG);
3805   if (npat != pat)
3806     free (npat);
3807   if (c == FNM_NOMATCH)
3808     return (0);
3809
3810   len = STRLEN (string);
3811   end = string + len;
3812
3813   switch (mtype)
3814     {
3815     case MATCH_ANY:
3816       for (p = string; p <= end; p++)
3817         {
3818           if (match_pattern_char (pat, p))
3819             {
3820               for (p1 = end; p1 >= p; p1--)
3821                 {
3822                   c = *p1; *p1 = '\0';
3823                   if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3824                     {
3825                       *p1 = c;
3826                       *sp = p;
3827                       *ep = p1;
3828                       return 1;
3829                     }
3830                   *p1 = c;
3831                 }
3832             }
3833         }
3834
3835       return (0);
3836
3837     case MATCH_BEG:
3838       if (match_pattern_char (pat, string) == 0)
3839         return (0);
3840
3841       for (p = end; p >= string; p--)
3842         {
3843           c = *p; *p = '\0';
3844           if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3845             {
3846               *p = c;
3847               *sp = string;
3848               *ep = p;
3849               return 1;
3850             }
3851           *p = c;
3852         }
3853
3854       return (0);
3855
3856     case MATCH_END:
3857       for (p = string; p <= end; p++)
3858         {
3859           if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3860             {
3861               *sp = p;
3862               *ep = end;
3863               return 1;
3864             }
3865
3866         }
3867
3868       return (0);
3869     }
3870
3871   return (0);
3872 }
3873
3874 #if defined (HANDLE_MULTIBYTE)
3875 /* Return 1 of the first character of WSTRING could match the first
3876    character of pattern WPAT.  Wide character version. */
3877 static int
3878 match_pattern_wchar (wpat, wstring)
3879      wchar_t *wpat, *wstring;
3880 {
3881   wchar_t wc;
3882
3883   if (*wstring == 0)
3884     return (0);
3885
3886   switch (wc = *wpat++)
3887     {
3888     default:
3889       return (*wstring == wc);
3890     case L'\\':
3891       return (*wstring == *wpat);
3892     case L'?':
3893       return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3894     case L'*':
3895       return (1);
3896     case L'+':
3897     case L'!':
3898     case L'@':
3899       return (*wpat == LPAREN ? 1 : (*wstring == wc));
3900     case L'[':
3901       return (*wstring != L'\0');
3902     }
3903 }
3904
3905 /* Match WPAT anywhere in WSTRING and return the match boundaries.
3906    This returns 1 in case of a successful match, 0 otherwise.  Wide
3907    character version. */
3908 static int
3909 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3910      wchar_t *wstring;
3911      char **indices;
3912      size_t wstrlen;
3913      wchar_t *wpat;
3914      int mtype;
3915      char **sp, **ep;
3916 {
3917   wchar_t wc, *wp, *nwpat, *wp1;
3918   int len;
3919 #if 0
3920   size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3921 #else
3922   int n, n1;
3923 #endif
3924
3925   /* If the pattern doesn't match anywhere in the string, go ahead and
3926      short-circuit right away.  A minor optimization, saves a bunch of
3927      unnecessary calls to strmatch (up to N calls for a string of N
3928      characters) if the match is unsuccessful.  To preserve the semantics
3929      of the substring matches below, we make sure that the pattern has
3930      `*' as first and last character, making a new pattern if necessary. */
3931   /* XXX - check this later if I ever implement `**' with special meaning,
3932      since this will potentially result in `**' at the beginning or end */
3933   len = wcslen (wpat);
3934   if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == L'(' && extended_glob) || wpat[len - 1] != L'*')        /*)*/
3935     {
3936       wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
3937       wp1 = wpat;
3938       if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == '(' && extended_glob))      /*)*/
3939         *wp++ = L'*';
3940       while (*wp1 != L'\0')
3941         *wp++ = *wp1++;
3942       if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3943         *wp++ = L'*';
3944       *wp = '\0';
3945     }
3946   else
3947     nwpat = wpat;
3948   len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3949   if (nwpat != wpat)
3950     free (nwpat);
3951   if (len == FNM_NOMATCH)
3952     return (0);
3953
3954   switch (mtype)
3955     {
3956     case MATCH_ANY:
3957       for (n = 0; n <= wstrlen; n++)
3958         {
3959           if (match_pattern_wchar (wpat, wstring + n))
3960             {
3961               for (n1 = wstrlen; n1 >= n; n1--)
3962                 {
3963                   wc = wstring[n1]; wstring[n1] = L'\0';
3964                   if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3965                     {
3966                       wstring[n1] = wc;
3967                       *sp = indices[n];
3968                       *ep = indices[n1];
3969                       return 1;
3970                     }
3971                   wstring[n1] = wc;
3972                 }
3973             }
3974         }
3975
3976       return (0);
3977
3978     case MATCH_BEG:
3979       if (match_pattern_wchar (wpat, wstring) == 0)
3980         return (0);
3981
3982       for (n = wstrlen; n >= 0; n--)
3983         {
3984           wc = wstring[n]; wstring[n] = L'\0';
3985           if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3986             {
3987               wstring[n] = wc;
3988               *sp = indices[0];
3989               *ep = indices[n];
3990               return 1;
3991             }
3992           wstring[n] = wc;
3993         }
3994
3995       return (0);
3996
3997     case MATCH_END:
3998       for (n = 0; n <= wstrlen; n++)
3999         {
4000           if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
4001             {
4002               *sp = indices[n];
4003               *ep = indices[wstrlen];
4004               return 1;
4005             }
4006         }
4007
4008       return (0);
4009     }
4010
4011   return (0);
4012 }
4013 #endif /* HANDLE_MULTIBYTE */
4014
4015 static int
4016 match_pattern (string, pat, mtype, sp, ep)
4017      char *string, *pat;
4018      int mtype;
4019      char **sp, **ep;
4020 {
4021 #if defined (HANDLE_MULTIBYTE)
4022   int ret;
4023   size_t n;
4024   wchar_t *wstring, *wpat;
4025   char **indices;
4026 #endif
4027
4028   if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
4029     return (0);
4030
4031 #if defined (HANDLE_MULTIBYTE)
4032   if (MB_CUR_MAX > 1)
4033     {
4034       n = xdupmbstowcs (&wpat, NULL, pat);
4035       if (n == (size_t)-1)
4036         return (match_upattern (string, pat, mtype, sp, ep));
4037       n = xdupmbstowcs (&wstring, &indices, string);
4038       if (n == (size_t)-1)
4039         {
4040           free (wpat);
4041           return (match_upattern (string, pat, mtype, sp, ep));
4042         }
4043       ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
4044
4045       free (wpat);
4046       free (wstring);
4047       free (indices);
4048
4049       return (ret);
4050     }
4051   else
4052 #endif
4053     return (match_upattern (string, pat, mtype, sp, ep));
4054 }
4055
4056 static int
4057 getpatspec (c, value)
4058      int c;
4059      char *value;
4060 {
4061   if (c == '#')
4062     return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
4063   else  /* c == '%' */
4064     return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
4065 }
4066
4067 /* Posix.2 says that the WORD should be run through tilde expansion,
4068    parameter expansion, command substitution and arithmetic expansion.
4069    This leaves the result quoted, so quote_string_for_globbing () has
4070    to be called to fix it up for strmatch ().  If QUOTED is non-zero,
4071    it means that the entire expression was enclosed in double quotes.
4072    This means that quoting characters in the pattern do not make any
4073    special pattern characters quoted.  For example, the `*' in the
4074    following retains its special meaning: "${foo#'*'}". */
4075 static char *
4076 getpattern (value, quoted, expandpat)
4077      char *value;
4078      int quoted, expandpat;
4079 {
4080   char *pat, *tword;
4081   WORD_LIST *l;
4082 #if 0
4083   int i;
4084 #endif
4085   /* There is a problem here:  how to handle single or double quotes in the
4086      pattern string when the whole expression is between double quotes?
4087      POSIX.2 says that enclosing double quotes do not cause the pattern to
4088      be quoted, but does that leave us a problem with @ and array[@] and their
4089      expansions inside a pattern? */
4090 #if 0
4091   if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
4092     {
4093       i = 0;
4094       pat = string_extract_double_quoted (tword, &i, 1);
4095       free (tword);
4096       tword = pat;
4097     }
4098 #endif
4099
4100   /* expand_string_for_rhs () leaves WORD quoted and does not perform
4101      word splitting. */
4102   l = *value ? expand_string_for_rhs (value,
4103                                       (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
4104                                       (int *)NULL, (int *)NULL)
4105              : (WORD_LIST *)0;
4106   pat = string_list (l);
4107   dispose_words (l);
4108   if (pat)
4109     {
4110       tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
4111       free (pat);
4112       pat = tword;
4113     }
4114   return (pat);
4115 }
4116
4117 #if 0
4118 /* Handle removing a pattern from a string as a result of ${name%[%]value}
4119    or ${name#[#]value}. */
4120 static char *
4121 variable_remove_pattern (value, pattern, patspec, quoted)
4122      char *value, *pattern;
4123      int patspec, quoted;
4124 {
4125   char *tword;
4126
4127   tword = remove_pattern (value, pattern, patspec);
4128
4129   return (tword);
4130 }
4131 #endif
4132
4133 static char *
4134 list_remove_pattern (list, pattern, patspec, itype, quoted)
4135      WORD_LIST *list;
4136      char *pattern;
4137      int patspec, itype, quoted;
4138 {
4139   WORD_LIST *new, *l;
4140   WORD_DESC *w;
4141   char *tword;
4142
4143   for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
4144     {
4145       tword = remove_pattern (l->word->word, pattern, patspec);
4146       w = alloc_word_desc ();
4147       w->word = tword ? tword : savestring ("");
4148       new = make_word_list (w, new);
4149     }
4150
4151   l = REVERSE_LIST (new, WORD_LIST *);
4152   tword = string_list_pos_params (itype, l, quoted);
4153   dispose_words (l);
4154
4155   return (tword);
4156 }
4157
4158 static char *
4159 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
4160      int itype;
4161      char *pattern;
4162      int patspec, quoted;
4163 {
4164   char *ret;
4165   WORD_LIST *list;
4166
4167   list = list_rest_of_args ();
4168   if (list == 0)
4169     return ((char *)NULL);
4170   ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4171   dispose_words (list);
4172   return (ret);
4173 }
4174
4175 #if defined (ARRAY_VARS)
4176 static char *
4177 array_remove_pattern (var, pattern, patspec, varname, quoted)
4178      SHELL_VAR *var;
4179      char *pattern;
4180      int patspec;
4181      char *varname;     /* so we can figure out how it's indexed */
4182      int quoted;
4183 {
4184   ARRAY *a;
4185   HASH_TABLE *h;
4186   int itype;
4187   char *ret;
4188   WORD_LIST *list;
4189   SHELL_VAR *v;
4190
4191   /* compute itype from varname here */
4192   v = array_variable_part (varname, &ret, 0);
4193   itype = ret[0];
4194
4195   a = (v && array_p (v)) ? array_cell (v) : 0;
4196   h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
4197   
4198   list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
4199   if (list == 0)
4200    return ((char *)NULL);
4201   ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4202   dispose_words (list);
4203
4204   return ret;
4205 }
4206 #endif /* ARRAY_VARS */
4207
4208 static char *
4209 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
4210      char *varname, *value, *patstr;
4211      int rtype, quoted;
4212 {
4213   int vtype, patspec, starsub;
4214   char *temp1, *val, *pattern;
4215   SHELL_VAR *v;
4216
4217   if (value == 0)
4218     return ((char *)NULL);
4219
4220   this_command_name = varname;
4221
4222   vtype = get_var_and_type (varname, value, quoted, &v, &val);
4223   if (vtype == -1)
4224     return ((char *)NULL);
4225
4226   starsub = vtype & VT_STARSUB;
4227   vtype &= ~VT_STARSUB;
4228
4229   patspec = getpatspec (rtype, patstr);
4230   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
4231     patstr++;
4232
4233   /* Need to pass getpattern newly-allocated memory in case of expansion --
4234      the expansion code will free the passed string on an error. */
4235   temp1 = savestring (patstr);
4236   pattern = getpattern (temp1, quoted, 1);
4237   free (temp1);
4238
4239   temp1 = (char *)NULL;         /* shut up gcc */
4240   switch (vtype)
4241     {
4242     case VT_VARIABLE:
4243     case VT_ARRAYMEMBER:
4244       temp1 = remove_pattern (val, pattern, patspec);
4245       if (vtype == VT_VARIABLE)
4246         FREE (val);
4247       if (temp1)
4248         {
4249           val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4250                         ? quote_string (temp1)
4251                         : quote_escapes (temp1);
4252           free (temp1);
4253           temp1 = val;
4254         }
4255       break;
4256 #if defined (ARRAY_VARS)
4257     case VT_ARRAYVAR:
4258       temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted);
4259       if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4260         {
4261           val = quote_escapes (temp1);
4262           free (temp1);
4263           temp1 = val;
4264         }
4265       break;
4266 #endif
4267     case VT_POSPARMS:
4268       temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
4269       if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4270         {
4271           val = quote_escapes (temp1);
4272           free (temp1);
4273           temp1 = val;
4274         }
4275       break;
4276     }
4277
4278   FREE (pattern);
4279   return temp1;
4280 }    
4281
4282 /*******************************************
4283  *                                         *
4284  *      Functions to expand WORD_DESCs     *
4285  *                                         *
4286  *******************************************/
4287
4288 /* Expand WORD, performing word splitting on the result.  This does
4289    parameter expansion, command substitution, arithmetic expansion,
4290    word splitting, and quote removal. */
4291
4292 WORD_LIST *
4293 expand_word (word, quoted)
4294      WORD_DESC *word;
4295      int quoted;
4296 {
4297   WORD_LIST *result, *tresult;
4298
4299   tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4300   result = word_list_split (tresult);
4301   dispose_words (tresult);
4302   return (result ? dequote_list (result) : result);
4303 }
4304
4305 /* Expand WORD, but do not perform word splitting on the result.  This
4306    does parameter expansion, command substitution, arithmetic expansion,
4307    and quote removal. */
4308 WORD_LIST *
4309 expand_word_unsplit (word, quoted)
4310      WORD_DESC *word;
4311      int quoted;
4312 {
4313   WORD_LIST *result;
4314
4315   expand_no_split_dollar_star = 1;
4316   result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4317   expand_no_split_dollar_star = 0;
4318
4319   return (result ? dequote_list (result) : result);
4320 }
4321
4322 /* Perform shell expansions on WORD, but do not perform word splitting or
4323    quote removal on the result. */
4324 WORD_LIST *
4325 expand_word_leave_quoted (word, quoted)
4326      WORD_DESC *word;
4327      int quoted;
4328 {
4329   return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
4330 }
4331
4332 #if defined (PROCESS_SUBSTITUTION)
4333
4334 /*****************************************************************/
4335 /*                                                               */
4336 /*                  Hacking Process Substitution                 */
4337 /*                                                               */
4338 /*****************************************************************/
4339
4340 #if !defined (HAVE_DEV_FD)
4341 /* Named pipes must be removed explicitly with `unlink'.  This keeps a list
4342    of FIFOs the shell has open.  unlink_fifo_list will walk the list and
4343    unlink all of them. add_fifo_list adds the name of an open FIFO to the
4344    list.  NFIFO is a count of the number of FIFOs in the list. */
4345 #define FIFO_INCR 20
4346
4347 struct temp_fifo {
4348   char *file;
4349   pid_t proc;
4350 };
4351
4352 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4353 static int nfifo;
4354 static int fifo_list_size;
4355
4356 static void
4357 add_fifo_list (pathname)
4358      char *pathname;
4359 {
4360   if (nfifo >= fifo_list_size - 1)
4361     {
4362       fifo_list_size += FIFO_INCR;
4363       fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4364                                 fifo_list_size * sizeof (struct temp_fifo));
4365     }
4366
4367   fifo_list[nfifo].file = savestring (pathname);
4368   nfifo++;
4369 }
4370
4371 void
4372 unlink_fifo_list ()
4373 {
4374   int saved, i, j;
4375
4376   if (nfifo == 0)
4377     return;
4378
4379   for (i = saved = 0; i < nfifo; i++)
4380     {
4381       if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4382         {
4383           unlink (fifo_list[i].file);
4384           free (fifo_list[i].file);
4385           fifo_list[i].file = (char *)NULL;
4386           fifo_list[i].proc = -1;
4387         }
4388       else
4389         saved++;
4390     }
4391
4392   /* If we didn't remove some of the FIFOs, compact the list. */
4393   if (saved)
4394     {
4395       for (i = j = 0; i < nfifo; i++)
4396         if (fifo_list[i].file)
4397           {
4398             fifo_list[j].file = fifo_list[i].file;
4399             fifo_list[j].proc = fifo_list[i].proc;
4400             j++;
4401           }
4402       nfifo = j;
4403     }
4404   else
4405     nfifo = 0;
4406 }
4407
4408 int
4409 fifos_pending ()
4410 {
4411   return nfifo;
4412 }
4413
4414 static char *
4415 make_named_pipe ()
4416 {
4417   char *tname;
4418
4419   tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
4420   if (mkfifo (tname, 0600) < 0)
4421     {
4422       free (tname);
4423       return ((char *)NULL);
4424     }
4425
4426   add_fifo_list (tname);
4427   return (tname);
4428 }
4429
4430 #else /* HAVE_DEV_FD */
4431
4432 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4433    has open to children.  NFDS is a count of the number of bits currently
4434    set in DEV_FD_LIST.  TOTFDS is a count of the highest possible number
4435    of open files. */
4436 static char *dev_fd_list = (char *)NULL;
4437 static int nfds;
4438 static int totfds;      /* The highest possible number of open files. */
4439
4440 static void
4441 add_fifo_list (fd)
4442      int fd;
4443 {
4444   if (!dev_fd_list || fd >= totfds)
4445     {
4446       int ofds;
4447
4448       ofds = totfds;
4449       totfds = getdtablesize ();
4450       if (totfds < 0 || totfds > 256)
4451         totfds = 256;
4452       if (fd >= totfds)
4453         totfds = fd + 2;
4454
4455       dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4456       memset (dev_fd_list + ofds, '\0', totfds - ofds);
4457     }
4458
4459   dev_fd_list[fd] = 1;
4460   nfds++;
4461 }
4462
4463 int
4464 fifos_pending ()
4465 {
4466   return 0;     /* used for cleanup; not needed with /dev/fd */
4467 }
4468
4469 void
4470 unlink_fifo_list ()
4471 {
4472   register int i;
4473
4474   if (nfds == 0)
4475     return;
4476
4477   for (i = 0; nfds && i < totfds; i++)
4478     if (dev_fd_list[i])
4479       {
4480         close (i);
4481         dev_fd_list[i] = 0;
4482         nfds--;
4483       }
4484
4485   nfds = 0;
4486 }
4487
4488 #if defined (NOTDEF)
4489 print_dev_fd_list ()
4490 {
4491   register int i;
4492
4493   fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4494   fflush (stderr);
4495
4496   for (i = 0; i < totfds; i++)
4497     {
4498       if (dev_fd_list[i])
4499         fprintf (stderr, " %d", i);
4500     }
4501   fprintf (stderr, "\n");
4502 }
4503 #endif /* NOTDEF */
4504
4505 static char *
4506 make_dev_fd_filename (fd)
4507      int fd;
4508 {
4509   char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4510
4511   ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8);
4512
4513   strcpy (ret, DEV_FD_PREFIX);
4514   p = inttostr (fd, intbuf, sizeof (intbuf));
4515   strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4516
4517   add_fifo_list (fd);
4518   return (ret);
4519 }
4520
4521 #endif /* HAVE_DEV_FD */
4522
4523 /* Return a filename that will open a connection to the process defined by
4524    executing STRING.  HAVE_DEV_FD, if defined, means open a pipe and return
4525    a filename in /dev/fd corresponding to a descriptor that is one of the
4526    ends of the pipe.  If not defined, we use named pipes on systems that have
4527    them.  Systems without /dev/fd and named pipes are out of luck.
4528
4529    OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4530    use the read end of the pipe and dup that file descriptor to fd 0 in
4531    the child.  If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4532    writing or use the write end of the pipe in the child, and dup that
4533    file descriptor to fd 1 in the child.  The parent does the opposite. */
4534
4535 static char *
4536 process_substitute (string, open_for_read_in_child)
4537      char *string;
4538      int open_for_read_in_child;
4539 {
4540   char *pathname;
4541   int fd, result;
4542   pid_t old_pid, pid;
4543 #if defined (HAVE_DEV_FD)
4544   int parent_pipe_fd, child_pipe_fd;
4545   int fildes[2];
4546 #endif /* HAVE_DEV_FD */
4547 #if defined (JOB_CONTROL)
4548   pid_t old_pipeline_pgrp;
4549 #endif
4550
4551   if (!string || !*string || wordexp_only)
4552     return ((char *)NULL);
4553
4554 #if !defined (HAVE_DEV_FD)
4555   pathname = make_named_pipe ();
4556 #else /* HAVE_DEV_FD */
4557   if (pipe (fildes) < 0)
4558     {
4559       sys_error (_("cannot make pipe for process substitution"));
4560       return ((char *)NULL);
4561     }
4562   /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4563      the pipe in the parent, otherwise the read end. */
4564   parent_pipe_fd = fildes[open_for_read_in_child];
4565   child_pipe_fd = fildes[1 - open_for_read_in_child];
4566   /* Move the parent end of the pipe to some high file descriptor, to
4567      avoid clashes with FDs used by the script. */
4568   parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4569
4570   pathname = make_dev_fd_filename (parent_pipe_fd);
4571 #endif /* HAVE_DEV_FD */
4572
4573   if (pathname == 0)
4574     {
4575       sys_error (_("cannot make pipe for process substitution"));
4576       return ((char *)NULL);
4577     }
4578
4579   old_pid = last_made_pid;
4580
4581 #if defined (JOB_CONTROL)
4582   old_pipeline_pgrp = pipeline_pgrp;
4583   pipeline_pgrp = shell_pgrp;
4584   save_pipeline (1);
4585 #endif /* JOB_CONTROL */
4586
4587   pid = make_child ((char *)NULL, 1);
4588   if (pid == 0)
4589     {
4590       reset_terminating_signals ();     /* XXX */
4591       free_pushed_string_input ();
4592       /* Cancel traps, in trap.c. */
4593       restore_original_signals ();
4594       setup_async_signals ();
4595       subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
4596     }
4597
4598 #if defined (JOB_CONTROL)
4599   set_sigchld_handler ();
4600   stop_making_children ();
4601   /* XXX - should we only do this in the parent? (as in command subst) */
4602   pipeline_pgrp = old_pipeline_pgrp;
4603 #endif /* JOB_CONTROL */
4604
4605   if (pid < 0)
4606     {
4607       sys_error (_("cannot make child for process substitution"));
4608       free (pathname);
4609 #if defined (HAVE_DEV_FD)
4610       close (parent_pipe_fd);
4611       close (child_pipe_fd);
4612 #endif /* HAVE_DEV_FD */
4613       return ((char *)NULL);
4614     }
4615
4616   if (pid > 0)
4617     {
4618 #if defined (JOB_CONTROL)
4619       restore_pipeline (1);
4620 #endif
4621
4622 #if !defined (HAVE_DEV_FD)
4623       fifo_list[nfifo-1].proc = pid;
4624 #endif
4625
4626       last_made_pid = old_pid;
4627
4628 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4629       close_pgrp_pipe ();
4630 #endif /* JOB_CONTROL && PGRP_PIPE */
4631
4632 #if defined (HAVE_DEV_FD)
4633       close (child_pipe_fd);
4634 #endif /* HAVE_DEV_FD */
4635
4636       return (pathname);
4637     }
4638
4639   set_sigint_handler ();
4640
4641 #if defined (JOB_CONTROL)
4642   set_job_control (0);
4643 #endif /* JOB_CONTROL */
4644
4645 #if !defined (HAVE_DEV_FD)
4646   /* Open the named pipe in the child. */
4647   fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4648   if (fd < 0)
4649     {
4650       /* Two separate strings for ease of translation. */
4651       if (open_for_read_in_child)
4652         sys_error (_("cannot open named pipe %s for reading"), pathname);
4653       else
4654         sys_error (_("cannot open named pipe %s for writing"), pathname);
4655
4656       exit (127);
4657     }
4658   if (open_for_read_in_child)
4659     {
4660       if (sh_unset_nodelay_mode (fd) < 0)
4661         {
4662           sys_error (_("cannot reset nodelay mode for fd %d"), fd);
4663           exit (127);
4664         }
4665     }
4666 #else /* HAVE_DEV_FD */
4667   fd = child_pipe_fd;
4668 #endif /* HAVE_DEV_FD */
4669
4670   if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4671     {
4672       sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4673         open_for_read_in_child ? 0 : 1);
4674       exit (127);
4675     }
4676
4677   if (fd != (open_for_read_in_child ? 0 : 1))
4678     close (fd);
4679
4680   /* Need to close any files that this process has open to pipes inherited
4681      from its parent. */
4682   if (current_fds_to_close)
4683     {
4684       close_fd_bitmap (current_fds_to_close);
4685       current_fds_to_close = (struct fd_bitmap *)NULL;
4686     }
4687
4688 #if defined (HAVE_DEV_FD)
4689   /* Make sure we close the parent's end of the pipe and clear the slot
4690      in the fd list so it is not closed later, if reallocated by, for
4691      instance, pipe(2). */
4692   close (parent_pipe_fd);
4693   dev_fd_list[parent_pipe_fd] = 0;
4694 #endif /* HAVE_DEV_FD */
4695
4696   result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4697
4698 #if !defined (HAVE_DEV_FD)
4699   /* Make sure we close the named pipe in the child before we exit. */
4700   close (open_for_read_in_child ? 0 : 1);
4701 #endif /* !HAVE_DEV_FD */
4702
4703   exit (result);
4704   /*NOTREACHED*/
4705 }
4706 #endif /* PROCESS_SUBSTITUTION */
4707
4708 /***********************************/
4709 /*                                 */
4710 /*      Command Substitution       */
4711 /*                                 */
4712 /***********************************/
4713
4714 static char *
4715 read_comsub (fd, quoted, rflag)
4716      int fd, quoted;
4717      int *rflag;
4718 {
4719   char *istring, buf[128], *bufp, *s;
4720   int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
4721   ssize_t bufn;
4722
4723   istring = (char *)NULL;
4724   istring_index = istring_size = bufn = tflag = 0;
4725
4726   for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
4727     skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
4728
4729 #ifdef __CYGWIN__
4730   setmode (fd, O_TEXT);         /* we don't want CR/LF, we want Unix-style */
4731 #endif
4732
4733   /* Read the output of the command through the pipe.  This may need to be
4734      changed to understand multibyte characters in the future. */
4735   while (1)
4736     {
4737       if (fd < 0)
4738         break;
4739       if (--bufn <= 0)
4740         {
4741           bufn = zread (fd, buf, sizeof (buf));
4742           if (bufn <= 0) 
4743             break;
4744           bufp = buf;
4745         }
4746       c = *bufp++;
4747
4748       if (c == 0)
4749         {
4750 #if 0
4751           internal_warning ("read_comsub: ignored null byte in input");
4752 #endif
4753           continue;
4754         }
4755
4756       /* Add the character to ISTRING, possibly after resizing it. */
4757       RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4758
4759       /* This is essentially quote_string inline */
4760       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
4761         istring[istring_index++] = CTLESC;
4762       /* Escape CTLESC and CTLNUL in the output to protect those characters
4763          from the rest of the word expansions (word splitting and globbing.)
4764          This is essentially quote_escapes inline. */
4765       else if (skip_ctlesc == 0 && c == CTLESC)
4766         {
4767           tflag |= W_HASCTLESC;
4768           istring[istring_index++] = CTLESC;
4769         }
4770       else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
4771         istring[istring_index++] = CTLESC;
4772
4773       istring[istring_index++] = c;
4774
4775 #if 0
4776 #if defined (__CYGWIN__)
4777       if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4778         {
4779           istring_index--;
4780           istring[istring_index - 1] = '\n';
4781         }
4782 #endif
4783 #endif
4784     }
4785
4786   if (istring)
4787     istring[istring_index] = '\0';
4788
4789   /* If we read no output, just return now and save ourselves some
4790      trouble. */
4791   if (istring_index == 0)
4792     {
4793       FREE (istring);
4794       if (rflag)
4795         *rflag = tflag;
4796       return (char *)NULL;
4797     }
4798
4799   /* Strip trailing newlines from the output of the command. */
4800   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4801     {
4802       while (istring_index > 0)
4803         {
4804           if (istring[istring_index - 1] == '\n')
4805             {
4806               --istring_index;
4807
4808               /* If the newline was quoted, remove the quoting char. */
4809               if (istring[istring_index - 1] == CTLESC)
4810                 --istring_index;
4811             }
4812           else
4813             break;
4814         }
4815       istring[istring_index] = '\0';
4816     }
4817   else
4818     strip_trailing (istring, istring_index - 1, 1);
4819
4820   if (rflag)
4821     *rflag = tflag;
4822   return istring;
4823 }
4824
4825 /* Perform command substitution on STRING.  This returns a WORD_DESC * with the
4826    contained string possibly quoted. */
4827 WORD_DESC *
4828 command_substitute (string, quoted)
4829      char *string;
4830      int quoted;
4831 {
4832   pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4833   char *istring;
4834   int result, fildes[2], function_value, pflags, rc, tflag;
4835   WORD_DESC *ret;
4836
4837   istring = (char *)NULL;
4838
4839   /* Don't fork () if there is no need to.  In the case of no command to
4840      run, just return NULL. */
4841   if (!string || !*string || (string[0] == '\n' && !string[1]))
4842     return ((WORD_DESC *)NULL);
4843
4844   if (wordexp_only && read_but_dont_execute)
4845     {
4846       last_command_exit_value = 125;
4847       jump_to_top_level (EXITPROG);
4848     }
4849
4850   /* We're making the assumption here that the command substitution will
4851      eventually run a command from the file system.  Since we'll run
4852      maybe_make_export_env in this subshell before executing that command,
4853      the parent shell and any other shells it starts will have to remake
4854      the environment.  If we make it before we fork, other shells won't
4855      have to.  Don't bother if we have any temporary variable assignments,
4856      though, because the export environment will be remade after this
4857      command completes anyway, but do it if all the words to be expanded
4858      are variable assignments. */
4859   if (subst_assign_varlist == 0 || garglist == 0)
4860     maybe_make_export_env ();   /* XXX */
4861
4862   /* Flags to pass to parse_and_execute() */
4863   pflags = interactive ? SEVAL_RESETLINE : 0;
4864
4865   /* Pipe the output of executing STRING into the current shell. */
4866   if (pipe (fildes) < 0)
4867     {
4868       sys_error (_("cannot make pipe for command substitution"));
4869       goto error_exit;
4870     }
4871
4872   old_pid = last_made_pid;
4873 #if defined (JOB_CONTROL)
4874   old_pipeline_pgrp = pipeline_pgrp;
4875   /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4876   if ((subshell_environment & SUBSHELL_PIPE) == 0)
4877     pipeline_pgrp = shell_pgrp;
4878   cleanup_the_pipeline ();
4879 #endif /* JOB_CONTROL */
4880
4881   old_async_pid = last_asynchronous_pid;
4882   pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4883   last_asynchronous_pid = old_async_pid;
4884
4885   if (pid == 0)
4886     /* Reset the signal handlers in the child, but don't free the
4887        trap strings. */
4888     reset_signal_handlers ();
4889
4890 #if defined (JOB_CONTROL)
4891   /* XXX DO THIS ONLY IN PARENT ? XXX */
4892   set_sigchld_handler ();
4893   stop_making_children ();
4894   if (pid != 0)
4895     pipeline_pgrp = old_pipeline_pgrp;
4896 #else
4897   stop_making_children ();
4898 #endif /* JOB_CONTROL */
4899
4900   if (pid < 0)
4901     {
4902       sys_error (_("cannot make child for command substitution"));
4903     error_exit:
4904
4905       FREE (istring);
4906       close (fildes[0]);
4907       close (fildes[1]);
4908       return ((WORD_DESC *)NULL);
4909     }
4910
4911   if (pid == 0)
4912     {
4913       set_sigint_handler ();    /* XXX */
4914
4915       free_pushed_string_input ();
4916
4917       if (dup2 (fildes[1], 1) < 0)
4918         {
4919           sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4920           exit (EXECUTION_FAILURE);
4921         }
4922
4923       /* If standard output is closed in the parent shell
4924          (such as after `exec >&-'), file descriptor 1 will be
4925          the lowest available file descriptor, and end up in
4926          fildes[0].  This can happen for stdin and stderr as well,
4927          but stdout is more important -- it will cause no output
4928          to be generated from this command. */
4929       if ((fildes[1] != fileno (stdin)) &&
4930           (fildes[1] != fileno (stdout)) &&
4931           (fildes[1] != fileno (stderr)))
4932         close (fildes[1]);
4933
4934       if ((fildes[0] != fileno (stdin)) &&
4935           (fildes[0] != fileno (stdout)) &&
4936           (fildes[0] != fileno (stderr)))
4937         close (fildes[0]);
4938
4939       /* The currently executing shell is not interactive. */
4940       interactive = 0;
4941
4942       /* This is a subshell environment. */
4943       subshell_environment |= SUBSHELL_COMSUB;
4944
4945       /* When not in POSIX mode, command substitution does not inherit
4946          the -e flag. */
4947       if (posixly_correct == 0)
4948         exit_immediately_on_error = 0;
4949
4950       remove_quoted_escapes (string);
4951
4952       startup_state = 2;        /* see if we can avoid a fork */
4953       /* Give command substitution a place to jump back to on failure,
4954          so we don't go back up to main (). */
4955       result = setjmp (top_level);
4956
4957       /* If we're running a command substitution inside a shell function,
4958          trap `return' so we don't return from the function in the subshell
4959          and go off to never-never land. */
4960       if (result == 0 && return_catch_flag)
4961         function_value = setjmp (return_catch);
4962       else
4963         function_value = 0;
4964
4965       if (result == ERREXIT)
4966         rc = last_command_exit_value;
4967       else if (result == EXITPROG)
4968         rc = last_command_exit_value;
4969       else if (result)
4970         rc = EXECUTION_FAILURE;
4971       else if (function_value)
4972         rc = return_catch_value;
4973       else
4974         {
4975           subshell_level++;
4976           rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4977           subshell_level--;
4978         }
4979
4980       last_command_exit_value = rc;
4981       rc = run_exit_trap ();
4982 #if defined (PROCESS_SUBSTITUTION)
4983       unlink_fifo_list ();
4984 #endif
4985       exit (rc);
4986     }
4987   else
4988     {
4989 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4990       close_pgrp_pipe ();
4991 #endif /* JOB_CONTROL && PGRP_PIPE */
4992
4993       close (fildes[1]);
4994
4995       tflag = 0;
4996       istring = read_comsub (fildes[0], quoted, &tflag);
4997
4998       close (fildes[0]);
4999
5000       current_command_subst_pid = pid;
5001       last_command_exit_value = wait_for (pid);
5002       last_command_subst_pid = pid;
5003       last_made_pid = old_pid;
5004
5005 #if defined (JOB_CONTROL)
5006       /* If last_command_exit_value > 128, then the substituted command
5007          was terminated by a signal.  If that signal was SIGINT, then send
5008          SIGINT to ourselves.  This will break out of loops, for instance. */
5009       if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
5010         kill (getpid (), SIGINT);
5011
5012       /* wait_for gives the terminal back to shell_pgrp.  If some other
5013          process group should have it, give it away to that group here.
5014          pipeline_pgrp is non-zero only while we are constructing a
5015          pipline, so what we are concerned about is whether or not that
5016          pipeline was started in the background.  A pipeline started in
5017          the background should never get the tty back here. */
5018 #if 0
5019       if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
5020 #else
5021       if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
5022 #endif
5023         give_terminal_to (pipeline_pgrp, 0);
5024 #endif /* JOB_CONTROL */
5025
5026       ret = alloc_word_desc ();
5027       ret->word = istring;
5028       ret->flags = tflag;
5029
5030       return ret;
5031     }
5032 }
5033
5034 /********************************************************
5035  *                                                      *
5036  *      Utility functions for parameter expansion       *
5037  *                                                      *
5038  ********************************************************/
5039
5040 #if defined (ARRAY_VARS)
5041
5042 static arrayind_t
5043 array_length_reference (s)
5044      char *s;
5045 {
5046   int len;
5047   arrayind_t ind;
5048   char *akey;
5049   char *t, c;
5050   ARRAY *array;
5051   SHELL_VAR *var;
5052
5053   var = array_variable_part (s, &t, &len);
5054
5055   /* If unbound variables should generate an error, report one and return
5056      failure. */
5057   if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
5058     {
5059       c = *--t;
5060       *t = '\0';
5061       err_unboundvar (s);
5062       *t = c;
5063       return (-1);
5064     }
5065   else if (var == 0)
5066     return 0;
5067
5068   /* We support a couple of expansions for variables that are not arrays.
5069      We'll return the length of the value for v[0], and 1 for v[@] or
5070      v[*].  Return 0 for everything else. */
5071
5072   array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
5073
5074   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
5075     {
5076       if (assoc_p (var))
5077         return (assoc_num_elements (assoc_cell (var)));
5078       else if (array_p (var))
5079         return (array_num_elements (array));
5080       else
5081         return 1;
5082     }
5083
5084   if (assoc_p (var))
5085     {
5086       t[len - 1] = '\0';
5087       akey = expand_assignment_string_to_string (t, 0); /* [ */
5088       t[len - 1] = ']';
5089       if (akey == 0 || *akey == 0)
5090         {
5091           err_badarraysub (t);
5092           return (-1);
5093         }
5094       t = assoc_reference (assoc_cell (var), akey);
5095     }
5096   else
5097     {
5098       ind = array_expand_index (t, len);
5099       if (ind < 0)
5100         {
5101           err_badarraysub (t);
5102           return (-1);
5103         }
5104       if (array_p (var))
5105         t = array_reference (array, ind);
5106       else
5107         t = (ind == 0) ? value_cell (var) : (char *)NULL;
5108     }
5109
5110   len = MB_STRLEN (t);
5111   return (len);
5112 }
5113 #endif /* ARRAY_VARS */
5114
5115 static int
5116 valid_brace_expansion_word (name, var_is_special)
5117      char *name;
5118      int var_is_special;
5119 {
5120   if (DIGIT (*name) && all_digits (name))
5121     return 1;
5122   else if (var_is_special)
5123     return 1;
5124 #if defined (ARRAY_VARS)
5125   else if (valid_array_reference (name))
5126     return 1;
5127 #endif /* ARRAY_VARS */
5128   else if (legal_identifier (name))
5129     return 1;
5130   else
5131     return 0;
5132 }
5133
5134 static int
5135 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
5136      char *name;
5137      int quoted;
5138      int *quoted_dollar_atp, *contains_dollar_at;
5139 {
5140   char *temp1;
5141
5142   if (name == 0)
5143     {
5144       if (quoted_dollar_atp)
5145         *quoted_dollar_atp = 0;
5146       if (contains_dollar_at)
5147         *contains_dollar_at = 0;
5148       return 0;
5149     }
5150
5151   /* check for $@ and $* */
5152   if (name[0] == '@' && name[1] == 0)
5153     {
5154       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5155         *quoted_dollar_atp = 1;
5156       if (contains_dollar_at)
5157         *contains_dollar_at = 1;
5158       return 1;
5159     }
5160   else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
5161     {
5162       if (contains_dollar_at)
5163         *contains_dollar_at = 1;
5164       return 1;
5165     }
5166
5167   /* Now check for ${array[@]} and ${array[*]} */
5168 #if defined (ARRAY_VARS)
5169   else if (valid_array_reference (name))
5170     {
5171       temp1 = xstrchr (name, '[');
5172       if (temp1 && temp1[1] == '@' && temp1[2] == ']')
5173         {
5174           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5175             *quoted_dollar_atp = 1;
5176           if (contains_dollar_at)
5177             *contains_dollar_at = 1;
5178           return 1;
5179         }       /* [ */
5180       /* ${array[*]}, when unquoted, should be treated like ${array[@]},
5181          which should result in separate words even when IFS is unset. */
5182       if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
5183         {
5184           if (contains_dollar_at)
5185             *contains_dollar_at = 1;
5186           return 1;
5187         }
5188     }
5189 #endif
5190   return 0;
5191 }
5192
5193 /* Parameter expand NAME, and return a new string which is the expansion,
5194    or NULL if there was no expansion.
5195    VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
5196    the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
5197    NAME was found inside of a double-quoted expression. */
5198 static WORD_DESC *
5199 parameter_brace_expand_word (name, var_is_special, quoted, pflags)
5200      char *name;
5201      int var_is_special, quoted, pflags;
5202 {
5203   WORD_DESC *ret;
5204   char *temp, *tt;
5205   intmax_t arg_index;
5206   SHELL_VAR *var;
5207   int atype, rflags;
5208
5209   ret = 0;
5210   temp = 0;
5211   rflags = 0;
5212
5213   /* Handle multiple digit arguments, as in ${11}. */  
5214   if (legal_number (name, &arg_index))
5215     {
5216       tt = get_dollar_var_value (arg_index);
5217       if (tt)
5218         temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5219                   ? quote_string (tt)
5220                   : quote_escapes (tt);
5221       else
5222         temp = (char *)NULL;
5223       FREE (tt);
5224     }
5225   else if (var_is_special)      /* ${@} */
5226     {
5227       int sindex;
5228       tt = (char *)xmalloc (2 + strlen (name));
5229       tt[sindex = 0] = '$';
5230       strcpy (tt + 1, name);
5231
5232       ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
5233                           (int *)NULL, (int *)NULL, pflags);
5234       free (tt);
5235     }
5236 #if defined (ARRAY_VARS)
5237   else if (valid_array_reference (name))
5238     {
5239       temp = array_value (name, quoted, &atype);
5240       if (atype == 0 && temp)
5241         temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5242                   ? quote_string (temp)
5243                   : quote_escapes (temp);
5244       else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5245         rflags |= W_HASQUOTEDNULL;
5246     }
5247 #endif
5248   else if (var = find_variable (name))
5249     {
5250       if (var_isset (var) && invisible_p (var) == 0)
5251         {
5252 #if defined (ARRAY_VARS)
5253           if (assoc_p (var))
5254             temp = assoc_reference (assoc_cell (var), "0");
5255           else if (array_p (var))
5256             temp = array_reference (array_cell (var), 0);
5257           else
5258             temp = value_cell (var);
5259 #else
5260           temp = value_cell (var);
5261 #endif
5262
5263           if (temp)
5264             temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5265                       ? quote_string (temp)
5266                       : quote_escapes (temp);
5267         }
5268       else
5269         temp = (char *)NULL;
5270     }
5271   else
5272     temp = (char *)NULL;
5273
5274   if (ret == 0)
5275     {
5276       ret = alloc_word_desc ();
5277       ret->word = temp;
5278       ret->flags |= rflags;
5279     }
5280   return ret;
5281 }
5282
5283 /* Expand an indirect reference to a variable: ${!NAME} expands to the
5284    value of the variable whose name is the value of NAME. */
5285 static WORD_DESC *
5286 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
5287      char *name;
5288      int var_is_special, quoted;
5289      int *quoted_dollar_atp, *contains_dollar_at;
5290 {
5291   char *temp, *t;
5292   WORD_DESC *w;
5293
5294   w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
5295   t = w->word;
5296   /* Have to dequote here if necessary */
5297   if (t)
5298     {
5299       temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5300                 ? dequote_string (t)
5301                 : dequote_escapes (t);
5302       free (t);
5303       t = temp;
5304     }
5305   dispose_word_desc (w);
5306
5307   chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5308   if (t == 0)
5309     return (WORD_DESC *)NULL;
5310
5311   w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
5312   free (t);
5313
5314   return w;
5315 }
5316
5317 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5318    depending on the value of C, the separating character.  C can be one of
5319    "-", "+", or "=".  QUOTED is true if the entire brace expression occurs
5320    between double quotes. */
5321 static WORD_DESC *
5322 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5323      char *name, *value;
5324      int c, quoted, *qdollaratp, *hasdollarat;
5325 {
5326   WORD_DESC *w;
5327   WORD_LIST *l;
5328   char *t, *t1, *temp;
5329   int hasdol;
5330
5331   /* If the entire expression is between double quotes, we want to treat
5332      the value as a double-quoted string, with the exception that we strip
5333      embedded unescaped double quotes (for sh backwards compatibility). */
5334   if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5335     {
5336       hasdol = 0;
5337       temp = string_extract_double_quoted (value, &hasdol, 1);
5338     }
5339   else
5340     temp = value;
5341
5342   w = alloc_word_desc ();
5343   hasdol = 0;
5344   /* XXX was 0 not quoted */
5345   l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5346             : (WORD_LIST *)0;
5347   if (hasdollarat)
5348     *hasdollarat = hasdol || (l && l->next);
5349   if (temp != value)
5350     free (temp);
5351   if (l)
5352     {
5353       /* The expansion of TEMP returned something.  We need to treat things
5354           slightly differently if HASDOL is non-zero.  If we have "$@", the
5355           individual words have already been quoted.  We need to turn them
5356           into a string with the words separated by the first character of
5357           $IFS without any additional quoting, so string_list_dollar_at won't
5358           do the right thing.  We use string_list_dollar_star instead. */
5359       temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5360
5361       /* If l->next is not null, we know that TEMP contained "$@", since that
5362          is the only expansion that creates more than one word. */
5363       if (qdollaratp && ((hasdol && quoted) || l->next))
5364         *qdollaratp = 1;
5365       dispose_words (l);
5366     }
5367   else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5368     {
5369       /* The brace expansion occurred between double quotes and there was
5370          a $@ in TEMP.  It does not matter if the $@ is quoted, as long as
5371          it does not expand to anything.  In this case, we want to return
5372          a quoted empty string. */
5373       temp = make_quoted_char ('\0');
5374       w->flags |= W_HASQUOTEDNULL;
5375     }
5376   else
5377     temp = (char *)NULL;
5378
5379   if (c == '-' || c == '+')
5380     {
5381       w->word = temp;
5382       return w;
5383     }
5384
5385   /* c == '=' */
5386   t = temp ? savestring (temp) : savestring ("");
5387   t1 = dequote_string (t);
5388   free (t);
5389 #if defined (ARRAY_VARS)
5390   if (valid_array_reference (name))
5391     assign_array_element (name, t1, 0);
5392   else
5393 #endif /* ARRAY_VARS */
5394   bind_variable (name, t1, 0);
5395   free (t1);
5396
5397   w->word = temp;
5398   return w;
5399 }
5400
5401 /* Deal with the right hand side of a ${name:?value} expansion in the case
5402    that NAME is null or not set.  If VALUE is non-null it is expanded and
5403    used as the error message to print, otherwise a standard message is
5404    printed. */
5405 static void
5406 parameter_brace_expand_error (name, value)
5407      char *name, *value;
5408 {
5409   WORD_LIST *l;
5410   char *temp;
5411
5412   if (value && *value)
5413     {
5414       l = expand_string (value, 0);
5415       temp =  string_list (l);
5416       report_error ("%s: %s", name, temp ? temp : "");  /* XXX was value not "" */
5417       FREE (temp);
5418       dispose_words (l);
5419     }
5420   else
5421     report_error (_("%s: parameter null or not set"), name);
5422
5423   /* Free the data we have allocated during this expansion, since we
5424      are about to longjmp out. */
5425   free (name);
5426   FREE (value);
5427 }
5428
5429 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5430    OK to do. */
5431 static int
5432 valid_length_expression (name)
5433      char *name;
5434 {
5435   return (name[1] == '\0' ||                                    /* ${#} */
5436           ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') ||  /* special param */
5437           (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5438 #if defined (ARRAY_VARS)
5439           valid_array_reference (name + 1) ||                   /* ${#a[7]} */
5440 #endif
5441           legal_identifier (name + 1));                         /* ${#PS1} */
5442 }
5443
5444 #if defined (HANDLE_MULTIBYTE)
5445 size_t
5446 mbstrlen (s)
5447      const char *s;
5448 {
5449   size_t clen, nc;
5450   mbstate_t mbs, mbsbak;
5451
5452   nc = 0;
5453   memset (&mbs, 0, sizeof (mbs));
5454   mbsbak = mbs;
5455   while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5456     {
5457       if (MB_INVALIDCH(clen))
5458         {
5459           clen = 1;     /* assume single byte */
5460           mbs = mbsbak;
5461         }
5462
5463       s += clen;
5464       nc++;
5465       mbsbak = mbs;
5466     }
5467   return nc;
5468 }
5469 #endif
5470       
5471
5472 /* Handle the parameter brace expansion that requires us to return the
5473    length of a parameter. */
5474 static intmax_t
5475 parameter_brace_expand_length (name)
5476      char *name;
5477 {
5478   char *t, *newname;
5479   intmax_t number, arg_index;
5480   WORD_LIST *list;
5481 #if defined (ARRAY_VARS)
5482   SHELL_VAR *var;
5483 #endif
5484
5485   if (name[1] == '\0')                  /* ${#} */
5486     number = number_of_args ();
5487   else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0')       /* ${#@}, ${#*} */
5488     number = number_of_args ();
5489   else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5490     {
5491       /* Take the lengths of some of the shell's special parameters. */
5492       switch (name[1])
5493         {
5494         case '-':
5495           t = which_set_flags ();
5496           break;
5497         case '?':
5498           t = itos (last_command_exit_value);
5499           break;
5500         case '$':
5501           t = itos (dollar_dollar_pid);
5502           break;
5503         case '!':
5504           if (last_asynchronous_pid == NO_PID)
5505             t = (char *)NULL;
5506           else
5507             t = itos (last_asynchronous_pid);
5508           break;
5509         case '#':
5510           t = itos (number_of_args ());
5511           break;
5512         }
5513       number = STRLEN (t);
5514       FREE (t);
5515     }
5516 #if defined (ARRAY_VARS)
5517   else if (valid_array_reference (name + 1))
5518     number = array_length_reference (name + 1);
5519 #endif /* ARRAY_VARS */
5520   else
5521     {
5522       number = 0;
5523
5524       if (legal_number (name + 1, &arg_index))          /* ${#1} */
5525         {
5526           t = get_dollar_var_value (arg_index);
5527           number = MB_STRLEN (t);
5528           FREE (t);
5529         }
5530 #if defined (ARRAY_VARS)
5531       else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
5532         {
5533           if (assoc_p (var))
5534             t = assoc_reference (assoc_cell (var), "0");
5535           else
5536             t = array_reference (array_cell (var), 0);
5537           number = MB_STRLEN (t);
5538         }
5539 #endif
5540       else                              /* ${#PS1} */
5541         {
5542           newname = savestring (name);
5543           newname[0] = '$';
5544           list = expand_string (newname, Q_DOUBLE_QUOTES);
5545           t = list ? string_list (list) : (char *)NULL;
5546           free (newname);
5547           if (list)
5548             dispose_words (list);
5549
5550           number = MB_STRLEN (t);
5551           FREE (t);
5552         }
5553     }
5554
5555   return (number);
5556 }
5557
5558 /* Skip characters in SUBSTR until DELIM.  SUBSTR is an arithmetic expression,
5559    so we do some ad-hoc parsing of an arithmetic expression to find
5560    the first DELIM, instead of using strchr(3).  Two rules:
5561         1.  If the substring contains a `(', read until closing `)'.
5562         2.  If the substring contains a `?', read past one `:' for each `?'.
5563 */
5564
5565 static char *
5566 skiparith (substr, delim)
5567      char *substr;
5568      int delim;
5569 {
5570   size_t sublen;
5571   int skipcol, pcount, i;
5572   DECLARE_MBSTATE;
5573
5574   sublen = strlen (substr);
5575   i = skipcol = pcount = 0;
5576   while (substr[i])
5577     {
5578       /* Balance parens */
5579       if (substr[i] == LPAREN)
5580         {
5581           pcount++;
5582           i++;
5583           continue;
5584         }
5585       if (substr[i] == RPAREN && pcount)
5586         {
5587           pcount--;
5588           i++;
5589           continue;
5590         }
5591       if (pcount)
5592         {
5593           ADVANCE_CHAR (substr, sublen, i);
5594           continue;
5595         }
5596
5597       /* Skip one `:' for each `?' */
5598       if (substr[i] == ':' && skipcol)
5599         {
5600           skipcol--;
5601           i++;
5602           continue;
5603         }
5604       if (substr[i] == delim)
5605         break;
5606       if (substr[i] == '?')
5607         {
5608           skipcol++;
5609           i++;
5610           continue;
5611         }
5612       ADVANCE_CHAR (substr, sublen, i);
5613     }
5614
5615   return (substr + i);
5616 }
5617
5618 /* Verify and limit the start and end of the desired substring.  If
5619    VTYPE == 0, a regular shell variable is being used; if it is 1,
5620    then the positional parameters are being used; if it is 2, then
5621    VALUE is really a pointer to an array variable that should be used.
5622    Return value is 1 if both values were OK, 0 if there was a problem
5623    with an invalid expression, or -1 if the values were out of range. */
5624 static int
5625 verify_substring_values (v, value, substr, vtype, e1p, e2p)
5626      SHELL_VAR *v;
5627      char *value, *substr;
5628      int vtype;
5629      intmax_t *e1p, *e2p;
5630 {
5631   char *t, *temp1, *temp2;
5632   arrayind_t len;
5633   int expok;
5634 #if defined (ARRAY_VARS)
5635  ARRAY *a;
5636  HASH_TABLE *h;
5637 #endif
5638
5639   /* duplicate behavior of strchr(3) */
5640   t = skiparith (substr, ':');
5641   if (*t && *t == ':')
5642     *t = '\0';
5643   else
5644     t = (char *)0;
5645
5646   temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
5647   *e1p = evalexp (temp1, &expok);
5648   free (temp1);
5649   if (expok == 0)
5650     return (0);
5651
5652   len = -1;     /* paranoia */
5653   switch (vtype)
5654     {
5655     case VT_VARIABLE:
5656     case VT_ARRAYMEMBER:
5657       len = MB_STRLEN (value);
5658       break;
5659     case VT_POSPARMS:
5660       len = number_of_args () + 1;
5661       if (*e1p == 0)
5662         len++;          /* add one arg if counting from $0 */
5663       break;
5664 #if defined (ARRAY_VARS)
5665     case VT_ARRAYVAR:
5666       /* For arrays, the first value deals with array indices.  Negative
5667          offsets count from one past the array's maximum index.  Associative
5668          arrays treat the number of elements as the maximum index. */
5669       if (assoc_p (v))
5670         {
5671           h = assoc_cell (v);
5672           len = assoc_num_elements (h) + (*e1p < 0);
5673         }
5674       else
5675         {
5676           a = (ARRAY *)value;
5677           len = array_max_index (a) + (*e1p < 0);       /* arrays index from 0 to n - 1 */
5678         }
5679       break;
5680 #endif
5681     }
5682
5683   if (len == -1)        /* paranoia */
5684     return -1;
5685
5686   if (*e1p < 0)         /* negative offsets count from end */
5687     *e1p += len;
5688
5689   if (*e1p > len || *e1p < 0)
5690     return (-1);
5691
5692 #if defined (ARRAY_VARS)
5693   /* For arrays, the second offset deals with the number of elements. */
5694   if (vtype == VT_ARRAYVAR)
5695     len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
5696 #endif
5697
5698   if (t)
5699     {
5700       t++;
5701       temp2 = savestring (t);
5702       temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
5703       free (temp2);
5704       t[-1] = ':';
5705       *e2p = evalexp (temp1, &expok);
5706       free (temp1);
5707       if (expok == 0)
5708         return (0);
5709       if (*e2p < 0)
5710         {
5711           internal_error (_("%s: substring expression < 0"), t);
5712           return (0);
5713         }
5714 #if defined (ARRAY_VARS)
5715       /* In order to deal with sparse arrays, push the intelligence about how
5716          to deal with the number of elements desired down to the array-
5717          specific functions.  */
5718       if (vtype != VT_ARRAYVAR)
5719 #endif
5720         {
5721           *e2p += *e1p;         /* want E2 chars starting at E1 */
5722           if (*e2p > len)
5723             *e2p = len;
5724         }
5725     }
5726   else
5727     *e2p = len;
5728
5729   return (1);
5730 }
5731
5732 /* Return the type of variable specified by VARNAME (simple variable,
5733    positional param, or array variable).  Also return the value specified
5734    by VARNAME (value of a variable or a reference to an array element).
5735    If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5736    characters in the value are quoted with CTLESC and takes appropriate
5737    steps.  For convenience, *VALP is set to the dequoted VALUE. */
5738 static int
5739 get_var_and_type (varname, value, quoted, varp, valp)
5740      char *varname, *value;
5741      int quoted;
5742      SHELL_VAR **varp;
5743      char **valp;
5744 {
5745   int vtype;
5746   char *temp;
5747 #if defined (ARRAY_VARS)
5748   SHELL_VAR *v;
5749 #endif
5750
5751   /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5752   vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5753   if (vtype == VT_POSPARMS && varname[0] == '*')
5754     vtype |= VT_STARSUB;
5755   *varp = (SHELL_VAR *)NULL;
5756
5757 #if defined (ARRAY_VARS)
5758   if (valid_array_reference (varname))
5759     {
5760       v = array_variable_part (varname, &temp, (int *)0);
5761       if (v && (array_p (v) || assoc_p (v)))
5762         { /* [ */
5763           if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5764             {
5765               /* Callers have to differentiate betwen indexed and associative */
5766               vtype = VT_ARRAYVAR;
5767               if (temp[0] == '*')
5768                 vtype |= VT_STARSUB;
5769               *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
5770             }
5771           else
5772             {
5773               vtype = VT_ARRAYMEMBER;
5774               *valp = array_value (varname, 1, (int *)NULL);
5775             }
5776           *varp = v;
5777         }
5778       else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5779         {
5780           vtype = VT_VARIABLE;
5781           *varp = v;
5782           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5783             *valp = dequote_string (value);
5784           else
5785             *valp = dequote_escapes (value);
5786         }
5787       else
5788         {
5789           vtype = VT_ARRAYMEMBER;
5790           *varp = v;
5791           *valp = array_value (varname, 1, (int *)NULL);
5792         }
5793     }
5794   else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
5795     {
5796       vtype = VT_ARRAYMEMBER;
5797       *varp = v;
5798       *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
5799     }
5800   else
5801 #endif
5802     {
5803       if (value && vtype == VT_VARIABLE)
5804         {
5805           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5806             *valp = dequote_string (value);
5807           else
5808             *valp = dequote_escapes (value);
5809         }
5810       else
5811         *valp = value;
5812     }
5813
5814   return vtype;
5815 }
5816
5817 /******************************************************/
5818 /*                                                    */
5819 /* Functions to extract substrings of variable values */
5820 /*                                                    */
5821 /******************************************************/
5822
5823 #if defined (HANDLE_MULTIBYTE)
5824 /* Character-oriented rather than strictly byte-oriented substrings.  S and
5825    E, rather being strict indices into STRING, indicate character (possibly
5826    multibyte character) positions that require calculation.
5827    Used by the ${param:offset[:length]} expansion. */
5828 static char *
5829 mb_substring (string, s, e)
5830      char *string;
5831      int s, e;
5832 {
5833   char *tt;
5834   int start, stop, i, slen;
5835   DECLARE_MBSTATE;
5836
5837   start = 0;
5838   /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5839   slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5840
5841   i = s;
5842   while (string[start] && i--)
5843     ADVANCE_CHAR (string, slen, start);
5844   stop = start;
5845   i = e - s;
5846   while (string[stop] && i--)
5847     ADVANCE_CHAR (string, slen, stop);
5848   tt = substring (string, start, stop);
5849   return tt;
5850 }
5851 #endif
5852   
5853 /* Process a variable substring expansion: ${name:e1[:e2]}.  If VARNAME
5854    is `@', use the positional parameters; otherwise, use the value of
5855    VARNAME.  If VARNAME is an array variable, use the array elements. */
5856
5857 static char *
5858 parameter_brace_substring (varname, value, substr, quoted)
5859      char *varname, *value, *substr;
5860      int quoted;
5861 {
5862   intmax_t e1, e2;
5863   int vtype, r, starsub;
5864   char *temp, *val, *tt, *oname;
5865   SHELL_VAR *v;
5866
5867   if (value == 0)
5868     return ((char *)NULL);
5869
5870   oname = this_command_name;
5871   this_command_name = varname;
5872
5873   vtype = get_var_and_type (varname, value, quoted, &v, &val);
5874   if (vtype == -1)
5875     {
5876       this_command_name = oname;
5877       return ((char *)NULL);
5878     }
5879
5880   starsub = vtype & VT_STARSUB;
5881   vtype &= ~VT_STARSUB;
5882
5883   r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
5884   this_command_name = oname;
5885   if (r <= 0)
5886     return ((r == 0) ? &expand_param_error : (char *)NULL);
5887
5888   switch (vtype)
5889     {
5890     case VT_VARIABLE:
5891     case VT_ARRAYMEMBER:
5892 #if defined (HANDLE_MULTIBYTE)
5893       if (MB_CUR_MAX > 1)
5894         tt = mb_substring (val, e1, e2);
5895       else
5896 #endif
5897       tt = substring (val, e1, e2);
5898
5899       if (vtype == VT_VARIABLE)
5900         FREE (val);
5901       if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5902         temp = quote_string (tt);
5903       else
5904         temp = tt ? quote_escapes (tt) : (char *)NULL;
5905       FREE (tt);
5906       break;
5907     case VT_POSPARMS:
5908       tt = pos_params (varname, e1, e2, quoted);
5909       if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5910         {
5911           temp = tt ? quote_escapes (tt) : (char *)NULL;
5912           FREE (tt);
5913         }
5914       else
5915         temp = tt;
5916       break;
5917 #if defined (ARRAY_VARS)
5918     case VT_ARRAYVAR:
5919       if (assoc_p (v))
5920         /* we convert to list and take first e2 elements starting at e1th
5921            element -- officially undefined for now */   
5922         temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
5923       else
5924       /* We want E2 to be the number of elements desired (arrays can be sparse,
5925          so verify_substring_values just returns the numbers specified and we
5926          rely on array_subrange to understand how to deal with them). */
5927         temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5928       /* array_subrange now calls array_quote_escapes as appropriate, so the
5929          caller no longer needs to. */
5930       break;
5931 #endif
5932     default:
5933       temp = (char *)NULL;
5934     }
5935
5936   return temp;
5937 }
5938
5939 /****************************************************************/
5940 /*                                                              */
5941 /* Functions to perform pattern substitution on variable values */
5942 /*                                                              */
5943 /****************************************************************/
5944
5945 char *
5946 pat_subst (string, pat, rep, mflags)
5947      char *string, *pat, *rep;
5948      int mflags;
5949 {
5950   char *ret, *s, *e, *str;
5951   int rsize, rptr, l, replen, mtype;
5952
5953   mtype = mflags & MATCH_TYPEMASK;
5954
5955   /* Special cases:
5956    *    1.  A null pattern with mtype == MATCH_BEG means to prefix STRING
5957    *        with REP and return the result.
5958    *    2.  A null pattern with mtype == MATCH_END means to append REP to
5959    *        STRING and return the result.
5960    */
5961   if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5962     {
5963       replen = STRLEN (rep);
5964       l = strlen (string);
5965       ret = (char *)xmalloc (replen + l + 2);
5966       if (replen == 0)
5967         strcpy (ret, string);
5968       else if (mtype == MATCH_BEG)
5969         {
5970           strcpy (ret, rep);
5971           strcpy (ret + replen, string);
5972         }
5973       else
5974         {
5975           strcpy (ret, string);
5976           strcpy (ret + l, rep);
5977         }
5978       return (ret);
5979     }
5980
5981   ret = (char *)xmalloc (rsize = 64);
5982   ret[0] = '\0';
5983
5984   for (replen = STRLEN (rep), rptr = 0, str = string;;)
5985     {
5986       if (match_pattern (str, pat, mtype, &s, &e) == 0)
5987         break;
5988       l = s - str;
5989       RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5990
5991       /* OK, now copy the leading unmatched portion of the string (from
5992          str to s) to ret starting at rptr (the current offset).  Then copy
5993          the replacement string at ret + rptr + (s - str).  Increment
5994          rptr (if necessary) and str and go on. */
5995       if (l)
5996         {
5997           strncpy (ret + rptr, str, l);
5998           rptr += l;
5999         }
6000       if (replen)
6001         {
6002           strncpy (ret + rptr, rep, replen);
6003           rptr += replen;
6004         }
6005       str = e;          /* e == end of match */
6006
6007       if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
6008         break;
6009
6010       if (s == e)
6011         e++, str++;             /* avoid infinite recursion on zero-length match */
6012     }
6013
6014   /* Now copy the unmatched portion of the input string */
6015   if (*str)
6016     {
6017       RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
6018       strcpy (ret + rptr, str);
6019     }
6020   else
6021     ret[rptr] = '\0';
6022
6023   return ret;
6024 }
6025
6026 /* Do pattern match and replacement on the positional parameters. */
6027 static char *
6028 pos_params_pat_subst (string, pat, rep, mflags)
6029      char *string, *pat, *rep;
6030      int mflags;
6031 {
6032   WORD_LIST *save, *params;
6033   WORD_DESC *w;
6034   char *ret;
6035   int pchar, qflags;
6036
6037   save = params = list_rest_of_args ();
6038   if (save == 0)
6039     return ((char *)NULL);
6040
6041   for ( ; params; params = params->next)
6042     {
6043       ret = pat_subst (params->word->word, pat, rep, mflags);
6044       w = alloc_word_desc ();
6045       w->word = ret ? ret : savestring ("");
6046       dispose_word (params->word);
6047       params->word = w;
6048     }
6049
6050   pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6051   qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6052
6053 #if 0
6054   if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
6055     ret = string_list_dollar_star (quote_list (save));
6056   else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
6057     ret = string_list_dollar_star (save);
6058   else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
6059     ret = string_list_dollar_at (save, qflags);
6060   else
6061     ret = string_list_dollar_star (save);
6062 #else
6063   ret = string_list_pos_params (pchar, save, qflags);
6064 #endif
6065
6066   dispose_words (save);
6067
6068   return (ret);
6069 }
6070
6071 /* Perform pattern substitution on VALUE, which is the expansion of
6072    VARNAME.  PATSUB is an expression supplying the pattern to match
6073    and the string to substitute.  QUOTED is a flags word containing
6074    the type of quoting currently in effect. */
6075 static char *
6076 parameter_brace_patsub (varname, value, patsub, quoted)
6077      char *varname, *value, *patsub;
6078      int quoted;
6079 {
6080   int vtype, mflags, starsub, delim;
6081   char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
6082   SHELL_VAR *v;
6083
6084   if (value == 0)
6085     return ((char *)NULL);
6086
6087   this_command_name = varname;
6088
6089   vtype = get_var_and_type (varname, value, quoted, &v, &val);
6090   if (vtype == -1)
6091     return ((char *)NULL);
6092
6093   starsub = vtype & VT_STARSUB;
6094   vtype &= ~VT_STARSUB;
6095
6096   mflags = 0;
6097   if (patsub && *patsub == '/')
6098     {
6099       mflags |= MATCH_GLOBREP;
6100       patsub++;
6101     }
6102
6103   /* Malloc this because expand_string_if_necessary or one of the expansion
6104      functions in its call chain may free it on a substitution error. */
6105   lpatsub = savestring (patsub);
6106
6107   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6108     mflags |= MATCH_QUOTED;
6109
6110   if (starsub)
6111     mflags |= MATCH_STARSUB;
6112
6113   /* If the pattern starts with a `/', make sure we skip over it when looking
6114      for the replacement delimiter. */
6115 #if 0
6116   if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
6117     *rep++ = '\0';
6118   else
6119     rep = (char *)NULL;
6120 #else
6121   delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
6122   if (lpatsub[delim] == '/')
6123     {
6124       lpatsub[delim] = 0;
6125       rep = lpatsub + delim + 1;
6126     }
6127   else
6128     rep = (char *)NULL;
6129 #endif
6130
6131   if (rep && *rep == '\0')
6132     rep = (char *)NULL;
6133
6134   /* Perform the same expansions on the pattern as performed by the
6135      pattern removal expansions. */
6136   pat = getpattern (lpatsub, quoted, 1);
6137
6138   if (rep)
6139     {
6140       if ((mflags & MATCH_QUOTED) == 0)
6141         rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
6142       else
6143         rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
6144     }
6145
6146   /* ksh93 doesn't allow the match specifier to be a part of the expanded
6147      pattern.  This is an extension.  Make sure we don't anchor the pattern
6148      at the beginning or end of the string if we're doing global replacement,
6149      though. */
6150   p = pat;
6151   if (mflags & MATCH_GLOBREP)
6152     mflags |= MATCH_ANY;
6153   else if (pat && pat[0] == '#')
6154     {
6155       mflags |= MATCH_BEG;
6156       p++;
6157     }
6158   else if (pat && pat[0] == '%')
6159     {
6160       mflags |= MATCH_END;
6161       p++;
6162     }
6163   else
6164     mflags |= MATCH_ANY;
6165
6166   /* OK, we now want to substitute REP for PAT in VAL.  If
6167      flags & MATCH_GLOBREP is non-zero, the substitution is done
6168      everywhere, otherwise only the first occurrence of PAT is
6169      replaced.  The pattern matching code doesn't understand
6170      CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6171      values passed in (VT_VARIABLE) so the pattern substitution
6172      code works right.  We need to requote special chars after
6173      we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6174      other cases if QUOTED == 0, since the posparams and arrays
6175      indexed by * or @ do special things when QUOTED != 0. */
6176
6177   switch (vtype)
6178     {
6179     case VT_VARIABLE:
6180     case VT_ARRAYMEMBER:
6181       temp = pat_subst (val, p, rep, mflags);
6182       if (vtype == VT_VARIABLE)
6183         FREE (val);
6184       if (temp)
6185         {
6186           tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6187           free (temp);
6188           temp = tt;
6189         }
6190       break;
6191     case VT_POSPARMS:
6192       temp = pos_params_pat_subst (val, p, rep, mflags);
6193       if (temp && (mflags & MATCH_QUOTED) == 0)
6194         {
6195           tt = quote_escapes (temp);
6196           free (temp);
6197           temp = tt;
6198         }
6199       break;
6200 #if defined (ARRAY_VARS)
6201     case VT_ARRAYVAR:
6202       temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6203                          : array_patsub (array_cell (v), p, rep, mflags);
6204       /* Don't call quote_escapes anymore; array_patsub calls
6205          array_quote_escapes as appropriate before adding the
6206          space separators; ditto for assoc_patsub. */
6207       break;
6208 #endif
6209     }
6210
6211   FREE (pat);
6212   FREE (rep);
6213   free (lpatsub);
6214
6215   return temp;
6216 }
6217
6218 /****************************************************************/
6219 /*                                                              */
6220 /*   Functions to perform case modification on variable values  */
6221 /*                                                              */
6222 /****************************************************************/
6223
6224 /* Do case modification on the positional parameters. */
6225
6226 static char *
6227 pos_params_modcase (string, pat, modop, mflags)
6228      char *string, *pat;
6229      int modop;
6230      int mflags;
6231 {
6232   WORD_LIST *save, *params;
6233   WORD_DESC *w;
6234   char *ret;
6235   int pchar, qflags;
6236
6237   save = params = list_rest_of_args ();
6238   if (save == 0)
6239     return ((char *)NULL);
6240
6241   for ( ; params; params = params->next)
6242     {
6243       ret = sh_modcase (params->word->word, pat, modop);
6244       w = alloc_word_desc ();
6245       w->word = ret ? ret : savestring ("");
6246       dispose_word (params->word);
6247       params->word = w;
6248     }
6249
6250   pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6251   qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6252
6253   ret = string_list_pos_params (pchar, save, qflags);
6254   dispose_words (save);
6255
6256   return (ret);
6257 }
6258
6259 /* Perform case modification on VALUE, which is the expansion of
6260    VARNAME.  MODSPEC is an expression supplying the type of modification
6261    to perform.  QUOTED is a flags word containing the type of quoting
6262    currently in effect. */
6263 static char *
6264 parameter_brace_casemod (varname, value, modspec, patspec, quoted)
6265      char *varname, *value;
6266      int modspec;
6267      char *patspec;
6268      int quoted;
6269 {
6270   int vtype, starsub, modop, mflags, x;
6271   char *val, *temp, *pat, *p, *lpat, *tt;
6272   SHELL_VAR *v;
6273
6274   if (value == 0)
6275     return ((char *)NULL);
6276
6277   this_command_name = varname;
6278
6279   vtype = get_var_and_type (varname, value, quoted, &v, &val);
6280   if (vtype == -1)
6281     return ((char *)NULL);
6282
6283   starsub = vtype & VT_STARSUB;
6284   vtype &= ~VT_STARSUB;
6285
6286   modop = 0;
6287   mflags = 0;
6288   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6289     mflags |= MATCH_QUOTED;
6290   if (starsub)
6291     mflags |= MATCH_STARSUB;
6292   
6293   p = patspec;
6294   if (modspec == '^')
6295     {
6296       x = p && p[0] == modspec;
6297       modop = x ? CASE_UPPER : CASE_UPFIRST;
6298       p += x;
6299     }
6300   else if (modspec == ',')
6301     {
6302       x = p && p[0] == modspec;
6303       modop = x ? CASE_LOWER : CASE_LOWFIRST;
6304       p += x;
6305     }
6306   else if (modspec == '~')
6307     {
6308       x = p && p[0] == modspec;
6309       modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6310       p += x;
6311     }
6312     
6313   lpat = p ? savestring (p) : 0;
6314   /* Perform the same expansions on the pattern as performed by the
6315      pattern removal expansions.  FOR LATER */
6316   pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6317
6318   /* OK, now we do the case modification. */
6319   switch (vtype)
6320     {
6321     case VT_VARIABLE:
6322     case VT_ARRAYMEMBER:
6323       temp = sh_modcase (val, pat, modop);
6324       if (vtype == VT_VARIABLE)
6325         FREE (val);
6326       if (temp)
6327         {
6328           tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6329           free (temp);
6330           temp = tt;
6331         }
6332       break;
6333
6334     case VT_POSPARMS:
6335       temp = pos_params_modcase (val, pat, modop, mflags);
6336       if (temp && (mflags & MATCH_QUOTED)  == 0)
6337         {
6338           tt = quote_escapes (temp);
6339           free (temp);
6340           temp = tt;
6341         }
6342       break;
6343
6344 #if defined (ARRAY_VARS)
6345     case VT_ARRAYVAR:
6346       temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6347                          : array_modcase (array_cell (v), pat, modop, mflags);
6348       /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6349          as appropriate before adding the space separators; ditto for
6350          assoc_modcase. */
6351       break;
6352 #endif
6353     }
6354
6355   FREE (pat);
6356   free (lpat);
6357
6358   return temp;
6359 }
6360
6361 /* Check for unbalanced parens in S, which is the contents of $(( ... )).  If
6362    any occur, this must be a nested command substitution, so return 0.
6363    Otherwise, return 1.  A valid arithmetic expression must always have a
6364    ( before a matching ), so any cases where there are more right parens
6365    means that this must not be an arithmetic expression, though the parser
6366    will not accept it without a balanced total number of parens. */
6367 static int
6368 chk_arithsub (s, len)
6369      const char *s;
6370      int len;
6371 {
6372   int i, count;
6373   DECLARE_MBSTATE;
6374
6375   i = count = 0;
6376   while (i < len)
6377     {
6378       if (s[i] == '(')
6379         count++;
6380       else if (s[i] == ')')
6381         {
6382           count--;
6383           if (count < 0)
6384             return 0;
6385         }
6386
6387       switch (s[i])
6388         {
6389         default:
6390           ADVANCE_CHAR (s, len, i);
6391           break;
6392
6393         case '\\':
6394           i++;
6395           if (s[i])
6396             ADVANCE_CHAR (s, len, i);
6397           break;
6398
6399         case '\'':
6400           i = skip_single_quoted (s, len, ++i);
6401           break;
6402
6403         case '"':
6404           i = skip_double_quoted ((char *)s, len, ++i);
6405           break;
6406         }
6407     }
6408
6409   return (count == 0);
6410 }
6411
6412 /****************************************************************/
6413 /*                                                              */
6414 /*      Functions to perform parameter expansion on a string    */
6415 /*                                                              */
6416 /****************************************************************/
6417
6418 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
6419 static WORD_DESC *
6420 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
6421      char *string;
6422      int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
6423 {
6424   int check_nullness, var_is_set, var_is_null, var_is_special;
6425   int want_substring, want_indir, want_patsub, want_casemod;
6426   char *name, *value, *temp, *temp1;
6427   WORD_DESC *tdesc, *ret;
6428   int t_index, sindex, c, tflag, modspec;
6429   intmax_t number;
6430
6431   temp = temp1 = value = (char *)NULL;
6432   var_is_set = var_is_null = var_is_special = check_nullness = 0;
6433   want_substring = want_indir = want_patsub = want_casemod = 0;
6434
6435   sindex = *indexp;
6436   t_index = ++sindex;
6437   /* ${#var} doesn't have any of the other parameter expansions on it. */
6438   if (string[t_index] == '#' && legal_variable_starter (string[t_index+1]))             /* {{ */
6439     name = string_extract (string, &t_index, "}", SX_VARNAME);
6440   else
6441 #if defined (CASEMOD_EXPANSIONS)
6442     /* To enable case-toggling expansions using the `~' operator character
6443        change the 1 to 0. */
6444 #  if defined (CASEMOD_CAPCASE)
6445     name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
6446 #  else
6447     name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
6448 #  endif /* CASEMOD_CAPCASE */
6449 #else
6450     name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
6451 #endif /* CASEMOD_EXPANSIONS */
6452
6453   ret = 0;
6454   tflag = 0;
6455
6456   /* If the name really consists of a special variable, then make sure
6457      that we have the entire name.  We don't allow indirect references
6458      to special variables except `#', `?', `@' and `*'. */
6459   if ((sindex == t_index &&
6460         (string[t_index] == '-' ||
6461          string[t_index] == '?' ||
6462          string[t_index] == '#')) ||
6463       (sindex == t_index - 1 && string[sindex] == '!' &&
6464         (string[t_index] == '#' ||
6465          string[t_index] == '?' ||
6466          string[t_index] == '@' ||
6467          string[t_index] == '*')))
6468     {
6469       t_index++;
6470       free (name);
6471       temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
6472       name = (char *)xmalloc (3 + (strlen (temp1)));
6473       *name = string[sindex];
6474       if (string[sindex] == '!')
6475         {
6476           /* indirect reference of $#, $?, $@, or $* */
6477           name[1] = string[sindex + 1];
6478           strcpy (name + 2, temp1);
6479         }
6480       else      
6481         strcpy (name + 1, temp1);
6482       free (temp1);
6483     }
6484   sindex = t_index;
6485
6486   /* Find out what character ended the variable name.  Then
6487      do the appropriate thing. */
6488   if (c = string[sindex])
6489     sindex++;
6490
6491   /* If c is followed by one of the valid parameter expansion
6492      characters, move past it as normal.  If not, assume that
6493      a substring specification is being given, and do not move
6494      past it. */
6495   if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
6496     {
6497       check_nullness++;
6498       if (c = string[sindex])
6499         sindex++;
6500     }
6501   else if (c == ':' && string[sindex] != RBRACE)
6502     want_substring = 1;
6503   else if (c == '/' && string[sindex] != RBRACE)
6504     want_patsub = 1;
6505 #if defined (CASEMOD_EXPANSIONS)
6506   else if (c == '^' || c == ',' || c == '~')
6507     {
6508       modspec = c;
6509       want_casemod = 1;
6510     }
6511 #endif
6512
6513   /* Catch the valid and invalid brace expressions that made it through the
6514      tests above. */
6515   /* ${#-} is a valid expansion and means to take the length of $-.
6516      Similarly for ${#?} and ${##}... */
6517   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6518         VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
6519     {
6520       name = (char *)xrealloc (name, 3);
6521       name[1] = c;
6522       name[2] = '\0';
6523       c = string[sindex++];
6524     }
6525
6526   /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
6527   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6528         member (c, "%:=+/") && string[sindex] == RBRACE)
6529     {
6530       temp = (char *)NULL;
6531       goto bad_substitution;
6532     }
6533
6534   /* Indirect expansion begins with a `!'.  A valid indirect expansion is
6535      either a variable name, one of the positional parameters or a special
6536      variable that expands to one of the positional parameters. */
6537   want_indir = *name == '!' &&
6538     (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
6539                                         || VALID_INDIR_PARAM (name[1]));
6540
6541   /* Determine the value of this variable. */
6542
6543   /* Check for special variables, directly referenced. */
6544   if (SPECIAL_VAR (name, want_indir))
6545     var_is_special++;
6546
6547   /* Check for special expansion things, like the length of a parameter */
6548   if (*name == '#' && name[1])
6549     {
6550       /* If we are not pointing at the character just after the
6551          closing brace, then we haven't gotten all of the name.
6552          Since it begins with a special character, this is a bad
6553          substitution.  Also check NAME for validity before trying
6554          to go on. */
6555       if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
6556         {
6557           temp = (char *)NULL;
6558           goto bad_substitution;
6559         }
6560
6561       number = parameter_brace_expand_length (name);
6562       free (name);
6563
6564       *indexp = sindex;
6565       if (number < 0)
6566         return (&expand_wdesc_error);
6567       else
6568         {
6569           ret = alloc_word_desc ();
6570           ret->word = itos (number);
6571           return ret;
6572         }
6573     }
6574
6575   /* ${@} is identical to $@. */
6576   if (name[0] == '@' && name[1] == '\0')
6577     {
6578       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6579         *quoted_dollar_atp = 1;
6580
6581       if (contains_dollar_at)
6582         *contains_dollar_at = 1;
6583     }
6584
6585   /* Process ${!PREFIX*} expansion. */
6586   if (want_indir && string[sindex - 1] == RBRACE &&
6587       (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
6588       legal_variable_starter ((unsigned char) name[1]))
6589     {
6590       char **x;
6591       WORD_LIST *xlist;
6592
6593       temp1 = savestring (name + 1);
6594       number = strlen (temp1);
6595       temp1[number - 1] = '\0';
6596       x = all_variables_matching_prefix (temp1);
6597       xlist = strvec_to_word_list (x, 0, 0);
6598       if (string[sindex - 2] == '*')
6599         temp = string_list_dollar_star (xlist);
6600       else
6601         {
6602           temp = string_list_dollar_at (xlist, quoted);
6603           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6604             *quoted_dollar_atp = 1;
6605           if (contains_dollar_at)
6606             *contains_dollar_at = 1;
6607         }
6608       free (x);
6609       dispose_words (xlist);
6610       free (temp1);
6611       *indexp = sindex;
6612
6613       ret = alloc_word_desc ();
6614       ret->word = temp;
6615       return ret;
6616     }
6617
6618 #if defined (ARRAY_VARS)      
6619   /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
6620   if (want_indir && string[sindex - 1] == RBRACE &&
6621       string[sindex - 2] == ']' && valid_array_reference (name+1))
6622     {
6623       char *x, *x1;
6624
6625       temp1 = savestring (name + 1);
6626       x = array_variable_name (temp1, &x1, (int *)0);   /* [ */
6627       FREE (x);
6628       if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
6629         {
6630           temp = array_keys (temp1, quoted);    /* handles assoc vars too */
6631           if (x1[0] == '@')
6632             {
6633               if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6634                 *quoted_dollar_atp = 1;
6635               if (contains_dollar_at)
6636                 *contains_dollar_at = 1;
6637             }       
6638
6639           free (temp1);
6640           *indexp = sindex;
6641
6642           ret = alloc_word_desc ();
6643           ret->word = temp;
6644           return ret;
6645         }
6646
6647       free (temp1);
6648     }
6649 #endif /* ARRAY_VARS */
6650       
6651   /* Make sure that NAME is valid before trying to go on. */
6652   if (valid_brace_expansion_word (want_indir ? name + 1 : name,
6653                                         var_is_special) == 0)
6654     {
6655       temp = (char *)NULL;
6656       goto bad_substitution;
6657     }
6658
6659   if (want_indir)
6660     tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6661   else
6662     tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
6663
6664   if (tdesc)
6665     {
6666       temp = tdesc->word;
6667       tflag = tdesc->flags;
6668       dispose_word_desc (tdesc);
6669     }
6670   else
6671     temp = (char  *)0;
6672
6673 #if defined (ARRAY_VARS)
6674   if (valid_array_reference (name))
6675     chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6676 #endif
6677
6678   var_is_set = temp != (char *)0;
6679   var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6680
6681   /* Get the rest of the stuff inside the braces. */
6682   if (c && c != RBRACE)
6683     {
6684       /* Extract the contents of the ${ ... } expansion
6685          according to the Posix.2 rules. */
6686       value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6687       if (string[sindex] == RBRACE)
6688         sindex++;
6689       else
6690         goto bad_substitution;
6691     }
6692   else
6693     value = (char *)NULL;
6694
6695   *indexp = sindex;
6696
6697   /* If this is a substring spec, process it and add the result. */
6698   if (want_substring)
6699     {
6700       temp1 = parameter_brace_substring (name, temp, value, quoted);
6701       FREE (name);
6702       FREE (value);
6703       FREE (temp);
6704
6705       if (temp1 == &expand_param_error)
6706         return (&expand_wdesc_error);
6707       else if (temp1 == &expand_param_fatal)
6708         return (&expand_wdesc_fatal);
6709
6710       ret = alloc_word_desc ();
6711       ret->word = temp1;
6712       if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6713         ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6714       return ret;
6715     }
6716   else if (want_patsub)
6717     {
6718       temp1 = parameter_brace_patsub (name, temp, value, quoted);
6719       FREE (name);
6720       FREE (value);
6721       FREE (temp);
6722
6723       if (temp1 == &expand_param_error)
6724         return (&expand_wdesc_error);
6725       else if (temp1 == &expand_param_fatal)
6726         return (&expand_wdesc_fatal);
6727
6728       ret = alloc_word_desc ();
6729       ret->word = temp1;
6730       ret = alloc_word_desc ();
6731       ret->word = temp1;
6732       if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6733         ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6734       return ret;
6735     }
6736 #if defined (CASEMOD_EXPANSIONS)
6737   else if (want_casemod)
6738     {
6739       temp1 = parameter_brace_casemod (name, temp, modspec, value, quoted);
6740       FREE (name);
6741       FREE (value);
6742       FREE (temp);
6743
6744       if (temp1 == &expand_param_error)
6745         return (&expand_wdesc_error);
6746       else if (temp1 == &expand_param_fatal)
6747         return (&expand_wdesc_fatal);
6748
6749       ret = alloc_word_desc ();
6750       ret->word = temp1;
6751       if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6752         ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6753       return ret;
6754     }
6755 #endif
6756
6757   /* Do the right thing based on which character ended the variable name. */
6758   switch (c)
6759     {
6760     default:
6761     case '\0':
6762     bad_substitution:
6763       report_error (_("%s: bad substitution"), string ? string : "??");
6764       FREE (value);
6765       FREE (temp);
6766       free (name);
6767       return &expand_wdesc_error;
6768
6769     case RBRACE:
6770       if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
6771         {
6772           last_command_exit_value = EXECUTION_FAILURE;
6773           err_unboundvar (name);
6774           FREE (value);
6775           FREE (temp);
6776           free (name);
6777           return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6778         }
6779       break;
6780
6781     case '#':   /* ${param#[#]pattern} */
6782     case '%':   /* ${param%[%]pattern} */
6783       if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6784         {
6785           FREE (value);
6786           break;
6787         }
6788       temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6789       free (temp);
6790       free (value);
6791
6792       ret = alloc_word_desc ();
6793       ret->word = temp1;
6794       if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6795         ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6796       return ret;
6797
6798     case '-':
6799     case '=':
6800     case '?':
6801     case '+':
6802       if (var_is_set && var_is_null == 0)
6803         {
6804           /* If the operator is `+', we don't want the value of the named
6805              variable for anything, just the value of the right hand side. */
6806
6807           if (c == '+')
6808             {
6809               /* XXX -- if we're double-quoted and the named variable is "$@",
6810                         we want to turn off any special handling of "$@" --
6811                         we're not using it, so whatever is on the rhs applies. */
6812               if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6813                 *quoted_dollar_atp = 0;
6814               if (contains_dollar_at)
6815                 *contains_dollar_at = 0;
6816
6817               FREE (temp);
6818               if (value)
6819                 {
6820                   ret = parameter_brace_expand_rhs (name, value, c,
6821                                                     quoted,
6822                                                     quoted_dollar_atp,
6823                                                     contains_dollar_at);
6824                   /* XXX - fix up later, esp. noting presence of
6825                            W_HASQUOTEDNULL in ret->flags */
6826                   free (value);
6827                 }
6828               else
6829                 temp = (char *)NULL;
6830             }
6831           else
6832             {
6833               FREE (value);
6834             }
6835           /* Otherwise do nothing; just use the value in TEMP. */
6836         }
6837       else      /* VAR not set or VAR is NULL. */
6838         {
6839           FREE (temp);
6840           temp = (char *)NULL;
6841           if (c == '=' && var_is_special)
6842             {
6843               report_error (_("$%s: cannot assign in this way"), name);
6844               free (name);
6845               free (value);
6846               return &expand_wdesc_error;
6847             }
6848           else if (c == '?')
6849             {
6850               parameter_brace_expand_error (name, value);
6851               return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6852             }
6853           else if (c != '+')
6854             {
6855               /* XXX -- if we're double-quoted and the named variable is "$@",
6856                         we want to turn off any special handling of "$@" --
6857                         we're not using it, so whatever is on the rhs applies. */
6858               if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6859                 *quoted_dollar_atp = 0;
6860               if (contains_dollar_at)
6861                 *contains_dollar_at = 0;
6862
6863               ret = parameter_brace_expand_rhs (name, value, c, quoted,
6864                                                 quoted_dollar_atp,
6865                                                 contains_dollar_at);
6866               /* XXX - fix up later, esp. noting presence of
6867                        W_HASQUOTEDNULL in tdesc->flags */
6868             }
6869           free (value);
6870         }
6871
6872       break;
6873     }
6874   free (name);
6875
6876   if (ret == 0)
6877     {
6878       ret = alloc_word_desc ();
6879       ret->flags = tflag;
6880       ret->word = temp;
6881     }
6882   return (ret);
6883 }
6884
6885 /* Expand a single ${xxx} expansion.  The braces are optional.  When
6886    the braces are used, parameter_brace_expand() does the work,
6887    possibly calling param_expand recursively. */
6888 static WORD_DESC *
6889 param_expand (string, sindex, quoted, expanded_something,
6890               contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6891               pflags)
6892      char *string;
6893      int *sindex, quoted, *expanded_something, *contains_dollar_at;
6894      int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6895 {
6896   char *temp, *temp1, uerror[3];
6897   int zindex, t_index, expok;
6898   unsigned char c;
6899   intmax_t number;
6900   SHELL_VAR *var;
6901   WORD_LIST *list;
6902   WORD_DESC *tdesc, *ret;
6903   int tflag;
6904
6905   zindex = *sindex;
6906   c = string[++zindex];
6907
6908   temp = (char *)NULL;
6909   ret = tdesc = (WORD_DESC *)NULL;
6910   tflag = 0;
6911
6912   /* Do simple cases first. Switch on what follows '$'. */
6913   switch (c)
6914     {
6915     /* $0 .. $9? */
6916     case '0':
6917     case '1':
6918     case '2':
6919     case '3':
6920     case '4':
6921     case '5':
6922     case '6':
6923     case '7':
6924     case '8':
6925     case '9':
6926       temp1 = dollar_vars[TODIGIT (c)];
6927       if (unbound_vars_is_error && temp1 == (char *)NULL)
6928         {
6929           uerror[0] = '$';
6930           uerror[1] = c;
6931           uerror[2] = '\0';
6932           err_unboundvar (uerror);
6933           last_command_exit_value = EXECUTION_FAILURE;
6934           return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6935         }
6936       if (temp1)
6937         temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6938                   ? quote_string (temp1)
6939                   : quote_escapes (temp1);
6940       else
6941         temp = (char *)NULL;
6942
6943       break;
6944
6945     /* $$ -- pid of the invoking shell. */
6946     case '$':
6947       temp = itos (dollar_dollar_pid);
6948       break;
6949
6950     /* $# -- number of positional parameters. */
6951     case '#':
6952       temp = itos (number_of_args ());
6953       break;
6954
6955     /* $? -- return value of the last synchronous command. */
6956     case '?':
6957       temp = itos (last_command_exit_value);
6958       break;
6959
6960     /* $- -- flags supplied to the shell on invocation or by `set'. */
6961     case '-':
6962       temp = which_set_flags ();
6963       break;
6964
6965       /* $! -- Pid of the last asynchronous command. */
6966     case '!':
6967       /* If no asynchronous pids have been created, expand to nothing.
6968          If `set -u' has been executed, and no async processes have
6969          been created, this is an expansion error. */
6970       if (last_asynchronous_pid == NO_PID)
6971         {
6972           if (expanded_something)
6973             *expanded_something = 0;
6974           temp = (char *)NULL;
6975           if (unbound_vars_is_error)
6976             {
6977               uerror[0] = '$';
6978               uerror[1] = c;
6979               uerror[2] = '\0';
6980               err_unboundvar (uerror);
6981               last_command_exit_value = EXECUTION_FAILURE;
6982               return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6983             }
6984         }
6985       else
6986         temp = itos (last_asynchronous_pid);
6987       break;
6988
6989     /* The only difference between this and $@ is when the arg is quoted. */
6990     case '*':           /* `$*' */
6991       list = list_rest_of_args ();
6992
6993 #if 0
6994       /* According to austin-group posix proposal by Geoff Clare in
6995          <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
6996
6997         "The shell shall write a message to standard error and
6998          immediately exit when it tries to expand an unset parameter
6999          other than the '@' and '*' special parameters."
7000       */
7001
7002       if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7003         {
7004           uerror[0] = '$';
7005           uerror[1] = '*';
7006           uerror[2] = '\0';
7007           last_command_exit_value = EXECUTION_FAILURE;
7008           err_unboundvar (uerror);
7009           return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7010         }
7011 #endif
7012
7013       /* If there are no command-line arguments, this should just
7014          disappear if there are other characters in the expansion,
7015          even if it's quoted. */
7016       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7017         temp = (char *)NULL;
7018       else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7019         {
7020           /* If we have "$*" we want to make a string of the positional
7021              parameters, separated by the first character of $IFS, and
7022              quote the whole string, including the separators.  If IFS
7023              is unset, the parameters are separated by ' '; if $IFS is
7024              null, the parameters are concatenated. */
7025           temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
7026           temp1 = quote_string (temp);
7027           if (*temp == 0)
7028             tflag |= W_HASQUOTEDNULL;
7029           free (temp);
7030           temp = temp1;
7031         }
7032       else
7033         {
7034           /* We check whether or not we're eventually going to split $* here,
7035              for example when IFS is empty and we are processing the rhs of
7036              an assignment statement.  In that case, we don't separate the
7037              arguments at all.  Otherwise, if the $* is not quoted it is
7038              identical to $@ */
7039 #if 1
7040 #  if defined (HANDLE_MULTIBYTE)
7041           if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7042 #  else
7043           if (expand_no_split_dollar_star && ifs_firstc == 0)
7044 #  endif
7045             temp = string_list_dollar_star (list);
7046           else
7047             temp = string_list_dollar_at (list, quoted);
7048 #else
7049           temp = string_list_dollar_at (list, quoted);
7050 #endif
7051           if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7052             *contains_dollar_at = 1;
7053         }
7054
7055       dispose_words (list);
7056       break;
7057
7058     /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7059        means that we have to turn quoting off after we split into
7060        the individually quoted arguments so that the final split
7061        on the first character of $IFS is still done.  */
7062     case '@':           /* `$@' */
7063       list = list_rest_of_args ();
7064
7065 #if 0
7066       /* According to austin-group posix proposal by Geoff Clare in
7067          <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7068
7069         "The shell shall write a message to standard error and
7070          immediately exit when it tries to expand an unset parameter
7071          other than the '@' and '*' special parameters."
7072       */
7073
7074       if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7075         {
7076           uerror[0] = '$';
7077           uerror[1] = '@';
7078           uerror[2] = '\0';
7079           last_command_exit_value = EXECUTION_FAILURE;
7080           err_unboundvar (uerror);
7081           return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7082         }
7083 #endif
7084
7085       /* We want to flag the fact that we saw this.  We can't turn
7086          off quoting entirely, because other characters in the
7087          string might need it (consider "\"$@\""), but we need some
7088          way to signal that the final split on the first character
7089          of $IFS should be done, even though QUOTED is 1. */
7090       if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7091         *quoted_dollar_at_p = 1;
7092       if (contains_dollar_at)
7093         *contains_dollar_at = 1;
7094
7095       /* We want to separate the positional parameters with the first
7096          character of $IFS in case $IFS is something other than a space.
7097          We also want to make sure that splitting is done no matter what --
7098          according to POSIX.2, this expands to a list of the positional
7099          parameters no matter what IFS is set to. */
7100       temp = string_list_dollar_at (list, quoted);
7101
7102       dispose_words (list);
7103       break;
7104
7105     case LBRACE:
7106       tdesc = parameter_brace_expand (string, &zindex, quoted,
7107                                       quoted_dollar_at_p,
7108                                       contains_dollar_at);
7109
7110       if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7111         return (tdesc);
7112       temp = tdesc ? tdesc->word : (char *)0;
7113
7114       /* XXX */
7115       /* Quoted nulls should be removed if there is anything else
7116          in the string. */
7117       /* Note that we saw the quoted null so we can add one back at
7118          the end of this function if there are no other characters
7119          in the string, discard TEMP, and go on.  The exception to
7120          this is when we have "${@}" and $1 is '', since $@ needs
7121          special handling. */
7122       if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7123         {
7124           if (had_quoted_null_p)
7125             *had_quoted_null_p = 1;
7126           if (*quoted_dollar_at_p == 0)
7127             {
7128               free (temp);
7129               tdesc->word = temp = (char *)NULL;
7130             }
7131             
7132         }
7133
7134       ret = tdesc;
7135       goto return0;
7136
7137     /* Do command or arithmetic substitution. */
7138     case LPAREN:
7139       /* We have to extract the contents of this paren substitution. */
7140       t_index = zindex + 1;
7141       temp = extract_command_subst (string, &t_index, 0);
7142       zindex = t_index;
7143
7144       /* For Posix.2-style `$(( ))' arithmetic substitution,
7145          extract the expression and pass it to the evaluator. */
7146       if (temp && *temp == LPAREN)
7147         {
7148           char *temp2;
7149           temp1 = temp + 1;
7150           temp2 = savestring (temp1);
7151           t_index = strlen (temp2) - 1;
7152
7153           if (temp2[t_index] != RPAREN)
7154             {
7155               free (temp2);
7156               goto comsub;
7157             }
7158
7159           /* Cut off ending `)' */
7160           temp2[t_index] = '\0';
7161
7162           if (chk_arithsub (temp2, t_index) == 0)
7163             {
7164               free (temp2);
7165               goto comsub;
7166             }
7167
7168           /* Expand variables found inside the expression. */
7169           temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7170           free (temp2);
7171
7172 arithsub:
7173           /* No error messages. */
7174           this_command_name = (char *)NULL;
7175           number = evalexp (temp1, &expok);
7176           free (temp);
7177           free (temp1);
7178           if (expok == 0)
7179             {
7180               if (interactive_shell == 0 && posixly_correct)
7181                 {
7182                   last_command_exit_value = EXECUTION_FAILURE;
7183                   return (&expand_wdesc_fatal);
7184                 }
7185               else
7186                 return (&expand_wdesc_error);
7187             }
7188           temp = itos (number);
7189           break;
7190         }
7191
7192 comsub:
7193       if (pflags & PF_NOCOMSUB)
7194         /* we need zindex+1 because string[zindex] == RPAREN */
7195         temp1 = substring (string, *sindex, zindex+1);
7196       else
7197         {
7198           tdesc = command_substitute (temp, quoted);
7199           temp1 = tdesc ? tdesc->word : (char *)NULL;
7200           if (tdesc)
7201             dispose_word_desc (tdesc);
7202         }
7203       FREE (temp);
7204       temp = temp1;
7205       break;
7206
7207     /* Do POSIX.2d9-style arithmetic substitution.  This will probably go
7208        away in a future bash release. */
7209     case '[':
7210       /* Extract the contents of this arithmetic substitution. */
7211       t_index = zindex + 1;
7212       temp = extract_arithmetic_subst (string, &t_index);
7213       zindex = t_index;
7214       if (temp == 0)
7215         {
7216           temp = savestring (string);
7217           if (expanded_something)
7218             *expanded_something = 0;
7219           goto return0;
7220         }         
7221
7222        /* Do initial variable expansion. */
7223       temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7224
7225       goto arithsub;
7226
7227     default:
7228       /* Find the variable in VARIABLE_LIST. */
7229       temp = (char *)NULL;
7230
7231       for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7232         ;
7233       temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7234
7235       /* If this isn't a variable name, then just output the `$'. */
7236       if (temp1 == 0 || *temp1 == '\0')
7237         {
7238           FREE (temp1);
7239           temp = (char *)xmalloc (2);
7240           temp[0] = '$';
7241           temp[1] = '\0';
7242           if (expanded_something)
7243             *expanded_something = 0;
7244           goto return0;
7245         }
7246
7247       /* If the variable exists, return its value cell. */
7248       var = find_variable (temp1);
7249
7250       if (var && invisible_p (var) == 0 && var_isset (var))
7251         {
7252 #if defined (ARRAY_VARS)
7253           if (assoc_p (var) || array_p (var))
7254             {
7255               temp = array_p (var) ? array_reference (array_cell (var), 0)
7256                                    : assoc_reference (assoc_cell (var), "0");
7257               if (temp)
7258                 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7259                           ? quote_string (temp)
7260                           : quote_escapes (temp);
7261               else if (unbound_vars_is_error)
7262                 goto unbound_variable;
7263             }
7264           else
7265 #endif
7266             {
7267               temp = value_cell (var);
7268
7269               temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7270                         ? quote_string (temp)
7271                         : quote_escapes (temp);
7272             }
7273
7274           free (temp1);
7275
7276           goto return0;
7277         }
7278
7279       temp = (char *)NULL;
7280
7281 unbound_variable:
7282       if (unbound_vars_is_error)
7283         err_unboundvar (temp1);
7284       else
7285         {
7286           free (temp1);
7287           goto return0;
7288         }
7289
7290       free (temp1);
7291       last_command_exit_value = EXECUTION_FAILURE;
7292       return ((unbound_vars_is_error && interactive_shell == 0)
7293                 ? &expand_wdesc_fatal
7294                 : &expand_wdesc_error);
7295     }
7296
7297   if (string[zindex])
7298     zindex++;
7299
7300 return0:
7301   *sindex = zindex;
7302
7303   if (ret == 0)
7304     {
7305       ret = alloc_word_desc ();
7306       ret->flags = tflag;       /* XXX */
7307       ret->word = temp;
7308     }
7309   return ret;
7310 }
7311
7312 /* Make a word list which is the result of parameter and variable
7313    expansion, command substitution, arithmetic substitution, and
7314    quote removal of WORD.  Return a pointer to a WORD_LIST which is
7315    the result of the expansion.  If WORD contains a null word, the
7316    word list returned is also null.
7317
7318    QUOTED contains flag values defined in shell.h.
7319
7320    ISEXP is used to tell expand_word_internal that the word should be
7321    treated as the result of an expansion.  This has implications for
7322    how IFS characters in the word are treated.
7323
7324    CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7325    they point to an integer value which receives information about expansion.
7326    CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7327    EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7328    else zero.
7329
7330    This only does word splitting in the case of $@ expansion.  In that
7331    case, we split on ' '. */
7332
7333 /* Values for the local variable quoted_state. */
7334 #define UNQUOTED         0
7335 #define PARTIALLY_QUOTED 1
7336 #define WHOLLY_QUOTED    2
7337
7338 static WORD_LIST *
7339 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7340      WORD_DESC *word;
7341      int quoted, isexp;
7342      int *contains_dollar_at;
7343      int *expanded_something;
7344 {
7345   WORD_LIST *list;
7346   WORD_DESC *tword;
7347
7348   /* The intermediate string that we build while expanding. */
7349   char *istring;
7350
7351   /* The current size of the above object. */
7352   int istring_size;
7353
7354   /* Index into ISTRING. */
7355   int istring_index;
7356
7357   /* Temporary string storage. */
7358   char *temp, *temp1;
7359
7360   /* The text of WORD. */
7361   register char *string;
7362
7363   /* The size of STRING. */
7364   size_t string_size;
7365
7366   /* The index into STRING. */
7367   int sindex;
7368
7369   /* This gets 1 if we see a $@ while quoted. */
7370   int quoted_dollar_at;
7371
7372   /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7373      whether WORD contains no quoting characters, a partially quoted
7374      string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7375   int quoted_state;
7376
7377   /* State flags */
7378   int had_quoted_null;
7379   int has_dollar_at;
7380   int tflag;
7381
7382   int assignoff;                /* If assignment, offset of `=' */
7383
7384   register unsigned char c;     /* Current character. */
7385   int t_index;                  /* For calls to string_extract_xxx. */
7386
7387   char twochars[2];
7388
7389   DECLARE_MBSTATE;
7390
7391   istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7392   istring[istring_index = 0] = '\0';
7393   quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7394   quoted_state = UNQUOTED;
7395
7396   string = word->word;
7397   if (string == 0)
7398     goto finished_with_string;
7399   /* Don't need the string length for the SADD... and COPY_ macros unless
7400      multibyte characters are possible. */
7401   string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7402
7403   if (contains_dollar_at)
7404     *contains_dollar_at = 0;
7405
7406   assignoff = -1;
7407
7408   /* Begin the expansion. */
7409
7410   for (sindex = 0; ;)
7411     {
7412       c = string[sindex];
7413
7414       /* Case on toplevel character. */
7415       switch (c)
7416         {
7417         case '\0':
7418           goto finished_with_string;
7419
7420         case CTLESC:
7421           sindex++;
7422 #if HANDLE_MULTIBYTE
7423           if (MB_CUR_MAX > 1 && string[sindex])
7424             {
7425               SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7426             }
7427           else
7428 #endif
7429             {
7430               temp = (char *)xmalloc (3);
7431               temp[0] = CTLESC;
7432               temp[1] = c = string[sindex];
7433               temp[2] = '\0';
7434             }
7435
7436 dollar_add_string:
7437           if (string[sindex])
7438             sindex++;
7439
7440 add_string:
7441           if (temp)
7442             {
7443               istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7444               temp = (char *)0;
7445             }
7446
7447           break;
7448
7449 #if defined (PROCESS_SUBSTITUTION)
7450           /* Process substitution. */
7451         case '<':
7452         case '>':
7453           {
7454             if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7455               {
7456                 sindex--;       /* add_character: label increments sindex */
7457                 goto add_character;
7458               }
7459             else
7460               t_index = sindex + 1; /* skip past both '<' and LPAREN */
7461
7462             temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7463             sindex = t_index;
7464
7465             /* If the process substitution specification is `<()', we want to
7466                open the pipe for writing in the child and produce output; if
7467                it is `>()', we want to open the pipe for reading in the child
7468                and consume input. */
7469             temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
7470
7471             FREE (temp1);
7472
7473             goto dollar_add_string;
7474           }
7475 #endif /* PROCESS_SUBSTITUTION */
7476
7477         case '=':
7478           /* Posix.2 section 3.6.1 says that tildes following `=' in words
7479              which are not assignment statements are not expanded.  If the
7480              shell isn't in posix mode, though, we perform tilde expansion
7481              on `likely candidate' unquoted assignment statements (flags
7482              include W_ASSIGNMENT but not W_QUOTED).  A likely candidate
7483              contains an unquoted :~ or =~.  Something to think about: we
7484              now have a flag that says  to perform tilde expansion on arguments
7485              to `assignment builtins' like declare and export that look like
7486              assignment statements.  We now do tilde expansion on such words
7487              even in POSIX mode. */     
7488           if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
7489             {
7490               if (isexp == 0 && isifs (c))
7491                 goto add_ifs_character;
7492               else
7493                 goto add_character;
7494             }
7495           /* If we're not in posix mode or forcing assignment-statement tilde
7496              expansion, note where the `=' appears in the word and prepare to
7497              do tilde expansion following the first `='. */
7498           if ((word->flags & W_ASSIGNMENT) &&
7499               (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7500               assignoff == -1 && sindex > 0)
7501             assignoff = sindex;
7502           if (sindex == assignoff && string[sindex+1] == '~')   /* XXX */
7503             word->flags |= W_ITILDE;
7504 #if 0
7505           else if ((word->flags & W_ASSIGNMENT) &&
7506                    (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7507                    string[sindex+1] == '~')
7508             word->flags |= W_ITILDE;
7509 #endif
7510           if (isexp == 0 && isifs (c))
7511             goto add_ifs_character;
7512           else
7513             goto add_character;
7514
7515         case ':':
7516           if (word->flags & W_NOTILDE)
7517             {
7518               if (isexp == 0 && isifs (c))
7519                 goto add_ifs_character;
7520               else
7521                 goto add_character;
7522             }
7523
7524           if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
7525               string[sindex+1] == '~')
7526             word->flags |= W_ITILDE;
7527
7528           if (isexp == 0 && isifs (c))
7529             goto add_ifs_character;
7530           else
7531             goto add_character;
7532
7533         case '~':
7534           /* If the word isn't supposed to be tilde expanded, or we're not
7535              at the start of a word or after an unquoted : or = in an
7536              assignment statement, we don't do tilde expansion. */
7537           if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
7538               (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
7539               (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7540             {
7541               word->flags &= ~W_ITILDE;
7542               if (isexp == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
7543                 goto add_ifs_character;
7544               else
7545                 goto add_character;
7546             }
7547
7548           if (word->flags & W_ASSIGNRHS)
7549             tflag = 2;
7550           else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
7551             tflag = 1;
7552           else
7553             tflag = 0;
7554
7555           temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
7556             
7557           word->flags &= ~W_ITILDE;
7558
7559           if (temp && *temp && t_index > 0)
7560             {
7561               temp1 = bash_tilde_expand (temp, tflag);
7562               if  (temp1 && *temp1 == '~' && STREQ (temp, temp1))
7563                 {
7564                   FREE (temp);
7565                   FREE (temp1);
7566                   goto add_character;           /* tilde expansion failed */
7567                 }
7568               free (temp);
7569               temp = temp1;
7570               sindex += t_index;
7571               goto add_quoted_string;           /* XXX was add_string */
7572             }
7573           else
7574             {
7575               FREE (temp);
7576               goto add_character;
7577             }
7578         
7579         case '$':
7580           if (expanded_something)
7581             *expanded_something = 1;
7582
7583           has_dollar_at = 0;
7584           tword = param_expand (string, &sindex, quoted, expanded_something,
7585                                &has_dollar_at, &quoted_dollar_at,
7586                                &had_quoted_null,
7587                                (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
7588
7589           if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
7590             {
7591               free (string);
7592               free (istring);
7593               return ((tword == &expand_wdesc_error) ? &expand_word_error
7594                                                      : &expand_word_fatal);
7595             }
7596           if (contains_dollar_at && has_dollar_at)
7597             *contains_dollar_at = 1;
7598
7599           if (tword && (tword->flags & W_HASQUOTEDNULL))
7600             had_quoted_null = 1;
7601
7602           temp = tword->word;
7603           dispose_word_desc (tword);
7604
7605           goto add_string;
7606           break;
7607
7608         case '`':               /* Backquoted command substitution. */
7609           {
7610             t_index = sindex++;
7611
7612             temp = string_extract (string, &sindex, "`", SX_REQMATCH);
7613             /* The test of sindex against t_index is to allow bare instances of
7614                ` to pass through, for backwards compatibility. */
7615             if (temp == &extract_string_error || temp == &extract_string_fatal)
7616               {
7617                 if (sindex - 1 == t_index)
7618                   {
7619                     sindex = t_index;
7620                     goto add_character;
7621                   }
7622                 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
7623                 free (string);
7624                 free (istring);
7625                 return ((temp == &extract_string_error) ? &expand_word_error
7626                                                         : &expand_word_fatal);
7627               }
7628                 
7629             if (expanded_something)
7630               *expanded_something = 1;
7631
7632             if (word->flags & W_NOCOMSUB)
7633               /* sindex + 1 because string[sindex] == '`' */
7634               temp1 = substring (string, t_index, sindex + 1);
7635             else
7636               {
7637                 de_backslash (temp);
7638                 tword = command_substitute (temp, quoted);
7639                 temp1 = tword ? tword->word : (char *)NULL;
7640                 if (tword)
7641                   dispose_word_desc (tword);
7642               }
7643             FREE (temp);
7644             temp = temp1;
7645             goto dollar_add_string;
7646           }
7647
7648         case '\\':
7649           if (string[sindex + 1] == '\n')
7650             {
7651               sindex += 2;
7652               continue;
7653             }
7654
7655           c = string[++sindex];
7656
7657           if (quoted & Q_HERE_DOCUMENT)
7658             tflag = CBSHDOC;
7659           else if (quoted & Q_DOUBLE_QUOTES)
7660             tflag = CBSDQUOTE;
7661           else
7662             tflag = 0;
7663
7664           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7665             {
7666               SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7667             }
7668           else if (c == 0)
7669             {
7670               c = CTLNUL;
7671               sindex--;         /* add_character: label increments sindex */
7672               goto add_character;
7673             }
7674           else
7675             {
7676               SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7677             }
7678
7679           sindex++;
7680 add_twochars:
7681           /* BEFORE jumping here, we need to increment sindex if appropriate */
7682           RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7683                                   DEFAULT_ARRAY_SIZE);
7684           istring[istring_index++] = twochars[0];
7685           istring[istring_index++] = twochars[1];
7686           istring[istring_index] = '\0';
7687
7688           break;
7689
7690         case '"':
7691 #if 0
7692           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7693 #else
7694           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7695 #endif
7696             goto add_character;
7697
7698           t_index = ++sindex;
7699           temp = string_extract_double_quoted (string, &sindex, 0);
7700
7701           /* If the quotes surrounded the entire string, then the
7702              whole word was quoted. */
7703           quoted_state = (t_index == 1 && string[sindex] == '\0')
7704                             ? WHOLLY_QUOTED
7705                             : PARTIALLY_QUOTED;
7706
7707           if (temp && *temp)
7708             {
7709               tword = alloc_word_desc ();
7710               tword->word = temp;
7711
7712               temp = (char *)NULL;
7713
7714               has_dollar_at = 0;
7715               /* Need to get W_HASQUOTEDNULL flag through this function. */
7716               list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7717
7718               if (list == &expand_word_error || list == &expand_word_fatal)
7719                 {
7720                   free (istring);
7721                   free (string);
7722                   /* expand_word_internal has already freed temp_word->word
7723                      for us because of the way it prints error messages. */
7724                   tword->word = (char *)NULL;
7725                   dispose_word (tword);
7726                   return list;
7727                 }
7728
7729               dispose_word (tword);
7730
7731               /* "$@" (a double-quoted dollar-at) expands into nothing,
7732                  not even a NULL word, when there are no positional
7733                  parameters. */
7734               if (list == 0 && has_dollar_at)
7735                 {
7736                   quoted_dollar_at++;
7737                   break;
7738                 }
7739
7740               /* If we get "$@", we know we have expanded something, so we
7741                  need to remember it for the final split on $IFS.  This is
7742                  a special case; it's the only case where a quoted string
7743                  can expand into more than one word.  It's going to come back
7744                  from the above call to expand_word_internal as a list with
7745                  a single word, in which all characters are quoted and
7746                  separated by blanks.  What we want to do is to turn it back
7747                  into a list for the next piece of code. */
7748               if (list)
7749                 dequote_list (list);
7750
7751               if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7752                 had_quoted_null = 1;
7753
7754               if (has_dollar_at)
7755                 {
7756                   quoted_dollar_at++;
7757                   if (contains_dollar_at)
7758                     *contains_dollar_at = 1;
7759                   if (expanded_something)
7760                     *expanded_something = 1;
7761                 }
7762             }
7763           else
7764             {
7765               /* What we have is "".  This is a minor optimization. */
7766               FREE (temp);
7767               list = (WORD_LIST *)NULL;
7768             }
7769
7770           /* The code above *might* return a list (consider the case of "$@",
7771              where it returns "$1", "$2", etc.).  We can't throw away the
7772              rest of the list, and we have to make sure each word gets added
7773              as quoted.  We test on tresult->next:  if it is non-NULL, we
7774              quote the whole list, save it to a string with string_list, and
7775              add that string. We don't need to quote the results of this
7776              (and it would be wrong, since that would quote the separators
7777              as well), so we go directly to add_string. */
7778           if (list)
7779             {
7780               if (list->next)
7781                 {
7782                   /* Testing quoted_dollar_at makes sure that "$@" is
7783                      split correctly when $IFS does not contain a space. */
7784                   temp = quoted_dollar_at
7785                                 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7786                                 : string_list (quote_list (list));
7787                   dispose_words (list);
7788                   goto add_string;
7789                 }
7790               else
7791                 {
7792                   temp = savestring (list->word->word);
7793                   tflag = list->word->flags;
7794                   dispose_words (list);
7795
7796                   /* If the string is not a quoted null string, we want
7797                      to remove any embedded unquoted CTLNUL characters.
7798                      We do not want to turn quoted null strings back into
7799                      the empty string, though.  We do this because we
7800                      want to remove any quoted nulls from expansions that
7801                      contain other characters.  For example, if we have
7802                      x"$*"y or "x$*y" and there are no positional parameters,
7803                      the $* should expand into nothing. */
7804                   /* We use the W_HASQUOTEDNULL flag to differentiate the
7805                      cases:  a quoted null character as above and when
7806                      CTLNUL is contained in the (non-null) expansion
7807                      of some variable.  We use the had_quoted_null flag to
7808                      pass the value through this function to its caller. */
7809                   if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7810                     remove_quoted_nulls (temp); /* XXX */
7811                 }
7812             }
7813           else
7814             temp = (char *)NULL;
7815
7816           /* We do not want to add quoted nulls to strings that are only
7817              partially quoted; we can throw them away. */
7818           if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7819             continue;
7820
7821         add_quoted_string:
7822
7823           if (temp)
7824             {
7825               temp1 = temp;
7826               temp = quote_string (temp);
7827               free (temp1);
7828               goto add_string;
7829             }
7830           else
7831             {
7832               /* Add NULL arg. */
7833               c = CTLNUL;
7834               sindex--;         /* add_character: label increments sindex */
7835               goto add_character;
7836             }
7837
7838           /* break; */
7839
7840         case '\'':
7841 #if 0
7842           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7843 #else
7844           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7845 #endif
7846             goto add_character;
7847
7848           t_index = ++sindex;
7849           temp = string_extract_single_quoted (string, &sindex);
7850
7851           /* If the entire STRING was surrounded by single quotes,
7852              then the string is wholly quoted. */
7853           quoted_state = (t_index == 1 && string[sindex] == '\0')
7854                             ? WHOLLY_QUOTED
7855                             : PARTIALLY_QUOTED;
7856
7857           /* If all we had was '', it is a null expansion. */
7858           if (*temp == '\0')
7859             {
7860               free (temp);
7861               temp = (char *)NULL;
7862             }
7863           else
7864             remove_quoted_escapes (temp);       /* ??? */
7865
7866           /* We do not want to add quoted nulls to strings that are only
7867              partially quoted; such nulls are discarded. */
7868           if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7869             continue;
7870
7871           /* If we have a quoted null expansion, add a quoted NULL to istring. */
7872           if (temp == 0)
7873             {
7874               c = CTLNUL;
7875               sindex--;         /* add_character: label increments sindex */
7876               goto add_character;
7877             }
7878           else
7879             goto add_quoted_string;
7880
7881           /* break; */
7882
7883         default:
7884           /* This is the fix for " $@ " */
7885         add_ifs_character:
7886           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7887             {
7888               if (string[sindex])       /* from old goto dollar_add_string */
7889                 sindex++;
7890               if (c == 0)
7891                 {
7892                   c = CTLNUL;
7893                   goto add_character;
7894                 }
7895               else
7896                 {
7897 #if HANDLE_MULTIBYTE
7898                   if (MB_CUR_MAX > 1)
7899                     sindex--;
7900
7901                   if (MB_CUR_MAX > 1)
7902                     {
7903                       SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7904                     }
7905                   else
7906 #endif
7907                     {
7908                       twochars[0] = CTLESC;
7909                       twochars[1] = c;
7910                       goto add_twochars;
7911                     }
7912                 }
7913             }
7914
7915           SADD_MBCHAR (temp, string, sindex, string_size);
7916
7917         add_character:
7918           RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7919                                   DEFAULT_ARRAY_SIZE);
7920           istring[istring_index++] = c;
7921           istring[istring_index] = '\0';
7922
7923           /* Next character. */
7924           sindex++;
7925         }
7926     }
7927
7928 finished_with_string:
7929   /* OK, we're ready to return.  If we have a quoted string, and
7930      quoted_dollar_at is not set, we do no splitting at all; otherwise
7931      we split on ' '.  The routines that call this will handle what to
7932      do if nothing has been expanded. */
7933
7934   /* Partially and wholly quoted strings which expand to the empty
7935      string are retained as an empty arguments.  Unquoted strings
7936      which expand to the empty string are discarded.  The single
7937      exception is the case of expanding "$@" when there are no
7938      positional parameters.  In that case, we discard the expansion. */
7939
7940   /* Because of how the code that handles "" and '' in partially
7941      quoted strings works, we need to make ISTRING into a QUOTED_NULL
7942      if we saw quoting characters, but the expansion was empty.
7943      "" and '' are tossed away before we get to this point when
7944      processing partially quoted strings.  This makes "" and $xxx""
7945      equivalent when xxx is unset.  We also look to see whether we
7946      saw a quoted null from a ${} expansion and add one back if we
7947      need to. */
7948
7949   /* If we expand to nothing and there were no single or double quotes
7950      in the word, we throw it away.  Otherwise, we return a NULL word.
7951      The single exception is for $@ surrounded by double quotes when
7952      there are no positional parameters.  In that case, we also throw
7953      the word away. */
7954
7955   if (*istring == '\0')
7956     {
7957       if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7958         {
7959           istring[0] = CTLNUL;
7960           istring[1] = '\0';
7961           tword = make_bare_word (istring);
7962           tword->flags |= W_HASQUOTEDNULL;              /* XXX */
7963           list = make_word_list (tword, (WORD_LIST *)NULL);
7964           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7965             tword->flags |= W_QUOTED;
7966         }
7967       /* According to sh, ksh, and Posix.2, if a word expands into nothing
7968          and a double-quoted "$@" appears anywhere in it, then the entire
7969          word is removed. */
7970       else  if (quoted_state == UNQUOTED || quoted_dollar_at)
7971         list = (WORD_LIST *)NULL;
7972 #if 0
7973       else
7974         {
7975           tword = make_bare_word (istring);
7976           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7977             tword->flags |= W_QUOTED;
7978           list = make_word_list (tword, (WORD_LIST *)NULL);
7979         }
7980 #else
7981       else
7982         list = (WORD_LIST *)NULL;
7983 #endif
7984     }
7985   else if (word->flags & W_NOSPLIT)
7986     {
7987       tword = make_bare_word (istring);
7988       if (word->flags & W_ASSIGNMENT)
7989         tword->flags |= W_ASSIGNMENT;   /* XXX */
7990       if (word->flags & W_COMPASSIGN)
7991         tword->flags |= W_COMPASSIGN;   /* XXX */
7992       if (word->flags & W_NOGLOB)
7993         tword->flags |= W_NOGLOB;       /* XXX */
7994       if (word->flags & W_NOEXPAND)
7995         tword->flags |= W_NOEXPAND;     /* XXX */
7996       if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7997         tword->flags |= W_QUOTED;
7998       if (had_quoted_null)
7999         tword->flags |= W_HASQUOTEDNULL;
8000       list = make_word_list (tword, (WORD_LIST *)NULL);
8001     }
8002   else
8003     {
8004       char *ifs_chars;
8005
8006       ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
8007
8008       /* If we have $@, we need to split the results no matter what.  If
8009          IFS is unset or NULL, string_list_dollar_at has separated the
8010          positional parameters with a space, so we split on space (we have
8011          set ifs_chars to " \t\n" above if ifs is unset).  If IFS is set,
8012          string_list_dollar_at has separated the positional parameters
8013          with the first character of $IFS, so we split on $IFS. */
8014       if (has_dollar_at && ifs_chars)
8015         list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
8016       else
8017         {
8018           tword = make_bare_word (istring);
8019           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8020             tword->flags |= W_QUOTED;
8021           if (word->flags & W_ASSIGNMENT)
8022             tword->flags |= W_ASSIGNMENT;
8023           if (word->flags & W_COMPASSIGN)
8024             tword->flags |= W_COMPASSIGN;
8025           if (word->flags & W_NOGLOB)
8026             tword->flags |= W_NOGLOB;
8027           if (word->flags & W_NOEXPAND)
8028             tword->flags |= W_NOEXPAND;
8029           if (had_quoted_null)
8030             tword->flags |= W_HASQUOTEDNULL;    /* XXX */
8031           list = make_word_list (tword, (WORD_LIST *)NULL);
8032         }
8033     }
8034
8035   free (istring);
8036   return (list);
8037 }
8038
8039 /* **************************************************************** */
8040 /*                                                                  */
8041 /*                 Functions for Quote Removal                      */
8042 /*                                                                  */
8043 /* **************************************************************** */
8044
8045 /* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
8046    backslash quoting rules for within double quotes or a here document. */
8047 char *
8048 string_quote_removal (string, quoted)
8049      char *string;
8050      int quoted;
8051 {
8052   size_t slen;
8053   char *r, *result_string, *temp, *send;
8054   int sindex, tindex, dquote;
8055   unsigned char c;
8056   DECLARE_MBSTATE;
8057
8058   /* The result can be no longer than the original string. */
8059   slen = strlen (string);
8060   send = string + slen;
8061
8062   r = result_string = (char *)xmalloc (slen + 1);
8063
8064   for (dquote = sindex = 0; c = string[sindex];)
8065     {
8066       switch (c)
8067         {
8068         case '\\':
8069           c = string[++sindex];
8070           if (c == 0)
8071             {
8072               *r++ = '\\';
8073               break;
8074             }
8075           if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8076             *r++ = '\\';
8077           /* FALLTHROUGH */
8078
8079         default:
8080           SCOPY_CHAR_M (r, string, send, sindex);
8081           break;
8082
8083         case '\'':
8084           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8085             {
8086               *r++ = c;
8087               sindex++;
8088               break;
8089             }
8090           tindex = sindex + 1;
8091           temp = string_extract_single_quoted (string, &tindex);
8092           if (temp)
8093             {
8094               strcpy (r, temp);
8095               r += strlen (r);
8096               free (temp);
8097             }
8098           sindex = tindex;
8099           break;
8100
8101         case '"':
8102           dquote = 1 - dquote;
8103           sindex++;
8104           break;
8105         }
8106     }
8107     *r = '\0';
8108     return (result_string);
8109 }
8110
8111 #if 0
8112 /* UNUSED */
8113 /* Perform quote removal on word WORD.  This allocates and returns a new
8114    WORD_DESC *. */
8115 WORD_DESC *
8116 word_quote_removal (word, quoted)
8117      WORD_DESC *word;
8118      int quoted;
8119 {
8120   WORD_DESC *w;
8121   char *t;
8122
8123   t = string_quote_removal (word->word, quoted);
8124   w = alloc_word_desc ();
8125   w->word = t ? t : savestring ("");
8126   return (w);
8127 }
8128
8129 /* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
8130    the members of the list are treated as if they are surrounded by
8131    double quotes.  Return a new list, or NULL if LIST is NULL. */
8132 WORD_LIST *
8133 word_list_quote_removal (list, quoted)
8134      WORD_LIST *list;
8135      int quoted;
8136 {
8137   WORD_LIST *result, *t, *tresult, *e;
8138
8139   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8140     {
8141       tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8142 #if 0
8143       result = (WORD_LIST *) list_append (result, tresult);
8144 #else
8145       if (result == 0)
8146         result = e = tresult;
8147       else
8148         {
8149           e->next = tresult;
8150           while (e->next)
8151             e = e->next;
8152         }
8153 #endif
8154     }
8155   return (result);
8156 }
8157 #endif
8158
8159 /*******************************************
8160  *                                         *
8161  *    Functions to perform word splitting  *
8162  *                                         *
8163  *******************************************/
8164
8165 void
8166 setifs (v)
8167      SHELL_VAR *v;
8168 {
8169   char *t;
8170   unsigned char uc;
8171
8172   ifs_var = v;
8173   ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8174
8175   /* Should really merge ifs_cmap with sh_syntaxtab.  XXX - doesn't yet
8176      handle multibyte chars in IFS */
8177   memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8178   for (t = ifs_value ; t && *t; t++)
8179     {
8180       uc = *t;
8181       ifs_cmap[uc] = 1;
8182     }
8183
8184 #if defined (HANDLE_MULTIBYTE)
8185   if (ifs_value == 0)
8186     {
8187       ifs_firstc[0] = '\0';
8188       ifs_firstc_len = 1;
8189     }
8190   else
8191     {
8192       size_t ifs_len;
8193       ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8194       ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8195       if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8196         {
8197           ifs_firstc[0] = ifs_value[0];
8198           ifs_firstc[1] = '\0';
8199           ifs_firstc_len = 1;
8200         }
8201       else
8202         memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8203     }
8204 #else
8205   ifs_firstc = ifs_value ? *ifs_value : 0;
8206 #endif
8207 }
8208
8209 char *
8210 getifs ()
8211 {
8212   return ifs_value;
8213 }
8214
8215 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8216    is not quoted.  list_string () performs quote removal for us, even if we
8217    don't do any splitting. */
8218 WORD_LIST *
8219 word_split (w, ifs_chars)
8220      WORD_DESC *w;
8221      char *ifs_chars;
8222 {
8223   WORD_LIST *result;
8224
8225   if (w)
8226     {
8227       char *xifs;
8228
8229       xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8230       result = list_string (w->word, xifs, w->flags & W_QUOTED);
8231     }
8232   else
8233     result = (WORD_LIST *)NULL;
8234
8235   return (result);
8236 }
8237
8238 /* Perform word splitting on LIST and return the RESULT.  It is possible
8239    to return (WORD_LIST *)NULL. */
8240 static WORD_LIST *
8241 word_list_split (list)
8242      WORD_LIST *list;
8243 {
8244   WORD_LIST *result, *t, *tresult, *e;
8245
8246   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8247     {
8248       tresult = word_split (t->word, ifs_value);
8249       if (result == 0)
8250         result = e = tresult;
8251       else
8252         {
8253           e->next = tresult;
8254           while (e->next)
8255             e = e->next;
8256         }
8257     }
8258   return (result);
8259 }
8260
8261 /**************************************************
8262  *                                                *
8263  *    Functions to expand an entire WORD_LIST     *
8264  *                                                *
8265  **************************************************/
8266
8267 /* Do any word-expansion-specific cleanup and jump to top_level */
8268 static void
8269 exp_jump_to_top_level (v)
8270      int v;
8271 {
8272   set_pipestatus_from_exit (last_command_exit_value);
8273
8274   /* Cleanup code goes here. */
8275   expand_no_split_dollar_star = 0;      /* XXX */
8276   expanding_redir = 0;
8277   assigning_in_environment = 0;
8278
8279   if (parse_and_execute_level == 0)
8280     top_level_cleanup ();                       /* from sig.c */
8281
8282   jump_to_top_level (v);
8283 }
8284
8285 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8286    ELIST, and set ELIST to the new list. */
8287 #define PREPEND_LIST(nlist, elist) \
8288         do { nlist->next = elist; elist = nlist; } while (0)
8289
8290 /* Separate out any initial variable assignments from TLIST.  If set -k has
8291    been executed, remove all assignment statements from TLIST.  Initial
8292    variable assignments and other environment assignments are placed
8293    on SUBST_ASSIGN_VARLIST. */
8294 static WORD_LIST *
8295 separate_out_assignments (tlist)
8296      WORD_LIST *tlist;
8297 {
8298   register WORD_LIST *vp, *lp;
8299
8300   if (!tlist)
8301     return ((WORD_LIST *)NULL);
8302
8303   if (subst_assign_varlist)
8304     dispose_words (subst_assign_varlist);       /* Clean up after previous error */
8305
8306   subst_assign_varlist = (WORD_LIST *)NULL;
8307   vp = lp = tlist;
8308
8309   /* Separate out variable assignments at the start of the command.
8310      Loop invariant: vp->next == lp
8311      Loop postcondition:
8312         lp = list of words left after assignment statements skipped
8313         tlist = original list of words
8314   */
8315   while (lp && (lp->word->flags & W_ASSIGNMENT))
8316     {
8317       vp = lp;
8318       lp = lp->next;
8319     }
8320
8321   /* If lp != tlist, we have some initial assignment statements.
8322      We make SUBST_ASSIGN_VARLIST point to the list of assignment
8323      words and TLIST point to the remaining words.  */
8324   if (lp != tlist)
8325     {
8326       subst_assign_varlist = tlist;
8327       /* ASSERT(vp->next == lp); */
8328       vp->next = (WORD_LIST *)NULL;     /* terminate variable list */
8329       tlist = lp;                       /* remainder of word list */
8330     }
8331
8332   /* vp == end of variable list */
8333   /* tlist == remainder of original word list without variable assignments */
8334   if (!tlist)
8335     /* All the words in tlist were assignment statements */
8336     return ((WORD_LIST *)NULL);
8337
8338   /* ASSERT(tlist != NULL); */
8339   /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8340
8341   /* If the -k option is in effect, we need to go through the remaining
8342      words, separate out the assignment words, and place them on
8343      SUBST_ASSIGN_VARLIST. */
8344   if (place_keywords_in_env)
8345     {
8346       WORD_LIST *tp;    /* tp == running pointer into tlist */
8347
8348       tp = tlist;
8349       lp = tlist->next;
8350
8351       /* Loop Invariant: tp->next == lp */
8352       /* Loop postcondition: tlist == word list without assignment statements */
8353       while (lp)
8354         {
8355           if (lp->word->flags & W_ASSIGNMENT)
8356             {
8357               /* Found an assignment statement, add this word to end of
8358                  subst_assign_varlist (vp). */
8359               if (!subst_assign_varlist)
8360                 subst_assign_varlist = vp = lp;
8361               else
8362                 {
8363                   vp->next = lp;
8364                   vp = lp;
8365                 }
8366
8367               /* Remove the word pointed to by LP from TLIST. */
8368               tp->next = lp->next;
8369               /* ASSERT(vp == lp); */
8370               lp->next = (WORD_LIST *)NULL;
8371               lp = tp->next;
8372             }
8373           else
8374             {
8375               tp = lp;
8376               lp = lp->next;
8377             }
8378         }
8379     }
8380   return (tlist);
8381 }
8382
8383 #define WEXP_VARASSIGN  0x001
8384 #define WEXP_BRACEEXP   0x002
8385 #define WEXP_TILDEEXP   0x004
8386 #define WEXP_PARAMEXP   0x008
8387 #define WEXP_PATHEXP    0x010
8388
8389 /* All of the expansions, including variable assignments at the start of
8390    the list. */
8391 #define WEXP_ALL        (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8392
8393 /* All of the expansions except variable assignments at the start of
8394    the list. */
8395 #define WEXP_NOVARS     (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8396
8397 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8398    expansion, command substitution, arithmetic expansion, word splitting, and
8399    quote removal. */
8400 #define WEXP_SHELLEXP   (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8401
8402 /* Take the list of words in LIST and do the various substitutions.  Return
8403    a new list of words which is the expanded list, and without things like
8404    variable assignments. */
8405
8406 WORD_LIST *
8407 expand_words (list)
8408      WORD_LIST *list;
8409 {
8410   return (expand_word_list_internal (list, WEXP_ALL));
8411 }
8412
8413 /* Same as expand_words (), but doesn't hack variable or environment
8414    variables. */
8415 WORD_LIST *
8416 expand_words_no_vars (list)
8417      WORD_LIST *list;
8418 {
8419   return (expand_word_list_internal (list, WEXP_NOVARS));
8420 }
8421
8422 WORD_LIST *
8423 expand_words_shellexp (list)
8424      WORD_LIST *list;
8425 {
8426   return (expand_word_list_internal (list, WEXP_SHELLEXP));
8427 }
8428
8429 static WORD_LIST *
8430 glob_expand_word_list (tlist, eflags)
8431      WORD_LIST *tlist;
8432      int eflags;
8433 {
8434   char **glob_array, *temp_string;
8435   register int glob_index;
8436   WORD_LIST *glob_list, *output_list, *disposables, *next;
8437   WORD_DESC *tword;
8438
8439   output_list = disposables = (WORD_LIST *)NULL;
8440   glob_array = (char **)NULL;
8441   while (tlist)
8442     {
8443       /* For each word, either globbing is attempted or the word is
8444          added to orig_list.  If globbing succeeds, the results are
8445          added to orig_list and the word (tlist) is added to the list
8446          of disposable words.  If globbing fails and failed glob
8447          expansions are left unchanged (the shell default), the
8448          original word is added to orig_list.  If globbing fails and
8449          failed glob expansions are removed, the original word is
8450          added to the list of disposable words.  orig_list ends up
8451          in reverse order and requires a call to REVERSE_LIST to
8452          be set right.  After all words are examined, the disposable
8453          words are freed. */
8454       next = tlist->next;
8455
8456       /* If the word isn't an assignment and contains an unquoted
8457          pattern matching character, then glob it. */
8458       if ((tlist->word->flags & W_NOGLOB) == 0 &&
8459           unquoted_glob_pattern_p (tlist->word->word))
8460         {
8461           glob_array = shell_glob_filename (tlist->word->word);
8462
8463           /* Handle error cases.
8464              I don't think we should report errors like "No such file
8465              or directory".  However, I would like to report errors
8466              like "Read failed". */
8467
8468           if (glob_array == 0 || GLOB_FAILED (glob_array))
8469             {
8470               glob_array = (char **)xmalloc (sizeof (char *));
8471               glob_array[0] = (char *)NULL;
8472             }
8473
8474           /* Dequote the current word in case we have to use it. */
8475           if (glob_array[0] == NULL)
8476             {
8477               temp_string = dequote_string (tlist->word->word);
8478               free (tlist->word->word);
8479               tlist->word->word = temp_string;
8480             }
8481
8482           /* Make the array into a word list. */
8483           glob_list = (WORD_LIST *)NULL;
8484           for (glob_index = 0; glob_array[glob_index]; glob_index++)
8485             {
8486               tword = make_bare_word (glob_array[glob_index]);
8487               tword->flags |= W_GLOBEXP;        /* XXX */
8488               glob_list = make_word_list (tword, glob_list);
8489             }
8490
8491           if (glob_list)
8492             {
8493               output_list = (WORD_LIST *)list_append (glob_list, output_list);
8494               PREPEND_LIST (tlist, disposables);
8495             }
8496           else if (fail_glob_expansion != 0)
8497             {
8498               report_error (_("no match: %s"), tlist->word->word);
8499               exp_jump_to_top_level (DISCARD);
8500             }
8501           else if (allow_null_glob_expansion == 0)
8502             {
8503               /* Failed glob expressions are left unchanged. */
8504               PREPEND_LIST (tlist, output_list);
8505             }
8506           else
8507             {
8508               /* Failed glob expressions are removed. */
8509               PREPEND_LIST (tlist, disposables);
8510             }
8511         }
8512       else
8513         {
8514           /* Dequote the string. */
8515           temp_string = dequote_string (tlist->word->word);
8516           free (tlist->word->word);
8517           tlist->word->word = temp_string;
8518           PREPEND_LIST (tlist, output_list);
8519         }
8520
8521       strvec_dispose (glob_array);
8522       glob_array = (char **)NULL;
8523
8524       tlist = next;
8525     }
8526
8527   if (disposables)
8528     dispose_words (disposables);
8529
8530   if (output_list)
8531     output_list = REVERSE_LIST (output_list, WORD_LIST *);
8532
8533   return (output_list);
8534 }
8535
8536 #if defined (BRACE_EXPANSION)
8537 static WORD_LIST *
8538 brace_expand_word_list (tlist, eflags)
8539      WORD_LIST *tlist;
8540      int eflags;
8541 {
8542   register char **expansions;
8543   char *temp_string;
8544   WORD_LIST *disposables, *output_list, *next;
8545   WORD_DESC *w;
8546   int eindex;
8547
8548   for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
8549     {
8550       next = tlist->next;
8551
8552       /* Only do brace expansion if the word has a brace character.  If
8553          not, just add the word list element to BRACES and continue.  In
8554          the common case, at least when running shell scripts, this will
8555          degenerate to a bunch of calls to `xstrchr', and then what is
8556          basically a reversal of TLIST into BRACES, which is corrected
8557          by a call to REVERSE_LIST () on BRACES when the end of TLIST
8558          is reached. */
8559       if (xstrchr (tlist->word->word, LBRACE))
8560         {
8561           expansions = brace_expand (tlist->word->word);
8562
8563           for (eindex = 0; temp_string = expansions[eindex]; eindex++)
8564             {
8565               w = make_word (temp_string);
8566               /* If brace expansion didn't change the word, preserve
8567                  the flags.  We may want to preserve the flags
8568                  unconditionally someday -- XXX */
8569               if (STREQ (temp_string, tlist->word->word))
8570                 w->flags = tlist->word->flags;
8571               output_list = make_word_list (w, output_list);
8572               free (expansions[eindex]);
8573             }
8574           free (expansions);
8575
8576           /* Add TLIST to the list of words to be freed after brace
8577              expansion has been performed. */
8578           PREPEND_LIST (tlist, disposables);
8579         }
8580       else
8581         PREPEND_LIST (tlist, output_list);
8582     }
8583
8584   if (disposables)
8585     dispose_words (disposables);
8586
8587   if (output_list)
8588     output_list = REVERSE_LIST (output_list, WORD_LIST *);
8589
8590   return (output_list);
8591 }
8592 #endif
8593
8594 #if defined (ARRAY_VARS)
8595 /* Take WORD, a compound associative array assignment, and internally run
8596    'declare -A w', where W is the variable name portion of WORD. */
8597 static int
8598 make_internal_declare (word, option)
8599      char *word;
8600      char *option;
8601 {
8602   int t;
8603   WORD_LIST *wl;
8604   WORD_DESC *w;
8605
8606   w = make_word (word);
8607
8608   t = assignment (w->word, 0);
8609   w->word[t] = '\0';
8610
8611   wl = make_word_list (w, (WORD_LIST *)NULL);
8612   wl = make_word_list (make_word (option), wl);
8613
8614   return (declare_builtin (wl));  
8615 }  
8616 #endif
8617
8618 static WORD_LIST *
8619 shell_expand_word_list (tlist, eflags)
8620      WORD_LIST *tlist;
8621      int eflags;
8622 {
8623   WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
8624   int expanded_something, has_dollar_at;
8625   char *temp_string;
8626
8627   /* We do tilde expansion all the time.  This is what 1003.2 says. */
8628   new_list = (WORD_LIST *)NULL;
8629   for (orig_list = tlist; tlist; tlist = next)
8630     {
8631       temp_string = tlist->word->word;
8632
8633       next = tlist->next;
8634
8635 #if defined (ARRAY_VARS)
8636       /* If this is a compound array assignment to a builtin that accepts
8637          such assignments (e.g., `declare'), take the assignment and perform
8638          it separately, handling the semantics of declarations inside shell
8639          functions.  This avoids the double-evaluation of such arguments,
8640          because `declare' does some evaluation of compound assignments on
8641          its own. */
8642       if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
8643         {
8644           int t;
8645
8646           if (tlist->word->flags & W_ASSIGNASSOC)
8647             make_internal_declare (tlist->word->word, "-A");
8648
8649           t = do_word_assignment (tlist->word);
8650           if (t == 0)
8651             {
8652               last_command_exit_value = EXECUTION_FAILURE;
8653               exp_jump_to_top_level (DISCARD);
8654             }
8655
8656           /* Now transform the word as ksh93 appears to do and go on */
8657           t = assignment (tlist->word->word, 0);
8658           tlist->word->word[t] = '\0';
8659           tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
8660         }
8661 #endif
8662
8663       expanded_something = 0;
8664       expanded = expand_word_internal
8665         (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
8666
8667       if (expanded == &expand_word_error || expanded == &expand_word_fatal)
8668         {
8669           /* By convention, each time this error is returned,
8670              tlist->word->word has already been freed. */
8671           tlist->word->word = (char *)NULL;
8672
8673           /* Dispose our copy of the original list. */
8674           dispose_words (orig_list);
8675           /* Dispose the new list we're building. */
8676           dispose_words (new_list);
8677
8678           last_command_exit_value = EXECUTION_FAILURE;
8679           if (expanded == &expand_word_error)
8680             exp_jump_to_top_level (DISCARD);
8681           else
8682             exp_jump_to_top_level (FORCE_EOF);
8683         }
8684
8685       /* Don't split words marked W_NOSPLIT. */
8686       if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
8687         {
8688           temp_list = word_list_split (expanded);
8689           dispose_words (expanded);
8690         }
8691       else
8692         {
8693           /* If no parameter expansion, command substitution, process
8694              substitution, or arithmetic substitution took place, then
8695              do not do word splitting.  We still have to remove quoted
8696              null characters from the result. */
8697           word_list_remove_quoted_nulls (expanded);
8698           temp_list = expanded;
8699         }
8700
8701       expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8702       new_list = (WORD_LIST *)list_append (expanded, new_list);
8703     }
8704
8705   if (orig_list)  
8706     dispose_words (orig_list);
8707
8708   if (new_list)
8709     new_list = REVERSE_LIST (new_list, WORD_LIST *);
8710
8711   return (new_list);
8712 }
8713
8714 /* The workhorse for expand_words () and expand_words_no_vars ().
8715    First arg is LIST, a WORD_LIST of words.
8716    Second arg EFLAGS is a flags word controlling which expansions are
8717    performed.
8718
8719    This does all of the substitutions: brace expansion, tilde expansion,
8720    parameter expansion, command substitution, arithmetic expansion,
8721    process substitution, word splitting, and pathname expansion, according
8722    to the bits set in EFLAGS.  Words with the W_QUOTED or W_NOSPLIT bits
8723    set, or for which no expansion is done, do not undergo word splitting.
8724    Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8725 static WORD_LIST *
8726 expand_word_list_internal (list, eflags)
8727      WORD_LIST *list;
8728      int eflags;
8729 {
8730   WORD_LIST *new_list, *temp_list;
8731   int tint;
8732
8733   if (list == 0)
8734     return ((WORD_LIST *)NULL);
8735
8736   garglist = new_list = copy_word_list (list);
8737   if (eflags & WEXP_VARASSIGN)
8738     {
8739       garglist = new_list = separate_out_assignments (new_list);
8740       if (new_list == 0)
8741         {
8742           if (subst_assign_varlist)
8743             {
8744               /* All the words were variable assignments, so they are placed
8745                  into the shell's environment. */
8746               for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8747                 {
8748                   this_command_name = (char *)NULL;     /* no arithmetic errors */
8749                   tint = do_word_assignment (temp_list->word);
8750                   /* Variable assignment errors in non-interactive shells
8751                      running in Posix.2 mode cause the shell to exit. */
8752                   if (tint == 0)
8753                     {
8754                       last_command_exit_value = EXECUTION_FAILURE;
8755                       if (interactive_shell == 0 && posixly_correct)
8756                         exp_jump_to_top_level (FORCE_EOF);
8757                       else
8758                         exp_jump_to_top_level (DISCARD);
8759                     }
8760                 }
8761               dispose_words (subst_assign_varlist);
8762               subst_assign_varlist = (WORD_LIST *)NULL;
8763             }
8764           return ((WORD_LIST *)NULL);
8765         }
8766     }
8767
8768   /* Begin expanding the words that remain.  The expansions take place on
8769      things that aren't really variable assignments. */
8770
8771 #if defined (BRACE_EXPANSION)
8772   /* Do brace expansion on this word if there are any brace characters
8773      in the string. */
8774   if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8775     new_list = brace_expand_word_list (new_list, eflags);
8776 #endif /* BRACE_EXPANSION */
8777
8778   /* Perform the `normal' shell expansions: tilde expansion, parameter and
8779      variable substitution, command substitution, arithmetic expansion,
8780      and word splitting. */
8781   new_list = shell_expand_word_list (new_list, eflags);
8782
8783   /* Okay, we're almost done.  Now let's just do some filename
8784      globbing. */
8785   if (new_list)
8786     {
8787       if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8788         /* Glob expand the word list unless globbing has been disabled. */
8789         new_list = glob_expand_word_list (new_list, eflags);
8790       else
8791         /* Dequote the words, because we're not performing globbing. */
8792         new_list = dequote_list (new_list);
8793     }
8794
8795   if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8796     {
8797       sh_wassign_func_t *assign_func;
8798
8799       /* If the remainder of the words expand to nothing, Posix.2 requires
8800          that the variable and environment assignments affect the shell's
8801          environment. */
8802       assign_func = new_list ? assign_in_env : do_word_assignment;
8803       tempenv_assign_error = 0;
8804
8805       for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8806         {
8807           this_command_name = (char *)NULL;
8808           assigning_in_environment = (assign_func == assign_in_env);
8809           tint = (*assign_func) (temp_list->word);
8810           assigning_in_environment = 0;
8811           /* Variable assignment errors in non-interactive shells running
8812              in Posix.2 mode cause the shell to exit. */
8813           if (tint == 0)
8814             {
8815               if (assign_func == do_word_assignment)
8816                 {
8817                   last_command_exit_value = EXECUTION_FAILURE;
8818                   if (interactive_shell == 0 && posixly_correct)
8819                     exp_jump_to_top_level (FORCE_EOF);
8820                   else
8821                     exp_jump_to_top_level (DISCARD);
8822                 }
8823               else
8824                 tempenv_assign_error++;
8825             }
8826         }
8827
8828       dispose_words (subst_assign_varlist);
8829       subst_assign_varlist = (WORD_LIST *)NULL;
8830     }
8831
8832 #if 0
8833   tint = list_length (new_list) + 1;
8834   RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8835   for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8836     glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8837   glob_argv_flags[tint] = '\0';
8838 #endif
8839
8840   return (new_list);
8841 }