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