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