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-2022 Free Software Foundation, Inc.
9 This file is part of GNU Bash, the Bourne Again SHell.
11 Bash is free software: you can redistribute it and/or modify
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 Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
27 #include "bashtypes.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"
51 #include "execute_cmd.h"
55 #include "mailcheck.h"
58 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
59 # include <mbstr.h> /* mbschr */
63 #include "builtins/getopt.h"
64 #include "builtins/common.h"
66 #include "builtins/builtext.h"
68 #include <tilde/tilde.h>
69 #include <glob/strmatch.h>
75 /* The size that strings change by. */
76 #define DEFAULT_INITIAL_ARRAY_SIZE 112
77 #define DEFAULT_ARRAY_SIZE 128
83 #define VT_ARRAYMEMBER 3
86 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
88 /* Flags for quoted_strchr */
89 #define ST_BACKSL 0x01
90 #define ST_CTLESC 0x02
91 #define ST_SQUOTE 0x04 /* unused yet */
92 #define ST_DQUOTE 0x08 /* unused yet */
94 /* These defs make it easier to use the editor. */
102 #if defined (HANDLE_MULTIBYTE)
107 #define DOLLAR_AT_STAR(c) ((c) == '@' || (c) == '*')
108 #define STR_DOLLAR_AT_STAR(s) (DOLLAR_AT_STAR ((s)[0]) && (s)[1] == '\0')
110 /* Evaluates to 1 if C is one of the shell's special parameters whose length
111 can be taken, but is also one of the special expansion characters. */
112 #define VALID_SPECIAL_LENGTH_PARAM(c) \
113 ((c) == '-' || (c) == '?' || (c) == '#' || (c) == '@')
115 /* Evaluates to 1 if C is one of the shell's special parameters for which an
116 indirect variable reference may be made. */
117 #define VALID_INDIR_PARAM(c) \
118 ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
120 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
121 in ${parameter[:]OPword}. */
122 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
124 /* Evaluates to 1 if this is one of the shell's special variables. */
125 #define SPECIAL_VAR(name, wi) \
126 (*name && ((DIGIT (*name) && all_digits (name)) || \
127 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
128 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1]))))
130 /* This can be used by all of the *_extract_* functions that have a similar
131 structure. It can't just be wrapped in a do...while(0) loop because of
132 the embedded `break'. The dangling else accommodates a trailing semicolon;
133 we could also put in a do ; while (0) */
135 #define CHECK_STRING_OVERRUN(oind, ind, len, ch) \
144 /* An expansion function that takes a string and a quoted flag and returns
145 a WORD_LIST *. Used as the type of the third argument to
146 expand_string_if_necessary(). */
147 typedef WORD_LIST
*EXPFUNC
PARAMS((char *, int));
149 /* Process ID of the last command executed within command substitution. */
150 pid_t last_command_subst_pid
= NO_PID
;
151 pid_t current_command_subst_pid
= NO_PID
;
153 /* Variables used to keep track of the characters in IFS. */
156 unsigned char ifs_cmap
[UCHAR_MAX
+ 1];
157 int ifs_is_set
, ifs_is_null
;
159 #if defined (HANDLE_MULTIBYTE)
160 unsigned char ifs_firstc
[MB_LEN_MAX
];
161 size_t ifs_firstc_len
;
163 unsigned char ifs_firstc
;
166 /* If non-zero, command substitution inherits the value of errexit option */
167 int inherit_errexit
= 0;
169 /* Sentinel to tell when we are performing variable assignments preceding a
170 command name and putting them into the environment. Used to make sure
171 we use the temporary environment when looking up variable values. */
172 int assigning_in_environment
;
174 /* Used to hold a list of variable assignments preceding a command. Global
175 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
176 SIGCHLD trap and so it can be saved and restored by the trap handlers. */
177 WORD_LIST
*subst_assign_varlist
= (WORD_LIST
*)NULL
;
179 /* Tell the expansion functions to not longjmp back to top_level on fatal
180 errors. Enabled when doing completion and prompt string expansion. */
181 int no_longjmp_on_fatal_error
= 0;
183 /* Non-zero means to allow unmatched globbed filenames to expand to
185 int allow_null_glob_expansion
;
187 /* Non-zero means to throw an error when globbing fails to match anything. */
188 int fail_glob_expansion
;
190 /* If non-zero, perform `&' substitution on the replacement string in the
191 pattern substitution word expansion. */
192 int patsub_replacement
= 1;
194 /* Extern functions and variables from different files. */
195 extern struct fd_bitmap
*current_fds_to_close
;
196 extern int wordexp_only
;
197 extern int singlequote_translations
;
198 extern int extended_quote
;
200 #if defined (JOB_CONTROL) && defined (PROCESS_SUBSTITUTION)
201 extern PROCESS
*last_procsub_child
;
204 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
205 extern wchar_t *wcsdup
PARAMS((const wchar_t *));
209 /* Variables to keep track of which words in an expanded word list (the
210 output of expand_word_list_internal) are the result of globbing
211 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
212 (CURRENTLY UNUSED). */
213 char *glob_argv_flags
;
214 static int glob_argv_flags_size
;
217 static WORD_LIST
*cached_quoted_dollar_at
= 0;
219 /* Distinguished error values to return from expansion functions */
220 static WORD_LIST expand_word_error
, expand_word_fatal
;
221 static WORD_DESC expand_wdesc_error
, expand_wdesc_fatal
;
222 static char expand_param_error
, expand_param_fatal
, expand_param_unset
;
223 static char extract_string_error
, extract_string_fatal
;
225 /* Set by expand_word_unsplit and several of the expand_string_XXX functions;
226 used to inhibit splitting and re-joining $* on $IFS, primarily when doing
227 assignment statements. The idea is that if we're in a context where this
228 is set, we're not going to be performing word splitting, so we use the same
229 rules to expand $* as we would if it appeared within double quotes. */
230 static int expand_no_split_dollar_star
= 0;
232 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
233 without any leading variable assignments. */
234 static WORD_LIST
*garglist
= (WORD_LIST
*)NULL
;
236 static char *quoted_substring
PARAMS((char *, int, int));
237 static int quoted_strlen
PARAMS((char *));
238 static char *quoted_strchr
PARAMS((char *, int, int));
240 static char *expand_string_if_necessary
PARAMS((char *, int, EXPFUNC
*));
241 static inline char *expand_string_to_string_internal
PARAMS((char *, int, EXPFUNC
*));
242 static WORD_LIST
*call_expand_word_internal
PARAMS((WORD_DESC
*, int, int, int *, int *));
243 static WORD_LIST
*expand_string_internal
PARAMS((char *, int));
244 static WORD_LIST
*expand_string_leave_quoted
PARAMS((char *, int));
245 static WORD_LIST
*expand_string_for_rhs
PARAMS((char *, int, int, int, int *, int *));
246 static WORD_LIST
*expand_string_for_pat
PARAMS((char *, int, int *, int *));
248 static char *quote_escapes_internal
PARAMS((const char *, int));
250 static WORD_LIST
*list_quote_escapes
PARAMS((WORD_LIST
*));
251 static WORD_LIST
*list_dequote_escapes
PARAMS((WORD_LIST
*));
253 static char *make_quoted_char
PARAMS((int));
254 static WORD_LIST
*quote_list
PARAMS((WORD_LIST
*));
256 static int unquoted_substring
PARAMS((char *, char *));
257 static int unquoted_member
PARAMS((int, char *));
259 #if defined (ARRAY_VARS)
260 static SHELL_VAR
*do_compound_assignment
PARAMS((char *, char *, int));
262 static int do_assignment_internal
PARAMS((const WORD_DESC
*, int));
264 static char *string_extract_verbatim
PARAMS((char *, size_t, int *, char *, int));
265 static char *string_extract
PARAMS((char *, int *, char *, int));
266 static char *string_extract_double_quoted
PARAMS((char *, int *, int));
267 static inline char *string_extract_single_quoted
PARAMS((char *, int *, int));
268 static inline int skip_single_quoted
PARAMS((const char *, size_t, int, int));
269 static int skip_double_quoted
PARAMS((char *, size_t, int, int));
270 static char *extract_delimited_string
PARAMS((char *, int *, char *, char *, char *, int));
271 static char *extract_heredoc_dolbrace_string
PARAMS((char *, int *, int, int));
272 static char *extract_dollar_brace_string
PARAMS((char *, int *, int, int));
273 static int skip_matched_pair
PARAMS((const char *, int, int, int, int));
275 static char *pos_params
PARAMS((char *, int, int, int, int));
277 static unsigned char *mb_getcharlens
PARAMS((char *, int));
279 static char *remove_upattern
PARAMS((char *, char *, int));
280 #if defined (HANDLE_MULTIBYTE)
281 static wchar_t *remove_wpattern
PARAMS((wchar_t *, size_t, wchar_t *, int));
283 static char *remove_pattern
PARAMS((char *, char *, int));
285 static int match_upattern
PARAMS((char *, char *, int, char **, char **));
286 #if defined (HANDLE_MULTIBYTE)
287 static int match_wpattern
PARAMS((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
289 static int match_pattern
PARAMS((char *, char *, int, char **, char **));
290 static int getpatspec
PARAMS((int, char *));
291 static char *getpattern
PARAMS((char *, int, int));
292 static char *variable_remove_pattern
PARAMS((char *, char *, int, int));
293 static char *list_remove_pattern
PARAMS((WORD_LIST
*, char *, int, int, int));
294 static char *parameter_list_remove_pattern
PARAMS((int, char *, int, int));
296 static char *array_remove_pattern
PARAMS((SHELL_VAR
*, char *, int, int, int));
298 static char *parameter_brace_remove_pattern
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int));
300 static char *string_var_assignment
PARAMS((SHELL_VAR
*, char *));
301 #if defined (ARRAY_VARS)
302 static char *array_var_assignment
PARAMS((SHELL_VAR
*, int, int, int));
304 static char *pos_params_assignment
PARAMS((WORD_LIST
*, int, int));
305 static char *string_transform
PARAMS((int, SHELL_VAR
*, char *));
306 static char *list_transform
PARAMS((int, SHELL_VAR
*, WORD_LIST
*, int, int));
307 static char *parameter_list_transform
PARAMS((int, int, int));
308 #if defined ARRAY_VARS
309 static char *array_transform
PARAMS((int, SHELL_VAR
*, int, int));
311 static char *parameter_brace_transform
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int, int));
312 static int valid_parameter_transform
PARAMS((char *));
314 static char *process_substitute
PARAMS((char *, int));
316 static char *optimize_cat_file
PARAMS((REDIRECT
*, int, int, int *));
317 static char *read_comsub
PARAMS((int, int, int, int *));
320 static arrayind_t array_length_reference
PARAMS((char *));
323 static int valid_brace_expansion_word
PARAMS((char *, int));
324 static int chk_atstar
PARAMS((char *, int, int, int *, int *));
325 static int chk_arithsub
PARAMS((const char *, int));
327 static WORD_DESC
*parameter_brace_expand_word
PARAMS((char *, int, int, int, array_eltstate_t
*));
328 static char *parameter_brace_find_indir
PARAMS((char *, int, int, int));
329 static WORD_DESC
*parameter_brace_expand_indir
PARAMS((char *, int, int, int, int *, int *));
330 static WORD_DESC
*parameter_brace_expand_rhs
PARAMS((char *, char *, int, int, int, int *, int *));
331 static void parameter_brace_expand_error
PARAMS((char *, char *, int));
333 static int valid_length_expression
PARAMS((char *));
334 static intmax_t parameter_brace_expand_length
PARAMS((char *));
336 static char *skiparith
PARAMS((char *, int));
337 static int verify_substring_values
PARAMS((SHELL_VAR
*, char *, char *, int, intmax_t *, intmax_t *));
338 static int get_var_and_type
PARAMS((char *, char *, array_eltstate_t
*, int, int, SHELL_VAR
**, char **));
339 static char *mb_substring
PARAMS((char *, int, int));
340 static char *parameter_brace_substring
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int));
342 static int shouldexp_replacement
PARAMS((char *));
344 static char *pos_params_pat_subst
PARAMS((char *, char *, char *, int));
346 static char *expand_string_for_patsub
PARAMS((char *, int));
347 static char *parameter_brace_patsub
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int));
349 static char *pos_params_casemod
PARAMS((char *, char *, int, int));
350 static char *parameter_brace_casemod
PARAMS((char *, char *, array_eltstate_t
*, int, char *, int, int, int));
352 static WORD_DESC
*parameter_brace_expand
PARAMS((char *, int *, int, int, int *, int *));
353 static WORD_DESC
*param_expand
PARAMS((char *, int *, int, int *, int *, int *, int *, int));
355 static WORD_LIST
*expand_word_internal
PARAMS((WORD_DESC
*, int, int, int *, int *));
357 static WORD_LIST
*word_list_split
PARAMS((WORD_LIST
*));
359 static void exp_jump_to_top_level
PARAMS((int));
361 static WORD_LIST
*separate_out_assignments
PARAMS((WORD_LIST
*));
362 static WORD_LIST
*glob_expand_word_list
PARAMS((WORD_LIST
*, int));
363 #ifdef BRACE_EXPANSION
364 static WORD_LIST
*brace_expand_word_list
PARAMS((WORD_LIST
*, int));
366 #if defined (ARRAY_VARS)
367 static int make_internal_declare
PARAMS((char *, char *, char *));
368 static void expand_compound_assignment_word
PARAMS((WORD_LIST
*, int));
369 static WORD_LIST
*expand_declaration_argument
PARAMS((WORD_LIST
*, WORD_LIST
*));
371 static WORD_LIST
*shell_expand_word_list
PARAMS((WORD_LIST
*, int));
372 static WORD_LIST
*expand_word_list_internal
PARAMS((WORD_LIST
*, int));
374 static int do_assignment_statements
PARAMS((WORD_LIST
*, char *, int));
376 /* **************************************************************** */
378 /* Utility Functions */
380 /* **************************************************************** */
384 dump_word_flags (flags
)
390 fprintf (stderr
, "%d -> ", f
);
394 fprintf (stderr
, "W_ARRAYIND%s", f
? "|" : "");
396 if (f
& W_ASSIGNASSOC
)
399 fprintf (stderr
, "W_ASSIGNASSOC%s", f
? "|" : "");
401 if (f
& W_ASSIGNARRAY
)
404 fprintf (stderr
, "W_ASSIGNARRAY%s", f
? "|" : "");
406 if (f
& W_SAWQUOTEDNULL
)
408 f
&= ~W_SAWQUOTEDNULL
;
409 fprintf (stderr
, "W_SAWQUOTEDNULL%s", f
? "|" : "");
414 fprintf (stderr
, "W_NOPROCSUB%s", f
? "|" : "");
419 fprintf (stderr
, "W_DQUOTE%s", f
? "|" : "");
421 if (f
& W_HASQUOTEDNULL
)
423 f
&= ~W_HASQUOTEDNULL
;
424 fprintf (stderr
, "W_HASQUOTEDNULL%s", f
? "|" : "");
429 fprintf (stderr
, "W_ASSIGNARG%s", f
? "|" : "");
434 fprintf (stderr
, "W_ASSNBLTIN%s", f
? "|" : "");
436 if (f
& W_ASSNGLOBAL
)
439 fprintf (stderr
, "W_ASSNGLOBAL%s", f
? "|" : "");
441 if (f
& W_COMPASSIGN
)
444 fprintf (stderr
, "W_COMPASSIGN%s", f
? "|" : "");
449 fprintf (stderr
, "W_EXPANDRHS%s", f
? "|" : "");
454 fprintf (stderr
, "W_NOTILDE%s", f
? "|" : "");
459 fprintf (stderr
, "W_ASSIGNRHS%s", f
? "|" : "");
461 if (f
& W_NOASSNTILDE
)
464 fprintf (stderr
, "W_NOASSNTILDE%s", f
? "|" : "");
469 fprintf (stderr
, "W_NOCOMSUB%s", f
? "|" : "");
474 fprintf (stderr
, "W_ARRAYREF%s", f
? "|" : "");
479 fprintf (stderr
, "W_DOLLARAT%s", f
? "|" : "");
484 fprintf (stderr
, "W_TILDEEXP%s", f
? "|" : "");
489 fprintf (stderr
, "W_NOSPLIT2%s", f
? "|" : "");
494 fprintf (stderr
, "W_NOSPLIT%s", f
? "|" : "");
499 fprintf (stderr
, "W_NOBRACE%s", f
? "|" : "");
504 fprintf (stderr
, "W_NOGLOB%s", f
? "|" : "");
506 if (f
& W_SPLITSPACE
)
509 fprintf (stderr
, "W_SPLITSPACE%s", f
? "|" : "");
511 if (f
& W_ASSIGNMENT
)
514 fprintf (stderr
, "W_ASSIGNMENT%s", f
? "|" : "");
519 fprintf (stderr
, "W_QUOTED%s", f
? "|" : "");
524 fprintf (stderr
, "W_HASDOLLAR%s", f
? "|" : "");
529 fprintf (stderr
, "W_COMPLETE%s", f
? "|" : "");
534 fprintf (stderr
, "W_CHKLOCAL%s", f
? "|" : "");
536 if (f
& W_FORCELOCAL
)
539 fprintf (stderr
, "W_FORCELOCAL%s", f
? "|" : "");
542 fprintf (stderr
, "\n");
547 #ifdef INCLUDE_UNUSED
549 quoted_substring (string
, start
, end
)
554 register char *result
, *s
, *r
;
558 /* Move to string[start], skipping quoted characters. */
559 for (s
= string
, l
= 0; *s
&& l
< start
; )
571 r
= result
= (char *)xmalloc (2*len
+ 1); /* save room for quotes */
573 /* Copy LEN characters, including quote characters. */
575 for (l
= 0; l
< len
; s
++)
589 #ifdef INCLUDE_UNUSED
590 /* Return the length of S, skipping over quoted characters */
614 #ifdef INCLUDE_UNUSED
615 /* Find the first occurrence of character C in string S, obeying shell
616 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
617 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
618 escaped with CTLESC are skipped. */
620 quoted_strchr (s
, c
, flags
)
628 if (((flags
& ST_BACKSL
) && *p
== '\\')
629 || ((flags
& ST_CTLESC
) && *p
== CTLESC
))
633 return ((char *)NULL
);
639 return ((char *)NULL
);
642 /* Return 1 if CHARACTER appears in an unquoted portion of
643 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
645 unquoted_member (character
, string
)
653 slen
= strlen (string
);
655 while (c
= string
[sindex
])
663 ADVANCE_CHAR (string
, slen
, sindex
);
669 ADVANCE_CHAR (string
, slen
, sindex
);
673 sindex
= skip_single_quoted (string
, slen
, ++sindex
, 0);
677 sindex
= skip_double_quoted (string
, slen
, ++sindex
, 0);
684 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
686 unquoted_substring (substr
, string
)
687 char *substr
, *string
;
690 int sindex
, c
, sublen
;
693 if (substr
== 0 || *substr
== '\0')
696 slen
= strlen (string
);
697 sublen
= strlen (substr
);
698 for (sindex
= 0; c
= string
[sindex
]; )
700 if (STREQN (string
+ sindex
, substr
, sublen
))
708 ADVANCE_CHAR (string
, slen
, sindex
);
712 sindex
= skip_single_quoted (string
, slen
, ++sindex
, 0);
716 sindex
= skip_double_quoted (string
, slen
, ++sindex
, 0);
720 ADVANCE_CHAR (string
, slen
, sindex
);
728 /* Most of the substitutions must be done in parallel. In order
729 to avoid using tons of unclear goto's, I have some functions
730 for manipulating malloc'ed strings. They all take INDX, a
731 pointer to an integer which is the offset into the string
732 where manipulation is taking place. They also take SIZE, a
733 pointer to an integer which is the current length of the
734 character array for this string. */
736 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
737 of space allocated to TARGET. SOURCE can be NULL, in which
738 case nothing happens. Gets rid of SOURCE by freeing it.
739 Returns TARGET in case the location has changed. */
741 sub_append_string (source
, target
, indx
, size
)
742 char *source
, *target
;
750 srclen
= STRLEN (source
);
751 if (srclen
>= (*size
- *indx
))
754 n
= (n
+ DEFAULT_ARRAY_SIZE
) - (n
% DEFAULT_ARRAY_SIZE
);
755 target
= (char *)xrealloc (target
, (*size
= n
));
758 FASTCOPY (source
, target
+ *indx
, srclen
);
760 target
[*indx
] = '\0';
769 /* Append the textual representation of NUMBER to TARGET.
770 INDX and SIZE are as in SUB_APPEND_STRING. */
772 sub_append_number (number
, target
, indx
, size
)
780 temp
= itos (number
);
781 return (sub_append_string (temp
, target
, indx
, size
));
785 /* Extract a substring from STRING, starting at SINDEX and ending with
786 one of the characters in CHARLIST. Don't make the ending character
787 part of the string. Leave SINDEX pointing at the ending character.
788 Understand about backslashes in the string. If (flags & SX_VARNAME)
789 is non-zero, and array variables have been compiled into the shell,
790 everything between a `[' and a corresponding `]' is skipped over.
791 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
792 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
793 contain a closing character from CHARLIST. */
795 string_extract (string
, sindex
, charlist
, flags
)
807 slen
= (MB_CUR_MAX
> 1) ? strlen (string
+ *sindex
) + *sindex
: 0;
810 while (c
= string
[i
])
819 #if defined (ARRAY_VARS)
820 else if ((flags
& SX_VARNAME
) && c
== LBRACK
)
823 /* If this is an array subscript, skip over it and continue. */
824 ni
= skipsubscript (string
, i
, 0);
825 if (string
[ni
] == RBRACK
)
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. ALLOWESC allows the single quote to be quoted by
1096 a backslash; it's not used yet. */
1097 static inline char *
1098 string_extract_single_quoted (string
, sindex
, allowesc
)
1109 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
1110 slen
= (MB_CUR_MAX
> 1) ? strlen (string
+ *sindex
) + *sindex
: 0;
1118 ADVANCE_CHAR (string
, slen
, i
);
1121 if (allowesc
&& string
[i
] == '\\')
1123 else if (string
[i
] == '\'')
1125 ADVANCE_CHAR (string
, slen
, i
);
1128 t
= substring (string
, *sindex
, i
);
1137 /* Skip over a single-quoted string. We overload the SX_COMPLETE flag to mean
1138 that we are splitting out words for completion and have encountered a $'...'
1139 string, which allows backslash-escaped single quotes. */
1141 skip_single_quoted (string
, slen
, sind
, flags
)
1151 while (string
[c
] && string
[c
] != '\'')
1153 if ((flags
& SX_COMPLETE
) && string
[c
] == '\\' && string
[c
+1] == '\'' && string
[c
+2])
1154 ADVANCE_CHAR (string
, slen
, c
);
1155 ADVANCE_CHAR (string
, slen
, c
);
1163 /* Just like string_extract, but doesn't hack backslashes or any of
1164 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
1166 string_extract_verbatim (string
, slen
, sindex
, charlist
, flags
)
1174 #if defined (HANDLE_MULTIBYTE)
1181 if ((flags
& SX_NOCTLESC
) && charlist
[0] == '\'' && charlist
[1] == '\0')
1183 temp
= string_extract_single_quoted (string
, sindex
, 0);
1184 --*sindex
; /* leave *sindex at separator character */
1188 /* This can never be called with charlist == NULL. If *charlist == NULL,
1189 we can skip the loop and just return a copy of the string, updating
1193 temp
= string
+ *sindex
;
1194 c
= (*sindex
== 0) ? slen
: STRLEN (temp
);
1195 temp
= savestring (temp
);
1201 #if defined (HANDLE_MULTIBYTE)
1204 while (c
= string
[i
])
1206 #if defined (HANDLE_MULTIBYTE)
1209 if ((flags
& SX_NOCTLESC
) == 0 && c
== CTLESC
)
1212 CHECK_STRING_OVERRUN (i
, i
, slen
, c
);
1215 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
1216 through, to protect the CTLNULs from later calls to
1217 remove_quoted_nulls. */
1218 else if ((flags
& SX_NOESCCTLNUL
) == 0 && c
== CTLESC
&& string
[i
+1] == CTLNUL
)
1221 CHECK_STRING_OVERRUN (i
, i
, slen
, c
);
1225 #if defined (HANDLE_MULTIBYTE)
1226 if (locale_utf8locale
&& slen
> i
&& UTF8_SINGLEBYTE (string
[i
]))
1227 mblength
= (string
[i
] != 0) ? 1 : 0;
1229 mblength
= MBLEN (string
+ i
, slen
- i
);
1233 mblength
= mbtowc (&wc
, string
+ i
, slen
- i
);
1234 if (MB_INVALIDCH (mblength
))
1236 if (MEMBER (c
, charlist
))
1244 len
= mbstowcs (wcharlist
, charlist
, 0);
1247 wcharlist
= (wchar_t *)xmalloc (sizeof (wchar_t) * (len
+ 1));
1248 mbstowcs (wcharlist
, charlist
, len
+ 1);
1251 if (wcschr (wcharlist
, wc
))
1257 if (MEMBER (c
, charlist
))
1260 ADVANCE_CHAR (string
, slen
, i
);
1263 #if defined (HANDLE_MULTIBYTE)
1267 temp
= substring (string
, *sindex
, i
);
1273 /* Extract the $( construct in STRING, and return a new string.
1274 Start extracting at (SINDEX) as if we had just seen "$(".
1275 Make (SINDEX) get the position of the matching ")". )
1276 XFLAGS is additional flags to pass to other extraction functions. */
1278 extract_command_subst (string
, sindex
, xflags
)
1285 if (string
[*sindex
] == LPAREN
|| (xflags
& SX_COMPLETE
))
1286 return (extract_delimited_string (string
, sindex
, "$(", "(", ")", xflags
|SX_COMMAND
)); /*)*/
1289 xflags
|= (no_longjmp_on_fatal_error
? SX_NOLONGJMP
: 0);
1290 ret
= xparse_dolparen (string
, string
+*sindex
, sindex
, xflags
);
1295 /* Extract the $[ construct in STRING, and return a new string. (])
1296 Start extracting at (SINDEX) as if we had just seen "$[".
1297 Make (SINDEX) get the position of the matching "]". */
1299 extract_arithmetic_subst (string
, sindex
)
1303 return (extract_delimited_string (string
, sindex
, "$[", "[", "]", 0)); /*]*/
1306 #if defined (PROCESS_SUBSTITUTION)
1307 /* Extract the <( or >( construct in STRING, and return a new string.
1308 Start extracting at (SINDEX) as if we had just seen "<(".
1309 Make (SINDEX) get the position of the matching ")". */ /*))*/
1311 extract_process_subst (string
, starter
, sindex
, xflags
)
1318 /* XXX - check xflags&SX_COMPLETE here? */
1319 return (extract_delimited_string (string
, sindex
, starter
, "(", ")", SX_COMMAND
));
1321 xflags
|= (no_longjmp_on_fatal_error
? SX_NOLONGJMP
: 0);
1322 return (xparse_dolparen (string
, string
+*sindex
, sindex
, xflags
));
1325 #endif /* PROCESS_SUBSTITUTION */
1327 #if defined (ARRAY_VARS)
1328 /* This can be fooled by unquoted right parens in the passed string. If
1329 each caller verifies that the last character in STRING is a right paren,
1330 we don't even need to call extract_delimited_string. */
1332 extract_array_assignment_list (string
, sindex
)
1339 slen
= strlen (string
);
1340 if (string
[slen
- 1] == RPAREN
)
1342 ret
= substring (string
, *sindex
, slen
- 1);
1350 /* Extract and create a new string from the contents of STRING, a
1351 character string delimited with OPENER and CLOSER. SINDEX is
1352 the address of an int describing the current offset in STRING;
1353 it should point to just after the first OPENER found. On exit,
1354 SINDEX gets the position of the last character of the matching CLOSER.
1355 If OPENER is more than a single character, ALT_OPENER, if non-null,
1356 contains a character string that can also match CLOSER and thus
1357 needs to be skipped. */
1359 extract_delimited_string (string
, sindex
, opener
, alt_opener
, closer
, flags
)
1362 char *opener
, *alt_opener
, *closer
;
1368 int pass_character
, nesting_level
, in_comment
;
1369 int len_closer
, len_opener
, len_alt_opener
;
1372 slen
= strlen (string
+ *sindex
) + *sindex
;
1373 len_opener
= STRLEN (opener
);
1374 len_alt_opener
= STRLEN (alt_opener
);
1375 len_closer
= STRLEN (closer
);
1377 pass_character
= in_comment
= 0;
1382 while (nesting_level
)
1386 /* If a recursive call or a call to ADVANCE_CHAR leaves the index beyond
1387 the end of the string, catch it and cut the loop. */
1391 c
= string
[i
= slen
];
1402 ADVANCE_CHAR (string
, slen
, i
);
1406 if (pass_character
) /* previous char was backslash */
1409 ADVANCE_CHAR (string
, slen
, i
);
1413 /* Not exactly right yet; should handle shell metacharacters and
1414 multibyte characters, too. See COMMENT_BEGIN define in parse.y */
1415 if ((flags
& SX_COMMAND
) && c
== '#' && (i
== 0 || string
[i
- 1] == '\n' || shellblank (string
[i
- 1])))
1418 ADVANCE_CHAR (string
, slen
, i
);
1422 if (c
== CTLESC
|| c
== '\\')
1429 /* Process a nested command substitution, but only if we're parsing an
1430 arithmetic substitution. */
1431 if ((flags
& SX_COMMAND
) && string
[i
] == '$' && string
[i
+1] == LPAREN
)
1434 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1435 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1440 /* Process a nested OPENER. */
1441 if (STREQN (string
+ i
, opener
, len_opener
))
1443 si
= i
+ len_opener
;
1444 t
= extract_delimited_string (string
, &si
, opener
, alt_opener
, closer
, flags
|SX_NOALLOC
);
1445 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1450 /* Process a nested ALT_OPENER */
1451 if (len_alt_opener
&& STREQN (string
+ i
, alt_opener
, len_alt_opener
))
1453 si
= i
+ len_alt_opener
;
1454 t
= extract_delimited_string (string
, &si
, alt_opener
, alt_opener
, closer
, flags
|SX_NOALLOC
);
1455 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1460 /* If the current substring terminates the delimited string, decrement
1461 the nesting level. */
1462 if (STREQN (string
+ i
, closer
, len_closer
))
1464 i
+= len_closer
- 1; /* move to last byte of the closer */
1466 if (nesting_level
== 0)
1470 /* Pass old-style command substitution through verbatim. */
1474 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1475 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1480 /* Pass single-quoted and double-quoted strings through verbatim. */
1481 if (c
== '\'' || c
== '"')
1484 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, si
, 0)
1485 : skip_double_quoted (string
, slen
, si
, 0);
1489 /* move past this character, which was not special. */
1490 ADVANCE_CHAR (string
, slen
, i
);
1493 if (c
== 0 && nesting_level
)
1495 if (no_longjmp_on_fatal_error
== 0)
1497 last_command_exit_value
= EXECUTION_FAILURE
;
1498 report_error (_("bad substitution: no closing `%s' in %s"), closer
, string
);
1499 exp_jump_to_top_level (DISCARD
);
1504 return (char *)NULL
;
1508 si
= i
- *sindex
- len_closer
+ 1;
1509 if (flags
& SX_NOALLOC
)
1510 result
= (char *)NULL
;
1513 result
= (char *)xmalloc (1 + si
);
1514 strncpy (result
, string
+ *sindex
, si
);
1522 /* A simplified version of extract_dollar_brace_string that exists to handle
1523 $'...' and $"..." quoting in here-documents, since the here-document read
1524 path doesn't. It's separate because we don't want to mess with the fast
1525 common path. We already know we're going to allocate and return a new
1526 string and quoted == Q_HERE_DOCUMENT. We might be able to cut it down
1527 some more, but extracting strings and adding them as we go adds complexity.
1528 This needs to match the logic in parse.y:parse_matched_pair so we get
1529 consistent behavior between here-documents and double-quoted strings. */
1531 extract_heredoc_dolbrace_string (string
, sindex
, quoted
, flags
)
1533 int *sindex
, quoted
, flags
;
1536 size_t slen
, tlen
, result_index
, result_size
;
1537 int pass_character
, nesting_level
, si
, dolbrace_state
;
1538 char *result
, *t
, *send
;
1543 slen
= strlen (string
+ *sindex
) + *sindex
;
1544 send
= string
+ slen
;
1548 result
= xmalloc (result_size
+ 1);
1550 /* This function isn't called if this condition is not true initially. */
1551 dolbrace_state
= DOLBRACE_QUOTE
;
1554 while (c
= string
[i
])
1559 RESIZE_MALLOCED_BUFFER (result
, result_index
, locale_mb_cur_max
+ 1, result_size
, 64);
1560 COPY_CHAR_I (result
, result_index
, string
, send
, i
);
1564 /* CTLESCs and backslashes quote the next character. */
1565 if (c
== CTLESC
|| c
== '\\')
1568 RESIZE_MALLOCED_BUFFER (result
, result_index
, 2, result_size
, 64);
1569 result
[result_index
++] = c
;
1574 /* The entire reason we have this separate function right here. */
1575 if (c
== '$' && string
[i
+1] == '\'')
1580 if ((posixly_correct
|| extended_quote
== 0) && dolbrace_state
!= DOLBRACE_QUOTE
&& dolbrace_state
!= DOLBRACE_QUOTE2
)
1582 RESIZE_MALLOCED_BUFFER (result
, result_index
, 3, result_size
, 64);
1583 result
[result_index
++] = '$';
1584 result
[result_index
++] = '\'';
1590 t
= string_extract_single_quoted (string
, &si
, 1); /* XXX */
1591 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1593 tlen
= si
- i
- 2; /* -2 since si is one after the close quote */
1594 ttrans
= ansiexpand (t
, 0, tlen
, &ttranslen
);
1597 /* needed to correctly quote any embedded single quotes. */
1598 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_QUOTE2
)
1600 t
= sh_single_quote (ttrans
);
1604 else if (extended_quote
) /* dolbrace_state == DOLBRACE_PARAM */
1606 /* This matches what parse.y:parse_matched_pair() does */
1611 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 1, result_size
, 64);
1612 strncpy (result
+ result_index
, t
, tlen
);
1613 result_index
+= tlen
;
1619 #if defined (TRANSLATABLE_STRINGS)
1620 if (c
== '$' && string
[i
+1] == '"')
1626 t
= string_extract_double_quoted (string
, &si
, flags
); /* XXX */
1627 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1629 tlen
= si
- i
- 2; /* -2 since si is one after the close quote */
1630 ttrans
= locale_expand (t
, 0, tlen
, line_number
, &ttranslen
);
1633 t
= singlequote_translations
? sh_single_quote (ttrans
) : sh_mkdoublequoted (ttrans
, ttranslen
, 0);
1637 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 1, result_size
, 64);
1638 strncpy (result
+ result_index
, t
, tlen
);
1639 result_index
+= tlen
;
1644 #endif /* TRANSLATABLE_STRINGS */
1646 if (c
== '$' && string
[i
+1] == LBRACE
)
1649 RESIZE_MALLOCED_BUFFER (result
, result_index
, 3, result_size
, 64);
1650 result
[result_index
++] = c
;
1651 result
[result_index
++] = string
[i
+1];
1653 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_QUOTE2
|| dolbrace_state
== DOLBRACE_WORD
)
1654 dolbrace_state
= DOLBRACE_PARAM
;
1661 if (nesting_level
== 0)
1663 RESIZE_MALLOCED_BUFFER (result
, result_index
, 2, result_size
, 64);
1664 result
[result_index
++] = c
;
1669 /* Pass the contents of old-style command substitutions through
1674 t
= string_extract (string
, &si
, "`", flags
); /* already know (flags & SX_NOALLOC) == 0) */
1675 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1678 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 3, result_size
, 64);
1679 result
[result_index
++] = c
;
1680 strncpy (result
+ result_index
, t
, tlen
);
1681 result_index
+= tlen
;
1682 result
[result_index
++] = string
[si
];
1688 /* Pass the contents of new-style command substitutions and
1689 arithmetic substitutions through verbatim. */
1690 if (string
[i
] == '$' && string
[i
+1] == LPAREN
)
1693 t
= extract_command_subst (string
, &si
, flags
);
1694 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1697 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 4, result_size
, 64);
1698 result
[result_index
++] = c
;
1699 result
[result_index
++] = LPAREN
;
1700 strncpy (result
+ result_index
, t
, tlen
);
1701 result_index
+= tlen
;
1702 result
[result_index
++] = string
[si
];
1708 #if defined (PROCESS_SUBSTITUTION)
1709 /* Technically this should only work at the start of a word */
1710 if ((string
[i
] == '<' || string
[i
] == '>') && string
[i
+1] == LPAREN
)
1713 t
= extract_process_subst (string
, (string
[i
] == '<' ? "<(" : ">)"), &si
, flags
);
1714 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1717 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 4, result_size
, 64);
1718 result
[result_index
++] = c
;
1719 result
[result_index
++] = LPAREN
;
1720 strncpy (result
+ result_index
, t
, tlen
);
1721 result_index
+= tlen
;
1722 result
[result_index
++] = string
[si
];
1729 if (c
== '\'' && posixly_correct
&& shell_compatibility_level
> 42 && dolbrace_state
!= DOLBRACE_QUOTE
)
1731 COPY_CHAR_I (result
, result_index
, string
, send
, i
);
1735 /* Pass the contents of single and double-quoted strings through verbatim. */
1736 if (c
== '"' || c
== '\'')
1740 t
= string_extract_double_quoted (string
, &si
, flags
);
1742 t
= string_extract_single_quoted (string
, &si
, 0);
1743 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1745 tlen
= si
- i
- 2; /* -2 since si is one after the close quote */
1746 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 3, result_size
, 64);
1747 result
[result_index
++] = c
;
1748 strncpy (result
+ result_index
, t
, tlen
);
1749 result_index
+= tlen
;
1750 result
[result_index
++] = string
[si
- 1];
1756 /* copy this character, which was not special. */
1757 COPY_CHAR_I (result
, result_index
, string
, send
, i
);
1759 /* This logic must agree with parse.y:parse_matched_pair, since they
1760 share the same defines. */
1761 if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '%' && (i
- *sindex
) > 1)
1762 dolbrace_state
= DOLBRACE_QUOTE
;
1763 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '#' && (i
- *sindex
) > 1)
1764 dolbrace_state
= DOLBRACE_QUOTE
;
1765 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '/' && (i
- *sindex
) > 1)
1766 dolbrace_state
= DOLBRACE_QUOTE2
; /* XXX */
1767 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '^' && (i
- *sindex
) > 1)
1768 dolbrace_state
= DOLBRACE_QUOTE
;
1769 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== ',' && (i
- *sindex
) > 1)
1770 dolbrace_state
= DOLBRACE_QUOTE
;
1771 /* This is intended to handle all of the [:]op expansions and the substring/
1772 length/pattern removal/pattern substitution expansions. */
1773 else if (dolbrace_state
== DOLBRACE_PARAM
&& strchr ("#%^,~:-=?+/", c
) != 0)
1774 dolbrace_state
= DOLBRACE_OP
;
1775 else if (dolbrace_state
== DOLBRACE_OP
&& strchr ("#%^,~:-=?+/", c
) == 0)
1776 dolbrace_state
= DOLBRACE_WORD
;
1779 if (c
== 0 && nesting_level
)
1782 if (no_longjmp_on_fatal_error
== 0)
1784 last_command_exit_value
= EXECUTION_FAILURE
;
1785 report_error (_("bad substitution: no closing `%s' in %s"), "}", string
);
1786 exp_jump_to_top_level (DISCARD
);
1791 return ((char *)NULL
);
1796 result
[result_index
] = '\0';
1801 #define PARAMEXPNEST_MAX 32 // for now
1802 static int dbstate
[PARAMEXPNEST_MAX
];
1804 /* Extract a parameter expansion expression within ${ and } from STRING.
1805 Obey the Posix.2 rules for finding the ending `}': count braces while
1806 skipping over enclosed quoted strings and command substitutions.
1807 SINDEX is the address of an int describing the current offset in STRING;
1808 it should point to just after the first `{' found. On exit, SINDEX
1809 gets the position of the matching `}'. QUOTED is non-zero if this
1810 occurs inside double quotes. */
1811 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1813 extract_dollar_brace_string (string
, sindex
, quoted
, flags
)
1815 int *sindex
, quoted
, flags
;
1819 int pass_character
, nesting_level
, si
, dolbrace_state
;
1823 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1824 parse_matched_pair(). The different initial value is to handle the
1825 case where this function is called to parse the word in
1826 ${param op word} (SX_WORD). */
1827 dolbrace_state
= (flags
& SX_WORD
) ? DOLBRACE_WORD
: DOLBRACE_PARAM
;
1828 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && (flags
& SX_POSIXEXP
))
1829 dolbrace_state
= DOLBRACE_QUOTE
;
1831 if (quoted
== Q_HERE_DOCUMENT
&& dolbrace_state
== DOLBRACE_QUOTE
&& (flags
& SX_NOALLOC
) == 0)
1832 return (extract_heredoc_dolbrace_string (string
, sindex
, quoted
, flags
));
1834 dbstate
[0] = dolbrace_state
;
1838 slen
= strlen (string
+ *sindex
) + *sindex
;
1841 while (c
= string
[i
])
1846 ADVANCE_CHAR (string
, slen
, i
);
1850 /* CTLESCs and backslashes quote the next character. */
1851 if (c
== CTLESC
|| c
== '\\')
1858 if (string
[i
] == '$' && string
[i
+1] == LBRACE
)
1860 if (nesting_level
< PARAMEXPNEST_MAX
)
1861 dbstate
[nesting_level
] = dolbrace_state
;
1864 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_WORD
)
1865 dolbrace_state
= DOLBRACE_PARAM
;
1872 if (nesting_level
== 0)
1874 dolbrace_state
= (nesting_level
< PARAMEXPNEST_MAX
) ? dbstate
[nesting_level
] : dbstate
[0]; /* Guess using initial state */
1879 /* Pass the contents of old-style command substitutions through
1884 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1886 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1892 /* Pass the contents of new-style command substitutions and
1893 arithmetic substitutions through verbatim. */
1894 if (string
[i
] == '$' && string
[i
+1] == LPAREN
)
1897 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1899 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1905 #if defined (PROCESS_SUBSTITUTION)
1906 /* Technically this should only work at the start of a word */
1907 if ((string
[i
] == '<' || string
[i
] == '>') && string
[i
+1] == LPAREN
)
1910 t
= extract_process_subst (string
, (string
[i
] == '<' ? "<(" : ">)"), &si
, flags
|SX_NOALLOC
);
1912 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1919 /* Pass the contents of double-quoted strings through verbatim. */
1923 i
= skip_double_quoted (string
, slen
, si
, 0);
1924 /* skip_XXX_quoted leaves index one past close quote */
1930 /*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
1931 if (posixly_correct
&& shell_compatibility_level
> 42 && dolbrace_state
!= DOLBRACE_QUOTE
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1932 ADVANCE_CHAR (string
, slen
, i
);
1936 i
= skip_single_quoted (string
, slen
, si
, 0);
1942 #if defined (ARRAY_VARS)
1943 if (c
== LBRACK
&& dolbrace_state
== DOLBRACE_PARAM
)
1945 si
= skipsubscript (string
, i
, 0);
1946 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1947 if (string
[si
] == RBRACK
)
1952 /* move past this character, which was not special. */
1953 ADVANCE_CHAR (string
, slen
, i
);
1955 /* This logic must agree with parse.y:parse_matched_pair, since they
1956 share the same defines. */
1957 if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '%' && (i
- *sindex
) > 1)
1958 dolbrace_state
= DOLBRACE_QUOTE
;
1959 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '#' && (i
- *sindex
) > 1)
1960 dolbrace_state
= DOLBRACE_QUOTE
;
1961 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '/' && (i
- *sindex
) > 1)
1962 dolbrace_state
= DOLBRACE_QUOTE2
; /* XXX */
1963 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '^' && (i
- *sindex
) > 1)
1964 dolbrace_state
= DOLBRACE_QUOTE
;
1965 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== ',' && (i
- *sindex
) > 1)
1966 dolbrace_state
= DOLBRACE_QUOTE
;
1967 /* This is intended to handle all of the [:]op expansions and the substring/
1968 length/pattern removal/pattern substitution expansions. */
1969 else if (dolbrace_state
== DOLBRACE_PARAM
&& strchr ("#%^,~:-=?+/", c
) != 0)
1970 dolbrace_state
= DOLBRACE_OP
;
1971 else if (dolbrace_state
== DOLBRACE_OP
&& strchr ("#%^,~:-=?+/", c
) == 0)
1972 dolbrace_state
= DOLBRACE_WORD
;
1975 if (c
== 0 && nesting_level
)
1977 if (no_longjmp_on_fatal_error
== 0)
1979 last_command_exit_value
= EXECUTION_FAILURE
;
1980 report_error (_("bad substitution: no closing `%s' in %s"), "}", string
);
1981 exp_jump_to_top_level (DISCARD
);
1986 return ((char *)NULL
);
1990 result
= (flags
& SX_NOALLOC
) ? (char *)NULL
: substring (string
, *sindex
, i
);
1996 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1997 STRING, and returns a pointer to it. */
1999 de_backslash (string
)
2002 register size_t slen
;
2003 register int i
, j
, prev_i
;
2006 slen
= strlen (string
);
2009 /* Loop copying string[i] to string[j], i >= j. */
2012 if (string
[i
] == '\\' && (string
[i
+ 1] == '`' || string
[i
+ 1] == '\\' ||
2013 string
[i
+ 1] == '$'))
2016 ADVANCE_CHAR (string
, slen
, i
);
2018 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
2029 /* Replace instances of \! in a string with !. */
2031 unquote_bang (string
)
2035 register char *temp
;
2037 temp
= (char *)xmalloc (1 + strlen (string
));
2039 for (i
= 0, j
= 0; (temp
[j
] = string
[i
]); i
++, j
++)
2041 if (string
[i
] == '\\' && string
[i
+ 1] == '!')
2047 strcpy (string
, temp
);
2052 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0)
2054 /* When FLAGS & 2 == 0, this function assumes STRING[I] == OPEN; when
2055 FLAGS & 2 != 0, it assumes STRING[I] points to one character past OPEN;
2056 returns with STRING[RET] == close; used to parse array subscripts.
2057 FLAGS & 1 means not to attempt to skip over matched pairs of quotes or
2058 backquotes, or skip word expansions; it is intended to be used after
2059 expansion has been performed and during final assignment parsing (see
2060 arrayfunc.c:assign_compound_array_list()) or during execution by a builtin
2061 which has already undergone word expansion. */
2063 skip_matched_pair (string
, start
, open
, close
, flags
)
2065 int start
, open
, close
, flags
;
2067 int i
, pass_next
, backq
, si
, c
, count
, oldjmp
;
2072 slen
= strlen (string
+ start
) + start
;
2073 oldjmp
= no_longjmp_on_fatal_error
;
2074 no_longjmp_on_fatal_error
= 1;
2076 /* Move to the first character after a leading OPEN. If FLAGS&2, we assume
2077 that START already points to that character. If not, we need to skip over
2079 i
= (flags
& 2) ? start
: start
+ 1;
2081 pass_next
= backq
= 0;
2082 ss
= (char *)string
;
2083 while (c
= string
[i
])
2090 ADVANCE_CHAR (string
, slen
, i
);
2093 else if ((flags
& 1) == 0 && c
== '\\')
2103 ADVANCE_CHAR (string
, slen
, i
);
2106 else if ((flags
& 1) == 0 && c
== '`')
2112 else if ((flags
& 1) == 0 && c
== open
)
2118 else if (c
== close
)
2126 else if ((flags
& 1) == 0 && (c
== '\'' || c
== '"'))
2128 i
= (c
== '\'') ? skip_single_quoted (ss
, slen
, ++i
, 0)
2129 : skip_double_quoted (ss
, slen
, ++i
, 0);
2130 /* no increment, the skip functions increment past the closing quote. */
2132 else if ((flags
& 1) == 0 && c
== '$' && (string
[i
+1] == LPAREN
|| string
[i
+1] == LBRACE
))
2135 if (string
[si
] == '\0')
2138 /* XXX - extract_command_subst here? */
2139 if (string
[i
+1] == LPAREN
)
2140 temp
= extract_delimited_string (ss
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
); /* ) */
2142 temp
= extract_dollar_brace_string (ss
, &si
, 0, SX_NOALLOC
);
2144 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2147 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2153 ADVANCE_CHAR (string
, slen
, i
);
2159 #if defined (ARRAY_VARS)
2160 /* FLAGS has 1 as a reserved value, since skip_matched_pair uses it for
2161 skipping over quoted strings and taking the first instance of the
2162 closing character. FLAGS & 2 means that STRING[START] points one
2163 character past the open bracket; FLAGS & 2 == 0 means that STRING[START]
2164 points to the open bracket. skip_matched_pair knows how to deal with this. */
2166 skipsubscript (string
, start
, flags
)
2170 return (skip_matched_pair (string
, start
, '[', ']', flags
));
2174 /* Skip characters in STRING until we find a character in DELIMS, and return
2175 the index of that character. START is the index into string at which we
2176 begin. This is similar in spirit to strpbrk, but it returns an index into
2177 STRING and takes a starting index. This little piece of code knows quite
2178 a lot of shell syntax. It's very similar to skip_double_quoted and other
2179 functions of that ilk. */
2181 skip_to_delim (string
, start
, delims
, flags
)
2187 int i
, pass_next
, backq
, dquote
, si
, c
, oldjmp
;
2188 int invert
, skipquote
, skipcmd
, noprocsub
, completeflag
;
2189 int arithexp
, skipcol
;
2191 char *temp
, open
[3];
2194 slen
= strlen (string
+ start
) + start
;
2195 oldjmp
= no_longjmp_on_fatal_error
;
2196 if (flags
& SD_NOJMP
)
2197 no_longjmp_on_fatal_error
= 1;
2198 invert
= (flags
& SD_INVERT
);
2199 skipcmd
= (flags
& SD_NOSKIPCMD
) == 0;
2200 noprocsub
= (flags
& SD_NOPROCSUB
);
2201 completeflag
= (flags
& SD_COMPLETE
) ? SX_COMPLETE
: 0;
2203 arithexp
= (flags
& SD_ARITHEXP
);
2207 pass_next
= backq
= dquote
= 0;
2208 while (c
= string
[i
])
2210 /* If this is non-zero, we should not let quote characters be delimiters
2211 and the current character is a single or double quote. We should not
2212 test whether or not it's a delimiter until after we skip single- or
2213 double-quoted strings. */
2214 skipquote
= ((flags
& SD_NOQUOTEDELIM
) && (c
== '\'' || c
=='"'));
2220 ADVANCE_CHAR (string
, slen
, i
);
2233 ADVANCE_CHAR (string
, slen
, i
);
2242 else if (arithexp
&& skipcol
&& c
== ':')
2248 else if (arithexp
&& c
== '?')
2254 else if (skipquote
== 0 && invert
== 0 && member (c
, delims
))
2256 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2257 quoted strings when looking for the history expansion character as a
2259 /* special case for programmable completion which takes place before
2260 parser converts backslash-escaped single quotes between $'...' to
2261 `regular' single-quoted strings. */
2262 else if (completeflag
&& i
> 0 && string
[i
-1] == '$' && c
== '\'')
2263 i
= skip_single_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2265 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2267 i
= skip_double_quoted (string
, slen
, ++i
, completeflag
);
2268 else if (c
== LPAREN
&& arithexp
)
2271 if (string
[si
] == '\0')
2274 temp
= extract_delimited_string (string
, &si
, "(", "(", ")", SX_NOALLOC
); /* ) */
2276 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2281 else if (c
== '$' && ((skipcmd
&& string
[i
+1] == LPAREN
) || string
[i
+1] == LBRACE
))
2284 if (string
[si
] == '\0')
2287 if (string
[i
+1] == LPAREN
)
2288 temp
= extract_delimited_string (string
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
|completeflag
); /* ) */
2290 temp
= extract_dollar_brace_string (string
, &si
, 0, SX_NOALLOC
);
2291 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2293 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2298 #if defined (PROCESS_SUBSTITUTION)
2299 else if (skipcmd
&& noprocsub
== 0 && (c
== '<' || c
== '>') && string
[i
+1] == LPAREN
)
2302 if (string
[si
] == '\0')
2305 temp
= extract_delimited_string (string
, &si
, (c
== '<') ? "<(" : ">(", "(", ")", SX_COMMAND
|SX_NOALLOC
); /* )) */
2306 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2308 if (string
[i
] == '\0')
2313 #endif /* PROCESS_SUBSTITUTION */
2314 #if defined (EXTENDED_GLOB)
2315 else if ((flags
& SD_EXTGLOB
) && extended_glob
&& string
[i
+1] == LPAREN
&& member (c
, "?*+!@"))
2318 if (string
[si
] == '\0')
2324 temp
= extract_delimited_string (string
, &si
, open
, "(", ")", SX_NOALLOC
); /* ) */
2326 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2328 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2334 else if ((flags
& SD_GLOB
) && c
== LBRACK
)
2337 if (string
[si
] == '\0')
2340 temp
= extract_delimited_string (string
, &si
, "[", "[", "]", SX_NOALLOC
); /* ] */
2343 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2348 else if ((skipquote
|| invert
) && (member (c
, delims
) == 0))
2351 ADVANCE_CHAR (string
, slen
, i
);
2357 #if defined (BANG_HISTORY)
2358 /* Skip to the history expansion character (delims[0]), paying attention to
2359 quoted strings and command and process substitution. This is a stripped-
2360 down version of skip_to_delims. The essential difference is that this
2361 resets the quoting state when starting a command substitution */
2363 skip_to_histexp (string
, start
, delims
, flags
)
2369 int i
, pass_next
, backq
, dquote
, c
, oldjmp
;
2370 int histexp_comsub
, histexp_backq
, old_dquote
;
2374 slen
= strlen (string
+ start
) + start
;
2375 oldjmp
= no_longjmp_on_fatal_error
;
2376 if (flags
& SD_NOJMP
)
2377 no_longjmp_on_fatal_error
= 1;
2379 histexp_comsub
= histexp_backq
= old_dquote
= 0;
2382 pass_next
= backq
= dquote
= 0;
2383 while (c
= string
[i
])
2390 ADVANCE_CHAR (string
, slen
, i
);
2399 else if (backq
&& c
== '`')
2403 dquote
= old_dquote
;
2411 old_dquote
= dquote
; /* simple - one level for now */
2416 /* When in double quotes, act as if the double quote is a member of
2417 history_no_expand_chars, like the history library does */
2418 else if (dquote
&& c
== delims
[0] && string
[i
+1] == '"')
2423 else if (c
== delims
[0])
2425 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2426 quoted strings when looking for the history expansion character as a
2428 else if (dquote
&& c
== '\'')
2434 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2435 /* The posixly_correct test makes posix-mode shells allow double quotes
2436 to quote the history expansion character */
2437 else if (posixly_correct
== 0 && c
== '"')
2439 dquote
= 1 - dquote
;
2444 i
= skip_double_quoted (string
, slen
, ++i
, 0);
2445 #if defined (PROCESS_SUBSTITUTION)
2446 else if ((c
== '$' || c
== '<' || c
== '>') && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2448 else if (c
== '$' && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2451 if (string
[i
+2] == '\0')
2455 old_dquote
= dquote
;
2458 else if (histexp_comsub
&& c
== RPAREN
)
2461 dquote
= old_dquote
;
2465 else if (backq
) /* placeholder */
2467 ADVANCE_CHAR (string
, slen
, i
);
2471 ADVANCE_CHAR (string
, slen
, i
);
2476 #endif /* BANG_HISTORY */
2478 #if defined (READLINE)
2479 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
2480 an unclosed quoted string), or if the character at EINDEX is quoted
2481 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
2482 single and double-quoted string parsing functions should not return an
2483 error if there are unclosed quotes or braces. The characters that this
2484 recognizes need to be the same as the contents of
2485 rl_completer_quote_characters. */
2488 char_is_quoted (string
, eindex
)
2492 int i
, pass_next
, c
, oldjmp
;
2496 slen
= strlen (string
);
2497 oldjmp
= no_longjmp_on_fatal_error
;
2498 no_longjmp_on_fatal_error
= 1;
2501 /* If we have an open quoted string from a previous line, see if it's
2502 closed before string[eindex], so we don't interpret that close quote
2503 as starting a new quoted string. */
2504 if (current_command_line_count
> 0 && dstack
.delimiter_depth
> 0)
2506 c
= dstack
.delimiters
[dstack
.delimiter_depth
- 1];
2508 i
= skip_single_quoted (string
, slen
, 0, 0);
2510 i
= skip_double_quoted (string
, slen
, 0, SX_COMPLETE
);
2522 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2524 ADVANCE_CHAR (string
, slen
, i
);
2533 else if (c
== '$' && string
[i
+1] == '\'' && string
[i
+2])
2536 i
= skip_single_quoted (string
, slen
, i
, SX_COMPLETE
);
2540 else if (c
== '\'' || c
== '"')
2542 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, ++i
, 0)
2543 : skip_double_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2546 /* no increment, the skip_xxx functions go one past end */
2549 ADVANCE_CHAR (string
, slen
, i
);
2556 unclosed_pair (string
, eindex
, openstr
)
2561 int i
, pass_next
, openc
, olen
;
2565 slen
= strlen (string
);
2566 olen
= strlen (openstr
);
2567 i
= pass_next
= openc
= 0;
2573 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2575 ADVANCE_CHAR (string
, slen
, i
);
2578 else if (string
[i
] == '\\')
2584 else if (STREQN (string
+ i
, openstr
, olen
))
2589 /* XXX - may want to handle $'...' specially here */
2590 else if (string
[i
] == '\'' || string
[i
] == '"')
2592 i
= (string
[i
] == '\'') ? skip_single_quoted (string
, slen
, i
, 0)
2593 : skip_double_quoted (string
, slen
, i
, SX_COMPLETE
);
2598 ADVANCE_CHAR (string
, slen
, i
);
2603 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
2604 individual words. If DELIMS is NULL, the current value of $IFS is used
2605 to split the string, and the function follows the shell field splitting
2606 rules. SENTINEL is an index to look for. NWP, if non-NULL,
2607 gets the number of words in the returned list. CWP, if non-NULL, gets
2608 the index of the word containing SENTINEL. Non-whitespace chars in
2609 DELIMS delimit separate fields. This is used by programmable completion. */
2611 split_at_delims (string
, slen
, delims
, sentinel
, flags
, nwp
, cwp
)
2615 int sentinel
, flags
;
2618 int ts
, te
, i
, nw
, cw
, ifs_split
, dflags
;
2619 char *token
, *d
, *d2
;
2620 WORD_LIST
*ret
, *tl
;
2622 if (string
== 0 || *string
== '\0')
2628 return ((WORD_LIST
*)NULL
);
2631 d
= (delims
== 0) ? ifs_value
: (char *)delims
;
2632 ifs_split
= delims
== 0;
2634 /* Make d2 the non-whitespace characters in delims */
2639 #if defined (HANDLE_MULTIBYTE)
2640 size_t mblength
= 1;
2644 slength
= strlen (delims
);
2645 d2
= (char *)xmalloc (slength
+ 1);
2649 #if defined (HANDLE_MULTIBYTE)
2650 mbstate_t state_bak
;
2652 mblength
= MBRLEN (delims
+ i
, slength
, &state
);
2653 if (MB_INVALIDCH (mblength
))
2655 else if (mblength
> 1)
2657 memcpy (d2
+ ts
, delims
+ i
, mblength
);
2660 slength
-= mblength
;
2664 if (whitespace (delims
[i
]) == 0)
2665 d2
[ts
++] = delims
[i
];
2673 ret
= (WORD_LIST
*)NULL
;
2675 /* Remove sequences of whitespace characters at the start of the string, as
2676 long as those characters are delimiters. */
2677 for (i
= 0; member (string
[i
], d
) && spctabnl (string
[i
]); i
++)
2679 if (string
[i
] == '\0')
2688 dflags
= flags
|SD_NOJMP
;
2691 te
= skip_to_delim (string
, ts
, d
, dflags
);
2693 /* If we have a non-whitespace delimiter character, use it to make a
2694 separate field. This is just about what $IFS splitting does and
2695 is closer to the behavior of the shell parser. */
2696 if (ts
== te
&& d2
&& member (string
[ts
], d2
))
2699 /* If we're using IFS splitting, the non-whitespace delimiter char
2700 and any additional IFS whitespace delimits a field. */
2702 while (member (string
[te
], d
) && spctabnl (string
[te
]) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2705 while (member (string
[te
], d2
) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2709 token
= substring (string
, ts
, te
);
2711 ret
= add_string_to_list (token
, ret
); /* XXX */
2715 if (sentinel
>= ts
&& sentinel
<= te
)
2718 /* If the cursor is at whitespace just before word start, set the
2719 sentinel word to the current word. */
2720 if (cwp
&& cw
== -1 && sentinel
== ts
-1)
2723 /* If the cursor is at whitespace between two words, make a new, empty
2724 word, add it before (well, after, since the list is in reverse order)
2725 the word we just added, and set the current word to that one. */
2726 if (cwp
&& cw
== -1 && sentinel
< ts
)
2728 tl
= make_word_list (make_word (""), ret
->next
);
2734 if (string
[te
] == 0)
2738 /* XXX - honor SD_NOQUOTEDELIM here */
2739 while (member (string
[i
], d
) && (ifs_split
|| spctabnl(string
[i
])) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2748 /* Special case for SENTINEL at the end of STRING. If we haven't found
2749 the word containing SENTINEL yet, and the index we're looking for is at
2750 the end of STRING (or past the end of the previously-found token,
2751 possible if the end of the line is composed solely of IFS whitespace)
2752 add an additional null argument and set the current word pointer to that. */
2753 if (cwp
&& cw
== -1 && (sentinel
>= slen
|| sentinel
>= te
))
2755 if (whitespace (string
[sentinel
- 1]))
2758 ret
= add_string_to_list (token
, ret
);
2771 return (REVERSE_LIST (ret
, WORD_LIST
*));
2773 #endif /* READLINE */
2777 /* Extract the name of the variable to bind to from the assignment string. */
2779 assignment_name (string
)
2785 offset
= assignment (string
, 0);
2787 return (char *)NULL
;
2788 temp
= substring (string
, 0, offset
);
2793 /* **************************************************************** */
2795 /* Functions to convert strings to WORD_LISTs and vice versa */
2797 /* **************************************************************** */
2799 /* Return a single string of all the words in LIST. SEP is the separator
2800 to put between individual elements of LIST in the output string. */
2802 string_list_internal (list
, sep
)
2806 register WORD_LIST
*t
;
2808 size_t word_len
, sep_len
, result_size
;
2811 return ((char *)NULL
);
2813 /* Short-circuit quickly if we don't need to separate anything. */
2814 if (list
->next
== 0)
2815 return (savestring (list
->word
->word
));
2817 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
2818 sep_len
= STRLEN (sep
);
2821 for (t
= list
; t
; t
= t
->next
)
2824 result_size
+= sep_len
;
2825 result_size
+= strlen (t
->word
->word
);
2828 r
= result
= (char *)xmalloc (result_size
+ 1);
2830 for (t
= list
; t
; t
= t
->next
)
2832 if (t
!= list
&& sep_len
)
2836 FASTCOPY (sep
, r
, sep_len
);
2843 word_len
= strlen (t
->word
->word
);
2844 FASTCOPY (t
->word
->word
, r
, word_len
);
2852 /* Return a single string of all the words present in LIST, separating
2853 each word with a space. */
2858 return (string_list_internal (list
, " "));
2861 /* An external interface that can be used by the rest of the shell to
2862 obtain a string containing the first character in $IFS. Handles all
2863 the multibyte complications. If LENP is non-null, it is set to the
2864 length of the returned string. */
2866 ifs_firstchar (lenp
)
2872 ret
= xmalloc (MB_LEN_MAX
+ 1);
2873 #if defined (HANDLE_MULTIBYTE)
2874 if (ifs_firstc_len
== 1)
2876 ret
[0] = ifs_firstc
[0];
2878 len
= ret
[0] ? 1 : 0;
2882 memcpy (ret
, ifs_firstc
, ifs_firstc_len
);
2883 ret
[len
= ifs_firstc_len
] = '\0';
2886 ret
[0] = ifs_firstc
;
2888 len
= ret
[0] ? 0 : 1;
2897 /* Return a single string of all the words present in LIST, obeying the
2898 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
2899 expansion [of $*] appears within a double quoted string, it expands
2900 to a single field with the value of each parameter separated by the
2901 first character of the IFS variable, or by a <space> if IFS is unset." */
2902 /* Posix interpretation 888 changes this when IFS is null by specifying
2903 that when unquoted, this expands to separate arguments */
2905 string_list_dollar_star (list
, quoted
, flags
)
2910 #if defined (HANDLE_MULTIBYTE)
2911 # if defined (__GNUC__)
2912 char sep
[MB_CUR_MAX
+ 1];
2920 #if defined (HANDLE_MULTIBYTE)
2921 # if !defined (__GNUC__)
2922 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2923 # endif /* !__GNUC__ */
2924 if (ifs_firstc_len
== 1)
2926 sep
[0] = ifs_firstc
[0];
2931 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
2932 sep
[ifs_firstc_len
] = '\0';
2935 sep
[0] = ifs_firstc
;
2939 ret
= string_list_internal (list
, sep
);
2940 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2946 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2947 is non-zero, the $@ appears within double quotes, and we should quote
2948 the list before converting it into a string. If IFS is unset, and the
2949 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2950 in the words in the list, because the default value of $IFS is
2951 <space><tab><newline>, IFS characters in the words in the list should
2952 also be split. If IFS is null, and the word is not quoted, we need
2953 to quote the words in the list to preserve the positional parameters
2955 Valid values for the FLAGS argument are the PF_ flags in command.h,
2956 the only one we care about is PF_ASSIGNRHS. $@ is supposed to expand
2957 to the positional parameters separated by spaces no matter what IFS is
2958 set to if in a context where word splitting is not performed. The only
2959 one that we didn't handle before is assignment statement arguments to
2960 declaration builtins like `declare'. */
2962 string_list_dollar_at (list
, quoted
, flags
)
2968 #if defined (HANDLE_MULTIBYTE)
2969 # if defined (__GNUC__)
2970 char sep
[MB_CUR_MAX
+ 1];
2973 # endif /* !__GNUC__ */
2979 /* XXX this could just be ifs = ifs_value; */
2980 ifs
= ifs_var
? value_cell (ifs_var
) : (char *)0;
2982 #if defined (HANDLE_MULTIBYTE)
2983 # if !defined (__GNUC__)
2984 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2985 # endif /* !__GNUC__ */
2986 /* XXX - testing PF_ASSIGNRHS to make sure positional parameters are
2987 separated with a space even when word splitting will not occur. */
2988 if (flags
& PF_ASSIGNRHS
)
2993 else if (ifs
&& *ifs
)
2995 if (ifs_firstc_len
== 1)
2997 sep
[0] = ifs_firstc
[0];
3002 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
3003 sep
[ifs_firstc_len
] = '\0';
3011 #else /* !HANDLE_MULTIBYTE */
3012 /* XXX - PF_ASSIGNRHS means no word splitting, so we want positional
3013 parameters separated by a space. */
3014 sep
[0] = ((flags
& PF_ASSIGNRHS
) || ifs
== 0 || *ifs
== 0) ? ' ' : *ifs
;
3016 #endif /* !HANDLE_MULTIBYTE */
3018 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
3019 it now that quote_escapes quotes spaces */
3020 tlist
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
3022 : list_quote_escapes (list
);
3024 ret
= string_list_internal (tlist
, sep
);
3025 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
3031 /* Turn the positional parameters into a string, understanding quoting and
3032 the various subtleties of using the first character of $IFS as the
3033 separator. Calls string_list_dollar_at, string_list_dollar_star, and
3034 string_list as appropriate. */
3035 /* This needs to fully understand the additional contexts where word
3036 splitting does not occur (W_ASSIGNRHS, etc.) */
3038 string_list_pos_params (pchar
, list
, quoted
, pflags
)
3046 if (pchar
== '*' && (quoted
& Q_DOUBLE_QUOTES
))
3048 tlist
= quote_list (list
);
3049 word_list_remove_quoted_nulls (tlist
);
3050 ret
= string_list_dollar_star (tlist
, 0, 0);
3052 else if (pchar
== '*' && (quoted
& Q_HERE_DOCUMENT
))
3054 tlist
= quote_list (list
);
3055 word_list_remove_quoted_nulls (tlist
);
3056 ret
= string_list (tlist
);
3058 else if (pchar
== '*' && quoted
== 0 && ifs_is_null
) /* XXX */
3059 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3060 else if (pchar
== '*' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
)) /* XXX */
3061 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3062 else if (pchar
== '*')
3064 /* Even when unquoted, string_list_dollar_star does the right thing
3065 making sure that the first character of $IFS is used as the
3067 ret
= string_list_dollar_star (list
, quoted
, 0);
3069 else if (pchar
== '@' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
3070 /* We use string_list_dollar_at, but only if the string is quoted, since
3071 that quotes the escapes if it's not, which we don't want. We could
3072 use string_list (the old code did), but that doesn't do the right
3073 thing if the first character of $IFS is not a space. We use
3074 string_list_dollar_star if the string is unquoted so we make sure that
3075 the elements of $@ are separated by the first character of $IFS for
3077 ret
= string_list_dollar_at (list
, quoted
, 0);
3078 else if (pchar
== '@' && quoted
== 0 && ifs_is_null
) /* XXX */
3079 ret
= string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3080 else if (pchar
== '@' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
3081 ret
= string_list_dollar_at (list
, quoted
, pflags
); /* Posix interp 888 */
3082 else if (pchar
== '@')
3083 ret
= string_list_dollar_star (list
, quoted
, 0);
3085 ret
= string_list ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? quote_list (list
) : list
);
3090 /* Return the list of words present in STRING. Separate the string into
3091 words at any of the characters found in SEPARATORS. If QUOTED is
3092 non-zero then word in the list will have its quoted flag set, otherwise
3093 the quoted flag is left as make_word () deemed fit.
3095 This obeys the P1003.2 word splitting semantics. If `separators' is
3096 exactly <space><tab><newline>, then the splitting algorithm is that of
3097 the Bourne shell, which treats any sequence of characters from `separators'
3098 as a delimiter. If IFS is unset, which results in `separators' being set
3099 to "", no splitting occurs. If separators has some other value, the
3100 following rules are applied (`IFS white space' means zero or more
3101 occurrences of <space>, <tab>, or <newline>, as long as those characters
3102 are in `separators'):
3104 1) IFS white space is ignored at the start and the end of the
3106 2) Each occurrence of a character in `separators' that is not
3107 IFS white space, along with any adjacent occurrences of
3108 IFS white space delimits a field.
3109 3) Any nonzero-length sequence of IFS white space delimits a field.
3112 /* BEWARE! list_string strips null arguments. Don't call it twice and
3113 expect to have "" preserved! */
3115 /* This performs word splitting and quoted null character removal on
3118 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
3119 : (c) == (separators)[0]) \
3122 /* member of the space character class in the current locale */
3123 #define ifs_whitespace(c) ISSPACE(c)
3125 /* "adjacent IFS white space" */
3126 #define ifs_whitesep(c) ((sh_style_split || separators == 0) ? spctabnl (c) \
3127 : ifs_whitespace (c))
3130 list_string (string
, separators
, quoted
)
3131 register char *string
, *separators
;
3136 char *current_word
, *s
;
3137 int sindex
, sh_style_split
, whitesep
, xflags
, free_word
;
3140 if (!string
|| !*string
)
3141 return ((WORD_LIST
*)NULL
);
3143 sh_style_split
= separators
&& separators
[0] == ' ' &&
3144 separators
[1] == '\t' &&
3145 separators
[2] == '\n' &&
3146 separators
[3] == '\0';
3147 for (xflags
= 0, s
= ifs_value
; s
&& *s
; s
++)
3149 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
3150 else if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
3154 /* Remove sequences of whitespace at the beginning of STRING, as
3155 long as those characters appear in IFS. Do not do this if
3156 STRING is quoted or if there are no separator characters. We use the
3157 Posix definition of whitespace as a member of the space character
3158 class in the current locale. */
3160 if (!quoted
|| !separators
|| !*separators
)
3162 /* issep() requires that separators be non-null, and always returns 0 if
3163 separator is the empty string, so don't bother if we get an empty string
3164 for separators. We already returned NULL above if STRING is empty. */
3165 if (!quoted
&& separators
&& *separators
)
3168 for (s
= string
; *s
&& issep (*s
) && ifs_whitespace (*s
); s
++);
3171 return ((WORD_LIST
*)NULL
);
3176 /* OK, now STRING points to a word that does not begin with white space.
3177 The splitting algorithm is:
3178 extract a word, stopping at a separator
3179 skip sequences of whitespace characters as long as they are separators
3180 This obeys the field splitting rules in Posix.2. */
3181 slen
= STRLEN (string
);
3182 for (result
= (WORD_LIST
*)NULL
, sindex
= 0; string
[sindex
]; )
3184 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3185 possible, but need it in string_extract_verbatim for bounds checking */
3186 current_word
= string_extract_verbatim (string
, slen
, &sindex
, separators
, xflags
);
3187 if (current_word
== 0)
3190 free_word
= 1; /* If non-zero, we free current_word */
3192 /* If we have a quoted empty string, add a quoted null argument. We
3193 want to preserve the quoted null character iff this is a quoted
3194 empty string; otherwise the quoted null characters are removed
3196 if (QUOTED_NULL (current_word
))
3198 t
= alloc_word_desc ();
3199 t
->word
= make_quoted_char ('\0');
3200 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
3201 result
= make_word_list (t
, result
);
3203 else if (current_word
[0] != '\0')
3205 /* If we have something, then add it regardless. However,
3206 perform quoted null character removal on the current word. */
3207 remove_quoted_nulls (current_word
);
3209 /* We don't want to set the word flags based on the string contents
3210 here -- that's mostly for the parser -- so we just allocate a
3211 WORD_DESC *, assign current_word (noting that we don't want to
3212 free it), and skip all of make_word. */
3213 t
= alloc_word_desc ();
3214 t
->word
= current_word
;
3215 result
= make_word_list (t
, result
);
3217 result
->word
->flags
&= ~W_HASQUOTEDNULL
; /* just to be sure */
3218 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
3219 result
->word
->flags
|= W_QUOTED
;
3220 /* If removing quoted null characters leaves an empty word, note
3221 that we saw this for the caller to act on. */
3222 if (current_word
== 0 || current_word
[0] == '\0')
3223 result
->word
->flags
|= W_SAWQUOTEDNULL
;
3226 /* If we're not doing sequences of separators in the traditional
3227 Bourne shell style, then add a quoted null argument. */
3228 else if (!sh_style_split
&& !ifs_whitespace (string
[sindex
]))
3230 t
= alloc_word_desc ();
3231 t
->word
= make_quoted_char ('\0');
3232 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
3233 result
= make_word_list (t
, result
);
3237 free (current_word
);
3239 /* Note whether or not the separator is IFS whitespace, used later. */
3240 whitesep
= string
[sindex
] && ifs_whitesep (string
[sindex
]);
3242 /* Move past the current separator character. */
3246 ADVANCE_CHAR (string
, slen
, sindex
);
3249 /* Now skip sequences of whitespace characters if they are
3250 in the list of separators. */
3251 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && issep (string
[sindex
]))
3254 /* If the first separator was IFS whitespace and the current character
3255 is a non-whitespace IFS character, it should be part of the current
3256 field delimiter, not a separate delimiter that would result in an
3257 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
3258 if (string
[sindex
] && whitesep
&& issep (string
[sindex
]) && !ifs_whitesep (string
[sindex
]))
3261 /* An IFS character that is not IFS white space, along with any
3262 adjacent IFS white space, shall delimit a field. (SUSv3) */
3263 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && isifs (string
[sindex
]))
3267 return (REVERSE_LIST (result
, WORD_LIST
*));
3270 /* Parse a single word from STRING, using SEPARATORS to separate fields.
3271 ENDPTR is set to the first character after the word. This is used by
3274 This is never called with SEPARATORS != $IFS, and takes advantage of that.
3276 XXX - this function is very similar to list_string; they should be
3279 /* character is in $IFS */
3280 #define islocalsep(c) (local_cmap[(unsigned char)(c)] != 0)
3283 get_word_from_string (stringp
, separators
, endptr
)
3284 char **stringp
, *separators
, **endptr
;
3288 int sindex
, sh_style_split
, whitesep
, xflags
;
3289 unsigned char local_cmap
[UCHAR_MAX
+1]; /* really only need single-byte chars here */
3292 if (!stringp
|| !*stringp
|| !**stringp
)
3293 return ((char *)NULL
);
3295 sh_style_split
= separators
&& separators
[0] == ' ' &&
3296 separators
[1] == '\t' &&
3297 separators
[2] == '\n' &&
3298 separators
[3] == '\0';
3299 memset (local_cmap
, '\0', sizeof (local_cmap
));
3300 for (xflags
= 0, s
= separators
; s
&& *s
; s
++)
3302 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
3303 if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
3304 local_cmap
[(unsigned char)*s
] = 1; /* local charmap of separators */
3310 /* Remove sequences of whitespace at the beginning of STRING, as
3311 long as those characters appear in SEPARATORS. This happens if
3312 SEPARATORS == $' \t\n' or if IFS is unset. */
3313 if (sh_style_split
|| separators
== 0)
3314 for (; *s
&& spctabnl (*s
) && islocalsep (*s
); s
++);
3316 for (; *s
&& ifs_whitespace (*s
) && islocalsep (*s
); s
++);
3318 /* If the string is nothing but whitespace, update it and return. */
3324 return ((char *)NULL
);
3327 /* OK, S points to a word that does not begin with white space.
3328 Now extract a word, stopping at a separator, save a pointer to
3329 the first character after the word, then skip sequences of spc,
3330 tab, or nl as long as they are separators.
3332 This obeys the field splitting rules in Posix.2. */
3334 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3335 possible, but need it in string_extract_verbatim for bounds checking */
3337 current_word
= string_extract_verbatim (s
, slen
, &sindex
, separators
, xflags
);
3339 /* Set ENDPTR to the first character after the end of the word. */
3341 *endptr
= s
+ sindex
;
3343 /* Note whether or not the separator is IFS whitespace, used later. */
3344 whitesep
= s
[sindex
] && ifs_whitesep (s
[sindex
]);
3346 /* Move past the current separator character. */
3350 ADVANCE_CHAR (s
, slen
, sindex
);
3353 /* Now skip sequences of space, tab, or newline characters if they are
3354 in the list of separators. */
3355 while (s
[sindex
] && spctabnl (s
[sindex
]) && islocalsep (s
[sindex
]))
3358 /* If the first separator was IFS whitespace and the current character is
3359 a non-whitespace IFS character, it should be part of the current field
3360 delimiter, not a separate delimiter that would result in an empty field.
3361 Look at POSIX.2, 3.6.5, (3)(b). */
3362 if (s
[sindex
] && whitesep
&& islocalsep (s
[sindex
]) && !ifs_whitesep (s
[sindex
]))
3365 /* An IFS character that is not IFS white space, along with any adjacent
3366 IFS white space, shall delimit a field. */
3367 while (s
[sindex
] && ifs_whitesep (s
[sindex
]) && islocalsep(s
[sindex
]))
3371 /* Update STRING to point to the next field. */
3372 *stringp
= s
+ sindex
;
3373 return (current_word
);
3376 /* Remove IFS white space at the end of STRING. Start at the end
3377 of the string and walk backwards until the beginning of the string
3378 or we find a character that's not IFS white space and not CTLESC.
3379 Only let CTLESC escape a white space character if SAW_ESCAPE is
3382 strip_trailing_ifs_whitespace (string
, separators
, saw_escape
)
3383 char *string
, *separators
;
3388 s
= string
+ STRLEN (string
) - 1;
3389 while (s
> string
&& ((spctabnl (*s
) && isifs (*s
)) ||
3390 (saw_escape
&& *s
== CTLESC
&& spctabnl (s
[1]))))
3398 /* Split STRING into words at whitespace. Obeys shell-style quoting with
3399 backslashes, single and double quotes. */
3401 list_string_with_quotes (string
)
3407 int c
, i
, tokstart
, len
;
3409 for (s
= string
; s
&& *s
&& spctabnl (*s
); s
++)
3411 if (s
== 0 || *s
== 0)
3412 return ((WORD_LIST
*)NULL
);
3416 list
= (WORD_LIST
*)NULL
;
3427 i
= skip_single_quoted (s
, s_len
, ++i
, 0);
3429 i
= skip_double_quoted (s
, s_len
, ++i
, 0);
3430 else if (c
== 0 || spctabnl (c
))
3432 /* We have found the end of a token. Make a word out of it and
3433 add it to the word list. */
3434 token
= substring (s
, tokstart
, i
);
3435 list
= add_string_to_list (token
, list
);
3437 while (spctabnl (s
[i
]))
3445 i
++; /* normal character */
3447 return (REVERSE_LIST (list
, WORD_LIST
*));
3451 /********************************************************/
3453 /* Functions to perform assignment statements */
3455 /********************************************************/
3457 #if defined (ARRAY_VARS)
3459 do_compound_assignment (name
, value
, flags
)
3464 int mklocal
, mkassoc
, mkglobal
, chklocal
;
3466 char *newname
; /* used for local nameref references */
3468 mklocal
= flags
& ASS_MKLOCAL
;
3469 mkassoc
= flags
& ASS_MKASSOC
;
3470 mkglobal
= flags
& ASS_MKGLOBAL
;
3471 chklocal
= flags
& ASS_CHKLOCAL
;
3473 if (mklocal
&& variable_context
)
3475 v
= find_variable (name
); /* follows namerefs */
3476 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : v
->name
;
3477 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3480 err_readonly (name
);
3481 return (v
); /* XXX */
3483 list
= expand_compound_array_assignment (v
, value
, flags
);
3485 v
= make_local_assoc_variable (newname
, 0);
3486 else if (v
== 0 || (array_p (v
) == 0 && assoc_p (v
) == 0) || v
->context
!= variable_context
)
3487 v
= make_local_array_variable (newname
, 0);
3489 assign_compound_array_list (v
, list
, flags
);
3491 dispose_words (list
);
3493 /* In a function but forcing assignment in global context. CHKLOCAL means to
3494 check for an existing local variable first. */
3495 else if (mkglobal
&& variable_context
)
3497 v
= chklocal
? find_variable (name
) : 0;
3498 if (v
&& (local_p (v
) == 0 || v
->context
!= variable_context
))
3501 v
= find_global_variable (name
);
3502 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3505 err_readonly (name
);
3506 return (v
); /* XXX */
3509 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : name
;
3510 list
= expand_compound_array_assignment (v
, value
, flags
);
3511 if (v
== 0 && mkassoc
)
3512 v
= make_new_assoc_variable (newname
);
3513 else if (v
&& mkassoc
&& assoc_p (v
) == 0)
3514 v
= convert_var_to_assoc (v
);
3516 v
= make_new_array_variable (newname
);
3517 else if (v
&& mkassoc
== 0 && array_p (v
) == 0)
3518 v
= convert_var_to_array (v
);
3520 assign_compound_array_list (v
, list
, flags
);
3522 dispose_words (list
);
3526 v
= assign_array_from_string (name
, value
, flags
);
3527 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3530 err_readonly (name
);
3531 return (v
); /* XXX */
3539 /* Given STRING, an assignment string, get the value of the right side
3540 of the `=', and bind it to the left side. If EXPAND is true, then
3541 perform parameter expansion, command substitution, and arithmetic
3542 expansion on the right-hand side. Perform tilde expansion in any
3543 case. Do not perform word splitting on the result of expansion. */
3545 do_assignment_internal (word
, expand
)
3546 const WORD_DESC
*word
;
3549 int offset
, appendop
, assign_list
, aflags
, retval
;
3550 char *name
, *value
, *temp
;
3552 #if defined (ARRAY_VARS)
3558 if (word
== 0 || word
->word
== 0)
3561 appendop
= assign_list
= aflags
= 0;
3562 string
= word
->word
;
3563 offset
= assignment (string
, 0);
3564 name
= savestring (string
);
3565 value
= (char *)NULL
;
3567 if (name
[offset
] == '=')
3569 if (name
[offset
- 1] == '+')
3572 name
[offset
- 1] = '\0';
3575 name
[offset
] = 0; /* might need this set later */
3576 temp
= name
+ offset
+ 1;
3578 #if defined (ARRAY_VARS)
3579 if (expand
&& (word
->flags
& W_COMPASSIGN
))
3581 assign_list
= ni
= 1;
3582 value
= extract_array_assignment_list (temp
, &ni
);
3586 if (expand
&& temp
[0])
3587 value
= expand_string_if_necessary (temp
, 0, expand_string_assignment
);
3589 value
= savestring (temp
);
3594 value
= (char *)xmalloc (1);
3598 if (echo_command_at_execute
)
3601 name
[offset
- 1] = '+';
3602 xtrace_print_assignment (name
, value
, assign_list
, 1);
3604 name
[offset
- 1] = '\0';
3607 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
3610 aflags
|= ASS_APPEND
;
3612 #if defined (ARRAY_VARS)
3613 if (t
= mbschr (name
, LBRACK
))
3617 report_error (_("%s: cannot assign list to array member"), name
);
3620 aflags
|= ASS_ALLOWALLSUB
; /* allow a[@]=value for existing associative arrays */
3621 entry
= assign_array_element (name
, value
, aflags
, (array_eltstate_t
*)0);
3625 else if (assign_list
)
3627 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_CHKLOCAL
))
3628 aflags
|= ASS_CHKLOCAL
;
3629 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
) == 0)
3630 aflags
|= ASS_MKLOCAL
;
3631 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
))
3632 aflags
|= ASS_MKGLOBAL
;
3633 if (word
->flags
& W_ASSIGNASSOC
)
3634 aflags
|= ASS_MKASSOC
;
3635 entry
= do_compound_assignment (name
, value
, aflags
);
3638 #endif /* ARRAY_VARS */
3639 entry
= bind_variable (name
, value
, aflags
);
3642 stupidly_hack_special_variables (entry
->name
); /* might be a nameref */
3644 stupidly_hack_special_variables (name
);
3646 /* Return 1 if the assignment seems to have been performed correctly. */
3647 if (entry
== 0 || readonly_p (entry
))
3648 retval
= 0; /* assignment failure */
3649 else if (noassign_p (entry
))
3651 set_exit_status (EXECUTION_FAILURE
);
3652 retval
= 1; /* error status, but not assignment failure */
3657 if (entry
&& retval
!= 0 && noassign_p (entry
) == 0)
3658 VUNSETATTR (entry
, att_invisible
);
3660 ASSIGN_RETURN (retval
);
3663 /* Perform the assignment statement in STRING, and expand the
3664 right side by doing tilde, command and parameter expansion. */
3666 do_assignment (string
)
3671 td
.flags
= W_ASSIGNMENT
;
3674 return do_assignment_internal (&td
, 1);
3678 do_word_assignment (word
, flags
)
3682 return do_assignment_internal (word
, 1);
3685 /* Given STRING, an assignment string, get the value of the right side
3686 of the `=', and bind it to the left side. Do not perform any word
3687 expansions on the right hand side. */
3689 do_assignment_no_expand (string
)
3694 td
.flags
= W_ASSIGNMENT
;
3697 return (do_assignment_internal (&td
, 0));
3700 /***************************************************
3702 * Functions to manage the positional parameters *
3704 ***************************************************/
3706 /* Return the word list that corresponds to `$*'. */
3708 list_rest_of_args ()
3710 register WORD_LIST
*list
, *args
;
3713 /* Break out of the loop as soon as one of the dollar variables is null. */
3714 for (i
= 1, list
= (WORD_LIST
*)NULL
; i
< 10 && dollar_vars
[i
]; i
++)
3715 list
= make_word_list (make_bare_word (dollar_vars
[i
]), list
);
3717 for (args
= rest_of_args
; args
; args
= args
->next
)
3718 list
= make_word_list (make_bare_word (args
->word
->word
), list
);
3720 return (REVERSE_LIST (list
, WORD_LIST
*));
3723 /* Return the value of a positional parameter. This handles values > 10. */
3725 get_dollar_var_value (ind
)
3732 temp
= dollar_vars
[ind
] ? savestring (dollar_vars
[ind
]) : (char *)NULL
;
3733 else /* We want something like ${11} */
3736 for (p
= rest_of_args
; p
&& ind
--; p
= p
->next
)
3738 temp
= p
? savestring (p
->word
->word
) : (char *)NULL
;
3743 /* Make a single large string out of the dollar digit variables,
3744 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
3745 case of "$*" with respect to IFS. */
3747 string_rest_of_args (dollar_star
)
3750 register WORD_LIST
*list
;
3753 list
= list_rest_of_args ();
3754 string
= dollar_star
? string_list_dollar_star (list
, 0, 0) : string_list (list
);
3755 dispose_words (list
);
3759 /* Return a string containing the positional parameters from START to
3760 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3761 which only makes a difference if QUOTED is non-zero. If QUOTED includes
3762 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
3763 no quoting chars are added. */
3765 pos_params (string
, start
, end
, quoted
, pflags
)
3767 int start
, end
, quoted
, pflags
;
3769 WORD_LIST
*save
, *params
, *h
, *t
;
3773 /* see if we can short-circuit. if start == end, we want 0 parameters. */
3775 return ((char *)NULL
);
3777 save
= params
= list_rest_of_args ();
3778 if (save
== 0 && start
> 0)
3779 return ((char *)NULL
);
3781 if (start
== 0) /* handle ${@:0[:x]} specially */
3783 t
= make_word_list (make_word (dollar_vars
[0]), params
);
3787 for (i
= start
? 1 : 0; params
&& i
< start
; i
++)
3788 params
= params
->next
;
3791 dispose_words (save
);
3792 return ((char *)NULL
);
3794 for (h
= t
= params
; params
&& i
< end
; i
++)
3797 params
= params
->next
;
3799 t
->next
= (WORD_LIST
*)NULL
;
3801 ret
= string_list_pos_params (string
[0], h
, quoted
, pflags
);
3806 dispose_words (save
);
3810 /******************************************************************/
3812 /* Functions to expand strings to strings or WORD_LISTs */
3814 /******************************************************************/
3816 #if defined (PROCESS_SUBSTITUTION)
3817 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
3819 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3822 /* If there are any characters in STRING that require full expansion,
3823 then call FUNC to expand STRING; otherwise just perform quote
3824 removal if necessary. This returns a new string. */
3826 expand_string_if_necessary (string
, quoted
, func
)
3837 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3838 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
3842 if (EXP_CHAR (string
[i
]))
3844 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
3846 ADVANCE_CHAR (string
, slen
, i
);
3851 list
= (*func
) (string
, quoted
);
3854 ret
= string_list (list
);
3855 dispose_words (list
);
3860 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
3861 ret
= string_quote_removal (string
, quoted
);
3863 ret
= savestring (string
);
3868 static inline char *
3869 expand_string_to_string_internal (string
, quoted
, func
)
3877 if (string
== 0 || *string
== '\0')
3878 return ((char *)NULL
);
3880 list
= (*func
) (string
, quoted
);
3883 ret
= string_list (list
);
3884 dispose_words (list
);
3893 expand_string_to_string (string
, quoted
)
3897 return (expand_string_to_string_internal (string
, quoted
, expand_string
));
3901 expand_string_unsplit_to_string (string
, quoted
)
3905 return (expand_string_to_string_internal (string
, quoted
, expand_string_unsplit
));
3909 expand_assignment_string_to_string (string
, quoted
)
3913 return (expand_string_to_string_internal (string
, quoted
, expand_string_assignment
));
3916 /* Kind of like a combination of dequote_string and quote_string_for_globbing;
3917 try to remove CTLESC quoting characters and convert CTLESC escaping a `&'
3918 or a backslash into a backslash. The output of this function must eventually
3919 be processed by strcreplace(). */
3921 quote_string_for_repl (string
, flags
)
3927 const char *s
, *send
;
3930 slen
= strlen (string
);
3931 send
= string
+ slen
;
3933 result
= (char *)xmalloc (slen
* 2 + 1);
3935 if (string
[0] == CTLESC
&& string
[1] == 0)
3942 /* This is awkward. We want to translate CTLESC-\ to \\ if we will
3943 eventually send this string through strcreplace(), which we will do
3944 only if shouldexp_replacement() determines that there is something
3945 to replace. We can either make sure to escape backslashes here and
3946 have shouldexp_replacement() signal that we should send the string to
3947 strcreplace() if it sees an escaped backslash, or we can scan the
3948 string before copying it and turn CTLESC-\ into \\ only if we encounter
3949 a CTLESC-& or a &. This does the former and changes shouldexp_replacement().
3950 If we double the backslashes here, we'll get doubled backslashes in any
3951 result that doesn't get passed to strcreplace(). */
3953 for (s
= string
, t
= result
; *s
; )
3955 /* This function's result has to be processed by strcreplace() */
3956 if (*s
== CTLESC
&& (s
[1] == '&' || s
[1] == '\\'))
3970 COPY_CHAR_P (t
, s
, send
);
3977 /* This does not perform word splitting on the WORD_LIST it returns and
3978 it treats $* as if it were quoted. It dequotes the WORD_LIST, adds
3979 backslash escapes before CTLESC-quoted backslash and `& if
3980 patsub_replacement is enabled. */
3982 expand_string_for_patsub (string
, quoted
)
3989 if (string
== 0 || *string
== '\0')
3990 return (char *)NULL
;
3992 value
= expand_string_for_pat (string
, quoted
, (int *)0, (int *)0);
3994 if (value
&& value
->word
)
3996 remove_quoted_nulls (value
->word
->word
); /* XXX */
3997 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4002 t
= (value
->next
) ? string_list (value
) : value
->word
->word
;
4003 ret
= quote_string_for_repl (t
, quoted
);
4004 if (t
!= value
->word
->word
)
4006 dispose_words (value
);
4015 expand_arith_string (string
, quoted
)
4020 WORD_LIST
*list
, *tlist
;
4026 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
4027 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
4031 if (EXP_CHAR (string
[i
]))
4033 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
4034 saw_quote
= string
[i
];
4035 ADVANCE_CHAR (string
, slen
, i
);
4040 /* This is expanded version of expand_string_internal as it's called by
4041 expand_string_leave_quoted */
4042 td
.flags
= W_NOPROCSUB
|W_NOTILDE
; /* don't want process substitution or tilde expansion */
4043 #if 0 /* TAG: bash-5.2 */
4044 if (quoted
& Q_ARRAYSUB
)
4045 td
.flags
|= W_NOCOMSUB
;
4047 td
.word
= savestring (string
);
4048 list
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4049 /* This takes care of the calls from expand_string_leave_quoted and
4053 tlist
= word_list_split (list
);
4054 dispose_words (list
);
4057 dequote_list (list
);
4059 /* This comes from expand_string_if_necessary */
4062 ret
= string_list (list
);
4063 dispose_words (list
);
4069 else if (saw_quote
&& (quoted
& Q_ARITH
))
4070 ret
= string_quote_removal (string
, quoted
);
4071 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
4072 ret
= string_quote_removal (string
, quoted
);
4074 ret
= savestring (string
);
4079 #if defined (COND_COMMAND)
4080 /* Just remove backslashes in STRING. Returns a new string. */
4082 remove_backslashes (string
)
4087 r
= ret
= (char *)xmalloc (strlen (string
) + 1);
4088 for (s
= string
; s
&& *s
; )
4100 /* This needs better error handling. */
4101 /* Expand W for use as an argument to a unary or binary operator in a
4102 [[...]] expression. If SPECIAL is 1, this is the rhs argument
4103 to the != or == operator, and should be treated as a pattern. In
4104 this case, we quote the string specially for the globbing code. If
4105 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
4106 be quoted appropriately for regcomp/regexec. If SPECIAL is 3, this is
4107 an array subscript and should be quoted after expansion so it's only
4108 expanded once (Q_ARITH). The caller is responsible
4109 for removing the backslashes if the unquoted word is needed later. In
4110 any case, since we don't perform word splitting, we need to do quoted
4111 null character removal. */
4113 cond_expand_word (w
, special
)
4121 if (w
->word
== 0 || w
->word
[0] == '\0')
4122 return ((char *)NULL
);
4124 expand_no_split_dollar_star
= 1;
4125 w
->flags
|= W_NOSPLIT2
;
4126 qflags
= (special
== 3) ? Q_ARITH
: 0;
4127 l
= call_expand_word_internal (w
, qflags
, 0, (int *)0, (int *)0);
4128 expand_no_split_dollar_star
= 0;
4131 if (special
== 0) /* LHS */
4134 word_list_remove_quoted_nulls (l
);
4136 r
= string_list (l
);
4138 else if (special
== 3) /* arithmetic expression, Q_ARITH */
4141 word_list_remove_quoted_nulls (l
); /* for now */
4143 r
= string_list (l
);
4147 /* Need to figure out whether or not we should call dequote_escapes
4148 or a new dequote_ctlnul function here, and under what
4150 qflags
= QGLOB_CVTNULL
|QGLOB_CTLESC
;
4152 qflags
|= QGLOB_REGEXP
;
4153 word_list_remove_quoted_nulls (l
);
4154 p
= string_list (l
);
4155 r
= quote_string_for_globbing (p
, qflags
);
4167 /* Expand $'...' and $"..." in a string for code paths that don't do it. The
4168 FLAGS argument is 1 if this function should treat CTLESC as a quote
4169 character (e.g., for here-documents) or not (e.g., for shell_expand_line). */
4171 expand_string_dollar_quote (string
, flags
)
4175 size_t slen
, retind
, retsize
;
4176 int sindex
, c
, translen
, peekc
, news
;
4177 char *ret
, *trans
, *send
, *t
;
4180 slen
= strlen (string
);
4181 send
= string
+ slen
;
4185 ret
= xmalloc (retsize
);
4188 while (c
= string
[sindex
])
4193 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 1, retsize
, 64);
4194 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4198 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 2, retsize
, 64);
4199 ret
[retind
++] = string
[sindex
++];
4202 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4208 news
= skip_single_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4210 news
= skip_double_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4211 translen
= news
- sindex
- 1;
4212 RESIZE_MALLOCED_BUFFER (ret
, retind
, translen
+ 3, retsize
, 64);
4216 strncpy (ret
+ retind
, string
+ sindex
, translen
);
4219 if (news
> sindex
&& string
[news
- 1] == c
)
4225 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 2, retsize
, 64);
4227 ret
[retind
++] = string
[sindex
++];
4229 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4233 peekc
= string
[++sindex
];
4234 #if defined (TRANSLATABLE_STRINGS)
4235 if (peekc
!= '\'' && peekc
!= '"')
4240 RESIZE_MALLOCED_BUFFER (ret
, retind
, 2, retsize
, 16);
4244 if (string
[sindex
+ 1] == '\0') /* don't bother */
4246 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4248 ret
[retind
++] = peekc
;
4254 /* SX_COMPLETE is the equivalent of ALLOWESC here */
4255 /* We overload SX_COMPLETE below */
4256 news
= skip_single_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4257 /* Check for unclosed string and don't bother if so */
4258 if (news
> sindex
&& string
[news
] == '\0' && string
[news
-1] != peekc
)
4260 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4262 ret
[retind
++] = peekc
;
4265 t
= substring (string
, sindex
, news
- 1);
4266 trans
= ansiexpand (t
, 0, news
-sindex
-1, &translen
);
4268 t
= sh_single_quote (trans
);
4271 #if defined (TRANSLATABLE_STRINGS)
4275 t
= string_extract_double_quoted (string
, &news
, SX_COMPLETE
);
4276 /* Check for unclosed string and don't bother if so */
4277 if (news
> sindex
&& string
[news
] == '\0' && string
[news
-1] != peekc
)
4279 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4281 ret
[retind
++] = peekc
;
4285 trans
= locale_expand (t
, 0, news
-sindex
, 0, &translen
);
4287 if (singlequote_translations
&&
4288 ((news
-sindex
-1) != translen
|| STREQN (t
, trans
, translen
) == 0))
4289 t
= sh_single_quote (trans
);
4291 t
= sh_mkdoublequoted (trans
, translen
, 0);
4294 #endif /* TRANSLATABLE_STRINGS */
4297 translen
= strlen (trans
);
4299 RESIZE_MALLOCED_BUFFER (ret
, retind
, translen
+ 1, retsize
, 128);
4300 strcpy (ret
+ retind
, trans
);
4311 /* Call expand_word_internal to expand W and handle error returns.
4312 A convenience function for functions that don't want to handle
4313 any errors or free any memory before aborting. */
4315 call_expand_word_internal (w
, q
, i
, c
, e
)
4321 result
= expand_word_internal (w
, q
, i
, c
, e
);
4322 if (result
== &expand_word_error
|| result
== &expand_word_fatal
)
4324 /* By convention, each time this error is returned, w->word has
4325 already been freed (it sometimes may not be in the fatal case,
4326 but that doesn't result in a memory leak because we're going
4327 to exit in most cases). */
4328 w
->word
= (char *)NULL
;
4329 last_command_exit_value
= EXECUTION_FAILURE
;
4330 exp_jump_to_top_level ((result
== &expand_word_error
) ? DISCARD
: FORCE_EOF
);
4338 /* Perform parameter expansion, command substitution, and arithmetic
4339 expansion on STRING, as if it were a word. Leave the result quoted.
4340 Since this does not perform word splitting, it leaves quoted nulls
4343 expand_string_internal (string
, quoted
)
4350 if (string
== 0 || *string
== 0)
4351 return ((WORD_LIST
*)NULL
);
4354 td
.word
= savestring (string
);
4356 tresult
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4362 /* Expand STRING by performing parameter expansion, command substitution,
4363 and arithmetic expansion. Dequote the resulting WORD_LIST before
4364 returning it, but do not perform word splitting. The call to
4365 remove_quoted_nulls () is in here because word splitting normally
4366 takes care of quote removal. */
4368 expand_string_unsplit (string
, quoted
)
4374 if (string
== 0 || *string
== '\0')
4375 return ((WORD_LIST
*)NULL
);
4377 expand_no_split_dollar_star
= 1;
4378 value
= expand_string_internal (string
, quoted
);
4379 expand_no_split_dollar_star
= 0;
4385 remove_quoted_nulls (value
->word
->word
); /* XXX */
4386 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4388 dequote_list (value
);
4393 /* Expand the rhs of an assignment statement */
4395 expand_string_assignment (string
, quoted
)
4402 if (string
== 0 || *string
== '\0')
4403 return ((WORD_LIST
*)NULL
);
4405 expand_no_split_dollar_star
= 1;
4408 /* Other shells (ksh93) do it this way, which affects how $@ is expanded
4409 in constructs like bar=${@#0} (preserves the spaces resulting from the
4410 expansion of $@ in a context where you don't do word splitting); Posix
4411 interp 888 makes the expansion of $@ in contexts where word splitting
4412 is not performed unspecified. */
4413 td
.flags
= W_ASSIGNRHS
|W_NOSPLIT2
; /* Posix interp 888 */
4415 td
.flags
= W_ASSIGNRHS
;
4417 td
.flags
|= (W_NOGLOB
|W_TILDEEXP
);
4418 td
.word
= savestring (string
);
4419 value
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4422 expand_no_split_dollar_star
= 0;
4428 remove_quoted_nulls (value
->word
->word
); /* XXX */
4429 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4431 dequote_list (value
);
4436 /* Expand one of the PS? prompt strings. This is a sort of combination of
4437 expand_string_unsplit and expand_string_internal, but returns the
4438 passed string when an error occurs. Might want to trap other calls
4439 to jump_to_top_level here so we don't endlessly loop. */
4441 expand_prompt_string (string
, quoted
, wflags
)
4449 if (string
== 0 || *string
== 0)
4450 return ((WORD_LIST
*)NULL
);
4453 td
.word
= savestring (string
);
4455 no_longjmp_on_fatal_error
= 1;
4456 value
= expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4457 no_longjmp_on_fatal_error
= 0;
4459 if (value
== &expand_word_error
|| value
== &expand_word_fatal
)
4461 value
= make_word_list (make_bare_word (string
), (WORD_LIST
*)NULL
);
4469 remove_quoted_nulls (value
->word
->word
); /* XXX */
4470 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4472 dequote_list (value
);
4477 /* Expand STRING just as if you were expanding a word, but do not dequote
4478 the resultant WORD_LIST. This is called only from within this file,
4479 and is used to correctly preserve quoted characters when expanding
4480 things like ${1+"$@"}. This does parameter expansion, command
4481 substitution, arithmetic expansion, and word splitting. */
4483 expand_string_leave_quoted (string
, quoted
)
4490 if (string
== 0 || *string
== '\0')
4491 return ((WORD_LIST
*)NULL
);
4493 tlist
= expand_string_internal (string
, quoted
);
4497 tresult
= word_list_split (tlist
);
4498 dispose_words (tlist
);
4501 return ((WORD_LIST
*)NULL
);
4504 /* This does not perform word splitting or dequote the WORD_LIST
4507 expand_string_for_rhs (string
, quoted
, op
, pflags
, dollar_at_p
, expanded_p
)
4509 int quoted
, op
, pflags
;
4510 int *dollar_at_p
, *expanded_p
;
4516 if (string
== 0 || *string
== '\0')
4517 return (WORD_LIST
*)NULL
;
4519 /* We want field splitting to be determined by what is going to be done with
4520 the entire ${parameterOPword} expansion, so we don't want to split the RHS
4521 we expand here. However, the expansion of $* is determined by whether we
4522 are going to eventually perform word splitting, so we want to set this
4523 depending on whether or not are are going to be splitting: if the expansion
4524 is quoted, if the OP is `=', or if IFS is set to the empty string, we
4525 are not going to be splitting, so we set expand_no_split_dollar_star to
4526 note this to callees.
4527 We pass through PF_ASSIGNRHS as W_ASSIGNRHS if this is on the RHS of an
4528 assignment statement. */
4529 /* The updated treatment of $* is the result of Posix interp 888 */
4530 /* This was further clarified on the austin-group list in March, 2017 and
4531 in Posix bug 1129 */
4532 old_nosplit
= expand_no_split_dollar_star
;
4533 expand_no_split_dollar_star
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || op
== '=' || ifs_is_null
== 0; /* XXX - was 1 */
4534 td
.flags
= W_EXPANDRHS
; /* expanding RHS of ${paramOPword} */
4535 td
.flags
|= W_NOSPLIT2
; /* no splitting, remove "" and '' */
4536 if (pflags
& PF_ASSIGNRHS
) /* pass through */
4537 td
.flags
|= W_ASSIGNRHS
;
4540 td
.flags
|= W_ASSIGNRHS
; /* expand b in ${a=b} like assignment */
4542 td
.flags
|= W_ASSIGNRHS
|W_NOASSNTILDE
; /* expand b in ${a=b} like assignment */
4544 td
.word
= savestring (string
);
4545 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
4546 expand_no_split_dollar_star
= old_nosplit
;
4552 /* This does not perform word splitting or dequote the WORD_LIST
4553 it returns and it treats $* as if it were quoted. */
4555 expand_string_for_pat (string
, quoted
, dollar_at_p
, expanded_p
)
4557 int quoted
, *dollar_at_p
, *expanded_p
;
4563 if (string
== 0 || *string
== '\0')
4564 return (WORD_LIST
*)NULL
;
4566 oexp
= expand_no_split_dollar_star
;
4567 expand_no_split_dollar_star
= 1;
4568 td
.flags
= W_NOSPLIT2
; /* no splitting, remove "" and '' */
4569 td
.word
= savestring (string
);
4570 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
4571 expand_no_split_dollar_star
= oexp
;
4577 /* Expand STRING just as if you were expanding a word. This also returns
4578 a list of words. Note that filename globbing is *NOT* done for word
4579 or string expansion, just when the shell is expanding a command. This
4580 does parameter expansion, command substitution, arithmetic expansion,
4581 and word splitting. Dequote the resultant WORD_LIST before returning. */
4583 expand_string (string
, quoted
)
4589 if (string
== 0 || *string
== '\0')
4590 return ((WORD_LIST
*)NULL
);
4592 result
= expand_string_leave_quoted (string
, quoted
);
4593 return (result
? dequote_list (result
) : result
);
4596 /*******************************************
4598 * Functions to expand WORD_DESCs *
4600 *******************************************/
4602 /* Expand WORD, performing word splitting on the result. This does
4603 parameter expansion, command substitution, arithmetic expansion,
4604 word splitting, and quote removal. */
4607 expand_word (word
, quoted
)
4611 WORD_LIST
*result
, *tresult
;
4613 tresult
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4614 result
= word_list_split (tresult
);
4615 dispose_words (tresult
);
4616 return (result
? dequote_list (result
) : result
);
4619 /* Expand WORD, but do not perform word splitting on the result. This
4620 does parameter expansion, command substitution, arithmetic expansion,
4621 and quote removal. */
4623 expand_word_unsplit (word
, quoted
)
4629 result
= expand_word_leave_quoted (word
, quoted
);
4630 return (result
? dequote_list (result
) : result
);
4633 /* Perform shell expansions on WORD, but do not perform word splitting or
4634 quote removal on the result. Virtually identical to expand_word_unsplit;
4635 could be combined if implementations don't diverge. */
4637 expand_word_leave_quoted (word
, quoted
)
4643 expand_no_split_dollar_star
= 1;
4645 word
->flags
|= W_NOSPLIT
;
4646 word
->flags
|= W_NOSPLIT2
;
4647 result
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4648 expand_no_split_dollar_star
= 0;
4653 /***************************************************
4655 * Functions to handle quoting chars *
4657 ***************************************************/
4661 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
4662 The parser passes CTLNUL as CTLESC CTLNUL. */
4664 /* Quote escape characters in string s, but no other characters. This is
4665 used to protect CTLESC and CTLNUL in variable values from the rest of
4666 the word expansion process after the variable is expanded (word splitting
4667 and filename generation). If IFS is null, we quote spaces as well, just
4668 in case we split on spaces later (in the case of unquoted $@, we will
4669 eventually attempt to split the entire word on spaces). Corresponding
4670 code exists in dequote_escapes. Even if we don't end up splitting on
4671 spaces, quoting spaces is not a problem. This should never be called on
4672 a string that is quoted with single or double quotes or part of a here
4673 document (effectively double-quoted).
4674 FLAGS says whether or not we are going to split the result. If we are not,
4675 and there is a CTLESC or CTLNUL in IFS, we need to quote CTLESC and CTLNUL,
4676 respectively, to prevent them from being removed as part of dequoting. */
4678 quote_escapes_internal (string
, flags
)
4682 const char *s
, *send
;
4685 int quote_spaces
, skip_ctlesc
, skip_ctlnul
, nosplit
;
4688 slen
= strlen (string
);
4689 send
= string
+ slen
;
4691 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4692 nosplit
= (flags
& PF_NOSPLIT2
);
4694 for (skip_ctlesc
= skip_ctlnul
= 0, s
= ifs_value
; s
&& *s
; s
++)
4696 skip_ctlesc
|= (nosplit
== 0 && *s
== CTLESC
);
4697 skip_ctlnul
|= (nosplit
== 0 && *s
== CTLNUL
);
4700 t
= result
= (char *)xmalloc ((slen
* 2) + 1);
4705 if ((skip_ctlesc
== 0 && *s
== CTLESC
) || (skip_ctlnul
== 0 && *s
== CTLNUL
) || (quote_spaces
&& *s
== ' '))
4707 COPY_CHAR_P (t
, s
, send
);
4715 quote_escapes (string
)
4718 return (quote_escapes_internal (string
, 0));
4725 return (quote_escapes_internal (string
, PF_NOSPLIT2
));
4729 list_quote_escapes (list
)
4732 register WORD_LIST
*w
;
4735 for (w
= list
; w
; w
= w
->next
)
4738 w
->word
->word
= quote_escapes (t
);
4744 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
4746 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
4747 This is necessary to make unquoted CTLESC and CTLNUL characters in the
4748 data stream pass through properly.
4750 We need to remove doubled CTLESC characters inside quoted strings before
4751 quoting the entire string, so we do not double the number of CTLESC
4754 Also used by parts of the pattern substitution code. */
4756 dequote_escapes (string
)
4759 const char *s
, *send
;
4768 slen
= strlen (string
);
4769 send
= string
+ slen
;
4771 t
= result
= (char *)xmalloc (slen
+ 1);
4773 if (strchr (string
, CTLESC
) == 0)
4774 return (strcpy (result
, string
));
4776 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4781 if (*s
== CTLESC
&& (s
[1] == CTLESC
|| s
[1] == CTLNUL
|| (quote_spaces
&& s
[1] == ' ')))
4787 COPY_CHAR_P (t
, s
, send
);
4794 #if defined (INCLUDE_UNUSED)
4796 list_dequote_escapes (list
)
4799 register WORD_LIST
*w
;
4802 for (w
= list
; w
; w
= w
->next
)
4805 w
->word
->word
= dequote_escapes (t
);
4812 /* Return a new string with the quoted representation of character C.
4813 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
4814 set in any resultant WORD_DESC where this value is the word. */
4816 make_quoted_char (c
)
4821 temp
= (char *)xmalloc (3);
4836 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
4837 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
4838 this value is the word. */
4840 quote_string (string
)
4845 char *result
, *send
;
4849 result
= (char *)xmalloc (2);
4857 slen
= strlen (string
);
4858 send
= string
+ slen
;
4860 result
= (char *)xmalloc ((slen
* 2) + 1);
4862 for (t
= result
; string
< send
; )
4865 COPY_CHAR_P (t
, string
, send
);
4872 /* De-quote quoted characters in STRING. */
4874 dequote_string (string
)
4877 register char *s
, *t
;
4879 char *result
, *send
;
4882 if (string
[0] == CTLESC
&& string
[1] == 0)
4883 internal_debug ("dequote_string: string with bare CTLESC");
4885 slen
= STRLEN (string
);
4887 t
= result
= (char *)xmalloc (slen
+ 1);
4889 if (QUOTED_NULL (string
))
4895 /* A string consisting of only a single CTLESC should pass through unchanged */
4896 if (string
[0] == CTLESC
&& string
[1] == 0)
4903 /* If no character in the string can be quoted, don't bother examining
4904 each character. Just return a copy of the string passed to us. */
4905 if (strchr (string
, CTLESC
) == NULL
)
4906 return (strcpy (result
, string
));
4908 send
= string
+ slen
;
4918 COPY_CHAR_P (t
, s
, send
);
4925 /* Quote the entire WORD_LIST list. */
4930 register WORD_LIST
*w
;
4933 for (w
= list
; w
; w
= w
->next
)
4936 w
->word
->word
= quote_string (t
);
4938 w
->word
->flags
|= W_HASQUOTEDNULL
; /* XXX - turn on W_HASQUOTEDNULL here? */
4939 w
->word
->flags
|= W_QUOTED
;
4951 s
= dequote_string (word
->word
);
4952 if (QUOTED_NULL (word
->word
))
4953 word
->flags
&= ~W_HASQUOTEDNULL
;
4960 /* De-quote quoted characters in each word in LIST. */
4966 register WORD_LIST
*tlist
;
4968 for (tlist
= list
; tlist
; tlist
= tlist
->next
)
4970 s
= dequote_string (tlist
->word
->word
);
4971 if (QUOTED_NULL (tlist
->word
->word
))
4972 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
4973 free (tlist
->word
->word
);
4974 tlist
->word
->word
= s
;
4979 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
4982 remove_quoted_escapes (string
)
4989 t
= dequote_escapes (string
);
4997 /* Remove quoted $IFS characters from STRING. Quoted IFS characters are
4998 added to protect them from word splitting, but we need to remove them
4999 if no word splitting takes place. This returns newly-allocated memory,
5000 so callers can use it to replace savestring(). */
5002 remove_quoted_ifs (string
)
5005 register size_t slen
;
5010 slen
= strlen (string
);
5011 send
= string
+ slen
;
5014 ret
= (char *)xmalloc (slen
+ 1);
5018 if (string
[i
] == CTLESC
)
5021 if (string
[i
] == 0 || isifs (string
[i
]) == 0)
5027 COPY_CHAR_I (ret
, j
, string
, send
, i
);
5035 remove_quoted_nulls (string
)
5038 register size_t slen
;
5039 register int i
, j
, prev_i
;
5042 if (strchr (string
, CTLNUL
) == 0) /* XXX */
5043 return string
; /* XXX */
5045 slen
= strlen (string
);
5050 if (string
[i
] == CTLESC
)
5052 /* Old code had j++, but we cannot assume that i == j at this
5053 point -- what if a CTLNUL has already been removed from the
5054 string? We don't want to drop the CTLESC or recopy characters
5055 that we've already copied down. */
5057 string
[j
++] = CTLESC
;
5061 else if (string
[i
] == CTLNUL
)
5068 ADVANCE_CHAR (string
, slen
, i
); /* COPY_CHAR_I? */
5071 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
5081 /* Perform quoted null character removal on each element of LIST.
5082 This modifies LIST. */
5084 word_list_remove_quoted_nulls (list
)
5087 register WORD_LIST
*t
;
5089 for (t
= list
; t
; t
= t
->next
)
5091 remove_quoted_nulls (t
->word
->word
);
5092 t
->word
->flags
&= ~W_HASQUOTEDNULL
;
5096 /* **************************************************************** */
5098 /* Functions for Matching and Removing Patterns */
5100 /* **************************************************************** */
5102 #if defined (HANDLE_MULTIBYTE)
5103 # ifdef INCLUDE_UNUSED
5104 static unsigned char *
5105 mb_getcharlens (string
, len
)
5109 int i
, offset
, last
;
5116 ret
= (unsigned char *)xmalloc (len
);
5117 memset (ret
, 0, len
);
5118 while (string
[last
])
5120 ADVANCE_CHAR (string
, len
, offset
);
5121 ret
[last
] = offset
- last
;
5129 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
5130 can have one of 4 values:
5131 RP_LONG_LEFT remove longest matching portion at start of PARAM
5132 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
5133 RP_LONG_RIGHT remove longest matching portion at end of PARAM
5134 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
5137 #define RP_LONG_LEFT 1
5138 #define RP_SHORT_LEFT 2
5139 #define RP_LONG_RIGHT 3
5140 #define RP_SHORT_RIGHT 4
5142 /* Returns its first argument if nothing matched; new memory otherwise */
5144 remove_upattern (param
, pattern
, op
)
5145 char *param
, *pattern
;
5148 register size_t len
;
5150 register char *p
, *ret
, c
;
5152 len
= STRLEN (param
);
5157 case RP_LONG_LEFT
: /* remove longest match at start */
5158 for (p
= end
; p
>= param
; p
--)
5161 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5164 return (savestring (p
));
5171 case RP_SHORT_LEFT
: /* remove shortest match at start */
5172 for (p
= param
; p
<= end
; p
++)
5175 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5178 return (savestring (p
));
5184 case RP_LONG_RIGHT
: /* remove longest match at end */
5185 for (p
= param
; p
<= end
; p
++)
5187 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5190 ret
= savestring (param
);
5197 case RP_SHORT_RIGHT
: /* remove shortest match at end */
5198 for (p
= end
; p
>= param
; p
--)
5200 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5203 ret
= savestring (param
);
5211 return (param
); /* no match, return original string */
5214 #if defined (HANDLE_MULTIBYTE)
5215 /* Returns its first argument if nothing matched; new memory otherwise */
5217 remove_wpattern (wparam
, wstrlen
, wpattern
, op
)
5228 case RP_LONG_LEFT
: /* remove longest match at start */
5229 for (n
= wstrlen
; n
>= 0; n
--)
5231 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5232 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5235 return (wcsdup (wparam
+ n
));
5241 case RP_SHORT_LEFT
: /* remove shortest match at start */
5242 for (n
= 0; n
<= wstrlen
; n
++)
5244 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5245 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5248 return (wcsdup (wparam
+ n
));
5254 case RP_LONG_RIGHT
: /* remove longest match at end */
5255 for (n
= 0; n
<= wstrlen
; n
++)
5257 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5259 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5260 ret
= wcsdup (wparam
);
5267 case RP_SHORT_RIGHT
: /* remove shortest match at end */
5268 for (n
= wstrlen
; n
>= 0; n
--)
5270 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5272 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5273 ret
= wcsdup (wparam
);
5281 return (wparam
); /* no match, return original string */
5283 #endif /* HANDLE_MULTIBYTE */
5286 remove_pattern (param
, pattern
, op
)
5287 char *param
, *pattern
;
5294 if (*param
== '\0' || pattern
== NULL
|| *pattern
== '\0') /* minor optimization */
5295 return (savestring (param
));
5297 #if defined (HANDLE_MULTIBYTE)
5300 wchar_t *ret
, *oret
;
5302 wchar_t *wparam
, *wpattern
;
5305 /* XXX - could optimize here by checking param and pattern for multibyte
5306 chars with mbsmbchar and calling remove_upattern. */
5308 n
= xdupmbstowcs (&wpattern
, NULL
, pattern
);
5309 if (n
== (size_t)-1)
5311 xret
= remove_upattern (param
, pattern
, op
);
5312 return ((xret
== param
) ? savestring (param
) : xret
);
5314 n
= xdupmbstowcs (&wparam
, NULL
, param
);
5316 if (n
== (size_t)-1)
5319 xret
= remove_upattern (param
, pattern
, op
);
5320 return ((xret
== param
) ? savestring (param
) : xret
);
5322 oret
= ret
= remove_wpattern (wparam
, n
, wpattern
, op
);
5323 /* Don't bother to convert wparam back to multibyte string if nothing
5324 matched; just return copy of original string */
5329 return (savestring (param
));
5336 xret
= (char *)xmalloc (n
+ 1);
5337 memset (&ps
, '\0', sizeof (mbstate_t));
5338 n
= wcsrtombs (xret
, (const wchar_t **)&ret
, n
, &ps
);
5339 xret
[n
] = '\0'; /* just to make sure */
5346 xret
= remove_upattern (param
, pattern
, op
);
5347 return ((xret
== param
) ? savestring (param
) : xret
);
5351 /* Match PAT anywhere in STRING and return the match boundaries.
5352 This returns 1 in case of a successful match, 0 otherwise. SP
5353 and EP are pointers into the string where the match begins and
5354 ends, respectively. MTYPE controls what kind of match is attempted.
5355 MATCH_BEG and MATCH_END anchor the match at the beginning and end
5356 of the string, respectively. The longest match is returned. */
5358 match_upattern (string
, pat
, mtype
, sp
, ep
)
5365 register char *p
, *p1
, *npat
;
5368 /* If the pattern doesn't match anywhere in the string, go ahead and
5369 short-circuit right away. A minor optimization, saves a bunch of
5370 unnecessary calls to strmatch (up to N calls for a string of N
5371 characters) if the match is unsuccessful. To preserve the semantics
5372 of the substring matches below, we make sure that the pattern has
5373 `*' as first and last character, making a new pattern if necessary. */
5374 /* XXX - check this later if I ever implement `**' with special meaning,
5375 since this will potentially result in `**' at the beginning or end */
5377 if (pat
[0] != '*' || (pat
[0] == '*' && pat
[1] == LPAREN
&& extended_glob
) || pat
[len
- 1] != '*')
5379 int unescaped_backslash
;
5382 p
= npat
= (char *)xmalloc (len
+ 3);
5384 if ((mtype
!= MATCH_BEG
) && (*p1
!= '*' || (*p1
== '*' && p1
[1] == LPAREN
&& extended_glob
)))
5389 /* Need to also handle a pattern that ends with an unescaped backslash.
5390 For right now, we ignore it because the pattern matching code will
5391 fail the match anyway */
5392 /* If the pattern ends with a `*' we leave it alone if it's preceded by
5393 an even number of backslashes, but if it's escaped by a backslash
5394 we need to add another `*'. */
5395 if ((mtype
!= MATCH_END
) && (p1
[-1] == '*' && (unescaped_backslash
= p1
[-2] == '\\')))
5398 while (pp
>= pat
&& *pp
-- == '\\')
5399 unescaped_backslash
= 1 - unescaped_backslash
;
5400 if (unescaped_backslash
)
5403 else if (mtype
!= MATCH_END
&& p1
[-1] != '*')
5406 if (p1
[-1] != '*' || p1
[-2] == '\\')
5413 c
= strmatch (npat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
5416 if (c
== FNM_NOMATCH
)
5419 len
= STRLEN (string
);
5422 mlen
= umatchlen (pat
, len
);
5423 if (mlen
> (int)len
)
5429 for (p
= string
; p
<= end
; p
++)
5431 if (match_pattern_char (pat
, p
, FNMATCH_IGNCASE
))
5433 p1
= (mlen
== -1) ? end
: p
+ mlen
;
5434 /* p1 - p = length of portion of string to be considered
5435 p = current position in string
5436 mlen = number of characters consumed by match (-1 for entire string)
5438 we want to break immediately if the potential match len
5439 is greater than the number of characters remaining in the
5444 for ( ; p1
>= p
; p1
--)
5446 c
= *p1
; *p1
= '\0';
5447 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5456 /* If MLEN != -1, we have a fixed length pattern. */
5467 if (match_pattern_char (pat
, string
, FNMATCH_IGNCASE
) == 0)
5470 for (p
= (mlen
== -1) ? end
: string
+ mlen
; p
>= string
; p
--)
5473 if (strmatch (pat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5481 /* If MLEN != -1, we have a fixed length pattern. */
5489 for (p
= end
- ((mlen
== -1) ? len
: mlen
); p
<= end
; p
++)
5491 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5497 /* If MLEN != -1, we have a fixed length pattern. */
5508 #if defined (HANDLE_MULTIBYTE)
5510 #define WFOLD(c) (match_ignore_case && iswupper (c) ? towlower (c) : (c))
5512 /* Match WPAT anywhere in WSTRING and return the match boundaries.
5513 This returns 1 in case of a successful match, 0 otherwise. Wide
5514 character version. */
5516 match_wpattern (wstring
, indices
, wstrlen
, wpat
, mtype
, sp
, ep
)
5524 wchar_t wc
, *wp
, *nwpat
, *wp1
;
5527 int n
, n1
, n2
, simple
;
5529 simple
= (wpat
[0] != L
'\\' && wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'[');
5530 #if defined (EXTENDED_GLOB)
5532 simple
&= (wpat
[1] != L
'(' || (wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'+' && wpat
[0] != L
'!' && wpat
[0] != L
'@')); /*)*/
5535 /* If the pattern doesn't match anywhere in the string, go ahead and
5536 short-circuit right away. A minor optimization, saves a bunch of
5537 unnecessary calls to strmatch (up to N calls for a string of N
5538 characters) if the match is unsuccessful. To preserve the semantics
5539 of the substring matches below, we make sure that the pattern has
5540 `*' as first and last character, making a new pattern if necessary. */
5541 len
= wcslen (wpat
);
5542 if (wpat
[0] != L
'*' || (wpat
[0] == L
'*' && wpat
[1] == WLPAREN
&& extended_glob
) || wpat
[len
- 1] != L
'*')
5544 int unescaped_backslash
;
5547 wp
= nwpat
= (wchar_t *)xmalloc ((len
+ 3) * sizeof (wchar_t));
5549 if (*wp1
!= L
'*' || (*wp1
== '*' && wp1
[1] == WLPAREN
&& extended_glob
))
5551 while (*wp1
!= L
'\0')
5554 /* See comments above in match_upattern. */
5555 if (wp1
[-1] == L
'*' && (unescaped_backslash
= wp1
[-2] == L
'\\'))
5558 while (wpp
>= wpat
&& *wpp
-- == L
'\\')
5559 unescaped_backslash
= 1 - unescaped_backslash
;
5560 if (unescaped_backslash
)
5563 else if (wp1
[-1] != L
'*')
5566 if (wp1
[-1] != L
'*' || wp1
[-2] == L
'\\')
5573 len
= wcsmatch (nwpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
5576 if (len
== FNM_NOMATCH
)
5579 mlen
= wmatchlen (wpat
, wstrlen
);
5580 if (mlen
> (int)wstrlen
)
5583 /* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
5587 for (n
= 0; n
<= wstrlen
; n
++)
5589 n2
= simple
? (WFOLD(*wpat
) == WFOLD(wstring
[n
])) : match_pattern_wchar (wpat
, wstring
+ n
, FNMATCH_IGNCASE
);
5592 n1
= (mlen
== -1) ? wstrlen
: n
+ mlen
;
5596 for ( ; n1
>= n
; n1
--)
5598 wc
= wstring
[n1
]; wstring
[n1
] = L
'\0';
5599 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5607 /* If MLEN != -1, we have a fixed length pattern. */
5617 if (match_pattern_wchar (wpat
, wstring
, FNMATCH_IGNCASE
) == 0)
5620 for (n
= (mlen
== -1) ? wstrlen
: mlen
; n
>= 0; n
--)
5622 wc
= wstring
[n
]; wstring
[n
] = L
'\0';
5623 if (wcsmatch (wpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5631 /* If MLEN != -1, we have a fixed length pattern. */
5639 for (n
= wstrlen
- ((mlen
== -1) ? wstrlen
: mlen
); n
<= wstrlen
; n
++)
5641 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5644 *ep
= indices
[wstrlen
];
5647 /* If MLEN != -1, we have a fixed length pattern. */
5658 #endif /* HANDLE_MULTIBYTE */
5661 match_pattern (string
, pat
, mtype
, sp
, ep
)
5666 #if defined (HANDLE_MULTIBYTE)
5669 wchar_t *wstring
, *wpat
;
5673 if (string
== 0 || pat
== 0 || *pat
== 0)
5676 #if defined (HANDLE_MULTIBYTE)
5679 if (mbsmbchar (string
) == 0 && mbsmbchar (pat
) == 0)
5680 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5682 n
= xdupmbstowcs (&wpat
, NULL
, pat
);
5683 if (n
== (size_t)-1)
5684 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5685 n
= xdupmbstowcs (&wstring
, &indices
, string
);
5686 if (n
== (size_t)-1)
5689 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5691 ret
= match_wpattern (wstring
, indices
, n
, wpat
, mtype
, sp
, ep
);
5701 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5705 getpatspec (c
, value
)
5710 return ((*value
== '#') ? RP_LONG_LEFT
: RP_SHORT_LEFT
);
5712 return ((*value
== '%') ? RP_LONG_RIGHT
: RP_SHORT_RIGHT
);
5715 /* Posix.2 says that the WORD should be run through tilde expansion,
5716 parameter expansion, command substitution and arithmetic expansion.
5717 This leaves the result quoted, so quote_string_for_globbing () has
5718 to be called to fix it up for strmatch (). If QUOTED is non-zero,
5719 it means that the entire expression was enclosed in double quotes.
5720 This means that quoting characters in the pattern do not make any
5721 special pattern characters quoted. For example, the `*' in the
5722 following retains its special meaning: "${foo#'*'}". */
5724 getpattern (value
, quoted
, expandpat
)
5726 int quoted
, expandpat
;
5733 /* There is a problem here: how to handle single or double quotes in the
5734 pattern string when the whole expression is between double quotes?
5735 POSIX.2 says that enclosing double quotes do not cause the pattern to
5736 be quoted, but does that leave us a problem with @ and array[@] and their
5737 expansions inside a pattern? */
5739 if (expandpat
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *tword
)
5742 pat
= string_extract_double_quoted (tword
, &i
, SX_STRIPDQ
);
5748 /* expand_string_for_pat () leaves WORD quoted and does not perform
5750 l
= *value
? expand_string_for_pat (value
,
5751 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? Q_PATQUOTE
: quoted
,
5752 (int *)NULL
, (int *)NULL
)
5755 word_list_remove_quoted_nulls (l
);
5756 pat
= string_list (l
);
5760 tword
= quote_string_for_globbing (pat
, QGLOB_CVTNULL
);
5768 /* Handle removing a pattern from a string as a result of ${name%[%]value}
5769 or ${name#[#]value}. */
5771 variable_remove_pattern (value
, pattern
, patspec
, quoted
)
5772 char *value
, *pattern
;
5773 int patspec
, quoted
;
5777 tword
= remove_pattern (value
, pattern
, patspec
);
5784 list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
)
5787 int patspec
, itype
, quoted
;
5793 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
5795 tword
= remove_pattern (l
->word
->word
, pattern
, patspec
);
5796 w
= alloc_word_desc ();
5797 w
->word
= tword
? tword
: savestring ("");
5798 new = make_word_list (w
, new);
5801 l
= REVERSE_LIST (new, WORD_LIST
*);
5802 tword
= string_list_pos_params (itype
, l
, quoted
, 0);
5809 parameter_list_remove_pattern (itype
, pattern
, patspec
, quoted
)
5812 int patspec
, quoted
;
5817 list
= list_rest_of_args ();
5819 return ((char *)NULL
);
5820 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5821 dispose_words (list
);
5825 #if defined (ARRAY_VARS)
5827 array_remove_pattern (var
, pattern
, patspec
, starsub
, quoted
)
5831 int starsub
; /* so we can figure out how it's indexed */
5841 v
= var
; /* XXX - for now */
5843 itype
= starsub
? '*' : '@';
5845 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
5846 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
5848 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
5850 return ((char *)NULL
);
5851 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5852 dispose_words (list
);
5856 #endif /* ARRAY_VARS */
5859 parameter_brace_remove_pattern (varname
, value
, estatep
, patstr
, rtype
, quoted
, flags
)
5860 char *varname
, *value
;
5861 array_eltstate_t
*estatep
;
5863 int rtype
, quoted
, flags
;
5865 int vtype
, patspec
, starsub
;
5866 char *temp1
, *val
, *pattern
, *oname
;
5870 return ((char *)NULL
);
5872 oname
= this_command_name
;
5873 this_command_name
= varname
;
5875 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
5878 this_command_name
= oname
;
5879 return ((char *)NULL
);
5882 starsub
= vtype
& VT_STARSUB
;
5883 vtype
&= ~VT_STARSUB
;
5885 patspec
= getpatspec (rtype
, patstr
);
5886 if (patspec
== RP_LONG_LEFT
|| patspec
== RP_LONG_RIGHT
)
5889 /* Need to pass getpattern newly-allocated memory in case of expansion --
5890 the expansion code will free the passed string on an error. */
5891 temp1
= savestring (patstr
);
5892 pattern
= getpattern (temp1
, quoted
, 1);
5895 temp1
= (char *)NULL
; /* shut up gcc */
5899 case VT_ARRAYMEMBER
:
5900 temp1
= remove_pattern (val
, pattern
, patspec
);
5901 if (vtype
== VT_VARIABLE
)
5905 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
5906 ? quote_string (temp1
)
5907 : quote_escapes (temp1
);
5912 #if defined (ARRAY_VARS)
5914 temp1
= array_remove_pattern (v
, pattern
, patspec
, starsub
, quoted
);
5915 if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5917 val
= quote_escapes (temp1
);
5924 temp1
= parameter_list_remove_pattern (varname
[0], pattern
, patspec
, quoted
);
5925 if (temp1
&& quoted
== 0 && ifs_is_null
)
5927 /* Posix interp 888 */
5929 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5931 val
= quote_escapes (temp1
);
5938 this_command_name
= oname
;
5944 #if defined (PROCESS_SUBSTITUTION)
5946 static void reap_some_procsubs
PARAMS((int));
5948 /*****************************************************************/
5950 /* Hacking Process Substitution */
5952 /*****************************************************************/
5954 #if !defined (HAVE_DEV_FD)
5955 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
5956 of FIFOs the shell has open. unlink_fifo_list will walk the list and
5957 unlink the ones that don't have a living process on the other end.
5958 unlink_all_fifos will walk the list and unconditionally unlink them, trying
5959 to open and close the FIFO first to release any child processes sleeping on
5960 the FIFO. add_fifo_list adds the name of an open FIFO to the list.
5961 NFIFO is a count of the number of FIFOs in the list. */
5962 #define FIFO_INCR 20
5964 /* PROC value of -1 means the process has been reaped and the FIFO needs to
5965 be removed. PROC value of 0 means the slot is unused. */
5971 static struct temp_fifo
*fifo_list
= (struct temp_fifo
*)NULL
;
5973 static int fifo_list_size
;
5980 for (i
= 0; i
< fifo_list_size
; i
++)
5982 if (fifo_list
[i
].file
)
5983 free (fifo_list
[i
].file
);
5984 fifo_list
[i
].file
= NULL
;
5985 fifo_list
[i
].proc
= 0;
5991 copy_fifo_list (sizep
)
5996 return (void *)NULL
;
6000 add_fifo_list (pathname
)
6005 if (nfifo
>= fifo_list_size
- 1)
6007 osize
= fifo_list_size
;
6008 fifo_list_size
+= FIFO_INCR
;
6009 fifo_list
= (struct temp_fifo
*)xrealloc (fifo_list
,
6010 fifo_list_size
* sizeof (struct temp_fifo
));
6011 for (i
= osize
; i
< fifo_list_size
; i
++)
6013 fifo_list
[i
].file
= (char *)NULL
;
6014 fifo_list
[i
].proc
= 0; /* unused */
6018 fifo_list
[nfifo
].file
= savestring (pathname
);
6026 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
6028 unlink (fifo_list
[i
].file
);
6029 free (fifo_list
[i
].file
);
6030 fifo_list
[i
].file
= (char *)NULL
;
6031 fifo_list
[i
].proc
= 0;
6043 for (i
= saved
= 0; i
< nfifo
; i
++)
6045 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
6047 unlink (fifo_list
[i
].file
);
6048 free (fifo_list
[i
].file
);
6049 fifo_list
[i
].file
= (char *)NULL
;
6050 fifo_list
[i
].proc
= 0;
6056 /* If we didn't remove some of the FIFOs, compact the list. */
6059 for (i
= j
= 0; i
< nfifo
; i
++)
6060 if (fifo_list
[i
].file
)
6064 fifo_list
[j
].file
= fifo_list
[i
].file
;
6065 fifo_list
[j
].proc
= fifo_list
[i
].proc
;
6066 fifo_list
[i
].file
= (char *)NULL
;
6067 fifo_list
[i
].proc
= 0;
6085 for (i
= 0; i
< nfifo
; i
++)
6087 fifo_list
[i
].proc
= (pid_t
)-1;
6088 #if defined (O_NONBLOCK)
6089 fd
= open (fifo_list
[i
].file
, O_RDWR
|O_NONBLOCK
);
6101 /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
6102 from some point in the past, and close all open FIFOs in fifo_list
6103 that are not marked as active in LIST. If LIST is NULL, close
6104 everything in fifo_list. LSIZE is the number of elements in LIST, in
6105 case it's larger than fifo_list_size (size of fifo_list). */
6107 close_new_fifos (list
, lsize
)
6116 unlink_fifo_list ();
6120 for (plist
= (char *)list
, i
= 0; i
< lsize
; i
++)
6121 if (plist
[i
] == 0 && i
< fifo_list_size
&& fifo_list
[i
].proc
!= -1)
6124 for (i
= lsize
; i
< fifo_list_size
; i
++)
6129 find_procsub_child (pid
)
6134 for (i
= 0; i
< nfifo
; i
++)
6135 if (fifo_list
[i
].proc
== pid
)
6141 set_procsub_status (ind
, pid
, status
)
6146 if (ind
>= 0 && ind
< nfifo
)
6147 fifo_list
[ind
].proc
= (pid_t
)-1; /* sentinel */
6150 /* If we've marked the process for this procsub as dead, close the
6151 associated file descriptor and delete the FIFO. */
6153 reap_some_procsubs (max
)
6158 for (i
= 0; i
< max
; i
++)
6159 if (fifo_list
[i
].proc
== (pid_t
)-1) /* reaped */
6166 reap_some_procsubs (nfifo
);
6176 for (i
= 0; i
< nfifo
; i
++)
6178 if (fifo_list
[i
].proc
!= (pid_t
)-1 && fifo_list
[i
].proc
> 0)
6180 r
= wait_for (fifo_list
[i
].proc
, 0);
6181 save_proc_status (fifo_list
[i
].proc
, r
);
6182 fifo_list
[i
].proc
= (pid_t
)-1;
6205 tname
= sh_mktmpname ("sh-np", MT_USERANDOM
|MT_USETMPDIR
);
6206 if (mkfifo (tname
, 0600) < 0)
6209 return ((char *)NULL
);
6212 add_fifo_list (tname
);
6216 #else /* HAVE_DEV_FD */
6218 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
6219 has open to children. NFDS is a count of the number of bits currently
6220 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
6222 /* dev_fd_list[I] value of -1 means the process has been reaped and file
6223 descriptor I needs to be closed. Value of 0 means the slot is unused. */
6225 static pid_t
*dev_fd_list
= (pid_t
*)NULL
;
6227 static int totfds
; /* The highest possible number of open files. */
6248 for (i
= 0; nfds
&& i
< totfds
; i
++)
6255 copy_fifo_list (sizep
)
6260 if (nfds
== 0 || totfds
== 0)
6264 return (void *)NULL
;
6269 ret
= xmalloc (totfds
* sizeof (pid_t
));
6270 return (memcpy (ret
, dev_fd_list
, totfds
* sizeof (pid_t
)));
6277 if (dev_fd_list
== 0 || fd
>= totfds
)
6282 totfds
= getdtablesize ();
6283 if (totfds
< 0 || totfds
> 256)
6288 dev_fd_list
= (pid_t
*)xrealloc (dev_fd_list
, totfds
* sizeof (dev_fd_list
[0]));
6289 /* XXX - might need a loop for this */
6290 memset (dev_fd_list
+ ofds
, '\0', (totfds
- ofds
) * sizeof (pid_t
));
6293 dev_fd_list
[fd
] = 1; /* marker; updated later */
6300 return 0; /* used for cleanup; not needed with /dev/fd */
6313 if (dev_fd_list
[fd
])
6316 dev_fd_list
[fd
] = 0;
6329 for (i
= totfds
-1; nfds
&& i
>= 0; i
--)
6338 unlink_fifo_list ();
6341 /* Take LIST, which is a snapshot copy of dev_fd_list from some point in
6342 the past, and close all open fds in dev_fd_list that are not marked
6343 as open in LIST. If LIST is NULL, close everything in dev_fd_list.
6344 LSIZE is the number of elements in LIST, in case it's larger than
6345 totfds (size of dev_fd_list). */
6347 close_new_fifos (list
, lsize
)
6356 unlink_fifo_list ();
6360 for (plist
= (pid_t
*)list
, i
= 0; i
< lsize
; i
++)
6361 if (plist
[i
] == 0 && i
< totfds
&& dev_fd_list
[i
])
6364 for (i
= lsize
; i
< totfds
; i
++)
6369 find_procsub_child (pid
)
6377 for (i
= 0; i
< totfds
; i
++)
6378 if (dev_fd_list
[i
] == pid
)
6385 set_procsub_status (ind
, pid
, status
)
6390 if (ind
>= 0 && ind
< totfds
)
6391 dev_fd_list
[ind
] = (pid_t
)-1; /* sentinel */
6394 /* If we've marked the process for this procsub as dead, close the
6395 associated file descriptor. */
6397 reap_some_procsubs (max
)
6402 for (i
= 0; nfds
> 0 && i
< max
; i
++)
6403 if (dev_fd_list
[i
] == (pid_t
)-1)
6410 reap_some_procsubs (totfds
);
6420 for (i
= 0; nfds
> 0 && i
< totfds
; i
++)
6422 if (dev_fd_list
[i
] != (pid_t
)-1 && dev_fd_list
[i
] > 0)
6424 r
= wait_for (dev_fd_list
[i
], 0);
6425 save_proc_status (dev_fd_list
[i
], r
);
6426 dev_fd_list
[i
] = (pid_t
)-1;
6432 #if defined (NOTDEF)
6433 print_dev_fd_list ()
6437 fprintf (stderr
, "pid %ld: dev_fd_list:", (long)getpid ());
6440 for (i
= 0; i
< totfds
; i
++)
6443 fprintf (stderr
, " %d", i
);
6445 fprintf (stderr
, "\n");
6450 make_dev_fd_filename (fd
)
6453 char *ret
, intbuf
[INT_STRLEN_BOUND (int) + 1], *p
;
6455 ret
= (char *)xmalloc (sizeof (DEV_FD_PREFIX
) + 8);
6457 strcpy (ret
, DEV_FD_PREFIX
);
6458 p
= inttostr (fd
, intbuf
, sizeof (intbuf
));
6459 strcpy (ret
+ sizeof (DEV_FD_PREFIX
) - 1, p
);
6465 #endif /* HAVE_DEV_FD */
6467 /* Return a filename that will open a connection to the process defined by
6468 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
6469 a filename in /dev/fd corresponding to a descriptor that is one of the
6470 ends of the pipe. If not defined, we use named pipes on systems that have
6471 them. Systems without /dev/fd and named pipes are out of luck.
6473 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
6474 use the read end of the pipe and dup that file descriptor to fd 0 in
6475 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
6476 writing or use the write end of the pipe in the child, and dup that
6477 file descriptor to fd 1 in the child. The parent does the opposite. */
6480 process_substitute (string
, open_for_read_in_child
)
6482 int open_for_read_in_child
;
6485 int fd
, result
, rc
, function_value
;
6487 #if defined (HAVE_DEV_FD)
6488 int parent_pipe_fd
, child_pipe_fd
;
6490 #endif /* HAVE_DEV_FD */
6491 #if defined (JOB_CONTROL)
6492 pid_t old_pipeline_pgrp
;
6495 if (!string
|| !*string
|| wordexp_only
)
6496 return ((char *)NULL
);
6498 #if !defined (HAVE_DEV_FD)
6499 pathname
= make_named_pipe ();
6500 #else /* HAVE_DEV_FD */
6501 if (pipe (fildes
) < 0)
6503 sys_error ("%s", _("cannot make pipe for process substitution"));
6504 return ((char *)NULL
);
6506 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
6507 the pipe in the parent, otherwise the read end. */
6508 parent_pipe_fd
= fildes
[open_for_read_in_child
];
6509 child_pipe_fd
= fildes
[1 - open_for_read_in_child
];
6510 /* Move the parent end of the pipe to some high file descriptor, to
6511 avoid clashes with FDs used by the script. */
6512 parent_pipe_fd
= move_to_high_fd (parent_pipe_fd
, 1, 64);
6514 pathname
= make_dev_fd_filename (parent_pipe_fd
);
6515 #endif /* HAVE_DEV_FD */
6519 sys_error ("%s", _("cannot make pipe for process substitution"));
6520 return ((char *)NULL
);
6523 old_pid
= last_made_pid
;
6525 #if defined (JOB_CONTROL)
6526 old_pipeline_pgrp
= pipeline_pgrp
;
6527 if (pipeline_pgrp
== 0 || (subshell_environment
& (SUBSHELL_PIPE
|SUBSHELL_FORK
|SUBSHELL_ASYNC
)) == 0)
6528 pipeline_pgrp
= shell_pgrp
;
6530 #endif /* JOB_CONTROL */
6532 pid
= make_child ((char *)NULL
, FORK_ASYNC
);
6536 int old_interactive
;
6538 old_interactive
= interactive
;
6540 /* The currently-executing shell is not interactive */
6543 reset_terminating_signals (); /* XXX */
6544 free_pushed_string_input ();
6545 /* Cancel traps, in trap.c. */
6546 restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
6547 subshell_environment
&= ~SUBSHELL_IGNTRAP
;
6548 QUIT
; /* catch any interrupts we got post-fork */
6549 setup_async_signals ();
6551 if (open_for_read_in_child
== 0 && old_interactive
&& (bash_input
.type
== st_stdin
|| bash_input
.type
== st_stream
))
6552 async_redirect_stdin ();
6555 subshell_environment
|= SUBSHELL_COMSUB
|SUBSHELL_PROCSUB
|SUBSHELL_ASYNC
;
6557 /* We don't inherit the verbose option for command substitutions now, so
6558 let's try it for process substitutions. */
6559 change_flag ('v', FLAG_OFF
);
6561 /* if we're expanding a redirection, we shouldn't have access to the
6562 temporary environment, but commands in the subshell should have
6563 access to their own temporary environment. */
6564 if (expanding_redir
)
6565 flush_temporary_env ();
6568 #if defined (JOB_CONTROL)
6569 set_sigchld_handler ();
6570 stop_making_children ();
6571 /* XXX - should we only do this in the parent? (as in command subst) */
6572 pipeline_pgrp
= old_pipeline_pgrp
;
6574 stop_making_children ();
6575 #endif /* JOB_CONTROL */
6579 sys_error ("%s", _("cannot make child for process substitution"));
6581 #if defined (HAVE_DEV_FD)
6582 close (parent_pipe_fd
);
6583 close (child_pipe_fd
);
6584 #endif /* HAVE_DEV_FD */
6585 #if defined (JOB_CONTROL)
6586 restore_pipeline (1);
6588 return ((char *)NULL
);
6593 #if defined (JOB_CONTROL)
6594 last_procsub_child
= restore_pipeline (0);
6595 /* We assume that last_procsub_child->next == last_procsub_child because
6596 of how jobs.c:add_process() works. */
6597 last_procsub_child
->next
= 0;
6598 procsub_add (last_procsub_child
);
6601 #if defined (HAVE_DEV_FD)
6602 dev_fd_list
[parent_pipe_fd
] = pid
;
6604 fifo_list
[nfifo
-1].proc
= pid
;
6607 last_made_pid
= old_pid
;
6609 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6611 #endif /* JOB_CONTROL && PGRP_PIPE */
6613 #if defined (HAVE_DEV_FD)
6614 close (child_pipe_fd
);
6615 #endif /* HAVE_DEV_FD */
6620 set_sigint_handler ();
6622 #if defined (JOB_CONTROL)
6623 /* make sure we don't have any job control */
6624 set_job_control (0);
6626 /* Clear out any existing list of process substitutions */
6629 /* The idea is that we want all the jobs we start from an async process
6630 substitution to be in the same process group, but not the same pgrp
6631 as our parent shell, since we don't want to affect our parent shell's
6632 jobs if we get a SIGHUP and end up calling hangup_all_jobs, for example.
6633 If pipeline_pgrp != shell_pgrp, we assume that there is a job control
6634 shell somewhere in our parent process chain (since make_child initializes
6635 pipeline_pgrp to shell_pgrp if job_control == 0). What we do in this
6636 case is to set pipeline_pgrp to our PID, so all jobs started by this
6637 process have that same pgrp and we are basically the process group leader.
6638 This should not have negative effects on child processes surviving
6639 after we exit, since we wait for the children we create, but that is
6640 something to watch for. */
6642 if (pipeline_pgrp
!= shell_pgrp
)
6643 pipeline_pgrp
= getpid ();
6644 #endif /* JOB_CONTROL */
6646 #if !defined (HAVE_DEV_FD)
6647 /* Open the named pipe in the child. */
6648 fd
= open (pathname
, open_for_read_in_child
? O_RDONLY
: O_WRONLY
);
6651 /* Two separate strings for ease of translation. */
6652 if (open_for_read_in_child
)
6653 sys_error (_("cannot open named pipe %s for reading"), pathname
);
6655 sys_error (_("cannot open named pipe %s for writing"), pathname
);
6659 if (open_for_read_in_child
)
6661 if (sh_unset_nodelay_mode (fd
) < 0)
6663 sys_error (_("cannot reset nodelay mode for fd %d"), fd
);
6667 #else /* HAVE_DEV_FD */
6669 #endif /* HAVE_DEV_FD */
6671 /* Discard buffered stdio output before replacing the underlying file
6673 if (open_for_read_in_child
== 0)
6676 if (dup2 (fd
, open_for_read_in_child
? 0 : 1) < 0)
6678 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname
,
6679 open_for_read_in_child
? 0 : 1);
6683 if (fd
!= (open_for_read_in_child
? 0 : 1))
6686 /* Need to close any files that this process has open to pipes inherited
6688 if (current_fds_to_close
)
6690 close_fd_bitmap (current_fds_to_close
);
6691 current_fds_to_close
= (struct fd_bitmap
*)NULL
;
6694 #if defined (HAVE_DEV_FD)
6695 /* Make sure we close the parent's end of the pipe and clear the slot
6696 in the fd list so it is not closed later, if reallocated by, for
6697 instance, pipe(2). */
6698 close (parent_pipe_fd
);
6699 dev_fd_list
[parent_pipe_fd
] = 0;
6700 #endif /* HAVE_DEV_FD */
6702 /* subshells shouldn't have this flag, which controls using the temporary
6703 environment for variable lookups. We have already flushed the temporary
6704 environment above in the case we're expanding a redirection, so processes
6705 executed by this command need to be able to set it independently of their
6707 expanding_redir
= 0;
6709 remove_quoted_escapes (string
);
6711 startup_state
= 2; /* see if we can avoid a fork */
6712 parse_and_execute_level
= 0;
6714 /* Give process substitution a place to jump back to on failure,
6715 so we don't go back up to main (). */
6716 result
= setjmp_nosigs (top_level
);
6718 /* If we're running a process substitution inside a shell function,
6719 trap `return' so we don't return from the function in the subshell
6720 and go off to never-never land. */
6721 if (result
== 0 && return_catch_flag
)
6722 function_value
= setjmp_nosigs (return_catch
);
6726 if (result
== ERREXIT
)
6727 rc
= last_command_exit_value
;
6728 else if (result
== EXITPROG
|| result
== EXITBLTIN
)
6729 rc
= last_command_exit_value
;
6731 rc
= EXECUTION_FAILURE
;
6732 else if (function_value
)
6733 rc
= return_catch_value
;
6737 rc
= parse_and_execute (string
, "process substitution", (SEVAL_NONINT
|SEVAL_NOHIST
));
6738 /* leave subshell level intact for any exit trap */
6741 #if !defined (HAVE_DEV_FD)
6742 /* Make sure we close the named pipe in the child before we exit. */
6743 close (open_for_read_in_child
? 0 : 1);
6744 #endif /* !HAVE_DEV_FD */
6746 last_command_exit_value
= rc
;
6747 rc
= run_exit_trap ();
6751 #endif /* PROCESS_SUBSTITUTION */
6753 /***********************************/
6755 /* Command Substitution */
6757 /***********************************/
6759 #define COMSUB_PIPEBUF 4096
6762 optimize_cat_file (r
, quoted
, flags
, flagp
)
6764 int quoted
, flags
, *flagp
;
6769 fd
= open_redir_file (r
, (char **)0);
6771 return &expand_param_error
;
6773 ret
= read_comsub (fd
, quoted
, flags
, flagp
);
6780 read_comsub (fd
, quoted
, flags
, rflag
)
6781 int fd
, quoted
, flags
;
6784 char *istring
, buf
[COMSUB_PIPEBUF
], *bufp
;
6785 int c
, tflag
, skip_ctlesc
, skip_ctlnul
;
6787 size_t istring_index
;
6788 size_t istring_size
;
6791 #if defined (HANDLE_MULTIBYTE)
6798 istring
= (char *)NULL
;
6799 istring_index
= istring_size
= bufn
= tflag
= 0;
6801 skip_ctlesc
= ifs_cmap
[CTLESC
];
6802 skip_ctlnul
= ifs_cmap
[CTLNUL
];
6804 mb_cur_max
= MB_CUR_MAX
;
6807 /* Read the output of the command through the pipe. */
6814 bufn
= zread (fd
, buf
, sizeof (buf
));
6826 internal_warning ("%s", _("command substitution: ignored null byte in input"));
6833 /* Add the character to ISTRING, possibly after resizing it. */
6834 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, mb_cur_max
+1, istring_size
, 512);
6836 /* This is essentially quote_string inline */
6837 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) /* || c == CTLESC || c == CTLNUL */)
6838 istring
[istring_index
++] = CTLESC
;
6839 else if ((flags
& PF_ASSIGNRHS
) && skip_ctlesc
&& c
== CTLESC
)
6840 istring
[istring_index
++] = CTLESC
;
6841 /* Escape CTLESC and CTLNUL in the output to protect those characters
6842 from the rest of the word expansions (word splitting and globbing.)
6843 This is essentially quote_escapes inline. */
6844 else if (skip_ctlesc
== 0 && c
== CTLESC
)
6845 istring
[istring_index
++] = CTLESC
;
6846 else if ((skip_ctlnul
== 0 && c
== CTLNUL
) || (c
== ' ' && (ifs_value
&& *ifs_value
== 0)))
6847 istring
[istring_index
++] = CTLESC
;
6849 #if defined (HANDLE_MULTIBYTE)
6850 if ((locale_utf8locale
&& (c
& 0x80)) ||
6851 (locale_utf8locale
== 0 && mb_cur_max
> 1 && (unsigned char)c
> 127))
6853 /* read a multibyte character from buf */
6854 /* punt on the hard case for now */
6855 memset (&ps
, '\0', sizeof (mbstate_t));
6856 mblen
= mbrtowc (&wc
, bufp
-1, bufn
, &ps
);
6857 if (MB_INVALIDCH (mblen
) || mblen
== 0 || mblen
== 1)
6858 istring
[istring_index
++] = c
;
6861 istring
[istring_index
++] = c
;
6862 for (i
= 0; i
< mblen
-1; i
++)
6863 istring
[istring_index
++] = *bufp
++;
6870 istring
[istring_index
++] = c
;
6874 istring
[istring_index
] = '\0';
6876 /* If we read no output, just return now and save ourselves some
6878 if (istring_index
== 0)
6883 return (char *)NULL
;
6886 /* Strip trailing newlines from the output of the command. */
6887 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
6889 while (istring_index
> 0)
6891 if (istring
[istring_index
- 1] == '\n')
6895 /* If the newline was quoted, remove the quoting char. */
6896 if (istring
[istring_index
- 1] == CTLESC
)
6902 istring
[istring_index
] = '\0';
6905 strip_trailing (istring
, istring_index
- 1, 1);
6912 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
6913 contained string possibly quoted. */
6915 command_substitute (string
, quoted
, flags
)
6920 pid_t pid
, old_pid
, old_pipeline_pgrp
, old_async_pid
;
6922 int result
, fildes
[2], function_value
, pflags
, rc
, tflag
, fork_flags
;
6926 istring
= (char *)NULL
;
6928 /* Don't fork () if there is no need to. In the case of no command to
6929 run, just return NULL. */
6930 for (s
= string
; s
&& *s
&& (shellblank (*s
) || *s
== '\n'); s
++)
6932 if (s
== 0 || *s
== 0)
6933 return ((WORD_DESC
*)NULL
);
6935 if (*s
== '<' && (s
[1] != '<' && s
[1] != '>' && s
[1] != '&'))
6939 cmd
= parse_string_to_command (string
, 0); /* XXX - flags */
6940 if (cmd
&& can_optimize_cat_file (cmd
))
6943 istring
= optimize_cat_file (cmd
->value
.Simple
->redirects
, quoted
, flags
, &tflag
);
6944 if (istring
== &expand_param_error
)
6946 last_command_exit_value
= EXECUTION_FAILURE
;
6950 last_command_exit_value
= EXECUTION_SUCCESS
; /* compat */
6951 last_command_subst_pid
= dollar_dollar_pid
;
6953 dispose_command (cmd
);
6954 ret
= alloc_word_desc ();
6955 ret
->word
= istring
;
6960 dispose_command (cmd
);
6963 if (wordexp_only
&& read_but_dont_execute
)
6965 last_command_exit_value
= EX_WEXPCOMSUB
;
6966 jump_to_top_level (EXITPROG
);
6969 /* We're making the assumption here that the command substitution will
6970 eventually run a command from the file system. Since we'll run
6971 maybe_make_export_env in this subshell before executing that command,
6972 the parent shell and any other shells it starts will have to remake
6973 the environment. If we make it before we fork, other shells won't
6974 have to. Don't bother if we have any temporary variable assignments,
6975 though, because the export environment will be remade after this
6976 command completes anyway, but do it if all the words to be expanded
6977 are variable assignments. */
6978 if (subst_assign_varlist
== 0 || garglist
== 0)
6979 maybe_make_export_env (); /* XXX */
6981 /* Flags to pass to parse_and_execute() */
6982 pflags
= (interactive
&& sourcelevel
== 0) ? SEVAL_RESETLINE
: 0;
6984 old_pid
= last_made_pid
;
6986 /* Pipe the output of executing STRING into the current shell. */
6987 if (pipe (fildes
) < 0)
6989 sys_error ("%s", _("cannot make pipe for command substitution"));
6993 #if defined (JOB_CONTROL)
6994 old_pipeline_pgrp
= pipeline_pgrp
;
6995 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline or
6996 we've already forked to run a disk command (and are expanding redirections,
6998 if ((subshell_environment
& (SUBSHELL_FORK
|SUBSHELL_PIPE
)) == 0)
6999 pipeline_pgrp
= shell_pgrp
;
7000 cleanup_the_pipeline ();
7001 #endif /* JOB_CONTROL */
7003 old_async_pid
= last_asynchronous_pid
;
7004 fork_flags
= (subshell_environment
&SUBSHELL_ASYNC
) ? FORK_ASYNC
: 0;
7005 pid
= make_child ((char *)NULL
, fork_flags
|FORK_NOTERM
);
7006 last_asynchronous_pid
= old_async_pid
;
7010 /* Reset the signal handlers in the child, but don't free the
7011 trap strings. Set a flag noting that we have to free the
7012 trap strings if we run trap to change a signal disposition. */
7013 reset_signal_handlers ();
7016 kill (getpid (), SIGINT
);
7017 CLRINTERRUPT
; /* if we're ignoring SIGINT somehow */
7019 QUIT
; /* catch any interrupts we got post-fork */
7020 subshell_environment
|= SUBSHELL_RESETTRAP
;
7021 subshell_environment
&= ~SUBSHELL_IGNTRAP
;
7024 #if defined (JOB_CONTROL)
7025 /* XXX DO THIS ONLY IN PARENT ? XXX */
7026 set_sigchld_handler ();
7027 stop_making_children ();
7029 pipeline_pgrp
= old_pipeline_pgrp
;
7031 stop_making_children ();
7032 #endif /* JOB_CONTROL */
7036 sys_error (_("cannot make child for command substitution"));
7039 last_made_pid
= old_pid
;
7044 return ((WORD_DESC
*)NULL
);
7049 /* The currently executing shell is not interactive. */
7052 #if defined (JOB_CONTROL)
7053 /* Invariant: in child processes started to run command substitutions,
7054 pipeline_pgrp == shell_pgrp. Other parts of the shell assume this. */
7055 if (pipeline_pgrp
> 0 && pipeline_pgrp
!= shell_pgrp
)
7056 shell_pgrp
= pipeline_pgrp
;
7059 set_sigint_handler (); /* XXX */
7061 free_pushed_string_input ();
7063 /* Discard buffered stdio output before replacing the underlying file
7067 if (dup2 (fildes
[1], 1) < 0)
7069 sys_error ("%s", _("command_substitute: cannot duplicate pipe as fd 1"));
7070 exit (EXECUTION_FAILURE
);
7073 /* If standard output is closed in the parent shell
7074 (such as after `exec >&-'), file descriptor 1 will be
7075 the lowest available file descriptor, and end up in
7076 fildes[0]. This can happen for stdin and stderr as well,
7077 but stdout is more important -- it will cause no output
7078 to be generated from this command. */
7079 if ((fildes
[1] != fileno (stdin
)) &&
7080 (fildes
[1] != fileno (stdout
)) &&
7081 (fildes
[1] != fileno (stderr
)))
7084 if ((fildes
[0] != fileno (stdin
)) &&
7085 (fildes
[0] != fileno (stdout
)) &&
7086 (fildes
[0] != fileno (stderr
)))
7090 /* Let stdio know the fd may have changed from text to binary mode, and
7091 make sure to preserve stdout line buffering. */
7092 freopen (NULL
, "w", stdout
);
7093 sh_setlinebuf (stdout
);
7094 #endif /* __CYGWIN__ */
7096 /* This is a subshell environment. */
7097 subshell_environment
|= SUBSHELL_COMSUB
;
7099 /* Many shells do not appear to inherit the -v option for command
7101 change_flag ('v', FLAG_OFF
);
7103 /* When inherit_errexit option is not enabled, command substitution does
7104 not inherit the -e flag. It is enabled when Posix mode is enabled */
7105 if (inherit_errexit
== 0)
7107 builtin_ignoring_errexit
= 0;
7108 change_flag ('e', FLAG_OFF
);
7112 /* If we are expanding a redirection, we can dispose of any temporary
7113 environment we received, since redirections are not supposed to have
7114 access to the temporary environment. We will have to see whether this
7115 affects temporary environments supplied to `eval', but the temporary
7116 environment gets copied to builtin_env at some point. */
7117 if (expanding_redir
)
7119 flush_temporary_env ();
7120 expanding_redir
= 0;
7123 remove_quoted_escapes (string
);
7125 /* We want to expand aliases on this pass if we are not in posix mode
7126 for backwards compatibility. */
7128 expand_aliases
= posixly_correct
== 0;
7130 startup_state
= 2; /* see if we can avoid a fork */
7131 parse_and_execute_level
= 0;
7133 /* Give command substitution a place to jump back to on failure,
7134 so we don't go back up to main (). */
7135 result
= setjmp_nosigs (top_level
);
7137 /* If we're running a command substitution inside a shell function,
7138 trap `return' so we don't return from the function in the subshell
7139 and go off to never-never land. */
7140 if (result
== 0 && return_catch_flag
)
7141 function_value
= setjmp_nosigs (return_catch
);
7145 if (result
== ERREXIT
)
7146 rc
= last_command_exit_value
;
7147 else if (result
== EXITPROG
|| result
== EXITBLTIN
)
7148 rc
= last_command_exit_value
;
7150 rc
= EXECUTION_FAILURE
;
7151 else if (function_value
)
7152 rc
= return_catch_value
;
7156 rc
= parse_and_execute (string
, "command substitution", pflags
|SEVAL_NOHIST
);
7157 /* leave subshell level intact for any exit trap */
7160 last_command_exit_value
= rc
;
7161 rc
= run_exit_trap ();
7162 #if defined (PROCESS_SUBSTITUTION)
7163 unlink_fifo_list ();
7171 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
7173 #endif /* JOB_CONTROL && PGRP_PIPE */
7177 begin_unwind_frame ("read-comsub");
7178 dummyfd
= fildes
[0];
7179 add_unwind_protect (close
, dummyfd
);
7181 /* Block SIGINT while we're reading from the pipe. If the child
7182 process gets a SIGINT, it will either handle it or die, and the
7183 read will return. */
7184 BLOCK_SIGNAL (SIGINT
, set
, oset
);
7186 istring
= read_comsub (fildes
[0], quoted
, flags
, &tflag
);
7189 discard_unwind_frame ("read-comsub");
7190 UNBLOCK_SIGNAL (oset
);
7192 current_command_subst_pid
= pid
;
7193 last_command_exit_value
= wait_for (pid
, JWAIT_NOTERM
);
7194 last_command_subst_pid
= pid
;
7195 last_made_pid
= old_pid
;
7197 #if defined (JOB_CONTROL)
7198 /* If last_command_exit_value > 128, then the substituted command
7199 was terminated by a signal. If that signal was SIGINT, then send
7200 SIGINT to ourselves. This will break out of loops, for instance. */
7201 if (last_command_exit_value
== (128 + SIGINT
) && last_command_exit_signal
== SIGINT
)
7202 kill (getpid (), SIGINT
);
7203 #endif /* JOB_CONTROL */
7205 ret
= alloc_word_desc ();
7206 ret
->word
= istring
;
7213 /********************************************************
7215 * Utility functions for parameter expansion *
7217 ********************************************************/
7219 #if defined (ARRAY_VARS)
7222 array_length_reference (s
)
7233 var
= array_variable_part (s
, 0, &t
, &len
);
7235 /* If unbound variables should generate an error, report one and return
7237 if ((var
== 0 || invisible_p (var
) || (assoc_p (var
) == 0 && array_p (var
) == 0)) && unbound_vars_is_error
)
7241 set_exit_status (EXECUTION_FAILURE
);
7246 else if (var
== 0 || invisible_p (var
))
7249 /* We support a couple of expansions for variables that are not arrays.
7250 We'll return the length of the value for v[0], and 1 for v[@] or
7251 v[*]. Return 0 for everything else. */
7253 array
= array_p (var
) ? array_cell (var
) : (ARRAY
*)NULL
;
7254 h
= assoc_p (var
) ? assoc_cell (var
) : (HASH_TABLE
*)NULL
;
7256 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == RBRACK
)
7259 return (h
? assoc_num_elements (h
) : 0);
7260 else if (array_p (var
))
7261 return (array
? array_num_elements (array
) : 0);
7263 return (var_isset (var
) ? 1 : 0);
7269 akey
= expand_subscript_string (t
, 0); /* [ */
7270 t
[len
- 1] = RBRACK
;
7271 if (akey
== 0 || *akey
== 0)
7273 err_badarraysub (t
);
7277 t
= assoc_reference (assoc_cell (var
), akey
);
7282 ind
= array_expand_index (var
, t
, len
, 0);
7283 /* negative subscripts to indexed arrays count back from end */
7284 if (var
&& array_p (var
) && ind
< 0)
7285 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
7288 err_badarraysub (t
);
7292 t
= array_reference (array
, ind
);
7294 t
= (ind
== 0) ? value_cell (var
) : (char *)NULL
;
7297 len
= MB_STRLEN (t
);
7300 #endif /* ARRAY_VARS */
7303 valid_brace_expansion_word (name
, var_is_special
)
7307 if (DIGIT (*name
) && all_digits (name
))
7309 else if (var_is_special
)
7311 #if defined (ARRAY_VARS)
7312 else if (valid_array_reference (name
, 0))
7314 #endif /* ARRAY_VARS */
7315 else if (legal_identifier (name
))
7322 chk_atstar (name
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
7325 int *quoted_dollar_atp
, *contains_dollar_at
;
7331 if (quoted_dollar_atp
)
7332 *quoted_dollar_atp
= 0;
7333 if (contains_dollar_at
)
7334 *contains_dollar_at
= 0;
7338 /* check for $@ and $* */
7339 if (name
[0] == '@' && name
[1] == 0)
7341 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
7342 *quoted_dollar_atp
= 1;
7343 if (contains_dollar_at
)
7344 *contains_dollar_at
= 1;
7347 else if (name
[0] == '*' && name
[1] == '\0' && quoted
== 0)
7349 /* Need more checks here that parallel what string_list_pos_params and
7350 param_expand do. Check expand_no_split_dollar_star and ??? */
7351 if (contains_dollar_at
&& expand_no_split_dollar_star
== 0)
7352 *contains_dollar_at
= 1;
7356 /* Now check for ${array[@]} and ${array[*]} */
7357 #if defined (ARRAY_VARS)
7358 else if (valid_array_reference (name
, 0))
7360 temp1
= mbschr (name
, LBRACK
);
7361 if (temp1
&& temp1
[1] == '@' && temp1
[2] == RBRACK
)
7363 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
7364 *quoted_dollar_atp
= 1;
7365 if (contains_dollar_at
)
7366 *contains_dollar_at
= 1;
7369 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
7370 which should result in separate words even when IFS is unset. */
7371 if (temp1
&& temp1
[1] == '*' && temp1
[2] == RBRACK
&& quoted
== 0)
7373 if (contains_dollar_at
)
7374 *contains_dollar_at
= 1;
7382 /* Parameter expand NAME, and return a new string which is the expansion,
7383 or NULL if there was no expansion. NAME is as given in ${NAMEcWORD}.
7384 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
7385 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
7386 NAME was found inside of a double-quoted expression. */
7388 parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, estatep
)
7390 int var_is_special
, quoted
, pflags
;
7391 array_eltstate_t
*estatep
;
7398 array_eltstate_t es
;
7404 #if defined (ARRAY_VARS)
7406 es
= *estatep
; /* structure copy */
7409 init_eltstate (&es
);
7410 es
.ind
= INTMAX_MIN
;
7414 /* Handle multiple digit arguments, as in ${11}. */
7415 if (legal_number (name
, &arg_index
))
7417 tt
= get_dollar_var_value (arg_index
);
7419 temp
= (*tt
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7421 : quote_escapes (tt
);
7423 temp
= (char *)NULL
;
7426 else if (var_is_special
) /* ${@} */
7429 tt
= (char *)xmalloc (2 + strlen (name
));
7430 tt
[sindex
= 0] = '$';
7431 strcpy (tt
+ 1, name
);
7433 ret
= param_expand (tt
, &sindex
, quoted
, (int *)NULL
, (int *)NULL
,
7434 (int *)NULL
, (int *)NULL
, pflags
);
7436 /* Make sure we note that we saw a quoted null string and pass the flag back
7437 to the caller in addition to the value. */
7438 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && STR_DOLLAR_AT_STAR (name
) &&
7439 ret
&& ret
->word
&& QUOTED_NULL (ret
->word
))
7440 ret
->flags
|= W_HASQUOTEDNULL
;
7444 #if defined (ARRAY_VARS)
7445 else if (valid_array_reference (name
, 0))
7448 var
= array_variable_part (name
, 0, &tt
, (int *)0);
7449 /* These are the cases where word splitting will not be performed */
7450 if (pflags
& PF_ASSIGNRHS
)
7452 if (ALL_ELEMENT_SUB (tt
[0]) && tt
[1] == RBRACK
)
7454 /* Only treat as double quoted if array variable */
7455 if (var
&& (array_p (var
) || assoc_p (var
)))
7456 temp
= array_value (name
, quoted
|Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &es
);
7458 temp
= array_value (name
, quoted
, 0, &es
);
7461 temp
= array_value (name
, quoted
, 0, &es
);
7463 /* Posix interp 888 */
7464 else if (pflags
& PF_NOSPLIT2
)
7466 /* Special cases, then general case, for each of A[@], A[*], A[n] */
7467 #if defined (HANDLE_MULTIBYTE)
7468 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
7470 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
7472 temp
= array_value (name
, Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &es
);
7473 else if (tt
[0] == '@' && tt
[1] == RBRACK
)
7474 temp
= array_value (name
, quoted
, 0, &es
);
7475 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
7476 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &es
);
7477 else if (tt
[0] == '*' && tt
[1] == RBRACK
)
7478 temp
= array_value (name
, quoted
, 0, &es
);
7480 temp
= array_value (name
, quoted
, 0, &es
);
7482 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
7483 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &es
);
7485 temp
= array_value (name
, quoted
, 0, &es
);
7486 if (es
.subtype
== 0 && temp
)
7488 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7489 ? quote_string (temp
)
7490 : quote_escapes (temp
);
7491 rflags
|= W_ARRAYIND
;
7493 *estatep
= es
; /* structure copy */
7495 /* Note that array[*] and array[@] expanded to a quoted null string by
7496 returning the W_HASQUOTEDNULL flag to the caller in addition to TEMP. */
7497 else if (es
.subtype
== 1 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7498 rflags
|= W_HASQUOTEDNULL
;
7499 else if (es
.subtype
== 2 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7500 rflags
|= W_HASQUOTEDNULL
;
7503 flush_eltstate (&es
);
7506 else if (var
= find_variable (name
))
7508 if (var_isset (var
) && invisible_p (var
) == 0)
7510 #if defined (ARRAY_VARS)
7511 /* We avoid a memory leak by saving TT as the memory allocated by
7512 assoc_to_string or array_to_string and leaving it 0 otherwise,
7513 then freeing TT after quoting temp. */
7515 if ((pflags
& PF_ALLINDS
) && assoc_p (var
))
7516 tt
= temp
= assoc_empty (assoc_cell (var
)) ? (char *)NULL
: assoc_to_string (assoc_cell (var
), " ", quoted
);
7517 else if ((pflags
& PF_ALLINDS
) && array_p (var
))
7518 tt
= temp
= array_empty (array_cell (var
)) ? (char *)NULL
: array_to_string (array_cell (var
), " ", quoted
);
7519 else if (assoc_p (var
))
7520 temp
= assoc_reference (assoc_cell (var
), "0");
7521 else if (array_p (var
))
7522 temp
= array_reference (array_cell (var
), 0);
7524 temp
= value_cell (var
);
7526 temp
= value_cell (var
);
7530 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7531 ? quote_string (temp
)
7532 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
7533 : quote_escapes (temp
));
7537 temp
= (char *)NULL
;
7539 else if (var
= find_variable_last_nameref (name
, 0))
7541 temp
= nameref_cell (var
);
7542 #if defined (ARRAY_VARS)
7543 /* Handle expanding nameref whose value is x[n] */
7544 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
7547 goto expand_arrayref
;
7551 /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
7552 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
7554 set_exit_status (EXECUTION_FAILURE
);
7555 report_error (_("%s: invalid variable name for name reference"), temp
);
7556 temp
= &expand_param_error
;
7559 temp
= (char *)NULL
;
7562 temp
= (char *)NULL
;
7566 ret
= alloc_word_desc ();
7568 ret
->flags
|= rflags
;
7574 parameter_brace_find_indir (name
, var_is_special
, quoted
, find_nameref
)
7576 int var_is_special
, quoted
, find_nameref
;
7583 if (find_nameref
&& var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)) &&
7584 nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
7585 return (savestring (t
));
7587 /* If var_is_special == 0, and name is not an array reference, this does
7588 more expansion than necessary. It should really look up the variable's
7589 value and not try to expand it. */
7590 pflags
= PF_IGNUNBOUND
;
7591 /* Note that we're not going to be doing word splitting here */
7594 pflags
|= PF_ASSIGNRHS
; /* suppresses word splitting */
7595 oldex
= expand_no_split_dollar_star
;
7596 expand_no_split_dollar_star
= 1;
7598 w
= parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, 0);
7600 expand_no_split_dollar_star
= oldex
;
7603 /* Have to dequote here if necessary */
7606 temp
= ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || var_is_special
)
7607 ? dequote_string (t
)
7608 : dequote_escapes (t
);
7612 dispose_word_desc (w
);
7617 /* Expand an indirect reference to a variable: ${!NAME} expands to the
7618 value of the variable whose name is the value of NAME. */
7620 parameter_brace_expand_indir (name
, var_is_special
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
7622 int var_is_special
, quoted
, pflags
;
7623 int *quoted_dollar_atp
, *contains_dollar_at
;
7629 /* See if it's a nameref first, behave in ksh93-compatible fashion.
7630 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
7631 bash performs an indirect lookup on foo[0] and expands the result;
7632 ksh93 expands bar[0]. We could do that here -- there are enough usable
7633 primitives to do that -- but do not at this point. */
7634 if (var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)))
7636 if (nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
7638 w
= alloc_word_desc ();
7639 w
->word
= savestring (t
);
7645 /* An indirect reference to a positional parameter or a special parameter
7646 is ok. Indirect references to array references, as explained above, are
7647 ok (currently). Only references to unset variables are errors at this
7649 if (legal_identifier (name
) && v
== 0)
7651 report_error (_("%s: invalid indirect expansion"), name
);
7652 w
= alloc_word_desc ();
7653 w
->word
= &expand_param_error
;
7658 t
= parameter_brace_find_indir (name
, var_is_special
, quoted
, 0);
7660 chk_atstar (t
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
7662 #if defined (ARRAY_VARS)
7663 /* Array references to unset variables are also an error */
7664 if (t
== 0 && valid_array_reference (name
, 0))
7666 v
= array_variable_part (name
, 0, (char **)0, (int *)0);
7669 report_error (_("%s: invalid indirect expansion"), name
);
7670 w
= alloc_word_desc ();
7671 w
->word
= &expand_param_error
;
7676 return (WORD_DESC
*)NULL
;
7681 return (WORD_DESC
*)NULL
;
7683 if (valid_brace_expansion_word (t
, SPECIAL_VAR (t
, 0)) == 0)
7685 report_error (_("%s: invalid variable name"), t
);
7687 w
= alloc_word_desc ();
7688 w
->word
= &expand_param_error
;
7693 w
= parameter_brace_expand_word (t
, SPECIAL_VAR(t
, 0), quoted
, pflags
, 0);
7699 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
7700 depending on the value of C, the separating character. C can be one of
7701 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
7702 between double quotes. */
7704 parameter_brace_expand_rhs (name
, value
, op
, quoted
, pflags
, qdollaratp
, hasdollarat
)
7706 int op
, quoted
, pflags
, *qdollaratp
, *hasdollarat
;
7710 char *t
, *t1
, *temp
, *vname
, *newval
;
7711 int l_hasdollat
, sindex
, arrayref
;
7713 array_eltstate_t es
;
7715 /*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
7716 /* If the entire expression is between double quotes, we want to treat
7717 the value as a double-quoted string, with the exception that we strip
7718 embedded unescaped double quotes (for sh backwards compatibility). */
7719 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *value
)
7722 temp
= string_extract_double_quoted (value
, &sindex
, SX_STRIPDQ
);
7727 w
= alloc_word_desc ();
7729 l
= *temp
? expand_string_for_rhs (temp
, quoted
, op
, pflags
, &l_hasdollat
, (int *)NULL
)
7732 *hasdollarat
= l_hasdollat
|| (l
&& l
->next
);
7736 /* list_string takes multiple CTLNULs and turns them into an empty word
7737 with W_SAWQUOTEDNULL set. Turn it back into a single CTLNUL for the
7738 rest of this function and the caller. */
7739 for (tl
= l
; tl
; tl
= tl
->next
)
7741 if (tl
->word
&& (tl
->word
->word
== 0 || tl
->word
->word
[0] == 0) &&
7742 (tl
->word
->flags
| W_SAWQUOTEDNULL
))
7744 t
= make_quoted_char ('\0');
7745 FREE (tl
->word
->word
);
7747 tl
->word
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
7748 tl
->word
->flags
&= ~W_SAWQUOTEDNULL
;
7754 /* If l->next is not null, we know that TEMP contained "$@", since that
7755 is the only expansion that creates more than one word. */
7756 if (qdollaratp
&& ((l_hasdollat
&& quoted
) || l
->next
))
7758 /*itrace("parameter_brace_expand_rhs: %s:%s: l != NULL, set *qdollaratp", name, value);*/
7762 /* The expansion of TEMP returned something. We need to treat things
7763 slightly differently if L_HASDOLLAT is non-zero. If we have "$@",
7764 the individual words have already been quoted. We need to turn them
7765 into a string with the words separated by the first character of
7766 $IFS without any additional quoting, so string_list_dollar_at won't
7767 do the right thing. If IFS is null, we want "$@" to split into
7768 separate arguments, not be concatenated, so we use string_list_internal
7769 and mark the word to be split on spaces later. We use
7770 string_list_dollar_star for "$@" otherwise. */
7771 if (l
->next
&& ifs_is_null
)
7773 temp
= string_list_internal (l
, " ");
7774 w
->flags
|= W_SPLITSPACE
;
7776 else if (l_hasdollat
|| l
->next
)
7777 temp
= string_list_dollar_star (l
, quoted
, 0);
7780 temp
= string_list (l
);
7781 if (temp
&& (QUOTED_NULL (temp
) == 0) && (l
->word
->flags
& W_SAWQUOTEDNULL
))
7782 w
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
7785 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
7786 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
7787 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
7788 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7789 (which is more paranoia than anything else), we need to return the
7790 quoted null string and set the flags to indicate it. */
7791 if (l
->next
== 0 && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
) && QUOTED_NULL (l
->word
->word
) && (l
->word
->flags
& W_HASQUOTEDNULL
))
7793 w
->flags
|= W_HASQUOTEDNULL
;
7794 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null, turning off qdollaratp", name, value);*/
7795 /* If we return a quoted null with L_HASDOLLARAT, we either have a
7796 construct like "${@-$@}" or "${@-${@-$@}}" with no positional
7797 parameters or a quoted expansion of "$@" with $1 == ''. In either
7798 case, we don't want to enable special handling of $@. */
7799 if (qdollaratp
&& l_hasdollat
)
7804 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && l_hasdollat
)
7806 /* Posix interp 221 changed the rules on this. The idea is that
7807 something like "$xxx$@" should expand the same as "${foo-$xxx$@}"
7808 when foo and xxx are unset. The problem is that it's not in any
7809 way backwards compatible and few other shells do it. We're eventually
7810 going to try and split the difference (heh) a little bit here. */
7811 /* l_hasdollat == 1 means we saw a quoted dollar at. */
7813 /* The brace expansion occurred between double quotes and there was
7814 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
7815 it does not expand to anything. In this case, we want to return
7816 a quoted empty string. Posix interp 888 */
7817 temp
= make_quoted_char ('\0');
7818 w
->flags
|= W_HASQUOTEDNULL
;
7819 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null", name, value);*/
7822 temp
= (char *)NULL
;
7824 if (op
== '-' || op
== '+')
7831 t1
= temp
? dequote_string (temp
) : savestring ("");
7837 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1]) || VALID_INDIR_PARAM (name
[1])))
7839 vname
= parameter_brace_find_indir (name
+ 1, SPECIAL_VAR (name
, 1), quoted
, 1);
7840 if (vname
== 0 || *vname
== 0)
7842 report_error (_("%s: invalid indirect expansion"), name
);
7846 return &expand_wdesc_error
;
7848 if (legal_identifier (vname
) == 0)
7850 report_error (_("%s: invalid variable name"), vname
);
7854 return &expand_wdesc_error
;
7859 #if defined (ARRAY_VARS)
7860 if (valid_array_reference (vname
, 0))
7862 init_eltstate (&es
);
7863 v
= assign_array_element (vname
, t1
, ASS_ALLOWALLSUB
, &es
);
7868 #endif /* ARRAY_VARS */
7869 v
= bind_variable (vname
, t1
, 0);
7871 if (v
== 0 || readonly_p (v
) || noassign_p (v
)) /* expansion error */
7873 if ((v
== 0 || readonly_p (v
)) && interactive_shell
== 0 && posixly_correct
)
7875 last_command_exit_value
= EXECUTION_FAILURE
;
7876 exp_jump_to_top_level (FORCE_EOF
);
7882 last_command_exit_value
= EX_BADUSAGE
;
7883 exp_jump_to_top_level (DISCARD
);
7887 stupidly_hack_special_variables (vname
);
7889 /* "In all cases, the final value of parameter shall be substituted." */
7890 if (shell_compatibility_level
> 51)
7893 #if defined (ARRAY_VARS)
7897 flush_eltstate (&es
);
7900 t1
= get_variable_value (v
);
7902 t1
= value_cell (v
);
7909 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
7911 /* If we are double-quoted or if we are not going to be performing word
7912 splitting, we want to quote the value we return appropriately, like
7913 the other expansions this function handles. */
7914 w
->word
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (t1
) : quote_escapes (t1
);
7915 /* If we have something that's non-null, but not a quoted null string,
7916 and we're not going to be performing word splitting (we know we're not
7917 because the operator is `='), we can forget we saw a quoted null. */
7918 if (w
->word
&& w
->word
[0] && QUOTED_NULL (w
->word
) == 0)
7919 w
->flags
&= ~W_SAWQUOTEDNULL
;
7921 /* If we convert a null string into a quoted null, make sure the caller
7923 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && QUOTED_NULL (w
->word
))
7924 w
->flags
|= W_HASQUOTEDNULL
;
7929 /* Deal with the right hand side of a ${name:?value} expansion in the case
7930 that NAME is null or not set. If VALUE is non-null it is expanded and
7931 used as the error message to print, otherwise a standard message is
7934 parameter_brace_expand_error (name
, value
, check_null
)
7941 set_exit_status (EXECUTION_FAILURE
); /* ensure it's non-zero */
7942 if (value
&& *value
)
7944 l
= expand_string (value
, 0);
7945 temp
= string_list (l
);
7946 report_error ("%s: %s", name
, temp
? temp
: ""); /* XXX was value not "" */
7950 else if (check_null
== 0)
7951 report_error (_("%s: parameter not set"), name
);
7953 report_error (_("%s: parameter null or not set"), name
);
7955 /* Free the data we have allocated during this expansion, since we
7956 are about to longjmp out. */
7961 /* Return 1 if NAME is something for which parameter_brace_expand_length is
7964 valid_length_expression (name
)
7967 return (name
[1] == '\0' || /* ${#} */
7968 ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0') || /* special param */
7969 (DIGIT (name
[1]) && all_digits (name
+ 1)) || /* ${#11} */
7970 #if defined (ARRAY_VARS)
7971 valid_array_reference (name
+ 1, 0) || /* ${#a[7]} */
7973 legal_identifier (name
+ 1)); /* ${#PS1} */
7976 /* Handle the parameter brace expansion that requires us to return the
7977 length of a parameter. */
7979 parameter_brace_expand_length (name
)
7983 intmax_t number
, arg_index
;
7987 var
= (SHELL_VAR
*)NULL
;
7989 if (name
[1] == '\0') /* ${#} */
7990 number
= number_of_args ();
7991 else if (DOLLAR_AT_STAR (name
[1]) && name
[2] == '\0') /* ${#@}, ${#*} */
7992 number
= number_of_args ();
7993 else if ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0')
7995 /* Take the lengths of some of the shell's special parameters. */
7999 t
= which_set_flags ();
8002 t
= itos (last_command_exit_value
);
8005 t
= itos (dollar_dollar_pid
);
8008 if (last_asynchronous_pid
== NO_PID
)
8009 t
= (char *)NULL
; /* XXX - error if set -u set? */
8011 t
= itos (last_asynchronous_pid
);
8014 t
= itos (number_of_args ());
8017 number
= STRLEN (t
);
8020 #if defined (ARRAY_VARS)
8021 else if (valid_array_reference (name
+ 1, 0))
8022 number
= array_length_reference (name
+ 1);
8023 #endif /* ARRAY_VARS */
8028 if (legal_number (name
+ 1, &arg_index
)) /* ${#1} */
8030 t
= get_dollar_var_value (arg_index
);
8031 if (t
== 0 && unbound_vars_is_error
)
8033 number
= MB_STRLEN (t
);
8036 #if defined (ARRAY_VARS)
8037 else if ((var
= find_variable (name
+ 1)) && (invisible_p (var
) == 0) && (array_p (var
) || assoc_p (var
)))
8040 t
= assoc_reference (assoc_cell (var
), "0");
8042 t
= array_reference (array_cell (var
), 0);
8043 if (t
== 0 && unbound_vars_is_error
)
8045 number
= MB_STRLEN (t
);
8048 /* Fast path for the common case of taking the length of a non-dynamic
8049 scalar variable value. */
8050 else if ((var
|| (var
= find_variable (name
+ 1))) &&
8051 invisible_p (var
) == 0 &&
8052 array_p (var
) == 0 && assoc_p (var
) == 0 &&
8053 var
->dynamic_value
== 0)
8054 number
= value_cell (var
) ? MB_STRLEN (value_cell (var
)) : 0;
8055 else if (var
== 0 && unbound_vars_is_error
== 0)
8059 newname
= savestring (name
);
8061 list
= expand_string (newname
, Q_DOUBLE_QUOTES
);
8062 t
= list
? string_list (list
) : (char *)NULL
;
8065 dispose_words (list
);
8067 number
= t
? MB_STRLEN (t
) : 0;
8075 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
8076 so we do some ad-hoc parsing of an arithmetic expression to find
8077 the first DELIM, instead of using strchr(3). Two rules:
8078 1. If the substring contains a `(', read until closing `)'.
8079 2. If the substring contains a `?', read past one `:' for each `?'.
8080 The SD_ARITHEXP flag to skip_to_delim takes care of doing this.
8084 skiparith (substr
, delim
)
8094 i
= skip_to_delim (substr
, 0, delims
, SD_ARITHEXP
);
8095 return (substr
+ i
);
8098 /* Verify and limit the start and end of the desired substring. If
8099 VTYPE == 0, a regular shell variable is being used; if it is 1,
8100 then the positional parameters are being used; if it is 2, then
8101 VALUE is really a pointer to an array variable that should be used.
8102 Return value is 1 if both values were OK, 0 if there was a problem
8103 with an invalid expression, or -1 if the values were out of range. */
8105 verify_substring_values (v
, value
, substr
, vtype
, e1p
, e2p
)
8107 char *value
, *substr
;
8109 intmax_t *e1p
, *e2p
;
8111 char *t
, *temp1
, *temp2
;
8114 #if defined (ARRAY_VARS)
8119 /* duplicate behavior of strchr(3) */
8120 t
= skiparith (substr
, ':');
8121 if (*t
&& *t
== ':')
8126 temp1
= expand_arith_string (substr
, Q_DOUBLE_QUOTES
|Q_ARITH
);
8127 eflag
= (shell_compatibility_level
> 51) ? 0 : EXP_EXPANDED
;
8129 *e1p
= evalexp (temp1
, eflag
, &expok
);
8134 len
= -1; /* paranoia */
8138 case VT_ARRAYMEMBER
:
8139 len
= MB_STRLEN (value
);
8142 len
= number_of_args () + 1;
8144 len
++; /* add one arg if counting from $0 */
8146 #if defined (ARRAY_VARS)
8148 /* For arrays, the first value deals with array indices. Negative
8149 offsets count from one past the array's maximum index. Associative
8150 arrays treat the number of elements as the maximum index. */
8154 len
= assoc_num_elements (h
) + (*e1p
< 0);
8159 len
= array_max_index (a
) + (*e1p
< 0); /* arrays index from 0 to n - 1 */
8165 if (len
== -1) /* paranoia */
8168 if (*e1p
< 0) /* negative offsets count from end */
8171 if (*e1p
> len
|| *e1p
< 0)
8174 #if defined (ARRAY_VARS)
8175 /* For arrays, the second offset deals with the number of elements. */
8176 if (vtype
== VT_ARRAYVAR
)
8177 len
= assoc_p (v
) ? assoc_num_elements (h
) : array_num_elements (a
);
8183 temp2
= savestring (t
);
8184 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
8187 *e2p
= evalexp (temp1
, eflag
, &expok
);
8192 /* Should we allow positional parameter length < 0 to count backwards
8193 from end of positional parameters? */
8195 if ((vtype
== VT_ARRAYVAR
|| vtype
== VT_POSPARMS
) && *e2p
< 0)
8196 #else /* XXX - postponed; this isn't really a valuable feature */
8197 if (vtype
== VT_ARRAYVAR
&& *e2p
< 0)
8200 internal_error (_("%s: substring expression < 0"), t
);
8203 #if defined (ARRAY_VARS)
8204 /* In order to deal with sparse arrays, push the intelligence about how
8205 to deal with the number of elements desired down to the array-
8206 specific functions. */
8207 if (vtype
!= VT_ARRAYVAR
)
8213 if (*e2p
< 0 || *e2p
< *e1p
)
8215 internal_error (_("%s: substring expression < 0"), t
);
8220 *e2p
+= *e1p
; /* want E2 chars starting at E1 */
8231 /* Return the type of variable specified by VARNAME (simple variable,
8232 positional param, or array variable). Also return the value specified
8233 by VARNAME (value of a variable or a reference to an array element).
8234 QUOTED is the standard description of quoting state, using Q_* defines.
8235 FLAGS is currently a set of flags to pass to array_value. If IND is
8236 not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
8237 passed to array_value so the array index is not computed again.
8238 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
8239 characters in the value are quoted with CTLESC and takes appropriate
8240 steps. For convenience, *VALP is set to the dequoted VALUE. */
8242 get_var_and_type (varname
, value
, estatep
, quoted
, flags
, varp
, valp
)
8243 char *varname
, *value
;
8244 array_eltstate_t
*estatep
;
8249 int vtype
, want_indir
;
8253 want_indir
= *varname
== '!' &&
8254 (legal_variable_starter ((unsigned char)varname
[1]) || DIGIT (varname
[1])
8255 || VALID_INDIR_PARAM (varname
[1]));
8257 vname
= parameter_brace_find_indir (varname
+1, SPECIAL_VAR (varname
, 1), quoted
, 1);
8258 /* XXX - what if vname == 0 || *vname == 0 ? */
8264 vtype
= VT_VARIABLE
;
8265 *varp
= (SHELL_VAR
*)NULL
;
8266 *valp
= (char *)NULL
;
8270 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
8271 vtype
= STR_DOLLAR_AT_STAR (vname
);
8272 if (vtype
== VT_POSPARMS
&& vname
[0] == '*')
8273 vtype
|= VT_STARSUB
;
8274 *varp
= (SHELL_VAR
*)NULL
;
8276 #if defined (ARRAY_VARS)
8277 if (valid_array_reference (vname
, 0))
8279 v
= array_variable_part (vname
, 0, &temp
, (int *)0);
8280 /* If we want to signal array_value to use an already-computed index,
8281 the caller will set ESTATEP->IND to that index and pass AV_USEIND in
8283 if (estatep
&& (flags
& AV_USEIND
) == 0)
8284 estatep
->ind
= INTMAX_MIN
;
8286 if (v
&& invisible_p (v
))
8288 vtype
= VT_ARRAYMEMBER
;
8289 *varp
= (SHELL_VAR
*)NULL
;
8290 *valp
= (char *)NULL
;
8292 if (v
&& (array_p (v
) || assoc_p (v
)))
8294 if (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
)
8296 /* Callers have to differentiate between indexed and associative */
8297 vtype
= VT_ARRAYVAR
;
8299 vtype
|= VT_STARSUB
;
8300 *valp
= array_p (v
) ? (char *)array_cell (v
) : (char *)assoc_cell (v
);
8304 vtype
= VT_ARRAYMEMBER
;
8305 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, estatep
);
8309 else if (v
&& (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
))
8311 vtype
= VT_VARIABLE
;
8313 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8314 *valp
= value
? dequote_string (value
) : (char *)NULL
;
8316 *valp
= value
? dequote_escapes (value
) : (char *)NULL
;
8320 vtype
= VT_ARRAYMEMBER
;
8322 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, estatep
);
8325 else if ((v
= find_variable (vname
)) && (invisible_p (v
) == 0) && (assoc_p (v
) || array_p (v
)))
8327 vtype
= VT_ARRAYMEMBER
;
8329 *valp
= assoc_p (v
) ? assoc_reference (assoc_cell (v
), "0") : array_reference (array_cell (v
), 0);
8334 if (value
&& vtype
== VT_VARIABLE
)
8336 *varp
= find_variable (vname
);
8337 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8338 *valp
= dequote_string (value
);
8340 *valp
= dequote_escapes (value
);
8352 /***********************************************************/
8354 /* Functions to perform transformations on variable values */
8356 /***********************************************************/
8359 string_var_assignment (v
, s
)
8363 char flags
[MAX_ATTRIBUTES
], *ret
, *val
;
8366 val
= (v
&& (invisible_p (v
) || var_isset (v
) == 0)) ? (char *)NULL
: sh_quote_reusable (s
, 0);
8367 i
= var_attribute_string (v
, 0, flags
);
8368 if (i
== 0 && val
== 0)
8369 return (char *)NULL
;
8371 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16 + MAX_ATTRIBUTES
);
8372 if (i
> 0 && val
== 0)
8373 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
8375 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
8377 sprintf (ret
, "%s=%s", v
->name
, val
);
8382 #if defined (ARRAY_VARS)
8384 array_var_assignment (v
, itype
, quoted
, atype
)
8386 int itype
, quoted
, atype
;
8388 char *ret
, *val
, flags
[MAX_ATTRIBUTES
];
8392 return (char *)NULL
;
8394 val
= array_p (v
) ? array_to_kvpair (array_cell (v
), 0)
8395 : assoc_to_kvpair (assoc_cell (v
), 0);
8397 val
= array_p (v
) ? array_to_assign (array_cell (v
), 0)
8398 : assoc_to_assign (assoc_cell (v
), 0);
8400 if (val
== 0 && (invisible_p (v
) || var_isset (v
) == 0))
8404 val
= (char *)xmalloc (3);
8411 ret
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (val
) : quote_escapes (val
);
8419 i
= var_attribute_string (v
, 0, flags
);
8420 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16);
8422 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
8424 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
8431 pos_params_assignment (list
, itype
, quoted
)
8438 /* first, we transform the list to quote each word. */
8439 temp
= list_transform ('Q', (SHELL_VAR
*)0, list
, itype
, quoted
);
8440 ret
= (char *)xmalloc (strlen (temp
) + 8);
8441 strcpy (ret
, "set -- ");
8442 strcpy (ret
+ 7, temp
);
8448 string_transform (xc
, v
, s
)
8453 char *ret
, flags
[MAX_ATTRIBUTES
], *t
;
8456 if (((xc
== 'A' || xc
== 'a') && v
== 0))
8457 return (char *)NULL
;
8458 else if (xc
!= 'a' && xc
!= 'A' && s
== 0)
8459 return (char *)NULL
;
8463 /* Transformations that interrogate the variable */
8465 i
= var_attribute_string (v
, 0, flags
);
8466 ret
= (i
> 0) ? savestring (flags
) : (char *)NULL
;
8469 ret
= string_var_assignment (v
, s
);
8473 ret
= sh_quote_reusable (s
, 0);
8475 /* Transformations that modify the variable's value */
8477 t
= ansiexpand (s
, 0, strlen (s
), (int *)0);
8478 ret
= dequote_escapes (t
);
8482 ret
= decode_prompt_string (s
);
8485 ret
= sh_quote_reusable (s
, 0);
8488 ret
= sh_modcase (s
, 0, CASE_UPPER
);
8491 ret
= sh_modcase (s
, 0, CASE_UPFIRST
); /* capitalize */
8494 ret
= sh_modcase (s
, 0, CASE_LOWER
);
8504 list_transform (xc
, v
, list
, itype
, quoted
)
8515 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
8517 tword
= string_transform (xc
, v
, l
->word
->word
);
8518 w
= alloc_word_desc ();
8519 w
->word
= tword
? tword
: savestring (""); /* XXX */
8520 new = make_word_list (w
, new);
8522 l
= REVERSE_LIST (new, WORD_LIST
*);
8525 /* If we are expanding in a context where word splitting will not be
8526 performed, treat as quoted. This changes how $* will be expanded. */
8527 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
8528 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8530 tword
= string_list_pos_params (itype
, l
, qflags
, 0);
8537 parameter_list_transform (xc
, itype
, quoted
)
8545 list
= list_rest_of_args ();
8547 return ((char *)NULL
);
8549 ret
= pos_params_assignment (list
, itype
, quoted
);
8551 ret
= list_transform (xc
, (SHELL_VAR
*)0, list
, itype
, quoted
);
8552 dispose_words (list
);
8556 #if defined (ARRAY_VARS)
8558 array_transform (xc
, var
, starsub
, quoted
)
8561 int starsub
; /* so we can figure out how it's indexed */
8571 v
= var
; /* XXX - for now */
8573 itype
= starsub
? '*' : '@';
8576 return (array_var_assignment (v
, itype
, quoted
, 1));
8578 return (array_var_assignment (v
, itype
, quoted
, 2));
8580 /* special case for unset arrays and attributes */
8581 if (xc
== 'a' && (invisible_p (v
) || var_isset (v
) == 0))
8583 char flags
[MAX_ATTRIBUTES
];
8586 i
= var_attribute_string (v
, 0, flags
);
8587 return ((i
> 0) ? savestring (flags
) : (char *)NULL
);
8590 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
8591 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
8597 return ((char *)NULL
);
8598 list
= array_p (v
) ? array_to_kvpair_list (a
) : assoc_to_kvpair_list (h
);
8600 /* If we are expanding in a context where word splitting will not be
8601 performed, treat as quoted. This changes how $* will be expanded. */
8602 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
8603 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8605 ret
= string_list_pos_params (itype
, list
, qflags
, 0);
8606 dispose_words (list
);
8610 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
8612 return ((char *)NULL
);
8613 ret
= list_transform (xc
, v
, list
, itype
, quoted
);
8614 dispose_words (list
);
8618 #endif /* ARRAY_VARS */
8621 valid_parameter_transform (xform
)
8627 /* check for valid values of xform[0] */
8630 case 'a': /* expand to a string with just attributes */
8631 case 'A': /* expand as an assignment statement with attributes */
8632 case 'K': /* expand assoc array to list of key/value pairs */
8633 case 'k': /* XXX - for now */
8634 case 'E': /* expand like $'...' */
8635 case 'P': /* expand like prompt string */
8636 case 'Q': /* quote reusably */
8637 case 'U': /* transform to uppercase */
8638 case 'u': /* transform by capitalizing */
8639 case 'L': /* transform to lowercase */
8647 parameter_brace_transform (varname
, value
, estatep
, xform
, rtype
, quoted
, pflags
, flags
)
8648 char *varname
, *value
;
8649 array_eltstate_t
*estatep
;
8651 int rtype
, quoted
, pflags
, flags
;
8653 int vtype
, xc
, starsub
;
8654 char *temp1
, *val
, *oname
;
8658 if (value
== 0 && xc
!= 'A' && xc
!= 'a')
8659 return ((char *)NULL
);
8661 oname
= this_command_name
;
8662 this_command_name
= varname
;
8664 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
8667 this_command_name
= oname
;
8668 return ((char *)NULL
);
8671 if (xform
[0] == 0 || valid_parameter_transform (xform
) == 0)
8673 this_command_name
= oname
;
8674 if (vtype
== VT_VARIABLE
)
8676 return (interactive_shell
? &expand_param_error
: &expand_param_fatal
);
8679 starsub
= vtype
& VT_STARSUB
;
8680 vtype
&= ~VT_STARSUB
;
8682 /* If we are asked to display the attributes of an unset variable, V will
8683 be NULL after the call to get_var_and_type. Double-check here. */
8684 if ((xc
== 'a' || xc
== 'A') && vtype
== VT_VARIABLE
&& varname
&& v
== 0)
8685 v
= find_variable (varname
);
8687 temp1
= (char *)NULL
; /* shut up gcc */
8691 case VT_ARRAYMEMBER
:
8692 temp1
= string_transform (xc
, v
, val
);
8693 if (vtype
== VT_VARIABLE
)
8697 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
8698 ? quote_string (temp1
)
8699 : quote_escapes (temp1
);
8704 #if defined (ARRAY_VARS)
8706 temp1
= array_transform (xc
, v
, starsub
, quoted
);
8707 if (temp1
&& quoted
== 0 && ifs_is_null
)
8709 /* Posix interp 888 */
8711 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8713 val
= quote_escapes (temp1
);
8720 temp1
= parameter_list_transform (xc
, varname
[0], quoted
);
8721 if (temp1
&& quoted
== 0 && ifs_is_null
)
8723 /* Posix interp 888 */
8725 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8727 val
= quote_escapes (temp1
);
8734 this_command_name
= oname
;
8738 /******************************************************/
8740 /* Functions to extract substrings of variable values */
8742 /******************************************************/
8744 #if defined (HANDLE_MULTIBYTE)
8745 /* Character-oriented rather than strictly byte-oriented substrings. S and
8746 E, rather being strict indices into STRING, indicate character (possibly
8747 multibyte character) positions that require calculation.
8748 Used by the ${param:offset[:length]} expansion. */
8750 mb_substring (string
, s
, e
)
8760 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
8761 slen
= (MB_CUR_MAX
> 1) ? STRLEN (string
) : 0;
8764 while (string
[start
] && i
--)
8765 ADVANCE_CHAR (string
, slen
, start
);
8768 while (string
[stop
] && i
--)
8769 ADVANCE_CHAR (string
, slen
, stop
);
8770 tt
= substring (string
, start
, stop
);
8775 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
8776 is `@', use the positional parameters; otherwise, use the value of
8777 VARNAME. If VARNAME is an array variable, use the array elements. */
8780 parameter_brace_substring (varname
, value
, estatep
, substr
, quoted
, pflags
, flags
)
8781 char *varname
, *value
;
8782 array_eltstate_t
*estatep
;
8784 int quoted
, pflags
, flags
;
8787 int vtype
, r
, starsub
;
8788 char *temp
, *val
, *tt
, *oname
;
8791 if (value
== 0 && ((varname
[0] != '@' && varname
[0] != '*') || varname
[1]))
8792 return ((char *)NULL
);
8794 oname
= this_command_name
;
8795 this_command_name
= varname
;
8797 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
8800 this_command_name
= oname
;
8801 return ((char *)NULL
);
8804 starsub
= vtype
& VT_STARSUB
;
8805 vtype
&= ~VT_STARSUB
;
8807 r
= verify_substring_values (v
, val
, substr
, vtype
, &e1
, &e2
);
8808 this_command_name
= oname
;
8811 if (vtype
== VT_VARIABLE
)
8813 return ((r
== 0) ? &expand_param_error
: (char *)NULL
);
8819 case VT_ARRAYMEMBER
:
8820 #if defined (HANDLE_MULTIBYTE)
8822 tt
= mb_substring (val
, e1
, e2
);
8825 tt
= substring (val
, e1
, e2
);
8827 if (vtype
== VT_VARIABLE
)
8829 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8830 temp
= quote_string (tt
);
8832 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8837 if (vtype
== VT_POSPARMS
)
8838 tt
= pos_params (varname
, e1
, e2
, quoted
, pflags
);
8839 #if defined (ARRAY_VARS)
8840 /* assoc_subrange and array_subrange both call string_list_pos_params,
8841 so we can treat this case just like VT_POSPARAMS. */
8842 else if (assoc_p (v
))
8843 /* we convert to list and take first e2 elements starting at e1th
8844 element -- officially undefined for now */
8845 tt
= assoc_subrange (assoc_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8847 /* We want E2 to be the number of elements desired (arrays can be
8848 sparse, so verify_substring_values just returns the numbers
8849 specified and we rely on array_subrange to understand how to
8851 tt
= array_subrange (array_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8853 /* We want to leave this alone in every case where pos_params/
8854 string_list_pos_params quotes the list members */
8855 if (tt
&& quoted
== 0 && ifs_is_null
)
8857 temp
= tt
; /* Posix interp 888 */
8859 else if (tt
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
8861 temp
= tt
; /* Posix interp 888 */
8863 else if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
8865 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8873 temp
= (char *)NULL
;
8879 /****************************************************************/
8881 /* Functions to perform pattern substitution on variable values */
8883 /****************************************************************/
8886 shouldexp_replacement (s
)
8895 while (c
= s
[sindex
])
8902 /* We want to remove this backslash because we treat it as special
8903 in this context. THIS ASSUMES THE STRING IS PROCESSED BY
8904 strcreplace() OR EQUIVALENT that handles removing backslashes
8905 preceding the special character. */
8906 if (s
[sindex
] == '&')
8908 if (s
[sindex
] == '\\')
8913 ADVANCE_CHAR (s
, slen
, sindex
);
8919 pat_subst (string
, pat
, rep
, mflags
)
8920 char *string
, *pat
, *rep
;
8923 char *ret
, *s
, *e
, *str
, *rstr
, *mstr
, *send
;
8924 int rptr
, mtype
, rxpand
, mlen
;
8925 size_t rsize
, l
, replen
, rslen
;
8929 return (savestring (""));
8931 mtype
= mflags
& MATCH_TYPEMASK
;
8932 rxpand
= mflags
& MATCH_EXPREP
;
8935 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
8936 * with REP and return the result.
8937 * 2. A null pattern with mtype == MATCH_END means to append REP to
8938 * STRING and return the result.
8939 * 3. A null STRING with a matching pattern means to append REP to
8940 * STRING and return the result.
8942 * These process `&' in the replacement string, like `sed' does when
8943 * presented with a BRE of `^' or `$'.
8945 if ((pat
== 0 || *pat
== 0) && (mtype
== MATCH_BEG
|| mtype
== MATCH_END
))
8947 rstr
= (mflags
& MATCH_EXPREP
) ? strcreplace (rep
, '&', "", 2) : rep
;
8948 rslen
= STRLEN (rstr
);
8949 l
= STRLEN (string
);
8950 ret
= (char *)xmalloc (rslen
+ l
+ 2);
8952 strcpy (ret
, string
);
8953 else if (mtype
== MATCH_BEG
)
8956 strcpy (ret
+ rslen
, string
);
8960 strcpy (ret
, string
);
8961 strcpy (ret
+ l
, rstr
);
8967 else if (*string
== 0 && (match_pattern (string
, pat
, mtype
, &s
, &e
) != 0))
8968 return ((mflags
& MATCH_EXPREP
) ? strcreplace (rep
, '&', "", 2) : savestring (rep
));
8970 ret
= (char *)xmalloc (rsize
= 64);
8972 send
= string
+ strlen (string
);
8974 for (replen
= STRLEN (rep
), rptr
= 0, str
= string
; *str
;)
8976 if (match_pattern (str
, pat
, mtype
, &s
, &e
) == 0)
8984 mstr
= xmalloc (mlen
+ 1);
8985 for (x
= 0; x
< mlen
; x
++)
8988 rstr
= strcreplace (rep
, '&', mstr
, 2);
8990 rslen
= strlen (rstr
);
8998 RESIZE_MALLOCED_BUFFER (ret
, rptr
, (l
+ rslen
), rsize
, 64);
9000 /* OK, now copy the leading unmatched portion of the string (from
9001 str to s) to ret starting at rptr (the current offset). Then copy
9002 the replacement string at ret + rptr + (s - str). Increment
9003 rptr (if necessary) and str and go on. */
9006 strncpy (ret
+ rptr
, str
, l
);
9011 strncpy (ret
+ rptr
, rstr
, rslen
);
9014 str
= e
; /* e == end of match */
9019 if (((mflags
& MATCH_GLOBREP
) == 0) || mtype
!= MATCH_ANY
)
9024 /* On a zero-length match, make sure we copy one character, since
9025 we increment one character to avoid infinite recursion. */
9026 char *p
, *origp
, *origs
;
9029 RESIZE_MALLOCED_BUFFER (ret
, rptr
, locale_mb_cur_max
, rsize
, 64);
9030 #if defined (HANDLE_MULTIBYTE)
9031 p
= origp
= ret
+ rptr
;
9033 COPY_CHAR_P (p
, str
, send
);
9037 ret
[rptr
++] = *str
++;
9038 e
++; /* avoid infinite recursion on zero-length match */
9043 /* Now copy the unmatched portion of the input string */
9047 RESIZE_MALLOCED_BUFFER (ret
, rptr
, l
, rsize
, 64);
9048 strcpy (ret
+ rptr
, str
);
9056 /* Do pattern match and replacement on the positional parameters. */
9058 pos_params_pat_subst (string
, pat
, rep
, mflags
)
9059 char *string
, *pat
, *rep
;
9062 WORD_LIST
*save
, *params
;
9065 int pchar
, qflags
, pflags
;
9067 save
= params
= list_rest_of_args ();
9069 return ((char *)NULL
);
9071 for ( ; params
; params
= params
->next
)
9073 ret
= pat_subst (params
->word
->word
, pat
, rep
, mflags
);
9074 w
= alloc_word_desc ();
9075 w
->word
= ret
? ret
: savestring ("");
9076 dispose_word (params
->word
);
9080 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
9081 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
9082 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
9084 /* If we are expanding in a context where word splitting will not be
9085 performed, treat as quoted. This changes how $* will be expanded. */
9086 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && expand_no_split_dollar_star
&& ifs_is_null
)
9087 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
9089 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
9090 dispose_words (save
);
9095 /* Perform pattern substitution on VALUE, which is the expansion of
9096 VARNAME. PATSUB is an expression supplying the pattern to match
9097 and the string to substitute. QUOTED is a flags word containing
9098 the type of quoting currently in effect. */
9100 parameter_brace_patsub (varname
, value
, estatep
, patsub
, quoted
, pflags
, flags
)
9101 char *varname
, *value
;
9102 array_eltstate_t
*estatep
;
9104 int quoted
, pflags
, flags
;
9106 int vtype
, mflags
, starsub
, delim
;
9107 char *val
, *temp
, *pat
, *rep
, *p
, *lpatsub
, *tt
, *oname
;
9111 return ((char *)NULL
);
9113 oname
= this_command_name
;
9114 this_command_name
= varname
; /* error messages */
9116 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
9119 this_command_name
= oname
;
9120 return ((char *)NULL
);
9123 starsub
= vtype
& VT_STARSUB
;
9124 vtype
&= ~VT_STARSUB
;
9127 /* PATSUB is never NULL when this is called. */
9130 mflags
|= MATCH_GLOBREP
;
9134 /* Malloc this because expand_string_if_necessary or one of the expansion
9135 functions in its call chain may free it on a substitution error. */
9136 lpatsub
= savestring (patsub
);
9138 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9139 mflags
|= MATCH_QUOTED
;
9142 mflags
|= MATCH_STARSUB
;
9144 if (pflags
& PF_ASSIGNRHS
)
9145 mflags
|= MATCH_ASSIGNRHS
;
9147 /* If the pattern starts with a `/', make sure we skip over it when looking
9148 for the replacement delimiter. */
9149 delim
= skip_to_delim (lpatsub
, ((*patsub
== '/') ? 1 : 0), "/", 0);
9150 if (lpatsub
[delim
] == '/')
9153 rep
= lpatsub
+ delim
+ 1;
9158 if (rep
&& *rep
== '\0')
9161 /* Perform the same expansions on the pattern as performed by the
9162 pattern removal expansions. */
9163 pat
= getpattern (lpatsub
, quoted
, 1);
9167 /* We want to perform quote removal on the expanded replacement even if
9168 the entire expansion is double-quoted because the parser and string
9169 extraction functions treated quotes in the replacement string as
9170 special. THIS IS NOT BACKWARDS COMPATIBLE WITH BASH-4.2. */
9171 if (shell_compatibility_level
> 42 && patsub_replacement
== 0)
9172 rep
= expand_string_if_necessary (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
), expand_string_unsplit
);
9173 else if (shell_compatibility_level
> 42 && patsub_replacement
)
9174 rep
= expand_string_for_patsub (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
));
9175 /* This is the bash-4.2 code. */
9176 else if ((mflags
& MATCH_QUOTED
) == 0)
9177 rep
= expand_string_if_necessary (rep
, quoted
, expand_string_unsplit
);
9179 rep
= expand_string_to_string_internal (rep
, quoted
, expand_string_unsplit
);
9181 /* Check whether or not to replace `&' in the replacement string after
9182 expanding it, since we want to treat backslashes quoting the `&'
9184 if (patsub_replacement
&& rep
&& *rep
&& shouldexp_replacement (rep
))
9185 mflags
|= MATCH_EXPREP
;
9189 /* ksh93 doesn't allow the match specifier to be a part of the expanded
9190 pattern. This is an extension. Make sure we don't anchor the pattern
9191 at the beginning or end of the string if we're doing global replacement,
9194 if (mflags
& MATCH_GLOBREP
)
9195 mflags
|= MATCH_ANY
;
9196 else if (pat
&& pat
[0] == '#')
9198 mflags
|= MATCH_BEG
;
9201 else if (pat
&& pat
[0] == '%')
9203 mflags
|= MATCH_END
;
9207 mflags
|= MATCH_ANY
;
9209 /* OK, we now want to substitute REP for PAT in VAL. If
9210 flags & MATCH_GLOBREP is non-zero, the substitution is done
9211 everywhere, otherwise only the first occurrence of PAT is
9212 replaced. The pattern matching code doesn't understand
9213 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
9214 values passed in (VT_VARIABLE) so the pattern substitution
9215 code works right. We need to requote special chars after
9216 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
9217 other cases if QUOTED == 0, since the posparams and arrays
9218 indexed by * or @ do special things when QUOTED != 0. */
9223 case VT_ARRAYMEMBER
:
9224 temp
= pat_subst (val
, p
, rep
, mflags
);
9225 if (vtype
== VT_VARIABLE
)
9229 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
9235 /* This does the right thing for the case where we are not performing
9236 word splitting. MATCH_STARSUB restricts it to ${* /foo/bar}, and
9237 pos_params_pat_subst/string_list_pos_params will do the right thing
9238 in turn for the case where ifs_is_null. Posix interp 888 */
9239 if ((pflags
& PF_NOSPLIT2
) && (mflags
& MATCH_STARSUB
))
9240 mflags
|= MATCH_ASSIGNRHS
;
9241 temp
= pos_params_pat_subst (val
, p
, rep
, mflags
);
9242 if (temp
&& quoted
== 0 && ifs_is_null
)
9244 /* Posix interp 888 */
9246 else if (temp
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
9248 /* Posix interp 888 */
9250 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9252 tt
= quote_escapes (temp
);
9257 #if defined (ARRAY_VARS)
9259 /* If we are expanding in a context where word splitting will not be
9260 performed, treat as quoted. This changes how ${A[*]} will be
9261 expanded to make it identical to $*. */
9262 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9263 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
9265 /* these eventually call string_list_pos_params */
9267 temp
= assoc_patsub (assoc_cell (v
), p
, rep
, mflags
);
9269 temp
= array_patsub (array_cell (v
), p
, rep
, mflags
);
9271 if (temp
&& quoted
== 0 && ifs_is_null
)
9273 /* Posix interp 888 */
9275 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9277 tt
= quote_escapes (temp
);
9289 this_command_name
= oname
;
9294 /****************************************************************/
9296 /* Functions to perform case modification on variable values */
9298 /****************************************************************/
9300 /* Do case modification on the positional parameters. */
9303 pos_params_modcase (string
, pat
, modop
, mflags
)
9308 WORD_LIST
*save
, *params
;
9311 int pchar
, qflags
, pflags
;
9313 save
= params
= list_rest_of_args ();
9315 return ((char *)NULL
);
9317 for ( ; params
; params
= params
->next
)
9319 ret
= sh_modcase (params
->word
->word
, pat
, modop
);
9320 w
= alloc_word_desc ();
9321 w
->word
= ret
? ret
: savestring ("");
9322 dispose_word (params
->word
);
9326 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
9327 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
9328 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
9330 /* If we are expanding in a context where word splitting will not be
9331 performed, treat as quoted. This changes how $* will be expanded. */
9332 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9333 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
9335 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
9336 dispose_words (save
);
9341 /* Perform case modification on VALUE, which is the expansion of
9342 VARNAME. MODSPEC is an expression supplying the type of modification
9343 to perform. QUOTED is a flags word containing the type of quoting
9344 currently in effect. */
9346 parameter_brace_casemod (varname
, value
, estatep
, modspec
, patspec
, quoted
, pflags
, flags
)
9347 char *varname
, *value
;
9348 array_eltstate_t
*estatep
;
9351 int quoted
, pflags
, flags
;
9353 int vtype
, starsub
, modop
, mflags
, x
;
9354 char *val
, *temp
, *pat
, *p
, *lpat
, *tt
, *oname
;
9358 return ((char *)NULL
);
9360 oname
= this_command_name
;
9361 this_command_name
= varname
;
9363 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
9366 this_command_name
= oname
;
9367 return ((char *)NULL
);
9370 starsub
= vtype
& VT_STARSUB
;
9371 vtype
&= ~VT_STARSUB
;
9375 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9376 mflags
|= MATCH_QUOTED
;
9378 mflags
|= MATCH_STARSUB
;
9379 if (pflags
& PF_ASSIGNRHS
)
9380 mflags
|= MATCH_ASSIGNRHS
;
9385 x
= p
&& p
[0] == modspec
;
9386 modop
= x
? CASE_UPPER
: CASE_UPFIRST
;
9389 else if (modspec
== ',')
9391 x
= p
&& p
[0] == modspec
;
9392 modop
= x
? CASE_LOWER
: CASE_LOWFIRST
;
9395 else if (modspec
== '~')
9397 x
= p
&& p
[0] == modspec
;
9398 modop
= x
? CASE_TOGGLEALL
: CASE_TOGGLE
;
9402 lpat
= p
? savestring (p
) : 0;
9403 /* Perform the same expansions on the pattern as performed by the
9404 pattern removal expansions. */
9405 pat
= lpat
? getpattern (lpat
, quoted
, 1) : 0;
9407 /* OK, now we do the case modification. */
9411 case VT_ARRAYMEMBER
:
9412 temp
= sh_modcase (val
, pat
, modop
);
9413 if (vtype
== VT_VARIABLE
)
9417 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
9424 temp
= pos_params_modcase (val
, pat
, modop
, mflags
);
9425 if (temp
&& quoted
== 0 && ifs_is_null
)
9427 /* Posix interp 888 */
9429 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9431 tt
= quote_escapes (temp
);
9437 #if defined (ARRAY_VARS)
9439 /* If we are expanding in a context where word splitting will not be
9440 performed, treat as quoted. This changes how ${A[*]} will be
9441 expanded to make it identical to $*. */
9442 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9443 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
9445 temp
= assoc_p (v
) ? assoc_modcase (assoc_cell (v
), pat
, modop
, mflags
)
9446 : array_modcase (array_cell (v
), pat
, modop
, mflags
);
9448 if (temp
&& quoted
== 0 && ifs_is_null
)
9450 /* Posix interp 888 */
9452 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9454 tt
= quote_escapes (temp
);
9466 this_command_name
= oname
;
9471 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
9472 any occur, this must be a nested command substitution, so return 0.
9473 Otherwise, return 1. A valid arithmetic expression must always have a
9474 ( before a matching ), so any cases where there are more right parens
9475 means that this must not be an arithmetic expression, though the parser
9476 will not accept it without a balanced total number of parens. */
9478 chk_arithsub (s
, len
)
9490 else if (s
[i
] == RPAREN
)
9500 ADVANCE_CHAR (s
, len
, i
);
9506 ADVANCE_CHAR (s
, len
, i
);
9510 i
= skip_single_quoted (s
, len
, ++i
, 0);
9514 i
= skip_double_quoted ((char *)s
, len
, ++i
, 0);
9519 return (count
== 0);
9522 /****************************************************************/
9524 /* Functions to perform parameter expansion on a string */
9526 /****************************************************************/
9528 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
9530 parameter_brace_expand (string
, indexp
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
9532 int *indexp
, quoted
, pflags
, *quoted_dollar_atp
, *contains_dollar_at
;
9534 int check_nullness
, var_is_set
, var_is_null
, var_is_special
;
9535 int want_substring
, want_indir
, want_patsub
, want_casemod
, want_attributes
;
9536 char *name
, *value
, *temp
, *temp1
;
9537 WORD_DESC
*tdesc
, *ret
;
9538 int t_index
, sindex
, c
, tflag
, modspec
, local_pflags
, all_element_arrayref
;
9540 array_eltstate_t es
;
9542 temp
= temp1
= value
= (char *)NULL
;
9543 var_is_set
= var_is_null
= var_is_special
= check_nullness
= 0;
9544 want_substring
= want_indir
= want_patsub
= want_casemod
= want_attributes
= 0;
9547 all_element_arrayref
= 0;
9551 /* ${#var} doesn't have any of the other parameter expansions on it. */
9552 if (string
[t_index
] == '#' && legal_variable_starter (string
[t_index
+1])) /* {{ */
9553 name
= string_extract (string
, &t_index
, "}", SX_VARNAME
);
9555 #if defined (CASEMOD_EXPANSIONS)
9556 /* To enable case-toggling expansions using the `~' operator character
9557 define CASEMOD_TOGGLECASE in config-top.h */
9558 # if defined (CASEMOD_TOGGLECASE)
9559 name
= string_extract (string
, &t_index
, "#%^,~:-=?+/@}", SX_VARNAME
);
9561 name
= string_extract (string
, &t_index
, "#%^,:-=?+/@}", SX_VARNAME
);
9562 # endif /* CASEMOD_TOGGLECASE */
9564 name
= string_extract (string
, &t_index
, "#%:-=?+/@}", SX_VARNAME
);
9565 #endif /* CASEMOD_EXPANSIONS */
9567 /* Handle ${@[stuff]} now that @ is a word expansion operator. Not exactly
9568 the cleanest code ever. */
9569 if (*name
== 0 && sindex
== t_index
&& string
[sindex
] == '@')
9571 name
= (char *)xrealloc (name
, 2);
9576 else if (*name
== '!' && t_index
> sindex
&& string
[t_index
] == '@' && string
[t_index
+1] == RBRACE
)
9578 name
= (char *)xrealloc (name
, t_index
- sindex
+ 2);
9579 name
[t_index
- sindex
] = '@';
9580 name
[t_index
- sindex
+ 1] = '\0';
9587 #if defined (ARRAY_VARS)
9588 init_eltstate (&es
);
9590 es
.ind
= INTMAX_MIN
; /* XXX */
9592 /* If the name really consists of a special variable, then make sure
9593 that we have the entire name. We don't allow indirect references
9594 to special variables except `#', `?', `@' and `*'. This clause is
9595 designed to handle ${#SPECIAL} and ${!SPECIAL}, not anything more
9597 if ((sindex
== t_index
&& VALID_SPECIAL_LENGTH_PARAM (string
[t_index
])) ||
9598 (sindex
== t_index
&& string
[sindex
] == '#' && VALID_SPECIAL_LENGTH_PARAM (string
[sindex
+ 1])) ||
9599 (sindex
== t_index
- 1 && string
[sindex
] == '!' && VALID_INDIR_PARAM (string
[t_index
])))
9602 temp1
= string_extract (string
, &t_index
, "#%:-=?+/@}", 0);
9603 name
= (char *)xrealloc (name
, 3 + (strlen (temp1
)));
9604 *name
= string
[sindex
];
9605 if (string
[sindex
] == '!')
9607 /* indirect reference of $#, $?, $@, or $* */
9608 name
[1] = string
[sindex
+ 1];
9609 strcpy (name
+ 2, temp1
);
9612 strcpy (name
+ 1, temp1
);
9617 /* Find out what character ended the variable name. Then
9618 do the appropriate thing. */
9619 if (c
= string
[sindex
])
9622 /* If c is followed by one of the valid parameter expansion
9623 characters, move past it as normal. If not, assume that
9624 a substring specification is being given, and do not move
9626 if (c
== ':' && VALID_PARAM_EXPAND_CHAR (string
[sindex
]))
9629 if (c
= string
[sindex
])
9632 else if (c
== ':' && string
[sindex
] != RBRACE
)
9634 else if (c
== '/' /* && string[sindex] != RBRACE */) /* XXX */
9636 #if defined (CASEMOD_EXPANSIONS)
9637 else if (c
== '^' || c
== ',' || c
== '~')
9643 else if (c
== '@' && (string
[sindex
] == 'a' || string
[sindex
] == 'A') && string
[sindex
+1] == RBRACE
)
9645 /* special case because we do not want to shortcut foo as foo[0] here */
9646 want_attributes
= 1;
9647 local_pflags
|= PF_ALLINDS
;
9650 /* Catch the valid and invalid brace expressions that made it through the
9652 /* ${#-} is a valid expansion and means to take the length of $-.
9653 Similarly for ${#?} and ${##}... */
9654 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
9655 VALID_SPECIAL_LENGTH_PARAM (c
) && string
[sindex
] == RBRACE
)
9657 name
= (char *)xrealloc (name
, 3);
9660 c
= string
[sindex
++];
9663 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
9664 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
9665 member (c
, "%:=+/") && string
[sindex
] == RBRACE
)
9667 temp
= (char *)NULL
;
9668 goto bad_substitution
; /* XXX - substitution error */
9671 /* Indirect expansion begins with a `!'. A valid indirect expansion is
9672 either a variable name, one of the positional parameters or a special
9673 variable that expands to one of the positional parameters. */
9674 want_indir
= *name
== '!' &&
9675 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1])
9676 || VALID_INDIR_PARAM (name
[1]));
9678 /* Determine the value of this variable whose name is NAME. */
9680 /* Check for special variables, directly referenced. */
9681 if (SPECIAL_VAR (name
, want_indir
))
9684 /* Check for special expansion things, like the length of a parameter */
9685 if (*name
== '#' && name
[1])
9687 /* If we are not pointing at the character just after the
9688 closing brace, then we haven't gotten all of the name.
9689 Since it begins with a special character, this is a bad
9690 substitution. Also check NAME for validity before trying
9692 if (string
[sindex
- 1] != RBRACE
|| (valid_length_expression (name
) == 0))
9694 temp
= (char *)NULL
;
9695 goto bad_substitution
; /* substitution error */
9698 number
= parameter_brace_expand_length (name
);
9699 if (number
== INTMAX_MIN
&& unbound_vars_is_error
)
9701 set_exit_status (EXECUTION_FAILURE
);
9702 err_unboundvar (name
+1);
9704 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9710 return (&expand_wdesc_error
);
9713 ret
= alloc_word_desc ();
9714 ret
->word
= itos (number
);
9719 /* ${@} is identical to $@. */
9720 if (name
[0] == '@' && name
[1] == '\0')
9722 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9723 *quoted_dollar_atp
= 1;
9725 if (contains_dollar_at
)
9726 *contains_dollar_at
= 1;
9728 tflag
|= W_DOLLARAT
;
9731 /* Process ${!PREFIX*} expansion. */
9732 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9733 (string
[sindex
- 2] == '*' || string
[sindex
- 2] == '@') &&
9734 legal_variable_starter ((unsigned char) name
[1]))
9739 temp1
= savestring (name
+ 1);
9740 number
= strlen (temp1
);
9741 temp1
[number
- 1] = '\0';
9742 x
= all_variables_matching_prefix (temp1
);
9743 xlist
= strvec_to_word_list (x
, 0, 0);
9744 if (string
[sindex
- 2] == '*')
9745 temp
= string_list_dollar_star (xlist
, quoted
, 0);
9748 temp
= string_list_dollar_at (xlist
, quoted
, 0);
9749 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9750 *quoted_dollar_atp
= 1;
9751 if (contains_dollar_at
)
9752 *contains_dollar_at
= 1;
9754 tflag
|= W_DOLLARAT
;
9757 dispose_words (xlist
);
9763 ret
= alloc_word_desc ();
9765 ret
->flags
= tflag
; /* XXX */
9769 #if defined (ARRAY_VARS)
9770 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */
9771 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9772 string
[sindex
- 2] == RBRACK
&& valid_array_reference (name
+1, 0))
9776 temp1
= savestring (name
+ 1);
9777 x
= array_variable_name (temp1
, 0, &x1
, (int *)0);
9779 if (ALL_ELEMENT_SUB (x1
[0]) && x1
[1] == RBRACK
)
9781 temp
= array_keys (temp1
, quoted
, pflags
); /* handles assoc vars too */
9784 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9785 *quoted_dollar_atp
= 1;
9786 if (contains_dollar_at
)
9787 *contains_dollar_at
= 1;
9789 tflag
|= W_DOLLARAT
;
9796 ret
= alloc_word_desc ();
9798 ret
->flags
= tflag
; /* XXX */
9804 #endif /* ARRAY_VARS */
9806 /* Make sure that NAME is valid before trying to go on. */
9807 if (valid_brace_expansion_word (want_indir
? name
+ 1 : name
,
9808 var_is_special
) == 0)
9810 temp
= (char *)NULL
;
9811 goto bad_substitution
; /* substitution error */
9816 tdesc
= parameter_brace_expand_indir (name
+ 1, var_is_special
, quoted
, pflags
|local_pflags
, quoted_dollar_atp
, contains_dollar_at
);
9817 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9819 temp
= (char *)NULL
;
9820 goto bad_substitution
;
9823 /* Turn off the W_ARRAYIND flag because there is no way for this function
9824 to return the index we're supposed to be using. */
9825 if (tdesc
&& tdesc
->flags
)
9826 tdesc
->flags
&= ~W_ARRAYIND
;
9828 /* If the indir expansion contains $@/$*, extend the special treatment
9829 of the case of no positional parameters and `set -u' to it. */
9830 if (contains_dollar_at
&& *contains_dollar_at
)
9831 all_element_arrayref
= 1;
9835 local_pflags
|= PF_IGNUNBOUND
|(pflags
&(PF_NOSPLIT2
|PF_ASSIGNRHS
));
9836 tdesc
= parameter_brace_expand_word (name
, var_is_special
, quoted
, local_pflags
, &es
);
9839 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9848 tflag
= tdesc
->flags
;
9849 dispose_word_desc (tdesc
);
9854 if (temp
== &expand_param_error
|| temp
== &expand_param_fatal
)
9858 return (temp
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9861 #if defined (ARRAY_VARS)
9862 if (valid_array_reference (name
, 0))
9868 /* If in a context where word splitting will not take place, treat as
9869 if double-quoted. Has effects with $* and ${array[*]} */
9871 if (pflags
& PF_ASSIGNRHS
)
9872 qflags
|= Q_DOUBLE_QUOTES
;
9873 /* We duplicate a little code here */
9874 t
= mbschr (name
, LBRACK
);
9875 if (t
&& ALL_ELEMENT_SUB (t
[1]) && t
[2] == RBRACK
)
9877 all_element_arrayref
= 1;
9878 if (expand_no_split_dollar_star
&& t
[1] == '*') /* XXX */
9879 qflags
|= Q_DOUBLE_QUOTES
;
9881 chk_atstar (name
, qflags
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
9885 var_is_set
= temp
!= (char *)0;
9886 var_is_null
= check_nullness
&& (var_is_set
== 0 || *temp
== 0);
9887 /* XXX - this may not need to be restricted to special variables */
9889 var_is_null
|= var_is_set
&& var_is_special
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
);
9890 #if defined (ARRAY_VARS)
9892 var_is_null
|= var_is_set
&&
9893 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) &&
9894 QUOTED_NULL (temp
) &&
9895 valid_array_reference (name
, 0) &&
9896 chk_atstar (name
, 0, 0, (int *)0, (int *)0);
9899 /* Get the rest of the stuff inside the braces. */
9900 if (c
&& c
!= RBRACE
)
9902 /* Extract the contents of the ${ ... } expansion
9903 according to the Posix.2 rules. */
9904 value
= extract_dollar_brace_string (string
, &sindex
, quoted
, (c
== '%' || c
== '#' || c
=='/' || c
== '^' || c
== ',' || c
==':') ? SX_POSIXEXP
|SX_WORD
: SX_WORD
);
9905 if (string
[sindex
] == RBRACE
)
9908 goto bad_substitution
; /* substitution error */
9911 value
= (char *)NULL
;
9915 /* All the cases where an expansion can possibly generate an unbound
9917 if (want_substring
|| want_patsub
|| want_casemod
|| c
== '@' || c
== '#' || c
== '%' || c
== RBRACE
)
9919 if (var_is_set
== 0 && unbound_vars_is_error
&& ((name
[0] != '@' && name
[0] != '*') || name
[1]) && all_element_arrayref
== 0)
9921 set_exit_status (EXECUTION_FAILURE
);
9922 err_unboundvar (name
);
9926 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9930 /* If this is a substring spec, process it and add the result. */
9933 temp1
= parameter_brace_substring (name
, temp
, &es
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9936 #if defined (ARRAY_VARS)
9937 flush_eltstate (&es
);
9940 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9943 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9946 ret
= alloc_word_desc ();
9948 /* We test quoted_dollar_atp because we want variants with double-quoted
9949 "$@" to take a different code path. In fact, we make sure at the end
9950 of expand_word_internal that we're only looking at these flags if
9951 quoted_dollar_at == 0. */
9953 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9954 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9955 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9956 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 &&
9957 (pflags
& PF_ASSIGNRHS
))
9958 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9959 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9960 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9961 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9966 else if (want_patsub
)
9968 temp1
= parameter_brace_patsub (name
, temp
, &es
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9971 #if defined (ARRAY_VARS)
9972 flush_eltstate (&es
);
9975 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9978 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9981 ret
= alloc_word_desc ();
9984 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9985 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9986 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9987 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9988 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9989 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9994 #if defined (CASEMOD_EXPANSIONS)
9995 else if (want_casemod
)
9997 temp1
= parameter_brace_casemod (name
, temp
, &es
, modspec
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10000 #if defined (ARRAY_VARS)
10001 flush_eltstate (&es
);
10004 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
10007 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10010 ret
= alloc_word_desc ();
10013 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
10014 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10015 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10016 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10017 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10018 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10025 /* Do the right thing based on which character ended the variable name. */
10031 set_exit_status (EXECUTION_FAILURE
);
10032 report_error (_("%s: bad substitution"), string
? string
: "??");
10036 #if defined (ARRAY_VARS)
10037 flush_eltstate (&es
);
10039 if (shell_compatibility_level
<= 43)
10040 return &expand_wdesc_error
;
10042 return ((posixly_correct
&& interactive_shell
== 0) ? &expand_wdesc_fatal
: &expand_wdesc_error
);
10048 temp1
= parameter_brace_transform (name
, temp
, &es
, value
, c
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10051 #if defined (ARRAY_VARS)
10052 flush_eltstate (&es
);
10055 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
10058 set_exit_status (EXECUTION_FAILURE
);
10059 report_error (_("%s: bad substitution"), string
? string
: "??");
10060 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10063 ret
= alloc_word_desc ();
10065 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10066 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10067 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10068 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10069 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10074 case '#': /* ${param#[#]pattern} */
10075 case '%': /* ${param%[%]pattern} */
10076 if (value
== 0 || *value
== '\0' || temp
== 0 || *temp
== '\0')
10081 temp1
= parameter_brace_remove_pattern (name
, temp
, &es
, value
, c
, quoted
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10084 #if defined (ARRAY_VARS)
10085 flush_eltstate (&es
);
10088 ret
= alloc_word_desc ();
10090 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10091 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10092 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10093 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10094 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10103 if (var_is_set
&& var_is_null
== 0)
10105 /* If the operator is `+', we don't want the value of the named
10106 variable for anything, just the value of the right hand side. */
10109 /* XXX -- if we're double-quoted and the named variable is "$@",
10110 we want to turn off any special handling of "$@" --
10111 we're not using it, so whatever is on the rhs applies. */
10112 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
10113 *quoted_dollar_atp
= 0;
10114 if (contains_dollar_at
)
10115 *contains_dollar_at
= 0;
10120 /* From Posix discussion on austin-group list. Issue 221
10121 requires that backslashes escaping `}' inside
10122 double-quoted ${...} be removed. */
10123 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10124 quoted
|= Q_DOLBRACE
;
10125 ret
= parameter_brace_expand_rhs (name
, value
, c
,
10129 contains_dollar_at
);
10130 /* XXX - fix up later, esp. noting presence of
10131 W_HASQUOTEDNULL in ret->flags */
10135 temp
= (char *)NULL
;
10141 /* Otherwise do nothing; just use the value in TEMP. */
10143 else /* VAR not set or VAR is NULL. */
10145 /* If we're freeing a quoted null here, we need to remember we saw
10146 it so we can restore it later if needed, or the caller can note it.
10147 The check against `+' doesn't really matter, since the other cases
10148 don't use or return TFLAG, but it's good for clarity. */
10149 if (c
== '+' && temp
&& QUOTED_NULL (temp
) &&
10150 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
10151 tflag
|= W_HASQUOTEDNULL
;
10154 temp
= (char *)NULL
;
10155 if (c
== '=' && var_is_special
)
10157 set_exit_status (EXECUTION_FAILURE
);
10158 report_error (_("$%s: cannot assign in this way"), name
);
10161 #if defined (ARRAY_VARS)
10162 flush_eltstate (&es
);
10164 return &expand_wdesc_error
;
10168 parameter_brace_expand_error (name
, value
, check_nullness
);
10169 #if defined (ARRAY_VARS)
10170 flush_eltstate (&es
);
10172 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10176 /* XXX -- if we're double-quoted and the named variable is "$@",
10177 we want to turn off any special handling of "$@" --
10178 we're not using it, so whatever is on the rhs applies. */
10179 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
10180 *quoted_dollar_atp
= 0;
10181 if (contains_dollar_at
)
10182 *contains_dollar_at
= 0;
10184 /* From Posix discussion on austin-group list. Issue 221 requires
10185 that backslashes escaping `}' inside double-quoted ${...} be
10187 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10188 quoted
|= Q_DOLBRACE
;
10189 ret
= parameter_brace_expand_rhs (name
, value
, c
, quoted
, pflags
,
10191 contains_dollar_at
);
10192 /* XXX - fix up later, esp. noting presence of
10193 W_HASQUOTEDNULL in tdesc->flags */
10201 #if defined (ARRAY_VARS)
10202 flush_eltstate (&es
);
10207 ret
= alloc_word_desc ();
10208 ret
->flags
= tflag
;
10214 /* Expand a single ${xxx} expansion. The braces are optional. When
10215 the braces are used, parameter_brace_expand() does the work,
10216 possibly calling param_expand recursively. */
10218 param_expand (string
, sindex
, quoted
, expanded_something
,
10219 contains_dollar_at
, quoted_dollar_at_p
, had_quoted_null_p
,
10222 int *sindex
, quoted
, *expanded_something
, *contains_dollar_at
;
10223 int *quoted_dollar_at_p
, *had_quoted_null_p
, pflags
;
10225 char *temp
, *temp1
, uerror
[3], *savecmd
;
10226 int zindex
, t_index
, expok
, eflag
;
10230 WORD_LIST
*list
, *l
;
10231 WORD_DESC
*tdesc
, *ret
;
10232 int tflag
, nullarg
;
10234 /*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
10236 c
= string
[++zindex
];
10238 temp
= (char *)NULL
;
10239 ret
= tdesc
= (WORD_DESC
*)NULL
;
10242 /* Do simple cases first. Switch on what follows '$'. */
10256 temp1
= dollar_vars
[TODIGIT (c
)];
10257 /* This doesn't get called when (pflags&PF_IGNUNBOUND) != 0 */
10258 if (unbound_vars_is_error
&& temp1
== (char *)NULL
)
10263 set_exit_status (EXECUTION_FAILURE
);
10264 err_unboundvar (uerror
);
10265 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10268 temp
= (*temp1
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10269 ? quote_string (temp1
)
10270 : quote_escapes (temp1
);
10272 temp
= (char *)NULL
;
10276 /* $$ -- pid of the invoking shell. */
10278 temp
= itos (dollar_dollar_pid
);
10281 /* $# -- number of positional parameters. */
10283 temp
= itos (number_of_args ());
10286 /* $? -- return value of the last synchronous command. */
10288 temp
= itos (last_command_exit_value
);
10291 /* $- -- flags supplied to the shell on invocation or by `set'. */
10293 temp
= which_set_flags ();
10296 /* $! -- Pid of the last asynchronous command. */
10298 /* If no asynchronous pids have been created, expand to nothing.
10299 If `set -u' has been executed, and no async processes have
10300 been created, this is an expansion error. */
10301 if (last_asynchronous_pid
== NO_PID
)
10303 if (expanded_something
)
10304 *expanded_something
= 0;
10305 temp
= (char *)NULL
;
10306 if (unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10311 set_exit_status (EXECUTION_FAILURE
);
10312 err_unboundvar (uerror
);
10313 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10317 temp
= itos (last_asynchronous_pid
);
10320 /* The only difference between this and $@ is when the arg is quoted. */
10321 case '*': /* `$*' */
10322 list
= list_rest_of_args ();
10325 /* According to austin-group posix proposal by Geoff Clare in
10326 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
10328 "The shell shall write a message to standard error and
10329 immediately exit when it tries to expand an unset parameter
10330 other than the '@' and '*' special parameters."
10333 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10338 set_exit_status (EXECUTION_FAILURE
);
10339 err_unboundvar (uerror
);
10340 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10344 /* If there are no command-line arguments, this should just
10345 disappear if there are other characters in the expansion,
10346 even if it's quoted. */
10347 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && list
== 0)
10348 temp
= (char *)NULL
;
10349 else if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
10351 /* If we have "$*" we want to make a string of the positional
10352 parameters, separated by the first character of $IFS, and
10353 quote the whole string, including the separators. If IFS
10354 is unset, the parameters are separated by ' '; if $IFS is
10355 null, the parameters are concatenated. */
10356 temp
= (quoted
& (Q_DOUBLE_QUOTES
|Q_PATQUOTE
)) ? string_list_dollar_star (list
, quoted
, 0) : string_list (list
);
10359 temp1
= (quoted
& Q_DOUBLE_QUOTES
) ? quote_string (temp
) : temp
;
10361 tflag
|= W_HASQUOTEDNULL
;
10369 /* We check whether or not we're eventually going to split $* here,
10370 for example when IFS is empty and we are processing the rhs of
10371 an assignment statement. In that case, we don't separate the
10372 arguments at all. Otherwise, if the $* is not quoted it is
10374 if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
== 0 && (pflags
& PF_ASSIGNRHS
))
10376 /* Posix interp 888: RHS of assignment, IFS unset: no splitting,
10377 separate with space */
10378 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10379 temp
= temp1
? quote_string (temp1
) : temp1
;
10380 /* XXX - tentative - note that we saw a quoted null here */
10381 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
10382 tflag
|= W_SAWQUOTEDNULL
;
10385 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_null
&& (pflags
& PF_ASSIGNRHS
))
10387 /* Posix interp 888: RHS of assignment, IFS set to '' */
10388 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10389 temp
= temp1
? quote_escapes (temp1
) : temp1
;
10392 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && (pflags
& PF_ASSIGNRHS
))
10394 /* Posix interp 888: RHS of assignment, IFS set to non-null value */
10395 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10396 temp
= temp1
? quote_string (temp1
) : temp1
;
10398 /* XXX - tentative - note that we saw a quoted null here */
10399 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
10400 tflag
|= W_SAWQUOTEDNULL
;
10403 /* XXX - should we check ifs_is_set here as well? */
10404 # if defined (HANDLE_MULTIBYTE)
10405 else if (expand_no_split_dollar_star
&& ifs_firstc
[0] == 0)
10407 else if (expand_no_split_dollar_star
&& ifs_firstc
== 0)
10409 /* Posix interp 888: not RHS, no splitting, IFS set to '' */
10410 temp
= string_list_dollar_star (list
, quoted
, 0);
10413 temp
= string_list_dollar_at (list
, quoted
, 0);
10414 /* Set W_SPLITSPACE to make sure the individual positional
10415 parameters are split into separate arguments */
10417 if (quoted
== 0 && (ifs_is_set
== 0 || ifs_is_null
))
10418 #else /* change with bash-5.0 */
10419 if (quoted
== 0 && ifs_is_null
)
10421 tflag
|= W_SPLITSPACE
;
10422 /* If we're not quoted but we still don't want word splitting, make
10423 we quote the IFS characters to protect them from splitting (e.g.,
10424 when $@ is in the string as well). */
10425 else if (temp
&& quoted
== 0 && ifs_is_set
&& (pflags
& PF_ASSIGNRHS
))
10427 temp1
= quote_string (temp
);
10433 if (expand_no_split_dollar_star
== 0 && contains_dollar_at
)
10434 *contains_dollar_at
= 1;
10437 dispose_words (list
);
10440 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
10441 means that we have to turn quoting off after we split into
10442 the individually quoted arguments so that the final split
10443 on the first character of $IFS is still done. */
10444 case '@': /* `$@' */
10445 list
= list_rest_of_args ();
10448 /* According to austin-group posix proposal by Geoff Clare in
10449 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
10451 "The shell shall write a message to standard error and
10452 immediately exit when it tries to expand an unset parameter
10453 other than the '@' and '*' special parameters."
10456 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10461 set_exit_status (EXECUTION_FAILURE
);
10462 err_unboundvar (uerror
);
10463 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10467 for (nullarg
= 0, l
= list
; l
; l
= l
->next
)
10469 if (l
->word
&& (l
->word
->word
== 0 || l
->word
->word
[0] == 0))
10473 /* We want to flag the fact that we saw this. We can't turn
10474 off quoting entirely, because other characters in the
10475 string might need it (consider "\"$@\""), but we need some
10476 way to signal that the final split on the first character
10477 of $IFS should be done, even though QUOTED is 1. */
10478 /* XXX - should this test include Q_PATQUOTE? */
10479 if (quoted_dollar_at_p
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10480 *quoted_dollar_at_p
= 1;
10481 if (contains_dollar_at
)
10482 *contains_dollar_at
= 1;
10484 /* We want to separate the positional parameters with the first
10485 character of $IFS in case $IFS is something other than a space.
10486 We also want to make sure that splitting is done no matter what --
10487 according to POSIX.2, this expands to a list of the positional
10488 parameters no matter what IFS is set to. */
10489 /* XXX - what to do when in a context where word splitting is not
10490 performed? Even when IFS is not the default, posix seems to imply
10491 that we have to expand $@ to all the positional parameters and
10492 separate them with spaces, which are preserved because word splitting
10493 doesn't take place. See below for how we use PF_NOSPLIT2 here. */
10495 /* These are the cases where word splitting will not be performed. */
10496 if (pflags
& PF_ASSIGNRHS
)
10498 temp
= string_list_dollar_at (list
, (quoted
|Q_DOUBLE_QUOTES
), pflags
);
10500 tflag
|= W_HASQUOTEDNULL
; /* we know quoting produces quoted nulls */
10503 /* This needs to match what expand_word_internal does with non-quoted $@
10504 does with separating with spaces. Passing Q_DOUBLE_QUOTES means that
10505 the characters in LIST will be quoted, and PF_ASSIGNRHS ensures that
10506 they will separated by spaces. After doing this, we need the special
10507 handling for PF_NOSPLIT2 in expand_word_internal to remove the CTLESC
10509 else if (pflags
& PF_NOSPLIT2
)
10511 #if defined (HANDLE_MULTIBYTE)
10512 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
10514 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
10516 /* Posix interp 888 */
10517 temp
= string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, pflags
);
10519 temp
= string_list_dollar_at (list
, quoted
, pflags
);
10522 temp
= string_list_dollar_at (list
, quoted
, pflags
);
10524 tflag
|= W_DOLLARAT
;
10525 dispose_words (list
);
10529 tdesc
= parameter_brace_expand (string
, &zindex
, quoted
, pflags
,
10530 quoted_dollar_at_p
,
10531 contains_dollar_at
);
10533 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
10535 temp
= tdesc
? tdesc
->word
: (char *)0;
10538 /* Quoted nulls should be removed if there is anything else
10540 /* Note that we saw the quoted null so we can add one back at
10541 the end of this function if there are no other characters
10542 in the string, discard TEMP, and go on. The exception to
10543 this is when we have "${@}" and $1 is '', since $@ needs
10544 special handling. */
10545 if (tdesc
&& tdesc
->word
&& (tdesc
->flags
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
))
10547 if (had_quoted_null_p
)
10548 *had_quoted_null_p
= 1;
10549 if (*quoted_dollar_at_p
== 0)
10552 tdesc
->word
= temp
= (char *)NULL
;
10560 /* Do command or arithmetic substitution. */
10562 /* We have to extract the contents of this paren substitution. */
10563 t_index
= zindex
+ 1;
10564 /* XXX - might want to check for string[t_index+2] == LPAREN and parse
10565 as arithmetic substitution immediately. */
10566 temp
= extract_command_subst (string
, &t_index
, (pflags
&PF_COMPLETE
) ? SX_COMPLETE
: 0);
10569 /* For Posix.2-style `$(( ))' arithmetic substitution,
10570 extract the expression and pass it to the evaluator. */
10571 if (temp
&& *temp
== LPAREN
)
10575 temp2
= savestring (temp1
);
10576 t_index
= strlen (temp2
) - 1;
10578 if (temp2
[t_index
] != RPAREN
)
10584 /* Cut off ending `)' */
10585 temp2
[t_index
] = '\0';
10587 if (chk_arithsub (temp2
, t_index
) == 0)
10591 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
10596 /* Expand variables found inside the expression. */
10597 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
10601 /* No error messages. */
10602 savecmd
= this_command_name
;
10603 this_command_name
= (char *)NULL
;
10605 eflag
= (shell_compatibility_level
> 51) ? 0 : EXP_EXPANDED
;
10606 number
= evalexp (temp1
, eflag
, &expok
);
10607 this_command_name
= savecmd
;
10612 if (interactive_shell
== 0 && posixly_correct
)
10614 set_exit_status (EXECUTION_FAILURE
);
10615 return (&expand_wdesc_fatal
);
10618 return (&expand_wdesc_error
);
10620 temp
= itos (number
);
10625 if (pflags
& PF_NOCOMSUB
)
10626 /* we need zindex+1 because string[zindex] == RPAREN */
10627 temp1
= substring (string
, *sindex
, zindex
+1);
10630 tdesc
= command_substitute (temp
, quoted
, pflags
&PF_ASSIGNRHS
);
10631 temp1
= tdesc
? tdesc
->word
: (char *)NULL
;
10633 dispose_word_desc (tdesc
);
10639 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
10640 away in a future bash release. */
10642 /* Extract the contents of this arithmetic substitution. */
10643 t_index
= zindex
+ 1;
10644 temp
= extract_arithmetic_subst (string
, &t_index
);
10648 temp
= savestring (string
);
10649 if (expanded_something
)
10650 *expanded_something
= 0;
10654 /* Do initial variable expansion. */
10655 temp1
= expand_arith_string (temp
, Q_DOUBLE_QUOTES
|Q_ARITH
);
10660 /* Find the variable in VARIABLE_LIST. */
10661 temp
= (char *)NULL
;
10663 for (t_index
= zindex
; (c
= string
[zindex
]) && legal_variable_char (c
); zindex
++)
10665 temp1
= (zindex
> t_index
) ? substring (string
, t_index
, zindex
) : (char *)NULL
;
10667 /* If this isn't a variable name, then just output the `$'. */
10668 if (temp1
== 0 || *temp1
== '\0')
10671 temp
= (char *)xmalloc (2);
10674 if (expanded_something
)
10675 *expanded_something
= 0;
10679 /* If the variable exists, return its value cell. */
10680 var
= find_variable (temp1
);
10682 if (var
&& invisible_p (var
) == 0 && var_isset (var
))
10684 #if defined (ARRAY_VARS)
10685 if (assoc_p (var
) || array_p (var
))
10687 temp
= array_p (var
) ? array_reference (array_cell (var
), 0)
10688 : assoc_reference (assoc_cell (var
), "0");
10690 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10691 ? quote_string (temp
)
10692 : quote_escapes (temp
);
10693 else if (unbound_vars_is_error
)
10694 goto unbound_variable
;
10699 temp
= value_cell (var
);
10701 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10702 ? quote_string (temp
)
10703 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
10704 : quote_escapes (temp
));
10711 else if (var
&& (invisible_p (var
) || var_isset (var
) == 0))
10712 temp
= (char *)NULL
;
10713 else if ((var
= find_variable_last_nameref (temp1
, 0)) && var_isset (var
) && invisible_p (var
) == 0)
10715 temp
= nameref_cell (var
);
10716 #if defined (ARRAY_VARS)
10717 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
10719 chk_atstar (temp
, quoted
, pflags
, quoted_dollar_at_p
, contains_dollar_at
);
10720 tdesc
= parameter_brace_expand_word (temp
, SPECIAL_VAR (temp
, 0), quoted
, pflags
, 0);
10721 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
10728 /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
10729 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
10731 set_exit_status (EXECUTION_FAILURE
);
10732 report_error (_("%s: invalid variable name for name reference"), temp
);
10733 return (&expand_wdesc_error
); /* XXX */
10736 temp
= (char *)NULL
;
10739 temp
= (char *)NULL
;
10742 if (unbound_vars_is_error
)
10744 set_exit_status (EXECUTION_FAILURE
);
10745 err_unboundvar (temp1
);
10754 set_exit_status (EXECUTION_FAILURE
);
10755 return ((unbound_vars_is_error
&& interactive_shell
== 0)
10756 ? &expand_wdesc_fatal
10757 : &expand_wdesc_error
);
10760 if (string
[zindex
])
10768 ret
= alloc_word_desc ();
10769 ret
->flags
= tflag
; /* XXX */
10775 #if defined (ARRAY_VARS)
10776 /* Characters that need to be backslash-quoted after expanding array subscripts */
10777 static char abstab
[256] = { '\1' };
10779 /* Run an array subscript through the appropriate word expansions. */
10781 expand_subscript_string (string
, quoted
)
10790 if (string
== 0 || *string
== 0)
10791 return (char *)NULL
;
10793 oe
= expand_no_split_dollar_star
;
10794 ret
= (char *)NULL
;
10796 td
.flags
= W_NOPROCSUB
|W_NOTILDE
|W_NOSPLIT2
; /* XXX - W_NOCOMSUB? */
10797 td
.word
= savestring (string
); /* in case it's freed on error */
10799 expand_no_split_dollar_star
= 1;
10800 tlist
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
10801 expand_no_split_dollar_star
= oe
;
10807 remove_quoted_nulls (tlist
->word
->word
);
10808 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
10810 dequote_list (tlist
);
10811 ret
= string_list (tlist
);
10812 dispose_words (tlist
);
10819 /* Expand the subscript in STRING, which is an array reference. To ensure we
10820 only expand it once, we quote the characters that would start another
10821 expansion and the bracket characters that are special to array subscripts. */
10823 expand_array_subscript (string
, sindex
, quoted
, flags
)
10828 char *ret
, *exp
, *t
;
10833 slen
= STRLEN (string
);
10835 if (abstab
[0] == '\1')
10837 /* These are basically the characters that start shell expansions plus
10838 the characters that delimit subscripts. */
10839 memset (abstab
, '\0', sizeof (abstab
));
10840 abstab
[LBRACK
] = abstab
[RBRACK
] = 1;
10841 abstab
['$'] = abstab
['`'] = abstab
['~'] = 1;
10842 abstab
['\\'] = abstab
['\''] = 1;
10843 abstab
['"'] = 1; /* XXX */
10844 /* We don't quote `@' or `*' in the subscript at all. */
10847 /* string[si] == LBRACK */
10848 ni
= skipsubscript (string
, si
, 0);
10849 /* These checks mirror the ones in valid_array_reference. The check for
10850 (ni - si) == 1 checks for empty subscripts. We don't check that the
10851 subscript is a separate word if we're parsing an arithmetic expression. */
10852 if (ni
>= slen
|| string
[ni
] != RBRACK
|| (ni
- si
) == 1 ||
10853 (string
[ni
+1] != '\0' && (quoted
& Q_ARITH
) == 0))
10855 /* let's check and see what fails this check */
10856 INTERNAL_DEBUG (("expand_array_subscript: bad subscript string: `%s'", string
+si
));
10857 ret
= (char *)xmalloc (2); /* badly-formed subscript */
10858 ret
[0] = string
[si
];
10864 /* STRING[ni] == RBRACK */
10865 exp
= substring (string
, si
+1, ni
);
10866 t
= expand_subscript_string (exp
, quoted
& ~(Q_ARITH
|Q_DOUBLE_QUOTES
));
10868 exp
= t
? sh_backslash_quote (t
, abstab
, 0) : savestring ("");
10871 slen
= STRLEN (exp
);
10872 ret
= xmalloc (slen
+ 2 + 1);
10874 strcpy (ret
+ 1, exp
);
10875 ret
[slen
+ 1] = ']';
10876 ret
[slen
+ 2] = '\0';
10886 invalidate_cached_quoted_dollar_at ()
10888 dispose_words (cached_quoted_dollar_at
);
10889 cached_quoted_dollar_at
= 0;
10892 /* Make a word list which is the result of parameter and variable
10893 expansion, command substitution, arithmetic substitution, and
10894 quote removal of WORD. Return a pointer to a WORD_LIST which is
10895 the result of the expansion. If WORD contains a null word, the
10896 word list returned is also null.
10898 QUOTED contains flag values defined in shell.h.
10900 ISEXP is used to tell expand_word_internal that the word should be
10901 treated as the result of an expansion. This has implications for
10902 how IFS characters in the word are treated.
10904 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
10905 they point to an integer value which receives information about expansion.
10906 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
10907 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
10910 This only does word splitting in the case of $@ expansion. In that
10911 case, we split on ' '. */
10913 /* Values for the local variable quoted_state. */
10915 #define PARTIALLY_QUOTED 1
10916 #define WHOLLY_QUOTED 2
10919 expand_word_internal (word
, quoted
, isexp
, contains_dollar_at
, expanded_something
)
10922 int *contains_dollar_at
;
10923 int *expanded_something
;
10928 /* The intermediate string that we build while expanding. */
10931 /* The current size of the above object. */
10932 size_t istring_size
;
10934 /* Index into ISTRING. */
10935 size_t istring_index
;
10937 /* Temporary string storage. */
10938 char *temp
, *temp1
;
10940 /* The text of WORD. */
10941 register char *string
;
10943 /* The size of STRING. */
10944 size_t string_size
;
10946 /* The index into STRING. */
10949 /* This gets 1 if we see a $@ while quoted. */
10950 int quoted_dollar_at
;
10952 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
10953 whether WORD contains no quoting characters, a partially quoted
10954 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
10958 int had_quoted_null
;
10959 int has_quoted_ifs
; /* did we add a quoted $IFS character here? */
10960 int has_dollar_at
, temp_has_dollar_at
;
10961 int internal_tilde
;
10962 int split_on_spaces
;
10963 int local_expanded
;
10965 int pflags
; /* flags passed to param_expand */
10968 int assignoff
; /* If assignment, offset of `=' */
10970 register unsigned char c
; /* Current character. */
10971 int t_index
; /* For calls to string_extract_xxx. */
10977 /* OK, let's see if we can optimize a common idiom: "$@". This needs to make sure
10978 that all of the flags callers care about (e.g., W_HASQUOTEDNULL) are set in
10980 if (STREQ (word
->word
, "\"$@\"") &&
10981 (word
->flags
== (W_HASDOLLAR
|W_QUOTED
)) &&
10982 dollar_vars
[1]) /* XXX - check IFS here as well? */
10984 if (contains_dollar_at
)
10985 *contains_dollar_at
= 1;
10986 if (expanded_something
)
10987 *expanded_something
= 1;
10988 if (cached_quoted_dollar_at
)
10989 return (copy_word_list (cached_quoted_dollar_at
));
10990 list
= list_rest_of_args ();
10991 list
= quote_list (list
);
10992 cached_quoted_dollar_at
= copy_word_list (list
);
10996 istring
= (char *)xmalloc (istring_size
= DEFAULT_INITIAL_ARRAY_SIZE
);
10997 istring
[istring_index
= 0] = '\0';
10998 quoted_dollar_at
= had_quoted_null
= has_dollar_at
= 0;
10999 has_quoted_ifs
= 0;
11000 split_on_spaces
= 0;
11001 internal_tilde
= 0; /* expanding =~ or :~ */
11002 quoted_state
= UNQUOTED
;
11004 string
= word
->word
;
11006 goto finished_with_string
;
11007 mb_cur_max
= MB_CUR_MAX
;
11009 /* Don't need the string length for the SADD... and COPY_ macros unless
11010 multibyte characters are possible, but do need it for bounds checking. */
11011 string_size
= (mb_cur_max
> 1) ? strlen (string
) : 1;
11013 if (contains_dollar_at
)
11014 *contains_dollar_at
= 0;
11018 /* Begin the expansion. */
11020 for (sindex
= 0; ;)
11022 c
= string
[sindex
];
11024 /* Case on top-level character. */
11028 goto finished_with_string
;
11032 #if HANDLE_MULTIBYTE
11033 if (mb_cur_max
> 1 && string
[sindex
])
11035 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
11040 temp
= (char *)xmalloc (3);
11042 temp
[1] = c
= string
[sindex
];
11047 if (string
[sindex
])
11053 istring
= sub_append_string (temp
, istring
, &istring_index
, &istring_size
);
11059 #if defined (PROCESS_SUBSTITUTION)
11060 /* Process substitution. */
11064 /* XXX - technically this should only be expanded at the start
11066 if (string
[++sindex
] != LPAREN
|| (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (word
->flags
& W_NOPROCSUB
))
11068 sindex
--; /* add_character: label increments sindex */
11069 goto add_character
;
11072 t_index
= sindex
+ 1; /* skip past both '<' and LPAREN */
11074 temp1
= extract_process_subst (string
, (c
== '<') ? "<(" : ">(", &t_index
, 0); /*))*/
11077 /* If the process substitution specification is `<()', we want to
11078 open the pipe for writing in the child and produce output; if
11079 it is `>()', we want to open the pipe for reading in the child
11080 and consume input. */
11081 temp
= temp1
? process_substitute (temp1
, (c
== '>')) : (char *)0;
11085 goto dollar_add_string
;
11087 #endif /* PROCESS_SUBSTITUTION */
11089 #if defined (ARRAY_VARS)
11091 if ((quoted
& Q_ARITH
) == 0 || shell_compatibility_level
<= 51)
11093 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
11094 goto add_ifs_character
;
11096 goto add_character
;
11100 temp
= expand_array_subscript (string
, &sindex
, quoted
, word
->flags
);
11106 /* Posix.2 section 3.6.1 says that tildes following `=' in words
11107 which are not assignment statements are not expanded. If the
11108 shell isn't in posix mode, though, we perform tilde expansion
11109 on `likely candidate' unquoted assignment statements (flags
11110 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
11111 contains an unquoted :~ or =~. Something to think about: we
11112 now have a flag that says to perform tilde expansion on arguments
11113 to `assignment builtins' like declare and export that look like
11114 assignment statements. We now do tilde expansion on such words
11115 even in POSIX mode. */
11116 if (word
->flags
& (W_ASSIGNRHS
|W_NOTILDE
))
11118 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11119 goto add_ifs_character
;
11121 goto add_character
;
11123 /* If we're not in posix mode or forcing assignment-statement tilde
11124 expansion, note where the first `=' appears in the word and prepare
11125 to do tilde expansion following the first `='. We have to keep
11126 track of the first `=' (using assignoff) to avoid being confused
11127 by an `=' in the rhs of the assignment statement. */
11128 if ((word
->flags
& W_ASSIGNMENT
) &&
11129 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
11130 assignoff
== -1 && sindex
> 0)
11131 assignoff
= sindex
;
11132 if (sindex
== assignoff
&& string
[sindex
+1] == '~') /* XXX */
11133 internal_tilde
= 1;
11135 if (word
->flags
& W_ASSIGNARG
)
11136 word
->flags
|= W_ASSIGNRHS
; /* affects $@ */
11138 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11141 goto add_ifs_character
;
11144 goto add_character
;
11147 if (word
->flags
& (W_NOTILDE
|W_NOASSNTILDE
))
11149 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11150 goto add_ifs_character
;
11152 goto add_character
;
11155 if ((word
->flags
& (W_ASSIGNMENT
|W_ASSIGNRHS
)) &&
11156 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
11157 string
[sindex
+1] == '~')
11158 internal_tilde
= 1;
11160 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11161 goto add_ifs_character
;
11163 goto add_character
;
11166 /* If the word isn't supposed to be tilde expanded, or we're not
11167 at the start of a word or after an unquoted : or = in an
11168 assignment statement, we don't do tilde expansion. We don't
11169 do tilde expansion if quoted or in an arithmetic context. */
11171 if ((word
->flags
& W_NOTILDE
) ||
11172 (sindex
> 0 && (internal_tilde
== 0)) ||
11173 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
11175 internal_tilde
= 0;
11176 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
11177 goto add_ifs_character
;
11179 goto add_character
;
11182 if (word
->flags
& W_ASSIGNRHS
)
11184 else if (word
->flags
& (W_ASSIGNMENT
|W_TILDEEXP
))
11189 temp
= bash_tilde_find_word (string
+ sindex
, tflag
, &t_index
);
11191 internal_tilde
= 0;
11193 if (temp
&& *temp
&& t_index
> 0)
11195 temp1
= bash_tilde_expand (temp
, tflag
);
11196 if (temp1
&& *temp1
== '~' && STREQ (temp
, temp1
))
11200 goto add_character
; /* tilde expansion failed */
11205 goto add_quoted_string
; /* XXX was add_string */
11210 goto add_character
;
11214 if (expanded_something
)
11215 *expanded_something
= 1;
11216 local_expanded
= 1;
11218 temp_has_dollar_at
= 0;
11219 pflags
= (word
->flags
& W_NOCOMSUB
) ? PF_NOCOMSUB
: 0;
11220 if (word
->flags
& W_NOSPLIT2
)
11221 pflags
|= PF_NOSPLIT2
;
11222 if (word
->flags
& W_ASSIGNRHS
)
11223 pflags
|= PF_ASSIGNRHS
;
11224 if (word
->flags
& W_COMPLETE
)
11225 pflags
|= PF_COMPLETE
;
11227 tword
= param_expand (string
, &sindex
, quoted
, expanded_something
,
11228 &temp_has_dollar_at
, "ed_dollar_at
,
11229 &had_quoted_null
, pflags
);
11230 has_dollar_at
+= temp_has_dollar_at
;
11231 split_on_spaces
+= (tword
->flags
& W_SPLITSPACE
);
11233 if (tword
== &expand_wdesc_error
|| tword
== &expand_wdesc_fatal
)
11237 return ((tword
== &expand_wdesc_error
) ? &expand_word_error
11238 : &expand_word_fatal
);
11240 if (contains_dollar_at
&& has_dollar_at
)
11241 *contains_dollar_at
= 1;
11243 if (tword
&& (tword
->flags
& W_HASQUOTEDNULL
))
11244 had_quoted_null
= 1; /* note for later */
11245 if (tword
&& (tword
->flags
& W_SAWQUOTEDNULL
))
11246 had_quoted_null
= 1; /* XXX */
11248 temp
= tword
? tword
->word
: (char *)NULL
;
11249 dispose_word_desc (tword
);
11251 /* Kill quoted nulls; we will add them back at the end of
11252 expand_word_internal if nothing else in the string */
11253 if (had_quoted_null
&& temp
&& QUOTED_NULL (temp
))
11256 temp
= (char *)NULL
;
11262 case '`': /* Backquoted command substitution. */
11264 t_index
= sindex
++;
11266 temp
= string_extract (string
, &sindex
, "`", (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: SX_REQMATCH
);
11267 /* The test of sindex against t_index is to allow bare instances of
11268 ` to pass through, for backwards compatibility. */
11269 if (temp
== &extract_string_error
|| temp
== &extract_string_fatal
)
11271 if (sindex
- 1 == t_index
)
11274 goto add_character
;
11276 set_exit_status (EXECUTION_FAILURE
);
11277 report_error (_("bad substitution: no closing \"`\" in %s") , string
+t_index
);
11280 return ((temp
== &extract_string_error
) ? &expand_word_error
11281 : &expand_word_fatal
);
11284 if (expanded_something
)
11285 *expanded_something
= 1;
11286 local_expanded
= 1;
11288 if (word
->flags
& W_NOCOMSUB
)
11289 /* sindex + 1 because string[sindex] == '`' */
11290 temp1
= substring (string
, t_index
, sindex
+ 1);
11293 de_backslash (temp
);
11294 tword
= command_substitute (temp
, quoted
, 0);
11295 temp1
= tword
? tword
->word
: (char *)NULL
;
11297 dispose_word_desc (tword
);
11301 goto dollar_add_string
;
11305 if (string
[sindex
+ 1] == '\n')
11311 c
= string
[++sindex
];
11313 /* "However, the double-quote character ( '"' ) shall not be treated
11314 specially within a here-document, except when the double-quote
11315 appears within "$()", "``", or "${}"." */
11316 if ((quoted
& Q_HERE_DOCUMENT
) && (quoted
& Q_DOLBRACE
) && c
== '"')
11317 tflag
= CBSDQUOTE
; /* special case */
11318 else if (quoted
& Q_HERE_DOCUMENT
)
11320 else if (quoted
& Q_DOUBLE_QUOTES
)
11325 /* From Posix discussion on austin-group list: Backslash escaping
11326 a } in ${...} is removed. Issue 0000221 */
11327 if ((quoted
& Q_DOLBRACE
) && c
== RBRACE
)
11329 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11331 /* This is the fix for " $@\ " */
11332 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0) && isexp
== 0 && isifs (c
))
11334 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11335 DEFAULT_ARRAY_SIZE
);
11336 istring
[istring_index
++] = CTLESC
;
11337 istring
[istring_index
++] = '\\';
11338 istring
[istring_index
] = '\0';
11340 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11342 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && c
== 0)
11344 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11345 DEFAULT_ARRAY_SIZE
);
11346 istring
[istring_index
++] = CTLESC
;
11347 istring
[istring_index
++] = '\\';
11348 istring
[istring_index
] = '\0';
11351 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0))
11353 SCOPY_CHAR_I (twochars
, '\\', c
, string
, sindex
, string_size
);
11358 sindex
--; /* add_character: label increments sindex */
11359 goto add_character
;
11363 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11368 /* BEFORE jumping here, we need to increment sindex if appropriate */
11369 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11370 DEFAULT_ARRAY_SIZE
);
11371 istring
[istring_index
++] = twochars
[0];
11372 istring
[istring_index
++] = twochars
[1];
11373 istring
[istring_index
] = '\0';
11378 /* XXX - revisit this */
11379 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && ((quoted
& Q_ARITH
) == 0))
11380 goto add_character
;
11382 t_index
= ++sindex
;
11383 temp
= string_extract_double_quoted (string
, &sindex
, (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: 0);
11385 /* If the quotes surrounded the entire string, then the
11386 whole word was quoted. */
11387 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
11389 : PARTIALLY_QUOTED
;
11393 tword
= alloc_word_desc ();
11394 tword
->word
= temp
;
11396 if (word
->flags
& W_ASSIGNARG
)
11397 tword
->flags
|= word
->flags
& (W_ASSIGNARG
|W_ASSIGNRHS
); /* affects $@ */
11398 if (word
->flags
& W_COMPLETE
)
11399 tword
->flags
|= W_COMPLETE
; /* for command substitutions */
11400 if (word
->flags
& W_NOCOMSUB
)
11401 tword
->flags
|= W_NOCOMSUB
;
11402 if (word
->flags
& W_NOPROCSUB
)
11403 tword
->flags
|= W_NOPROCSUB
;
11405 if (word
->flags
& W_ASSIGNRHS
)
11406 tword
->flags
|= W_ASSIGNRHS
;
11408 temp
= (char *)NULL
;
11410 temp_has_dollar_at
= 0; /* does this quoted (sub)string include $@? */
11411 /* Need to get W_HASQUOTEDNULL flag through this function. */
11412 /* XXX - preserve Q_ARITH here? */
11413 list
= expand_word_internal (tword
, Q_DOUBLE_QUOTES
|(quoted
&Q_ARITH
), 0, &temp_has_dollar_at
, (int *)NULL
);
11414 has_dollar_at
+= temp_has_dollar_at
;
11416 if (list
== &expand_word_error
|| list
== &expand_word_fatal
)
11420 /* expand_word_internal has already freed temp_word->word
11421 for us because of the way it prints error messages. */
11422 tword
->word
= (char *)NULL
;
11423 dispose_word (tword
);
11427 dispose_word (tword
);
11429 /* "$@" (a double-quoted dollar-at) expands into nothing,
11430 not even a NULL word, when there are no positional
11431 parameters. Posix interp 888 says that other parts of the
11432 word that expand to quoted nulls result in quoted nulls, so
11433 we can't just throw the entire word away if we have "$@"
11434 anywhere in it. We use had_quoted_null to keep track */
11435 if (list
== 0 && temp_has_dollar_at
) /* XXX - was has_dollar_at */
11437 quoted_dollar_at
++;
11441 /* If this list comes back with a quoted null from expansion,
11442 we have either "$x" or "$@" with $1 == ''. In either case,
11443 we need to make sure we add a quoted null argument and
11444 disable the special handling that "$@" gets. */
11445 if (list
&& list
->word
&& list
->next
== 0 && (list
->word
->flags
& W_HASQUOTEDNULL
))
11447 if (had_quoted_null
&& temp_has_dollar_at
)
11448 quoted_dollar_at
++;
11449 had_quoted_null
= 1; /* XXX */
11452 /* If we get "$@", we know we have expanded something, so we
11453 need to remember it for the final split on $IFS. This is
11454 a special case; it's the only case where a quoted string
11455 can expand into more than one word. It's going to come back
11456 from the above call to expand_word_internal as a list with
11459 dequote_list (list
);
11461 if (temp_has_dollar_at
) /* XXX - was has_dollar_at */
11463 quoted_dollar_at
++;
11464 if (contains_dollar_at
)
11465 *contains_dollar_at
= 1;
11466 if (expanded_something
)
11467 *expanded_something
= 1;
11468 local_expanded
= 1;
11473 /* What we have is "". This is a minor optimization. */
11475 list
= (WORD_LIST
*)NULL
;
11476 had_quoted_null
= 1; /* note for later */
11479 /* The code above *might* return a list (consider the case of "$@",
11480 where it returns "$1", "$2", etc.). We can't throw away the
11481 rest of the list, and we have to make sure each word gets added
11482 as quoted. We test on tresult->next: if it is non-NULL, we
11483 quote the whole list, save it to a string with string_list, and
11484 add that string. We don't need to quote the results of this
11485 (and it would be wrong, since that would quote the separators
11486 as well), so we go directly to add_string. */
11491 /* Testing quoted_dollar_at makes sure that "$@" is
11492 split correctly when $IFS does not contain a space. */
11493 temp
= quoted_dollar_at
11494 ? string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, 0)
11495 : string_list (quote_list (list
));
11496 dispose_words (list
);
11501 temp
= savestring (list
->word
->word
);
11502 tflag
= list
->word
->flags
;
11503 dispose_words (list
);
11505 /* If the string is not a quoted null string, we want
11506 to remove any embedded unquoted CTLNUL characters.
11507 We do not want to turn quoted null strings back into
11508 the empty string, though. We do this because we
11509 want to remove any quoted nulls from expansions that
11510 contain other characters. For example, if we have
11511 x"$*"y or "x$*y" and there are no positional parameters,
11512 the $* should expand into nothing. */
11513 /* We use the W_HASQUOTEDNULL flag to differentiate the
11514 cases: a quoted null character as above and when
11515 CTLNUL is contained in the (non-null) expansion
11516 of some variable. We use the had_quoted_null flag to
11517 pass the value through this function to its caller. */
11518 if ((tflag
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
) == 0)
11519 remove_quoted_nulls (temp
); /* XXX */
11523 temp
= (char *)NULL
;
11525 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
11526 had_quoted_null
= 1; /* note for later */
11528 /* We do not want to add quoted nulls to strings that are only
11529 partially quoted; we can throw them away. The exception to
11530 this is when we are going to be performing word splitting,
11531 since we have to preserve a null argument if the next character
11532 will cause word splitting. */
11533 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
11537 had_quoted_null
= 1;
11538 goto add_character
;
11540 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
11548 temp
= quote_string (temp
);
11554 /* Add NULL arg. */
11556 sindex
--; /* add_character: label increments sindex */
11557 had_quoted_null
= 1; /* note for later */
11558 goto add_character
;
11564 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
11565 goto add_character
;
11567 t_index
= ++sindex
;
11568 temp
= string_extract_single_quoted (string
, &sindex
, 0);
11570 /* If the entire STRING was surrounded by single quotes,
11571 then the string is wholly quoted. */
11572 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
11574 : PARTIALLY_QUOTED
;
11576 /* If all we had was '', it is a null expansion. */
11580 temp
= (char *)NULL
;
11583 remove_quoted_escapes (temp
); /* ??? */
11585 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
11586 had_quoted_null
= 1; /* note for later */
11588 /* We do not want to add quoted nulls to strings that are only
11589 partially quoted; such nulls are discarded. See above for the
11590 exception, which is when the string is going to be split.
11591 Posix interp 888/1129 */
11592 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
11596 goto add_character
;
11599 if (temp
== 0 && (quoted_state
== PARTIALLY_QUOTED
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
11602 /* If we have a quoted null expansion, add a quoted NULL to istring. */
11606 sindex
--; /* add_character: label increments sindex */
11607 goto add_character
;
11610 goto add_quoted_string
;
11615 /* If we are in a context where the word is not going to be split, but
11616 we need to account for $@ and $* producing one word for each
11617 positional parameter, add quoted spaces so the spaces in the
11618 expansion of "$@", if any, behave correctly. We still may need to
11619 split if we are expanding the rhs of a word expansion. */
11620 if (ifs_is_null
|| split_on_spaces
|| ((word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
|W_ASSIGNRHS
)) && (word
->flags
& W_EXPANDRHS
) == 0))
11622 if (string
[sindex
])
11624 twochars
[0] = CTLESC
;
11631 /* This is the fix for " $@ " */
11633 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (isexp
== 0 && isifs (c
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0))
11635 if ((quoted
&(Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0)
11637 add_quoted_character
:
11638 if (string
[sindex
]) /* from old goto dollar_add_string */
11643 goto add_character
;
11647 #if HANDLE_MULTIBYTE
11648 /* XXX - should make sure that c is actually multibyte,
11649 otherwise we can use the twochars branch */
11650 if (mb_cur_max
> 1)
11653 if (mb_cur_max
> 1)
11655 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
11660 twochars
[0] = CTLESC
;
11667 SADD_MBCHAR (temp
, string
, sindex
, string_size
);
11670 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 1, istring_size
,
11671 DEFAULT_ARRAY_SIZE
);
11672 istring
[istring_index
++] = c
;
11673 istring
[istring_index
] = '\0';
11675 /* Next character. */
11680 finished_with_string
:
11681 /* OK, we're ready to return. If we have a quoted string, and
11682 quoted_dollar_at is not set, we do no splitting at all; otherwise
11683 we split on ' '. The routines that call this will handle what to
11684 do if nothing has been expanded. */
11686 /* Partially and wholly quoted strings which expand to the empty
11687 string are retained as an empty arguments. Unquoted strings
11688 which expand to the empty string are discarded. The single
11689 exception is the case of expanding "$@" when there are no
11690 positional parameters. In that case, we discard the expansion. */
11692 /* Because of how the code that handles "" and '' in partially
11693 quoted strings works, we need to make ISTRING into a QUOTED_NULL
11694 if we saw quoting characters, but the expansion was empty.
11695 "" and '' are tossed away before we get to this point when
11696 processing partially quoted strings. This makes "" and $xxx""
11697 equivalent when xxx is unset. We also look to see whether we
11698 saw a quoted null from a ${} expansion and add one back if we
11701 /* If we expand to nothing and there were no single or double quotes
11702 in the word, we throw it away. Otherwise, we return a NULL word.
11703 The single exception is for $@ surrounded by double quotes when
11704 there are no positional parameters. In that case, we also throw
11707 if (*istring
== '\0')
11710 if (quoted_dollar_at
== 0 && (had_quoted_null
|| quoted_state
== PARTIALLY_QUOTED
))
11712 if (had_quoted_null
|| (quoted_dollar_at
== 0 && quoted_state
== PARTIALLY_QUOTED
))
11715 istring
[0] = CTLNUL
;
11717 tword
= alloc_word_desc ();
11718 tword
->word
= istring
;
11719 istring
= 0; /* avoid later free() */
11720 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11721 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11722 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
11723 tword
->flags
|= W_QUOTED
;
11725 /* According to sh, ksh, and Posix.2, if a word expands into nothing
11726 and a double-quoted "$@" appears anywhere in it, then the entire
11727 word is removed. */
11728 /* XXX - exception appears to be that quoted null strings result in
11730 else if (quoted_state
== UNQUOTED
|| quoted_dollar_at
)
11731 list
= (WORD_LIST
*)NULL
;
11733 list
= (WORD_LIST
*)NULL
;
11735 else if (word
->flags
& W_NOSPLIT
)
11737 tword
= alloc_word_desc ();
11738 tword
->word
= istring
;
11739 if (had_quoted_null
&& QUOTED_NULL (istring
))
11740 tword
->flags
|= W_HASQUOTEDNULL
;
11741 istring
= 0; /* avoid later free() */
11742 if (word
->flags
& W_ASSIGNMENT
)
11743 tword
->flags
|= W_ASSIGNMENT
; /* XXX */
11744 if (word
->flags
& W_COMPASSIGN
)
11745 tword
->flags
|= W_COMPASSIGN
; /* XXX */
11746 if (word
->flags
& W_NOGLOB
)
11747 tword
->flags
|= W_NOGLOB
; /* XXX */
11748 if (word
->flags
& W_NOBRACE
)
11749 tword
->flags
|= W_NOBRACE
; /* XXX */
11750 if (word
->flags
& W_ARRAYREF
)
11751 tword
->flags
|= W_ARRAYREF
;
11752 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
11753 tword
->flags
|= W_QUOTED
;
11754 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11756 else if (word
->flags
& W_ASSIGNRHS
)
11758 list
= list_string (istring
, "", quoted
);
11759 tword
= list
->word
;
11760 if (had_quoted_null
&& QUOTED_NULL (istring
))
11761 tword
->flags
|= W_HASQUOTEDNULL
;
11764 istring
= 0; /* avoid later free() */
11765 goto set_word_flags
;
11771 ifs_chars
= (quoted_dollar_at
|| has_dollar_at
) ? ifs_value
: (char *)NULL
;
11773 /* If we have $@, we need to split the results no matter what. If
11774 IFS is unset or NULL, string_list_dollar_at has separated the
11775 positional parameters with a space, so we split on space (we have
11776 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
11777 string_list_dollar_at has separated the positional parameters
11778 with the first character of $IFS, so we split on $IFS. If
11779 SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
11780 unset or null, and we want to make sure that we split on spaces
11781 regardless of what else has happened to IFS since the expansion,
11782 or we expanded "$@" with IFS null and we need to split the positional
11783 parameters into separate words. */
11784 if (split_on_spaces
)
11786 /* If IFS is not set, and the word is not quoted, we want to split
11787 the individual words on $' \t\n'. We rely on previous steps to
11788 quote the portions of the word that should not be split */
11789 if (ifs_is_set
== 0)
11790 list
= list_string (istring
, " \t\n", 1); /* XXX quoted == 1? */
11792 list
= list_string (istring
, " ", 1); /* XXX quoted == 1? */
11795 /* If we have $@ (has_dollar_at != 0) and we are in a context where we
11796 don't want to split the result (W_NOSPLIT2), and we are not quoted,
11797 we have already separated the arguments with the first character of
11798 $IFS. In this case, we want to return a list with a single word
11799 with the separator possibly replaced with a space (it's what other
11800 shells seem to do).
11801 quoted_dollar_at is internal to this function and is set if we are
11802 passed an argument that is unquoted (quoted == 0) but we encounter a
11803 double-quoted $@ while expanding it. */
11804 else if (has_dollar_at
&& quoted_dollar_at
== 0 && ifs_chars
&& quoted
== 0 && (word
->flags
& W_NOSPLIT2
))
11806 tword
= alloc_word_desc ();
11807 /* Only split and rejoin if we have to */
11808 if (*ifs_chars
&& *ifs_chars
!= ' ')
11810 /* list_string dequotes CTLESCs in the string it's passed, so we
11811 need it to get the space separation right if space isn't the
11812 first character in IFS (but is present) and to remove the
11813 quoting we added back in param_expand(). */
11814 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
11815 /* This isn't exactly right in the case where we're expanding
11816 the RHS of an expansion like ${var-$@} where IFS=: (for
11817 example). The W_NOSPLIT2 means we do the separation with :;
11818 the list_string removes the quotes and breaks the string into
11819 a list, and the string_list rejoins it on spaces. When we
11820 return, we expect to be able to split the results, but the
11821 space separation means the right split doesn't happen. */
11822 tword
->word
= string_list (list
);
11825 tword
->word
= istring
;
11826 if (had_quoted_null
&& QUOTED_NULL (istring
))
11827 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11828 if (tword
->word
!= istring
)
11830 istring
= 0; /* avoid later free() */
11831 goto set_word_flags
;
11833 else if (has_dollar_at
&& ifs_chars
)
11834 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
11837 tword
= alloc_word_desc ();
11838 if (expanded_something
&& *expanded_something
== 0 && has_quoted_ifs
)
11839 tword
->word
= remove_quoted_ifs (istring
);
11841 tword
->word
= istring
;
11842 if (had_quoted_null
&& QUOTED_NULL (istring
)) /* should check for more than one */
11843 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11844 else if (had_quoted_null
)
11845 tword
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
11846 if (tword
->word
!= istring
)
11848 istring
= 0; /* avoid later free() */
11850 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || (quoted_state
== WHOLLY_QUOTED
))
11851 tword
->flags
|= W_QUOTED
;
11852 if (word
->flags
& W_ASSIGNMENT
)
11853 tword
->flags
|= W_ASSIGNMENT
;
11854 if (word
->flags
& W_COMPASSIGN
)
11855 tword
->flags
|= W_COMPASSIGN
;
11856 if (word
->flags
& W_NOGLOB
)
11857 tword
->flags
|= W_NOGLOB
;
11858 if (word
->flags
& W_NOBRACE
)
11859 tword
->flags
|= W_NOBRACE
;
11860 if (word
->flags
& W_ARRAYREF
)
11861 tword
->flags
|= W_ARRAYREF
;
11862 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11870 /* **************************************************************** */
11872 /* Functions for Quote Removal */
11874 /* **************************************************************** */
11876 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
11877 backslash quoting rules for within double quotes or a here document. */
11879 string_quote_removal (string
, quoted
)
11884 char *r
, *result_string
, *temp
, *send
;
11885 int sindex
, tindex
, dquote
;
11889 /* The result can be no longer than the original string. */
11890 slen
= strlen (string
);
11891 send
= string
+ slen
;
11893 r
= result_string
= (char *)xmalloc (slen
+ 1);
11895 for (dquote
= sindex
= 0; c
= string
[sindex
];)
11900 c
= string
[++sindex
];
11906 if (((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
) && (sh_syntaxtab
[c
] & CBSDQUOTE
) == 0)
11911 SCOPY_CHAR_M (r
, string
, send
, sindex
);
11915 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
)
11921 tindex
= sindex
+ 1;
11922 temp
= string_extract_single_quoted (string
, &tindex
, 0);
11933 dquote
= 1 - dquote
;
11939 return (result_string
);
11944 /* Perform quote removal on word WORD. This allocates and returns a new
11947 word_quote_removal (word
, quoted
)
11954 t
= string_quote_removal (word
->word
, quoted
);
11955 w
= alloc_word_desc ();
11956 w
->word
= t
? t
: savestring ("");
11960 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
11961 the members of the list are treated as if they are surrounded by
11962 double quotes. Return a new list, or NULL if LIST is NULL. */
11964 word_list_quote_removal (list
, quoted
)
11968 WORD_LIST
*result
, *t
, *tresult
, *e
;
11970 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
11972 tresult
= make_word_list (word_quote_removal (t
->word
, quoted
), (WORD_LIST
*)NULL
);
11974 result
= (WORD_LIST
*) list_append (result
, tresult
);
11977 result
= e
= tresult
;
11990 /*******************************************
11992 * Functions to perform word splitting *
11994 *******************************************/
12004 ifs_value
= (v
&& value_cell (v
)) ? value_cell (v
) : " \t\n";
12006 ifs_is_set
= ifs_var
!= 0;
12007 ifs_is_null
= ifs_is_set
&& (*ifs_value
== 0);
12009 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
12010 handle multibyte chars in IFS */
12011 memset (ifs_cmap
, '\0', sizeof (ifs_cmap
));
12012 for (t
= ifs_value
; t
&& *t
; t
++)
12018 #if defined (HANDLE_MULTIBYTE)
12019 if (ifs_value
== 0)
12021 ifs_firstc
[0] = '\0'; /* XXX - ? */
12022 ifs_firstc_len
= 1;
12026 if (locale_utf8locale
&& UTF8_SINGLEBYTE (*ifs_value
))
12027 ifs_firstc_len
= (*ifs_value
!= 0) ? 1 : 0;
12031 ifs_len
= strnlen (ifs_value
, MB_CUR_MAX
);
12032 ifs_firstc_len
= MBLEN (ifs_value
, ifs_len
);
12034 if (ifs_firstc_len
== 1 || ifs_firstc_len
== 0 || MB_INVALIDCH (ifs_firstc_len
))
12036 ifs_firstc
[0] = ifs_value
[0];
12037 ifs_firstc
[1] = '\0';
12038 ifs_firstc_len
= 1;
12041 memcpy (ifs_firstc
, ifs_value
, ifs_firstc_len
);
12044 ifs_firstc
= ifs_value
? *ifs_value
: 0;
12054 /* This splits a single word into a WORD LIST on $IFS, but only if the word
12055 is not quoted. list_string () performs quote removal for us, even if we
12056 don't do any splitting. */
12058 word_split (w
, ifs_chars
)
12068 xifs
= ((w
->flags
& W_QUOTED
) || ifs_chars
== 0) ? "" : ifs_chars
;
12069 result
= list_string (w
->word
, xifs
, w
->flags
& W_QUOTED
);
12072 result
= (WORD_LIST
*)NULL
;
12077 /* Perform word splitting on LIST and return the RESULT. It is possible
12078 to return (WORD_LIST *)NULL. */
12080 word_list_split (list
)
12083 WORD_LIST
*result
, *t
, *tresult
, *e
;
12086 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
12088 tresult
= word_split (t
->word
, ifs_value
);
12089 /* POSIX 2.6: "If the complete expansion appropriate for a word results
12090 in an empty field, that empty field shall be deleted from the list
12091 of fields that form the completely expanded command, unless the
12092 original word contained single-quote or double-quote characters."
12093 This is where we handle these words that contain quoted null strings
12094 and other characters that expand to nothing after word splitting. */
12095 if (tresult
== 0 && t
->word
&& (t
->word
->flags
& W_SAWQUOTEDNULL
)) /* XXX */
12097 w
= alloc_word_desc ();
12098 w
->word
= (char *)xmalloc (1);
12100 tresult
= make_word_list (w
, (WORD_LIST
*)NULL
);
12102 #if defined (ARRAY_VARS)
12103 /* pass W_ARRAYREF through for words that are not split and are
12104 identical to the original word. */
12105 if (tresult
&& tresult
->next
== 0 && t
->next
== 0 && (t
->word
->flags
& W_ARRAYREF
) && STREQ (t
->word
->word
, tresult
->word
->word
))
12106 tresult
->word
->flags
|= W_ARRAYREF
;
12109 result
= e
= tresult
;
12120 /**************************************************
12122 * Functions to expand an entire WORD_LIST *
12124 **************************************************/
12126 /* Do any word-expansion-specific cleanup and jump to top_level */
12128 exp_jump_to_top_level (v
)
12131 set_pipestatus_from_exit (last_command_exit_value
);
12133 /* Cleanup code goes here. */
12134 expand_no_split_dollar_star
= 0; /* XXX */
12135 if (expanding_redir
)
12136 undo_partial_redirects ();
12137 expanding_redir
= 0;
12138 assigning_in_environment
= 0;
12140 if (parse_and_execute_level
== 0)
12141 top_level_cleanup (); /* from sig.c */
12143 jump_to_top_level (v
);
12146 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
12147 ELIST, and set ELIST to the new list. */
12148 #define PREPEND_LIST(nlist, elist) \
12149 do { nlist->next = elist; elist = nlist; } while (0)
12151 /* Separate out any initial variable assignments from TLIST. If set -k has
12152 been executed, remove all assignment statements from TLIST. Initial
12153 variable assignments and other environment assignments are placed
12154 on SUBST_ASSIGN_VARLIST. */
12156 separate_out_assignments (tlist
)
12159 register WORD_LIST
*vp
, *lp
;
12162 return ((WORD_LIST
*)NULL
);
12164 if (subst_assign_varlist
)
12165 dispose_words (subst_assign_varlist
); /* Clean up after previous error */
12167 subst_assign_varlist
= (WORD_LIST
*)NULL
;
12170 /* Separate out variable assignments at the start of the command.
12171 Loop invariant: vp->next == lp
12172 Loop postcondition:
12173 lp = list of words left after assignment statements skipped
12174 tlist = original list of words
12176 while (lp
&& (lp
->word
->flags
& W_ASSIGNMENT
))
12182 /* If lp != tlist, we have some initial assignment statements.
12183 We make SUBST_ASSIGN_VARLIST point to the list of assignment
12184 words and TLIST point to the remaining words. */
12187 subst_assign_varlist
= tlist
;
12188 /* ASSERT(vp->next == lp); */
12189 vp
->next
= (WORD_LIST
*)NULL
; /* terminate variable list */
12190 tlist
= lp
; /* remainder of word list */
12193 /* vp == end of variable list */
12194 /* tlist == remainder of original word list without variable assignments */
12196 /* All the words in tlist were assignment statements */
12197 return ((WORD_LIST
*)NULL
);
12199 /* ASSERT(tlist != NULL); */
12200 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
12202 /* If the -k option is in effect, we need to go through the remaining
12203 words, separate out the assignment words, and place them on
12204 SUBST_ASSIGN_VARLIST. */
12205 if (place_keywords_in_env
)
12207 WORD_LIST
*tp
; /* tp == running pointer into tlist */
12212 /* Loop Invariant: tp->next == lp */
12213 /* Loop postcondition: tlist == word list without assignment statements */
12216 if (lp
->word
->flags
& W_ASSIGNMENT
)
12218 /* Found an assignment statement, add this word to end of
12219 subst_assign_varlist (vp). */
12220 if (!subst_assign_varlist
)
12221 subst_assign_varlist
= vp
= lp
;
12228 /* Remove the word pointed to by LP from TLIST. */
12229 tp
->next
= lp
->next
;
12230 /* ASSERT(vp == lp); */
12231 lp
->next
= (WORD_LIST
*)NULL
;
12244 #define WEXP_VARASSIGN 0x001
12245 #define WEXP_BRACEEXP 0x002
12246 #define WEXP_TILDEEXP 0x004
12247 #define WEXP_PARAMEXP 0x008
12248 #define WEXP_PATHEXP 0x010
12250 /* All of the expansions, including variable assignments at the start of
12252 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
12254 /* All of the expansions except variable assignments at the start of
12256 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
12258 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
12259 expansion, command substitution, arithmetic expansion, word splitting, and
12261 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
12263 /* Take the list of words in LIST and do the various substitutions. Return
12264 a new list of words which is the expanded list, and without things like
12265 variable assignments. */
12268 expand_words (list
)
12271 return (expand_word_list_internal (list
, WEXP_ALL
));
12274 /* Same as expand_words (), but doesn't hack variable or environment
12277 expand_words_no_vars (list
)
12280 return (expand_word_list_internal (list
, WEXP_NOVARS
));
12284 expand_words_shellexp (list
)
12287 return (expand_word_list_internal (list
, WEXP_SHELLEXP
));
12291 glob_expand_word_list (tlist
, eflags
)
12295 char **glob_array
, *temp_string
;
12296 register int glob_index
;
12297 WORD_LIST
*glob_list
, *output_list
, *disposables
, *next
;
12301 output_list
= disposables
= (WORD_LIST
*)NULL
;
12302 glob_array
= (char **)NULL
;
12305 /* For each word, either globbing is attempted or the word is
12306 added to orig_list. If globbing succeeds, the results are
12307 added to orig_list and the word (tlist) is added to the list
12308 of disposable words. If globbing fails and failed glob
12309 expansions are left unchanged (the shell default), the
12310 original word is added to orig_list. If globbing fails and
12311 failed glob expansions are removed, the original word is
12312 added to the list of disposable words. orig_list ends up
12313 in reverse order and requires a call to REVERSE_LIST to
12314 be set right. After all words are examined, the disposable
12315 words are freed. */
12316 next
= tlist
->next
;
12318 /* If the word isn't an assignment and contains an unquoted
12319 pattern matching character, then glob it. */
12320 if ((tlist
->word
->flags
& W_NOGLOB
) == 0 &&
12321 unquoted_glob_pattern_p (tlist
->word
->word
))
12323 glob_array
= shell_glob_filename (tlist
->word
->word
, QGLOB_CTLESC
); /* XXX */
12325 /* Handle error cases.
12326 I don't think we should report errors like "No such file
12327 or directory". However, I would like to report errors
12328 like "Read failed". */
12330 if (glob_array
== 0 || GLOB_FAILED (glob_array
))
12332 glob_array
= (char **)xmalloc (sizeof (char *));
12333 glob_array
[0] = (char *)NULL
;
12336 /* Dequote the current word in case we have to use it. */
12337 if (glob_array
[0] == NULL
)
12339 temp_string
= dequote_string (tlist
->word
->word
);
12340 free (tlist
->word
->word
);
12341 tlist
->word
->word
= temp_string
;
12344 /* Make the array into a word list. */
12345 glob_list
= (WORD_LIST
*)NULL
;
12346 for (glob_index
= 0; glob_array
[glob_index
]; glob_index
++)
12348 tword
= make_bare_word (glob_array
[glob_index
]);
12349 glob_list
= make_word_list (tword
, glob_list
);
12354 output_list
= (WORD_LIST
*)list_append (glob_list
, output_list
);
12355 PREPEND_LIST (tlist
, disposables
);
12357 else if (fail_glob_expansion
!= 0)
12359 last_command_exit_value
= EXECUTION_FAILURE
;
12360 report_error (_("no match: %s"), tlist
->word
->word
);
12361 exp_jump_to_top_level (DISCARD
);
12363 else if (allow_null_glob_expansion
== 0)
12365 /* Failed glob expressions are left unchanged. */
12366 PREPEND_LIST (tlist
, output_list
);
12370 /* Failed glob expressions are removed. */
12371 PREPEND_LIST (tlist
, disposables
);
12376 /* Dequote the string. */
12377 temp_string
= dequote_string (tlist
->word
->word
);
12378 free (tlist
->word
->word
);
12379 tlist
->word
->word
= temp_string
;
12380 PREPEND_LIST (tlist
, output_list
);
12383 strvec_dispose (glob_array
);
12384 glob_array
= (char **)NULL
;
12390 dispose_words (disposables
);
12393 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
12395 return (output_list
);
12398 #if defined (BRACE_EXPANSION)
12400 brace_expand_word_list (tlist
, eflags
)
12404 register char **expansions
;
12406 WORD_LIST
*disposables
, *output_list
, *next
;
12410 for (disposables
= output_list
= (WORD_LIST
*)NULL
; tlist
; tlist
= next
)
12412 next
= tlist
->next
;
12414 if (tlist
->word
->flags
& W_NOBRACE
)
12416 /*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
12417 PREPEND_LIST (tlist
, output_list
);
12421 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
12423 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
12424 PREPEND_LIST (tlist
, output_list
);
12428 /* Only do brace expansion if the word has a brace character. If
12429 not, just add the word list element to BRACES and continue. In
12430 the common case, at least when running shell scripts, this will
12431 degenerate to a bunch of calls to `mbschr', and then what is
12432 basically a reversal of TLIST into BRACES, which is corrected
12433 by a call to REVERSE_LIST () on BRACES when the end of TLIST
12435 if (mbschr (tlist
->word
->word
, LBRACE
))
12437 expansions
= brace_expand (tlist
->word
->word
);
12439 for (eindex
= 0; temp_string
= expansions
[eindex
]; eindex
++)
12441 w
= alloc_word_desc ();
12442 w
->word
= temp_string
;
12444 /* If brace expansion didn't change the word, preserve
12445 the flags. We may want to preserve the flags
12446 unconditionally someday -- XXX */
12447 if (STREQ (temp_string
, tlist
->word
->word
))
12448 w
->flags
= tlist
->word
->flags
;
12450 w
= make_word_flags (w
, temp_string
);
12452 output_list
= make_word_list (w
, output_list
);
12456 /* Add TLIST to the list of words to be freed after brace
12457 expansion has been performed. */
12458 PREPEND_LIST (tlist
, disposables
);
12461 PREPEND_LIST (tlist
, output_list
);
12465 dispose_words (disposables
);
12468 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
12470 return (output_list
);
12474 #if defined (ARRAY_VARS)
12475 /* Take WORD, a compound array assignment, and internally run (for example),
12476 'declare -A w', where W is the variable name portion of WORD. OPTION is
12477 the list of options to supply to `declare'. CMD is the declaration command
12478 we are expanding right now; it's unused currently. */
12480 make_internal_declare (word
, option
, cmd
)
12489 w
= make_word (word
);
12491 t
= assignment (w
->word
, 0);
12492 if (w
->word
[t
] == '=')
12495 if (w
->word
[t
- 1] == '+') /* cut off any append op */
12496 w
->word
[t
- 1] = '\0';
12499 wl
= make_word_list (w
, (WORD_LIST
*)NULL
);
12500 wl
= make_word_list (make_word (option
), wl
);
12502 r
= declare_builtin (wl
);
12504 dispose_words (wl
);
12508 /* Expand VALUE in NAME[+]=( VALUE ) to a list of words. FLAGS is 1 if NAME
12509 is an associative array.
12511 If we are processing an indexed array, expand_compound_array_assignment
12512 will expand all the individual words and quote_compound_array_list will
12513 single-quote them. If we are processing an associative array, we use
12514 parse_string_to_word_list to split VALUE into a list of words instead of
12515 faking up a shell variable and calling expand_compound_array_assignment.
12516 expand_and_quote_assoc_word expands and single-quotes each word in VALUE
12517 together so we don't have problems finding the end of the subscript when
12520 Words in VALUE can be individual words, which are expanded and single-quoted,
12521 or words of the form [IND]=VALUE, which end up as explained below, as
12522 ['expanded-ind']='expanded-value'. */
12525 expand_oneword (value
, flags
)
12535 /* Indexed array */
12536 l
= expand_compound_array_assignment ((SHELL_VAR
*)NULL
, value
, flags
);
12537 /* Now we quote the results of the expansion above to prevent double
12539 quote_compound_array_list (l
, flags
);
12544 /* Associative array */
12545 l
= parse_string_to_word_list (value
, 1, "array assign");
12546 #if ASSOC_KVPAIR_ASSIGNMENT
12547 kvpair
= kvpair_assignment_p (l
);
12550 /* For associative arrays, with their arbitrary subscripts, we have to
12551 expand and quote in one step so we don't have to search for the
12552 closing right bracket more than once. */
12553 for (nl
= l
; nl
; nl
= nl
->next
)
12555 #if ASSOC_KVPAIR_ASSIGNMENT
12557 /* keys and values undergo the same set of expansions */
12558 t
= expand_and_quote_kvpair_word (nl
->word
->word
);
12561 if ((nl
->word
->flags
& W_ASSIGNMENT
) == 0)
12562 t
= sh_single_quote (nl
->word
->word
? nl
->word
->word
: "");
12564 t
= expand_and_quote_assoc_word (nl
->word
->word
, flags
);
12565 free (nl
->word
->word
);
12566 nl
->word
->word
= t
;
12572 /* Expand a single compound assignment argument to a declaration builtin.
12573 This word takes the form NAME[+]=( VALUE ). The NAME[+]= is passed through
12574 unchanged. The VALUE is expanded and each word in the result is single-
12575 quoted. Words of the form [key]=value end up as
12576 ['expanded-key']='expanded-value'. Associative arrays have special
12577 handling, see expand_oneword() above. The return value is
12578 NAME[+]=( expanded-and-quoted-VALUE ). */
12580 expand_compound_assignment_word (tlist
, flags
)
12586 char *value
, *temp
;
12588 /*itrace("expand_compound_assignment_word: original word = -%s-", tlist->word->word);*/
12589 t
= assignment (tlist
->word
->word
, 0);
12591 /* value doesn't have the open and close parens */
12593 value
= extract_array_assignment_list (tlist
->word
->word
+ t
+ 1, &oind
);
12594 /* This performs one round of expansion on the index/key and value and
12595 single-quotes each word in the result. */
12596 l
= expand_oneword (value
, flags
);
12599 value
= string_list (l
);
12602 wlen
= STRLEN (value
);
12604 /* Now, let's rebuild the string */
12605 temp
= xmalloc (t
+ 3 + wlen
+ 1); /* name[+]=(value) */
12606 memcpy (temp
, tlist
->word
->word
, ++t
);
12609 memcpy (temp
+ t
, value
, wlen
);
12613 /*itrace("expand_compound_assignment_word: reconstructed word = -%s-", temp);*/
12615 free (tlist
->word
->word
);
12616 tlist
->word
->word
= temp
;
12621 /* Expand and process an argument to a declaration command. We have already
12622 set flags in TLIST->word->flags depending on the declaration command
12623 (declare, local, etc.) and the options supplied to it (-a, -A, etc.).
12624 TLIST->word->word is of the form NAME[+]=( VALUE ).
12626 This does several things, all using pieces of other functions to get the
12627 evaluation sequence right. It's called for compound array assignments with
12628 the W_ASSIGNMENT flag set (basically, valid identifier names on the lhs).
12629 It parses out which flags need to be set for declare to create the variable
12630 correctly, then calls declare internally (make_internal_declare) to make
12631 sure the variable exists with the correct attributes. Before the variable
12632 is created, it calls expand_compound_assignment_word to expand VALUE to a
12633 list of words, appropriately quoted for further evaluation. This preserves
12634 the semantics of word-expansion-before-calling-builtins. Finally, it calls
12635 do_word_assignment to perform the expansion and assignment with the same
12636 expansion semantics as a standalone assignment statement (no word splitting,
12637 etc.) even though the word is single-quoted so all that needs to happen is
12640 expand_declaration_argument (tlist
, wcmd
)
12641 WORD_LIST
*tlist
, *wcmd
;
12643 char opts
[16], omap
[128];
12644 int t
, opti
, oind
, skip
, inheriting
;
12647 inheriting
= localvar_inherit
;
12649 if (tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
|W_CHKLOCAL
|W_ASSIGNARRAY
))
12650 opts
[opti
++] = '-';
12652 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
)) == (W_ASSIGNASSOC
|W_ASSNGLOBAL
))
12654 opts
[opti
++] = 'g';
12655 opts
[opti
++] = 'A';
12657 else if (tlist
->word
->flags
& W_ASSIGNASSOC
)
12659 opts
[opti
++] = 'A';
12661 else if ((tlist
->word
->flags
& (W_ASSIGNARRAY
|W_ASSNGLOBAL
)) == (W_ASSIGNARRAY
|W_ASSNGLOBAL
))
12663 opts
[opti
++] = 'g';
12664 opts
[opti
++] = 'a';
12666 else if (tlist
->word
->flags
& W_ASSIGNARRAY
)
12668 opts
[opti
++] = 'a';
12670 else if (tlist
->word
->flags
& W_ASSNGLOBAL
)
12671 opts
[opti
++] = 'g';
12673 if (tlist
->word
->flags
& W_CHKLOCAL
)
12674 opts
[opti
++] = 'G';
12676 /* If we have special handling note the integer attribute and others
12677 that transform the value upon assignment. What we do is take all
12678 of the option arguments and scan through them looking for options
12679 that cause such transformations, and add them to the `opts' array. */
12681 memset (omap
, '\0', sizeof (omap
));
12682 for (l
= wcmd
->next
; l
!= tlist
; l
= l
->next
)
12686 if (l
->word
->word
[0] != '-' && l
->word
->word
[0] != '+')
12687 break; /* non-option argument */
12688 if (l
->word
->word
[0] == '-' && l
->word
->word
[1] == '-' && l
->word
->word
[2] == 0)
12689 break; /* -- signals end of options */
12690 optchar
= l
->word
->word
[0];
12691 for (oind
= 1; l
->word
->word
[oind
]; oind
++)
12692 switch (l
->word
->word
[oind
])
12700 omap
[l
->word
->word
[oind
]] = 1;
12702 opts
[opti
++] = optchar
;
12709 for (oind
= 0; oind
< sizeof (omap
); oind
++)
12711 opts
[opti
++] = oind
;
12713 /* If there are no -a/-A options, but we have a compound assignment,
12714 we have a choice: we can set opts[0]='-', opts[1]='a', since the
12715 default is to create an indexed array, and call
12716 make_internal_declare with that, or we can just skip the -a and let
12717 declare_builtin deal with it. Once we're here, we're better set
12718 up for the latter, since we don't want to deal with looking up
12719 any existing variable here -- better to let declare_builtin do it.
12720 We need the variable created, though, especially if it's local, so
12721 we get the scoping right before we call do_word_assignment.
12722 To ensure that make_local_declare gets called, we add `--' if there
12723 aren't any options. */
12724 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSIGNARRAY
)) == 0)
12728 opts
[opti
++] = '-';
12729 opts
[opti
++] = '-';
12734 /* This isn't perfect, but it's a start. Improvements later. We expand
12735 tlist->word->word and single-quote the results to avoid multiple
12736 expansions by, say, do_assignment_internal(). We have to weigh the
12737 cost of reconstructing the compound assignment string with its single
12738 quoting and letting the declare builtin handle it. The single quotes
12739 will prevent any unwanted additional expansion or word splitting. */
12740 expand_compound_assignment_word (tlist
, (tlist
->word
->flags
& W_ASSIGNASSOC
) ? 1 : 0);
12745 t
= make_internal_declare (tlist
->word
->word
, opts
, wcmd
? wcmd
->word
->word
: (char *)0);
12746 if (t
!= EXECUTION_SUCCESS
)
12748 last_command_exit_value
= t
;
12749 if (tlist
->word
->flags
& W_FORCELOCAL
) /* non-fatal error */
12752 exp_jump_to_top_level (DISCARD
);
12758 t
= do_word_assignment (tlist
->word
, 0);
12761 last_command_exit_value
= EXECUTION_FAILURE
;
12762 exp_jump_to_top_level (DISCARD
);
12766 /* Now transform the word as ksh93 appears to do and go on */
12767 t
= assignment (tlist
->word
->word
, 0);
12768 tlist
->word
->word
[t
] = '\0';
12769 if (tlist
->word
->word
[t
- 1] == '+')
12770 tlist
->word
->word
[t
- 1] = '\0'; /* cut off append op */
12771 tlist
->word
->flags
&= ~(W_ASSIGNMENT
|W_NOSPLIT
|W_COMPASSIGN
|W_ASSIGNARG
|W_ASSIGNASSOC
|W_ASSIGNARRAY
);
12775 #endif /* ARRAY_VARS */
12778 shell_expand_word_list (tlist
, eflags
)
12782 WORD_LIST
*expanded
, *orig_list
, *new_list
, *next
, *temp_list
, *wcmd
;
12783 int expanded_something
, has_dollar_at
;
12785 /* We do tilde expansion all the time. This is what 1003.2 says. */
12786 wcmd
= new_list
= (WORD_LIST
*)NULL
;
12788 for (orig_list
= tlist
; tlist
; tlist
= next
)
12790 if (wcmd
== 0 && (tlist
->word
->flags
& W_ASSNBLTIN
))
12793 next
= tlist
->next
;
12795 #if defined (ARRAY_VARS)
12796 /* If this is a compound array assignment to a builtin that accepts
12797 such assignments (e.g., `declare'), take the assignment and perform
12798 it separately, handling the semantics of declarations inside shell
12799 functions. This avoids the double-evaluation of such arguments,
12800 because `declare' does some evaluation of compound assignments on
12802 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
12803 expand_declaration_argument (tlist
, wcmd
);
12806 expanded_something
= 0;
12807 expanded
= expand_word_internal
12808 (tlist
->word
, 0, 0, &has_dollar_at
, &expanded_something
);
12810 if (expanded
== &expand_word_error
|| expanded
== &expand_word_fatal
)
12812 /* By convention, each time this error is returned,
12813 tlist->word->word has already been freed. */
12814 tlist
->word
->word
= (char *)NULL
;
12816 /* Dispose our copy of the original list. */
12817 dispose_words (orig_list
);
12818 /* Dispose the new list we're building. */
12819 dispose_words (new_list
);
12821 last_command_exit_value
= EXECUTION_FAILURE
;
12822 if (expanded
== &expand_word_error
)
12823 exp_jump_to_top_level (DISCARD
);
12825 exp_jump_to_top_level (FORCE_EOF
);
12828 /* Don't split words marked W_NOSPLIT. */
12829 if (expanded_something
&& (tlist
->word
->flags
& W_NOSPLIT
) == 0)
12831 temp_list
= word_list_split (expanded
);
12832 dispose_words (expanded
);
12836 /* If no parameter expansion, command substitution, process
12837 substitution, or arithmetic substitution took place, then
12838 do not do word splitting. We still have to remove quoted
12839 null characters from the result. */
12840 word_list_remove_quoted_nulls (expanded
);
12841 temp_list
= expanded
;
12844 expanded
= REVERSE_LIST (temp_list
, WORD_LIST
*);
12845 new_list
= (WORD_LIST
*)list_append (expanded
, new_list
);
12849 dispose_words (orig_list
);
12852 new_list
= REVERSE_LIST (new_list
, WORD_LIST
*);
12857 /* Perform assignment statements optionally preceding a command name COMMAND.
12858 If COMMAND == NULL, is_nullcmd usually == 1. Follow the POSIX rules for
12859 variable assignment errors. */
12861 do_assignment_statements (varlist
, command
, is_nullcmd
)
12862 WORD_LIST
*varlist
;
12866 WORD_LIST
*temp_list
;
12868 sh_wassign_func_t
*assign_func
;
12869 int is_special_builtin
, is_builtin_or_func
, tint
;
12871 /* If the remainder of the words expand to nothing, Posix.2 requires
12872 that the variable and environment assignments affect the shell's
12873 environment (do_word_assignment). */
12874 assign_func
= is_nullcmd
? do_word_assignment
: assign_in_env
;
12875 tempenv_assign_error
= 0;
12877 is_builtin_or_func
= command
&& (find_shell_builtin (command
) || find_function (command
));
12878 /* Posix says that special builtins exit if a variable assignment error
12879 occurs in an assignment preceding it. (XXX - this is old -- current Posix
12880 says that any variable assignment error causes a non-interactive shell
12881 to exit. See the STRICT_POSIX checks below. */
12882 is_special_builtin
= posixly_correct
&& command
&& find_special_builtin (command
);
12884 savecmd
= this_command_name
;
12885 for (temp_list
= varlist
; temp_list
; temp_list
= temp_list
->next
)
12887 this_command_name
= (char *)NULL
;
12888 assigning_in_environment
= is_nullcmd
== 0;
12889 tint
= (*assign_func
) (temp_list
->word
, is_builtin_or_func
);
12890 assigning_in_environment
= 0;
12891 this_command_name
= savecmd
;
12893 /* Variable assignment errors in non-interactive shells running
12894 in posix mode cause the shell to exit. */
12897 if (is_nullcmd
) /* assignment statement */
12899 last_command_exit_value
= EXECUTION_FAILURE
;
12900 #if defined (STRICT_POSIX)
12901 if (posixly_correct
&& interactive_shell
== 0)
12903 if (posixly_correct
&& interactive_shell
== 0 && executing_command_builtin
== 0)
12905 exp_jump_to_top_level (FORCE_EOF
);
12907 exp_jump_to_top_level (DISCARD
);
12909 /* In posix mode, assignment errors in the temporary environment
12910 cause a non-interactive shell executing a special builtin to
12911 exit and a non-interactive shell to otherwise jump back to the
12912 top level. This is what POSIX says to do for variable assignment
12913 errors, and POSIX says errors in assigning to the temporary
12914 environment are treated as variable assignment errors.
12915 (XXX - this is not what current POSIX says - look at the
12916 STRICT_POSIX defines. */
12917 else if (posixly_correct
)
12919 last_command_exit_value
= EXECUTION_FAILURE
;
12920 #if defined (STRICT_POSIX)
12921 exp_jump_to_top_level ((interactive_shell
== 0) ? FORCE_EOF
: DISCARD
);
12923 if (interactive_shell
== 0 && is_special_builtin
)
12924 exp_jump_to_top_level (FORCE_EOF
);
12925 else if (interactive_shell
== 0)
12926 exp_jump_to_top_level (DISCARD
); /* XXX - maybe change later */
12928 exp_jump_to_top_level (DISCARD
);
12932 tempenv_assign_error
++;
12935 return (tempenv_assign_error
);
12938 /* The workhorse for expand_words () and expand_words_no_vars ().
12939 First arg is LIST, a WORD_LIST of words.
12940 Second arg EFLAGS is a flags word controlling which expansions are
12943 This does all of the substitutions: brace expansion, tilde expansion,
12944 parameter expansion, command substitution, arithmetic expansion,
12945 process substitution, word splitting, and pathname expansion, according
12946 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
12947 set, or for which no expansion is done, do not undergo word splitting.
12948 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
12949 with W_NOBRACE set do not undergo brace expansion (see
12950 brace_expand_word_list above). */
12952 expand_word_list_internal (list
, eflags
)
12956 WORD_LIST
*new_list
, *temp_list
;
12958 tempenv_assign_error
= 0;
12960 return ((WORD_LIST
*)NULL
);
12962 garglist
= new_list
= copy_word_list (list
);
12963 if (eflags
& WEXP_VARASSIGN
)
12965 garglist
= new_list
= separate_out_assignments (new_list
);
12968 if (subst_assign_varlist
)
12969 do_assignment_statements (subst_assign_varlist
, (char *)NULL
, 1);
12971 dispose_words (subst_assign_varlist
);
12972 subst_assign_varlist
= (WORD_LIST
*)NULL
;
12974 return ((WORD_LIST
*)NULL
);
12978 /* Begin expanding the words that remain. The expansions take place on
12979 things that aren't really variable assignments. */
12981 #if defined (BRACE_EXPANSION)
12982 /* Do brace expansion on this word if there are any brace characters
12984 if ((eflags
& WEXP_BRACEEXP
) && brace_expansion
&& new_list
)
12985 new_list
= brace_expand_word_list (new_list
, eflags
);
12986 #endif /* BRACE_EXPANSION */
12988 /* Perform the `normal' shell expansions: tilde expansion, parameter and
12989 variable substitution, command substitution, arithmetic expansion,
12990 and word splitting. */
12991 new_list
= shell_expand_word_list (new_list
, eflags
);
12993 /* Okay, we're almost done. Now let's just do some filename
12997 if ((eflags
& WEXP_PATHEXP
) && disallow_filename_globbing
== 0)
12998 /* Glob expand the word list unless globbing has been disabled. */
12999 new_list
= glob_expand_word_list (new_list
, eflags
);
13001 /* Dequote the words, because we're not performing globbing. */
13002 new_list
= dequote_list (new_list
);
13005 if ((eflags
& WEXP_VARASSIGN
) && subst_assign_varlist
)
13007 do_assignment_statements (subst_assign_varlist
, (new_list
&& new_list
->word
) ? new_list
->word
->word
: (char *)NULL
, new_list
== 0);
13009 dispose_words (subst_assign_varlist
);
13010 subst_assign_varlist
= (WORD_LIST
*)NULL
;