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-2020 Free Software Foundation, Inc.
9 This file is part of GNU Bush, the Bourne Again SHell.
11 Bush is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 Bush is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with Bush. If not, see <http://www.gnu.org/licenses/>.
27 #include "bushtypes.h"
29 #include "chartypes.h"
30 #if defined (HAVE_PWD_H)
36 #if defined (HAVE_UNISTD_H)
40 #define NEED_FPURGE_DECL
43 #include "posixstat.h"
47 #include "lxrgmr/parser.h"
50 #include "runner/execute_cmd.h"
53 #include "impl/pathexp.h"
54 #include "mailcheck.h"
57 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
58 # include <mbstr.h> /* mbschr */
62 #include "builtins/getopt.h"
63 #include "builtins/common.h"
65 #include "builtins/builtext.h"
67 #include <tilde/tilde.h>
68 #include <glob/strmatch.h>
74 /* The size that strings change by. */
75 #define DEFAULT_INITIAL_ARRAY_SIZE 112
76 #define DEFAULT_ARRAY_SIZE 128
82 #define VT_ARRAYMEMBER 3
85 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
87 /* Flags for quoted_strchr */
88 #define ST_BACKSL 0x01
89 #define ST_CTLESC 0x02
90 #define ST_SQUOTE 0x04 /* unused yet */
91 #define ST_DQUOTE 0x08 /* unused yet */
93 /* These defs make it easier to use the editor. */
101 #if defined (HANDLE_MULTIBYTE)
106 #define DOLLAR_AT_STAR(c) ((c) == '@' || (c) == '*')
107 #define STR_DOLLAR_AT_STAR(s) (DOLLAR_AT_STAR ((s)[0]) && (s)[1] == '\0')
109 /* Evaluates to 1 if C is one of the shell's special parameters whose length
110 can be taken, but is also one of the special expansion characters. */
111 #define VALID_SPECIAL_LENGTH_PARAM(c) \
112 ((c) == '-' || (c) == '?' || (c) == '#' || (c) == '@')
114 /* Evaluates to 1 if C is one of the shell's special parameters for which an
115 indirect variable reference may be made. */
116 #define VALID_INDIR_PARAM(c) \
117 ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
119 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
120 in ${parameter[:]OPword}. */
121 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
123 /* Evaluates to 1 if this is one of the shell's special variables. */
124 #define SPECIAL_VAR(name, wi) \
125 (*name && ((DIGIT (*name) && all_digits (name)) || \
126 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
127 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1]))))
129 /* This can be used by all of the *_extract_* functions that have a similar
130 structure. It can't just be wrapped in a do...while(0) loop because of
131 the embedded `break'. The dangling else accommodates a trailing semicolon;
132 we could also put in a do ; while (0) */
134 #define CHECK_STRING_OVERRUN(oind, ind, len, ch) \
143 /* An expansion function that takes a string and a quoted flag and returns
144 a WORD_LIST *. Used as the type of the third argument to
145 expand_string_if_necessary(). */
146 typedef WORD_LIST
*EXPFUNC
PARAMS((char *, int));
148 /* Process ID of the last command executed within command substitution. */
149 pid_t last_command_subst_pid
= NO_PID
;
150 pid_t current_command_subst_pid
= NO_PID
;
152 /* Variables used to keep track of the characters in IFS. */
155 unsigned char ifs_cmap
[UCHAR_MAX
+ 1];
156 int ifs_is_set
, ifs_is_null
;
158 #if defined (HANDLE_MULTIBYTE)
159 unsigned char ifs_firstc
[MB_LEN_MAX
];
160 size_t ifs_firstc_len
;
162 unsigned char ifs_firstc
;
165 /* If non-zero, command substitution inherits the value of errexit option */
166 int inherit_errexit
= 0;
168 /* Sentinel to tell when we are performing variable assignments preceding a
169 command name and putting them into the environment. Used to make sure
170 we use the temporary environment when looking up variable values. */
171 int assigning_in_environment
;
173 /* Used to hold a list of variable assignments preceding a command. Global
174 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
175 SIGCHLD trap and so it can be saved and restored by the trap handlers. */
176 WORD_LIST
*subst_assign_varlist
= (WORD_LIST
*)NULL
;
178 /* Tell the expansion functions to not longjmp back to top_level on fatal
179 errors. Enabled when doing completion and prompt string expansion. */
180 int no_longjmp_on_fatal_error
= 0;
182 /* Non-zero means to allow unmatched globbed filenames to expand to
184 int allow_null_glob_expansion
;
186 /* Non-zero means to throw an error when globbing fails to match anything. */
187 int fail_glob_expansion
;
189 /* Extern functions and variables from different files. */
190 extern struct fd_bitmap
*current_fds_to_close
;
191 extern int wordexp_only
;
193 #if defined (JOB_CONTROL) && defined (PROCESS_SUBSTITUTION)
194 extern PROCESS
*last_procsub_child
;
197 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
198 extern wchar_t *wcsdup
PARAMS((const wchar_t *));
202 /* Variables to keep track of which words in an expanded word list (the
203 output of expand_word_list_internal) are the result of globbing
204 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
205 (CURRENTLY UNUSED). */
206 char *glob_argv_flags
;
207 static int glob_argv_flags_size
;
210 static WORD_LIST
*cached_quoted_dollar_at
= 0;
212 /* Distinguished error values to return from expansion functions */
213 static WORD_LIST expand_word_error
, expand_word_fatal
;
214 static WORD_DESC expand_wdesc_error
, expand_wdesc_fatal
;
215 static char expand_param_error
, expand_param_fatal
, expand_param_unset
;
216 static char extract_string_error
, extract_string_fatal
;
218 /* Set by expand_word_unsplit and several of the expand_string_XXX functions;
219 used to inhibit splitting and re-joining $* on $IFS, primarily when doing
220 assignment statements. The idea is that if we're in a context where this
221 is set, we're not going to be performing word splitting, so we use the same
222 rules to expand $* as we would if it appeared within double quotes. */
223 static int expand_no_split_dollar_star
= 0;
225 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
226 without any leading variable assignments. */
227 static WORD_LIST
*garglist
= (WORD_LIST
*)NULL
;
229 static char *quoted_substring
PARAMS((char *, int, int));
230 static int quoted_strlen
PARAMS((char *));
231 static char *quoted_strchr
PARAMS((char *, int, int));
233 static char *expand_string_if_necessary
PARAMS((char *, int, EXPFUNC
*));
234 static inline char *expand_string_to_string_internal
PARAMS((char *, int, EXPFUNC
*));
235 static WORD_LIST
*call_expand_word_internal
PARAMS((WORD_DESC
*, int, int, int *, int *));
236 static WORD_LIST
*expand_string_internal
PARAMS((char *, int));
237 static WORD_LIST
*expand_string_leave_quoted
PARAMS((char *, int));
238 static WORD_LIST
*expand_string_for_rhs
PARAMS((char *, int, int, int, int *, int *));
239 static WORD_LIST
*expand_string_for_pat
PARAMS((char *, int, int *, int *));
241 static char *quote_escapes_internal
PARAMS((const char *, int));
243 static WORD_LIST
*list_quote_escapes
PARAMS((WORD_LIST
*));
244 static WORD_LIST
*list_dequote_escapes
PARAMS((WORD_LIST
*));
246 static char *make_quoted_char
PARAMS((int));
247 static WORD_LIST
*quote_list
PARAMS((WORD_LIST
*));
249 static int unquoted_substring
PARAMS((char *, char *));
250 static int unquoted_member
PARAMS((int, char *));
252 #if defined (ARRAY_VARS)
253 static SHELL_VAR
*do_compound_assignment
PARAMS((char *, char *, int));
255 static int do_assignment_internal
PARAMS((const WORD_DESC
*, int));
257 static char *string_extract_verbatim
PARAMS((char *, size_t, int *, char *, int));
258 static char *string_extract
PARAMS((char *, int *, char *, int));
259 static char *string_extract_double_quoted
PARAMS((char *, int *, int));
260 static inline char *string_extract_single_quoted
PARAMS((char *, int *));
261 static inline int skip_single_quoted
PARAMS((const char *, size_t, int, int));
262 static int skip_double_quoted
PARAMS((char *, size_t, int, int));
263 static char *extract_delimited_string
PARAMS((char *, int *, char *, char *, char *, int));
264 static char *extract_dollar_brace_string
PARAMS((char *, int *, int, int));
265 static int skip_matched_pair
PARAMS((const char *, int, int, int, int));
267 static char *pos_params
PARAMS((char *, int, int, int, int));
269 static unsigned char *mb_getcharlens
PARAMS((char *, int));
271 static char *remove_upattern
PARAMS((char *, char *, int));
272 #if defined (HANDLE_MULTIBYTE)
273 static wchar_t *remove_wpattern
PARAMS((wchar_t *, size_t, wchar_t *, int));
275 static char *remove_pattern
PARAMS((char *, char *, int));
277 static int match_upattern
PARAMS((char *, char *, int, char **, char **));
278 #if defined (HANDLE_MULTIBYTE)
279 static int match_wpattern
PARAMS((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
281 static int match_pattern
PARAMS((char *, char *, int, char **, char **));
282 static int getpatspec
PARAMS((int, char *));
283 static char *getpattern
PARAMS((char *, int, int));
284 static char *variable_remove_pattern
PARAMS((char *, char *, int, int));
285 static char *list_remove_pattern
PARAMS((WORD_LIST
*, char *, int, int, int));
286 static char *parameter_list_remove_pattern
PARAMS((int, char *, int, int));
288 static char *array_remove_pattern
PARAMS((SHELL_VAR
*, char *, int, int, int));
290 static char *parameter_brace_remove_pattern
PARAMS((char *, char *, int, char *, int, int, int));
292 static char *string_var_assignment
PARAMS((SHELL_VAR
*, char *));
293 #if defined (ARRAY_VARS)
294 static char *array_var_assignment
PARAMS((SHELL_VAR
*, int, int, int));
296 static char *pos_params_assignment
PARAMS((WORD_LIST
*, int, int));
297 static char *string_transform
PARAMS((int, SHELL_VAR
*, char *));
298 static char *list_transform
PARAMS((int, SHELL_VAR
*, WORD_LIST
*, int, int));
299 static char *parameter_list_transform
PARAMS((int, int, int));
300 #if defined ARRAY_VARS
301 static char *array_transform
PARAMS((int, SHELL_VAR
*, int, int));
303 static char *parameter_brace_transform
PARAMS((char *, char *, int, char *, int, int, int, int));
304 static int valid_parameter_transform
PARAMS((char *));
306 static char *process_substitute
PARAMS((char *, int));
308 static char *read_comsub
PARAMS((int, int, int, int *));
311 static arrayind_t array_length_reference
PARAMS((char *));
314 static int valid_brace_expansion_word
PARAMS((char *, int));
315 static int chk_atstar
PARAMS((char *, int, int, int *, int *));
316 static int chk_arithsub
PARAMS((const char *, int));
318 static WORD_DESC
*parameter_brace_expand_word
PARAMS((char *, int, int, int, arrayind_t
*));
319 static char *parameter_brace_find_indir
PARAMS((char *, int, int, int));
320 static WORD_DESC
*parameter_brace_expand_indir
PARAMS((char *, int, int, int, int *, int *));
321 static WORD_DESC
*parameter_brace_expand_rhs
PARAMS((char *, char *, int, int, int, int *, int *));
322 static void parameter_brace_expand_error
PARAMS((char *, char *, int));
324 static int valid_length_expression
PARAMS((char *));
325 static intmax_t parameter_brace_expand_length
PARAMS((char *));
327 static char *skiparith
PARAMS((char *, int));
328 static int verify_substring_values
PARAMS((SHELL_VAR
*, char *, char *, int, intmax_t *, intmax_t *));
329 static int get_var_and_type
PARAMS((char *, char *, arrayind_t
, int, int, SHELL_VAR
**, char **));
330 static char *mb_substring
PARAMS((char *, int, int));
331 static char *parameter_brace_substring
PARAMS((char *, char *, int, char *, int, int, int));
333 static int shouldexp_replacement
PARAMS((char *));
335 static char *pos_params_pat_subst
PARAMS((char *, char *, char *, int));
337 static char *parameter_brace_patsub
PARAMS((char *, char *, int, char *, int, int, int));
339 static char *pos_params_casemod
PARAMS((char *, char *, int, int));
340 static char *parameter_brace_casemod
PARAMS((char *, char *, int, int, char *, int, int, int));
342 static WORD_DESC
*parameter_brace_expand
PARAMS((char *, int *, int, int, int *, int *));
343 static WORD_DESC
*param_expand
PARAMS((char *, int *, int, int *, int *, int *, int *, int));
345 static WORD_LIST
*expand_word_internal
PARAMS((WORD_DESC
*, int, int, int *, int *));
347 static WORD_LIST
*word_list_split
PARAMS((WORD_LIST
*));
349 static void exp_jump_to_top_level
PARAMS((int));
351 static WORD_LIST
*separate_out_assignments
PARAMS((WORD_LIST
*));
352 static WORD_LIST
*glob_expand_word_list
PARAMS((WORD_LIST
*, int));
353 #ifdef BRACE_EXPANSION
354 static WORD_LIST
*brace_expand_word_list
PARAMS((WORD_LIST
*, int));
356 #if defined (ARRAY_VARS)
357 static int make_internal_declare
PARAMS((char *, char *, char *));
358 static void expand_compound_assignment_word
PARAMS((WORD_LIST
*, int));
359 static WORD_LIST
*expand_declaration_argument
PARAMS((WORD_LIST
*, WORD_LIST
*));
361 static WORD_LIST
*shell_expand_word_list
PARAMS((WORD_LIST
*, int));
362 static WORD_LIST
*expand_word_list_internal
PARAMS((WORD_LIST
*, int));
364 /* **************************************************************** */
366 /* Utility Functions */
368 /* **************************************************************** */
372 dump_word_flags (flags
)
378 fprintf (stderr
, "%d -> ", f
);
382 fprintf (stderr
, "W_ARRAYIND%s", f
? "|" : "");
384 if (f
& W_ASSIGNASSOC
)
387 fprintf (stderr
, "W_ASSIGNASSOC%s", f
? "|" : "");
389 if (f
& W_ASSIGNARRAY
)
392 fprintf (stderr
, "W_ASSIGNARRAY%s", f
? "|" : "");
394 if (f
& W_SAWQUOTEDNULL
)
396 f
&= ~W_SAWQUOTEDNULL
;
397 fprintf (stderr
, "W_SAWQUOTEDNULL%s", f
? "|" : "");
402 fprintf (stderr
, "W_NOPROCSUB%s", f
? "|" : "");
407 fprintf (stderr
, "W_DQUOTE%s", f
? "|" : "");
409 if (f
& W_HASQUOTEDNULL
)
411 f
&= ~W_HASQUOTEDNULL
;
412 fprintf (stderr
, "W_HASQUOTEDNULL%s", f
? "|" : "");
417 fprintf (stderr
, "W_ASSIGNARG%s", f
? "|" : "");
422 fprintf (stderr
, "W_ASSNBLTIN%s", f
? "|" : "");
424 if (f
& W_ASSNGLOBAL
)
427 fprintf (stderr
, "W_ASSNGLOBAL%s", f
? "|" : "");
429 if (f
& W_COMPASSIGN
)
432 fprintf (stderr
, "W_COMPASSIGN%s", f
? "|" : "");
437 fprintf (stderr
, "W_EXPANDRHS%s", f
? "|" : "");
442 fprintf (stderr
, "W_ITILDE%s", f
? "|" : "");
447 fprintf (stderr
, "W_NOTILDE%s", f
? "|" : "");
452 fprintf (stderr
, "W_ASSIGNRHS%s", f
? "|" : "");
454 if (f
& W_NOASSNTILDE
)
457 fprintf (stderr
, "W_NOASSNTILDE%s", f
? "|" : "");
462 fprintf (stderr
, "W_NOCOMSUB%s", f
? "|" : "");
464 if (f
& W_DOLLARSTAR
)
467 fprintf (stderr
, "W_DOLLARSTAR%s", f
? "|" : "");
472 fprintf (stderr
, "W_DOLLARAT%s", f
? "|" : "");
477 fprintf (stderr
, "W_TILDEEXP%s", f
? "|" : "");
482 fprintf (stderr
, "W_NOSPLIT2%s", f
? "|" : "");
487 fprintf (stderr
, "W_NOSPLIT%s", f
? "|" : "");
492 fprintf (stderr
, "W_NOBRACE%s", f
? "|" : "");
497 fprintf (stderr
, "W_NOGLOB%s", f
? "|" : "");
499 if (f
& W_SPLITSPACE
)
502 fprintf (stderr
, "W_SPLITSPACE%s", f
? "|" : "");
504 if (f
& W_ASSIGNMENT
)
507 fprintf (stderr
, "W_ASSIGNMENT%s", f
? "|" : "");
512 fprintf (stderr
, "W_QUOTED%s", f
? "|" : "");
517 fprintf (stderr
, "W_HASDOLLAR%s", f
? "|" : "");
522 fprintf (stderr
, "W_COMPLETE%s", f
? "|" : "");
527 fprintf (stderr
, "W_CHKLOCAL%s", f
? "|" : "");
529 if (f
& W_FORCELOCAL
)
532 fprintf (stderr
, "W_FORCELOCAL%s", f
? "|" : "");
535 fprintf (stderr
, "\n");
540 #ifdef INCLUDE_UNUSED
542 quoted_substring (string
, start
, end
)
547 register char *result
, *s
, *r
;
551 /* Move to string[start], skipping quoted characters. */
552 for (s
= string
, l
= 0; *s
&& l
< start
; )
564 r
= result
= (char *)xmalloc (2*len
+ 1); /* save room for quotes */
566 /* Copy LEN characters, including quote characters. */
568 for (l
= 0; l
< len
; s
++)
582 #ifdef INCLUDE_UNUSED
583 /* Return the length of S, skipping over quoted characters */
607 #ifdef INCLUDE_UNUSED
608 /* Find the first occurrence of character C in string S, obeying shell
609 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
610 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
611 escaped with CTLESC are skipped. */
613 quoted_strchr (s
, c
, flags
)
621 if (((flags
& ST_BACKSL
) && *p
== '\\')
622 || ((flags
& ST_CTLESC
) && *p
== CTLESC
))
626 return ((char *)NULL
);
632 return ((char *)NULL
);
635 /* Return 1 if CHARACTER appears in an unquoted portion of
636 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
638 unquoted_member (character
, string
)
646 slen
= strlen (string
);
648 while (c
= string
[sindex
])
656 ADVANCE_CHAR (string
, slen
, sindex
);
662 ADVANCE_CHAR (string
, slen
, sindex
);
666 sindex
= skip_single_quoted (string
, slen
, ++sindex
, 0);
670 sindex
= skip_double_quoted (string
, slen
, ++sindex
, 0);
677 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
679 unquoted_substring (substr
, string
)
680 char *substr
, *string
;
683 int sindex
, c
, sublen
;
686 if (substr
== 0 || *substr
== '\0')
689 slen
= strlen (string
);
690 sublen
= strlen (substr
);
691 for (sindex
= 0; c
= string
[sindex
]; )
693 if (STREQN (string
+ sindex
, substr
, sublen
))
701 ADVANCE_CHAR (string
, slen
, sindex
);
705 sindex
= skip_single_quoted (string
, slen
, ++sindex
, 0);
709 sindex
= skip_double_quoted (string
, slen
, ++sindex
, 0);
713 ADVANCE_CHAR (string
, slen
, sindex
);
721 /* Most of the substitutions must be done in parallel. In order
722 to avoid using tons of unclear goto's, I have some functions
723 for manipulating malloc'ed strings. They all take INDX, a
724 pointer to an integer which is the offset into the string
725 where manipulation is taking place. They also take SIZE, a
726 pointer to an integer which is the current length of the
727 character array for this string. */
729 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
730 of space allocated to TARGET. SOURCE can be NULL, in which
731 case nothing happens. Gets rid of SOURCE by freeing it.
732 Returns TARGET in case the location has changed. */
734 sub_append_string (source
, target
, indx
, size
)
735 char *source
, *target
;
744 srclen
= STRLEN (source
);
745 if (srclen
>= (int)(*size
- *indx
))
748 n
= (n
+ DEFAULT_ARRAY_SIZE
) - (n
% DEFAULT_ARRAY_SIZE
);
749 target
= (char *)xrealloc (target
, (*size
= n
));
752 FASTCOPY (source
, target
+ *indx
, srclen
);
754 target
[*indx
] = '\0';
763 /* Append the textual representation of NUMBER to TARGET.
764 INDX and SIZE are as in SUB_APPEND_STRING. */
766 sub_append_number (number
, target
, indx
, size
)
774 temp
= itos (number
);
775 return (sub_append_string (temp
, target
, indx
, size
));
779 /* Extract a substring from STRING, starting at SINDEX and ending with
780 one of the characters in CHARLIST. Don't make the ending character
781 part of the string. Leave SINDEX pointing at the ending character.
782 Understand about backslashes in the string. If (flags & SX_VARNAME)
783 is non-zero, and array variables have been compiled into the shell,
784 everything between a `[' and a corresponding `]' is skipped over.
785 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
786 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
787 contain a closing character from CHARLIST. */
789 string_extract (string
, sindex
, charlist
, flags
)
801 slen
= (MB_CUR_MAX
> 1) ? strlen (string
+ *sindex
) + *sindex
: 0;
804 while (c
= string
[i
])
813 #if defined (ARRAY_VARS)
814 else if ((flags
& SX_VARNAME
) && c
== LBRACK
)
817 /* If this is an array subscript, skip over it and continue. */
818 ni
= skipsubscript (string
, i
, 0);
819 if (string
[ni
] == RBRACK
)
823 // else if (c == ':' && string[i+1] == ':' && legal_variable_starter(string[i+2]))
824 else if (c
== ':' && string
[i
+1] == ':' && org_legal_variable_starter(string
[i
+2]) )
829 else if (MEMBER (c
, charlist
))
835 ADVANCE_CHAR (string
, slen
, i
);
838 /* If we had to have a matching delimiter and didn't find one, return an
839 error and let the caller deal with it. */
840 if ((flags
& SX_REQMATCH
) && found
== 0)
843 return (&extract_string_error
);
846 temp
= (flags
& SX_NOALLOC
) ? (char *)NULL
: substring (string
, *sindex
, i
);
852 /* Extract the contents of STRING as if it is enclosed in double quotes.
853 SINDEX, when passed in, is the offset of the character immediately
854 following the opening double quote; on exit, SINDEX is left pointing after
855 the closing double quote. If STRIPDQ is non-zero, unquoted double
856 quotes are stripped and the string is terminated by a null byte.
857 Backslashes between the embedded double quotes are processed. If STRIPDQ
858 is zero, an unquoted `"' terminates the string. */
860 string_extract_double_quoted (string
, sindex
, flags
)
868 char *temp
, *ret
; /* The new string we return. */
869 int pass_next
, backquote
, si
; /* State variables for the machine. */
874 slen
= strlen (string
+ *sindex
) + *sindex
;
875 send
= string
+ slen
;
877 stripdq
= (flags
& SX_STRIPDQ
);
879 pass_next
= backquote
= dquote
= 0;
880 temp
= (char *)xmalloc (1 + slen
- *sindex
);
884 while (c
= string
[i
])
886 /* Process a character that was quoted by a backslash. */
889 /* XXX - take another look at this in light of Interp 221 */
892 ``The backslash shall retain its special meaning as an escape
893 character only when followed by one of the characters:
896 If STRIPDQ is zero, we handle the double quotes here and let
897 expand_word_internal handle the rest. If STRIPDQ is non-zero,
898 we have already been through one round of backslash stripping,
899 and want to strip these backslashes only if DQUOTE is non-zero,
900 indicating that we are inside an embedded double-quoted string. */
902 /* If we are in an embedded quoted string, then don't strip
903 backslashes before characters for which the backslash
904 retains its special meaning, but remove backslashes in
905 front of other characters. If we are not in an
906 embedded quoted string, don't strip backslashes at all.
907 This mess is necessary because the string was already
908 surrounded by double quotes (and sh has some really weird
910 The returned string will be run through expansion as if
911 it were double-quoted. */
912 if ((stripdq
== 0 && c
!= '"') ||
913 (stripdq
&& ((dquote
&& (sh_syntaxtab
[c
] & CBSDQUOTE
)) || dquote
== 0)))
918 COPY_CHAR_I (temp
, j
, string
, send
, i
);
922 /* A backslash protects the next character. The code just above
923 handles preserving the backslash in front of any character but
932 /* Inside backquotes, ``the portion of the quoted string from the
933 initial backquote and the characters up to the next backquote
934 that is not preceded by a backslash, having escape characters
935 removed, defines that command''. */
940 temp
[j
++] = c
; /* COPY_CHAR_I? */
953 /* Pass everything between `$(' and the matching `)' or a quoted
954 ${ ... } pair through according to the Posix.2 specification. */
955 if (c
== '$' && ((string
[i
+ 1] == LPAREN
) || (string
[i
+ 1] == LBRACE
)))
960 if (string
[i
+ 1] == LPAREN
)
961 ret
= extract_command_subst (string
, &si
, (flags
& SX_COMPLETE
));
963 ret
= extract_dollar_brace_string (string
, &si
, Q_DOUBLE_QUOTES
, 0);
966 temp
[j
++] = string
[i
+ 1];
968 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
970 if (ret
== 0 && no_longjmp_on_fatal_error
)
973 ret
= string
+ i
+ 2;
976 /* XXX - CHECK_STRING_OVERRUN here? */
977 for (t
= 0; ret
[t
]; t
++, j
++)
979 temp
[j
] = string
[si
];
981 if (si
< i
+ 2) /* we went back? */
996 /* Add any character but a double quote to the quoted string we're
999 goto add_one_character
;
1013 /* Point to after the closing quote. */
1021 /* This should really be another option to string_extract_double_quoted. */
1023 skip_double_quoted (string
, slen
, sind
, flags
)
1031 int pass_next
, backquote
, si
;
1034 pass_next
= backquote
= 0;
1036 while (c
= string
[i
])
1041 ADVANCE_CHAR (string
, slen
, i
);
1054 ADVANCE_CHAR (string
, slen
, i
);
1063 else if (c
== '$' && ((string
[i
+ 1] == LPAREN
) || (string
[i
+ 1] == LBRACE
)))
1066 if (string
[i
+ 1] == LPAREN
)
1067 ret
= extract_command_subst (string
, &si
, SX_NOALLOC
|(flags
&SX_COMPLETE
));
1069 ret
= extract_dollar_brace_string (string
, &si
, Q_DOUBLE_QUOTES
, SX_NOALLOC
);
1071 /* These can consume the entire string if they are unterminated */
1072 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1079 ADVANCE_CHAR (string
, slen
, i
);
1092 /* Extract the contents of STRING as if it is enclosed in single quotes.
1093 SINDEX, when passed in, is the offset of the character immediately
1094 following the opening single quote; on exit, SINDEX is left pointing after
1095 the closing single quote. */
1096 static inline char *
1097 string_extract_single_quoted (string
, sindex
)
1106 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
1107 slen
= (MB_CUR_MAX
> 1) ? strlen (string
+ *sindex
) + *sindex
: 0;
1109 while (string
[i
] && string
[i
] != '\'')
1110 ADVANCE_CHAR (string
, slen
, i
);
1112 t
= substring (string
, *sindex
, i
);
1121 /* Skip over a single-quoted string. We overload the SX_COMPLETE flag to mean
1122 that we are splitting out words for completion and have encountered a $'...'
1123 string, which allows backslash-escaped single quotes. */
1125 skip_single_quoted (string
, slen
, sind
, flags
)
1135 while (string
[c
] && string
[c
] != '\'')
1137 if ((flags
& SX_COMPLETE
) && string
[c
] == '\\' && string
[c
+1] == '\'' && string
[c
+2])
1138 ADVANCE_CHAR (string
, slen
, c
);
1139 ADVANCE_CHAR (string
, slen
, c
);
1147 /* Just like string_extract, but doesn't hack backslashes or any of
1148 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
1150 string_extract_verbatim (string
, slen
, sindex
, charlist
, flags
)
1158 #if defined (HANDLE_MULTIBYTE)
1165 if ((flags
& SX_NOCTLESC
) && charlist
[0] == '\'' && charlist
[1] == '\0')
1167 temp
= string_extract_single_quoted (string
, sindex
);
1168 --*sindex
; /* leave *sindex at separator character */
1172 /* This can never be called with charlist == NULL. If *charlist == NULL,
1173 we can skip the loop and just return a copy of the string, updating
1177 temp
= string
+ *sindex
;
1178 c
= (*sindex
== 0) ? slen
: STRLEN (temp
);
1179 temp
= savestring (temp
);
1185 #if defined (HANDLE_MULTIBYTE)
1188 while (c
= string
[i
])
1190 #if defined (HANDLE_MULTIBYTE)
1193 if ((flags
& SX_NOCTLESC
) == 0 && c
== CTLESC
)
1196 CHECK_STRING_OVERRUN (i
, i
, slen
, c
);
1199 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
1200 through, to protect the CTLNULs from later calls to
1201 remove_quoted_nulls. */
1202 else if ((flags
& SX_NOESCCTLNUL
) == 0 && c
== CTLESC
&& string
[i
+1] == CTLNUL
)
1205 CHECK_STRING_OVERRUN (i
, i
, slen
, c
);
1209 #if defined (HANDLE_MULTIBYTE)
1210 if (locale_utf8locale
&& slen
> i
&& UTF8_SINGLEBYTE (string
[i
]))
1211 mblength
= (string
[i
] != 0) ? 1 : 0;
1213 mblength
= MBLEN (string
+ i
, slen
- i
);
1217 mblength
= mbtowc (&wc
, string
+ i
, slen
- i
);
1218 if (MB_INVALIDCH (mblength
))
1220 if (MEMBER (c
, charlist
))
1228 len
= mbstowcs (wcharlist
, charlist
, 0);
1231 wcharlist
= (wchar_t *)xmalloc (sizeof (wchar_t) * (len
+ 1));
1232 mbstowcs (wcharlist
, charlist
, len
+ 1);
1235 if (wcschr (wcharlist
, wc
))
1241 if (MEMBER (c
, charlist
))
1244 ADVANCE_CHAR (string
, slen
, i
);
1247 #if defined (HANDLE_MULTIBYTE)
1251 temp
= substring (string
, *sindex
, i
);
1257 /* Extract the $( construct in STRING, and return a new string.
1258 Start extracting at (SINDEX) as if we had just seen "$(".
1259 Make (SINDEX) get the position of the matching ")". )
1260 XFLAGS is additional flags to pass to other extraction functions. */
1262 extract_command_subst (string
, sindex
, xflags
)
1269 if (string
[*sindex
] == LPAREN
|| (xflags
& SX_COMPLETE
))
1270 return (extract_delimited_string (string
, sindex
, "$(", "(", ")", xflags
|SX_COMMAND
)); /*)*/
1273 xflags
|= (no_longjmp_on_fatal_error
? SX_NOLONGJMP
: 0);
1274 ret
= xparse_dolparen (string
, string
+*sindex
, sindex
, xflags
);
1279 /* Extract the $[ construct in STRING, and return a new string. (])
1280 Start extracting at (SINDEX) as if we had just seen "$[".
1281 Make (SINDEX) get the position of the matching "]". */
1283 extract_arithmetic_subst (string
, sindex
)
1287 return (extract_delimited_string (string
, sindex
, "$[", "[", "]", 0)); /*]*/
1290 #if defined (PROCESS_SUBSTITUTION)
1291 /* Extract the <( or >( construct in STRING, and return a new string.
1292 Start extracting at (SINDEX) as if we had just seen "<(".
1293 Make (SINDEX) get the position of the matching ")". */ /*))*/
1295 extract_process_subst (string
, starter
, sindex
, xflags
)
1302 /* XXX - check xflags&SX_COMPLETE here? */
1303 return (extract_delimited_string (string
, sindex
, starter
, "(", ")", SX_COMMAND
));
1305 xflags
|= (no_longjmp_on_fatal_error
? SX_NOLONGJMP
: 0);
1306 return (xparse_dolparen (string
, string
+*sindex
, sindex
, xflags
));
1309 #endif /* PROCESS_SUBSTITUTION */
1311 #if defined (ARRAY_VARS)
1312 /* This can be fooled by unquoted right parens in the passed string. If
1313 each caller verifies that the last character in STRING is a right paren,
1314 we don't even need to call extract_delimited_string. */
1316 extract_array_assignment_list (string
, sindex
)
1323 slen
= strlen (string
);
1324 if (string
[slen
- 1] == RPAREN
)
1326 ret
= substring (string
, *sindex
, slen
- 1);
1334 /* Extract and create a new string from the contents of STRING, a
1335 character string delimited with OPENER and CLOSER. SINDEX is
1336 the address of an int describing the current offset in STRING;
1337 it should point to just after the first OPENER found. On exit,
1338 SINDEX gets the position of the last character of the matching CLOSER.
1339 If OPENER is more than a single character, ALT_OPENER, if non-null,
1340 contains a character string that can also match CLOSER and thus
1341 needs to be skipped. */
1343 extract_delimited_string (string
, sindex
, opener
, alt_opener
, closer
, flags
)
1346 char *opener
, *alt_opener
, *closer
;
1352 int pass_character
, nesting_level
, in_comment
;
1353 int len_closer
, len_opener
, len_alt_opener
;
1356 slen
= strlen (string
+ *sindex
) + *sindex
;
1357 len_opener
= STRLEN (opener
);
1358 len_alt_opener
= STRLEN (alt_opener
);
1359 len_closer
= STRLEN (closer
);
1361 pass_character
= in_comment
= 0;
1366 while (nesting_level
)
1370 /* If a recursive call or a call to ADVANCE_CHAR leaves the index beyond
1371 the end of the string, catch it and cut the loop. */
1375 c
= string
[i
= slen
];
1386 ADVANCE_CHAR (string
, slen
, i
);
1390 if (pass_character
) /* previous char was backslash */
1393 ADVANCE_CHAR (string
, slen
, i
);
1397 /* Not exactly right yet; should handle shell metacharacters and
1398 multibyte characters, too. See COMMENT_BEGIN define in parse.y */
1399 if ((flags
& SX_COMMAND
) && c
== '#' && (i
== 0 || string
[i
- 1] == '\n' || shellblank (string
[i
- 1])))
1402 ADVANCE_CHAR (string
, slen
, i
);
1406 if (c
== CTLESC
|| c
== '\\')
1413 /* Process a nested command substitution, but only if we're parsing an
1414 arithmetic substitution. */
1415 if ((flags
& SX_COMMAND
) && string
[i
] == '$' && string
[i
+1] == LPAREN
)
1418 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1419 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1424 /* Process a nested OPENER. */
1425 if (STREQN (string
+ i
, opener
, len_opener
))
1427 si
= i
+ len_opener
;
1428 t
= extract_delimited_string (string
, &si
, opener
, alt_opener
, closer
, flags
|SX_NOALLOC
);
1429 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1434 /* Process a nested ALT_OPENER */
1435 if (len_alt_opener
&& STREQN (string
+ i
, alt_opener
, len_alt_opener
))
1437 si
= i
+ len_alt_opener
;
1438 t
= extract_delimited_string (string
, &si
, alt_opener
, alt_opener
, closer
, flags
|SX_NOALLOC
);
1439 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1444 /* If the current substring terminates the delimited string, decrement
1445 the nesting level. */
1446 if (STREQN (string
+ i
, closer
, len_closer
))
1448 i
+= len_closer
- 1; /* move to last byte of the closer */
1450 if (nesting_level
== 0)
1454 /* Pass old-style command substitution through verbatim. */
1458 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1459 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1464 /* Pass single-quoted and double-quoted strings through verbatim. */
1465 if (c
== '\'' || c
== '"')
1468 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, si
, 0)
1469 : skip_double_quoted (string
, slen
, si
, 0);
1473 /* move past this character, which was not special. */
1474 ADVANCE_CHAR (string
, slen
, i
);
1477 if (c
== 0 && nesting_level
)
1479 if (no_longjmp_on_fatal_error
== 0)
1481 last_command_exit_value
= EXECUTION_FAILURE
;
1482 report_error (_("bad substitution: no closing `%s' in %s"), closer
, string
);
1483 exp_jump_to_top_level (DISCARD
);
1488 return (char *)NULL
;
1492 si
= i
- *sindex
- len_closer
+ 1;
1493 if (flags
& SX_NOALLOC
)
1494 result
= (char *)NULL
;
1497 result
= (char *)xmalloc (1 + si
);
1498 strncpy (result
, string
+ *sindex
, si
);
1506 /* Extract a parameter expansion expression within ${ and } from STRING.
1507 Obey the Posix.2 rules for finding the ending `}': count braces while
1508 skipping over enclosed quoted strings and command substitutions.
1509 SINDEX is the address of an int describing the current offset in STRING;
1510 it should point to just after the first `{' found. On exit, SINDEX
1511 gets the position of the matching `}'. QUOTED is non-zero if this
1512 occurs inside double quotes. */
1513 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1515 extract_dollar_brace_string (string
, sindex
, quoted
, flags
)
1517 int *sindex
, quoted
, flags
;
1521 int pass_character
, nesting_level
, si
, dolbrace_state
;
1527 slen
= strlen (string
+ *sindex
) + *sindex
;
1529 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1530 parse_matched_pair(). The different initial value is to handle the
1531 case where this function is called to parse the word in
1532 ${param op word} (SX_WORD). */
1533 dolbrace_state
= (flags
& SX_WORD
) ? DOLBRACE_WORD
: DOLBRACE_PARAM
;
1534 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && (flags
& SX_POSIXEXP
))
1535 dolbrace_state
= DOLBRACE_QUOTE
;
1538 while (c
= string
[i
])
1543 ADVANCE_CHAR (string
, slen
, i
);
1547 /* CTLESCs and backslashes quote the next character. */
1548 if (c
== CTLESC
|| c
== '\\')
1555 if (string
[i
] == '$' && string
[i
+1] == LBRACE
)
1565 if (nesting_level
== 0)
1571 /* Pass the contents of old-style command substitutions through
1576 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1578 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1584 /* Pass the contents of new-style command substitutions and
1585 arithmetic substitutions through verbatim. */
1586 if (string
[i
] == '$' && string
[i
+1] == LPAREN
)
1589 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1591 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1597 #if defined (PROCESS_SUBSTITUTION)
1598 /* Technically this should only work at the start of a word */
1599 if ((string
[i
] == '<' || string
[i
] == '>') && string
[i
+1] == LPAREN
)
1602 t
= extract_process_subst (string
, (string
[i
] == '<' ? "<(" : ">)"), &si
, flags
|SX_NOALLOC
);
1604 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1611 /* Pass the contents of double-quoted strings through verbatim. */
1615 i
= skip_double_quoted (string
, slen
, si
, 0);
1616 /* skip_XXX_quoted leaves index one past close quote */
1622 /*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
1623 if (posixly_correct
&& shell_compatibility_level
> 42 && dolbrace_state
!= DOLBRACE_QUOTE
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1624 ADVANCE_CHAR (string
, slen
, i
);
1628 i
= skip_single_quoted (string
, slen
, si
, 0);
1634 #if defined (ARRAY_VARS)
1635 if (c
== LBRACK
&& dolbrace_state
== DOLBRACE_PARAM
)
1637 si
= skipsubscript (string
, i
, 0);
1638 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1639 if (string
[si
] == RBRACK
)
1644 /* move past this character, which was not special. */
1645 ADVANCE_CHAR (string
, slen
, i
);
1647 /* This logic must agree with parse.y:parse_matched_pair, since they
1648 share the same defines. */
1649 if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '%' && (i
- *sindex
) > 1)
1650 dolbrace_state
= DOLBRACE_QUOTE
;
1651 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '#' && (i
- *sindex
) > 1)
1652 dolbrace_state
= DOLBRACE_QUOTE
;
1653 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '/' && (i
- *sindex
) > 1)
1654 dolbrace_state
= DOLBRACE_QUOTE2
; /* XXX */
1655 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '^' && (i
- *sindex
) > 1)
1656 dolbrace_state
= DOLBRACE_QUOTE
;
1657 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== ',' && (i
- *sindex
) > 1)
1658 dolbrace_state
= DOLBRACE_QUOTE
;
1659 /* This is intended to handle all of the [:]op expansions and the substring/
1660 length/pattern removal/pattern substitution expansions. */
1661 else if (dolbrace_state
== DOLBRACE_PARAM
&& strchr ("#%^,~:-=?+/", c
) != 0)
1662 dolbrace_state
= DOLBRACE_OP
;
1663 else if (dolbrace_state
== DOLBRACE_OP
&& strchr ("#%^,~:-=?+/", c
) == 0)
1664 dolbrace_state
= DOLBRACE_WORD
;
1667 if (c
== 0 && nesting_level
)
1669 if (no_longjmp_on_fatal_error
== 0)
1671 last_command_exit_value
= EXECUTION_FAILURE
;
1672 report_error (_("bad substitution: no closing `%s' in %s"), "}", string
);
1673 exp_jump_to_top_level (DISCARD
);
1678 return ((char *)NULL
);
1682 result
= (flags
& SX_NOALLOC
) ? (char *)NULL
: substring (string
, *sindex
, i
);
1688 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1689 STRING, and returns a pointer to it. */
1691 de_backslash (string
)
1694 register size_t slen
;
1695 register int i
, j
, prev_i
;
1698 slen
= strlen (string
);
1701 /* Loop copying string[i] to string[j], i >= j. */
1704 if (string
[i
] == '\\' && (string
[i
+ 1] == '`' || string
[i
+ 1] == '\\' ||
1705 string
[i
+ 1] == '$'))
1708 ADVANCE_CHAR (string
, slen
, i
);
1710 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
1721 /* Replace instances of \! in a string with !. */
1723 unquote_bang (string
)
1727 register char *temp
;
1729 temp
= (char *)xmalloc (1 + strlen (string
));
1731 for (i
= 0, j
= 0; (temp
[j
] = string
[i
]); i
++, j
++)
1733 if (string
[i
] == '\\' && string
[i
+ 1] == '!')
1739 strcpy (string
, temp
);
1744 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0)
1746 /* This function assumes s[i] == open; returns with s[ret] == close; used to
1747 parse array subscripts. FLAGS & 1 means to not attempt to skip over
1748 matched pairs of quotes or backquotes, or skip word expansions; it is
1749 intended to be used after expansion has been performed and during final
1750 assignment parsing (see arrayfunc.c:assign_compound_array_list()) or
1751 during execution by a builtin which has already undergone word expansion. */
1753 skip_matched_pair (string
, start
, open
, close
, flags
)
1755 int start
, open
, close
, flags
;
1757 int i
, pass_next
, backq
, si
, c
, count
, oldjmp
;
1762 slen
= strlen (string
+ start
) + start
;
1763 oldjmp
= no_longjmp_on_fatal_error
;
1764 no_longjmp_on_fatal_error
= 1;
1766 i
= start
+ 1; /* skip over leading bracket */
1768 pass_next
= backq
= 0;
1769 ss
= (char *)string
;
1770 while (c
= string
[i
])
1777 ADVANCE_CHAR (string
, slen
, i
);
1780 else if ((flags
& 1) == 0 && c
== '\\')
1790 ADVANCE_CHAR (string
, slen
, i
);
1793 else if ((flags
& 1) == 0 && c
== '`')
1799 else if ((flags
& 1) == 0 && c
== open
)
1805 else if (c
== close
)
1813 else if ((flags
& 1) == 0 && (c
== '\'' || c
== '"'))
1815 i
= (c
== '\'') ? skip_single_quoted (ss
, slen
, ++i
, 0)
1816 : skip_double_quoted (ss
, slen
, ++i
, 0);
1817 /* no increment, the skip functions increment past the closing quote. */
1819 else if ((flags
&1) == 0 && c
== '$' && (string
[i
+1] == LPAREN
|| string
[i
+1] == LBRACE
))
1822 if (string
[si
] == '\0')
1825 /* XXX - extract_command_subst here? */
1826 if (string
[i
+1] == LPAREN
)
1827 temp
= extract_delimited_string (ss
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
); /* ) */
1829 temp
= extract_dollar_brace_string (ss
, &si
, 0, SX_NOALLOC
);
1831 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1834 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
1840 ADVANCE_CHAR (string
, slen
, i
);
1846 #if defined (ARRAY_VARS)
1847 /* Flags has 1 as a reserved value, since skip_matched_pair uses it for
1848 skipping over quoted strings and taking the first instance of the
1849 closing character. */
1851 skipsubscript (string
, start
, flags
)
1855 return (skip_matched_pair (string
, start
, '[', ']', flags
));
1859 /* Skip characters in STRING until we find a character in DELIMS, and return
1860 the index of that character. START is the index into string at which we
1861 begin. This is similar in spirit to strpbrk, but it returns an index into
1862 STRING and takes a starting index. This little piece of code knows quite
1863 a lot of shell syntax. It's very similar to skip_double_quoted and other
1864 functions of that ilk. */
1866 skip_to_delim (string
, start
, delims
, flags
)
1872 int i
, pass_next
, backq
, dquote
, si
, c
, oldjmp
;
1873 int invert
, skipquote
, skipcmd
, noprocsub
, completeflag
;
1874 int arithexp
, skipcol
;
1876 char *temp
, open
[3];
1879 slen
= strlen (string
+ start
) + start
;
1880 oldjmp
= no_longjmp_on_fatal_error
;
1881 if (flags
& SD_NOJMP
)
1882 no_longjmp_on_fatal_error
= 1;
1883 invert
= (flags
& SD_INVERT
);
1884 skipcmd
= (flags
& SD_NOSKIPCMD
) == 0;
1885 noprocsub
= (flags
& SD_NOPROCSUB
);
1886 completeflag
= (flags
& SD_COMPLETE
) ? SX_COMPLETE
: 0;
1888 arithexp
= (flags
& SD_ARITHEXP
);
1892 pass_next
= backq
= dquote
= 0;
1893 while (c
= string
[i
])
1895 /* If this is non-zero, we should not let quote characters be delimiters
1896 and the current character is a single or double quote. We should not
1897 test whether or not it's a delimiter until after we skip single- or
1898 double-quoted strings. */
1899 skipquote
= ((flags
& SD_NOQUOTEDELIM
) && (c
== '\'' || c
=='"'));
1905 ADVANCE_CHAR (string
, slen
, i
);
1918 ADVANCE_CHAR (string
, slen
, i
);
1927 else if (arithexp
&& skipcol
&& c
== ':')
1933 else if (arithexp
&& c
== '?')
1939 else if (skipquote
== 0 && invert
== 0 && member (c
, delims
))
1941 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
1942 quoted strings when looking for the history expansion character as a
1944 /* special case for programmable completion which takes place before
1945 parser converts backslash-escaped single quotes between $'...' to
1946 `regular' single-quoted strings. */
1947 else if (completeflag
&& i
> 0 && string
[i
-1] == '$' && c
== '\'')
1948 i
= skip_single_quoted (string
, slen
, ++i
, SX_COMPLETE
);
1950 i
= skip_single_quoted (string
, slen
, ++i
, 0);
1952 i
= skip_double_quoted (string
, slen
, ++i
, completeflag
);
1953 else if (c
== LPAREN
&& arithexp
)
1956 if (string
[si
] == '\0')
1959 temp
= extract_delimited_string (string
, &si
, "(", "(", ")", SX_NOALLOC
); /* ) */
1961 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
1966 else if (c
== '$' && ((skipcmd
&& string
[i
+1] == LPAREN
) || string
[i
+1] == LBRACE
))
1969 if (string
[si
] == '\0')
1972 if (string
[i
+1] == LPAREN
)
1973 temp
= extract_delimited_string (string
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
); /* ) */
1975 temp
= extract_dollar_brace_string (string
, &si
, 0, SX_NOALLOC
);
1976 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1978 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
1983 #if defined (PROCESS_SUBSTITUTION)
1984 else if (skipcmd
&& noprocsub
== 0 && (c
== '<' || c
== '>') && string
[i
+1] == LPAREN
)
1987 if (string
[si
] == '\0')
1990 temp
= extract_delimited_string (string
, &si
, (c
== '<') ? "<(" : ">(", "(", ")", SX_COMMAND
|SX_NOALLOC
); /* )) */
1991 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1993 if (string
[i
] == '\0')
1998 #endif /* PROCESS_SUBSTITUTION */
1999 #if defined (EXTENDED_GLOB)
2000 else if ((flags
& SD_EXTGLOB
) && extended_glob
&& string
[i
+1] == LPAREN
&& member (c
, "?*+!@"))
2003 if (string
[si
] == '\0')
2009 temp
= extract_delimited_string (string
, &si
, open
, "(", ")", SX_NOALLOC
); /* ) */
2011 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2013 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2019 else if ((flags
& SD_GLOB
) && c
== LBRACK
)
2022 if (string
[si
] == '\0')
2025 temp
= extract_delimited_string (string
, &si
, "[", "[", "]", SX_NOALLOC
); /* ] */
2028 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2033 else if ((skipquote
|| invert
) && (member (c
, delims
) == 0))
2036 ADVANCE_CHAR (string
, slen
, i
);
2042 #if defined (BANG_HISTORY)
2043 /* Skip to the history expansion character (delims[0]), paying attention to
2044 quoted strings and command and process substitution. This is a stripped-
2045 down version of skip_to_delims. The essential difference is that this
2046 resets the quoting state when starting a command substitution */
2048 skip_to_histexp (string
, start
, delims
, flags
)
2054 int i
, pass_next
, backq
, dquote
, c
, oldjmp
;
2055 int histexp_comsub
, histexp_backq
, old_dquote
;
2059 slen
= strlen (string
+ start
) + start
;
2060 oldjmp
= no_longjmp_on_fatal_error
;
2061 if (flags
& SD_NOJMP
)
2062 no_longjmp_on_fatal_error
= 1;
2064 histexp_comsub
= histexp_backq
= old_dquote
= 0;
2067 pass_next
= backq
= dquote
= 0;
2068 while (c
= string
[i
])
2075 ADVANCE_CHAR (string
, slen
, i
);
2084 else if (backq
&& c
== '`')
2088 dquote
= old_dquote
;
2096 old_dquote
= dquote
; /* simple - one level for now */
2101 /* When in double quotes, act as if the double quote is a member of
2102 history_no_expand_chars, like the history library does */
2103 else if (dquote
&& c
== delims
[0] && string
[i
+1] == '"')
2108 else if (c
== delims
[0])
2110 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2111 quoted strings when looking for the history expansion character as a
2113 else if (dquote
&& c
== '\'')
2119 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2120 /* The posixly_correct test makes posix-mode shells allow double quotes
2121 to quote the history expansion character */
2122 else if (posixly_correct
== 0 && c
== '"')
2124 dquote
= 1 - dquote
;
2129 i
= skip_double_quoted (string
, slen
, ++i
, 0);
2130 #if defined (PROCESS_SUBSTITUTION)
2131 else if ((c
== '$' || c
== '<' || c
== '>') && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2133 else if (c
== '$' && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2136 if (string
[i
+2] == '\0')
2140 old_dquote
= dquote
;
2143 else if (histexp_comsub
&& c
== RPAREN
)
2146 dquote
= old_dquote
;
2150 else if (backq
) /* placeholder */
2152 ADVANCE_CHAR (string
, slen
, i
);
2156 ADVANCE_CHAR (string
, slen
, i
);
2161 #endif /* BANG_HISTORY */
2163 #if defined (READLINE)
2164 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
2165 an unclosed quoted string), or if the character at EINDEX is quoted
2166 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
2167 single and double-quoted string parsing functions should not return an
2168 error if there are unclosed quotes or braces. The characters that this
2169 recognizes need to be the same as the contents of
2170 rl_completer_quote_characters. */
2173 char_is_quoted (string
, eindex
)
2177 int i
, pass_next
, c
, oldjmp
;
2181 slen
= strlen (string
);
2182 oldjmp
= no_longjmp_on_fatal_error
;
2183 no_longjmp_on_fatal_error
= 1;
2192 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2194 ADVANCE_CHAR (string
, slen
, i
);
2203 else if (c
== '$' && string
[i
+1] == '\'' && string
[i
+2])
2206 i
= skip_single_quoted (string
, slen
, i
, SX_COMPLETE
);
2210 else if (c
== '\'' || c
== '"')
2212 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, ++i
, 0)
2213 : skip_double_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2216 /* no increment, the skip_xxx functions go one past end */
2219 ADVANCE_CHAR (string
, slen
, i
);
2226 unclosed_pair (string
, eindex
, openstr
)
2231 int i
, pass_next
, openc
, olen
;
2235 slen
= strlen (string
);
2236 olen
= strlen (openstr
);
2237 i
= pass_next
= openc
= 0;
2243 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2245 ADVANCE_CHAR (string
, slen
, i
);
2248 else if (string
[i
] == '\\')
2254 else if (STREQN (string
+ i
, openstr
, olen
))
2259 /* XXX - may want to handle $'...' specially here */
2260 else if (string
[i
] == '\'' || string
[i
] == '"')
2262 i
= (string
[i
] == '\'') ? skip_single_quoted (string
, slen
, i
, 0)
2263 : skip_double_quoted (string
, slen
, i
, SX_COMPLETE
);
2268 ADVANCE_CHAR (string
, slen
, i
);
2273 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
2274 individual words. If DELIMS is NULL, the current value of $IFS is used
2275 to split the string, and the function follows the shell field splitting
2276 rules. SENTINEL is an index to look for. NWP, if non-NULL,
2277 gets the number of words in the returned list. CWP, if non-NULL, gets
2278 the index of the word containing SENTINEL. Non-whitespace chars in
2279 DELIMS delimit separate fields. This is used by programmable completion. */
2281 split_at_delims (string
, slen
, delims
, sentinel
, flags
, nwp
, cwp
)
2285 int sentinel
, flags
;
2288 int ts
, te
, i
, nw
, cw
, ifs_split
, dflags
;
2289 char *token
, *d
, *d2
;
2290 WORD_LIST
*ret
, *tl
;
2292 if (string
== 0 || *string
== '\0')
2298 return ((WORD_LIST
*)NULL
);
2301 d
= (delims
== 0) ? ifs_value
: delims
;
2302 ifs_split
= delims
== 0;
2304 /* Make d2 the non-whitespace characters in delims */
2309 #if defined (HANDLE_MULTIBYTE)
2310 size_t mblength
= 1;
2314 slength
= strlen (delims
);
2315 d2
= (char *)xmalloc (slength
+ 1);
2319 #if defined (HANDLE_MULTIBYTE)
2320 mbstate_t state_bak
;
2322 mblength
= MBRLEN (delims
+ i
, slength
, &state
);
2323 if (MB_INVALIDCH (mblength
))
2325 else if (mblength
> 1)
2327 memcpy (d2
+ ts
, delims
+ i
, mblength
);
2330 slength
-= mblength
;
2334 if (whitespace (delims
[i
]) == 0)
2335 d2
[ts
++] = delims
[i
];
2343 ret
= (WORD_LIST
*)NULL
;
2345 /* Remove sequences of whitespace characters at the start of the string, as
2346 long as those characters are delimiters. */
2347 for (i
= 0; member (string
[i
], d
) && spctabnl (string
[i
]); i
++)
2349 if (string
[i
] == '\0')
2358 dflags
= flags
|SD_NOJMP
;
2361 te
= skip_to_delim (string
, ts
, d
, dflags
);
2363 /* If we have a non-whitespace delimiter character, use it to make a
2364 separate field. This is just about what $IFS splitting does and
2365 is closer to the behavior of the shell parser. */
2366 if (ts
== te
&& d2
&& member (string
[ts
], d2
))
2369 /* If we're using IFS splitting, the non-whitespace delimiter char
2370 and any additional IFS whitespace delimits a field. */
2372 while (member (string
[te
], d
) && spctabnl (string
[te
]) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2375 while (member (string
[te
], d2
) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2379 token
= substring (string
, ts
, te
);
2381 ret
= add_string_to_list (token
, ret
); /* XXX */
2385 if (sentinel
>= ts
&& sentinel
<= te
)
2388 /* If the cursor is at whitespace just before word start, set the
2389 sentinel word to the current word. */
2390 if (cwp
&& cw
== -1 && sentinel
== ts
-1)
2393 /* If the cursor is at whitespace between two words, make a new, empty
2394 word, add it before (well, after, since the list is in reverse order)
2395 the word we just added, and set the current word to that one. */
2396 if (cwp
&& cw
== -1 && sentinel
< ts
)
2398 tl
= make_word_list (make_word (""), ret
->next
);
2404 if (string
[te
] == 0)
2408 /* XXX - honor SD_NOQUOTEDELIM here */
2409 while (member (string
[i
], d
) && (ifs_split
|| spctabnl(string
[i
])) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2418 /* Special case for SENTINEL at the end of STRING. If we haven't found
2419 the word containing SENTINEL yet, and the index we're looking for is at
2420 the end of STRING (or past the end of the previously-found token,
2421 possible if the end of the line is composed solely of IFS whitespace)
2422 add an additional null argument and set the current word pointer to that. */
2423 if (cwp
&& cw
== -1 && (sentinel
>= slen
|| sentinel
>= te
))
2425 if (whitespace (string
[sentinel
- 1]))
2428 ret
= add_string_to_list (token
, ret
);
2441 return (REVERSE_LIST (ret
, WORD_LIST
*));
2443 #endif /* READLINE */
2447 /* Extract the name of the variable to bind to from the assignment string. */
2449 assignment_name (string
)
2455 offset
= assignment (string
, 0);
2457 return (char *)NULL
;
2458 temp
= substring (string
, 0, offset
);
2463 /* **************************************************************** */
2465 /* Functions to convert strings to WORD_LISTs and vice versa */
2467 /* **************************************************************** */
2469 /* Return a single string of all the words in LIST. SEP is the separator
2470 to put between individual elements of LIST in the output string. */
2472 string_list_internal (list
, sep
)
2476 register WORD_LIST
*t
;
2478 size_t word_len
, sep_len
, result_size
;
2481 return ((char *)NULL
);
2483 /* Short-circuit quickly if we don't need to separate anything. */
2484 if (list
->next
== 0)
2485 return (savestring (list
->word
->word
));
2487 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
2488 sep_len
= STRLEN (sep
);
2491 for (t
= list
; t
; t
= t
->next
)
2494 result_size
+= sep_len
;
2495 result_size
+= strlen (t
->word
->word
);
2498 r
= result
= (char *)xmalloc (result_size
+ 1);
2500 for (t
= list
; t
; t
= t
->next
)
2502 if (t
!= list
&& sep_len
)
2506 FASTCOPY (sep
, r
, sep_len
);
2513 word_len
= strlen (t
->word
->word
);
2514 FASTCOPY (t
->word
->word
, r
, word_len
);
2522 /* Return a single string of all the words present in LIST, separating
2523 each word with a space. */
2528 return (string_list_internal (list
, " "));
2531 /* An external interface that can be used by the rest of the shell to
2532 obtain a string containing the first character in $IFS. Handles all
2533 the multibyte complications. If LENP is non-null, it is set to the
2534 length of the returned string. */
2536 ifs_firstchar (lenp
)
2542 ret
= xmalloc (MB_LEN_MAX
+ 1);
2543 #if defined (HANDLE_MULTIBYTE)
2544 if (ifs_firstc_len
== 1)
2546 ret
[0] = ifs_firstc
[0];
2548 len
= ret
[0] ? 1 : 0;
2552 memcpy (ret
, ifs_firstc
, ifs_firstc_len
);
2553 ret
[len
= ifs_firstc_len
] = '\0';
2556 ret
[0] = ifs_firstc
;
2558 len
= ret
[0] ? 0 : 1;
2567 /* Return a single string of all the words present in LIST, obeying the
2568 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
2569 expansion [of $*] appears within a double quoted string, it expands
2570 to a single field with the value of each parameter separated by the
2571 first character of the IFS variable, or by a <space> if IFS is unset." */
2572 /* Posix interpretation 888 changes this when IFS is null by specifying
2573 that when unquoted, this expands to separate arguments */
2575 string_list_dollar_star (list
, quoted
, flags
)
2580 #if defined (HANDLE_MULTIBYTE)
2581 # if defined (__GNUC__)
2582 char sep
[MB_CUR_MAX
+ 1];
2590 #if defined (HANDLE_MULTIBYTE)
2591 # if !defined (__GNUC__)
2592 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2593 # endif /* !__GNUC__ */
2594 if (ifs_firstc_len
== 1)
2596 sep
[0] = ifs_firstc
[0];
2601 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
2602 sep
[ifs_firstc_len
] = '\0';
2605 sep
[0] = ifs_firstc
;
2609 ret
= string_list_internal (list
, sep
);
2610 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2616 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2617 is non-zero, the $@ appears within double quotes, and we should quote
2618 the list before converting it into a string. If IFS is unset, and the
2619 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2620 in the words in the list, because the default value of $IFS is
2621 <space><tab><newline>, IFS characters in the words in the list should
2622 also be split. If IFS is null, and the word is not quoted, we need
2623 to quote the words in the list to preserve the positional parameters
2625 Valid values for the FLAGS argument are the PF_ flags in command.h,
2626 the only one we care about is PF_ASSIGNRHS. $@ is supposed to expand
2627 to the positional parameters separated by spaces no matter what IFS is
2628 set to if in a context where word splitting is not performed. The only
2629 one that we didn't handle before is assignment statement arguments to
2630 declaration builtins like `declare'. */
2632 string_list_dollar_at (list
, quoted
, flags
)
2638 #if defined (HANDLE_MULTIBYTE)
2639 # if defined (__GNUC__)
2640 char sep
[MB_CUR_MAX
+ 1];
2643 # endif /* !__GNUC__ */
2649 /* XXX this could just be ifs = ifs_value; */
2650 ifs
= ifs_var
? value_cell (ifs_var
) : (char *)0;
2652 #if defined (HANDLE_MULTIBYTE)
2653 # if !defined (__GNUC__)
2654 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2655 # endif /* !__GNUC__ */
2656 /* XXX - testing PF_ASSIGNRHS to make sure positional parameters are
2657 separated with a space even when word splitting will not occur. */
2658 if (flags
& PF_ASSIGNRHS
)
2663 else if (ifs
&& *ifs
)
2665 if (ifs_firstc_len
== 1)
2667 sep
[0] = ifs_firstc
[0];
2672 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
2673 sep
[ifs_firstc_len
] = '\0';
2681 #else /* !HANDLE_MULTIBYTE */
2682 /* XXX - PF_ASSIGNRHS means no word splitting, so we want positional
2683 parameters separated by a space. */
2684 sep
[0] = ((flags
& PF_ASSIGNRHS
) || ifs
== 0 || *ifs
== 0) ? ' ' : *ifs
;
2686 #endif /* !HANDLE_MULTIBYTE */
2688 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
2689 it now that quote_escapes quotes spaces */
2690 tlist
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
2692 : list_quote_escapes (list
);
2694 ret
= string_list_internal (tlist
, sep
);
2695 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2701 /* Turn the positional parameters into a string, understanding quoting and
2702 the various subtleties of using the first character of $IFS as the
2703 separator. Calls string_list_dollar_at, string_list_dollar_star, and
2704 string_list as appropriate. */
2705 /* This needs to fully understand the additional contexts where word
2706 splitting does not occur (W_ASSIGNRHS, etc.) */
2708 string_list_pos_params (pchar
, list
, quoted
, pflags
)
2716 if (pchar
== '*' && (quoted
& Q_DOUBLE_QUOTES
))
2718 tlist
= quote_list (list
);
2719 word_list_remove_quoted_nulls (tlist
);
2720 ret
= string_list_dollar_star (tlist
, 0, 0);
2722 else if (pchar
== '*' && (quoted
& Q_HERE_DOCUMENT
))
2724 tlist
= quote_list (list
);
2725 word_list_remove_quoted_nulls (tlist
);
2726 ret
= string_list (tlist
);
2728 else if (pchar
== '*' && quoted
== 0 && ifs_is_null
) /* XXX */
2729 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
2730 else if (pchar
== '*' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
)) /* XXX */
2731 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
2732 else if (pchar
== '*')
2734 /* Even when unquoted, string_list_dollar_star does the right thing
2735 making sure that the first character of $IFS is used as the
2737 ret
= string_list_dollar_star (list
, quoted
, 0);
2739 else if (pchar
== '@' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
2740 /* We use string_list_dollar_at, but only if the string is quoted, since
2741 that quotes the escapes if it's not, which we don't want. We could
2742 use string_list (the old code did), but that doesn't do the right
2743 thing if the first character of $IFS is not a space. We use
2744 string_list_dollar_star if the string is unquoted so we make sure that
2745 the elements of $@ are separated by the first character of $IFS for
2747 ret
= string_list_dollar_at (list
, quoted
, 0);
2748 else if (pchar
== '@' && quoted
== 0 && ifs_is_null
) /* XXX */
2749 ret
= string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
2750 else if (pchar
== '@' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
2751 ret
= string_list_dollar_at (list
, quoted
, pflags
); /* Posix interp 888 */
2752 else if (pchar
== '@')
2753 ret
= string_list_dollar_star (list
, quoted
, 0);
2755 ret
= string_list ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? quote_list (list
) : list
);
2760 /* Return the list of words present in STRING. Separate the string into
2761 words at any of the characters found in SEPARATORS. If QUOTED is
2762 non-zero then word in the list will have its quoted flag set, otherwise
2763 the quoted flag is left as make_word () deemed fit.
2765 This obeys the P1003.2 word splitting semantics. If `separators' is
2766 exactly <space><tab><newline>, then the splitting algorithm is that of
2767 the Bourne shell, which treats any sequence of characters from `separators'
2768 as a delimiter. If IFS is unset, which results in `separators' being set
2769 to "", no splitting occurs. If separators has some other value, the
2770 following rules are applied (`IFS white space' means zero or more
2771 occurrences of <space>, <tab>, or <newline>, as long as those characters
2772 are in `separators'):
2774 1) IFS white space is ignored at the start and the end of the
2776 2) Each occurrence of a character in `separators' that is not
2777 IFS white space, along with any adjacent occurrences of
2778 IFS white space delimits a field.
2779 3) Any nonzero-length sequence of IFS white space delimits a field.
2782 /* BEWARE! list_string strips null arguments. Don't call it twice and
2783 expect to have "" preserved! */
2785 /* This performs word splitting and quoted null character removal on
2788 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2789 : (c) == (separators)[0]) \
2792 /* member of the space character class in the current locale */
2793 #define ifs_whitespace(c) ISSPACE(c)
2795 /* "adjacent IFS white space" */
2796 #define ifs_whitesep(c) ((sh_style_split || separators == 0) ? spctabnl (c) \
2797 : ifs_whitespace (c))
2800 list_string (string
, separators
, quoted
)
2801 register char *string
, *separators
;
2806 char *current_word
, *s
;
2807 int sindex
, sh_style_split
, whitesep
, xflags
, free_word
;
2810 if (!string
|| !*string
)
2811 return ((WORD_LIST
*)NULL
);
2813 sh_style_split
= separators
&& separators
[0] == ' ' &&
2814 separators
[1] == '\t' &&
2815 separators
[2] == '\n' &&
2816 separators
[3] == '\0';
2817 for (xflags
= 0, s
= ifs_value
; s
&& *s
; s
++)
2819 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
2820 else if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
2824 /* Remove sequences of whitespace at the beginning of STRING, as
2825 long as those characters appear in IFS. Do not do this if
2826 STRING is quoted or if there are no separator characters. We use the
2827 Posix definition of whitespace as a member of the space character
2828 class in the current locale. */
2830 if (!quoted
|| !separators
|| !*separators
)
2832 /* issep() requires that separators be non-null, and always returns 0 if
2833 separator is the empty string, so don't bother if we get an empty string
2834 for separators. We already returned NULL above if STRING is empty. */
2835 if (!quoted
&& separators
&& *separators
)
2838 for (s
= string
; *s
&& issep (*s
) && ifs_whitespace (*s
); s
++);
2841 return ((WORD_LIST
*)NULL
);
2846 /* OK, now STRING points to a word that does not begin with white space.
2847 The splitting algorithm is:
2848 extract a word, stopping at a separator
2849 skip sequences of whitespace characters as long as they are separators
2850 This obeys the field splitting rules in Posix.2. */
2851 slen
= STRLEN (string
);
2852 for (result
= (WORD_LIST
*)NULL
, sindex
= 0; string
[sindex
]; )
2854 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
2855 possible, but need it in string_extract_verbatim for bounds checking */
2856 current_word
= string_extract_verbatim (string
, slen
, &sindex
, separators
, xflags
);
2857 if (current_word
== 0)
2860 free_word
= 1; /* If non-zero, we free current_word */
2862 /* If we have a quoted empty string, add a quoted null argument. We
2863 want to preserve the quoted null character iff this is a quoted
2864 empty string; otherwise the quoted null characters are removed
2866 if (QUOTED_NULL (current_word
))
2868 t
= alloc_word_desc ();
2869 t
->word
= make_quoted_char ('\0');
2870 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
2871 result
= make_word_list (t
, result
);
2873 else if (current_word
[0] != '\0')
2875 /* If we have something, then add it regardless. However,
2876 perform quoted null character removal on the current word. */
2877 remove_quoted_nulls (current_word
);
2879 /* We don't want to set the word flags based on the string contents
2880 here -- that's mostly for the parser -- so we just allocate a
2881 WORD_DESC *, assign current_word (noting that we don't want to
2882 free it), and skip all of make_word. */
2883 t
= alloc_word_desc ();
2884 t
->word
= current_word
;
2885 result
= make_word_list (t
, result
);
2887 result
->word
->flags
&= ~W_HASQUOTEDNULL
; /* just to be sure */
2888 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
2889 result
->word
->flags
|= W_QUOTED
;
2890 /* If removing quoted null characters leaves an empty word, note
2891 that we saw this for the caller to act on. */
2892 if (current_word
== 0 || current_word
[0] == '\0')
2893 result
->word
->flags
|= W_SAWQUOTEDNULL
;
2896 /* If we're not doing sequences of separators in the traditional
2897 Bourne shell style, then add a quoted null argument. */
2898 else if (!sh_style_split
&& !ifs_whitespace (string
[sindex
]))
2900 t
= alloc_word_desc ();
2901 t
->word
= make_quoted_char ('\0');
2902 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
2903 result
= make_word_list (t
, result
);
2907 free (current_word
);
2909 /* Note whether or not the separator is IFS whitespace, used later. */
2910 whitesep
= string
[sindex
] && ifs_whitesep (string
[sindex
]);
2912 /* Move past the current separator character. */
2916 ADVANCE_CHAR (string
, slen
, sindex
);
2919 /* Now skip sequences of whitespace characters if they are
2920 in the list of separators. */
2921 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && issep (string
[sindex
]))
2924 /* If the first separator was IFS whitespace and the current character
2925 is a non-whitespace IFS character, it should be part of the current
2926 field delimiter, not a separate delimiter that would result in an
2927 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2928 if (string
[sindex
] && whitesep
&& issep (string
[sindex
]) && !ifs_whitesep (string
[sindex
]))
2931 /* An IFS character that is not IFS white space, along with any
2932 adjacent IFS white space, shall delimit a field. (SUSv3) */
2933 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && isifs (string
[sindex
]))
2937 return (REVERSE_LIST (result
, WORD_LIST
*));
2940 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2941 ENDPTR is set to the first character after the word. This is used by
2944 This is never called with SEPARATORS != $IFS, and takes advantage of that.
2946 XXX - this function is very similar to list_string; they should be
2949 /* character is in $IFS */
2950 #define islocalsep(c) (local_cmap[(unsigned char)(c)] != 0)
2953 get_word_from_string (stringp
, separators
, endptr
)
2954 char **stringp
, *separators
, **endptr
;
2958 int sindex
, sh_style_split
, whitesep
, xflags
;
2959 unsigned char local_cmap
[UCHAR_MAX
+1]; /* really only need single-byte chars here */
2962 if (!stringp
|| !*stringp
|| !**stringp
)
2963 return ((char *)NULL
);
2965 sh_style_split
= separators
&& separators
[0] == ' ' &&
2966 separators
[1] == '\t' &&
2967 separators
[2] == '\n' &&
2968 separators
[3] == '\0';
2969 memset (local_cmap
, '\0', sizeof (local_cmap
));
2970 for (xflags
= 0, s
= separators
; s
&& *s
; s
++)
2972 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
2973 if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
2974 local_cmap
[(unsigned char)*s
] = 1; /* local charmap of separators */
2980 /* Remove sequences of whitespace at the beginning of STRING, as
2981 long as those characters appear in SEPARATORS. This happens if
2982 SEPARATORS == $' \t\n' or if IFS is unset. */
2983 if (sh_style_split
|| separators
== 0)
2984 for (; *s
&& spctabnl (*s
) && islocalsep (*s
); s
++);
2986 for (; *s
&& ifs_whitespace (*s
) && islocalsep (*s
); s
++);
2988 /* If the string is nothing but whitespace, update it and return. */
2994 return ((char *)NULL
);
2997 /* OK, S points to a word that does not begin with white space.
2998 Now extract a word, stopping at a separator, save a pointer to
2999 the first character after the word, then skip sequences of spc,
3000 tab, or nl as long as they are separators.
3002 This obeys the field splitting rules in Posix.2. */
3004 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3005 possible, but need it in string_extract_verbatim for bounds checking */
3007 current_word
= string_extract_verbatim (s
, slen
, &sindex
, separators
, xflags
);
3009 /* Set ENDPTR to the first character after the end of the word. */
3011 *endptr
= s
+ sindex
;
3013 /* Note whether or not the separator is IFS whitespace, used later. */
3014 whitesep
= s
[sindex
] && ifs_whitesep (s
[sindex
]);
3016 /* Move past the current separator character. */
3020 ADVANCE_CHAR (s
, slen
, sindex
);
3023 /* Now skip sequences of space, tab, or newline characters if they are
3024 in the list of separators. */
3025 while (s
[sindex
] && spctabnl (s
[sindex
]) && islocalsep (s
[sindex
]))
3028 /* If the first separator was IFS whitespace and the current character is
3029 a non-whitespace IFS character, it should be part of the current field
3030 delimiter, not a separate delimiter that would result in an empty field.
3031 Look at POSIX.2, 3.6.5, (3)(b). */
3032 if (s
[sindex
] && whitesep
&& islocalsep (s
[sindex
]) && !ifs_whitesep (s
[sindex
]))
3035 /* An IFS character that is not IFS white space, along with any adjacent
3036 IFS white space, shall delimit a field. */
3037 while (s
[sindex
] && ifs_whitesep (s
[sindex
]) && islocalsep(s
[sindex
]))
3041 /* Update STRING to point to the next field. */
3042 *stringp
= s
+ sindex
;
3043 return (current_word
);
3046 /* Remove IFS white space at the end of STRING. Start at the end
3047 of the string and walk backwards until the beginning of the string
3048 or we find a character that's not IFS white space and not CTLESC.
3049 Only let CTLESC escape a white space character if SAW_ESCAPE is
3052 strip_trailing_ifs_whitespace (string
, separators
, saw_escape
)
3053 char *string
, *separators
;
3058 s
= string
+ STRLEN (string
) - 1;
3059 while (s
> string
&& ((spctabnl (*s
) && isifs (*s
)) ||
3060 (saw_escape
&& *s
== CTLESC
&& spctabnl (s
[1]))))
3068 /* Split STRING into words at whitespace. Obeys shell-style quoting with
3069 backslashes, single and double quotes. */
3071 list_string_with_quotes (string
)
3077 int c
, i
, tokstart
, len
;
3079 for (s
= string
; s
&& *s
&& spctabnl (*s
); s
++)
3081 if (s
== 0 || *s
== 0)
3082 return ((WORD_LIST
*)NULL
);
3086 list
= (WORD_LIST
*)NULL
;
3097 i
= skip_single_quoted (s
, s_len
, ++i
, 0);
3099 i
= skip_double_quoted (s
, s_len
, ++i
, 0);
3100 else if (c
== 0 || spctabnl (c
))
3102 /* We have found the end of a token. Make a word out of it and
3103 add it to the word list. */
3104 token
= substring (s
, tokstart
, i
);
3105 list
= add_string_to_list (token
, list
);
3107 while (spctabnl (s
[i
]))
3115 i
++; /* normal character */
3117 return (REVERSE_LIST (list
, WORD_LIST
*));
3121 /********************************************************/
3123 /* Functions to perform assignment statements */
3125 /********************************************************/
3127 #if defined (ARRAY_VARS)
3129 do_compound_assignment (name
, value
, flags
)
3134 int mklocal
, mkassoc
, mkglobal
, chklocal
;
3136 char *newname
; /* used for local nameref references */
3138 mklocal
= flags
& ASS_MKLOCAL
;
3139 mkassoc
= flags
& ASS_MKASSOC
;
3140 mkglobal
= flags
& ASS_MKGLOBAL
;
3141 chklocal
= flags
& ASS_CHKLOCAL
;
3143 if (mklocal
&& variable_context
)
3145 v
= find_variable (name
); /* follows namerefs */
3146 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : v
->name
;
3147 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3150 err_readonly (name
);
3151 return (v
); /* XXX */
3153 list
= expand_compound_array_assignment (v
, value
, flags
);
3155 v
= make_local_assoc_variable (newname
, 0);
3156 else if (v
== 0 || (array_p (v
) == 0 && assoc_p (v
) == 0) || v
->context
!= variable_context
)
3157 v
= make_local_array_variable (newname
, 0);
3159 assign_compound_array_list (v
, list
, flags
);
3161 dispose_words (list
);
3163 /* In a function but forcing assignment in global context. CHKLOCAL means to
3164 check for an existing local variable first. */
3165 else if (mkglobal
&& variable_context
)
3167 v
= chklocal
? find_variable (name
) : 0;
3168 if (v
&& (local_p (v
) == 0 || v
->context
!= variable_context
))
3171 v
= find_global_variable (name
);
3172 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3175 err_readonly (name
);
3176 return (v
); /* XXX */
3179 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : name
;
3180 list
= expand_compound_array_assignment (v
, value
, flags
);
3181 if (v
== 0 && mkassoc
)
3182 v
= make_new_assoc_variable (newname
);
3183 else if (v
&& mkassoc
&& assoc_p (v
) == 0)
3184 v
= convert_var_to_assoc (v
);
3186 v
= make_new_array_variable (newname
);
3187 else if (v
&& mkassoc
== 0 && array_p (v
) == 0)
3188 v
= convert_var_to_array (v
);
3190 assign_compound_array_list (v
, list
, flags
);
3192 dispose_words (list
);
3196 v
= assign_array_from_string (name
, value
, flags
);
3197 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3200 err_readonly (name
);
3201 return (v
); /* XXX */
3209 /* Given STRING, an assignment string, get the value of the right side
3210 of the `=', and bind it to the left side. If EXPAND is true, then
3211 perform parameter expansion, command substitution, and arithmetic
3212 expansion on the right-hand side. Perform tilde expansion in any
3213 case. Do not perform word splitting on the result of expansion. */
3215 do_assignment_internal (word
, expand
)
3216 const WORD_DESC
*word
;
3219 int offset
, appendop
, assign_list
, aflags
, retval
;
3220 char *name
, *value
, *temp
;
3222 #if defined (ARRAY_VARS)
3228 if (word
== 0 || word
->word
== 0)
3231 appendop
= assign_list
= aflags
= 0;
3232 string
= word
->word
;
3233 offset
= assignment (string
, 0);
3234 name
= savestring (string
);
3235 value
= (char *)NULL
;
3237 if (name
[offset
] == '=')
3239 if (name
[offset
- 1] == '+')
3242 name
[offset
- 1] = '\0';
3245 name
[offset
] = 0; /* might need this set later */
3246 temp
= name
+ offset
+ 1;
3248 #if defined (ARRAY_VARS)
3249 if (expand
&& (word
->flags
& W_COMPASSIGN
))
3251 assign_list
= ni
= 1;
3252 value
= extract_array_assignment_list (temp
, &ni
);
3256 if (expand
&& temp
[0])
3257 value
= expand_string_if_necessary (temp
, 0, expand_string_assignment
);
3259 value
= savestring (temp
);
3264 value
= (char *)xmalloc (1);
3268 if (echo_command_at_execute
|| debug_info
)
3271 name
[offset
- 1] = '+';
3272 xtrace_print_assignment (name
, value
, assign_list
, 1);
3274 name
[offset
- 1] = '\0';
3277 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
3280 aflags
|= ASS_APPEND
;
3282 #if defined (ARRAY_VARS)
3283 if (t
= mbschr (name
, LBRACK
))
3287 report_error (_("%s: cannot assign list to array member"), name
);
3290 entry
= assign_array_element (name
, value
, aflags
);
3294 else if (assign_list
)
3296 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_CHKLOCAL
))
3297 aflags
|= ASS_CHKLOCAL
;
3298 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
) == 0)
3299 aflags
|= ASS_MKLOCAL
;
3300 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
))
3301 aflags
|= ASS_MKGLOBAL
;
3302 if (word
->flags
& W_ASSIGNASSOC
)
3303 aflags
|= ASS_MKASSOC
;
3304 entry
= do_compound_assignment (name
, value
, aflags
);
3307 #endif /* ARRAY_VARS */
3308 entry
= bind_variable (name
, value
, aflags
);
3311 stupidly_hack_special_variables (entry
->name
); /* might be a nameref */
3313 stupidly_hack_special_variables (name
);
3315 /* Return 1 if the assignment seems to have been performed correctly. */
3316 if (entry
== 0 || readonly_p (entry
))
3317 retval
= 0; /* assignment failure */
3318 else if (noassign_p (entry
))
3320 set_exit_status (EXECUTION_FAILURE
);
3321 retval
= 1; /* error status, but not assignment failure */
3326 if (entry
&& retval
!= 0 && noassign_p (entry
) == 0)
3327 VUNSETATTR (entry
, att_invisible
);
3329 ASSIGN_RETURN (retval
);
3332 /* Perform the assignment statement in STRING, and expand the
3333 right side by doing tilde, command and parameter expansion. */
3335 do_assignment (string
)
3340 td
.flags
= W_ASSIGNMENT
;
3343 return do_assignment_internal (&td
, 1);
3347 do_word_assignment (word
, flags
)
3351 return do_assignment_internal (word
, 1);
3354 /* Given STRING, an assignment string, get the value of the right side
3355 of the `=', and bind it to the left side. Do not perform any word
3356 expansions on the right hand side. */
3358 do_assignment_no_expand (string
)
3363 td
.flags
= W_ASSIGNMENT
;
3366 return (do_assignment_internal (&td
, 0));
3369 /***************************************************
3371 * Functions to manage the positional parameters *
3373 ***************************************************/
3375 /* Return the word list that corresponds to `$*'. */
3377 list_rest_of_args ()
3379 register WORD_LIST
*list
, *args
;
3382 /* Break out of the loop as soon as one of the dollar variables is null. */
3383 for (i
= 1, list
= (WORD_LIST
*)NULL
; i
< 10 && dollar_vars
[i
]; i
++)
3384 list
= make_word_list (make_bare_word (dollar_vars
[i
]), list
);
3386 for (args
= rest_of_args
; args
; args
= args
->next
)
3387 list
= make_word_list (make_bare_word (args
->word
->word
), list
);
3389 return (REVERSE_LIST (list
, WORD_LIST
*));
3392 /* Return the value of a positional parameter. This handles values > 10. */
3394 get_dollar_var_value (ind
)
3401 temp
= dollar_vars
[ind
] ? savestring (dollar_vars
[ind
]) : (char *)NULL
;
3402 else /* We want something like ${11} */
3405 for (p
= rest_of_args
; p
&& ind
--; p
= p
->next
)
3407 temp
= p
? savestring (p
->word
->word
) : (char *)NULL
;
3412 /* Make a single large string out of the dollar digit variables,
3413 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
3414 case of "$*" with respect to IFS. */
3416 string_rest_of_args (dollar_star
)
3419 register WORD_LIST
*list
;
3422 list
= list_rest_of_args ();
3423 string
= dollar_star
? string_list_dollar_star (list
, 0, 0) : string_list (list
);
3424 dispose_words (list
);
3428 /* Return a string containing the positional parameters from START to
3429 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3430 which only makes a difference if QUOTED is non-zero. If QUOTED includes
3431 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
3432 no quoting chars are added. */
3434 pos_params (string
, start
, end
, quoted
, pflags
)
3436 int start
, end
, quoted
, pflags
;
3438 WORD_LIST
*save
, *params
, *h
, *t
;
3442 /* see if we can short-circuit. if start == end, we want 0 parameters. */
3444 return ((char *)NULL
);
3446 save
= params
= list_rest_of_args ();
3447 if (save
== 0 && start
> 0)
3448 return ((char *)NULL
);
3450 if (start
== 0) /* handle ${@:0[:x]} specially */
3452 t
= make_word_list (make_word (dollar_vars
[0]), params
);
3456 for (i
= start
? 1 : 0; params
&& i
< start
; i
++)
3457 params
= params
->next
;
3460 dispose_words (save
);
3461 return ((char *)NULL
);
3463 for (h
= t
= params
; params
&& i
< end
; i
++)
3466 params
= params
->next
;
3468 t
->next
= (WORD_LIST
*)NULL
;
3470 ret
= string_list_pos_params (string
[0], h
, quoted
, pflags
);
3475 dispose_words (save
);
3479 /******************************************************************/
3481 /* Functions to expand strings to strings or WORD_LISTs */
3483 /******************************************************************/
3485 #if defined (PROCESS_SUBSTITUTION)
3486 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
3488 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3491 /* If there are any characters in STRING that require full expansion,
3492 then call FUNC to expand STRING; otherwise just perform quote
3493 removal if necessary. This returns a new string. */
3495 expand_string_if_necessary (string
, quoted
, func
)
3506 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3507 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
3511 if (EXP_CHAR (string
[i
]))
3513 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
3515 ADVANCE_CHAR (string
, slen
, i
);
3520 list
= (*func
) (string
, quoted
);
3523 ret
= string_list (list
);
3524 dispose_words (list
);
3529 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
3530 ret
= string_quote_removal (string
, quoted
);
3532 ret
= savestring (string
);
3537 static inline char *
3538 expand_string_to_string_internal (string
, quoted
, func
)
3546 if (string
== 0 || *string
== '\0')
3547 return ((char *)NULL
);
3549 list
= (*func
) (string
, quoted
);
3552 ret
= string_list (list
);
3553 dispose_words (list
);
3562 expand_string_to_string (string
, quoted
)
3566 return (expand_string_to_string_internal (string
, quoted
, expand_string
));
3570 expand_string_unsplit_to_string (string
, quoted
)
3574 return (expand_string_to_string_internal (string
, quoted
, expand_string_unsplit
));
3578 expand_assignment_string_to_string (string
, quoted
)
3582 return (expand_string_to_string_internal (string
, quoted
, expand_string_assignment
));
3586 expand_arith_string (string
, quoted
)
3591 WORD_LIST
*list
, *tlist
;
3597 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3598 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
3602 if (EXP_CHAR (string
[i
]))
3604 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
3606 ADVANCE_CHAR (string
, slen
, i
);
3611 /* This is expanded version of expand_string_internal as it's called by
3612 expand_string_leave_quoted */
3613 td
.flags
= W_NOPROCSUB
|W_NOTILDE
; /* don't want process substitution or tilde expansion */
3614 #if 0 /* TAG: bush-5.2 */
3615 if (quoted
& Q_ARRAYSUB
)
3616 td
.flags
|= W_NOCOMSUB
;
3618 td
.word
= savestring (string
);
3619 list
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
3620 /* This takes care of the calls from expand_string_leave_quoted and
3624 tlist
= word_list_split (list
);
3625 dispose_words (list
);
3628 dequote_list (list
);
3630 /* This comes from expand_string_if_necessary */
3633 ret
= string_list (list
);
3634 dispose_words (list
);
3640 else if (saw_quote
&& (quoted
& Q_ARITH
))
3641 ret
= string_quote_removal (string
, quoted
);
3642 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
3643 ret
= string_quote_removal (string
, quoted
);
3645 ret
= savestring (string
);
3650 #if defined (COND_COMMAND)
3651 /* Just remove backslashes in STRING. Returns a new string. */
3653 remove_backslashes (string
)
3658 r
= ret
= (char *)xmalloc (strlen (string
) + 1);
3659 for (s
= string
; s
&& *s
; )
3671 /* This needs better error handling. */
3672 /* Expand W for use as an argument to a unary or binary operator in a
3673 [[...]] expression. If SPECIAL is 1, this is the rhs argument
3674 to the != or == operator, and should be treated as a pattern. In
3675 this case, we quote the string specially for the globbing code. If
3676 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
3677 be quoted appropriately for regcomp/regexec. The caller is responsible
3678 for removing the backslashes if the unquoted word is needed later. In
3679 any case, since we don't perform word splitting, we need to do quoted
3680 null character removal. */
3682 cond_expand_word (w
, special
)
3690 if (w
->word
== 0 || w
->word
[0] == '\0')
3691 return ((char *)NULL
);
3693 expand_no_split_dollar_star
= 1;
3694 w
->flags
|= W_NOSPLIT2
;
3695 l
= call_expand_word_internal (w
, 0, 0, (int *)0, (int *)0);
3696 expand_no_split_dollar_star
= 0;
3699 if (special
== 0) /* LHS */
3702 word_list_remove_quoted_nulls (l
);
3704 r
= string_list (l
);
3708 /* Need to figure out whether or not we should call dequote_escapes
3709 or a new dequote_ctlnul function here, and under what
3711 qflags
= QGLOB_CVTNULL
|QGLOB_CTLESC
;
3713 qflags
|= QGLOB_REGEXP
;
3714 word_list_remove_quoted_nulls (l
);
3715 p
= string_list (l
);
3716 r
= quote_string_for_globbing (p
, qflags
);
3728 /* Call expand_word_internal to expand W and handle error returns.
3729 A convenience function for functions that don't want to handle
3730 any errors or free any memory before aborting. */
3732 call_expand_word_internal (w
, q
, i
, c
, e
)
3738 result
= expand_word_internal (w
, q
, i
, c
, e
);
3739 if (result
== &expand_word_error
|| result
== &expand_word_fatal
)
3741 /* By convention, each time this error is returned, w->word has
3742 already been freed (it sometimes may not be in the fatal case,
3743 but that doesn't result in a memory leak because we're going
3744 to exit in most cases). */
3745 w
->word
= (char *)NULL
;
3746 last_command_exit_value
= EXECUTION_FAILURE
;
3747 exp_jump_to_top_level ((result
== &expand_word_error
) ? DISCARD
: FORCE_EOF
);
3755 /* Perform parameter expansion, command substitution, and arithmetic
3756 expansion on STRING, as if it were a word. Leave the result quoted.
3757 Since this does not perform word splitting, it leaves quoted nulls
3760 expand_string_internal (string
, quoted
)
3767 if (string
== 0 || *string
== 0)
3768 return ((WORD_LIST
*)NULL
);
3771 td
.word
= savestring (string
);
3773 tresult
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
3779 /* Expand STRING by performing parameter expansion, command substitution,
3780 and arithmetic expansion. Dequote the resulting WORD_LIST before
3781 returning it, but do not perform word splitting. The call to
3782 remove_quoted_nulls () is in here because word splitting normally
3783 takes care of quote removal. */
3785 expand_string_unsplit (string
, quoted
)
3791 if (string
== 0 || *string
== '\0')
3792 return ((WORD_LIST
*)NULL
);
3794 expand_no_split_dollar_star
= 1;
3795 value
= expand_string_internal (string
, quoted
);
3796 expand_no_split_dollar_star
= 0;
3802 remove_quoted_nulls (value
->word
->word
); /* XXX */
3803 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
3805 dequote_list (value
);
3810 /* Expand the rhs of an assignment statement */
3812 expand_string_assignment (string
, quoted
)
3819 if (string
== 0 || *string
== '\0')
3820 return ((WORD_LIST
*)NULL
);
3822 expand_no_split_dollar_star
= 1;
3825 /* Other shells (ksh93) do it this way, which affects how $@ is expanded
3826 in constructs like bar=${@#0} (preserves the spaces resulting from the
3827 expansion of $@ in a context where you don't do word splitting); Posix
3828 interp 888 makes the expansion of $@ in contexts where word splitting
3829 is not performed unspecified. */
3830 td
.flags
= W_ASSIGNRHS
|W_NOSPLIT2
; /* Posix interp 888 */
3832 td
.flags
= W_ASSIGNRHS
;
3834 td
.word
= savestring (string
);
3835 value
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
3838 expand_no_split_dollar_star
= 0;
3844 remove_quoted_nulls (value
->word
->word
); /* XXX */
3845 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
3847 dequote_list (value
);
3853 /* Expand one of the PS? prompt strings. This is a sort of combination of
3854 expand_string_unsplit and expand_string_internal, but returns the
3855 passed string when an error occurs. Might want to trap other calls
3856 to jump_to_top_level here so we don't endlessly loop. */
3858 expand_prompt_string (string
, quoted
, wflags
)
3866 if (string
== 0 || *string
== 0)
3867 return ((WORD_LIST
*)NULL
);
3870 td
.word
= savestring (string
);
3872 no_longjmp_on_fatal_error
= 1;
3873 value
= expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
3874 no_longjmp_on_fatal_error
= 0;
3876 if (value
== &expand_word_error
|| value
== &expand_word_fatal
)
3878 value
= make_word_list (make_bare_word (string
), (WORD_LIST
*)NULL
);
3886 remove_quoted_nulls (value
->word
->word
); /* XXX */
3887 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
3889 dequote_list (value
);
3894 /* Expand STRING just as if you were expanding a word, but do not dequote
3895 the resultant WORD_LIST. This is called only from within this file,
3896 and is used to correctly preserve quoted characters when expanding
3897 things like ${1+"$@"}. This does parameter expansion, command
3898 substitution, arithmetic expansion, and word splitting. */
3900 expand_string_leave_quoted (string
, quoted
)
3907 if (string
== 0 || *string
== '\0')
3908 return ((WORD_LIST
*)NULL
);
3910 tlist
= expand_string_internal (string
, quoted
);
3914 tresult
= word_list_split (tlist
);
3915 dispose_words (tlist
);
3918 return ((WORD_LIST
*)NULL
);
3921 /* This does not perform word splitting or dequote the WORD_LIST
3924 expand_string_for_rhs (string
, quoted
, op
, pflags
, dollar_at_p
, expanded_p
)
3926 int quoted
, op
, pflags
;
3927 int *dollar_at_p
, *expanded_p
;
3933 if (string
== 0 || *string
== '\0')
3934 return (WORD_LIST
*)NULL
;
3936 /* We want field splitting to be determined by what is going to be done with
3937 the entire ${parameterOPword} expansion, so we don't want to split the RHS
3938 we expand here. However, the expansion of $* is determined by whether we
3939 are going to eventually perform word splitting, so we want to set this
3940 depending on whether or not are are going to be splitting: if the expansion
3941 is quoted, if the OP is `=', or if IFS is set to the empty string, we
3942 are not going to be splitting, so we set expand_no_split_dollar_star to
3943 note this to callees.
3944 We pass through PF_ASSIGNRHS as W_ASSIGNRHS if this is on the RHS of an
3945 assignment statement. */
3946 /* The updated treatment of $* is the result of Posix interp 888 */
3947 /* This was further clarified on the austin-group list in March, 2017 and
3948 in Posix bug 1129 */
3949 old_nosplit
= expand_no_split_dollar_star
;
3950 expand_no_split_dollar_star
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || op
== '=' || ifs_is_null
== 0; /* XXX - was 1 */
3951 td
.flags
= W_EXPANDRHS
; /* expanding RHS of ${paramOPword} */
3952 td
.flags
|= W_NOSPLIT2
; /* no splitting, remove "" and '' */
3953 if (pflags
& PF_ASSIGNRHS
) /* pass through */
3954 td
.flags
|= W_ASSIGNRHS
;
3957 td
.flags
|= W_ASSIGNRHS
; /* expand b in ${a=b} like assignment */
3959 td
.flags
|= W_ASSIGNRHS
|W_NOASSNTILDE
; /* expand b in ${a=b} like assignment */
3962 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
3963 expand_no_split_dollar_star
= old_nosplit
;
3968 /* This does not perform word splitting or dequote the WORD_LIST
3969 it returns and it treats $* as if it were quoted. */
3971 expand_string_for_pat (string
, quoted
, dollar_at_p
, expanded_p
)
3973 int quoted
, *dollar_at_p
, *expanded_p
;
3979 if (string
== 0 || *string
== '\0')
3980 return (WORD_LIST
*)NULL
;
3982 oexp
= expand_no_split_dollar_star
;
3983 expand_no_split_dollar_star
= 1;
3984 td
.flags
= W_NOSPLIT2
; /* no splitting, remove "" and '' */
3986 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
3987 expand_no_split_dollar_star
= oexp
;
3992 /* Expand STRING just as if you were expanding a word. This also returns
3993 a list of words. Note that filename globbing is *NOT* done for word
3994 or string expansion, just when the shell is expanding a command. This
3995 does parameter expansion, command substitution, arithmetic expansion,
3996 and word splitting. Dequote the resultant WORD_LIST before returning. */
3998 expand_string (string
, quoted
)
4004 if (string
== 0 || *string
== '\0')
4005 return ((WORD_LIST
*)NULL
);
4007 result
= expand_string_leave_quoted (string
, quoted
);
4008 return (result
? dequote_list (result
) : result
);
4011 /*******************************************
4013 * Functions to expand WORD_DESCs *
4015 *******************************************/
4017 /* Expand WORD, performing word splitting on the result. This does
4018 parameter expansion, command substitution, arithmetic expansion,
4019 word splitting, and quote removal. */
4022 expand_word (word
, quoted
)
4026 WORD_LIST
*result
, *tresult
;
4028 tresult
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4029 result
= word_list_split (tresult
);
4030 dispose_words (tresult
);
4031 return (result
? dequote_list (result
) : result
);
4034 /* Expand WORD, but do not perform word splitting on the result. This
4035 does parameter expansion, command substitution, arithmetic expansion,
4036 and quote removal. */
4038 expand_word_unsplit (word
, quoted
)
4044 result
= expand_word_leave_quoted (word
, quoted
);
4045 return (result
? dequote_list (result
) : result
);
4048 /* Perform shell expansions on WORD, but do not perform word splitting or
4049 quote removal on the result. Virtually identical to expand_word_unsplit;
4050 could be combined if implementations don't diverge. */
4052 expand_word_leave_quoted (word
, quoted
)
4058 expand_no_split_dollar_star
= 1;
4060 word
->flags
|= W_NOSPLIT
;
4061 word
->flags
|= W_NOSPLIT2
;
4062 result
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4063 expand_no_split_dollar_star
= 0;
4068 /***************************************************
4070 * Functions to handle quoting chars *
4072 ***************************************************/
4076 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
4077 The parser passes CTLNUL as CTLESC CTLNUL. */
4079 /* Quote escape characters in string s, but no other characters. This is
4080 used to protect CTLESC and CTLNUL in variable values from the rest of
4081 the word expansion process after the variable is expanded (word splitting
4082 and filename generation). If IFS is null, we quote spaces as well, just
4083 in case we split on spaces later (in the case of unquoted $@, we will
4084 eventually attempt to split the entire word on spaces). Corresponding
4085 code exists in dequote_escapes. Even if we don't end up splitting on
4086 spaces, quoting spaces is not a problem. This should never be called on
4087 a string that is quoted with single or double quotes or part of a here
4088 document (effectively double-quoted).
4089 FLAGS says whether or not we are going to split the result. If we are not,
4090 and there is a CTLESC or CTLNUL in IFS, we need to quote CTLESC and CTLNUL,
4091 respectively, to prevent them from being removed as part of dequoting. */
4093 quote_escapes_internal (string
, flags
)
4097 const char *s
, *send
;
4100 int quote_spaces
, skip_ctlesc
, skip_ctlnul
, nosplit
;
4103 slen
= strlen (string
);
4104 send
= string
+ slen
;
4106 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4107 nosplit
= (flags
& PF_NOSPLIT2
);
4109 for (skip_ctlesc
= skip_ctlnul
= 0, s
= ifs_value
; s
&& *s
; s
++)
4111 skip_ctlesc
|= (nosplit
== 0 && *s
== CTLESC
);
4112 skip_ctlnul
|= (nosplit
== 0 && *s
== CTLNUL
);
4115 t
= result
= (char *)xmalloc ((slen
* 2) + 1);
4120 if ((skip_ctlesc
== 0 && *s
== CTLESC
) || (skip_ctlnul
== 0 && *s
== CTLNUL
) || (quote_spaces
&& *s
== ' '))
4122 COPY_CHAR_P (t
, s
, send
);
4130 quote_escapes (string
)
4133 return (quote_escapes_internal (string
, 0));
4140 return (quote_escapes_internal (string
, PF_NOSPLIT2
));
4144 list_quote_escapes (list
)
4147 register WORD_LIST
*w
;
4150 for (w
= list
; w
; w
= w
->next
)
4153 w
->word
->word
= quote_escapes (t
);
4159 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
4161 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
4162 This is necessary to make unquoted CTLESC and CTLNUL characters in the
4163 data stream pass through properly.
4165 We need to remove doubled CTLESC characters inside quoted strings before
4166 quoting the entire string, so we do not double the number of CTLESC
4169 Also used by parts of the pattern substitution code. */
4171 dequote_escapes (string
)
4174 const char *s
, *send
;
4183 slen
= strlen (string
);
4184 send
= string
+ slen
;
4186 t
= result
= (char *)xmalloc (slen
+ 1);
4188 if (strchr (string
, CTLESC
) == 0)
4189 return (strcpy (result
, string
));
4191 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4196 if (*s
== CTLESC
&& (s
[1] == CTLESC
|| s
[1] == CTLNUL
|| (quote_spaces
&& s
[1] == ' ')))
4202 COPY_CHAR_P (t
, s
, send
);
4209 #if defined (INCLUDE_UNUSED)
4211 list_dequote_escapes (list
)
4214 register WORD_LIST
*w
;
4217 for (w
= list
; w
; w
= w
->next
)
4220 w
->word
->word
= dequote_escapes (t
);
4227 /* Return a new string with the quoted representation of character C.
4228 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
4229 set in any resultant WORD_DESC where this value is the word. */
4231 make_quoted_char (c
)
4236 temp
= (char *)xmalloc (3);
4251 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
4252 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
4253 this value is the word. */
4255 quote_string (string
)
4260 char *result
, *send
;
4264 result
= (char *)xmalloc (2);
4272 slen
= strlen (string
);
4273 send
= string
+ slen
;
4275 result
= (char *)xmalloc ((slen
* 2) + 1);
4277 for (t
= result
; string
< send
; )
4280 COPY_CHAR_P (t
, string
, send
);
4287 /* De-quote quoted characters in STRING. */
4289 dequote_string (string
)
4292 register char *s
, *t
;
4294 char *result
, *send
;
4298 if (string
[0] == CTLESC
&& string
[1] == 0)
4299 internal_inform ("dequote_string: string with bare CTLESC");
4302 slen
= STRLEN (string
);
4304 t
= result
= (char *)xmalloc (slen
+ 1);
4306 if (QUOTED_NULL (string
))
4312 /* A string consisting of only a single CTLESC should pass through unchanged */
4313 if (string
[0] == CTLESC
&& string
[1] == 0)
4320 /* If no character in the string can be quoted, don't bother examining
4321 each character. Just return a copy of the string passed to us. */
4322 if (strchr (string
, CTLESC
) == NULL
)
4323 return (strcpy (result
, string
));
4325 send
= string
+ slen
;
4335 COPY_CHAR_P (t
, s
, send
);
4342 /* Quote the entire WORD_LIST list. */
4347 register WORD_LIST
*w
;
4350 for (w
= list
; w
; w
= w
->next
)
4353 w
->word
->word
= quote_string (t
);
4355 w
->word
->flags
|= W_HASQUOTEDNULL
; /* XXX - turn on W_HASQUOTEDNULL here? */
4356 w
->word
->flags
|= W_QUOTED
;
4368 s
= dequote_string (word
->word
);
4369 if (QUOTED_NULL (word
->word
))
4370 word
->flags
&= ~W_HASQUOTEDNULL
;
4377 /* De-quote quoted characters in each word in LIST. */
4383 register WORD_LIST
*tlist
;
4385 for (tlist
= list
; tlist
; tlist
= tlist
->next
)
4387 s
= dequote_string (tlist
->word
->word
);
4388 if (QUOTED_NULL (tlist
->word
->word
))
4389 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
4390 free (tlist
->word
->word
);
4391 tlist
->word
->word
= s
;
4396 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
4399 remove_quoted_escapes (string
)
4406 t
= dequote_escapes (string
);
4414 /* Remove quoted $IFS characters from STRING. Quoted IFS characters are
4415 added to protect them from word splitting, but we need to remove them
4416 if no word splitting takes place. This returns newly-allocated memory,
4417 so callers can use it to replace savestring(). */
4419 remove_quoted_ifs (string
)
4422 register size_t slen
;
4427 slen
= strlen (string
);
4428 send
= string
+ slen
;
4431 ret
= (char *)xmalloc (slen
+ 1);
4435 if (string
[i
] == CTLESC
)
4438 if (string
[i
] == 0 || isifs (string
[i
]) == 0)
4444 COPY_CHAR_I (ret
, j
, string
, send
, i
);
4452 remove_quoted_nulls (string
)
4455 register size_t slen
;
4456 register int i
, j
, prev_i
;
4459 if (strchr (string
, CTLNUL
) == 0) /* XXX */
4460 return string
; /* XXX */
4462 slen
= strlen (string
);
4467 if (string
[i
] == CTLESC
)
4469 /* Old code had j++, but we cannot assume that i == j at this
4470 point -- what if a CTLNUL has already been removed from the
4471 string? We don't want to drop the CTLESC or recopy characters
4472 that we've already copied down. */
4474 string
[j
++] = CTLESC
;
4478 else if (string
[i
] == CTLNUL
)
4485 ADVANCE_CHAR (string
, slen
, i
); /* COPY_CHAR_I? */
4488 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
4498 /* Perform quoted null character removal on each element of LIST.
4499 This modifies LIST. */
4501 word_list_remove_quoted_nulls (list
)
4504 register WORD_LIST
*t
;
4506 for (t
= list
; t
; t
= t
->next
)
4508 remove_quoted_nulls (t
->word
->word
);
4509 t
->word
->flags
&= ~W_HASQUOTEDNULL
;
4513 /* **************************************************************** */
4515 /* Functions for Matching and Removing Patterns */
4517 /* **************************************************************** */
4519 #if defined (HANDLE_MULTIBYTE)
4520 # ifdef INCLUDE_UNUSED
4521 static unsigned char *
4522 mb_getcharlens (string
, len
)
4526 int i
, offset
, last
;
4533 ret
= (unsigned char *)xmalloc (len
);
4534 memset (ret
, 0, len
);
4535 while (string
[last
])
4537 ADVANCE_CHAR (string
, len
, offset
);
4538 ret
[last
] = offset
- last
;
4546 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
4547 can have one of 4 values:
4548 RP_LONG_LEFT remove longest matching portion at start of PARAM
4549 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
4550 RP_LONG_RIGHT remove longest matching portion at end of PARAM
4551 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
4554 #define RP_LONG_LEFT 1
4555 #define RP_SHORT_LEFT 2
4556 #define RP_LONG_RIGHT 3
4557 #define RP_SHORT_RIGHT 4
4559 /* Returns its first argument if nothing matched; new memory otherwise */
4561 remove_upattern (param
, pattern
, op
)
4562 char *param
, *pattern
;
4565 register size_t len
;
4567 register char *p
, *ret
, c
;
4569 len
= STRLEN (param
);
4574 case RP_LONG_LEFT
: /* remove longest match at start */
4575 for (p
= end
; p
>= param
; p
--)
4578 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4581 return (savestring (p
));
4588 case RP_SHORT_LEFT
: /* remove shortest match at start */
4589 for (p
= param
; p
<= end
; p
++)
4592 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4595 return (savestring (p
));
4601 case RP_LONG_RIGHT
: /* remove longest match at end */
4602 for (p
= param
; p
<= end
; p
++)
4604 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4607 ret
= savestring (param
);
4614 case RP_SHORT_RIGHT
: /* remove shortest match at end */
4615 for (p
= end
; p
>= param
; p
--)
4617 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4620 ret
= savestring (param
);
4628 return (param
); /* no match, return original string */
4631 #if defined (HANDLE_MULTIBYTE)
4632 /* Returns its first argument if nothing matched; new memory otherwise */
4634 remove_wpattern (wparam
, wstrlen
, wpattern
, op
)
4645 case RP_LONG_LEFT
: /* remove longest match at start */
4646 for (n
= wstrlen
; n
>= 0; n
--)
4648 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
4649 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4652 return (wcsdup (wparam
+ n
));
4658 case RP_SHORT_LEFT
: /* remove shortest match at start */
4659 for (n
= 0; n
<= wstrlen
; n
++)
4661 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
4662 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4665 return (wcsdup (wparam
+ n
));
4671 case RP_LONG_RIGHT
: /* remove longest match at end */
4672 for (n
= 0; n
<= wstrlen
; n
++)
4674 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4676 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
4677 ret
= wcsdup (wparam
);
4684 case RP_SHORT_RIGHT
: /* remove shortest match at end */
4685 for (n
= wstrlen
; n
>= 0; n
--)
4687 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
4689 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
4690 ret
= wcsdup (wparam
);
4698 return (wparam
); /* no match, return original string */
4700 #endif /* HANDLE_MULTIBYTE */
4703 remove_pattern (param
, pattern
, op
)
4704 char *param
, *pattern
;
4711 if (*param
== '\0' || pattern
== NULL
|| *pattern
== '\0') /* minor optimization */
4712 return (savestring (param
));
4714 #if defined (HANDLE_MULTIBYTE)
4717 wchar_t *ret
, *oret
;
4719 wchar_t *wparam
, *wpattern
;
4722 /* XXX - could optimize here by checking param and pattern for multibyte
4723 chars with mbsmbchar and calling remove_upattern. */
4725 n
= xdupmbstowcs (&wpattern
, NULL
, pattern
);
4726 if (n
== (size_t)-1)
4728 xret
= remove_upattern (param
, pattern
, op
);
4729 return ((xret
== param
) ? savestring (param
) : xret
);
4731 n
= xdupmbstowcs (&wparam
, NULL
, param
);
4733 if (n
== (size_t)-1)
4736 xret
= remove_upattern (param
, pattern
, op
);
4737 return ((xret
== param
) ? savestring (param
) : xret
);
4739 oret
= ret
= remove_wpattern (wparam
, n
, wpattern
, op
);
4740 /* Don't bother to convert wparam back to multibyte string if nothing
4741 matched; just return copy of original string */
4746 return (savestring (param
));
4753 xret
= (char *)xmalloc (n
+ 1);
4754 memset (&ps
, '\0', sizeof (mbstate_t));
4755 n
= wcsrtombs (xret
, (const wchar_t **)&ret
, n
, &ps
);
4756 xret
[n
] = '\0'; /* just to make sure */
4763 xret
= remove_upattern (param
, pattern
, op
);
4764 return ((xret
== param
) ? savestring (param
) : xret
);
4768 /* Match PAT anywhere in STRING and return the match boundaries.
4769 This returns 1 in case of a successful match, 0 otherwise. SP
4770 and EP are pointers into the string where the match begins and
4771 ends, respectively. MTYPE controls what kind of match is attempted.
4772 MATCH_BEG and MATCH_END anchor the match at the beginning and end
4773 of the string, respectively. The longest match is returned. */
4775 match_upattern (string
, pat
, mtype
, sp
, ep
)
4782 register char *p
, *p1
, *npat
;
4785 /* If the pattern doesn't match anywhere in the string, go ahead and
4786 short-circuit right away. A minor optimization, saves a bunch of
4787 unnecessary calls to strmatch (up to N calls for a string of N
4788 characters) if the match is unsuccessful. To preserve the semantics
4789 of the substring matches below, we make sure that the pattern has
4790 `*' as first and last character, making a new pattern if necessary. */
4791 /* XXX - check this later if I ever implement `**' with special meaning,
4792 since this will potentially result in `**' at the beginning or end */
4794 if (pat
[0] != '*' || (pat
[0] == '*' && pat
[1] == LPAREN
&& extended_glob
) || pat
[len
- 1] != '*')
4796 int unescaped_backslash
;
4799 p
= npat
= (char *)xmalloc (len
+ 3);
4801 if ((mtype
!= MATCH_BEG
) && (*p1
!= '*' || (*p1
== '*' && p1
[1] == LPAREN
&& extended_glob
)))
4806 /* Need to also handle a pattern that ends with an unescaped backslash.
4807 For right now, we ignore it because the pattern matching code will
4808 fail the match anyway */
4809 /* If the pattern ends with a `*' we leave it alone if it's preceded by
4810 an even number of backslashes, but if it's escaped by a backslash
4811 we need to add another `*'. */
4812 if ((mtype
!= MATCH_END
) && (p1
[-1] == '*' && (unescaped_backslash
= p1
[-2] == '\\')))
4815 while (pp
>= pat
&& *pp
-- == '\\')
4816 unescaped_backslash
= 1 - unescaped_backslash
;
4817 if (unescaped_backslash
)
4820 else if (mtype
!= MATCH_END
&& p1
[-1] != '*')
4823 if (p1
[-1] != '*' || p1
[-2] == '\\')
4830 c
= strmatch (npat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
4833 if (c
== FNM_NOMATCH
)
4836 len
= STRLEN (string
);
4839 mlen
= umatchlen (pat
, len
);
4840 if (mlen
> (int)len
)
4846 for (p
= string
; p
<= end
; p
++)
4848 if (match_pattern_char (pat
, p
, FNMATCH_IGNCASE
))
4850 p1
= (mlen
== -1) ? end
: p
+ mlen
;
4851 /* p1 - p = length of portion of string to be considered
4852 p = current position in string
4853 mlen = number of characters consumed by match (-1 for entire string)
4855 we want to break immediately if the potential match len
4856 is greater than the number of characters remaining in the
4861 for ( ; p1
>= p
; p1
--)
4863 c
= *p1
; *p1
= '\0';
4864 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
4873 /* If MLEN != -1, we have a fixed length pattern. */
4884 if (match_pattern_char (pat
, string
, FNMATCH_IGNCASE
) == 0)
4887 for (p
= (mlen
== -1) ? end
: string
+ mlen
; p
>= string
; p
--)
4890 if (strmatch (pat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
4898 /* If MLEN != -1, we have a fixed length pattern. */
4906 for (p
= end
- ((mlen
== -1) ? len
: mlen
); p
<= end
; p
++)
4908 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
4914 /* If MLEN != -1, we have a fixed length pattern. */
4925 #if defined (HANDLE_MULTIBYTE)
4927 #define WFOLD(c) (match_ignore_case && iswupper (c) ? towlower (c) : (c))
4929 /* Match WPAT anywhere in WSTRING and return the match boundaries.
4930 This returns 1 in case of a successful match, 0 otherwise. Wide
4931 character version. */
4933 match_wpattern (wstring
, indices
, wstrlen
, wpat
, mtype
, sp
, ep
)
4941 wchar_t wc
, *wp
, *nwpat
, *wp1
;
4944 int n
, n1
, n2
, simple
;
4946 simple
= (wpat
[0] != L
'\\' && wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'[');
4947 #if defined (EXTENDED_GLOB)
4949 simple
&= (wpat
[1] != L
'(' || (wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'+' && wpat
[0] != L
'!' && wpat
[0] != L
'@')); /*)*/
4952 /* If the pattern doesn't match anywhere in the string, go ahead and
4953 short-circuit right away. A minor optimization, saves a bunch of
4954 unnecessary calls to strmatch (up to N calls for a string of N
4955 characters) if the match is unsuccessful. To preserve the semantics
4956 of the substring matches below, we make sure that the pattern has
4957 `*' as first and last character, making a new pattern if necessary. */
4958 len
= wcslen (wpat
);
4959 if (wpat
[0] != L
'*' || (wpat
[0] == L
'*' && wpat
[1] == WLPAREN
&& extended_glob
) || wpat
[len
- 1] != L
'*')
4961 int unescaped_backslash
;
4964 wp
= nwpat
= (wchar_t *)xmalloc ((len
+ 3) * sizeof (wchar_t));
4966 if (*wp1
!= L
'*' || (*wp1
== '*' && wp1
[1] == WLPAREN
&& extended_glob
))
4968 while (*wp1
!= L
'\0')
4971 /* See comments above in match_upattern. */
4972 if (wp1
[-1] == L
'*' && (unescaped_backslash
= wp1
[-2] == L
'\\'))
4975 while (wpp
>= wpat
&& *wpp
-- == L
'\\')
4976 unescaped_backslash
= 1 - unescaped_backslash
;
4977 if (unescaped_backslash
)
4980 else if (wp1
[-1] != L
'*')
4983 if (wp1
[-1] != L
'*' || wp1
[-2] == L
'\\')
4990 len
= wcsmatch (nwpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
4993 if (len
== FNM_NOMATCH
)
4996 mlen
= wmatchlen (wpat
, wstrlen
);
4997 if (mlen
> (int)wstrlen
)
5000 /* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
5004 for (n
= 0; n
<= wstrlen
; n
++)
5006 n2
= simple
? (WFOLD(*wpat
) == WFOLD(wstring
[n
])) : match_pattern_wchar (wpat
, wstring
+ n
, FNMATCH_IGNCASE
);
5009 n1
= (mlen
== -1) ? wstrlen
: n
+ mlen
;
5013 for ( ; n1
>= n
; n1
--)
5015 wc
= wstring
[n1
]; wstring
[n1
] = L
'\0';
5016 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5024 /* If MLEN != -1, we have a fixed length pattern. */
5034 if (match_pattern_wchar (wpat
, wstring
, FNMATCH_IGNCASE
) == 0)
5037 for (n
= (mlen
== -1) ? wstrlen
: mlen
; n
>= 0; n
--)
5039 wc
= wstring
[n
]; wstring
[n
] = L
'\0';
5040 if (wcsmatch (wpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5048 /* If MLEN != -1, we have a fixed length pattern. */
5056 for (n
= wstrlen
- ((mlen
== -1) ? wstrlen
: mlen
); n
<= wstrlen
; n
++)
5058 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5061 *ep
= indices
[wstrlen
];
5064 /* If MLEN != -1, we have a fixed length pattern. */
5075 #endif /* HANDLE_MULTIBYTE */
5078 match_pattern (string
, pat
, mtype
, sp
, ep
)
5083 #if defined (HANDLE_MULTIBYTE)
5086 wchar_t *wstring
, *wpat
;
5090 if (string
== 0 || pat
== 0 || *pat
== 0)
5093 #if defined (HANDLE_MULTIBYTE)
5096 if (mbsmbchar (string
) == 0 && mbsmbchar (pat
) == 0)
5097 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5099 n
= xdupmbstowcs (&wpat
, NULL
, pat
);
5100 if (n
== (size_t)-1)
5101 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5102 n
= xdupmbstowcs (&wstring
, &indices
, string
);
5103 if (n
== (size_t)-1)
5106 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5108 ret
= match_wpattern (wstring
, indices
, n
, wpat
, mtype
, sp
, ep
);
5118 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5122 getpatspec (c
, value
)
5127 return ((*value
== '#') ? RP_LONG_LEFT
: RP_SHORT_LEFT
);
5129 return ((*value
== '%') ? RP_LONG_RIGHT
: RP_SHORT_RIGHT
);
5132 /* Posix.2 says that the WORD should be run through tilde expansion,
5133 parameter expansion, command substitution and arithmetic expansion.
5134 This leaves the result quoted, so quote_string_for_globbing () has
5135 to be called to fix it up for strmatch (). If QUOTED is non-zero,
5136 it means that the entire expression was enclosed in double quotes.
5137 This means that quoting characters in the pattern do not make any
5138 special pattern characters quoted. For example, the `*' in the
5139 following retains its special meaning: "${foo#'*'}". */
5141 getpattern (value
, quoted
, expandpat
)
5143 int quoted
, expandpat
;
5150 /* There is a problem here: how to handle single or double quotes in the
5151 pattern string when the whole expression is between double quotes?
5152 POSIX.2 says that enclosing double quotes do not cause the pattern to
5153 be quoted, but does that leave us a problem with @ and array[@] and their
5154 expansions inside a pattern? */
5156 if (expandpat
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *tword
)
5159 pat
= string_extract_double_quoted (tword
, &i
, SX_STRIPDQ
);
5165 /* expand_string_for_pat () leaves WORD quoted and does not perform
5167 l
= *value
? expand_string_for_pat (value
,
5168 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? Q_PATQUOTE
: quoted
,
5169 (int *)NULL
, (int *)NULL
)
5172 word_list_remove_quoted_nulls (l
);
5173 pat
= string_list (l
);
5177 tword
= quote_string_for_globbing (pat
, QGLOB_CVTNULL
);
5185 /* Handle removing a pattern from a string as a result of ${name%[%]value}
5186 or ${name#[#]value}. */
5188 variable_remove_pattern (value
, pattern
, patspec
, quoted
)
5189 char *value
, *pattern
;
5190 int patspec
, quoted
;
5194 tword
= remove_pattern (value
, pattern
, patspec
);
5201 list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
)
5204 int patspec
, itype
, quoted
;
5210 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
5212 tword
= remove_pattern (l
->word
->word
, pattern
, patspec
);
5213 w
= alloc_word_desc ();
5214 w
->word
= tword
? tword
: savestring ("");
5215 new = make_word_list (w
, new);
5218 l
= REVERSE_LIST (new, WORD_LIST
*);
5219 tword
= string_list_pos_params (itype
, l
, quoted
, 0);
5226 parameter_list_remove_pattern (itype
, pattern
, patspec
, quoted
)
5229 int patspec
, quoted
;
5234 list
= list_rest_of_args ();
5236 return ((char *)NULL
);
5237 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5238 dispose_words (list
);
5242 #if defined (ARRAY_VARS)
5244 array_remove_pattern (var
, pattern
, patspec
, starsub
, quoted
)
5248 int starsub
; /* so we can figure out how it's indexed */
5258 v
= var
; /* XXX - for now */
5260 itype
= starsub
? '*' : '@';
5262 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
5263 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
5265 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
5267 return ((char *)NULL
);
5268 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5269 dispose_words (list
);
5273 #endif /* ARRAY_VARS */
5276 parameter_brace_remove_pattern (varname
, value
, ind
, patstr
, rtype
, quoted
, flags
)
5277 char *varname
, *value
;
5280 int rtype
, quoted
, flags
;
5282 int vtype
, patspec
, starsub
;
5283 char *temp1
, *val
, *pattern
, *oname
;
5287 return ((char *)NULL
);
5289 oname
= this_command_name
;
5290 this_command_name
= varname
;
5292 vtype
= get_var_and_type (varname
, value
, ind
, quoted
, flags
, &v
, &val
);
5295 this_command_name
= oname
;
5296 return ((char *)NULL
);
5299 starsub
= vtype
& VT_STARSUB
;
5300 vtype
&= ~VT_STARSUB
;
5302 patspec
= getpatspec (rtype
, patstr
);
5303 if (patspec
== RP_LONG_LEFT
|| patspec
== RP_LONG_RIGHT
)
5306 /* Need to pass getpattern newly-allocated memory in case of expansion --
5307 the expansion code will free the passed string on an error. */
5308 temp1
= savestring (patstr
);
5309 pattern
= getpattern (temp1
, quoted
, 1);
5312 temp1
= (char *)NULL
; /* shut up gcc */
5316 case VT_ARRAYMEMBER
:
5317 temp1
= remove_pattern (val
, pattern
, patspec
);
5318 if (vtype
== VT_VARIABLE
)
5322 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
5323 ? quote_string (temp1
)
5324 : quote_escapes (temp1
);
5329 #if defined (ARRAY_VARS)
5331 temp1
= array_remove_pattern (v
, pattern
, patspec
, starsub
, quoted
);
5332 if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5334 val
= quote_escapes (temp1
);
5341 temp1
= parameter_list_remove_pattern (varname
[0], pattern
, patspec
, quoted
);
5342 if (temp1
&& quoted
== 0 && ifs_is_null
)
5344 /* Posix interp 888 */
5346 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5348 val
= quote_escapes (temp1
);
5355 this_command_name
= oname
;
5361 #if defined (PROCESS_SUBSTITUTION)
5363 static void reap_some_procsubs
PARAMS((int));
5365 /*****************************************************************/
5367 /* Hacking Process Substitution */
5369 /*****************************************************************/
5371 #if !defined (HAVE_DEV_FD)
5372 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
5373 of FIFOs the shell has open. unlink_fifo_list will walk the list and
5374 unlink the ones that don't have a living process on the other end.
5375 unlink_all_fifos will walk the list and unconditionally unlink them, trying
5376 to open and close the FIFO first to release any child processes sleeping on
5377 the FIFO. add_fifo_list adds the name of an open FIFO to the list.
5378 NFIFO is a count of the number of FIFOs in the list. */
5379 #define FIFO_INCR 20
5381 /* PROC value of -1 means the process has been reaped and the FIFO needs to
5382 be removed. PROC value of 0 means the slot is unused. */
5388 static struct temp_fifo
*fifo_list
= (struct temp_fifo
*)NULL
;
5390 static int fifo_list_size
;
5397 for (i
= 0; i
< fifo_list_size
; i
++)
5399 if (fifo_list
[i
].file
)
5400 free (fifo_list
[i
].file
);
5401 fifo_list
[i
].file
= NULL
;
5402 fifo_list
[i
].proc
= 0;
5408 copy_fifo_list (sizep
)
5413 return (void *)NULL
;
5417 add_fifo_list (pathname
)
5422 if (nfifo
>= fifo_list_size
- 1)
5424 osize
= fifo_list_size
;
5425 fifo_list_size
+= FIFO_INCR
;
5426 fifo_list
= (struct temp_fifo
*)xrealloc (fifo_list
,
5427 fifo_list_size
* sizeof (struct temp_fifo
));
5428 for (i
= osize
; i
< fifo_list_size
; i
++)
5430 fifo_list
[i
].file
= (char *)NULL
;
5431 fifo_list
[i
].proc
= 0; /* unused */
5435 fifo_list
[nfifo
].file
= savestring (pathname
);
5443 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
5445 unlink (fifo_list
[i
].file
);
5446 free (fifo_list
[i
].file
);
5447 fifo_list
[i
].file
= (char *)NULL
;
5448 fifo_list
[i
].proc
= 0;
5460 for (i
= saved
= 0; i
< nfifo
; i
++)
5462 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
5464 unlink (fifo_list
[i
].file
);
5465 free (fifo_list
[i
].file
);
5466 fifo_list
[i
].file
= (char *)NULL
;
5467 fifo_list
[i
].proc
= 0;
5473 /* If we didn't remove some of the FIFOs, compact the list. */
5476 for (i
= j
= 0; i
< nfifo
; i
++)
5477 if (fifo_list
[i
].file
)
5481 fifo_list
[j
].file
= fifo_list
[i
].file
;
5482 fifo_list
[j
].proc
= fifo_list
[i
].proc
;
5483 fifo_list
[i
].file
= (char *)NULL
;
5484 fifo_list
[i
].proc
= 0;
5502 for (i
= 0; i
< nfifo
; i
++)
5504 fifo_list
[i
].proc
= (pid_t
)-1;
5505 fd
= open (fifo_list
[i
].file
, O_RDWR
|O_NONBLOCK
);
5514 /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
5515 from some point in the past, and close all open FIFOs in fifo_list
5516 that are not marked as active in LIST. If LIST is NULL, close
5517 everything in fifo_list. LSIZE is the number of elements in LIST, in
5518 case it's larger than fifo_list_size (size of fifo_list). */
5520 close_new_fifos (list
, lsize
)
5529 unlink_fifo_list ();
5533 for (plist
= (char *)list
, i
= 0; i
< lsize
; i
++)
5534 if (plist
[i
] == 0 && i
< fifo_list_size
&& fifo_list
[i
].proc
!= -1)
5537 for (i
= lsize
; i
< fifo_list_size
; i
++)
5542 find_procsub_child (pid
)
5547 for (i
= 0; i
< nfifo
; i
++)
5548 if (fifo_list
[i
].proc
== pid
)
5554 set_procsub_status (ind
, pid
, status
)
5559 if (ind
>= 0 && ind
< nfifo
)
5560 fifo_list
[ind
].proc
= (pid_t
)-1; /* sentinel */
5563 /* If we've marked the process for this procsub as dead, close the
5564 associated file descriptor and delete the FIFO. */
5566 reap_some_procsubs (max
)
5571 for (i
= 0; i
< max
; i
++)
5572 if (fifo_list
[i
].proc
== (pid_t
)-1) /* reaped */
5579 reap_some_procsubs (nfifo
);
5589 for (i
= 0; i
< nfifo
; i
++)
5591 if (fifo_list
[i
].proc
!= (pid_t
)-1 && fifo_list
[i
].proc
> 0)
5593 r
= wait_for (fifo_list
[i
].proc
, 0);
5594 save_proc_status (fifo_list
[i
].proc
, r
);
5595 fifo_list
[i
].proc
= (pid_t
)-1;
5618 tname
= sh_mktmpname ("sh-np", MT_USERANDOM
|MT_USETMPDIR
);
5619 if (mkfifo (tname
, 0600) < 0)
5622 return ((char *)NULL
);
5625 add_fifo_list (tname
);
5629 #else /* HAVE_DEV_FD */
5631 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
5632 has open to children. NFDS is a count of the number of bits currently
5633 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
5635 /* dev_fd_list[I] value of -1 means the process has been reaped and file
5636 descriptor I needs to be closed. Value of 0 means the slot is unused. */
5638 static pid_t
*dev_fd_list
= (pid_t
*)NULL
;
5640 static int totfds
; /* The highest possible number of open files. */
5661 for (i
= 0; nfds
&& i
< totfds
; i
++)
5668 copy_fifo_list (sizep
)
5673 if (nfds
== 0 || totfds
== 0)
5677 return (void *)NULL
;
5682 ret
= xmalloc (totfds
* sizeof (pid_t
));
5683 return (memcpy (ret
, dev_fd_list
, totfds
* sizeof (pid_t
)));
5690 if (dev_fd_list
== 0 || fd
>= totfds
)
5695 totfds
= getdtablesize ();
5696 if (totfds
< 0 || totfds
> 256)
5701 dev_fd_list
= (pid_t
*)xrealloc (dev_fd_list
, totfds
* sizeof (dev_fd_list
[0]));
5702 /* XXX - might need a loop for this */
5703 memset (dev_fd_list
+ ofds
, '\0', (totfds
- ofds
) * sizeof (pid_t
));
5706 dev_fd_list
[fd
] = 1; /* marker; updated later */
5713 return 0; /* used for cleanup; not needed with /dev/fd */
5726 if (dev_fd_list
[fd
])
5729 dev_fd_list
[fd
] = 0;
5742 for (i
= totfds
-1; nfds
&& i
>= 0; i
--)
5751 unlink_fifo_list ();
5754 /* Take LIST, which is a snapshot copy of dev_fd_list from some point in
5755 the past, and close all open fds in dev_fd_list that are not marked
5756 as open in LIST. If LIST is NULL, close everything in dev_fd_list.
5757 LSIZE is the number of elements in LIST, in case it's larger than
5758 totfds (size of dev_fd_list). */
5760 close_new_fifos (list
, lsize
)
5769 unlink_fifo_list ();
5773 for (plist
= (pid_t
*)list
, i
= 0; i
< lsize
; i
++)
5774 if (plist
[i
] == 0 && i
< totfds
&& dev_fd_list
[i
])
5777 for (i
= lsize
; i
< totfds
; i
++)
5782 find_procsub_child (pid
)
5790 for (i
= 0; i
< totfds
; i
++)
5791 if (dev_fd_list
[i
] == pid
)
5798 set_procsub_status (ind
, pid
, status
)
5803 if (ind
>= 0 && ind
< totfds
)
5804 dev_fd_list
[ind
] = (pid_t
)-1; /* sentinel */
5807 /* If we've marked the process for this procsub as dead, close the
5808 associated file descriptor. */
5810 reap_some_procsubs (max
)
5815 for (i
= 0; nfds
> 0 && i
< max
; i
++)
5816 if (dev_fd_list
[i
] == (pid_t
)-1)
5823 reap_some_procsubs (totfds
);
5833 for (i
= 0; nfds
> 0 && i
< totfds
; i
++)
5835 if (dev_fd_list
[i
] != (pid_t
)-1 && dev_fd_list
[i
] > 0)
5837 r
= wait_for (dev_fd_list
[i
], 0);
5838 save_proc_status (dev_fd_list
[i
], r
);
5839 dev_fd_list
[i
] = (pid_t
)-1;
5845 #if defined (NOTDEF)
5846 print_dev_fd_list ()
5850 fprintf (stderr
, "pid %ld: dev_fd_list:", (long)getpid ());
5853 for (i
= 0; i
< totfds
; i
++)
5856 fprintf (stderr
, " %d", i
);
5858 fprintf (stderr
, "\n");
5863 make_dev_fd_filename (fd
)
5866 char *ret
, intbuf
[INT_STRLEN_BOUND (int) + 1], *p
;
5868 ret
= (char *)xmalloc (sizeof (DEV_FD_PREFIX
) + 8);
5870 strcpy (ret
, DEV_FD_PREFIX
);
5871 p
= inttostr (fd
, intbuf
, sizeof (intbuf
));
5872 strcpy (ret
+ sizeof (DEV_FD_PREFIX
) - 1, p
);
5878 #endif /* HAVE_DEV_FD */
5880 /* Return a filename that will open a connection to the process defined by
5881 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
5882 a filename in /dev/fd corresponding to a descriptor that is one of the
5883 ends of the pipe. If not defined, we use named pipes on systems that have
5884 them. Systems without /dev/fd and named pipes are out of luck.
5886 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
5887 use the read end of the pipe and dup that file descriptor to fd 0 in
5888 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
5889 writing or use the write end of the pipe in the child, and dup that
5890 file descriptor to fd 1 in the child. The parent does the opposite. */
5893 process_substitute (string
, open_for_read_in_child
)
5895 int open_for_read_in_child
;
5898 int fd
, result
, rc
, function_value
;
5900 #if defined (HAVE_DEV_FD)
5901 int parent_pipe_fd
, child_pipe_fd
;
5903 #endif /* HAVE_DEV_FD */
5904 #if defined (JOB_CONTROL)
5905 pid_t old_pipeline_pgrp
;
5908 if (!string
|| !*string
|| wordexp_only
)
5909 return ((char *)NULL
);
5911 #if !defined (HAVE_DEV_FD)
5912 pathname
= make_named_pipe ();
5913 #else /* HAVE_DEV_FD */
5914 if (pipe (fildes
) < 0)
5916 sys_error ("%s", _("cannot make pipe for process substitution"));
5917 return ((char *)NULL
);
5919 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
5920 the pipe in the parent, otherwise the read end. */
5921 parent_pipe_fd
= fildes
[open_for_read_in_child
];
5922 child_pipe_fd
= fildes
[1 - open_for_read_in_child
];
5923 /* Move the parent end of the pipe to some high file descriptor, to
5924 avoid clashes with FDs used by the script. */
5925 parent_pipe_fd
= move_to_high_fd (parent_pipe_fd
, 1, 64);
5927 pathname
= make_dev_fd_filename (parent_pipe_fd
);
5928 #endif /* HAVE_DEV_FD */
5932 sys_error ("%s", _("cannot make pipe for process substitution"));
5933 return ((char *)NULL
);
5936 old_pid
= last_made_pid
;
5938 #if defined (JOB_CONTROL)
5939 old_pipeline_pgrp
= pipeline_pgrp
;
5940 if (pipeline_pgrp
== 0 || (subshell_environment
& (SUBSHELL_PIPE
|SUBSHELL_FORK
|SUBSHELL_ASYNC
)) == 0)
5941 pipeline_pgrp
= shell_pgrp
;
5943 #endif /* JOB_CONTROL */
5945 pid
= make_child ((char *)NULL
, FORK_ASYNC
);
5949 int old_interactive
;
5951 old_interactive
= interactive
;
5953 /* The currently-executing shell is not interactive */
5956 reset_terminating_signals (); /* XXX */
5957 free_pushed_string_input ();
5958 /* Cancel traps, in trap.c. */
5959 restore_original_signals (); /* XXX - what about special builtins? bush-4.2 */
5960 QUIT
; /* catch any interrupts we got post-fork */
5961 setup_async_signals ();
5963 if (open_for_read_in_child
== 0 && old_interactive
&& (bush_input
.type
== st_stdin
|| bush_input
.type
== st_stream
))
5964 async_redirect_stdin ();
5967 subshell_environment
|= SUBSHELL_COMSUB
|SUBSHELL_PROCSUB
|SUBSHELL_ASYNC
;
5969 /* We don't inherit the verbose option for command substitutions now, so
5970 let's try it for process substitutions. */
5971 change_flag ('v', FLAG_OFF
);
5973 /* if we're expanding a redirection, we shouldn't have access to the
5974 temporary environment, but commands in the subshell should have
5975 access to their own temporary environment. */
5976 if (expanding_redir
)
5977 flush_temporary_env ();
5980 #if defined (JOB_CONTROL)
5981 set_sigchld_handler ();
5982 stop_making_children ();
5983 /* XXX - should we only do this in the parent? (as in command subst) */
5984 pipeline_pgrp
= old_pipeline_pgrp
;
5986 stop_making_children ();
5987 #endif /* JOB_CONTROL */
5991 sys_error ("%s", _("cannot make child for process substitution"));
5993 #if defined (HAVE_DEV_FD)
5994 close (parent_pipe_fd
);
5995 close (child_pipe_fd
);
5996 #endif /* HAVE_DEV_FD */
5997 #if defined (JOB_CONTROL)
5998 restore_pipeline (1);
6000 return ((char *)NULL
);
6005 #if defined (JOB_CONTROL)
6006 last_procsub_child
= restore_pipeline (0);
6007 /* We assume that last_procsub_child->next == last_procsub_child because
6008 of how jobs.c:add_process() works. */
6009 last_procsub_child
->next
= 0;
6010 procsub_add (last_procsub_child
);
6013 #if defined (HAVE_DEV_FD)
6014 dev_fd_list
[parent_pipe_fd
] = pid
;
6016 fifo_list
[nfifo
-1].proc
= pid
;
6019 last_made_pid
= old_pid
;
6021 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6023 #endif /* JOB_CONTROL && PGRP_PIPE */
6025 #if defined (HAVE_DEV_FD)
6026 close (child_pipe_fd
);
6027 #endif /* HAVE_DEV_FD */
6032 set_sigint_handler ();
6034 #if defined (JOB_CONTROL)
6035 /* make sure we don't have any job control */
6036 set_job_control (0);
6038 /* Clear out any existing list of process substitutions */
6041 /* The idea is that we want all the jobs we start from an async process
6042 substitution to be in the same process group, but not the same pgrp
6043 as our parent shell, since we don't want to affect our parent shell's
6044 jobs if we get a SIGHUP and end up calling hangup_all_jobs, for example.
6045 If pipeline_pgrp != shell_pgrp, we assume that there is a job control
6046 shell somewhere in our parent process chain (since make_child initializes
6047 pipeline_pgrp to shell_pgrp if job_control == 0). What we do in this
6048 case is to set pipeline_pgrp to our PID, so all jobs started by this
6049 process have that same pgrp and we are basically the process group leader.
6050 This should not have negative effects on child processes surviving
6051 after we exit, since we wait for the children we create, but that is
6052 something to watch for. */
6054 if (pipeline_pgrp
!= shell_pgrp
)
6055 pipeline_pgrp
= getpid ();
6056 #endif /* JOB_CONTROL */
6058 #if !defined (HAVE_DEV_FD)
6059 /* Open the named pipe in the child. */
6060 fd
= open (pathname
, open_for_read_in_child
? O_RDONLY
: O_WRONLY
);
6063 /* Two separate strings for ease of translation. */
6064 if (open_for_read_in_child
)
6065 sys_error (_("cannot open named pipe %s for reading"), pathname
);
6067 sys_error (_("cannot open named pipe %s for writing"), pathname
);
6071 if (open_for_read_in_child
)
6073 if (sh_unset_nodelay_mode (fd
) < 0)
6075 sys_error (_("cannot reset nodelay mode for fd %d"), fd
);
6079 #else /* HAVE_DEV_FD */
6081 #endif /* HAVE_DEV_FD */
6083 /* Discard buffered stdio output before replacing the underlying file
6085 if (open_for_read_in_child
== 0)
6088 if (dup2 (fd
, open_for_read_in_child
? 0 : 1) < 0)
6090 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname
,
6091 open_for_read_in_child
? 0 : 1);
6095 if (fd
!= (open_for_read_in_child
? 0 : 1))
6098 /* Need to close any files that this process has open to pipes inherited
6100 if (current_fds_to_close
)
6102 close_fd_bitmap (current_fds_to_close
);
6103 current_fds_to_close
= (struct fd_bitmap
*)NULL
;
6106 #if defined (HAVE_DEV_FD)
6107 /* Make sure we close the parent's end of the pipe and clear the slot
6108 in the fd list so it is not closed later, if reallocated by, for
6109 instance, pipe(2). */
6110 close (parent_pipe_fd
);
6111 dev_fd_list
[parent_pipe_fd
] = 0;
6112 #endif /* HAVE_DEV_FD */
6114 /* subshells shouldn't have this flag, which controls using the temporary
6115 environment for variable lookups. We have already flushed the temporary
6116 environment above in the case we're expanding a redirection, so processes
6117 executed by this command need to be able to set it independently of their
6119 expanding_redir
= 0;
6121 remove_quoted_escapes (string
);
6123 #if 0 /* TAG: bush-5.2 */
6124 startup_state
= 2; /* see if we can avoid a fork */
6125 parse_and_execute_level
= 0;
6128 /* Give process substitution a place to jump back to on failure,
6129 so we don't go back up to main (). */
6130 result
= setjmp_nosigs (top_level
);
6132 /* If we're running a process substitution inside a shell function,
6133 trap `return' so we don't return from the function in the subshell
6134 and go off to never-never land. */
6135 if (result
== 0 && return_catch_flag
)
6136 function_value
= setjmp_nosigs (return_catch
);
6140 if (result
== ERREXIT
)
6141 rc
= last_command_exit_value
;
6142 else if (result
== EXITPROG
)
6143 rc
= last_command_exit_value
;
6145 rc
= EXECUTION_FAILURE
;
6146 else if (function_value
)
6147 rc
= return_catch_value
;
6151 rc
= parse_and_execute (string
, "process substitution", (SEVAL_NONINT
|SEVAL_NOHIST
));
6152 /* leave subshell level intact for any exit trap */
6155 #if !defined (HAVE_DEV_FD)
6156 /* Make sure we close the named pipe in the child before we exit. */
6157 close (open_for_read_in_child
? 0 : 1);
6158 #endif /* !HAVE_DEV_FD */
6160 last_command_exit_value
= rc
;
6161 rc
= run_exit_trap ();
6165 #endif /* PROCESS_SUBSTITUTION */
6167 /***********************************/
6169 /* Command Substitution */
6171 /***********************************/
6174 read_comsub (fd
, quoted
, flags
, rflag
)
6175 int fd
, quoted
, flags
;
6178 char *istring
, buf
[512], *bufp
;
6179 int istring_index
, c
, tflag
, skip_ctlesc
, skip_ctlnul
;
6181 size_t istring_size
;
6184 #if defined (HANDLE_MULTIBYTE)
6191 istring
= (char *)NULL
;
6192 istring_index
= istring_size
= bufn
= tflag
= 0;
6194 skip_ctlesc
= ifs_cmap
[CTLESC
];
6195 skip_ctlnul
= ifs_cmap
[CTLNUL
];
6197 mb_cur_max
= MB_CUR_MAX
;
6200 /* Read the output of the command through the pipe. */
6207 bufn
= zread (fd
, buf
, sizeof (buf
));
6219 internal_warning ("%s", _("command substitution: ignored null byte in input"));
6226 /* Add the character to ISTRING, possibly after resizing it. */
6227 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, mb_cur_max
+1, istring_size
, 512);
6229 /* This is essentially quote_string inline */
6230 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) /* || c == CTLESC || c == CTLNUL */)
6231 istring
[istring_index
++] = CTLESC
;
6232 else if ((flags
& PF_ASSIGNRHS
) && skip_ctlesc
&& c
== CTLESC
)
6233 istring
[istring_index
++] = CTLESC
;
6234 /* Escape CTLESC and CTLNUL in the output to protect those characters
6235 from the rest of the word expansions (word splitting and globbing.)
6236 This is essentially quote_escapes inline. */
6237 else if (skip_ctlesc
== 0 && c
== CTLESC
)
6238 istring
[istring_index
++] = CTLESC
;
6239 else if ((skip_ctlnul
== 0 && c
== CTLNUL
) || (c
== ' ' && (ifs_value
&& *ifs_value
== 0)))
6240 istring
[istring_index
++] = CTLESC
;
6242 #if defined (HANDLE_MULTIBYTE)
6243 if ((locale_utf8locale
&& (c
& 0x80)) ||
6244 (locale_utf8locale
== 0 && mb_cur_max
> 1 && (unsigned char)c
> 127))
6246 /* read a multibyte character from buf */
6247 /* punt on the hard case for now */
6248 memset (&ps
, '\0', sizeof (mbstate_t));
6249 mblen
= mbrtowc (&wc
, bufp
-1, bufn
+1, &ps
);
6250 if (MB_INVALIDCH (mblen
) || mblen
== 0 || mblen
== 1)
6251 istring
[istring_index
++] = c
;
6254 istring
[istring_index
++] = c
;
6255 for (i
= 0; i
< mblen
-1; i
++)
6256 istring
[istring_index
++] = *bufp
++;
6263 istring
[istring_index
++] = c
;
6267 istring
[istring_index
] = '\0';
6269 /* If we read no output, just return now and save ourselves some
6271 if (istring_index
== 0)
6276 return (char *)NULL
;
6279 /* Strip trailing newlines from the output of the command. */
6280 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
6282 while (istring_index
> 0)
6284 if (istring
[istring_index
- 1] == '\n')
6288 /* If the newline was quoted, remove the quoting char. */
6289 if (istring
[istring_index
- 1] == CTLESC
)
6295 istring
[istring_index
] = '\0';
6298 strip_trailing (istring
, istring_index
- 1, 1);
6305 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
6306 contained string possibly quoted. */
6308 command_substitute (string
, quoted
, flags
)
6313 pid_t pid
, old_pid
, old_pipeline_pgrp
, old_async_pid
;
6315 int result
, fildes
[2], function_value
, pflags
, rc
, tflag
, fork_flags
;
6319 istring
= (char *)NULL
;
6321 /* Don't fork () if there is no need to. In the case of no command to
6322 run, just return NULL. */
6324 for (s
= string
; s
&& *s
&& (shellblank (*s
) || *s
== '\n'); s
++)
6326 if (s
== 0 || *s
== 0)
6327 return ((WORD_DESC
*)NULL
);
6329 if (!string
|| !*string
|| (string
[0] == '\n' && !string
[1]))
6330 return ((WORD_DESC
*)NULL
);
6333 if (wordexp_only
&& read_but_dont_execute
)
6335 last_command_exit_value
= EX_WEXPCOMSUB
;
6336 jump_to_top_level (EXITPROG
);
6339 /* We're making the assumption here that the command substitution will
6340 eventually run a command from the file system. Since we'll run
6341 maybe_make_export_env in this subshell before executing that command,
6342 the parent shell and any other shells it starts will have to remake
6343 the environment. If we make it before we fork, other shells won't
6344 have to. Don't bother if we have any temporary variable assignments,
6345 though, because the export environment will be remade after this
6346 command completes anyway, but do it if all the words to be expanded
6347 are variable assignments. */
6348 if (subst_assign_varlist
== 0 || garglist
== 0)
6349 maybe_make_export_env (); /* XXX */
6351 /* Flags to pass to parse_and_execute() */
6352 pflags
= (interactive
&& sourcelevel
== 0) ? SEVAL_RESETLINE
: 0;
6354 old_pid
= last_made_pid
;
6356 /* Pipe the output of executing STRING into the current shell. */
6357 if (pipe (fildes
) < 0)
6359 sys_error ("%s", _("cannot make pipe for command substitution"));
6363 #if defined (JOB_CONTROL)
6364 old_pipeline_pgrp
= pipeline_pgrp
;
6365 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
6366 if ((subshell_environment
& SUBSHELL_PIPE
) == 0)
6367 pipeline_pgrp
= shell_pgrp
;
6368 cleanup_the_pipeline ();
6369 #endif /* JOB_CONTROL */
6371 old_async_pid
= last_asynchronous_pid
;
6372 fork_flags
= (subshell_environment
&SUBSHELL_ASYNC
) ? FORK_ASYNC
: 0;
6373 pid
= make_child ((char *)NULL
, fork_flags
|FORK_NOTERM
);
6374 last_asynchronous_pid
= old_async_pid
;
6378 /* Reset the signal handlers in the child, but don't free the
6379 trap strings. Set a flag noting that we have to free the
6380 trap strings if we run trap to change a signal disposition. */
6381 reset_signal_handlers ();
6384 kill (getpid (), SIGINT
);
6385 CLRINTERRUPT
; /* if we're ignoring SIGINT somehow */
6387 QUIT
; /* catch any interrupts we got post-fork */
6388 subshell_environment
|= SUBSHELL_RESETTRAP
;
6391 #if defined (JOB_CONTROL)
6392 /* XXX DO THIS ONLY IN PARENT ? XXX */
6393 set_sigchld_handler ();
6394 stop_making_children ();
6396 pipeline_pgrp
= old_pipeline_pgrp
;
6398 stop_making_children ();
6399 #endif /* JOB_CONTROL */
6403 sys_error (_("cannot make child for command substitution"));
6406 last_made_pid
= old_pid
;
6411 return ((WORD_DESC
*)NULL
);
6416 /* The currently executing shell is not interactive. */
6419 set_sigint_handler (); /* XXX */
6421 free_pushed_string_input ();
6423 /* Discard buffered stdio output before replacing the underlying file
6427 if (dup2 (fildes
[1], 1) < 0)
6429 sys_error ("%s", _("command_substitute: cannot duplicate pipe as fd 1"));
6430 exit (EXECUTION_FAILURE
);
6433 /* If standard output is closed in the parent shell
6434 (such as after `exec >&-'), file descriptor 1 will be
6435 the lowest available file descriptor, and end up in
6436 fildes[0]. This can happen for stdin and stderr as well,
6437 but stdout is more important -- it will cause no output
6438 to be generated from this command. */
6439 if ((fildes
[1] != fileno (stdin
)) &&
6440 (fildes
[1] != fileno (stdout
)) &&
6441 (fildes
[1] != fileno (stderr
)))
6444 if ((fildes
[0] != fileno (stdin
)) &&
6445 (fildes
[0] != fileno (stdout
)) &&
6446 (fildes
[0] != fileno (stderr
)))
6450 /* Let stdio know the fd may have changed from text to binary mode, and
6451 make sure to preserve stdout line buffering. */
6452 freopen (NULL
, "w", stdout
);
6453 sh_setlinebuf (stdout
);
6454 #endif /* __CYGWIN__ */
6456 /* This is a subshell environment. */
6457 subshell_environment
|= SUBSHELL_COMSUB
;
6459 /* Many shells do not appear to inherit the -v option for command
6461 change_flag ('v', FLAG_OFF
);
6463 /* When inherit_errexit option is not enabled, command substitution does
6464 not inherit the -e flag. It is enabled when Posix mode is enabled */
6465 if (inherit_errexit
== 0)
6467 builtin_ignoring_errexit
= 0;
6468 change_flag ('e', FLAG_OFF
);
6472 /* If we are expanding a redirection, we can dispose of any temporary
6473 environment we received, since redirections are not supposed to have
6474 access to the temporary environment. We will have to see whether this
6475 affects temporary environments supplied to `eval', but the temporary
6476 environment gets copied to builtin_env at some point. */
6477 if (expanding_redir
)
6479 flush_temporary_env ();
6480 expanding_redir
= 0;
6483 remove_quoted_escapes (string
);
6485 startup_state
= 2; /* see if we can avoid a fork */
6486 parse_and_execute_level
= 0;
6488 /* Give command substitution a place to jump back to on failure,
6489 so we don't go back up to main (). */
6490 result
= setjmp_nosigs (top_level
);
6492 /* If we're running a command substitution inside a shell function,
6493 trap `return' so we don't return from the function in the subshell
6494 and go off to never-never land. */
6495 if (result
== 0 && return_catch_flag
)
6496 function_value
= setjmp_nosigs (return_catch
);
6500 if (result
== ERREXIT
)
6501 rc
= last_command_exit_value
;
6502 else if (result
== EXITPROG
)
6503 rc
= last_command_exit_value
;
6505 rc
= EXECUTION_FAILURE
;
6506 else if (function_value
)
6507 rc
= return_catch_value
;
6511 rc
= parse_and_execute (string
, "command substitution", pflags
|SEVAL_NOHIST
);
6512 /* leave subshell level intact for any exit trap */
6515 last_command_exit_value
= rc
;
6516 rc
= run_exit_trap ();
6517 #if defined (PROCESS_SUBSTITUTION)
6518 unlink_fifo_list ();
6526 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6528 #endif /* JOB_CONTROL && PGRP_PIPE */
6532 begin_unwind_frame ("read-comsub");
6533 dummyfd
= fildes
[0];
6534 add_unwind_protect (close
, dummyfd
);
6536 /* Block SIGINT while we're reading from the pipe. If the child
6537 process gets a SIGINT, it will either handle it or die, and the
6538 read will return. */
6539 BLOCK_SIGNAL (SIGINT
, set
, oset
);
6541 istring
= read_comsub (fildes
[0], quoted
, flags
, &tflag
);
6544 discard_unwind_frame ("read-comsub");
6545 UNBLOCK_SIGNAL (oset
);
6547 current_command_subst_pid
= pid
;
6548 last_command_exit_value
= wait_for (pid
, JWAIT_NOTERM
);
6549 last_command_subst_pid
= pid
;
6550 last_made_pid
= old_pid
;
6552 #if defined (JOB_CONTROL)
6553 /* If last_command_exit_value > 128, then the substituted command
6554 was terminated by a signal. If that signal was SIGINT, then send
6555 SIGINT to ourselves. This will break out of loops, for instance. */
6556 if (last_command_exit_value
== (128 + SIGINT
) && last_command_exit_signal
== SIGINT
)
6557 kill (getpid (), SIGINT
);
6558 #endif /* JOB_CONTROL */
6560 ret
= alloc_word_desc ();
6561 ret
->word
= istring
;
6568 /********************************************************
6570 * Utility functions for parameter expansion *
6572 ********************************************************/
6574 #if defined (ARRAY_VARS)
6577 array_length_reference (s
)
6588 var
= array_variable_part (s
, 0, &t
, &len
);
6590 /* If unbound variables should generate an error, report one and return
6592 if ((var
== 0 || invisible_p (var
) || (assoc_p (var
) == 0 && array_p (var
) == 0)) && unbound_vars_is_error
)
6596 set_exit_status (EXECUTION_FAILURE
);
6601 else if (var
== 0 || invisible_p (var
))
6604 /* We support a couple of expansions for variables that are not arrays.
6605 We'll return the length of the value for v[0], and 1 for v[@] or
6606 v[*]. Return 0 for everything else. */
6608 array
= array_p (var
) ? array_cell (var
) : (ARRAY
*)NULL
;
6609 h
= assoc_p (var
) ? assoc_cell (var
) : (HASH_TABLE
*)NULL
;
6611 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == RBRACK
)
6614 return (h
? assoc_num_elements (h
) : 0);
6615 else if (array_p (var
))
6616 return (array
? array_num_elements (array
) : 0);
6618 return (var_isset (var
) ? 1 : 0);
6624 akey
= expand_assignment_string_to_string (t
, 0); /* [ */
6625 t
[len
- 1] = RBRACK
;
6626 if (akey
== 0 || *akey
== 0)
6628 err_badarraysub (t
);
6632 t
= assoc_reference (assoc_cell (var
), akey
);
6637 ind
= array_expand_index (var
, t
, len
, 0);
6638 /* negative subscripts to indexed arrays count back from end */
6639 if (var
&& array_p (var
) && ind
< 0)
6640 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
6643 err_badarraysub (t
);
6647 t
= array_reference (array
, ind
);
6649 t
= (ind
== 0) ? value_cell (var
) : (char *)NULL
;
6652 len
= MB_STRLEN (t
);
6655 #endif /* ARRAY_VARS */
6658 valid_brace_expansion_word (name
, var_is_special
)
6662 if (DIGIT (*name
) && all_digits (name
))
6664 else if (var_is_special
)
6666 #if defined (ARRAY_VARS)
6667 else if (valid_array_reference (name
, 0))
6669 #endif /* ARRAY_VARS */
6670 else if (legal_identifier (name
))
6677 chk_atstar (name
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
6680 int *quoted_dollar_atp
, *contains_dollar_at
;
6686 if (quoted_dollar_atp
)
6687 *quoted_dollar_atp
= 0;
6688 if (contains_dollar_at
)
6689 *contains_dollar_at
= 0;
6693 /* check for $@ and $* */
6694 if (name
[0] == '@' && name
[1] == 0)
6696 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
6697 *quoted_dollar_atp
= 1;
6698 if (contains_dollar_at
)
6699 *contains_dollar_at
= 1;
6702 else if (name
[0] == '*' && name
[1] == '\0' && quoted
== 0)
6704 /* Need more checks here that parallel what string_list_pos_params and
6705 param_expand do. Check expand_no_split_dollar_star and ??? */
6706 if (contains_dollar_at
&& expand_no_split_dollar_star
== 0)
6707 *contains_dollar_at
= 1;
6711 /* Now check for ${array[@]} and ${array[*]} */
6712 #if defined (ARRAY_VARS)
6713 else if (valid_array_reference (name
, 0))
6715 temp1
= mbschr (name
, LBRACK
);
6716 if (temp1
&& temp1
[1] == '@' && temp1
[2] == RBRACK
)
6718 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
6719 *quoted_dollar_atp
= 1;
6720 if (contains_dollar_at
)
6721 *contains_dollar_at
= 1;
6724 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
6725 which should result in separate words even when IFS is unset. */
6726 if (temp1
&& temp1
[1] == '*' && temp1
[2] == RBRACK
&& quoted
== 0)
6728 if (contains_dollar_at
)
6729 *contains_dollar_at
= 1;
6737 /* Parameter expand NAME, and return a new string which is the expansion,
6738 or NULL if there was no expansion. NAME is as given in ${NAMEcWORD}.
6739 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
6740 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
6741 NAME was found inside of a double-quoted expression. */
6743 parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, indp
)
6745 int var_is_special
, quoted
, pflags
;
6762 /* Handle multiple digit arguments, as in ${11}. */
6763 if (legal_number (name
, &arg_index
))
6765 tt
= get_dollar_var_value (arg_index
);
6767 temp
= (*tt
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
6769 : quote_escapes (tt
);
6771 temp
= (char *)NULL
;
6774 else if (var_is_special
) /* ${@} */
6777 tt
= (char *)xmalloc (2 + strlen (name
));
6778 tt
[sindex
= 0] = '$';
6779 strcpy (tt
+ 1, name
);
6781 ret
= param_expand (tt
, &sindex
, quoted
, (int *)NULL
, (int *)NULL
,
6782 (int *)NULL
, (int *)NULL
, pflags
);
6785 #if defined (ARRAY_VARS)
6786 else if (valid_array_reference (name
, 0))
6789 var
= array_variable_part (name
, 0, &tt
, (int *)0);
6790 /* These are the cases where word splitting will not be performed */
6791 if (pflags
& PF_ASSIGNRHS
)
6793 if (ALL_ELEMENT_SUB (tt
[0]) && tt
[1] == RBRACK
)
6795 /* Only treat as double quoted if array variable */
6796 if (var
&& (array_p (var
) || assoc_p (var
)))
6797 temp
= array_value (name
, quoted
|Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &atype
, &ind
);
6799 temp
= array_value (name
, quoted
, 0, &atype
, &ind
);
6802 temp
= array_value (name
, quoted
, 0, &atype
, &ind
);
6804 /* Posix interp 888 */
6805 else if (pflags
& PF_NOSPLIT2
)
6807 /* Special cases, then general case, for each of A[@], A[*], A[n] */
6808 #if defined (HANDLE_MULTIBYTE)
6809 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
6811 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
6813 temp
= array_value (name
, Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &atype
, &ind
);
6814 else if (tt
[0] == '@' && tt
[1] == RBRACK
)
6815 temp
= array_value (name
, quoted
, 0, &atype
, &ind
);
6816 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
6817 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &atype
, &ind
);
6818 else if (tt
[0] == '*' && tt
[1] == RBRACK
)
6819 temp
= array_value (name
, quoted
, 0, &atype
, &ind
);
6821 temp
= array_value (name
, quoted
, 0, &atype
, &ind
);
6823 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
6824 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &atype
, &ind
);
6826 temp
= array_value (name
, quoted
, 0, &atype
, &ind
);
6827 if (atype
== 0 && temp
)
6829 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
6830 ? quote_string (temp
)
6831 : quote_escapes (temp
);
6832 rflags
|= W_ARRAYIND
;
6836 else if (atype
== 1 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
6837 rflags
|= W_HASQUOTEDNULL
;
6840 else if (var
= find_variable (name
))
6842 if (var_isset (var
) && invisible_p (var
) == 0)
6844 #if defined (ARRAY_VARS)
6845 /* We avoid a memory leak by saving TT as the memory allocated by
6846 assoc_to_string or array_to_string and leaving it 0 otherwise,
6847 then freeing TT after quoting temp. */
6849 if ((pflags
& PF_ALLINDS
) && assoc_p (var
))
6850 tt
= temp
= assoc_empty (assoc_cell (var
)) ? (char *)NULL
: assoc_to_string (assoc_cell (var
), " ", quoted
);
6851 else if ((pflags
& PF_ALLINDS
) && array_p (var
))
6852 tt
= temp
= array_empty (array_cell (var
)) ? (char *)NULL
: array_to_string (array_cell (var
), " ", quoted
);
6853 else if (assoc_p (var
))
6854 temp
= assoc_reference (assoc_cell (var
), "0");
6855 else if (array_p (var
))
6856 temp
= array_reference (array_cell (var
), 0);
6858 temp
= value_cell (var
);
6860 temp
= value_cell (var
);
6864 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
6865 ? quote_string (temp
)
6866 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
6867 : quote_escapes (temp
));
6871 temp
= (char *)NULL
;
6873 else if (var
= find_variable_last_nameref (name
, 0))
6875 temp
= nameref_cell (var
);
6876 #if defined (ARRAY_VARS)
6877 /* Handle expanding nameref whose value is x[n] */
6878 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
6881 goto expand_arrayref
;
6885 /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
6886 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
6888 set_exit_status (EXECUTION_FAILURE
);
6889 report_error (_("%s: invalid variable name for name reference"), temp
);
6890 temp
= &expand_param_error
;
6893 temp
= (char *)NULL
;
6896 temp
= (char *)NULL
;
6900 ret
= alloc_word_desc ();
6902 ret
->flags
|= rflags
;
6908 parameter_brace_find_indir (name
, var_is_special
, quoted
, find_nameref
)
6910 int var_is_special
, quoted
, find_nameref
;
6917 if (find_nameref
&& var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)) &&
6918 nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
6919 return (savestring (t
));
6921 /* If var_is_special == 0, and name is not an array reference, this does
6922 more expansion than necessary. It should really look up the variable's
6923 value and not try to expand it. */
6924 pflags
= PF_IGNUNBOUND
;
6925 /* Note that we're not going to be doing word splitting here */
6928 pflags
|= PF_ASSIGNRHS
; /* suppresses word splitting */
6929 oldex
= expand_no_split_dollar_star
;
6930 expand_no_split_dollar_star
= 1;
6932 w
= parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, 0);
6934 expand_no_split_dollar_star
= oldex
;
6937 /* Have to dequote here if necessary */
6940 temp
= ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || var_is_special
)
6941 ? dequote_string (t
)
6942 : dequote_escapes (t
);
6946 dispose_word_desc (w
);
6951 /* Expand an indirect reference to a variable: ${!NAME} expands to the
6952 value of the variable whose name is the value of NAME. */
6954 parameter_brace_expand_indir (name
, var_is_special
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
6956 int var_is_special
, quoted
, pflags
;
6957 int *quoted_dollar_atp
, *contains_dollar_at
;
6963 /* See if it's a nameref first, behave in ksh93-compatible fashion.
6964 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
6965 bush performs an indirect lookup on foo[0] and expands the result;
6966 ksh93 expands bar[0]. We could do that here -- there are enough usable
6967 primitives to do that -- but do not at this point. */
6968 if (var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)))
6970 if (nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
6972 w
= alloc_word_desc ();
6973 w
->word
= savestring (t
);
6979 /* An indirect reference to a positional parameter or a special parameter
6980 is ok. Indirect references to array references, as explained above, are
6981 ok (currently). Only references to unset variables are errors at this
6983 if (legal_identifier (name
) && v
== 0)
6985 report_error (_("%s: invalid indirect expansion"), name
);
6986 w
= alloc_word_desc ();
6987 w
->word
= &expand_param_error
;
6992 t
= parameter_brace_find_indir (name
, var_is_special
, quoted
, 0);
6994 chk_atstar (t
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
6996 #if defined (ARRAY_VARS)
6997 /* Array references to unset variables are also an error */
6998 if (t
== 0 && valid_array_reference (name
, 0))
7000 v
= array_variable_part (name
, 0, (char **)0, (int *)0);
7003 report_error (_("%s: invalid indirect expansion"), name
);
7004 w
= alloc_word_desc ();
7005 w
->word
= &expand_param_error
;
7010 return (WORD_DESC
*)NULL
;
7015 return (WORD_DESC
*)NULL
;
7017 if (valid_brace_expansion_word (t
, SPECIAL_VAR (t
, 0)) == 0)
7019 report_error (_("%s: invalid variable name"), t
);
7021 w
= alloc_word_desc ();
7022 w
->word
= &expand_param_error
;
7027 w
= parameter_brace_expand_word (t
, SPECIAL_VAR(t
, 0), quoted
, pflags
, 0);
7033 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
7034 depending on the value of C, the separating character. C can be one of
7035 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
7036 between double quotes. */
7038 parameter_brace_expand_rhs (name
, value
, op
, quoted
, pflags
, qdollaratp
, hasdollarat
)
7040 int op
, quoted
, pflags
, *qdollaratp
, *hasdollarat
;
7044 char *t
, *t1
, *temp
, *vname
;
7045 int l_hasdollat
, sindex
;
7048 /*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
7049 /* If the entire expression is between double quotes, we want to treat
7050 the value as a double-quoted string, with the exception that we strip
7051 embedded unescaped double quotes (for sh backwards compatibility). */
7052 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *value
)
7055 temp
= string_extract_double_quoted (value
, &sindex
, SX_STRIPDQ
);
7060 w
= alloc_word_desc ();
7062 l
= *temp
? expand_string_for_rhs (temp
, quoted
, op
, pflags
, &l_hasdollat
, (int *)NULL
)
7065 *hasdollarat
= l_hasdollat
|| (l
&& l
->next
);
7069 /* list_string takes multiple CTLNULs and turns them into an empty word
7070 with W_SAWQUOTEDNULL set. Turn it back into a single CTLNUL for the
7071 rest of this function and the caller. */
7072 for (tl
= l
; tl
; tl
= tl
->next
)
7074 if (tl
->word
&& (tl
->word
->word
== 0 || tl
->word
->word
[0] == 0) &&
7075 (tl
->word
->flags
| W_SAWQUOTEDNULL
))
7077 t
= make_quoted_char ('\0');
7078 FREE (tl
->word
->word
);
7080 tl
->word
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
7081 tl
->word
->flags
&= ~W_SAWQUOTEDNULL
;
7087 /* If l->next is not null, we know that TEMP contained "$@", since that
7088 is the only expansion that creates more than one word. */
7089 if (qdollaratp
&& ((l_hasdollat
&& quoted
) || l
->next
))
7091 /*itrace("parameter_brace_expand_rhs: %s:%s: l != NULL, set *qdollaratp", name, value);*/
7095 /* The expansion of TEMP returned something. We need to treat things
7096 slightly differently if L_HASDOLLAT is non-zero. If we have "$@",
7097 the individual words have already been quoted. We need to turn them
7098 into a string with the words separated by the first character of
7099 $IFS without any additional quoting, so string_list_dollar_at won't
7100 do the right thing. If IFS is null, we want "$@" to split into
7101 separate arguments, not be concatenated, so we use string_list_internal
7102 and mark the word to be split on spaces later. We use
7103 string_list_dollar_star for "$@" otherwise. */
7104 if (l
->next
&& ifs_is_null
)
7106 temp
= string_list_internal (l
, " ");
7107 w
->flags
|= W_SPLITSPACE
;
7109 else if (l_hasdollat
|| l
->next
)
7110 temp
= string_list_dollar_star (l
, quoted
, 0);
7113 temp
= string_list (l
);
7114 if (temp
&& (QUOTED_NULL (temp
) == 0) && (l
->word
->flags
& W_SAWQUOTEDNULL
))
7115 w
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
7118 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
7119 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
7120 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
7121 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7122 (which is more paranoia than anything else), we need to return the
7123 quoted null string and set the flags to indicate it. */
7124 if (l
->next
== 0 && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
) && QUOTED_NULL (l
->word
->word
) && (l
->word
->flags
& W_HASQUOTEDNULL
))
7126 w
->flags
|= W_HASQUOTEDNULL
;
7127 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null, turning off qdollaratp", name, value);*/
7128 /* If we return a quoted null with L_HASDOLLARAT, we either have a
7129 construct like "${@-$@}" or "${@-${@-$@}}" with no positional
7130 parameters or a quoted expansion of "$@" with $1 == ''. In either
7131 case, we don't want to enable special handling of $@. */
7132 if (qdollaratp
&& l_hasdollat
)
7137 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && l_hasdollat
)
7139 /* Posix interp 221 changed the rules on this. The idea is that
7140 something like "$xxx$@" should expand the same as "${foo-$xxx$@}"
7141 when foo and xxx are unset. The problem is that it's not in any
7142 way backwards compatible and few other shells do it. We're eventually
7143 going to try and split the difference (heh) a little bit here. */
7144 /* l_hasdollat == 1 means we saw a quoted dollar at. */
7146 /* The brace expansion occurred between double quotes and there was
7147 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
7148 it does not expand to anything. In this case, we want to return
7149 a quoted empty string. Posix interp 888 */
7150 temp
= make_quoted_char ('\0');
7151 w
->flags
|= W_HASQUOTEDNULL
;
7152 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null", name, value);*/
7155 temp
= (char *)NULL
;
7157 if (op
== '-' || op
== '+')
7164 t1
= temp
? dequote_string (temp
) : savestring ("");
7170 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1]) || VALID_INDIR_PARAM (name
[1])))
7172 vname
= parameter_brace_find_indir (name
+ 1, SPECIAL_VAR (name
, 1), quoted
, 1);
7173 if (vname
== 0 || *vname
== 0)
7175 report_error (_("%s: invalid indirect expansion"), name
);
7179 return &expand_wdesc_error
;
7181 if (legal_identifier (vname
) == 0)
7183 report_error (_("%s: invalid variable name"), vname
);
7187 return &expand_wdesc_error
;
7191 #if defined (ARRAY_VARS)
7192 if (valid_array_reference (vname
, 0))
7193 v
= assign_array_element (vname
, t1
, 0);
7195 #endif /* ARRAY_VARS */
7196 v
= bind_variable (vname
, t1
, 0);
7198 if (v
== 0 || readonly_p (v
) || noassign_p (v
)) /* expansion error */
7200 if ((v
== 0 || readonly_p (v
)) && interactive_shell
== 0 && posixly_correct
)
7202 last_command_exit_value
= EXECUTION_FAILURE
;
7203 exp_jump_to_top_level (FORCE_EOF
);
7209 last_command_exit_value
= EX_BADUSAGE
;
7210 exp_jump_to_top_level (DISCARD
);
7214 stupidly_hack_special_variables (vname
);
7219 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
7221 /* If we are double-quoted or if we are not going to be performing word
7222 splitting, we want to quote the value we return appropriately, like
7223 the other expansions this function handles. */
7224 w
->word
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (t1
) : quote_escapes (t1
);
7225 /* If we have something that's non-null, that's not a quoted null string,
7226 and we're not going to be performing word splitting (we know we're not
7227 because the operator is `='), we can forget we saw a quoted null. */
7228 if (w
->word
&& w
->word
[0] && QUOTED_NULL (w
->word
) == 0)
7229 w
->flags
&= ~W_SAWQUOTEDNULL
;
7232 /* If we convert a null string into a quoted null, make sure the caller
7234 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && QUOTED_NULL (w
->word
))
7235 w
->flags
|= W_HASQUOTEDNULL
;
7240 /* Deal with the right hand side of a ${name:?value} expansion in the case
7241 that NAME is null or not set. If VALUE is non-null it is expanded and
7242 used as the error message to print, otherwise a standard message is
7245 parameter_brace_expand_error (name
, value
, check_null
)
7252 set_exit_status (EXECUTION_FAILURE
); /* ensure it's non-zero */
7253 if (value
&& *value
)
7255 l
= expand_string (value
, 0);
7256 temp
= string_list (l
);
7257 report_error ("%s: %s", name
, temp
? temp
: ""); /* XXX was value not "" */
7261 else if (check_null
== 0)
7262 report_error (_("%s: parameter not set"), name
);
7264 report_error (_("%s: parameter null or not set"), name
);
7266 /* Free the data we have allocated during this expansion, since we
7267 are about to longjmp out. */
7272 /* Return 1 if NAME is something for which parameter_brace_expand_length is
7275 valid_length_expression (name
)
7278 return (name
[1] == '\0' || /* ${#} */
7279 ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0') || /* special param */
7280 (DIGIT (name
[1]) && all_digits (name
+ 1)) || /* ${#11} */
7281 #if defined (ARRAY_VARS)
7282 valid_array_reference (name
+ 1, 0) || /* ${#a[7]} */
7284 legal_identifier (name
+ 1)); /* ${#PS1} */
7287 /* Handle the parameter brace expansion that requires us to return the
7288 length of a parameter. */
7290 parameter_brace_expand_length (name
)
7294 intmax_t number
, arg_index
;
7298 var
= (SHELL_VAR
*)NULL
;
7300 if (name
[1] == '\0') /* ${#} */
7301 number
= number_of_args ();
7302 else if (DOLLAR_AT_STAR (name
[1]) && name
[2] == '\0') /* ${#@}, ${#*} */
7303 number
= number_of_args ();
7304 else if ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0')
7306 /* Take the lengths of some of the shell's special parameters. */
7310 t
= which_set_flags ();
7313 t
= itos (last_command_exit_value
);
7316 t
= itos (dollar_dollar_pid
);
7319 if (last_asynchronous_pid
== NO_PID
)
7320 t
= (char *)NULL
; /* XXX - error if set -u set? */
7322 t
= itos (last_asynchronous_pid
);
7325 t
= itos (number_of_args ());
7328 number
= STRLEN (t
);
7331 #if defined (ARRAY_VARS)
7332 else if (valid_array_reference (name
+ 1, 0))
7333 number
= array_length_reference (name
+ 1);
7334 #endif /* ARRAY_VARS */
7339 if (legal_number (name
+ 1, &arg_index
)) /* ${#1} */
7341 t
= get_dollar_var_value (arg_index
);
7342 if (t
== 0 && unbound_vars_is_error
)
7344 number
= MB_STRLEN (t
);
7347 #if defined (ARRAY_VARS)
7348 else if ((var
= find_variable (name
+ 1)) && (invisible_p (var
) == 0) && (array_p (var
) || assoc_p (var
)))
7351 t
= assoc_reference (assoc_cell (var
), "0");
7353 t
= array_reference (array_cell (var
), 0);
7354 if (t
== 0 && unbound_vars_is_error
)
7356 number
= MB_STRLEN (t
);
7359 /* Fast path for the common case of taking the length of a non-dynamic
7360 scalar variable value. */
7361 else if ((var
|| (var
= find_variable (name
+ 1))) &&
7362 invisible_p (var
) == 0 &&
7363 array_p (var
) == 0 && assoc_p (var
) == 0 &&
7364 var
->dynamic_value
== 0)
7365 number
= value_cell (var
) ? MB_STRLEN (value_cell (var
)) : 0;
7366 else if (var
== 0 && unbound_vars_is_error
== 0)
7370 newname
= savestring (name
);
7372 list
= expand_string (newname
, Q_DOUBLE_QUOTES
);
7373 t
= list
? string_list (list
) : (char *)NULL
;
7376 dispose_words (list
);
7378 number
= t
? MB_STRLEN (t
) : 0;
7386 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
7387 so we do some ad-hoc parsing of an arithmetic expression to find
7388 the first DELIM, instead of using strchr(3). Two rules:
7389 1. If the substring contains a `(', read until closing `)'.
7390 2. If the substring contains a `?', read past one `:' for each `?'.
7391 The SD_ARITHEXP flag to skip_to_delim takes care of doing this.
7395 skiparith (substr
, delim
)
7405 i
= skip_to_delim (substr
, 0, delims
, SD_ARITHEXP
);
7406 return (substr
+ i
);
7409 /* Verify and limit the start and end of the desired substring. If
7410 VTYPE == 0, a regular shell variable is being used; if it is 1,
7411 then the positional parameters are being used; if it is 2, then
7412 VALUE is really a pointer to an array variable that should be used.
7413 Return value is 1 if both values were OK, 0 if there was a problem
7414 with an invalid expression, or -1 if the values were out of range. */
7416 verify_substring_values (v
, value
, substr
, vtype
, e1p
, e2p
)
7418 char *value
, *substr
;
7420 intmax_t *e1p
, *e2p
;
7422 char *t
, *temp1
, *temp2
;
7425 #if defined (ARRAY_VARS)
7430 /* duplicate behavior of strchr(3) */
7431 t
= skiparith (substr
, ':');
7432 if (*t
&& *t
== ':')
7437 temp1
= expand_arith_string (substr
, Q_DOUBLE_QUOTES
);
7438 *e1p
= evalexp (temp1
, 0, &expok
); /* XXX - EXP_EXPANDED? */
7443 len
= -1; /* paranoia */
7447 case VT_ARRAYMEMBER
:
7448 len
= MB_STRLEN (value
);
7451 len
= number_of_args () + 1;
7453 len
++; /* add one arg if counting from $0 */
7455 #if defined (ARRAY_VARS)
7457 /* For arrays, the first value deals with array indices. Negative
7458 offsets count from one past the array's maximum index. Associative
7459 arrays treat the number of elements as the maximum index. */
7463 len
= assoc_num_elements (h
) + (*e1p
< 0);
7468 len
= array_max_index (a
) + (*e1p
< 0); /* arrays index from 0 to n - 1 */
7474 if (len
== -1) /* paranoia */
7477 if (*e1p
< 0) /* negative offsets count from end */
7480 if (*e1p
> len
|| *e1p
< 0)
7483 #if defined (ARRAY_VARS)
7484 /* For arrays, the second offset deals with the number of elements. */
7485 if (vtype
== VT_ARRAYVAR
)
7486 len
= assoc_p (v
) ? assoc_num_elements (h
) : array_num_elements (a
);
7492 temp2
= savestring (t
);
7493 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
);
7496 *e2p
= evalexp (temp1
, 0, &expok
); /* XXX - EXP_EXPANDED? */
7501 /* Should we allow positional parameter length < 0 to count backwards
7502 from end of positional parameters? */
7504 if ((vtype
== VT_ARRAYVAR
|| vtype
== VT_POSPARMS
) && *e2p
< 0)
7505 #else /* TAG: bush-5.2 */
7506 if (vtype
== VT_ARRAYVAR
&& *e2p
< 0)
7509 internal_error (_("%s: substring expression < 0"), t
);
7512 #if defined (ARRAY_VARS)
7513 /* In order to deal with sparse arrays, push the intelligence about how
7514 to deal with the number of elements desired down to the array-
7515 specific functions. */
7516 if (vtype
!= VT_ARRAYVAR
)
7522 if (*e2p
< 0 || *e2p
< *e1p
)
7524 internal_error (_("%s: substring expression < 0"), t
);
7529 *e2p
+= *e1p
; /* want E2 chars starting at E1 */
7540 /* Return the type of variable specified by VARNAME (simple variable,
7541 positional param, or array variable). Also return the value specified
7542 by VARNAME (value of a variable or a reference to an array element).
7543 QUOTED is the standard description of quoting state, using Q_* defines.
7544 FLAGS is currently a set of flags to pass to array_value. If IND is
7545 non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
7546 passed to array_value so the array index is not computed again.
7547 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
7548 characters in the value are quoted with CTLESC and takes appropriate
7549 steps. For convenience, *VALP is set to the dequoted VALUE. */
7551 get_var_and_type (varname
, value
, ind
, quoted
, flags
, varp
, valp
)
7552 char *varname
, *value
;
7558 int vtype
, want_indir
;
7563 want_indir
= *varname
== '!' &&
7564 (legal_variable_starter ((unsigned char)varname
[1]) || DIGIT (varname
[1])
7565 || VALID_INDIR_PARAM (varname
[1]));
7567 vname
= parameter_brace_find_indir (varname
+1, SPECIAL_VAR (varname
, 1), quoted
, 1);
7568 /* XXX - what if vname == 0 || *vname == 0 ? */
7574 vtype
= VT_VARIABLE
;
7575 *varp
= (SHELL_VAR
*)NULL
;
7576 *valp
= (char *)NULL
;
7580 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
7581 vtype
= STR_DOLLAR_AT_STAR (vname
);
7582 if (vtype
== VT_POSPARMS
&& vname
[0] == '*')
7583 vtype
|= VT_STARSUB
;
7584 *varp
= (SHELL_VAR
*)NULL
;
7586 #if defined (ARRAY_VARS)
7587 if (valid_array_reference (vname
, 0))
7589 v
= array_variable_part (vname
, 0, &temp
, (int *)0);
7590 /* If we want to signal array_value to use an already-computed index,
7591 set LIND to that index */
7592 lind
= (ind
!= INTMAX_MIN
&& (flags
& AV_USEIND
)) ? ind
: 0;
7593 if (v
&& invisible_p (v
))
7595 vtype
= VT_ARRAYMEMBER
;
7596 *varp
= (SHELL_VAR
*)NULL
;
7597 *valp
= (char *)NULL
;
7599 if (v
&& (array_p (v
) || assoc_p (v
)))
7601 if (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
)
7603 /* Callers have to differentiate between indexed and associative */
7604 vtype
= VT_ARRAYVAR
;
7606 vtype
|= VT_STARSUB
;
7607 *valp
= array_p (v
) ? (char *)array_cell (v
) : (char *)assoc_cell (v
);
7611 vtype
= VT_ARRAYMEMBER
;
7612 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, (int *)NULL
, &lind
);
7616 else if (v
&& (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
))
7618 vtype
= VT_VARIABLE
;
7620 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
7621 *valp
= value
? dequote_string (value
) : (char *)NULL
;
7623 *valp
= value
? dequote_escapes (value
) : (char *)NULL
;
7627 vtype
= VT_ARRAYMEMBER
;
7629 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, (int *)NULL
, &lind
);
7632 else if ((v
= find_variable (vname
)) && (invisible_p (v
) == 0) && (assoc_p (v
) || array_p (v
)))
7634 vtype
= VT_ARRAYMEMBER
;
7636 *valp
= assoc_p (v
) ? assoc_reference (assoc_cell (v
), "0") : array_reference (array_cell (v
), 0);
7641 if (value
&& vtype
== VT_VARIABLE
)
7643 *varp
= find_variable (vname
);
7644 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
7645 *valp
= dequote_string (value
);
7647 *valp
= dequote_escapes (value
);
7659 /***********************************************************/
7661 /* Functions to perform transformations on variable values */
7663 /***********************************************************/
7666 string_var_assignment (v
, s
)
7670 char flags
[MAX_ATTRIBUTES
], *ret
, *val
;
7673 val
= (v
&& (invisible_p (v
) || var_isset (v
) == 0)) ? (char *)NULL
: sh_quote_reusable (s
, 0);
7674 i
= var_attribute_string (v
, 0, flags
);
7675 if (i
== 0 && val
== 0)
7676 return (char *)NULL
;
7678 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16 + MAX_ATTRIBUTES
);
7679 if (i
> 0 && val
== 0)
7680 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
7682 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
7684 sprintf (ret
, "%s=%s", v
->name
, val
);
7689 #if defined (ARRAY_VARS)
7691 array_var_assignment (v
, itype
, quoted
, atype
)
7693 int itype
, quoted
, atype
;
7695 char *ret
, *val
, flags
[MAX_ATTRIBUTES
];
7699 return (char *)NULL
;
7701 val
= array_p (v
) ? array_to_kvpair (array_cell (v
), 0)
7702 : assoc_to_kvpair (assoc_cell (v
), 0);
7704 val
= array_p (v
) ? array_to_assign (array_cell (v
), 0)
7705 : assoc_to_assign (assoc_cell (v
), 0);
7707 if (val
== 0 && (invisible_p (v
) || var_isset (v
) == 0))
7711 val
= (char *)xmalloc (3);
7718 ret
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (val
) : quote_escapes (val
);
7726 i
= var_attribute_string (v
, 0, flags
);
7727 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16);
7729 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
7731 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
7738 pos_params_assignment (list
, itype
, quoted
)
7745 /* first, we transform the list to quote each word. */
7746 temp
= list_transform ('Q', (SHELL_VAR
*)0, list
, itype
, quoted
);
7747 ret
= (char *)xmalloc (strlen (temp
) + 8);
7748 strcpy (ret
, "set -- ");
7749 strcpy (ret
+ 7, temp
);
7755 string_transform (xc
, v
, s
)
7760 char *ret
, flags
[MAX_ATTRIBUTES
], *t
;
7763 if (((xc
== 'A' || xc
== 'a') && v
== 0))
7764 return (char *)NULL
;
7765 else if (xc
!= 'a' && xc
!= 'A' && s
== 0)
7766 return (char *)NULL
;
7770 /* Transformations that interrogate the variable */
7772 i
= var_attribute_string (v
, 0, flags
);
7773 ret
= (i
> 0) ? savestring (flags
) : (char *)NULL
;
7776 ret
= string_var_assignment (v
, s
);
7779 ret
= sh_quote_reusable (s
, 0);
7781 /* Transformations that modify the variable's value */
7783 t
= ansiexpand (s
, 0, strlen (s
), (int *)0);
7784 ret
= dequote_escapes (t
);
7788 ret
= decode_prompt_string (s
);
7791 ret
= sh_quote_reusable (s
, 0);
7794 ret
= sh_modcase (s
, 0, CASE_UPPER
);
7797 ret
= sh_modcase (s
, 0, CASE_UPFIRST
); /* capitalize */
7800 ret
= sh_modcase (s
, 0, CASE_LOWER
);
7810 list_transform (xc
, v
, list
, itype
, quoted
)
7821 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
7823 tword
= string_transform (xc
, v
, l
->word
->word
);
7824 w
= alloc_word_desc ();
7825 w
->word
= tword
? tword
: savestring (""); /* XXX */
7826 new = make_word_list (w
, new);
7828 l
= REVERSE_LIST (new, WORD_LIST
*);
7831 /* If we are expanding in a context where word splitting will not be
7832 performed, treat as quoted. This changes how $* will be expanded. */
7833 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
7834 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
7836 tword
= string_list_pos_params (itype
, l
, qflags
, 0);
7843 parameter_list_transform (xc
, itype
, quoted
)
7851 list
= list_rest_of_args ();
7853 return ((char *)NULL
);
7855 ret
= pos_params_assignment (list
, itype
, quoted
);
7857 ret
= list_transform (xc
, (SHELL_VAR
*)0, list
, itype
, quoted
);
7858 dispose_words (list
);
7862 #if defined (ARRAY_VARS)
7864 array_transform (xc
, var
, starsub
, quoted
)
7867 int starsub
; /* so we can figure out how it's indexed */
7877 v
= var
; /* XXX - for now */
7879 itype
= starsub
? '*' : '@';
7882 return (array_var_assignment (v
, itype
, quoted
, 1));
7884 return (array_var_assignment (v
, itype
, quoted
, 2));
7886 /* special case for unset arrays and attributes */
7887 if (xc
== 'a' && (invisible_p (v
) || var_isset (v
) == 0))
7889 char flags
[MAX_ATTRIBUTES
];
7892 i
= var_attribute_string (v
, 0, flags
);
7893 return ((i
> 0) ? savestring (flags
) : (char *)NULL
);
7896 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
7897 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
7899 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
7901 return ((char *)NULL
);
7902 ret
= list_transform (xc
, v
, list
, itype
, quoted
);
7903 dispose_words (list
);
7907 #endif /* ARRAY_VARS */
7910 valid_parameter_transform (xform
)
7916 /* check for valid values of xform[0] */
7919 case 'a': /* expand to a string with just attributes */
7920 case 'A': /* expand as an assignment statement with attributes */
7921 case 'K': /* expand assoc array to list of key/value pairs */
7922 case 'E': /* expand like $'...' */
7923 case 'P': /* expand like prompt string */
7924 case 'Q': /* quote reusably */
7925 case 'U': /* transform to uppercase */
7926 case 'u': /* tranform by capitalizing */
7927 case 'L': /* transform to lowercase */
7935 parameter_brace_transform (varname
, value
, ind
, xform
, rtype
, quoted
, pflags
, flags
)
7936 char *varname
, *value
;
7939 int rtype
, quoted
, pflags
, flags
;
7941 int vtype
, xc
, starsub
;
7942 char *temp1
, *val
, *oname
;
7946 if (value
== 0 && xc
!= 'A' && xc
!= 'a')
7947 return ((char *)NULL
);
7949 oname
= this_command_name
;
7950 this_command_name
= varname
;
7952 vtype
= get_var_and_type (varname
, value
, ind
, quoted
, flags
, &v
, &val
);
7955 this_command_name
= oname
;
7956 return ((char *)NULL
);
7959 if (valid_parameter_transform (xform
) == 0)
7961 this_command_name
= oname
;
7962 #if 0 /* TAG: bush-5.2 Martin Schulte <gnu@schrader-schulte.de> 10/2020 */
7963 return (interactive_shell
? &expand_param_error
: &expand_param_fatal
);
7965 return &expand_param_error
;
7969 starsub
= vtype
& VT_STARSUB
;
7970 vtype
&= ~VT_STARSUB
;
7972 /* If we are asked to display the attributes of an unset variable, V will
7973 be NULL after the call to get_var_and_type. Double-check here. */
7974 if ((xc
== 'a' || xc
== 'A') && vtype
== VT_VARIABLE
&& varname
&& v
== 0)
7975 v
= find_variable (varname
);
7977 temp1
= (char *)NULL
; /* shut up gcc */
7981 case VT_ARRAYMEMBER
:
7982 temp1
= string_transform (xc
, v
, val
);
7983 if (vtype
== VT_VARIABLE
)
7987 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
7988 ? quote_string (temp1
)
7989 : quote_escapes (temp1
);
7994 #if defined (ARRAY_VARS)
7996 temp1
= array_transform (xc
, v
, starsub
, quoted
);
7997 if (temp1
&& quoted
== 0 && ifs_is_null
)
7999 /* Posix interp 888 */
8001 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8003 val
= quote_escapes (temp1
);
8010 temp1
= parameter_list_transform (xc
, varname
[0], quoted
);
8011 if (temp1
&& quoted
== 0 && ifs_is_null
)
8013 /* Posix interp 888 */
8015 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8017 val
= quote_escapes (temp1
);
8024 this_command_name
= oname
;
8028 /******************************************************/
8030 /* Functions to extract substrings of variable values */
8032 /******************************************************/
8034 #if defined (HANDLE_MULTIBYTE)
8035 /* Character-oriented rather than strictly byte-oriented substrings. S and
8036 E, rather being strict indices into STRING, indicate character (possibly
8037 multibyte character) positions that require calculation.
8038 Used by the ${param:offset[:length]} expansion. */
8040 mb_substring (string
, s
, e
)
8050 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
8051 slen
= (MB_CUR_MAX
> 1) ? STRLEN (string
) : 0;
8054 while (string
[start
] && i
--)
8055 ADVANCE_CHAR (string
, slen
, start
);
8058 while (string
[stop
] && i
--)
8059 ADVANCE_CHAR (string
, slen
, stop
);
8060 tt
= substring (string
, start
, stop
);
8065 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
8066 is `@', use the positional parameters; otherwise, use the value of
8067 VARNAME. If VARNAME is an array variable, use the array elements. */
8070 parameter_brace_substring (varname
, value
, ind
, substr
, quoted
, pflags
, flags
)
8071 char *varname
, *value
;
8074 int quoted
, pflags
, flags
;
8077 int vtype
, r
, starsub
;
8078 char *temp
, *val
, *tt
, *oname
;
8081 if (value
== 0 && ((varname
[0] != '@' && varname
[0] != '*') || varname
[1]))
8082 return ((char *)NULL
);
8084 oname
= this_command_name
;
8085 this_command_name
= varname
;
8087 vtype
= get_var_and_type (varname
, value
, ind
, quoted
, flags
, &v
, &val
);
8090 this_command_name
= oname
;
8091 return ((char *)NULL
);
8094 starsub
= vtype
& VT_STARSUB
;
8095 vtype
&= ~VT_STARSUB
;
8097 r
= verify_substring_values (v
, val
, substr
, vtype
, &e1
, &e2
);
8098 this_command_name
= oname
;
8101 if (vtype
== VT_VARIABLE
)
8103 return ((r
== 0) ? &expand_param_error
: (char *)NULL
);
8109 case VT_ARRAYMEMBER
:
8110 #if defined (HANDLE_MULTIBYTE)
8112 tt
= mb_substring (val
, e1
, e2
);
8115 tt
= substring (val
, e1
, e2
);
8117 if (vtype
== VT_VARIABLE
)
8119 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8120 temp
= quote_string (tt
);
8122 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8127 if (vtype
== VT_POSPARMS
)
8128 tt
= pos_params (varname
, e1
, e2
, quoted
, pflags
);
8129 #if defined (ARRAY_VARS)
8130 /* assoc_subrange and array_subrange both call string_list_pos_params,
8131 so we can treat this case just like VT_POSPARAMS. */
8132 else if (assoc_p (v
))
8133 /* we convert to list and take first e2 elements starting at e1th
8134 element -- officially undefined for now */
8135 tt
= assoc_subrange (assoc_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8137 /* We want E2 to be the number of elements desired (arrays can be
8138 sparse, so verify_substring_values just returns the numbers
8139 specified and we rely on array_subrange to understand how to
8141 tt
= array_subrange (array_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8143 /* We want to leave this alone in every case where pos_params/
8144 string_list_pos_params quotes the list members */
8145 if (tt
&& quoted
== 0 && ifs_is_null
)
8147 temp
= tt
; /* Posix interp 888 */
8149 else if (tt
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
8151 temp
= tt
; /* Posix interp 888 */
8153 else if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
8155 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8163 temp
= (char *)NULL
;
8169 /****************************************************************/
8171 /* Functions to perform pattern substitution on variable values */
8173 /****************************************************************/
8175 #ifdef INCLUDE_UNUSED
8177 shouldexp_replacement (s
)
8182 for (p
= s
; p
&& *p
; p
++)
8194 pat_subst (string
, pat
, rep
, mflags
)
8195 char *string
, *pat
, *rep
;
8198 char *ret
, *s
, *e
, *str
, *rstr
, *mstr
, *send
;
8199 int rptr
, mtype
, rxpand
, mlen
;
8200 size_t rsize
, l
, replen
, rslen
;
8204 return (savestring (""));
8206 mtype
= mflags
& MATCH_TYPEMASK
;
8208 #if 0 /* TAG: bush-5.2? */
8209 rxpand
= (rep
&& *rep
) ? shouldexp_replacement (rep
) : 0;
8215 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
8216 * with REP and return the result.
8217 * 2. A null pattern with mtype == MATCH_END means to append REP to
8218 * STRING and return the result.
8219 * 3. A null STRING with a matching pattern means to append REP to
8220 * STRING and return the result.
8221 * These don't understand or process `&' in the replacement string.
8223 if ((pat
== 0 || *pat
== 0) && (mtype
== MATCH_BEG
|| mtype
== MATCH_END
))
8225 replen
= STRLEN (rep
);
8226 l
= STRLEN (string
);
8227 ret
= (char *)xmalloc (replen
+ l
+ 2);
8229 strcpy (ret
, string
);
8230 else if (mtype
== MATCH_BEG
)
8233 strcpy (ret
+ replen
, string
);
8237 strcpy (ret
, string
);
8238 strcpy (ret
+ l
, rep
);
8242 else if (*string
== 0 && (match_pattern (string
, pat
, mtype
, &s
, &e
) != 0))
8244 replen
= STRLEN (rep
);
8245 ret
= (char *)xmalloc (replen
+ 1);
8253 ret
= (char *)xmalloc (rsize
= 64);
8255 send
= string
+ strlen (string
);
8257 for (replen
= STRLEN (rep
), rptr
= 0, str
= string
; *str
;)
8259 if (match_pattern (str
, pat
, mtype
, &s
, &e
) == 0)
8267 mstr
= xmalloc (mlen
+ 1);
8268 for (x
= 0; x
< mlen
; x
++)
8271 rstr
= strcreplace (rep
, '&', mstr
, 0);
8273 rslen
= strlen (rstr
);
8281 RESIZE_MALLOCED_BUFFER (ret
, rptr
, (l
+ rslen
), rsize
, 64);
8283 /* OK, now copy the leading unmatched portion of the string (from
8284 str to s) to ret starting at rptr (the current offset). Then copy
8285 the replacement string at ret + rptr + (s - str). Increment
8286 rptr (if necessary) and str and go on. */
8289 strncpy (ret
+ rptr
, str
, l
);
8294 strncpy (ret
+ rptr
, rstr
, rslen
);
8297 str
= e
; /* e == end of match */
8302 if (((mflags
& MATCH_GLOBREP
) == 0) || mtype
!= MATCH_ANY
)
8307 /* On a zero-length match, make sure we copy one character, since
8308 we increment one character to avoid infinite recursion. */
8309 char *p
, *origp
, *origs
;
8312 RESIZE_MALLOCED_BUFFER (ret
, rptr
, locale_mb_cur_max
, rsize
, 64);
8313 #if defined (HANDLE_MULTIBYTE)
8314 p
= origp
= ret
+ rptr
;
8316 COPY_CHAR_P (p
, str
, send
);
8320 ret
[rptr
++] = *str
++;
8321 e
++; /* avoid infinite recursion on zero-length match */
8326 /* Now copy the unmatched portion of the input string */
8329 RESIZE_MALLOCED_BUFFER (ret
, rptr
, STRLEN(str
) + 1, rsize
, 64);
8330 strcpy (ret
+ rptr
, str
);
8338 /* Do pattern match and replacement on the positional parameters. */
8340 pos_params_pat_subst (string
, pat
, rep
, mflags
)
8341 char *string
, *pat
, *rep
;
8344 WORD_LIST
*save
, *params
;
8347 int pchar
, qflags
, pflags
;
8349 save
= params
= list_rest_of_args ();
8351 return ((char *)NULL
);
8353 for ( ; params
; params
= params
->next
)
8355 ret
= pat_subst (params
->word
->word
, pat
, rep
, mflags
);
8356 w
= alloc_word_desc ();
8357 w
->word
= ret
? ret
: savestring ("");
8358 dispose_word (params
->word
);
8362 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
8363 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
8364 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
8366 /* If we are expanding in a context where word splitting will not be
8367 performed, treat as quoted. This changes how $* will be expanded. */
8368 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && expand_no_split_dollar_star
&& ifs_is_null
)
8369 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8371 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
8372 dispose_words (save
);
8377 /* Perform pattern substitution on VALUE, which is the expansion of
8378 VARNAME. PATSUB is an expression supplying the pattern to match
8379 and the string to substitute. QUOTED is a flags word containing
8380 the type of quoting currently in effect. */
8382 parameter_brace_patsub (varname
, value
, ind
, patsub
, quoted
, pflags
, flags
)
8383 char *varname
, *value
;
8386 int quoted
, pflags
, flags
;
8388 int vtype
, mflags
, starsub
, delim
;
8389 char *val
, *temp
, *pat
, *rep
, *p
, *lpatsub
, *tt
, *oname
;
8393 return ((char *)NULL
);
8395 oname
= this_command_name
;
8396 this_command_name
= varname
; /* error messages */
8398 vtype
= get_var_and_type (varname
, value
, ind
, quoted
, flags
, &v
, &val
);
8401 this_command_name
= oname
;
8402 return ((char *)NULL
);
8405 starsub
= vtype
& VT_STARSUB
;
8406 vtype
&= ~VT_STARSUB
;
8409 /* PATSUB is never NULL when this is called. */
8412 mflags
|= MATCH_GLOBREP
;
8416 /* Malloc this because expand_string_if_necessary or one of the expansion
8417 functions in its call chain may free it on a substitution error. */
8418 lpatsub
= savestring (patsub
);
8420 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
8421 mflags
|= MATCH_QUOTED
;
8424 mflags
|= MATCH_STARSUB
;
8426 if (pflags
& PF_ASSIGNRHS
)
8427 mflags
|= MATCH_ASSIGNRHS
;
8429 /* If the pattern starts with a `/', make sure we skip over it when looking
8430 for the replacement delimiter. */
8431 delim
= skip_to_delim (lpatsub
, ((*patsub
== '/') ? 1 : 0), "/", 0);
8432 if (lpatsub
[delim
] == '/')
8435 rep
= lpatsub
+ delim
+ 1;
8440 if (rep
&& *rep
== '\0')
8443 /* Perform the same expansions on the pattern as performed by the
8444 pattern removal expansions. */
8445 pat
= getpattern (lpatsub
, quoted
, 1);
8449 /* We want to perform quote removal on the expanded replacement even if
8450 the entire expansion is double-quoted because the parser and string
8451 extraction functions treated quotes in the replacement string as
8452 special. THIS IS NOT BACKWARDS COMPATIBLE WITH BUSH-4.2. */
8453 if (shell_compatibility_level
> 42)
8454 rep
= expand_string_if_necessary (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
), expand_string_unsplit
);
8455 /* This is the bush-4.2 code. */
8456 else if ((mflags
& MATCH_QUOTED
) == 0)
8457 rep
= expand_string_if_necessary (rep
, quoted
, expand_string_unsplit
);
8459 rep
= expand_string_to_string_internal (rep
, quoted
, expand_string_unsplit
);
8462 /* ksh93 doesn't allow the match specifier to be a part of the expanded
8463 pattern. This is an extension. Make sure we don't anchor the pattern
8464 at the beginning or end of the string if we're doing global replacement,
8467 if (mflags
& MATCH_GLOBREP
)
8468 mflags
|= MATCH_ANY
;
8469 else if (pat
&& pat
[0] == '#')
8471 mflags
|= MATCH_BEG
;
8474 else if (pat
&& pat
[0] == '%')
8476 mflags
|= MATCH_END
;
8480 mflags
|= MATCH_ANY
;
8482 /* OK, we now want to substitute REP for PAT in VAL. If
8483 flags & MATCH_GLOBREP is non-zero, the substitution is done
8484 everywhere, otherwise only the first occurrence of PAT is
8485 replaced. The pattern matching code doesn't understand
8486 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
8487 values passed in (VT_VARIABLE) so the pattern substitution
8488 code works right. We need to requote special chars after
8489 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
8490 other cases if QUOTED == 0, since the posparams and arrays
8491 indexed by * or @ do special things when QUOTED != 0. */
8496 case VT_ARRAYMEMBER
:
8497 temp
= pat_subst (val
, p
, rep
, mflags
);
8498 if (vtype
== VT_VARIABLE
)
8502 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
8508 /* This does the right thing for the case where we are not performing
8509 word splitting. MATCH_STARSUB restricts it to ${* /foo/bar}, and
8510 pos_params_pat_subst/string_list_pos_params will do the right thing
8511 in turn for the case where ifs_is_null. Posix interp 888 */
8512 if ((pflags
& PF_NOSPLIT2
) && (mflags
& MATCH_STARSUB
))
8513 mflags
|= MATCH_ASSIGNRHS
;
8514 temp
= pos_params_pat_subst (val
, p
, rep
, mflags
);
8515 if (temp
&& quoted
== 0 && ifs_is_null
)
8517 /* Posix interp 888 */
8519 else if (temp
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
8521 /* Posix interp 888 */
8523 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
8525 tt
= quote_escapes (temp
);
8530 #if defined (ARRAY_VARS)
8532 /* If we are expanding in a context where word splitting will not be
8533 performed, treat as quoted. This changes how ${A[*]} will be
8534 expanded to make it identical to $*. */
8535 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
8536 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
8538 /* these eventually call string_list_pos_params */
8540 temp
= assoc_patsub (assoc_cell (v
), p
, rep
, mflags
);
8542 temp
= array_patsub (array_cell (v
), p
, rep
, mflags
);
8544 if (temp
&& quoted
== 0 && ifs_is_null
)
8546 /* Posix interp 888 */
8548 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
8550 tt
= quote_escapes (temp
);
8562 this_command_name
= oname
;
8567 /****************************************************************/
8569 /* Functions to perform case modification on variable values */
8571 /****************************************************************/
8573 /* Do case modification on the positional parameters. */
8576 pos_params_modcase (string
, pat
, modop
, mflags
)
8581 WORD_LIST
*save
, *params
;
8584 int pchar
, qflags
, pflags
;
8586 save
= params
= list_rest_of_args ();
8588 return ((char *)NULL
);
8590 for ( ; params
; params
= params
->next
)
8592 ret
= sh_modcase (params
->word
->word
, pat
, modop
);
8593 w
= alloc_word_desc ();
8594 w
->word
= ret
? ret
: savestring ("");
8595 dispose_word (params
->word
);
8599 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
8600 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
8601 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
8603 /* If we are expanding in a context where word splitting will not be
8604 performed, treat as quoted. This changes how $* will be expanded. */
8605 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
8606 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8608 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
8609 dispose_words (save
);
8614 /* Perform case modification on VALUE, which is the expansion of
8615 VARNAME. MODSPEC is an expression supplying the type of modification
8616 to perform. QUOTED is a flags word containing the type of quoting
8617 currently in effect. */
8619 parameter_brace_casemod (varname
, value
, ind
, modspec
, patspec
, quoted
, pflags
, flags
)
8620 char *varname
, *value
;
8623 int quoted
, pflags
, flags
;
8625 int vtype
, starsub
, modop
, mflags
, x
;
8626 char *val
, *temp
, *pat
, *p
, *lpat
, *tt
, *oname
;
8630 return ((char *)NULL
);
8632 oname
= this_command_name
;
8633 this_command_name
= varname
;
8635 vtype
= get_var_and_type (varname
, value
, ind
, quoted
, flags
, &v
, &val
);
8638 this_command_name
= oname
;
8639 return ((char *)NULL
);
8642 starsub
= vtype
& VT_STARSUB
;
8643 vtype
&= ~VT_STARSUB
;
8647 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
8648 mflags
|= MATCH_QUOTED
;
8650 mflags
|= MATCH_STARSUB
;
8651 if (pflags
& PF_ASSIGNRHS
)
8652 mflags
|= MATCH_ASSIGNRHS
;
8657 x
= p
&& p
[0] == modspec
;
8658 modop
= x
? CASE_UPPER
: CASE_UPFIRST
;
8661 else if (modspec
== ',')
8663 x
= p
&& p
[0] == modspec
;
8664 modop
= x
? CASE_LOWER
: CASE_LOWFIRST
;
8667 else if (modspec
== '~')
8669 x
= p
&& p
[0] == modspec
;
8670 modop
= x
? CASE_TOGGLEALL
: CASE_TOGGLE
;
8674 lpat
= p
? savestring (p
) : 0;
8675 /* Perform the same expansions on the pattern as performed by the
8676 pattern removal expansions. */
8677 pat
= lpat
? getpattern (lpat
, quoted
, 1) : 0;
8679 /* OK, now we do the case modification. */
8683 case VT_ARRAYMEMBER
:
8684 temp
= sh_modcase (val
, pat
, modop
);
8685 if (vtype
== VT_VARIABLE
)
8689 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
8696 temp
= pos_params_modcase (val
, pat
, modop
, mflags
);
8697 if (temp
&& quoted
== 0 && ifs_is_null
)
8699 /* Posix interp 888 */
8701 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
8703 tt
= quote_escapes (temp
);
8709 #if defined (ARRAY_VARS)
8711 /* If we are expanding in a context where word splitting will not be
8712 performed, treat as quoted. This changes how ${A[*]} will be
8713 expanded to make it identical to $*. */
8714 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
8715 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
8717 temp
= assoc_p (v
) ? assoc_modcase (assoc_cell (v
), pat
, modop
, mflags
)
8718 : array_modcase (array_cell (v
), pat
, modop
, mflags
);
8720 if (temp
&& quoted
== 0 && ifs_is_null
)
8722 /* Posix interp 888 */
8724 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
8726 tt
= quote_escapes (temp
);
8738 this_command_name
= oname
;
8743 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
8744 any occur, this must be a nested command substitution, so return 0.
8745 Otherwise, return 1. A valid arithmetic expression must always have a
8746 ( before a matching ), so any cases where there are more right parens
8747 means that this must not be an arithmetic expression, though the parser
8748 will not accept it without a balanced total number of parens. */
8750 chk_arithsub (s
, len
)
8762 else if (s
[i
] == RPAREN
)
8772 ADVANCE_CHAR (s
, len
, i
);
8778 ADVANCE_CHAR (s
, len
, i
);
8782 i
= skip_single_quoted (s
, len
, ++i
, 0);
8786 i
= skip_double_quoted ((char *)s
, len
, ++i
, 0);
8791 return (count
== 0);
8794 /****************************************************************/
8796 /* Functions to perform parameter expansion on a string */
8798 /****************************************************************/
8800 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
8802 parameter_brace_expand (string
, indexp
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
8804 int *indexp
, quoted
, pflags
, *quoted_dollar_atp
, *contains_dollar_at
;
8806 int check_nullness
, var_is_set
, var_is_null
, var_is_special
;
8807 int want_substring
, want_indir
, want_patsub
, want_casemod
, want_attributes
;
8808 char *name
, *value
, *temp
, *temp1
;
8809 WORD_DESC
*tdesc
, *ret
;
8810 int t_index
, sindex
, c
, tflag
, modspec
, local_pflags
, all_element_arrayref
;
8814 temp
= temp1
= value
= (char *)NULL
;
8815 var_is_set
= var_is_null
= var_is_special
= check_nullness
= 0;
8816 want_substring
= want_indir
= want_patsub
= want_casemod
= want_attributes
= 0;
8819 all_element_arrayref
= 0;
8823 /* ${#var} doesn't have any of the other parameter expansions on it. */
8824 if (string
[t_index
] == '#' && legal_variable_starter (string
[t_index
+1])) /* {{ */
8825 name
= string_extract (string
, &t_index
, "}", SX_VARNAME
);
8827 #if defined (CASEMOD_EXPANSIONS)
8828 /* To enable case-toggling expansions using the `~' operator character
8829 define CASEMOD_TOGGLECASE in config-top.h */
8830 # if defined (CASEMOD_TOGGLECASE)
8831 name
= string_extract (string
, &t_index
, "#%^,~:-=?+/@}", SX_VARNAME
);
8833 name
= string_extract (string
, &t_index
, "#%^,:-=?+/@}", SX_VARNAME
);
8834 # endif /* CASEMOD_TOGGLECASE */
8836 name
= string_extract (string
, &t_index
, "#%:-=?+/@}", SX_VARNAME
);
8837 #endif /* CASEMOD_EXPANSIONS */
8839 /* Handle ${@[stuff]} now that @ is a word expansion operator. Not exactly
8840 the cleanest code ever. */
8841 if (*name
== 0 && sindex
== t_index
&& string
[sindex
] == '@')
8843 name
= (char *)xrealloc (name
, 2);
8848 else if (*name
== '!' && t_index
> sindex
&& string
[t_index
] == '@' && string
[t_index
+1] == RBRACE
)
8850 name
= (char *)xrealloc (name
, t_index
- sindex
+ 2);
8851 name
[t_index
- sindex
] = '@';
8852 name
[t_index
- sindex
+ 1] = '\0';
8861 /* If the name really consists of a special variable, then make sure
8862 that we have the entire name. We don't allow indirect references
8863 to special variables except `#', `?', `@' and `*'. This clause is
8864 designed to handle ${#SPECIAL} and ${!SPECIAL}, not anything more
8866 if ((sindex
== t_index
&& VALID_SPECIAL_LENGTH_PARAM (string
[t_index
])) ||
8867 (sindex
== t_index
&& string
[sindex
] == '#' && VALID_SPECIAL_LENGTH_PARAM (string
[sindex
+ 1])) ||
8868 (sindex
== t_index
- 1 && string
[sindex
] == '!' && VALID_INDIR_PARAM (string
[t_index
])))
8871 temp1
= string_extract (string
, &t_index
, "#%:-=?+/@}", 0);
8872 name
= (char *)xrealloc (name
, 3 + (strlen (temp1
)));
8873 *name
= string
[sindex
];
8874 if (string
[sindex
] == '!')
8876 /* indirect reference of $#, $?, $@, or $* */
8877 name
[1] = string
[sindex
+ 1];
8878 strcpy (name
+ 2, temp1
);
8881 strcpy (name
+ 1, temp1
);
8886 /* Find out what character ended the variable name. Then
8887 do the appropriate thing. */
8888 if (c
= string
[sindex
])
8891 /* If c is followed by one of the valid parameter expansion
8892 characters, move past it as normal. If not, assume that
8893 a substring specification is being given, and do not move
8895 if (c
== ':' && VALID_PARAM_EXPAND_CHAR (string
[sindex
]))
8898 if (c
= string
[sindex
])
8901 else if (c
== ':' && string
[sindex
] != RBRACE
)
8903 else if (c
== '/' /* && string[sindex] != RBRACE */) /* XXX */
8905 #if defined (CASEMOD_EXPANSIONS)
8906 else if (c
== '^' || c
== ',' || c
== '~')
8912 else if (c
== '@' && (string
[sindex
] == 'a' || string
[sindex
] == 'A') && string
[sindex
+1] == RBRACE
)
8914 /* special case because we do not want to shortcut foo as foo[0] here */
8915 want_attributes
= 1;
8916 local_pflags
|= PF_ALLINDS
;
8919 /* Catch the valid and invalid brace expressions that made it through the
8921 /* ${#-} is a valid expansion and means to take the length of $-.
8922 Similarly for ${#?} and ${##}... */
8923 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
8924 VALID_SPECIAL_LENGTH_PARAM (c
) && string
[sindex
] == RBRACE
)
8926 name
= (char *)xrealloc (name
, 3);
8929 c
= string
[sindex
++];
8932 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
8933 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
8934 member (c
, "%:=+/") && string
[sindex
] == RBRACE
)
8936 temp
= (char *)NULL
;
8937 goto bad_substitution
; /* XXX - substitution error */
8940 /* Indirect expansion begins with a `!'. A valid indirect expansion is
8941 either a variable name, one of the positional parameters or a special
8942 variable that expands to one of the positional parameters. */
8943 want_indir
= *name
== '!' &&
8944 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1])
8945 || VALID_INDIR_PARAM (name
[1]));
8947 /* Determine the value of this variable whose name is NAME. */
8949 /* Check for special variables, directly referenced. */
8950 if (SPECIAL_VAR (name
, want_indir
))
8953 /* Check for special expansion things, like the length of a parameter */
8954 if (*name
== '#' && name
[1])
8956 /* If we are not pointing at the character just after the
8957 closing brace, then we haven't gotten all of the name.
8958 Since it begins with a special character, this is a bad
8959 substitution. Also check NAME for validity before trying
8961 if (string
[sindex
- 1] != RBRACE
|| (valid_length_expression (name
) == 0))
8963 temp
= (char *)NULL
;
8964 goto bad_substitution
; /* substitution error */
8967 number
= parameter_brace_expand_length (name
);
8968 if (number
== INTMAX_MIN
&& unbound_vars_is_error
)
8970 set_exit_status (EXECUTION_FAILURE
);
8971 err_unboundvar (name
+1);
8973 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
8979 return (&expand_wdesc_error
);
8982 ret
= alloc_word_desc ();
8983 ret
->word
= itos (number
);
8988 /* ${@} is identical to $@. */
8989 if (name
[0] == '@' && name
[1] == '\0')
8991 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
8992 *quoted_dollar_atp
= 1;
8994 if (contains_dollar_at
)
8995 *contains_dollar_at
= 1;
8997 tflag
|= W_DOLLARAT
;
9000 /* Process ${!PREFIX*} expansion. */
9001 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9002 (string
[sindex
- 2] == '*' || string
[sindex
- 2] == '@') &&
9003 legal_variable_starter ((unsigned char) name
[1]))
9008 temp1
= savestring (name
+ 1);
9009 number
= strlen (temp1
);
9010 temp1
[number
- 1] = '\0';
9011 x
= all_variables_matching_prefix (temp1
);
9012 xlist
= strvec_to_word_list (x
, 0, 0);
9013 if (string
[sindex
- 2] == '*')
9014 temp
= string_list_dollar_star (xlist
, quoted
, 0);
9017 temp
= string_list_dollar_at (xlist
, quoted
, 0);
9018 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9019 *quoted_dollar_atp
= 1;
9020 if (contains_dollar_at
)
9021 *contains_dollar_at
= 1;
9023 tflag
|= W_DOLLARAT
;
9026 dispose_words (xlist
);
9032 ret
= alloc_word_desc ();
9034 ret
->flags
= tflag
; /* XXX */
9038 #if defined (ARRAY_VARS)
9039 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */
9040 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9041 string
[sindex
- 2] == RBRACK
&& valid_array_reference (name
+1, 0))
9045 temp1
= savestring (name
+ 1);
9046 x
= array_variable_name (temp1
, 0, &x1
, (int *)0);
9048 if (ALL_ELEMENT_SUB (x1
[0]) && x1
[1] == RBRACK
)
9050 temp
= array_keys (temp1
, quoted
, pflags
); /* handles assoc vars too */
9053 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9054 *quoted_dollar_atp
= 1;
9055 if (contains_dollar_at
)
9056 *contains_dollar_at
= 1;
9058 tflag
|= W_DOLLARAT
;
9065 ret
= alloc_word_desc ();
9067 ret
->flags
= tflag
; /* XXX */
9073 #endif /* ARRAY_VARS */
9075 /* Make sure that NAME is valid before trying to go on. */
9076 if (valid_brace_expansion_word (want_indir
? name
+ 1 : name
,
9077 var_is_special
) == 0)
9079 temp
= (char *)NULL
;
9080 goto bad_substitution
; /* substitution error */
9085 tdesc
= parameter_brace_expand_indir (name
+ 1, var_is_special
, quoted
, pflags
|local_pflags
, quoted_dollar_atp
, contains_dollar_at
);
9086 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9088 temp
= (char *)NULL
;
9089 goto bad_substitution
;
9092 /* Turn off the W_ARRAYIND flag because there is no way for this function
9093 to return the index we're supposed to be using. */
9094 if (tdesc
&& tdesc
->flags
)
9095 tdesc
->flags
&= ~W_ARRAYIND
;
9099 local_pflags
|= PF_IGNUNBOUND
|(pflags
&(PF_NOSPLIT2
|PF_ASSIGNRHS
));
9100 tdesc
= parameter_brace_expand_word (name
, var_is_special
, quoted
, local_pflags
, &ind
);
9103 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9112 tflag
= tdesc
->flags
;
9113 dispose_word_desc (tdesc
);
9118 if (temp
== &expand_param_error
|| temp
== &expand_param_fatal
)
9122 return (temp
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9125 #if defined (ARRAY_VARS)
9126 if (valid_array_reference (name
, 0))
9132 /* If in a context where word splitting will not take place, treat as
9133 if double-quoted. Has effects with $* and ${array[*]} */
9135 if (pflags
& PF_ASSIGNRHS
)
9136 qflags
|= Q_DOUBLE_QUOTES
;
9137 /* We duplicate a little code here */
9138 t
= mbschr (name
, LBRACK
);
9139 if (t
&& ALL_ELEMENT_SUB (t
[1]) && t
[2] == RBRACK
)
9141 all_element_arrayref
= 1;
9142 if (expand_no_split_dollar_star
&& t
[1] == '*') /* XXX */
9143 qflags
|= Q_DOUBLE_QUOTES
;
9145 chk_atstar (name
, qflags
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
9149 var_is_set
= temp
!= (char *)0;
9150 var_is_null
= check_nullness
&& (var_is_set
== 0 || *temp
== 0);
9151 /* XXX - this may not need to be restricted to special variables */
9153 var_is_null
|= var_is_set
&& var_is_special
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
);
9154 #if defined (ARRAY_VARS)
9156 var_is_null
|= var_is_set
&&
9157 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) &&
9158 QUOTED_NULL (temp
) &&
9159 valid_array_reference (name
, 0) &&
9160 chk_atstar (name
, 0, 0, (int *)0, (int *)0);
9163 /* Get the rest of the stuff inside the braces. */
9164 if (c
&& c
!= RBRACE
)
9166 /* Extract the contents of the ${ ... } expansion
9167 according to the Posix.2 rules. */
9168 value
= extract_dollar_brace_string (string
, &sindex
, quoted
, (c
== '%' || c
== '#' || c
=='/' || c
== '^' || c
== ',' || c
==':') ? SX_POSIXEXP
|SX_WORD
: SX_WORD
);
9169 if (string
[sindex
] == RBRACE
)
9172 goto bad_substitution
; /* substitution error */
9175 value
= (char *)NULL
;
9179 /* All the cases where an expansion can possibly generate an unbound
9181 if (want_substring
|| want_patsub
|| want_casemod
|| c
== '@' || c
== '#' || c
== '%' || c
== RBRACE
)
9183 if (var_is_set
== 0 && unbound_vars_is_error
&& ((name
[0] != '@' && name
[0] != '*') || name
[1]) && all_element_arrayref
== 0)
9185 set_exit_status (EXECUTION_FAILURE
);
9186 err_unboundvar (name
);
9190 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9194 /* If this is a substring spec, process it and add the result. */
9197 temp1
= parameter_brace_substring (name
, temp
, ind
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9201 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9204 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9207 ret
= alloc_word_desc ();
9209 /* We test quoted_dollar_atp because we want variants with double-quoted
9210 "$@" to take a different code path. In fact, we make sure at the end
9211 of expand_word_internal that we're only looking at these flags if
9212 quoted_dollar_at == 0. */
9214 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9215 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9216 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9217 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 &&
9218 (pflags
& PF_ASSIGNRHS
))
9219 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9220 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9221 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9222 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9227 else if (want_patsub
)
9229 temp1
= parameter_brace_patsub (name
, temp
, ind
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9233 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9236 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9239 ret
= alloc_word_desc ();
9242 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9243 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9244 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9245 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9246 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9247 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9252 #if defined (CASEMOD_EXPANSIONS)
9253 else if (want_casemod
)
9255 temp1
= parameter_brace_casemod (name
, temp
, ind
, modspec
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9259 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9262 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9265 ret
= alloc_word_desc ();
9268 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9269 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9270 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9271 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9272 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9273 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9280 /* Do the right thing based on which character ended the variable name. */
9286 set_exit_status (EXECUTION_FAILURE
);
9287 report_error (_("%s: bad substitution"), string
? string
: "??");
9291 if (shell_compatibility_level
<= 43)
9292 return &expand_wdesc_error
;
9294 return ((posixly_correct
&& interactive_shell
== 0) ? &expand_wdesc_fatal
: &expand_wdesc_error
);
9300 temp1
= parameter_brace_transform (name
, temp
, ind
, value
, c
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9304 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9307 set_exit_status (EXECUTION_FAILURE
);
9308 report_error (_("%s: bad substitution"), string
? string
: "??");
9309 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9312 ret
= alloc_word_desc ();
9314 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9315 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9316 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9317 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9318 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9323 case '#': /* ${param#[#]pattern} */
9324 case '%': /* ${param%[%]pattern} */
9325 if (value
== 0 || *value
== '\0' || temp
== 0 || *temp
== '\0')
9330 temp1
= parameter_brace_remove_pattern (name
, temp
, ind
, value
, c
, quoted
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9334 ret
= alloc_word_desc ();
9336 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9337 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9338 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9339 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9340 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9349 if (var_is_set
&& var_is_null
== 0)
9351 /* If the operator is `+', we don't want the value of the named
9352 variable for anything, just the value of the right hand side. */
9355 /* XXX -- if we're double-quoted and the named variable is "$@",
9356 we want to turn off any special handling of "$@" --
9357 we're not using it, so whatever is on the rhs applies. */
9358 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9359 *quoted_dollar_atp
= 0;
9360 if (contains_dollar_at
)
9361 *contains_dollar_at
= 0;
9366 /* From Posix discussion on austin-group list. Issue 221
9367 requires that backslashes escaping `}' inside
9368 double-quoted ${...} be removed. */
9369 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9370 quoted
|= Q_DOLBRACE
;
9371 ret
= parameter_brace_expand_rhs (name
, value
, c
,
9375 contains_dollar_at
);
9376 /* XXX - fix up later, esp. noting presence of
9377 W_HASQUOTEDNULL in ret->flags */
9381 temp
= (char *)NULL
;
9387 /* Otherwise do nothing; just use the value in TEMP. */
9389 else /* VAR not set or VAR is NULL. */
9392 temp
= (char *)NULL
;
9393 if (c
== '=' && var_is_special
)
9395 set_exit_status (EXECUTION_FAILURE
);
9396 report_error (_("$%s: cannot assign in this way"), name
);
9399 return &expand_wdesc_error
;
9403 parameter_brace_expand_error (name
, value
, check_nullness
);
9404 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9408 /* XXX -- if we're double-quoted and the named variable is "$@",
9409 we want to turn off any special handling of "$@" --
9410 we're not using it, so whatever is on the rhs applies. */
9411 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9412 *quoted_dollar_atp
= 0;
9413 if (contains_dollar_at
)
9414 *contains_dollar_at
= 0;
9416 /* From Posix discussion on austin-group list. Issue 221 requires
9417 that backslashes escaping `}' inside double-quoted ${...} be
9419 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9420 quoted
|= Q_DOLBRACE
;
9421 ret
= parameter_brace_expand_rhs (name
, value
, c
, quoted
, pflags
,
9423 contains_dollar_at
);
9424 /* XXX - fix up later, esp. noting presence of
9425 W_HASQUOTEDNULL in tdesc->flags */
9436 ret
= alloc_word_desc ();
9443 /* Expand a single ${xxx} expansion. The braces are optional. When
9444 the braces are used, parameter_brace_expand() does the work,
9445 possibly calling param_expand recursively. */
9447 param_expand (string
, sindex
, quoted
, expanded_something
,
9448 contains_dollar_at
, quoted_dollar_at_p
, had_quoted_null_p
,
9451 int *sindex
, quoted
, *expanded_something
, *contains_dollar_at
;
9452 int *quoted_dollar_at_p
, *had_quoted_null_p
, pflags
;
9454 char *temp
, *temp1
, uerror
[3], *savecmd
;
9455 int zindex
, t_index
, expok
;
9459 WORD_LIST
*list
, *l
;
9460 WORD_DESC
*tdesc
, *ret
;
9463 /*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
9465 c
= string
[++zindex
];
9467 temp
= (char *)NULL
;
9468 ret
= tdesc
= (WORD_DESC
*)NULL
;
9471 /* Do simple cases first. Switch on what follows '$'. */
9485 temp1
= dollar_vars
[TODIGIT (c
)];
9486 /* This doesn't get called when (pflags&PF_IGNUNBOUND) != 0 */
9487 if (unbound_vars_is_error
&& temp1
== (char *)NULL
)
9492 set_exit_status (EXECUTION_FAILURE
);
9493 err_unboundvar (uerror
);
9494 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9497 temp
= (*temp1
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9498 ? quote_string (temp1
)
9499 : quote_escapes (temp1
);
9501 temp
= (char *)NULL
;
9505 /* $$ -- pid of the invoking shell. */
9507 temp
= itos (dollar_dollar_pid
);
9510 /* $# -- number of positional parameters. */
9512 temp
= itos (number_of_args ());
9515 /* $? -- return value of the last synchronous command. */
9517 temp
= itos (last_command_exit_value
);
9520 /* $- -- flags supplied to the shell on invocation or by `set'. */
9522 temp
= which_set_flags ();
9525 /* $! -- Pid of the last asynchronous command. */
9527 /* If no asynchronous pids have been created, expand to nothing.
9528 If `set -u' has been executed, and no async processes have
9529 been created, this is an expansion error. */
9530 if (last_asynchronous_pid
== NO_PID
)
9532 if (expanded_something
)
9533 *expanded_something
= 0;
9534 temp
= (char *)NULL
;
9535 if (unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
9540 set_exit_status (EXECUTION_FAILURE
);
9541 err_unboundvar (uerror
);
9542 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9546 temp
= itos (last_asynchronous_pid
);
9549 /* The only difference between this and $@ is when the arg is quoted. */
9550 case '*': /* `$*' */
9551 list
= list_rest_of_args ();
9554 /* According to austin-group posix proposal by Geoff Clare in
9555 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
9557 "The shell shall write a message to standard error and
9558 immediately exit when it tries to expand an unset parameter
9559 other than the '@' and '*' special parameters."
9562 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
9567 set_exit_status (EXECUTION_FAILURE
);
9568 err_unboundvar (uerror
);
9569 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9573 /* If there are no command-line arguments, this should just
9574 disappear if there are other characters in the expansion,
9575 even if it's quoted. */
9576 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && list
== 0)
9577 temp
= (char *)NULL
;
9578 else if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
9580 /* If we have "$*" we want to make a string of the positional
9581 parameters, separated by the first character of $IFS, and
9582 quote the whole string, including the separators. If IFS
9583 is unset, the parameters are separated by ' '; if $IFS is
9584 null, the parameters are concatenated. */
9585 temp
= (quoted
& (Q_DOUBLE_QUOTES
|Q_PATQUOTE
)) ? string_list_dollar_star (list
, quoted
, 0) : string_list (list
);
9588 temp1
= (quoted
& Q_DOUBLE_QUOTES
) ? quote_string (temp
) : temp
;
9590 tflag
|= W_HASQUOTEDNULL
;
9598 /* We check whether or not we're eventually going to split $* here,
9599 for example when IFS is empty and we are processing the rhs of
9600 an assignment statement. In that case, we don't separate the
9601 arguments at all. Otherwise, if the $* is not quoted it is
9603 if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
== 0 && (pflags
& PF_ASSIGNRHS
))
9605 /* Posix interp 888: RHS of assignment, IFS unset: no splitting,
9606 separate with space */
9607 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
9608 temp
= temp1
? quote_string (temp1
) : temp1
;
9609 /* XXX - tentative - note that we saw a quoted null here */
9610 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
9611 tflag
|= W_SAWQUOTEDNULL
;
9614 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_null
&& (pflags
& PF_ASSIGNRHS
))
9616 /* Posix interp 888: RHS of assignment, IFS set to '' */
9617 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
9618 temp
= temp1
? quote_escapes (temp1
) : temp1
;
9621 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && (pflags
& PF_ASSIGNRHS
))
9623 /* Posix interp 888: RHS of assignment, IFS set to non-null value */
9624 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
9625 temp
= temp1
? quote_string (temp1
) : temp1
;
9627 /* XXX - tentative - note that we saw a quoted null here */
9628 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
9629 tflag
|= W_SAWQUOTEDNULL
;
9632 /* XXX - should we check ifs_is_set here as well? */
9633 # if defined (HANDLE_MULTIBYTE)
9634 else if (expand_no_split_dollar_star
&& ifs_firstc
[0] == 0)
9636 else if (expand_no_split_dollar_star
&& ifs_firstc
== 0)
9638 /* Posix interp 888: not RHS, no splitting, IFS set to '' */
9639 temp
= string_list_dollar_star (list
, quoted
, 0);
9642 temp
= string_list_dollar_at (list
, quoted
, 0);
9643 /* Set W_SPLITSPACE to make sure the individual positional
9644 parameters are split into separate arguments */
9646 if (quoted
== 0 && (ifs_is_set
== 0 || ifs_is_null
))
9647 #else /* change with bush-5.0 */
9648 if (quoted
== 0 && ifs_is_null
)
9650 tflag
|= W_SPLITSPACE
;
9651 /* If we're not quoted but we still don't want word splitting, make
9652 we quote the IFS characters to protect them from splitting (e.g.,
9653 when $@ is in the string as well). */
9654 else if (temp
&& quoted
== 0 && ifs_is_set
&& (pflags
& PF_ASSIGNRHS
))
9656 temp1
= quote_string (temp
);
9662 if (expand_no_split_dollar_star
== 0 && contains_dollar_at
)
9663 *contains_dollar_at
= 1;
9666 dispose_words (list
);
9669 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
9670 means that we have to turn quoting off after we split into
9671 the individually quoted arguments so that the final split
9672 on the first character of $IFS is still done. */
9673 case '@': /* `$@' */
9674 list
= list_rest_of_args ();
9677 /* According to austin-group posix proposal by Geoff Clare in
9678 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
9680 "The shell shall write a message to standard error and
9681 immediately exit when it tries to expand an unset parameter
9682 other than the '@' and '*' special parameters."
9685 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
9690 set_exit_status (EXECUTION_FAILURE
);
9691 err_unboundvar (uerror
);
9692 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9696 for (nullarg
= 0, l
= list
; l
; l
= l
->next
)
9698 if (l
->word
&& (l
->word
->word
== 0 || l
->word
->word
[0] == 0))
9702 /* We want to flag the fact that we saw this. We can't turn
9703 off quoting entirely, because other characters in the
9704 string might need it (consider "\"$@\""), but we need some
9705 way to signal that the final split on the first character
9706 of $IFS should be done, even though QUOTED is 1. */
9707 /* XXX - should this test include Q_PATQUOTE? */
9708 if (quoted_dollar_at_p
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9709 *quoted_dollar_at_p
= 1;
9710 if (contains_dollar_at
)
9711 *contains_dollar_at
= 1;
9713 /* We want to separate the positional parameters with the first
9714 character of $IFS in case $IFS is something other than a space.
9715 We also want to make sure that splitting is done no matter what --
9716 according to POSIX.2, this expands to a list of the positional
9717 parameters no matter what IFS is set to. */
9718 /* XXX - what to do when in a context where word splitting is not
9719 performed? Even when IFS is not the default, posix seems to imply
9720 that we have to expand $@ to all the positional parameters and
9721 separate them with spaces, which are preserved because word splitting
9722 doesn't take place. See below for how we use PF_NOSPLIT2 here. */
9724 /* These are the cases where word splitting will not be performed. */
9725 if (pflags
& PF_ASSIGNRHS
)
9727 temp
= string_list_dollar_at (list
, (quoted
|Q_DOUBLE_QUOTES
), pflags
);
9729 tflag
|= W_HASQUOTEDNULL
; /* we know quoting produces quoted nulls */
9732 /* This needs to match what expand_word_internal does with non-quoted $@
9733 does with separating with spaces. Passing Q_DOUBLE_QUOTES means that
9734 the characters in LIST will be quoted, and PF_ASSIGNRHS ensures that
9735 they will separated by spaces. After doing this, we need the special
9736 handling for PF_NOSPLIT2 in expand_word_internal to remove the CTLESC
9738 else if (pflags
& PF_NOSPLIT2
)
9740 #if defined (HANDLE_MULTIBYTE)
9741 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
9743 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
9745 /* Posix interp 888 */
9746 temp
= string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, pflags
);
9748 temp
= string_list_dollar_at (list
, quoted
, pflags
);
9751 temp
= string_list_dollar_at (list
, quoted
, pflags
);
9753 tflag
|= W_DOLLARAT
;
9754 dispose_words (list
);
9758 tdesc
= parameter_brace_expand (string
, &zindex
, quoted
, pflags
,
9760 contains_dollar_at
);
9762 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9764 temp
= tdesc
? tdesc
->word
: (char *)0;
9767 /* Quoted nulls should be removed if there is anything else
9769 /* Note that we saw the quoted null so we can add one back at
9770 the end of this function if there are no other characters
9771 in the string, discard TEMP, and go on. The exception to
9772 this is when we have "${@}" and $1 is '', since $@ needs
9773 special handling. */
9774 if (tdesc
&& tdesc
->word
&& (tdesc
->flags
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
))
9776 if (had_quoted_null_p
)
9777 *had_quoted_null_p
= 1;
9778 if (*quoted_dollar_at_p
== 0)
9781 tdesc
->word
= temp
= (char *)NULL
;
9789 /* Do command or arithmetic substitution. */
9791 /* We have to extract the contents of this paren substitution. */
9792 t_index
= zindex
+ 1;
9793 /* XXX - might want to check for string[t_index+2] == LPAREN and parse
9794 as arithmetic substitution immediately. */
9795 temp
= extract_command_subst (string
, &t_index
, (pflags
&PF_COMPLETE
) ? SX_COMPLETE
: 0);
9798 /* For Posix.2-style `$(( ))' arithmetic substitution,
9799 extract the expression and pass it to the evaluator. */
9800 if (temp
&& *temp
== LPAREN
)
9804 temp2
= savestring (temp1
);
9805 t_index
= strlen (temp2
) - 1;
9807 if (temp2
[t_index
] != RPAREN
)
9813 /* Cut off ending `)' */
9814 temp2
[t_index
] = '\0';
9816 if (chk_arithsub (temp2
, t_index
) == 0)
9820 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
9825 /* Expand variables found inside the expression. */
9826 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
9830 /* No error messages. */
9831 savecmd
= this_command_name
;
9832 this_command_name
= (char *)NULL
;
9833 number
= evalexp (temp1
, EXP_EXPANDED
, &expok
);
9834 this_command_name
= savecmd
;
9839 if (interactive_shell
== 0 && posixly_correct
)
9841 set_exit_status (EXECUTION_FAILURE
);
9842 return (&expand_wdesc_fatal
);
9845 return (&expand_wdesc_error
);
9847 temp
= itos (number
);
9852 if (pflags
& PF_NOCOMSUB
)
9853 /* we need zindex+1 because string[zindex] == RPAREN */
9854 temp1
= substring (string
, *sindex
, zindex
+1);
9857 tdesc
= command_substitute (temp
, quoted
, pflags
&PF_ASSIGNRHS
);
9858 temp1
= tdesc
? tdesc
->word
: (char *)NULL
;
9860 dispose_word_desc (tdesc
);
9866 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
9867 away in a future bush release. */
9869 /* Extract the contents of this arithmetic substitution. */
9870 t_index
= zindex
+ 1;
9871 temp
= extract_arithmetic_subst (string
, &t_index
);
9875 temp
= savestring (string
);
9876 if (expanded_something
)
9877 *expanded_something
= 0;
9881 /* Do initial variable expansion. */
9882 temp1
= expand_arith_string (temp
, Q_DOUBLE_QUOTES
|Q_ARITH
);
9887 /* Find the variable in VARIABLE_LIST. */
9888 temp
= (char *)NULL
;
9890 for (t_index
= zindex
; (c
= string
[zindex
]) && legal_variable_char (c
); zindex
++)
9894 if (string
[zindex
+1] == ':')
9901 temp1
= (zindex
> t_index
) ? substring (string
, t_index
, zindex
) : (char *)NULL
;
9903 /* If this isn't a variable name, then just output the `$'. */
9904 if (temp1
== 0 || *temp1
== '\0')
9907 temp
= (char *)xmalloc (2);
9910 if (expanded_something
)
9911 *expanded_something
= 0;
9915 /* If the variable exists, return its value cell. */
9916 var
= find_variable (temp1
);
9918 if (var
&& invisible_p (var
) == 0 && var_isset (var
))
9920 #if defined (ARRAY_VARS)
9921 if (assoc_p (var
) || array_p (var
))
9923 temp
= array_p (var
) ? array_reference (array_cell (var
), 0)
9924 : assoc_reference (assoc_cell (var
), "0");
9926 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9927 ? quote_string (temp
)
9928 : quote_escapes (temp
);
9929 else if (unbound_vars_is_error
)
9930 goto unbound_variable
;
9935 temp
= value_cell (var
);
9937 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9938 ? quote_string (temp
)
9939 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
9940 : quote_escapes (temp
));
9947 else if (var
&& (invisible_p (var
) || var_isset (var
) == 0))
9948 temp
= (char *)NULL
;
9949 else if ((var
= find_variable_last_nameref (temp1
, 0)) && var_isset (var
) && invisible_p (var
) == 0)
9951 temp
= nameref_cell (var
);
9952 #if defined (ARRAY_VARS)
9953 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
9955 tdesc
= parameter_brace_expand_word (temp
, SPECIAL_VAR (temp
, 0), quoted
, pflags
, (arrayind_t
*)NULL
);
9956 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9963 /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
9964 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
9966 set_exit_status (EXECUTION_FAILURE
);
9967 report_error (_("%s: invalid variable name for name reference"), temp
);
9968 return (&expand_wdesc_error
); /* XXX */
9971 temp
= (char *)NULL
;
9974 temp
= (char *)NULL
;
9977 if (unbound_vars_is_error
)
9979 set_exit_status (EXECUTION_FAILURE
);
9980 err_unboundvar (temp1
);
9989 set_exit_status (EXECUTION_FAILURE
);
9990 return ((unbound_vars_is_error
&& interactive_shell
== 0)
9991 ? &expand_wdesc_fatal
9992 : &expand_wdesc_error
);
10003 ret
= alloc_word_desc ();
10004 ret
->flags
= tflag
; /* XXX */
10011 invalidate_cached_quoted_dollar_at ()
10013 dispose_words (cached_quoted_dollar_at
);
10014 cached_quoted_dollar_at
= 0;
10017 /* Make a word list which is the result of parameter and variable
10018 expansion, command substitution, arithmetic substitution, and
10019 quote removal of WORD. Return a pointer to a WORD_LIST which is
10020 the result of the expansion. If WORD contains a null word, the
10021 word list returned is also null.
10023 QUOTED contains flag values defined in shell.h.
10025 ISEXP is used to tell expand_word_internal that the word should be
10026 treated as the result of an expansion. This has implications for
10027 how IFS characters in the word are treated.
10029 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
10030 they point to an integer value which receives information about expansion.
10031 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
10032 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
10035 This only does word splitting in the case of $@ expansion. In that
10036 case, we split on ' '. */
10038 /* Values for the local variable quoted_state. */
10040 #define PARTIALLY_QUOTED 1
10041 #define WHOLLY_QUOTED 2
10044 expand_word_internal (word
, quoted
, isexp
, contains_dollar_at
, expanded_something
)
10047 int *contains_dollar_at
;
10048 int *expanded_something
;
10053 /* The intermediate string that we build while expanding. */
10056 /* The current size of the above object. */
10057 size_t istring_size
;
10059 /* Index into ISTRING. */
10062 /* Temporary string storage. */
10063 char *temp
, *temp1
;
10065 /* The text of WORD. */
10066 register char *string
;
10068 /* The size of STRING. */
10069 size_t string_size
;
10071 /* The index into STRING. */
10074 /* This gets 1 if we see a $@ while quoted. */
10075 int quoted_dollar_at
;
10077 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
10078 whether WORD contains no quoting characters, a partially quoted
10079 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
10083 int had_quoted_null
;
10084 int has_quoted_ifs
; /* did we add a quoted $IFS character here? */
10085 int has_dollar_at
, temp_has_dollar_at
;
10086 int split_on_spaces
;
10087 int local_expanded
;
10089 int pflags
; /* flags passed to param_expand */
10092 int assignoff
; /* If assignment, offset of `=' */
10094 register unsigned char c
; /* Current character. */
10095 int t_index
; /* For calls to string_extract_xxx. */
10101 /* OK, let's see if we can optimize a common idiom: "$@" */
10102 if (STREQ (word
->word
, "\"$@\"") &&
10103 (word
->flags
== (W_HASDOLLAR
|W_QUOTED
)) &&
10104 dollar_vars
[1]) /* XXX - check IFS here as well? */
10106 if (contains_dollar_at
)
10107 *contains_dollar_at
= 1;
10108 if (expanded_something
)
10109 *expanded_something
= 1;
10110 if (cached_quoted_dollar_at
)
10111 return (copy_word_list (cached_quoted_dollar_at
));
10112 list
= list_rest_of_args ();
10113 list
= quote_list (list
);
10114 cached_quoted_dollar_at
= copy_word_list (list
);
10118 istring
= (char *)xmalloc (istring_size
= DEFAULT_INITIAL_ARRAY_SIZE
);
10119 istring
[istring_index
= 0] = '\0';
10120 quoted_dollar_at
= had_quoted_null
= has_dollar_at
= 0;
10121 has_quoted_ifs
= 0;
10122 split_on_spaces
= 0;
10123 quoted_state
= UNQUOTED
;
10125 string
= word
->word
;
10127 goto finished_with_string
;
10128 mb_cur_max
= MB_CUR_MAX
;
10130 /* Don't need the string length for the SADD... and COPY_ macros unless
10131 multibyte characters are possible, but do need it for bounds checking. */
10132 string_size
= (mb_cur_max
> 1) ? strlen (string
) : 1;
10134 if (contains_dollar_at
)
10135 *contains_dollar_at
= 0;
10139 /* Begin the expansion. */
10141 for (sindex
= 0; ;)
10143 c
= string
[sindex
];
10145 /* Case on top-level character. */
10149 goto finished_with_string
;
10153 #if HANDLE_MULTIBYTE
10154 if (mb_cur_max
> 1 && string
[sindex
])
10156 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
10161 temp
= (char *)xmalloc (3);
10163 temp
[1] = c
= string
[sindex
];
10168 if (string
[sindex
])
10174 istring
= sub_append_string (temp
, istring
, &istring_index
, &istring_size
);
10180 #if defined (PROCESS_SUBSTITUTION)
10181 /* Process substitution. */
10185 /* XXX - technically this should only be expanded at the start
10187 if (string
[++sindex
] != LPAREN
|| (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (word
->flags
& (W_DQUOTE
|W_NOPROCSUB
)))
10189 sindex
--; /* add_character: label increments sindex */
10190 goto add_character
;
10193 t_index
= sindex
+ 1; /* skip past both '<' and LPAREN */
10195 temp1
= extract_process_subst (string
, (c
== '<') ? "<(" : ">(", &t_index
, 0); /*))*/
10198 /* If the process substitution specification is `<()', we want to
10199 open the pipe for writing in the child and produce output; if
10200 it is `>()', we want to open the pipe for reading in the child
10201 and consume input. */
10202 temp
= temp1
? process_substitute (temp1
, (c
== '>')) : (char *)0;
10206 goto dollar_add_string
;
10208 #endif /* PROCESS_SUBSTITUTION */
10211 /* Posix.2 section 3.6.1 says that tildes following `=' in words
10212 which are not assignment statements are not expanded. If the
10213 shell isn't in posix mode, though, we perform tilde expansion
10214 on `likely candidate' unquoted assignment statements (flags
10215 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
10216 contains an unquoted :~ or =~. Something to think about: we
10217 now have a flag that says to perform tilde expansion on arguments
10218 to `assignment builtins' like declare and export that look like
10219 assignment statements. We now do tilde expansion on such words
10220 even in POSIX mode. */
10221 if (word
->flags
& (W_ASSIGNRHS
|W_NOTILDE
))
10223 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
10224 goto add_ifs_character
;
10226 goto add_character
;
10228 /* If we're not in posix mode or forcing assignment-statement tilde
10229 expansion, note where the first `=' appears in the word and prepare
10230 to do tilde expansion following the first `='. We have to keep
10231 track of the first `=' (using assignoff) to avoid being confused
10232 by an `=' in the rhs of the assignment statement. */
10233 if ((word
->flags
& W_ASSIGNMENT
) &&
10234 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
10235 assignoff
== -1 && sindex
> 0)
10236 assignoff
= sindex
;
10237 if (sindex
== assignoff
&& string
[sindex
+1] == '~') /* XXX */
10238 word
->flags
|= W_ITILDE
;
10240 if (word
->flags
& W_ASSIGNARG
)
10241 word
->flags
|= W_ASSIGNRHS
; /* affects $@ */
10243 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
10246 goto add_ifs_character
;
10249 goto add_character
;
10252 if (word
->flags
& (W_NOTILDE
|W_NOASSNTILDE
))
10254 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
10255 goto add_ifs_character
;
10257 goto add_character
;
10260 if ((word
->flags
& (W_ASSIGNMENT
|W_ASSIGNRHS
)) &&
10261 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
10262 string
[sindex
+1] == '~')
10263 word
->flags
|= W_ITILDE
;
10265 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
10266 goto add_ifs_character
;
10268 goto add_character
;
10271 /* If the word isn't supposed to be tilde expanded, or we're not
10272 at the start of a word or after an unquoted : or = in an
10273 assignment statement, we don't do tilde expansion. We don't
10274 do tilde expansion if quoted or in an arithmetic context. */
10276 if ((word
->flags
& (W_NOTILDE
|W_DQUOTE
)) ||
10277 (sindex
> 0 && ((word
->flags
& W_ITILDE
) == 0)) ||
10278 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
10280 word
->flags
&= ~W_ITILDE
;
10281 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
10282 goto add_ifs_character
;
10284 goto add_character
;
10287 if (word
->flags
& W_ASSIGNRHS
)
10289 else if (word
->flags
& (W_ASSIGNMENT
|W_TILDEEXP
))
10294 temp
= bush_tilde_find_word (string
+ sindex
, tflag
, &t_index
);
10296 word
->flags
&= ~W_ITILDE
;
10298 if (temp
&& *temp
&& t_index
> 0)
10300 temp1
= bush_tilde_expand (temp
, tflag
);
10301 if (temp1
&& *temp1
== '~' && STREQ (temp
, temp1
))
10305 goto add_character
; /* tilde expansion failed */
10310 goto add_quoted_string
; /* XXX was add_string */
10315 goto add_character
;
10319 if (expanded_something
)
10320 *expanded_something
= 1;
10321 local_expanded
= 1;
10323 temp_has_dollar_at
= 0;
10324 pflags
= (word
->flags
& W_NOCOMSUB
) ? PF_NOCOMSUB
: 0;
10325 if (word
->flags
& W_NOSPLIT2
)
10326 pflags
|= PF_NOSPLIT2
;
10327 if (word
->flags
& W_ASSIGNRHS
)
10328 pflags
|= PF_ASSIGNRHS
;
10329 if (word
->flags
& W_COMPLETE
)
10330 pflags
|= PF_COMPLETE
;
10332 tword
= param_expand (string
, &sindex
, quoted
, expanded_something
,
10333 &temp_has_dollar_at
, "ed_dollar_at
,
10334 &had_quoted_null
, pflags
);
10335 has_dollar_at
+= temp_has_dollar_at
;
10336 split_on_spaces
+= (tword
->flags
& W_SPLITSPACE
);
10338 if (tword
== &expand_wdesc_error
|| tword
== &expand_wdesc_fatal
)
10342 return ((tword
== &expand_wdesc_error
) ? &expand_word_error
10343 : &expand_word_fatal
);
10345 if (contains_dollar_at
&& has_dollar_at
)
10346 *contains_dollar_at
= 1;
10348 if (tword
&& (tword
->flags
& W_HASQUOTEDNULL
))
10349 had_quoted_null
= 1; /* note for later */
10350 if (tword
&& (tword
->flags
& W_SAWQUOTEDNULL
))
10351 had_quoted_null
= 1; /* XXX */
10353 temp
= tword
? tword
->word
: (char *)NULL
;
10354 dispose_word_desc (tword
);
10356 /* Kill quoted nulls; we will add them back at the end of
10357 expand_word_internal if nothing else in the string */
10358 if (had_quoted_null
&& temp
&& QUOTED_NULL (temp
))
10361 temp
= (char *)NULL
;
10367 case '`': /* Backquoted command substitution. */
10369 t_index
= sindex
++;
10371 temp
= string_extract (string
, &sindex
, "`", SX_REQMATCH
);
10372 /* The test of sindex against t_index is to allow bare instances of
10373 ` to pass through, for backwards compatibility. */
10374 if (temp
== &extract_string_error
|| temp
== &extract_string_fatal
)
10376 if (sindex
- 1 == t_index
)
10379 goto add_character
;
10381 set_exit_status (EXECUTION_FAILURE
);
10382 report_error (_("bad substitution: no closing \"`\" in %s") , string
+t_index
);
10385 return ((temp
== &extract_string_error
) ? &expand_word_error
10386 : &expand_word_fatal
);
10389 if (expanded_something
)
10390 *expanded_something
= 1;
10391 local_expanded
= 1;
10393 if (word
->flags
& W_NOCOMSUB
)
10394 /* sindex + 1 because string[sindex] == '`' */
10395 temp1
= substring (string
, t_index
, sindex
+ 1);
10398 de_backslash (temp
);
10399 tword
= command_substitute (temp
, quoted
, 0);
10400 temp1
= tword
? tword
->word
: (char *)NULL
;
10402 dispose_word_desc (tword
);
10406 goto dollar_add_string
;
10410 if (string
[sindex
+ 1] == '\n')
10416 c
= string
[++sindex
];
10418 /* "However, the double-quote character ( '"' ) shall not be treated
10419 specially within a here-document, except when the double-quote
10420 appears within "$()", "``", or "${}"." */
10421 if ((quoted
& Q_HERE_DOCUMENT
) && (quoted
& Q_DOLBRACE
) && c
== '"')
10422 tflag
= CBSDQUOTE
; /* special case */
10423 else if (quoted
& Q_HERE_DOCUMENT
)
10425 else if (quoted
& Q_DOUBLE_QUOTES
)
10430 /* From Posix discussion on austin-group list: Backslash escaping
10431 a } in ${...} is removed. Issue 0000221 */
10432 if ((quoted
& Q_DOLBRACE
) && c
== RBRACE
)
10434 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
10436 /* This is the fix for " $@\ " */
10437 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0) && isexp
== 0 && isifs (c
))
10439 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
10440 DEFAULT_ARRAY_SIZE
);
10441 istring
[istring_index
++] = CTLESC
;
10442 istring
[istring_index
++] = '\\';
10443 istring
[istring_index
] = '\0';
10445 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
10447 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && c
== 0)
10449 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
10450 DEFAULT_ARRAY_SIZE
);
10451 istring
[istring_index
++] = CTLESC
;
10452 istring
[istring_index
++] = '\\';
10453 istring
[istring_index
] = '\0';
10456 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0))
10458 SCOPY_CHAR_I (twochars
, '\\', c
, string
, sindex
, string_size
);
10463 sindex
--; /* add_character: label increments sindex */
10464 goto add_character
;
10468 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
10473 /* BEFORE jumping here, we need to increment sindex if appropriate */
10474 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
10475 DEFAULT_ARRAY_SIZE
);
10476 istring
[istring_index
++] = twochars
[0];
10477 istring
[istring_index
++] = twochars
[1];
10478 istring
[istring_index
] = '\0';
10483 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && ((quoted
& Q_ARITH
) == 0))
10484 goto add_character
;
10486 t_index
= ++sindex
;
10487 temp
= string_extract_double_quoted (string
, &sindex
, (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: 0);
10489 /* If the quotes surrounded the entire string, then the
10490 whole word was quoted. */
10491 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
10493 : PARTIALLY_QUOTED
;
10497 tword
= alloc_word_desc ();
10498 tword
->word
= temp
;
10500 if (word
->flags
& W_ASSIGNARG
)
10501 tword
->flags
|= word
->flags
& (W_ASSIGNARG
|W_ASSIGNRHS
); /* affects $@ */
10502 if (word
->flags
& W_COMPLETE
)
10503 tword
->flags
|= W_COMPLETE
; /* for command substitutions */
10504 if (word
->flags
& W_NOCOMSUB
)
10505 tword
->flags
|= W_NOCOMSUB
;
10506 if (word
->flags
& W_NOPROCSUB
)
10507 tword
->flags
|= W_NOPROCSUB
;
10509 if (word
->flags
& W_ASSIGNRHS
)
10510 tword
->flags
|= W_ASSIGNRHS
;
10512 temp
= (char *)NULL
;
10514 temp_has_dollar_at
= 0; /* does this quoted (sub)string include $@? */
10515 /* Need to get W_HASQUOTEDNULL flag through this function. */
10516 list
= expand_word_internal (tword
, Q_DOUBLE_QUOTES
, 0, &temp_has_dollar_at
, (int *)NULL
);
10517 has_dollar_at
+= temp_has_dollar_at
;
10519 if (list
== &expand_word_error
|| list
== &expand_word_fatal
)
10523 /* expand_word_internal has already freed temp_word->word
10524 for us because of the way it prints error messages. */
10525 tword
->word
= (char *)NULL
;
10526 dispose_word (tword
);
10530 dispose_word (tword
);
10532 /* "$@" (a double-quoted dollar-at) expands into nothing,
10533 not even a NULL word, when there are no positional
10534 parameters. Posix interp 888 says that other parts of the
10535 word that expand to quoted nulls result in quoted nulls, so
10536 we can't just throw the entire word away if we have "$@"
10537 anywhere in it. We use had_quoted_null to keep track */
10538 if (list
== 0 && temp_has_dollar_at
) /* XXX - was has_dollar_at */
10540 quoted_dollar_at
++;
10544 /* If this list comes back with a quoted null from expansion,
10545 we have either "$x" or "$@" with $1 == ''. In either case,
10546 we need to make sure we add a quoted null argument and
10547 disable the special handling that "$@" gets. */
10548 if (list
&& list
->word
&& list
->next
== 0 && (list
->word
->flags
& W_HASQUOTEDNULL
))
10550 if (had_quoted_null
&& temp_has_dollar_at
)
10551 quoted_dollar_at
++;
10552 had_quoted_null
= 1; /* XXX */
10555 /* If we get "$@", we know we have expanded something, so we
10556 need to remember it for the final split on $IFS. This is
10557 a special case; it's the only case where a quoted string
10558 can expand into more than one word. It's going to come back
10559 from the above call to expand_word_internal as a list with
10562 dequote_list (list
);
10564 if (temp_has_dollar_at
) /* XXX - was has_dollar_at */
10566 quoted_dollar_at
++;
10567 if (contains_dollar_at
)
10568 *contains_dollar_at
= 1;
10569 if (expanded_something
)
10570 *expanded_something
= 1;
10571 local_expanded
= 1;
10576 /* What we have is "". This is a minor optimization. */
10578 list
= (WORD_LIST
*)NULL
;
10579 had_quoted_null
= 1; /* note for later */
10582 /* The code above *might* return a list (consider the case of "$@",
10583 where it returns "$1", "$2", etc.). We can't throw away the
10584 rest of the list, and we have to make sure each word gets added
10585 as quoted. We test on tresult->next: if it is non-NULL, we
10586 quote the whole list, save it to a string with string_list, and
10587 add that string. We don't need to quote the results of this
10588 (and it would be wrong, since that would quote the separators
10589 as well), so we go directly to add_string. */
10594 /* Testing quoted_dollar_at makes sure that "$@" is
10595 split correctly when $IFS does not contain a space. */
10596 temp
= quoted_dollar_at
10597 ? string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, 0)
10598 : string_list (quote_list (list
));
10599 dispose_words (list
);
10604 temp
= savestring (list
->word
->word
);
10605 tflag
= list
->word
->flags
;
10606 dispose_words (list
);
10608 /* If the string is not a quoted null string, we want
10609 to remove any embedded unquoted CTLNUL characters.
10610 We do not want to turn quoted null strings back into
10611 the empty string, though. We do this because we
10612 want to remove any quoted nulls from expansions that
10613 contain other characters. For example, if we have
10614 x"$*"y or "x$*y" and there are no positional parameters,
10615 the $* should expand into nothing. */
10616 /* We use the W_HASQUOTEDNULL flag to differentiate the
10617 cases: a quoted null character as above and when
10618 CTLNUL is contained in the (non-null) expansion
10619 of some variable. We use the had_quoted_null flag to
10620 pass the value through this function to its caller. */
10621 if ((tflag
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
) == 0)
10622 remove_quoted_nulls (temp
); /* XXX */
10626 temp
= (char *)NULL
;
10628 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
10629 had_quoted_null
= 1; /* note for later */
10631 /* We do not want to add quoted nulls to strings that are only
10632 partially quoted; we can throw them away. The exception to
10633 this is when we are going to be performing word splitting,
10634 since we have to preserve a null argument if the next character
10635 will cause word splitting. */
10636 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
10640 had_quoted_null
= 1;
10641 goto add_character
;
10643 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
10651 temp
= quote_string (temp
);
10657 /* Add NULL arg. */
10659 sindex
--; /* add_character: label increments sindex */
10660 had_quoted_null
= 1; /* note for later */
10661 goto add_character
;
10667 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
10668 goto add_character
;
10670 t_index
= ++sindex
;
10671 temp
= string_extract_single_quoted (string
, &sindex
);
10673 /* If the entire STRING was surrounded by single quotes,
10674 then the string is wholly quoted. */
10675 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
10677 : PARTIALLY_QUOTED
;
10679 /* If all we had was '', it is a null expansion. */
10683 temp
= (char *)NULL
;
10686 remove_quoted_escapes (temp
); /* ??? */
10688 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
10689 had_quoted_null
= 1; /* note for later */
10691 /* We do not want to add quoted nulls to strings that are only
10692 partially quoted; such nulls are discarded. See above for the
10693 exception, which is when the string is going to be split.
10694 Posix interp 888/1129 */
10695 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
10699 goto add_character
;
10702 if (temp
== 0 && (quoted_state
== PARTIALLY_QUOTED
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
10705 /* If we have a quoted null expansion, add a quoted NULL to istring. */
10709 sindex
--; /* add_character: label increments sindex */
10710 goto add_character
;
10713 goto add_quoted_string
;
10718 /* If we are in a context where the word is not going to be split, but
10719 we need to account for $@ and $* producing one word for each
10720 positional parameter, add quoted spaces so the spaces in the
10721 expansion of "$@", if any, behave correctly. We still may need to
10722 split if we are expanding the rhs of a word expansion. */
10723 if (ifs_is_null
|| split_on_spaces
|| ((word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
|W_ASSIGNRHS
)) && (word
->flags
& W_EXPANDRHS
) == 0))
10725 if (string
[sindex
])
10727 twochars
[0] = CTLESC
;
10734 /* This is the fix for " $@ " */
10736 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (isexp
== 0 && isifs (c
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0))
10738 if ((quoted
&(Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0)
10740 add_quoted_character
:
10741 if (string
[sindex
]) /* from old goto dollar_add_string */
10746 goto add_character
;
10750 #if HANDLE_MULTIBYTE
10751 /* XXX - should make sure that c is actually multibyte,
10752 otherwise we can use the twochars branch */
10753 if (mb_cur_max
> 1)
10756 if (mb_cur_max
> 1)
10758 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
10763 twochars
[0] = CTLESC
;
10770 SADD_MBCHAR (temp
, string
, sindex
, string_size
);
10773 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 1, istring_size
,
10774 DEFAULT_ARRAY_SIZE
);
10775 istring
[istring_index
++] = c
;
10776 istring
[istring_index
] = '\0';
10778 /* Next character. */
10783 finished_with_string
:
10784 /* OK, we're ready to return. If we have a quoted string, and
10785 quoted_dollar_at is not set, we do no splitting at all; otherwise
10786 we split on ' '. The routines that call this will handle what to
10787 do if nothing has been expanded. */
10789 /* Partially and wholly quoted strings which expand to the empty
10790 string are retained as an empty arguments. Unquoted strings
10791 which expand to the empty string are discarded. The single
10792 exception is the case of expanding "$@" when there are no
10793 positional parameters. In that case, we discard the expansion. */
10795 /* Because of how the code that handles "" and '' in partially
10796 quoted strings works, we need to make ISTRING into a QUOTED_NULL
10797 if we saw quoting characters, but the expansion was empty.
10798 "" and '' are tossed away before we get to this point when
10799 processing partially quoted strings. This makes "" and $xxx""
10800 equivalent when xxx is unset. We also look to see whether we
10801 saw a quoted null from a ${} expansion and add one back if we
10804 /* If we expand to nothing and there were no single or double quotes
10805 in the word, we throw it away. Otherwise, we return a NULL word.
10806 The single exception is for $@ surrounded by double quotes when
10807 there are no positional parameters. In that case, we also throw
10810 if (*istring
== '\0')
10812 if (quoted_dollar_at
== 0 && (had_quoted_null
|| quoted_state
== PARTIALLY_QUOTED
))
10814 istring
[0] = CTLNUL
;
10816 tword
= alloc_word_desc ();
10817 tword
->word
= istring
;
10818 istring
= 0; /* avoid later free() */
10819 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
10820 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
10821 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10822 tword
->flags
|= W_QUOTED
;
10824 /* According to sh, ksh, and Posix.2, if a word expands into nothing
10825 and a double-quoted "$@" appears anywhere in it, then the entire
10826 word is removed. */
10827 /* XXX - exception appears to be that quoted null strings result in
10829 else if (quoted_state
== UNQUOTED
|| quoted_dollar_at
)
10830 list
= (WORD_LIST
*)NULL
;
10832 list
= (WORD_LIST
*)NULL
;
10834 else if (word
->flags
& W_NOSPLIT
)
10836 tword
= alloc_word_desc ();
10837 tword
->word
= istring
;
10838 if (had_quoted_null
&& QUOTED_NULL (istring
))
10839 tword
->flags
|= W_HASQUOTEDNULL
;
10840 istring
= 0; /* avoid later free() */
10841 if (word
->flags
& W_ASSIGNMENT
)
10842 tword
->flags
|= W_ASSIGNMENT
; /* XXX */
10843 if (word
->flags
& W_COMPASSIGN
)
10844 tword
->flags
|= W_COMPASSIGN
; /* XXX */
10845 if (word
->flags
& W_NOGLOB
)
10846 tword
->flags
|= W_NOGLOB
; /* XXX */
10847 if (word
->flags
& W_NOBRACE
)
10848 tword
->flags
|= W_NOBRACE
; /* XXX */
10849 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10850 tword
->flags
|= W_QUOTED
;
10851 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
10853 else if (word
->flags
& W_ASSIGNRHS
)
10855 list
= list_string (istring
, "", quoted
);
10856 tword
= list
->word
;
10857 if (had_quoted_null
&& QUOTED_NULL (istring
))
10858 tword
->flags
|= W_HASQUOTEDNULL
;
10861 istring
= 0; /* avoid later free() */
10862 goto set_word_flags
;
10868 ifs_chars
= (quoted_dollar_at
|| has_dollar_at
) ? ifs_value
: (char *)NULL
;
10870 /* If we have $@, we need to split the results no matter what. If
10871 IFS is unset or NULL, string_list_dollar_at has separated the
10872 positional parameters with a space, so we split on space (we have
10873 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
10874 string_list_dollar_at has separated the positional parameters
10875 with the first character of $IFS, so we split on $IFS. If
10876 SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
10877 unset or null, and we want to make sure that we split on spaces
10878 regardless of what else has happened to IFS since the expansion,
10879 or we expanded "$@" with IFS null and we need to split the positional
10880 parameters into separate words. */
10881 if (split_on_spaces
)
10883 /* If IFS is not set, and the word is not quoted, we want to split
10884 the individual words on $' \t\n'. We rely on previous steps to
10885 quote the portions of the word that should not be split */
10886 if (ifs_is_set
== 0)
10887 list
= list_string (istring
, " \t\n", 1); /* XXX quoted == 1? */
10889 list
= list_string (istring
, " ", 1); /* XXX quoted == 1? */
10892 /* If we have $@ (has_dollar_at != 0) and we are in a context where we
10893 don't want to split the result (W_NOSPLIT2), and we are not quoted,
10894 we have already separated the arguments with the first character of
10895 $IFS. In this case, we want to return a list with a single word
10896 with the separator possibly replaced with a space (it's what other
10897 shells seem to do).
10898 quoted_dollar_at is internal to this function and is set if we are
10899 passed an argument that is unquoted (quoted == 0) but we encounter a
10900 double-quoted $@ while expanding it. */
10901 else if (has_dollar_at
&& quoted_dollar_at
== 0 && ifs_chars
&& quoted
== 0 && (word
->flags
& W_NOSPLIT2
))
10903 tword
= alloc_word_desc ();
10904 /* Only split and rejoin if we have to */
10905 if (*ifs_chars
&& *ifs_chars
!= ' ')
10907 /* list_string dequotes CTLESCs in the string it's passed, so we
10908 need it to get the space separation right if space isn't the
10909 first character in IFS (but is present) and to remove the
10910 quoting we added back in param_expand(). */
10911 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
10912 /* This isn't exactly right in the case where we're expanding
10913 the RHS of an expansion like ${var-$@} where IFS=: (for
10914 example). The W_NOSPLIT2 means we do the separation with :;
10915 the list_string removes the quotes and breaks the string into
10916 a list, and the string_list rejoins it on spaces. When we
10917 return, we expect to be able to split the results, but the
10918 space separation means the right split doesn't happen. */
10919 tword
->word
= string_list (list
);
10922 tword
->word
= istring
;
10923 if (had_quoted_null
&& QUOTED_NULL (istring
))
10924 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
10925 if (tword
->word
!= istring
)
10927 istring
= 0; /* avoid later free() */
10928 goto set_word_flags
;
10930 else if (has_dollar_at
&& ifs_chars
)
10931 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
10934 tword
= alloc_word_desc ();
10935 if (expanded_something
&& *expanded_something
== 0 && has_quoted_ifs
)
10936 tword
->word
= remove_quoted_ifs (istring
);
10938 tword
->word
= istring
;
10939 if (had_quoted_null
&& QUOTED_NULL (istring
)) /* should check for more than one */
10940 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
10941 else if (had_quoted_null
)
10942 tword
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
10943 if (tword
->word
!= istring
)
10945 istring
= 0; /* avoid later free() */
10947 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || (quoted_state
== WHOLLY_QUOTED
))
10948 tword
->flags
|= W_QUOTED
;
10949 if (word
->flags
& W_ASSIGNMENT
)
10950 tword
->flags
|= W_ASSIGNMENT
;
10951 if (word
->flags
& W_COMPASSIGN
)
10952 tword
->flags
|= W_COMPASSIGN
;
10953 if (word
->flags
& W_NOGLOB
)
10954 tword
->flags
|= W_NOGLOB
;
10955 if (word
->flags
& W_NOBRACE
)
10956 tword
->flags
|= W_NOBRACE
;
10957 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
10965 /* **************************************************************** */
10967 /* Functions for Quote Removal */
10969 /* **************************************************************** */
10971 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
10972 backslash quoting rules for within double quotes or a here document. */
10974 string_quote_removal (string
, quoted
)
10979 char *r
, *result_string
, *temp
, *send
;
10980 int sindex
, tindex
, dquote
;
10984 /* The result can be no longer than the original string. */
10985 slen
= strlen (string
);
10986 send
= string
+ slen
;
10988 r
= result_string
= (char *)xmalloc (slen
+ 1);
10990 for (dquote
= sindex
= 0; c
= string
[sindex
];)
10995 c
= string
[++sindex
];
11001 if (((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
) && (sh_syntaxtab
[c
] & CBSDQUOTE
) == 0)
11006 SCOPY_CHAR_M (r
, string
, send
, sindex
);
11010 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
)
11016 tindex
= sindex
+ 1;
11017 temp
= string_extract_single_quoted (string
, &tindex
);
11028 dquote
= 1 - dquote
;
11034 return (result_string
);
11039 /* Perform quote removal on word WORD. This allocates and returns a new
11042 word_quote_removal (word
, quoted
)
11049 t
= string_quote_removal (word
->word
, quoted
);
11050 w
= alloc_word_desc ();
11051 w
->word
= t
? t
: savestring ("");
11055 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
11056 the members of the list are treated as if they are surrounded by
11057 double quotes. Return a new list, or NULL if LIST is NULL. */
11059 word_list_quote_removal (list
, quoted
)
11063 WORD_LIST
*result
, *t
, *tresult
, *e
;
11065 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
11067 tresult
= make_word_list (word_quote_removal (t
->word
, quoted
), (WORD_LIST
*)NULL
);
11069 result
= (WORD_LIST
*) list_append (result
, tresult
);
11072 result
= e
= tresult
;
11085 /*******************************************
11087 * Functions to perform word splitting *
11089 *******************************************/
11099 ifs_value
= (v
&& value_cell (v
)) ? value_cell (v
) : " \t\n";
11101 ifs_is_set
= ifs_var
!= 0;
11102 ifs_is_null
= ifs_is_set
&& (*ifs_value
== 0);
11104 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
11105 handle multibyte chars in IFS */
11106 memset (ifs_cmap
, '\0', sizeof (ifs_cmap
));
11107 for (t
= ifs_value
; t
&& *t
; t
++)
11113 #if defined (HANDLE_MULTIBYTE)
11114 if (ifs_value
== 0)
11116 ifs_firstc
[0] = '\0'; /* XXX - ? */
11117 ifs_firstc_len
= 1;
11121 if (locale_utf8locale
&& UTF8_SINGLEBYTE (*ifs_value
))
11122 ifs_firstc_len
= (*ifs_value
!= 0) ? 1 : 0;
11126 ifs_len
= strnlen (ifs_value
, MB_CUR_MAX
);
11127 ifs_firstc_len
= MBLEN (ifs_value
, ifs_len
);
11129 if (ifs_firstc_len
== 1 || ifs_firstc_len
== 0 || MB_INVALIDCH (ifs_firstc_len
))
11131 ifs_firstc
[0] = ifs_value
[0];
11132 ifs_firstc
[1] = '\0';
11133 ifs_firstc_len
= 1;
11136 memcpy (ifs_firstc
, ifs_value
, ifs_firstc_len
);
11139 ifs_firstc
= ifs_value
? *ifs_value
: 0;
11149 /* This splits a single word into a WORD LIST on $IFS, but only if the word
11150 is not quoted. list_string () performs quote removal for us, even if we
11151 don't do any splitting. */
11153 word_split (w
, ifs_chars
)
11163 xifs
= ((w
->flags
& W_QUOTED
) || ifs_chars
== 0) ? "" : ifs_chars
;
11164 result
= list_string (w
->word
, xifs
, w
->flags
& W_QUOTED
);
11167 result
= (WORD_LIST
*)NULL
;
11172 /* Perform word splitting on LIST and return the RESULT. It is possible
11173 to return (WORD_LIST *)NULL. */
11175 word_list_split (list
)
11178 WORD_LIST
*result
, *t
, *tresult
, *e
;
11181 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
11183 tresult
= word_split (t
->word
, ifs_value
);
11184 /* POSIX 2.6: "If the complete expansion appropriate for a word results
11185 in an empty field, that empty field shall be deleted from the list
11186 of fields that form the completely expanded command, unless the
11187 original word contained single-quote or double-quote characters."
11188 This is where we handle these words that contain quoted null strings
11189 and other characters that expand to nothing after word splitting. */
11190 if (tresult
== 0 && t
->word
&& (t
->word
->flags
& W_SAWQUOTEDNULL
)) /* XXX */
11192 w
= alloc_word_desc ();
11193 w
->word
= (char *)xmalloc (1);
11195 tresult
= make_word_list (w
, (WORD_LIST
*)NULL
);
11198 result
= e
= tresult
;
11209 /**************************************************
11211 * Functions to expand an entire WORD_LIST *
11213 **************************************************/
11215 /* Do any word-expansion-specific cleanup and jump to top_level */
11217 exp_jump_to_top_level (v
)
11220 set_pipestatus_from_exit (last_command_exit_value
);
11222 /* Cleanup code goes here. */
11223 expand_no_split_dollar_star
= 0; /* XXX */
11224 if (expanding_redir
)
11225 undo_partial_redirects ();
11226 expanding_redir
= 0;
11227 assigning_in_environment
= 0;
11229 if (parse_and_execute_level
== 0)
11230 top_level_cleanup (); /* from sig.c */
11232 jump_to_top_level (v
);
11235 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
11236 ELIST, and set ELIST to the new list. */
11237 #define PREPEND_LIST(nlist, elist) \
11238 do { nlist->next = elist; elist = nlist; } while (0)
11240 /* Separate out any initial variable assignments from TLIST. If set -k has
11241 been executed, remove all assignment statements from TLIST. Initial
11242 variable assignments and other environment assignments are placed
11243 on SUBST_ASSIGN_VARLIST. */
11245 separate_out_assignments (tlist
)
11248 register WORD_LIST
*vp
, *lp
;
11251 return ((WORD_LIST
*)NULL
);
11253 if (subst_assign_varlist
)
11254 dispose_words (subst_assign_varlist
); /* Clean up after previous error */
11256 subst_assign_varlist
= (WORD_LIST
*)NULL
;
11259 /* Separate out variable assignments at the start of the command.
11260 Loop invariant: vp->next == lp
11261 Loop postcondition:
11262 lp = list of words left after assignment statements skipped
11263 tlist = original list of words
11265 while (lp
&& (lp
->word
->flags
& W_ASSIGNMENT
))
11271 /* If lp != tlist, we have some initial assignment statements.
11272 We make SUBST_ASSIGN_VARLIST point to the list of assignment
11273 words and TLIST point to the remaining words. */
11276 subst_assign_varlist
= tlist
;
11277 /* ASSERT(vp->next == lp); */
11278 vp
->next
= (WORD_LIST
*)NULL
; /* terminate variable list */
11279 tlist
= lp
; /* remainder of word list */
11282 /* vp == end of variable list */
11283 /* tlist == remainder of original word list without variable assignments */
11285 /* All the words in tlist were assignment statements */
11286 return ((WORD_LIST
*)NULL
);
11288 /* ASSERT(tlist != NULL); */
11289 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
11291 /* If the -k option is in effect, we need to go through the remaining
11292 words, separate out the assignment words, and place them on
11293 SUBST_ASSIGN_VARLIST. */
11294 if (place_keywords_in_env
)
11296 WORD_LIST
*tp
; /* tp == running pointer into tlist */
11301 /* Loop Invariant: tp->next == lp */
11302 /* Loop postcondition: tlist == word list without assignment statements */
11305 if (lp
->word
->flags
& W_ASSIGNMENT
)
11307 /* Found an assignment statement, add this word to end of
11308 subst_assign_varlist (vp). */
11309 if (!subst_assign_varlist
)
11310 subst_assign_varlist
= vp
= lp
;
11317 /* Remove the word pointed to by LP from TLIST. */
11318 tp
->next
= lp
->next
;
11319 /* ASSERT(vp == lp); */
11320 lp
->next
= (WORD_LIST
*)NULL
;
11333 #define WEXP_VARASSIGN 0x001
11334 #define WEXP_BRACEEXP 0x002
11335 #define WEXP_TILDEEXP 0x004
11336 #define WEXP_PARAMEXP 0x008
11337 #define WEXP_PATHEXP 0x010
11339 /* All of the expansions, including variable assignments at the start of
11341 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
11343 /* All of the expansions except variable assignments at the start of
11345 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
11347 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
11348 expansion, command substitution, arithmetic expansion, word splitting, and
11350 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
11352 /* Take the list of words in LIST and do the various substitutions. Return
11353 a new list of words which is the expanded list, and without things like
11354 variable assignments. */
11357 expand_words (list
)
11360 return (expand_word_list_internal (list
, WEXP_ALL
));
11363 /* Same as expand_words (), but doesn't hack variable or environment
11366 expand_words_no_vars (list
)
11369 return (expand_word_list_internal (list
, WEXP_NOVARS
));
11373 expand_words_shellexp (list
)
11376 return (expand_word_list_internal (list
, WEXP_SHELLEXP
));
11380 glob_expand_word_list (tlist
, eflags
)
11384 char **glob_array
, *temp_string
;
11385 register int glob_index
;
11386 WORD_LIST
*glob_list
, *output_list
, *disposables
, *next
;
11390 output_list
= disposables
= (WORD_LIST
*)NULL
;
11391 glob_array
= (char **)NULL
;
11394 /* For each word, either globbing is attempted or the word is
11395 added to orig_list. If globbing succeeds, the results are
11396 added to orig_list and the word (tlist) is added to the list
11397 of disposable words. If globbing fails and failed glob
11398 expansions are left unchanged (the shell default), the
11399 original word is added to orig_list. If globbing fails and
11400 failed glob expansions are removed, the original word is
11401 added to the list of disposable words. orig_list ends up
11402 in reverse order and requires a call to REVERSE_LIST to
11403 be set right. After all words are examined, the disposable
11404 words are freed. */
11405 next
= tlist
->next
;
11407 /* If the word isn't an assignment and contains an unquoted
11408 pattern matching character, then glob it. */
11409 if ((tlist
->word
->flags
& W_NOGLOB
) == 0 &&
11410 unquoted_glob_pattern_p (tlist
->word
->word
))
11412 glob_array
= shell_glob_filename (tlist
->word
->word
, QGLOB_CTLESC
); /* XXX */
11414 /* Handle error cases.
11415 I don't think we should report errors like "No such file
11416 or directory". However, I would like to report errors
11417 like "Read failed". */
11419 if (glob_array
== 0 || GLOB_FAILED (glob_array
))
11421 glob_array
= (char **)xmalloc (sizeof (char *));
11422 glob_array
[0] = (char *)NULL
;
11425 /* Dequote the current word in case we have to use it. */
11426 if (glob_array
[0] == NULL
)
11428 temp_string
= dequote_string (tlist
->word
->word
);
11429 free (tlist
->word
->word
);
11430 tlist
->word
->word
= temp_string
;
11433 /* Make the array into a word list. */
11434 glob_list
= (WORD_LIST
*)NULL
;
11435 for (glob_index
= 0; glob_array
[glob_index
]; glob_index
++)
11437 tword
= make_bare_word (glob_array
[glob_index
]);
11438 glob_list
= make_word_list (tword
, glob_list
);
11443 output_list
= (WORD_LIST
*)list_append (glob_list
, output_list
);
11444 PREPEND_LIST (tlist
, disposables
);
11446 else if (fail_glob_expansion
!= 0)
11448 last_command_exit_value
= EXECUTION_FAILURE
;
11449 report_error (_("no match: %s"), tlist
->word
->word
);
11450 exp_jump_to_top_level (DISCARD
);
11452 else if (allow_null_glob_expansion
== 0)
11454 /* Failed glob expressions are left unchanged. */
11455 PREPEND_LIST (tlist
, output_list
);
11459 /* Failed glob expressions are removed. */
11460 PREPEND_LIST (tlist
, disposables
);
11465 /* Dequote the string. */
11466 temp_string
= dequote_string (tlist
->word
->word
);
11467 free (tlist
->word
->word
);
11468 tlist
->word
->word
= temp_string
;
11469 PREPEND_LIST (tlist
, output_list
);
11472 strvec_dispose (glob_array
);
11473 glob_array
= (char **)NULL
;
11479 dispose_words (disposables
);
11482 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
11484 return (output_list
);
11487 #if defined (BRACE_EXPANSION)
11489 brace_expand_word_list (tlist
, eflags
)
11493 register char **expansions
;
11495 WORD_LIST
*disposables
, *output_list
, *next
;
11499 for (disposables
= output_list
= (WORD_LIST
*)NULL
; tlist
; tlist
= next
)
11501 next
= tlist
->next
;
11503 if (tlist
->word
->flags
& W_NOBRACE
)
11505 /*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
11506 PREPEND_LIST (tlist
, output_list
);
11510 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
11512 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
11513 PREPEND_LIST (tlist
, output_list
);
11517 /* Only do brace expansion if the word has a brace character. If
11518 not, just add the word list element to BRACES and continue. In
11519 the common case, at least when running shell scripts, this will
11520 degenerate to a bunch of calls to `mbschr', and then what is
11521 basically a reversal of TLIST into BRACES, which is corrected
11522 by a call to REVERSE_LIST () on BRACES when the end of TLIST
11524 if (mbschr (tlist
->word
->word
, LBRACE
))
11526 expansions
= brace_expand (tlist
->word
->word
);
11528 for (eindex
= 0; temp_string
= expansions
[eindex
]; eindex
++)
11530 w
= alloc_word_desc ();
11531 w
->word
= temp_string
;
11533 /* If brace expansion didn't change the word, preserve
11534 the flags. We may want to preserve the flags
11535 unconditionally someday -- XXX */
11536 if (STREQ (temp_string
, tlist
->word
->word
))
11537 w
->flags
= tlist
->word
->flags
;
11539 w
= make_word_flags (w
, temp_string
);
11541 output_list
= make_word_list (w
, output_list
);
11545 /* Add TLIST to the list of words to be freed after brace
11546 expansion has been performed. */
11547 PREPEND_LIST (tlist
, disposables
);
11550 PREPEND_LIST (tlist
, output_list
);
11554 dispose_words (disposables
);
11557 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
11559 return (output_list
);
11563 #if defined (ARRAY_VARS)
11564 /* Take WORD, a compound array assignment, and internally run (for example),
11565 'declare -A w', where W is the variable name portion of WORD. OPTION is
11566 the list of options to supply to `declare'. CMD is the declaration command
11567 we are expanding right now; it's unused currently. */
11569 make_internal_declare (word
, option
, cmd
)
11578 w
= make_word (word
);
11580 t
= assignment (w
->word
, 0);
11581 if (w
->word
[t
] == '=')
11584 if (w
->word
[t
- 1] == '+') /* cut off any append op */
11585 w
->word
[t
- 1] = '\0';
11588 wl
= make_word_list (w
, (WORD_LIST
*)NULL
);
11589 wl
= make_word_list (make_word (option
), wl
);
11591 r
= declare_builtin (wl
);
11593 dispose_words (wl
);
11597 /* Expand VALUE in NAME[+]=( VALUE ) to a list of words. FLAGS is 1 if NAME
11598 is an associative array.
11600 If we are processing an indexed array, expand_compound_array_assignment
11601 will expand all the individual words and quote_compound_array_list will
11602 single-quote them. If we are processing an associative array, we use
11603 parse_string_to_word_list to split VALUE into a list of words instead of
11604 faking up a shell variable and calling expand_compound_array_assignment.
11605 expand_and_quote_assoc_word expands and single-quotes each word in VALUE
11606 together so we don't have problems finding the end of the subscript when
11609 Words in VALUE can be individual words, which are expanded and single-quoted,
11610 or words of the form [IND]=VALUE, which end up as explained below, as
11611 ['expanded-ind']='expanded-value'. */
11614 expand_oneword (value
, flags
)
11623 /* Indexed array */
11624 l
= expand_compound_array_assignment ((SHELL_VAR
*)NULL
, value
, flags
);
11625 /* Now we quote the results of the expansion above to prevent double
11627 quote_compound_array_list (l
, flags
);
11632 /* Associative array */
11633 l
= parse_string_to_word_list (value
, 1, "array assign");
11634 /* For associative arrays, with their arbitrary subscripts, we have to
11635 expand and quote in one step so we don't have to search for the
11636 closing right bracket more than once. */
11637 for (nl
= l
; nl
; nl
= nl
->next
)
11639 if ((nl
->word
->flags
& W_ASSIGNMENT
) == 0)
11640 t
= sh_single_quote (nl
->word
->word
? nl
->word
->word
: "");
11642 t
= expand_and_quote_assoc_word (nl
->word
->word
, flags
);
11643 free (nl
->word
->word
);
11644 nl
->word
->word
= t
;
11650 /* Expand a single compound assignment argument to a declaration builtin.
11651 This word takes the form NAME[+]=( VALUE ). The NAME[+]= is passed through
11652 unchanged. The VALUE is expanded and each word in the result is single-
11653 quoted. Words of the form [key]=value end up as
11654 ['expanded-key']='expanded-value'. Associative arrays have special
11655 handling, see expand_oneword() above. The return value is
11656 NAME[+]=( expanded-and-quoted-VALUE ). */
11658 expand_compound_assignment_word (tlist
, flags
)
11664 char *value
, *temp
;
11666 /*itrace("expand_compound_assignment_word: original word = -%s-", tlist->word->word);*/
11667 t
= assignment (tlist
->word
->word
, 0);
11669 /* value doesn't have the open and close parens */
11671 value
= extract_array_assignment_list (tlist
->word
->word
+ t
+ 1, &oind
);
11672 /* This performs one round of expansion on the index/key and value and
11673 single-quotes each word in the result. */
11674 l
= expand_oneword (value
, flags
);
11677 value
= string_list (l
);
11678 wlen
= STRLEN (value
);
11680 /* Now, let's rebuild the string */
11681 temp
= xmalloc (t
+ 3 + wlen
+ 1); /* name[+]=(value) */
11682 memcpy (temp
, tlist
->word
->word
, ++t
);
11685 memcpy (temp
+ t
, value
, wlen
);
11689 /*itrace("expand_compound_assignment_word: reconstructed word = -%s-", temp);*/
11691 free (tlist
->word
->word
);
11692 tlist
->word
->word
= temp
;
11697 /* Expand and process an argument to a declaration command. We have already
11698 set flags in TLIST->word->flags depending on the declaration command
11699 (declare, local, etc.) and the options supplied to it (-a, -A, etc.).
11700 TLIST->word->word is of the form NAME[+]=( VALUE ).
11702 This does several things, all using pieces of other functions to get the
11703 evaluation sequence right. It's called for compound array assignments with
11704 the W_ASSIGNMENT flag set (basically, valid identifier names on the lhs).
11705 It parses out which flags need to be set for declare to create the variable
11706 correctly, then calls declare internally (make_internal_declare) to make
11707 sure the variable exists with the correct attributes. Before the variable
11708 is created, it calls expand_compound_assignment_word to expand VALUE to a
11709 list of words, appropriately quoted for further evaluation. This preserves
11710 the semantics of word-expansion-before-calling-builtins. Finally, it calls
11711 do_word_assignment to perform the expansion and assignment with the same
11712 expansion semantics as a standalone assignment statement (no word splitting,
11713 etc.) even though the word is single-quoted so all that needs to happen is
11716 expand_declaration_argument (tlist
, wcmd
)
11717 WORD_LIST
*tlist
, *wcmd
;
11719 char opts
[16], omap
[128];
11720 int t
, opti
, oind
, skip
, inheriting
;
11723 inheriting
= localvar_inherit
;
11725 if (tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
|W_CHKLOCAL
|W_ASSIGNARRAY
))
11726 opts
[opti
++] = '-';
11728 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
)) == (W_ASSIGNASSOC
|W_ASSNGLOBAL
))
11730 opts
[opti
++] = 'g';
11731 opts
[opti
++] = 'A';
11733 else if (tlist
->word
->flags
& W_ASSIGNASSOC
)
11735 opts
[opti
++] = 'A';
11737 else if ((tlist
->word
->flags
& (W_ASSIGNARRAY
|W_ASSNGLOBAL
)) == (W_ASSIGNARRAY
|W_ASSNGLOBAL
))
11739 opts
[opti
++] = 'g';
11740 opts
[opti
++] = 'a';
11742 else if (tlist
->word
->flags
& W_ASSIGNARRAY
)
11744 opts
[opti
++] = 'a';
11746 else if (tlist
->word
->flags
& W_ASSNGLOBAL
)
11747 opts
[opti
++] = 'g';
11749 if (tlist
->word
->flags
& W_CHKLOCAL
)
11750 opts
[opti
++] = 'G';
11752 /* If we have special handling note the integer attribute and others
11753 that transform the value upon assignment. What we do is take all
11754 of the option arguments and scan through them looking for options
11755 that cause such transformations, and add them to the `opts' array. */
11757 memset (omap
, '\0', sizeof (omap
));
11758 for (l
= wcmd
->next
; l
!= tlist
; l
= l
->next
)
11760 if (l
->word
->word
[0] != '-')
11761 break; /* non-option argument */
11762 if (l
->word
->word
[0] == '-' && l
->word
->word
[1] == '-' && l
->word
->word
[2] == 0)
11763 break; /* -- signals end of options */
11764 for (oind
= 1; l
->word
->word
[oind
]; oind
++)
11765 switch (l
->word
->word
[oind
])
11773 omap
[l
->word
->word
[oind
]] = 1;
11775 opts
[opti
++] = '-';
11782 for (oind
= 0; oind
< sizeof (omap
); oind
++)
11784 opts
[opti
++] = oind
;
11786 /* If there are no -a/-A options, but we have a compound assignment,
11787 we have a choice: we can set opts[0]='-', opts[1]='a', since the
11788 default is to create an indexed array, and call
11789 make_internal_declare with that, or we can just skip the -a and let
11790 declare_builtin deal with it. Once we're here, we're better set
11791 up for the latter, since we don't want to deal with looking up
11792 any existing variable here -- better to let declare_builtin do it.
11793 We need the variable created, though, especially if it's local, so
11794 we get the scoping right before we call do_word_assignment.
11795 To ensure that make_local_declare gets called, we add `--' if there
11796 aren't any options. */
11797 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSIGNARRAY
)) == 0)
11801 opts
[opti
++] = '-';
11802 opts
[opti
++] = '-';
11807 /* This isn't perfect, but it's a start. Improvements later. We expand
11808 tlist->word->word and single-quote the results to avoid multiple
11809 expansions by, say, do_assignment_internal(). We have to weigh the
11810 cost of reconstructing the compound assignment string with its single
11811 quoting and letting the declare builtin handle it. The single quotes
11812 will prevent any unwanted additional expansion or word splitting. */
11813 expand_compound_assignment_word (tlist
, (tlist
->word
->flags
& W_ASSIGNASSOC
) ? 1 : 0);
11818 t
= make_internal_declare (tlist
->word
->word
, opts
, wcmd
? wcmd
->word
->word
: (char *)0);
11819 if (t
!= EXECUTION_SUCCESS
)
11821 last_command_exit_value
= t
;
11822 if (tlist
->word
->flags
& W_FORCELOCAL
) /* non-fatal error */
11825 exp_jump_to_top_level (DISCARD
);
11831 t
= do_word_assignment (tlist
->word
, 0);
11834 last_command_exit_value
= EXECUTION_FAILURE
;
11835 exp_jump_to_top_level (DISCARD
);
11839 /* Now transform the word as ksh93 appears to do and go on */
11840 t
= assignment (tlist
->word
->word
, 0);
11841 tlist
->word
->word
[t
] = '\0';
11842 if (tlist
->word
->word
[t
- 1] == '+')
11843 tlist
->word
->word
[t
- 1] = '\0'; /* cut off append op */
11844 tlist
->word
->flags
&= ~(W_ASSIGNMENT
|W_NOSPLIT
|W_COMPASSIGN
|W_ASSIGNARG
|W_ASSIGNASSOC
|W_ASSIGNARRAY
);
11848 #endif /* ARRAY_VARS */
11851 shell_expand_word_list (tlist
, eflags
)
11855 WORD_LIST
*expanded
, *orig_list
, *new_list
, *next
, *temp_list
, *wcmd
;
11856 int expanded_something
, has_dollar_at
;
11858 /* We do tilde expansion all the time. This is what 1003.2 says. */
11859 wcmd
= new_list
= (WORD_LIST
*)NULL
;
11861 for (orig_list
= tlist
; tlist
; tlist
= next
)
11863 if (wcmd
== 0 && (tlist
->word
->flags
& W_ASSNBLTIN
))
11866 next
= tlist
->next
;
11868 #if defined (ARRAY_VARS)
11869 /* If this is a compound array assignment to a builtin that accepts
11870 such assignments (e.g., `declare'), take the assignment and perform
11871 it separately, handling the semantics of declarations inside shell
11872 functions. This avoids the double-evaluation of such arguments,
11873 because `declare' does some evaluation of compound assignments on
11875 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
11876 expand_declaration_argument (tlist
, wcmd
);
11879 expanded_something
= 0;
11880 expanded
= expand_word_internal
11881 (tlist
->word
, 0, 0, &has_dollar_at
, &expanded_something
);
11883 if (expanded
== &expand_word_error
|| expanded
== &expand_word_fatal
)
11885 /* By convention, each time this error is returned,
11886 tlist->word->word has already been freed. */
11887 tlist
->word
->word
= (char *)NULL
;
11889 /* Dispose our copy of the original list. */
11890 dispose_words (orig_list
);
11891 /* Dispose the new list we're building. */
11892 dispose_words (new_list
);
11894 last_command_exit_value
= EXECUTION_FAILURE
;
11895 if (expanded
== &expand_word_error
)
11896 exp_jump_to_top_level (DISCARD
);
11898 exp_jump_to_top_level (FORCE_EOF
);
11901 /* Don't split words marked W_NOSPLIT. */
11902 if (expanded_something
&& (tlist
->word
->flags
& W_NOSPLIT
) == 0)
11904 temp_list
= word_list_split (expanded
);
11905 dispose_words (expanded
);
11909 /* If no parameter expansion, command substitution, process
11910 substitution, or arithmetic substitution took place, then
11911 do not do word splitting. We still have to remove quoted
11912 null characters from the result. */
11913 word_list_remove_quoted_nulls (expanded
);
11914 temp_list
= expanded
;
11917 expanded
= REVERSE_LIST (temp_list
, WORD_LIST
*);
11918 new_list
= (WORD_LIST
*)list_append (expanded
, new_list
);
11922 dispose_words (orig_list
);
11925 new_list
= REVERSE_LIST (new_list
, WORD_LIST
*);
11930 /* The workhorse for expand_words () and expand_words_no_vars ().
11931 First arg is LIST, a WORD_LIST of words.
11932 Second arg EFLAGS is a flags word controlling which expansions are
11935 This does all of the substitutions: brace expansion, tilde expansion,
11936 parameter expansion, command substitution, arithmetic expansion,
11937 process substitution, word splitting, and pathname expansion, according
11938 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
11939 set, or for which no expansion is done, do not undergo word splitting.
11940 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
11941 with W_NOBRACE set do not undergo brace expansion (see
11942 brace_expand_word_list above). */
11944 expand_word_list_internal (list
, eflags
)
11948 WORD_LIST
*new_list
, *temp_list
;
11952 tempenv_assign_error
= 0;
11954 return ((WORD_LIST
*)NULL
);
11956 garglist
= new_list
= copy_word_list (list
);
11957 if (eflags
& WEXP_VARASSIGN
)
11959 garglist
= new_list
= separate_out_assignments (new_list
);
11962 if (subst_assign_varlist
)
11964 /* All the words were variable assignments, so they are placed
11965 into the shell's environment. */
11966 for (temp_list
= subst_assign_varlist
; temp_list
; temp_list
= temp_list
->next
)
11968 savecmd
= this_command_name
;
11969 this_command_name
= (char *)NULL
; /* no arithmetic errors */
11970 tint
= do_word_assignment (temp_list
->word
, 0);
11971 this_command_name
= savecmd
;
11972 /* Variable assignment errors in non-interactive shells
11973 running in Posix.2 mode cause the shell to exit, unless
11974 they are being run by the `command' builtin. */
11977 last_command_exit_value
= EXECUTION_FAILURE
;
11978 if (interactive_shell
== 0 && posixly_correct
&& executing_command_builtin
== 0)
11979 exp_jump_to_top_level (FORCE_EOF
);
11981 exp_jump_to_top_level (DISCARD
);
11984 dispose_words (subst_assign_varlist
);
11985 subst_assign_varlist
= (WORD_LIST
*)NULL
;
11987 return ((WORD_LIST
*)NULL
);
11991 /* Begin expanding the words that remain. The expansions take place on
11992 things that aren't really variable assignments. */
11994 #if defined (BRACE_EXPANSION)
11995 /* Do brace expansion on this word if there are any brace characters
11997 if ((eflags
& WEXP_BRACEEXP
) && brace_expansion
&& new_list
)
11998 new_list
= brace_expand_word_list (new_list
, eflags
);
11999 #endif /* BRACE_EXPANSION */
12001 /* Perform the `normal' shell expansions: tilde expansion, parameter and
12002 variable substitution, command substitution, arithmetic expansion,
12003 and word splitting. */
12004 new_list
= shell_expand_word_list (new_list
, eflags
);
12006 /* Okay, we're almost done. Now let's just do some filename
12010 if ((eflags
& WEXP_PATHEXP
) && disallow_filename_globbing
== 0)
12011 /* Glob expand the word list unless globbing has been disabled. */
12012 new_list
= glob_expand_word_list (new_list
, eflags
);
12014 /* Dequote the words, because we're not performing globbing. */
12015 new_list
= dequote_list (new_list
);
12018 if ((eflags
& WEXP_VARASSIGN
) && subst_assign_varlist
)
12020 sh_wassign_func_t
*assign_func
;
12021 int is_special_builtin
, is_builtin_or_func
;
12023 /* If the remainder of the words expand to nothing, Posix.2 requires
12024 that the variable and environment assignments affect the shell's
12026 assign_func
= new_list
? assign_in_env
: do_word_assignment
;
12027 tempenv_assign_error
= 0;
12029 is_builtin_or_func
= (new_list
&& new_list
->word
&& (find_shell_builtin (new_list
->word
->word
) || find_function (new_list
->word
->word
)));
12030 /* Posix says that special builtins exit if a variable assignment error
12031 occurs in an assignment preceding it. */
12032 is_special_builtin
= (posixly_correct
&& new_list
&& new_list
->word
&& find_special_builtin (new_list
->word
->word
));
12034 for (temp_list
= subst_assign_varlist
; temp_list
; temp_list
= temp_list
->next
)
12036 savecmd
= this_command_name
;
12037 this_command_name
= (char *)NULL
;
12038 assigning_in_environment
= (assign_func
== assign_in_env
);
12039 tint
= (*assign_func
) (temp_list
->word
, is_builtin_or_func
);
12040 assigning_in_environment
= 0;
12041 this_command_name
= savecmd
;
12042 /* Variable assignment errors in non-interactive shells running
12043 in Posix.2 mode cause the shell to exit. */
12046 if (assign_func
== do_word_assignment
)
12048 last_command_exit_value
= EXECUTION_FAILURE
;
12049 if (interactive_shell
== 0 && posixly_correct
)
12050 exp_jump_to_top_level (FORCE_EOF
);
12052 exp_jump_to_top_level (DISCARD
);
12054 else if (interactive_shell
== 0 && is_special_builtin
)
12056 last_command_exit_value
= EXECUTION_FAILURE
;
12057 exp_jump_to_top_level (FORCE_EOF
);
12060 tempenv_assign_error
++;
12064 dispose_words (subst_assign_varlist
);
12065 subst_assign_varlist
= (WORD_LIST
*)NULL
;