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