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