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