fcc024bf2f1048b18183aa86666a43b2ff58e370
[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 /* Handle the parameter brace expansion that requires us to return the
4695    length of a parameter. */
4696 static intmax_t
4697 parameter_brace_expand_length (name)
4698      char *name;
4699 {
4700   char *t, *newname;
4701   intmax_t number, arg_index;
4702   WORD_LIST *list;
4703 #if defined (ARRAY_VARS)
4704   SHELL_VAR *var;
4705 #endif
4706
4707   if (name[1] == '\0')                  /* ${#} */
4708     number = number_of_args ();
4709   else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0')       /* ${#@}, ${#*} */
4710     number = number_of_args ();
4711   else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
4712     {
4713       /* Take the lengths of some of the shell's special parameters. */
4714       switch (name[1])
4715         {
4716         case '-':
4717           t = which_set_flags ();
4718           break;
4719         case '?':
4720           t = itos (last_command_exit_value);
4721           break;
4722         case '$':
4723           t = itos (dollar_dollar_pid);
4724           break;
4725         case '!':
4726           if (last_asynchronous_pid == NO_PID)
4727             t = (char *)NULL;
4728           else
4729             t = itos (last_asynchronous_pid);
4730           break;
4731         case '#':
4732           t = itos (number_of_args ());
4733           break;
4734         }
4735       number = STRLEN (t);
4736       FREE (t);
4737     }
4738 #if defined (ARRAY_VARS)
4739   else if (valid_array_reference (name + 1))
4740     number = array_length_reference (name + 1);
4741 #endif /* ARRAY_VARS */
4742   else
4743     {
4744       number = 0;
4745
4746       if (legal_number (name + 1, &arg_index))          /* ${#1} */
4747         {
4748           t = get_dollar_var_value (arg_index);
4749           number = STRLEN (t);
4750           FREE (t);
4751         }
4752 #if defined (ARRAY_VARS)
4753       else if ((var = find_variable (name + 1)) && array_p (var))
4754         {
4755           t = array_reference (array_cell (var), 0);
4756           number = STRLEN (t);
4757         }
4758 #endif
4759       else                              /* ${#PS1} */
4760         {
4761           newname = savestring (name);
4762           newname[0] = '$';
4763           list = expand_string (newname, Q_DOUBLE_QUOTES);
4764           t = list ? string_list (list) : (char *)NULL;
4765           free (newname);
4766           if (list)
4767             dispose_words (list);
4768
4769           number = STRLEN (t);
4770           FREE (t);
4771         }
4772     }
4773
4774   return (number);
4775 }
4776
4777 /* Skip characters in SUBSTR until DELIM.  SUBSTR is an arithmetic expression,
4778    so we do some ad-hoc parsing of an arithmetic expression to find
4779    the first DELIM, instead of using strchr(3).  Two rules:
4780         1.  If the substring contains a `(', read until closing `)'.
4781         2.  If the substring contains a `?', read past one `:' for each `?'.
4782 */
4783
4784 static char *
4785 skiparith (substr, delim)
4786      char *substr;
4787      int delim;
4788 {
4789   size_t sublen;
4790   int skipcol, pcount, i;
4791   DECLARE_MBSTATE;
4792
4793   sublen = strlen (substr);
4794   i = skipcol = pcount = 0;
4795   while (substr[i])
4796     {
4797       /* Balance parens */
4798       if (substr[i] == LPAREN)
4799         {
4800           pcount++;
4801           i++;
4802           continue;
4803         }
4804       if (substr[i] == RPAREN && pcount)
4805         {
4806           pcount--;
4807           i++;
4808           continue;
4809         }
4810       if (pcount)
4811         {
4812           ADVANCE_CHAR (substr, sublen, i);
4813           continue;
4814         }
4815
4816       /* Skip one `:' for each `?' */
4817       if (substr[i] == ':' && skipcol)
4818         {
4819           skipcol--;
4820           i++;
4821           continue;
4822         }
4823       if (substr[i] == delim)
4824         break;
4825       if (substr[i] == '?')
4826         {
4827           skipcol++;
4828           i++;
4829           continue;
4830         }
4831       ADVANCE_CHAR (substr, sublen, i);
4832     }
4833
4834   return (substr + i);
4835 }
4836
4837 /* Verify and limit the start and end of the desired substring.  If
4838    VTYPE == 0, a regular shell variable is being used; if it is 1,
4839    then the positional parameters are being used; if it is 2, then
4840    VALUE is really a pointer to an array variable that should be used.
4841    Return value is 1 if both values were OK, 0 if there was a problem
4842    with an invalid expression, or -1 if the values were out of range. */
4843 static int
4844 verify_substring_values (value, substr, vtype, e1p, e2p)
4845      char *value, *substr;
4846      int vtype;
4847      intmax_t *e1p, *e2p;
4848 {
4849   char *t, *temp1, *temp2;
4850   arrayind_t len;
4851   int expok;
4852 #if defined (ARRAY_VARS)
4853  ARRAY *a;
4854 #endif
4855
4856   /* duplicate behavior of strchr(3) */
4857   t = skiparith (substr, ':');
4858   if (*t && *t == ':')
4859     *t = '\0';
4860   else
4861     t = (char *)0;
4862
4863   temp1 = expand_string_if_necessary (substr, Q_DOUBLE_QUOTES, expand_string);
4864   *e1p = evalexp (temp1, &expok);
4865   free (temp1);
4866   if (expok == 0)
4867     return (0);
4868
4869   len = -1;     /* paranoia */
4870   switch (vtype)
4871     {
4872     case VT_VARIABLE:
4873     case VT_ARRAYMEMBER:
4874       len = strlen (value);
4875       break;
4876     case VT_POSPARMS:
4877       len = number_of_args () + 1;
4878       break;
4879 #if defined (ARRAY_VARS)
4880     case VT_ARRAYVAR:
4881       a = (ARRAY *)value;
4882       /* For arrays, the first value deals with array indices. */
4883       len = array_max_index (a);        /* arrays index from 0 to n - 1 */
4884       break;
4885 #endif
4886     }
4887
4888   if (len == -1)        /* paranoia */
4889     return -1;
4890
4891   if (*e1p < 0)         /* negative offsets count from end */
4892     *e1p += len;
4893
4894   if (*e1p >= len || *e1p < 0)
4895     return (-1);
4896
4897 #if defined (ARRAY_VARS)
4898   /* For arrays, the second offset deals with the number of elements. */
4899   if (vtype == VT_ARRAYVAR)
4900     len = array_num_elements (a);
4901 #endif
4902
4903   if (t)
4904     {
4905       t++;
4906       temp2 = savestring (t);
4907       temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
4908       free (temp2);
4909       t[-1] = ':';
4910       *e2p = evalexp (temp1, &expok);
4911       free (temp1);
4912       if (expok == 0)
4913         return (0);
4914       if (*e2p < 0)
4915         {
4916           internal_error (_("%s: substring expression < 0"), t);
4917           return (0);
4918         }
4919 #if defined (ARRAY_VARS)
4920       /* In order to deal with sparse arrays, push the intelligence about how
4921          to deal with the number of elements desired down to the array-
4922          specific functions.  */
4923       if (vtype != VT_ARRAYVAR)
4924 #endif
4925         {
4926           *e2p += *e1p;         /* want E2 chars starting at E1 */
4927           if (*e2p > len)
4928             *e2p = len;
4929         }
4930     }
4931   else
4932     *e2p = len;
4933
4934   return (1);
4935 }
4936
4937 /* Return the type of variable specified by VARNAME (simple variable,
4938    positional param, or array variable).  Also return the value specified
4939    by VARNAME (value of a variable or a reference to an array element).
4940    If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
4941    characters in the value are quoted with CTLESC and takes appropriate
4942    steps.  For convenience, *VALP is set to the dequoted VALUE. */
4943 static int
4944 get_var_and_type (varname, value, quoted, varp, valp)
4945      char *varname, *value;
4946      int quoted;
4947      SHELL_VAR **varp;
4948      char **valp;
4949 {
4950   int vtype;
4951   char *temp;
4952 #if defined (ARRAY_VARS)
4953   SHELL_VAR *v;
4954 #endif
4955
4956   /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
4957   vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
4958   if (vtype == VT_POSPARMS && varname[0] == '*')
4959     vtype |= VT_STARSUB;
4960   *varp = (SHELL_VAR *)NULL;
4961
4962 #if defined (ARRAY_VARS)
4963   if (valid_array_reference (varname))
4964     {
4965       v = array_variable_part (varname, &temp, (int *)0);
4966       if (v && array_p (v))
4967         { /* [ */
4968           if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
4969             {
4970               vtype = VT_ARRAYVAR;
4971               if (temp[0] == '*')
4972                 vtype |= VT_STARSUB;
4973               *valp = (char *)array_cell (v);
4974             }
4975           else
4976             {
4977               vtype = VT_ARRAYMEMBER;
4978               *valp = array_value (varname, 1, (int *)NULL);
4979             }
4980           *varp = v;
4981         }
4982       else
4983         return -1;
4984     }
4985   else if ((v = find_variable (varname)) && array_p (v))
4986     {
4987       vtype = VT_ARRAYMEMBER;
4988       *varp = v;
4989       *valp = array_reference (array_cell (v), 0);
4990     }
4991   else
4992 #endif
4993 #if 1
4994     {
4995       if (value && vtype == VT_VARIABLE)
4996         {
4997           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
4998             *valp = dequote_string (value);
4999           else
5000             *valp = dequote_escapes (value);
5001         }
5002       else
5003         *valp = value;
5004     }
5005 #else
5006   *valp = (value && vtype == VT_VARIABLE) ? dequote_escapes (value) : value;
5007 #endif
5008
5009   return vtype;
5010 }
5011
5012 /******************************************************/
5013 /*                                                    */
5014 /* Functions to extract substrings of variable values */
5015 /*                                                    */
5016 /******************************************************/
5017
5018 #if defined (HANDLE_MULTIBYTE)
5019 /* Character-oriented rather than strictly byte-oriented substrings.  S and
5020    E, rather being strict indices into STRING, indicate character (possibly
5021    multibyte character) positions that require calculation.
5022    Used by the ${param:offset[:length]} expansion. */
5023 static char *
5024 mb_substring (string, s, e)
5025      char *string;
5026      int s, e;
5027 {
5028   char *tt;
5029   int start, stop, i, slen;
5030   DECLARE_MBSTATE;
5031
5032   start = 0;
5033   slen = STRLEN (string);
5034
5035   i = s;
5036   while (string[start] && i--)
5037     ADVANCE_CHAR (string, slen, start);
5038   stop = start;
5039   i = e - s;
5040   while (string[stop] && i--)
5041     ADVANCE_CHAR (string, slen, stop);
5042   tt = substring (string, start, stop);
5043   return tt;
5044 }
5045 #endif
5046   
5047 /* Process a variable substring expansion: ${name:e1[:e2]}.  If VARNAME
5048    is `@', use the positional parameters; otherwise, use the value of
5049    VARNAME.  If VARNAME is an array variable, use the array elements. */
5050
5051 static char *
5052 parameter_brace_substring (varname, value, substr, quoted)
5053      char *varname, *value, *substr;
5054      int quoted;
5055 {
5056   intmax_t e1, e2;
5057   int vtype, r, starsub;
5058   char *temp, *val, *tt;
5059   SHELL_VAR *v;
5060
5061   if (value == 0)
5062     return ((char *)NULL);
5063
5064   this_command_name = varname;
5065
5066   vtype = get_var_and_type (varname, value, quoted, &v, &val);
5067   if (vtype == -1)
5068     return ((char *)NULL);
5069
5070   starsub = vtype & VT_STARSUB;
5071   vtype &= ~VT_STARSUB;
5072
5073   r = verify_substring_values (val, substr, vtype, &e1, &e2);
5074   if (r <= 0)
5075     return ((r == 0) ? &expand_param_error : (char *)NULL);
5076
5077   switch (vtype)
5078     {
5079     case VT_VARIABLE:
5080     case VT_ARRAYMEMBER:
5081 #if defined (HANDLE_MULTIBYTE)
5082       if (MB_CUR_MAX > 1)
5083         tt = mb_substring (val, e1, e2);
5084       else
5085 #endif
5086       tt = substring (val, e1, e2);
5087
5088       if (vtype == VT_VARIABLE)
5089         FREE (val);
5090       if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5091         temp = quote_string (tt);
5092       else
5093         temp = tt ? quote_escapes (tt) : (char *)NULL;
5094       FREE (tt);
5095       break;
5096     case VT_POSPARMS:
5097       tt = pos_params (varname, e1, e2, quoted);
5098       if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5099         {
5100           temp = tt ? quote_escapes (tt) : (char *)NULL;
5101           FREE (tt);
5102         }
5103       else
5104         temp = tt;
5105       break;
5106 #if defined (ARRAY_VARS)
5107     case VT_ARRAYVAR:
5108       /* We want E2 to be the number of elements desired (arrays can be sparse,
5109          so verify_substring_values just returns the numbers specified and we
5110          rely on array_subrange to understand how to deal with them). */
5111       tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5112       if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5113         {
5114           temp = tt ? quote_escapes (tt) : (char *)NULL;
5115           FREE (tt);
5116         }
5117       else
5118         temp = tt;
5119       break;
5120 #endif
5121     default:
5122       temp = (char *)NULL;
5123     }
5124
5125   return temp;
5126 }
5127
5128 /****************************************************************/
5129 /*                                                              */
5130 /* Functions to perform pattern substitution on variable values */
5131 /*                                                              */
5132 /****************************************************************/
5133
5134 char *
5135 pat_subst (string, pat, rep, mflags)
5136      char *string, *pat, *rep;
5137      int mflags;
5138 {
5139   char *ret, *s, *e, *str;
5140   int rsize, rptr, l, replen, mtype;
5141
5142   mtype = mflags & MATCH_TYPEMASK;
5143
5144   /* Special cases:
5145    *    1.  A null pattern with mtype == MATCH_BEG means to prefix STRING
5146    *        with REP and return the result.
5147    *    2.  A null pattern with mtype == MATCH_END means to append REP to
5148    *        STRING and return the result.
5149    */
5150   if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5151     {
5152       replen = STRLEN (rep);
5153       l = strlen (string);
5154       ret = (char *)xmalloc (replen + l + 2);
5155       if (replen == 0)
5156         strcpy (ret, string);
5157       else if (mtype == MATCH_BEG)
5158         {
5159           strcpy (ret, rep);
5160           strcpy (ret + replen, string);
5161         }
5162       else
5163         {
5164           strcpy (ret, string);
5165           strcpy (ret + l, rep);
5166         }
5167       return (ret);
5168     }
5169
5170   ret = (char *)xmalloc (rsize = 64);
5171   ret[0] = '\0';
5172
5173   for (replen = STRLEN (rep), rptr = 0, str = string;;)
5174     {
5175       if (match_pattern (str, pat, mtype, &s, &e) == 0)
5176         break;
5177       l = s - str;
5178       RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5179
5180       /* OK, now copy the leading unmatched portion of the string (from
5181          str to s) to ret starting at rptr (the current offset).  Then copy
5182          the replacement string at ret + rptr + (s - str).  Increment
5183          rptr (if necessary) and str and go on. */
5184       if (l)
5185         {
5186           strncpy (ret + rptr, str, l);
5187           rptr += l;
5188         }
5189       if (replen)
5190         {
5191           strncpy (ret + rptr, rep, replen);
5192           rptr += replen;
5193         }
5194       str = e;          /* e == end of match */
5195
5196       if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
5197         break;
5198
5199       if (s == e)
5200         e++, str++;             /* avoid infinite recursion on zero-length match */
5201     }
5202
5203   /* Now copy the unmatched portion of the input string */
5204   if (*str)
5205     {
5206       RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
5207       strcpy (ret + rptr, str);
5208     }
5209   else
5210     ret[rptr] = '\0';
5211
5212   return ret;
5213 }
5214
5215 /* Do pattern match and replacement on the positional parameters. */
5216 static char *
5217 pos_params_pat_subst (string, pat, rep, mflags)
5218      char *string, *pat, *rep;
5219      int mflags;
5220 {
5221   WORD_LIST *save, *params;
5222   WORD_DESC *w;
5223   char *ret, *tt;
5224
5225   save = params = list_rest_of_args ();
5226   if (save == 0)
5227     return ((char *)NULL);
5228
5229   for ( ; params; params = params->next)
5230     {
5231       ret = pat_subst (params->word->word, pat, rep, mflags);
5232       w = make_bare_word (ret);
5233       dispose_word (params->word);
5234       params->word = w;
5235       FREE (ret);
5236     }
5237
5238   if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
5239     ret = string_list_dollar_star (quote_list (save));
5240   else
5241     ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
5242   dispose_words (save);
5243
5244   return (ret);
5245 }
5246
5247 /* Perform pattern substitution on VALUE, which is the expansion of
5248    VARNAME.  PATSUB is an expression supplying the pattern to match
5249    and the string to substitute.  QUOTED is a flags word containing
5250    the type of quoting currently in effect. */
5251 static char *
5252 parameter_brace_patsub (varname, value, patsub, quoted)
5253      char *varname, *value, *patsub;
5254      int quoted;
5255 {
5256   int vtype, mflags, starsub;
5257   char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
5258   SHELL_VAR *v;
5259
5260   if (value == 0)
5261     return ((char *)NULL);
5262
5263   this_command_name = varname;
5264
5265   vtype = get_var_and_type (varname, value, quoted, &v, &val);
5266   if (vtype == -1)
5267     return ((char *)NULL);
5268
5269   starsub = vtype & VT_STARSUB;
5270   vtype &= ~VT_STARSUB;
5271
5272   mflags = 0;
5273   if (*patsub == '/')
5274     {
5275       mflags |= MATCH_GLOBREP;
5276       patsub++;
5277     }
5278
5279   /* Malloc this because expand_string_if_necessary or one of the expansion
5280      functions in its call chain may free it on a substitution error. */
5281   lpatsub = savestring (patsub);
5282
5283   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5284     mflags |= MATCH_QUOTED;
5285
5286   if (starsub)
5287     mflags |= MATCH_STARSUB;
5288
5289   if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
5290     *rep++ = '\0';
5291   else
5292     rep = (char *)NULL;
5293
5294   if (rep && *rep == '\0')
5295     rep = (char *)NULL;
5296
5297 #if 0
5298   /* Expand PAT and REP for command, variable and parameter, arithmetic,
5299      and process substitution.  Also perform quote removal.  Do not
5300      perform word splitting or filename generation. */
5301   pat = expand_string_if_necessary (lpatsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit);
5302 #else
5303   /* Perform the same expansions on the pattern as performed by the
5304      pattern removal expansions. */
5305   pat = getpattern (lpatsub, quoted, 1);
5306 #endif
5307
5308   if (rep)
5309     {
5310       if ((mflags & MATCH_QUOTED) == 0)
5311         rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
5312       else
5313         rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
5314     }
5315
5316   p = pat;
5317   if (pat && pat[0] == '#')
5318     {
5319       mflags |= MATCH_BEG;
5320       p++;
5321     }
5322   else if (pat && pat[0] == '%')
5323     {
5324       mflags |= MATCH_END;
5325       p++;
5326     }
5327   else
5328     mflags |= MATCH_ANY;
5329
5330   /* OK, we now want to substitute REP for PAT in VAL.  If
5331      flags & MATCH_GLOBREP is non-zero, the substitution is done
5332      everywhere, otherwise only the first occurrence of PAT is
5333      replaced.  The pattern matching code doesn't understand
5334      CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
5335      values passed in (VT_VARIABLE) so the pattern substitution
5336      code works right.  We need to requote special chars after
5337      we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
5338      other cases if QUOTED == 0, since the posparams and arrays
5339      indexed by * or @ do special things when QUOTED != 0. */
5340
5341   switch (vtype)
5342     {
5343     case VT_VARIABLE:
5344     case VT_ARRAYMEMBER:
5345       temp = pat_subst (val, p, rep, mflags);
5346       if (vtype == VT_VARIABLE)
5347         FREE (val);
5348       if (temp)
5349         {
5350           tt = quote_escapes (temp);
5351           free (temp);
5352           temp = tt;
5353         }
5354       break;
5355     case VT_POSPARMS:
5356       temp = pos_params_pat_subst (val, p, rep, mflags);
5357       if (temp && (mflags & MATCH_QUOTED) == 0)
5358         {
5359           tt = quote_escapes (temp);
5360           free (temp);
5361           temp = tt;
5362         }
5363       break;
5364 #if defined (ARRAY_VARS)
5365     case VT_ARRAYVAR:
5366       temp = array_patsub (array_cell (v), p, rep, mflags);
5367       if (temp && (mflags & MATCH_QUOTED) == 0)
5368         {
5369           tt = quote_escapes (temp);
5370           free (temp);
5371           temp = tt;
5372         }
5373       break;
5374 #endif
5375     }
5376
5377   FREE (pat);
5378   FREE (rep);
5379   free (lpatsub);
5380
5381   return temp;
5382 }
5383
5384 /****************************************************************/
5385 /*                                                              */
5386 /*      Functions to perform parameter expansion on a string    */
5387 /*                                                              */
5388 /****************************************************************/
5389
5390 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
5391 static char *
5392 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
5393      char *string;
5394      int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
5395 {
5396   int check_nullness, var_is_set, var_is_null, var_is_special;
5397   int want_substring, want_indir, want_patsub;
5398   char *name, *value, *temp, *temp1;
5399   int t_index, sindex, c;
5400   intmax_t number;
5401
5402   value = (char *)NULL;
5403   var_is_set = var_is_null = var_is_special = check_nullness = 0;
5404   want_substring = want_indir = want_patsub = 0;
5405
5406   sindex = *indexp;
5407   t_index = ++sindex;
5408   name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
5409
5410   /* If the name really consists of a special variable, then make sure
5411      that we have the entire name.  We don't allow indirect references
5412      to special variables except `#', `?', `@' and `*'. */
5413   if ((sindex == t_index &&
5414         (string[t_index] == '-' ||
5415          string[t_index] == '?' ||
5416          string[t_index] == '#')) ||
5417       (sindex == t_index - 1 && string[sindex] == '!' &&
5418         (string[t_index] == '#' ||
5419          string[t_index] == '?' ||
5420          string[t_index] == '@' ||
5421          string[t_index] == '*')))
5422     {
5423       t_index++;
5424       free (name);
5425       temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
5426       name = (char *)xmalloc (3 + (strlen (temp1)));
5427       *name = string[sindex];
5428       if (string[sindex] == '!')
5429         {
5430           /* indirect reference of $#, $?, $@, or $* */
5431           name[1] = string[sindex + 1];
5432           strcpy (name + 2, temp1);
5433         }
5434       else      
5435         strcpy (name + 1, temp1);
5436       free (temp1);
5437     }
5438   sindex = t_index;
5439
5440   /* Find out what character ended the variable name.  Then
5441      do the appropriate thing. */
5442   if (c = string[sindex])
5443     sindex++;
5444
5445   /* If c is followed by one of the valid parameter expansion
5446      characters, move past it as normal.  If not, assume that
5447      a substring specification is being given, and do not move
5448      past it. */
5449   if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
5450     {
5451       check_nullness++;
5452       if (c = string[sindex])
5453         sindex++;
5454     }
5455   else if (c == ':' && string[sindex] != RBRACE)
5456     want_substring = 1;
5457   else if (c == '/' && string[sindex] != RBRACE)
5458     want_patsub = 1;
5459
5460   /* Catch the valid and invalid brace expressions that made it through the
5461      tests above. */
5462   /* ${#-} is a valid expansion and means to take the length of $-.
5463      Similarly for ${#?} and ${##}... */
5464   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
5465         VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
5466     {
5467       name = (char *)xrealloc (name, 3);
5468       name[1] = c;
5469       name[2] = '\0';
5470       c = string[sindex++];
5471     }
5472
5473   /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
5474   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
5475         member (c, "%:=+/") && string[sindex] == RBRACE)
5476     {
5477       temp = (char *)NULL;
5478       goto bad_substitution;
5479     }
5480
5481   /* Indirect expansion begins with a `!'.  A valid indirect expansion is
5482      either a variable name, one of the positional parameters or a special
5483      variable that expands to one of the positional parameters. */
5484   want_indir = *name == '!' &&
5485     (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
5486                                         || VALID_INDIR_PARAM (name[1]));
5487
5488   /* Determine the value of this variable. */
5489
5490   /* Check for special variables, directly referenced. */
5491   if (SPECIAL_VAR (name, want_indir))
5492     var_is_special++;
5493
5494   /* Check for special expansion things, like the length of a parameter */
5495   if (*name == '#' && name[1])
5496     {
5497       /* If we are not pointing at the character just after the
5498          closing brace, then we haven't gotten all of the name.
5499          Since it begins with a special character, this is a bad
5500          substitution.  Also check NAME for validity before trying
5501          to go on. */
5502       if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
5503         {
5504           temp = (char *)NULL;
5505           goto bad_substitution;
5506         }
5507
5508       number = parameter_brace_expand_length (name);
5509       free (name);
5510
5511       *indexp = sindex;
5512       return ((number < 0) ? &expand_param_error : itos (number));
5513     }
5514
5515   /* ${@} is identical to $@. */
5516   if (name[0] == '@' && name[1] == '\0')
5517     {
5518       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5519         *quoted_dollar_atp = 1;
5520
5521       if (contains_dollar_at)
5522         *contains_dollar_at = 1;
5523     }
5524
5525   /* Process ${!PREFIX*} expansion. */
5526   if (want_indir && string[sindex - 1] == RBRACE &&
5527       (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
5528       legal_variable_starter ((unsigned char) name[1]))
5529     {
5530       char **x;
5531       WORD_LIST *xlist;
5532
5533       temp1 = savestring (name + 1);
5534       number = strlen (temp1);
5535       temp1[number - 1] = '\0';
5536       x = all_variables_matching_prefix (temp1);
5537       xlist = strvec_to_word_list (x, 0, 0);
5538       if (string[sindex - 2] == '*')
5539         temp = string_list_dollar_star (xlist);
5540       else
5541         {
5542           temp = string_list_dollar_at (xlist, quoted);
5543           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5544             *quoted_dollar_atp = 1;
5545           if (contains_dollar_at)
5546             *contains_dollar_at = 1;
5547         }
5548       free (x);
5549       free (xlist);
5550       free (temp1);
5551       *indexp = sindex;
5552       return (temp);
5553     }
5554
5555 #if defined (ARRAY_VARS)      
5556   /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
5557   if (want_indir && string[sindex - 1] == RBRACE &&
5558       string[sindex - 2] == ']' && valid_array_reference (name+1))
5559     {
5560       char *x, *x1;
5561
5562       temp1 = savestring (name + 1);
5563       x = array_variable_name (temp1, &x1, (int *)0);   /* [ */
5564       FREE (x);
5565       if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
5566         {
5567           temp = array_keys (temp1, quoted);
5568           if (x1[0] == '@')
5569             {
5570               if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5571                 *quoted_dollar_atp = 1;
5572               if (contains_dollar_at)
5573                 *contains_dollar_at = 1;
5574             }       
5575
5576           free (temp1);
5577           *indexp = sindex;
5578           return (temp);
5579         }
5580
5581       free (temp1);
5582     }
5583 #endif /* ARRAY_VARS */
5584       
5585   /* Make sure that NAME is valid before trying to go on. */
5586   if (valid_brace_expansion_word (want_indir ? name + 1 : name,
5587                                         var_is_special) == 0)
5588     {
5589       temp = (char *)NULL;
5590       goto bad_substitution;
5591     }
5592
5593   if (want_indir)
5594     temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
5595   else
5596     temp = parameter_brace_expand_word (name, var_is_special, quoted);
5597
5598 #if defined (ARRAY_VARS)
5599   if (valid_array_reference (name))
5600     chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
5601 #endif
5602
5603   var_is_set = temp != (char *)0;
5604   var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
5605
5606   /* Get the rest of the stuff inside the braces. */
5607   if (c && c != RBRACE)
5608     {
5609       /* Extract the contents of the ${ ... } expansion
5610          according to the Posix.2 rules. */
5611       value = extract_dollar_brace_string (string, &sindex, quoted, 0);
5612       if (string[sindex] == RBRACE)
5613         sindex++;
5614       else
5615         goto bad_substitution;
5616     }
5617   else
5618     value = (char *)NULL;
5619
5620   *indexp = sindex;
5621
5622   /* If this is a substring spec, process it and add the result. */
5623   if (want_substring)
5624     {
5625       temp1 = parameter_brace_substring (name, temp, value, quoted);
5626       FREE (name);
5627       FREE (value);
5628       FREE (temp);
5629       return (temp1);
5630     }
5631   else if (want_patsub)
5632     {
5633       temp1 = parameter_brace_patsub (name, temp, value, quoted);
5634       FREE (name);
5635       FREE (value);
5636       FREE (temp);
5637       return (temp1);
5638     }
5639
5640   /* Do the right thing based on which character ended the variable name. */
5641   switch (c)
5642     {
5643     default:
5644     case '\0':
5645     bad_substitution:
5646       report_error (_("%s: bad substitution"), string ? string : "??");
5647       FREE (value);
5648       FREE (temp);
5649       free (name);
5650       return &expand_param_error;
5651
5652     case RBRACE:
5653       if (var_is_set == 0 && unbound_vars_is_error)
5654         {
5655           err_unboundvar (name);
5656           FREE (value);
5657           FREE (temp);
5658           free (name);
5659           last_command_exit_value = EXECUTION_FAILURE;
5660           return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5661         }
5662       break;
5663
5664     case '#':   /* ${param#[#]pattern} */
5665     case '%':   /* ${param%[%]pattern} */
5666       if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
5667         {
5668           FREE (value);
5669           break;
5670         }
5671       temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
5672       free (temp);
5673       free (value);
5674       temp = temp1;
5675       break;
5676
5677     case '-':
5678     case '=':
5679     case '?':
5680     case '+':
5681       if (var_is_set && var_is_null == 0)
5682         {
5683           /* If the operator is `+', we don't want the value of the named
5684              variable for anything, just the value of the right hand side. */
5685
5686           if (c == '+')
5687             {
5688               /* XXX -- if we're double-quoted and the named variable is "$@",
5689                         we want to turn off any special handling of "$@" --
5690                         we're not using it, so whatever is on the rhs applies. */
5691               if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5692                 *quoted_dollar_atp = 0;
5693               if (contains_dollar_at)
5694                 *contains_dollar_at = 0;
5695
5696               FREE (temp);
5697               if (value)
5698                 {
5699                   temp = parameter_brace_expand_rhs (name, value, c,
5700                                                      quoted,
5701                                                      quoted_dollar_atp,
5702                                                      contains_dollar_at);
5703                   free (value);
5704                 }
5705               else
5706                 temp = (char *)NULL;
5707             }
5708           else
5709             {
5710               FREE (value);
5711             }
5712           /* Otherwise do nothing; just use the value in TEMP. */
5713         }
5714       else      /* VAR not set or VAR is NULL. */
5715         {
5716           FREE (temp);
5717           temp = (char *)NULL;
5718           if (c == '=' && var_is_special)
5719             {
5720               report_error (_("$%s: cannot assign in this way"), name);
5721               free (name);
5722               free (value);
5723               return &expand_param_error;
5724             }
5725           else if (c == '?')
5726             {
5727               parameter_brace_expand_error (name, value);
5728               return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5729             }
5730           else if (c != '+')
5731             {
5732               /* XXX -- if we're double-quoted and the named variable is "$@",
5733                         we want to turn off any special handling of "$@" --
5734                         we're not using it, so whatever is on the rhs applies. */
5735               if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5736                 *quoted_dollar_atp = 0;
5737               if (contains_dollar_at)
5738                 *contains_dollar_at = 0;
5739
5740               temp = parameter_brace_expand_rhs (name, value, c, quoted,
5741                                                  quoted_dollar_atp,
5742                                                  contains_dollar_at);
5743             }
5744           free (value);
5745         }
5746
5747       break;
5748     }
5749   free (name);
5750   return (temp);
5751 }
5752
5753 /* Expand a single ${xxx} expansion.  The braces are optional.  When
5754    the braces are used, parameter_brace_expand() does the work,
5755    possibly calling param_expand recursively. */
5756 static char *
5757 param_expand (string, sindex, quoted, expanded_something,
5758               contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
5759               pflags)
5760      char *string;
5761      int *sindex, quoted, *expanded_something, *contains_dollar_at;
5762      int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
5763 {
5764   char *temp, *temp1, uerror[3];
5765   int zindex, t_index, expok;
5766   unsigned char c;
5767   intmax_t number;
5768   SHELL_VAR *var;
5769   WORD_LIST *list;
5770
5771   zindex = *sindex;
5772   c = string[++zindex];
5773
5774   temp = (char *)NULL;
5775
5776   /* Do simple cases first. Switch on what follows '$'. */
5777   switch (c)
5778     {
5779     /* $0 .. $9? */
5780     case '0':
5781     case '1':
5782     case '2':
5783     case '3':
5784     case '4':
5785     case '5':
5786     case '6':
5787     case '7':
5788     case '8':
5789     case '9':
5790       temp1 = dollar_vars[TODIGIT (c)];
5791       if (unbound_vars_is_error && temp1 == (char *)NULL)
5792         {
5793           uerror[0] = '$';
5794           uerror[1] = c;
5795           uerror[2] = '\0';
5796           err_unboundvar (uerror);
5797           last_command_exit_value = EXECUTION_FAILURE;
5798           return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5799         }
5800 #if 1
5801       if (temp1)
5802         temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
5803                   ? quote_string (temp1)
5804                   : quote_escapes (temp1);
5805       else
5806         temp = (char *)NULL;
5807 #else
5808       temp = temp1 ? quote_escapes (temp1) : (char *)NULL;
5809 #endif
5810       break;
5811
5812     /* $$ -- pid of the invoking shell. */
5813     case '$':
5814       temp = itos (dollar_dollar_pid);
5815       break;
5816
5817     /* $# -- number of positional parameters. */
5818     case '#':
5819       temp = itos (number_of_args ());
5820       break;
5821
5822     /* $? -- return value of the last synchronous command. */
5823     case '?':
5824       temp = itos (last_command_exit_value);
5825       break;
5826
5827     /* $- -- flags supplied to the shell on invocation or by `set'. */
5828     case '-':
5829       temp = which_set_flags ();
5830       break;
5831
5832       /* $! -- Pid of the last asynchronous command. */
5833     case '!':
5834       /* If no asynchronous pids have been created, expand to nothing.
5835          If `set -u' has been executed, and no async processes have
5836          been created, this is an expansion error. */
5837       if (last_asynchronous_pid == NO_PID)
5838         {
5839           if (expanded_something)
5840             *expanded_something = 0;
5841           temp = (char *)NULL;
5842           if (unbound_vars_is_error)
5843             {
5844               uerror[0] = '$';
5845               uerror[1] = c;
5846               uerror[2] = '\0';
5847               err_unboundvar (uerror);
5848               last_command_exit_value = EXECUTION_FAILURE;
5849               return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5850             }
5851         }
5852       else
5853         temp = itos (last_asynchronous_pid);
5854       break;
5855
5856     /* The only difference between this and $@ is when the arg is quoted. */
5857     case '*':           /* `$*' */
5858       list = list_rest_of_args ();
5859
5860       /* If there are no command-line arguments, this should just
5861          disappear if there are other characters in the expansion,
5862          even if it's quoted. */
5863       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
5864         temp = (char *)NULL;
5865       else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5866         {
5867           /* If we have "$*" we want to make a string of the positional
5868              parameters, separated by the first character of $IFS, and
5869              quote the whole string, including the separators.  If IFS
5870              is unset, the parameters are separated by ' '; if $IFS is
5871              null, the parameters are concatenated. */
5872 #if 0
5873           temp = string_list_dollar_star (list);
5874 #else
5875           temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
5876 #endif
5877           temp1 = quote_string (temp);
5878           free (temp);
5879           temp = temp1;
5880         }
5881       else
5882         {
5883           /* If the $* is not quoted it is identical to $@ */
5884           temp = string_list_dollar_at (list, quoted);
5885           if (expand_no_split_dollar_star == 0 && contains_dollar_at)
5886             *contains_dollar_at = 1;
5887         }
5888
5889       dispose_words (list);
5890       break;
5891
5892     /* When we have "$@" what we want is "$1" "$2" "$3" ... This
5893        means that we have to turn quoting off after we split into
5894        the individually quoted arguments so that the final split
5895        on the first character of $IFS is still done.  */
5896     case '@':           /* `$@' */
5897       list = list_rest_of_args ();
5898
5899       /* We want to flag the fact that we saw this.  We can't turn
5900          off quoting entirely, because other characters in the
5901          string might need it (consider "\"$@\""), but we need some
5902          way to signal that the final split on the first character
5903          of $IFS should be done, even though QUOTED is 1. */
5904       if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
5905         *quoted_dollar_at_p = 1;
5906       if (contains_dollar_at)
5907         *contains_dollar_at = 1;
5908
5909       /* We want to separate the positional parameters with the first
5910          character of $IFS in case $IFS is something other than a space.
5911          We also want to make sure that splitting is done no matter what --
5912          according to POSIX.2, this expands to a list of the positional
5913          parameters no matter what IFS is set to. */
5914       temp = string_list_dollar_at (list, quoted);
5915
5916       dispose_words (list);
5917       break;
5918
5919     case LBRACE:
5920       temp = parameter_brace_expand (string, &zindex, quoted,
5921                                      quoted_dollar_at_p,
5922                                      contains_dollar_at);
5923       if (temp == &expand_param_error || temp == &expand_param_fatal)
5924         return (temp);
5925
5926       /* XXX */
5927       /* Quoted nulls should be removed if there is anything else
5928          in the string. */
5929       /* Note that we saw the quoted null so we can add one back at
5930          the end of this function if there are no other characters
5931          in the string, discard TEMP, and go on.  The exception to
5932          this is when we have "${@}" and $1 is '', since $@ needs
5933          special handling. */
5934       if (temp && QUOTED_NULL (temp))
5935         {
5936           if (had_quoted_null_p)
5937             *had_quoted_null_p = 1;
5938           if (*quoted_dollar_at_p == 0)
5939             {
5940               free (temp);
5941               temp = (char *)NULL;
5942             }
5943             
5944         }
5945
5946       goto return0;
5947
5948     /* Do command or arithmetic substitution. */
5949     case LPAREN:
5950       /* We have to extract the contents of this paren substitution. */
5951       t_index = zindex + 1;
5952       temp = extract_command_subst (string, &t_index);
5953       zindex = t_index;
5954
5955       /* For Posix.2-style `$(( ))' arithmetic substitution,
5956          extract the expression and pass it to the evaluator. */
5957       if (temp && *temp == LPAREN)
5958         {
5959           char *temp2;
5960           temp1 = temp + 1;
5961           temp2 = savestring (temp1);
5962           t_index = strlen (temp2) - 1;
5963
5964           if (temp2[t_index] != RPAREN)
5965             {
5966               free (temp2);
5967               goto comsub;
5968             }
5969
5970           /* Cut off ending `)' */
5971           temp2[t_index] = '\0';
5972
5973           /* Expand variables found inside the expression. */
5974           temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
5975           free (temp2);
5976
5977 arithsub:
5978           /* No error messages. */
5979           this_command_name = (char *)NULL;
5980           number = evalexp (temp1, &expok);
5981           free (temp);
5982           free (temp1);
5983           if (expok == 0)
5984             {
5985               if (interactive_shell == 0 && posixly_correct)
5986                 {
5987                   last_command_exit_value = EXECUTION_FAILURE;
5988                   return (&expand_param_fatal);
5989                 }
5990               else
5991                 return (&expand_param_error);
5992             }
5993           temp = itos (number);
5994           break;
5995         }
5996
5997 comsub:
5998       if (pflags & PF_NOCOMSUB)
5999         /* we need zindex+1 because string[zindex] == RPAREN */
6000         temp1 = substring (string, *sindex, zindex+1);
6001       else
6002         temp1 = command_substitute (temp, quoted);
6003       FREE (temp);
6004       temp = temp1;
6005       break;
6006
6007     /* Do POSIX.2d9-style arithmetic substitution.  This will probably go
6008        away in a future bash release. */
6009     case '[':
6010       /* Extract the contents of this arithmetic substitution. */
6011       t_index = zindex + 1;
6012       temp = extract_arithmetic_subst (string, &t_index);
6013       zindex = t_index;
6014
6015        /* Do initial variable expansion. */
6016       temp1 = expand_string_if_necessary (temp, Q_DOUBLE_QUOTES, expand_string);
6017
6018       goto arithsub;
6019
6020     default:
6021       /* Find the variable in VARIABLE_LIST. */
6022       temp = (char *)NULL;
6023
6024       for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
6025         ;
6026       temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
6027
6028       /* If this isn't a variable name, then just output the `$'. */
6029       if (temp1 == 0 || *temp1 == '\0')
6030         {
6031           FREE (temp1);
6032           temp = (char *)xmalloc (2);
6033           temp[0] = '$';
6034           temp[1] = '\0';
6035           if (expanded_something)
6036             *expanded_something = 0;
6037           goto return0;
6038         }
6039
6040       /* If the variable exists, return its value cell. */
6041       var = find_variable (temp1);
6042
6043       if (var && invisible_p (var) == 0 && var_isset (var))
6044         {
6045 #if defined (ARRAY_VARS)
6046           if (array_p (var))
6047             {
6048               temp = array_reference (array_cell (var), 0);
6049               if (temp)
6050                 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6051                           ? quote_string (temp)
6052                           : quote_escapes (temp);
6053               else if (unbound_vars_is_error)
6054                 goto unbound_variable;
6055             }
6056           else
6057 #endif
6058             {
6059               temp = value_cell (var);
6060
6061               temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6062                         ? quote_string (temp)
6063                         : quote_escapes (temp);
6064             }
6065
6066           free (temp1);
6067
6068           goto return0;
6069         }
6070
6071       temp = (char *)NULL;
6072
6073 unbound_variable:
6074       if (unbound_vars_is_error)
6075         err_unboundvar (temp1);
6076       else
6077         {
6078           free (temp1);
6079           goto return0;
6080         }
6081
6082       free (temp1);
6083       last_command_exit_value = EXECUTION_FAILURE;
6084       return ((unbound_vars_is_error && interactive_shell == 0)
6085                 ? &expand_param_fatal
6086                 : &expand_param_error);
6087     }
6088
6089   if (string[zindex])
6090     zindex++;
6091
6092 return0:
6093   *sindex = zindex;
6094   return (temp);
6095 }
6096
6097 /* Make a word list which is the result of parameter and variable
6098    expansion, command substitution, arithmetic substitution, and
6099    quote removal of WORD.  Return a pointer to a WORD_LIST which is
6100    the result of the expansion.  If WORD contains a null word, the
6101    word list returned is also null.
6102
6103    QUOTED contains flag values defined in shell.h.
6104
6105    ISEXP is used to tell expand_word_internal that the word should be
6106    treated as the result of an expansion.  This has implications for
6107    how IFS characters in the word are treated.
6108
6109    CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
6110    they point to an integer value which receives information about expansion.
6111    CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
6112    EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
6113    else zero.
6114
6115    This only does word splitting in the case of $@ expansion.  In that
6116    case, we split on ' '. */
6117
6118 /* Values for the local variable quoted_state. */
6119 #define UNQUOTED         0
6120 #define PARTIALLY_QUOTED 1
6121 #define WHOLLY_QUOTED    2
6122
6123 static WORD_LIST *
6124 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
6125      WORD_DESC *word;
6126      int quoted, isexp;
6127      int *contains_dollar_at;
6128      int *expanded_something;
6129 {
6130   WORD_LIST *list;
6131   WORD_DESC *tword;
6132
6133   /* The intermediate string that we build while expanding. */
6134   char *istring;
6135
6136   /* The current size of the above object. */
6137   int istring_size;
6138
6139   /* Index into ISTRING. */
6140   int istring_index;
6141
6142   /* Temporary string storage. */
6143   char *temp, *temp1;
6144
6145   /* The text of WORD. */
6146   register char *string;
6147
6148   /* The size of STRING. */
6149   size_t string_size;
6150
6151   /* The index into STRING. */
6152   int sindex;
6153
6154   /* This gets 1 if we see a $@ while quoted. */
6155   int quoted_dollar_at;
6156
6157   /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
6158      whether WORD contains no quoting characters, a partially quoted
6159      string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
6160   int quoted_state;
6161
6162   int had_quoted_null;
6163   int has_dollar_at;
6164   int tflag;
6165
6166   register unsigned char c;     /* Current character. */
6167   int t_index;                  /* For calls to string_extract_xxx. */
6168
6169   char twochars[2];
6170
6171   DECLARE_MBSTATE;
6172
6173   istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
6174   istring[istring_index = 0] = '\0';
6175   quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
6176   quoted_state = UNQUOTED;
6177
6178   string = word->word;
6179   if (string == 0)
6180     goto finished_with_string;
6181   string_size = strlen (string);
6182
6183   if (contains_dollar_at)
6184     *contains_dollar_at = 0;
6185
6186   /* Begin the expansion. */
6187
6188   for (sindex = 0; ;)
6189     {
6190       c = string[sindex];
6191
6192       /* Case on toplevel character. */
6193       switch (c)
6194         {
6195         case '\0':
6196           goto finished_with_string;
6197
6198         case CTLESC:
6199           sindex++;
6200 #if HANDLE_MULTIBYTE
6201           if (MB_CUR_MAX > 1 && string[sindex])
6202             {
6203               SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
6204             }
6205           else
6206 #endif
6207             {
6208               temp = (char *)xmalloc (3);
6209               temp[0] = CTLESC;
6210               temp[1] = c = string[sindex];
6211               temp[2] = '\0';
6212             }
6213
6214 dollar_add_string:
6215           if (string[sindex])
6216             sindex++;
6217
6218 add_string:
6219           if (temp)
6220             {
6221               istring = sub_append_string (temp, istring, &istring_index, &istring_size);
6222               temp = (char *)0;
6223             }
6224
6225           break;
6226
6227 #if defined (PROCESS_SUBSTITUTION)
6228           /* Process substitution. */
6229         case '<':
6230         case '>':
6231           {
6232             if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
6233               {
6234                 sindex--;       /* add_character: label increments sindex */
6235                 goto add_character;
6236               }
6237             else
6238               t_index = sindex + 1; /* skip past both '<' and LPAREN */
6239
6240             temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
6241             sindex = t_index;
6242
6243             /* If the process substitution specification is `<()', we want to
6244                open the pipe for writing in the child and produce output; if
6245                it is `>()', we want to open the pipe for reading in the child
6246                and consume input. */
6247             temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
6248
6249             FREE (temp1);
6250
6251             goto dollar_add_string;
6252           }
6253 #endif /* PROCESS_SUBSTITUTION */
6254
6255         case '$':
6256           if (expanded_something)
6257             *expanded_something = 1;
6258
6259           has_dollar_at = 0;
6260           temp = param_expand (string, &sindex, quoted, expanded_something,
6261                                &has_dollar_at, &quoted_dollar_at,
6262                                &had_quoted_null,
6263                                (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
6264
6265           if (temp == &expand_param_error || temp == &expand_param_fatal)
6266             {
6267               free (string);
6268               free (istring);
6269               return ((temp == &expand_param_error) ? &expand_word_error
6270                                                     : &expand_word_fatal);
6271             }
6272           if (contains_dollar_at && has_dollar_at)
6273             *contains_dollar_at = 1;
6274           goto add_string;
6275           break;
6276
6277         case '`':               /* Backquoted command substitution. */
6278           {
6279             t_index = sindex++;
6280
6281             if (expanded_something)
6282               *expanded_something = 1;
6283
6284             temp = string_extract (string, &sindex, "`", 0);
6285             if (word->flags & W_NOCOMSUB)
6286               /* sindex + 1 because string[sindex] == '`' */
6287               temp1 = substring (string, t_index, sindex + 1);
6288             else
6289               {
6290                 de_backslash (temp);
6291                 temp1 = command_substitute (temp, quoted);
6292               }
6293             FREE (temp);
6294             temp = temp1;
6295             goto dollar_add_string;
6296           }
6297
6298         case '\\':
6299           if (string[sindex + 1] == '\n')
6300             {
6301               sindex += 2;
6302               continue;
6303             }
6304
6305           c = string[++sindex];
6306
6307           if (quoted & Q_HERE_DOCUMENT)
6308             tflag = CBSHDOC;
6309           else if (quoted & Q_DOUBLE_QUOTES)
6310             tflag = CBSDQUOTE;
6311           else
6312             tflag = 0;
6313
6314           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
6315             {
6316               SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
6317             }
6318           else if (c == 0)
6319             {
6320               c = CTLNUL;
6321               sindex--;         /* add_character: label increments sindex */
6322               goto add_character;
6323             }
6324           else
6325             {
6326               SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
6327             }
6328
6329           sindex++;
6330 add_twochars:
6331           /* BEFORE jumping here, we need to increment sindex if appropriate */
6332           RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
6333                                   DEFAULT_ARRAY_SIZE);
6334           istring[istring_index++] = twochars[0];
6335           istring[istring_index++] = twochars[1];
6336           istring[istring_index] = '\0';
6337
6338           break;
6339
6340         case '"':
6341 #if 0
6342           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_PATQUOTE))
6343 #else
6344           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6345 #endif
6346             goto add_character;
6347
6348           t_index = ++sindex;
6349           temp = string_extract_double_quoted (string, &sindex, 0);
6350
6351           /* If the quotes surrounded the entire string, then the
6352              whole word was quoted. */
6353           quoted_state = (t_index == 1 && string[sindex] == '\0')
6354                             ? WHOLLY_QUOTED
6355                             : PARTIALLY_QUOTED;
6356
6357           if (temp && *temp)
6358             {
6359               tword = make_word (temp);         /* XXX */
6360               free (temp);
6361               temp = (char *)NULL;
6362
6363               has_dollar_at = 0;
6364               list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
6365
6366               if (list == &expand_word_error || list == &expand_word_fatal)
6367                 {
6368                   free (istring);
6369                   free (string);
6370                   /* expand_word_internal has already freed temp_word->word
6371                      for us because of the way it prints error messages. */
6372                   tword->word = (char *)NULL;
6373                   dispose_word (tword);
6374                   return list;
6375                 }
6376
6377               dispose_word (tword);
6378
6379               /* "$@" (a double-quoted dollar-at) expands into nothing,
6380                  not even a NULL word, when there are no positional
6381                  parameters. */
6382               if (list == 0 && has_dollar_at)
6383                 {
6384                   quoted_dollar_at++;
6385                   break;
6386                 }
6387
6388               /* If we get "$@", we know we have expanded something, so we
6389                  need to remember it for the final split on $IFS.  This is
6390                  a special case; it's the only case where a quoted string
6391                  can expand into more than one word.  It's going to come back
6392                  from the above call to expand_word_internal as a list with
6393                  a single word, in which all characters are quoted and
6394                  separated by blanks.  What we want to do is to turn it back
6395                  into a list for the next piece of code. */
6396               if (list)
6397                 dequote_list (list);
6398
6399               if (has_dollar_at)
6400                 {
6401                   quoted_dollar_at++;
6402                   if (contains_dollar_at)
6403                     *contains_dollar_at = 1;
6404                   if (expanded_something)
6405                     *expanded_something = 1;
6406                 }
6407             }
6408           else
6409             {
6410               /* What we have is "".  This is a minor optimization. */
6411               FREE (temp);
6412               list = (WORD_LIST *)NULL;
6413             }
6414
6415           /* The code above *might* return a list (consider the case of "$@",
6416              where it returns "$1", "$2", etc.).  We can't throw away the
6417              rest of the list, and we have to make sure each word gets added
6418              as quoted.  We test on tresult->next:  if it is non-NULL, we
6419              quote the whole list, save it to a string with string_list, and
6420              add that string. We don't need to quote the results of this
6421              (and it would be wrong, since that would quote the separators
6422              as well), so we go directly to add_string. */
6423           if (list)
6424             {
6425               if (list->next)
6426                 {
6427                   /* Testing quoted_dollar_at makes sure that "$@" is
6428                      split correctly when $IFS does not contain a space. */
6429                   temp = quoted_dollar_at
6430                                 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
6431                                 : string_list (quote_list (list));
6432                   dispose_words (list);
6433                   goto add_string;
6434                 }
6435               else
6436                 {
6437                   temp = savestring (list->word->word);
6438                   dispose_words (list);
6439 #if 1
6440                   /* If the string is not a quoted null string, we want
6441                      to remove any embedded unquoted CTLNUL characters.
6442                      We do not want to turn quoted null strings back into
6443                      the empty string, though.  We do this because we
6444                      want to remove any quoted nulls from expansions that
6445                      contain other characters.  For example, if we have
6446                      x"$*"y or "x$*y" and there are no positional parameters,
6447                      the $* should expand into nothing. */
6448                   /* HOWEVER, this fails if the string contains a literal
6449                      CTLNUL or CTLNUL is contained in the (non-null) expansion
6450                      of some variable.  I'm not sure what to do about this
6451                      yet.  There has to be some way to indicate the difference
6452                      between the two.  An auxiliary data structure might be
6453                      necessary. */
6454                   if (QUOTED_NULL (temp) == 0)
6455                     remove_quoted_nulls (temp); /* XXX */
6456 #endif
6457                 }
6458             }
6459           else
6460             temp = (char *)NULL;
6461
6462           /* We do not want to add quoted nulls to strings that are only
6463              partially quoted; we can throw them away. */
6464           if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
6465             continue;
6466
6467         add_quoted_string:
6468
6469           if (temp)
6470             {
6471               temp1 = temp;
6472               temp = quote_string (temp);
6473               free (temp1);
6474               goto add_string;
6475             }
6476           else
6477             {
6478               /* Add NULL arg. */
6479               c = CTLNUL;
6480               sindex--;         /* add_character: label increments sindex */
6481               goto add_character;
6482             }
6483
6484           /* break; */
6485
6486         case '\'':
6487 #if 0
6488           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_PATQUOTE))
6489 #else
6490           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6491 #endif
6492             goto add_character;
6493
6494           t_index = ++sindex;
6495           temp = string_extract_single_quoted (string, &sindex);
6496
6497           /* If the entire STRING was surrounded by single quotes,
6498              then the string is wholly quoted. */
6499           quoted_state = (t_index == 1 && string[sindex] == '\0')
6500                             ? WHOLLY_QUOTED
6501                             : PARTIALLY_QUOTED;
6502
6503           /* If all we had was '', it is a null expansion. */
6504           if (*temp == '\0')
6505             {
6506               free (temp);
6507               temp = (char *)NULL;
6508             }
6509           else
6510             remove_quoted_escapes (temp);       /* ??? */
6511
6512           /* We do not want to add quoted nulls to strings that are only
6513              partially quoted; such nulls are discarded. */
6514           if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
6515             continue;
6516
6517           /* If we have a quoted null expansion, add a quoted NULL to istring. */
6518           if (temp == 0)
6519             {
6520               c = CTLNUL;
6521               sindex--;         /* add_character: label increments sindex */
6522               goto add_character;
6523             }
6524           else
6525             goto add_quoted_string;
6526
6527           /* break; */
6528
6529         default:
6530           /* This is the fix for " $@ " */
6531           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
6532             {
6533               if (string[sindex])       /* from old goto dollar_add_string */
6534                 sindex++;
6535               if (c == 0)
6536                 {
6537                   c = CTLNUL;
6538                   goto add_character;
6539                 }
6540               else
6541                 {
6542 #if HANDLE_MULTIBYTE
6543                   if (MB_CUR_MAX > 1)
6544                     sindex--;
6545
6546                   if (MB_CUR_MAX > 1)
6547                     {
6548                       SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
6549                     }
6550                   else
6551 #endif
6552                     {
6553                       twochars[0] = CTLESC;
6554                       twochars[1] = c;
6555                       goto add_twochars;
6556                     }
6557                 }
6558             }
6559
6560           SADD_MBCHAR (temp, string, sindex, string_size);
6561
6562         add_character:
6563           RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
6564                                   DEFAULT_ARRAY_SIZE);
6565           istring[istring_index++] = c;
6566           istring[istring_index] = '\0';
6567
6568           /* Next character. */
6569           sindex++;
6570         }
6571     }
6572
6573 finished_with_string:
6574   /* OK, we're ready to return.  If we have a quoted string, and
6575      quoted_dollar_at is not set, we do no splitting at all; otherwise
6576      we split on ' '.  The routines that call this will handle what to
6577      do if nothing has been expanded. */
6578
6579   /* Partially and wholly quoted strings which expand to the empty
6580      string are retained as an empty arguments.  Unquoted strings
6581      which expand to the empty string are discarded.  The single
6582      exception is the case of expanding "$@" when there are no
6583      positional parameters.  In that case, we discard the expansion. */
6584
6585   /* Because of how the code that handles "" and '' in partially
6586      quoted strings works, we need to make ISTRING into a QUOTED_NULL
6587      if we saw quoting characters, but the expansion was empty.
6588      "" and '' are tossed away before we get to this point when
6589      processing partially quoted strings.  This makes "" and $xxx""
6590      equivalent when xxx is unset.  We also look to see whether we
6591      saw a quoted null from a ${} expansion and add one back if we
6592      need to. */
6593
6594   /* If we expand to nothing and there were no single or double quotes
6595      in the word, we throw it away.  Otherwise, we return a NULL word.
6596      The single exception is for $@ surrounded by double quotes when
6597      there are no positional parameters.  In that case, we also throw
6598      the word away. */
6599
6600   if (*istring == '\0')
6601     {
6602       if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
6603         {
6604           istring[0] = CTLNUL;
6605           istring[1] = '\0';
6606           tword = make_bare_word (istring);
6607           list = make_word_list (tword, (WORD_LIST *)NULL);
6608           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6609             tword->flags |= W_QUOTED;
6610         }
6611       /* According to sh, ksh, and Posix.2, if a word expands into nothing
6612          and a double-quoted "$@" appears anywhere in it, then the entire
6613          word is removed. */
6614       else  if (quoted_state == UNQUOTED || quoted_dollar_at)
6615         list = (WORD_LIST *)NULL;
6616 #if 0
6617       else
6618         {
6619           tword = make_bare_word (istring);
6620           list = make_word_list (tword, (WORD_LIST *)NULL);
6621           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6622             tword->flags |= W_QUOTED;
6623         }
6624 #else
6625       else
6626         list = (WORD_LIST *)NULL;
6627 #endif
6628     }
6629   else if (word->flags & W_NOSPLIT)
6630     {
6631       tword = make_bare_word (istring);
6632       list = make_word_list (tword, (WORD_LIST *)NULL);
6633       if (word->flags & W_ASSIGNMENT)
6634         tword->flags |= W_ASSIGNMENT;   /* XXX */
6635       if (word->flags & W_NOGLOB)
6636         tword->flags |= W_NOGLOB;       /* XXX */
6637       if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6638         tword->flags |= W_QUOTED;
6639     }
6640   else
6641     {
6642       char *ifs_chars;
6643
6644       ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
6645
6646       /* If we have $@, we need to split the results no matter what.  If
6647          IFS is unset or NULL, string_list_dollar_at has separated the
6648          positional parameters with a space, so we split on space (we have
6649          set ifs_chars to " \t\n" above if ifs is unset).  If IFS is set,
6650          string_list_dollar_at has separated the positional parameters
6651          with the first character of $IFS, so we split on $IFS. */
6652       if (has_dollar_at && ifs_chars)
6653         list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
6654       else
6655         {
6656           tword = make_bare_word (istring);
6657           list = make_word_list (tword, (WORD_LIST *)NULL);
6658           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
6659             tword->flags |= W_QUOTED;
6660           if (word->flags & W_ASSIGNMENT)
6661             tword->flags |= W_ASSIGNMENT;
6662           if (word->flags & W_NOGLOB)
6663             tword->flags |= W_NOGLOB;
6664         }
6665     }
6666
6667   free (istring);
6668   return (list);
6669 }
6670
6671 /* **************************************************************** */
6672 /*                                                                  */
6673 /*                 Functions for Quote Removal                      */
6674 /*                                                                  */
6675 /* **************************************************************** */
6676
6677 /* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
6678    backslash quoting rules for within double quotes or a here document. */
6679 char *
6680 string_quote_removal (string, quoted)
6681      char *string;
6682      int quoted;
6683 {
6684   size_t slen;
6685   char *r, *result_string, *temp, *send;
6686   int sindex, tindex, dquote;
6687   unsigned char c;
6688   DECLARE_MBSTATE;
6689
6690   /* The result can be no longer than the original string. */
6691   slen = strlen (string);
6692   send = string + slen;
6693
6694   r = result_string = (char *)xmalloc (slen + 1);
6695
6696   for (dquote = sindex = 0; c = string[sindex];)
6697     {
6698       switch (c)
6699         {
6700         case '\\':
6701           c = string[++sindex];
6702           if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
6703             *r++ = '\\';
6704           /* FALLTHROUGH */
6705
6706         default:
6707           SCOPY_CHAR_M (r, string, send, sindex);
6708           break;
6709
6710         case '\'':
6711           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
6712             {
6713               *r++ = c;
6714               sindex++;
6715               break;
6716             }
6717           tindex = sindex + 1;
6718           temp = string_extract_single_quoted (string, &tindex);
6719           if (temp)
6720             {
6721               strcpy (r, temp);
6722               r += strlen (r);
6723               free (temp);
6724             }
6725           sindex = tindex;
6726           break;
6727
6728         case '"':
6729           dquote = 1 - dquote;
6730           sindex++;
6731           break;
6732         }
6733     }
6734     *r = '\0';
6735     return (result_string);
6736 }
6737
6738 #if 0
6739 /* UNUSED */
6740 /* Perform quote removal on word WORD.  This allocates and returns a new
6741    WORD_DESC *. */
6742 WORD_DESC *
6743 word_quote_removal (word, quoted)
6744      WORD_DESC *word;
6745      int quoted;
6746 {
6747   WORD_DESC *w;
6748   char *t;
6749
6750   t = string_quote_removal (word->word, quoted);
6751   w = make_bare_word (t);
6752   free (t);
6753   return (w);
6754 }
6755
6756 /* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
6757    the members of the list are treated as if they are surrounded by
6758    double quotes.  Return a new list, or NULL if LIST is NULL. */
6759 WORD_LIST *
6760 word_list_quote_removal (list, quoted)
6761      WORD_LIST *list;
6762      int quoted;
6763 {
6764   WORD_LIST *result, *t, *tresult;
6765
6766   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
6767     {
6768       tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
6769       result = (WORD_LIST *) list_append (result, tresult);
6770     }
6771   return (result);
6772 }
6773 #endif
6774
6775 /*******************************************
6776  *                                         *
6777  *    Functions to perform word splitting  *
6778  *                                         *
6779  *******************************************/
6780
6781 void
6782 setifs (v)
6783      SHELL_VAR *v;
6784 {
6785   char *t;
6786   unsigned char uc;
6787
6788   ifs_var = v;
6789   ifs_value = v ? value_cell (v) : " \t\n";
6790
6791   /* Should really merge ifs_cmap with sh_syntaxtab. */
6792   memset (ifs_cmap, '\0', sizeof (ifs_cmap));
6793   for (t = ifs_value ; t && *t; t++)
6794     {
6795       uc = *t;
6796       ifs_cmap[uc] = 1;
6797     }
6798
6799   ifs_firstc = ifs_value ? *ifs_value : 0;
6800 }
6801
6802 char *
6803 getifs ()
6804 {
6805   return ifs_value;
6806 }
6807
6808 /* This splits a single word into a WORD LIST on $IFS, but only if the word
6809    is not quoted.  list_string () performs quote removal for us, even if we
6810    don't do any splitting. */
6811 WORD_LIST *
6812 word_split (w, ifs_chars)
6813      WORD_DESC *w;
6814      char *ifs_chars;
6815 {
6816   WORD_LIST *result;
6817
6818   if (w)
6819     {
6820       char *xifs;
6821
6822       xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
6823       result = list_string (w->word, xifs, w->flags & W_QUOTED);
6824     }
6825   else
6826     result = (WORD_LIST *)NULL;
6827
6828   return (result);
6829 }
6830
6831 /* Perform word splitting on LIST and return the RESULT.  It is possible
6832    to return (WORD_LIST *)NULL. */
6833 static WORD_LIST *
6834 word_list_split (list)
6835      WORD_LIST *list;
6836 {
6837   WORD_LIST *result, *t, *tresult;
6838
6839   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
6840     {
6841       tresult = word_split (t->word, ifs_value);
6842       result = (WORD_LIST *) list_append (result, tresult);
6843     }
6844   return (result);
6845 }
6846
6847 /**************************************************
6848  *                                                *
6849  *    Functions to expand an entire WORD_LIST     *
6850  *                                                *
6851  **************************************************/
6852
6853 /* Do any word-expansion-specific cleanup and jump to top_level */
6854 static void
6855 exp_jump_to_top_level (v)
6856      int v;
6857 {
6858   /* Cleanup code goes here. */
6859   expand_no_split_dollar_star = 0;      /* XXX */
6860   expanding_redir = 0;
6861
6862   jump_to_top_level (v);
6863 }
6864
6865 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
6866    ELIST, and set ELIST to the new list. */
6867 #define PREPEND_LIST(nlist, elist) \
6868         do { nlist->next = elist; elist = nlist; } while (0)
6869
6870 /* Separate out any initial variable assignments from TLIST.  If set -k has
6871    been executed, remove all assignment statements from TLIST.  Initial
6872    variable assignments and other environment assignments are placed
6873    on SUBST_ASSIGN_VARLIST. */
6874 static WORD_LIST *
6875 separate_out_assignments (tlist)
6876      WORD_LIST *tlist;
6877 {
6878   register WORD_LIST *vp, *lp;
6879
6880   if (!tlist)
6881     return ((WORD_LIST *)NULL);
6882
6883   if (subst_assign_varlist)
6884     dispose_words (subst_assign_varlist);       /* Clean up after previous error */
6885
6886   subst_assign_varlist = (WORD_LIST *)NULL;
6887   vp = lp = tlist;
6888
6889   /* Separate out variable assignments at the start of the command.
6890      Loop invariant: vp->next == lp
6891      Loop postcondition:
6892         lp = list of words left after assignment statements skipped
6893         tlist = original list of words
6894   */
6895   while (lp && (lp->word->flags & W_ASSIGNMENT))
6896     {
6897       vp = lp;
6898       lp = lp->next;
6899     }
6900
6901   /* If lp != tlist, we have some initial assignment statements.
6902      We make SUBST_ASSIGN_VARLIST point to the list of assignment
6903      words and TLIST point to the remaining words.  */
6904   if (lp != tlist)
6905     {
6906       subst_assign_varlist = tlist;
6907       /* ASSERT(vp->next == lp); */
6908       vp->next = (WORD_LIST *)NULL;     /* terminate variable list */
6909       tlist = lp;                       /* remainder of word list */
6910     }
6911
6912   /* vp == end of variable list */
6913   /* tlist == remainder of original word list without variable assignments */
6914   if (!tlist)
6915     /* All the words in tlist were assignment statements */
6916     return ((WORD_LIST *)NULL);
6917
6918   /* ASSERT(tlist != NULL); */
6919   /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
6920
6921   /* If the -k option is in effect, we need to go through the remaining
6922      words, separate out the assignment words, and place them on
6923      SUBST_ASSIGN_VARLIST. */
6924   if (place_keywords_in_env)
6925     {
6926       WORD_LIST *tp;    /* tp == running pointer into tlist */
6927
6928       tp = tlist;
6929       lp = tlist->next;
6930
6931       /* Loop Invariant: tp->next == lp */
6932       /* Loop postcondition: tlist == word list without assignment statements */
6933       while (lp)
6934         {
6935           if (lp->word->flags & W_ASSIGNMENT)
6936             {
6937               /* Found an assignment statement, add this word to end of
6938                  subst_assign_varlist (vp). */
6939               if (!subst_assign_varlist)
6940                 subst_assign_varlist = vp = lp;
6941               else
6942                 {
6943                   vp->next = lp;
6944                   vp = lp;
6945                 }
6946
6947               /* Remove the word pointed to by LP from TLIST. */
6948               tp->next = lp->next;
6949               /* ASSERT(vp == lp); */
6950               lp->next = (WORD_LIST *)NULL;
6951               lp = tp->next;
6952             }
6953           else
6954             {
6955               tp = lp;
6956               lp = lp->next;
6957             }
6958         }
6959     }
6960   return (tlist);
6961 }
6962
6963 #define WEXP_VARASSIGN  0x001
6964 #define WEXP_BRACEEXP   0x002
6965 #define WEXP_TILDEEXP   0x004
6966 #define WEXP_PARAMEXP   0x008
6967 #define WEXP_PATHEXP    0x010
6968
6969 /* All of the expansions, including variable assignments at the start of
6970    the list. */
6971 #define WEXP_ALL        (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
6972
6973 /* All of the expansions except variable assignments at the start of
6974    the list. */
6975 #define WEXP_NOVARS     (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
6976
6977 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
6978    expansion, command substitution, arithmetic expansion, word splitting, and
6979    quote removal. */
6980 #define WEXP_SHELLEXP   (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
6981
6982 /* Take the list of words in LIST and do the various substitutions.  Return
6983    a new list of words which is the expanded list, and without things like
6984    variable assignments. */
6985
6986 WORD_LIST *
6987 expand_words (list)
6988      WORD_LIST *list;
6989 {
6990   return (expand_word_list_internal (list, WEXP_ALL));
6991 }
6992
6993 /* Same as expand_words (), but doesn't hack variable or environment
6994    variables. */
6995 WORD_LIST *
6996 expand_words_no_vars (list)
6997      WORD_LIST *list;
6998 {
6999   return (expand_word_list_internal (list, WEXP_NOVARS));
7000 }
7001
7002 WORD_LIST *
7003 expand_words_shellexp (list)
7004      WORD_LIST *list;
7005 {
7006   return (expand_word_list_internal (list, WEXP_SHELLEXP));
7007 }
7008
7009 static WORD_LIST *
7010 glob_expand_word_list (tlist, eflags)
7011      WORD_LIST *tlist;
7012      int eflags;
7013 {
7014   char **glob_array, *temp_string;
7015   register int glob_index;
7016   WORD_LIST *glob_list, *output_list, *disposables, *next;
7017   WORD_DESC *tword;
7018
7019   output_list = disposables = (WORD_LIST *)NULL;
7020   glob_array = (char **)NULL;
7021   while (tlist)
7022     {
7023       /* For each word, either globbing is attempted or the word is
7024          added to orig_list.  If globbing succeeds, the results are
7025          added to orig_list and the word (tlist) is added to the list
7026          of disposable words.  If globbing fails and failed glob
7027          expansions are left unchanged (the shell default), the
7028          original word is added to orig_list.  If globbing fails and
7029          failed glob expansions are removed, the original word is
7030          added to the list of disposable words.  orig_list ends up
7031          in reverse order and requires a call to REVERSE_LIST to
7032          be set right.  After all words are examined, the disposable
7033          words are freed. */
7034       next = tlist->next;
7035
7036       /* If the word isn't an assignment and contains an unquoted
7037          pattern matching character, then glob it. */
7038       if ((tlist->word->flags & W_NOGLOB) == 0 &&
7039           unquoted_glob_pattern_p (tlist->word->word))
7040         {
7041           glob_array = shell_glob_filename (tlist->word->word);
7042
7043           /* Handle error cases.
7044              I don't think we should report errors like "No such file
7045              or directory".  However, I would like to report errors
7046              like "Read failed". */
7047
7048           if (glob_array == 0 || GLOB_FAILED (glob_array))
7049             {
7050               glob_array = (char **)xmalloc (sizeof (char *));
7051               glob_array[0] = (char *)NULL;
7052             }
7053
7054           /* Dequote the current word in case we have to use it. */
7055           if (glob_array[0] == NULL)
7056             {
7057               temp_string = dequote_string (tlist->word->word);
7058               free (tlist->word->word);
7059               tlist->word->word = temp_string;
7060             }
7061
7062           /* Make the array into a word list. */
7063           glob_list = (WORD_LIST *)NULL;
7064           for (glob_index = 0; glob_array[glob_index]; glob_index++)
7065             {
7066               tword = make_bare_word (glob_array[glob_index]);
7067               tword->flags |= W_GLOBEXP;        /* XXX */
7068               glob_list = make_word_list (tword, glob_list);
7069             }
7070
7071           if (glob_list)
7072             {
7073               output_list = (WORD_LIST *)list_append (glob_list, output_list);
7074               PREPEND_LIST (tlist, disposables);
7075             }
7076           else if (fail_glob_expansion != 0)
7077             {
7078               report_error (_("no match: %s"), tlist->word->word);
7079               jump_to_top_level (DISCARD);
7080             }
7081           else if (allow_null_glob_expansion == 0)
7082             {
7083               /* Failed glob expressions are left unchanged. */
7084               PREPEND_LIST (tlist, output_list);
7085             }
7086           else
7087             {
7088               /* Failed glob expressions are removed. */
7089               PREPEND_LIST (tlist, disposables);
7090             }
7091         }
7092       else
7093         {
7094           /* Dequote the string. */
7095           temp_string = dequote_string (tlist->word->word);
7096           free (tlist->word->word);
7097           tlist->word->word = temp_string;
7098           PREPEND_LIST (tlist, output_list);
7099         }
7100
7101       strvec_dispose (glob_array);
7102       glob_array = (char **)NULL;
7103
7104       tlist = next;
7105     }
7106
7107   if (disposables)
7108     dispose_words (disposables);
7109
7110   if (output_list)
7111     output_list = REVERSE_LIST (output_list, WORD_LIST *);
7112
7113   return (output_list);
7114 }
7115
7116 #if defined (BRACE_EXPANSION)
7117 static WORD_LIST *
7118 brace_expand_word_list (tlist, eflags)
7119      WORD_LIST *tlist;
7120      int eflags;
7121 {
7122   register char **expansions;
7123   char *temp_string;
7124   WORD_LIST *disposables, *output_list, *next;
7125   WORD_DESC *w;
7126   int eindex;
7127
7128   for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
7129     {
7130       next = tlist->next;
7131
7132       /* Only do brace expansion if the word has a brace character.  If
7133          not, just add the word list element to BRACES and continue.  In
7134          the common case, at least when running shell scripts, this will
7135          degenerate to a bunch of calls to `xstrchr', and then what is
7136          basically a reversal of TLIST into BRACES, which is corrected
7137          by a call to REVERSE_LIST () on BRACES when the end of TLIST
7138          is reached. */
7139       if (xstrchr (tlist->word->word, LBRACE))
7140         {
7141           expansions = brace_expand (tlist->word->word);
7142
7143           for (eindex = 0; temp_string = expansions[eindex]; eindex++)
7144             {
7145               w = make_word (temp_string);
7146               /* If brace expansion didn't change the word, preserve
7147                  the flags.  We may want to preserve the flags
7148                  unconditionally someday -- XXX */
7149               if (STREQ (temp_string, tlist->word->word))
7150                 w->flags = tlist->word->flags;
7151               output_list = make_word_list (w, output_list);
7152               free (expansions[eindex]);
7153             }
7154           free (expansions);
7155
7156           /* Add TLIST to the list of words to be freed after brace
7157              expansion has been performed. */
7158           PREPEND_LIST (tlist, disposables);
7159         }
7160       else
7161         PREPEND_LIST (tlist, output_list);
7162     }
7163
7164   if (disposables)
7165     dispose_words (disposables);
7166
7167   if (output_list)
7168     output_list = REVERSE_LIST (output_list, WORD_LIST *);
7169
7170   return (output_list);
7171 }
7172 #endif
7173
7174 static WORD_LIST *
7175 shell_expand_word_list (tlist, eflags)
7176      WORD_LIST *tlist;
7177      int eflags;
7178 {
7179   WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
7180   int expanded_something, has_dollar_at;
7181   char *temp_string;
7182
7183   /* We do tilde expansion all the time.  This is what 1003.2 says. */
7184   new_list = (WORD_LIST *)NULL;
7185   for (orig_list = tlist; tlist; tlist = next)
7186     {
7187       temp_string = tlist->word->word;
7188
7189       next = tlist->next;
7190
7191       /* Posix.2 section 3.6.1 says that tildes following `=' in words
7192          which are not assignment statements are not expanded.  If the
7193          shell isn't in posix mode, though, we perform tilde expansion
7194          on `likely candidate' unquoted assignment statements (flags
7195          include W_ASSIGNMENT but not W_QUOTED).  A likely candidate
7196          contains an unquoted :~ or =~.  Something to think about: we
7197          now have a flag that says  to perform tilde expansion on arguments
7198          to `assignment builtins' like declare and export that look like
7199          assignment statements.  We now do tilde expansion on such words
7200          even in POSIX mode. */
7201       if (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
7202              (posixly_correct == 0 || (tlist->word->flags & W_TILDEEXP)) &&
7203              (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string)))
7204         {
7205           tlist->word->word = bash_tilde_expand (temp_string, 1);
7206           free (temp_string);
7207         }
7208       else if (temp_string[0] == '~')
7209         {
7210           tlist->word->word = bash_tilde_expand (temp_string, 0);
7211           free (temp_string);
7212         }
7213
7214       expanded_something = 0;
7215       expanded = expand_word_internal
7216         (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
7217
7218       if (expanded == &expand_word_error || expanded == &expand_word_fatal)
7219         {
7220           /* By convention, each time this error is returned,
7221              tlist->word->word has already been freed. */
7222           tlist->word->word = (char *)NULL;
7223
7224           /* Dispose our copy of the original list. */
7225           dispose_words (orig_list);
7226           /* Dispose the new list we're building. */
7227           dispose_words (new_list);
7228
7229           last_command_exit_value = EXECUTION_FAILURE;
7230           if (expanded == &expand_word_error)
7231             exp_jump_to_top_level (DISCARD);
7232           else
7233             exp_jump_to_top_level (FORCE_EOF);
7234         }
7235
7236       /* Don't split words marked W_NOSPLIT. */
7237       if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
7238         {
7239           temp_list = word_list_split (expanded);
7240           dispose_words (expanded);
7241         }
7242       else
7243         {
7244           /* If no parameter expansion, command substitution, process
7245              substitution, or arithmetic substitution took place, then
7246              do not do word splitting.  We still have to remove quoted
7247              null characters from the result. */
7248           word_list_remove_quoted_nulls (expanded);
7249           temp_list = expanded;
7250         }
7251
7252       expanded = REVERSE_LIST (temp_list, WORD_LIST *);
7253       new_list = (WORD_LIST *)list_append (expanded, new_list);
7254     }
7255
7256   if (orig_list)  
7257     dispose_words (orig_list);
7258
7259   if (new_list)
7260     new_list = REVERSE_LIST (new_list, WORD_LIST *);
7261
7262   return (new_list);
7263 }
7264
7265 /* The workhorse for expand_words () and expand_words_no_vars ().
7266    First arg is LIST, a WORD_LIST of words.
7267    Second arg EFLAGS is a flags word controlling which expansions are
7268    performed.
7269
7270    This does all of the substitutions: brace expansion, tilde expansion,
7271    parameter expansion, command substitution, arithmetic expansion,
7272    process substitution, word splitting, and pathname expansion, according
7273    to the bits set in EFLAGS.  Words with the W_QUOTED or W_NOSPLIT bits
7274    set, or for which no expansion is done, do not undergo word splitting.
7275    Words with the W_NOGLOB bit set do not undergo pathname expansion. */
7276 static WORD_LIST *
7277 expand_word_list_internal (list, eflags)
7278      WORD_LIST *list;
7279      int eflags;
7280 {
7281   WORD_LIST *new_list, *temp_list;
7282   int tint;
7283
7284   if (list == 0)
7285     return ((WORD_LIST *)NULL);
7286
7287   garglist = new_list = copy_word_list (list);
7288   if (eflags & WEXP_VARASSIGN)
7289     {
7290       garglist = new_list = separate_out_assignments (new_list);
7291       if (new_list == 0)
7292         {
7293           if (subst_assign_varlist)
7294             {
7295               /* All the words were variable assignments, so they are placed
7296                  into the shell's environment. */
7297               for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
7298                 {
7299                   this_command_name = (char *)NULL;     /* no arithmetic errors */
7300                   tint = do_assignment (temp_list->word->word);
7301                   /* Variable assignment errors in non-interactive shells
7302                      running in Posix.2 mode cause the shell to exit. */
7303                   if (tint == 0)
7304                     {
7305                       last_command_exit_value = EXECUTION_FAILURE;
7306                       if (interactive_shell == 0 && posixly_correct)
7307                         exp_jump_to_top_level (FORCE_EOF);
7308                       else
7309                         exp_jump_to_top_level (DISCARD);
7310                     }
7311                 }
7312               dispose_words (subst_assign_varlist);
7313               subst_assign_varlist = (WORD_LIST *)NULL;
7314             }
7315           return ((WORD_LIST *)NULL);
7316         }
7317     }
7318
7319   /* Begin expanding the words that remain.  The expansions take place on
7320      things that aren't really variable assignments. */
7321
7322 #if defined (BRACE_EXPANSION)
7323   /* Do brace expansion on this word if there are any brace characters
7324      in the string. */
7325   if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
7326     new_list = brace_expand_word_list (new_list, eflags);
7327 #endif /* BRACE_EXPANSION */
7328
7329   /* Perform the `normal' shell expansions: tilde expansion, parameter and
7330      variable substitution, command substitution, arithmetic expansion,
7331      and word splitting. */
7332   new_list = shell_expand_word_list (new_list, eflags);
7333
7334   /* Okay, we're almost done.  Now let's just do some filename
7335      globbing. */
7336   if (new_list)
7337     {
7338       if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
7339         /* Glob expand the word list unless globbing has been disabled. */
7340         new_list = glob_expand_word_list (new_list, eflags);
7341       else
7342         /* Dequote the words, because we're not performing globbing. */
7343         new_list = dequote_list (new_list);
7344     }
7345
7346   if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
7347     {
7348       sh_assign_func_t *assign_func;
7349
7350       /* If the remainder of the words expand to nothing, Posix.2 requires
7351          that the variable and environment assignments affect the shell's
7352          environment. */
7353       assign_func = new_list ? assign_in_env : do_assignment;
7354       tempenv_assign_error = 0;
7355
7356       for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
7357         {
7358           this_command_name = (char *)NULL;
7359           tint = (*assign_func) (temp_list->word->word);
7360           /* Variable assignment errors in non-interactive shells running
7361              in Posix.2 mode cause the shell to exit. */
7362           if (tint == 0)
7363             {
7364               if (assign_func == do_assignment)
7365                 {
7366                   last_command_exit_value = EXECUTION_FAILURE;
7367                   if (interactive_shell == 0 && posixly_correct)
7368                     exp_jump_to_top_level (FORCE_EOF);
7369                   else
7370                     exp_jump_to_top_level (DISCARD);
7371                 }
7372               else
7373                 tempenv_assign_error++;
7374             }
7375         }
7376
7377       dispose_words (subst_assign_varlist);
7378       subst_assign_varlist = (WORD_LIST *)NULL;
7379     }
7380
7381 #if 0
7382   tint = list_length (new_list) + 1;
7383   RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
7384   for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
7385     glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
7386   glob_argv_flags[tint] = '\0';
7387 #endif
7388
7389   return (new_list);
7390 }