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