Imported from ../bash-2.03.tar.gz.
[platform/upstream/bash.git] / subst.c
1 /* subst.c -- The part of the shell that does parameter, command, and
2    globbing substitutions. */
3
4 /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
5
6    This file is part of GNU Bash, the Bourne Again SHell.
7
8    Bash is free software; you can redistribute it and/or modify it under
9    the terms of the GNU General Public License as published by the Free
10    Software Foundation; either version 2, or (at your option) any later
11    version.
12
13    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14    WARRANTY; without even the implied warranty of MERCHANTABILITY or
15    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16    for more details.
17
18    You should have received a copy of the GNU General Public License along
19    with Bash; see the file COPYING.  If not, write to the Free Software
20    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include "config.h"
23
24 #include "bashtypes.h"
25 #include <stdio.h>
26 #include <pwd.h>
27 #include <signal.h>
28 #include <errno.h>
29
30 #if defined (HAVE_UNISTD_H)
31 #  include <unistd.h>
32 #endif
33
34 #include "bashansi.h"
35 #include "posixstat.h"
36
37 #include "shell.h"
38 #include "flags.h"
39 #include "jobs.h"
40 #include "execute_cmd.h"
41 #include "filecntl.h"
42 #include "trap.h"
43 #include "pathexp.h"
44 #include "mailcheck.h"
45
46 #if !defined (HAVE_RESTARTABLE_SYSCALLS)        /* for getc_with_restart */
47 #include "input.h"
48 #endif
49
50 #include "builtins/getopt.h"
51 #include "builtins/common.h"
52
53 #include <tilde/tilde.h>
54 #include <glob/fnmatch.h>
55
56 #if !defined (errno)
57 extern int errno;
58 #endif /* !errno */
59
60 /* The size that strings change by. */
61 #define DEFAULT_INITIAL_ARRAY_SIZE 112
62 #define DEFAULT_ARRAY_SIZE 128
63
64 /* Variable types. */
65 #define VT_VARIABLE     0
66 #define VT_POSPARMS     1
67 #define VT_ARRAYVAR     2
68 #define VT_ARRAYMEMBER  3
69
70 /* Flags for quoted_strchr */
71 #define ST_BACKSL       0x01
72 #define ST_CTLESC       0x02
73
74 /* These defs make it easier to use the editor. */
75 #define LBRACE          '{'
76 #define RBRACE          '}'
77 #define LPAREN          '('
78 #define RPAREN          ')'
79
80 /* Process ID of the last command executed within command substitution. */
81 pid_t last_command_subst_pid = NO_PID;
82 pid_t current_command_subst_pid = NO_PID;
83
84 /* Extern functions and variables from different files. */
85 extern int last_command_exit_value, interactive, interactive_shell;
86 extern int subshell_environment, startup_state;
87 extern int dollar_dollar_pid;
88 extern int posixly_correct;
89 extern char *this_command_name;
90 extern struct fd_bitmap *current_fds_to_close;
91 extern int wordexp_only;
92
93 extern void getopts_reset ();
94
95 /* Non-zero means to allow unmatched globbed filenames to expand to
96    a null file. */
97 int allow_null_glob_expansion;
98
99 /* Variables to keep track of which words in an expanded word list (the
100    output of expand_word_list_internal) are the result of globbing
101    expansions.  GLOB_ARGV_FLAGS is used by execute_cmd.c. */
102 char *glob_argv_flags;
103 static int glob_argv_flags_size;
104
105 static WORD_LIST expand_word_error, expand_word_fatal;
106 static char expand_param_error, expand_param_fatal;
107
108 static int doing_completion = 0;
109
110 static char *make_quoted_char ();
111 static void remove_quoted_nulls ();
112 static char *param_expand ();
113 static char *maybe_expand_string ();
114 static WORD_LIST *call_expand_word_internal ();
115 static WORD_LIST *expand_string_internal ();
116 static WORD_LIST *expand_word_internal (), *expand_word_list_internal ();
117 static WORD_LIST *expand_string_leave_quoted ();
118 static WORD_LIST *expand_string_for_rhs ();
119 static char *getifs ();
120 static WORD_LIST *word_list_split ();
121 static WORD_LIST *quote_list (), *dequote_list ();
122 static char *quote_escapes ();
123 static WORD_LIST *list_quote_escapes ();
124 static int unquoted_substring (), unquoted_member ();
125 static int do_assignment_internal ();
126 static char *string_extract_verbatim (), *string_extract ();
127 static char *string_extract_double_quoted (), *string_extract_single_quoted ();
128 static char *string_list_dollar_at (), *string_list_dollar_star ();
129 static inline int skip_single_quoted (), skip_double_quoted ();
130 static char *extract_delimited_string ();
131 static char *extract_dollar_brace_string ();
132
133 /* **************************************************************** */
134 /*                                                                  */
135 /*                      Utility Functions                           */
136 /*                                                                  */
137 /* **************************************************************** */
138
139 /* Cons a new string from STRING starting at START and ending at END,
140    not including END. */
141 char *
142 substring (string, start, end)
143      char *string;
144      int start, end;
145 {
146   register int len;
147   register char *result;
148
149   len = end - start;
150   result = xmalloc (len + 1);
151   strncpy (result, string + start, len);
152   result[len] = '\0';
153   return (result);
154 }
155
156 static char *
157 quoted_substring (string, start, end)
158      char *string;
159      int start, end;
160 {
161   register int len, l;
162   register char *result, *s, *r;
163
164   len = end - start;
165
166   /* Move to string[start], skipping quoted characters. */
167   for (s = string, l = 0; *s && l < start; )
168     {
169       if (*s == CTLESC)
170         {
171           s++;
172           continue;
173         }
174       l++;
175       if (*s == 0)
176         break;
177     }
178
179   r = result = xmalloc (2*len + 1);      /* save room for quotes */
180
181   /* Copy LEN characters, including quote characters. */
182   s = string + l;
183   for (l = 0; l < len; s++)
184     {
185       if (*s == CTLESC)
186         *r++ = *s++;
187       *r++ = *s;
188       l++;
189       if (*s == 0)
190         break;
191     }
192   *r = '\0';
193   return result;
194 }
195
196 /* Find the first occurrence of character C in string S, obeying shell
197    quoting rules.  If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
198    characters are skipped.  If (FLAGS & ST_CTLESC) is non-zero, characters
199    escaped with CTLESC are skipped. */
200 static inline char *
201 quoted_strchr (s, c, flags)
202      char *s;
203      int c, flags;
204 {
205   register char *p;
206
207   for (p = s; *p; p++)
208     {
209       if (((flags & ST_BACKSL) && *p == '\\')
210             || ((flags & ST_CTLESC) && *p == CTLESC))
211         {
212           p++;
213           if (*p == '\0')
214             return ((char *)NULL);
215           continue;
216         }
217       else if (*p == c)
218         return p;
219     }
220   return ((char *)NULL);
221 }
222
223 /* Return 1 if CHARACTER appears in an unquoted portion of
224    STRING.  Return 0 otherwise. */
225 static int
226 unquoted_member (character, string)
227      int character;
228      char *string;
229 {
230   int sindex, c;
231
232   for (sindex = 0; c = string[sindex]; )
233     {
234       if (c == character)
235         return (1);
236
237       switch (c)
238         {
239         default:
240           sindex++;
241           break;
242
243         case '\\':
244           sindex++;
245           if (string[sindex])
246             sindex++;
247           break;
248
249         case '\'':
250           sindex = skip_single_quoted (string, ++sindex);
251           break;
252
253         case '"':
254           sindex = skip_double_quoted (string, ++sindex);
255           break;
256         }
257     }
258   return (0);
259 }
260
261 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
262 static int
263 unquoted_substring (substr, string)
264      char *substr, *string;
265 {
266   int sindex, c, sublen;
267
268   if (substr == 0 || *substr == '\0')
269     return (0);
270
271   sublen = strlen (substr);
272   for (sindex = 0; c = string[sindex]; )
273     {
274       if (STREQN (string + sindex, substr, sublen))
275         return (1);
276
277       switch (c)
278         {
279         case '\\':
280           sindex++;
281
282           if (string[sindex])
283             sindex++;
284           break;
285
286         case '\'':
287           sindex = skip_single_quoted (string, ++sindex);
288           break;
289
290         case '"':
291           sindex = skip_double_quoted (string, ++sindex);
292           break;
293
294         default:
295           sindex++;
296           break;
297         }
298     }
299   return (0);
300 }
301
302 /* Most of the substitutions must be done in parallel.  In order
303    to avoid using tons of unclear goto's, I have some functions
304    for manipulating malloc'ed strings.  They all take INDX, a
305    pointer to an integer which is the offset into the string
306    where manipulation is taking place.  They also take SIZE, a
307    pointer to an integer which is the current length of the
308    character array for this string. */
309
310 /* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
311    of space allocated to TARGET.  SOURCE can be NULL, in which
312    case nothing happens.  Gets rid of SOURCE by freeing it.
313    Returns TARGET in case the location has changed. */
314 inline char *
315 sub_append_string (source, target, indx, size)
316      char *source, *target;
317      int *indx, *size;
318 {
319   if (source)
320     {
321       int srclen, n;
322
323       srclen = STRLEN (source);
324       if (srclen >= (int)(*size - *indx))
325         {
326           n = srclen + *indx;
327           n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
328           target = xrealloc (target, (*size = n));
329         }
330
331       FASTCOPY (source, target + *indx, srclen);
332       *indx += srclen;
333       target[*indx] = '\0';
334
335       free (source);
336     }
337   return (target);
338 }
339
340 #if 0
341 /* UNUSED */
342 /* Append the textual representation of NUMBER to TARGET.
343    INDX and SIZE are as in SUB_APPEND_STRING. */
344 char *
345 sub_append_number (number, target, indx, size)
346      int number, *indx, *size;
347      char *target;
348 {
349   char *temp;
350
351   temp = itos (number);
352   return (sub_append_string (temp, target, indx, size));
353 }
354 #endif
355
356 /* Extract a substring from STRING, starting at SINDEX and ending with
357    one of the characters in CHARLIST.  Don't make the ending character
358    part of the string.  Leave SINDEX pointing at the ending character.
359    Understand about backslashes in the string.  If VARNAME is non-zero,
360    and array variables have been compiled into the shell, everything
361    between a `[' and a corresponding `]' is skipped over. */
362 static char *
363 string_extract (string, sindex, charlist, varname)
364      char *string, *charlist;
365      int *sindex, varname;
366 {
367   register int c, i;
368   char *temp;
369
370   for (i = *sindex; c = string[i]; i++)
371     {
372       if (c == '\\')
373         if (string[i + 1])
374           i++;
375         else
376           break;
377 #if defined (ARRAY_VARS)
378       else if (varname && c == '[')
379         {
380           int ni;
381           /* If this is an array subscript, skip over it and continue. */
382           ni = skipsubscript (string, i);
383           if (string[ni] == ']')
384             i = ni;
385         }
386 #endif
387       else if (MEMBER (c, charlist))
388           break;
389     }
390   c = i - *sindex;
391   temp = xmalloc (1 + c);
392   strncpy (temp, string + *sindex, c);
393   temp[c] = '\0';
394   *sindex = i;
395   return (temp);
396 }
397
398 /* Extract the contents of STRING as if it is enclosed in double quotes.
399    SINDEX, when passed in, is the offset of the character immediately
400    following the opening double quote; on exit, SINDEX is left pointing after
401    the closing double quote.  If STRIPDQ is non-zero, unquoted double
402    quotes are stripped and the string is terminated by a null byte.
403    Backslashes between the embedded double quotes are processed.  If STRIPDQ
404    is zero, an unquoted `"' terminates the string. */
405 static inline char *
406 string_extract_double_quoted (string, sindex, stripdq)
407      char *string;
408      int *sindex, stripdq;
409 {
410   int c, j, i, t;
411   char *temp, *ret;             /* The new string we return. */
412   int pass_next, backquote, si; /* State variables for the machine. */
413   int dquote;
414
415   pass_next = backquote = dquote = 0;
416   temp = xmalloc (1 + strlen (string) - *sindex);
417
418   for (j = 0, i = *sindex; c = string[i]; i++)
419     {
420       /* Process a character that was quoted by a backslash. */
421       if (pass_next)
422         {
423           /* Posix.2 sez:
424
425              ``The backslash shall retain its special meaning as an escape
426              character only when followed by one of the characters:
427                 $       `       "       \       <newline>''.
428
429              If STRIPDQ is zero, we handle the double quotes here and let
430              expand_word_internal handle the rest.  If STRIPDQ is non-zero,
431              we have already been through one round of backslash stripping,
432              and want to strip these backslashes only if DQUOTE is non-zero,
433              indicating that we are inside an embedded double-quoted string. */
434
435              /* If we are in an embedded quoted string, then don't strip
436                 backslashes before characters for which the backslash
437                 retains its special meaning, but remove backslashes in
438                 front of other characters.  If we are not in an
439                 embedded quoted string, don't strip backslashes at all.
440                 This mess is necessary because the string was already
441                 surrounded by double quotes (and sh has some really weird
442                 quoting rules).
443                 The returned string will be run through expansion as if
444                 it were double-quoted. */
445           if ((stripdq == 0 && c != '"') ||
446               (stripdq && ((dquote && strchr (slashify_in_quotes, c)) || dquote == 0)))
447             temp[j++] = '\\';
448           temp[j++] = c;
449           pass_next = 0;
450           continue;
451         }
452
453       /* A backslash protects the next character.  The code just above
454          handles preserving the backslash in front of any character but
455          a double quote. */
456       if (c == '\\')
457         {
458           pass_next++;
459           continue;
460         }
461
462       /* Inside backquotes, ``the portion of the quoted string from the
463          initial backquote and the characters up to the next backquote
464          that is not preceded by a backslash, having escape characters
465          removed, defines that command''. */
466       if (backquote)
467         {
468           if (c == '`')
469             backquote = 0;
470           temp[j++] = c;
471           continue;
472         }
473
474       if (c == '`')
475         {
476           temp[j++] = c;
477           backquote++;
478           continue;
479         }
480
481       /* Pass everything between `$(' and the matching `)' or a quoted
482          ${ ... } pair through according to the Posix.2 specification. */
483       if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
484         {
485           si = i + 2;
486           if (string[i + 1] == LPAREN)
487             ret = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
488           else
489             ret = extract_dollar_brace_string (string, &si, 1);
490
491           temp[j++] = '$';
492           temp[j++] = string[i + 1];
493
494           for (t = 0; ret[t]; t++, j++)
495             temp[j] = ret[t];
496           temp[j++] = string[si];
497
498           i = si;
499           free (ret);
500           continue;
501         }
502
503       /* Add any character but a double quote to the quoted string we're
504          accumulating. */
505       if (c != '"')
506         {
507           temp[j++] = c;
508           continue;
509         }
510
511       /* c == '"' */
512       if (stripdq)
513         {
514           dquote ^= 1;
515           continue;
516         }
517
518       break;
519     }
520   temp[j] = '\0';
521
522   /* Point to after the closing quote. */
523   if (c)
524     i++;
525   *sindex = i;
526
527   return (temp);
528 }
529
530 /* This should really be another option to string_extract_double_quoted. */
531 static inline int
532 skip_double_quoted (string, sind)
533      char *string;
534      int sind;
535 {
536   int c, j, i;
537   char *ret;
538   int pass_next, backquote, si;
539
540   pass_next = backquote = 0;
541
542   for (j = 0, i = sind; c = string[i]; i++)
543     {
544       if (pass_next)
545         {
546           pass_next = 0;
547           continue;
548         }
549       else if (c == '\\')
550         {
551           pass_next++;
552           continue;
553         }
554       else if (backquote)
555         {
556           if (c == '`')
557             backquote = 0;
558           continue;
559         }
560       else if (c == '`')
561         {
562           backquote++;
563           continue;
564         }
565       else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
566         {
567           si = i + 2;
568           if (string[i + 1] == LPAREN)
569             ret = extract_delimited_string (string, &si, "$(", "(", ")");
570           else
571             ret = extract_dollar_brace_string (string, &si, 0);
572
573           i = si;
574           free (ret);
575           continue;
576         }
577       else if (c != '"')
578         continue;
579       else
580         break;
581     }
582
583   if (c)
584     i++;
585
586   return (i);
587 }
588
589 /* Extract the contents of STRING as if it is enclosed in single quotes.
590    SINDEX, when passed in, is the offset of the character immediately
591    following the opening single quote; on exit, SINDEX is left pointing after
592    the closing single quote. */
593 static inline char *
594 string_extract_single_quoted (string, sindex)
595      char *string;
596      int *sindex;
597 {
598   register int i, j;
599   char *t;
600
601   for (i = *sindex; string[i] && string[i] != '\''; i++)
602     ;
603
604   j = i - *sindex;
605   t = xmalloc (1 + j);
606   strncpy (t, string + *sindex, j);
607   t[j] = '\0';
608
609   if (string[i])
610     i++;
611   *sindex = i;
612
613   return (t);
614 }
615
616 static inline int
617 skip_single_quoted (string, sind)
618      char *string;
619      int sind;
620 {
621   register int i;
622
623   for (i = sind; string[i] && string[i] != '\''; i++)
624     ;
625   if (string[i])
626     i++;
627   return i;
628 }
629
630 /* Just like string_extract, but doesn't hack backslashes or any of
631    that other stuff.  Obeys quoting.  Used to do splitting on $IFS. */
632 static char *
633 string_extract_verbatim (string, sindex, charlist)
634      char *string, *charlist;
635      int *sindex;
636 {
637   register int i = *sindex;
638   int c;
639   char *temp;
640
641   if (charlist[0] == '\'' && charlist[1] == '\0')
642     {
643       temp = string_extract_single_quoted (string, sindex);
644       --*sindex;        /* leave *sindex at separator character */
645       return temp;
646     }
647
648   for (i = *sindex; c = string[i]; i++)
649     {
650       if (c == CTLESC)
651         {
652           i++;
653           continue;
654         }
655
656       if (MEMBER (c, charlist))
657         break;
658     }
659
660   c = i - *sindex;
661   temp = xmalloc (1 + c);
662   strncpy (temp, string + *sindex, c);
663   temp[c] = '\0';
664   *sindex = i;
665
666   return (temp);
667 }
668
669 /* Extract the $( construct in STRING, and return a new string.
670    Start extracting at (SINDEX) as if we had just seen "$(".
671    Make (SINDEX) get the position of the matching ")". */
672 char *
673 extract_command_subst (string, sindex)
674      char *string;
675      int *sindex;
676 {
677   return (extract_delimited_string (string, sindex, "$(", "(", ")"));
678 }
679
680 /* Extract the $[ construct in STRING, and return a new string.
681    Start extracting at (SINDEX) as if we had just seen "$[".
682    Make (SINDEX) get the position of the matching "]". */
683 char *
684 extract_arithmetic_subst (string, sindex)
685      char *string;
686      int *sindex;
687 {
688   return (extract_delimited_string (string, sindex, "$[", "[", "]"));
689 }
690
691 #if defined (PROCESS_SUBSTITUTION)
692 /* Extract the <( or >( construct in STRING, and return a new string.
693    Start extracting at (SINDEX) as if we had just seen "<(".
694    Make (SINDEX) get the position of the matching ")". */ /*))*/
695 char *
696 extract_process_subst (string, starter, sindex)
697      char *string;
698      char *starter;
699      int *sindex;
700 {
701   return (extract_delimited_string (string, sindex, starter, "(", ")"));
702 }
703 #endif /* PROCESS_SUBSTITUTION */
704
705 #if defined (ARRAY_VARS)
706 char *
707 extract_array_assignment_list (string, sindex)
708      char *string;
709      int *sindex;
710 {
711   return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")"));
712 }
713 #endif
714
715 /* Extract and create a new string from the contents of STRING, a
716    character string delimited with OPENER and CLOSER.  SINDEX is
717    the address of an int describing the current offset in STRING;
718    it should point to just after the first OPENER found.  On exit,
719    SINDEX gets the position of the last character of the matching CLOSER.
720    If OPENER is more than a single character, ALT_OPENER, if non-null,
721    contains a character string that can also match CLOSER and thus
722    needs to be skipped. */
723 static char *
724 extract_delimited_string (string, sindex, opener, alt_opener, closer)
725      char *string;
726      int *sindex;
727      char *opener, *alt_opener, *closer;
728 {
729   int i, c, si;
730   char *t, *result;
731   int pass_character, nesting_level;
732   int len_closer, len_opener, len_alt_opener;
733
734   len_opener = STRLEN (opener);
735   len_alt_opener = STRLEN (alt_opener);
736   len_closer = STRLEN (closer);
737
738   pass_character = 0;
739
740   nesting_level = 1;
741   i = *sindex;
742
743   while (nesting_level)
744     {
745       c = string[i];
746
747       if (c == 0)
748         break;
749
750       if (pass_character)       /* previous char was backslash */
751         {
752           pass_character = 0;
753           i++;
754           continue;
755         }
756
757       if (c == CTLESC)
758         {
759           pass_character++;
760           i++;
761           continue;
762         }
763
764 #if 0
765       if (c == '\\' && delimiter == '"' &&
766               (member (string[i], slashify_in_quotes)))
767 #else
768       if (c == '\\')
769 #endif
770         {
771           pass_character++;
772           i++;
773           continue;
774         }
775
776       /* Process a nested OPENER. */
777       if (STREQN (string + i, opener, len_opener))
778         {
779           si = i + len_opener;
780           t = extract_delimited_string (string, &si, opener, alt_opener, closer);
781           i = si + 1;
782           FREE (t);
783           continue;
784         }
785
786       /* Process a nested ALT_OPENER */
787       if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
788         {
789           si = i + len_alt_opener;
790           t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer);
791           i = si + 1;
792           FREE (t);
793           continue;
794         }
795
796       /* If the current substring terminates the delimited string, decrement
797          the nesting level. */
798       if (STREQN (string + i, closer, len_closer))
799         {
800           i += len_closer - 1;  /* move to last char of the closer */
801           nesting_level--;
802           if (nesting_level == 0)
803             break;
804         }
805
806       /* Pass old-style command substitution through verbatim. */
807       if (c == '`')
808         {
809           si = i + 1;
810           t = string_extract (string, &si, "`", 0);
811           i = si + 1;
812           FREE (t);
813           continue;
814         }
815
816       /* Pass single-quoted strings through verbatim. */
817       if (c == '\'')
818         {
819           si = i + 1;
820           i = skip_single_quoted (string, si);
821           continue;
822         }
823
824       /* Pass embedded double-quoted strings through verbatim as well. */
825       if (c == '"')
826         {
827           si = i + 1;
828           i = skip_double_quoted (string, si);
829           continue;
830         }
831
832       i++;      /* move past this character, which was not special. */
833     }
834
835   if (c == 0 && nesting_level)
836     {
837       report_error ("bad substitution: no `%s' in %s", closer, string);
838       jump_to_top_level (DISCARD);
839     }
840
841   si = i - *sindex - len_closer + 1;
842   result = xmalloc (1 + si);
843   strncpy (result, string + *sindex, si);
844   result[si] = '\0';
845   *sindex = i;
846
847   return (result);
848 }
849
850 /* Extract a parameter expansion expression within ${ and } from STRING.
851    Obey the Posix.2 rules for finding the ending `}': count braces while
852    skipping over enclosed quoted strings and command substitutions.
853    SINDEX is the address of an int describing the current offset in STRING;
854    it should point to just after the first `{' found.  On exit, SINDEX
855    gets the position of the matching `}'.  QUOTED is non-zero if this
856    occurs inside double quotes. */
857 /* XXX -- this is very similar to extract_delimited_string -- XXX */
858 static char *
859 extract_dollar_brace_string (string, sindex, quoted)
860      char *string;
861      int *sindex, quoted;
862 {
863   register int i, c, l;
864   int pass_character, nesting_level, si;
865   char *result, *t;
866
867   pass_character = 0;
868
869   nesting_level = 1;
870
871   for (i = *sindex; (c = string[i]); i++)
872     {
873       if (pass_character)
874         {
875           pass_character = 0;
876           continue;
877         }
878
879       /* CTLESCs and backslashes quote the next character. */
880       if (c == CTLESC || c == '\\')
881         {
882           pass_character++;
883           continue;
884         }
885
886       if (string[i] == '$' && string[i+1] == LBRACE)
887         {
888           nesting_level++;
889           i++;
890           continue;
891         }
892
893       if (c == RBRACE)
894         {
895           nesting_level--;
896           if (nesting_level == 0)
897             break;
898           continue;
899         }
900
901       /* Pass the contents of old-style command substitutions through
902          verbatim. */
903       if (c == '`')
904         {
905           si = i + 1;
906           t = string_extract (string, &si, "`", 0);
907           i = si;
908           free (t);
909           continue;
910         }
911
912       /* Pass the contents of new-style command substitutions and
913          arithmetic substitutions through verbatim. */
914       if (string[i] == '$' && string[i+1] == LPAREN)
915         {
916           si = i + 2;
917           t = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
918           i = si;
919           free (t);
920           continue;
921         }
922
923       /* Pass the contents of single-quoted and double-quoted strings
924          through verbatim. */
925       if (c == '\'' || c == '"')
926         {
927           si = i + 1;
928           i = (c == '\'') ? skip_single_quoted (string, si)
929                           : skip_double_quoted (string, si);
930           /* skip_XXX_quoted leaves index one past close quote */
931           i--;
932           continue;
933         }
934     }
935
936   if (c == 0 && nesting_level && doing_completion == 0)
937     {
938       report_error ("bad substitution: no ending `}' in %s", string);
939       jump_to_top_level (DISCARD);
940     }
941
942   l = i - *sindex;
943   result = xmalloc (1 + l);
944   strncpy (result, string + *sindex, l);
945   result[l] = '\0';
946   *sindex = i;
947
948   return (result);
949 }
950
951 /* Remove backslashes which are quoting backquotes from STRING.  Modifies
952    STRING, and returns a pointer to it. */
953 char *
954 de_backslash (string)
955      char *string;
956 {
957   register int i, l;
958
959   for (i = 0, l = strlen (string); i < l; i++)
960     if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
961                               string[i + 1] == '$'))
962       strcpy (string + i, string + i + 1);      /* XXX - should be memmove */
963   return (string);
964 }
965
966 #if 0
967 /*UNUSED*/
968 /* Replace instances of \! in a string with !. */
969 void
970 unquote_bang (string)
971      char *string;
972 {
973   register int i, j;
974   register char *temp;
975
976   temp = xmalloc (1 + strlen (string));
977
978   for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
979     {
980       if (string[i] == '\\' && string[i + 1] == '!')
981         {
982           temp[j] = '!';
983           i++;
984         }
985     }
986   strcpy (string, temp);
987   free (temp);
988 }
989 #endif
990
991 #if defined (READLINE)
992 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
993    an unclosed quoted string), or if the character at EINDEX is quoted
994    by a backslash. DOING_COMPLETION is used to flag that the various
995    single and double-quoted string parsing functions should not return an
996    error if there are unclosed quotes or braces. */
997
998 #define CQ_RETURN(x) do { doing_completion = 0; return (x); } while (0)
999
1000 int
1001 char_is_quoted (string, eindex)
1002      char *string;
1003      int eindex;
1004 {
1005   int i, pass_next, quoted;
1006
1007   doing_completion = 1;
1008   for (i = pass_next = quoted = 0; i <= eindex; i++)
1009     {
1010       if (pass_next)
1011         {
1012           pass_next = 0;
1013           if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
1014             CQ_RETURN(1);
1015           continue;
1016         }
1017       else if (string[i] == '\'' || string[i] == '"')
1018         {
1019           i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
1020                                   : skip_double_quoted (string, ++i);
1021           if (i > eindex)
1022             CQ_RETURN(1);
1023           i--;  /* the skip functions increment past the closing quote. */
1024         }
1025       else if (string[i] == '\\')
1026         {
1027           pass_next = 1;
1028           continue;
1029         }
1030     }
1031   CQ_RETURN(0);
1032 }
1033
1034 int
1035 unclosed_pair (string, eindex, openstr)
1036      char *string;
1037      int eindex;
1038      char *openstr;
1039 {
1040   int i, pass_next, openc, olen;
1041
1042   olen = strlen (openstr);
1043   for (i = pass_next = openc = 0; i <= eindex; i++)
1044     {
1045       if (pass_next)
1046         {
1047           pass_next = 0;
1048           if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
1049             return 0;
1050           continue;
1051         }
1052       else if (STREQN (string + i, openstr, olen))
1053         {
1054           openc = 1 - openc;
1055           i += olen - 1;
1056         }
1057       else if (string[i] == '\'' || string[i] == '"')
1058         {
1059           i = (string[i] == '\'') ? skip_single_quoted (string, i)
1060                                   : skip_double_quoted (string, i);
1061           if (i > eindex)
1062             return 0;
1063         }
1064       else if (string[i] == '\\')
1065         {
1066           pass_next = 1;
1067           continue;
1068         }
1069     }
1070   return (openc);
1071 }
1072 #endif /* READLINE */
1073
1074 #if 0
1075 /* UNUSED */
1076 /* Extract the name of the variable to bind to from the assignment string. */
1077 char *
1078 assignment_name (string)
1079      char *string;
1080 {
1081   int offset;
1082   char *temp;
1083
1084   offset = assignment (string);
1085   if (offset == 0)
1086     return (char *)NULL;
1087   temp = xmalloc (offset + 1);
1088   strncpy (temp, string, offset);
1089   temp[offset] = '\0';
1090   return (temp);
1091 }
1092 #endif
1093
1094 /* **************************************************************** */
1095 /*                                                                  */
1096 /*     Functions to convert strings to WORD_LISTs and vice versa    */
1097 /*                                                                  */
1098 /* **************************************************************** */
1099
1100 /* Return a single string of all the words in LIST.  SEP is the separator
1101    to put between individual elements of LIST in the output string. */
1102 static char *
1103 string_list_internal (list, sep)
1104      WORD_LIST *list;
1105      char *sep;
1106 {
1107   register WORD_LIST *t;
1108   char *result, *r;
1109   int word_len, sep_len, result_size;
1110
1111   if (list == 0)
1112     return ((char *)NULL);
1113
1114   /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1115   sep_len = STRLEN (sep);
1116   result_size = 0;
1117
1118   for (t = list; t; t = t->next)
1119     {
1120       if (t != list)
1121         result_size += sep_len;
1122       result_size += strlen (t->word->word);
1123     }
1124
1125   r = result = xmalloc (result_size + 1);
1126
1127   for (t = list; t; t = t->next)
1128     {
1129       if (t != list && sep_len)
1130         {
1131           if (sep_len > 1)
1132             {
1133               FASTCOPY (sep, r, sep_len);
1134               r += sep_len;
1135             }
1136           else
1137             *r++ = sep[0];
1138         }
1139
1140       word_len = strlen (t->word->word);
1141       FASTCOPY (t->word->word, r, word_len);
1142       r += word_len;
1143     }
1144
1145   *r = '\0';
1146   return (result);
1147 }
1148
1149 /* Return a single string of all the words present in LIST, separating
1150    each word with a space. */
1151 char *
1152 string_list (list)
1153      WORD_LIST *list;
1154 {
1155   return (string_list_internal (list, " "));
1156 }
1157
1158 /* Return a single string of all the words present in LIST, obeying the
1159    quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1160    expansion [of $*] appears within a double quoted string, it expands
1161    to a single field with the value of each parameter separated by the
1162    first character of the IFS variable, or by a <space> if IFS is unset." */
1163 static char *
1164 string_list_dollar_star (list)
1165      WORD_LIST *list;
1166 {
1167   char *ifs, sep[2];
1168
1169   ifs = get_string_value ("IFS");
1170
1171   sep[0] = (ifs == 0) ? ' ' : *ifs;
1172   sep[1] = '\0';
1173
1174   return (string_list_internal (list, sep));
1175 }
1176
1177 /* Turn $@ into a string.  If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1178    is non-zero, the $@ appears within double quotes, and we should quote
1179    the list before converting it into a string.  If IFS is unset, and the
1180    word is not quoted, we just need to quote CTLESC and CTLNUL characters
1181    in the words in the list, because the default value of $IFS is
1182    <space><tab><newline>, IFS characters in the words in the list should
1183    also be split.  If IFS is null, and the word is not quoted, we need
1184    to quote the words in the list to preserve the positional parameters
1185    exactly. */
1186 static char *
1187 string_list_dollar_at (list, quoted)
1188      WORD_LIST *list;
1189      int quoted;
1190 {
1191   char *ifs, sep[2];
1192   WORD_LIST *tlist;
1193
1194   ifs = get_string_value ("IFS");
1195
1196   sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1197   sep[1] = '\0';
1198
1199   tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1200                 ? quote_list (list)
1201                 : list_quote_escapes (list);
1202   return (string_list_internal (tlist, sep));
1203 }
1204
1205 /* Return the list of words present in STRING.  Separate the string into
1206    words at any of the characters found in SEPARATORS.  If QUOTED is
1207    non-zero then word in the list will have its quoted flag set, otherwise
1208    the quoted flag is left as make_word () deemed fit.
1209
1210    This obeys the P1003.2 word splitting semantics.  If `separators' is
1211    exactly <space><tab><newline>, then the splitting algorithm is that of
1212    the Bourne shell, which treats any sequence of characters from `separators'
1213    as a delimiter.  If IFS is unset, which results in `separators' being set
1214    to "", no splitting occurs.  If separators has some other value, the
1215    following rules are applied (`IFS white space' means zero or more
1216    occurrences of <space>, <tab>, or <newline>, as long as those characters
1217    are in `separators'):
1218
1219         1) IFS white space is ignored at the start and the end of the
1220            string.
1221         2) Each occurrence of a character in `separators' that is not
1222            IFS white space, along with any adjacent occurrences of
1223            IFS white space delimits a field.
1224         3) Any nonzero-length sequence of IFS white space delimits a field.
1225    */
1226
1227 /* BEWARE!  list_string strips null arguments.  Don't call it twice and
1228    expect to have "" preserved! */
1229
1230 /* This performs word splitting and quoted null character removal on
1231    STRING. */
1232 #define issep(c)        (member ((c), separators))
1233
1234 WORD_LIST *
1235 list_string (string, separators, quoted)
1236      register char *string, *separators;
1237      int quoted;
1238 {
1239   WORD_LIST *result;
1240   WORD_DESC *t;
1241   char *current_word, *s;
1242   int sindex, sh_style_split;
1243
1244   if (!string || !*string)
1245     return ((WORD_LIST *)NULL);
1246
1247   sh_style_split =
1248     separators && *separators && (STREQ (separators, " \t\n"));
1249
1250   /* Remove sequences of whitespace at the beginning of STRING, as
1251      long as those characters appear in IFS.  Do not do this if
1252      STRING is quoted or if there are no separator characters. */
1253   if (!quoted || !separators || !*separators)
1254     {
1255       for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1256
1257       if (!*s)
1258         return ((WORD_LIST *)NULL);
1259
1260       string = s;
1261     }
1262
1263   /* OK, now STRING points to a word that does not begin with white space.
1264      The splitting algorithm is:
1265         extract a word, stopping at a separator
1266         skip sequences of spc, tab, or nl as long as they are separators
1267      This obeys the field splitting rules in Posix.2. */
1268   for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1269     {
1270       current_word = string_extract_verbatim (string, &sindex, separators);
1271       if (current_word == 0)
1272         break;
1273
1274       /* If we have a quoted empty string, add a quoted null argument.  We
1275          want to preserve the quoted null character iff this is a quoted
1276          empty string; otherwise the quoted null characters are removed
1277          below. */
1278       if (QUOTED_NULL (current_word))
1279         {
1280           t = make_bare_word ("");
1281           t->flags |= W_QUOTED;
1282           free (t->word);
1283           t->word = make_quoted_char ('\0');
1284           result = make_word_list (t, result);
1285         }
1286       else if (current_word[0] != '\0')
1287         {
1288           /* If we have something, then add it regardless.  However,
1289              perform quoted null character removal on the current word. */
1290           remove_quoted_nulls (current_word);
1291 #if 0
1292           result = make_word_list (make_word (current_word), result);
1293 #else
1294           result = add_string_to_list (current_word, result);
1295 #endif    
1296           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1297             result->word->flags |= W_QUOTED;
1298         }
1299
1300       /* If we're not doing sequences of separators in the traditional
1301          Bourne shell style, then add a quoted null argument. */
1302       else if (!sh_style_split && !spctabnl (string[sindex]))
1303         {
1304           t = make_bare_word ("");
1305           t->flags |= W_QUOTED;
1306           free (t->word);
1307           t->word = make_quoted_char ('\0');
1308           result = make_word_list (t, result);
1309         }
1310
1311       free (current_word);
1312
1313       /* Move past the current separator character. */
1314       if (string[sindex])
1315         sindex++;
1316
1317       /* Now skip sequences of space, tab, or newline characters if they are
1318          in the list of separators. */
1319       while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1320         sindex++;
1321     }
1322   return (REVERSE_LIST (result, WORD_LIST *));
1323 }
1324
1325 /* Parse a single word from STRING, using SEPARATORS to separate fields.
1326    ENDPTR is set to the first character after the word.  This is used by
1327    the `read' builtin.
1328    XXX - this function is very similar to list_string; they should be
1329          combined - XXX */
1330 char *
1331 get_word_from_string (stringp, separators, endptr)
1332      char **stringp, *separators, **endptr;
1333 {
1334   register char *s;
1335   char *current_word;
1336   int sindex, sh_style_split;
1337
1338   if (!stringp || !*stringp || !**stringp)
1339     return ((char *)NULL);
1340
1341   s = *stringp;
1342
1343   sh_style_split =
1344     separators && *separators && (STREQ (separators, " \t\n"));
1345
1346   /* Remove sequences of whitespace at the beginning of STRING, as
1347      long as those characters appear in IFS. */
1348   if (sh_style_split || !separators || !*separators)
1349     {
1350       for (; *s && spctabnl (*s) && issep (*s); s++);
1351
1352       /* If the string is nothing but whitespace, update it and return. */
1353       if (!*s)
1354         {
1355           *stringp = s;
1356           if (endptr)
1357             *endptr = s;
1358           return ((char *)NULL);
1359         }
1360     }
1361
1362   /* OK, S points to a word that does not begin with white space.
1363      Now extract a word, stopping at a separator, save a pointer to
1364      the first character after the word, then skip sequences of spc,
1365      tab, or nl as long as they are separators.
1366
1367      This obeys the field splitting rules in Posix.2. */
1368   sindex = 0;
1369   current_word = string_extract_verbatim (s, &sindex, separators);
1370
1371   /* Set ENDPTR to the first character after the end of the word. */
1372   if (endptr)
1373     *endptr = s + sindex;
1374
1375   /* Move past the current separator character. */
1376   if (s[sindex])
1377     sindex++;
1378
1379   /* Now skip sequences of space, tab, or newline characters if they are
1380      in the list of separators. */
1381   while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1382     sindex++;
1383
1384   /* Update STRING to point to the next field. */
1385   *stringp = s + sindex;
1386   return (current_word);
1387 }
1388
1389 /* Remove IFS white space at the end of STRING.  Start at the end
1390    of the string and walk backwards until the beginning of the string
1391    or we find a character that's not IFS white space and not CTLESC.
1392    Only let CTLESC escape a white space character if SAW_ESCAPE is
1393    non-zero.  */
1394 char *
1395 strip_trailing_ifs_whitespace (string, separators, saw_escape)
1396      char *string, *separators;
1397      int saw_escape;
1398 {
1399   char *s;
1400
1401   s = string + STRLEN (string) - 1;
1402   while (s > string && ((spctabnl (*s) && issep (*s)) ||
1403                         (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1404     s--;
1405   *++s = '\0';
1406   return string;
1407 }
1408
1409 #if defined (ARRAY_VARS)
1410 WORD_LIST *
1411 list_string_with_quotes (string)
1412      char *string;
1413 {
1414   WORD_LIST *list;
1415   char *token, *s;
1416   int c, i, tokstart, len;
1417
1418   for (s = string; s && *s && spctabnl (*s); s++)
1419     ;
1420   if (s == 0 || *s == 0)
1421     return ((WORD_LIST *)NULL);
1422
1423   tokstart = i = 0;
1424   list = (WORD_LIST *)NULL;
1425   while (1)
1426     {
1427       c = s[i];
1428       if (c == '\\')
1429         {
1430           i++;
1431           if (s[i])
1432             i++;
1433         }
1434       else if (c == '\'')
1435         i = skip_single_quoted (s, ++i);
1436       else if (c == '"')
1437         i = skip_double_quoted (s, ++i);
1438       else if (c == 0 || spctabnl (c))
1439         {
1440           /* We have found the end of a token.  Make a word out of it and
1441              add it to the word list. */
1442           len = i - tokstart;
1443           token = xmalloc (len + 1);
1444           strncpy (token, s + tokstart, len);
1445           token[len] = '\0';
1446 #if 0
1447           list = make_word_list (make_word (token), list);
1448 #else
1449           list = add_string_to_list (token, list);
1450 #endif
1451           free (token);
1452           while (spctabnl (s[i]))
1453             i++;
1454           if (s[i])
1455             tokstart = i;
1456           else
1457             break;
1458         }
1459       else
1460         i++;    /* normal character */
1461     }
1462   return (REVERSE_LIST (list, WORD_LIST *));
1463 }
1464 #endif /* ARRAY_VARS */
1465
1466 /********************************************************/
1467 /*                                                      */
1468 /*      Functions to perform assignment statements      */
1469 /*                                                      */
1470 /********************************************************/
1471
1472 #if defined (ARRAY_VARS)
1473 SHELL_VAR *
1474 do_array_element_assignment (name, value)
1475      char *name, *value;
1476 {
1477   char *t;
1478   int ind, ni;
1479   SHELL_VAR *entry;
1480
1481   t = strchr (name, '[');
1482   if (t == 0)
1483     return ((SHELL_VAR *)NULL);
1484   ind = t - name;
1485   ni = skipsubscript (name, ind);
1486   if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= ind + 1))
1487     {
1488       report_error ("%s: bad array subscript", name);
1489       return ((SHELL_VAR *)NULL);
1490     }
1491   *t++ = '\0';
1492   ind = array_expand_index (t, ni - ind);
1493   if (ind < 0)
1494     {
1495       t[-1] = '[';              /* restore original name */
1496       report_error ("%s: bad array subscript", name);
1497       return ((SHELL_VAR *)NULL);
1498     }
1499   entry = bind_array_variable (name, ind, value);
1500   t[-1] = '[';          /* restore original name */
1501   return (entry);
1502 }
1503 #endif /* ARRAY_VARS */
1504
1505 /* Given STRING, an assignment string, get the value of the right side
1506    of the `=', and bind it to the left side.  If EXPAND is true, then
1507    perform parameter expansion, command substitution, and arithmetic
1508    expansion on the right-hand side.  Perform tilde expansion in any
1509    case.  Do not perform word splitting on the result of expansion. */
1510 static int
1511 do_assignment_internal (string, expand)
1512      char *string;
1513      int expand;
1514 {
1515   int offset;
1516   char *name, *value;
1517   SHELL_VAR *entry;
1518 #if defined (ARRAY_VARS)
1519   char *t;
1520   int ni, assign_list = 0;
1521 #endif
1522
1523   offset = assignment (string);
1524   name = savestring (string);
1525   value = (char *)NULL;
1526
1527   if (name[offset] == '=')
1528     {
1529       char *temp;
1530
1531       name[offset] = 0;
1532       temp = name + offset + 1;
1533
1534 #if defined (ARRAY_VARS)
1535       if (expand && temp[0] == LPAREN && strchr (temp, RPAREN))
1536         {
1537           assign_list = ni = 1;
1538           value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")");
1539         }
1540       else
1541 #endif
1542
1543       /* Perform tilde expansion. */
1544       if (expand && temp[0])
1545         {
1546           temp = (strchr (temp, '~') && unquoted_member ('~', temp))
1547                         ? bash_tilde_expand (temp)
1548                         : savestring (temp);
1549
1550           value = maybe_expand_string (temp, 0, expand_string_unsplit);
1551           free (temp);
1552         }
1553       else
1554         value = savestring (temp);
1555     }
1556
1557   if (value == 0)
1558     {
1559       value = xmalloc (1);
1560       value[0] = '\0';
1561     }
1562
1563   if (echo_command_at_execute)
1564 #if defined (ARRAY_VARS)
1565     if (assign_list)
1566       fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
1567     else
1568 #endif
1569     fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1570
1571 #define ASSIGN_RETURN(r)        do { FREE (value); free (name); return (r); } while (0)
1572
1573 #if defined (ARRAY_VARS)
1574   if (t = strchr (name, '['))
1575     {
1576       if (assign_list)
1577         {
1578           report_error ("%s: cannot assign list to array member", name);
1579           ASSIGN_RETURN (0);
1580         }
1581       entry = do_array_element_assignment (name, value);
1582       if (entry == 0)
1583         ASSIGN_RETURN (0);
1584     }
1585   else if (assign_list)
1586     entry = assign_array_from_string (name, value);
1587   else
1588 #endif /* ARRAY_VARS */
1589   entry = bind_variable (name, value);
1590
1591   stupidly_hack_special_variables (name);
1592
1593   if (entry)
1594     entry->attributes &= ~att_invisible;
1595
1596   /* Return 1 if the assignment seems to have been performed correctly. */
1597   ASSIGN_RETURN (entry ? ((entry->attributes & att_readonly) == 0) : 0);
1598 }
1599
1600 /* Perform the assignment statement in STRING, and expand the
1601    right side by doing command and parameter expansion. */
1602 int
1603 do_assignment (string)
1604      char *string;
1605 {
1606   return do_assignment_internal (string, 1);
1607 }
1608
1609 /* Given STRING, an assignment string, get the value of the right side
1610    of the `=', and bind it to the left side.  Do not do command and
1611    parameter substitution on the right hand side. */
1612 int
1613 do_assignment_no_expand (string)
1614      char *string;
1615 {
1616   return do_assignment_internal (string, 0);
1617 }
1618
1619 /***************************************************
1620  *                                                 *
1621  *  Functions to manage the positional parameters  *
1622  *                                                 *
1623  ***************************************************/
1624
1625 /* Return the word list that corresponds to `$*'. */
1626 WORD_LIST *
1627 list_rest_of_args ()
1628 {
1629   register WORD_LIST *list, *args;
1630   int i;
1631
1632   /* Break out of the loop as soon as one of the dollar variables is null. */
1633   for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
1634     list = make_word_list (make_bare_word (dollar_vars[i]), list);
1635
1636   for (args = rest_of_args; args; args = args->next)
1637     list = make_word_list (make_bare_word (args->word->word), list);
1638
1639   return (REVERSE_LIST (list, WORD_LIST *));
1640 }
1641
1642 int
1643 number_of_args ()
1644 {
1645   register WORD_LIST *list;
1646   int n;
1647
1648   for (n = 0; n < 9 && dollar_vars[n+1]; n++)
1649     ;
1650   for (list = rest_of_args; list; list = list->next)
1651     n++;
1652   return n;
1653 }
1654
1655 /* Return the value of a positional parameter.  This handles values > 10. */
1656 char *
1657 get_dollar_var_value (ind)
1658      int ind;
1659 {
1660   char *temp;
1661   WORD_LIST *p;
1662
1663   if (ind < 10)
1664     temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
1665   else  /* We want something like ${11} */
1666     {
1667       ind -= 10;
1668       for (p = rest_of_args; p && ind--; p = p->next)
1669         ;
1670       temp = p ? savestring (p->word->word) : (char *)NULL;
1671     }
1672   return (temp);
1673 }
1674
1675 /* Make a single large string out of the dollar digit variables,
1676    and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
1677    case of "$*" with respect to IFS. */
1678 char *
1679 string_rest_of_args (dollar_star)
1680      int dollar_star;
1681 {
1682   register WORD_LIST *list;
1683   char *string;
1684
1685   list = list_rest_of_args ();
1686   string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1687   dispose_words (list);
1688   return (string);
1689 }
1690
1691 /* Return a string containing the positional parameters from START to
1692    END, inclusive.  If STRING[0] == '*', we obey the rules for $*,
1693    which only makes a difference if QUOTED is non-zero. */
1694 static char *
1695 pos_params (string, start, end, quoted)
1696      char *string;
1697      int start, end, quoted;
1698 {
1699   WORD_LIST *save, *params, *h, *t;
1700   char *ret;
1701   int i;
1702
1703   save = params = list_rest_of_args ();
1704   if (save == 0)
1705     return ((char *)NULL);
1706
1707   for (i = 1; params && i < start; i++)
1708     params = params->next;
1709   if (params == 0)
1710     return ((char *)NULL);
1711   for (h = t = params; params && i < end; i++)
1712     {
1713       t = params;
1714       params = params->next;
1715     }
1716
1717   t->next = (WORD_LIST *)NULL;
1718   if (string[0] == '*')
1719     ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h);
1720   else
1721     ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
1722   t->next = params;
1723
1724   dispose_words (save);
1725   return (ret);
1726 }
1727
1728 /******************************************************************/
1729 /*                                                                */
1730 /*      Functions to expand strings to strings or WORD_LISTs      */
1731 /*                                                                */
1732 /******************************************************************/
1733
1734 #if defined (PROCESS_SUBSTITUTION)
1735 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1736 #else
1737 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1738 #endif
1739
1740 /* If there are any characters in STRING that require full expansion,
1741    then call FUNC to expand STRING; otherwise just perform quote
1742    removal if necessary.  This returns a new string. */
1743 static char *
1744 maybe_expand_string (string, quoted, func)
1745      char *string;
1746      int quoted;
1747      WORD_LIST *(*func)();
1748 {
1749   WORD_LIST *list;
1750   int i, saw_quote;
1751   char *ret;
1752
1753   for (i = saw_quote = 0; string[i]; i++)
1754     {
1755       if (EXP_CHAR (string[i]))
1756         break;
1757       else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1758         saw_quote = 1;
1759     }
1760
1761   if (string[i])
1762     {
1763       list = (*func) (string, quoted);
1764       if (list)
1765         {
1766           ret = string_list (list);
1767           dispose_words (list);
1768         }
1769       else
1770         ret = (char *)NULL;
1771     }
1772   else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
1773     ret = string_quote_removal (string, quoted);
1774   else
1775     ret = savestring (string);
1776   return ret;
1777 }
1778
1779 static inline char *
1780 expand_string_to_string (string, quoted, func)
1781      char *string;
1782      int quoted;
1783      WORD_LIST *(*func)();
1784 {
1785   WORD_LIST *list;
1786   char *ret;
1787
1788   if (string == 0 || *string == '\0')
1789     return ((char *)NULL);
1790
1791   list = (*func) (string, quoted);
1792   if (list)
1793     {
1794       ret = string_list (list);
1795       dispose_words (list);
1796     }
1797   else
1798     ret = (char *)NULL;
1799
1800   return (ret);
1801 }
1802
1803 #if defined (COND_COMMAND)
1804 /* Just remove backslashes in STRING.  Returns a new string. */
1805 char *
1806 remove_backslashes (string)
1807      char *string;
1808 {
1809   char *r, *ret, *s;
1810
1811   r = ret = xmalloc (strlen (string) + 1);
1812   for (s = string; s && *s; )
1813     {
1814       if (*s == '\\')
1815         s++;
1816       if (*s == 0)
1817         break;
1818       *r++ = *s++;
1819     }
1820   *r = '\0';
1821   return ret;
1822 }
1823
1824 /* This needs better error handling. */
1825 /* Expand W for use as an argument to a unary or binary operator in a
1826    [[...]] expression.  If SPECIAL is nonzero, this is the rhs argument
1827    to the != or == operator, and should be treated as a pattern.  In
1828    this case, we quote the string specially for the globbing code.  The
1829    caller is responsible for removing the backslashes if the unquoted
1830    words is needed later. */   
1831 char *
1832 cond_expand_word (w, special)
1833      WORD_DESC *w;
1834      int special;
1835 {
1836   char *r, *p;
1837   WORD_LIST *l;
1838
1839   if (w->word == 0 || w->word[0] == '\0')
1840     return ((char *)NULL);
1841
1842   l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
1843   if (l)
1844     {
1845       if (special == 0)
1846         {
1847           dequote_list (l);
1848           r = string_list (l);
1849         }
1850       else
1851         {
1852           p = string_list (l);
1853           r = quote_string_for_globbing (p, QGLOB_CVTNULL);
1854           free (p);
1855         }
1856       dispose_words (l);
1857     }
1858   else
1859     r = (char *)NULL;
1860
1861   return r;
1862 }
1863 #endif
1864
1865 /* Call expand_word_internal to expand W and handle error returns.
1866    A convenience function for functions that don't want to handle
1867    any errors or free any memory before aborting. */
1868 static WORD_LIST *
1869 call_expand_word_internal (w, q, i, c, e)
1870      WORD_DESC *w;
1871      int q, i, *c, *e;
1872 {
1873   WORD_LIST *result;
1874
1875   result = expand_word_internal (w, q, i, c, e);
1876   if (result == &expand_word_error)
1877     {
1878       /* By convention, each time this error is returned, w->word has
1879          already been freed. */
1880       w->word = (char *)NULL;
1881       jump_to_top_level (DISCARD);
1882       /* NOTREACHED */
1883     }
1884   else if (result == &expand_word_fatal)
1885     jump_to_top_level (FORCE_EOF);
1886     /* NOTREACHED */
1887   else
1888     return (result);
1889 }
1890
1891 /* Perform parameter expansion, command substitution, and arithmetic
1892    expansion on STRING, as if it were a word.  Leave the result quoted. */
1893 static WORD_LIST *
1894 expand_string_internal (string, quoted)
1895      char *string;
1896      int quoted;
1897 {
1898   WORD_DESC td;
1899   WORD_LIST *tresult;
1900
1901   if (string == 0 || *string == 0)
1902     return ((WORD_LIST *)NULL);
1903
1904   bzero ((char *)&td, sizeof (td));
1905   td.word = string;
1906   tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
1907   return (tresult);
1908 }
1909
1910 /* Expand STRING by performing parameter expansion, command substitution,
1911    and arithmetic expansion.  Dequote the resulting WORD_LIST before
1912    returning it, but do not perform word splitting.  The call to
1913    remove_quoted_nulls () is in here because word splitting normally
1914    takes care of quote removal. */
1915 WORD_LIST *
1916 expand_string_unsplit (string, quoted)
1917      char *string;
1918      int quoted;
1919 {
1920   WORD_LIST *value;
1921
1922   if (!string || !*string)
1923     return ((WORD_LIST *)NULL);
1924
1925   value = expand_string_internal (string, quoted);
1926   if (value)
1927     {
1928       if (value->word)
1929         remove_quoted_nulls (value->word->word);
1930       dequote_list (value);
1931     }
1932   return (value);
1933 }
1934
1935 /* Expand STRING just as if you were expanding a word, but do not dequote
1936    the resultant WORD_LIST.  This is called only from within this file,
1937    and is used to correctly preserve quoted characters when expanding
1938    things like ${1+"$@"}.  This does parameter expansion, command
1939    substitution, arithmetic expansion, and word splitting. */
1940 static WORD_LIST *
1941 expand_string_leave_quoted (string, quoted)
1942      char *string;
1943      int quoted;
1944 {
1945   WORD_LIST *tlist;
1946   WORD_LIST *tresult;
1947
1948   if (string == 0 || *string == '\0')
1949     return ((WORD_LIST *)NULL);
1950
1951   tlist = expand_string_internal (string, quoted);
1952
1953   if (tlist)
1954     {
1955       tresult = word_list_split (tlist);
1956       dispose_words (tlist);
1957       return (tresult);
1958     }
1959   return ((WORD_LIST *)NULL);
1960 }
1961
1962 /* This does not perform word splitting or dequote the WORD_LIST
1963    it returns. */
1964 static WORD_LIST *
1965 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
1966      char *string;
1967      int quoted, *dollar_at_p, *has_dollar_at;
1968 {
1969   WORD_DESC td;
1970   WORD_LIST *tresult;
1971
1972   if (string == 0 || *string == '\0')
1973     return (WORD_LIST *)NULL;
1974
1975   bzero ((char *)&td, sizeof (td));
1976   td.word = string;
1977   tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
1978   return (tresult);
1979 }
1980
1981 /* Expand STRING just as if you were expanding a word.  This also returns
1982    a list of words.  Note that filename globbing is *NOT* done for word
1983    or string expansion, just when the shell is expanding a command.  This
1984    does parameter expansion, command substitution, arithmetic expansion,
1985    and word splitting.  Dequote the resultant WORD_LIST before returning. */
1986 WORD_LIST *
1987 expand_string (string, quoted)
1988      char *string;
1989      int quoted;
1990 {
1991   WORD_LIST *result;
1992
1993   if (!string || !*string)
1994     return ((WORD_LIST *)NULL);
1995
1996   result = expand_string_leave_quoted (string, quoted);
1997   return (result ? dequote_list (result) : result);
1998 }
1999
2000 /***************************************************
2001  *                                                 *
2002  *      Functions to handle quoting chars          *
2003  *                                                 *
2004  ***************************************************/
2005
2006 /* Conventions:
2007
2008      A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
2009      The parser passes CTLNUL as CTLESC CTLNUL. */
2010
2011 /* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2012    This is necessary to make unquoted CTLESC and CTLNUL characters in the
2013    data stream pass through properly.
2014    Here we remove doubled CTLESC characters inside quoted strings before
2015    quoting the entire string, so we do not double the number of CTLESC
2016    characters. */
2017 static char *
2018 remove_quoted_escapes (string)
2019      char *string;
2020 {
2021   register char *s;
2022   int docopy;
2023   char *t, *t1;
2024
2025   if (string == NULL)
2026     return (string);
2027
2028   t1 = t = xmalloc (strlen (string) + 1);
2029   for (docopy = 0, s = string; *s; s++, t1++)
2030     {
2031       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2032         {
2033           s++;
2034           docopy = 1;
2035         }
2036       *t1 = *s;
2037     }
2038   *t1 = '\0';
2039   if (docopy)
2040     strcpy (string, t);
2041   free (t);
2042   return (string);
2043 }
2044
2045 /* Quote escape characters in string s, but no other characters.  This is
2046    used to protect CTLESC and CTLNUL in variable values from the rest of
2047    the word expansion process after the variable is expanded. */
2048 static char *
2049 quote_escapes (string)
2050      char *string;
2051 {
2052   register char *s, *t;
2053   char *result;
2054
2055   result = xmalloc ((strlen (string) * 2) + 1);
2056   for (s = string, t = result; *s; )
2057     {
2058       if (*s == CTLESC || *s == CTLNUL)
2059         *t++ = CTLESC;
2060       *t++ = *s++;
2061     }
2062   *t = '\0';
2063   return (result);
2064 }
2065
2066 static WORD_LIST *
2067 list_quote_escapes (list)
2068      WORD_LIST *list;
2069 {
2070   register WORD_LIST *w;
2071   char *t;
2072
2073   for (w = list; w; w = w->next)
2074     {
2075       t = w->word->word;
2076       w->word->word = quote_escapes (t);
2077       free (t);
2078     }
2079   return list;
2080 }
2081
2082 #ifdef INCLUDE_UNUSED
2083 static char *
2084 dequote_escapes (string)
2085      char *string;
2086 {
2087   register char *s, *t;
2088   char *result;
2089
2090   result = xmalloc (strlen (string) + 1);
2091   for (s = string, t = result; *s; )
2092     {
2093       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2094         {
2095           s++;
2096           if (*s == '\0')
2097             break;
2098         }
2099       *t++ = *s++;
2100     }
2101   *t = '\0';
2102   return result;
2103 }
2104 #endif
2105
2106 static WORD_LIST *
2107 dequote_list (list)
2108      WORD_LIST *list;
2109 {
2110   register char *s;
2111   register WORD_LIST *tlist;
2112
2113   for (tlist = list; tlist; tlist = tlist->next)
2114     {
2115       s = dequote_string (tlist->word->word);
2116       free (tlist->word->word);
2117       tlist->word->word = s;
2118     }
2119   return list;
2120 }
2121
2122 static char *
2123 make_quoted_char (c)
2124      int c;
2125 {
2126   char *temp;
2127
2128   temp = xmalloc (3);
2129   if (c == 0)
2130     {
2131       temp[0] = CTLNUL;
2132       temp[1] = '\0';
2133     }
2134   else
2135     {
2136       temp[0] = CTLESC;
2137       temp[1] = c;
2138       temp[2] = '\0';
2139     }
2140   return (temp);
2141 }
2142
2143 /* Quote STRING.  Return a new string. */
2144 char *
2145 quote_string (string)
2146      char *string;
2147 {
2148   register char *t;
2149   char *result;
2150
2151   if (*string == 0)
2152     {
2153       result = xmalloc (2);
2154       result[0] = CTLNUL;
2155       result[1] = '\0';
2156     }
2157   else
2158     {
2159       result = xmalloc ((strlen (string) * 2) + 1);
2160
2161       for (t = result; *string; )
2162         {
2163           *t++ = CTLESC;
2164           *t++ = *string++;
2165         }
2166       *t = '\0';
2167     }
2168   return (result);
2169 }
2170
2171 /* De-quoted quoted characters in STRING. */
2172 char *
2173 dequote_string (string)
2174      char *string;
2175 {
2176   register char *t;
2177   char *result;
2178
2179   result = xmalloc (strlen (string) + 1);
2180
2181   if (QUOTED_NULL (string))
2182     {
2183       result[0] = '\0';
2184       return (result);
2185     }
2186
2187   /* If no character in the string can be quoted, don't bother examining
2188      each character.  Just return a copy of the string passed to us. */
2189   if (strchr (string, CTLESC) == NULL)          /* XXX */
2190     {                                           /* XXX */
2191       strcpy (result, string);                  /* XXX */
2192       return (result);                          /* XXX */
2193     }
2194
2195   for (t = result; *string; string++, t++)
2196     {
2197       if (*string == CTLESC)
2198         {
2199           string++;
2200
2201           if (!*string)
2202             break;
2203         }
2204
2205       *t = *string;
2206     }
2207
2208   *t = '\0';
2209   return (result);
2210 }
2211
2212 /* Quote the entire WORD_LIST list. */
2213 static WORD_LIST *
2214 quote_list (list)
2215      WORD_LIST *list;
2216 {
2217   register WORD_LIST *w;
2218   char *t;
2219
2220   for (w = list; w; w = w->next)
2221     {
2222       t = w->word->word;
2223       w->word->word = quote_string (t);
2224       free (t);
2225       w->word->flags |= W_QUOTED;
2226     }
2227   return list;
2228 }
2229
2230 /* Perform quoted null character removal on STRING.  We don't allow any
2231    quoted null characters in the middle or at the ends of strings because
2232    of how expand_word_internal works.  remove_quoted_nulls () turns
2233    STRING into an empty string iff it only consists of a quoted null,
2234    and removes all unquoted CTLNUL characters. */
2235 /*
2236 #define remove_quoted_nulls(string) \
2237   do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
2238 */
2239 static void
2240 remove_quoted_nulls (string)
2241      char *string;
2242 {
2243   char *nstr, *s, *p;
2244
2245   nstr = savestring (string);
2246   nstr[0] = '\0';
2247   for (p = nstr, s = string; *s; s++)
2248     {
2249       if (*s == CTLESC)
2250         {
2251           *p++ = *s++;  /* CTLESC */
2252           if (*s == 0)
2253             break;
2254           *p++ = *s;    /* quoted char */
2255           continue;
2256         }
2257       if (*s == CTLNUL)
2258         continue;
2259       *p++ = *s;
2260     }
2261   *p = '\0';
2262   strcpy (string, nstr);
2263   free (nstr);
2264 }
2265
2266 /* Perform quoted null character removal on each element of LIST.
2267    This modifies LIST. */
2268 void
2269 word_list_remove_quoted_nulls (list)
2270      WORD_LIST *list;
2271 {
2272   register WORD_LIST *t;
2273
2274   for (t = list; t; t = t->next)
2275     remove_quoted_nulls (t->word->word);
2276 }
2277
2278 /* **************************************************************** */
2279 /*                                                                  */
2280 /*         Functions for Matching and Removing Patterns             */
2281 /*                                                                  */
2282 /* **************************************************************** */
2283
2284 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
2285    can have one of 4 values:
2286         RP_LONG_LEFT    remove longest matching portion at start of PARAM
2287         RP_SHORT_LEFT   remove shortest matching portion at start of PARAM
2288         RP_LONG_RIGHT   remove longest matching portion at end of PARAM
2289         RP_SHORT_RIGHT  remove shortest matching portion at end of PARAM
2290 */
2291
2292 #define RP_LONG_LEFT    1
2293 #define RP_SHORT_LEFT   2
2294 #define RP_LONG_RIGHT   3
2295 #define RP_SHORT_RIGHT  4
2296
2297 static char *
2298 remove_pattern (param, pattern, op)
2299      char *param, *pattern;
2300      int op;
2301 {
2302   register int len;
2303   register char *end;
2304   register char *p, *ret, c;
2305
2306   if (param == NULL || *param == '\0')
2307     return (param);
2308   if (pattern == NULL || *pattern == '\0')      /* minor optimization */
2309     return (savestring (param));
2310
2311   len = STRLEN (param);
2312   end = param + len;
2313
2314   switch (op)
2315     {
2316       case RP_LONG_LEFT:        /* remove longest match at start */
2317         for (p = end; p >= param; p--)
2318           {
2319             c = *p; *p = '\0';
2320             if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2321               {
2322                 *p = c;
2323                 return (savestring (p));
2324               }
2325             *p = c;
2326           }
2327         break;
2328
2329       case RP_SHORT_LEFT:       /* remove shortest match at start */
2330         for (p = param; p <= end; p++)
2331           {
2332             c = *p; *p = '\0';
2333             if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2334               {
2335                 *p = c;
2336                 return (savestring (p));
2337               }
2338             *p = c;
2339           }
2340         break;
2341
2342       case RP_LONG_RIGHT:       /* remove longest match at end */
2343         for (p = param; p <= end; p++)
2344           {
2345             if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2346               {
2347                 c = *p; *p = '\0';
2348                 ret = savestring (param);
2349                 *p = c;
2350                 return (ret);
2351               }
2352           }
2353         break;
2354
2355       case RP_SHORT_RIGHT:      /* remove shortest match at end */
2356         for (p = end; p >= param; p--)
2357           {
2358             if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2359               {
2360                 c = *p; *p = '\0';
2361                 ret = savestring (param);
2362                 *p = c;
2363                 return (ret);
2364               }
2365           }
2366         break;
2367     }
2368   return (savestring (param));  /* no match, return original string */
2369 }
2370
2371 /* Return 1 of the first character of STRING could match the first
2372    character of pattern PAT.  Used to avoid n2 calls to fnmatch(). */
2373 static int
2374 match_pattern_char (pat, string)
2375      char *pat, *string;
2376 {
2377   char c;
2378
2379   if (*string == 0)
2380     return (0);
2381
2382   switch (c = *pat++)
2383     {
2384     default:
2385       return (*string == c);
2386     case '\\':
2387       return (*string == *pat);
2388     case '?':
2389       return (*string == LPAREN ? 1 : (*string != '\0'));
2390     case '*':
2391       return (1);
2392     case '+':
2393     case '!':
2394     case '@':
2395       return (*string == LPAREN ? 1 : (*string == c));
2396     case '[':
2397       return (*string != '\0');
2398     }
2399 }
2400
2401 /* Match PAT anywhere in STRING and return the match boundaries.
2402    This returns 1 in case of a successful match, 0 otherwise.  SP
2403    and EP are pointers into the string where the match begins and
2404    ends, respectively.  MTYPE controls what kind of match is attempted.
2405    MATCH_BEG and MATCH_END anchor the match at the beginning and end
2406    of the string, respectively.  The longest match is returned. */
2407 static int
2408 match_pattern (string, pat, mtype, sp, ep)
2409      char *string, *pat;
2410      int mtype;
2411      char **sp, **ep;
2412 {
2413   int c;
2414   register char *p, *p1;
2415   char *end;
2416
2417   if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
2418     return (0);
2419
2420   end = string + STRLEN (string);
2421
2422   switch (mtype)
2423     {
2424     case MATCH_ANY:
2425       for (p = string; p <= end; p++)
2426         {
2427           if (match_pattern_char (pat, p))
2428             {
2429               for (p1 = end; p1 >= p; p1--)
2430                 {
2431                   c = *p1; *p1 = '\0';
2432                   if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0)
2433                     {
2434                       *p1 = c;
2435                       *sp = p;
2436                       *ep = p1;
2437                       return 1;
2438                     }
2439                   *p1 = c;
2440                 }
2441             }
2442         }
2443       return (0);
2444
2445     case MATCH_BEG:
2446       if (match_pattern_char (pat, string) == 0)
2447         return (0);
2448       for (p = end; p >= string; p--)
2449         {
2450           c = *p; *p = '\0';
2451           if (fnmatch (pat, string, FNMATCH_EXTFLAG) == 0)
2452             {
2453               *p = c;
2454               *sp = string;
2455               *ep = p;
2456               return 1;
2457             }
2458           *p = c;
2459         }
2460       return (0);
2461
2462     case MATCH_END:
2463       for (p = string; p <= end; p++)
2464         if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0)
2465           {
2466             *sp = p;
2467             *ep = end;
2468             return 1;
2469           }
2470       return (0);
2471     }
2472
2473   return (0);
2474 }
2475
2476 static int
2477 getpatspec (c, value)
2478      int c;
2479      char *value;
2480 {
2481   if (c == '#')
2482     return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
2483   else  /* c == '%' */
2484     return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
2485 }
2486
2487 /* Posix.2 says that the WORD should be run through tilde expansion,
2488    parameter expansion, command substitution and arithmetic expansion.
2489    This leaves the result quoted, so quote_string_for_globbing () has
2490    to be called to fix it up for fnmatch ().  If QUOTED is non-zero,
2491    it means that the entire expression was enclosed in double quotes.
2492    This means that quoting characters in the pattern do not make any
2493    special pattern characters quoted.  For example, the `*' in the
2494    following retains its special meaning: "${foo#'*'}". */
2495 static char *
2496 getpattern (value, quoted, expandpat)
2497      char *value;
2498      int quoted, expandpat;
2499 {
2500   char *pat, *tword;
2501   WORD_LIST *l;
2502   int i;
2503
2504   tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value);
2505
2506   /* expand_string_internal () leaves WORD quoted and does not perform
2507      word splitting. */
2508   if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
2509     {
2510       i = 0;
2511       pat = string_extract_double_quoted (tword, &i, 1);
2512       free (tword);
2513       tword = pat;
2514     }
2515
2516   /* There is a problem here:  how to handle single or double quotes in the
2517      pattern string when the whole expression is between double quotes? */
2518 #if 0
2519   l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL)
2520 #else
2521   l = *tword ? expand_string_for_rhs (tword,
2522                                       (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted,
2523                                       (int *)NULL, (int *)NULL)
2524 #endif
2525              : (WORD_LIST *)0;
2526   free (tword);
2527   pat = string_list (l);
2528   dispose_words (l);
2529   if (pat)
2530     {
2531       tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
2532       free (pat);
2533       pat = tword;
2534     }
2535   return (pat);
2536 }
2537
2538 /* Handle removing a pattern from a string as a result of ${name%[%]value}
2539    or ${name#[#]value}. */
2540 static char *
2541 parameter_brace_remove_pattern (value, temp, c, quoted)
2542      char *value, *temp;
2543      int c, quoted;
2544 {
2545   int patspec;
2546   char *pattern, *tword;
2547
2548   patspec = getpatspec (c, value);
2549   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2550     value++;
2551
2552   pattern = getpattern (value, quoted, 1);
2553
2554   tword = remove_pattern (temp, pattern, patspec);
2555
2556   FREE (pattern);
2557   return (tword);
2558 }
2559
2560 static char *
2561 list_remove_pattern (list, pattern, patspec, type, quoted)
2562      WORD_LIST *list;
2563      char *pattern;
2564      int patspec, type, quoted;
2565 {
2566   WORD_LIST *new, *l;
2567   WORD_DESC *w;
2568   char *tword;
2569
2570   for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
2571     {
2572       tword = remove_pattern (l->word->word, pattern, patspec);
2573       w = make_bare_word (tword);
2574       free (tword);
2575       new = make_word_list (w, new);
2576     }
2577
2578   l = REVERSE_LIST (new, WORD_LIST *);
2579   if (type == '*')
2580     tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
2581   else
2582     tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
2583
2584   dispose_words (l);
2585   return (tword);
2586 }
2587
2588 static char *
2589 parameter_list_remove_pattern (value, type, c, quoted)
2590      char *value;
2591      int type, c, quoted;
2592 {
2593   int patspec;
2594   char *pattern, *ret;
2595   WORD_LIST *list;
2596
2597   patspec = getpatspec (c, value);
2598   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2599     value++;
2600
2601   pattern = getpattern (value, quoted, 1);
2602
2603   list = list_rest_of_args ();
2604   ret = list_remove_pattern (list, pattern, patspec, type, quoted);
2605   dispose_words (list);
2606   FREE (pattern);
2607   return (ret);
2608 }
2609
2610 #if defined (ARRAY_VARS)
2611 static char *
2612 array_remove_pattern (value, aspec, aval, c, quoted)
2613      char *value, *aspec, *aval;        /* AVAL == evaluated ASPEC */
2614      int c, quoted;
2615 {
2616   SHELL_VAR *var;
2617   int len, patspec;
2618   char *ret, *t, *pattern;
2619   WORD_LIST *l;
2620
2621   var = array_variable_part (aspec, &t, &len);
2622   if (var == 0)
2623     return ((char *)NULL);
2624
2625   patspec = getpatspec (c, value);
2626   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2627     value++;
2628
2629   pattern = getpattern (value, quoted, 1);
2630
2631   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
2632     {
2633       if (array_p (var) == 0)
2634         {
2635           report_error ("%s: bad array subscript", aspec);
2636           FREE (pattern);
2637           return ((char *)NULL);
2638         }
2639       l = array_to_word_list (array_cell (var));
2640       if (l == 0)
2641         return ((char *)NULL);
2642       ret = list_remove_pattern (l, pattern, patspec, t[0], quoted);
2643       dispose_words (l);
2644     }
2645   else
2646     {
2647       ret = remove_pattern (aval, pattern, patspec);
2648       if (ret)
2649         {
2650           t = quote_escapes (ret);
2651           free (ret);
2652           ret = t;
2653         }
2654     }
2655
2656   FREE (pattern);
2657   return ret;
2658 }
2659 #endif /* ARRAY_VARS */
2660
2661 /*******************************************
2662  *                                         *
2663  *      Functions to expand WORD_DESCs     *
2664  *                                         *
2665  *******************************************/
2666
2667 /* Expand WORD, performing word splitting on the result.  This does
2668    parameter expansion, command substitution, arithmetic expansion,
2669    word splitting, and quote removal. */
2670
2671 WORD_LIST *
2672 expand_word (word, quoted)
2673      WORD_DESC *word;
2674      int quoted;
2675 {
2676   WORD_LIST *result, *tresult;
2677
2678   tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
2679   result = word_list_split (tresult);
2680   dispose_words (tresult);
2681   return (result ? dequote_list (result) : result);
2682 }
2683
2684 /* Expand WORD, but do not perform word splitting on the result.  This
2685    does parameter expansion, command substitution, arithmetic expansion,
2686    and quote removal. */
2687 WORD_LIST *
2688 expand_word_no_split (word, quoted)
2689      WORD_DESC *word;
2690      int quoted;
2691 {
2692   WORD_LIST *result;
2693
2694   result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
2695   return (result ? dequote_list (result) : result);
2696 }
2697
2698 /* Perform shell expansions on WORD, but do not perform word splitting or
2699    quote removal on the result. */
2700 WORD_LIST *
2701 expand_word_leave_quoted (word, quoted)
2702      WORD_DESC *word;
2703      int quoted;
2704 {
2705   return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
2706 }
2707
2708 #if defined (PROCESS_SUBSTITUTION)
2709
2710 /*****************************************************************/
2711 /*                                                               */
2712 /*                  Hacking Process Substitution                 */
2713 /*                                                               */
2714 /*****************************************************************/
2715
2716 #if !defined (HAVE_DEV_FD)
2717 /* Named pipes must be removed explicitly with `unlink'.  This keeps a list
2718    of FIFOs the shell has open.  unlink_fifo_list will walk the list and
2719    unlink all of them. add_fifo_list adds the name of an open FIFO to the
2720    list.  NFIFO is a count of the number of FIFOs in the list. */
2721 #define FIFO_INCR 20
2722 extern char *mktemp ();
2723
2724 static char **fifo_list = (char **)NULL;
2725 static int nfifo;
2726 static int fifo_list_size;
2727
2728 static void
2729 add_fifo_list (pathname)
2730      char *pathname;
2731 {
2732   if (nfifo >= fifo_list_size - 1)
2733     {
2734       fifo_list_size += FIFO_INCR;
2735       fifo_list = (char **)xrealloc (fifo_list,
2736                                      fifo_list_size * sizeof (char *));
2737     }
2738
2739   fifo_list[nfifo++] = savestring (pathname);
2740 }
2741
2742 void
2743 unlink_fifo_list ()
2744 {
2745   if (nfifo == 0)
2746     return;
2747
2748   while (nfifo--)
2749     {
2750       unlink (fifo_list[nfifo]);
2751       free (fifo_list[nfifo]);
2752       fifo_list[nfifo] = (char *)NULL;
2753     }
2754   nfifo = 0;
2755 }
2756
2757 static char *
2758 make_named_pipe ()
2759 {
2760   char *tname;
2761
2762   tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
2763   if (mkfifo (tname, 0600) < 0)
2764     {
2765       free (tname);
2766       return ((char *)NULL);
2767     }
2768
2769   add_fifo_list (tname);
2770   return (tname);
2771 }
2772
2773 #else /* HAVE_DEV_FD */
2774
2775 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
2776    has open to children.  NFDS is a count of the number of bits currently
2777    set in DEV_FD_LIST.  TOTFDS is a count of the highest possible number
2778    of open files. */
2779 static char *dev_fd_list = (char *)NULL;
2780 static int nfds;
2781 static int totfds;      /* The highest possible number of open files. */
2782
2783 static void
2784 add_fifo_list (fd)
2785      int fd;
2786 {
2787   if (!dev_fd_list || fd >= totfds)
2788     {
2789       int ofds;
2790
2791       ofds = totfds;
2792       totfds = getdtablesize ();
2793       if (totfds < 0 || totfds > 256)
2794         totfds = 256;
2795       if (fd > totfds)
2796         totfds = fd + 2;
2797
2798       dev_fd_list = xrealloc (dev_fd_list, totfds);
2799       bzero (dev_fd_list + ofds, totfds - ofds);
2800     }
2801
2802   dev_fd_list[fd] = 1;
2803   nfds++;
2804 }
2805
2806 void
2807 unlink_fifo_list ()
2808 {
2809   register int i;
2810
2811   if (nfds == 0)
2812     return;
2813
2814   for (i = 0; nfds && i < totfds; i++)
2815     if (dev_fd_list[i])
2816       {
2817         close (i);
2818         dev_fd_list[i] = 0;
2819         nfds--;
2820       }
2821
2822   nfds = 0;
2823 }
2824
2825 #if defined (NOTDEF)
2826 print_dev_fd_list ()
2827 {
2828   register int i;
2829
2830   fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
2831   fflush (stderr);
2832
2833   for (i = 0; i < totfds; i++)
2834     {
2835       if (dev_fd_list[i])
2836         fprintf (stderr, " %d", i);
2837     }
2838   fprintf (stderr, "\n");
2839 }
2840 #endif /* NOTDEF */
2841
2842 static char *
2843 make_dev_fd_filename (fd)
2844      int fd;
2845 {
2846   char *ret;
2847
2848   ret = xmalloc (sizeof (DEV_FD_PREFIX) + 4);
2849   sprintf (ret, "%s%d", DEV_FD_PREFIX, fd);
2850   add_fifo_list (fd);
2851   return (ret);
2852 }
2853
2854 #endif /* HAVE_DEV_FD */
2855
2856 /* Return a filename that will open a connection to the process defined by
2857    executing STRING.  HAVE_DEV_FD, if defined, means open a pipe and return
2858    a filename in /dev/fd corresponding to a descriptor that is one of the
2859    ends of the pipe.  If not defined, we use named pipes on systems that have
2860    them.  Systems without /dev/fd and named pipes are out of luck.
2861
2862    OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
2863    use the read end of the pipe and dup that file descriptor to fd 0 in
2864    the child.  If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
2865    writing or use the write end of the pipe in the child, and dup that
2866    file descriptor to fd 1 in the child.  The parent does the opposite. */
2867
2868 static char *
2869 process_substitute (string, open_for_read_in_child)
2870      char *string;
2871      int open_for_read_in_child;
2872 {
2873   char *pathname;
2874   int fd, result;
2875   pid_t old_pid, pid;
2876 #if defined (HAVE_DEV_FD)
2877   int parent_pipe_fd, child_pipe_fd;
2878   int fildes[2];
2879 #endif /* HAVE_DEV_FD */
2880 #if defined (JOB_CONTROL)
2881   pid_t old_pipeline_pgrp;
2882 #endif
2883
2884   if (!string || !*string || wordexp_only)
2885     return ((char *)NULL);
2886
2887 #if !defined (HAVE_DEV_FD)
2888   pathname = make_named_pipe ();
2889 #else /* HAVE_DEV_FD */
2890   if (pipe (fildes) < 0)
2891     {
2892       sys_error ("cannot make pipe for process substitution");
2893       return ((char *)NULL);
2894     }
2895   /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
2896      the pipe in the parent, otherwise the read end. */
2897   parent_pipe_fd = fildes[open_for_read_in_child];
2898   child_pipe_fd = fildes[1 - open_for_read_in_child];
2899   /* Move the parent end of the pipe to some high file descriptor, to
2900      avoid clashes with FDs used by the script. */
2901   parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
2902
2903   pathname = make_dev_fd_filename (parent_pipe_fd);
2904 #endif /* HAVE_DEV_FD */
2905
2906   if (!pathname)
2907     {
2908       sys_error ("cannot make pipe for process substitution");
2909       return ((char *)NULL);
2910     }
2911
2912   old_pid = last_made_pid;
2913
2914 #if defined (JOB_CONTROL)
2915   old_pipeline_pgrp = pipeline_pgrp;
2916   pipeline_pgrp = shell_pgrp;
2917 #if 0
2918   cleanup_the_pipeline ();
2919 #else
2920   save_pipeline (1);
2921 #endif
2922 #endif /* JOB_CONTROL */
2923
2924   pid = make_child ((char *)NULL, 1);
2925   if (pid == 0)
2926     {
2927       reset_terminating_signals ();     /* XXX */
2928       /* Cancel traps, in trap.c. */
2929       restore_original_signals ();
2930       setup_async_signals ();
2931       subshell_environment = SUBSHELL_COMSUB;
2932     }
2933
2934 #if defined (JOB_CONTROL)
2935   set_sigchld_handler ();
2936   stop_making_children ();
2937   pipeline_pgrp = old_pipeline_pgrp;
2938 #endif /* JOB_CONTROL */
2939
2940   if (pid < 0)
2941     {
2942       sys_error ("cannot make child for process substitution");
2943       free (pathname);
2944 #if defined (HAVE_DEV_FD)
2945       close (parent_pipe_fd);
2946       close (child_pipe_fd);
2947 #endif /* HAVE_DEV_FD */
2948       return ((char *)NULL);
2949     }
2950
2951   if (pid > 0)
2952     {
2953 #if defined (JOB_CONTROL)
2954       restore_pipeline (1);
2955 #endif
2956
2957       last_made_pid = old_pid;
2958
2959 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2960       close_pgrp_pipe ();
2961 #endif /* JOB_CONTROL && PGRP_PIPE */
2962
2963 #if defined (HAVE_DEV_FD)
2964       close (child_pipe_fd);
2965 #endif /* HAVE_DEV_FD */
2966
2967       return (pathname);
2968     }
2969
2970   set_sigint_handler ();
2971
2972 #if defined (JOB_CONTROL)
2973   set_job_control (0);
2974 #endif /* JOB_CONTROL */
2975
2976 #if !defined (HAVE_DEV_FD)
2977   /* Open the named pipe in the child. */
2978   fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
2979   if (fd < 0)
2980     {
2981       sys_error ("cannot open named pipe %s for %s", pathname,
2982         open_for_read_in_child ? "reading" : "writing");
2983       exit (127);
2984     }
2985 #else /* HAVE_DEV_FD */
2986   fd = child_pipe_fd;
2987 #endif /* HAVE_DEV_FD */
2988
2989   if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
2990     {
2991       sys_error ("cannot duplicate named pipe %s as fd %d", pathname,
2992         open_for_read_in_child ? 0 : 1);
2993       exit (127);
2994     }
2995
2996   close (fd);
2997
2998   /* Need to close any files that this process has open to pipes inherited
2999      from its parent. */
3000   if (current_fds_to_close)
3001     {
3002       close_fd_bitmap (current_fds_to_close);
3003       current_fds_to_close = (struct fd_bitmap *)NULL;
3004     }
3005
3006 #if defined (HAVE_DEV_FD)
3007   /* Make sure we close the parent's end of the pipe and clear the slot
3008      in the fd list so it is not closed later, if reallocated by, for
3009      instance, pipe(2). */
3010   close (parent_pipe_fd);
3011   dev_fd_list[parent_pipe_fd] = 0;
3012 #endif /* HAVE_DEV_FD */
3013
3014   result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
3015
3016 #if !defined (HAVE_DEV_FD)
3017   /* Make sure we close the named pipe in the child before we exit. */
3018   close (open_for_read_in_child ? 0 : 1);
3019 #endif /* !HAVE_DEV_FD */
3020
3021   exit (result);
3022   /*NOTREACHED*/
3023 }
3024 #endif /* PROCESS_SUBSTITUTION */
3025
3026 /***********************************/
3027 /*                                 */
3028 /*      Command Substitution       */
3029 /*                                 */
3030 /***********************************/
3031
3032 static char *
3033 read_comsub (fd, quoted)
3034      int fd, quoted;
3035 {
3036   char *istring, buf[128], *bufp;
3037   int bufn, istring_index, istring_size, c;
3038
3039   istring = (char *)NULL;
3040   istring_index = istring_size = bufn = 0;
3041
3042   /* Read the output of the command through the pipe. */
3043   while (1)
3044     {
3045       if (fd < 0)
3046         break;
3047       if (--bufn <= 0)
3048         {
3049           while ((bufn = read (fd, buf, sizeof(buf))) < 0 && errno == EINTR)
3050             ;
3051           if (bufn <= 0) 
3052             break;
3053           bufp = buf;
3054         }
3055       c = *bufp++;
3056
3057       /* Add the character to ISTRING, possibly after resizing it. */
3058       RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
3059
3060       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
3061         istring[istring_index++] = CTLESC;
3062
3063       istring[istring_index++] = c;
3064     }
3065
3066   if (istring)
3067     istring[istring_index] = '\0';
3068
3069   /* If we read no output, just return now and save ourselves some
3070      trouble. */
3071   if (istring_index == 0)
3072     {
3073       FREE (istring);
3074       return (char *)NULL;
3075     }
3076
3077   /* Strip trailing newlines from the output of the command. */
3078   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
3079     {
3080       while (istring_index > 0)
3081         {
3082           if (istring[istring_index - 1] == '\n')
3083             {
3084               --istring_index;
3085
3086               /* If the newline was quoted, remove the quoting char. */
3087               if (istring[istring_index - 1] == CTLESC)
3088                 --istring_index;
3089             }
3090           else
3091             break;
3092         }
3093       istring[istring_index] = '\0';
3094     }
3095   else
3096     strip_trailing (istring, istring_index - 1, 1);
3097
3098   return istring;
3099 }
3100
3101 /* Perform command substitution on STRING.  This returns a string,
3102    possibly quoted. */
3103 static char *
3104 command_substitute (string, quoted)
3105      char *string;
3106      int quoted;
3107 {
3108   pid_t pid, old_pid, old_pipeline_pgrp;
3109   char *istring;
3110   int result, fildes[2];
3111
3112   istring = (char *)NULL;
3113
3114   /* Don't fork () if there is no need to.  In the case of no command to
3115      run, just return NULL. */
3116   if (!string || !*string || (string[0] == '\n' && !string[1]))
3117     return ((char *)NULL);
3118
3119   if (wordexp_only && read_but_dont_execute)
3120     {
3121       last_command_exit_value = 125;
3122       jump_to_top_level (EXITPROG);
3123     }
3124
3125   /* Pipe the output of executing STRING into the current shell. */
3126   if (pipe (fildes) < 0)
3127     {
3128       sys_error ("cannot make pipes for command substitution");
3129       goto error_exit;
3130     }
3131
3132   old_pid = last_made_pid;
3133 #if defined (JOB_CONTROL)
3134   old_pipeline_pgrp = pipeline_pgrp;
3135   pipeline_pgrp = shell_pgrp;
3136   cleanup_the_pipeline ();
3137 #endif
3138
3139   pid = make_child ((char *)NULL, 0);
3140   if (pid == 0)
3141     /* Reset the signal handlers in the child, but don't free the
3142        trap strings. */
3143     reset_signal_handlers ();
3144
3145 #if defined (JOB_CONTROL)
3146   set_sigchld_handler ();
3147   stop_making_children ();
3148   pipeline_pgrp = old_pipeline_pgrp;
3149 #endif /* JOB_CONTROL */
3150
3151   if (pid < 0)
3152     {
3153       sys_error ("cannot make child for command substitution");
3154     error_exit:
3155
3156       FREE (istring);
3157       close (fildes[0]);
3158       close (fildes[1]);
3159       return ((char *)NULL);
3160     }
3161
3162   if (pid == 0)
3163     {
3164       set_sigint_handler ();    /* XXX */
3165 #if defined (JOB_CONTROL)
3166       set_job_control (0);
3167 #endif
3168       if (dup2 (fildes[1], 1) < 0)
3169         {
3170           sys_error ("command_substitute: cannot duplicate pipe as fd 1");
3171           exit (EXECUTION_FAILURE);
3172         }
3173
3174       /* If standard output is closed in the parent shell
3175          (such as after `exec >&-'), file descriptor 1 will be
3176          the lowest available file descriptor, and end up in
3177          fildes[0].  This can happen for stdin and stderr as well,
3178          but stdout is more important -- it will cause no output
3179          to be generated from this command. */
3180       if ((fildes[1] != fileno (stdin)) &&
3181           (fildes[1] != fileno (stdout)) &&
3182           (fildes[1] != fileno (stderr)))
3183         close (fildes[1]);
3184
3185       if ((fildes[0] != fileno (stdin)) &&
3186           (fildes[0] != fileno (stdout)) &&
3187           (fildes[0] != fileno (stderr)))
3188         close (fildes[0]);
3189
3190       /* The currently executing shell is not interactive. */
3191       interactive = 0;
3192
3193       /* This is a subshell environment. */
3194       subshell_environment = SUBSHELL_COMSUB;
3195
3196       /* Command substitution does not inherit the -e flag. */
3197       exit_immediately_on_error = 0;
3198
3199       remove_quoted_escapes (string);
3200
3201       startup_state = 2;        /* see if we can avoid a fork */
3202       /* Give command substitution a place to jump back to on failure,
3203          so we don't go back up to main (). */
3204       result = setjmp (top_level);
3205
3206       if (result == EXITPROG)
3207         exit (last_command_exit_value);
3208       else if (result)
3209         exit (EXECUTION_FAILURE);
3210       else
3211         exit (parse_and_execute (string, "command substitution", SEVAL_NOHIST));
3212     }
3213   else
3214     {
3215 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
3216       close_pgrp_pipe ();
3217 #endif /* JOB_CONTROL && PGRP_PIPE */
3218
3219       close (fildes[1]);
3220
3221       istring = read_comsub (fildes[0], quoted);
3222
3223       close (fildes[0]);
3224
3225       current_command_subst_pid = pid;
3226       last_command_exit_value = wait_for (pid);
3227       last_command_subst_pid = pid;
3228       last_made_pid = old_pid;
3229
3230 #if defined (JOB_CONTROL)
3231       /* If last_command_exit_value > 128, then the substituted command
3232          was terminated by a signal.  If that signal was SIGINT, then send
3233          SIGINT to ourselves.  This will break out of loops, for instance. */
3234       if (last_command_exit_value == (128 + SIGINT))
3235         kill (getpid (), SIGINT);
3236
3237       /* wait_for gives the terminal back to shell_pgrp.  If some other
3238          process group should have it, give it away to that group here.
3239          pipeline_pgrp is non-zero only while we are constructing a
3240          pipline, so what we are concerned about is whether or not that
3241          pipeline was started in the background.  A pipeline started in
3242          the background should never get the tty back here. */
3243 #if 0
3244       if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
3245 #else
3246       if (interactive && pipeline_pgrp != (pid_t)0 && subshell_environment != SUBSHELL_ASYNC)
3247 #endif
3248         give_terminal_to (pipeline_pgrp);
3249 #endif /* JOB_CONTROL */
3250
3251       return (istring);
3252     }
3253 }
3254
3255 /********************************************************
3256  *                                                      *
3257  *      Utility functions for parameter expansion       *
3258  *                                                      *
3259  ********************************************************/
3260
3261 /* Utility functions to manage arrays and their contents for expansion */
3262
3263 #if defined (ARRAY_VARS)
3264 int
3265 valid_array_reference (name)
3266      char *name;
3267 {
3268   char *t;
3269   int r, len;
3270
3271   t = strchr (name, '[');
3272   if (t)
3273     {
3274       *t = '\0';
3275       r = legal_identifier (name);
3276       *t = '[';
3277       if (r == 0)
3278         return 0;
3279       /* Check for a properly-terminated non-blank subscript. */
3280       len = skipsubscript (t, 0);
3281       if (t[len] != ']' || len == 1)
3282         return 0;
3283       for (r = 1; r < len; r++)
3284         if (whitespace (t[r]) == 0)
3285           return 1;
3286       return 0;
3287     }
3288   return 0;
3289 }
3290
3291 /* Expand the array index beginning at S and extending LEN characters. */
3292 int
3293 array_expand_index (s, len)
3294      char *s;
3295      int len;
3296 {
3297   char *exp, *t;
3298   int val, expok;
3299
3300   exp = xmalloc (len);
3301   strncpy (exp, s, len - 1);
3302   exp[len - 1] = '\0';
3303   t = maybe_expand_string (exp, 0, expand_string);
3304   this_command_name = (char *)NULL;
3305   val = evalexp (t, &expok);
3306   free (t);
3307   free (exp);
3308   if (expok == 0)
3309     jump_to_top_level (DISCARD);
3310   return val;
3311 }
3312
3313 /* Return the variable specified by S without any subscript.  If non-null,
3314    return the index of the start of the subscript in *SUBP.  If non-null,
3315    the length of the subscript is returned in *LENP. */
3316 SHELL_VAR *
3317 array_variable_part (s, subp, lenp)
3318      char *s, **subp;
3319      int *lenp;
3320 {
3321   char *t;
3322   int ind, ni;
3323   SHELL_VAR *var;
3324
3325   t = strchr (s, '[');
3326   ind = t - s;
3327   ni = skipsubscript (s, ind);
3328   if (ni <= ind + 1 || s[ni] != ']')
3329     {
3330       report_error ("%s: bad array subscript", s);
3331       return ((SHELL_VAR *)NULL);
3332     }
3333
3334   *t = '\0';
3335   var = find_variable (s);
3336   *t++ = '[';
3337
3338   if (subp)
3339     *subp = t;
3340   if (lenp)
3341     *lenp = ni - ind;
3342   return var;
3343 }
3344
3345 static char *
3346 array_value_internal (s, quoted, allow_all)
3347      char *s;
3348      int quoted, allow_all;
3349 {
3350   int len, ind;
3351   char *retval, *t, *temp;
3352   WORD_LIST *l, *list;
3353   SHELL_VAR *var;
3354
3355   var = array_variable_part (s, &t, &len);
3356
3357   if (var == 0)
3358     return (char *)NULL;
3359
3360   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3361     {
3362       if (array_p (var) == 0 || allow_all == 0)
3363         {
3364           report_error ("%s: bad array subscript", s);
3365           return ((char *)NULL);
3366         }
3367       l = array_to_word_list (array_cell (var));
3368       if (l == (WORD_LIST *)NULL)
3369         return ((char *) NULL);
3370
3371 #if 0
3372       if (t[0] == '*')          /* ${name[*]} */
3373         retval = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
3374       else                      /* ${name[@]} */
3375         retval = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3376 #else
3377       if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
3378         {
3379           temp = string_list_dollar_star (l);
3380           retval = quote_string (temp);
3381           free (temp);
3382         }
3383       else      /* ${name[@]} or unquoted ${name[*]} */
3384         retval = string_list_dollar_at (l, quoted);
3385 #endif
3386
3387       dispose_words (l);
3388     }
3389   else
3390     {
3391       ind = array_expand_index (t, len);
3392       if (ind < 0)
3393         {
3394           report_error ("%s: bad array subscript", var->name);
3395           return ((char *)NULL);
3396         }
3397       if (array_p (var) == 0)
3398         return (ind == 0 ? savestring (value_cell (var)) : (char *)NULL);
3399       retval = array_reference (array_cell (var), ind);
3400       if (retval)
3401         retval = quote_escapes (retval);
3402     }
3403
3404   return retval;
3405 }
3406
3407 static char *
3408 array_value (s, quoted)
3409      char *s;
3410      int quoted;
3411 {
3412   return (array_value_internal (s, quoted, 1));
3413 }
3414
3415 /* Return the value of the array indexing expression S as a single string.
3416    If ALLOW_ALL is 0, do not allow `@' and `*' subscripts.  This is used
3417    by other parts of the shell such as the arithmetic expression evaluator
3418    in expr.c. */
3419 char *
3420 get_array_value (s, allow_all)
3421      char *s;
3422      int allow_all;
3423 {
3424   return (array_value_internal (s, 0, allow_all));
3425 }
3426
3427 static int
3428 array_length_reference (s)
3429      char *s;
3430 {
3431   int ind, len;
3432   char *t;
3433   ARRAY *array;
3434   SHELL_VAR *var;
3435
3436   var = array_variable_part (s, &t, &len);
3437
3438   /* If unbound variables should generate an error, report one and return
3439      failure. */
3440   if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
3441     {
3442       ind = *--t;
3443       *t = '\0';
3444       report_error ("%s: unbound variable", s);
3445       *t++ = (char)ind;
3446       return (-1);
3447     }
3448   else if (var == 0)
3449     return 0;
3450   else if (array_p (var) == 0)
3451     return 1;
3452
3453   array = array_cell (var);
3454
3455   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3456     return (array_num_elements (array));
3457
3458   ind = array_expand_index (t, len);
3459   if (ind < 0)
3460     {
3461       report_error ("%s: bad array subscript", t);
3462       return (-1);
3463     }
3464   t = array_reference (array, ind);
3465   len = STRLEN (t);
3466
3467   return (len);
3468 }
3469 #endif /* ARRAY_VARS */
3470
3471 static int
3472 valid_brace_expansion_word (name, var_is_special)
3473      char *name;
3474      int var_is_special;
3475 {
3476   if (digit (*name) && all_digits (name))
3477     return 1;
3478   else if (var_is_special)
3479     return 1;
3480 #if defined (ARRAY_VARS)
3481   else if (valid_array_reference (name))
3482     return 1;
3483 #endif /* ARRAY_VARS */
3484   else if (legal_identifier (name))
3485     return 1;
3486   else
3487     return 0;
3488 }
3489
3490 /* Parameter expand NAME, and return a new string which is the expansion,
3491    or NULL if there was no expansion.
3492    VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
3493    the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
3494    NAME was found inside of a double-quoted expression. */
3495 static char *
3496 parameter_brace_expand_word (name, var_is_special, quoted)
3497      char *name;
3498      int var_is_special, quoted;
3499 {
3500   char *temp, *tt;
3501   int arg_index;
3502   SHELL_VAR *var;
3503   WORD_LIST *l;
3504
3505   /* Handle multiple digit arguments, as in ${11}. */
3506   if (digit (*name))
3507     {
3508       arg_index = atoi (name);
3509       temp = get_dollar_var_value (arg_index);
3510     }
3511   else if (var_is_special)      /* ${@} */
3512     {
3513       int sindex;
3514       tt = xmalloc (2 + strlen (name));
3515       tt[sindex = 0] = '$';
3516       strcpy (tt + 1, name);
3517 #if 0
3518       l = expand_string_leave_quoted (tt, quoted);
3519       free (tt);
3520       temp = string_list (l);
3521       dispose_words (l);
3522 #else
3523       temp = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
3524                            (int *)NULL, (int *)NULL, 0);
3525       free (tt);
3526 #endif
3527     }
3528 #if defined (ARRAY_VARS)
3529   else if (valid_array_reference (name))
3530     {
3531       temp = array_value (name, quoted);
3532     }
3533 #endif
3534   else if (var = find_variable (name))
3535     {
3536       if (var && invisible_p (var) == 0)
3537         {
3538 #if defined (ARRAY_VARS)
3539           temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
3540 #else
3541           temp = value_cell (var);
3542 #endif
3543
3544           if (temp)
3545             temp = quote_escapes (temp);
3546
3547           if (tempvar_p (var))
3548             dispose_variable (var);
3549         }
3550       else
3551         temp = (char *)NULL;
3552     }
3553   else
3554     temp = (char *)NULL;
3555
3556   return (temp);
3557 }
3558
3559 /* Expand an indirect reference to a variable: ${!NAME} expands to the
3560    value of the variable whose name is the value of NAME. */
3561 static char *
3562 parameter_brace_expand_indir (name, var_is_special, quoted)
3563      char *name;
3564      int var_is_special, quoted;
3565 {
3566   char *temp, *t;
3567
3568   t = parameter_brace_expand_word (name, var_is_special, quoted);
3569   if (t == 0)
3570     return (t);
3571   temp = parameter_brace_expand_word (t, t[0] == '@' && t[1] == '\0', quoted);
3572   free (t);
3573   return temp;
3574 }
3575
3576 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
3577    depending on the value of C, the separating character.  C can be one of
3578    "-", "+", or "=".  QUOTED is true if the entire brace expression occurs
3579    between double quotes. */
3580 static char *
3581 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
3582      char *name, *value;
3583      int c, quoted, *qdollaratp, *hasdollarat;
3584 {
3585   WORD_LIST *l;
3586   char *t, *t1, *temp;
3587   int hasdol;
3588
3589   temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
3590         ? bash_tilde_expand (value)
3591         : savestring (value);
3592
3593   /* If the entire expression is between double quotes, we want to treat
3594      the value as a double-quoted string, with the exception that we strip
3595      embedded unescaped double quotes. */
3596   if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *temp)
3597     {
3598       hasdol = 0;
3599       t = string_extract_double_quoted (temp, &hasdol, 1);
3600       free (temp);
3601       temp = t;
3602     }
3603
3604   hasdol = 0;
3605   /* XXX was 0 not quoted */
3606   l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
3607             : (WORD_LIST *)0;
3608   if (hasdollarat)
3609     *hasdollarat = hasdol || (l && l->next);
3610   free (temp);
3611   if (l)
3612     {
3613       /* The expansion of TEMP returned something.  We need to treat things
3614           slightly differently if HASDOL is non-zero. */
3615       temp = string_list (l);
3616       /* If l->next is not null, we know that TEMP contained "$@", since that
3617          is the only expansion that creates more than one word. */
3618       if ((hasdol && quoted) || l->next)
3619         *qdollaratp = 1;
3620       dispose_words (l);
3621     }
3622   else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
3623     {
3624       /* The brace expansion occurred between double quotes and there was
3625          a $@ in TEMP.  It does not matter if the $@ is quoted, as long as
3626          it does not expand to anything.  In this case, we want to return
3627          a quoted empty string. */
3628       temp = xmalloc (2);
3629       temp[0] = CTLNUL;
3630       temp[1] = '\0';
3631     }
3632   else
3633     temp = (char *)NULL;
3634
3635   if (c == '-' || c == '+')
3636     return (temp);
3637
3638   /* c == '=' */
3639   t = temp ? savestring (temp) : savestring ("");
3640   t1 = dequote_string (t);
3641   free (t);
3642   bind_variable (name, t1);
3643   free (t1);
3644   return (temp);
3645 }
3646
3647 /* Deal with the right hand side of a ${name:?value} expansion in the case
3648    that NAME is null or not set.  If VALUE is non-null it is expanded and
3649    used as the error message to print, otherwise a standard message is
3650    printed. */
3651 static void
3652 parameter_brace_expand_error (name, value)
3653      char *name, *value;
3654 {
3655   WORD_LIST *l;
3656   char *temp;
3657
3658   if (value && *value)
3659     {
3660       l = expand_string (value, 0);
3661       temp =  string_list (l);
3662       report_error ("%s: %s", name, temp ? temp : "");  /* XXX was value not "" */
3663       FREE (temp);
3664       dispose_words (l);
3665     }
3666   else
3667     report_error ("%s: parameter null or not set", name);
3668
3669   /* Free the data we have allocated during this expansion, since we
3670      are about to longjmp out. */
3671   free (name);
3672   FREE (value);
3673 }
3674
3675 /* Return 1 if NAME is something for which parameter_brace_expand_length is
3676    OK to do. */
3677 static int
3678 valid_length_expression (name)
3679      char *name;
3680 {
3681   return (!name[1] ||                                           /* ${#} */
3682           ((name[1] == '@' || name[1] == '*') && !name[2]) ||   /* ${#@}, ${#*} */
3683           (member (name[1], "-?$!#") && !name[2]) ||            /* ${#-}, etc. */
3684           (digit (name[1]) && all_digits (name + 1)) ||         /* ${#11} */
3685 #if defined (ARRAY_VARS)
3686           valid_array_reference (name + 1) ||                   /* ${#a[7]} */
3687 #endif
3688           legal_identifier (name + 1));                         /* ${#PS1} */
3689 }
3690
3691 /* Handle the parameter brace expansion that requires us to return the
3692    length of a parameter. */
3693 static int
3694 parameter_brace_expand_length (name)
3695      char *name;
3696 {
3697   char *t, *newname;
3698   int number;
3699   WORD_LIST *list;
3700 #if defined (ARRAY_VARS)
3701   SHELL_VAR *var;
3702 #endif
3703
3704   if (name[1] == '\0')                  /* ${#} */
3705     number = number_of_args ();
3706   else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0')       /* ${#@}, ${#*} */
3707     number = number_of_args ();
3708   else if (member (name[1], "-?$!#") && name[2] == '\0')
3709     {
3710       /* Take the lengths of some of the shell's special parameters. */
3711       switch (name[1])
3712         {
3713         case '-':
3714           t = which_set_flags ();
3715           break;
3716         case '?':
3717           t = itos (last_command_exit_value);
3718           break;
3719         case '$':
3720           t = itos (dollar_dollar_pid);
3721           break;
3722         case '!':
3723           if (last_asynchronous_pid == NO_PID)
3724             t = (char *)NULL;
3725           else
3726             t = itos ((int)last_asynchronous_pid);
3727           break;
3728         case '#':
3729           t = itos (number_of_args ());
3730           break;
3731         }
3732       number = STRLEN (t);
3733       FREE (t);
3734     }
3735 #if defined (ARRAY_VARS)
3736   else if (valid_array_reference (name + 1))
3737     number = array_length_reference (name + 1);
3738 #endif /* ARRAY_VARS */
3739   else
3740     {
3741       number = 0;
3742
3743       if (digit (name[1]))              /* ${#1} */
3744         {
3745           t = get_dollar_var_value (atoi (name + 1));
3746           number = STRLEN (t);
3747           FREE (t);
3748         }
3749 #if defined (ARRAY_VARS)
3750       else if ((var = find_variable (name + 1)) && array_p (var))
3751         {
3752           t = array_reference (array_cell (var), 0);
3753           number = STRLEN (t);
3754         }
3755 #endif
3756       else                              /* ${#PS1} */
3757         {
3758           newname = savestring (name);
3759           newname[0] = '$';
3760           list = expand_string (newname, Q_DOUBLE_QUOTES);
3761           t = list ? string_list (list) : (char *)NULL;
3762           free (newname);
3763           if (list)
3764             dispose_words (list);
3765
3766           number = STRLEN (t);
3767           FREE (t);
3768         }
3769     }
3770
3771   return (number);
3772 }
3773
3774 /* Verify and limit the start and end of the desired substring.  If
3775    VTYPE == 0, a regular shell variable is being used; if it is 1,
3776    then the positional parameters are being used; if it is 2, then
3777    VALUE is really a pointer to an array variable that should be used.
3778    Return value is 1 if both values were OK, 0 if there was a problem
3779    with an invalid expression, or -1 if the values were out of range. */
3780 static int
3781 verify_substring_values (value, substr, vtype, e1p, e2p)
3782      char *value, *substr;
3783      int vtype, *e1p, *e2p;
3784 {
3785   char *t, *temp1;
3786   int len, expok;
3787 #if defined (ARRAY_VARS)
3788  ARRAY *a;
3789 #endif
3790
3791   t = strchr (substr, ':');
3792   if (t)
3793     *t = '\0';
3794   temp1 = maybe_expand_string (substr, Q_DOUBLE_QUOTES, expand_string);
3795   *e1p = evalexp (temp1, &expok);
3796   free (temp1);
3797   if (expok == 0)
3798     return (0);
3799
3800   switch (vtype)
3801     {
3802     case VT_VARIABLE:
3803     case VT_ARRAYMEMBER:
3804       len = strlen (value);
3805       break;
3806     case VT_POSPARMS:
3807       len = number_of_args () + 1;
3808       break;
3809 #if defined (ARRAY_VARS)
3810     case VT_ARRAYVAR:
3811       a = (ARRAY *)value;
3812       len = array_num_elements (a) + 1;
3813       break;
3814 #endif
3815     }
3816
3817   if (*e1p < 0)         /* negative offsets count from end */
3818     *e1p += len;
3819
3820   if (*e1p >= len || *e1p < 0)
3821     return (-1);
3822
3823   if (t)
3824     {
3825       t++;
3826       temp1 = maybe_expand_string (t, Q_DOUBLE_QUOTES, expand_string);
3827       t[-1] = ':';
3828       *e2p = evalexp (temp1, &expok);
3829       free (temp1);
3830       if (expok == 0)
3831         return (0);
3832       if (*e2p < 0)
3833         {
3834           internal_error ("%s: substring expression < 0", t);
3835           return (0);
3836         }
3837       *e2p += *e1p;             /* want E2 chars starting at E1 */
3838       if (*e2p > len)
3839         *e2p = len;
3840     }
3841   else
3842     *e2p = len;
3843
3844   return (1);
3845 }
3846
3847 /* Return the type of variable specified by VARNAME (simple variable,
3848    positional param, or array variable).  Also return the value specified
3849    by VARNAME (value of a variable or a reference to an array element). */
3850 static int
3851 get_var_and_type (varname, value, varp, valp)
3852      char *varname, *value;
3853      SHELL_VAR **varp;
3854      char **valp;
3855 {
3856   int vtype;
3857   char *temp;
3858 #if defined (ARRAY_VARS)
3859   SHELL_VAR *v;
3860 #endif
3861
3862   vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';       /* VT_POSPARMS */
3863   *varp = (SHELL_VAR *)NULL;
3864
3865 #if defined (ARRAY_VARS)
3866   if (valid_array_reference (varname))
3867     {
3868       v = array_variable_part (varname, &temp, (int *)0);
3869       if (v && array_p (v))
3870         {
3871           if ((temp[0] == '@' || temp[0] == '*') && temp[1] == ']')
3872             {
3873               vtype = VT_ARRAYVAR;
3874               *valp = (char *)array_cell (v);
3875             }
3876           else
3877             {
3878               vtype = VT_ARRAYMEMBER;
3879               *valp = array_value (varname, 1);
3880             }
3881           *varp = v;
3882         }
3883       else
3884         return -1;
3885     }
3886   else if ((v = find_variable (varname)) && array_p (v))
3887     {
3888       vtype = VT_VARIABLE;
3889       *varp = v;
3890       *valp = array_reference (array_cell (v), 0);
3891     }
3892   else
3893 #endif
3894   *valp = value;
3895
3896   return vtype;
3897 }
3898
3899 /******************************************************/
3900 /*                                                    */
3901 /* Functions to extract substrings of variable values */
3902 /*                                                    */
3903 /******************************************************/
3904
3905 /* Process a variable substring expansion: ${name:e1[:e2]}.  If VARNAME
3906    is `@', use the positional parameters; otherwise, use the value of
3907    VARNAME.  If VARNAME is an array variable, use the array elements. */
3908
3909 static char *
3910 parameter_brace_substring (varname, value, substr, quoted)
3911      char *varname, *value, *substr;
3912      int quoted;
3913 {
3914   int e1, e2, vtype, r;
3915   char *temp, *val;
3916   SHELL_VAR *v;
3917
3918   if (value == 0)
3919     return ((char *)NULL);
3920
3921   this_command_name = varname;
3922
3923   vtype = get_var_and_type (varname, value, &v, &val);
3924   if (vtype == -1)
3925     return ((char *)NULL);
3926
3927   r = verify_substring_values (val, substr, vtype, &e1, &e2);
3928   if (r <= 0)
3929     {
3930       if (val && vtype == VT_ARRAYMEMBER)
3931         free (val);
3932       return ((r == 0) ? &expand_param_error : (char *)NULL);
3933     }
3934
3935   switch (vtype)
3936     {
3937     case VT_VARIABLE:
3938     case VT_ARRAYMEMBER:
3939       temp = quoted ? quoted_substring (value, e1, e2) : substring (value, e1, e2);
3940       break;
3941     case VT_POSPARMS:
3942       temp = pos_params (varname, e1, e2, quoted);
3943       break;
3944 #if defined (ARRAY_VARS)
3945     case VT_ARRAYVAR:
3946       temp = array_subrange (array_cell (v), e1, e2, quoted);
3947       break;
3948 #endif
3949     }
3950
3951   return temp;
3952 }
3953
3954 /****************************************************************/
3955 /*                                                              */
3956 /* Functions to perform pattern substitution on variable values */
3957 /*                                                              */
3958 /****************************************************************/
3959
3960 char *
3961 pat_subst (string, pat, rep, mflags)
3962      char *string, *pat, *rep;
3963      int mflags;
3964 {
3965   char *ret, *s, *e, *str;
3966   int rsize, rptr, l, replen, mtype;
3967
3968   mtype = mflags & MATCH_TYPEMASK;
3969
3970   /* Special cases:
3971    *    1.  A null pattern with mtype == MATCH_BEG means to prefix STRING
3972    *        with REP and return the result.
3973    *    2.  A null pattern with mtype == MATCH_END means to append REP to
3974    *        STRING and return the result.
3975    */
3976   if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
3977     {
3978       replen = STRLEN (rep);
3979       l = strlen (string);
3980       ret = xmalloc (replen + l + 2);
3981       if (mtype == MATCH_BEG)
3982         {
3983           strcpy (ret, rep);
3984           strcpy (ret + replen, string);
3985         }
3986       else
3987         {
3988           strcpy (ret, string);
3989           strcpy (ret + l, rep);
3990         }
3991       return (ret);
3992     }
3993
3994   ret = xmalloc (rsize = 64);
3995   ret[0] = '\0';
3996
3997   for (replen = STRLEN (rep), rptr = 0, str = string;;)
3998     {
3999       if (match_pattern (str, pat, mtype, &s, &e) == 0)
4000         break;
4001       l = s - str;
4002       RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
4003
4004       /* OK, now copy the leading unmatched portion of the string (from
4005          str to s) to ret starting at rptr (the current offset).  Then copy
4006          the replacement string at ret + rptr + (s - str).  Increment
4007          rptr (if necessary) and str and go on. */
4008       if (l)
4009         {
4010           strncpy (ret + rptr, str, l);
4011           rptr += l;
4012         }
4013       if (replen)
4014         {
4015           strncpy (ret + rptr, rep, replen);
4016           rptr += replen;
4017         }
4018       str = e;          /* e == end of match */
4019       if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
4020         break;
4021     }
4022
4023   /* Now copy the unmatched portion of the input string */
4024   if (*str)
4025     {
4026       RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
4027       strcpy (ret + rptr, str);
4028     }
4029   else
4030     ret[rptr] = '\0';
4031
4032   return ret;
4033 }
4034
4035 /* Do pattern match and replacement on the positional parameters. */
4036 static char *
4037 pos_params_pat_subst (string, pat, rep, mflags)
4038      char *string, *pat, *rep;
4039      int mflags;
4040 {
4041   WORD_LIST *save, *params;
4042   WORD_DESC *w;
4043   char *ret;
4044
4045   save = params = list_rest_of_args ();
4046   if (save == 0)
4047     return ((char *)NULL);
4048
4049   for ( ; params; params = params->next)
4050     {
4051       ret = pat_subst (params->word->word, pat, rep, mflags);
4052       w = make_bare_word (ret);
4053       dispose_word (params->word);
4054       params->word = w;
4055       FREE (ret);
4056     }
4057
4058   ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
4059   dispose_words (save);
4060
4061   return (ret);
4062 }
4063
4064 /* Perform pattern substitution on VALUE, which is the expansion of
4065    VARNAME.  PATSUB is an expression supplying the pattern to match
4066    and the string to substitute.  QUOTED is a flags word containing
4067    the type of quoting currently in effect. */
4068 static char *
4069 parameter_brace_patsub (varname, value, patsub, quoted)
4070      char *varname, *value, *patsub;
4071      int quoted;
4072 {
4073   int vtype, mflags;
4074   char *val, *temp, *pat, *rep, *p;
4075   SHELL_VAR *v;
4076
4077   if (value == 0)
4078     return ((char *)NULL);
4079
4080   this_command_name = varname;
4081
4082   vtype = get_var_and_type (varname, value, &v, &val);
4083   if (vtype == -1)
4084     return ((char *)NULL);
4085
4086   mflags = 0;
4087   if (*patsub == '/')
4088     {
4089       mflags |= MATCH_GLOBREP;
4090       patsub++;
4091     }
4092
4093   if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4094     mflags |= MATCH_QUOTED;
4095
4096   if (rep = quoted_strchr (patsub, '/', ST_BACKSL))
4097     *rep++ = '\0';
4098   else
4099     rep = (char *)NULL;
4100
4101   if (rep && *rep == '\0')
4102     rep = (char *)NULL;
4103
4104   /* Expand PAT and REP for command, variable and parameter, arithmetic,
4105      and process substitution.  Also perform quote removal.  Do not
4106      perform word splitting or filename generation. */
4107 #if 0
4108   pat = maybe_expand_string (patsub, quoted, expand_string_unsplit);
4109 #else
4110   pat = maybe_expand_string (patsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit);
4111 #endif
4112   if (rep)
4113     {
4114       if ((mflags & MATCH_QUOTED) == 0)
4115         rep = maybe_expand_string (rep, quoted, expand_string_unsplit);
4116       else
4117         rep = expand_string_to_string (rep, quoted, expand_string_unsplit);
4118     }
4119
4120   p = pat;
4121   if (pat && pat[0] == '#')
4122     {
4123       mflags |= MATCH_BEG;
4124       p++;
4125     }
4126   else if (pat && pat[0] == '%')
4127     {
4128       mflags |= MATCH_END;
4129       p++;
4130     }
4131   else
4132     mflags |= MATCH_ANY;
4133
4134   /* OK, we now want to substitute REP for PAT in VAL.  If
4135      flags & MATCH_GLOBREP is non-zero, the substitution is done
4136      everywhere, otherwise only the first occurrence of PAT is
4137      replaced. */
4138   switch (vtype)
4139     {
4140     case VT_VARIABLE:
4141     case VT_ARRAYMEMBER:
4142       temp = pat_subst (val, p, rep, mflags);
4143       break;
4144     case VT_POSPARMS:
4145       temp = pos_params_pat_subst (val, p, rep, mflags);
4146       break;
4147 #if defined (ARRAY_VARS)
4148     case VT_ARRAYVAR:
4149       temp = array_pat_subst (array_cell (v), p, rep, mflags);
4150       break;
4151 #endif
4152     }
4153
4154   if (val && v && array_p (v) && vtype == VT_ARRAYMEMBER)
4155     free (val);
4156
4157   FREE (pat);
4158   FREE (rep);
4159
4160   return temp;
4161 }
4162
4163 /****************************************************************/
4164 /*                                                              */
4165 /*      Functions to perform parameter expansion on a string    */
4166 /*                                                              */
4167 /****************************************************************/
4168
4169 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
4170 static char *
4171 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
4172      char *string;
4173      int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
4174 {
4175   int check_nullness, var_is_set, var_is_null, var_is_special;
4176   int want_substring, want_indir, want_patsub;
4177   char *name, *value, *temp, *temp1;
4178   int t_index, sindex, c, number;
4179
4180   value = (char *)NULL;
4181   var_is_set = var_is_null = var_is_special = check_nullness = 0;
4182   want_substring = want_indir = want_patsub = 0;
4183
4184   sindex = *indexp;
4185   t_index = ++sindex;
4186   name = string_extract (string, &t_index, "#%:-=?+/}", 1);
4187
4188   /* If the name really consists of a special variable, then make sure
4189      that we have the entire name.  We don't allow indirect references
4190      to special variables except `#', `?', `@' and `*'. */
4191   if ((sindex == t_index &&
4192         (string[t_index] == '-' ||
4193          string[t_index] == '?' ||
4194          string[t_index] == '#')) ||
4195       (sindex == t_index - 1 && string[sindex] == '!' &&
4196         (string[t_index] == '#' ||
4197          string[t_index] == '?' ||
4198          string[t_index] == '@' ||
4199          string[t_index] == '*')))
4200     {
4201       t_index++;
4202       free (name);
4203       temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
4204       name = xmalloc (3 + (strlen (temp1)));
4205       *name = string[sindex];
4206       if (string[sindex] == '!')
4207         {
4208           /* indirect reference of $#, $?, $@, or $* */
4209           name[1] = string[sindex + 1];
4210           strcpy (name + 2, temp1);
4211         }
4212       else      
4213         strcpy (name + 1, temp1);
4214       free (temp1);
4215     }
4216   sindex = t_index;
4217
4218   /* Find out what character ended the variable name.  Then
4219      do the appropriate thing. */
4220   if (c = string[sindex])
4221     sindex++;
4222
4223   /* If c is followed by one of the valid parameter expansion
4224      characters, move past it as normal.  If not, assume that
4225      a substring specification is being given, and do not move
4226      past it. */
4227   if (c == ':' && member (string[sindex], "-=?+"))
4228     {
4229       check_nullness++;
4230       if (c = string[sindex])
4231         sindex++;
4232     }
4233   else if (c == ':' && string[sindex] != RBRACE)
4234     want_substring = 1;
4235   else if (c == '/' && string[sindex] != RBRACE)
4236     want_patsub = 1;
4237
4238   /* Catch the valid and invalid brace expressions that made it through the
4239      tests above. */
4240   /* ${#-} is a valid expansion and means to take the length of $-.
4241      Similarly for ${#?} and ${##}... */
4242   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4243         member (c, "-?#") && string[sindex] == RBRACE)
4244     {
4245       name = xrealloc (name, 3);
4246       name[1] = c;
4247       name[2] = '\0';
4248       c = string[sindex++];
4249     }
4250
4251   /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
4252   if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4253         member (c, "%:=+/") && string[sindex] == RBRACE)
4254     {
4255       temp = (char *)NULL;
4256       goto bad_substitution;
4257     }
4258
4259   /* Indirect expansion begins with a `!'.  A valid indirect expansion is
4260      either a variable name, one of the positional parameters or a special
4261      variable that expands to one of the positional parameters. */
4262   want_indir = *name == '!' &&
4263     (legal_variable_starter (name[1]) || digit (name[1]) || member (name[1], "#?@*"));
4264
4265   /* Determine the value of this variable. */
4266
4267   /* Check for special variables, directly referenced. */
4268   if ((digit (*name) && all_digits (name)) ||
4269       (name[1] == '\0' && member (*name, "#-?$!@*")) ||
4270       (want_indir && name[2] == '\0' && member (name[1], "#?@*")))
4271     var_is_special++;
4272
4273   /* Check for special expansion things, like the length of a parameter */
4274   if (*name == '#' && name[1])
4275     {
4276       /* If we are not pointing at the character just after the
4277          closing brace, then we haven't gotten all of the name.
4278          Since it begins with a special character, this is a bad
4279          substitution.  Also check NAME for validity before trying
4280          to go on. */
4281       if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
4282         {
4283           temp = (char *)NULL;
4284           goto bad_substitution;
4285         }
4286
4287       number = parameter_brace_expand_length (name);
4288       free (name);
4289
4290       *indexp = sindex;
4291       return ((number < 0) ? &expand_param_error : itos (number));
4292     }
4293
4294   /* ${@} is identical to $@. */
4295   if (name[0] == '@' && name[1] == '\0')
4296     {
4297       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4298         *quoted_dollar_atp = 1;
4299
4300       if (contains_dollar_at)
4301         *contains_dollar_at = 1;
4302     }
4303
4304   /* Make sure that NAME is valid before trying to go on. */
4305   if (valid_brace_expansion_word (want_indir ? name + 1 : name,
4306                                         var_is_special) == 0)
4307     {
4308       temp = (char *)NULL;
4309       goto bad_substitution;
4310     }
4311
4312   if (want_indir)
4313     temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted);
4314   else
4315     temp = parameter_brace_expand_word (name, var_is_special, quoted);
4316
4317 #if defined (ARRAY_VARS)
4318 #if 0
4319   if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && valid_array_reference (name))
4320 #else
4321   if (valid_array_reference (name))
4322 #endif
4323     {
4324       temp1 = strchr (name, '[');
4325       if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4326         {
4327           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4328             *quoted_dollar_atp = 1;
4329           if (contains_dollar_at)
4330             *contains_dollar_at = 1;
4331         }       /* [ */
4332       /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4333          which should result in separate words even when IFS is unset. */
4334       if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4335         {
4336           if (contains_dollar_at)
4337             *contains_dollar_at = 1;
4338         }
4339     }
4340 #endif
4341
4342   var_is_set = temp != (char *)0;
4343   var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
4344
4345   /* Get the rest of the stuff inside the braces. */
4346   if (c && c != RBRACE)
4347     {
4348       /* Extract the contents of the ${ ... } expansion
4349          according to the Posix.2 rules. */
4350       value = extract_dollar_brace_string (string, &sindex, quoted);
4351       if (string[sindex] == RBRACE)
4352         sindex++;
4353       else
4354         goto bad_substitution;
4355     }
4356   else
4357     value = (char *)NULL;
4358
4359   *indexp = sindex;
4360
4361   /* If this is a substring spec, process it and add the result. */
4362   if (want_substring)
4363     {
4364       temp1 = parameter_brace_substring (name, temp, value, quoted);
4365       FREE (name);
4366       FREE (value);
4367       FREE (temp);
4368       return (temp1);
4369     }
4370   else if (want_patsub)
4371     {
4372       temp1 = parameter_brace_patsub (name, temp, value, quoted);
4373       FREE (name);
4374       FREE (value);
4375       FREE (temp);
4376       return (temp1);
4377     }
4378
4379   /* Do the right thing based on which character ended the variable name. */
4380   switch (c)
4381     {
4382     default:
4383     case '\0':
4384     bad_substitution:
4385       report_error ("%s: bad substitution", string ? string : "??");
4386       FREE (value);
4387       FREE (temp);
4388       free (name);
4389       return &expand_param_error;
4390
4391     case RBRACE:
4392       if (var_is_set == 0 && unbound_vars_is_error)
4393         {
4394           report_error ("%s: unbound variable", name);
4395           FREE (value);
4396           FREE (temp);
4397           free (name);
4398           last_command_exit_value = EXECUTION_FAILURE;
4399           return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4400         }
4401       break;
4402
4403     case '#':   /* ${param#[#]pattern} */
4404     case '%':   /* ${param%[%]pattern} */
4405       if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
4406         {
4407           FREE (value);
4408           break;
4409         }
4410       if ((name[0] == '@' || name[0] == '*') && name[1] == '\0')
4411         temp1 = parameter_list_remove_pattern (value, name[0], c, quoted);
4412 #if defined (ARRAY_VARS)
4413       else if (valid_array_reference (name))
4414         temp1 = array_remove_pattern (value, name, temp, c, quoted);
4415 #endif
4416       else
4417         temp1 = parameter_brace_remove_pattern (value, temp, c, quoted);
4418       free (temp);
4419       free (value);
4420       temp = temp1;
4421       break;
4422
4423     case '-':
4424     case '=':
4425     case '?':
4426     case '+':
4427       if (var_is_set && var_is_null == 0)
4428         {
4429           /* We don't want the value of the named variable for
4430              anything, just the value of the right hand side. */
4431           if (c == '+')
4432             {
4433               FREE (temp);
4434               if (value)
4435                 {
4436                   temp = parameter_brace_expand_rhs (name, value, c,
4437                                                      quoted,
4438                                                      quoted_dollar_atp,
4439                                                      contains_dollar_at);
4440                   free (value);
4441                 }
4442               else
4443                 temp = (char *)NULL;
4444             }
4445           else
4446             {
4447               FREE (value);
4448             }
4449           /* Otherwise do nothing; just use the value in TEMP. */
4450         }
4451       else      /* VAR not set or VAR is NULL. */
4452         {
4453           FREE (temp);
4454           temp = (char *)NULL;
4455           if (c == '=' && var_is_special)
4456             {
4457               report_error ("$%s: cannot assign in this way", name);
4458               free (name);
4459               free (value);
4460               return &expand_param_error;
4461             }
4462           else if (c == '?')
4463             {
4464               parameter_brace_expand_error (name, value);
4465               return (interactive ? &expand_param_error : &expand_param_fatal);
4466             }
4467           else if (c != '+')
4468             temp = parameter_brace_expand_rhs (name, value, c, quoted,
4469                                                quoted_dollar_atp,
4470                                                contains_dollar_at);
4471           free (value);
4472         }
4473       break;
4474     }
4475   free (name);
4476   return (temp);
4477 }
4478
4479 /* Expand a single ${xxx} expansion.  The braces are optional.  When
4480    the braces are used, parameter_brace_expand() does the work,
4481    possibly calling param_expand recursively. */
4482 static char *
4483 param_expand (string, sindex, quoted, expanded_something,
4484               contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
4485               pflags)
4486      char *string;
4487      int *sindex, quoted, *expanded_something, *contains_dollar_at;
4488      int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
4489 {
4490   char *temp, *temp1;
4491   int zindex, number, c, t_index, expok;
4492   SHELL_VAR *var;
4493   WORD_LIST *list, *tlist;
4494
4495   zindex = *sindex;
4496   c = string[++zindex];
4497
4498   temp = (char *)NULL;
4499
4500   /* Do simple cases first. Switch on what follows '$'. */
4501   switch (c)
4502     {
4503     /* $0 .. $9? */
4504     case '0':
4505     case '1':
4506     case '2':
4507     case '3':
4508     case '4':
4509     case '5':
4510     case '6':
4511     case '7':
4512     case '8':
4513     case '9':
4514       temp1 = dollar_vars[digit_value (c)];
4515       if (unbound_vars_is_error && temp1 == (char *)NULL)
4516         {
4517           report_error ("$%c: unbound variable", c);
4518           last_command_exit_value = EXECUTION_FAILURE;
4519           return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4520         }
4521       temp = temp1 ? savestring (temp1) : (char *)NULL;
4522       break;
4523
4524     /* $$ -- pid of the invoking shell. */
4525     case '$':
4526       temp = itos (dollar_dollar_pid);
4527       break;
4528
4529     /* $# -- number of positional parameters. */
4530     case '#':
4531       temp = itos (number_of_args ());
4532       break;
4533
4534     /* $? -- return value of the last synchronous command. */
4535     case '?':
4536       temp = itos (last_command_exit_value);
4537       break;
4538
4539     /* $- -- flags supplied to the shell on invocation or by `set'. */
4540     case '-':
4541       temp = which_set_flags ();
4542       break;
4543
4544       /* $! -- Pid of the last asynchronous command. */
4545     case '!':
4546       /* If no asynchronous pids have been created, expand to nothing.
4547          If `set -u' has been executed, and no async processes have
4548          been created, this is an expansion error. */
4549       if (last_asynchronous_pid == NO_PID)
4550         {
4551           if (expanded_something)
4552             *expanded_something = 0;
4553           temp = (char *)NULL;
4554           if (unbound_vars_is_error)
4555             {
4556               report_error ("$%c: unbound variable", c);
4557               last_command_exit_value = EXECUTION_FAILURE;
4558               return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4559             }
4560         }
4561       else
4562         temp = itos ((int)last_asynchronous_pid);
4563       break;
4564
4565     /* The only difference between this and $@ is when the arg is quoted. */
4566     case '*':           /* `$*' */
4567       list = list_rest_of_args ();
4568
4569       /* If there are no command-line arguments, this should just
4570          disappear if there are other characters in the expansion,
4571          even if it's quoted. */
4572       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
4573         temp = (char *)NULL;
4574       else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4575         {
4576           /* If we have "$*" we want to make a string of the positional
4577              parameters, separated by the first character of $IFS, and
4578              quote the whole string, including the separators.  If IFS
4579              is unset, the parameters are separated by ' '; if $IFS is
4580              null, the parameters are concatenated. */
4581           temp = string_list_dollar_star (list);
4582           temp1 = quote_string (temp);
4583           free (temp);
4584           temp = temp1;
4585         }
4586       else
4587         {
4588           /* If the $* is not quoted it is identical to $@ */
4589           temp = string_list_dollar_at (list, quoted);
4590           if (contains_dollar_at)
4591             *contains_dollar_at = 1;
4592         }
4593
4594       dispose_words (list);
4595       break;
4596
4597     /* When we have "$@" what we want is "$1" "$2" "$3" ... This
4598        means that we have to turn quoting off after we split into
4599        the individually quoted arguments so that the final split
4600        on the first character of $IFS is still done.  */
4601     case '@':           /* `$@' */
4602       list = list_rest_of_args ();
4603
4604       /* We want to flag the fact that we saw this.  We can't turn
4605          off quoting entirely, because other characters in the
4606          string might need it (consider "\"$@\""), but we need some
4607          way to signal that the final split on the first character
4608          of $IFS should be done, even though QUOTED is 1. */
4609       if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
4610         *quoted_dollar_at_p = 1;
4611       if (contains_dollar_at)
4612         *contains_dollar_at = 1;
4613
4614       /* We want to separate the positional parameters with the first
4615          character of $IFS in case $IFS is something other than a space.
4616          We also want to make sure that splitting is done no matter what --
4617          according to POSIX.2, this expands to a list of the positional
4618          parameters no matter what IFS is set to. */
4619       temp = string_list_dollar_at (list, quoted);
4620
4621       dispose_words (list);
4622       break;
4623
4624     case LBRACE:
4625       temp = parameter_brace_expand (string, &zindex, quoted,
4626                                      quoted_dollar_at_p,
4627                                      contains_dollar_at);
4628       if (temp == &expand_param_error || temp == &expand_param_fatal)
4629         return (temp);
4630
4631       /* XXX */
4632       /* quoted nulls should be removed if there is anything else
4633          in the string. */
4634       /* Note that we saw the quoted null so we can add one back at
4635          the end of this function if there are no other characters
4636          in the string, discard TEMP, and go on. */
4637       if (temp && QUOTED_NULL (temp))
4638         {
4639           if (had_quoted_null_p)
4640             *had_quoted_null_p = 1;
4641           free (temp);
4642           temp = (char *)NULL;
4643         }
4644
4645       goto return0;
4646
4647     /* Do command or arithmetic substitution. */
4648     case LPAREN:
4649       /* We have to extract the contents of this paren substitution. */
4650       t_index = zindex + 1;
4651       temp = extract_command_subst (string, &t_index);
4652       zindex = t_index;
4653
4654       /* For Posix.2-style `$(( ))' arithmetic substitution,
4655          extract the expression and pass it to the evaluator. */
4656       if (temp && *temp == LPAREN)
4657         {
4658           char *temp2;
4659           temp1 = temp + 1;
4660           temp2 = savestring (temp1);
4661           t_index = strlen (temp2) - 1;
4662
4663           if (temp2[t_index] != RPAREN)
4664             {
4665               free (temp2);
4666               goto comsub;
4667             }
4668
4669           /* Cut off ending `)' */
4670           temp2[t_index] = '\0';
4671
4672           /* Expand variables found inside the expression. */
4673           temp1 = maybe_expand_string (temp2, Q_DOUBLE_QUOTES, expand_string);
4674           free (temp2);
4675
4676 arithsub:
4677           /* No error messages. */
4678           this_command_name = (char *)NULL;
4679           number = evalexp (temp1, &expok);
4680           free (temp);
4681           free (temp1);
4682           if (expok == 0)
4683             {
4684               if (interactive_shell == 0 && posixly_correct)
4685                 {
4686                   last_command_exit_value = EXECUTION_FAILURE;
4687                   return (&expand_param_fatal);
4688                 }
4689               else
4690                 return (&expand_param_error);
4691             }
4692           temp = itos (number);
4693           break;
4694         }
4695
4696 comsub:
4697       temp1 = command_substitute (temp, quoted);
4698       FREE (temp);
4699       temp = temp1;
4700       break;
4701
4702     /* Do POSIX.2d9-style arithmetic substitution.  This will probably go
4703        away in a future bash release. */
4704     case '[':
4705       /* We have to extract the contents of this arithmetic substitution. */
4706       t_index = zindex + 1;
4707       temp = extract_arithmetic_subst (string, &t_index);
4708       zindex = t_index;
4709
4710        /* Do initial variable expansion. */
4711       temp1 = maybe_expand_string (temp, Q_DOUBLE_QUOTES, expand_string);
4712
4713       goto arithsub;
4714
4715     default:
4716       /* Find the variable in VARIABLE_LIST. */
4717       temp = (char *)NULL;
4718
4719       for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
4720         ;
4721       temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
4722
4723       /* If this isn't a variable name, then just output the `$'. */
4724       if (temp1 == 0 || *temp1 == '\0')
4725         {
4726           FREE (temp1);
4727           temp = xmalloc (2);
4728           temp[0] = '$';
4729           temp[1] = '\0';
4730           if (expanded_something)
4731             *expanded_something = 0;
4732           goto return0;
4733         }
4734
4735       /* If the variable exists, return its value cell. */
4736       var = find_variable (temp1);
4737
4738       if (var && invisible_p (var) == 0 && value_cell (var))
4739         {
4740 #if defined (ARRAY_VARS)
4741           if (array_p (var))
4742             {
4743               temp = array_reference (array_cell (var), 0);
4744               if (temp)
4745                 temp = quote_escapes (temp);
4746             }
4747           else
4748 #endif
4749           temp = quote_escapes (value_cell (var));
4750           free (temp1);
4751           if (tempvar_p (var))          /* XXX */
4752             {
4753               dispose_variable (var);   /* XXX */
4754               var = (SHELL_VAR *)NULL;
4755             }
4756           goto return0;
4757         }
4758
4759       temp = (char *)NULL;
4760
4761       if (unbound_vars_is_error)
4762         report_error ("%s: unbound variable", temp1);
4763       else
4764         {
4765           free (temp1);
4766           goto return0;
4767         }
4768
4769       free (temp1);
4770       last_command_exit_value = EXECUTION_FAILURE;
4771       return ((unbound_vars_is_error && interactive_shell == 0)
4772                 ? &expand_param_fatal
4773                 : &expand_param_error);
4774     }
4775
4776   if (string[zindex])
4777     zindex++;
4778
4779 return0:
4780   *sindex = zindex;
4781   return (temp);
4782 }
4783
4784 /* Make a word list which is the result of parameter and variable
4785    expansion, command substitution, arithmetic substitution, and
4786    quote removal of WORD.  Return a pointer to a WORD_LIST which is
4787    the result of the expansion.  If WORD contains a null word, the
4788    word list returned is also null.
4789
4790    QUOTED contains flag values defined in shell.h.
4791
4792    ISEXP is used to tell expand_word_internal that the word should be
4793    treated as the result of an expansion.  This has implications for
4794    how IFS characters in the word are treated.
4795
4796    CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
4797    they point to an integer value which receives information about expansion.
4798    CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
4799    EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
4800    else zero.
4801
4802    This only does word splitting in the case of $@ expansion.  In that
4803    case, we split on ' '. */
4804
4805 /* Values for the local variable quoted_state. */
4806 #define UNQUOTED         0
4807 #define PARTIALLY_QUOTED 1
4808 #define WHOLLY_QUOTED    2
4809
4810 static WORD_LIST *
4811 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
4812      WORD_DESC *word;
4813      int quoted, isexp;
4814      int *contains_dollar_at;
4815      int *expanded_something;
4816 {
4817   WORD_LIST *list;
4818   WORD_DESC *tword;
4819   SHELL_VAR *var;
4820
4821   /* The intermediate string that we build while expanding. */
4822   char *istring;
4823
4824   /* The current size of the above object. */
4825   int istring_size;
4826
4827   /* Index into ISTRING. */
4828   int istring_index;
4829
4830   /* Temporary string storage. */
4831   char *temp, *temp1;
4832
4833   /* The text of WORD. */
4834   register char *string;
4835
4836   /* The index into STRING. */
4837   int sindex;
4838
4839   /* This gets 1 if we see a $@ while quoted. */
4840   int quoted_dollar_at;
4841
4842   /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
4843      whether WORD contains no quoting characters, a partially quoted
4844      string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
4845   int quoted_state;
4846
4847   int had_quoted_null;
4848   int has_dollar_at;
4849
4850   register int c;               /* Current character. */
4851   int number;                   /* Temporary number value. */
4852   int t_index;                  /* For calls to string_extract_xxx. */
4853
4854   char ifscmap[256];
4855
4856   istring = xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
4857   istring[istring_index = 0] = '\0';
4858   quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
4859   quoted_state = UNQUOTED;
4860
4861   string = word->word;
4862   if (string == 0)
4863     goto finished_with_string;
4864
4865   if (contains_dollar_at)
4866     *contains_dollar_at = 0;
4867
4868   /* Cache a bitmap of characters in IFS for quoting IFS characters that are
4869      not part of an expansion.  POSIX.2 says this is a must. */
4870   temp = getifs ();
4871   bzero (ifscmap, sizeof (ifscmap));
4872   for (temp1 = temp; temp1 && *temp1; temp1++)
4873 #if 0
4874     /* This check compensates for what I think is a parsing problem -- the
4875        end brace matching algorithms for ${...} expressions differ between
4876        parse.y and subst.c.  For instance, the parser passes
4877        ${abc:-G { I } K } as one word when it should be three. */
4878     if (*temp1 != ' ' && *temp1 != '\t' && *temp1 != '\n')
4879 #endif
4880       ifscmap[*temp1] = 1;
4881
4882   /* Begin the expansion. */
4883
4884   for (sindex = 0; ;)
4885     {
4886       c = string[sindex];
4887
4888       /* Case on toplevel character. */
4889       switch (c)
4890         {
4891         case '\0':
4892           goto finished_with_string;
4893
4894         case CTLESC:
4895           temp = xmalloc (3);
4896           temp[0] = CTLESC;
4897           temp[1] = c = string[++sindex];
4898           temp[2] = '\0';
4899
4900 dollar_add_string:
4901           if (string[sindex])
4902             sindex++;
4903
4904 add_string:
4905           if (temp)
4906             {
4907               istring = sub_append_string (temp, istring, &istring_index, &istring_size);
4908               temp = (char *)0;
4909             }
4910
4911           break;
4912
4913 #if defined (PROCESS_SUBSTITUTION)
4914           /* Process substitution. */
4915         case '<':
4916         case '>':
4917           {
4918             if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
4919               {
4920                 sindex--;
4921                 goto add_character;
4922               }
4923             else
4924               t_index = sindex + 1; /* skip past both '<' and LPAREN */
4925
4926             temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
4927             sindex = t_index;
4928
4929             /* If the process substitution specification is `<()', we want to
4930                open the pipe for writing in the child and produce output; if
4931                it is `>()', we want to open the pipe for reading in the child
4932                and consume input. */
4933             temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
4934
4935             FREE (temp1);
4936
4937             goto dollar_add_string;
4938           }
4939 #endif /* PROCESS_SUBSTITUTION */
4940
4941         case '$':
4942           if (expanded_something)
4943             *expanded_something = 1;
4944
4945           has_dollar_at = 0;
4946           temp = param_expand (string, &sindex, quoted, expanded_something,
4947                                &has_dollar_at, &quoted_dollar_at,
4948                                &had_quoted_null, 0);
4949
4950           if (temp == &expand_param_error || temp == &expand_param_fatal)
4951             {
4952               free (string);
4953               free (istring);
4954               return ((temp == &expand_param_error) ? &expand_word_error
4955                                                     : &expand_word_fatal);
4956             }
4957           if (contains_dollar_at && has_dollar_at)
4958             *contains_dollar_at = 1;
4959           goto add_string;
4960           break;
4961
4962         case '`':               /* Backquoted command substitution. */
4963           {
4964             sindex++;
4965
4966             if (expanded_something)
4967               *expanded_something = 1;
4968
4969             temp = string_extract (string, &sindex, "`", 0);
4970             de_backslash (temp);
4971             temp1 = command_substitute (temp, quoted);
4972             FREE (temp);
4973             temp = temp1;
4974             goto dollar_add_string;
4975           }
4976
4977         case '\\':
4978           if (string[sindex + 1] == '\n')
4979             {
4980               sindex += 2;
4981               continue;
4982             }
4983
4984           c = string[++sindex];
4985
4986           if (quoted & Q_HERE_DOCUMENT)
4987             temp1 = slashify_in_here_document;
4988           else if (quoted & Q_DOUBLE_QUOTES)
4989             temp1 = slashify_in_quotes;
4990           else
4991             temp1 = "";
4992
4993           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && member (c, temp1) == 0)
4994             {
4995               temp = xmalloc (3);
4996               temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
4997             }
4998           else
4999             /* This character is quoted, so add it in quoted mode. */
5000             temp = make_quoted_char (c);
5001
5002           if (c)
5003             sindex++;
5004           goto add_string;
5005
5006         case '"':
5007           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
5008             goto add_character;
5009
5010           t_index = ++sindex;
5011           temp = string_extract_double_quoted (string, &sindex, 0);
5012
5013           /* If the quotes surrounded the entire string, then the
5014              whole word was quoted. */
5015           quoted_state = (t_index == 1 && string[sindex] == '\0')
5016                             ? WHOLLY_QUOTED
5017                             : PARTIALLY_QUOTED;
5018
5019           if (temp && *temp)
5020             {
5021               tword = make_word (temp);         /* XXX */
5022               free (temp);
5023               temp = (char *)NULL;
5024
5025               has_dollar_at = 0;
5026               list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
5027
5028               if (list == &expand_word_error || list == &expand_word_fatal)
5029                 {
5030                   free (istring);
5031                   free (string);
5032                   /* expand_word_internal has already freed temp_word->word
5033                      for us because of the way it prints error messages. */
5034                   tword->word = (char *)NULL;
5035                   dispose_word (tword);
5036                   return list;
5037                 }
5038
5039               dispose_word (tword);
5040
5041               /* "$@" (a double-quoted dollar-at) expands into nothing,
5042                  not even a NULL word, when there are no positional
5043                  parameters. */
5044               if (list == 0 && has_dollar_at)
5045                 {
5046                   quoted_dollar_at++;
5047                   break;
5048                 }
5049
5050               /* If we get "$@", we know we have expanded something, so we
5051                  need to remember it for the final split on $IFS.  This is
5052                  a special case; it's the only case where a quoted string
5053                  can expand into more than one word.  It's going to come back
5054                  from the above call to expand_word_internal as a list with
5055                  a single word, in which all characters are quoted and
5056                  separated by blanks.  What we want to do is to turn it back
5057                  into a list for the next piece of code. */
5058               if (list)
5059                 dequote_list (list);
5060
5061               if (has_dollar_at)
5062                 {
5063                   quoted_dollar_at++;
5064                   if (contains_dollar_at)
5065                     *contains_dollar_at = 1;
5066                   if (expanded_something)
5067                     *expanded_something = 1;
5068                 }
5069             }
5070           else
5071             {
5072               /* What we have is "".  This is a minor optimization. */
5073               free (temp);
5074               list = (WORD_LIST *)NULL;
5075             }
5076
5077           /* The code above *might* return a list (consider the case of "$@",
5078              where it returns "$1", "$2", etc.).  We can't throw away the
5079              rest of the list, and we have to make sure each word gets added
5080              as quoted.  We test on tresult->next:  if it is non-NULL, we
5081              quote the whole list, save it to a string with string_list, and
5082              add that string. We don't need to quote the results of this
5083              (and it would be wrong, since that would quote the separators
5084              as well), so we go directly to add_string. */
5085           if (list)
5086             {
5087               if (list->next)
5088                 {
5089                   /* Testing quoted_dollar_at makes sure that "$@" is
5090                      split correctly when $IFS does not contain a space. */
5091                   temp = quoted_dollar_at
5092                                 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
5093                                 : string_list (quote_list (list));
5094                   dispose_words (list);
5095                   goto add_string;
5096                 }
5097               else
5098                 {
5099                   temp = savestring (list->word->word);
5100                   dispose_words (list);
5101 #if 1
5102                   /* If the string is not a quoted null string, we want
5103                      to remove any embedded unquoted CTLNUL characters.
5104                      We do not want to turn quoted null strings back into
5105                      the empty string, though.  We do this because we
5106                      want to remove any quoted nulls from expansions that
5107                      contain other characters.  For example, if we have
5108                      x"$*"y or "x$*y" and there are no positional parameters,
5109                      the $* should expand into nothing. */                   
5110                   if (QUOTED_NULL (temp) == 0)
5111                     remove_quoted_nulls (temp); /* XXX */
5112 #endif
5113                 }
5114             }
5115           else
5116             temp = (char *)NULL;
5117
5118           /* We do not want to add quoted nulls to strings that are only
5119              partially quoted; we can throw them away. */
5120           if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
5121             continue;
5122
5123         add_quoted_string:
5124
5125           if (temp)
5126             {
5127               temp1 = temp;
5128               temp = quote_string (temp);
5129               free (temp1);
5130             }
5131           else
5132             {
5133               /* Add NULL arg. */
5134               temp = xmalloc (2);
5135               temp[0] = CTLNUL;
5136               temp[1] = '\0';
5137             }
5138           goto add_string;
5139           /* break; */
5140
5141         case '\'':
5142           if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
5143             goto add_character;
5144
5145           t_index = ++sindex;
5146           temp = string_extract_single_quoted (string, &sindex);
5147
5148           /* If the entire STRING was surrounded by single quotes,
5149              then the string is wholly quoted. */
5150           quoted_state = (t_index == 1 && string[sindex] == '\0')
5151                             ? WHOLLY_QUOTED
5152                             : PARTIALLY_QUOTED;
5153
5154           /* If all we had was '', it is a null expansion. */
5155           if (*temp == '\0')
5156             {
5157               free (temp);
5158               temp = (char *)NULL;
5159             }
5160           else
5161             remove_quoted_escapes (temp);
5162
5163           /* We do not want to add quoted nulls to strings that are only
5164              partially quoted; such nulls are discarded. */
5165           if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
5166             continue;
5167
5168           goto add_quoted_string;
5169           /* break; */
5170
5171         default:
5172           /* This is the fix for " $@ " */
5173           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && ifscmap[c]))
5174             {
5175               temp = make_quoted_char (c);
5176               goto dollar_add_string;
5177             }
5178
5179         add_character:
5180           RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
5181                                   DEFAULT_ARRAY_SIZE);
5182           istring[istring_index++] = c;
5183           istring[istring_index] = '\0';
5184
5185           /* Next character. */
5186           sindex++;
5187         }
5188     }
5189
5190 finished_with_string:
5191   /* OK, we're ready to return.  If we have a quoted string, and
5192      quoted_dollar_at is not set, we do no splitting at all; otherwise
5193      we split on ' '.  The routines that call this will handle what to
5194      do if nothing has been expanded. */
5195
5196   /* Partially and wholly quoted strings which expand to the empty
5197      string are retained as an empty arguments.  Unquoted strings
5198      which expand to the empty string are discarded.  The single
5199      exception is the case of expanding "$@" when there are no
5200      positional parameters.  In that case, we discard the expansion. */
5201
5202   /* Because of how the code that handles "" and '' in partially
5203      quoted strings works, we need to make ISTRING into a QUOTED_NULL
5204      if we saw quoting characters, but the expansion was empty.
5205      "" and '' are tossed away before we get to this point when
5206      processing partially quoted strings.  This makes "" and $xxx""
5207      equivalent when xxx is unset.  We also look to see whether we
5208      saw a quoted null from a ${} expansion and add one back if we
5209      need to. */
5210
5211   /* If we expand to nothing and there were no single or double quotes
5212      in the word, we throw it away.  Otherwise, we return a NULL word.
5213      The single exception is for $@ surrounded by double quotes when
5214      there are no positional parameters.  In that case, we also throw
5215      the word away. */
5216
5217   if (*istring == '\0')
5218     {
5219       if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
5220         {
5221           istring[0] = CTLNUL;
5222           istring[1] = '\0';
5223           tword = make_bare_word (istring);
5224           list = make_word_list (tword, (WORD_LIST *)NULL);
5225           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5226             tword->flags |= W_QUOTED;
5227         }
5228       /* According to sh, ksh, and Posix.2, if a word expands into nothing
5229          and a double-quoted "$@" appears anywhere in it, then the entire
5230          word is removed. */
5231       else  if (quoted_state == UNQUOTED || quoted_dollar_at)
5232         list = (WORD_LIST *)NULL;
5233 #if 0
5234       else
5235         {
5236           tword = make_bare_word (istring);
5237           list = make_word_list (tword, (WORD_LIST *)NULL);
5238           if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5239             tword->flags |= W_QUOTED;
5240         }
5241 #endif
5242     }
5243   else if (word->flags & W_NOSPLIT)
5244     {
5245       tword = make_bare_word (istring);
5246       list = make_word_list (tword, (WORD_LIST *)NULL);
5247       if (word->flags & W_ASSIGNMENT)
5248         tword->flags |= W_ASSIGNMENT;   /* XXX */
5249       if (word->flags & W_NOGLOB)
5250         tword->flags |= W_NOGLOB;       /* XXX */
5251       if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5252         tword->flags |= W_QUOTED;
5253     }
5254   else
5255     {
5256       char *ifs_chars;
5257
5258       ifs_chars = (quoted_dollar_at || has_dollar_at) ? getifs () : (char *)NULL;
5259
5260       /* If we have $@, we need to split the results no matter what.  If
5261          IFS is unset or NULL, string_list_dollar_at has separated the
5262          positional parameters with a space, so we split on space (we have
5263          set ifs_chars to " \t\n" above if ifs is unset).  If IFS is set,
5264          string_list_dollar_at has separated the positional parameters
5265          with the first character of $IFS, so we split on $IFS. */
5266       if (has_dollar_at && ifs_chars)
5267         list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
5268       else
5269         {
5270           tword = make_bare_word (istring);
5271           list = make_word_list (tword, (WORD_LIST *)NULL);
5272           if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
5273             tword->flags |= W_QUOTED;
5274           if (word->flags & W_ASSIGNMENT)
5275             tword->flags |= W_ASSIGNMENT;
5276           if (word->flags & W_NOGLOB)
5277             tword->flags |= W_NOGLOB;
5278         }
5279     }
5280
5281   free (istring);
5282   return (list);
5283 }
5284
5285 /* **************************************************************** */
5286 /*                                                                  */
5287 /*                 Functions for Quote Removal                      */
5288 /*                                                                  */
5289 /* **************************************************************** */
5290
5291 /* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
5292    backslash quoting rules for within double quotes. */
5293 char *
5294 string_quote_removal (string, quoted)
5295      char *string;
5296      int quoted;
5297 {
5298   char *r, *result_string, *temp;
5299   int sindex, tindex, c, dquote;
5300
5301   /* The result can be no longer than the original string. */
5302   r = result_string = xmalloc (strlen (string) + 1);
5303
5304   for (dquote = sindex = 0; c = string[sindex];)
5305     {
5306       switch (c)
5307         {
5308         case '\\':
5309           c = string[++sindex];
5310           if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && member (c, slashify_in_quotes) == 0)
5311             *r++ = '\\';
5312           /* FALLTHROUGH */
5313
5314         default:
5315           *r++ = c;
5316           sindex++;
5317           break;
5318
5319         case '\'':
5320           if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
5321             {
5322               *r++ = c;
5323               sindex++;
5324               break;
5325             }
5326           tindex = sindex + 1;
5327           temp = string_extract_single_quoted (string, &tindex);
5328           if (temp)
5329             {
5330               strcpy (r, temp);
5331               r += strlen (r);
5332               free (temp);
5333             }
5334           sindex = tindex;
5335           break;
5336
5337         case '"':
5338           dquote = 1 - dquote;
5339           sindex++;
5340           break;
5341         }
5342     }
5343     *r = '\0';
5344     return (result_string);
5345 }
5346
5347 #if 0
5348 /* UNUSED */
5349 /* Perform quote removal on word WORD.  This allocates and returns a new
5350    WORD_DESC *. */
5351 WORD_DESC *
5352 word_quote_removal (word, quoted)
5353      WORD_DESC *word;
5354      int quoted;
5355 {
5356   WORD_DESC *w;
5357   char *t;
5358
5359   t = string_quote_removal (word->word, quoted);
5360   w = make_bare_word (t);
5361   free (t);
5362   return (w);
5363 }
5364
5365 /* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
5366    the members of the list are treated as if they are surrounded by
5367    double quotes.  Return a new list, or NULL if LIST is NULL. */
5368 WORD_LIST *
5369 word_list_quote_removal (list, quoted)
5370      WORD_LIST *list;
5371      int quoted;
5372 {
5373   WORD_LIST *result, *t, *tresult;
5374
5375   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5376     {
5377       tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
5378       tresult->word = word_quote_removal (t->word, quoted);
5379       tresult->next = (WORD_LIST *)NULL;
5380       result = (WORD_LIST *) list_append (result, tresult);
5381     }
5382   return (result);
5383 }
5384 #endif
5385
5386 /*******************************************
5387  *                                         *
5388  *    Functions to perform word splitting  *
5389  *                                         *
5390  *******************************************/
5391
5392 static char *
5393 getifs ()
5394 {
5395   SHELL_VAR *ifs;
5396
5397   ifs = find_variable ("IFS");
5398   /* If IFS is unset, it defaults to " \t\n". */
5399   return (ifs ? value_cell (ifs) : " \t\n");
5400 }
5401
5402 /* This splits a single word into a WORD LIST on $IFS, but only if the word
5403    is not quoted.  list_string () performs quote removal for us, even if we
5404    don't do any splitting. */
5405 WORD_LIST *
5406 word_split (w)
5407      WORD_DESC *w;
5408 {
5409   WORD_LIST *result;
5410   SHELL_VAR *ifs;
5411   char *ifs_chars;
5412
5413   if (w)
5414     {
5415       ifs = find_variable ("IFS");
5416       /* If IFS is unset, it defaults to " \t\n". */
5417       ifs_chars = ifs ? value_cell (ifs) : " \t\n";
5418
5419       if ((w->flags & W_QUOTED) || !ifs_chars)
5420         ifs_chars = "";
5421
5422       result = list_string (w->word, ifs_chars, w->flags & W_QUOTED);
5423
5424       if (ifs && tempvar_p (ifs))       /* XXX */
5425         dispose_variable (ifs);         /* XXX */
5426     }
5427   else
5428     result = (WORD_LIST *)NULL;
5429
5430   return (result);
5431 }
5432
5433 /* Perform word splitting on LIST and return the RESULT.  It is possible
5434    to return (WORD_LIST *)NULL. */
5435 static WORD_LIST *
5436 word_list_split (list)
5437      WORD_LIST *list;
5438 {
5439   WORD_LIST *result, *t, *tresult;
5440
5441   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5442     {
5443       tresult = word_split (t->word);
5444       result = (WORD_LIST *) list_append (result, tresult);
5445     }
5446   return (result);
5447 }
5448
5449 /**************************************************
5450  *                                                *
5451  *    Functions to expand an entire WORD_LIST     *
5452  *                                                *
5453  **************************************************/
5454
5455 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
5456    ELIST, and set ELIST to the new list. */
5457 #define PREPEND_LIST(nlist, elist) \
5458         do { nlist->next = elist; elist = nlist; } while (0)
5459
5460 static WORD_LIST *varlist = (WORD_LIST *)NULL;
5461
5462 /* Separate out any initial variable assignments from TLIST.  If set -k has
5463    been executed, remove all assignment statements from TLIST.  Initial
5464    variable assignments and other environment assignments are placed
5465    on VARLIST. */
5466 static WORD_LIST *
5467 separate_out_assignments (tlist)
5468      WORD_LIST *tlist;
5469 {
5470   register WORD_LIST *vp, *lp;
5471
5472   if (!tlist)
5473     return ((WORD_LIST *)NULL);
5474
5475   if (varlist)
5476     dispose_words (varlist);    /* Clean up after previous error */
5477
5478   varlist = (WORD_LIST *)NULL;
5479   vp = lp = tlist;
5480
5481   /* Separate out variable assignments at the start of the command.
5482      Loop invariant: vp->next == lp
5483      Loop postcondition:
5484         lp = list of words left after assignment statements skipped
5485         tlist = original list of words
5486   */
5487   while (lp && (lp->word->flags & W_ASSIGNMENT))
5488     {
5489       vp = lp;
5490       lp = lp->next;
5491     }
5492
5493   /* If lp != tlist, we have some initial assignment statements. */
5494   /* We make VARLIST point to the list of assignment words and
5495      TLIST point to the remaining words.  */
5496   if (lp != tlist)
5497     {
5498       varlist = tlist;
5499       /* ASSERT(vp->next == lp); */
5500       vp->next = (WORD_LIST *)NULL;     /* terminate variable list */
5501       tlist = lp;                       /* remainder of word list */
5502     }
5503
5504   /* vp == end of variable list */
5505   /* tlist == remainder of original word list without variable assignments */
5506   if (!tlist)
5507     /* All the words in tlist were assignment statements */
5508     return ((WORD_LIST *)NULL);
5509
5510   /* ASSERT(tlist != NULL); */
5511   /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
5512
5513   /* If the -k option is in effect, we need to go through the remaining
5514      words, separate out the assignment words, and place them on VARLIST. */
5515   if (place_keywords_in_env)
5516     {
5517       WORD_LIST *tp;    /* tp == running pointer into tlist */
5518
5519       tp = tlist;
5520       lp = tlist->next;
5521
5522       /* Loop Invariant: tp->next == lp */
5523       /* Loop postcondition: tlist == word list without assignment statements */
5524       while (lp)
5525         {
5526           if (lp->word->flags & W_ASSIGNMENT)
5527             {
5528               /* Found an assignment statement, add this word to end of
5529                  varlist (vp). */
5530               if (!varlist)
5531                 varlist = vp = lp;
5532               else
5533                 {
5534                   vp->next = lp;
5535                   vp = lp;
5536                 }
5537
5538               /* Remove the word pointed to by LP from TLIST. */
5539               tp->next = lp->next;
5540               /* ASSERT(vp == lp); */
5541               lp->next = (WORD_LIST *)NULL;
5542               lp = tp->next;
5543             }
5544           else
5545             {
5546               tp = lp;
5547               lp = lp->next;
5548             }
5549         }
5550     }
5551   return (tlist);
5552 }
5553
5554 #define WEXP_VARASSIGN  0x001
5555 #define WEXP_BRACEEXP   0x002
5556 #define WEXP_TILDEEXP   0x004
5557 #define WEXP_PARAMEXP   0x008
5558 #define WEXP_PATHEXP    0x010
5559
5560 /* All of the expansions, including variable assignments at the start of
5561    the list. */
5562 #define WEXP_ALL        (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
5563
5564 /* All of the expansions except variable assignments at the start of
5565    the list. */
5566 #define WEXP_NOVARS     (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
5567
5568 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
5569    expansion, command substitution, arithmetic expansion, word splitting, and
5570    quote removal. */
5571 #define WEXP_SHELLEXP   (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
5572
5573 /* Take the list of words in LIST and do the various substitutions.  Return
5574    a new list of words which is the expanded list, and without things like
5575    variable assignments. */
5576
5577 WORD_LIST *
5578 expand_words (list)
5579      WORD_LIST *list;
5580 {
5581   return (expand_word_list_internal (list, WEXP_ALL));
5582 }
5583
5584 /* Same as expand_words (), but doesn't hack variable or environment
5585    variables. */
5586 WORD_LIST *
5587 expand_words_no_vars (list)
5588      WORD_LIST *list;
5589 {
5590   return (expand_word_list_internal (list, WEXP_NOVARS));
5591 }
5592
5593 WORD_LIST *
5594 expand_words_shellexp (list)
5595      WORD_LIST *list;
5596 {
5597   return (expand_word_list_internal (list, WEXP_SHELLEXP));
5598 }
5599
5600 static WORD_LIST *
5601 glob_expand_word_list (tlist, eflags)
5602      WORD_LIST *tlist;
5603      int eflags;
5604 {
5605   char **glob_array, *temp_string;
5606   register int glob_index;
5607   WORD_LIST *glob_list, *output_list, *disposables, *next;
5608   WORD_DESC *tword;
5609
5610   output_list = disposables = (WORD_LIST *)NULL;
5611   glob_array = (char **)NULL;
5612   while (tlist)
5613     {
5614       /* For each word, either globbing is attempted or the word is
5615          added to orig_list.  If globbing succeeds, the results are
5616          added to orig_list and the word (tlist) is added to the list
5617          of disposable words.  If globbing fails and failed glob
5618          expansions are left unchanged (the shell default), the
5619          original word is added to orig_list.  If globbing fails and
5620          failed glob expansions are removed, the original word is
5621          added to the list of disposable words.  orig_list ends up
5622          in reverse order and requires a call to reverse_list to
5623          be set right.  After all words are examined, the disposable
5624          words are freed. */
5625       next = tlist->next;
5626
5627       /* If the word isn't an assignment and contains an unquoted
5628          pattern matching character, then glob it. */
5629 #if 0
5630       if ((tlist->word->flags & W_ASSIGNMENT) == 0 &&
5631 #else
5632       if ((tlist->word->flags & W_NOGLOB) == 0 &&
5633 #endif
5634           unquoted_glob_pattern_p (tlist->word->word))
5635         {
5636           glob_array = shell_glob_filename (tlist->word->word);
5637
5638           /* Handle error cases.
5639              I don't think we should report errors like "No such file
5640              or directory".  However, I would like to report errors
5641              like "Read failed". */
5642
5643           if (GLOB_FAILED (glob_array))
5644             {
5645               glob_array = (char **) xmalloc (sizeof (char *));
5646               glob_array[0] = (char *)NULL;
5647             }
5648
5649           /* Dequote the current word in case we have to use it. */
5650           if (glob_array[0] == NULL)
5651             {
5652               temp_string = dequote_string (tlist->word->word);
5653               free (tlist->word->word);
5654               tlist->word->word = temp_string;
5655             }
5656
5657           /* Make the array into a word list. */
5658           glob_list = (WORD_LIST *)NULL;
5659           for (glob_index = 0; glob_array[glob_index]; glob_index++)
5660             {
5661               tword = make_bare_word (glob_array[glob_index]);
5662               tword->flags |= W_GLOBEXP;        /* XXX */
5663               glob_list = make_word_list (tword, glob_list);
5664             }
5665
5666           if (glob_list)
5667             {
5668               output_list = (WORD_LIST *)list_append (glob_list, output_list);
5669               PREPEND_LIST (tlist, disposables);
5670             }
5671           else if (allow_null_glob_expansion == 0)
5672             {
5673               /* Failed glob expressions are left unchanged. */
5674               PREPEND_LIST (tlist, output_list);
5675             }
5676           else
5677             {
5678               /* Failed glob expressions are removed. */
5679               PREPEND_LIST (tlist, disposables);
5680             }
5681         }
5682       else
5683         {
5684           /* Dequote the string. */
5685           temp_string = dequote_string (tlist->word->word);
5686           free (tlist->word->word);
5687           tlist->word->word = temp_string;
5688           PREPEND_LIST (tlist, output_list);
5689         }
5690
5691       free_array (glob_array);
5692       glob_array = (char **)NULL;
5693
5694       tlist = next;
5695     }
5696
5697   if (disposables)
5698     dispose_words (disposables);
5699
5700   if (output_list)
5701     output_list = REVERSE_LIST (output_list, WORD_LIST *);
5702
5703   return (output_list);
5704 }
5705
5706 #if defined (BRACE_EXPANSION)
5707 static WORD_LIST *
5708 brace_expand_word_list (tlist, eflags)
5709      WORD_LIST *tlist;
5710      int eflags;
5711 {
5712   register char **expansions;
5713   char *temp_string;
5714   WORD_LIST *disposables, *output_list, *next;
5715   WORD_DESC *w;
5716   int eindex;
5717
5718   for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
5719     {
5720       next = tlist->next;
5721
5722       /* Only do brace expansion if the word has a brace character.  If
5723          not, just add the word list element to BRACES and continue.  In
5724          the common case, at least when running shell scripts, this will
5725          degenerate to a bunch of calls to `strchr', and then what is
5726          basically a reversal of TLIST into BRACES, which is corrected
5727          by a call to reverse_list () on BRACES when the end of TLIST
5728          is reached. */
5729       if (strchr (tlist->word->word, LBRACE))
5730         {
5731           expansions = brace_expand (tlist->word->word);
5732
5733           for (eindex = 0; temp_string = expansions[eindex]; eindex++)
5734             {
5735               w = make_word (temp_string);
5736               /* If brace expansion didn't change the word, preserve
5737                  the flags.  We may want to preserve the flags
5738                  unconditionally someday -- XXX */
5739               if (STREQ (temp_string, tlist->word->word))
5740                 w->flags = tlist->word->flags;
5741               output_list = make_word_list (w, output_list);
5742               free (expansions[eindex]);
5743             }
5744           free (expansions);
5745
5746           /* Add TLIST to the list of words to be freed after brace
5747              expansion has been performed. */
5748           PREPEND_LIST (tlist, disposables);
5749         }
5750       else
5751         PREPEND_LIST (tlist, output_list);
5752     }
5753
5754   if (disposables)
5755     dispose_words (disposables);
5756
5757   if (output_list)
5758     output_list = REVERSE_LIST (output_list, WORD_LIST *);
5759
5760   return (output_list);
5761 }
5762 #endif
5763
5764 static WORD_LIST *
5765 shell_expand_word_list (tlist, eflags)
5766      WORD_LIST *tlist;
5767      int eflags;
5768 {
5769   WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
5770   int expanded_something, has_dollar_at;
5771   char *temp_string;
5772
5773   /* We do tilde expansion all the time.  This is what 1003.2 says. */
5774   new_list = (WORD_LIST *)NULL;
5775   for (orig_list = tlist; tlist; tlist = next)
5776     {
5777       temp_string = tlist->word->word;
5778
5779       next = tlist->next;
5780
5781       /* Posix.2 section 3.6.1 says that tildes following `=' in words
5782          which are not assignment statements are not expanded.  We do
5783          this only if POSIXLY_CORRECT is enabled.  Essentially, we do
5784          tilde expansion on unquoted assignment statements (flags include
5785          W_ASSIGNMENT but not W_QUOTED). */
5786       if (temp_string[0] == '~' ||
5787             (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
5788              posixly_correct == 0 &&
5789              strchr (temp_string, '~') &&
5790              (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string))))
5791         {
5792           tlist->word->word = bash_tilde_expand (temp_string);
5793           free (temp_string);
5794         }
5795
5796       expanded_something = 0;
5797       expanded = expand_word_internal
5798         (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
5799
5800       if (expanded == &expand_word_error || expanded == &expand_word_fatal)
5801         {
5802           /* By convention, each time this error is returned,
5803              tlist->word->word has already been freed. */
5804           tlist->word->word = (char *)NULL;
5805
5806           /* Dispose our copy of the original list. */
5807           dispose_words (orig_list);
5808           /* Dispose the new list we're building. */
5809           dispose_words (new_list);
5810
5811           if (expanded == &expand_word_error)
5812             jump_to_top_level (DISCARD);
5813           else
5814             jump_to_top_level (FORCE_EOF);
5815         }
5816
5817       /* Don't split words marked W_NOSPLIT. */
5818       if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
5819         {
5820           temp_list = word_list_split (expanded);
5821           dispose_words (expanded);
5822         }
5823       else
5824         {
5825           /* If no parameter expansion, command substitution, process
5826              substitution, or arithmetic substitution took place, then
5827              do not do word splitting.  We still have to remove quoted
5828              null characters from the result. */
5829           word_list_remove_quoted_nulls (expanded);
5830           temp_list = expanded;
5831         }
5832
5833       expanded = REVERSE_LIST (temp_list, WORD_LIST *);
5834       new_list = (WORD_LIST *)list_append (expanded, new_list);
5835     }
5836
5837   if (orig_list)  
5838     dispose_words (orig_list);
5839
5840   if (new_list)
5841     new_list = REVERSE_LIST (new_list, WORD_LIST *);
5842
5843   return (new_list);
5844 }
5845
5846 /* The workhorse for expand_words () and expand_words_no_vars ().
5847    First arg is LIST, a WORD_LIST of words.
5848    Second arg EFLAGS is a flags word controlling which expansions are
5849    performed.
5850
5851    This does all of the substitutions: brace expansion, tilde expansion,
5852    parameter expansion, command substitution, arithmetic expansion,
5853    process substitution, word splitting, and pathname expansion, according
5854    to the bits set in EFLAGS.  Words with the W_QUOTED or W_NOSPLIT bits
5855    set, or for which no expansion is done, do not undergo word splitting.
5856    Words with the W_NOGLOB bit set do not undergo pathname expansion. */
5857 static WORD_LIST *
5858 expand_word_list_internal (list, eflags)
5859      WORD_LIST *list;
5860      int eflags;
5861 {
5862   WORD_LIST *new_list, *temp_list;
5863   int tint;
5864
5865   if (list == 0)
5866     return ((WORD_LIST *)NULL);
5867
5868   new_list = copy_word_list (list);
5869
5870   if (eflags & WEXP_VARASSIGN)
5871     {
5872       new_list = separate_out_assignments (new_list);
5873       if (new_list == 0)
5874         {
5875           if (varlist)
5876             {
5877               /* All the words were variable assignments, so they are placed
5878                  into the shell's environment. */
5879               for (temp_list = varlist; temp_list; temp_list = temp_list->next)
5880                 {
5881                   this_command_name = (char *)NULL;     /* no arithmetic errors */
5882                   tint = do_assignment (temp_list->word->word);
5883                   /* Variable assignment errors in non-interactive shells
5884                      running in Posix.2 mode cause the shell to exit. */
5885                   if (tint == 0 && interactive_shell == 0 && posixly_correct)
5886                     {
5887                       last_command_exit_value = EXECUTION_FAILURE;
5888                       jump_to_top_level (FORCE_EOF);
5889                     }
5890                 }
5891               dispose_words (varlist);
5892               varlist = (WORD_LIST *)NULL;
5893             }
5894           return ((WORD_LIST *)NULL);
5895         }
5896     }
5897
5898   /* Begin expanding the words that remain.  The expansions take place on
5899      things that aren't really variable assignments. */
5900
5901 #if defined (BRACE_EXPANSION)
5902   /* Do brace expansion on this word if there are any brace characters
5903      in the string. */
5904   if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
5905     new_list = brace_expand_word_list (new_list, eflags);
5906 #endif /* BRACE_EXPANSION */
5907
5908   /* Perform the `normal' shell expansions: tilde expansion, parameter and
5909      variable substitution, command substitution, arithmetic expansion,
5910      and word splitting. */
5911   new_list = shell_expand_word_list (new_list, eflags);
5912
5913   /* Okay, we're almost done.  Now let's just do some filename
5914      globbing. */
5915   if (new_list)
5916     {
5917       if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
5918         /* Glob expand the word list unless globbing has been disabled. */
5919         new_list = glob_expand_word_list (new_list, eflags);
5920       else
5921         /* Dequote the words, because we're not performing globbing. */
5922         new_list = dequote_list (new_list);
5923     }
5924
5925   if ((eflags & WEXP_VARASSIGN) && varlist)
5926     {
5927       Function *assign_func;
5928
5929       /* If the remainder of the words expand to nothing, Posix.2 requires
5930          that the variable and environment assignments affect the shell's
5931          environment. */
5932       assign_func = new_list ? assign_in_env : do_assignment;
5933
5934       for (temp_list = varlist; temp_list; temp_list = temp_list->next)
5935         {
5936           this_command_name = (char *)NULL;
5937           tint = (*assign_func) (temp_list->word->word);
5938           /* Variable assignment errors in non-interactive shells running
5939              in Posix.2 mode cause the shell to exit. */
5940           if (tint == 0 && assign_func == do_assignment &&
5941                 interactive_shell == 0 && posixly_correct)
5942             {
5943               last_command_exit_value = EXECUTION_FAILURE;
5944               jump_to_top_level (FORCE_EOF);
5945             }
5946         }
5947
5948       dispose_words (varlist);
5949       varlist = (WORD_LIST *)NULL;
5950     }
5951
5952 #if 0
5953   tint = list_length (new_list) + 1;
5954   RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
5955   for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
5956     glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
5957   glob_argv_flags[tint] = '\0';
5958 #endif
5959
5960   return (new_list);
5961 }