Patch-ID: bash32-028
[bash.git] / subst.c
blobc916761c7f418e28c4beee0206b2d0380df98ea8
1 /* subst.c -- The part of the shell that does parameter, command, arithmetic,
2 and globbing substitutions. */
4 /* ``Have a little faith, there's magic in the night. You ain't a
5 beauty, but, hey, you're alright.'' */
7 /* Copyright (C) 1987-2007 Free Software Foundation, Inc.
9 This file is part of GNU Bash, the Bourne Again SHell.
11 Bash is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
16 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License along
22 with Bash; see the file COPYING. If not, write to the Free Software
23 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
25 #include "config.h"
27 #include "bashtypes.h"
28 #include <stdio.h>
29 #include "chartypes.h"
30 #include <pwd.h>
31 #include <signal.h>
32 #include <errno.h>
34 #if defined (HAVE_UNISTD_H)
35 # include <unistd.h>
36 #endif
38 #include "bashansi.h"
39 #include "posixstat.h"
40 #include "bashintl.h"
42 #include "shell.h"
43 #include "flags.h"
44 #include "jobs.h"
45 #include "execute_cmd.h"
46 #include "filecntl.h"
47 #include "trap.h"
48 #include "pathexp.h"
49 #include "mailcheck.h"
51 #include "shmbutil.h"
53 #include "builtins/getopt.h"
54 #include "builtins/common.h"
56 #include <tilde/tilde.h>
57 #include <glob/strmatch.h>
59 #if !defined (errno)
60 extern int errno;
61 #endif /* !errno */
63 /* The size that strings change by. */
64 #define DEFAULT_INITIAL_ARRAY_SIZE 112
65 #define DEFAULT_ARRAY_SIZE 128
67 /* Variable types. */
68 #define VT_VARIABLE 0
69 #define VT_POSPARMS 1
70 #define VT_ARRAYVAR 2
71 #define VT_ARRAYMEMBER 3
73 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
75 /* Flags for quoted_strchr */
76 #define ST_BACKSL 0x01
77 #define ST_CTLESC 0x02
78 #define ST_SQUOTE 0x04 /* unused yet */
79 #define ST_DQUOTE 0x08 /* unused yet */
81 /* Flags for the string extraction functions. */
82 #define EX_NOALLOC 0x01 /* just skip; don't return substring */
83 #define EX_VARNAME 0x02 /* variable name; for string_extract () */
84 #define EX_REQMATCH 0x04 /* closing/matching delimiter required */
85 #define EX_COMMAND 0x08 /* extracting a shell script/command */
87 /* Flags for the `pflags' argument to param_expand() */
88 #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
90 /* These defs make it easier to use the editor. */
91 #define LBRACE '{'
92 #define RBRACE '}'
93 #define LPAREN '('
94 #define RPAREN ')'
96 /* Evaluates to 1 if C is one of the shell's special parameters whose length
97 can be taken, but is also one of the special expansion characters. */
98 #define VALID_SPECIAL_LENGTH_PARAM(c) \
99 ((c) == '-' || (c) == '?' || (c) == '#')
101 /* Evaluates to 1 if C is one of the shell's special parameters for which an
102 indirect variable reference may be made. */
103 #define VALID_INDIR_PARAM(c) \
104 ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
106 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
107 in ${parameter[:]OPword}. */
108 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
110 /* Evaluates to 1 if this is one of the shell's special variables. */
111 #define SPECIAL_VAR(name, wi) \
112 ((DIGIT (*name) && all_digits (name)) || \
113 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
114 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
116 /* An expansion function that takes a string and a quoted flag and returns
117 a WORD_LIST *. Used as the type of the third argument to
118 expand_string_if_necessary(). */
119 typedef WORD_LIST *EXPFUNC __P((char *, int));
121 /* Process ID of the last command executed within command substitution. */
122 pid_t last_command_subst_pid = NO_PID;
123 pid_t current_command_subst_pid = NO_PID;
125 /* Variables used to keep track of the characters in IFS. */
126 SHELL_VAR *ifs_var;
127 char *ifs_value;
128 unsigned char ifs_cmap[UCHAR_MAX + 1];
130 #if defined (HANDLE_MULTIBYTE)
131 unsigned char ifs_firstc[MB_LEN_MAX];
132 size_t ifs_firstc_len;
133 #else
134 unsigned char ifs_firstc;
135 #endif
137 /* Extern functions and variables from different files. */
138 extern int last_command_exit_value, last_command_exit_signal;
139 extern int subshell_environment;
140 extern int subshell_level;
141 extern int eof_encountered;
142 extern int return_catch_flag, return_catch_value;
143 extern pid_t dollar_dollar_pid;
144 extern int posixly_correct;
145 extern char *this_command_name;
146 extern struct fd_bitmap *current_fds_to_close;
147 extern int wordexp_only;
148 extern int expanding_redir;
149 extern int tempenv_assign_error;
151 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
152 extern wchar_t *wcsdup __P((const wchar_t *));
153 #endif
155 /* Non-zero means to allow unmatched globbed filenames to expand to
156 a null file. */
157 int allow_null_glob_expansion;
159 /* Non-zero means to throw an error when globbing fails to match anything. */
160 int fail_glob_expansion;
162 #if 0
163 /* Variables to keep track of which words in an expanded word list (the
164 output of expand_word_list_internal) are the result of globbing
165 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
166 (CURRENTLY UNUSED). */
167 char *glob_argv_flags;
168 static int glob_argv_flags_size;
169 #endif
171 static WORD_LIST expand_word_error, expand_word_fatal;
172 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
173 static char expand_param_error, expand_param_fatal;
174 static char extract_string_error, extract_string_fatal;
176 /* Tell the expansion functions to not longjmp back to top_level on fatal
177 errors. Enabled when doing completion and prompt string expansion. */
178 static int no_longjmp_on_fatal_error = 0;
180 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
181 $* on $IFS, primarily when doing assignment statements. */
182 static int expand_no_split_dollar_star = 0;
184 /* Used to hold a list of variable assignments preceding a command. Global
185 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
186 SIGCHLD trap. */
187 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
189 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
190 without any leading variable assignments. */
191 static WORD_LIST *garglist = (WORD_LIST *)NULL;
193 static char *quoted_substring __P((char *, int, int));
194 static int quoted_strlen __P((char *));
195 static char *quoted_strchr __P((char *, int, int));
197 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
198 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
199 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
200 static WORD_LIST *expand_string_internal __P((char *, int));
201 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
202 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
204 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
205 static char *dequote_escapes __P((char *));
206 static char *make_quoted_char __P((int));
207 static WORD_LIST *quote_list __P((WORD_LIST *));
208 static char *remove_quoted_escapes __P((char *));
209 static char *remove_quoted_nulls __P((char *));
211 static int unquoted_substring __P((char *, char *));
212 static int unquoted_member __P((int, char *));
214 #if defined (ARRAY_VARS)
215 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
216 #endif
217 static int do_assignment_internal __P((const WORD_DESC *, int));
219 static char *string_extract_verbatim __P((char *, size_t, int *, char *));
220 static char *string_extract __P((char *, int *, char *, int));
221 static char *string_extract_double_quoted __P((char *, int *, int));
222 static inline char *string_extract_single_quoted __P((char *, int *));
223 static inline int skip_single_quoted __P((const char *, size_t, int));
224 static int skip_double_quoted __P((char *, size_t, int));
225 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
226 static char *extract_dollar_brace_string __P((char *, int *, int, int));
228 static char *pos_params __P((char *, int, int, int));
230 static unsigned char *mb_getcharlens __P((char *, int));
232 static char *remove_upattern __P((char *, char *, int));
233 #if defined (HANDLE_MULTIBYTE)
234 static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
235 #endif
236 static char *remove_pattern __P((char *, char *, int));
238 static int match_pattern_char __P((char *, char *));
239 static int match_upattern __P((char *, char *, int, char **, char **));
240 #if defined (HANDLE_MULTIBYTE)
241 static int match_pattern_wchar __P((wchar_t *, wchar_t *));
242 static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
243 #endif
244 static int match_pattern __P((char *, char *, int, char **, char **));
245 static int getpatspec __P((int, char *));
246 static char *getpattern __P((char *, int, int));
247 static char *variable_remove_pattern __P((char *, char *, int, int));
248 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
249 static char *parameter_list_remove_pattern __P((int, char *, int, int));
250 #ifdef ARRAY_VARS
251 static char *array_remove_pattern __P((ARRAY *, char *, int, char *, int));
252 #endif
253 static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
255 static char *process_substitute __P((char *, int));
257 static char *read_comsub __P((int, int));
259 #ifdef ARRAY_VARS
260 static arrayind_t array_length_reference __P((char *));
261 #endif
263 static int valid_brace_expansion_word __P((char *, int));
264 static int chk_atstar __P((char *, int, int *, int *));
265 static int chk_arithsub __P((const char *, int));
267 static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
268 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
269 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
270 static void parameter_brace_expand_error __P((char *, char *));
272 static int valid_length_expression __P((char *));
273 static intmax_t parameter_brace_expand_length __P((char *));
275 static char *skiparith __P((char *, int));
276 static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
277 static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
278 static char *mb_substring __P((char *, int, int));
279 static char *parameter_brace_substring __P((char *, char *, char *, int));
281 static char *pos_params_pat_subst __P((char *, char *, char *, int));
283 static char *parameter_brace_patsub __P((char *, char *, char *, int));
285 static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
286 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
288 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
290 static WORD_LIST *word_list_split __P((WORD_LIST *));
292 static void exp_jump_to_top_level __P((int));
294 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
295 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
296 #ifdef BRACE_EXPANSION
297 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
298 #endif
299 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
300 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
302 /* **************************************************************** */
303 /* */
304 /* Utility Functions */
305 /* */
306 /* **************************************************************** */
308 #ifdef INCLUDE_UNUSED
309 static char *
310 quoted_substring (string, start, end)
311 char *string;
312 int start, end;
314 register int len, l;
315 register char *result, *s, *r;
317 len = end - start;
319 /* Move to string[start], skipping quoted characters. */
320 for (s = string, l = 0; *s && l < start; )
322 if (*s == CTLESC)
324 s++;
325 continue;
327 l++;
328 if (*s == 0)
329 break;
332 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
334 /* Copy LEN characters, including quote characters. */
335 s = string + l;
336 for (l = 0; l < len; s++)
338 if (*s == CTLESC)
339 *r++ = *s++;
340 *r++ = *s;
341 l++;
342 if (*s == 0)
343 break;
345 *r = '\0';
346 return result;
348 #endif
350 #ifdef INCLUDE_UNUSED
351 /* Return the length of S, skipping over quoted characters */
352 static int
353 quoted_strlen (s)
354 char *s;
356 register char *p;
357 int i;
359 i = 0;
360 for (p = s; *p; p++)
362 if (*p == CTLESC)
364 p++;
365 if (*p == 0)
366 return (i + 1);
368 i++;
371 return i;
373 #endif
375 /* Find the first occurrence of character C in string S, obeying shell
376 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
377 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
378 escaped with CTLESC are skipped. */
379 static char *
380 quoted_strchr (s, c, flags)
381 char *s;
382 int c, flags;
384 register char *p;
386 for (p = s; *p; p++)
388 if (((flags & ST_BACKSL) && *p == '\\')
389 || ((flags & ST_CTLESC) && *p == CTLESC))
391 p++;
392 if (*p == '\0')
393 return ((char *)NULL);
394 continue;
396 else if (*p == c)
397 return p;
399 return ((char *)NULL);
402 /* Return 1 if CHARACTER appears in an unquoted portion of
403 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
404 static int
405 unquoted_member (character, string)
406 int character;
407 char *string;
409 size_t slen;
410 int sindex, c;
411 DECLARE_MBSTATE;
413 slen = strlen (string);
414 sindex = 0;
415 while (c = string[sindex])
417 if (c == character)
418 return (1);
420 switch (c)
422 default:
423 ADVANCE_CHAR (string, slen, sindex);
424 break;
426 case '\\':
427 sindex++;
428 if (string[sindex])
429 ADVANCE_CHAR (string, slen, sindex);
430 break;
432 case '\'':
433 sindex = skip_single_quoted (string, slen, ++sindex);
434 break;
436 case '"':
437 sindex = skip_double_quoted (string, slen, ++sindex);
438 break;
441 return (0);
444 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
445 static int
446 unquoted_substring (substr, string)
447 char *substr, *string;
449 size_t slen;
450 int sindex, c, sublen;
451 DECLARE_MBSTATE;
453 if (substr == 0 || *substr == '\0')
454 return (0);
456 slen = strlen (string);
457 sublen = strlen (substr);
458 for (sindex = 0; c = string[sindex]; )
460 if (STREQN (string + sindex, substr, sublen))
461 return (1);
463 switch (c)
465 case '\\':
466 sindex++;
468 if (string[sindex])
469 ADVANCE_CHAR (string, slen, sindex);
470 break;
472 case '\'':
473 sindex = skip_single_quoted (string, slen, ++sindex);
474 break;
476 case '"':
477 sindex = skip_double_quoted (string, slen, ++sindex);
478 break;
480 default:
481 ADVANCE_CHAR (string, slen, sindex);
482 break;
485 return (0);
488 /* Most of the substitutions must be done in parallel. In order
489 to avoid using tons of unclear goto's, I have some functions
490 for manipulating malloc'ed strings. They all take INDX, a
491 pointer to an integer which is the offset into the string
492 where manipulation is taking place. They also take SIZE, a
493 pointer to an integer which is the current length of the
494 character array for this string. */
496 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
497 of space allocated to TARGET. SOURCE can be NULL, in which
498 case nothing happens. Gets rid of SOURCE by freeing it.
499 Returns TARGET in case the location has changed. */
500 INLINE char *
501 sub_append_string (source, target, indx, size)
502 char *source, *target;
503 int *indx, *size;
505 if (source)
507 int srclen, n;
509 srclen = STRLEN (source);
510 if (srclen >= (int)(*size - *indx))
512 n = srclen + *indx;
513 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
514 target = (char *)xrealloc (target, (*size = n));
517 FASTCOPY (source, target + *indx, srclen);
518 *indx += srclen;
519 target[*indx] = '\0';
521 free (source);
523 return (target);
526 #if 0
527 /* UNUSED */
528 /* Append the textual representation of NUMBER to TARGET.
529 INDX and SIZE are as in SUB_APPEND_STRING. */
530 char *
531 sub_append_number (number, target, indx, size)
532 intmax_t number;
533 int *indx, *size;
534 char *target;
536 char *temp;
538 temp = itos (number);
539 return (sub_append_string (temp, target, indx, size));
541 #endif
543 /* Extract a substring from STRING, starting at SINDEX and ending with
544 one of the characters in CHARLIST. Don't make the ending character
545 part of the string. Leave SINDEX pointing at the ending character.
546 Understand about backslashes in the string. If (flags & EX_VARNAME)
547 is non-zero, and array variables have been compiled into the shell,
548 everything between a `[' and a corresponding `]' is skipped over.
549 If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
550 update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
551 contain a closing character from CHARLIST. */
552 static char *
553 string_extract (string, sindex, charlist, flags)
554 char *string;
555 int *sindex;
556 char *charlist;
557 int flags;
559 register int c, i;
560 int found;
561 size_t slen;
562 char *temp;
563 DECLARE_MBSTATE;
565 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
566 i = *sindex;
567 found = 0;
568 while (c = string[i])
570 if (c == '\\')
572 if (string[i + 1])
573 i++;
574 else
575 break;
577 #if defined (ARRAY_VARS)
578 else if ((flags & EX_VARNAME) && c == '[')
580 int ni;
581 /* If this is an array subscript, skip over it and continue. */
582 ni = skipsubscript (string, i);
583 if (string[ni] == ']')
584 i = ni;
586 #endif
587 else if (MEMBER (c, charlist))
589 found = 1;
590 break;
593 ADVANCE_CHAR (string, slen, i);
596 /* If we had to have a matching delimiter and didn't find one, return an
597 error and let the caller deal with it. */
598 if ((flags & EX_REQMATCH) && found == 0)
600 *sindex = i;
601 return (&extract_string_error);
604 temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
605 *sindex = i;
607 return (temp);
610 /* Extract the contents of STRING as if it is enclosed in double quotes.
611 SINDEX, when passed in, is the offset of the character immediately
612 following the opening double quote; on exit, SINDEX is left pointing after
613 the closing double quote. If STRIPDQ is non-zero, unquoted double
614 quotes are stripped and the string is terminated by a null byte.
615 Backslashes between the embedded double quotes are processed. If STRIPDQ
616 is zero, an unquoted `"' terminates the string. */
617 static char *
618 string_extract_double_quoted (string, sindex, stripdq)
619 char *string;
620 int *sindex, stripdq;
622 size_t slen;
623 char *send;
624 int j, i, t;
625 unsigned char c;
626 char *temp, *ret; /* The new string we return. */
627 int pass_next, backquote, si; /* State variables for the machine. */
628 int dquote;
629 DECLARE_MBSTATE;
631 slen = strlen (string + *sindex) + *sindex;
632 send = string + slen;
634 pass_next = backquote = dquote = 0;
635 temp = (char *)xmalloc (1 + slen - *sindex);
637 j = 0;
638 i = *sindex;
639 while (c = string[i])
641 /* Process a character that was quoted by a backslash. */
642 if (pass_next)
644 /* Posix.2 sez:
646 ``The backslash shall retain its special meaning as an escape
647 character only when followed by one of the characters:
648 $ ` " \ <newline>''.
650 If STRIPDQ is zero, we handle the double quotes here and let
651 expand_word_internal handle the rest. If STRIPDQ is non-zero,
652 we have already been through one round of backslash stripping,
653 and want to strip these backslashes only if DQUOTE is non-zero,
654 indicating that we are inside an embedded double-quoted string. */
656 /* If we are in an embedded quoted string, then don't strip
657 backslashes before characters for which the backslash
658 retains its special meaning, but remove backslashes in
659 front of other characters. If we are not in an
660 embedded quoted string, don't strip backslashes at all.
661 This mess is necessary because the string was already
662 surrounded by double quotes (and sh has some really weird
663 quoting rules).
664 The returned string will be run through expansion as if
665 it were double-quoted. */
666 if ((stripdq == 0 && c != '"') ||
667 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
668 temp[j++] = '\\';
669 pass_next = 0;
671 add_one_character:
672 COPY_CHAR_I (temp, j, string, send, i);
673 continue;
676 /* A backslash protects the next character. The code just above
677 handles preserving the backslash in front of any character but
678 a double quote. */
679 if (c == '\\')
681 pass_next++;
682 i++;
683 continue;
686 /* Inside backquotes, ``the portion of the quoted string from the
687 initial backquote and the characters up to the next backquote
688 that is not preceded by a backslash, having escape characters
689 removed, defines that command''. */
690 if (backquote)
692 if (c == '`')
693 backquote = 0;
694 temp[j++] = c;
695 i++;
696 continue;
699 if (c == '`')
701 temp[j++] = c;
702 backquote++;
703 i++;
704 continue;
707 /* Pass everything between `$(' and the matching `)' or a quoted
708 ${ ... } pair through according to the Posix.2 specification. */
709 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
711 int free_ret = 1;
713 si = i + 2;
714 if (string[i + 1] == LPAREN)
715 ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_COMMAND); /*)*/
716 else
717 ret = extract_dollar_brace_string (string, &si, 1, 0);
719 temp[j++] = '$';
720 temp[j++] = string[i + 1];
722 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
723 is set. */
724 if (ret == 0 && no_longjmp_on_fatal_error)
726 free_ret = 0;
727 ret = string + i + 2;
730 for (t = 0; ret[t]; t++, j++)
731 temp[j] = ret[t];
732 temp[j] = string[si];
734 if (string[si])
736 j++;
737 i = si + 1;
739 else
740 i = si;
742 if (free_ret)
743 free (ret);
744 continue;
747 /* Add any character but a double quote to the quoted string we're
748 accumulating. */
749 if (c != '"')
750 goto add_one_character;
752 /* c == '"' */
753 if (stripdq)
755 dquote ^= 1;
756 i++;
757 continue;
760 break;
762 temp[j] = '\0';
764 /* Point to after the closing quote. */
765 if (c)
766 i++;
767 *sindex = i;
769 return (temp);
772 /* This should really be another option to string_extract_double_quoted. */
773 static int
774 skip_double_quoted (string, slen, sind)
775 char *string;
776 size_t slen;
777 int sind;
779 int c, i;
780 char *ret;
781 int pass_next, backquote, si;
782 DECLARE_MBSTATE;
784 pass_next = backquote = 0;
785 i = sind;
786 while (c = string[i])
788 if (pass_next)
790 pass_next = 0;
791 ADVANCE_CHAR (string, slen, i);
792 continue;
794 else if (c == '\\')
796 pass_next++;
797 i++;
798 continue;
800 else if (backquote)
802 if (c == '`')
803 backquote = 0;
804 ADVANCE_CHAR (string, slen, i);
805 continue;
807 else if (c == '`')
809 backquote++;
810 i++;
811 continue;
813 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
815 si = i + 2;
816 if (string[i + 1] == LPAREN)
817 ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
818 else
819 ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
821 i = si + 1;
822 continue;
824 else if (c != '"')
826 ADVANCE_CHAR (string, slen, i);
827 continue;
829 else
830 break;
833 if (c)
834 i++;
836 return (i);
839 /* Extract the contents of STRING as if it is enclosed in single quotes.
840 SINDEX, when passed in, is the offset of the character immediately
841 following the opening single quote; on exit, SINDEX is left pointing after
842 the closing single quote. */
843 static inline char *
844 string_extract_single_quoted (string, sindex)
845 char *string;
846 int *sindex;
848 register int i;
849 size_t slen;
850 char *t;
851 DECLARE_MBSTATE;
853 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
854 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
855 i = *sindex;
856 while (string[i] && string[i] != '\'')
857 ADVANCE_CHAR (string, slen, i);
859 t = substring (string, *sindex, i);
861 if (string[i])
862 i++;
863 *sindex = i;
865 return (t);
868 static inline int
869 skip_single_quoted (string, slen, sind)
870 const char *string;
871 size_t slen;
872 int sind;
874 register int c;
875 DECLARE_MBSTATE;
877 c = sind;
878 while (string[c] && string[c] != '\'')
879 ADVANCE_CHAR (string, slen, c);
881 if (string[c])
882 c++;
883 return c;
886 /* Just like string_extract, but doesn't hack backslashes or any of
887 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
888 static char *
889 string_extract_verbatim (string, slen, sindex, charlist)
890 char *string;
891 size_t slen;
892 int *sindex;
893 char *charlist;
895 register int i = *sindex;
896 #if defined (HANDLE_MULTIBYTE)
897 size_t clen;
898 wchar_t *wcharlist;
899 #endif
900 int c;
901 char *temp;
902 DECLARE_MBSTATE;
904 if (charlist[0] == '\'' && charlist[1] == '\0')
906 temp = string_extract_single_quoted (string, sindex);
907 --*sindex; /* leave *sindex at separator character */
908 return temp;
911 i = *sindex;
912 #if 0
913 /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
914 this only if MB_CUR_MAX > 1. */
915 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
916 #endif
917 #if defined (HANDLE_MULTIBYTE)
918 clen = strlen (charlist);
919 wcharlist = 0;
920 #endif
921 while (c = string[i])
923 #if defined (HANDLE_MULTIBYTE)
924 size_t mblength;
925 #endif
926 if (c == CTLESC)
928 i += 2;
929 continue;
932 #if defined (HANDLE_MULTIBYTE)
933 mblength = MBLEN (string + i, slen - i);
934 if (mblength > 1)
936 wchar_t wc;
937 mblength = mbtowc (&wc, string + i, slen - i);
938 if (MB_INVALIDCH (mblength))
940 if (MEMBER (c, charlist))
941 break;
943 else
945 if (wcharlist == 0)
947 size_t len;
948 len = mbstowcs (wcharlist, charlist, 0);
949 if (len == -1)
950 len = 0;
951 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
952 mbstowcs (wcharlist, charlist, len + 1);
955 if (wcschr (wcharlist, wc))
956 break;
959 else
960 #endif
961 if (MEMBER (c, charlist))
962 break;
964 ADVANCE_CHAR (string, slen, i);
967 #if defined (HANDLE_MULTIBYTE)
968 FREE (wcharlist);
969 #endif
971 temp = substring (string, *sindex, i);
972 *sindex = i;
974 return (temp);
977 /* Extract the $( construct in STRING, and return a new string.
978 Start extracting at (SINDEX) as if we had just seen "$(".
979 Make (SINDEX) get the position of the matching ")". ) */
980 char *
981 extract_command_subst (string, sindex)
982 char *string;
983 int *sindex;
985 return (extract_delimited_string (string, sindex, "$(", "(", ")", EX_COMMAND)); /*)*/
988 /* Extract the $[ construct in STRING, and return a new string. (])
989 Start extracting at (SINDEX) as if we had just seen "$[".
990 Make (SINDEX) get the position of the matching "]". */
991 char *
992 extract_arithmetic_subst (string, sindex)
993 char *string;
994 int *sindex;
996 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
999 #if defined (PROCESS_SUBSTITUTION)
1000 /* Extract the <( or >( construct in STRING, and return a new string.
1001 Start extracting at (SINDEX) as if we had just seen "<(".
1002 Make (SINDEX) get the position of the matching ")". */ /*))*/
1003 char *
1004 extract_process_subst (string, starter, sindex)
1005 char *string;
1006 char *starter;
1007 int *sindex;
1009 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1011 #endif /* PROCESS_SUBSTITUTION */
1013 #if defined (ARRAY_VARS)
1014 /* This can be fooled by unquoted right parens in the passed string. If
1015 each caller verifies that the last character in STRING is a right paren,
1016 we don't even need to call extract_delimited_string. */
1017 char *
1018 extract_array_assignment_list (string, sindex)
1019 char *string;
1020 int *sindex;
1022 int slen;
1023 char *ret;
1025 slen = strlen (string); /* ( */
1026 if (string[slen - 1] == ')')
1028 ret = substring (string, *sindex, slen - 1);
1029 *sindex = slen - 1;
1030 return ret;
1032 return 0;
1034 #endif
1036 /* Extract and create a new string from the contents of STRING, a
1037 character string delimited with OPENER and CLOSER. SINDEX is
1038 the address of an int describing the current offset in STRING;
1039 it should point to just after the first OPENER found. On exit,
1040 SINDEX gets the position of the last character of the matching CLOSER.
1041 If OPENER is more than a single character, ALT_OPENER, if non-null,
1042 contains a character string that can also match CLOSER and thus
1043 needs to be skipped. */
1044 static char *
1045 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1046 char *string;
1047 int *sindex;
1048 char *opener, *alt_opener, *closer;
1049 int flags;
1051 int i, c, si;
1052 size_t slen;
1053 char *t, *result;
1054 int pass_character, nesting_level, in_comment;
1055 int len_closer, len_opener, len_alt_opener;
1056 DECLARE_MBSTATE;
1058 slen = strlen (string + *sindex) + *sindex;
1059 len_opener = STRLEN (opener);
1060 len_alt_opener = STRLEN (alt_opener);
1061 len_closer = STRLEN (closer);
1063 pass_character = in_comment = 0;
1065 nesting_level = 1;
1066 i = *sindex;
1068 while (nesting_level)
1070 c = string[i];
1072 if (c == 0)
1073 break;
1075 if (in_comment)
1077 if (c == '\n')
1078 in_comment = 0;
1079 ADVANCE_CHAR (string, slen, i);
1080 continue;
1083 if (pass_character) /* previous char was backslash */
1085 pass_character = 0;
1086 ADVANCE_CHAR (string, slen, i);
1087 continue;
1090 /* Not exactly right yet; should handle shell metacharacters and
1091 multibyte characters, too. */
1092 if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
1094 in_comment = 1;
1095 ADVANCE_CHAR (string, slen, i);
1096 continue;
1099 if (c == CTLESC || c == '\\')
1101 pass_character++;
1102 i++;
1103 continue;
1106 /* Process a nested OPENER. */
1107 if (STREQN (string + i, opener, len_opener))
1109 si = i + len_opener;
1110 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
1111 i = si + 1;
1112 continue;
1115 /* Process a nested ALT_OPENER */
1116 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1118 si = i + len_alt_opener;
1119 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
1120 i = si + 1;
1121 continue;
1124 /* If the current substring terminates the delimited string, decrement
1125 the nesting level. */
1126 if (STREQN (string + i, closer, len_closer))
1128 i += len_closer - 1; /* move to last byte of the closer */
1129 nesting_level--;
1130 if (nesting_level == 0)
1131 break;
1134 /* Pass old-style command substitution through verbatim. */
1135 if (c == '`')
1137 si = i + 1;
1138 t = string_extract (string, &si, "`", flags|EX_NOALLOC);
1139 i = si + 1;
1140 continue;
1143 /* Pass single-quoted and double-quoted strings through verbatim. */
1144 if (c == '\'' || c == '"')
1146 si = i + 1;
1147 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1148 : skip_double_quoted (string, slen, si);
1149 continue;
1152 /* move past this character, which was not special. */
1153 ADVANCE_CHAR (string, slen, i);
1156 if (c == 0 && nesting_level)
1158 if (no_longjmp_on_fatal_error == 0)
1160 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1161 last_command_exit_value = EXECUTION_FAILURE;
1162 exp_jump_to_top_level (DISCARD);
1164 else
1166 *sindex = i;
1167 return (char *)NULL;
1171 si = i - *sindex - len_closer + 1;
1172 if (flags & EX_NOALLOC)
1173 result = (char *)NULL;
1174 else
1176 result = (char *)xmalloc (1 + si);
1177 strncpy (result, string + *sindex, si);
1178 result[si] = '\0';
1180 *sindex = i;
1182 return (result);
1185 /* Extract a parameter expansion expression within ${ and } from STRING.
1186 Obey the Posix.2 rules for finding the ending `}': count braces while
1187 skipping over enclosed quoted strings and command substitutions.
1188 SINDEX is the address of an int describing the current offset in STRING;
1189 it should point to just after the first `{' found. On exit, SINDEX
1190 gets the position of the matching `}'. QUOTED is non-zero if this
1191 occurs inside double quotes. */
1192 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1193 static char *
1194 extract_dollar_brace_string (string, sindex, quoted, flags)
1195 char *string;
1196 int *sindex, quoted, flags;
1198 register int i, c;
1199 size_t slen;
1200 int pass_character, nesting_level, si;
1201 char *result, *t;
1202 DECLARE_MBSTATE;
1204 pass_character = 0;
1205 nesting_level = 1;
1206 slen = strlen (string + *sindex) + *sindex;
1208 i = *sindex;
1209 while (c = string[i])
1211 if (pass_character)
1213 pass_character = 0;
1214 ADVANCE_CHAR (string, slen, i);
1215 continue;
1218 /* CTLESCs and backslashes quote the next character. */
1219 if (c == CTLESC || c == '\\')
1221 pass_character++;
1222 i++;
1223 continue;
1226 if (string[i] == '$' && string[i+1] == LBRACE)
1228 nesting_level++;
1229 i += 2;
1230 continue;
1233 if (c == RBRACE)
1235 nesting_level--;
1236 if (nesting_level == 0)
1237 break;
1238 i++;
1239 continue;
1242 /* Pass the contents of old-style command substitutions through
1243 verbatim. */
1244 if (c == '`')
1246 si = i + 1;
1247 t = string_extract (string, &si, "`", flags|EX_NOALLOC);
1248 i = si + 1;
1249 continue;
1252 /* Pass the contents of new-style command substitutions and
1253 arithmetic substitutions through verbatim. */
1254 if (string[i] == '$' && string[i+1] == LPAREN)
1256 si = i + 2;
1257 t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC|EX_COMMAND); /*)*/
1258 i = si + 1;
1259 continue;
1262 /* Pass the contents of single-quoted and double-quoted strings
1263 through verbatim. */
1264 if (c == '\'' || c == '"')
1266 si = i + 1;
1267 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1268 : skip_double_quoted (string, slen, si);
1269 /* skip_XXX_quoted leaves index one past close quote */
1270 continue;
1273 /* move past this character, which was not special. */
1274 ADVANCE_CHAR (string, slen, i);
1277 if (c == 0 && nesting_level)
1279 if (no_longjmp_on_fatal_error == 0)
1280 { /* { */
1281 report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1282 last_command_exit_value = EXECUTION_FAILURE;
1283 exp_jump_to_top_level (DISCARD);
1285 else
1287 *sindex = i;
1288 return ((char *)NULL);
1292 result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1293 *sindex = i;
1295 return (result);
1298 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1299 STRING, and returns a pointer to it. */
1300 char *
1301 de_backslash (string)
1302 char *string;
1304 register size_t slen;
1305 register int i, j, prev_i;
1306 DECLARE_MBSTATE;
1308 slen = strlen (string);
1309 i = j = 0;
1311 /* Loop copying string[i] to string[j], i >= j. */
1312 while (i < slen)
1314 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1315 string[i + 1] == '$'))
1316 i++;
1317 prev_i = i;
1318 ADVANCE_CHAR (string, slen, i);
1319 if (j < prev_i)
1320 do string[j++] = string[prev_i++]; while (prev_i < i);
1321 else
1322 j = i;
1324 string[j] = '\0';
1326 return (string);
1329 #if 0
1330 /*UNUSED*/
1331 /* Replace instances of \! in a string with !. */
1332 void
1333 unquote_bang (string)
1334 char *string;
1336 register int i, j;
1337 register char *temp;
1339 temp = (char *)xmalloc (1 + strlen (string));
1341 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1343 if (string[i] == '\\' && string[i + 1] == '!')
1345 temp[j] = '!';
1346 i++;
1349 strcpy (string, temp);
1350 free (temp);
1352 #endif
1354 #if defined (READLINE)
1355 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1356 an unclosed quoted string), or if the character at EINDEX is quoted
1357 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1358 single and double-quoted string parsing functions should not return an
1359 error if there are unclosed quotes or braces. The characters that this
1360 recognizes need to be the same as the contents of
1361 rl_completer_quote_characters. */
1363 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1366 char_is_quoted (string, eindex)
1367 char *string;
1368 int eindex;
1370 int i, pass_next, c;
1371 size_t slen;
1372 DECLARE_MBSTATE;
1374 slen = strlen (string);
1375 no_longjmp_on_fatal_error = 1;
1376 i = pass_next = 0;
1377 while (i <= eindex)
1379 c = string[i];
1381 if (pass_next)
1383 pass_next = 0;
1384 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1385 CQ_RETURN(1);
1386 ADVANCE_CHAR (string, slen, i);
1387 continue;
1389 else if (c == '\\')
1391 pass_next = 1;
1392 i++;
1393 continue;
1395 else if (c == '\'' || c == '"')
1397 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1398 : skip_double_quoted (string, slen, ++i);
1399 if (i > eindex)
1400 CQ_RETURN(1);
1401 /* no increment, the skip_xxx functions go one past end */
1403 else
1404 ADVANCE_CHAR (string, slen, i);
1407 CQ_RETURN(0);
1411 unclosed_pair (string, eindex, openstr)
1412 char *string;
1413 int eindex;
1414 char *openstr;
1416 int i, pass_next, openc, olen;
1417 size_t slen;
1418 DECLARE_MBSTATE;
1420 slen = strlen (string);
1421 olen = strlen (openstr);
1422 i = pass_next = openc = 0;
1423 while (i <= eindex)
1425 if (pass_next)
1427 pass_next = 0;
1428 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1429 return 0;
1430 ADVANCE_CHAR (string, slen, i);
1431 continue;
1433 else if (string[i] == '\\')
1435 pass_next = 1;
1436 i++;
1437 continue;
1439 else if (STREQN (string + i, openstr, olen))
1441 openc = 1 - openc;
1442 i += olen;
1444 else if (string[i] == '\'' || string[i] == '"')
1446 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1447 : skip_double_quoted (string, slen, i);
1448 if (i > eindex)
1449 return 0;
1451 else
1452 ADVANCE_CHAR (string, slen, i);
1454 return (openc);
1457 /* Skip characters in STRING until we find a character in DELIMS, and return
1458 the index of that character. START is the index into string at which we
1459 begin. This is similar in spirit to strpbrk, but it returns an index into
1460 STRING and takes a starting index. This little piece of code knows quite
1461 a lot of shell syntax. It's very similar to skip_double_quoted and other
1462 functions of that ilk. */
1464 skip_to_delim (string, start, delims)
1465 char *string;
1466 int start;
1467 char *delims;
1469 int i, pass_next, backq, si, c;
1470 size_t slen;
1471 char *temp;
1472 DECLARE_MBSTATE;
1474 slen = strlen (string + start) + start;
1475 no_longjmp_on_fatal_error = 1;
1476 i = start;
1477 pass_next = backq = 0;
1478 while (c = string[i])
1480 if (pass_next)
1482 pass_next = 0;
1483 if (c == 0)
1484 CQ_RETURN(i);
1485 ADVANCE_CHAR (string, slen, i);
1486 continue;
1488 else if (c == '\\')
1490 pass_next = 1;
1491 i++;
1492 continue;
1494 else if (backq)
1496 if (c == '`')
1497 backq = 0;
1498 ADVANCE_CHAR (string, slen, i);
1499 continue;
1501 else if (c == '`')
1503 backq = 1;
1504 i++;
1505 continue;
1507 else if (c == '\'' || c == '"')
1509 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1510 : skip_double_quoted (string, slen, ++i);
1511 /* no increment, the skip functions increment past the closing quote. */
1513 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1515 si = i + 2;
1516 if (string[si] == '\0')
1517 CQ_RETURN(si);
1519 if (string[i+1] == LPAREN)
1520 temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
1521 else
1522 temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
1523 i = si;
1524 if (string[i] == '\0') /* don't increment i past EOS in loop */
1525 break;
1526 i++;
1527 continue;
1529 else if (member (c, delims))
1530 break;
1531 else
1532 ADVANCE_CHAR (string, slen, i);
1535 CQ_RETURN(i);
1538 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1539 individual words. If DELIMS is NULL, the current value of $IFS is used
1540 to split the string, and the function follows the shell field splitting
1541 rules. SENTINEL is an index to look for. NWP, if non-NULL,
1542 gets the number of words in the returned list. CWP, if non-NULL, gets
1543 the index of the word containing SENTINEL. Non-whitespace chars in
1544 DELIMS delimit separate fields. */
1545 WORD_LIST *
1546 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1547 char *string;
1548 int slen;
1549 char *delims;
1550 int sentinel;
1551 int *nwp, *cwp;
1553 int ts, te, i, nw, cw, ifs_split;
1554 char *token, *d, *d2;
1555 WORD_LIST *ret, *tl;
1557 if (string == 0 || *string == '\0')
1559 if (nwp)
1560 *nwp = 0;
1561 if (cwp)
1562 *cwp = 0;
1563 return ((WORD_LIST *)NULL);
1566 d = (delims == 0) ? ifs_value : delims;
1567 ifs_split = delims == 0;
1569 /* Make d2 the non-whitespace characters in delims */
1570 d2 = 0;
1571 if (delims)
1573 size_t slength;
1574 #if defined (HANDLE_MULTIBYTE)
1575 size_t mblength = 1;
1576 #endif
1577 DECLARE_MBSTATE;
1579 slength = strlen (delims);
1580 d2 = (char *)xmalloc (slength + 1);
1581 i = ts = 0;
1582 while (delims[i])
1584 #if defined (HANDLE_MULTIBYTE)
1585 mbstate_t state_bak;
1586 state_bak = state;
1587 mblength = MBRLEN (delims + i, slength, &state);
1588 if (MB_INVALIDCH (mblength))
1589 state = state_bak;
1590 else if (mblength > 1)
1592 memcpy (d2 + ts, delims + i, mblength);
1593 ts += mblength;
1594 i += mblength;
1595 slength -= mblength;
1596 continue;
1598 #endif
1599 if (whitespace (delims[i]) == 0)
1600 d2[ts++] = delims[i];
1602 i++;
1603 slength--;
1605 d2[ts] = '\0';
1608 ret = (WORD_LIST *)NULL;
1610 /* Remove sequences of whitspace characters at the start of the string, as
1611 long as those characters are delimiters. */
1612 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1614 if (string[i] == '\0')
1615 return (ret);
1617 ts = i;
1618 nw = 0;
1619 cw = -1;
1620 while (1)
1622 te = skip_to_delim (string, ts, d);
1624 /* If we have a non-whitespace delimiter character, use it to make a
1625 separate field. This is just about what $IFS splitting does and
1626 is closer to the behavior of the shell parser. */
1627 if (ts == te && d2 && member (string[ts], d2))
1629 te = ts + 1;
1630 /* If we're using IFS splitting, the non-whitespace delimiter char
1631 and any additional IFS whitespace delimits a field. */
1632 if (ifs_split)
1633 while (member (string[te], d) && spctabnl (string[te]))
1634 te++;
1635 else
1636 while (member (string[te], d2))
1637 te++;
1640 token = substring (string, ts, te);
1642 ret = add_string_to_list (token, ret);
1643 free (token);
1644 nw++;
1646 if (sentinel >= ts && sentinel <= te)
1647 cw = nw;
1649 /* If the cursor is at whitespace just before word start, set the
1650 sentinel word to the current word. */
1651 if (cwp && cw == -1 && sentinel == ts-1)
1652 cw = nw;
1654 /* If the cursor is at whitespace between two words, make a new, empty
1655 word, add it before (well, after, since the list is in reverse order)
1656 the word we just added, and set the current word to that one. */
1657 if (cwp && cw == -1 && sentinel < ts)
1659 tl = make_word_list (make_word (""), ret->next);
1660 ret->next = tl;
1661 cw = nw;
1662 nw++;
1665 if (string[te] == 0)
1666 break;
1668 i = te;
1669 while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
1670 i++;
1672 if (string[i])
1673 ts = i;
1674 else
1675 break;
1678 /* Special case for SENTINEL at the end of STRING. If we haven't found
1679 the word containing SENTINEL yet, and the index we're looking for is at
1680 the end of STRING, add an additional null argument and set the current
1681 word pointer to that. */
1682 if (cwp && cw == -1 && sentinel >= slen)
1684 if (whitespace (string[sentinel - 1]))
1686 token = "";
1687 ret = add_string_to_list (token, ret);
1688 nw++;
1690 cw = nw;
1693 if (nwp)
1694 *nwp = nw;
1695 if (cwp)
1696 *cwp = cw;
1698 return (REVERSE_LIST (ret, WORD_LIST *));
1700 #endif /* READLINE */
1702 #if 0
1703 /* UNUSED */
1704 /* Extract the name of the variable to bind to from the assignment string. */
1705 char *
1706 assignment_name (string)
1707 char *string;
1709 int offset;
1710 char *temp;
1712 offset = assignment (string, 0);
1713 if (offset == 0)
1714 return (char *)NULL;
1715 temp = substring (string, 0, offset);
1716 return (temp);
1718 #endif
1720 /* **************************************************************** */
1721 /* */
1722 /* Functions to convert strings to WORD_LISTs and vice versa */
1723 /* */
1724 /* **************************************************************** */
1726 /* Return a single string of all the words in LIST. SEP is the separator
1727 to put between individual elements of LIST in the output string. */
1728 char *
1729 string_list_internal (list, sep)
1730 WORD_LIST *list;
1731 char *sep;
1733 register WORD_LIST *t;
1734 char *result, *r;
1735 int word_len, sep_len, result_size;
1737 if (list == 0)
1738 return ((char *)NULL);
1740 /* Short-circuit quickly if we don't need to separate anything. */
1741 if (list->next == 0)
1742 return (savestring (list->word->word));
1744 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1745 sep_len = STRLEN (sep);
1746 result_size = 0;
1748 for (t = list; t; t = t->next)
1750 if (t != list)
1751 result_size += sep_len;
1752 result_size += strlen (t->word->word);
1755 r = result = (char *)xmalloc (result_size + 1);
1757 for (t = list; t; t = t->next)
1759 if (t != list && sep_len)
1761 if (sep_len > 1)
1763 FASTCOPY (sep, r, sep_len);
1764 r += sep_len;
1766 else
1767 *r++ = sep[0];
1770 word_len = strlen (t->word->word);
1771 FASTCOPY (t->word->word, r, word_len);
1772 r += word_len;
1775 *r = '\0';
1776 return (result);
1779 /* Return a single string of all the words present in LIST, separating
1780 each word with a space. */
1781 char *
1782 string_list (list)
1783 WORD_LIST *list;
1785 return (string_list_internal (list, " "));
1788 /* Return a single string of all the words present in LIST, obeying the
1789 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1790 expansion [of $*] appears within a double quoted string, it expands
1791 to a single field with the value of each parameter separated by the
1792 first character of the IFS variable, or by a <space> if IFS is unset." */
1793 char *
1794 string_list_dollar_star (list)
1795 WORD_LIST *list;
1797 char *ret;
1798 #if defined (HANDLE_MULTIBYTE)
1799 # if defined (__GNUC__)
1800 char sep[MB_CUR_MAX + 1];
1801 # else
1802 char *sep = 0;
1803 # endif
1804 #else
1805 char sep[2];
1806 #endif
1808 #if defined (HANDLE_MULTIBYTE)
1809 # if !defined (__GNUC__)
1810 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1811 # endif /* !__GNUC__ */
1812 if (ifs_firstc_len == 1)
1814 sep[0] = ifs_firstc[0];
1815 sep[1] = '\0';
1817 else
1819 memcpy (sep, ifs_firstc, ifs_firstc_len);
1820 sep[ifs_firstc_len] = '\0';
1822 #else
1823 sep[0] = ifs_firstc;
1824 sep[1] = '\0';
1825 #endif
1827 ret = string_list_internal (list, sep);
1828 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1829 free (sep);
1830 #endif
1831 return ret;
1834 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1835 is non-zero, the $@ appears within double quotes, and we should quote
1836 the list before converting it into a string. If IFS is unset, and the
1837 word is not quoted, we just need to quote CTLESC and CTLNUL characters
1838 in the words in the list, because the default value of $IFS is
1839 <space><tab><newline>, IFS characters in the words in the list should
1840 also be split. If IFS is null, and the word is not quoted, we need
1841 to quote the words in the list to preserve the positional parameters
1842 exactly. */
1843 char *
1844 string_list_dollar_at (list, quoted)
1845 WORD_LIST *list;
1846 int quoted;
1848 char *ifs, *ret;
1849 #if defined (HANDLE_MULTIBYTE)
1850 # if defined (__GNUC__)
1851 char sep[MB_CUR_MAX + 1];
1852 # else
1853 char *sep = 0;
1854 # endif /* !__GNUC__ */
1855 #else
1856 char sep[2];
1857 #endif
1858 WORD_LIST *tlist;
1860 /* XXX this could just be ifs = ifs_value; */
1861 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
1863 #if defined (HANDLE_MULTIBYTE)
1864 # if !defined (__GNUC__)
1865 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1866 # endif /* !__GNUC__ */
1867 if (ifs && *ifs)
1869 if (ifs_firstc_len == 1)
1871 sep[0] = ifs_firstc[0];
1872 sep[1] = '\0';
1874 else
1876 memcpy (sep, ifs_firstc, ifs_firstc_len);
1877 sep[ifs_firstc_len] = '\0';
1880 else
1882 sep[0] = ' ';
1883 sep[1] = '\0';
1885 #else
1886 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1887 sep[1] = '\0';
1888 #endif
1890 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
1891 it now that quote_escapes quotes spaces */
1892 #if 0
1893 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1894 #else
1895 tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1896 #endif
1897 ? quote_list (list)
1898 : list_quote_escapes (list);
1900 ret = string_list_internal (tlist, sep);
1901 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1902 free (sep);
1903 #endif
1904 return ret;
1907 /* Return the list of words present in STRING. Separate the string into
1908 words at any of the characters found in SEPARATORS. If QUOTED is
1909 non-zero then word in the list will have its quoted flag set, otherwise
1910 the quoted flag is left as make_word () deemed fit.
1912 This obeys the P1003.2 word splitting semantics. If `separators' is
1913 exactly <space><tab><newline>, then the splitting algorithm is that of
1914 the Bourne shell, which treats any sequence of characters from `separators'
1915 as a delimiter. If IFS is unset, which results in `separators' being set
1916 to "", no splitting occurs. If separators has some other value, the
1917 following rules are applied (`IFS white space' means zero or more
1918 occurrences of <space>, <tab>, or <newline>, as long as those characters
1919 are in `separators'):
1921 1) IFS white space is ignored at the start and the end of the
1922 string.
1923 2) Each occurrence of a character in `separators' that is not
1924 IFS white space, along with any adjacent occurrences of
1925 IFS white space delimits a field.
1926 3) Any nonzero-length sequence of IFS white space delimits a field.
1929 /* BEWARE! list_string strips null arguments. Don't call it twice and
1930 expect to have "" preserved! */
1932 /* This performs word splitting and quoted null character removal on
1933 STRING. */
1934 #define issep(c) \
1935 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
1936 : (c) == (separators)[0]) \
1937 : 0)
1939 WORD_LIST *
1940 list_string (string, separators, quoted)
1941 register char *string, *separators;
1942 int quoted;
1944 WORD_LIST *result;
1945 WORD_DESC *t;
1946 char *current_word, *s;
1947 int sindex, sh_style_split, whitesep;
1948 size_t slen;
1950 if (!string || !*string)
1951 return ((WORD_LIST *)NULL);
1953 sh_style_split = separators && separators[0] == ' ' &&
1954 separators[1] == '\t' &&
1955 separators[2] == '\n' &&
1956 separators[3] == '\0';
1958 slen = 0;
1959 /* Remove sequences of whitespace at the beginning of STRING, as
1960 long as those characters appear in IFS. Do not do this if
1961 STRING is quoted or if there are no separator characters. */
1962 if (!quoted || !separators || !*separators)
1964 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1966 if (!*s)
1967 return ((WORD_LIST *)NULL);
1969 string = s;
1972 /* OK, now STRING points to a word that does not begin with white space.
1973 The splitting algorithm is:
1974 extract a word, stopping at a separator
1975 skip sequences of spc, tab, or nl as long as they are separators
1976 This obeys the field splitting rules in Posix.2. */
1977 slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
1978 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1980 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
1981 unless multibyte chars are possible. */
1982 current_word = string_extract_verbatim (string, slen, &sindex, separators);
1983 if (current_word == 0)
1984 break;
1986 /* If we have a quoted empty string, add a quoted null argument. We
1987 want to preserve the quoted null character iff this is a quoted
1988 empty string; otherwise the quoted null characters are removed
1989 below. */
1990 if (QUOTED_NULL (current_word))
1992 t = alloc_word_desc ();
1993 t->word = make_quoted_char ('\0');
1994 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
1995 result = make_word_list (t, result);
1997 else if (current_word[0] != '\0')
1999 /* If we have something, then add it regardless. However,
2000 perform quoted null character removal on the current word. */
2001 remove_quoted_nulls (current_word);
2002 result = add_string_to_list (current_word, result);
2003 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
2004 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2005 result->word->flags |= W_QUOTED;
2008 /* If we're not doing sequences of separators in the traditional
2009 Bourne shell style, then add a quoted null argument. */
2010 else if (!sh_style_split && !spctabnl (string[sindex]))
2012 t = alloc_word_desc ();
2013 t->word = make_quoted_char ('\0');
2014 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2015 result = make_word_list (t, result);
2018 free (current_word);
2020 /* Note whether or not the separator is IFS whitespace, used later. */
2021 whitesep = string[sindex] && spctabnl (string[sindex]);
2023 /* Move past the current separator character. */
2024 if (string[sindex])
2026 DECLARE_MBSTATE;
2027 ADVANCE_CHAR (string, slen, sindex);
2030 /* Now skip sequences of space, tab, or newline characters if they are
2031 in the list of separators. */
2032 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2033 sindex++;
2035 /* If the first separator was IFS whitespace and the current character
2036 is a non-whitespace IFS character, it should be part of the current
2037 field delimiter, not a separate delimiter that would result in an
2038 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2039 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2041 sindex++;
2042 /* An IFS character that is not IFS white space, along with any
2043 adjacent IFS white space, shall delimit a field. (SUSv3) */
2044 while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2045 sindex++;
2048 return (REVERSE_LIST (result, WORD_LIST *));
2051 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2052 ENDPTR is set to the first character after the word. This is used by
2053 the `read' builtin. This is never called with SEPARATORS != $IFS;
2054 it should be simplified.
2056 XXX - this function is very similar to list_string; they should be
2057 combined - XXX */
2058 char *
2059 get_word_from_string (stringp, separators, endptr)
2060 char **stringp, *separators, **endptr;
2062 register char *s;
2063 char *current_word;
2064 int sindex, sh_style_split, whitesep;
2065 size_t slen;
2067 if (!stringp || !*stringp || !**stringp)
2068 return ((char *)NULL);
2070 s = *stringp;
2072 sh_style_split = separators && separators[0] == ' ' &&
2073 separators[1] == '\t' &&
2074 separators[2] == '\n' &&
2075 separators[3] == '\0';
2077 slen = 0;
2079 /* Remove sequences of whitespace at the beginning of STRING, as
2080 long as those characters appear in IFS. */
2081 if (sh_style_split || !separators || !*separators)
2083 for (; *s && spctabnl (*s) && isifs (*s); s++);
2085 /* If the string is nothing but whitespace, update it and return. */
2086 if (!*s)
2088 *stringp = s;
2089 if (endptr)
2090 *endptr = s;
2091 return ((char *)NULL);
2095 /* OK, S points to a word that does not begin with white space.
2096 Now extract a word, stopping at a separator, save a pointer to
2097 the first character after the word, then skip sequences of spc,
2098 tab, or nl as long as they are separators.
2100 This obeys the field splitting rules in Posix.2. */
2101 sindex = 0;
2102 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2103 unless multibyte chars are possible. */
2104 slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2105 current_word = string_extract_verbatim (s, slen, &sindex, separators);
2107 /* Set ENDPTR to the first character after the end of the word. */
2108 if (endptr)
2109 *endptr = s + sindex;
2111 /* Note whether or not the separator is IFS whitespace, used later. */
2112 whitesep = s[sindex] && spctabnl (s[sindex]);
2114 /* Move past the current separator character. */
2115 if (s[sindex])
2117 DECLARE_MBSTATE;
2118 ADVANCE_CHAR (s, slen, sindex);
2121 /* Now skip sequences of space, tab, or newline characters if they are
2122 in the list of separators. */
2123 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2124 sindex++;
2126 /* If the first separator was IFS whitespace and the current character is
2127 a non-whitespace IFS character, it should be part of the current field
2128 delimiter, not a separate delimiter that would result in an empty field.
2129 Look at POSIX.2, 3.6.5, (3)(b). */
2130 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2132 sindex++;
2133 /* An IFS character that is not IFS white space, along with any adjacent
2134 IFS white space, shall delimit a field. */
2135 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2136 sindex++;
2139 /* Update STRING to point to the next field. */
2140 *stringp = s + sindex;
2141 return (current_word);
2144 /* Remove IFS white space at the end of STRING. Start at the end
2145 of the string and walk backwards until the beginning of the string
2146 or we find a character that's not IFS white space and not CTLESC.
2147 Only let CTLESC escape a white space character if SAW_ESCAPE is
2148 non-zero. */
2149 char *
2150 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2151 char *string, *separators;
2152 int saw_escape;
2154 char *s;
2156 s = string + STRLEN (string) - 1;
2157 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2158 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2159 s--;
2160 *++s = '\0';
2161 return string;
2164 #if 0
2165 /* UNUSED */
2166 /* Split STRING into words at whitespace. Obeys shell-style quoting with
2167 backslashes, single and double quotes. */
2168 WORD_LIST *
2169 list_string_with_quotes (string)
2170 char *string;
2172 WORD_LIST *list;
2173 char *token, *s;
2174 size_t s_len;
2175 int c, i, tokstart, len;
2177 for (s = string; s && *s && spctabnl (*s); s++)
2179 if (s == 0 || *s == 0)
2180 return ((WORD_LIST *)NULL);
2182 s_len = strlen (s);
2183 tokstart = i = 0;
2184 list = (WORD_LIST *)NULL;
2185 while (1)
2187 c = s[i];
2188 if (c == '\\')
2190 i++;
2191 if (s[i])
2192 i++;
2194 else if (c == '\'')
2195 i = skip_single_quoted (s, s_len, ++i);
2196 else if (c == '"')
2197 i = skip_double_quoted (s, s_len, ++i);
2198 else if (c == 0 || spctabnl (c))
2200 /* We have found the end of a token. Make a word out of it and
2201 add it to the word list. */
2202 token = substring (s, tokstart, i);
2203 list = add_string_to_list (token, list);
2204 free (token);
2205 while (spctabnl (s[i]))
2206 i++;
2207 if (s[i])
2208 tokstart = i;
2209 else
2210 break;
2212 else
2213 i++; /* normal character */
2215 return (REVERSE_LIST (list, WORD_LIST *));
2217 #endif
2219 /********************************************************/
2220 /* */
2221 /* Functions to perform assignment statements */
2222 /* */
2223 /********************************************************/
2225 #if defined (ARRAY_VARS)
2226 static SHELL_VAR *
2227 do_compound_assignment (name, value, flags)
2228 char *name, *value;
2229 int flags;
2231 SHELL_VAR *v;
2232 int mklocal;
2233 WORD_LIST *list;
2235 mklocal = flags & ASS_MKLOCAL;
2237 if (mklocal && variable_context)
2239 list = expand_compound_array_assignment (value, flags);
2240 v = find_variable (name);
2241 if (v == 0 || array_p (v) == 0 || v->context != variable_context)
2242 v = make_local_array_variable (name);
2243 assign_compound_array_list (v, list, flags);
2245 else
2246 v = assign_array_from_string (name, value, flags);
2248 return (v);
2250 #endif
2252 /* Given STRING, an assignment string, get the value of the right side
2253 of the `=', and bind it to the left side. If EXPAND is true, then
2254 perform parameter expansion, command substitution, and arithmetic
2255 expansion on the right-hand side. Perform tilde expansion in any
2256 case. Do not perform word splitting on the result of expansion. */
2257 static int
2258 do_assignment_internal (word, expand)
2259 const WORD_DESC *word;
2260 int expand;
2262 int offset, tlen, appendop, assign_list, aflags;
2263 char *name, *value;
2264 SHELL_VAR *entry;
2265 #if defined (ARRAY_VARS)
2266 char *t;
2267 int ni;
2268 #endif
2269 const char *string;
2271 if (word == 0 || word->word == 0)
2272 return 0;
2274 appendop = assign_list = aflags = 0;
2275 string = word->word;
2276 offset = assignment (string, 0);
2277 name = savestring (string);
2278 value = (char *)NULL;
2280 if (name[offset] == '=')
2282 char *temp;
2284 if (name[offset - 1] == '+')
2286 appendop = 1;
2287 name[offset - 1] = '\0';
2290 name[offset] = 0; /* might need this set later */
2291 temp = name + offset + 1;
2292 tlen = STRLEN (temp);
2294 #if defined (ARRAY_VARS)
2295 if (expand && (word->flags & W_COMPASSIGN))
2297 assign_list = ni = 1;
2298 value = extract_array_assignment_list (temp, &ni);
2300 else
2301 #endif
2303 if (expand && temp[0])
2304 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2305 else
2306 value = savestring (temp);
2309 if (value == 0)
2311 value = (char *)xmalloc (1);
2312 value[0] = '\0';
2315 if (echo_command_at_execute)
2317 if (appendop)
2318 name[offset - 1] = '+';
2319 xtrace_print_assignment (name, value, assign_list, 1);
2320 if (appendop)
2321 name[offset - 1] = '\0';
2324 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
2326 if (appendop)
2327 aflags |= ASS_APPEND;
2329 #if defined (ARRAY_VARS)
2330 if (t = xstrchr (name, '[')) /*]*/
2332 if (assign_list)
2334 report_error (_("%s: cannot assign list to array member"), name);
2335 ASSIGN_RETURN (0);
2337 entry = assign_array_element (name, value, aflags);
2338 if (entry == 0)
2339 ASSIGN_RETURN (0);
2341 else if (assign_list)
2343 if (word->flags & W_ASSIGNARG)
2344 aflags |= ASS_MKLOCAL;
2345 entry = do_compound_assignment (name, value, aflags);
2347 else
2348 #endif /* ARRAY_VARS */
2349 entry = bind_variable (name, value, aflags);
2351 stupidly_hack_special_variables (name);
2353 if (entry)
2354 VUNSETATTR (entry, att_invisible);
2356 /* Return 1 if the assignment seems to have been performed correctly. */
2357 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2360 /* Perform the assignment statement in STRING, and expand the
2361 right side by doing tilde, command and parameter expansion. */
2363 do_assignment (string)
2364 char *string;
2366 WORD_DESC td;
2368 td.flags = W_ASSIGNMENT;
2369 td.word = string;
2371 return do_assignment_internal (&td, 1);
2375 do_word_assignment (word)
2376 WORD_DESC *word;
2378 return do_assignment_internal (word, 1);
2381 /* Given STRING, an assignment string, get the value of the right side
2382 of the `=', and bind it to the left side. Do not perform any word
2383 expansions on the right hand side. */
2385 do_assignment_no_expand (string)
2386 char *string;
2388 WORD_DESC td;
2390 td.flags = W_ASSIGNMENT;
2391 td.word = string;
2393 return (do_assignment_internal (&td, 0));
2396 /***************************************************
2398 * Functions to manage the positional parameters *
2400 ***************************************************/
2402 /* Return the word list that corresponds to `$*'. */
2403 WORD_LIST *
2404 list_rest_of_args ()
2406 register WORD_LIST *list, *args;
2407 int i;
2409 /* Break out of the loop as soon as one of the dollar variables is null. */
2410 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2411 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2413 for (args = rest_of_args; args; args = args->next)
2414 list = make_word_list (make_bare_word (args->word->word), list);
2416 return (REVERSE_LIST (list, WORD_LIST *));
2420 number_of_args ()
2422 register WORD_LIST *list;
2423 int n;
2425 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2427 for (list = rest_of_args; list; list = list->next)
2428 n++;
2429 return n;
2432 /* Return the value of a positional parameter. This handles values > 10. */
2433 char *
2434 get_dollar_var_value (ind)
2435 intmax_t ind;
2437 char *temp;
2438 WORD_LIST *p;
2440 if (ind < 10)
2441 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2442 else /* We want something like ${11} */
2444 ind -= 10;
2445 for (p = rest_of_args; p && ind--; p = p->next)
2447 temp = p ? savestring (p->word->word) : (char *)NULL;
2449 return (temp);
2452 /* Make a single large string out of the dollar digit variables,
2453 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2454 case of "$*" with respect to IFS. */
2455 char *
2456 string_rest_of_args (dollar_star)
2457 int dollar_star;
2459 register WORD_LIST *list;
2460 char *string;
2462 list = list_rest_of_args ();
2463 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2464 dispose_words (list);
2465 return (string);
2468 /* Return a string containing the positional parameters from START to
2469 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2470 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2471 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2472 no quoting chars are added. */
2473 static char *
2474 pos_params (string, start, end, quoted)
2475 char *string;
2476 int start, end, quoted;
2478 WORD_LIST *save, *params, *h, *t;
2479 char *ret;
2480 int i;
2482 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2483 if (start == end)
2484 return ((char *)NULL);
2486 save = params = list_rest_of_args ();
2487 if (save == 0)
2488 return ((char *)NULL);
2490 for (i = 1; params && i < start; i++)
2491 params = params->next;
2492 if (params == 0)
2493 return ((char *)NULL);
2494 for (h = t = params; params && i < end; i++)
2496 t = params;
2497 params = params->next;
2500 t->next = (WORD_LIST *)NULL;
2501 if (string[0] == '*')
2503 if (quoted & Q_DOUBLE_QUOTES)
2504 ret = string_list_dollar_star (quote_list (h));
2505 else if (quoted & Q_HERE_DOCUMENT)
2506 ret = string_list (quote_list (h));
2507 else
2508 ret = string_list (h);
2510 else
2511 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
2512 if (t != params)
2513 t->next = params;
2515 dispose_words (save);
2516 return (ret);
2519 /******************************************************************/
2520 /* */
2521 /* Functions to expand strings to strings or WORD_LISTs */
2522 /* */
2523 /******************************************************************/
2525 #if defined (PROCESS_SUBSTITUTION)
2526 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
2527 #else
2528 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
2529 #endif
2531 /* If there are any characters in STRING that require full expansion,
2532 then call FUNC to expand STRING; otherwise just perform quote
2533 removal if necessary. This returns a new string. */
2534 static char *
2535 expand_string_if_necessary (string, quoted, func)
2536 char *string;
2537 int quoted;
2538 EXPFUNC *func;
2540 WORD_LIST *list;
2541 size_t slen;
2542 int i, saw_quote;
2543 char *ret;
2544 DECLARE_MBSTATE;
2546 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
2547 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
2548 i = saw_quote = 0;
2549 while (string[i])
2551 if (EXP_CHAR (string[i]))
2552 break;
2553 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2554 saw_quote = 1;
2555 ADVANCE_CHAR (string, slen, i);
2558 if (string[i])
2560 list = (*func) (string, quoted);
2561 if (list)
2563 ret = string_list (list);
2564 dispose_words (list);
2566 else
2567 ret = (char *)NULL;
2569 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2570 ret = string_quote_removal (string, quoted);
2571 else
2572 ret = savestring (string);
2574 return ret;
2577 static inline char *
2578 expand_string_to_string_internal (string, quoted, func)
2579 char *string;
2580 int quoted;
2581 EXPFUNC *func;
2583 WORD_LIST *list;
2584 char *ret;
2586 if (string == 0 || *string == '\0')
2587 return ((char *)NULL);
2589 list = (*func) (string, quoted);
2590 if (list)
2592 ret = string_list (list);
2593 dispose_words (list);
2595 else
2596 ret = (char *)NULL;
2598 return (ret);
2601 char *
2602 expand_string_to_string (string, quoted)
2603 char *string;
2604 int quoted;
2606 return (expand_string_to_string_internal (string, quoted, expand_string));
2609 char *
2610 expand_string_unsplit_to_string (string, quoted)
2611 char *string;
2612 int quoted;
2614 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2617 char *
2618 expand_assignment_string_to_string (string, quoted)
2619 char *string;
2620 int quoted;
2622 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
2625 char *
2626 expand_arith_string (string, quoted)
2627 char *string;
2629 return (expand_string_if_necessary (string, quoted, expand_string));
2632 #if defined (COND_COMMAND)
2633 /* Just remove backslashes in STRING. Returns a new string. */
2634 char *
2635 remove_backslashes (string)
2636 char *string;
2638 char *r, *ret, *s;
2640 r = ret = (char *)xmalloc (strlen (string) + 1);
2641 for (s = string; s && *s; )
2643 if (*s == '\\')
2644 s++;
2645 if (*s == 0)
2646 break;
2647 *r++ = *s++;
2649 *r = '\0';
2650 return ret;
2653 /* This needs better error handling. */
2654 /* Expand W for use as an argument to a unary or binary operator in a
2655 [[...]] expression. If SPECIAL is 1, this is the rhs argument
2656 to the != or == operator, and should be treated as a pattern. In
2657 this case, we quote the string specially for the globbing code. If
2658 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
2659 be quoted appropriately for regcomp/regexec. The caller is responsible
2660 for removing the backslashes if the unquoted word is needed later. */
2661 char *
2662 cond_expand_word (w, special)
2663 WORD_DESC *w;
2664 int special;
2666 char *r, *p;
2667 WORD_LIST *l;
2668 int qflags;
2670 if (w->word == 0 || w->word[0] == '\0')
2671 return ((char *)NULL);
2673 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2674 if (l)
2676 if (special == 0)
2678 dequote_list (l);
2679 r = string_list (l);
2681 else
2683 qflags = QGLOB_CVTNULL;
2684 if (special == 2)
2685 qflags |= QGLOB_REGEXP;
2686 p = string_list (l);
2687 r = quote_string_for_globbing (p, qflags);
2688 free (p);
2690 dispose_words (l);
2692 else
2693 r = (char *)NULL;
2695 return r;
2697 #endif
2699 /* Call expand_word_internal to expand W and handle error returns.
2700 A convenience function for functions that don't want to handle
2701 any errors or free any memory before aborting. */
2702 static WORD_LIST *
2703 call_expand_word_internal (w, q, i, c, e)
2704 WORD_DESC *w;
2705 int q, i, *c, *e;
2707 WORD_LIST *result;
2709 result = expand_word_internal (w, q, i, c, e);
2710 if (result == &expand_word_error || result == &expand_word_fatal)
2712 /* By convention, each time this error is returned, w->word has
2713 already been freed (it sometimes may not be in the fatal case,
2714 but that doesn't result in a memory leak because we're going
2715 to exit in most cases). */
2716 w->word = (char *)NULL;
2717 last_command_exit_value = EXECUTION_FAILURE;
2718 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2719 /* NOTREACHED */
2721 else
2722 return (result);
2725 /* Perform parameter expansion, command substitution, and arithmetic
2726 expansion on STRING, as if it were a word. Leave the result quoted. */
2727 static WORD_LIST *
2728 expand_string_internal (string, quoted)
2729 char *string;
2730 int quoted;
2732 WORD_DESC td;
2733 WORD_LIST *tresult;
2735 if (string == 0 || *string == 0)
2736 return ((WORD_LIST *)NULL);
2738 td.flags = 0;
2739 td.word = savestring (string);
2741 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2743 FREE (td.word);
2744 return (tresult);
2747 /* Expand STRING by performing parameter expansion, command substitution,
2748 and arithmetic expansion. Dequote the resulting WORD_LIST before
2749 returning it, but do not perform word splitting. The call to
2750 remove_quoted_nulls () is in here because word splitting normally
2751 takes care of quote removal. */
2752 WORD_LIST *
2753 expand_string_unsplit (string, quoted)
2754 char *string;
2755 int quoted;
2757 WORD_LIST *value;
2759 if (string == 0 || *string == '\0')
2760 return ((WORD_LIST *)NULL);
2762 expand_no_split_dollar_star = 1;
2763 value = expand_string_internal (string, quoted);
2764 expand_no_split_dollar_star = 0;
2766 if (value)
2768 if (value->word)
2770 remove_quoted_nulls (value->word->word);
2771 value->word->flags &= ~W_HASQUOTEDNULL;
2773 dequote_list (value);
2775 return (value);
2778 /* Expand the rhs of an assignment statement */
2779 WORD_LIST *
2780 expand_string_assignment (string, quoted)
2781 char *string;
2782 int quoted;
2784 WORD_DESC td;
2785 WORD_LIST *value;
2787 if (string == 0 || *string == '\0')
2788 return ((WORD_LIST *)NULL);
2790 expand_no_split_dollar_star = 1;
2792 td.flags = W_ASSIGNRHS;
2793 td.word = savestring (string);
2794 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2795 FREE (td.word);
2797 expand_no_split_dollar_star = 0;
2799 if (value)
2801 if (value->word)
2803 remove_quoted_nulls (value->word->word);
2804 value->word->flags &= ~W_HASQUOTEDNULL;
2806 dequote_list (value);
2808 return (value);
2812 /* Expand one of the PS? prompt strings. This is a sort of combination of
2813 expand_string_unsplit and expand_string_internal, but returns the
2814 passed string when an error occurs. Might want to trap other calls
2815 to jump_to_top_level here so we don't endlessly loop. */
2816 WORD_LIST *
2817 expand_prompt_string (string, quoted)
2818 char *string;
2819 int quoted;
2821 WORD_LIST *value;
2822 WORD_DESC td;
2824 if (string == 0 || *string == 0)
2825 return ((WORD_LIST *)NULL);
2827 td.flags = 0;
2828 td.word = savestring (string);
2830 no_longjmp_on_fatal_error = 1;
2831 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2832 no_longjmp_on_fatal_error = 0;
2834 if (value == &expand_word_error || value == &expand_word_fatal)
2836 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
2837 return value;
2839 FREE (td.word);
2840 if (value)
2842 if (value->word)
2844 remove_quoted_nulls (value->word->word);
2845 value->word->flags &= ~W_HASQUOTEDNULL;
2847 dequote_list (value);
2849 return (value);
2852 /* Expand STRING just as if you were expanding a word, but do not dequote
2853 the resultant WORD_LIST. This is called only from within this file,
2854 and is used to correctly preserve quoted characters when expanding
2855 things like ${1+"$@"}. This does parameter expansion, command
2856 substitution, arithmetic expansion, and word splitting. */
2857 static WORD_LIST *
2858 expand_string_leave_quoted (string, quoted)
2859 char *string;
2860 int quoted;
2862 WORD_LIST *tlist;
2863 WORD_LIST *tresult;
2865 if (string == 0 || *string == '\0')
2866 return ((WORD_LIST *)NULL);
2868 tlist = expand_string_internal (string, quoted);
2870 if (tlist)
2872 tresult = word_list_split (tlist);
2873 dispose_words (tlist);
2874 return (tresult);
2876 return ((WORD_LIST *)NULL);
2879 /* This does not perform word splitting or dequote the WORD_LIST
2880 it returns. */
2881 static WORD_LIST *
2882 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
2883 char *string;
2884 int quoted, *dollar_at_p, *has_dollar_at;
2886 WORD_DESC td;
2887 WORD_LIST *tresult;
2889 if (string == 0 || *string == '\0')
2890 return (WORD_LIST *)NULL;
2892 td.flags = 0;
2893 td.word = string;
2894 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
2895 return (tresult);
2898 /* Expand STRING just as if you were expanding a word. This also returns
2899 a list of words. Note that filename globbing is *NOT* done for word
2900 or string expansion, just when the shell is expanding a command. This
2901 does parameter expansion, command substitution, arithmetic expansion,
2902 and word splitting. Dequote the resultant WORD_LIST before returning. */
2903 WORD_LIST *
2904 expand_string (string, quoted)
2905 char *string;
2906 int quoted;
2908 WORD_LIST *result;
2910 if (string == 0 || *string == '\0')
2911 return ((WORD_LIST *)NULL);
2913 result = expand_string_leave_quoted (string, quoted);
2914 return (result ? dequote_list (result) : result);
2917 /***************************************************
2919 * Functions to handle quoting chars *
2921 ***************************************************/
2923 /* Conventions:
2925 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
2926 The parser passes CTLNUL as CTLESC CTLNUL. */
2928 /* Quote escape characters in string s, but no other characters. This is
2929 used to protect CTLESC and CTLNUL in variable values from the rest of
2930 the word expansion process after the variable is expanded. If IFS is
2931 null, we quote spaces as well, just in case we split on spaces later
2932 (in the case of unquoted $@, we will eventually attempt to split the
2933 entire word on spaces). Corresponding code exists in dequote_escapes.
2934 Even if we don't end up splitting on spaces, quoting spaces is not a
2935 problem. */
2936 char *
2937 quote_escapes (string)
2938 char *string;
2940 register char *s, *t;
2941 size_t slen;
2942 char *result, *send;
2943 int quote_spaces;
2944 DECLARE_MBSTATE;
2946 slen = strlen (string);
2947 send = string + slen;
2949 quote_spaces = (ifs_value && *ifs_value == 0);
2950 t = result = (char *)xmalloc ((slen * 2) + 1);
2951 s = string;
2953 while (*s)
2955 if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
2956 *t++ = CTLESC;
2957 COPY_CHAR_P (t, s, send);
2959 *t = '\0';
2960 return (result);
2963 static WORD_LIST *
2964 list_quote_escapes (list)
2965 WORD_LIST *list;
2967 register WORD_LIST *w;
2968 char *t;
2970 for (w = list; w; w = w->next)
2972 t = w->word->word;
2973 w->word->word = quote_escapes (t);
2974 free (t);
2976 return list;
2979 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
2981 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2982 This is necessary to make unquoted CTLESC and CTLNUL characters in the
2983 data stream pass through properly.
2985 We need to remove doubled CTLESC characters inside quoted strings before
2986 quoting the entire string, so we do not double the number of CTLESC
2987 characters.
2989 Also used by parts of the pattern substitution code. */
2990 static char *
2991 dequote_escapes (string)
2992 char *string;
2994 register char *s, *t;
2995 size_t slen;
2996 char *result, *send;
2997 int quote_spaces;
2998 DECLARE_MBSTATE;
3000 if (string == 0)
3001 return string;
3003 slen = strlen (string);
3004 send = string + slen;
3006 t = result = (char *)xmalloc (slen + 1);
3007 s = string;
3009 if (strchr (string, CTLESC) == 0)
3010 return (strcpy (result, s));
3012 quote_spaces = (ifs_value && *ifs_value == 0);
3013 while (*s)
3015 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
3017 s++;
3018 if (*s == '\0')
3019 break;
3021 COPY_CHAR_P (t, s, send);
3023 *t = '\0';
3024 return result;
3027 /* Return a new string with the quoted representation of character C.
3028 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3029 set in any resultant WORD_DESC where this value is the word. */
3030 static char *
3031 make_quoted_char (c)
3032 int c;
3034 char *temp;
3036 temp = (char *)xmalloc (3);
3037 if (c == 0)
3039 temp[0] = CTLNUL;
3040 temp[1] = '\0';
3042 else
3044 temp[0] = CTLESC;
3045 temp[1] = c;
3046 temp[2] = '\0';
3048 return (temp);
3051 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
3052 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3053 this value is the word. */
3054 char *
3055 quote_string (string)
3056 char *string;
3058 register char *t;
3059 size_t slen;
3060 char *result, *send;
3062 if (*string == 0)
3064 result = (char *)xmalloc (2);
3065 result[0] = CTLNUL;
3066 result[1] = '\0';
3068 else
3070 DECLARE_MBSTATE;
3072 slen = strlen (string);
3073 send = string + slen;
3075 result = (char *)xmalloc ((slen * 2) + 1);
3077 for (t = result; string < send; )
3079 *t++ = CTLESC;
3080 COPY_CHAR_P (t, string, send);
3082 *t = '\0';
3084 return (result);
3087 /* De-quote quoted characters in STRING. */
3088 char *
3089 dequote_string (string)
3090 char *string;
3092 register char *s, *t;
3093 size_t slen;
3094 char *result, *send;
3095 DECLARE_MBSTATE;
3097 slen = strlen (string);
3099 t = result = (char *)xmalloc (slen + 1);
3101 if (QUOTED_NULL (string))
3103 result[0] = '\0';
3104 return (result);
3107 /* If no character in the string can be quoted, don't bother examining
3108 each character. Just return a copy of the string passed to us. */
3109 if (strchr (string, CTLESC) == NULL)
3110 return (strcpy (result, string));
3112 send = string + slen;
3113 s = string;
3114 while (*s)
3116 if (*s == CTLESC)
3118 s++;
3119 if (*s == '\0')
3120 break;
3122 COPY_CHAR_P (t, s, send);
3125 *t = '\0';
3126 return (result);
3129 /* Quote the entire WORD_LIST list. */
3130 static WORD_LIST *
3131 quote_list (list)
3132 WORD_LIST *list;
3134 register WORD_LIST *w;
3135 char *t;
3137 for (w = list; w; w = w->next)
3139 t = w->word->word;
3140 w->word->word = quote_string (t);
3141 free (t);
3142 w->word->flags |= W_QUOTED;
3143 /* XXX - turn on W_HAVEQUOTEDNULL here? */
3145 return list;
3148 /* De-quote quoted characters in each word in LIST. */
3149 WORD_LIST *
3150 dequote_list (list)
3151 WORD_LIST *list;
3153 register char *s;
3154 register WORD_LIST *tlist;
3156 for (tlist = list; tlist; tlist = tlist->next)
3158 s = dequote_string (tlist->word->word);
3159 free (tlist->word->word);
3160 tlist->word->word = s;
3161 /* XXX - turn off W_HAVEQUOTEDNULL here? */
3163 return list;
3166 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3167 string. */
3168 static char *
3169 remove_quoted_escapes (string)
3170 char *string;
3172 char *t;
3174 if (string)
3176 t = dequote_escapes (string);
3177 strcpy (string, t);
3178 free (t);
3181 return (string);
3184 /* Perform quoted null character removal on STRING. We don't allow any
3185 quoted null characters in the middle or at the ends of strings because
3186 of how expand_word_internal works. remove_quoted_nulls () turns
3187 STRING into an empty string iff it only consists of a quoted null,
3188 and removes all unquoted CTLNUL characters. */
3189 static char *
3190 remove_quoted_nulls (string)
3191 char *string;
3193 register size_t slen;
3194 register int i, j, prev_i;
3195 DECLARE_MBSTATE;
3197 if (strchr (string, CTLNUL) == 0) /* XXX */
3198 return string; /* XXX */
3200 slen = strlen (string);
3201 i = j = 0;
3203 while (i < slen)
3205 if (string[i] == CTLESC)
3207 /* Old code had j++, but we cannot assume that i == j at this
3208 point -- what if a CTLNUL has already been removed from the
3209 string? We don't want to drop the CTLESC or recopy characters
3210 that we've already copied down. */
3211 i++; string[j++] = CTLESC;
3212 if (i == slen)
3213 break;
3215 else if (string[i] == CTLNUL)
3216 i++;
3218 prev_i = i;
3219 ADVANCE_CHAR (string, slen, i);
3220 if (j < prev_i)
3222 do string[j++] = string[prev_i++]; while (prev_i < i);
3224 else
3225 j = i;
3227 string[j] = '\0';
3229 return (string);
3232 /* Perform quoted null character removal on each element of LIST.
3233 This modifies LIST. */
3234 void
3235 word_list_remove_quoted_nulls (list)
3236 WORD_LIST *list;
3238 register WORD_LIST *t;
3240 for (t = list; t; t = t->next)
3242 remove_quoted_nulls (t->word->word);
3243 t->word->flags &= ~W_HASQUOTEDNULL;
3247 /* **************************************************************** */
3248 /* */
3249 /* Functions for Matching and Removing Patterns */
3250 /* */
3251 /* **************************************************************** */
3253 #if defined (HANDLE_MULTIBYTE)
3254 #if 0 /* Currently unused */
3255 static unsigned char *
3256 mb_getcharlens (string, len)
3257 char *string;
3258 int len;
3260 int i, offset, last;
3261 unsigned char *ret;
3262 char *p;
3263 DECLARE_MBSTATE;
3265 i = offset = 0;
3266 last = 0;
3267 ret = (unsigned char *)xmalloc (len);
3268 memset (ret, 0, len);
3269 while (string[last])
3271 ADVANCE_CHAR (string, len, offset);
3272 ret[last] = offset - last;
3273 last = offset;
3275 return ret;
3277 #endif
3278 #endif
3280 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3281 can have one of 4 values:
3282 RP_LONG_LEFT remove longest matching portion at start of PARAM
3283 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3284 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3285 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3288 #define RP_LONG_LEFT 1
3289 #define RP_SHORT_LEFT 2
3290 #define RP_LONG_RIGHT 3
3291 #define RP_SHORT_RIGHT 4
3293 static char *
3294 remove_upattern (param, pattern, op)
3295 char *param, *pattern;
3296 int op;
3298 register int len;
3299 register char *end;
3300 register char *p, *ret, c;
3302 len = STRLEN (param);
3303 end = param + len;
3305 switch (op)
3307 case RP_LONG_LEFT: /* remove longest match at start */
3308 for (p = end; p >= param; p--)
3310 c = *p; *p = '\0';
3311 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3313 *p = c;
3314 return (savestring (p));
3316 *p = c;
3319 break;
3321 case RP_SHORT_LEFT: /* remove shortest match at start */
3322 for (p = param; p <= end; p++)
3324 c = *p; *p = '\0';
3325 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3327 *p = c;
3328 return (savestring (p));
3330 *p = c;
3332 break;
3334 case RP_LONG_RIGHT: /* remove longest match at end */
3335 for (p = param; p <= end; p++)
3337 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3339 c = *p; *p = '\0';
3340 ret = savestring (param);
3341 *p = c;
3342 return (ret);
3345 break;
3347 case RP_SHORT_RIGHT: /* remove shortest match at end */
3348 for (p = end; p >= param; p--)
3350 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3352 c = *p; *p = '\0';
3353 ret = savestring (param);
3354 *p = c;
3355 return (ret);
3358 break;
3361 return (savestring (param)); /* no match, return original string */
3364 #if defined (HANDLE_MULTIBYTE)
3365 static wchar_t *
3366 remove_wpattern (wparam, wstrlen, wpattern, op)
3367 wchar_t *wparam;
3368 size_t wstrlen;
3369 wchar_t *wpattern;
3370 int op;
3372 wchar_t wc, *ret;
3373 int n;
3375 switch (op)
3377 case RP_LONG_LEFT: /* remove longest match at start */
3378 for (n = wstrlen; n >= 0; n--)
3380 wc = wparam[n]; wparam[n] = L'\0';
3381 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3383 wparam[n] = wc;
3384 return (wcsdup (wparam + n));
3386 wparam[n] = wc;
3388 break;
3390 case RP_SHORT_LEFT: /* remove shortest match at start */
3391 for (n = 0; n <= wstrlen; n++)
3393 wc = wparam[n]; wparam[n] = L'\0';
3394 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3396 wparam[n] = wc;
3397 return (wcsdup (wparam + n));
3399 wparam[n] = wc;
3401 break;
3403 case RP_LONG_RIGHT: /* remove longest match at end */
3404 for (n = 0; n <= wstrlen; n++)
3406 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3408 wc = wparam[n]; wparam[n] = L'\0';
3409 ret = wcsdup (wparam);
3410 wparam[n] = wc;
3411 return (ret);
3414 break;
3416 case RP_SHORT_RIGHT: /* remove shortest match at end */
3417 for (n = wstrlen; n >= 0; n--)
3419 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3421 wc = wparam[n]; wparam[n] = L'\0';
3422 ret = wcsdup (wparam);
3423 wparam[n] = wc;
3424 return (ret);
3427 break;
3430 return (wcsdup (wparam)); /* no match, return original string */
3432 #endif /* HANDLE_MULTIBYTE */
3434 static char *
3435 remove_pattern (param, pattern, op)
3436 char *param, *pattern;
3437 int op;
3439 if (param == NULL)
3440 return (param);
3441 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3442 return (savestring (param));
3444 #if defined (HANDLE_MULTIBYTE)
3445 if (MB_CUR_MAX > 1)
3447 wchar_t *ret, *oret;
3448 size_t n;
3449 wchar_t *wparam, *wpattern;
3450 mbstate_t ps;
3451 char *xret;
3453 n = xdupmbstowcs (&wpattern, NULL, pattern);
3454 if (n == (size_t)-1)
3455 return (remove_upattern (param, pattern, op));
3456 n = xdupmbstowcs (&wparam, NULL, param);
3457 if (n == (size_t)-1)
3459 free (wpattern);
3460 return (remove_upattern (param, pattern, op));
3462 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3464 free (wparam);
3465 free (wpattern);
3467 n = strlen (param);
3468 xret = (char *)xmalloc (n + 1);
3469 memset (&ps, '\0', sizeof (mbstate_t));
3470 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3471 xret[n] = '\0'; /* just to make sure */
3472 free (oret);
3473 return xret;
3475 else
3476 #endif
3477 return (remove_upattern (param, pattern, op));
3480 /* Return 1 of the first character of STRING could match the first
3481 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
3482 static int
3483 match_pattern_char (pat, string)
3484 char *pat, *string;
3486 char c;
3488 if (*string == 0)
3489 return (0);
3491 switch (c = *pat++)
3493 default:
3494 return (*string == c);
3495 case '\\':
3496 return (*string == *pat);
3497 case '?':
3498 return (*pat == LPAREN ? 1 : (*string != '\0'));
3499 case '*':
3500 return (1);
3501 case '+':
3502 case '!':
3503 case '@':
3504 return (*pat == LPAREN ? 1 : (*string == c));
3505 case '[':
3506 return (*string != '\0');
3510 /* Match PAT anywhere in STRING and return the match boundaries.
3511 This returns 1 in case of a successful match, 0 otherwise. SP
3512 and EP are pointers into the string where the match begins and
3513 ends, respectively. MTYPE controls what kind of match is attempted.
3514 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3515 of the string, respectively. The longest match is returned. */
3516 static int
3517 match_upattern (string, pat, mtype, sp, ep)
3518 char *string, *pat;
3519 int mtype;
3520 char **sp, **ep;
3522 int c, len;
3523 register char *p, *p1, *npat;
3524 char *end;
3526 /* If the pattern doesn't match anywhere in the string, go ahead and
3527 short-circuit right away. A minor optimization, saves a bunch of
3528 unnecessary calls to strmatch (up to N calls for a string of N
3529 characters) if the match is unsuccessful. To preserve the semantics
3530 of the substring matches below, we make sure that the pattern has
3531 `*' as first and last character, making a new pattern if necessary. */
3532 /* XXX - check this later if I ever implement `**' with special meaning,
3533 since this will potentially result in `**' at the beginning or end */
3534 len = STRLEN (pat);
3535 if (pat[0] != '*' || pat[len - 1] != '*')
3537 p = npat = (char *)xmalloc (len + 3);
3538 p1 = pat;
3539 if (*p1 != '*')
3540 *p++ = '*';
3541 while (*p1)
3542 *p++ = *p1++;
3543 if (p1[-1] != '*' || p[-2] == '\\')
3544 *p++ = '*';
3545 *p = '\0';
3547 else
3548 npat = pat;
3549 c = strmatch (npat, string, FNMATCH_EXTFLAG);
3550 if (npat != pat)
3551 free (npat);
3552 if (c == FNM_NOMATCH)
3553 return (0);
3555 len = STRLEN (string);
3556 end = string + len;
3558 switch (mtype)
3560 case MATCH_ANY:
3561 for (p = string; p <= end; p++)
3563 if (match_pattern_char (pat, p))
3565 for (p1 = end; p1 >= p; p1--)
3567 c = *p1; *p1 = '\0';
3568 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3570 *p1 = c;
3571 *sp = p;
3572 *ep = p1;
3573 return 1;
3575 *p1 = c;
3580 return (0);
3582 case MATCH_BEG:
3583 if (match_pattern_char (pat, string) == 0)
3584 return (0);
3586 for (p = end; p >= string; p--)
3588 c = *p; *p = '\0';
3589 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3591 *p = c;
3592 *sp = string;
3593 *ep = p;
3594 return 1;
3596 *p = c;
3599 return (0);
3601 case MATCH_END:
3602 for (p = string; p <= end; p++)
3604 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3606 *sp = p;
3607 *ep = end;
3608 return 1;
3613 return (0);
3616 return (0);
3619 #if defined (HANDLE_MULTIBYTE)
3620 /* Return 1 of the first character of WSTRING could match the first
3621 character of pattern WPAT. Wide character version. */
3622 static int
3623 match_pattern_wchar (wpat, wstring)
3624 wchar_t *wpat, *wstring;
3626 wchar_t wc;
3628 if (*wstring == 0)
3629 return (0);
3631 switch (wc = *wpat++)
3633 default:
3634 return (*wstring == wc);
3635 case L'\\':
3636 return (*wstring == *wpat);
3637 case L'?':
3638 return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3639 case L'*':
3640 return (1);
3641 case L'+':
3642 case L'!':
3643 case L'@':
3644 return (*wpat == LPAREN ? 1 : (*wstring == wc));
3645 case L'[':
3646 return (*wstring != L'\0');
3650 /* Match WPAT anywhere in WSTRING and return the match boundaries.
3651 This returns 1 in case of a successful match, 0 otherwise. Wide
3652 character version. */
3653 static int
3654 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3655 wchar_t *wstring;
3656 char **indices;
3657 size_t wstrlen;
3658 wchar_t *wpat;
3659 int mtype;
3660 char **sp, **ep;
3662 wchar_t wc, *wp, *nwpat, *wp1;
3663 int len;
3664 #if 0
3665 size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3666 #else
3667 int n, n1;
3668 #endif
3670 /* If the pattern doesn't match anywhere in the string, go ahead and
3671 short-circuit right away. A minor optimization, saves a bunch of
3672 unnecessary calls to strmatch (up to N calls for a string of N
3673 characters) if the match is unsuccessful. To preserve the semantics
3674 of the substring matches below, we make sure that the pattern has
3675 `*' as first and last character, making a new pattern if necessary. */
3676 /* XXX - check this later if I ever implement `**' with special meaning,
3677 since this will potentially result in `**' at the beginning or end */
3678 len = wcslen (wpat);
3679 if (wpat[0] != L'*' || wpat[len - 1] != L'*')
3681 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
3682 wp1 = wpat;
3683 if (*wp1 != L'*')
3684 *wp++ = L'*';
3685 while (*wp1 != L'\0')
3686 *wp++ = *wp1++;
3687 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3688 *wp++ = L'*';
3689 *wp = '\0';
3691 else
3692 nwpat = wpat;
3693 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3694 if (nwpat != wpat)
3695 free (nwpat);
3696 if (len == FNM_NOMATCH)
3697 return (0);
3699 switch (mtype)
3701 case MATCH_ANY:
3702 for (n = 0; n <= wstrlen; n++)
3704 if (match_pattern_wchar (wpat, wstring + n))
3706 for (n1 = wstrlen; n1 >= n; n1--)
3708 wc = wstring[n1]; wstring[n1] = L'\0';
3709 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3711 wstring[n1] = wc;
3712 *sp = indices[n];
3713 *ep = indices[n1];
3714 return 1;
3716 wstring[n1] = wc;
3721 return (0);
3723 case MATCH_BEG:
3724 if (match_pattern_wchar (wpat, wstring) == 0)
3725 return (0);
3727 for (n = wstrlen; n >= 0; n--)
3729 wc = wstring[n]; wstring[n] = L'\0';
3730 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3732 wstring[n] = wc;
3733 *sp = indices[0];
3734 *ep = indices[n];
3735 return 1;
3737 wstring[n] = wc;
3740 return (0);
3742 case MATCH_END:
3743 for (n = 0; n <= wstrlen; n++)
3745 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3747 *sp = indices[n];
3748 *ep = indices[wstrlen];
3749 return 1;
3753 return (0);
3756 return (0);
3758 #endif /* HANDLE_MULTIBYTE */
3760 static int
3761 match_pattern (string, pat, mtype, sp, ep)
3762 char *string, *pat;
3763 int mtype;
3764 char **sp, **ep;
3766 #if defined (HANDLE_MULTIBYTE)
3767 int ret;
3768 size_t n;
3769 wchar_t *wstring, *wpat;
3770 char **indices;
3771 #endif
3773 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
3774 return (0);
3776 #if defined (HANDLE_MULTIBYTE)
3777 if (MB_CUR_MAX > 1)
3779 n = xdupmbstowcs (&wpat, NULL, pat);
3780 if (n == (size_t)-1)
3781 return (match_upattern (string, pat, mtype, sp, ep));
3782 n = xdupmbstowcs (&wstring, &indices, string);
3783 if (n == (size_t)-1)
3785 free (wpat);
3786 return (match_upattern (string, pat, mtype, sp, ep));
3788 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
3790 free (wpat);
3791 free (wstring);
3792 free (indices);
3794 return (ret);
3796 else
3797 #endif
3798 return (match_upattern (string, pat, mtype, sp, ep));
3801 static int
3802 getpatspec (c, value)
3803 int c;
3804 char *value;
3806 if (c == '#')
3807 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
3808 else /* c == '%' */
3809 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
3812 /* Posix.2 says that the WORD should be run through tilde expansion,
3813 parameter expansion, command substitution and arithmetic expansion.
3814 This leaves the result quoted, so quote_string_for_globbing () has
3815 to be called to fix it up for strmatch (). If QUOTED is non-zero,
3816 it means that the entire expression was enclosed in double quotes.
3817 This means that quoting characters in the pattern do not make any
3818 special pattern characters quoted. For example, the `*' in the
3819 following retains its special meaning: "${foo#'*'}". */
3820 static char *
3821 getpattern (value, quoted, expandpat)
3822 char *value;
3823 int quoted, expandpat;
3825 char *pat, *tword;
3826 WORD_LIST *l;
3827 #if 0
3828 int i;
3829 #endif
3831 /* There is a problem here: how to handle single or double quotes in the
3832 pattern string when the whole expression is between double quotes?
3833 POSIX.2 says that enclosing double quotes do not cause the pattern to
3834 be quoted, but does that leave us a problem with @ and array[@] and their
3835 expansions inside a pattern? */
3836 #if 0
3837 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
3839 i = 0;
3840 pat = string_extract_double_quoted (tword, &i, 1);
3841 free (tword);
3842 tword = pat;
3844 #endif
3846 /* expand_string_for_rhs () leaves WORD quoted and does not perform
3847 word splitting. */
3848 l = *value ? expand_string_for_rhs (value,
3849 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
3850 (int *)NULL, (int *)NULL)
3851 : (WORD_LIST *)0;
3852 pat = string_list (l);
3853 dispose_words (l);
3854 if (pat)
3856 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
3857 free (pat);
3858 pat = tword;
3860 return (pat);
3863 #if 0
3864 /* Handle removing a pattern from a string as a result of ${name%[%]value}
3865 or ${name#[#]value}. */
3866 static char *
3867 variable_remove_pattern (value, pattern, patspec, quoted)
3868 char *value, *pattern;
3869 int patspec, quoted;
3871 char *tword;
3873 tword = remove_pattern (value, pattern, patspec);
3875 return (tword);
3877 #endif
3879 static char *
3880 list_remove_pattern (list, pattern, patspec, itype, quoted)
3881 WORD_LIST *list;
3882 char *pattern;
3883 int patspec, itype, quoted;
3885 WORD_LIST *new, *l;
3886 WORD_DESC *w;
3887 char *tword;
3889 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
3891 tword = remove_pattern (l->word->word, pattern, patspec);
3892 w = alloc_word_desc ();
3893 w->word = tword ? tword : savestring ("");
3894 new = make_word_list (w, new);
3897 l = REVERSE_LIST (new, WORD_LIST *);
3898 if (itype == '*')
3899 tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
3900 else
3901 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3903 dispose_words (l);
3904 return (tword);
3907 static char *
3908 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
3909 int itype;
3910 char *pattern;
3911 int patspec, quoted;
3913 char *ret;
3914 WORD_LIST *list;
3916 list = list_rest_of_args ();
3917 if (list == 0)
3918 return ((char *)NULL);
3919 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3920 dispose_words (list);
3921 return (ret);
3924 #if defined (ARRAY_VARS)
3925 static char *
3926 array_remove_pattern (a, pattern, patspec, varname, quoted)
3927 ARRAY *a;
3928 char *pattern;
3929 int patspec;
3930 char *varname; /* so we can figure out how it's indexed */
3931 int quoted;
3933 int itype;
3934 char *ret;
3935 WORD_LIST *list;
3936 SHELL_VAR *v;
3938 /* compute itype from varname here */
3939 v = array_variable_part (varname, &ret, 0);
3940 itype = ret[0];
3942 list = array_to_word_list (a);
3943 if (list == 0)
3944 return ((char *)NULL);
3945 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3946 dispose_words (list);
3948 return ret;
3950 #endif /* ARRAY_VARS */
3952 static char *
3953 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
3954 char *varname, *value, *patstr;
3955 int rtype, quoted;
3957 int vtype, patspec, starsub;
3958 char *temp1, *val, *pattern;
3959 SHELL_VAR *v;
3961 if (value == 0)
3962 return ((char *)NULL);
3964 this_command_name = varname;
3966 vtype = get_var_and_type (varname, value, quoted, &v, &val);
3967 if (vtype == -1)
3968 return ((char *)NULL);
3970 starsub = vtype & VT_STARSUB;
3971 vtype &= ~VT_STARSUB;
3973 patspec = getpatspec (rtype, patstr);
3974 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
3975 patstr++;
3977 /* Need to pass getpattern newly-allocated memory in case of expansion --
3978 the expansion code will free the passed string on an error. */
3979 temp1 = savestring (patstr);
3980 pattern = getpattern (temp1, quoted, 1);
3981 free (temp1);
3983 temp1 = (char *)NULL; /* shut up gcc */
3984 switch (vtype)
3986 case VT_VARIABLE:
3987 case VT_ARRAYMEMBER:
3988 temp1 = remove_pattern (val, pattern, patspec);
3989 if (vtype == VT_VARIABLE)
3990 FREE (val);
3991 if (temp1)
3993 val = quote_escapes (temp1);
3994 free (temp1);
3995 temp1 = val;
3997 break;
3998 #if defined (ARRAY_VARS)
3999 case VT_ARRAYVAR:
4000 temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
4001 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4003 val = quote_escapes (temp1);
4004 free (temp1);
4005 temp1 = val;
4007 break;
4008 #endif
4009 case VT_POSPARMS:
4010 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
4011 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4013 val = quote_escapes (temp1);
4014 free (temp1);
4015 temp1 = val;
4017 break;
4020 FREE (pattern);
4021 return temp1;
4024 /*******************************************
4026 * Functions to expand WORD_DESCs *
4028 *******************************************/
4030 /* Expand WORD, performing word splitting on the result. This does
4031 parameter expansion, command substitution, arithmetic expansion,
4032 word splitting, and quote removal. */
4034 WORD_LIST *
4035 expand_word (word, quoted)
4036 WORD_DESC *word;
4037 int quoted;
4039 WORD_LIST *result, *tresult;
4041 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4042 result = word_list_split (tresult);
4043 dispose_words (tresult);
4044 return (result ? dequote_list (result) : result);
4047 /* Expand WORD, but do not perform word splitting on the result. This
4048 does parameter expansion, command substitution, arithmetic expansion,
4049 and quote removal. */
4050 WORD_LIST *
4051 expand_word_unsplit (word, quoted)
4052 WORD_DESC *word;
4053 int quoted;
4055 WORD_LIST *result;
4057 expand_no_split_dollar_star = 1;
4058 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4059 expand_no_split_dollar_star = 0;
4061 return (result ? dequote_list (result) : result);
4064 /* Perform shell expansions on WORD, but do not perform word splitting or
4065 quote removal on the result. */
4066 WORD_LIST *
4067 expand_word_leave_quoted (word, quoted)
4068 WORD_DESC *word;
4069 int quoted;
4071 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
4074 #if defined (PROCESS_SUBSTITUTION)
4076 /*****************************************************************/
4077 /* */
4078 /* Hacking Process Substitution */
4079 /* */
4080 /*****************************************************************/
4082 #if !defined (HAVE_DEV_FD)
4083 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
4084 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4085 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4086 list. NFIFO is a count of the number of FIFOs in the list. */
4087 #define FIFO_INCR 20
4089 struct temp_fifo {
4090 char *file;
4091 pid_t proc;
4094 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4095 static int nfifo;
4096 static int fifo_list_size;
4098 static void
4099 add_fifo_list (pathname)
4100 char *pathname;
4102 if (nfifo >= fifo_list_size - 1)
4104 fifo_list_size += FIFO_INCR;
4105 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4106 fifo_list_size * sizeof (struct temp_fifo));
4109 fifo_list[nfifo].file = savestring (pathname);
4110 nfifo++;
4113 void
4114 unlink_fifo_list ()
4116 int saved, i, j;
4118 if (nfifo == 0)
4119 return;
4121 for (i = saved = 0; i < nfifo; i++)
4123 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4125 unlink (fifo_list[i].file);
4126 free (fifo_list[i].file);
4127 fifo_list[i].file = (char *)NULL;
4128 fifo_list[i].proc = -1;
4130 else
4131 saved++;
4134 /* If we didn't remove some of the FIFOs, compact the list. */
4135 if (saved)
4137 for (i = j = 0; i < nfifo; i++)
4138 if (fifo_list[i].file)
4140 fifo_list[j].file = fifo_list[i].file;
4141 fifo_list[j].proc = fifo_list[i].proc;
4142 j++;
4144 nfifo = j;
4146 else
4147 nfifo = 0;
4151 fifos_pending ()
4153 return nfifo;
4156 static char *
4157 make_named_pipe ()
4159 char *tname;
4161 tname = sh_mktmpname ("sh-np", MT_USERANDOM);
4162 if (mkfifo (tname, 0600) < 0)
4164 free (tname);
4165 return ((char *)NULL);
4168 add_fifo_list (tname);
4169 return (tname);
4172 #else /* HAVE_DEV_FD */
4174 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4175 has open to children. NFDS is a count of the number of bits currently
4176 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4177 of open files. */
4178 static char *dev_fd_list = (char *)NULL;
4179 static int nfds;
4180 static int totfds; /* The highest possible number of open files. */
4182 static void
4183 add_fifo_list (fd)
4184 int fd;
4186 if (!dev_fd_list || fd >= totfds)
4188 int ofds;
4190 ofds = totfds;
4191 totfds = getdtablesize ();
4192 if (totfds < 0 || totfds > 256)
4193 totfds = 256;
4194 if (fd > totfds)
4195 totfds = fd + 2;
4197 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4198 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4201 dev_fd_list[fd] = 1;
4202 nfds++;
4206 fifos_pending ()
4208 return 0; /* used for cleanup; not needed with /dev/fd */
4211 void
4212 unlink_fifo_list ()
4214 register int i;
4216 if (nfds == 0)
4217 return;
4219 for (i = 0; nfds && i < totfds; i++)
4220 if (dev_fd_list[i])
4222 close (i);
4223 dev_fd_list[i] = 0;
4224 nfds--;
4227 nfds = 0;
4230 #if defined (NOTDEF)
4231 print_dev_fd_list ()
4233 register int i;
4235 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4236 fflush (stderr);
4238 for (i = 0; i < totfds; i++)
4240 if (dev_fd_list[i])
4241 fprintf (stderr, " %d", i);
4243 fprintf (stderr, "\n");
4245 #endif /* NOTDEF */
4247 static char *
4248 make_dev_fd_filename (fd)
4249 int fd;
4251 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4253 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
4255 strcpy (ret, DEV_FD_PREFIX);
4256 p = inttostr (fd, intbuf, sizeof (intbuf));
4257 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4259 add_fifo_list (fd);
4260 return (ret);
4263 #endif /* HAVE_DEV_FD */
4265 /* Return a filename that will open a connection to the process defined by
4266 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4267 a filename in /dev/fd corresponding to a descriptor that is one of the
4268 ends of the pipe. If not defined, we use named pipes on systems that have
4269 them. Systems without /dev/fd and named pipes are out of luck.
4271 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4272 use the read end of the pipe and dup that file descriptor to fd 0 in
4273 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4274 writing or use the write end of the pipe in the child, and dup that
4275 file descriptor to fd 1 in the child. The parent does the opposite. */
4277 static char *
4278 process_substitute (string, open_for_read_in_child)
4279 char *string;
4280 int open_for_read_in_child;
4282 char *pathname;
4283 int fd, result;
4284 pid_t old_pid, pid;
4285 #if defined (HAVE_DEV_FD)
4286 int parent_pipe_fd, child_pipe_fd;
4287 int fildes[2];
4288 #endif /* HAVE_DEV_FD */
4289 #if defined (JOB_CONTROL)
4290 pid_t old_pipeline_pgrp;
4291 #endif
4293 if (!string || !*string || wordexp_only)
4294 return ((char *)NULL);
4296 #if !defined (HAVE_DEV_FD)
4297 pathname = make_named_pipe ();
4298 #else /* HAVE_DEV_FD */
4299 if (pipe (fildes) < 0)
4301 sys_error (_("cannot make pipe for process substitution"));
4302 return ((char *)NULL);
4304 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4305 the pipe in the parent, otherwise the read end. */
4306 parent_pipe_fd = fildes[open_for_read_in_child];
4307 child_pipe_fd = fildes[1 - open_for_read_in_child];
4308 /* Move the parent end of the pipe to some high file descriptor, to
4309 avoid clashes with FDs used by the script. */
4310 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4312 pathname = make_dev_fd_filename (parent_pipe_fd);
4313 #endif /* HAVE_DEV_FD */
4315 if (!pathname)
4317 sys_error (_("cannot make pipe for process substitution"));
4318 return ((char *)NULL);
4321 old_pid = last_made_pid;
4323 #if defined (JOB_CONTROL)
4324 old_pipeline_pgrp = pipeline_pgrp;
4325 pipeline_pgrp = shell_pgrp;
4326 save_pipeline (1);
4327 #endif /* JOB_CONTROL */
4329 pid = make_child ((char *)NULL, 1);
4330 if (pid == 0)
4332 reset_terminating_signals (); /* XXX */
4333 free_pushed_string_input ();
4334 /* Cancel traps, in trap.c. */
4335 restore_original_signals ();
4336 setup_async_signals ();
4337 subshell_environment |= SUBSHELL_COMSUB;
4340 #if defined (JOB_CONTROL)
4341 set_sigchld_handler ();
4342 stop_making_children ();
4343 pipeline_pgrp = old_pipeline_pgrp;
4344 #endif /* JOB_CONTROL */
4346 if (pid < 0)
4348 sys_error (_("cannot make child for process substitution"));
4349 free (pathname);
4350 #if defined (HAVE_DEV_FD)
4351 close (parent_pipe_fd);
4352 close (child_pipe_fd);
4353 #endif /* HAVE_DEV_FD */
4354 return ((char *)NULL);
4357 if (pid > 0)
4359 #if defined (JOB_CONTROL)
4360 restore_pipeline (1);
4361 #endif
4363 #if !defined (HAVE_DEV_FD)
4364 fifo_list[nfifo-1].proc = pid;
4365 #endif
4367 last_made_pid = old_pid;
4369 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4370 close_pgrp_pipe ();
4371 #endif /* JOB_CONTROL && PGRP_PIPE */
4373 #if defined (HAVE_DEV_FD)
4374 close (child_pipe_fd);
4375 #endif /* HAVE_DEV_FD */
4377 return (pathname);
4380 set_sigint_handler ();
4382 #if defined (JOB_CONTROL)
4383 set_job_control (0);
4384 #endif /* JOB_CONTROL */
4386 #if !defined (HAVE_DEV_FD)
4387 /* Open the named pipe in the child. */
4388 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4389 if (fd < 0)
4391 /* Two separate strings for ease of translation. */
4392 if (open_for_read_in_child)
4393 sys_error (_("cannot open named pipe %s for reading"), pathname);
4394 else
4395 sys_error (_("cannot open named pipe %s for writing"), pathname);
4397 exit (127);
4399 if (open_for_read_in_child)
4401 if (sh_unset_nodelay_mode (fd) < 0)
4403 sys_error (_("cannout reset nodelay mode for fd %d"), fd);
4404 exit (127);
4407 #else /* HAVE_DEV_FD */
4408 fd = child_pipe_fd;
4409 #endif /* HAVE_DEV_FD */
4411 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4413 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4414 open_for_read_in_child ? 0 : 1);
4415 exit (127);
4418 if (fd != (open_for_read_in_child ? 0 : 1))
4419 close (fd);
4421 /* Need to close any files that this process has open to pipes inherited
4422 from its parent. */
4423 if (current_fds_to_close)
4425 close_fd_bitmap (current_fds_to_close);
4426 current_fds_to_close = (struct fd_bitmap *)NULL;
4429 #if defined (HAVE_DEV_FD)
4430 /* Make sure we close the parent's end of the pipe and clear the slot
4431 in the fd list so it is not closed later, if reallocated by, for
4432 instance, pipe(2). */
4433 close (parent_pipe_fd);
4434 dev_fd_list[parent_pipe_fd] = 0;
4435 #endif /* HAVE_DEV_FD */
4437 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4439 #if !defined (HAVE_DEV_FD)
4440 /* Make sure we close the named pipe in the child before we exit. */
4441 close (open_for_read_in_child ? 0 : 1);
4442 #endif /* !HAVE_DEV_FD */
4444 exit (result);
4445 /*NOTREACHED*/
4447 #endif /* PROCESS_SUBSTITUTION */
4449 /***********************************/
4450 /* */
4451 /* Command Substitution */
4452 /* */
4453 /***********************************/
4455 static char *
4456 read_comsub (fd, quoted)
4457 int fd, quoted;
4459 char *istring, buf[128], *bufp;
4460 int istring_index, istring_size, c;
4461 ssize_t bufn;
4463 istring = (char *)NULL;
4464 istring_index = istring_size = bufn = 0;
4466 #ifdef __CYGWIN__
4467 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
4468 #endif
4470 /* Read the output of the command through the pipe. */
4471 while (1)
4473 if (fd < 0)
4474 break;
4475 if (--bufn <= 0)
4477 bufn = zread (fd, buf, sizeof (buf));
4478 if (bufn <= 0)
4479 break;
4480 bufp = buf;
4482 c = *bufp++;
4484 if (c == 0)
4486 #if 0
4487 internal_warning ("read_comsub: ignored null byte in input");
4488 #endif
4489 continue;
4492 /* Add the character to ISTRING, possibly after resizing it. */
4493 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4495 /* This is essentially quote_string inline */
4496 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
4497 istring[istring_index++] = CTLESC;
4498 /* Escape CTLESC and CTLNUL in the output to protect those characters
4499 from the rest of the word expansions (word splitting and globbing.)
4500 This is essentially quote_escapes inline. */
4501 else if (c == CTLESC)
4502 istring[istring_index++] = CTLESC;
4503 else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
4504 istring[istring_index++] = CTLESC;
4506 istring[istring_index++] = c;
4508 #if 0
4509 #if defined (__CYGWIN__)
4510 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4512 istring_index--;
4513 istring[istring_index - 1] = '\n';
4515 #endif
4516 #endif
4519 if (istring)
4520 istring[istring_index] = '\0';
4522 /* If we read no output, just return now and save ourselves some
4523 trouble. */
4524 if (istring_index == 0)
4526 FREE (istring);
4527 return (char *)NULL;
4530 /* Strip trailing newlines from the output of the command. */
4531 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4533 while (istring_index > 0)
4535 if (istring[istring_index - 1] == '\n')
4537 --istring_index;
4539 /* If the newline was quoted, remove the quoting char. */
4540 if (istring[istring_index - 1] == CTLESC)
4541 --istring_index;
4543 else
4544 break;
4546 istring[istring_index] = '\0';
4548 else
4549 strip_trailing (istring, istring_index - 1, 1);
4551 return istring;
4554 /* Perform command substitution on STRING. This returns a string,
4555 possibly quoted. */
4556 char *
4557 command_substitute (string, quoted)
4558 char *string;
4559 int quoted;
4561 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4562 char *istring;
4563 int result, fildes[2], function_value, pflags, rc;
4565 istring = (char *)NULL;
4567 /* Don't fork () if there is no need to. In the case of no command to
4568 run, just return NULL. */
4569 if (!string || !*string || (string[0] == '\n' && !string[1]))
4570 return ((char *)NULL);
4572 if (wordexp_only && read_but_dont_execute)
4574 last_command_exit_value = 125;
4575 jump_to_top_level (EXITPROG);
4578 /* We're making the assumption here that the command substitution will
4579 eventually run a command from the file system. Since we'll run
4580 maybe_make_export_env in this subshell before executing that command,
4581 the parent shell and any other shells it starts will have to remake
4582 the environment. If we make it before we fork, other shells won't
4583 have to. Don't bother if we have any temporary variable assignments,
4584 though, because the export environment will be remade after this
4585 command completes anyway, but do it if all the words to be expanded
4586 are variable assignments. */
4587 if (subst_assign_varlist == 0 || garglist == 0)
4588 maybe_make_export_env (); /* XXX */
4590 /* Flags to pass to parse_and_execute() */
4591 pflags = interactive ? SEVAL_RESETLINE : 0;
4593 /* Pipe the output of executing STRING into the current shell. */
4594 if (pipe (fildes) < 0)
4596 sys_error (_("cannot make pipe for command substitution"));
4597 goto error_exit;
4600 old_pid = last_made_pid;
4601 #if defined (JOB_CONTROL)
4602 old_pipeline_pgrp = pipeline_pgrp;
4603 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4604 if ((subshell_environment & SUBSHELL_PIPE) == 0)
4605 pipeline_pgrp = shell_pgrp;
4606 cleanup_the_pipeline ();
4607 #endif /* JOB_CONTROL */
4609 old_async_pid = last_asynchronous_pid;
4610 #if 0
4611 pid = make_child ((char *)NULL, 0);
4612 #else
4613 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4614 #endif
4615 last_asynchronous_pid = old_async_pid;
4617 if (pid == 0)
4618 /* Reset the signal handlers in the child, but don't free the
4619 trap strings. */
4620 reset_signal_handlers ();
4622 #if defined (JOB_CONTROL)
4623 set_sigchld_handler ();
4624 stop_making_children ();
4625 pipeline_pgrp = old_pipeline_pgrp;
4626 #else
4627 stop_making_children ();
4628 #endif /* JOB_CONTROL */
4630 if (pid < 0)
4632 sys_error (_("cannot make child for command substitution"));
4633 error_exit:
4635 FREE (istring);
4636 close (fildes[0]);
4637 close (fildes[1]);
4638 return ((char *)NULL);
4641 if (pid == 0)
4643 set_sigint_handler (); /* XXX */
4645 free_pushed_string_input ();
4647 if (dup2 (fildes[1], 1) < 0)
4649 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4650 exit (EXECUTION_FAILURE);
4653 /* If standard output is closed in the parent shell
4654 (such as after `exec >&-'), file descriptor 1 will be
4655 the lowest available file descriptor, and end up in
4656 fildes[0]. This can happen for stdin and stderr as well,
4657 but stdout is more important -- it will cause no output
4658 to be generated from this command. */
4659 if ((fildes[1] != fileno (stdin)) &&
4660 (fildes[1] != fileno (stdout)) &&
4661 (fildes[1] != fileno (stderr)))
4662 close (fildes[1]);
4664 if ((fildes[0] != fileno (stdin)) &&
4665 (fildes[0] != fileno (stdout)) &&
4666 (fildes[0] != fileno (stderr)))
4667 close (fildes[0]);
4669 /* The currently executing shell is not interactive. */
4670 interactive = 0;
4672 /* This is a subshell environment. */
4673 subshell_environment |= SUBSHELL_COMSUB;
4675 /* When not in POSIX mode, command substitution does not inherit
4676 the -e flag. */
4677 if (posixly_correct == 0)
4678 exit_immediately_on_error = 0;
4680 remove_quoted_escapes (string);
4682 startup_state = 2; /* see if we can avoid a fork */
4683 /* Give command substitution a place to jump back to on failure,
4684 so we don't go back up to main (). */
4685 result = setjmp (top_level);
4687 /* If we're running a command substitution inside a shell function,
4688 trap `return' so we don't return from the function in the subshell
4689 and go off to never-never land. */
4690 if (result == 0 && return_catch_flag)
4691 function_value = setjmp (return_catch);
4692 else
4693 function_value = 0;
4695 if (result == ERREXIT)
4696 rc = last_command_exit_value;
4697 else if (result == EXITPROG)
4698 rc = last_command_exit_value;
4699 else if (result)
4700 rc = EXECUTION_FAILURE;
4701 else if (function_value)
4702 rc = return_catch_value;
4703 else
4705 subshell_level++;
4706 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4707 subshell_level--;
4710 last_command_exit_value = rc;
4711 rc = run_exit_trap ();
4712 #if defined (PROCESS_SUBSTITUTION)
4713 unlink_fifo_list ();
4714 #endif
4715 exit (rc);
4717 else
4719 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4720 close_pgrp_pipe ();
4721 #endif /* JOB_CONTROL && PGRP_PIPE */
4723 close (fildes[1]);
4725 istring = read_comsub (fildes[0], quoted);
4727 close (fildes[0]);
4729 current_command_subst_pid = pid;
4730 last_command_exit_value = wait_for (pid);
4731 last_command_subst_pid = pid;
4732 last_made_pid = old_pid;
4734 #if defined (JOB_CONTROL)
4735 /* If last_command_exit_value > 128, then the substituted command
4736 was terminated by a signal. If that signal was SIGINT, then send
4737 SIGINT to ourselves. This will break out of loops, for instance. */
4738 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
4739 kill (getpid (), SIGINT);
4741 /* wait_for gives the terminal back to shell_pgrp. If some other
4742 process group should have it, give it away to that group here.
4743 pipeline_pgrp is non-zero only while we are constructing a
4744 pipline, so what we are concerned about is whether or not that
4745 pipeline was started in the background. A pipeline started in
4746 the background should never get the tty back here. */
4747 #if 0
4748 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
4749 #else
4750 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
4751 #endif
4752 give_terminal_to (pipeline_pgrp, 0);
4753 #endif /* JOB_CONTROL */
4755 return (istring);
4759 /********************************************************
4761 * Utility functions for parameter expansion *
4763 ********************************************************/
4765 #if defined (ARRAY_VARS)
4767 static arrayind_t
4768 array_length_reference (s)
4769 char *s;
4771 int len;
4772 arrayind_t ind;
4773 char *t, c;
4774 ARRAY *array;
4775 SHELL_VAR *var;
4777 var = array_variable_part (s, &t, &len);
4779 /* If unbound variables should generate an error, report one and return
4780 failure. */
4781 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
4783 c = *--t;
4784 *t = '\0';
4785 err_unboundvar (s);
4786 *t = c;
4787 return (-1);
4789 else if (var == 0)
4790 return 0;
4792 /* We support a couple of expansions for variables that are not arrays.
4793 We'll return the length of the value for v[0], and 1 for v[@] or
4794 v[*]. Return 0 for everything else. */
4796 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
4798 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
4799 return (array_p (var) ? array_num_elements (array) : 1);
4801 ind = array_expand_index (t, len);
4802 if (ind < 0)
4804 err_badarraysub (t);
4805 return (-1);
4808 if (array_p (var))
4809 t = array_reference (array, ind);
4810 else
4811 t = (ind == 0) ? value_cell (var) : (char *)NULL;
4813 len = STRLEN (t);
4814 return (len);
4816 #endif /* ARRAY_VARS */
4818 static int
4819 valid_brace_expansion_word (name, var_is_special)
4820 char *name;
4821 int var_is_special;
4823 if (DIGIT (*name) && all_digits (name))
4824 return 1;
4825 else if (var_is_special)
4826 return 1;
4827 #if defined (ARRAY_VARS)
4828 else if (valid_array_reference (name))
4829 return 1;
4830 #endif /* ARRAY_VARS */
4831 else if (legal_identifier (name))
4832 return 1;
4833 else
4834 return 0;
4837 static int
4838 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
4839 char *name;
4840 int quoted;
4841 int *quoted_dollar_atp, *contains_dollar_at;
4843 char *temp1;
4845 if (name == 0)
4847 if (quoted_dollar_atp)
4848 *quoted_dollar_atp = 0;
4849 if (contains_dollar_at)
4850 *contains_dollar_at = 0;
4851 return 0;
4854 /* check for $@ and $* */
4855 if (name[0] == '@' && name[1] == 0)
4857 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4858 *quoted_dollar_atp = 1;
4859 if (contains_dollar_at)
4860 *contains_dollar_at = 1;
4861 return 1;
4863 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
4865 if (contains_dollar_at)
4866 *contains_dollar_at = 1;
4867 return 1;
4870 /* Now check for ${array[@]} and ${array[*]} */
4871 #if defined (ARRAY_VARS)
4872 else if (valid_array_reference (name))
4874 temp1 = xstrchr (name, '[');
4875 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4877 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4878 *quoted_dollar_atp = 1;
4879 if (contains_dollar_at)
4880 *contains_dollar_at = 1;
4881 return 1;
4882 } /* [ */
4883 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4884 which should result in separate words even when IFS is unset. */
4885 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4887 if (contains_dollar_at)
4888 *contains_dollar_at = 1;
4889 return 1;
4892 #endif
4893 return 0;
4896 /* Parameter expand NAME, and return a new string which is the expansion,
4897 or NULL if there was no expansion.
4898 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
4899 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
4900 NAME was found inside of a double-quoted expression. */
4901 static WORD_DESC *
4902 parameter_brace_expand_word (name, var_is_special, quoted)
4903 char *name;
4904 int var_is_special, quoted;
4906 WORD_DESC *ret;
4907 char *temp, *tt;
4908 intmax_t arg_index;
4909 SHELL_VAR *var;
4910 int atype;
4912 ret = 0;
4913 temp = 0;
4915 /* Handle multiple digit arguments, as in ${11}. */
4916 if (legal_number (name, &arg_index))
4918 tt = get_dollar_var_value (arg_index);
4919 if (tt)
4920 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4921 ? quote_string (tt)
4922 : quote_escapes (tt);
4923 else
4924 temp = (char *)NULL;
4925 FREE (tt);
4927 else if (var_is_special) /* ${@} */
4929 int sindex;
4930 tt = (char *)xmalloc (2 + strlen (name));
4931 tt[sindex = 0] = '$';
4932 strcpy (tt + 1, name);
4934 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
4935 (int *)NULL, (int *)NULL, 0);
4936 free (tt);
4938 #if defined (ARRAY_VARS)
4939 else if (valid_array_reference (name))
4941 temp = array_value (name, quoted, &atype);
4942 if (atype == 0 && temp)
4943 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4944 ? quote_string (temp)
4945 : quote_escapes (temp);
4947 #endif
4948 else if (var = find_variable (name))
4950 if (var_isset (var) && invisible_p (var) == 0)
4952 #if defined (ARRAY_VARS)
4953 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
4954 #else
4955 temp = value_cell (var);
4956 #endif
4958 if (temp)
4959 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4960 ? quote_string (temp)
4961 : quote_escapes (temp);
4963 else
4964 temp = (char *)NULL;
4966 else
4967 temp = (char *)NULL;
4969 if (ret == 0)
4971 ret = alloc_word_desc ();
4972 ret->word = temp;
4974 return ret;
4977 /* Expand an indirect reference to a variable: ${!NAME} expands to the
4978 value of the variable whose name is the value of NAME. */
4979 static WORD_DESC *
4980 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
4981 char *name;
4982 int var_is_special, quoted;
4983 int *quoted_dollar_atp, *contains_dollar_at;
4985 char *temp, *t;
4986 WORD_DESC *w;
4988 w = parameter_brace_expand_word (name, var_is_special, quoted);
4989 t = w->word;
4990 /* Have to dequote here if necessary */
4991 if (t)
4993 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
4994 ? dequote_string (t)
4995 : dequote_escapes (t);
4996 free (t);
4997 t = temp;
4999 dispose_word_desc (w);
5001 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5002 if (t == 0)
5003 return (WORD_DESC *)NULL;
5005 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
5006 free (t);
5008 return w;
5011 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5012 depending on the value of C, the separating character. C can be one of
5013 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5014 between double quotes. */
5015 static WORD_DESC *
5016 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5017 char *name, *value;
5018 int c, quoted, *qdollaratp, *hasdollarat;
5020 WORD_DESC *w;
5021 WORD_LIST *l;
5022 char *t, *t1, *temp;
5023 int hasdol;
5025 /* If the entire expression is between double quotes, we want to treat
5026 the value as a double-quoted string, with the exception that we strip
5027 embedded unescaped double quotes. */
5028 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5030 hasdol = 0;
5031 temp = string_extract_double_quoted (value, &hasdol, 1);
5033 else
5034 temp = value;
5036 w = alloc_word_desc ();
5037 hasdol = 0;
5038 /* XXX was 0 not quoted */
5039 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5040 : (WORD_LIST *)0;
5041 if (hasdollarat)
5042 *hasdollarat = hasdol || (l && l->next);
5043 if (temp != value)
5044 free (temp);
5045 if (l)
5047 /* The expansion of TEMP returned something. We need to treat things
5048 slightly differently if HASDOL is non-zero. If we have "$@", the
5049 individual words have already been quoted. We need to turn them
5050 into a string with the words separated by the first character of
5051 $IFS without any additional quoting, so string_list_dollar_at won't
5052 do the right thing. We use string_list_dollar_star instead. */
5053 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5055 /* If l->next is not null, we know that TEMP contained "$@", since that
5056 is the only expansion that creates more than one word. */
5057 if (qdollaratp && ((hasdol && quoted) || l->next))
5058 *qdollaratp = 1;
5059 dispose_words (l);
5061 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5063 /* The brace expansion occurred between double quotes and there was
5064 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5065 it does not expand to anything. In this case, we want to return
5066 a quoted empty string. */
5067 temp = make_quoted_char ('\0');
5068 w->flags |= W_HASQUOTEDNULL;
5070 else
5071 temp = (char *)NULL;
5073 if (c == '-' || c == '+')
5075 w->word = temp;
5076 return w;
5079 /* c == '=' */
5080 t = temp ? savestring (temp) : savestring ("");
5081 t1 = dequote_string (t);
5082 free (t);
5083 #if defined (ARRAY_VARS)
5084 if (valid_array_reference (name))
5085 assign_array_element (name, t1, 0);
5086 else
5087 #endif /* ARRAY_VARS */
5088 bind_variable (name, t1, 0);
5089 free (t1);
5091 w->word = temp;
5092 return w;
5095 /* Deal with the right hand side of a ${name:?value} expansion in the case
5096 that NAME is null or not set. If VALUE is non-null it is expanded and
5097 used as the error message to print, otherwise a standard message is
5098 printed. */
5099 static void
5100 parameter_brace_expand_error (name, value)
5101 char *name, *value;
5103 WORD_LIST *l;
5104 char *temp;
5106 if (value && *value)
5108 l = expand_string (value, 0);
5109 temp = string_list (l);
5110 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5111 FREE (temp);
5112 dispose_words (l);
5114 else
5115 report_error (_("%s: parameter null or not set"), name);
5117 /* Free the data we have allocated during this expansion, since we
5118 are about to longjmp out. */
5119 free (name);
5120 FREE (value);
5123 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5124 OK to do. */
5125 static int
5126 valid_length_expression (name)
5127 char *name;
5129 return (name[1] == '\0' || /* ${#} */
5130 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5131 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5132 #if defined (ARRAY_VARS)
5133 valid_array_reference (name + 1) || /* ${#a[7]} */
5134 #endif
5135 legal_identifier (name + 1)); /* ${#PS1} */
5138 #if defined (HANDLE_MULTIBYTE)
5139 size_t
5140 mbstrlen (s)
5141 const char *s;
5143 size_t clen, nc;
5144 mbstate_t mbs, mbsbak;
5146 nc = 0;
5147 memset (&mbs, 0, sizeof (mbs));
5148 mbsbak = mbs;
5149 while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5151 if (MB_INVALIDCH(clen))
5153 clen = 1; /* assume single byte */
5154 mbs = mbsbak;
5157 s += clen;
5158 nc++;
5159 mbsbak = mbs;
5161 return nc;
5163 #endif
5166 /* Handle the parameter brace expansion that requires us to return the
5167 length of a parameter. */
5168 static intmax_t
5169 parameter_brace_expand_length (name)
5170 char *name;
5172 char *t, *newname;
5173 intmax_t number, arg_index;
5174 WORD_LIST *list;
5175 #if defined (ARRAY_VARS)
5176 SHELL_VAR *var;
5177 #endif
5179 if (name[1] == '\0') /* ${#} */
5180 number = number_of_args ();
5181 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5182 number = number_of_args ();
5183 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5185 /* Take the lengths of some of the shell's special parameters. */
5186 switch (name[1])
5188 case '-':
5189 t = which_set_flags ();
5190 break;
5191 case '?':
5192 t = itos (last_command_exit_value);
5193 break;
5194 case '$':
5195 t = itos (dollar_dollar_pid);
5196 break;
5197 case '!':
5198 if (last_asynchronous_pid == NO_PID)
5199 t = (char *)NULL;
5200 else
5201 t = itos (last_asynchronous_pid);
5202 break;
5203 case '#':
5204 t = itos (number_of_args ());
5205 break;
5207 number = STRLEN (t);
5208 FREE (t);
5210 #if defined (ARRAY_VARS)
5211 else if (valid_array_reference (name + 1))
5212 number = array_length_reference (name + 1);
5213 #endif /* ARRAY_VARS */
5214 else
5216 number = 0;
5218 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5220 t = get_dollar_var_value (arg_index);
5221 number = MB_STRLEN (t);
5222 FREE (t);
5224 #if defined (ARRAY_VARS)
5225 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && array_p (var))
5227 t = array_reference (array_cell (var), 0);
5228 number = MB_STRLEN (t);
5230 #endif
5231 else /* ${#PS1} */
5233 newname = savestring (name);
5234 newname[0] = '$';
5235 list = expand_string (newname, Q_DOUBLE_QUOTES);
5236 t = list ? string_list (list) : (char *)NULL;
5237 free (newname);
5238 if (list)
5239 dispose_words (list);
5241 number = MB_STRLEN (t);
5242 FREE (t);
5246 return (number);
5249 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5250 so we do some ad-hoc parsing of an arithmetic expression to find
5251 the first DELIM, instead of using strchr(3). Two rules:
5252 1. If the substring contains a `(', read until closing `)'.
5253 2. If the substring contains a `?', read past one `:' for each `?'.
5256 static char *
5257 skiparith (substr, delim)
5258 char *substr;
5259 int delim;
5261 size_t sublen;
5262 int skipcol, pcount, i;
5263 DECLARE_MBSTATE;
5265 sublen = strlen (substr);
5266 i = skipcol = pcount = 0;
5267 while (substr[i])
5269 /* Balance parens */
5270 if (substr[i] == LPAREN)
5272 pcount++;
5273 i++;
5274 continue;
5276 if (substr[i] == RPAREN && pcount)
5278 pcount--;
5279 i++;
5280 continue;
5282 if (pcount)
5284 ADVANCE_CHAR (substr, sublen, i);
5285 continue;
5288 /* Skip one `:' for each `?' */
5289 if (substr[i] == ':' && skipcol)
5291 skipcol--;
5292 i++;
5293 continue;
5295 if (substr[i] == delim)
5296 break;
5297 if (substr[i] == '?')
5299 skipcol++;
5300 i++;
5301 continue;
5303 ADVANCE_CHAR (substr, sublen, i);
5306 return (substr + i);
5309 /* Verify and limit the start and end of the desired substring. If
5310 VTYPE == 0, a regular shell variable is being used; if it is 1,
5311 then the positional parameters are being used; if it is 2, then
5312 VALUE is really a pointer to an array variable that should be used.
5313 Return value is 1 if both values were OK, 0 if there was a problem
5314 with an invalid expression, or -1 if the values were out of range. */
5315 static int
5316 verify_substring_values (value, substr, vtype, e1p, e2p)
5317 char *value, *substr;
5318 int vtype;
5319 intmax_t *e1p, *e2p;
5321 char *t, *temp1, *temp2;
5322 arrayind_t len;
5323 int expok;
5324 #if defined (ARRAY_VARS)
5325 ARRAY *a;
5326 #endif
5328 /* duplicate behavior of strchr(3) */
5329 t = skiparith (substr, ':');
5330 if (*t && *t == ':')
5331 *t = '\0';
5332 else
5333 t = (char *)0;
5335 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
5336 *e1p = evalexp (temp1, &expok);
5337 free (temp1);
5338 if (expok == 0)
5339 return (0);
5341 len = -1; /* paranoia */
5342 switch (vtype)
5344 case VT_VARIABLE:
5345 case VT_ARRAYMEMBER:
5346 len = MB_STRLEN (value);
5347 break;
5348 case VT_POSPARMS:
5349 len = number_of_args () + 1;
5350 break;
5351 #if defined (ARRAY_VARS)
5352 case VT_ARRAYVAR:
5353 a = (ARRAY *)value;
5354 /* For arrays, the first value deals with array indices. Negative
5355 offsets count from one past the array's maximum index. */
5356 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
5357 break;
5358 #endif
5361 if (len == -1) /* paranoia */
5362 return -1;
5364 if (*e1p < 0) /* negative offsets count from end */
5365 *e1p += len;
5367 if (*e1p > len || *e1p < 0)
5368 return (-1);
5370 #if defined (ARRAY_VARS)
5371 /* For arrays, the second offset deals with the number of elements. */
5372 if (vtype == VT_ARRAYVAR)
5373 len = array_num_elements (a);
5374 #endif
5376 if (t)
5378 t++;
5379 temp2 = savestring (t);
5380 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
5381 free (temp2);
5382 t[-1] = ':';
5383 *e2p = evalexp (temp1, &expok);
5384 free (temp1);
5385 if (expok == 0)
5386 return (0);
5387 if (*e2p < 0)
5389 internal_error (_("%s: substring expression < 0"), t);
5390 return (0);
5392 #if defined (ARRAY_VARS)
5393 /* In order to deal with sparse arrays, push the intelligence about how
5394 to deal with the number of elements desired down to the array-
5395 specific functions. */
5396 if (vtype != VT_ARRAYVAR)
5397 #endif
5399 *e2p += *e1p; /* want E2 chars starting at E1 */
5400 if (*e2p > len)
5401 *e2p = len;
5404 else
5405 *e2p = len;
5407 return (1);
5410 /* Return the type of variable specified by VARNAME (simple variable,
5411 positional param, or array variable). Also return the value specified
5412 by VARNAME (value of a variable or a reference to an array element).
5413 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5414 characters in the value are quoted with CTLESC and takes appropriate
5415 steps. For convenience, *VALP is set to the dequoted VALUE. */
5416 static int
5417 get_var_and_type (varname, value, quoted, varp, valp)
5418 char *varname, *value;
5419 int quoted;
5420 SHELL_VAR **varp;
5421 char **valp;
5423 int vtype;
5424 char *temp;
5425 #if defined (ARRAY_VARS)
5426 SHELL_VAR *v;
5427 #endif
5429 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5430 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5431 if (vtype == VT_POSPARMS && varname[0] == '*')
5432 vtype |= VT_STARSUB;
5433 *varp = (SHELL_VAR *)NULL;
5435 #if defined (ARRAY_VARS)
5436 if (valid_array_reference (varname))
5438 v = array_variable_part (varname, &temp, (int *)0);
5439 if (v && array_p (v))
5440 { /* [ */
5441 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5443 vtype = VT_ARRAYVAR;
5444 if (temp[0] == '*')
5445 vtype |= VT_STARSUB;
5446 *valp = (char *)array_cell (v);
5448 else
5450 vtype = VT_ARRAYMEMBER;
5451 *valp = array_value (varname, 1, (int *)NULL);
5453 *varp = v;
5455 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5457 vtype = VT_VARIABLE;
5458 *varp = v;
5459 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5460 *valp = dequote_string (value);
5461 else
5462 *valp = dequote_escapes (value);
5464 else
5465 return -1;
5467 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v))
5469 vtype = VT_ARRAYMEMBER;
5470 *varp = v;
5471 *valp = array_reference (array_cell (v), 0);
5473 else
5474 #endif
5476 if (value && vtype == VT_VARIABLE)
5478 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5479 *valp = dequote_string (value);
5480 else
5481 *valp = dequote_escapes (value);
5483 else
5484 *valp = value;
5487 return vtype;
5490 /******************************************************/
5491 /* */
5492 /* Functions to extract substrings of variable values */
5493 /* */
5494 /******************************************************/
5496 #if defined (HANDLE_MULTIBYTE)
5497 /* Character-oriented rather than strictly byte-oriented substrings. S and
5498 E, rather being strict indices into STRING, indicate character (possibly
5499 multibyte character) positions that require calculation.
5500 Used by the ${param:offset[:length]} expansion. */
5501 static char *
5502 mb_substring (string, s, e)
5503 char *string;
5504 int s, e;
5506 char *tt;
5507 int start, stop, i, slen;
5508 DECLARE_MBSTATE;
5510 start = 0;
5511 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5512 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5514 i = s;
5515 while (string[start] && i--)
5516 ADVANCE_CHAR (string, slen, start);
5517 stop = start;
5518 i = e - s;
5519 while (string[stop] && i--)
5520 ADVANCE_CHAR (string, slen, stop);
5521 tt = substring (string, start, stop);
5522 return tt;
5524 #endif
5526 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
5527 is `@', use the positional parameters; otherwise, use the value of
5528 VARNAME. If VARNAME is an array variable, use the array elements. */
5530 static char *
5531 parameter_brace_substring (varname, value, substr, quoted)
5532 char *varname, *value, *substr;
5533 int quoted;
5535 intmax_t e1, e2;
5536 int vtype, r, starsub;
5537 char *temp, *val, *tt, *oname;
5538 SHELL_VAR *v;
5540 if (value == 0)
5541 return ((char *)NULL);
5543 oname = this_command_name;
5544 this_command_name = varname;
5546 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5547 if (vtype == -1)
5549 this_command_name = oname;
5550 return ((char *)NULL);
5553 starsub = vtype & VT_STARSUB;
5554 vtype &= ~VT_STARSUB;
5556 r = verify_substring_values (val, substr, vtype, &e1, &e2);
5557 this_command_name = oname;
5558 if (r <= 0)
5559 return ((r == 0) ? &expand_param_error : (char *)NULL);
5561 switch (vtype)
5563 case VT_VARIABLE:
5564 case VT_ARRAYMEMBER:
5565 #if defined (HANDLE_MULTIBYTE)
5566 if (MB_CUR_MAX > 1)
5567 tt = mb_substring (val, e1, e2);
5568 else
5569 #endif
5570 tt = substring (val, e1, e2);
5572 if (vtype == VT_VARIABLE)
5573 FREE (val);
5574 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5575 temp = quote_string (tt);
5576 else
5577 temp = tt ? quote_escapes (tt) : (char *)NULL;
5578 FREE (tt);
5579 break;
5580 case VT_POSPARMS:
5581 tt = pos_params (varname, e1, e2, quoted);
5582 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5584 temp = tt ? quote_escapes (tt) : (char *)NULL;
5585 FREE (tt);
5587 else
5588 temp = tt;
5589 break;
5590 #if defined (ARRAY_VARS)
5591 case VT_ARRAYVAR:
5592 /* We want E2 to be the number of elements desired (arrays can be sparse,
5593 so verify_substring_values just returns the numbers specified and we
5594 rely on array_subrange to understand how to deal with them). */
5595 tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5596 #if 0
5597 /* array_subrange now calls array_quote_escapes as appropriate, so the
5598 caller no longer needs to. */
5599 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5601 temp = tt ? quote_escapes (tt) : (char *)NULL;
5602 FREE (tt);
5604 else
5605 #endif
5606 temp = tt;
5607 break;
5608 #endif
5609 default:
5610 temp = (char *)NULL;
5613 return temp;
5616 /****************************************************************/
5617 /* */
5618 /* Functions to perform pattern substitution on variable values */
5619 /* */
5620 /****************************************************************/
5622 char *
5623 pat_subst (string, pat, rep, mflags)
5624 char *string, *pat, *rep;
5625 int mflags;
5627 char *ret, *s, *e, *str;
5628 int rsize, rptr, l, replen, mtype;
5630 mtype = mflags & MATCH_TYPEMASK;
5632 /* Special cases:
5633 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
5634 * with REP and return the result.
5635 * 2. A null pattern with mtype == MATCH_END means to append REP to
5636 * STRING and return the result.
5638 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5640 replen = STRLEN (rep);
5641 l = strlen (string);
5642 ret = (char *)xmalloc (replen + l + 2);
5643 if (replen == 0)
5644 strcpy (ret, string);
5645 else if (mtype == MATCH_BEG)
5647 strcpy (ret, rep);
5648 strcpy (ret + replen, string);
5650 else
5652 strcpy (ret, string);
5653 strcpy (ret + l, rep);
5655 return (ret);
5658 ret = (char *)xmalloc (rsize = 64);
5659 ret[0] = '\0';
5661 for (replen = STRLEN (rep), rptr = 0, str = string;;)
5663 if (match_pattern (str, pat, mtype, &s, &e) == 0)
5664 break;
5665 l = s - str;
5666 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5668 /* OK, now copy the leading unmatched portion of the string (from
5669 str to s) to ret starting at rptr (the current offset). Then copy
5670 the replacement string at ret + rptr + (s - str). Increment
5671 rptr (if necessary) and str and go on. */
5672 if (l)
5674 strncpy (ret + rptr, str, l);
5675 rptr += l;
5677 if (replen)
5679 strncpy (ret + rptr, rep, replen);
5680 rptr += replen;
5682 str = e; /* e == end of match */
5684 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
5685 break;
5687 if (s == e)
5688 e++, str++; /* avoid infinite recursion on zero-length match */
5691 /* Now copy the unmatched portion of the input string */
5692 if (*str)
5694 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
5695 strcpy (ret + rptr, str);
5697 else
5698 ret[rptr] = '\0';
5700 return ret;
5703 /* Do pattern match and replacement on the positional parameters. */
5704 static char *
5705 pos_params_pat_subst (string, pat, rep, mflags)
5706 char *string, *pat, *rep;
5707 int mflags;
5709 WORD_LIST *save, *params;
5710 WORD_DESC *w;
5711 char *ret;
5713 save = params = list_rest_of_args ();
5714 if (save == 0)
5715 return ((char *)NULL);
5717 for ( ; params; params = params->next)
5719 ret = pat_subst (params->word->word, pat, rep, mflags);
5720 w = alloc_word_desc ();
5721 w->word = ret ? ret : savestring ("");
5722 dispose_word (params->word);
5723 params->word = w;
5726 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
5727 ret = string_list_dollar_star (quote_list (save));
5728 else
5729 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
5730 dispose_words (save);
5732 return (ret);
5735 /* Perform pattern substitution on VALUE, which is the expansion of
5736 VARNAME. PATSUB is an expression supplying the pattern to match
5737 and the string to substitute. QUOTED is a flags word containing
5738 the type of quoting currently in effect. */
5739 static char *
5740 parameter_brace_patsub (varname, value, patsub, quoted)
5741 char *varname, *value, *patsub;
5742 int quoted;
5744 int vtype, mflags, starsub;
5745 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
5746 SHELL_VAR *v;
5748 if (value == 0)
5749 return ((char *)NULL);
5751 this_command_name = varname;
5753 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5754 if (vtype == -1)
5755 return ((char *)NULL);
5757 starsub = vtype & VT_STARSUB;
5758 vtype &= ~VT_STARSUB;
5760 mflags = 0;
5761 if (patsub && *patsub == '/')
5763 mflags |= MATCH_GLOBREP;
5764 patsub++;
5767 /* Malloc this because expand_string_if_necessary or one of the expansion
5768 functions in its call chain may free it on a substitution error. */
5769 lpatsub = savestring (patsub);
5771 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5772 mflags |= MATCH_QUOTED;
5774 if (starsub)
5775 mflags |= MATCH_STARSUB;
5777 /* If the pattern starts with a `/', make sure we skip over it when looking
5778 for the replacement delimiter. */
5779 if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
5780 *rep++ = '\0';
5781 else
5782 rep = (char *)NULL;
5784 if (rep && *rep == '\0')
5785 rep = (char *)NULL;
5787 /* Perform the same expansions on the pattern as performed by the
5788 pattern removal expansions. */
5789 pat = getpattern (lpatsub, quoted, 1);
5791 if (rep)
5793 if ((mflags & MATCH_QUOTED) == 0)
5794 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
5795 else
5796 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
5799 /* ksh93 doesn't allow the match specifier to be a part of the expanded
5800 pattern. This is an extension. Make sure we don't anchor the pattern
5801 at the beginning or end of the string if we're doing global replacement,
5802 though. */
5803 p = pat;
5804 if (mflags & MATCH_GLOBREP)
5805 mflags |= MATCH_ANY;
5806 else if (pat && pat[0] == '#')
5808 mflags |= MATCH_BEG;
5809 p++;
5811 else if (pat && pat[0] == '%')
5813 mflags |= MATCH_END;
5814 p++;
5816 else
5817 mflags |= MATCH_ANY;
5819 /* OK, we now want to substitute REP for PAT in VAL. If
5820 flags & MATCH_GLOBREP is non-zero, the substitution is done
5821 everywhere, otherwise only the first occurrence of PAT is
5822 replaced. The pattern matching code doesn't understand
5823 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
5824 values passed in (VT_VARIABLE) so the pattern substitution
5825 code works right. We need to requote special chars after
5826 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
5827 other cases if QUOTED == 0, since the posparams and arrays
5828 indexed by * or @ do special things when QUOTED != 0. */
5830 switch (vtype)
5832 case VT_VARIABLE:
5833 case VT_ARRAYMEMBER:
5834 temp = pat_subst (val, p, rep, mflags);
5835 if (vtype == VT_VARIABLE)
5836 FREE (val);
5837 if (temp)
5839 tt = quote_escapes (temp);
5840 free (temp);
5841 temp = tt;
5843 break;
5844 case VT_POSPARMS:
5845 temp = pos_params_pat_subst (val, p, rep, mflags);
5846 if (temp && (mflags & MATCH_QUOTED) == 0)
5848 tt = quote_escapes (temp);
5849 free (temp);
5850 temp = tt;
5852 break;
5853 #if defined (ARRAY_VARS)
5854 case VT_ARRAYVAR:
5855 temp = array_patsub (array_cell (v), p, rep, mflags);
5856 #if 0
5857 /* Don't need to do this anymore; array_patsub calls array_quote_escapes
5858 as appropriate before adding the space separators. */
5859 if (temp && (mflags & MATCH_QUOTED) == 0)
5861 tt = quote_escapes (temp);
5862 free (temp);
5863 temp = tt;
5865 #endif
5866 break;
5867 #endif
5870 FREE (pat);
5871 FREE (rep);
5872 free (lpatsub);
5874 return temp;
5877 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
5878 any occur, this must be a nested command substitution, so return 0.
5879 Otherwise, return 1. A valid arithmetic expression must always have a
5880 ( before a matching ), so any cases where there are more right parens
5881 means that this must not be an arithmetic expression, though the parser
5882 will not accept it without a balanced total number of parens. */
5883 static int
5884 chk_arithsub (s, len)
5885 const char *s;
5886 int len;
5888 int i, count;
5889 DECLARE_MBSTATE;
5891 i = count = 0;
5892 while (i < len)
5894 if (s[i] == '(')
5895 count++;
5896 else if (s[i] == ')')
5898 count--;
5899 if (count < 0)
5900 return 0;
5903 switch (s[i])
5905 default:
5906 ADVANCE_CHAR (s, len, i);
5907 break;
5909 case '\\':
5910 i++;
5911 if (s[i])
5912 ADVANCE_CHAR (s, len, i);
5913 break;
5915 case '\'':
5916 i = skip_single_quoted (s, len, ++i);
5917 break;
5919 case '"':
5920 i = skip_double_quoted ((char *)s, len, ++i);
5921 break;
5925 return (count == 0);
5928 /****************************************************************/
5929 /* */
5930 /* Functions to perform parameter expansion on a string */
5931 /* */
5932 /****************************************************************/
5934 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
5935 static WORD_DESC *
5936 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
5937 char *string;
5938 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
5940 int check_nullness, var_is_set, var_is_null, var_is_special;
5941 int want_substring, want_indir, want_patsub;
5942 char *name, *value, *temp, *temp1;
5943 WORD_DESC *tdesc, *ret;
5944 int t_index, sindex, c, tflag;
5945 intmax_t number;
5947 value = (char *)NULL;
5948 var_is_set = var_is_null = var_is_special = check_nullness = 0;
5949 want_substring = want_indir = want_patsub = 0;
5951 sindex = *indexp;
5952 t_index = ++sindex;
5953 /* ${#var} doesn't have any of the other parameter expansions on it. */
5954 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
5955 name = string_extract (string, &t_index, "}", EX_VARNAME);
5956 else
5957 name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
5959 ret = 0;
5960 tflag = 0;
5962 /* If the name really consists of a special variable, then make sure
5963 that we have the entire name. We don't allow indirect references
5964 to special variables except `#', `?', `@' and `*'. */
5965 if ((sindex == t_index &&
5966 (string[t_index] == '-' ||
5967 string[t_index] == '?' ||
5968 string[t_index] == '#')) ||
5969 (sindex == t_index - 1 && string[sindex] == '!' &&
5970 (string[t_index] == '#' ||
5971 string[t_index] == '?' ||
5972 string[t_index] == '@' ||
5973 string[t_index] == '*')))
5975 t_index++;
5976 free (name);
5977 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
5978 name = (char *)xmalloc (3 + (strlen (temp1)));
5979 *name = string[sindex];
5980 if (string[sindex] == '!')
5982 /* indirect reference of $#, $?, $@, or $* */
5983 name[1] = string[sindex + 1];
5984 strcpy (name + 2, temp1);
5986 else
5987 strcpy (name + 1, temp1);
5988 free (temp1);
5990 sindex = t_index;
5992 /* Find out what character ended the variable name. Then
5993 do the appropriate thing. */
5994 if (c = string[sindex])
5995 sindex++;
5997 /* If c is followed by one of the valid parameter expansion
5998 characters, move past it as normal. If not, assume that
5999 a substring specification is being given, and do not move
6000 past it. */
6001 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
6003 check_nullness++;
6004 if (c = string[sindex])
6005 sindex++;
6007 else if (c == ':' && string[sindex] != RBRACE)
6008 want_substring = 1;
6009 else if (c == '/' && string[sindex] != RBRACE)
6010 want_patsub = 1;
6012 /* Catch the valid and invalid brace expressions that made it through the
6013 tests above. */
6014 /* ${#-} is a valid expansion and means to take the length of $-.
6015 Similarly for ${#?} and ${##}... */
6016 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6017 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
6019 name = (char *)xrealloc (name, 3);
6020 name[1] = c;
6021 name[2] = '\0';
6022 c = string[sindex++];
6025 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
6026 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6027 member (c, "%:=+/") && string[sindex] == RBRACE)
6029 temp = (char *)NULL;
6030 goto bad_substitution;
6033 /* Indirect expansion begins with a `!'. A valid indirect expansion is
6034 either a variable name, one of the positional parameters or a special
6035 variable that expands to one of the positional parameters. */
6036 want_indir = *name == '!' &&
6037 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
6038 || VALID_INDIR_PARAM (name[1]));
6040 /* Determine the value of this variable. */
6042 /* Check for special variables, directly referenced. */
6043 if (SPECIAL_VAR (name, want_indir))
6044 var_is_special++;
6046 /* Check for special expansion things, like the length of a parameter */
6047 if (*name == '#' && name[1])
6049 /* If we are not pointing at the character just after the
6050 closing brace, then we haven't gotten all of the name.
6051 Since it begins with a special character, this is a bad
6052 substitution. Also check NAME for validity before trying
6053 to go on. */
6054 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
6056 temp = (char *)NULL;
6057 goto bad_substitution;
6060 number = parameter_brace_expand_length (name);
6061 free (name);
6063 *indexp = sindex;
6064 if (number < 0)
6065 return (&expand_wdesc_error);
6066 else
6068 ret = alloc_word_desc ();
6069 ret->word = itos (number);
6070 return ret;
6074 /* ${@} is identical to $@. */
6075 if (name[0] == '@' && name[1] == '\0')
6077 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6078 *quoted_dollar_atp = 1;
6080 if (contains_dollar_at)
6081 *contains_dollar_at = 1;
6084 /* Process ${!PREFIX*} expansion. */
6085 if (want_indir && string[sindex - 1] == RBRACE &&
6086 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
6087 legal_variable_starter ((unsigned char) name[1]))
6089 char **x;
6090 WORD_LIST *xlist;
6092 temp1 = savestring (name + 1);
6093 number = strlen (temp1);
6094 temp1[number - 1] = '\0';
6095 x = all_variables_matching_prefix (temp1);
6096 xlist = strvec_to_word_list (x, 0, 0);
6097 if (string[sindex - 2] == '*')
6098 temp = string_list_dollar_star (xlist);
6099 else
6101 temp = string_list_dollar_at (xlist, quoted);
6102 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6103 *quoted_dollar_atp = 1;
6104 if (contains_dollar_at)
6105 *contains_dollar_at = 1;
6107 free (x);
6108 free (xlist);
6109 free (temp1);
6110 *indexp = sindex;
6112 ret = alloc_word_desc ();
6113 ret->word = temp;
6114 return ret;
6117 #if defined (ARRAY_VARS)
6118 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
6119 if (want_indir && string[sindex - 1] == RBRACE &&
6120 string[sindex - 2] == ']' && valid_array_reference (name+1))
6122 char *x, *x1;
6124 temp1 = savestring (name + 1);
6125 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
6126 FREE (x);
6127 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
6129 temp = array_keys (temp1, quoted);
6130 if (x1[0] == '@')
6132 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6133 *quoted_dollar_atp = 1;
6134 if (contains_dollar_at)
6135 *contains_dollar_at = 1;
6138 free (temp1);
6139 *indexp = sindex;
6141 ret = alloc_word_desc ();
6142 ret->word = temp;
6143 return ret;
6146 free (temp1);
6148 #endif /* ARRAY_VARS */
6150 /* Make sure that NAME is valid before trying to go on. */
6151 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
6152 var_is_special) == 0)
6154 temp = (char *)NULL;
6155 goto bad_substitution;
6158 if (want_indir)
6159 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6160 else
6161 tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
6163 if (tdesc)
6165 temp = tdesc->word;
6166 tflag = tdesc->flags;
6167 dispose_word_desc (tdesc);
6169 else
6170 temp = (char *)0;
6172 #if defined (ARRAY_VARS)
6173 if (valid_array_reference (name))
6174 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6175 #endif
6177 var_is_set = temp != (char *)0;
6178 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6180 /* Get the rest of the stuff inside the braces. */
6181 if (c && c != RBRACE)
6183 /* Extract the contents of the ${ ... } expansion
6184 according to the Posix.2 rules. */
6185 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6186 if (string[sindex] == RBRACE)
6187 sindex++;
6188 else
6189 goto bad_substitution;
6191 else
6192 value = (char *)NULL;
6194 *indexp = sindex;
6196 /* If this is a substring spec, process it and add the result. */
6197 if (want_substring)
6199 temp1 = parameter_brace_substring (name, temp, value, quoted);
6200 FREE (name);
6201 FREE (value);
6202 FREE (temp);
6204 if (temp1 == &expand_param_error)
6205 return (&expand_wdesc_error);
6206 else if (temp1 == &expand_param_fatal)
6207 return (&expand_wdesc_fatal);
6209 ret = alloc_word_desc ();
6210 ret->word = temp1;
6211 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6212 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6213 return ret;
6215 else if (want_patsub)
6217 temp1 = parameter_brace_patsub (name, temp, value, quoted);
6218 FREE (name);
6219 FREE (value);
6220 FREE (temp);
6222 if (temp1 == &expand_param_error)
6223 return (&expand_wdesc_error);
6224 else if (temp1 == &expand_param_fatal)
6225 return (&expand_wdesc_fatal);
6227 ret = alloc_word_desc ();
6228 ret->word = temp1;
6229 return ret;
6232 /* Do the right thing based on which character ended the variable name. */
6233 switch (c)
6235 default:
6236 case '\0':
6237 bad_substitution:
6238 report_error (_("%s: bad substitution"), string ? string : "??");
6239 FREE (value);
6240 FREE (temp);
6241 free (name);
6242 return &expand_wdesc_error;
6244 case RBRACE:
6245 if (var_is_set == 0 && unbound_vars_is_error)
6247 err_unboundvar (name);
6248 FREE (value);
6249 FREE (temp);
6250 free (name);
6251 last_command_exit_value = EXECUTION_FAILURE;
6252 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6254 break;
6256 case '#': /* ${param#[#]pattern} */
6257 case '%': /* ${param%[%]pattern} */
6258 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6260 FREE (value);
6261 break;
6263 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6264 free (temp);
6265 free (value);
6266 temp = temp1;
6267 break;
6269 case '-':
6270 case '=':
6271 case '?':
6272 case '+':
6273 if (var_is_set && var_is_null == 0)
6275 /* If the operator is `+', we don't want the value of the named
6276 variable for anything, just the value of the right hand side. */
6278 if (c == '+')
6280 /* XXX -- if we're double-quoted and the named variable is "$@",
6281 we want to turn off any special handling of "$@" --
6282 we're not using it, so whatever is on the rhs applies. */
6283 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6284 *quoted_dollar_atp = 0;
6285 if (contains_dollar_at)
6286 *contains_dollar_at = 0;
6288 FREE (temp);
6289 if (value)
6291 ret = parameter_brace_expand_rhs (name, value, c,
6292 quoted,
6293 quoted_dollar_atp,
6294 contains_dollar_at);
6295 /* XXX - fix up later, esp. noting presence of
6296 W_HASQUOTEDNULL in ret->flags */
6297 free (value);
6299 else
6300 temp = (char *)NULL;
6302 else
6304 FREE (value);
6306 /* Otherwise do nothing; just use the value in TEMP. */
6308 else /* VAR not set or VAR is NULL. */
6310 FREE (temp);
6311 temp = (char *)NULL;
6312 if (c == '=' && var_is_special)
6314 report_error (_("$%s: cannot assign in this way"), name);
6315 free (name);
6316 free (value);
6317 return &expand_wdesc_error;
6319 else if (c == '?')
6321 parameter_brace_expand_error (name, value);
6322 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6324 else if (c != '+')
6326 /* XXX -- if we're double-quoted and the named variable is "$@",
6327 we want to turn off any special handling of "$@" --
6328 we're not using it, so whatever is on the rhs applies. */
6329 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6330 *quoted_dollar_atp = 0;
6331 if (contains_dollar_at)
6332 *contains_dollar_at = 0;
6334 ret = parameter_brace_expand_rhs (name, value, c, quoted,
6335 quoted_dollar_atp,
6336 contains_dollar_at);
6337 /* XXX - fix up later, esp. noting presence of
6338 W_HASQUOTEDNULL in tdesc->flags */
6340 free (value);
6343 break;
6345 free (name);
6347 if (ret == 0)
6349 ret = alloc_word_desc ();
6350 ret->flags = tflag;
6351 ret->word = temp;
6353 return (ret);
6356 /* Expand a single ${xxx} expansion. The braces are optional. When
6357 the braces are used, parameter_brace_expand() does the work,
6358 possibly calling param_expand recursively. */
6359 static WORD_DESC *
6360 param_expand (string, sindex, quoted, expanded_something,
6361 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6362 pflags)
6363 char *string;
6364 int *sindex, quoted, *expanded_something, *contains_dollar_at;
6365 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6367 char *temp, *temp1, uerror[3];
6368 int zindex, t_index, expok;
6369 unsigned char c;
6370 intmax_t number;
6371 SHELL_VAR *var;
6372 WORD_LIST *list;
6373 WORD_DESC *tdesc, *ret;
6374 int tflag;
6376 zindex = *sindex;
6377 c = string[++zindex];
6379 temp = (char *)NULL;
6380 ret = tdesc = (WORD_DESC *)NULL;
6381 tflag = 0;
6383 /* Do simple cases first. Switch on what follows '$'. */
6384 switch (c)
6386 /* $0 .. $9? */
6387 case '0':
6388 case '1':
6389 case '2':
6390 case '3':
6391 case '4':
6392 case '5':
6393 case '6':
6394 case '7':
6395 case '8':
6396 case '9':
6397 temp1 = dollar_vars[TODIGIT (c)];
6398 if (unbound_vars_is_error && temp1 == (char *)NULL)
6400 uerror[0] = '$';
6401 uerror[1] = c;
6402 uerror[2] = '\0';
6403 err_unboundvar (uerror);
6404 last_command_exit_value = EXECUTION_FAILURE;
6405 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6407 if (temp1)
6408 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6409 ? quote_string (temp1)
6410 : quote_escapes (temp1);
6411 else
6412 temp = (char *)NULL;
6414 break;
6416 /* $$ -- pid of the invoking shell. */
6417 case '$':
6418 temp = itos (dollar_dollar_pid);
6419 break;
6421 /* $# -- number of positional parameters. */
6422 case '#':
6423 temp = itos (number_of_args ());
6424 break;
6426 /* $? -- return value of the last synchronous command. */
6427 case '?':
6428 temp = itos (last_command_exit_value);
6429 break;
6431 /* $- -- flags supplied to the shell on invocation or by `set'. */
6432 case '-':
6433 temp = which_set_flags ();
6434 break;
6436 /* $! -- Pid of the last asynchronous command. */
6437 case '!':
6438 /* If no asynchronous pids have been created, expand to nothing.
6439 If `set -u' has been executed, and no async processes have
6440 been created, this is an expansion error. */
6441 if (last_asynchronous_pid == NO_PID)
6443 if (expanded_something)
6444 *expanded_something = 0;
6445 temp = (char *)NULL;
6446 if (unbound_vars_is_error)
6448 uerror[0] = '$';
6449 uerror[1] = c;
6450 uerror[2] = '\0';
6451 err_unboundvar (uerror);
6452 last_command_exit_value = EXECUTION_FAILURE;
6453 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6456 else
6457 temp = itos (last_asynchronous_pid);
6458 break;
6460 /* The only difference between this and $@ is when the arg is quoted. */
6461 case '*': /* `$*' */
6462 list = list_rest_of_args ();
6464 /* If there are no command-line arguments, this should just
6465 disappear if there are other characters in the expansion,
6466 even if it's quoted. */
6467 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
6468 temp = (char *)NULL;
6469 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6471 /* If we have "$*" we want to make a string of the positional
6472 parameters, separated by the first character of $IFS, and
6473 quote the whole string, including the separators. If IFS
6474 is unset, the parameters are separated by ' '; if $IFS is
6475 null, the parameters are concatenated. */
6476 temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
6477 temp1 = quote_string (temp);
6478 if (*temp == 0)
6479 tflag |= W_HASQUOTEDNULL;
6480 free (temp);
6481 temp = temp1;
6483 else
6485 /* We check whether or not we're eventually going to split $* here,
6486 for example when IFS is empty and we are processing the rhs of
6487 an assignment statement. In that case, we don't separate the
6488 arguments at all. Otherwise, if the $* is not quoted it is
6489 identical to $@ */
6490 #if 1
6491 # if defined (HANDLE_MULTIBYTE)
6492 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
6493 # else
6494 if (expand_no_split_dollar_star && ifs_firstc == 0)
6495 # endif
6496 temp = string_list_dollar_star (list);
6497 else
6498 temp = string_list_dollar_at (list, quoted);
6499 #else
6500 temp = string_list_dollar_at (list, quoted);
6501 #endif
6502 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
6503 *contains_dollar_at = 1;
6506 dispose_words (list);
6507 break;
6509 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
6510 means that we have to turn quoting off after we split into
6511 the individually quoted arguments so that the final split
6512 on the first character of $IFS is still done. */
6513 case '@': /* `$@' */
6514 list = list_rest_of_args ();
6516 /* We want to flag the fact that we saw this. We can't turn
6517 off quoting entirely, because other characters in the
6518 string might need it (consider "\"$@\""), but we need some
6519 way to signal that the final split on the first character
6520 of $IFS should be done, even though QUOTED is 1. */
6521 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6522 *quoted_dollar_at_p = 1;
6523 if (contains_dollar_at)
6524 *contains_dollar_at = 1;
6526 /* We want to separate the positional parameters with the first
6527 character of $IFS in case $IFS is something other than a space.
6528 We also want to make sure that splitting is done no matter what --
6529 according to POSIX.2, this expands to a list of the positional
6530 parameters no matter what IFS is set to. */
6531 temp = string_list_dollar_at (list, quoted);
6533 dispose_words (list);
6534 break;
6536 case LBRACE:
6537 tdesc = parameter_brace_expand (string, &zindex, quoted,
6538 quoted_dollar_at_p,
6539 contains_dollar_at);
6541 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
6542 return (tdesc);
6543 temp = tdesc ? tdesc->word : (char *)0;
6545 /* XXX */
6546 /* Quoted nulls should be removed if there is anything else
6547 in the string. */
6548 /* Note that we saw the quoted null so we can add one back at
6549 the end of this function if there are no other characters
6550 in the string, discard TEMP, and go on. The exception to
6551 this is when we have "${@}" and $1 is '', since $@ needs
6552 special handling. */
6553 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
6555 if (had_quoted_null_p)
6556 *had_quoted_null_p = 1;
6557 if (*quoted_dollar_at_p == 0)
6559 free (temp);
6560 tdesc->word = temp = (char *)NULL;
6565 ret = tdesc;
6566 goto return0;
6568 /* Do command or arithmetic substitution. */
6569 case LPAREN:
6570 /* We have to extract the contents of this paren substitution. */
6571 t_index = zindex + 1;
6572 temp = extract_command_subst (string, &t_index);
6573 zindex = t_index;
6575 /* For Posix.2-style `$(( ))' arithmetic substitution,
6576 extract the expression and pass it to the evaluator. */
6577 if (temp && *temp == LPAREN)
6579 char *temp2;
6580 temp1 = temp + 1;
6581 temp2 = savestring (temp1);
6582 t_index = strlen (temp2) - 1;
6584 if (temp2[t_index] != RPAREN)
6586 free (temp2);
6587 goto comsub;
6590 /* Cut off ending `)' */
6591 temp2[t_index] = '\0';
6593 if (chk_arithsub (temp2, t_index) == 0)
6595 free (temp2);
6596 goto comsub;
6599 /* Expand variables found inside the expression. */
6600 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
6601 free (temp2);
6603 arithsub:
6604 /* No error messages. */
6605 this_command_name = (char *)NULL;
6606 number = evalexp (temp1, &expok);
6607 free (temp);
6608 free (temp1);
6609 if (expok == 0)
6611 if (interactive_shell == 0 && posixly_correct)
6613 last_command_exit_value = EXECUTION_FAILURE;
6614 return (&expand_wdesc_fatal);
6616 else
6617 return (&expand_wdesc_error);
6619 temp = itos (number);
6620 break;
6623 comsub:
6624 if (pflags & PF_NOCOMSUB)
6625 /* we need zindex+1 because string[zindex] == RPAREN */
6626 temp1 = substring (string, *sindex, zindex+1);
6627 else
6628 temp1 = command_substitute (temp, quoted);
6629 FREE (temp);
6630 temp = temp1;
6631 break;
6633 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
6634 away in a future bash release. */
6635 case '[':
6636 /* Extract the contents of this arithmetic substitution. */
6637 t_index = zindex + 1;
6638 temp = extract_arithmetic_subst (string, &t_index);
6639 zindex = t_index;
6641 /* Do initial variable expansion. */
6642 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
6644 goto arithsub;
6646 default:
6647 /* Find the variable in VARIABLE_LIST. */
6648 temp = (char *)NULL;
6650 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
6652 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
6654 /* If this isn't a variable name, then just output the `$'. */
6655 if (temp1 == 0 || *temp1 == '\0')
6657 FREE (temp1);
6658 temp = (char *)xmalloc (2);
6659 temp[0] = '$';
6660 temp[1] = '\0';
6661 if (expanded_something)
6662 *expanded_something = 0;
6663 goto return0;
6666 /* If the variable exists, return its value cell. */
6667 var = find_variable (temp1);
6669 if (var && invisible_p (var) == 0 && var_isset (var))
6671 #if defined (ARRAY_VARS)
6672 if (array_p (var))
6674 temp = array_reference (array_cell (var), 0);
6675 if (temp)
6676 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6677 ? quote_string (temp)
6678 : quote_escapes (temp);
6679 else if (unbound_vars_is_error)
6680 goto unbound_variable;
6682 else
6683 #endif
6685 temp = value_cell (var);
6687 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6688 ? quote_string (temp)
6689 : quote_escapes (temp);
6692 free (temp1);
6694 goto return0;
6697 temp = (char *)NULL;
6699 unbound_variable:
6700 if (unbound_vars_is_error)
6701 err_unboundvar (temp1);
6702 else
6704 free (temp1);
6705 goto return0;
6708 free (temp1);
6709 last_command_exit_value = EXECUTION_FAILURE;
6710 return ((unbound_vars_is_error && interactive_shell == 0)
6711 ? &expand_wdesc_fatal
6712 : &expand_wdesc_error);
6715 if (string[zindex])
6716 zindex++;
6718 return0:
6719 *sindex = zindex;
6721 if (ret == 0)
6723 ret = alloc_word_desc ();
6724 ret->flags = tflag; /* XXX */
6725 ret->word = temp;
6727 return ret;
6730 /* Make a word list which is the result of parameter and variable
6731 expansion, command substitution, arithmetic substitution, and
6732 quote removal of WORD. Return a pointer to a WORD_LIST which is
6733 the result of the expansion. If WORD contains a null word, the
6734 word list returned is also null.
6736 QUOTED contains flag values defined in shell.h.
6738 ISEXP is used to tell expand_word_internal that the word should be
6739 treated as the result of an expansion. This has implications for
6740 how IFS characters in the word are treated.
6742 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
6743 they point to an integer value which receives information about expansion.
6744 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
6745 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
6746 else zero.
6748 This only does word splitting in the case of $@ expansion. In that
6749 case, we split on ' '. */
6751 /* Values for the local variable quoted_state. */
6752 #define UNQUOTED 0
6753 #define PARTIALLY_QUOTED 1
6754 #define WHOLLY_QUOTED 2
6756 static WORD_LIST *
6757 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
6758 WORD_DESC *word;
6759 int quoted, isexp;
6760 int *contains_dollar_at;
6761 int *expanded_something;
6763 WORD_LIST *list;
6764 WORD_DESC *tword;
6766 /* The intermediate string that we build while expanding. */
6767 char *istring;
6769 /* The current size of the above object. */
6770 int istring_size;
6772 /* Index into ISTRING. */
6773 int istring_index;
6775 /* Temporary string storage. */
6776 char *temp, *temp1;
6778 /* The text of WORD. */
6779 register char *string;
6781 /* The size of STRING. */
6782 size_t string_size;
6784 /* The index into STRING. */
6785 int sindex;
6787 /* This gets 1 if we see a $@ while quoted. */
6788 int quoted_dollar_at;
6790 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
6791 whether WORD contains no quoting characters, a partially quoted
6792 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
6793 int quoted_state;
6795 /* State flags */
6796 int had_quoted_null;
6797 int has_dollar_at;
6798 int tflag;
6800 int assignoff; /* If assignment, offset of `=' */
6802 register unsigned char c; /* Current character. */
6803 int t_index; /* For calls to string_extract_xxx. */
6805 char twochars[2];
6807 DECLARE_MBSTATE;
6809 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
6810 istring[istring_index = 0] = '\0';
6811 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
6812 quoted_state = UNQUOTED;
6814 string = word->word;
6815 if (string == 0)
6816 goto finished_with_string;
6817 /* Don't need the string length for the SADD... and COPY_ macros unless
6818 multibyte characters are possible. */
6819 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
6821 if (contains_dollar_at)
6822 *contains_dollar_at = 0;
6824 assignoff = -1;
6826 /* Begin the expansion. */
6828 for (sindex = 0; ;)
6830 c = string[sindex];
6832 /* Case on toplevel character. */
6833 switch (c)
6835 case '\0':
6836 goto finished_with_string;
6838 case CTLESC:
6839 sindex++;
6840 #if HANDLE_MULTIBYTE
6841 if (MB_CUR_MAX > 1 && string[sindex])
6843 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
6845 else
6846 #endif
6848 temp = (char *)xmalloc (3);
6849 temp[0] = CTLESC;
6850 temp[1] = c = string[sindex];
6851 temp[2] = '\0';
6854 dollar_add_string:
6855 if (string[sindex])
6856 sindex++;
6858 add_string:
6859 if (temp)
6861 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
6862 temp = (char *)0;
6865 break;
6867 #if defined (PROCESS_SUBSTITUTION)
6868 /* Process substitution. */
6869 case '<':
6870 case '>':
6872 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
6874 sindex--; /* add_character: label increments sindex */
6875 goto add_character;
6877 else
6878 t_index = sindex + 1; /* skip past both '<' and LPAREN */
6880 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
6881 sindex = t_index;
6883 /* If the process substitution specification is `<()', we want to
6884 open the pipe for writing in the child and produce output; if
6885 it is `>()', we want to open the pipe for reading in the child
6886 and consume input. */
6887 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
6889 FREE (temp1);
6891 goto dollar_add_string;
6893 #endif /* PROCESS_SUBSTITUTION */
6895 case '=':
6896 /* Posix.2 section 3.6.1 says that tildes following `=' in words
6897 which are not assignment statements are not expanded. If the
6898 shell isn't in posix mode, though, we perform tilde expansion
6899 on `likely candidate' unquoted assignment statements (flags
6900 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
6901 contains an unquoted :~ or =~. Something to think about: we
6902 now have a flag that says to perform tilde expansion on arguments
6903 to `assignment builtins' like declare and export that look like
6904 assignment statements. We now do tilde expansion on such words
6905 even in POSIX mode. */
6906 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
6907 goto add_character;
6908 /* If we're not in posix mode or forcing assignment-statement tilde
6909 expansion, note where the `=' appears in the word and prepare to
6910 do tilde expansion following the first `='. */
6911 if ((word->flags & W_ASSIGNMENT) &&
6912 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
6913 assignoff == -1 && sindex > 0)
6914 assignoff = sindex;
6915 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
6916 word->flags |= W_ITILDE;
6917 #if 0
6918 else if ((word->flags & W_ASSIGNMENT) &&
6919 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
6920 string[sindex+1] == '~')
6921 word->flags |= W_ITILDE;
6922 #endif
6923 goto add_character;
6925 case ':':
6926 if (word->flags & W_NOTILDE)
6927 goto add_character;
6929 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
6930 string[sindex+1] == '~')
6931 word->flags |= W_ITILDE;
6932 goto add_character;
6934 case '~':
6935 /* If the word isn't supposed to be tilde expanded, or we're not
6936 at the start of a word or after an unquoted : or = in an
6937 assignment statement, we don't do tilde expansion. */
6938 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
6939 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
6940 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6942 word->flags &= ~W_ITILDE;
6943 goto add_character;
6946 if (word->flags & W_ASSIGNRHS)
6947 tflag = 2;
6948 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
6949 tflag = 1;
6950 else
6951 tflag = 0;
6953 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
6955 word->flags &= ~W_ITILDE;
6957 if (temp && *temp && t_index > 0)
6959 temp1 = bash_tilde_expand (temp, tflag);
6960 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
6962 FREE (temp);
6963 FREE (temp1);
6964 goto add_character; /* tilde expansion failed */
6966 free (temp);
6967 temp = temp1;
6968 sindex += t_index;
6969 goto add_string;
6971 else
6973 FREE (temp);
6974 goto add_character;
6977 case '$':
6978 if (expanded_something)
6979 *expanded_something = 1;
6981 has_dollar_at = 0;
6982 tword = param_expand (string, &sindex, quoted, expanded_something,
6983 &has_dollar_at, &quoted_dollar_at,
6984 &had_quoted_null,
6985 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
6987 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
6989 free (string);
6990 free (istring);
6991 return ((tword == &expand_wdesc_error) ? &expand_word_error
6992 : &expand_word_fatal);
6994 if (contains_dollar_at && has_dollar_at)
6995 *contains_dollar_at = 1;
6997 if (tword && (tword->flags & W_HASQUOTEDNULL))
6998 had_quoted_null = 1;
7000 temp = tword->word;
7001 dispose_word_desc (tword);
7003 goto add_string;
7004 break;
7006 case '`': /* Backquoted command substitution. */
7008 t_index = sindex++;
7010 temp = string_extract (string, &sindex, "`", EX_REQMATCH);
7011 /* The test of sindex against t_index is to allow bare instances of
7012 ` to pass through, for backwards compatibility. */
7013 if (temp == &extract_string_error || temp == &extract_string_fatal)
7015 if (sindex - 1 == t_index)
7017 sindex = t_index;
7018 goto add_character;
7020 report_error ("bad substitution: no closing \"`\" in %s", string+t_index);
7021 free (string);
7022 free (istring);
7023 return ((temp == &extract_string_error) ? &expand_word_error
7024 : &expand_word_fatal);
7027 if (expanded_something)
7028 *expanded_something = 1;
7030 if (word->flags & W_NOCOMSUB)
7031 /* sindex + 1 because string[sindex] == '`' */
7032 temp1 = substring (string, t_index, sindex + 1);
7033 else
7035 de_backslash (temp);
7036 temp1 = command_substitute (temp, quoted);
7038 FREE (temp);
7039 temp = temp1;
7040 goto dollar_add_string;
7043 case '\\':
7044 if (string[sindex + 1] == '\n')
7046 sindex += 2;
7047 continue;
7050 c = string[++sindex];
7052 if (quoted & Q_HERE_DOCUMENT)
7053 tflag = CBSHDOC;
7054 else if (quoted & Q_DOUBLE_QUOTES)
7055 tflag = CBSDQUOTE;
7056 else
7057 tflag = 0;
7059 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7061 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7063 else if (c == 0)
7065 c = CTLNUL;
7066 sindex--; /* add_character: label increments sindex */
7067 goto add_character;
7069 else
7071 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7074 sindex++;
7075 add_twochars:
7076 /* BEFORE jumping here, we need to increment sindex if appropriate */
7077 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7078 DEFAULT_ARRAY_SIZE);
7079 istring[istring_index++] = twochars[0];
7080 istring[istring_index++] = twochars[1];
7081 istring[istring_index] = '\0';
7083 break;
7085 case '"':
7086 #if 0
7087 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7088 #else
7089 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7090 #endif
7091 goto add_character;
7093 t_index = ++sindex;
7094 temp = string_extract_double_quoted (string, &sindex, 0);
7096 /* If the quotes surrounded the entire string, then the
7097 whole word was quoted. */
7098 quoted_state = (t_index == 1 && string[sindex] == '\0')
7099 ? WHOLLY_QUOTED
7100 : PARTIALLY_QUOTED;
7102 if (temp && *temp)
7104 tword = alloc_word_desc ();
7105 tword->word = temp;
7107 temp = (char *)NULL;
7109 has_dollar_at = 0;
7110 /* Need to get W_HASQUOTEDNULL flag through this function. */
7111 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7113 if (list == &expand_word_error || list == &expand_word_fatal)
7115 free (istring);
7116 free (string);
7117 /* expand_word_internal has already freed temp_word->word
7118 for us because of the way it prints error messages. */
7119 tword->word = (char *)NULL;
7120 dispose_word (tword);
7121 return list;
7124 dispose_word (tword);
7126 /* "$@" (a double-quoted dollar-at) expands into nothing,
7127 not even a NULL word, when there are no positional
7128 parameters. */
7129 if (list == 0 && has_dollar_at)
7131 quoted_dollar_at++;
7132 break;
7135 /* If we get "$@", we know we have expanded something, so we
7136 need to remember it for the final split on $IFS. This is
7137 a special case; it's the only case where a quoted string
7138 can expand into more than one word. It's going to come back
7139 from the above call to expand_word_internal as a list with
7140 a single word, in which all characters are quoted and
7141 separated by blanks. What we want to do is to turn it back
7142 into a list for the next piece of code. */
7143 if (list)
7144 dequote_list (list);
7146 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7147 had_quoted_null = 1;
7149 if (has_dollar_at)
7151 quoted_dollar_at++;
7152 if (contains_dollar_at)
7153 *contains_dollar_at = 1;
7154 if (expanded_something)
7155 *expanded_something = 1;
7158 else
7160 /* What we have is "". This is a minor optimization. */
7161 FREE (temp);
7162 list = (WORD_LIST *)NULL;
7165 /* The code above *might* return a list (consider the case of "$@",
7166 where it returns "$1", "$2", etc.). We can't throw away the
7167 rest of the list, and we have to make sure each word gets added
7168 as quoted. We test on tresult->next: if it is non-NULL, we
7169 quote the whole list, save it to a string with string_list, and
7170 add that string. We don't need to quote the results of this
7171 (and it would be wrong, since that would quote the separators
7172 as well), so we go directly to add_string. */
7173 if (list)
7175 if (list->next)
7177 /* Testing quoted_dollar_at makes sure that "$@" is
7178 split correctly when $IFS does not contain a space. */
7179 temp = quoted_dollar_at
7180 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7181 : string_list (quote_list (list));
7182 dispose_words (list);
7183 goto add_string;
7185 else
7187 temp = savestring (list->word->word);
7188 tflag = list->word->flags;
7189 dispose_words (list);
7191 /* If the string is not a quoted null string, we want
7192 to remove any embedded unquoted CTLNUL characters.
7193 We do not want to turn quoted null strings back into
7194 the empty string, though. We do this because we
7195 want to remove any quoted nulls from expansions that
7196 contain other characters. For example, if we have
7197 x"$*"y or "x$*y" and there are no positional parameters,
7198 the $* should expand into nothing. */
7199 /* We use the W_HASQUOTEDNULL flag to differentiate the
7200 cases: a quoted null character as above and when
7201 CTLNUL is contained in the (non-null) expansion
7202 of some variable. We use the had_quoted_null flag to
7203 pass the value through this function to its caller. */
7204 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7205 remove_quoted_nulls (temp); /* XXX */
7208 else
7209 temp = (char *)NULL;
7211 /* We do not want to add quoted nulls to strings that are only
7212 partially quoted; we can throw them away. */
7213 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7214 continue;
7216 add_quoted_string:
7218 if (temp)
7220 temp1 = temp;
7221 temp = quote_string (temp);
7222 free (temp1);
7223 goto add_string;
7225 else
7227 /* Add NULL arg. */
7228 c = CTLNUL;
7229 sindex--; /* add_character: label increments sindex */
7230 goto add_character;
7233 /* break; */
7235 case '\'':
7236 #if 0
7237 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7238 #else
7239 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7240 #endif
7241 goto add_character;
7243 t_index = ++sindex;
7244 temp = string_extract_single_quoted (string, &sindex);
7246 /* If the entire STRING was surrounded by single quotes,
7247 then the string is wholly quoted. */
7248 quoted_state = (t_index == 1 && string[sindex] == '\0')
7249 ? WHOLLY_QUOTED
7250 : PARTIALLY_QUOTED;
7252 /* If all we had was '', it is a null expansion. */
7253 if (*temp == '\0')
7255 free (temp);
7256 temp = (char *)NULL;
7258 else
7259 remove_quoted_escapes (temp); /* ??? */
7261 /* We do not want to add quoted nulls to strings that are only
7262 partially quoted; such nulls are discarded. */
7263 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7264 continue;
7266 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7267 if (temp == 0)
7269 c = CTLNUL;
7270 sindex--; /* add_character: label increments sindex */
7271 goto add_character;
7273 else
7274 goto add_quoted_string;
7276 /* break; */
7278 default:
7279 /* This is the fix for " $@ " */
7280 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7282 if (string[sindex]) /* from old goto dollar_add_string */
7283 sindex++;
7284 if (c == 0)
7286 c = CTLNUL;
7287 goto add_character;
7289 else
7291 #if HANDLE_MULTIBYTE
7292 if (MB_CUR_MAX > 1)
7293 sindex--;
7295 if (MB_CUR_MAX > 1)
7297 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7299 else
7300 #endif
7302 twochars[0] = CTLESC;
7303 twochars[1] = c;
7304 goto add_twochars;
7309 SADD_MBCHAR (temp, string, sindex, string_size);
7311 add_character:
7312 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7313 DEFAULT_ARRAY_SIZE);
7314 istring[istring_index++] = c;
7315 istring[istring_index] = '\0';
7317 /* Next character. */
7318 sindex++;
7322 finished_with_string:
7323 /* OK, we're ready to return. If we have a quoted string, and
7324 quoted_dollar_at is not set, we do no splitting at all; otherwise
7325 we split on ' '. The routines that call this will handle what to
7326 do if nothing has been expanded. */
7328 /* Partially and wholly quoted strings which expand to the empty
7329 string are retained as an empty arguments. Unquoted strings
7330 which expand to the empty string are discarded. The single
7331 exception is the case of expanding "$@" when there are no
7332 positional parameters. In that case, we discard the expansion. */
7334 /* Because of how the code that handles "" and '' in partially
7335 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7336 if we saw quoting characters, but the expansion was empty.
7337 "" and '' are tossed away before we get to this point when
7338 processing partially quoted strings. This makes "" and $xxx""
7339 equivalent when xxx is unset. We also look to see whether we
7340 saw a quoted null from a ${} expansion and add one back if we
7341 need to. */
7343 /* If we expand to nothing and there were no single or double quotes
7344 in the word, we throw it away. Otherwise, we return a NULL word.
7345 The single exception is for $@ surrounded by double quotes when
7346 there are no positional parameters. In that case, we also throw
7347 the word away. */
7349 if (*istring == '\0')
7351 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7353 istring[0] = CTLNUL;
7354 istring[1] = '\0';
7355 tword = make_bare_word (istring);
7356 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7357 list = make_word_list (tword, (WORD_LIST *)NULL);
7358 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7359 tword->flags |= W_QUOTED;
7361 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7362 and a double-quoted "$@" appears anywhere in it, then the entire
7363 word is removed. */
7364 else if (quoted_state == UNQUOTED || quoted_dollar_at)
7365 list = (WORD_LIST *)NULL;
7366 #if 0
7367 else
7369 tword = make_bare_word (istring);
7370 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7371 tword->flags |= W_QUOTED;
7372 list = make_word_list (tword, (WORD_LIST *)NULL);
7374 #else
7375 else
7376 list = (WORD_LIST *)NULL;
7377 #endif
7379 else if (word->flags & W_NOSPLIT)
7381 tword = make_bare_word (istring);
7382 if (word->flags & W_ASSIGNMENT)
7383 tword->flags |= W_ASSIGNMENT; /* XXX */
7384 if (word->flags & W_COMPASSIGN)
7385 tword->flags |= W_COMPASSIGN; /* XXX */
7386 if (word->flags & W_NOGLOB)
7387 tword->flags |= W_NOGLOB; /* XXX */
7388 if (word->flags & W_NOEXPAND)
7389 tword->flags |= W_NOEXPAND; /* XXX */
7390 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7391 tword->flags |= W_QUOTED;
7392 if (had_quoted_null)
7393 tword->flags |= W_HASQUOTEDNULL;
7394 list = make_word_list (tword, (WORD_LIST *)NULL);
7396 else
7398 char *ifs_chars;
7400 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
7402 /* If we have $@, we need to split the results no matter what. If
7403 IFS is unset or NULL, string_list_dollar_at has separated the
7404 positional parameters with a space, so we split on space (we have
7405 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
7406 string_list_dollar_at has separated the positional parameters
7407 with the first character of $IFS, so we split on $IFS. */
7408 if (has_dollar_at && ifs_chars)
7409 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
7410 else
7412 tword = make_bare_word (istring);
7413 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
7414 tword->flags |= W_QUOTED;
7415 if (word->flags & W_ASSIGNMENT)
7416 tword->flags |= W_ASSIGNMENT;
7417 if (word->flags & W_COMPASSIGN)
7418 tword->flags |= W_COMPASSIGN;
7419 if (word->flags & W_NOGLOB)
7420 tword->flags |= W_NOGLOB;
7421 if (word->flags & W_NOEXPAND)
7422 tword->flags |= W_NOEXPAND;
7423 if (had_quoted_null)
7424 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7425 list = make_word_list (tword, (WORD_LIST *)NULL);
7429 free (istring);
7430 return (list);
7433 /* **************************************************************** */
7434 /* */
7435 /* Functions for Quote Removal */
7436 /* */
7437 /* **************************************************************** */
7439 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
7440 backslash quoting rules for within double quotes or a here document. */
7441 char *
7442 string_quote_removal (string, quoted)
7443 char *string;
7444 int quoted;
7446 size_t slen;
7447 char *r, *result_string, *temp, *send;
7448 int sindex, tindex, dquote;
7449 unsigned char c;
7450 DECLARE_MBSTATE;
7452 /* The result can be no longer than the original string. */
7453 slen = strlen (string);
7454 send = string + slen;
7456 r = result_string = (char *)xmalloc (slen + 1);
7458 for (dquote = sindex = 0; c = string[sindex];)
7460 switch (c)
7462 case '\\':
7463 c = string[++sindex];
7464 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
7465 *r++ = '\\';
7466 /* FALLTHROUGH */
7468 default:
7469 SCOPY_CHAR_M (r, string, send, sindex);
7470 break;
7472 case '\'':
7473 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
7475 *r++ = c;
7476 sindex++;
7477 break;
7479 tindex = sindex + 1;
7480 temp = string_extract_single_quoted (string, &tindex);
7481 if (temp)
7483 strcpy (r, temp);
7484 r += strlen (r);
7485 free (temp);
7487 sindex = tindex;
7488 break;
7490 case '"':
7491 dquote = 1 - dquote;
7492 sindex++;
7493 break;
7496 *r = '\0';
7497 return (result_string);
7500 #if 0
7501 /* UNUSED */
7502 /* Perform quote removal on word WORD. This allocates and returns a new
7503 WORD_DESC *. */
7504 WORD_DESC *
7505 word_quote_removal (word, quoted)
7506 WORD_DESC *word;
7507 int quoted;
7509 WORD_DESC *w;
7510 char *t;
7512 t = string_quote_removal (word->word, quoted);
7513 w = alloc_word_desc ();
7514 w->word = t ? t : savestring ("");
7515 return (w);
7518 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
7519 the members of the list are treated as if they are surrounded by
7520 double quotes. Return a new list, or NULL if LIST is NULL. */
7521 WORD_LIST *
7522 word_list_quote_removal (list, quoted)
7523 WORD_LIST *list;
7524 int quoted;
7526 WORD_LIST *result, *t, *tresult, *e;
7528 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7530 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
7531 #if 0
7532 result = (WORD_LIST *) list_append (result, tresult);
7533 #else
7534 if (result == 0)
7535 result = e = tresult;
7536 else
7538 e->next = tresult;
7539 while (e->next)
7540 e = e->next;
7542 #endif
7544 return (result);
7546 #endif
7548 /*******************************************
7550 * Functions to perform word splitting *
7552 *******************************************/
7554 void
7555 setifs (v)
7556 SHELL_VAR *v;
7558 char *t;
7559 unsigned char uc;
7561 ifs_var = v;
7562 #if 0
7563 ifs_value = v ? value_cell (v) : " \t\n";
7564 #else
7565 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
7566 #endif
7568 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
7569 handle multibyte chars in IFS */
7570 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
7571 for (t = ifs_value ; t && *t; t++)
7573 uc = *t;
7574 ifs_cmap[uc] = 1;
7577 #if defined (HANDLE_MULTIBYTE)
7578 if (ifs_value == 0)
7580 ifs_firstc[0] = '\0';
7581 ifs_firstc_len = 1;
7583 else
7585 size_t ifs_len;
7586 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
7587 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
7588 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
7590 ifs_firstc[0] = ifs_value[0];
7591 ifs_firstc[1] = '\0';
7592 ifs_firstc_len = 1;
7594 else
7595 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
7597 #else
7598 ifs_firstc = ifs_value ? *ifs_value : 0;
7599 #endif
7602 char *
7603 getifs ()
7605 return ifs_value;
7608 /* This splits a single word into a WORD LIST on $IFS, but only if the word
7609 is not quoted. list_string () performs quote removal for us, even if we
7610 don't do any splitting. */
7611 WORD_LIST *
7612 word_split (w, ifs_chars)
7613 WORD_DESC *w;
7614 char *ifs_chars;
7616 WORD_LIST *result;
7618 if (w)
7620 char *xifs;
7622 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
7623 result = list_string (w->word, xifs, w->flags & W_QUOTED);
7625 else
7626 result = (WORD_LIST *)NULL;
7628 return (result);
7631 /* Perform word splitting on LIST and return the RESULT. It is possible
7632 to return (WORD_LIST *)NULL. */
7633 static WORD_LIST *
7634 word_list_split (list)
7635 WORD_LIST *list;
7637 WORD_LIST *result, *t, *tresult, *e;
7639 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7641 tresult = word_split (t->word, ifs_value);
7642 if (result == 0)
7643 result = e = tresult;
7644 else
7646 e->next = tresult;
7647 while (e->next)
7648 e = e->next;
7651 return (result);
7654 /**************************************************
7656 * Functions to expand an entire WORD_LIST *
7658 **************************************************/
7660 /* Do any word-expansion-specific cleanup and jump to top_level */
7661 static void
7662 exp_jump_to_top_level (v)
7663 int v;
7665 /* Cleanup code goes here. */
7666 expand_no_split_dollar_star = 0; /* XXX */
7667 expanding_redir = 0;
7669 top_level_cleanup (); /* from sig.c */
7671 jump_to_top_level (v);
7674 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
7675 ELIST, and set ELIST to the new list. */
7676 #define PREPEND_LIST(nlist, elist) \
7677 do { nlist->next = elist; elist = nlist; } while (0)
7679 /* Separate out any initial variable assignments from TLIST. If set -k has
7680 been executed, remove all assignment statements from TLIST. Initial
7681 variable assignments and other environment assignments are placed
7682 on SUBST_ASSIGN_VARLIST. */
7683 static WORD_LIST *
7684 separate_out_assignments (tlist)
7685 WORD_LIST *tlist;
7687 register WORD_LIST *vp, *lp;
7689 if (!tlist)
7690 return ((WORD_LIST *)NULL);
7692 if (subst_assign_varlist)
7693 dispose_words (subst_assign_varlist); /* Clean up after previous error */
7695 subst_assign_varlist = (WORD_LIST *)NULL;
7696 vp = lp = tlist;
7698 /* Separate out variable assignments at the start of the command.
7699 Loop invariant: vp->next == lp
7700 Loop postcondition:
7701 lp = list of words left after assignment statements skipped
7702 tlist = original list of words
7704 while (lp && (lp->word->flags & W_ASSIGNMENT))
7706 vp = lp;
7707 lp = lp->next;
7710 /* If lp != tlist, we have some initial assignment statements.
7711 We make SUBST_ASSIGN_VARLIST point to the list of assignment
7712 words and TLIST point to the remaining words. */
7713 if (lp != tlist)
7715 subst_assign_varlist = tlist;
7716 /* ASSERT(vp->next == lp); */
7717 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
7718 tlist = lp; /* remainder of word list */
7721 /* vp == end of variable list */
7722 /* tlist == remainder of original word list without variable assignments */
7723 if (!tlist)
7724 /* All the words in tlist were assignment statements */
7725 return ((WORD_LIST *)NULL);
7727 /* ASSERT(tlist != NULL); */
7728 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
7730 /* If the -k option is in effect, we need to go through the remaining
7731 words, separate out the assignment words, and place them on
7732 SUBST_ASSIGN_VARLIST. */
7733 if (place_keywords_in_env)
7735 WORD_LIST *tp; /* tp == running pointer into tlist */
7737 tp = tlist;
7738 lp = tlist->next;
7740 /* Loop Invariant: tp->next == lp */
7741 /* Loop postcondition: tlist == word list without assignment statements */
7742 while (lp)
7744 if (lp->word->flags & W_ASSIGNMENT)
7746 /* Found an assignment statement, add this word to end of
7747 subst_assign_varlist (vp). */
7748 if (!subst_assign_varlist)
7749 subst_assign_varlist = vp = lp;
7750 else
7752 vp->next = lp;
7753 vp = lp;
7756 /* Remove the word pointed to by LP from TLIST. */
7757 tp->next = lp->next;
7758 /* ASSERT(vp == lp); */
7759 lp->next = (WORD_LIST *)NULL;
7760 lp = tp->next;
7762 else
7764 tp = lp;
7765 lp = lp->next;
7769 return (tlist);
7772 #define WEXP_VARASSIGN 0x001
7773 #define WEXP_BRACEEXP 0x002
7774 #define WEXP_TILDEEXP 0x004
7775 #define WEXP_PARAMEXP 0x008
7776 #define WEXP_PATHEXP 0x010
7778 /* All of the expansions, including variable assignments at the start of
7779 the list. */
7780 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
7782 /* All of the expansions except variable assignments at the start of
7783 the list. */
7784 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
7786 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
7787 expansion, command substitution, arithmetic expansion, word splitting, and
7788 quote removal. */
7789 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
7791 /* Take the list of words in LIST and do the various substitutions. Return
7792 a new list of words which is the expanded list, and without things like
7793 variable assignments. */
7795 WORD_LIST *
7796 expand_words (list)
7797 WORD_LIST *list;
7799 return (expand_word_list_internal (list, WEXP_ALL));
7802 /* Same as expand_words (), but doesn't hack variable or environment
7803 variables. */
7804 WORD_LIST *
7805 expand_words_no_vars (list)
7806 WORD_LIST *list;
7808 return (expand_word_list_internal (list, WEXP_NOVARS));
7811 WORD_LIST *
7812 expand_words_shellexp (list)
7813 WORD_LIST *list;
7815 return (expand_word_list_internal (list, WEXP_SHELLEXP));
7818 static WORD_LIST *
7819 glob_expand_word_list (tlist, eflags)
7820 WORD_LIST *tlist;
7821 int eflags;
7823 char **glob_array, *temp_string;
7824 register int glob_index;
7825 WORD_LIST *glob_list, *output_list, *disposables, *next;
7826 WORD_DESC *tword;
7828 output_list = disposables = (WORD_LIST *)NULL;
7829 glob_array = (char **)NULL;
7830 while (tlist)
7832 /* For each word, either globbing is attempted or the word is
7833 added to orig_list. If globbing succeeds, the results are
7834 added to orig_list and the word (tlist) is added to the list
7835 of disposable words. If globbing fails and failed glob
7836 expansions are left unchanged (the shell default), the
7837 original word is added to orig_list. If globbing fails and
7838 failed glob expansions are removed, the original word is
7839 added to the list of disposable words. orig_list ends up
7840 in reverse order and requires a call to REVERSE_LIST to
7841 be set right. After all words are examined, the disposable
7842 words are freed. */
7843 next = tlist->next;
7845 /* If the word isn't an assignment and contains an unquoted
7846 pattern matching character, then glob it. */
7847 if ((tlist->word->flags & W_NOGLOB) == 0 &&
7848 unquoted_glob_pattern_p (tlist->word->word))
7850 glob_array = shell_glob_filename (tlist->word->word);
7852 /* Handle error cases.
7853 I don't think we should report errors like "No such file
7854 or directory". However, I would like to report errors
7855 like "Read failed". */
7857 if (glob_array == 0 || GLOB_FAILED (glob_array))
7859 glob_array = (char **)xmalloc (sizeof (char *));
7860 glob_array[0] = (char *)NULL;
7863 /* Dequote the current word in case we have to use it. */
7864 if (glob_array[0] == NULL)
7866 temp_string = dequote_string (tlist->word->word);
7867 free (tlist->word->word);
7868 tlist->word->word = temp_string;
7871 /* Make the array into a word list. */
7872 glob_list = (WORD_LIST *)NULL;
7873 for (glob_index = 0; glob_array[glob_index]; glob_index++)
7875 tword = make_bare_word (glob_array[glob_index]);
7876 tword->flags |= W_GLOBEXP; /* XXX */
7877 glob_list = make_word_list (tword, glob_list);
7880 if (glob_list)
7882 output_list = (WORD_LIST *)list_append (glob_list, output_list);
7883 PREPEND_LIST (tlist, disposables);
7885 else if (fail_glob_expansion != 0)
7887 report_error (_("no match: %s"), tlist->word->word);
7888 exp_jump_to_top_level (DISCARD);
7890 else if (allow_null_glob_expansion == 0)
7892 /* Failed glob expressions are left unchanged. */
7893 PREPEND_LIST (tlist, output_list);
7895 else
7897 /* Failed glob expressions are removed. */
7898 PREPEND_LIST (tlist, disposables);
7901 else
7903 /* Dequote the string. */
7904 temp_string = dequote_string (tlist->word->word);
7905 free (tlist->word->word);
7906 tlist->word->word = temp_string;
7907 PREPEND_LIST (tlist, output_list);
7910 strvec_dispose (glob_array);
7911 glob_array = (char **)NULL;
7913 tlist = next;
7916 if (disposables)
7917 dispose_words (disposables);
7919 if (output_list)
7920 output_list = REVERSE_LIST (output_list, WORD_LIST *);
7922 return (output_list);
7925 #if defined (BRACE_EXPANSION)
7926 static WORD_LIST *
7927 brace_expand_word_list (tlist, eflags)
7928 WORD_LIST *tlist;
7929 int eflags;
7931 register char **expansions;
7932 char *temp_string;
7933 WORD_LIST *disposables, *output_list, *next;
7934 WORD_DESC *w;
7935 int eindex;
7937 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
7939 next = tlist->next;
7941 /* Only do brace expansion if the word has a brace character. If
7942 not, just add the word list element to BRACES and continue. In
7943 the common case, at least when running shell scripts, this will
7944 degenerate to a bunch of calls to `xstrchr', and then what is
7945 basically a reversal of TLIST into BRACES, which is corrected
7946 by a call to REVERSE_LIST () on BRACES when the end of TLIST
7947 is reached. */
7948 if (xstrchr (tlist->word->word, LBRACE))
7950 expansions = brace_expand (tlist->word->word);
7952 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
7954 w = make_word (temp_string);
7955 /* If brace expansion didn't change the word, preserve
7956 the flags. We may want to preserve the flags
7957 unconditionally someday -- XXX */
7958 if (STREQ (temp_string, tlist->word->word))
7959 w->flags = tlist->word->flags;
7960 output_list = make_word_list (w, output_list);
7961 free (expansions[eindex]);
7963 free (expansions);
7965 /* Add TLIST to the list of words to be freed after brace
7966 expansion has been performed. */
7967 PREPEND_LIST (tlist, disposables);
7969 else
7970 PREPEND_LIST (tlist, output_list);
7973 if (disposables)
7974 dispose_words (disposables);
7976 if (output_list)
7977 output_list = REVERSE_LIST (output_list, WORD_LIST *);
7979 return (output_list);
7981 #endif
7983 static WORD_LIST *
7984 shell_expand_word_list (tlist, eflags)
7985 WORD_LIST *tlist;
7986 int eflags;
7988 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
7989 int expanded_something, has_dollar_at;
7990 char *temp_string;
7992 /* We do tilde expansion all the time. This is what 1003.2 says. */
7993 new_list = (WORD_LIST *)NULL;
7994 for (orig_list = tlist; tlist; tlist = next)
7996 temp_string = tlist->word->word;
7998 next = tlist->next;
8000 #if defined (ARRAY_VARS)
8001 /* If this is a compound array assignment to a builtin that accepts
8002 such assignments (e.g., `declare'), take the assignment and perform
8003 it separately, handling the semantics of declarations inside shell
8004 functions. This avoids the double-evaluation of such arguments,
8005 because `declare' does some evaluation of compound assignments on
8006 its own. */
8007 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
8009 int t;
8011 t = do_word_assignment (tlist->word);
8012 if (t == 0)
8014 last_command_exit_value = EXECUTION_FAILURE;
8015 exp_jump_to_top_level (DISCARD);
8018 /* Now transform the word as ksh93 appears to do and go on */
8019 t = assignment (tlist->word->word, 0);
8020 tlist->word->word[t] = '\0';
8021 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG);
8023 #endif
8025 expanded_something = 0;
8026 expanded = expand_word_internal
8027 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
8029 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
8031 /* By convention, each time this error is returned,
8032 tlist->word->word has already been freed. */
8033 tlist->word->word = (char *)NULL;
8035 /* Dispose our copy of the original list. */
8036 dispose_words (orig_list);
8037 /* Dispose the new list we're building. */
8038 dispose_words (new_list);
8040 last_command_exit_value = EXECUTION_FAILURE;
8041 if (expanded == &expand_word_error)
8042 exp_jump_to_top_level (DISCARD);
8043 else
8044 exp_jump_to_top_level (FORCE_EOF);
8047 /* Don't split words marked W_NOSPLIT. */
8048 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
8050 temp_list = word_list_split (expanded);
8051 dispose_words (expanded);
8053 else
8055 /* If no parameter expansion, command substitution, process
8056 substitution, or arithmetic substitution took place, then
8057 do not do word splitting. We still have to remove quoted
8058 null characters from the result. */
8059 word_list_remove_quoted_nulls (expanded);
8060 temp_list = expanded;
8063 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8064 new_list = (WORD_LIST *)list_append (expanded, new_list);
8067 if (orig_list)
8068 dispose_words (orig_list);
8070 if (new_list)
8071 new_list = REVERSE_LIST (new_list, WORD_LIST *);
8073 return (new_list);
8076 /* The workhorse for expand_words () and expand_words_no_vars ().
8077 First arg is LIST, a WORD_LIST of words.
8078 Second arg EFLAGS is a flags word controlling which expansions are
8079 performed.
8081 This does all of the substitutions: brace expansion, tilde expansion,
8082 parameter expansion, command substitution, arithmetic expansion,
8083 process substitution, word splitting, and pathname expansion, according
8084 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
8085 set, or for which no expansion is done, do not undergo word splitting.
8086 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8087 static WORD_LIST *
8088 expand_word_list_internal (list, eflags)
8089 WORD_LIST *list;
8090 int eflags;
8092 WORD_LIST *new_list, *temp_list;
8093 int tint;
8095 if (list == 0)
8096 return ((WORD_LIST *)NULL);
8098 garglist = new_list = copy_word_list (list);
8099 if (eflags & WEXP_VARASSIGN)
8101 garglist = new_list = separate_out_assignments (new_list);
8102 if (new_list == 0)
8104 if (subst_assign_varlist)
8106 /* All the words were variable assignments, so they are placed
8107 into the shell's environment. */
8108 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8110 this_command_name = (char *)NULL; /* no arithmetic errors */
8111 tint = do_word_assignment (temp_list->word);
8112 /* Variable assignment errors in non-interactive shells
8113 running in Posix.2 mode cause the shell to exit. */
8114 if (tint == 0)
8116 last_command_exit_value = EXECUTION_FAILURE;
8117 if (interactive_shell == 0 && posixly_correct)
8118 exp_jump_to_top_level (FORCE_EOF);
8119 else
8120 exp_jump_to_top_level (DISCARD);
8123 dispose_words (subst_assign_varlist);
8124 subst_assign_varlist = (WORD_LIST *)NULL;
8126 return ((WORD_LIST *)NULL);
8130 /* Begin expanding the words that remain. The expansions take place on
8131 things that aren't really variable assignments. */
8133 #if defined (BRACE_EXPANSION)
8134 /* Do brace expansion on this word if there are any brace characters
8135 in the string. */
8136 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8137 new_list = brace_expand_word_list (new_list, eflags);
8138 #endif /* BRACE_EXPANSION */
8140 /* Perform the `normal' shell expansions: tilde expansion, parameter and
8141 variable substitution, command substitution, arithmetic expansion,
8142 and word splitting. */
8143 new_list = shell_expand_word_list (new_list, eflags);
8145 /* Okay, we're almost done. Now let's just do some filename
8146 globbing. */
8147 if (new_list)
8149 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8150 /* Glob expand the word list unless globbing has been disabled. */
8151 new_list = glob_expand_word_list (new_list, eflags);
8152 else
8153 /* Dequote the words, because we're not performing globbing. */
8154 new_list = dequote_list (new_list);
8157 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8159 sh_wassign_func_t *assign_func;
8161 /* If the remainder of the words expand to nothing, Posix.2 requires
8162 that the variable and environment assignments affect the shell's
8163 environment. */
8164 assign_func = new_list ? assign_in_env : do_word_assignment;
8165 tempenv_assign_error = 0;
8167 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8169 this_command_name = (char *)NULL;
8170 tint = (*assign_func) (temp_list->word);
8171 /* Variable assignment errors in non-interactive shells running
8172 in Posix.2 mode cause the shell to exit. */
8173 if (tint == 0)
8175 if (assign_func == do_word_assignment)
8177 last_command_exit_value = EXECUTION_FAILURE;
8178 if (interactive_shell == 0 && posixly_correct)
8179 exp_jump_to_top_level (FORCE_EOF);
8180 else
8181 exp_jump_to_top_level (DISCARD);
8183 else
8184 tempenv_assign_error++;
8188 dispose_words (subst_assign_varlist);
8189 subst_assign_varlist = (WORD_LIST *)NULL;
8192 #if 0
8193 tint = list_length (new_list) + 1;
8194 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8195 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8196 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8197 glob_argv_flags[tint] = '\0';
8198 #endif
8200 return (new_list);