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