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 /* Extract a parameter expansion expression within ${ and } from STRING.
1802 Obey the Posix.2 rules for finding the ending `}': count braces while
1803 skipping over enclosed quoted strings and command substitutions.
1804 SINDEX is the address of an int describing the current offset in STRING;
1805 it should point to just after the first `{' found. On exit, SINDEX
1806 gets the position of the matching `}'. QUOTED is non-zero if this
1807 occurs inside double quotes. */
1808 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1810 extract_dollar_brace_string (string
, sindex
, quoted
, flags
)
1812 int *sindex
, quoted
, flags
;
1816 int pass_character
, nesting_level
, si
, dolbrace_state
;
1820 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1821 parse_matched_pair(). The different initial value is to handle the
1822 case where this function is called to parse the word in
1823 ${param op word} (SX_WORD). */
1824 dolbrace_state
= (flags
& SX_WORD
) ? DOLBRACE_WORD
: DOLBRACE_PARAM
;
1825 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && (flags
& SX_POSIXEXP
))
1826 dolbrace_state
= DOLBRACE_QUOTE
;
1828 if (quoted
== Q_HERE_DOCUMENT
&& dolbrace_state
== DOLBRACE_QUOTE
&& (flags
& SX_NOALLOC
) == 0)
1829 return (extract_heredoc_dolbrace_string (string
, sindex
, quoted
, flags
));
1833 slen
= strlen (string
+ *sindex
) + *sindex
;
1836 while (c
= string
[i
])
1841 ADVANCE_CHAR (string
, slen
, i
);
1845 /* CTLESCs and backslashes quote the next character. */
1846 if (c
== CTLESC
|| c
== '\\')
1853 if (string
[i
] == '$' && string
[i
+1] == LBRACE
)
1857 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_WORD
)
1858 dolbrace_state
= DOLBRACE_PARAM
;
1865 if (nesting_level
== 0)
1871 /* Pass the contents of old-style command substitutions through
1876 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1878 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1884 /* Pass the contents of new-style command substitutions and
1885 arithmetic substitutions through verbatim. */
1886 if (string
[i
] == '$' && string
[i
+1] == LPAREN
)
1889 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1891 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1897 #if defined (PROCESS_SUBSTITUTION)
1898 /* Technically this should only work at the start of a word */
1899 if ((string
[i
] == '<' || string
[i
] == '>') && string
[i
+1] == LPAREN
)
1902 t
= extract_process_subst (string
, (string
[i
] == '<' ? "<(" : ">)"), &si
, flags
|SX_NOALLOC
);
1904 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1911 /* Pass the contents of double-quoted strings through verbatim. */
1915 i
= skip_double_quoted (string
, slen
, si
, 0);
1916 /* skip_XXX_quoted leaves index one past close quote */
1922 /*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
1923 if (posixly_correct
&& shell_compatibility_level
> 42 && dolbrace_state
!= DOLBRACE_QUOTE
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1924 ADVANCE_CHAR (string
, slen
, i
);
1928 i
= skip_single_quoted (string
, slen
, si
, 0);
1934 #if defined (ARRAY_VARS)
1935 if (c
== LBRACK
&& dolbrace_state
== DOLBRACE_PARAM
)
1937 si
= skipsubscript (string
, i
, 0);
1938 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1939 if (string
[si
] == RBRACK
)
1944 /* move past this character, which was not special. */
1945 ADVANCE_CHAR (string
, slen
, i
);
1947 /* This logic must agree with parse.y:parse_matched_pair, since they
1948 share the same defines. */
1949 if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '%' && (i
- *sindex
) > 1)
1950 dolbrace_state
= DOLBRACE_QUOTE
;
1951 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '#' && (i
- *sindex
) > 1)
1952 dolbrace_state
= DOLBRACE_QUOTE
;
1953 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '/' && (i
- *sindex
) > 1)
1954 dolbrace_state
= DOLBRACE_QUOTE2
; /* XXX */
1955 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '^' && (i
- *sindex
) > 1)
1956 dolbrace_state
= DOLBRACE_QUOTE
;
1957 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== ',' && (i
- *sindex
) > 1)
1958 dolbrace_state
= DOLBRACE_QUOTE
;
1959 /* This is intended to handle all of the [:]op expansions and the substring/
1960 length/pattern removal/pattern substitution expansions. */
1961 else if (dolbrace_state
== DOLBRACE_PARAM
&& strchr ("#%^,~:-=?+/", c
) != 0)
1962 dolbrace_state
= DOLBRACE_OP
;
1963 else if (dolbrace_state
== DOLBRACE_OP
&& strchr ("#%^,~:-=?+/", c
) == 0)
1964 dolbrace_state
= DOLBRACE_WORD
;
1967 if (c
== 0 && nesting_level
)
1969 if (no_longjmp_on_fatal_error
== 0)
1971 last_command_exit_value
= EXECUTION_FAILURE
;
1972 report_error (_("bad substitution: no closing `%s' in %s"), "}", string
);
1973 exp_jump_to_top_level (DISCARD
);
1978 return ((char *)NULL
);
1982 result
= (flags
& SX_NOALLOC
) ? (char *)NULL
: substring (string
, *sindex
, i
);
1988 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1989 STRING, and returns a pointer to it. */
1991 de_backslash (string
)
1994 register size_t slen
;
1995 register int i
, j
, prev_i
;
1998 slen
= strlen (string
);
2001 /* Loop copying string[i] to string[j], i >= j. */
2004 if (string
[i
] == '\\' && (string
[i
+ 1] == '`' || string
[i
+ 1] == '\\' ||
2005 string
[i
+ 1] == '$'))
2008 ADVANCE_CHAR (string
, slen
, i
);
2010 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
2021 /* Replace instances of \! in a string with !. */
2023 unquote_bang (string
)
2027 register char *temp
;
2029 temp
= (char *)xmalloc (1 + strlen (string
));
2031 for (i
= 0, j
= 0; (temp
[j
] = string
[i
]); i
++, j
++)
2033 if (string
[i
] == '\\' && string
[i
+ 1] == '!')
2039 strcpy (string
, temp
);
2044 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0)
2046 /* When FLAGS & 2 == 0, this function assumes STRING[I] == OPEN; when
2047 FLAGS & 2 != 0, it assumes STRING[I] points to one character past OPEN;
2048 returns with STRING[RET] == close; used to parse array subscripts.
2049 FLAGS & 1 means not to attempt to skip over matched pairs of quotes or
2050 backquotes, or skip word expansions; it is intended to be used after
2051 expansion has been performed and during final assignment parsing (see
2052 arrayfunc.c:assign_compound_array_list()) or during execution by a builtin
2053 which has already undergone word expansion. */
2055 skip_matched_pair (string
, start
, open
, close
, flags
)
2057 int start
, open
, close
, flags
;
2059 int i
, pass_next
, backq
, si
, c
, count
, oldjmp
;
2064 slen
= strlen (string
+ start
) + start
;
2065 oldjmp
= no_longjmp_on_fatal_error
;
2066 no_longjmp_on_fatal_error
= 1;
2068 /* Move to the first character after a leading OPEN. If FLAGS&2, we assume
2069 that START already points to that character. If not, we need to skip over
2071 i
= (flags
& 2) ? start
: start
+ 1;
2073 pass_next
= backq
= 0;
2074 ss
= (char *)string
;
2075 while (c
= string
[i
])
2082 ADVANCE_CHAR (string
, slen
, i
);
2085 else if ((flags
& 1) == 0 && c
== '\\')
2095 ADVANCE_CHAR (string
, slen
, i
);
2098 else if ((flags
& 1) == 0 && c
== '`')
2104 else if ((flags
& 1) == 0 && c
== open
)
2110 else if (c
== close
)
2118 else if ((flags
& 1) == 0 && (c
== '\'' || c
== '"'))
2120 i
= (c
== '\'') ? skip_single_quoted (ss
, slen
, ++i
, 0)
2121 : skip_double_quoted (ss
, slen
, ++i
, 0);
2122 /* no increment, the skip functions increment past the closing quote. */
2124 else if ((flags
& 1) == 0 && c
== '$' && (string
[i
+1] == LPAREN
|| string
[i
+1] == LBRACE
))
2127 if (string
[si
] == '\0')
2130 /* XXX - extract_command_subst here? */
2131 if (string
[i
+1] == LPAREN
)
2132 temp
= extract_delimited_string (ss
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
); /* ) */
2134 temp
= extract_dollar_brace_string (ss
, &si
, 0, SX_NOALLOC
);
2136 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2139 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2145 ADVANCE_CHAR (string
, slen
, i
);
2151 #if defined (ARRAY_VARS)
2152 /* FLAGS has 1 as a reserved value, since skip_matched_pair uses it for
2153 skipping over quoted strings and taking the first instance of the
2154 closing character. FLAGS & 2 means that STRING[START] points one
2155 character past the open bracket; FLAGS & 2 == 0 means that STRING[START]
2156 points to the open bracket. skip_matched_pair knows how to deal with this. */
2158 skipsubscript (string
, start
, flags
)
2162 return (skip_matched_pair (string
, start
, '[', ']', flags
));
2166 /* Skip characters in STRING until we find a character in DELIMS, and return
2167 the index of that character. START is the index into string at which we
2168 begin. This is similar in spirit to strpbrk, but it returns an index into
2169 STRING and takes a starting index. This little piece of code knows quite
2170 a lot of shell syntax. It's very similar to skip_double_quoted and other
2171 functions of that ilk. */
2173 skip_to_delim (string
, start
, delims
, flags
)
2179 int i
, pass_next
, backq
, dquote
, si
, c
, oldjmp
;
2180 int invert
, skipquote
, skipcmd
, noprocsub
, completeflag
;
2181 int arithexp
, skipcol
;
2183 char *temp
, open
[3];
2186 slen
= strlen (string
+ start
) + start
;
2187 oldjmp
= no_longjmp_on_fatal_error
;
2188 if (flags
& SD_NOJMP
)
2189 no_longjmp_on_fatal_error
= 1;
2190 invert
= (flags
& SD_INVERT
);
2191 skipcmd
= (flags
& SD_NOSKIPCMD
) == 0;
2192 noprocsub
= (flags
& SD_NOPROCSUB
);
2193 completeflag
= (flags
& SD_COMPLETE
) ? SX_COMPLETE
: 0;
2195 arithexp
= (flags
& SD_ARITHEXP
);
2199 pass_next
= backq
= dquote
= 0;
2200 while (c
= string
[i
])
2202 /* If this is non-zero, we should not let quote characters be delimiters
2203 and the current character is a single or double quote. We should not
2204 test whether or not it's a delimiter until after we skip single- or
2205 double-quoted strings. */
2206 skipquote
= ((flags
& SD_NOQUOTEDELIM
) && (c
== '\'' || c
=='"'));
2212 ADVANCE_CHAR (string
, slen
, i
);
2225 ADVANCE_CHAR (string
, slen
, i
);
2234 else if (arithexp
&& skipcol
&& c
== ':')
2240 else if (arithexp
&& c
== '?')
2246 else if (skipquote
== 0 && invert
== 0 && member (c
, delims
))
2248 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2249 quoted strings when looking for the history expansion character as a
2251 /* special case for programmable completion which takes place before
2252 parser converts backslash-escaped single quotes between $'...' to
2253 `regular' single-quoted strings. */
2254 else if (completeflag
&& i
> 0 && string
[i
-1] == '$' && c
== '\'')
2255 i
= skip_single_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2257 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2259 i
= skip_double_quoted (string
, slen
, ++i
, completeflag
);
2260 else if (c
== LPAREN
&& arithexp
)
2263 if (string
[si
] == '\0')
2266 temp
= extract_delimited_string (string
, &si
, "(", "(", ")", SX_NOALLOC
); /* ) */
2268 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2273 else if (c
== '$' && ((skipcmd
&& string
[i
+1] == LPAREN
) || string
[i
+1] == LBRACE
))
2276 if (string
[si
] == '\0')
2279 if (string
[i
+1] == LPAREN
)
2280 temp
= extract_delimited_string (string
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
|completeflag
); /* ) */
2282 temp
= extract_dollar_brace_string (string
, &si
, 0, SX_NOALLOC
);
2283 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2285 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2290 #if defined (PROCESS_SUBSTITUTION)
2291 else if (skipcmd
&& noprocsub
== 0 && (c
== '<' || c
== '>') && string
[i
+1] == LPAREN
)
2294 if (string
[si
] == '\0')
2297 temp
= extract_delimited_string (string
, &si
, (c
== '<') ? "<(" : ">(", "(", ")", SX_COMMAND
|SX_NOALLOC
); /* )) */
2298 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2300 if (string
[i
] == '\0')
2305 #endif /* PROCESS_SUBSTITUTION */
2306 #if defined (EXTENDED_GLOB)
2307 else if ((flags
& SD_EXTGLOB
) && extended_glob
&& string
[i
+1] == LPAREN
&& member (c
, "?*+!@"))
2310 if (string
[si
] == '\0')
2316 temp
= extract_delimited_string (string
, &si
, open
, "(", ")", SX_NOALLOC
); /* ) */
2318 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2320 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2326 else if ((flags
& SD_GLOB
) && c
== LBRACK
)
2329 if (string
[si
] == '\0')
2332 temp
= extract_delimited_string (string
, &si
, "[", "[", "]", SX_NOALLOC
); /* ] */
2335 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2340 else if ((skipquote
|| invert
) && (member (c
, delims
) == 0))
2343 ADVANCE_CHAR (string
, slen
, i
);
2349 #if defined (BANG_HISTORY)
2350 /* Skip to the history expansion character (delims[0]), paying attention to
2351 quoted strings and command and process substitution. This is a stripped-
2352 down version of skip_to_delims. The essential difference is that this
2353 resets the quoting state when starting a command substitution */
2355 skip_to_histexp (string
, start
, delims
, flags
)
2361 int i
, pass_next
, backq
, dquote
, c
, oldjmp
;
2362 int histexp_comsub
, histexp_backq
, old_dquote
;
2366 slen
= strlen (string
+ start
) + start
;
2367 oldjmp
= no_longjmp_on_fatal_error
;
2368 if (flags
& SD_NOJMP
)
2369 no_longjmp_on_fatal_error
= 1;
2371 histexp_comsub
= histexp_backq
= old_dquote
= 0;
2374 pass_next
= backq
= dquote
= 0;
2375 while (c
= string
[i
])
2382 ADVANCE_CHAR (string
, slen
, i
);
2391 else if (backq
&& c
== '`')
2395 dquote
= old_dquote
;
2403 old_dquote
= dquote
; /* simple - one level for now */
2408 /* When in double quotes, act as if the double quote is a member of
2409 history_no_expand_chars, like the history library does */
2410 else if (dquote
&& c
== delims
[0] && string
[i
+1] == '"')
2415 else if (c
== delims
[0])
2417 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2418 quoted strings when looking for the history expansion character as a
2420 else if (dquote
&& c
== '\'')
2426 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2427 /* The posixly_correct test makes posix-mode shells allow double quotes
2428 to quote the history expansion character */
2429 else if (posixly_correct
== 0 && c
== '"')
2431 dquote
= 1 - dquote
;
2436 i
= skip_double_quoted (string
, slen
, ++i
, 0);
2437 #if defined (PROCESS_SUBSTITUTION)
2438 else if ((c
== '$' || c
== '<' || c
== '>') && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2440 else if (c
== '$' && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2443 if (string
[i
+2] == '\0')
2447 old_dquote
= dquote
;
2450 else if (histexp_comsub
&& c
== RPAREN
)
2453 dquote
= old_dquote
;
2457 else if (backq
) /* placeholder */
2459 ADVANCE_CHAR (string
, slen
, i
);
2463 ADVANCE_CHAR (string
, slen
, i
);
2468 #endif /* BANG_HISTORY */
2470 #if defined (READLINE)
2471 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
2472 an unclosed quoted string), or if the character at EINDEX is quoted
2473 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
2474 single and double-quoted string parsing functions should not return an
2475 error if there are unclosed quotes or braces. The characters that this
2476 recognizes need to be the same as the contents of
2477 rl_completer_quote_characters. */
2480 char_is_quoted (string
, eindex
)
2484 int i
, pass_next
, c
, oldjmp
;
2488 slen
= strlen (string
);
2489 oldjmp
= no_longjmp_on_fatal_error
;
2490 no_longjmp_on_fatal_error
= 1;
2493 /* If we have an open quoted string from a previous line, see if it's
2494 closed before string[eindex], so we don't interpret that close quote
2495 as starting a new quoted string. */
2496 if (current_command_line_count
> 0 && dstack
.delimiter_depth
> 0)
2498 c
= dstack
.delimiters
[dstack
.delimiter_depth
- 1];
2500 i
= skip_single_quoted (string
, slen
, 0, 0);
2502 i
= skip_double_quoted (string
, slen
, 0, SX_COMPLETE
);
2514 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2516 ADVANCE_CHAR (string
, slen
, i
);
2525 else if (c
== '$' && string
[i
+1] == '\'' && string
[i
+2])
2528 i
= skip_single_quoted (string
, slen
, i
, SX_COMPLETE
);
2532 else if (c
== '\'' || c
== '"')
2534 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, ++i
, 0)
2535 : skip_double_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2538 /* no increment, the skip_xxx functions go one past end */
2541 ADVANCE_CHAR (string
, slen
, i
);
2548 unclosed_pair (string
, eindex
, openstr
)
2553 int i
, pass_next
, openc
, olen
;
2557 slen
= strlen (string
);
2558 olen
= strlen (openstr
);
2559 i
= pass_next
= openc
= 0;
2565 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2567 ADVANCE_CHAR (string
, slen
, i
);
2570 else if (string
[i
] == '\\')
2576 else if (STREQN (string
+ i
, openstr
, olen
))
2581 /* XXX - may want to handle $'...' specially here */
2582 else if (string
[i
] == '\'' || string
[i
] == '"')
2584 i
= (string
[i
] == '\'') ? skip_single_quoted (string
, slen
, i
, 0)
2585 : skip_double_quoted (string
, slen
, i
, SX_COMPLETE
);
2590 ADVANCE_CHAR (string
, slen
, i
);
2595 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
2596 individual words. If DELIMS is NULL, the current value of $IFS is used
2597 to split the string, and the function follows the shell field splitting
2598 rules. SENTINEL is an index to look for. NWP, if non-NULL,
2599 gets the number of words in the returned list. CWP, if non-NULL, gets
2600 the index of the word containing SENTINEL. Non-whitespace chars in
2601 DELIMS delimit separate fields. This is used by programmable completion. */
2603 split_at_delims (string
, slen
, delims
, sentinel
, flags
, nwp
, cwp
)
2607 int sentinel
, flags
;
2610 int ts
, te
, i
, nw
, cw
, ifs_split
, dflags
;
2611 char *token
, *d
, *d2
;
2612 WORD_LIST
*ret
, *tl
;
2614 if (string
== 0 || *string
== '\0')
2620 return ((WORD_LIST
*)NULL
);
2623 d
= (delims
== 0) ? ifs_value
: (char *)delims
;
2624 ifs_split
= delims
== 0;
2626 /* Make d2 the non-whitespace characters in delims */
2631 #if defined (HANDLE_MULTIBYTE)
2632 size_t mblength
= 1;
2636 slength
= strlen (delims
);
2637 d2
= (char *)xmalloc (slength
+ 1);
2641 #if defined (HANDLE_MULTIBYTE)
2642 mbstate_t state_bak
;
2644 mblength
= MBRLEN (delims
+ i
, slength
, &state
);
2645 if (MB_INVALIDCH (mblength
))
2647 else if (mblength
> 1)
2649 memcpy (d2
+ ts
, delims
+ i
, mblength
);
2652 slength
-= mblength
;
2656 if (whitespace (delims
[i
]) == 0)
2657 d2
[ts
++] = delims
[i
];
2665 ret
= (WORD_LIST
*)NULL
;
2667 /* Remove sequences of whitespace characters at the start of the string, as
2668 long as those characters are delimiters. */
2669 for (i
= 0; member (string
[i
], d
) && spctabnl (string
[i
]); i
++)
2671 if (string
[i
] == '\0')
2680 dflags
= flags
|SD_NOJMP
;
2683 te
= skip_to_delim (string
, ts
, d
, dflags
);
2685 /* If we have a non-whitespace delimiter character, use it to make a
2686 separate field. This is just about what $IFS splitting does and
2687 is closer to the behavior of the shell parser. */
2688 if (ts
== te
&& d2
&& member (string
[ts
], d2
))
2691 /* If we're using IFS splitting, the non-whitespace delimiter char
2692 and any additional IFS whitespace delimits a field. */
2694 while (member (string
[te
], d
) && spctabnl (string
[te
]) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2697 while (member (string
[te
], d2
) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2701 token
= substring (string
, ts
, te
);
2703 ret
= add_string_to_list (token
, ret
); /* XXX */
2707 if (sentinel
>= ts
&& sentinel
<= te
)
2710 /* If the cursor is at whitespace just before word start, set the
2711 sentinel word to the current word. */
2712 if (cwp
&& cw
== -1 && sentinel
== ts
-1)
2715 /* If the cursor is at whitespace between two words, make a new, empty
2716 word, add it before (well, after, since the list is in reverse order)
2717 the word we just added, and set the current word to that one. */
2718 if (cwp
&& cw
== -1 && sentinel
< ts
)
2720 tl
= make_word_list (make_word (""), ret
->next
);
2726 if (string
[te
] == 0)
2730 /* XXX - honor SD_NOQUOTEDELIM here */
2731 while (member (string
[i
], d
) && (ifs_split
|| spctabnl(string
[i
])) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2740 /* Special case for SENTINEL at the end of STRING. If we haven't found
2741 the word containing SENTINEL yet, and the index we're looking for is at
2742 the end of STRING (or past the end of the previously-found token,
2743 possible if the end of the line is composed solely of IFS whitespace)
2744 add an additional null argument and set the current word pointer to that. */
2745 if (cwp
&& cw
== -1 && (sentinel
>= slen
|| sentinel
>= te
))
2747 if (whitespace (string
[sentinel
- 1]))
2750 ret
= add_string_to_list (token
, ret
);
2763 return (REVERSE_LIST (ret
, WORD_LIST
*));
2765 #endif /* READLINE */
2769 /* Extract the name of the variable to bind to from the assignment string. */
2771 assignment_name (string
)
2777 offset
= assignment (string
, 0);
2779 return (char *)NULL
;
2780 temp
= substring (string
, 0, offset
);
2785 /* **************************************************************** */
2787 /* Functions to convert strings to WORD_LISTs and vice versa */
2789 /* **************************************************************** */
2791 /* Return a single string of all the words in LIST. SEP is the separator
2792 to put between individual elements of LIST in the output string. */
2794 string_list_internal (list
, sep
)
2798 register WORD_LIST
*t
;
2800 size_t word_len
, sep_len
, result_size
;
2803 return ((char *)NULL
);
2805 /* Short-circuit quickly if we don't need to separate anything. */
2806 if (list
->next
== 0)
2807 return (savestring (list
->word
->word
));
2809 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
2810 sep_len
= STRLEN (sep
);
2813 for (t
= list
; t
; t
= t
->next
)
2816 result_size
+= sep_len
;
2817 result_size
+= strlen (t
->word
->word
);
2820 r
= result
= (char *)xmalloc (result_size
+ 1);
2822 for (t
= list
; t
; t
= t
->next
)
2824 if (t
!= list
&& sep_len
)
2828 FASTCOPY (sep
, r
, sep_len
);
2835 word_len
= strlen (t
->word
->word
);
2836 FASTCOPY (t
->word
->word
, r
, word_len
);
2844 /* Return a single string of all the words present in LIST, separating
2845 each word with a space. */
2850 return (string_list_internal (list
, " "));
2853 /* An external interface that can be used by the rest of the shell to
2854 obtain a string containing the first character in $IFS. Handles all
2855 the multibyte complications. If LENP is non-null, it is set to the
2856 length of the returned string. */
2858 ifs_firstchar (lenp
)
2864 ret
= xmalloc (MB_LEN_MAX
+ 1);
2865 #if defined (HANDLE_MULTIBYTE)
2866 if (ifs_firstc_len
== 1)
2868 ret
[0] = ifs_firstc
[0];
2870 len
= ret
[0] ? 1 : 0;
2874 memcpy (ret
, ifs_firstc
, ifs_firstc_len
);
2875 ret
[len
= ifs_firstc_len
] = '\0';
2878 ret
[0] = ifs_firstc
;
2880 len
= ret
[0] ? 0 : 1;
2889 /* Return a single string of all the words present in LIST, obeying the
2890 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
2891 expansion [of $*] appears within a double quoted string, it expands
2892 to a single field with the value of each parameter separated by the
2893 first character of the IFS variable, or by a <space> if IFS is unset." */
2894 /* Posix interpretation 888 changes this when IFS is null by specifying
2895 that when unquoted, this expands to separate arguments */
2897 string_list_dollar_star (list
, quoted
, flags
)
2902 #if defined (HANDLE_MULTIBYTE)
2903 # if defined (__GNUC__)
2904 char sep
[MB_CUR_MAX
+ 1];
2912 #if defined (HANDLE_MULTIBYTE)
2913 # if !defined (__GNUC__)
2914 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2915 # endif /* !__GNUC__ */
2916 if (ifs_firstc_len
== 1)
2918 sep
[0] = ifs_firstc
[0];
2923 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
2924 sep
[ifs_firstc_len
] = '\0';
2927 sep
[0] = ifs_firstc
;
2931 ret
= string_list_internal (list
, sep
);
2932 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2938 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2939 is non-zero, the $@ appears within double quotes, and we should quote
2940 the list before converting it into a string. If IFS is unset, and the
2941 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2942 in the words in the list, because the default value of $IFS is
2943 <space><tab><newline>, IFS characters in the words in the list should
2944 also be split. If IFS is null, and the word is not quoted, we need
2945 to quote the words in the list to preserve the positional parameters
2947 Valid values for the FLAGS argument are the PF_ flags in command.h,
2948 the only one we care about is PF_ASSIGNRHS. $@ is supposed to expand
2949 to the positional parameters separated by spaces no matter what IFS is
2950 set to if in a context where word splitting is not performed. The only
2951 one that we didn't handle before is assignment statement arguments to
2952 declaration builtins like `declare'. */
2954 string_list_dollar_at (list
, quoted
, flags
)
2960 #if defined (HANDLE_MULTIBYTE)
2961 # if defined (__GNUC__)
2962 char sep
[MB_CUR_MAX
+ 1];
2965 # endif /* !__GNUC__ */
2971 /* XXX this could just be ifs = ifs_value; */
2972 ifs
= ifs_var
? value_cell (ifs_var
) : (char *)0;
2974 #if defined (HANDLE_MULTIBYTE)
2975 # if !defined (__GNUC__)
2976 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2977 # endif /* !__GNUC__ */
2978 /* XXX - testing PF_ASSIGNRHS to make sure positional parameters are
2979 separated with a space even when word splitting will not occur. */
2980 if (flags
& PF_ASSIGNRHS
)
2985 else if (ifs
&& *ifs
)
2987 if (ifs_firstc_len
== 1)
2989 sep
[0] = ifs_firstc
[0];
2994 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
2995 sep
[ifs_firstc_len
] = '\0';
3003 #else /* !HANDLE_MULTIBYTE */
3004 /* XXX - PF_ASSIGNRHS means no word splitting, so we want positional
3005 parameters separated by a space. */
3006 sep
[0] = ((flags
& PF_ASSIGNRHS
) || ifs
== 0 || *ifs
== 0) ? ' ' : *ifs
;
3008 #endif /* !HANDLE_MULTIBYTE */
3010 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
3011 it now that quote_escapes quotes spaces */
3012 tlist
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
3014 : list_quote_escapes (list
);
3016 ret
= string_list_internal (tlist
, sep
);
3017 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
3023 /* Turn the positional parameters into a string, understanding quoting and
3024 the various subtleties of using the first character of $IFS as the
3025 separator. Calls string_list_dollar_at, string_list_dollar_star, and
3026 string_list as appropriate. */
3027 /* This needs to fully understand the additional contexts where word
3028 splitting does not occur (W_ASSIGNRHS, etc.) */
3030 string_list_pos_params (pchar
, list
, quoted
, pflags
)
3038 if (pchar
== '*' && (quoted
& Q_DOUBLE_QUOTES
))
3040 tlist
= quote_list (list
);
3041 word_list_remove_quoted_nulls (tlist
);
3042 ret
= string_list_dollar_star (tlist
, 0, 0);
3044 else if (pchar
== '*' && (quoted
& Q_HERE_DOCUMENT
))
3046 tlist
= quote_list (list
);
3047 word_list_remove_quoted_nulls (tlist
);
3048 ret
= string_list (tlist
);
3050 else if (pchar
== '*' && quoted
== 0 && ifs_is_null
) /* XXX */
3051 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3052 else if (pchar
== '*' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
)) /* XXX */
3053 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3054 else if (pchar
== '*')
3056 /* Even when unquoted, string_list_dollar_star does the right thing
3057 making sure that the first character of $IFS is used as the
3059 ret
= string_list_dollar_star (list
, quoted
, 0);
3061 else if (pchar
== '@' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
3062 /* We use string_list_dollar_at, but only if the string is quoted, since
3063 that quotes the escapes if it's not, which we don't want. We could
3064 use string_list (the old code did), but that doesn't do the right
3065 thing if the first character of $IFS is not a space. We use
3066 string_list_dollar_star if the string is unquoted so we make sure that
3067 the elements of $@ are separated by the first character of $IFS for
3069 ret
= string_list_dollar_at (list
, quoted
, 0);
3070 else if (pchar
== '@' && quoted
== 0 && ifs_is_null
) /* XXX */
3071 ret
= string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3072 else if (pchar
== '@' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
3073 ret
= string_list_dollar_at (list
, quoted
, pflags
); /* Posix interp 888 */
3074 else if (pchar
== '@')
3075 ret
= string_list_dollar_star (list
, quoted
, 0);
3077 ret
= string_list ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? quote_list (list
) : list
);
3082 /* Return the list of words present in STRING. Separate the string into
3083 words at any of the characters found in SEPARATORS. If QUOTED is
3084 non-zero then word in the list will have its quoted flag set, otherwise
3085 the quoted flag is left as make_word () deemed fit.
3087 This obeys the P1003.2 word splitting semantics. If `separators' is
3088 exactly <space><tab><newline>, then the splitting algorithm is that of
3089 the Bourne shell, which treats any sequence of characters from `separators'
3090 as a delimiter. If IFS is unset, which results in `separators' being set
3091 to "", no splitting occurs. If separators has some other value, the
3092 following rules are applied (`IFS white space' means zero or more
3093 occurrences of <space>, <tab>, or <newline>, as long as those characters
3094 are in `separators'):
3096 1) IFS white space is ignored at the start and the end of the
3098 2) Each occurrence of a character in `separators' that is not
3099 IFS white space, along with any adjacent occurrences of
3100 IFS white space delimits a field.
3101 3) Any nonzero-length sequence of IFS white space delimits a field.
3104 /* BEWARE! list_string strips null arguments. Don't call it twice and
3105 expect to have "" preserved! */
3107 /* This performs word splitting and quoted null character removal on
3110 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
3111 : (c) == (separators)[0]) \
3114 /* member of the space character class in the current locale */
3115 #define ifs_whitespace(c) ISSPACE(c)
3117 /* "adjacent IFS white space" */
3118 #define ifs_whitesep(c) ((sh_style_split || separators == 0) ? spctabnl (c) \
3119 : ifs_whitespace (c))
3122 list_string (string
, separators
, quoted
)
3123 register char *string
, *separators
;
3128 char *current_word
, *s
;
3129 int sindex
, sh_style_split
, whitesep
, xflags
, free_word
;
3132 if (!string
|| !*string
)
3133 return ((WORD_LIST
*)NULL
);
3135 sh_style_split
= separators
&& separators
[0] == ' ' &&
3136 separators
[1] == '\t' &&
3137 separators
[2] == '\n' &&
3138 separators
[3] == '\0';
3139 for (xflags
= 0, s
= ifs_value
; s
&& *s
; s
++)
3141 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
3142 else if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
3146 /* Remove sequences of whitespace at the beginning of STRING, as
3147 long as those characters appear in IFS. Do not do this if
3148 STRING is quoted or if there are no separator characters. We use the
3149 Posix definition of whitespace as a member of the space character
3150 class in the current locale. */
3152 if (!quoted
|| !separators
|| !*separators
)
3154 /* issep() requires that separators be non-null, and always returns 0 if
3155 separator is the empty string, so don't bother if we get an empty string
3156 for separators. We already returned NULL above if STRING is empty. */
3157 if (!quoted
&& separators
&& *separators
)
3160 for (s
= string
; *s
&& issep (*s
) && ifs_whitespace (*s
); s
++);
3163 return ((WORD_LIST
*)NULL
);
3168 /* OK, now STRING points to a word that does not begin with white space.
3169 The splitting algorithm is:
3170 extract a word, stopping at a separator
3171 skip sequences of whitespace characters as long as they are separators
3172 This obeys the field splitting rules in Posix.2. */
3173 slen
= STRLEN (string
);
3174 for (result
= (WORD_LIST
*)NULL
, sindex
= 0; string
[sindex
]; )
3176 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3177 possible, but need it in string_extract_verbatim for bounds checking */
3178 current_word
= string_extract_verbatim (string
, slen
, &sindex
, separators
, xflags
);
3179 if (current_word
== 0)
3182 free_word
= 1; /* If non-zero, we free current_word */
3184 /* If we have a quoted empty string, add a quoted null argument. We
3185 want to preserve the quoted null character iff this is a quoted
3186 empty string; otherwise the quoted null characters are removed
3188 if (QUOTED_NULL (current_word
))
3190 t
= alloc_word_desc ();
3191 t
->word
= make_quoted_char ('\0');
3192 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
3193 result
= make_word_list (t
, result
);
3195 else if (current_word
[0] != '\0')
3197 /* If we have something, then add it regardless. However,
3198 perform quoted null character removal on the current word. */
3199 remove_quoted_nulls (current_word
);
3201 /* We don't want to set the word flags based on the string contents
3202 here -- that's mostly for the parser -- so we just allocate a
3203 WORD_DESC *, assign current_word (noting that we don't want to
3204 free it), and skip all of make_word. */
3205 t
= alloc_word_desc ();
3206 t
->word
= current_word
;
3207 result
= make_word_list (t
, result
);
3209 result
->word
->flags
&= ~W_HASQUOTEDNULL
; /* just to be sure */
3210 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
3211 result
->word
->flags
|= W_QUOTED
;
3212 /* If removing quoted null characters leaves an empty word, note
3213 that we saw this for the caller to act on. */
3214 if (current_word
== 0 || current_word
[0] == '\0')
3215 result
->word
->flags
|= W_SAWQUOTEDNULL
;
3218 /* If we're not doing sequences of separators in the traditional
3219 Bourne shell style, then add a quoted null argument. */
3220 else if (!sh_style_split
&& !ifs_whitespace (string
[sindex
]))
3222 t
= alloc_word_desc ();
3223 t
->word
= make_quoted_char ('\0');
3224 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
3225 result
= make_word_list (t
, result
);
3229 free (current_word
);
3231 /* Note whether or not the separator is IFS whitespace, used later. */
3232 whitesep
= string
[sindex
] && ifs_whitesep (string
[sindex
]);
3234 /* Move past the current separator character. */
3238 ADVANCE_CHAR (string
, slen
, sindex
);
3241 /* Now skip sequences of whitespace characters if they are
3242 in the list of separators. */
3243 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && issep (string
[sindex
]))
3246 /* If the first separator was IFS whitespace and the current character
3247 is a non-whitespace IFS character, it should be part of the current
3248 field delimiter, not a separate delimiter that would result in an
3249 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
3250 if (string
[sindex
] && whitesep
&& issep (string
[sindex
]) && !ifs_whitesep (string
[sindex
]))
3253 /* An IFS character that is not IFS white space, along with any
3254 adjacent IFS white space, shall delimit a field. (SUSv3) */
3255 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && isifs (string
[sindex
]))
3259 return (REVERSE_LIST (result
, WORD_LIST
*));
3262 /* Parse a single word from STRING, using SEPARATORS to separate fields.
3263 ENDPTR is set to the first character after the word. This is used by
3266 This is never called with SEPARATORS != $IFS, and takes advantage of that.
3268 XXX - this function is very similar to list_string; they should be
3271 /* character is in $IFS */
3272 #define islocalsep(c) (local_cmap[(unsigned char)(c)] != 0)
3275 get_word_from_string (stringp
, separators
, endptr
)
3276 char **stringp
, *separators
, **endptr
;
3280 int sindex
, sh_style_split
, whitesep
, xflags
;
3281 unsigned char local_cmap
[UCHAR_MAX
+1]; /* really only need single-byte chars here */
3284 if (!stringp
|| !*stringp
|| !**stringp
)
3285 return ((char *)NULL
);
3287 sh_style_split
= separators
&& separators
[0] == ' ' &&
3288 separators
[1] == '\t' &&
3289 separators
[2] == '\n' &&
3290 separators
[3] == '\0';
3291 memset (local_cmap
, '\0', sizeof (local_cmap
));
3292 for (xflags
= 0, s
= separators
; s
&& *s
; s
++)
3294 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
3295 if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
3296 local_cmap
[(unsigned char)*s
] = 1; /* local charmap of separators */
3302 /* Remove sequences of whitespace at the beginning of STRING, as
3303 long as those characters appear in SEPARATORS. This happens if
3304 SEPARATORS == $' \t\n' or if IFS is unset. */
3305 if (sh_style_split
|| separators
== 0)
3306 for (; *s
&& spctabnl (*s
) && islocalsep (*s
); s
++);
3308 for (; *s
&& ifs_whitespace (*s
) && islocalsep (*s
); s
++);
3310 /* If the string is nothing but whitespace, update it and return. */
3316 return ((char *)NULL
);
3319 /* OK, S points to a word that does not begin with white space.
3320 Now extract a word, stopping at a separator, save a pointer to
3321 the first character after the word, then skip sequences of spc,
3322 tab, or nl as long as they are separators.
3324 This obeys the field splitting rules in Posix.2. */
3326 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3327 possible, but need it in string_extract_verbatim for bounds checking */
3329 current_word
= string_extract_verbatim (s
, slen
, &sindex
, separators
, xflags
);
3331 /* Set ENDPTR to the first character after the end of the word. */
3333 *endptr
= s
+ sindex
;
3335 /* Note whether or not the separator is IFS whitespace, used later. */
3336 whitesep
= s
[sindex
] && ifs_whitesep (s
[sindex
]);
3338 /* Move past the current separator character. */
3342 ADVANCE_CHAR (s
, slen
, sindex
);
3345 /* Now skip sequences of space, tab, or newline characters if they are
3346 in the list of separators. */
3347 while (s
[sindex
] && spctabnl (s
[sindex
]) && islocalsep (s
[sindex
]))
3350 /* If the first separator was IFS whitespace and the current character is
3351 a non-whitespace IFS character, it should be part of the current field
3352 delimiter, not a separate delimiter that would result in an empty field.
3353 Look at POSIX.2, 3.6.5, (3)(b). */
3354 if (s
[sindex
] && whitesep
&& islocalsep (s
[sindex
]) && !ifs_whitesep (s
[sindex
]))
3357 /* An IFS character that is not IFS white space, along with any adjacent
3358 IFS white space, shall delimit a field. */
3359 while (s
[sindex
] && ifs_whitesep (s
[sindex
]) && islocalsep(s
[sindex
]))
3363 /* Update STRING to point to the next field. */
3364 *stringp
= s
+ sindex
;
3365 return (current_word
);
3368 /* Remove IFS white space at the end of STRING. Start at the end
3369 of the string and walk backwards until the beginning of the string
3370 or we find a character that's not IFS white space and not CTLESC.
3371 Only let CTLESC escape a white space character if SAW_ESCAPE is
3374 strip_trailing_ifs_whitespace (string
, separators
, saw_escape
)
3375 char *string
, *separators
;
3380 s
= string
+ STRLEN (string
) - 1;
3381 while (s
> string
&& ((spctabnl (*s
) && isifs (*s
)) ||
3382 (saw_escape
&& *s
== CTLESC
&& spctabnl (s
[1]))))
3390 /* Split STRING into words at whitespace. Obeys shell-style quoting with
3391 backslashes, single and double quotes. */
3393 list_string_with_quotes (string
)
3399 int c
, i
, tokstart
, len
;
3401 for (s
= string
; s
&& *s
&& spctabnl (*s
); s
++)
3403 if (s
== 0 || *s
== 0)
3404 return ((WORD_LIST
*)NULL
);
3408 list
= (WORD_LIST
*)NULL
;
3419 i
= skip_single_quoted (s
, s_len
, ++i
, 0);
3421 i
= skip_double_quoted (s
, s_len
, ++i
, 0);
3422 else if (c
== 0 || spctabnl (c
))
3424 /* We have found the end of a token. Make a word out of it and
3425 add it to the word list. */
3426 token
= substring (s
, tokstart
, i
);
3427 list
= add_string_to_list (token
, list
);
3429 while (spctabnl (s
[i
]))
3437 i
++; /* normal character */
3439 return (REVERSE_LIST (list
, WORD_LIST
*));
3443 /********************************************************/
3445 /* Functions to perform assignment statements */
3447 /********************************************************/
3449 #if defined (ARRAY_VARS)
3451 do_compound_assignment (name
, value
, flags
)
3456 int mklocal
, mkassoc
, mkglobal
, chklocal
;
3458 char *newname
; /* used for local nameref references */
3460 mklocal
= flags
& ASS_MKLOCAL
;
3461 mkassoc
= flags
& ASS_MKASSOC
;
3462 mkglobal
= flags
& ASS_MKGLOBAL
;
3463 chklocal
= flags
& ASS_CHKLOCAL
;
3465 if (mklocal
&& variable_context
)
3467 v
= find_variable (name
); /* follows namerefs */
3468 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : v
->name
;
3469 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3472 err_readonly (name
);
3473 return (v
); /* XXX */
3475 list
= expand_compound_array_assignment (v
, value
, flags
);
3477 v
= make_local_assoc_variable (newname
, 0);
3478 else if (v
== 0 || (array_p (v
) == 0 && assoc_p (v
) == 0) || v
->context
!= variable_context
)
3479 v
= make_local_array_variable (newname
, 0);
3481 assign_compound_array_list (v
, list
, flags
);
3483 dispose_words (list
);
3485 /* In a function but forcing assignment in global context. CHKLOCAL means to
3486 check for an existing local variable first. */
3487 else if (mkglobal
&& variable_context
)
3489 v
= chklocal
? find_variable (name
) : 0;
3490 if (v
&& (local_p (v
) == 0 || v
->context
!= variable_context
))
3493 v
= find_global_variable (name
);
3494 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3497 err_readonly (name
);
3498 return (v
); /* XXX */
3501 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : name
;
3502 list
= expand_compound_array_assignment (v
, value
, flags
);
3503 if (v
== 0 && mkassoc
)
3504 v
= make_new_assoc_variable (newname
);
3505 else if (v
&& mkassoc
&& assoc_p (v
) == 0)
3506 v
= convert_var_to_assoc (v
);
3508 v
= make_new_array_variable (newname
);
3509 else if (v
&& mkassoc
== 0 && array_p (v
) == 0)
3510 v
= convert_var_to_array (v
);
3512 assign_compound_array_list (v
, list
, flags
);
3514 dispose_words (list
);
3518 v
= assign_array_from_string (name
, value
, flags
);
3519 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3522 err_readonly (name
);
3523 return (v
); /* XXX */
3531 /* Given STRING, an assignment string, get the value of the right side
3532 of the `=', and bind it to the left side. If EXPAND is true, then
3533 perform parameter expansion, command substitution, and arithmetic
3534 expansion on the right-hand side. Perform tilde expansion in any
3535 case. Do not perform word splitting on the result of expansion. */
3537 do_assignment_internal (word
, expand
)
3538 const WORD_DESC
*word
;
3541 int offset
, appendop
, assign_list
, aflags
, retval
;
3542 char *name
, *value
, *temp
;
3544 #if defined (ARRAY_VARS)
3550 if (word
== 0 || word
->word
== 0)
3553 appendop
= assign_list
= aflags
= 0;
3554 string
= word
->word
;
3555 offset
= assignment (string
, 0);
3556 name
= savestring (string
);
3557 value
= (char *)NULL
;
3559 if (name
[offset
] == '=')
3561 if (name
[offset
- 1] == '+')
3564 name
[offset
- 1] = '\0';
3567 name
[offset
] = 0; /* might need this set later */
3568 temp
= name
+ offset
+ 1;
3570 #if defined (ARRAY_VARS)
3571 if (expand
&& (word
->flags
& W_COMPASSIGN
))
3573 assign_list
= ni
= 1;
3574 value
= extract_array_assignment_list (temp
, &ni
);
3578 if (expand
&& temp
[0])
3579 value
= expand_string_if_necessary (temp
, 0, expand_string_assignment
);
3581 value
= savestring (temp
);
3586 value
= (char *)xmalloc (1);
3590 if (echo_command_at_execute
)
3593 name
[offset
- 1] = '+';
3594 xtrace_print_assignment (name
, value
, assign_list
, 1);
3596 name
[offset
- 1] = '\0';
3599 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
3602 aflags
|= ASS_APPEND
;
3604 #if defined (ARRAY_VARS)
3605 if (t
= mbschr (name
, LBRACK
))
3609 report_error (_("%s: cannot assign list to array member"), name
);
3612 aflags
|= ASS_ALLOWALLSUB
; /* allow a[@]=value for existing associative arrays */
3613 entry
= assign_array_element (name
, value
, aflags
, (array_eltstate_t
*)0);
3617 else if (assign_list
)
3619 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_CHKLOCAL
))
3620 aflags
|= ASS_CHKLOCAL
;
3621 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
) == 0)
3622 aflags
|= ASS_MKLOCAL
;
3623 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
))
3624 aflags
|= ASS_MKGLOBAL
;
3625 if (word
->flags
& W_ASSIGNASSOC
)
3626 aflags
|= ASS_MKASSOC
;
3627 entry
= do_compound_assignment (name
, value
, aflags
);
3630 #endif /* ARRAY_VARS */
3631 entry
= bind_variable (name
, value
, aflags
);
3634 stupidly_hack_special_variables (entry
->name
); /* might be a nameref */
3636 stupidly_hack_special_variables (name
);
3638 /* Return 1 if the assignment seems to have been performed correctly. */
3639 if (entry
== 0 || readonly_p (entry
))
3640 retval
= 0; /* assignment failure */
3641 else if (noassign_p (entry
))
3643 set_exit_status (EXECUTION_FAILURE
);
3644 retval
= 1; /* error status, but not assignment failure */
3649 if (entry
&& retval
!= 0 && noassign_p (entry
) == 0)
3650 VUNSETATTR (entry
, att_invisible
);
3652 ASSIGN_RETURN (retval
);
3655 /* Perform the assignment statement in STRING, and expand the
3656 right side by doing tilde, command and parameter expansion. */
3658 do_assignment (string
)
3663 td
.flags
= W_ASSIGNMENT
;
3666 return do_assignment_internal (&td
, 1);
3670 do_word_assignment (word
, flags
)
3674 return do_assignment_internal (word
, 1);
3677 /* Given STRING, an assignment string, get the value of the right side
3678 of the `=', and bind it to the left side. Do not perform any word
3679 expansions on the right hand side. */
3681 do_assignment_no_expand (string
)
3686 td
.flags
= W_ASSIGNMENT
;
3689 return (do_assignment_internal (&td
, 0));
3692 /***************************************************
3694 * Functions to manage the positional parameters *
3696 ***************************************************/
3698 /* Return the word list that corresponds to `$*'. */
3700 list_rest_of_args ()
3702 register WORD_LIST
*list
, *args
;
3705 /* Break out of the loop as soon as one of the dollar variables is null. */
3706 for (i
= 1, list
= (WORD_LIST
*)NULL
; i
< 10 && dollar_vars
[i
]; i
++)
3707 list
= make_word_list (make_bare_word (dollar_vars
[i
]), list
);
3709 for (args
= rest_of_args
; args
; args
= args
->next
)
3710 list
= make_word_list (make_bare_word (args
->word
->word
), list
);
3712 return (REVERSE_LIST (list
, WORD_LIST
*));
3715 /* Return the value of a positional parameter. This handles values > 10. */
3717 get_dollar_var_value (ind
)
3724 temp
= dollar_vars
[ind
] ? savestring (dollar_vars
[ind
]) : (char *)NULL
;
3725 else /* We want something like ${11} */
3728 for (p
= rest_of_args
; p
&& ind
--; p
= p
->next
)
3730 temp
= p
? savestring (p
->word
->word
) : (char *)NULL
;
3735 /* Make a single large string out of the dollar digit variables,
3736 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
3737 case of "$*" with respect to IFS. */
3739 string_rest_of_args (dollar_star
)
3742 register WORD_LIST
*list
;
3745 list
= list_rest_of_args ();
3746 string
= dollar_star
? string_list_dollar_star (list
, 0, 0) : string_list (list
);
3747 dispose_words (list
);
3751 /* Return a string containing the positional parameters from START to
3752 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3753 which only makes a difference if QUOTED is non-zero. If QUOTED includes
3754 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
3755 no quoting chars are added. */
3757 pos_params (string
, start
, end
, quoted
, pflags
)
3759 int start
, end
, quoted
, pflags
;
3761 WORD_LIST
*save
, *params
, *h
, *t
;
3765 /* see if we can short-circuit. if start == end, we want 0 parameters. */
3767 return ((char *)NULL
);
3769 save
= params
= list_rest_of_args ();
3770 if (save
== 0 && start
> 0)
3771 return ((char *)NULL
);
3773 if (start
== 0) /* handle ${@:0[:x]} specially */
3775 t
= make_word_list (make_word (dollar_vars
[0]), params
);
3779 for (i
= start
? 1 : 0; params
&& i
< start
; i
++)
3780 params
= params
->next
;
3783 dispose_words (save
);
3784 return ((char *)NULL
);
3786 for (h
= t
= params
; params
&& i
< end
; i
++)
3789 params
= params
->next
;
3791 t
->next
= (WORD_LIST
*)NULL
;
3793 ret
= string_list_pos_params (string
[0], h
, quoted
, pflags
);
3798 dispose_words (save
);
3802 /******************************************************************/
3804 /* Functions to expand strings to strings or WORD_LISTs */
3806 /******************************************************************/
3808 #if defined (PROCESS_SUBSTITUTION)
3809 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
3811 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3814 /* If there are any characters in STRING that require full expansion,
3815 then call FUNC to expand STRING; otherwise just perform quote
3816 removal if necessary. This returns a new string. */
3818 expand_string_if_necessary (string
, quoted
, func
)
3829 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3830 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
3834 if (EXP_CHAR (string
[i
]))
3836 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
3838 ADVANCE_CHAR (string
, slen
, i
);
3843 list
= (*func
) (string
, quoted
);
3846 ret
= string_list (list
);
3847 dispose_words (list
);
3852 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
3853 ret
= string_quote_removal (string
, quoted
);
3855 ret
= savestring (string
);
3860 static inline char *
3861 expand_string_to_string_internal (string
, quoted
, func
)
3869 if (string
== 0 || *string
== '\0')
3870 return ((char *)NULL
);
3872 list
= (*func
) (string
, quoted
);
3875 ret
= string_list (list
);
3876 dispose_words (list
);
3885 expand_string_to_string (string
, quoted
)
3889 return (expand_string_to_string_internal (string
, quoted
, expand_string
));
3893 expand_string_unsplit_to_string (string
, quoted
)
3897 return (expand_string_to_string_internal (string
, quoted
, expand_string_unsplit
));
3901 expand_assignment_string_to_string (string
, quoted
)
3905 return (expand_string_to_string_internal (string
, quoted
, expand_string_assignment
));
3908 /* Kind of like a combination of dequote_string and quote_string_for_globbing;
3909 try to remove CTLESC quoting characters and convert CTLESC escaping a `&'
3910 or a backslash into a backslash. The output of this function must eventually
3911 be processed by strcreplace(). */
3913 quote_string_for_repl (string
, flags
)
3919 const char *s
, *send
;
3922 slen
= strlen (string
);
3923 send
= string
+ slen
;
3925 result
= (char *)xmalloc (slen
* 2 + 1);
3927 if (string
[0] == CTLESC
&& string
[1] == 0)
3934 /* This is awkward. We want to translate CTLESC-\ to \\ if we will
3935 eventually send this string through strcreplace(), which we will do
3936 only if shouldexp_replacement() determines that there is something
3937 to replace. We can either make sure to escape backslashes here and
3938 have shouldexp_replacement() signal that we should send the string to
3939 strcreplace() if it sees an escaped backslash, or we can scan the
3940 string before copying it and turn CTLESC-\ into \\ only if we encounter
3941 a CTLESC-& or a &. This does the former and changes shouldexp_replacement().
3942 If we double the backslashes here, we'll get doubled backslashes in any
3943 result that doesn't get passed to strcreplace(). */
3945 for (s
= string
, t
= result
; *s
; )
3947 /* This function's result has to be processed by strcreplace() */
3948 if (*s
== CTLESC
&& (s
[1] == '&' || s
[1] == '\\'))
3962 COPY_CHAR_P (t
, s
, send
);
3969 /* This does not perform word splitting on the WORD_LIST it returns and
3970 it treats $* as if it were quoted. It dequotes the WORD_LIST, adds
3971 backslash escapes before CTLESC-quoted backslash and `& if
3972 patsub_replacement is enabled. */
3974 expand_string_for_patsub (string
, quoted
)
3981 if (string
== 0 || *string
== '\0')
3982 return (char *)NULL
;
3984 value
= expand_string_for_pat (string
, quoted
, (int *)0, (int *)0);
3986 if (value
&& value
->word
)
3988 remove_quoted_nulls (value
->word
->word
); /* XXX */
3989 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
3994 t
= (value
->next
) ? string_list (value
) : value
->word
->word
;
3995 ret
= quote_string_for_repl (t
, quoted
);
3996 if (t
!= value
->word
->word
)
3998 dispose_words (value
);
4007 expand_arith_string (string
, quoted
)
4012 WORD_LIST
*list
, *tlist
;
4018 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
4019 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
4023 if (EXP_CHAR (string
[i
]))
4025 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
4026 saw_quote
= string
[i
];
4027 ADVANCE_CHAR (string
, slen
, i
);
4032 /* This is expanded version of expand_string_internal as it's called by
4033 expand_string_leave_quoted */
4034 td
.flags
= W_NOPROCSUB
|W_NOTILDE
; /* don't want process substitution or tilde expansion */
4035 #if 0 /* TAG: bash-5.2 */
4036 if (quoted
& Q_ARRAYSUB
)
4037 td
.flags
|= W_NOCOMSUB
;
4039 td
.word
= savestring (string
);
4040 list
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4041 /* This takes care of the calls from expand_string_leave_quoted and
4045 tlist
= word_list_split (list
);
4046 dispose_words (list
);
4049 dequote_list (list
);
4051 /* This comes from expand_string_if_necessary */
4054 ret
= string_list (list
);
4055 dispose_words (list
);
4061 else if (saw_quote
&& (quoted
& Q_ARITH
))
4062 ret
= string_quote_removal (string
, quoted
);
4063 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
4064 ret
= string_quote_removal (string
, quoted
);
4066 ret
= savestring (string
);
4071 #if defined (COND_COMMAND)
4072 /* Just remove backslashes in STRING. Returns a new string. */
4074 remove_backslashes (string
)
4079 r
= ret
= (char *)xmalloc (strlen (string
) + 1);
4080 for (s
= string
; s
&& *s
; )
4092 /* This needs better error handling. */
4093 /* Expand W for use as an argument to a unary or binary operator in a
4094 [[...]] expression. If SPECIAL is 1, this is the rhs argument
4095 to the != or == operator, and should be treated as a pattern. In
4096 this case, we quote the string specially for the globbing code. If
4097 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
4098 be quoted appropriately for regcomp/regexec. If SPECIAL is 3, this is
4099 an array subscript and should be quoted after expansion so it's only
4100 expanded once (Q_ARITH). The caller is responsible
4101 for removing the backslashes if the unquoted word is needed later. In
4102 any case, since we don't perform word splitting, we need to do quoted
4103 null character removal. */
4105 cond_expand_word (w
, special
)
4113 if (w
->word
== 0 || w
->word
[0] == '\0')
4114 return ((char *)NULL
);
4116 expand_no_split_dollar_star
= 1;
4117 w
->flags
|= W_NOSPLIT2
;
4118 qflags
= (special
== 3) ? Q_ARITH
: 0;
4119 l
= call_expand_word_internal (w
, qflags
, 0, (int *)0, (int *)0);
4120 expand_no_split_dollar_star
= 0;
4123 if (special
== 0) /* LHS */
4126 word_list_remove_quoted_nulls (l
);
4128 r
= string_list (l
);
4130 else if (special
== 3) /* arithmetic expression, Q_ARITH */
4133 word_list_remove_quoted_nulls (l
); /* for now */
4135 r
= string_list (l
);
4139 /* Need to figure out whether or not we should call dequote_escapes
4140 or a new dequote_ctlnul function here, and under what
4142 qflags
= QGLOB_CVTNULL
|QGLOB_CTLESC
;
4144 qflags
|= QGLOB_REGEXP
;
4145 word_list_remove_quoted_nulls (l
);
4146 p
= string_list (l
);
4147 r
= quote_string_for_globbing (p
, qflags
);
4159 /* Expand $'...' and $"..." in a string for code paths that don't do it. The
4160 FLAGS argument is 1 if this function should treat CTLESC as a quote
4161 character (e.g., for here-documents) or not (e.g., for shell_expand_line). */
4163 expand_string_dollar_quote (string
, flags
)
4167 size_t slen
, retind
, retsize
;
4168 int sindex
, c
, translen
, peekc
, news
;
4169 char *ret
, *trans
, *send
, *t
;
4172 slen
= strlen (string
);
4173 send
= string
+ slen
;
4177 ret
= xmalloc (retsize
);
4180 while (c
= string
[sindex
])
4185 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 1, retsize
, 64);
4186 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4190 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 2, retsize
, 64);
4191 ret
[retind
++] = string
[sindex
++];
4194 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4200 news
= skip_single_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4202 news
= skip_double_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4203 translen
= news
- sindex
- 1;
4204 RESIZE_MALLOCED_BUFFER (ret
, retind
, translen
+ 3, retsize
, 64);
4208 strncpy (ret
+ retind
, string
+ sindex
, translen
);
4211 if (news
> sindex
&& string
[news
- 1] == c
)
4217 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 2, retsize
, 64);
4219 ret
[retind
++] = string
[sindex
++];
4221 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4225 peekc
= string
[++sindex
];
4226 #if defined (TRANSLATABLE_STRINGS)
4227 if (peekc
!= '\'' && peekc
!= '"')
4232 RESIZE_MALLOCED_BUFFER (ret
, retind
, 2, retsize
, 16);
4236 if (string
[sindex
+ 1] == '\0') /* don't bother */
4238 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4240 ret
[retind
++] = peekc
;
4246 /* SX_COMPLETE is the equivalent of ALLOWESC here */
4247 /* We overload SX_COMPLETE below */
4248 news
= skip_single_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4249 /* Check for unclosed string and don't bother if so */
4250 if (news
> sindex
&& string
[news
] == '\0' && string
[news
-1] != peekc
)
4252 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4254 ret
[retind
++] = peekc
;
4257 t
= substring (string
, sindex
, news
- 1);
4258 trans
= ansiexpand (t
, 0, news
-sindex
-1, &translen
);
4260 t
= sh_single_quote (trans
);
4263 #if defined (TRANSLATABLE_STRINGS)
4267 t
= string_extract_double_quoted (string
, &news
, SX_COMPLETE
);
4268 /* Check for unclosed string and don't bother if so */
4269 if (news
> sindex
&& string
[news
] == '\0' && string
[news
-1] != peekc
)
4271 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4273 ret
[retind
++] = peekc
;
4277 trans
= locale_expand (t
, 0, news
-sindex
, 0, &translen
);
4279 if (singlequote_translations
&&
4280 ((news
-sindex
-1) != translen
|| STREQN (t
, trans
, translen
) == 0))
4281 t
= sh_single_quote (trans
);
4283 t
= sh_mkdoublequoted (trans
, translen
, 0);
4286 #endif /* TRANSLATABLE_STRINGS */
4289 translen
= strlen (trans
);
4291 RESIZE_MALLOCED_BUFFER (ret
, retind
, translen
+ 1, retsize
, 128);
4292 strcpy (ret
+ retind
, trans
);
4303 /* Call expand_word_internal to expand W and handle error returns.
4304 A convenience function for functions that don't want to handle
4305 any errors or free any memory before aborting. */
4307 call_expand_word_internal (w
, q
, i
, c
, e
)
4313 result
= expand_word_internal (w
, q
, i
, c
, e
);
4314 if (result
== &expand_word_error
|| result
== &expand_word_fatal
)
4316 /* By convention, each time this error is returned, w->word has
4317 already been freed (it sometimes may not be in the fatal case,
4318 but that doesn't result in a memory leak because we're going
4319 to exit in most cases). */
4320 w
->word
= (char *)NULL
;
4321 last_command_exit_value
= EXECUTION_FAILURE
;
4322 exp_jump_to_top_level ((result
== &expand_word_error
) ? DISCARD
: FORCE_EOF
);
4330 /* Perform parameter expansion, command substitution, and arithmetic
4331 expansion on STRING, as if it were a word. Leave the result quoted.
4332 Since this does not perform word splitting, it leaves quoted nulls
4335 expand_string_internal (string
, quoted
)
4342 if (string
== 0 || *string
== 0)
4343 return ((WORD_LIST
*)NULL
);
4346 td
.word
= savestring (string
);
4348 tresult
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4354 /* Expand STRING by performing parameter expansion, command substitution,
4355 and arithmetic expansion. Dequote the resulting WORD_LIST before
4356 returning it, but do not perform word splitting. The call to
4357 remove_quoted_nulls () is in here because word splitting normally
4358 takes care of quote removal. */
4360 expand_string_unsplit (string
, quoted
)
4366 if (string
== 0 || *string
== '\0')
4367 return ((WORD_LIST
*)NULL
);
4369 expand_no_split_dollar_star
= 1;
4370 value
= expand_string_internal (string
, quoted
);
4371 expand_no_split_dollar_star
= 0;
4377 remove_quoted_nulls (value
->word
->word
); /* XXX */
4378 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4380 dequote_list (value
);
4385 /* Expand the rhs of an assignment statement */
4387 expand_string_assignment (string
, quoted
)
4394 if (string
== 0 || *string
== '\0')
4395 return ((WORD_LIST
*)NULL
);
4397 expand_no_split_dollar_star
= 1;
4400 /* Other shells (ksh93) do it this way, which affects how $@ is expanded
4401 in constructs like bar=${@#0} (preserves the spaces resulting from the
4402 expansion of $@ in a context where you don't do word splitting); Posix
4403 interp 888 makes the expansion of $@ in contexts where word splitting
4404 is not performed unspecified. */
4405 td
.flags
= W_ASSIGNRHS
|W_NOSPLIT2
; /* Posix interp 888 */
4407 td
.flags
= W_ASSIGNRHS
;
4409 td
.flags
|= (W_NOGLOB
|W_TILDEEXP
);
4410 td
.word
= savestring (string
);
4411 value
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4414 expand_no_split_dollar_star
= 0;
4420 remove_quoted_nulls (value
->word
->word
); /* XXX */
4421 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4423 dequote_list (value
);
4428 /* Expand one of the PS? prompt strings. This is a sort of combination of
4429 expand_string_unsplit and expand_string_internal, but returns the
4430 passed string when an error occurs. Might want to trap other calls
4431 to jump_to_top_level here so we don't endlessly loop. */
4433 expand_prompt_string (string
, quoted
, wflags
)
4441 if (string
== 0 || *string
== 0)
4442 return ((WORD_LIST
*)NULL
);
4445 td
.word
= savestring (string
);
4447 no_longjmp_on_fatal_error
= 1;
4448 value
= expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4449 no_longjmp_on_fatal_error
= 0;
4451 if (value
== &expand_word_error
|| value
== &expand_word_fatal
)
4453 value
= make_word_list (make_bare_word (string
), (WORD_LIST
*)NULL
);
4461 remove_quoted_nulls (value
->word
->word
); /* XXX */
4462 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4464 dequote_list (value
);
4469 /* Expand STRING just as if you were expanding a word, but do not dequote
4470 the resultant WORD_LIST. This is called only from within this file,
4471 and is used to correctly preserve quoted characters when expanding
4472 things like ${1+"$@"}. This does parameter expansion, command
4473 substitution, arithmetic expansion, and word splitting. */
4475 expand_string_leave_quoted (string
, quoted
)
4482 if (string
== 0 || *string
== '\0')
4483 return ((WORD_LIST
*)NULL
);
4485 tlist
= expand_string_internal (string
, quoted
);
4489 tresult
= word_list_split (tlist
);
4490 dispose_words (tlist
);
4493 return ((WORD_LIST
*)NULL
);
4496 /* This does not perform word splitting or dequote the WORD_LIST
4499 expand_string_for_rhs (string
, quoted
, op
, pflags
, dollar_at_p
, expanded_p
)
4501 int quoted
, op
, pflags
;
4502 int *dollar_at_p
, *expanded_p
;
4508 if (string
== 0 || *string
== '\0')
4509 return (WORD_LIST
*)NULL
;
4511 /* We want field splitting to be determined by what is going to be done with
4512 the entire ${parameterOPword} expansion, so we don't want to split the RHS
4513 we expand here. However, the expansion of $* is determined by whether we
4514 are going to eventually perform word splitting, so we want to set this
4515 depending on whether or not are are going to be splitting: if the expansion
4516 is quoted, if the OP is `=', or if IFS is set to the empty string, we
4517 are not going to be splitting, so we set expand_no_split_dollar_star to
4518 note this to callees.
4519 We pass through PF_ASSIGNRHS as W_ASSIGNRHS if this is on the RHS of an
4520 assignment statement. */
4521 /* The updated treatment of $* is the result of Posix interp 888 */
4522 /* This was further clarified on the austin-group list in March, 2017 and
4523 in Posix bug 1129 */
4524 old_nosplit
= expand_no_split_dollar_star
;
4525 expand_no_split_dollar_star
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || op
== '=' || ifs_is_null
== 0; /* XXX - was 1 */
4526 td
.flags
= W_EXPANDRHS
; /* expanding RHS of ${paramOPword} */
4527 td
.flags
|= W_NOSPLIT2
; /* no splitting, remove "" and '' */
4528 if (pflags
& PF_ASSIGNRHS
) /* pass through */
4529 td
.flags
|= W_ASSIGNRHS
;
4532 td
.flags
|= W_ASSIGNRHS
; /* expand b in ${a=b} like assignment */
4534 td
.flags
|= W_ASSIGNRHS
|W_NOASSNTILDE
; /* expand b in ${a=b} like assignment */
4536 td
.word
= savestring (string
);
4537 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
4538 expand_no_split_dollar_star
= old_nosplit
;
4544 /* This does not perform word splitting or dequote the WORD_LIST
4545 it returns and it treats $* as if it were quoted. */
4547 expand_string_for_pat (string
, quoted
, dollar_at_p
, expanded_p
)
4549 int quoted
, *dollar_at_p
, *expanded_p
;
4555 if (string
== 0 || *string
== '\0')
4556 return (WORD_LIST
*)NULL
;
4558 oexp
= expand_no_split_dollar_star
;
4559 expand_no_split_dollar_star
= 1;
4560 td
.flags
= W_NOSPLIT2
; /* no splitting, remove "" and '' */
4561 td
.word
= savestring (string
);
4562 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
4563 expand_no_split_dollar_star
= oexp
;
4569 /* Expand STRING just as if you were expanding a word. This also returns
4570 a list of words. Note that filename globbing is *NOT* done for word
4571 or string expansion, just when the shell is expanding a command. This
4572 does parameter expansion, command substitution, arithmetic expansion,
4573 and word splitting. Dequote the resultant WORD_LIST before returning. */
4575 expand_string (string
, quoted
)
4581 if (string
== 0 || *string
== '\0')
4582 return ((WORD_LIST
*)NULL
);
4584 result
= expand_string_leave_quoted (string
, quoted
);
4585 return (result
? dequote_list (result
) : result
);
4588 /*******************************************
4590 * Functions to expand WORD_DESCs *
4592 *******************************************/
4594 /* Expand WORD, performing word splitting on the result. This does
4595 parameter expansion, command substitution, arithmetic expansion,
4596 word splitting, and quote removal. */
4599 expand_word (word
, quoted
)
4603 WORD_LIST
*result
, *tresult
;
4605 tresult
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4606 result
= word_list_split (tresult
);
4607 dispose_words (tresult
);
4608 return (result
? dequote_list (result
) : result
);
4611 /* Expand WORD, but do not perform word splitting on the result. This
4612 does parameter expansion, command substitution, arithmetic expansion,
4613 and quote removal. */
4615 expand_word_unsplit (word
, quoted
)
4621 result
= expand_word_leave_quoted (word
, quoted
);
4622 return (result
? dequote_list (result
) : result
);
4625 /* Perform shell expansions on WORD, but do not perform word splitting or
4626 quote removal on the result. Virtually identical to expand_word_unsplit;
4627 could be combined if implementations don't diverge. */
4629 expand_word_leave_quoted (word
, quoted
)
4635 expand_no_split_dollar_star
= 1;
4637 word
->flags
|= W_NOSPLIT
;
4638 word
->flags
|= W_NOSPLIT2
;
4639 result
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4640 expand_no_split_dollar_star
= 0;
4645 /***************************************************
4647 * Functions to handle quoting chars *
4649 ***************************************************/
4653 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
4654 The parser passes CTLNUL as CTLESC CTLNUL. */
4656 /* Quote escape characters in string s, but no other characters. This is
4657 used to protect CTLESC and CTLNUL in variable values from the rest of
4658 the word expansion process after the variable is expanded (word splitting
4659 and filename generation). If IFS is null, we quote spaces as well, just
4660 in case we split on spaces later (in the case of unquoted $@, we will
4661 eventually attempt to split the entire word on spaces). Corresponding
4662 code exists in dequote_escapes. Even if we don't end up splitting on
4663 spaces, quoting spaces is not a problem. This should never be called on
4664 a string that is quoted with single or double quotes or part of a here
4665 document (effectively double-quoted).
4666 FLAGS says whether or not we are going to split the result. If we are not,
4667 and there is a CTLESC or CTLNUL in IFS, we need to quote CTLESC and CTLNUL,
4668 respectively, to prevent them from being removed as part of dequoting. */
4670 quote_escapes_internal (string
, flags
)
4674 const char *s
, *send
;
4677 int quote_spaces
, skip_ctlesc
, skip_ctlnul
, nosplit
;
4680 slen
= strlen (string
);
4681 send
= string
+ slen
;
4683 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4684 nosplit
= (flags
& PF_NOSPLIT2
);
4686 for (skip_ctlesc
= skip_ctlnul
= 0, s
= ifs_value
; s
&& *s
; s
++)
4688 skip_ctlesc
|= (nosplit
== 0 && *s
== CTLESC
);
4689 skip_ctlnul
|= (nosplit
== 0 && *s
== CTLNUL
);
4692 t
= result
= (char *)xmalloc ((slen
* 2) + 1);
4697 if ((skip_ctlesc
== 0 && *s
== CTLESC
) || (skip_ctlnul
== 0 && *s
== CTLNUL
) || (quote_spaces
&& *s
== ' '))
4699 COPY_CHAR_P (t
, s
, send
);
4707 quote_escapes (string
)
4710 return (quote_escapes_internal (string
, 0));
4717 return (quote_escapes_internal (string
, PF_NOSPLIT2
));
4721 list_quote_escapes (list
)
4724 register WORD_LIST
*w
;
4727 for (w
= list
; w
; w
= w
->next
)
4730 w
->word
->word
= quote_escapes (t
);
4736 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
4738 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
4739 This is necessary to make unquoted CTLESC and CTLNUL characters in the
4740 data stream pass through properly.
4742 We need to remove doubled CTLESC characters inside quoted strings before
4743 quoting the entire string, so we do not double the number of CTLESC
4746 Also used by parts of the pattern substitution code. */
4748 dequote_escapes (string
)
4751 const char *s
, *send
;
4760 slen
= strlen (string
);
4761 send
= string
+ slen
;
4763 t
= result
= (char *)xmalloc (slen
+ 1);
4765 if (strchr (string
, CTLESC
) == 0)
4766 return (strcpy (result
, string
));
4768 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4773 if (*s
== CTLESC
&& (s
[1] == CTLESC
|| s
[1] == CTLNUL
|| (quote_spaces
&& s
[1] == ' ')))
4779 COPY_CHAR_P (t
, s
, send
);
4786 #if defined (INCLUDE_UNUSED)
4788 list_dequote_escapes (list
)
4791 register WORD_LIST
*w
;
4794 for (w
= list
; w
; w
= w
->next
)
4797 w
->word
->word
= dequote_escapes (t
);
4804 /* Return a new string with the quoted representation of character C.
4805 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
4806 set in any resultant WORD_DESC where this value is the word. */
4808 make_quoted_char (c
)
4813 temp
= (char *)xmalloc (3);
4828 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
4829 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
4830 this value is the word. */
4832 quote_string (string
)
4837 char *result
, *send
;
4841 result
= (char *)xmalloc (2);
4849 slen
= strlen (string
);
4850 send
= string
+ slen
;
4852 result
= (char *)xmalloc ((slen
* 2) + 1);
4854 for (t
= result
; string
< send
; )
4857 COPY_CHAR_P (t
, string
, send
);
4864 /* De-quote quoted characters in STRING. */
4866 dequote_string (string
)
4869 register char *s
, *t
;
4871 char *result
, *send
;
4874 if (string
[0] == CTLESC
&& string
[1] == 0)
4875 internal_debug ("dequote_string: string with bare CTLESC");
4877 slen
= STRLEN (string
);
4879 t
= result
= (char *)xmalloc (slen
+ 1);
4881 if (QUOTED_NULL (string
))
4887 /* A string consisting of only a single CTLESC should pass through unchanged */
4888 if (string
[0] == CTLESC
&& string
[1] == 0)
4895 /* If no character in the string can be quoted, don't bother examining
4896 each character. Just return a copy of the string passed to us. */
4897 if (strchr (string
, CTLESC
) == NULL
)
4898 return (strcpy (result
, string
));
4900 send
= string
+ slen
;
4910 COPY_CHAR_P (t
, s
, send
);
4917 /* Quote the entire WORD_LIST list. */
4922 register WORD_LIST
*w
;
4925 for (w
= list
; w
; w
= w
->next
)
4928 w
->word
->word
= quote_string (t
);
4930 w
->word
->flags
|= W_HASQUOTEDNULL
; /* XXX - turn on W_HASQUOTEDNULL here? */
4931 w
->word
->flags
|= W_QUOTED
;
4943 s
= dequote_string (word
->word
);
4944 if (QUOTED_NULL (word
->word
))
4945 word
->flags
&= ~W_HASQUOTEDNULL
;
4952 /* De-quote quoted characters in each word in LIST. */
4958 register WORD_LIST
*tlist
;
4960 for (tlist
= list
; tlist
; tlist
= tlist
->next
)
4962 s
= dequote_string (tlist
->word
->word
);
4963 if (QUOTED_NULL (tlist
->word
->word
))
4964 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
4965 free (tlist
->word
->word
);
4966 tlist
->word
->word
= s
;
4971 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
4974 remove_quoted_escapes (string
)
4981 t
= dequote_escapes (string
);
4989 /* Remove quoted $IFS characters from STRING. Quoted IFS characters are
4990 added to protect them from word splitting, but we need to remove them
4991 if no word splitting takes place. This returns newly-allocated memory,
4992 so callers can use it to replace savestring(). */
4994 remove_quoted_ifs (string
)
4997 register size_t slen
;
5002 slen
= strlen (string
);
5003 send
= string
+ slen
;
5006 ret
= (char *)xmalloc (slen
+ 1);
5010 if (string
[i
] == CTLESC
)
5013 if (string
[i
] == 0 || isifs (string
[i
]) == 0)
5019 COPY_CHAR_I (ret
, j
, string
, send
, i
);
5027 remove_quoted_nulls (string
)
5030 register size_t slen
;
5031 register int i
, j
, prev_i
;
5034 if (strchr (string
, CTLNUL
) == 0) /* XXX */
5035 return string
; /* XXX */
5037 slen
= strlen (string
);
5042 if (string
[i
] == CTLESC
)
5044 /* Old code had j++, but we cannot assume that i == j at this
5045 point -- what if a CTLNUL has already been removed from the
5046 string? We don't want to drop the CTLESC or recopy characters
5047 that we've already copied down. */
5049 string
[j
++] = CTLESC
;
5053 else if (string
[i
] == CTLNUL
)
5060 ADVANCE_CHAR (string
, slen
, i
); /* COPY_CHAR_I? */
5063 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
5073 /* Perform quoted null character removal on each element of LIST.
5074 This modifies LIST. */
5076 word_list_remove_quoted_nulls (list
)
5079 register WORD_LIST
*t
;
5081 for (t
= list
; t
; t
= t
->next
)
5083 remove_quoted_nulls (t
->word
->word
);
5084 t
->word
->flags
&= ~W_HASQUOTEDNULL
;
5088 /* **************************************************************** */
5090 /* Functions for Matching and Removing Patterns */
5092 /* **************************************************************** */
5094 #if defined (HANDLE_MULTIBYTE)
5095 # ifdef INCLUDE_UNUSED
5096 static unsigned char *
5097 mb_getcharlens (string
, len
)
5101 int i
, offset
, last
;
5108 ret
= (unsigned char *)xmalloc (len
);
5109 memset (ret
, 0, len
);
5110 while (string
[last
])
5112 ADVANCE_CHAR (string
, len
, offset
);
5113 ret
[last
] = offset
- last
;
5121 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
5122 can have one of 4 values:
5123 RP_LONG_LEFT remove longest matching portion at start of PARAM
5124 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
5125 RP_LONG_RIGHT remove longest matching portion at end of PARAM
5126 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
5129 #define RP_LONG_LEFT 1
5130 #define RP_SHORT_LEFT 2
5131 #define RP_LONG_RIGHT 3
5132 #define RP_SHORT_RIGHT 4
5134 /* Returns its first argument if nothing matched; new memory otherwise */
5136 remove_upattern (param
, pattern
, op
)
5137 char *param
, *pattern
;
5140 register size_t len
;
5142 register char *p
, *ret
, c
;
5144 len
= STRLEN (param
);
5149 case RP_LONG_LEFT
: /* remove longest match at start */
5150 for (p
= end
; p
>= param
; p
--)
5153 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5156 return (savestring (p
));
5163 case RP_SHORT_LEFT
: /* remove shortest match at start */
5164 for (p
= param
; p
<= end
; p
++)
5167 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5170 return (savestring (p
));
5176 case RP_LONG_RIGHT
: /* remove longest match at end */
5177 for (p
= param
; p
<= end
; p
++)
5179 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5182 ret
= savestring (param
);
5189 case RP_SHORT_RIGHT
: /* remove shortest match at end */
5190 for (p
= end
; p
>= param
; p
--)
5192 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5195 ret
= savestring (param
);
5203 return (param
); /* no match, return original string */
5206 #if defined (HANDLE_MULTIBYTE)
5207 /* Returns its first argument if nothing matched; new memory otherwise */
5209 remove_wpattern (wparam
, wstrlen
, wpattern
, op
)
5220 case RP_LONG_LEFT
: /* remove longest match at start */
5221 for (n
= wstrlen
; n
>= 0; n
--)
5223 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5224 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5227 return (wcsdup (wparam
+ n
));
5233 case RP_SHORT_LEFT
: /* remove shortest match at start */
5234 for (n
= 0; n
<= wstrlen
; n
++)
5236 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5237 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5240 return (wcsdup (wparam
+ n
));
5246 case RP_LONG_RIGHT
: /* remove longest match at end */
5247 for (n
= 0; n
<= wstrlen
; n
++)
5249 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5251 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5252 ret
= wcsdup (wparam
);
5259 case RP_SHORT_RIGHT
: /* remove shortest match at end */
5260 for (n
= wstrlen
; n
>= 0; n
--)
5262 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5264 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5265 ret
= wcsdup (wparam
);
5273 return (wparam
); /* no match, return original string */
5275 #endif /* HANDLE_MULTIBYTE */
5278 remove_pattern (param
, pattern
, op
)
5279 char *param
, *pattern
;
5286 if (*param
== '\0' || pattern
== NULL
|| *pattern
== '\0') /* minor optimization */
5287 return (savestring (param
));
5289 #if defined (HANDLE_MULTIBYTE)
5292 wchar_t *ret
, *oret
;
5294 wchar_t *wparam
, *wpattern
;
5297 /* XXX - could optimize here by checking param and pattern for multibyte
5298 chars with mbsmbchar and calling remove_upattern. */
5300 n
= xdupmbstowcs (&wpattern
, NULL
, pattern
);
5301 if (n
== (size_t)-1)
5303 xret
= remove_upattern (param
, pattern
, op
);
5304 return ((xret
== param
) ? savestring (param
) : xret
);
5306 n
= xdupmbstowcs (&wparam
, NULL
, param
);
5308 if (n
== (size_t)-1)
5311 xret
= remove_upattern (param
, pattern
, op
);
5312 return ((xret
== param
) ? savestring (param
) : xret
);
5314 oret
= ret
= remove_wpattern (wparam
, n
, wpattern
, op
);
5315 /* Don't bother to convert wparam back to multibyte string if nothing
5316 matched; just return copy of original string */
5321 return (savestring (param
));
5328 xret
= (char *)xmalloc (n
+ 1);
5329 memset (&ps
, '\0', sizeof (mbstate_t));
5330 n
= wcsrtombs (xret
, (const wchar_t **)&ret
, n
, &ps
);
5331 xret
[n
] = '\0'; /* just to make sure */
5338 xret
= remove_upattern (param
, pattern
, op
);
5339 return ((xret
== param
) ? savestring (param
) : xret
);
5343 /* Match PAT anywhere in STRING and return the match boundaries.
5344 This returns 1 in case of a successful match, 0 otherwise. SP
5345 and EP are pointers into the string where the match begins and
5346 ends, respectively. MTYPE controls what kind of match is attempted.
5347 MATCH_BEG and MATCH_END anchor the match at the beginning and end
5348 of the string, respectively. The longest match is returned. */
5350 match_upattern (string
, pat
, mtype
, sp
, ep
)
5357 register char *p
, *p1
, *npat
;
5360 /* If the pattern doesn't match anywhere in the string, go ahead and
5361 short-circuit right away. A minor optimization, saves a bunch of
5362 unnecessary calls to strmatch (up to N calls for a string of N
5363 characters) if the match is unsuccessful. To preserve the semantics
5364 of the substring matches below, we make sure that the pattern has
5365 `*' as first and last character, making a new pattern if necessary. */
5366 /* XXX - check this later if I ever implement `**' with special meaning,
5367 since this will potentially result in `**' at the beginning or end */
5369 if (pat
[0] != '*' || (pat
[0] == '*' && pat
[1] == LPAREN
&& extended_glob
) || pat
[len
- 1] != '*')
5371 int unescaped_backslash
;
5374 p
= npat
= (char *)xmalloc (len
+ 3);
5376 if ((mtype
!= MATCH_BEG
) && (*p1
!= '*' || (*p1
== '*' && p1
[1] == LPAREN
&& extended_glob
)))
5381 /* Need to also handle a pattern that ends with an unescaped backslash.
5382 For right now, we ignore it because the pattern matching code will
5383 fail the match anyway */
5384 /* If the pattern ends with a `*' we leave it alone if it's preceded by
5385 an even number of backslashes, but if it's escaped by a backslash
5386 we need to add another `*'. */
5387 if ((mtype
!= MATCH_END
) && (p1
[-1] == '*' && (unescaped_backslash
= p1
[-2] == '\\')))
5390 while (pp
>= pat
&& *pp
-- == '\\')
5391 unescaped_backslash
= 1 - unescaped_backslash
;
5392 if (unescaped_backslash
)
5395 else if (mtype
!= MATCH_END
&& p1
[-1] != '*')
5398 if (p1
[-1] != '*' || p1
[-2] == '\\')
5405 c
= strmatch (npat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
5408 if (c
== FNM_NOMATCH
)
5411 len
= STRLEN (string
);
5414 mlen
= umatchlen (pat
, len
);
5415 if (mlen
> (int)len
)
5421 for (p
= string
; p
<= end
; p
++)
5423 if (match_pattern_char (pat
, p
, FNMATCH_IGNCASE
))
5425 p1
= (mlen
== -1) ? end
: p
+ mlen
;
5426 /* p1 - p = length of portion of string to be considered
5427 p = current position in string
5428 mlen = number of characters consumed by match (-1 for entire string)
5430 we want to break immediately if the potential match len
5431 is greater than the number of characters remaining in the
5436 for ( ; p1
>= p
; p1
--)
5438 c
= *p1
; *p1
= '\0';
5439 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5448 /* If MLEN != -1, we have a fixed length pattern. */
5459 if (match_pattern_char (pat
, string
, FNMATCH_IGNCASE
) == 0)
5462 for (p
= (mlen
== -1) ? end
: string
+ mlen
; p
>= string
; p
--)
5465 if (strmatch (pat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5473 /* If MLEN != -1, we have a fixed length pattern. */
5481 for (p
= end
- ((mlen
== -1) ? len
: mlen
); p
<= end
; p
++)
5483 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5489 /* If MLEN != -1, we have a fixed length pattern. */
5500 #if defined (HANDLE_MULTIBYTE)
5502 #define WFOLD(c) (match_ignore_case && iswupper (c) ? towlower (c) : (c))
5504 /* Match WPAT anywhere in WSTRING and return the match boundaries.
5505 This returns 1 in case of a successful match, 0 otherwise. Wide
5506 character version. */
5508 match_wpattern (wstring
, indices
, wstrlen
, wpat
, mtype
, sp
, ep
)
5516 wchar_t wc
, *wp
, *nwpat
, *wp1
;
5519 int n
, n1
, n2
, simple
;
5521 simple
= (wpat
[0] != L
'\\' && wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'[');
5522 #if defined (EXTENDED_GLOB)
5524 simple
&= (wpat
[1] != L
'(' || (wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'+' && wpat
[0] != L
'!' && wpat
[0] != L
'@')); /*)*/
5527 /* If the pattern doesn't match anywhere in the string, go ahead and
5528 short-circuit right away. A minor optimization, saves a bunch of
5529 unnecessary calls to strmatch (up to N calls for a string of N
5530 characters) if the match is unsuccessful. To preserve the semantics
5531 of the substring matches below, we make sure that the pattern has
5532 `*' as first and last character, making a new pattern if necessary. */
5533 len
= wcslen (wpat
);
5534 if (wpat
[0] != L
'*' || (wpat
[0] == L
'*' && wpat
[1] == WLPAREN
&& extended_glob
) || wpat
[len
- 1] != L
'*')
5536 int unescaped_backslash
;
5539 wp
= nwpat
= (wchar_t *)xmalloc ((len
+ 3) * sizeof (wchar_t));
5541 if (*wp1
!= L
'*' || (*wp1
== '*' && wp1
[1] == WLPAREN
&& extended_glob
))
5543 while (*wp1
!= L
'\0')
5546 /* See comments above in match_upattern. */
5547 if (wp1
[-1] == L
'*' && (unescaped_backslash
= wp1
[-2] == L
'\\'))
5550 while (wpp
>= wpat
&& *wpp
-- == L
'\\')
5551 unescaped_backslash
= 1 - unescaped_backslash
;
5552 if (unescaped_backslash
)
5555 else if (wp1
[-1] != L
'*')
5558 if (wp1
[-1] != L
'*' || wp1
[-2] == L
'\\')
5565 len
= wcsmatch (nwpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
5568 if (len
== FNM_NOMATCH
)
5571 mlen
= wmatchlen (wpat
, wstrlen
);
5572 if (mlen
> (int)wstrlen
)
5575 /* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
5579 for (n
= 0; n
<= wstrlen
; n
++)
5581 n2
= simple
? (WFOLD(*wpat
) == WFOLD(wstring
[n
])) : match_pattern_wchar (wpat
, wstring
+ n
, FNMATCH_IGNCASE
);
5584 n1
= (mlen
== -1) ? wstrlen
: n
+ mlen
;
5588 for ( ; n1
>= n
; n1
--)
5590 wc
= wstring
[n1
]; wstring
[n1
] = L
'\0';
5591 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5599 /* If MLEN != -1, we have a fixed length pattern. */
5609 if (match_pattern_wchar (wpat
, wstring
, FNMATCH_IGNCASE
) == 0)
5612 for (n
= (mlen
== -1) ? wstrlen
: mlen
; n
>= 0; n
--)
5614 wc
= wstring
[n
]; wstring
[n
] = L
'\0';
5615 if (wcsmatch (wpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5623 /* If MLEN != -1, we have a fixed length pattern. */
5631 for (n
= wstrlen
- ((mlen
== -1) ? wstrlen
: mlen
); n
<= wstrlen
; n
++)
5633 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5636 *ep
= indices
[wstrlen
];
5639 /* If MLEN != -1, we have a fixed length pattern. */
5650 #endif /* HANDLE_MULTIBYTE */
5653 match_pattern (string
, pat
, mtype
, sp
, ep
)
5658 #if defined (HANDLE_MULTIBYTE)
5661 wchar_t *wstring
, *wpat
;
5665 if (string
== 0 || pat
== 0 || *pat
== 0)
5668 #if defined (HANDLE_MULTIBYTE)
5671 if (mbsmbchar (string
) == 0 && mbsmbchar (pat
) == 0)
5672 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5674 n
= xdupmbstowcs (&wpat
, NULL
, pat
);
5675 if (n
== (size_t)-1)
5676 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5677 n
= xdupmbstowcs (&wstring
, &indices
, string
);
5678 if (n
== (size_t)-1)
5681 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5683 ret
= match_wpattern (wstring
, indices
, n
, wpat
, mtype
, sp
, ep
);
5693 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5697 getpatspec (c
, value
)
5702 return ((*value
== '#') ? RP_LONG_LEFT
: RP_SHORT_LEFT
);
5704 return ((*value
== '%') ? RP_LONG_RIGHT
: RP_SHORT_RIGHT
);
5707 /* Posix.2 says that the WORD should be run through tilde expansion,
5708 parameter expansion, command substitution and arithmetic expansion.
5709 This leaves the result quoted, so quote_string_for_globbing () has
5710 to be called to fix it up for strmatch (). If QUOTED is non-zero,
5711 it means that the entire expression was enclosed in double quotes.
5712 This means that quoting characters in the pattern do not make any
5713 special pattern characters quoted. For example, the `*' in the
5714 following retains its special meaning: "${foo#'*'}". */
5716 getpattern (value
, quoted
, expandpat
)
5718 int quoted
, expandpat
;
5725 /* There is a problem here: how to handle single or double quotes in the
5726 pattern string when the whole expression is between double quotes?
5727 POSIX.2 says that enclosing double quotes do not cause the pattern to
5728 be quoted, but does that leave us a problem with @ and array[@] and their
5729 expansions inside a pattern? */
5731 if (expandpat
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *tword
)
5734 pat
= string_extract_double_quoted (tword
, &i
, SX_STRIPDQ
);
5740 /* expand_string_for_pat () leaves WORD quoted and does not perform
5742 l
= *value
? expand_string_for_pat (value
,
5743 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? Q_PATQUOTE
: quoted
,
5744 (int *)NULL
, (int *)NULL
)
5747 word_list_remove_quoted_nulls (l
);
5748 pat
= string_list (l
);
5752 tword
= quote_string_for_globbing (pat
, QGLOB_CVTNULL
);
5760 /* Handle removing a pattern from a string as a result of ${name%[%]value}
5761 or ${name#[#]value}. */
5763 variable_remove_pattern (value
, pattern
, patspec
, quoted
)
5764 char *value
, *pattern
;
5765 int patspec
, quoted
;
5769 tword
= remove_pattern (value
, pattern
, patspec
);
5776 list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
)
5779 int patspec
, itype
, quoted
;
5785 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
5787 tword
= remove_pattern (l
->word
->word
, pattern
, patspec
);
5788 w
= alloc_word_desc ();
5789 w
->word
= tword
? tword
: savestring ("");
5790 new = make_word_list (w
, new);
5793 l
= REVERSE_LIST (new, WORD_LIST
*);
5794 tword
= string_list_pos_params (itype
, l
, quoted
, 0);
5801 parameter_list_remove_pattern (itype
, pattern
, patspec
, quoted
)
5804 int patspec
, quoted
;
5809 list
= list_rest_of_args ();
5811 return ((char *)NULL
);
5812 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5813 dispose_words (list
);
5817 #if defined (ARRAY_VARS)
5819 array_remove_pattern (var
, pattern
, patspec
, starsub
, quoted
)
5823 int starsub
; /* so we can figure out how it's indexed */
5833 v
= var
; /* XXX - for now */
5835 itype
= starsub
? '*' : '@';
5837 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
5838 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
5840 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
5842 return ((char *)NULL
);
5843 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5844 dispose_words (list
);
5848 #endif /* ARRAY_VARS */
5851 parameter_brace_remove_pattern (varname
, value
, estatep
, patstr
, rtype
, quoted
, flags
)
5852 char *varname
, *value
;
5853 array_eltstate_t
*estatep
;
5855 int rtype
, quoted
, flags
;
5857 int vtype
, patspec
, starsub
;
5858 char *temp1
, *val
, *pattern
, *oname
;
5862 return ((char *)NULL
);
5864 oname
= this_command_name
;
5865 this_command_name
= varname
;
5867 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
5870 this_command_name
= oname
;
5871 return ((char *)NULL
);
5874 starsub
= vtype
& VT_STARSUB
;
5875 vtype
&= ~VT_STARSUB
;
5877 patspec
= getpatspec (rtype
, patstr
);
5878 if (patspec
== RP_LONG_LEFT
|| patspec
== RP_LONG_RIGHT
)
5881 /* Need to pass getpattern newly-allocated memory in case of expansion --
5882 the expansion code will free the passed string on an error. */
5883 temp1
= savestring (patstr
);
5884 pattern
= getpattern (temp1
, quoted
, 1);
5887 temp1
= (char *)NULL
; /* shut up gcc */
5891 case VT_ARRAYMEMBER
:
5892 temp1
= remove_pattern (val
, pattern
, patspec
);
5893 if (vtype
== VT_VARIABLE
)
5897 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
5898 ? quote_string (temp1
)
5899 : quote_escapes (temp1
);
5904 #if defined (ARRAY_VARS)
5906 temp1
= array_remove_pattern (v
, pattern
, patspec
, starsub
, quoted
);
5907 if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5909 val
= quote_escapes (temp1
);
5916 temp1
= parameter_list_remove_pattern (varname
[0], pattern
, patspec
, quoted
);
5917 if (temp1
&& quoted
== 0 && ifs_is_null
)
5919 /* Posix interp 888 */
5921 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5923 val
= quote_escapes (temp1
);
5930 this_command_name
= oname
;
5936 #if defined (PROCESS_SUBSTITUTION)
5938 static void reap_some_procsubs
PARAMS((int));
5940 /*****************************************************************/
5942 /* Hacking Process Substitution */
5944 /*****************************************************************/
5946 #if !defined (HAVE_DEV_FD)
5947 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
5948 of FIFOs the shell has open. unlink_fifo_list will walk the list and
5949 unlink the ones that don't have a living process on the other end.
5950 unlink_all_fifos will walk the list and unconditionally unlink them, trying
5951 to open and close the FIFO first to release any child processes sleeping on
5952 the FIFO. add_fifo_list adds the name of an open FIFO to the list.
5953 NFIFO is a count of the number of FIFOs in the list. */
5954 #define FIFO_INCR 20
5956 /* PROC value of -1 means the process has been reaped and the FIFO needs to
5957 be removed. PROC value of 0 means the slot is unused. */
5963 static struct temp_fifo
*fifo_list
= (struct temp_fifo
*)NULL
;
5965 static int fifo_list_size
;
5972 for (i
= 0; i
< fifo_list_size
; i
++)
5974 if (fifo_list
[i
].file
)
5975 free (fifo_list
[i
].file
);
5976 fifo_list
[i
].file
= NULL
;
5977 fifo_list
[i
].proc
= 0;
5983 copy_fifo_list (sizep
)
5988 return (void *)NULL
;
5992 add_fifo_list (pathname
)
5997 if (nfifo
>= fifo_list_size
- 1)
5999 osize
= fifo_list_size
;
6000 fifo_list_size
+= FIFO_INCR
;
6001 fifo_list
= (struct temp_fifo
*)xrealloc (fifo_list
,
6002 fifo_list_size
* sizeof (struct temp_fifo
));
6003 for (i
= osize
; i
< fifo_list_size
; i
++)
6005 fifo_list
[i
].file
= (char *)NULL
;
6006 fifo_list
[i
].proc
= 0; /* unused */
6010 fifo_list
[nfifo
].file
= savestring (pathname
);
6018 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
6020 unlink (fifo_list
[i
].file
);
6021 free (fifo_list
[i
].file
);
6022 fifo_list
[i
].file
= (char *)NULL
;
6023 fifo_list
[i
].proc
= 0;
6035 for (i
= saved
= 0; i
< nfifo
; i
++)
6037 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
6039 unlink (fifo_list
[i
].file
);
6040 free (fifo_list
[i
].file
);
6041 fifo_list
[i
].file
= (char *)NULL
;
6042 fifo_list
[i
].proc
= 0;
6048 /* If we didn't remove some of the FIFOs, compact the list. */
6051 for (i
= j
= 0; i
< nfifo
; i
++)
6052 if (fifo_list
[i
].file
)
6056 fifo_list
[j
].file
= fifo_list
[i
].file
;
6057 fifo_list
[j
].proc
= fifo_list
[i
].proc
;
6058 fifo_list
[i
].file
= (char *)NULL
;
6059 fifo_list
[i
].proc
= 0;
6077 for (i
= 0; i
< nfifo
; i
++)
6079 fifo_list
[i
].proc
= (pid_t
)-1;
6080 #if defined (O_NONBLOCK)
6081 fd
= open (fifo_list
[i
].file
, O_RDWR
|O_NONBLOCK
);
6093 /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
6094 from some point in the past, and close all open FIFOs in fifo_list
6095 that are not marked as active in LIST. If LIST is NULL, close
6096 everything in fifo_list. LSIZE is the number of elements in LIST, in
6097 case it's larger than fifo_list_size (size of fifo_list). */
6099 close_new_fifos (list
, lsize
)
6108 unlink_fifo_list ();
6112 for (plist
= (char *)list
, i
= 0; i
< lsize
; i
++)
6113 if (plist
[i
] == 0 && i
< fifo_list_size
&& fifo_list
[i
].proc
!= -1)
6116 for (i
= lsize
; i
< fifo_list_size
; i
++)
6121 find_procsub_child (pid
)
6126 for (i
= 0; i
< nfifo
; i
++)
6127 if (fifo_list
[i
].proc
== pid
)
6133 set_procsub_status (ind
, pid
, status
)
6138 if (ind
>= 0 && ind
< nfifo
)
6139 fifo_list
[ind
].proc
= (pid_t
)-1; /* sentinel */
6142 /* If we've marked the process for this procsub as dead, close the
6143 associated file descriptor and delete the FIFO. */
6145 reap_some_procsubs (max
)
6150 for (i
= 0; i
< max
; i
++)
6151 if (fifo_list
[i
].proc
== (pid_t
)-1) /* reaped */
6158 reap_some_procsubs (nfifo
);
6168 for (i
= 0; i
< nfifo
; i
++)
6170 if (fifo_list
[i
].proc
!= (pid_t
)-1 && fifo_list
[i
].proc
> 0)
6172 r
= wait_for (fifo_list
[i
].proc
, 0);
6173 save_proc_status (fifo_list
[i
].proc
, r
);
6174 fifo_list
[i
].proc
= (pid_t
)-1;
6197 tname
= sh_mktmpname ("sh-np", MT_USERANDOM
|MT_USETMPDIR
);
6198 if (mkfifo (tname
, 0600) < 0)
6201 return ((char *)NULL
);
6204 add_fifo_list (tname
);
6208 #else /* HAVE_DEV_FD */
6210 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
6211 has open to children. NFDS is a count of the number of bits currently
6212 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
6214 /* dev_fd_list[I] value of -1 means the process has been reaped and file
6215 descriptor I needs to be closed. Value of 0 means the slot is unused. */
6217 static pid_t
*dev_fd_list
= (pid_t
*)NULL
;
6219 static int totfds
; /* The highest possible number of open files. */
6240 for (i
= 0; nfds
&& i
< totfds
; i
++)
6247 copy_fifo_list (sizep
)
6252 if (nfds
== 0 || totfds
== 0)
6256 return (void *)NULL
;
6261 ret
= xmalloc (totfds
* sizeof (pid_t
));
6262 return (memcpy (ret
, dev_fd_list
, totfds
* sizeof (pid_t
)));
6269 if (dev_fd_list
== 0 || fd
>= totfds
)
6274 totfds
= getdtablesize ();
6275 if (totfds
< 0 || totfds
> 256)
6280 dev_fd_list
= (pid_t
*)xrealloc (dev_fd_list
, totfds
* sizeof (dev_fd_list
[0]));
6281 /* XXX - might need a loop for this */
6282 memset (dev_fd_list
+ ofds
, '\0', (totfds
- ofds
) * sizeof (pid_t
));
6285 dev_fd_list
[fd
] = 1; /* marker; updated later */
6292 return 0; /* used for cleanup; not needed with /dev/fd */
6305 if (dev_fd_list
[fd
])
6308 dev_fd_list
[fd
] = 0;
6321 for (i
= totfds
-1; nfds
&& i
>= 0; i
--)
6330 unlink_fifo_list ();
6333 /* Take LIST, which is a snapshot copy of dev_fd_list from some point in
6334 the past, and close all open fds in dev_fd_list that are not marked
6335 as open in LIST. If LIST is NULL, close everything in dev_fd_list.
6336 LSIZE is the number of elements in LIST, in case it's larger than
6337 totfds (size of dev_fd_list). */
6339 close_new_fifos (list
, lsize
)
6348 unlink_fifo_list ();
6352 for (plist
= (pid_t
*)list
, i
= 0; i
< lsize
; i
++)
6353 if (plist
[i
] == 0 && i
< totfds
&& dev_fd_list
[i
])
6356 for (i
= lsize
; i
< totfds
; i
++)
6361 find_procsub_child (pid
)
6369 for (i
= 0; i
< totfds
; i
++)
6370 if (dev_fd_list
[i
] == pid
)
6377 set_procsub_status (ind
, pid
, status
)
6382 if (ind
>= 0 && ind
< totfds
)
6383 dev_fd_list
[ind
] = (pid_t
)-1; /* sentinel */
6386 /* If we've marked the process for this procsub as dead, close the
6387 associated file descriptor. */
6389 reap_some_procsubs (max
)
6394 for (i
= 0; nfds
> 0 && i
< max
; i
++)
6395 if (dev_fd_list
[i
] == (pid_t
)-1)
6402 reap_some_procsubs (totfds
);
6412 for (i
= 0; nfds
> 0 && i
< totfds
; i
++)
6414 if (dev_fd_list
[i
] != (pid_t
)-1 && dev_fd_list
[i
] > 0)
6416 r
= wait_for (dev_fd_list
[i
], 0);
6417 save_proc_status (dev_fd_list
[i
], r
);
6418 dev_fd_list
[i
] = (pid_t
)-1;
6424 #if defined (NOTDEF)
6425 print_dev_fd_list ()
6429 fprintf (stderr
, "pid %ld: dev_fd_list:", (long)getpid ());
6432 for (i
= 0; i
< totfds
; i
++)
6435 fprintf (stderr
, " %d", i
);
6437 fprintf (stderr
, "\n");
6442 make_dev_fd_filename (fd
)
6445 char *ret
, intbuf
[INT_STRLEN_BOUND (int) + 1], *p
;
6447 ret
= (char *)xmalloc (sizeof (DEV_FD_PREFIX
) + 8);
6449 strcpy (ret
, DEV_FD_PREFIX
);
6450 p
= inttostr (fd
, intbuf
, sizeof (intbuf
));
6451 strcpy (ret
+ sizeof (DEV_FD_PREFIX
) - 1, p
);
6457 #endif /* HAVE_DEV_FD */
6459 /* Return a filename that will open a connection to the process defined by
6460 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
6461 a filename in /dev/fd corresponding to a descriptor that is one of the
6462 ends of the pipe. If not defined, we use named pipes on systems that have
6463 them. Systems without /dev/fd and named pipes are out of luck.
6465 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
6466 use the read end of the pipe and dup that file descriptor to fd 0 in
6467 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
6468 writing or use the write end of the pipe in the child, and dup that
6469 file descriptor to fd 1 in the child. The parent does the opposite. */
6472 process_substitute (string
, open_for_read_in_child
)
6474 int open_for_read_in_child
;
6477 int fd
, result
, rc
, function_value
;
6479 #if defined (HAVE_DEV_FD)
6480 int parent_pipe_fd
, child_pipe_fd
;
6482 #endif /* HAVE_DEV_FD */
6483 #if defined (JOB_CONTROL)
6484 pid_t old_pipeline_pgrp
;
6487 if (!string
|| !*string
|| wordexp_only
)
6488 return ((char *)NULL
);
6490 #if !defined (HAVE_DEV_FD)
6491 pathname
= make_named_pipe ();
6492 #else /* HAVE_DEV_FD */
6493 if (pipe (fildes
) < 0)
6495 sys_error ("%s", _("cannot make pipe for process substitution"));
6496 return ((char *)NULL
);
6498 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
6499 the pipe in the parent, otherwise the read end. */
6500 parent_pipe_fd
= fildes
[open_for_read_in_child
];
6501 child_pipe_fd
= fildes
[1 - open_for_read_in_child
];
6502 /* Move the parent end of the pipe to some high file descriptor, to
6503 avoid clashes with FDs used by the script. */
6504 parent_pipe_fd
= move_to_high_fd (parent_pipe_fd
, 1, 64);
6506 pathname
= make_dev_fd_filename (parent_pipe_fd
);
6507 #endif /* HAVE_DEV_FD */
6511 sys_error ("%s", _("cannot make pipe for process substitution"));
6512 return ((char *)NULL
);
6515 old_pid
= last_made_pid
;
6517 #if defined (JOB_CONTROL)
6518 old_pipeline_pgrp
= pipeline_pgrp
;
6519 if (pipeline_pgrp
== 0 || (subshell_environment
& (SUBSHELL_PIPE
|SUBSHELL_FORK
|SUBSHELL_ASYNC
)) == 0)
6520 pipeline_pgrp
= shell_pgrp
;
6522 #endif /* JOB_CONTROL */
6524 pid
= make_child ((char *)NULL
, FORK_ASYNC
);
6528 int old_interactive
;
6530 old_interactive
= interactive
;
6532 /* The currently-executing shell is not interactive */
6535 reset_terminating_signals (); /* XXX */
6536 free_pushed_string_input ();
6537 /* Cancel traps, in trap.c. */
6538 restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
6539 subshell_environment
&= ~SUBSHELL_IGNTRAP
;
6540 QUIT
; /* catch any interrupts we got post-fork */
6541 setup_async_signals ();
6543 if (open_for_read_in_child
== 0 && old_interactive
&& (bash_input
.type
== st_stdin
|| bash_input
.type
== st_stream
))
6544 async_redirect_stdin ();
6547 subshell_environment
|= SUBSHELL_COMSUB
|SUBSHELL_PROCSUB
|SUBSHELL_ASYNC
;
6549 /* We don't inherit the verbose option for command substitutions now, so
6550 let's try it for process substitutions. */
6551 change_flag ('v', FLAG_OFF
);
6553 /* if we're expanding a redirection, we shouldn't have access to the
6554 temporary environment, but commands in the subshell should have
6555 access to their own temporary environment. */
6556 if (expanding_redir
)
6557 flush_temporary_env ();
6560 #if defined (JOB_CONTROL)
6561 set_sigchld_handler ();
6562 stop_making_children ();
6563 /* XXX - should we only do this in the parent? (as in command subst) */
6564 pipeline_pgrp
= old_pipeline_pgrp
;
6566 stop_making_children ();
6567 #endif /* JOB_CONTROL */
6571 sys_error ("%s", _("cannot make child for process substitution"));
6573 #if defined (HAVE_DEV_FD)
6574 close (parent_pipe_fd
);
6575 close (child_pipe_fd
);
6576 #endif /* HAVE_DEV_FD */
6577 #if defined (JOB_CONTROL)
6578 restore_pipeline (1);
6580 return ((char *)NULL
);
6585 #if defined (JOB_CONTROL)
6586 last_procsub_child
= restore_pipeline (0);
6587 /* We assume that last_procsub_child->next == last_procsub_child because
6588 of how jobs.c:add_process() works. */
6589 last_procsub_child
->next
= 0;
6590 procsub_add (last_procsub_child
);
6593 #if defined (HAVE_DEV_FD)
6594 dev_fd_list
[parent_pipe_fd
] = pid
;
6596 fifo_list
[nfifo
-1].proc
= pid
;
6599 last_made_pid
= old_pid
;
6601 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6603 #endif /* JOB_CONTROL && PGRP_PIPE */
6605 #if defined (HAVE_DEV_FD)
6606 close (child_pipe_fd
);
6607 #endif /* HAVE_DEV_FD */
6612 set_sigint_handler ();
6614 #if defined (JOB_CONTROL)
6615 /* make sure we don't have any job control */
6616 set_job_control (0);
6618 /* Clear out any existing list of process substitutions */
6621 /* The idea is that we want all the jobs we start from an async process
6622 substitution to be in the same process group, but not the same pgrp
6623 as our parent shell, since we don't want to affect our parent shell's
6624 jobs if we get a SIGHUP and end up calling hangup_all_jobs, for example.
6625 If pipeline_pgrp != shell_pgrp, we assume that there is a job control
6626 shell somewhere in our parent process chain (since make_child initializes
6627 pipeline_pgrp to shell_pgrp if job_control == 0). What we do in this
6628 case is to set pipeline_pgrp to our PID, so all jobs started by this
6629 process have that same pgrp and we are basically the process group leader.
6630 This should not have negative effects on child processes surviving
6631 after we exit, since we wait for the children we create, but that is
6632 something to watch for. */
6634 if (pipeline_pgrp
!= shell_pgrp
)
6635 pipeline_pgrp
= getpid ();
6636 #endif /* JOB_CONTROL */
6638 #if !defined (HAVE_DEV_FD)
6639 /* Open the named pipe in the child. */
6640 fd
= open (pathname
, open_for_read_in_child
? O_RDONLY
: O_WRONLY
);
6643 /* Two separate strings for ease of translation. */
6644 if (open_for_read_in_child
)
6645 sys_error (_("cannot open named pipe %s for reading"), pathname
);
6647 sys_error (_("cannot open named pipe %s for writing"), pathname
);
6651 if (open_for_read_in_child
)
6653 if (sh_unset_nodelay_mode (fd
) < 0)
6655 sys_error (_("cannot reset nodelay mode for fd %d"), fd
);
6659 #else /* HAVE_DEV_FD */
6661 #endif /* HAVE_DEV_FD */
6663 /* Discard buffered stdio output before replacing the underlying file
6665 if (open_for_read_in_child
== 0)
6668 if (dup2 (fd
, open_for_read_in_child
? 0 : 1) < 0)
6670 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname
,
6671 open_for_read_in_child
? 0 : 1);
6675 if (fd
!= (open_for_read_in_child
? 0 : 1))
6678 /* Need to close any files that this process has open to pipes inherited
6680 if (current_fds_to_close
)
6682 close_fd_bitmap (current_fds_to_close
);
6683 current_fds_to_close
= (struct fd_bitmap
*)NULL
;
6686 #if defined (HAVE_DEV_FD)
6687 /* Make sure we close the parent's end of the pipe and clear the slot
6688 in the fd list so it is not closed later, if reallocated by, for
6689 instance, pipe(2). */
6690 close (parent_pipe_fd
);
6691 dev_fd_list
[parent_pipe_fd
] = 0;
6692 #endif /* HAVE_DEV_FD */
6694 /* subshells shouldn't have this flag, which controls using the temporary
6695 environment for variable lookups. We have already flushed the temporary
6696 environment above in the case we're expanding a redirection, so processes
6697 executed by this command need to be able to set it independently of their
6699 expanding_redir
= 0;
6701 remove_quoted_escapes (string
);
6703 startup_state
= 2; /* see if we can avoid a fork */
6704 parse_and_execute_level
= 0;
6706 /* Give process substitution a place to jump back to on failure,
6707 so we don't go back up to main (). */
6708 result
= setjmp_nosigs (top_level
);
6710 /* If we're running a process substitution inside a shell function,
6711 trap `return' so we don't return from the function in the subshell
6712 and go off to never-never land. */
6713 if (result
== 0 && return_catch_flag
)
6714 function_value
= setjmp_nosigs (return_catch
);
6718 if (result
== ERREXIT
)
6719 rc
= last_command_exit_value
;
6720 else if (result
== EXITPROG
|| result
== EXITBLTIN
)
6721 rc
= last_command_exit_value
;
6723 rc
= EXECUTION_FAILURE
;
6724 else if (function_value
)
6725 rc
= return_catch_value
;
6729 rc
= parse_and_execute (string
, "process substitution", (SEVAL_NONINT
|SEVAL_NOHIST
));
6730 /* leave subshell level intact for any exit trap */
6733 #if !defined (HAVE_DEV_FD)
6734 /* Make sure we close the named pipe in the child before we exit. */
6735 close (open_for_read_in_child
? 0 : 1);
6736 #endif /* !HAVE_DEV_FD */
6738 last_command_exit_value
= rc
;
6739 rc
= run_exit_trap ();
6743 #endif /* PROCESS_SUBSTITUTION */
6745 /***********************************/
6747 /* Command Substitution */
6749 /***********************************/
6751 #define COMSUB_PIPEBUF 4096
6754 optimize_cat_file (r
, quoted
, flags
, flagp
)
6756 int quoted
, flags
, *flagp
;
6761 fd
= open_redir_file (r
, (char **)0);
6763 return &expand_param_error
;
6765 ret
= read_comsub (fd
, quoted
, flags
, flagp
);
6772 read_comsub (fd
, quoted
, flags
, rflag
)
6773 int fd
, quoted
, flags
;
6776 char *istring
, buf
[COMSUB_PIPEBUF
], *bufp
;
6777 int c
, tflag
, skip_ctlesc
, skip_ctlnul
;
6779 size_t istring_index
;
6780 size_t istring_size
;
6783 #if defined (HANDLE_MULTIBYTE)
6790 istring
= (char *)NULL
;
6791 istring_index
= istring_size
= bufn
= tflag
= 0;
6793 skip_ctlesc
= ifs_cmap
[CTLESC
];
6794 skip_ctlnul
= ifs_cmap
[CTLNUL
];
6796 mb_cur_max
= MB_CUR_MAX
;
6799 /* Read the output of the command through the pipe. */
6806 bufn
= zread (fd
, buf
, sizeof (buf
));
6818 internal_warning ("%s", _("command substitution: ignored null byte in input"));
6825 /* Add the character to ISTRING, possibly after resizing it. */
6826 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, mb_cur_max
+1, istring_size
, 512);
6828 /* This is essentially quote_string inline */
6829 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) /* || c == CTLESC || c == CTLNUL */)
6830 istring
[istring_index
++] = CTLESC
;
6831 else if ((flags
& PF_ASSIGNRHS
) && skip_ctlesc
&& c
== CTLESC
)
6832 istring
[istring_index
++] = CTLESC
;
6833 /* Escape CTLESC and CTLNUL in the output to protect those characters
6834 from the rest of the word expansions (word splitting and globbing.)
6835 This is essentially quote_escapes inline. */
6836 else if (skip_ctlesc
== 0 && c
== CTLESC
)
6837 istring
[istring_index
++] = CTLESC
;
6838 else if ((skip_ctlnul
== 0 && c
== CTLNUL
) || (c
== ' ' && (ifs_value
&& *ifs_value
== 0)))
6839 istring
[istring_index
++] = CTLESC
;
6841 #if defined (HANDLE_MULTIBYTE)
6842 if ((locale_utf8locale
&& (c
& 0x80)) ||
6843 (locale_utf8locale
== 0 && mb_cur_max
> 1 && (unsigned char)c
> 127))
6845 /* read a multibyte character from buf */
6846 /* punt on the hard case for now */
6847 memset (&ps
, '\0', sizeof (mbstate_t));
6848 mblen
= mbrtowc (&wc
, bufp
-1, bufn
, &ps
);
6849 if (MB_INVALIDCH (mblen
) || mblen
== 0 || mblen
== 1)
6850 istring
[istring_index
++] = c
;
6853 istring
[istring_index
++] = c
;
6854 for (i
= 0; i
< mblen
-1; i
++)
6855 istring
[istring_index
++] = *bufp
++;
6862 istring
[istring_index
++] = c
;
6866 istring
[istring_index
] = '\0';
6868 /* If we read no output, just return now and save ourselves some
6870 if (istring_index
== 0)
6875 return (char *)NULL
;
6878 /* Strip trailing newlines from the output of the command. */
6879 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
6881 while (istring_index
> 0)
6883 if (istring
[istring_index
- 1] == '\n')
6887 /* If the newline was quoted, remove the quoting char. */
6888 if (istring
[istring_index
- 1] == CTLESC
)
6894 istring
[istring_index
] = '\0';
6897 strip_trailing (istring
, istring_index
- 1, 1);
6904 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
6905 contained string possibly quoted. */
6907 command_substitute (string
, quoted
, flags
)
6912 pid_t pid
, old_pid
, old_pipeline_pgrp
, old_async_pid
;
6914 int result
, fildes
[2], function_value
, pflags
, rc
, tflag
, fork_flags
;
6918 istring
= (char *)NULL
;
6920 /* Don't fork () if there is no need to. In the case of no command to
6921 run, just return NULL. */
6922 for (s
= string
; s
&& *s
&& (shellblank (*s
) || *s
== '\n'); s
++)
6924 if (s
== 0 || *s
== 0)
6925 return ((WORD_DESC
*)NULL
);
6927 if (*s
== '<' && (s
[1] != '<' && s
[1] != '>' && s
[1] != '&'))
6931 cmd
= parse_string_to_command (string
, 0); /* XXX - flags */
6932 if (cmd
&& can_optimize_cat_file (cmd
))
6935 istring
= optimize_cat_file (cmd
->value
.Simple
->redirects
, quoted
, flags
, &tflag
);
6936 if (istring
== &expand_param_error
)
6938 last_command_exit_value
= EXECUTION_FAILURE
;
6942 last_command_exit_value
= EXECUTION_SUCCESS
; /* compat */
6943 last_command_subst_pid
= dollar_dollar_pid
;
6945 dispose_command (cmd
);
6946 ret
= alloc_word_desc ();
6947 ret
->word
= istring
;
6952 dispose_command (cmd
);
6955 if (wordexp_only
&& read_but_dont_execute
)
6957 last_command_exit_value
= EX_WEXPCOMSUB
;
6958 jump_to_top_level (EXITPROG
);
6961 /* We're making the assumption here that the command substitution will
6962 eventually run a command from the file system. Since we'll run
6963 maybe_make_export_env in this subshell before executing that command,
6964 the parent shell and any other shells it starts will have to remake
6965 the environment. If we make it before we fork, other shells won't
6966 have to. Don't bother if we have any temporary variable assignments,
6967 though, because the export environment will be remade after this
6968 command completes anyway, but do it if all the words to be expanded
6969 are variable assignments. */
6970 if (subst_assign_varlist
== 0 || garglist
== 0)
6971 maybe_make_export_env (); /* XXX */
6973 /* Flags to pass to parse_and_execute() */
6974 pflags
= (interactive
&& sourcelevel
== 0) ? SEVAL_RESETLINE
: 0;
6976 old_pid
= last_made_pid
;
6978 /* Pipe the output of executing STRING into the current shell. */
6979 if (pipe (fildes
) < 0)
6981 sys_error ("%s", _("cannot make pipe for command substitution"));
6985 #if defined (JOB_CONTROL)
6986 old_pipeline_pgrp
= pipeline_pgrp
;
6987 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline or
6988 we've already forked to run a disk command (and are expanding redirections,
6990 if ((subshell_environment
& (SUBSHELL_FORK
|SUBSHELL_PIPE
)) == 0)
6991 pipeline_pgrp
= shell_pgrp
;
6992 cleanup_the_pipeline ();
6993 #endif /* JOB_CONTROL */
6995 old_async_pid
= last_asynchronous_pid
;
6996 fork_flags
= (subshell_environment
&SUBSHELL_ASYNC
) ? FORK_ASYNC
: 0;
6997 pid
= make_child ((char *)NULL
, fork_flags
|FORK_NOTERM
);
6998 last_asynchronous_pid
= old_async_pid
;
7002 /* Reset the signal handlers in the child, but don't free the
7003 trap strings. Set a flag noting that we have to free the
7004 trap strings if we run trap to change a signal disposition. */
7005 reset_signal_handlers ();
7008 kill (getpid (), SIGINT
);
7009 CLRINTERRUPT
; /* if we're ignoring SIGINT somehow */
7011 QUIT
; /* catch any interrupts we got post-fork */
7012 subshell_environment
|= SUBSHELL_RESETTRAP
;
7013 subshell_environment
&= ~SUBSHELL_IGNTRAP
;
7016 #if defined (JOB_CONTROL)
7017 /* XXX DO THIS ONLY IN PARENT ? XXX */
7018 set_sigchld_handler ();
7019 stop_making_children ();
7021 pipeline_pgrp
= old_pipeline_pgrp
;
7023 stop_making_children ();
7024 #endif /* JOB_CONTROL */
7028 sys_error (_("cannot make child for command substitution"));
7031 last_made_pid
= old_pid
;
7036 return ((WORD_DESC
*)NULL
);
7041 /* The currently executing shell is not interactive. */
7044 #if defined (JOB_CONTROL)
7045 /* Invariant: in child processes started to run command substitutions,
7046 pipeline_pgrp == shell_pgrp. Other parts of the shell assume this. */
7047 if (pipeline_pgrp
> 0 && pipeline_pgrp
!= shell_pgrp
)
7048 shell_pgrp
= pipeline_pgrp
;
7051 set_sigint_handler (); /* XXX */
7053 free_pushed_string_input ();
7055 /* Discard buffered stdio output before replacing the underlying file
7059 if (dup2 (fildes
[1], 1) < 0)
7061 sys_error ("%s", _("command_substitute: cannot duplicate pipe as fd 1"));
7062 exit (EXECUTION_FAILURE
);
7065 /* If standard output is closed in the parent shell
7066 (such as after `exec >&-'), file descriptor 1 will be
7067 the lowest available file descriptor, and end up in
7068 fildes[0]. This can happen for stdin and stderr as well,
7069 but stdout is more important -- it will cause no output
7070 to be generated from this command. */
7071 if ((fildes
[1] != fileno (stdin
)) &&
7072 (fildes
[1] != fileno (stdout
)) &&
7073 (fildes
[1] != fileno (stderr
)))
7076 if ((fildes
[0] != fileno (stdin
)) &&
7077 (fildes
[0] != fileno (stdout
)) &&
7078 (fildes
[0] != fileno (stderr
)))
7082 /* Let stdio know the fd may have changed from text to binary mode, and
7083 make sure to preserve stdout line buffering. */
7084 freopen (NULL
, "w", stdout
);
7085 sh_setlinebuf (stdout
);
7086 #endif /* __CYGWIN__ */
7088 /* This is a subshell environment. */
7089 subshell_environment
|= SUBSHELL_COMSUB
;
7091 /* Many shells do not appear to inherit the -v option for command
7093 change_flag ('v', FLAG_OFF
);
7095 /* When inherit_errexit option is not enabled, command substitution does
7096 not inherit the -e flag. It is enabled when Posix mode is enabled */
7097 if (inherit_errexit
== 0)
7099 builtin_ignoring_errexit
= 0;
7100 change_flag ('e', FLAG_OFF
);
7104 /* If we are expanding a redirection, we can dispose of any temporary
7105 environment we received, since redirections are not supposed to have
7106 access to the temporary environment. We will have to see whether this
7107 affects temporary environments supplied to `eval', but the temporary
7108 environment gets copied to builtin_env at some point. */
7109 if (expanding_redir
)
7111 flush_temporary_env ();
7112 expanding_redir
= 0;
7115 remove_quoted_escapes (string
);
7117 /* We want to expand aliases on this pass if we are not in posix mode
7118 for backwards compatibility. */
7120 expand_aliases
= posixly_correct
== 0;
7122 startup_state
= 2; /* see if we can avoid a fork */
7123 parse_and_execute_level
= 0;
7125 /* Give command substitution a place to jump back to on failure,
7126 so we don't go back up to main (). */
7127 result
= setjmp_nosigs (top_level
);
7129 /* If we're running a command substitution inside a shell function,
7130 trap `return' so we don't return from the function in the subshell
7131 and go off to never-never land. */
7132 if (result
== 0 && return_catch_flag
)
7133 function_value
= setjmp_nosigs (return_catch
);
7137 if (result
== ERREXIT
)
7138 rc
= last_command_exit_value
;
7139 else if (result
== EXITPROG
|| result
== EXITBLTIN
)
7140 rc
= last_command_exit_value
;
7142 rc
= EXECUTION_FAILURE
;
7143 else if (function_value
)
7144 rc
= return_catch_value
;
7148 rc
= parse_and_execute (string
, "command substitution", pflags
|SEVAL_NOHIST
);
7149 /* leave subshell level intact for any exit trap */
7152 last_command_exit_value
= rc
;
7153 rc
= run_exit_trap ();
7154 #if defined (PROCESS_SUBSTITUTION)
7155 unlink_fifo_list ();
7163 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
7165 #endif /* JOB_CONTROL && PGRP_PIPE */
7169 begin_unwind_frame ("read-comsub");
7170 dummyfd
= fildes
[0];
7171 add_unwind_protect (close
, dummyfd
);
7173 /* Block SIGINT while we're reading from the pipe. If the child
7174 process gets a SIGINT, it will either handle it or die, and the
7175 read will return. */
7176 BLOCK_SIGNAL (SIGINT
, set
, oset
);
7178 istring
= read_comsub (fildes
[0], quoted
, flags
, &tflag
);
7181 discard_unwind_frame ("read-comsub");
7182 UNBLOCK_SIGNAL (oset
);
7184 current_command_subst_pid
= pid
;
7185 last_command_exit_value
= wait_for (pid
, JWAIT_NOTERM
);
7186 last_command_subst_pid
= pid
;
7187 last_made_pid
= old_pid
;
7189 #if defined (JOB_CONTROL)
7190 /* If last_command_exit_value > 128, then the substituted command
7191 was terminated by a signal. If that signal was SIGINT, then send
7192 SIGINT to ourselves. This will break out of loops, for instance. */
7193 if (last_command_exit_value
== (128 + SIGINT
) && last_command_exit_signal
== SIGINT
)
7194 kill (getpid (), SIGINT
);
7195 #endif /* JOB_CONTROL */
7197 ret
= alloc_word_desc ();
7198 ret
->word
= istring
;
7205 /********************************************************
7207 * Utility functions for parameter expansion *
7209 ********************************************************/
7211 #if defined (ARRAY_VARS)
7214 array_length_reference (s
)
7225 var
= array_variable_part (s
, 0, &t
, &len
);
7227 /* If unbound variables should generate an error, report one and return
7229 if ((var
== 0 || invisible_p (var
) || (assoc_p (var
) == 0 && array_p (var
) == 0)) && unbound_vars_is_error
)
7233 set_exit_status (EXECUTION_FAILURE
);
7238 else if (var
== 0 || invisible_p (var
))
7241 /* We support a couple of expansions for variables that are not arrays.
7242 We'll return the length of the value for v[0], and 1 for v[@] or
7243 v[*]. Return 0 for everything else. */
7245 array
= array_p (var
) ? array_cell (var
) : (ARRAY
*)NULL
;
7246 h
= assoc_p (var
) ? assoc_cell (var
) : (HASH_TABLE
*)NULL
;
7248 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == RBRACK
)
7251 return (h
? assoc_num_elements (h
) : 0);
7252 else if (array_p (var
))
7253 return (array
? array_num_elements (array
) : 0);
7255 return (var_isset (var
) ? 1 : 0);
7261 akey
= expand_subscript_string (t
, 0); /* [ */
7262 t
[len
- 1] = RBRACK
;
7263 if (akey
== 0 || *akey
== 0)
7265 err_badarraysub (t
);
7269 t
= assoc_reference (assoc_cell (var
), akey
);
7274 ind
= array_expand_index (var
, t
, len
, 0);
7275 /* negative subscripts to indexed arrays count back from end */
7276 if (var
&& array_p (var
) && ind
< 0)
7277 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
7280 err_badarraysub (t
);
7284 t
= array_reference (array
, ind
);
7286 t
= (ind
== 0) ? value_cell (var
) : (char *)NULL
;
7289 len
= MB_STRLEN (t
);
7292 #endif /* ARRAY_VARS */
7295 valid_brace_expansion_word (name
, var_is_special
)
7299 if (DIGIT (*name
) && all_digits (name
))
7301 else if (var_is_special
)
7303 #if defined (ARRAY_VARS)
7304 else if (valid_array_reference (name
, 0))
7306 #endif /* ARRAY_VARS */
7307 else if (legal_identifier (name
))
7314 chk_atstar (name
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
7317 int *quoted_dollar_atp
, *contains_dollar_at
;
7323 if (quoted_dollar_atp
)
7324 *quoted_dollar_atp
= 0;
7325 if (contains_dollar_at
)
7326 *contains_dollar_at
= 0;
7330 /* check for $@ and $* */
7331 if (name
[0] == '@' && name
[1] == 0)
7333 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
7334 *quoted_dollar_atp
= 1;
7335 if (contains_dollar_at
)
7336 *contains_dollar_at
= 1;
7339 else if (name
[0] == '*' && name
[1] == '\0' && quoted
== 0)
7341 /* Need more checks here that parallel what string_list_pos_params and
7342 param_expand do. Check expand_no_split_dollar_star and ??? */
7343 if (contains_dollar_at
&& expand_no_split_dollar_star
== 0)
7344 *contains_dollar_at
= 1;
7348 /* Now check for ${array[@]} and ${array[*]} */
7349 #if defined (ARRAY_VARS)
7350 else if (valid_array_reference (name
, 0))
7352 temp1
= mbschr (name
, LBRACK
);
7353 if (temp1
&& temp1
[1] == '@' && temp1
[2] == RBRACK
)
7355 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
7356 *quoted_dollar_atp
= 1;
7357 if (contains_dollar_at
)
7358 *contains_dollar_at
= 1;
7361 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
7362 which should result in separate words even when IFS is unset. */
7363 if (temp1
&& temp1
[1] == '*' && temp1
[2] == RBRACK
&& quoted
== 0)
7365 if (contains_dollar_at
)
7366 *contains_dollar_at
= 1;
7374 /* Parameter expand NAME, and return a new string which is the expansion,
7375 or NULL if there was no expansion. NAME is as given in ${NAMEcWORD}.
7376 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
7377 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
7378 NAME was found inside of a double-quoted expression. */
7380 parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, estatep
)
7382 int var_is_special
, quoted
, pflags
;
7383 array_eltstate_t
*estatep
;
7390 array_eltstate_t es
;
7396 #if defined (ARRAY_VARS)
7398 es
= *estatep
; /* structure copy */
7401 init_eltstate (&es
);
7402 es
.ind
= INTMAX_MIN
;
7406 /* Handle multiple digit arguments, as in ${11}. */
7407 if (legal_number (name
, &arg_index
))
7409 tt
= get_dollar_var_value (arg_index
);
7411 temp
= (*tt
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7413 : quote_escapes (tt
);
7415 temp
= (char *)NULL
;
7418 else if (var_is_special
) /* ${@} */
7421 tt
= (char *)xmalloc (2 + strlen (name
));
7422 tt
[sindex
= 0] = '$';
7423 strcpy (tt
+ 1, name
);
7425 ret
= param_expand (tt
, &sindex
, quoted
, (int *)NULL
, (int *)NULL
,
7426 (int *)NULL
, (int *)NULL
, pflags
);
7428 /* Make sure we note that we saw a quoted null string and pass the flag back
7429 to the caller in addition to the value. */
7430 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && STR_DOLLAR_AT_STAR (name
) &&
7431 ret
&& ret
->word
&& QUOTED_NULL (ret
->word
))
7432 ret
->flags
|= W_HASQUOTEDNULL
;
7436 #if defined (ARRAY_VARS)
7437 else if (valid_array_reference (name
, 0))
7440 var
= array_variable_part (name
, 0, &tt
, (int *)0);
7441 /* These are the cases where word splitting will not be performed */
7442 if (pflags
& PF_ASSIGNRHS
)
7444 if (ALL_ELEMENT_SUB (tt
[0]) && tt
[1] == RBRACK
)
7446 /* Only treat as double quoted if array variable */
7447 if (var
&& (array_p (var
) || assoc_p (var
)))
7448 temp
= array_value (name
, quoted
|Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &es
);
7450 temp
= array_value (name
, quoted
, 0, &es
);
7453 temp
= array_value (name
, quoted
, 0, &es
);
7455 /* Posix interp 888 */
7456 else if (pflags
& PF_NOSPLIT2
)
7458 /* Special cases, then general case, for each of A[@], A[*], A[n] */
7459 #if defined (HANDLE_MULTIBYTE)
7460 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
7462 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
7464 temp
= array_value (name
, Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &es
);
7465 else if (tt
[0] == '@' && tt
[1] == RBRACK
)
7466 temp
= array_value (name
, quoted
, 0, &es
);
7467 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
7468 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &es
);
7469 else if (tt
[0] == '*' && tt
[1] == RBRACK
)
7470 temp
= array_value (name
, quoted
, 0, &es
);
7472 temp
= array_value (name
, quoted
, 0, &es
);
7474 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
7475 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &es
);
7477 temp
= array_value (name
, quoted
, 0, &es
);
7478 if (es
.subtype
== 0 && temp
)
7480 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7481 ? quote_string (temp
)
7482 : quote_escapes (temp
);
7483 rflags
|= W_ARRAYIND
;
7485 *estatep
= es
; /* structure copy */
7487 /* Note that array[*] and array[@] expanded to a quoted null string by
7488 returning the W_HASQUOTEDNULL flag to the caller in addition to TEMP. */
7489 else if (es
.subtype
== 1 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7490 rflags
|= W_HASQUOTEDNULL
;
7491 else if (es
.subtype
== 2 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7492 rflags
|= W_HASQUOTEDNULL
;
7495 flush_eltstate (&es
);
7498 else if (var
= find_variable (name
))
7500 if (var_isset (var
) && invisible_p (var
) == 0)
7502 #if defined (ARRAY_VARS)
7503 /* We avoid a memory leak by saving TT as the memory allocated by
7504 assoc_to_string or array_to_string and leaving it 0 otherwise,
7505 then freeing TT after quoting temp. */
7507 if ((pflags
& PF_ALLINDS
) && assoc_p (var
))
7508 tt
= temp
= assoc_empty (assoc_cell (var
)) ? (char *)NULL
: assoc_to_string (assoc_cell (var
), " ", quoted
);
7509 else if ((pflags
& PF_ALLINDS
) && array_p (var
))
7510 tt
= temp
= array_empty (array_cell (var
)) ? (char *)NULL
: array_to_string (array_cell (var
), " ", quoted
);
7511 else if (assoc_p (var
))
7512 temp
= assoc_reference (assoc_cell (var
), "0");
7513 else if (array_p (var
))
7514 temp
= array_reference (array_cell (var
), 0);
7516 temp
= value_cell (var
);
7518 temp
= value_cell (var
);
7522 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7523 ? quote_string (temp
)
7524 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
7525 : quote_escapes (temp
));
7529 temp
= (char *)NULL
;
7531 else if (var
= find_variable_last_nameref (name
, 0))
7533 temp
= nameref_cell (var
);
7534 #if defined (ARRAY_VARS)
7535 /* Handle expanding nameref whose value is x[n] */
7536 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
7539 goto expand_arrayref
;
7543 /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
7544 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
7546 set_exit_status (EXECUTION_FAILURE
);
7547 report_error (_("%s: invalid variable name for name reference"), temp
);
7548 temp
= &expand_param_error
;
7551 temp
= (char *)NULL
;
7554 temp
= (char *)NULL
;
7558 ret
= alloc_word_desc ();
7560 ret
->flags
|= rflags
;
7566 parameter_brace_find_indir (name
, var_is_special
, quoted
, find_nameref
)
7568 int var_is_special
, quoted
, find_nameref
;
7575 if (find_nameref
&& var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)) &&
7576 nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
7577 return (savestring (t
));
7579 /* If var_is_special == 0, and name is not an array reference, this does
7580 more expansion than necessary. It should really look up the variable's
7581 value and not try to expand it. */
7582 pflags
= PF_IGNUNBOUND
;
7583 /* Note that we're not going to be doing word splitting here */
7586 pflags
|= PF_ASSIGNRHS
; /* suppresses word splitting */
7587 oldex
= expand_no_split_dollar_star
;
7588 expand_no_split_dollar_star
= 1;
7590 w
= parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, 0);
7592 expand_no_split_dollar_star
= oldex
;
7595 /* Have to dequote here if necessary */
7598 temp
= ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || var_is_special
)
7599 ? dequote_string (t
)
7600 : dequote_escapes (t
);
7604 dispose_word_desc (w
);
7609 /* Expand an indirect reference to a variable: ${!NAME} expands to the
7610 value of the variable whose name is the value of NAME. */
7612 parameter_brace_expand_indir (name
, var_is_special
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
7614 int var_is_special
, quoted
, pflags
;
7615 int *quoted_dollar_atp
, *contains_dollar_at
;
7621 /* See if it's a nameref first, behave in ksh93-compatible fashion.
7622 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
7623 bash performs an indirect lookup on foo[0] and expands the result;
7624 ksh93 expands bar[0]. We could do that here -- there are enough usable
7625 primitives to do that -- but do not at this point. */
7626 if (var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)))
7628 if (nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
7630 w
= alloc_word_desc ();
7631 w
->word
= savestring (t
);
7637 /* An indirect reference to a positional parameter or a special parameter
7638 is ok. Indirect references to array references, as explained above, are
7639 ok (currently). Only references to unset variables are errors at this
7641 if (legal_identifier (name
) && v
== 0)
7643 report_error (_("%s: invalid indirect expansion"), name
);
7644 w
= alloc_word_desc ();
7645 w
->word
= &expand_param_error
;
7650 t
= parameter_brace_find_indir (name
, var_is_special
, quoted
, 0);
7652 chk_atstar (t
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
7654 #if defined (ARRAY_VARS)
7655 /* Array references to unset variables are also an error */
7656 if (t
== 0 && valid_array_reference (name
, 0))
7658 v
= array_variable_part (name
, 0, (char **)0, (int *)0);
7661 report_error (_("%s: invalid indirect expansion"), name
);
7662 w
= alloc_word_desc ();
7663 w
->word
= &expand_param_error
;
7668 return (WORD_DESC
*)NULL
;
7673 return (WORD_DESC
*)NULL
;
7675 if (valid_brace_expansion_word (t
, SPECIAL_VAR (t
, 0)) == 0)
7677 report_error (_("%s: invalid variable name"), t
);
7679 w
= alloc_word_desc ();
7680 w
->word
= &expand_param_error
;
7685 w
= parameter_brace_expand_word (t
, SPECIAL_VAR(t
, 0), quoted
, pflags
, 0);
7691 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
7692 depending on the value of C, the separating character. C can be one of
7693 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
7694 between double quotes. */
7696 parameter_brace_expand_rhs (name
, value
, op
, quoted
, pflags
, qdollaratp
, hasdollarat
)
7698 int op
, quoted
, pflags
, *qdollaratp
, *hasdollarat
;
7702 char *t
, *t1
, *temp
, *vname
, *newval
;
7703 int l_hasdollat
, sindex
, arrayref
;
7705 array_eltstate_t es
;
7707 /*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
7708 /* If the entire expression is between double quotes, we want to treat
7709 the value as a double-quoted string, with the exception that we strip
7710 embedded unescaped double quotes (for sh backwards compatibility). */
7711 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *value
)
7714 temp
= string_extract_double_quoted (value
, &sindex
, SX_STRIPDQ
);
7719 w
= alloc_word_desc ();
7721 l
= *temp
? expand_string_for_rhs (temp
, quoted
, op
, pflags
, &l_hasdollat
, (int *)NULL
)
7724 *hasdollarat
= l_hasdollat
|| (l
&& l
->next
);
7728 /* list_string takes multiple CTLNULs and turns them into an empty word
7729 with W_SAWQUOTEDNULL set. Turn it back into a single CTLNUL for the
7730 rest of this function and the caller. */
7731 for (tl
= l
; tl
; tl
= tl
->next
)
7733 if (tl
->word
&& (tl
->word
->word
== 0 || tl
->word
->word
[0] == 0) &&
7734 (tl
->word
->flags
| W_SAWQUOTEDNULL
))
7736 t
= make_quoted_char ('\0');
7737 FREE (tl
->word
->word
);
7739 tl
->word
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
7740 tl
->word
->flags
&= ~W_SAWQUOTEDNULL
;
7746 /* If l->next is not null, we know that TEMP contained "$@", since that
7747 is the only expansion that creates more than one word. */
7748 if (qdollaratp
&& ((l_hasdollat
&& quoted
) || l
->next
))
7750 /*itrace("parameter_brace_expand_rhs: %s:%s: l != NULL, set *qdollaratp", name, value);*/
7754 /* The expansion of TEMP returned something. We need to treat things
7755 slightly differently if L_HASDOLLAT is non-zero. If we have "$@",
7756 the individual words have already been quoted. We need to turn them
7757 into a string with the words separated by the first character of
7758 $IFS without any additional quoting, so string_list_dollar_at won't
7759 do the right thing. If IFS is null, we want "$@" to split into
7760 separate arguments, not be concatenated, so we use string_list_internal
7761 and mark the word to be split on spaces later. We use
7762 string_list_dollar_star for "$@" otherwise. */
7763 if (l
->next
&& ifs_is_null
)
7765 temp
= string_list_internal (l
, " ");
7766 w
->flags
|= W_SPLITSPACE
;
7768 else if (l_hasdollat
|| l
->next
)
7769 temp
= string_list_dollar_star (l
, quoted
, 0);
7772 temp
= string_list (l
);
7773 if (temp
&& (QUOTED_NULL (temp
) == 0) && (l
->word
->flags
& W_SAWQUOTEDNULL
))
7774 w
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
7777 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
7778 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
7779 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
7780 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7781 (which is more paranoia than anything else), we need to return the
7782 quoted null string and set the flags to indicate it. */
7783 if (l
->next
== 0 && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
) && QUOTED_NULL (l
->word
->word
) && (l
->word
->flags
& W_HASQUOTEDNULL
))
7785 w
->flags
|= W_HASQUOTEDNULL
;
7786 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null, turning off qdollaratp", name, value);*/
7787 /* If we return a quoted null with L_HASDOLLARAT, we either have a
7788 construct like "${@-$@}" or "${@-${@-$@}}" with no positional
7789 parameters or a quoted expansion of "$@" with $1 == ''. In either
7790 case, we don't want to enable special handling of $@. */
7791 if (qdollaratp
&& l_hasdollat
)
7796 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && l_hasdollat
)
7798 /* Posix interp 221 changed the rules on this. The idea is that
7799 something like "$xxx$@" should expand the same as "${foo-$xxx$@}"
7800 when foo and xxx are unset. The problem is that it's not in any
7801 way backwards compatible and few other shells do it. We're eventually
7802 going to try and split the difference (heh) a little bit here. */
7803 /* l_hasdollat == 1 means we saw a quoted dollar at. */
7805 /* The brace expansion occurred between double quotes and there was
7806 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
7807 it does not expand to anything. In this case, we want to return
7808 a quoted empty string. Posix interp 888 */
7809 temp
= make_quoted_char ('\0');
7810 w
->flags
|= W_HASQUOTEDNULL
;
7811 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null", name, value);*/
7814 temp
= (char *)NULL
;
7816 if (op
== '-' || op
== '+')
7823 t1
= temp
? dequote_string (temp
) : savestring ("");
7829 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1]) || VALID_INDIR_PARAM (name
[1])))
7831 vname
= parameter_brace_find_indir (name
+ 1, SPECIAL_VAR (name
, 1), quoted
, 1);
7832 if (vname
== 0 || *vname
== 0)
7834 report_error (_("%s: invalid indirect expansion"), name
);
7838 return &expand_wdesc_error
;
7840 if (legal_identifier (vname
) == 0)
7842 report_error (_("%s: invalid variable name"), vname
);
7846 return &expand_wdesc_error
;
7851 #if defined (ARRAY_VARS)
7852 if (valid_array_reference (vname
, 0))
7854 init_eltstate (&es
);
7855 v
= assign_array_element (vname
, t1
, ASS_ALLOWALLSUB
, &es
);
7860 #endif /* ARRAY_VARS */
7861 v
= bind_variable (vname
, t1
, 0);
7863 if (v
== 0 || readonly_p (v
) || noassign_p (v
)) /* expansion error */
7865 if ((v
== 0 || readonly_p (v
)) && interactive_shell
== 0 && posixly_correct
)
7867 last_command_exit_value
= EXECUTION_FAILURE
;
7868 exp_jump_to_top_level (FORCE_EOF
);
7874 last_command_exit_value
= EX_BADUSAGE
;
7875 exp_jump_to_top_level (DISCARD
);
7879 stupidly_hack_special_variables (vname
);
7881 /* "In all cases, the final value of parameter shall be substituted." */
7882 if (shell_compatibility_level
> 51)
7885 #if defined (ARRAY_VARS)
7889 flush_eltstate (&es
);
7892 t1
= get_variable_value (v
);
7894 t1
= value_cell (v
);
7901 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
7903 /* If we are double-quoted or if we are not going to be performing word
7904 splitting, we want to quote the value we return appropriately, like
7905 the other expansions this function handles. */
7906 w
->word
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (t1
) : quote_escapes (t1
);
7907 /* If we have something that's non-null, but not a quoted null string,
7908 and we're not going to be performing word splitting (we know we're not
7909 because the operator is `='), we can forget we saw a quoted null. */
7910 if (w
->word
&& w
->word
[0] && QUOTED_NULL (w
->word
) == 0)
7911 w
->flags
&= ~W_SAWQUOTEDNULL
;
7913 /* If we convert a null string into a quoted null, make sure the caller
7915 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && QUOTED_NULL (w
->word
))
7916 w
->flags
|= W_HASQUOTEDNULL
;
7921 /* Deal with the right hand side of a ${name:?value} expansion in the case
7922 that NAME is null or not set. If VALUE is non-null it is expanded and
7923 used as the error message to print, otherwise a standard message is
7926 parameter_brace_expand_error (name
, value
, check_null
)
7933 set_exit_status (EXECUTION_FAILURE
); /* ensure it's non-zero */
7934 if (value
&& *value
)
7936 l
= expand_string (value
, 0);
7937 temp
= string_list (l
);
7938 report_error ("%s: %s", name
, temp
? temp
: ""); /* XXX was value not "" */
7942 else if (check_null
== 0)
7943 report_error (_("%s: parameter not set"), name
);
7945 report_error (_("%s: parameter null or not set"), name
);
7947 /* Free the data we have allocated during this expansion, since we
7948 are about to longjmp out. */
7953 /* Return 1 if NAME is something for which parameter_brace_expand_length is
7956 valid_length_expression (name
)
7959 return (name
[1] == '\0' || /* ${#} */
7960 ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0') || /* special param */
7961 (DIGIT (name
[1]) && all_digits (name
+ 1)) || /* ${#11} */
7962 #if defined (ARRAY_VARS)
7963 valid_array_reference (name
+ 1, 0) || /* ${#a[7]} */
7965 legal_identifier (name
+ 1)); /* ${#PS1} */
7968 /* Handle the parameter brace expansion that requires us to return the
7969 length of a parameter. */
7971 parameter_brace_expand_length (name
)
7975 intmax_t number
, arg_index
;
7979 var
= (SHELL_VAR
*)NULL
;
7981 if (name
[1] == '\0') /* ${#} */
7982 number
= number_of_args ();
7983 else if (DOLLAR_AT_STAR (name
[1]) && name
[2] == '\0') /* ${#@}, ${#*} */
7984 number
= number_of_args ();
7985 else if ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0')
7987 /* Take the lengths of some of the shell's special parameters. */
7991 t
= which_set_flags ();
7994 t
= itos (last_command_exit_value
);
7997 t
= itos (dollar_dollar_pid
);
8000 if (last_asynchronous_pid
== NO_PID
)
8001 t
= (char *)NULL
; /* XXX - error if set -u set? */
8003 t
= itos (last_asynchronous_pid
);
8006 t
= itos (number_of_args ());
8009 number
= STRLEN (t
);
8012 #if defined (ARRAY_VARS)
8013 else if (valid_array_reference (name
+ 1, 0))
8014 number
= array_length_reference (name
+ 1);
8015 #endif /* ARRAY_VARS */
8020 if (legal_number (name
+ 1, &arg_index
)) /* ${#1} */
8022 t
= get_dollar_var_value (arg_index
);
8023 if (t
== 0 && unbound_vars_is_error
)
8025 number
= MB_STRLEN (t
);
8028 #if defined (ARRAY_VARS)
8029 else if ((var
= find_variable (name
+ 1)) && (invisible_p (var
) == 0) && (array_p (var
) || assoc_p (var
)))
8032 t
= assoc_reference (assoc_cell (var
), "0");
8034 t
= array_reference (array_cell (var
), 0);
8035 if (t
== 0 && unbound_vars_is_error
)
8037 number
= MB_STRLEN (t
);
8040 /* Fast path for the common case of taking the length of a non-dynamic
8041 scalar variable value. */
8042 else if ((var
|| (var
= find_variable (name
+ 1))) &&
8043 invisible_p (var
) == 0 &&
8044 array_p (var
) == 0 && assoc_p (var
) == 0 &&
8045 var
->dynamic_value
== 0)
8046 number
= value_cell (var
) ? MB_STRLEN (value_cell (var
)) : 0;
8047 else if (var
== 0 && unbound_vars_is_error
== 0)
8051 newname
= savestring (name
);
8053 list
= expand_string (newname
, Q_DOUBLE_QUOTES
);
8054 t
= list
? string_list (list
) : (char *)NULL
;
8057 dispose_words (list
);
8059 number
= t
? MB_STRLEN (t
) : 0;
8067 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
8068 so we do some ad-hoc parsing of an arithmetic expression to find
8069 the first DELIM, instead of using strchr(3). Two rules:
8070 1. If the substring contains a `(', read until closing `)'.
8071 2. If the substring contains a `?', read past one `:' for each `?'.
8072 The SD_ARITHEXP flag to skip_to_delim takes care of doing this.
8076 skiparith (substr
, delim
)
8086 i
= skip_to_delim (substr
, 0, delims
, SD_ARITHEXP
);
8087 return (substr
+ i
);
8090 /* Verify and limit the start and end of the desired substring. If
8091 VTYPE == 0, a regular shell variable is being used; if it is 1,
8092 then the positional parameters are being used; if it is 2, then
8093 VALUE is really a pointer to an array variable that should be used.
8094 Return value is 1 if both values were OK, 0 if there was a problem
8095 with an invalid expression, or -1 if the values were out of range. */
8097 verify_substring_values (v
, value
, substr
, vtype
, e1p
, e2p
)
8099 char *value
, *substr
;
8101 intmax_t *e1p
, *e2p
;
8103 char *t
, *temp1
, *temp2
;
8106 #if defined (ARRAY_VARS)
8111 /* duplicate behavior of strchr(3) */
8112 t
= skiparith (substr
, ':');
8113 if (*t
&& *t
== ':')
8118 temp1
= expand_arith_string (substr
, Q_DOUBLE_QUOTES
|Q_ARITH
);
8119 eflag
= (shell_compatibility_level
> 51) ? 0 : EXP_EXPANDED
;
8121 *e1p
= evalexp (temp1
, eflag
, &expok
);
8126 len
= -1; /* paranoia */
8130 case VT_ARRAYMEMBER
:
8131 len
= MB_STRLEN (value
);
8134 len
= number_of_args () + 1;
8136 len
++; /* add one arg if counting from $0 */
8138 #if defined (ARRAY_VARS)
8140 /* For arrays, the first value deals with array indices. Negative
8141 offsets count from one past the array's maximum index. Associative
8142 arrays treat the number of elements as the maximum index. */
8146 len
= assoc_num_elements (h
) + (*e1p
< 0);
8151 len
= array_max_index (a
) + (*e1p
< 0); /* arrays index from 0 to n - 1 */
8157 if (len
== -1) /* paranoia */
8160 if (*e1p
< 0) /* negative offsets count from end */
8163 if (*e1p
> len
|| *e1p
< 0)
8166 #if defined (ARRAY_VARS)
8167 /* For arrays, the second offset deals with the number of elements. */
8168 if (vtype
== VT_ARRAYVAR
)
8169 len
= assoc_p (v
) ? assoc_num_elements (h
) : array_num_elements (a
);
8175 temp2
= savestring (t
);
8176 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
8179 *e2p
= evalexp (temp1
, eflag
, &expok
);
8184 /* Should we allow positional parameter length < 0 to count backwards
8185 from end of positional parameters? */
8187 if ((vtype
== VT_ARRAYVAR
|| vtype
== VT_POSPARMS
) && *e2p
< 0)
8188 #else /* XXX - postponed; this isn't really a valuable feature */
8189 if (vtype
== VT_ARRAYVAR
&& *e2p
< 0)
8192 internal_error (_("%s: substring expression < 0"), t
);
8195 #if defined (ARRAY_VARS)
8196 /* In order to deal with sparse arrays, push the intelligence about how
8197 to deal with the number of elements desired down to the array-
8198 specific functions. */
8199 if (vtype
!= VT_ARRAYVAR
)
8205 if (*e2p
< 0 || *e2p
< *e1p
)
8207 internal_error (_("%s: substring expression < 0"), t
);
8212 *e2p
+= *e1p
; /* want E2 chars starting at E1 */
8223 /* Return the type of variable specified by VARNAME (simple variable,
8224 positional param, or array variable). Also return the value specified
8225 by VARNAME (value of a variable or a reference to an array element).
8226 QUOTED is the standard description of quoting state, using Q_* defines.
8227 FLAGS is currently a set of flags to pass to array_value. If IND is
8228 not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
8229 passed to array_value so the array index is not computed again.
8230 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
8231 characters in the value are quoted with CTLESC and takes appropriate
8232 steps. For convenience, *VALP is set to the dequoted VALUE. */
8234 get_var_and_type (varname
, value
, estatep
, quoted
, flags
, varp
, valp
)
8235 char *varname
, *value
;
8236 array_eltstate_t
*estatep
;
8241 int vtype
, want_indir
;
8245 want_indir
= *varname
== '!' &&
8246 (legal_variable_starter ((unsigned char)varname
[1]) || DIGIT (varname
[1])
8247 || VALID_INDIR_PARAM (varname
[1]));
8249 vname
= parameter_brace_find_indir (varname
+1, SPECIAL_VAR (varname
, 1), quoted
, 1);
8250 /* XXX - what if vname == 0 || *vname == 0 ? */
8256 vtype
= VT_VARIABLE
;
8257 *varp
= (SHELL_VAR
*)NULL
;
8258 *valp
= (char *)NULL
;
8262 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
8263 vtype
= STR_DOLLAR_AT_STAR (vname
);
8264 if (vtype
== VT_POSPARMS
&& vname
[0] == '*')
8265 vtype
|= VT_STARSUB
;
8266 *varp
= (SHELL_VAR
*)NULL
;
8268 #if defined (ARRAY_VARS)
8269 if (valid_array_reference (vname
, 0))
8271 v
= array_variable_part (vname
, 0, &temp
, (int *)0);
8272 /* If we want to signal array_value to use an already-computed index,
8273 the caller will set ESTATEP->IND to that index and pass AV_USEIND in
8275 if (estatep
&& (flags
& AV_USEIND
) == 0)
8276 estatep
->ind
= INTMAX_MIN
;
8278 if (v
&& invisible_p (v
))
8280 vtype
= VT_ARRAYMEMBER
;
8281 *varp
= (SHELL_VAR
*)NULL
;
8282 *valp
= (char *)NULL
;
8284 if (v
&& (array_p (v
) || assoc_p (v
)))
8286 if (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
)
8288 /* Callers have to differentiate between indexed and associative */
8289 vtype
= VT_ARRAYVAR
;
8291 vtype
|= VT_STARSUB
;
8292 *valp
= array_p (v
) ? (char *)array_cell (v
) : (char *)assoc_cell (v
);
8296 vtype
= VT_ARRAYMEMBER
;
8297 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, estatep
);
8301 else if (v
&& (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
))
8303 vtype
= VT_VARIABLE
;
8305 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8306 *valp
= value
? dequote_string (value
) : (char *)NULL
;
8308 *valp
= value
? dequote_escapes (value
) : (char *)NULL
;
8312 vtype
= VT_ARRAYMEMBER
;
8314 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, estatep
);
8317 else if ((v
= find_variable (vname
)) && (invisible_p (v
) == 0) && (assoc_p (v
) || array_p (v
)))
8319 vtype
= VT_ARRAYMEMBER
;
8321 *valp
= assoc_p (v
) ? assoc_reference (assoc_cell (v
), "0") : array_reference (array_cell (v
), 0);
8326 if (value
&& vtype
== VT_VARIABLE
)
8328 *varp
= find_variable (vname
);
8329 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8330 *valp
= dequote_string (value
);
8332 *valp
= dequote_escapes (value
);
8344 /***********************************************************/
8346 /* Functions to perform transformations on variable values */
8348 /***********************************************************/
8351 string_var_assignment (v
, s
)
8355 char flags
[MAX_ATTRIBUTES
], *ret
, *val
;
8358 val
= (v
&& (invisible_p (v
) || var_isset (v
) == 0)) ? (char *)NULL
: sh_quote_reusable (s
, 0);
8359 i
= var_attribute_string (v
, 0, flags
);
8360 if (i
== 0 && val
== 0)
8361 return (char *)NULL
;
8363 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16 + MAX_ATTRIBUTES
);
8364 if (i
> 0 && val
== 0)
8365 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
8367 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
8369 sprintf (ret
, "%s=%s", v
->name
, val
);
8374 #if defined (ARRAY_VARS)
8376 array_var_assignment (v
, itype
, quoted
, atype
)
8378 int itype
, quoted
, atype
;
8380 char *ret
, *val
, flags
[MAX_ATTRIBUTES
];
8384 return (char *)NULL
;
8386 val
= array_p (v
) ? array_to_kvpair (array_cell (v
), 0)
8387 : assoc_to_kvpair (assoc_cell (v
), 0);
8389 val
= array_p (v
) ? array_to_assign (array_cell (v
), 0)
8390 : assoc_to_assign (assoc_cell (v
), 0);
8392 if (val
== 0 && (invisible_p (v
) || var_isset (v
) == 0))
8396 val
= (char *)xmalloc (3);
8403 ret
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (val
) : quote_escapes (val
);
8411 i
= var_attribute_string (v
, 0, flags
);
8412 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16);
8414 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
8416 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
8423 pos_params_assignment (list
, itype
, quoted
)
8430 /* first, we transform the list to quote each word. */
8431 temp
= list_transform ('Q', (SHELL_VAR
*)0, list
, itype
, quoted
);
8432 ret
= (char *)xmalloc (strlen (temp
) + 8);
8433 strcpy (ret
, "set -- ");
8434 strcpy (ret
+ 7, temp
);
8440 string_transform (xc
, v
, s
)
8445 char *ret
, flags
[MAX_ATTRIBUTES
], *t
;
8448 if (((xc
== 'A' || xc
== 'a') && v
== 0))
8449 return (char *)NULL
;
8450 else if (xc
!= 'a' && xc
!= 'A' && s
== 0)
8451 return (char *)NULL
;
8455 /* Transformations that interrogate the variable */
8457 i
= var_attribute_string (v
, 0, flags
);
8458 ret
= (i
> 0) ? savestring (flags
) : (char *)NULL
;
8461 ret
= string_var_assignment (v
, s
);
8465 ret
= sh_quote_reusable (s
, 0);
8467 /* Transformations that modify the variable's value */
8469 t
= ansiexpand (s
, 0, strlen (s
), (int *)0);
8470 ret
= dequote_escapes (t
);
8474 ret
= decode_prompt_string (s
);
8477 ret
= sh_quote_reusable (s
, 0);
8480 ret
= sh_modcase (s
, 0, CASE_UPPER
);
8483 ret
= sh_modcase (s
, 0, CASE_UPFIRST
); /* capitalize */
8486 ret
= sh_modcase (s
, 0, CASE_LOWER
);
8496 list_transform (xc
, v
, list
, itype
, quoted
)
8507 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
8509 tword
= string_transform (xc
, v
, l
->word
->word
);
8510 w
= alloc_word_desc ();
8511 w
->word
= tword
? tword
: savestring (""); /* XXX */
8512 new = make_word_list (w
, new);
8514 l
= REVERSE_LIST (new, WORD_LIST
*);
8517 /* If we are expanding in a context where word splitting will not be
8518 performed, treat as quoted. This changes how $* will be expanded. */
8519 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
8520 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8522 tword
= string_list_pos_params (itype
, l
, qflags
, 0);
8529 parameter_list_transform (xc
, itype
, quoted
)
8537 list
= list_rest_of_args ();
8539 return ((char *)NULL
);
8541 ret
= pos_params_assignment (list
, itype
, quoted
);
8543 ret
= list_transform (xc
, (SHELL_VAR
*)0, list
, itype
, quoted
);
8544 dispose_words (list
);
8548 #if defined (ARRAY_VARS)
8550 array_transform (xc
, var
, starsub
, quoted
)
8553 int starsub
; /* so we can figure out how it's indexed */
8563 v
= var
; /* XXX - for now */
8565 itype
= starsub
? '*' : '@';
8568 return (array_var_assignment (v
, itype
, quoted
, 1));
8570 return (array_var_assignment (v
, itype
, quoted
, 2));
8572 /* special case for unset arrays and attributes */
8573 if (xc
== 'a' && (invisible_p (v
) || var_isset (v
) == 0))
8575 char flags
[MAX_ATTRIBUTES
];
8578 i
= var_attribute_string (v
, 0, flags
);
8579 return ((i
> 0) ? savestring (flags
) : (char *)NULL
);
8582 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
8583 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
8589 return ((char *)NULL
);
8590 list
= array_p (v
) ? array_to_kvpair_list (a
) : assoc_to_kvpair_list (h
);
8592 /* If we are expanding in a context where word splitting will not be
8593 performed, treat as quoted. This changes how $* will be expanded. */
8594 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
8595 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8597 ret
= string_list_pos_params (itype
, list
, qflags
, 0);
8598 dispose_words (list
);
8602 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
8604 return ((char *)NULL
);
8605 ret
= list_transform (xc
, v
, list
, itype
, quoted
);
8606 dispose_words (list
);
8610 #endif /* ARRAY_VARS */
8613 valid_parameter_transform (xform
)
8619 /* check for valid values of xform[0] */
8622 case 'a': /* expand to a string with just attributes */
8623 case 'A': /* expand as an assignment statement with attributes */
8624 case 'K': /* expand assoc array to list of key/value pairs */
8625 case 'k': /* XXX - for now */
8626 case 'E': /* expand like $'...' */
8627 case 'P': /* expand like prompt string */
8628 case 'Q': /* quote reusably */
8629 case 'U': /* transform to uppercase */
8630 case 'u': /* transform by capitalizing */
8631 case 'L': /* transform to lowercase */
8639 parameter_brace_transform (varname
, value
, estatep
, xform
, rtype
, quoted
, pflags
, flags
)
8640 char *varname
, *value
;
8641 array_eltstate_t
*estatep
;
8643 int rtype
, quoted
, pflags
, flags
;
8645 int vtype
, xc
, starsub
;
8646 char *temp1
, *val
, *oname
;
8650 if (value
== 0 && xc
!= 'A' && xc
!= 'a')
8651 return ((char *)NULL
);
8653 oname
= this_command_name
;
8654 this_command_name
= varname
;
8656 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
8659 this_command_name
= oname
;
8660 return ((char *)NULL
);
8663 if (xform
[0] == 0 || valid_parameter_transform (xform
) == 0)
8665 this_command_name
= oname
;
8666 if (vtype
== VT_VARIABLE
)
8668 return (interactive_shell
? &expand_param_error
: &expand_param_fatal
);
8671 starsub
= vtype
& VT_STARSUB
;
8672 vtype
&= ~VT_STARSUB
;
8674 /* If we are asked to display the attributes of an unset variable, V will
8675 be NULL after the call to get_var_and_type. Double-check here. */
8676 if ((xc
== 'a' || xc
== 'A') && vtype
== VT_VARIABLE
&& varname
&& v
== 0)
8677 v
= find_variable (varname
);
8679 temp1
= (char *)NULL
; /* shut up gcc */
8683 case VT_ARRAYMEMBER
:
8684 temp1
= string_transform (xc
, v
, val
);
8685 if (vtype
== VT_VARIABLE
)
8689 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
8690 ? quote_string (temp1
)
8691 : quote_escapes (temp1
);
8696 #if defined (ARRAY_VARS)
8698 temp1
= array_transform (xc
, v
, starsub
, quoted
);
8699 if (temp1
&& quoted
== 0 && ifs_is_null
)
8701 /* Posix interp 888 */
8703 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8705 val
= quote_escapes (temp1
);
8712 temp1
= parameter_list_transform (xc
, varname
[0], quoted
);
8713 if (temp1
&& quoted
== 0 && ifs_is_null
)
8715 /* Posix interp 888 */
8717 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8719 val
= quote_escapes (temp1
);
8726 this_command_name
= oname
;
8730 /******************************************************/
8732 /* Functions to extract substrings of variable values */
8734 /******************************************************/
8736 #if defined (HANDLE_MULTIBYTE)
8737 /* Character-oriented rather than strictly byte-oriented substrings. S and
8738 E, rather being strict indices into STRING, indicate character (possibly
8739 multibyte character) positions that require calculation.
8740 Used by the ${param:offset[:length]} expansion. */
8742 mb_substring (string
, s
, e
)
8752 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
8753 slen
= (MB_CUR_MAX
> 1) ? STRLEN (string
) : 0;
8756 while (string
[start
] && i
--)
8757 ADVANCE_CHAR (string
, slen
, start
);
8760 while (string
[stop
] && i
--)
8761 ADVANCE_CHAR (string
, slen
, stop
);
8762 tt
= substring (string
, start
, stop
);
8767 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
8768 is `@', use the positional parameters; otherwise, use the value of
8769 VARNAME. If VARNAME is an array variable, use the array elements. */
8772 parameter_brace_substring (varname
, value
, estatep
, substr
, quoted
, pflags
, flags
)
8773 char *varname
, *value
;
8774 array_eltstate_t
*estatep
;
8776 int quoted
, pflags
, flags
;
8779 int vtype
, r
, starsub
;
8780 char *temp
, *val
, *tt
, *oname
;
8783 if (value
== 0 && ((varname
[0] != '@' && varname
[0] != '*') || varname
[1]))
8784 return ((char *)NULL
);
8786 oname
= this_command_name
;
8787 this_command_name
= varname
;
8789 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
8792 this_command_name
= oname
;
8793 return ((char *)NULL
);
8796 starsub
= vtype
& VT_STARSUB
;
8797 vtype
&= ~VT_STARSUB
;
8799 r
= verify_substring_values (v
, val
, substr
, vtype
, &e1
, &e2
);
8800 this_command_name
= oname
;
8803 if (vtype
== VT_VARIABLE
)
8805 return ((r
== 0) ? &expand_param_error
: (char *)NULL
);
8811 case VT_ARRAYMEMBER
:
8812 #if defined (HANDLE_MULTIBYTE)
8814 tt
= mb_substring (val
, e1
, e2
);
8817 tt
= substring (val
, e1
, e2
);
8819 if (vtype
== VT_VARIABLE
)
8821 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8822 temp
= quote_string (tt
);
8824 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8829 if (vtype
== VT_POSPARMS
)
8830 tt
= pos_params (varname
, e1
, e2
, quoted
, pflags
);
8831 #if defined (ARRAY_VARS)
8832 /* assoc_subrange and array_subrange both call string_list_pos_params,
8833 so we can treat this case just like VT_POSPARAMS. */
8834 else if (assoc_p (v
))
8835 /* we convert to list and take first e2 elements starting at e1th
8836 element -- officially undefined for now */
8837 tt
= assoc_subrange (assoc_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8839 /* We want E2 to be the number of elements desired (arrays can be
8840 sparse, so verify_substring_values just returns the numbers
8841 specified and we rely on array_subrange to understand how to
8843 tt
= array_subrange (array_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8845 /* We want to leave this alone in every case where pos_params/
8846 string_list_pos_params quotes the list members */
8847 if (tt
&& quoted
== 0 && ifs_is_null
)
8849 temp
= tt
; /* Posix interp 888 */
8851 else if (tt
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
8853 temp
= tt
; /* Posix interp 888 */
8855 else if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
8857 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8865 temp
= (char *)NULL
;
8871 /****************************************************************/
8873 /* Functions to perform pattern substitution on variable values */
8875 /****************************************************************/
8878 shouldexp_replacement (s
)
8887 while (c
= s
[sindex
])
8894 /* We want to remove this backslash because we treat it as special
8895 in this context. THIS ASSUMES THE STRING IS PROCESSED BY
8896 strcreplace() OR EQUIVALENT that handles removing backslashes
8897 preceding the special character. */
8898 if (s
[sindex
] == '&')
8900 if (s
[sindex
] == '\\')
8905 ADVANCE_CHAR (s
, slen
, sindex
);
8911 pat_subst (string
, pat
, rep
, mflags
)
8912 char *string
, *pat
, *rep
;
8915 char *ret
, *s
, *e
, *str
, *rstr
, *mstr
, *send
;
8916 int rptr
, mtype
, rxpand
, mlen
;
8917 size_t rsize
, l
, replen
, rslen
;
8921 return (savestring (""));
8923 mtype
= mflags
& MATCH_TYPEMASK
;
8924 rxpand
= mflags
& MATCH_EXPREP
;
8927 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
8928 * with REP and return the result.
8929 * 2. A null pattern with mtype == MATCH_END means to append REP to
8930 * STRING and return the result.
8931 * 3. A null STRING with a matching pattern means to append REP to
8932 * STRING and return the result.
8934 * These process `&' in the replacement string, like `sed' does when
8935 * presented with a BRE of `^' or `$'.
8937 if ((pat
== 0 || *pat
== 0) && (mtype
== MATCH_BEG
|| mtype
== MATCH_END
))
8939 rstr
= (mflags
& MATCH_EXPREP
) ? strcreplace (rep
, '&', "", 2) : rep
;
8940 rslen
= STRLEN (rstr
);
8941 l
= STRLEN (string
);
8942 ret
= (char *)xmalloc (rslen
+ l
+ 2);
8944 strcpy (ret
, string
);
8945 else if (mtype
== MATCH_BEG
)
8948 strcpy (ret
+ rslen
, string
);
8952 strcpy (ret
, string
);
8953 strcpy (ret
+ l
, rstr
);
8959 else if (*string
== 0 && (match_pattern (string
, pat
, mtype
, &s
, &e
) != 0))
8960 return ((mflags
& MATCH_EXPREP
) ? strcreplace (rep
, '&', "", 2) : savestring (rep
));
8962 ret
= (char *)xmalloc (rsize
= 64);
8964 send
= string
+ strlen (string
);
8966 for (replen
= STRLEN (rep
), rptr
= 0, str
= string
; *str
;)
8968 if (match_pattern (str
, pat
, mtype
, &s
, &e
) == 0)
8976 mstr
= xmalloc (mlen
+ 1);
8977 for (x
= 0; x
< mlen
; x
++)
8980 rstr
= strcreplace (rep
, '&', mstr
, 2);
8982 rslen
= strlen (rstr
);
8990 RESIZE_MALLOCED_BUFFER (ret
, rptr
, (l
+ rslen
), rsize
, 64);
8992 /* OK, now copy the leading unmatched portion of the string (from
8993 str to s) to ret starting at rptr (the current offset). Then copy
8994 the replacement string at ret + rptr + (s - str). Increment
8995 rptr (if necessary) and str and go on. */
8998 strncpy (ret
+ rptr
, str
, l
);
9003 strncpy (ret
+ rptr
, rstr
, rslen
);
9006 str
= e
; /* e == end of match */
9011 if (((mflags
& MATCH_GLOBREP
) == 0) || mtype
!= MATCH_ANY
)
9016 /* On a zero-length match, make sure we copy one character, since
9017 we increment one character to avoid infinite recursion. */
9018 char *p
, *origp
, *origs
;
9021 RESIZE_MALLOCED_BUFFER (ret
, rptr
, locale_mb_cur_max
, rsize
, 64);
9022 #if defined (HANDLE_MULTIBYTE)
9023 p
= origp
= ret
+ rptr
;
9025 COPY_CHAR_P (p
, str
, send
);
9029 ret
[rptr
++] = *str
++;
9030 e
++; /* avoid infinite recursion on zero-length match */
9035 /* Now copy the unmatched portion of the input string */
9039 RESIZE_MALLOCED_BUFFER (ret
, rptr
, l
, rsize
, 64);
9040 strcpy (ret
+ rptr
, str
);
9048 /* Do pattern match and replacement on the positional parameters. */
9050 pos_params_pat_subst (string
, pat
, rep
, mflags
)
9051 char *string
, *pat
, *rep
;
9054 WORD_LIST
*save
, *params
;
9057 int pchar
, qflags
, pflags
;
9059 save
= params
= list_rest_of_args ();
9061 return ((char *)NULL
);
9063 for ( ; params
; params
= params
->next
)
9065 ret
= pat_subst (params
->word
->word
, pat
, rep
, mflags
);
9066 w
= alloc_word_desc ();
9067 w
->word
= ret
? ret
: savestring ("");
9068 dispose_word (params
->word
);
9072 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
9073 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
9074 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
9076 /* If we are expanding in a context where word splitting will not be
9077 performed, treat as quoted. This changes how $* will be expanded. */
9078 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && expand_no_split_dollar_star
&& ifs_is_null
)
9079 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
9081 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
9082 dispose_words (save
);
9087 /* Perform pattern substitution on VALUE, which is the expansion of
9088 VARNAME. PATSUB is an expression supplying the pattern to match
9089 and the string to substitute. QUOTED is a flags word containing
9090 the type of quoting currently in effect. */
9092 parameter_brace_patsub (varname
, value
, estatep
, patsub
, quoted
, pflags
, flags
)
9093 char *varname
, *value
;
9094 array_eltstate_t
*estatep
;
9096 int quoted
, pflags
, flags
;
9098 int vtype
, mflags
, starsub
, delim
;
9099 char *val
, *temp
, *pat
, *rep
, *p
, *lpatsub
, *tt
, *oname
;
9103 return ((char *)NULL
);
9105 oname
= this_command_name
;
9106 this_command_name
= varname
; /* error messages */
9108 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
9111 this_command_name
= oname
;
9112 return ((char *)NULL
);
9115 starsub
= vtype
& VT_STARSUB
;
9116 vtype
&= ~VT_STARSUB
;
9119 /* PATSUB is never NULL when this is called. */
9122 mflags
|= MATCH_GLOBREP
;
9126 /* Malloc this because expand_string_if_necessary or one of the expansion
9127 functions in its call chain may free it on a substitution error. */
9128 lpatsub
= savestring (patsub
);
9130 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9131 mflags
|= MATCH_QUOTED
;
9134 mflags
|= MATCH_STARSUB
;
9136 if (pflags
& PF_ASSIGNRHS
)
9137 mflags
|= MATCH_ASSIGNRHS
;
9139 /* If the pattern starts with a `/', make sure we skip over it when looking
9140 for the replacement delimiter. */
9141 delim
= skip_to_delim (lpatsub
, ((*patsub
== '/') ? 1 : 0), "/", 0);
9142 if (lpatsub
[delim
] == '/')
9145 rep
= lpatsub
+ delim
+ 1;
9150 if (rep
&& *rep
== '\0')
9153 /* Perform the same expansions on the pattern as performed by the
9154 pattern removal expansions. */
9155 pat
= getpattern (lpatsub
, quoted
, 1);
9159 /* We want to perform quote removal on the expanded replacement even if
9160 the entire expansion is double-quoted because the parser and string
9161 extraction functions treated quotes in the replacement string as
9162 special. THIS IS NOT BACKWARDS COMPATIBLE WITH BASH-4.2. */
9163 if (shell_compatibility_level
> 42 && patsub_replacement
== 0)
9164 rep
= expand_string_if_necessary (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
), expand_string_unsplit
);
9165 else if (shell_compatibility_level
> 42 && patsub_replacement
)
9166 rep
= expand_string_for_patsub (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
));
9167 /* This is the bash-4.2 code. */
9168 else if ((mflags
& MATCH_QUOTED
) == 0)
9169 rep
= expand_string_if_necessary (rep
, quoted
, expand_string_unsplit
);
9171 rep
= expand_string_to_string_internal (rep
, quoted
, expand_string_unsplit
);
9173 /* Check whether or not to replace `&' in the replacement string after
9174 expanding it, since we want to treat backslashes quoting the `&'
9176 if (patsub_replacement
&& rep
&& *rep
&& shouldexp_replacement (rep
))
9177 mflags
|= MATCH_EXPREP
;
9181 /* ksh93 doesn't allow the match specifier to be a part of the expanded
9182 pattern. This is an extension. Make sure we don't anchor the pattern
9183 at the beginning or end of the string if we're doing global replacement,
9186 if (mflags
& MATCH_GLOBREP
)
9187 mflags
|= MATCH_ANY
;
9188 else if (pat
&& pat
[0] == '#')
9190 mflags
|= MATCH_BEG
;
9193 else if (pat
&& pat
[0] == '%')
9195 mflags
|= MATCH_END
;
9199 mflags
|= MATCH_ANY
;
9201 /* OK, we now want to substitute REP for PAT in VAL. If
9202 flags & MATCH_GLOBREP is non-zero, the substitution is done
9203 everywhere, otherwise only the first occurrence of PAT is
9204 replaced. The pattern matching code doesn't understand
9205 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
9206 values passed in (VT_VARIABLE) so the pattern substitution
9207 code works right. We need to requote special chars after
9208 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
9209 other cases if QUOTED == 0, since the posparams and arrays
9210 indexed by * or @ do special things when QUOTED != 0. */
9215 case VT_ARRAYMEMBER
:
9216 temp
= pat_subst (val
, p
, rep
, mflags
);
9217 if (vtype
== VT_VARIABLE
)
9221 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
9227 /* This does the right thing for the case where we are not performing
9228 word splitting. MATCH_STARSUB restricts it to ${* /foo/bar}, and
9229 pos_params_pat_subst/string_list_pos_params will do the right thing
9230 in turn for the case where ifs_is_null. Posix interp 888 */
9231 if ((pflags
& PF_NOSPLIT2
) && (mflags
& MATCH_STARSUB
))
9232 mflags
|= MATCH_ASSIGNRHS
;
9233 temp
= pos_params_pat_subst (val
, p
, rep
, mflags
);
9234 if (temp
&& quoted
== 0 && ifs_is_null
)
9236 /* Posix interp 888 */
9238 else if (temp
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
9240 /* Posix interp 888 */
9242 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9244 tt
= quote_escapes (temp
);
9249 #if defined (ARRAY_VARS)
9251 /* If we are expanding in a context where word splitting will not be
9252 performed, treat as quoted. This changes how ${A[*]} will be
9253 expanded to make it identical to $*. */
9254 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9255 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
9257 /* these eventually call string_list_pos_params */
9259 temp
= assoc_patsub (assoc_cell (v
), p
, rep
, mflags
);
9261 temp
= array_patsub (array_cell (v
), p
, rep
, mflags
);
9263 if (temp
&& quoted
== 0 && ifs_is_null
)
9265 /* Posix interp 888 */
9267 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9269 tt
= quote_escapes (temp
);
9281 this_command_name
= oname
;
9286 /****************************************************************/
9288 /* Functions to perform case modification on variable values */
9290 /****************************************************************/
9292 /* Do case modification on the positional parameters. */
9295 pos_params_modcase (string
, pat
, modop
, mflags
)
9300 WORD_LIST
*save
, *params
;
9303 int pchar
, qflags
, pflags
;
9305 save
= params
= list_rest_of_args ();
9307 return ((char *)NULL
);
9309 for ( ; params
; params
= params
->next
)
9311 ret
= sh_modcase (params
->word
->word
, pat
, modop
);
9312 w
= alloc_word_desc ();
9313 w
->word
= ret
? ret
: savestring ("");
9314 dispose_word (params
->word
);
9318 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
9319 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
9320 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
9322 /* If we are expanding in a context where word splitting will not be
9323 performed, treat as quoted. This changes how $* will be expanded. */
9324 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9325 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
9327 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
9328 dispose_words (save
);
9333 /* Perform case modification on VALUE, which is the expansion of
9334 VARNAME. MODSPEC is an expression supplying the type of modification
9335 to perform. QUOTED is a flags word containing the type of quoting
9336 currently in effect. */
9338 parameter_brace_casemod (varname
, value
, estatep
, modspec
, patspec
, quoted
, pflags
, flags
)
9339 char *varname
, *value
;
9340 array_eltstate_t
*estatep
;
9343 int quoted
, pflags
, flags
;
9345 int vtype
, starsub
, modop
, mflags
, x
;
9346 char *val
, *temp
, *pat
, *p
, *lpat
, *tt
, *oname
;
9350 return ((char *)NULL
);
9352 oname
= this_command_name
;
9353 this_command_name
= varname
;
9355 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
9358 this_command_name
= oname
;
9359 return ((char *)NULL
);
9362 starsub
= vtype
& VT_STARSUB
;
9363 vtype
&= ~VT_STARSUB
;
9367 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9368 mflags
|= MATCH_QUOTED
;
9370 mflags
|= MATCH_STARSUB
;
9371 if (pflags
& PF_ASSIGNRHS
)
9372 mflags
|= MATCH_ASSIGNRHS
;
9377 x
= p
&& p
[0] == modspec
;
9378 modop
= x
? CASE_UPPER
: CASE_UPFIRST
;
9381 else if (modspec
== ',')
9383 x
= p
&& p
[0] == modspec
;
9384 modop
= x
? CASE_LOWER
: CASE_LOWFIRST
;
9387 else if (modspec
== '~')
9389 x
= p
&& p
[0] == modspec
;
9390 modop
= x
? CASE_TOGGLEALL
: CASE_TOGGLE
;
9394 lpat
= p
? savestring (p
) : 0;
9395 /* Perform the same expansions on the pattern as performed by the
9396 pattern removal expansions. */
9397 pat
= lpat
? getpattern (lpat
, quoted
, 1) : 0;
9399 /* OK, now we do the case modification. */
9403 case VT_ARRAYMEMBER
:
9404 temp
= sh_modcase (val
, pat
, modop
);
9405 if (vtype
== VT_VARIABLE
)
9409 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
9416 temp
= pos_params_modcase (val
, pat
, modop
, mflags
);
9417 if (temp
&& quoted
== 0 && ifs_is_null
)
9419 /* Posix interp 888 */
9421 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9423 tt
= quote_escapes (temp
);
9429 #if defined (ARRAY_VARS)
9431 /* If we are expanding in a context where word splitting will not be
9432 performed, treat as quoted. This changes how ${A[*]} will be
9433 expanded to make it identical to $*. */
9434 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9435 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
9437 temp
= assoc_p (v
) ? assoc_modcase (assoc_cell (v
), pat
, modop
, mflags
)
9438 : array_modcase (array_cell (v
), pat
, modop
, mflags
);
9440 if (temp
&& quoted
== 0 && ifs_is_null
)
9442 /* Posix interp 888 */
9444 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9446 tt
= quote_escapes (temp
);
9458 this_command_name
= oname
;
9463 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
9464 any occur, this must be a nested command substitution, so return 0.
9465 Otherwise, return 1. A valid arithmetic expression must always have a
9466 ( before a matching ), so any cases where there are more right parens
9467 means that this must not be an arithmetic expression, though the parser
9468 will not accept it without a balanced total number of parens. */
9470 chk_arithsub (s
, len
)
9482 else if (s
[i
] == RPAREN
)
9492 ADVANCE_CHAR (s
, len
, i
);
9498 ADVANCE_CHAR (s
, len
, i
);
9502 i
= skip_single_quoted (s
, len
, ++i
, 0);
9506 i
= skip_double_quoted ((char *)s
, len
, ++i
, 0);
9511 return (count
== 0);
9514 /****************************************************************/
9516 /* Functions to perform parameter expansion on a string */
9518 /****************************************************************/
9520 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
9522 parameter_brace_expand (string
, indexp
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
9524 int *indexp
, quoted
, pflags
, *quoted_dollar_atp
, *contains_dollar_at
;
9526 int check_nullness
, var_is_set
, var_is_null
, var_is_special
;
9527 int want_substring
, want_indir
, want_patsub
, want_casemod
, want_attributes
;
9528 char *name
, *value
, *temp
, *temp1
;
9529 WORD_DESC
*tdesc
, *ret
;
9530 int t_index
, sindex
, c
, tflag
, modspec
, local_pflags
, all_element_arrayref
;
9532 array_eltstate_t es
;
9534 temp
= temp1
= value
= (char *)NULL
;
9535 var_is_set
= var_is_null
= var_is_special
= check_nullness
= 0;
9536 want_substring
= want_indir
= want_patsub
= want_casemod
= want_attributes
= 0;
9539 all_element_arrayref
= 0;
9543 /* ${#var} doesn't have any of the other parameter expansions on it. */
9544 if (string
[t_index
] == '#' && legal_variable_starter (string
[t_index
+1])) /* {{ */
9545 name
= string_extract (string
, &t_index
, "}", SX_VARNAME
);
9547 #if defined (CASEMOD_EXPANSIONS)
9548 /* To enable case-toggling expansions using the `~' operator character
9549 define CASEMOD_TOGGLECASE in config-top.h */
9550 # if defined (CASEMOD_TOGGLECASE)
9551 name
= string_extract (string
, &t_index
, "#%^,~:-=?+/@}", SX_VARNAME
);
9553 name
= string_extract (string
, &t_index
, "#%^,:-=?+/@}", SX_VARNAME
);
9554 # endif /* CASEMOD_TOGGLECASE */
9556 name
= string_extract (string
, &t_index
, "#%:-=?+/@}", SX_VARNAME
);
9557 #endif /* CASEMOD_EXPANSIONS */
9559 /* Handle ${@[stuff]} now that @ is a word expansion operator. Not exactly
9560 the cleanest code ever. */
9561 if (*name
== 0 && sindex
== t_index
&& string
[sindex
] == '@')
9563 name
= (char *)xrealloc (name
, 2);
9568 else if (*name
== '!' && t_index
> sindex
&& string
[t_index
] == '@' && string
[t_index
+1] == RBRACE
)
9570 name
= (char *)xrealloc (name
, t_index
- sindex
+ 2);
9571 name
[t_index
- sindex
] = '@';
9572 name
[t_index
- sindex
+ 1] = '\0';
9579 #if defined (ARRAY_VARS)
9580 init_eltstate (&es
);
9582 es
.ind
= INTMAX_MIN
; /* XXX */
9584 /* If the name really consists of a special variable, then make sure
9585 that we have the entire name. We don't allow indirect references
9586 to special variables except `#', `?', `@' and `*'. This clause is
9587 designed to handle ${#SPECIAL} and ${!SPECIAL}, not anything more
9589 if ((sindex
== t_index
&& VALID_SPECIAL_LENGTH_PARAM (string
[t_index
])) ||
9590 (sindex
== t_index
&& string
[sindex
] == '#' && VALID_SPECIAL_LENGTH_PARAM (string
[sindex
+ 1])) ||
9591 (sindex
== t_index
- 1 && string
[sindex
] == '!' && VALID_INDIR_PARAM (string
[t_index
])))
9594 temp1
= string_extract (string
, &t_index
, "#%:-=?+/@}", 0);
9595 name
= (char *)xrealloc (name
, 3 + (strlen (temp1
)));
9596 *name
= string
[sindex
];
9597 if (string
[sindex
] == '!')
9599 /* indirect reference of $#, $?, $@, or $* */
9600 name
[1] = string
[sindex
+ 1];
9601 strcpy (name
+ 2, temp1
);
9604 strcpy (name
+ 1, temp1
);
9609 /* Find out what character ended the variable name. Then
9610 do the appropriate thing. */
9611 if (c
= string
[sindex
])
9614 /* If c is followed by one of the valid parameter expansion
9615 characters, move past it as normal. If not, assume that
9616 a substring specification is being given, and do not move
9618 if (c
== ':' && VALID_PARAM_EXPAND_CHAR (string
[sindex
]))
9621 if (c
= string
[sindex
])
9624 else if (c
== ':' && string
[sindex
] != RBRACE
)
9626 else if (c
== '/' /* && string[sindex] != RBRACE */) /* XXX */
9628 #if defined (CASEMOD_EXPANSIONS)
9629 else if (c
== '^' || c
== ',' || c
== '~')
9635 else if (c
== '@' && (string
[sindex
] == 'a' || string
[sindex
] == 'A') && string
[sindex
+1] == RBRACE
)
9637 /* special case because we do not want to shortcut foo as foo[0] here */
9638 want_attributes
= 1;
9639 local_pflags
|= PF_ALLINDS
;
9642 /* Catch the valid and invalid brace expressions that made it through the
9644 /* ${#-} is a valid expansion and means to take the length of $-.
9645 Similarly for ${#?} and ${##}... */
9646 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
9647 VALID_SPECIAL_LENGTH_PARAM (c
) && string
[sindex
] == RBRACE
)
9649 name
= (char *)xrealloc (name
, 3);
9652 c
= string
[sindex
++];
9655 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
9656 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
9657 member (c
, "%:=+/") && string
[sindex
] == RBRACE
)
9659 temp
= (char *)NULL
;
9660 goto bad_substitution
; /* XXX - substitution error */
9663 /* Indirect expansion begins with a `!'. A valid indirect expansion is
9664 either a variable name, one of the positional parameters or a special
9665 variable that expands to one of the positional parameters. */
9666 want_indir
= *name
== '!' &&
9667 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1])
9668 || VALID_INDIR_PARAM (name
[1]));
9670 /* Determine the value of this variable whose name is NAME. */
9672 /* Check for special variables, directly referenced. */
9673 if (SPECIAL_VAR (name
, want_indir
))
9676 /* Check for special expansion things, like the length of a parameter */
9677 if (*name
== '#' && name
[1])
9679 /* If we are not pointing at the character just after the
9680 closing brace, then we haven't gotten all of the name.
9681 Since it begins with a special character, this is a bad
9682 substitution. Also check NAME for validity before trying
9684 if (string
[sindex
- 1] != RBRACE
|| (valid_length_expression (name
) == 0))
9686 temp
= (char *)NULL
;
9687 goto bad_substitution
; /* substitution error */
9690 number
= parameter_brace_expand_length (name
);
9691 if (number
== INTMAX_MIN
&& unbound_vars_is_error
)
9693 set_exit_status (EXECUTION_FAILURE
);
9694 err_unboundvar (name
+1);
9696 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9702 return (&expand_wdesc_error
);
9705 ret
= alloc_word_desc ();
9706 ret
->word
= itos (number
);
9711 /* ${@} is identical to $@. */
9712 if (name
[0] == '@' && name
[1] == '\0')
9714 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9715 *quoted_dollar_atp
= 1;
9717 if (contains_dollar_at
)
9718 *contains_dollar_at
= 1;
9720 tflag
|= W_DOLLARAT
;
9723 /* Process ${!PREFIX*} expansion. */
9724 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9725 (string
[sindex
- 2] == '*' || string
[sindex
- 2] == '@') &&
9726 legal_variable_starter ((unsigned char) name
[1]))
9731 temp1
= savestring (name
+ 1);
9732 number
= strlen (temp1
);
9733 temp1
[number
- 1] = '\0';
9734 x
= all_variables_matching_prefix (temp1
);
9735 xlist
= strvec_to_word_list (x
, 0, 0);
9736 if (string
[sindex
- 2] == '*')
9737 temp
= string_list_dollar_star (xlist
, quoted
, 0);
9740 temp
= string_list_dollar_at (xlist
, quoted
, 0);
9741 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9742 *quoted_dollar_atp
= 1;
9743 if (contains_dollar_at
)
9744 *contains_dollar_at
= 1;
9746 tflag
|= W_DOLLARAT
;
9749 dispose_words (xlist
);
9755 ret
= alloc_word_desc ();
9757 ret
->flags
= tflag
; /* XXX */
9761 #if defined (ARRAY_VARS)
9762 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */
9763 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9764 string
[sindex
- 2] == RBRACK
&& valid_array_reference (name
+1, 0))
9768 temp1
= savestring (name
+ 1);
9769 x
= array_variable_name (temp1
, 0, &x1
, (int *)0);
9771 if (ALL_ELEMENT_SUB (x1
[0]) && x1
[1] == RBRACK
)
9773 temp
= array_keys (temp1
, quoted
, pflags
); /* handles assoc vars too */
9776 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9777 *quoted_dollar_atp
= 1;
9778 if (contains_dollar_at
)
9779 *contains_dollar_at
= 1;
9781 tflag
|= W_DOLLARAT
;
9788 ret
= alloc_word_desc ();
9790 ret
->flags
= tflag
; /* XXX */
9796 #endif /* ARRAY_VARS */
9798 /* Make sure that NAME is valid before trying to go on. */
9799 if (valid_brace_expansion_word (want_indir
? name
+ 1 : name
,
9800 var_is_special
) == 0)
9802 temp
= (char *)NULL
;
9803 goto bad_substitution
; /* substitution error */
9808 tdesc
= parameter_brace_expand_indir (name
+ 1, var_is_special
, quoted
, pflags
|local_pflags
, quoted_dollar_atp
, contains_dollar_at
);
9809 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9811 temp
= (char *)NULL
;
9812 goto bad_substitution
;
9815 /* Turn off the W_ARRAYIND flag because there is no way for this function
9816 to return the index we're supposed to be using. */
9817 if (tdesc
&& tdesc
->flags
)
9818 tdesc
->flags
&= ~W_ARRAYIND
;
9820 /* If the indir expansion contains $@/$*, extend the special treatment
9821 of the case of no positional parameters and `set -u' to it. */
9822 if (contains_dollar_at
&& *contains_dollar_at
)
9823 all_element_arrayref
= 1;
9827 local_pflags
|= PF_IGNUNBOUND
|(pflags
&(PF_NOSPLIT2
|PF_ASSIGNRHS
));
9828 tdesc
= parameter_brace_expand_word (name
, var_is_special
, quoted
, local_pflags
, &es
);
9831 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9840 tflag
= tdesc
->flags
;
9841 dispose_word_desc (tdesc
);
9846 if (temp
== &expand_param_error
|| temp
== &expand_param_fatal
)
9850 return (temp
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9853 #if defined (ARRAY_VARS)
9854 if (valid_array_reference (name
, 0))
9860 /* If in a context where word splitting will not take place, treat as
9861 if double-quoted. Has effects with $* and ${array[*]} */
9863 if (pflags
& PF_ASSIGNRHS
)
9864 qflags
|= Q_DOUBLE_QUOTES
;
9865 /* We duplicate a little code here */
9866 t
= mbschr (name
, LBRACK
);
9867 if (t
&& ALL_ELEMENT_SUB (t
[1]) && t
[2] == RBRACK
)
9869 all_element_arrayref
= 1;
9870 if (expand_no_split_dollar_star
&& t
[1] == '*') /* XXX */
9871 qflags
|= Q_DOUBLE_QUOTES
;
9873 chk_atstar (name
, qflags
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
9877 var_is_set
= temp
!= (char *)0;
9878 var_is_null
= check_nullness
&& (var_is_set
== 0 || *temp
== 0);
9879 /* XXX - this may not need to be restricted to special variables */
9881 var_is_null
|= var_is_set
&& var_is_special
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
);
9882 #if defined (ARRAY_VARS)
9884 var_is_null
|= var_is_set
&&
9885 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) &&
9886 QUOTED_NULL (temp
) &&
9887 valid_array_reference (name
, 0) &&
9888 chk_atstar (name
, 0, 0, (int *)0, (int *)0);
9891 /* Get the rest of the stuff inside the braces. */
9892 if (c
&& c
!= RBRACE
)
9894 /* Extract the contents of the ${ ... } expansion
9895 according to the Posix.2 rules. */
9896 value
= extract_dollar_brace_string (string
, &sindex
, quoted
, (c
== '%' || c
== '#' || c
=='/' || c
== '^' || c
== ',' || c
==':') ? SX_POSIXEXP
|SX_WORD
: SX_WORD
);
9897 if (string
[sindex
] == RBRACE
)
9900 goto bad_substitution
; /* substitution error */
9903 value
= (char *)NULL
;
9907 /* All the cases where an expansion can possibly generate an unbound
9909 if (want_substring
|| want_patsub
|| want_casemod
|| c
== '@' || c
== '#' || c
== '%' || c
== RBRACE
)
9911 if (var_is_set
== 0 && unbound_vars_is_error
&& ((name
[0] != '@' && name
[0] != '*') || name
[1]) && all_element_arrayref
== 0)
9913 set_exit_status (EXECUTION_FAILURE
);
9914 err_unboundvar (name
);
9918 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9922 /* If this is a substring spec, process it and add the result. */
9925 temp1
= parameter_brace_substring (name
, temp
, &es
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9928 #if defined (ARRAY_VARS)
9929 flush_eltstate (&es
);
9932 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9935 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9938 ret
= alloc_word_desc ();
9940 /* We test quoted_dollar_atp because we want variants with double-quoted
9941 "$@" to take a different code path. In fact, we make sure at the end
9942 of expand_word_internal that we're only looking at these flags if
9943 quoted_dollar_at == 0. */
9945 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9946 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9947 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9948 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 &&
9949 (pflags
& PF_ASSIGNRHS
))
9950 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9951 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9952 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9953 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9958 else if (want_patsub
)
9960 temp1
= parameter_brace_patsub (name
, temp
, &es
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9963 #if defined (ARRAY_VARS)
9964 flush_eltstate (&es
);
9967 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9970 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9973 ret
= alloc_word_desc ();
9976 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9977 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9978 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9979 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9980 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9981 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9986 #if defined (CASEMOD_EXPANSIONS)
9987 else if (want_casemod
)
9989 temp1
= parameter_brace_casemod (name
, temp
, &es
, modspec
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9992 #if defined (ARRAY_VARS)
9993 flush_eltstate (&es
);
9996 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9999 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10002 ret
= alloc_word_desc ();
10005 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
10006 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10007 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10008 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10009 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10010 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10017 /* Do the right thing based on which character ended the variable name. */
10023 set_exit_status (EXECUTION_FAILURE
);
10024 report_error (_("%s: bad substitution"), string
? string
: "??");
10028 #if defined (ARRAY_VARS)
10029 flush_eltstate (&es
);
10031 if (shell_compatibility_level
<= 43)
10032 return &expand_wdesc_error
;
10034 return ((posixly_correct
&& interactive_shell
== 0) ? &expand_wdesc_fatal
: &expand_wdesc_error
);
10040 temp1
= parameter_brace_transform (name
, temp
, &es
, value
, c
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10043 #if defined (ARRAY_VARS)
10044 flush_eltstate (&es
);
10047 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
10050 set_exit_status (EXECUTION_FAILURE
);
10051 report_error (_("%s: bad substitution"), string
? string
: "??");
10052 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10055 ret
= alloc_word_desc ();
10057 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10058 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10059 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10060 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10061 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10066 case '#': /* ${param#[#]pattern} */
10067 case '%': /* ${param%[%]pattern} */
10068 if (value
== 0 || *value
== '\0' || temp
== 0 || *temp
== '\0')
10073 temp1
= parameter_brace_remove_pattern (name
, temp
, &es
, value
, c
, quoted
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10076 #if defined (ARRAY_VARS)
10077 flush_eltstate (&es
);
10080 ret
= alloc_word_desc ();
10082 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10083 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10084 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10085 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10086 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10095 if (var_is_set
&& var_is_null
== 0)
10097 /* If the operator is `+', we don't want the value of the named
10098 variable for anything, just the value of the right hand side. */
10101 /* XXX -- if we're double-quoted and the named variable is "$@",
10102 we want to turn off any special handling of "$@" --
10103 we're not using it, so whatever is on the rhs applies. */
10104 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
10105 *quoted_dollar_atp
= 0;
10106 if (contains_dollar_at
)
10107 *contains_dollar_at
= 0;
10112 /* From Posix discussion on austin-group list. Issue 221
10113 requires that backslashes escaping `}' inside
10114 double-quoted ${...} be removed. */
10115 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10116 quoted
|= Q_DOLBRACE
;
10117 ret
= parameter_brace_expand_rhs (name
, value
, c
,
10121 contains_dollar_at
);
10122 /* XXX - fix up later, esp. noting presence of
10123 W_HASQUOTEDNULL in ret->flags */
10127 temp
= (char *)NULL
;
10133 /* Otherwise do nothing; just use the value in TEMP. */
10135 else /* VAR not set or VAR is NULL. */
10137 /* If we're freeing a quoted null here, we need to remember we saw
10138 it so we can restore it later if needed, or the caller can note it.
10139 The check against `+' doesn't really matter, since the other cases
10140 don't use or return TFLAG, but it's good for clarity. */
10141 if (c
== '+' && temp
&& QUOTED_NULL (temp
) &&
10142 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
10143 tflag
|= W_HASQUOTEDNULL
;
10146 temp
= (char *)NULL
;
10147 if (c
== '=' && var_is_special
)
10149 set_exit_status (EXECUTION_FAILURE
);
10150 report_error (_("$%s: cannot assign in this way"), name
);
10153 #if defined (ARRAY_VARS)
10154 flush_eltstate (&es
);
10156 return &expand_wdesc_error
;
10160 parameter_brace_expand_error (name
, value
, check_nullness
);
10161 #if defined (ARRAY_VARS)
10162 flush_eltstate (&es
);
10164 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10168 /* XXX -- if we're double-quoted and the named variable is "$@",
10169 we want to turn off any special handling of "$@" --
10170 we're not using it, so whatever is on the rhs applies. */
10171 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
10172 *quoted_dollar_atp
= 0;
10173 if (contains_dollar_at
)
10174 *contains_dollar_at
= 0;
10176 /* From Posix discussion on austin-group list. Issue 221 requires
10177 that backslashes escaping `}' inside double-quoted ${...} be
10179 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10180 quoted
|= Q_DOLBRACE
;
10181 ret
= parameter_brace_expand_rhs (name
, value
, c
, quoted
, pflags
,
10183 contains_dollar_at
);
10184 /* XXX - fix up later, esp. noting presence of
10185 W_HASQUOTEDNULL in tdesc->flags */
10193 #if defined (ARRAY_VARS)
10194 flush_eltstate (&es
);
10199 ret
= alloc_word_desc ();
10200 ret
->flags
= tflag
;
10206 /* Expand a single ${xxx} expansion. The braces are optional. When
10207 the braces are used, parameter_brace_expand() does the work,
10208 possibly calling param_expand recursively. */
10210 param_expand (string
, sindex
, quoted
, expanded_something
,
10211 contains_dollar_at
, quoted_dollar_at_p
, had_quoted_null_p
,
10214 int *sindex
, quoted
, *expanded_something
, *contains_dollar_at
;
10215 int *quoted_dollar_at_p
, *had_quoted_null_p
, pflags
;
10217 char *temp
, *temp1
, uerror
[3], *savecmd
;
10218 int zindex
, t_index
, expok
, eflag
;
10222 WORD_LIST
*list
, *l
;
10223 WORD_DESC
*tdesc
, *ret
;
10224 int tflag
, nullarg
;
10226 /*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
10228 c
= string
[++zindex
];
10230 temp
= (char *)NULL
;
10231 ret
= tdesc
= (WORD_DESC
*)NULL
;
10234 /* Do simple cases first. Switch on what follows '$'. */
10248 temp1
= dollar_vars
[TODIGIT (c
)];
10249 /* This doesn't get called when (pflags&PF_IGNUNBOUND) != 0 */
10250 if (unbound_vars_is_error
&& temp1
== (char *)NULL
)
10255 set_exit_status (EXECUTION_FAILURE
);
10256 err_unboundvar (uerror
);
10257 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10260 temp
= (*temp1
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10261 ? quote_string (temp1
)
10262 : quote_escapes (temp1
);
10264 temp
= (char *)NULL
;
10268 /* $$ -- pid of the invoking shell. */
10270 temp
= itos (dollar_dollar_pid
);
10273 /* $# -- number of positional parameters. */
10275 temp
= itos (number_of_args ());
10278 /* $? -- return value of the last synchronous command. */
10280 temp
= itos (last_command_exit_value
);
10283 /* $- -- flags supplied to the shell on invocation or by `set'. */
10285 temp
= which_set_flags ();
10288 /* $! -- Pid of the last asynchronous command. */
10290 /* If no asynchronous pids have been created, expand to nothing.
10291 If `set -u' has been executed, and no async processes have
10292 been created, this is an expansion error. */
10293 if (last_asynchronous_pid
== NO_PID
)
10295 if (expanded_something
)
10296 *expanded_something
= 0;
10297 temp
= (char *)NULL
;
10298 if (unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10303 set_exit_status (EXECUTION_FAILURE
);
10304 err_unboundvar (uerror
);
10305 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10309 temp
= itos (last_asynchronous_pid
);
10312 /* The only difference between this and $@ is when the arg is quoted. */
10313 case '*': /* `$*' */
10314 list
= list_rest_of_args ();
10317 /* According to austin-group posix proposal by Geoff Clare in
10318 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
10320 "The shell shall write a message to standard error and
10321 immediately exit when it tries to expand an unset parameter
10322 other than the '@' and '*' special parameters."
10325 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10330 set_exit_status (EXECUTION_FAILURE
);
10331 err_unboundvar (uerror
);
10332 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10336 /* If there are no command-line arguments, this should just
10337 disappear if there are other characters in the expansion,
10338 even if it's quoted. */
10339 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && list
== 0)
10340 temp
= (char *)NULL
;
10341 else if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
10343 /* If we have "$*" we want to make a string of the positional
10344 parameters, separated by the first character of $IFS, and
10345 quote the whole string, including the separators. If IFS
10346 is unset, the parameters are separated by ' '; if $IFS is
10347 null, the parameters are concatenated. */
10348 temp
= (quoted
& (Q_DOUBLE_QUOTES
|Q_PATQUOTE
)) ? string_list_dollar_star (list
, quoted
, 0) : string_list (list
);
10351 temp1
= (quoted
& Q_DOUBLE_QUOTES
) ? quote_string (temp
) : temp
;
10353 tflag
|= W_HASQUOTEDNULL
;
10361 /* We check whether or not we're eventually going to split $* here,
10362 for example when IFS is empty and we are processing the rhs of
10363 an assignment statement. In that case, we don't separate the
10364 arguments at all. Otherwise, if the $* is not quoted it is
10366 if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
== 0 && (pflags
& PF_ASSIGNRHS
))
10368 /* Posix interp 888: RHS of assignment, IFS unset: no splitting,
10369 separate with space */
10370 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10371 temp
= temp1
? quote_string (temp1
) : temp1
;
10372 /* XXX - tentative - note that we saw a quoted null here */
10373 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
10374 tflag
|= W_SAWQUOTEDNULL
;
10377 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_null
&& (pflags
& PF_ASSIGNRHS
))
10379 /* Posix interp 888: RHS of assignment, IFS set to '' */
10380 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10381 temp
= temp1
? quote_escapes (temp1
) : temp1
;
10384 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && (pflags
& PF_ASSIGNRHS
))
10386 /* Posix interp 888: RHS of assignment, IFS set to non-null value */
10387 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10388 temp
= temp1
? quote_string (temp1
) : temp1
;
10390 /* XXX - tentative - note that we saw a quoted null here */
10391 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
10392 tflag
|= W_SAWQUOTEDNULL
;
10395 /* XXX - should we check ifs_is_set here as well? */
10396 # if defined (HANDLE_MULTIBYTE)
10397 else if (expand_no_split_dollar_star
&& ifs_firstc
[0] == 0)
10399 else if (expand_no_split_dollar_star
&& ifs_firstc
== 0)
10401 /* Posix interp 888: not RHS, no splitting, IFS set to '' */
10402 temp
= string_list_dollar_star (list
, quoted
, 0);
10405 temp
= string_list_dollar_at (list
, quoted
, 0);
10406 /* Set W_SPLITSPACE to make sure the individual positional
10407 parameters are split into separate arguments */
10409 if (quoted
== 0 && (ifs_is_set
== 0 || ifs_is_null
))
10410 #else /* change with bash-5.0 */
10411 if (quoted
== 0 && ifs_is_null
)
10413 tflag
|= W_SPLITSPACE
;
10414 /* If we're not quoted but we still don't want word splitting, make
10415 we quote the IFS characters to protect them from splitting (e.g.,
10416 when $@ is in the string as well). */
10417 else if (temp
&& quoted
== 0 && ifs_is_set
&& (pflags
& PF_ASSIGNRHS
))
10419 temp1
= quote_string (temp
);
10425 if (expand_no_split_dollar_star
== 0 && contains_dollar_at
)
10426 *contains_dollar_at
= 1;
10429 dispose_words (list
);
10432 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
10433 means that we have to turn quoting off after we split into
10434 the individually quoted arguments so that the final split
10435 on the first character of $IFS is still done. */
10436 case '@': /* `$@' */
10437 list
= list_rest_of_args ();
10440 /* According to austin-group posix proposal by Geoff Clare in
10441 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
10443 "The shell shall write a message to standard error and
10444 immediately exit when it tries to expand an unset parameter
10445 other than the '@' and '*' special parameters."
10448 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10453 set_exit_status (EXECUTION_FAILURE
);
10454 err_unboundvar (uerror
);
10455 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10459 for (nullarg
= 0, l
= list
; l
; l
= l
->next
)
10461 if (l
->word
&& (l
->word
->word
== 0 || l
->word
->word
[0] == 0))
10465 /* We want to flag the fact that we saw this. We can't turn
10466 off quoting entirely, because other characters in the
10467 string might need it (consider "\"$@\""), but we need some
10468 way to signal that the final split on the first character
10469 of $IFS should be done, even though QUOTED is 1. */
10470 /* XXX - should this test include Q_PATQUOTE? */
10471 if (quoted_dollar_at_p
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10472 *quoted_dollar_at_p
= 1;
10473 if (contains_dollar_at
)
10474 *contains_dollar_at
= 1;
10476 /* We want to separate the positional parameters with the first
10477 character of $IFS in case $IFS is something other than a space.
10478 We also want to make sure that splitting is done no matter what --
10479 according to POSIX.2, this expands to a list of the positional
10480 parameters no matter what IFS is set to. */
10481 /* XXX - what to do when in a context where word splitting is not
10482 performed? Even when IFS is not the default, posix seems to imply
10483 that we have to expand $@ to all the positional parameters and
10484 separate them with spaces, which are preserved because word splitting
10485 doesn't take place. See below for how we use PF_NOSPLIT2 here. */
10487 /* These are the cases where word splitting will not be performed. */
10488 if (pflags
& PF_ASSIGNRHS
)
10490 temp
= string_list_dollar_at (list
, (quoted
|Q_DOUBLE_QUOTES
), pflags
);
10492 tflag
|= W_HASQUOTEDNULL
; /* we know quoting produces quoted nulls */
10495 /* This needs to match what expand_word_internal does with non-quoted $@
10496 does with separating with spaces. Passing Q_DOUBLE_QUOTES means that
10497 the characters in LIST will be quoted, and PF_ASSIGNRHS ensures that
10498 they will separated by spaces. After doing this, we need the special
10499 handling for PF_NOSPLIT2 in expand_word_internal to remove the CTLESC
10501 else if (pflags
& PF_NOSPLIT2
)
10503 #if defined (HANDLE_MULTIBYTE)
10504 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
10506 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
10508 /* Posix interp 888 */
10509 temp
= string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, pflags
);
10511 temp
= string_list_dollar_at (list
, quoted
, pflags
);
10514 temp
= string_list_dollar_at (list
, quoted
, pflags
);
10516 tflag
|= W_DOLLARAT
;
10517 dispose_words (list
);
10521 tdesc
= parameter_brace_expand (string
, &zindex
, quoted
, pflags
,
10522 quoted_dollar_at_p
,
10523 contains_dollar_at
);
10525 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
10527 temp
= tdesc
? tdesc
->word
: (char *)0;
10530 /* Quoted nulls should be removed if there is anything else
10532 /* Note that we saw the quoted null so we can add one back at
10533 the end of this function if there are no other characters
10534 in the string, discard TEMP, and go on. The exception to
10535 this is when we have "${@}" and $1 is '', since $@ needs
10536 special handling. */
10537 if (tdesc
&& tdesc
->word
&& (tdesc
->flags
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
))
10539 if (had_quoted_null_p
)
10540 *had_quoted_null_p
= 1;
10541 if (*quoted_dollar_at_p
== 0)
10544 tdesc
->word
= temp
= (char *)NULL
;
10552 /* Do command or arithmetic substitution. */
10554 /* We have to extract the contents of this paren substitution. */
10555 t_index
= zindex
+ 1;
10556 /* XXX - might want to check for string[t_index+2] == LPAREN and parse
10557 as arithmetic substitution immediately. */
10558 temp
= extract_command_subst (string
, &t_index
, (pflags
&PF_COMPLETE
) ? SX_COMPLETE
: 0);
10561 /* For Posix.2-style `$(( ))' arithmetic substitution,
10562 extract the expression and pass it to the evaluator. */
10563 if (temp
&& *temp
== LPAREN
)
10567 temp2
= savestring (temp1
);
10568 t_index
= strlen (temp2
) - 1;
10570 if (temp2
[t_index
] != RPAREN
)
10576 /* Cut off ending `)' */
10577 temp2
[t_index
] = '\0';
10579 if (chk_arithsub (temp2
, t_index
) == 0)
10583 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
10588 /* Expand variables found inside the expression. */
10589 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
10593 /* No error messages. */
10594 savecmd
= this_command_name
;
10595 this_command_name
= (char *)NULL
;
10597 eflag
= (shell_compatibility_level
> 51) ? 0 : EXP_EXPANDED
;
10598 number
= evalexp (temp1
, eflag
, &expok
);
10599 this_command_name
= savecmd
;
10604 if (interactive_shell
== 0 && posixly_correct
)
10606 set_exit_status (EXECUTION_FAILURE
);
10607 return (&expand_wdesc_fatal
);
10610 return (&expand_wdesc_error
);
10612 temp
= itos (number
);
10617 if (pflags
& PF_NOCOMSUB
)
10618 /* we need zindex+1 because string[zindex] == RPAREN */
10619 temp1
= substring (string
, *sindex
, zindex
+1);
10622 tdesc
= command_substitute (temp
, quoted
, pflags
&PF_ASSIGNRHS
);
10623 temp1
= tdesc
? tdesc
->word
: (char *)NULL
;
10625 dispose_word_desc (tdesc
);
10631 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
10632 away in a future bash release. */
10634 /* Extract the contents of this arithmetic substitution. */
10635 t_index
= zindex
+ 1;
10636 temp
= extract_arithmetic_subst (string
, &t_index
);
10640 temp
= savestring (string
);
10641 if (expanded_something
)
10642 *expanded_something
= 0;
10646 /* Do initial variable expansion. */
10647 temp1
= expand_arith_string (temp
, Q_DOUBLE_QUOTES
|Q_ARITH
);
10652 /* Find the variable in VARIABLE_LIST. */
10653 temp
= (char *)NULL
;
10655 for (t_index
= zindex
; (c
= string
[zindex
]) && legal_variable_char (c
); zindex
++)
10657 temp1
= (zindex
> t_index
) ? substring (string
, t_index
, zindex
) : (char *)NULL
;
10659 /* If this isn't a variable name, then just output the `$'. */
10660 if (temp1
== 0 || *temp1
== '\0')
10663 temp
= (char *)xmalloc (2);
10666 if (expanded_something
)
10667 *expanded_something
= 0;
10671 /* If the variable exists, return its value cell. */
10672 var
= find_variable (temp1
);
10674 if (var
&& invisible_p (var
) == 0 && var_isset (var
))
10676 #if defined (ARRAY_VARS)
10677 if (assoc_p (var
) || array_p (var
))
10679 temp
= array_p (var
) ? array_reference (array_cell (var
), 0)
10680 : assoc_reference (assoc_cell (var
), "0");
10682 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10683 ? quote_string (temp
)
10684 : quote_escapes (temp
);
10685 else if (unbound_vars_is_error
)
10686 goto unbound_variable
;
10691 temp
= value_cell (var
);
10693 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10694 ? quote_string (temp
)
10695 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
10696 : quote_escapes (temp
));
10703 else if (var
&& (invisible_p (var
) || var_isset (var
) == 0))
10704 temp
= (char *)NULL
;
10705 else if ((var
= find_variable_last_nameref (temp1
, 0)) && var_isset (var
) && invisible_p (var
) == 0)
10707 temp
= nameref_cell (var
);
10708 #if defined (ARRAY_VARS)
10709 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
10711 chk_atstar (temp
, quoted
, pflags
, quoted_dollar_at_p
, contains_dollar_at
);
10712 tdesc
= parameter_brace_expand_word (temp
, SPECIAL_VAR (temp
, 0), quoted
, pflags
, 0);
10713 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
10720 /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
10721 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
10723 set_exit_status (EXECUTION_FAILURE
);
10724 report_error (_("%s: invalid variable name for name reference"), temp
);
10725 return (&expand_wdesc_error
); /* XXX */
10728 temp
= (char *)NULL
;
10731 temp
= (char *)NULL
;
10734 if (unbound_vars_is_error
)
10736 set_exit_status (EXECUTION_FAILURE
);
10737 err_unboundvar (temp1
);
10746 set_exit_status (EXECUTION_FAILURE
);
10747 return ((unbound_vars_is_error
&& interactive_shell
== 0)
10748 ? &expand_wdesc_fatal
10749 : &expand_wdesc_error
);
10752 if (string
[zindex
])
10760 ret
= alloc_word_desc ();
10761 ret
->flags
= tflag
; /* XXX */
10767 #if defined (ARRAY_VARS)
10768 /* Characters that need to be backslash-quoted after expanding array subscripts */
10769 static char abstab
[256] = { '\1' };
10771 /* Run an array subscript through the appropriate word expansions. */
10773 expand_subscript_string (string
, quoted
)
10782 if (string
== 0 || *string
== 0)
10783 return (char *)NULL
;
10785 oe
= expand_no_split_dollar_star
;
10786 ret
= (char *)NULL
;
10788 td
.flags
= W_NOPROCSUB
|W_NOTILDE
|W_NOSPLIT2
; /* XXX - W_NOCOMSUB? */
10789 td
.word
= savestring (string
); /* in case it's freed on error */
10791 expand_no_split_dollar_star
= 1;
10792 tlist
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
10793 expand_no_split_dollar_star
= oe
;
10799 remove_quoted_nulls (tlist
->word
->word
);
10800 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
10802 dequote_list (tlist
);
10803 ret
= string_list (tlist
);
10804 dispose_words (tlist
);
10811 /* Expand the subscript in STRING, which is an array reference. To ensure we
10812 only expand it once, we quote the characters that would start another
10813 expansion and the bracket characters that are special to array subscripts. */
10815 expand_array_subscript (string
, sindex
, quoted
, flags
)
10820 char *ret
, *exp
, *t
;
10825 slen
= STRLEN (string
);
10827 if (abstab
[0] == '\1')
10829 /* These are basically the characters that start shell expansions plus
10830 the characters that delimit subscripts. */
10831 memset (abstab
, '\0', sizeof (abstab
));
10832 abstab
[LBRACK
] = abstab
[RBRACK
] = 1;
10833 abstab
['$'] = abstab
['`'] = abstab
['~'] = 1;
10834 abstab
['\\'] = abstab
['\''] = 1;
10835 abstab
['"'] = 1; /* XXX */
10836 /* We don't quote `@' or `*' in the subscript at all. */
10839 /* string[si] == LBRACK */
10840 ni
= skipsubscript (string
, si
, 0);
10841 /* These checks mirror the ones in valid_array_reference. The check for
10842 (ni - si) == 1 checks for empty subscripts. We don't check that the
10843 subscript is a separate word if we're parsing an arithmetic expression. */
10844 if (ni
>= slen
|| string
[ni
] != RBRACK
|| (ni
- si
) == 1 ||
10845 (string
[ni
+1] != '\0' && (quoted
& Q_ARITH
) == 0))
10847 /* let's check and see what fails this check */
10848 INTERNAL_DEBUG (("expand_array_subscript: bad subscript string: `%s'", string
+si
));
10849 ret
= (char *)xmalloc (2); /* badly-formed subscript */
10850 ret
[0] = string
[si
];
10856 /* STRING[ni] == RBRACK */
10857 exp
= substring (string
, si
+1, ni
);
10858 t
= expand_subscript_string (exp
, quoted
& ~(Q_ARITH
|Q_DOUBLE_QUOTES
));
10860 exp
= t
? sh_backslash_quote (t
, abstab
, 0) : savestring ("");
10863 slen
= STRLEN (exp
);
10864 ret
= xmalloc (slen
+ 2 + 1);
10866 strcpy (ret
+ 1, exp
);
10867 ret
[slen
+ 1] = ']';
10868 ret
[slen
+ 2] = '\0';
10878 invalidate_cached_quoted_dollar_at ()
10880 dispose_words (cached_quoted_dollar_at
);
10881 cached_quoted_dollar_at
= 0;
10884 /* Make a word list which is the result of parameter and variable
10885 expansion, command substitution, arithmetic substitution, and
10886 quote removal of WORD. Return a pointer to a WORD_LIST which is
10887 the result of the expansion. If WORD contains a null word, the
10888 word list returned is also null.
10890 QUOTED contains flag values defined in shell.h.
10892 ISEXP is used to tell expand_word_internal that the word should be
10893 treated as the result of an expansion. This has implications for
10894 how IFS characters in the word are treated.
10896 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
10897 they point to an integer value which receives information about expansion.
10898 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
10899 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
10902 This only does word splitting in the case of $@ expansion. In that
10903 case, we split on ' '. */
10905 /* Values for the local variable quoted_state. */
10907 #define PARTIALLY_QUOTED 1
10908 #define WHOLLY_QUOTED 2
10911 expand_word_internal (word
, quoted
, isexp
, contains_dollar_at
, expanded_something
)
10914 int *contains_dollar_at
;
10915 int *expanded_something
;
10920 /* The intermediate string that we build while expanding. */
10923 /* The current size of the above object. */
10924 size_t istring_size
;
10926 /* Index into ISTRING. */
10927 size_t istring_index
;
10929 /* Temporary string storage. */
10930 char *temp
, *temp1
;
10932 /* The text of WORD. */
10933 register char *string
;
10935 /* The size of STRING. */
10936 size_t string_size
;
10938 /* The index into STRING. */
10941 /* This gets 1 if we see a $@ while quoted. */
10942 int quoted_dollar_at
;
10944 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
10945 whether WORD contains no quoting characters, a partially quoted
10946 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
10950 int had_quoted_null
;
10951 int has_quoted_ifs
; /* did we add a quoted $IFS character here? */
10952 int has_dollar_at
, temp_has_dollar_at
;
10953 int internal_tilde
;
10954 int split_on_spaces
;
10955 int local_expanded
;
10957 int pflags
; /* flags passed to param_expand */
10960 int assignoff
; /* If assignment, offset of `=' */
10962 register unsigned char c
; /* Current character. */
10963 int t_index
; /* For calls to string_extract_xxx. */
10969 /* OK, let's see if we can optimize a common idiom: "$@". This needs to make sure
10970 that all of the flags callers care about (e.g., W_HASQUOTEDNULL) are set in
10972 if (STREQ (word
->word
, "\"$@\"") &&
10973 (word
->flags
== (W_HASDOLLAR
|W_QUOTED
)) &&
10974 dollar_vars
[1]) /* XXX - check IFS here as well? */
10976 if (contains_dollar_at
)
10977 *contains_dollar_at
= 1;
10978 if (expanded_something
)
10979 *expanded_something
= 1;
10980 if (cached_quoted_dollar_at
)
10981 return (copy_word_list (cached_quoted_dollar_at
));
10982 list
= list_rest_of_args ();
10983 list
= quote_list (list
);
10984 cached_quoted_dollar_at
= copy_word_list (list
);
10988 istring
= (char *)xmalloc (istring_size
= DEFAULT_INITIAL_ARRAY_SIZE
);
10989 istring
[istring_index
= 0] = '\0';
10990 quoted_dollar_at
= had_quoted_null
= has_dollar_at
= 0;
10991 has_quoted_ifs
= 0;
10992 split_on_spaces
= 0;
10993 internal_tilde
= 0; /* expanding =~ or :~ */
10994 quoted_state
= UNQUOTED
;
10996 string
= word
->word
;
10998 goto finished_with_string
;
10999 mb_cur_max
= MB_CUR_MAX
;
11001 /* Don't need the string length for the SADD... and COPY_ macros unless
11002 multibyte characters are possible, but do need it for bounds checking. */
11003 string_size
= (mb_cur_max
> 1) ? strlen (string
) : 1;
11005 if (contains_dollar_at
)
11006 *contains_dollar_at
= 0;
11010 /* Begin the expansion. */
11012 for (sindex
= 0; ;)
11014 c
= string
[sindex
];
11016 /* Case on top-level character. */
11020 goto finished_with_string
;
11024 #if HANDLE_MULTIBYTE
11025 if (mb_cur_max
> 1 && string
[sindex
])
11027 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
11032 temp
= (char *)xmalloc (3);
11034 temp
[1] = c
= string
[sindex
];
11039 if (string
[sindex
])
11045 istring
= sub_append_string (temp
, istring
, &istring_index
, &istring_size
);
11051 #if defined (PROCESS_SUBSTITUTION)
11052 /* Process substitution. */
11056 /* XXX - technically this should only be expanded at the start
11058 if (string
[++sindex
] != LPAREN
|| (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (word
->flags
& W_NOPROCSUB
))
11060 sindex
--; /* add_character: label increments sindex */
11061 goto add_character
;
11064 t_index
= sindex
+ 1; /* skip past both '<' and LPAREN */
11066 temp1
= extract_process_subst (string
, (c
== '<') ? "<(" : ">(", &t_index
, 0); /*))*/
11069 /* If the process substitution specification is `<()', we want to
11070 open the pipe for writing in the child and produce output; if
11071 it is `>()', we want to open the pipe for reading in the child
11072 and consume input. */
11073 temp
= temp1
? process_substitute (temp1
, (c
== '>')) : (char *)0;
11077 goto dollar_add_string
;
11079 #endif /* PROCESS_SUBSTITUTION */
11081 #if defined (ARRAY_VARS)
11083 if ((quoted
& Q_ARITH
) == 0 || shell_compatibility_level
<= 51)
11085 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
11086 goto add_ifs_character
;
11088 goto add_character
;
11092 temp
= expand_array_subscript (string
, &sindex
, quoted
, word
->flags
);
11098 /* Posix.2 section 3.6.1 says that tildes following `=' in words
11099 which are not assignment statements are not expanded. If the
11100 shell isn't in posix mode, though, we perform tilde expansion
11101 on `likely candidate' unquoted assignment statements (flags
11102 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
11103 contains an unquoted :~ or =~. Something to think about: we
11104 now have a flag that says to perform tilde expansion on arguments
11105 to `assignment builtins' like declare and export that look like
11106 assignment statements. We now do tilde expansion on such words
11107 even in POSIX mode. */
11108 if (word
->flags
& (W_ASSIGNRHS
|W_NOTILDE
))
11110 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11111 goto add_ifs_character
;
11113 goto add_character
;
11115 /* If we're not in posix mode or forcing assignment-statement tilde
11116 expansion, note where the first `=' appears in the word and prepare
11117 to do tilde expansion following the first `='. We have to keep
11118 track of the first `=' (using assignoff) to avoid being confused
11119 by an `=' in the rhs of the assignment statement. */
11120 if ((word
->flags
& W_ASSIGNMENT
) &&
11121 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
11122 assignoff
== -1 && sindex
> 0)
11123 assignoff
= sindex
;
11124 if (sindex
== assignoff
&& string
[sindex
+1] == '~') /* XXX */
11125 internal_tilde
= 1;
11127 if (word
->flags
& W_ASSIGNARG
)
11128 word
->flags
|= W_ASSIGNRHS
; /* affects $@ */
11130 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11133 goto add_ifs_character
;
11136 goto add_character
;
11139 if (word
->flags
& (W_NOTILDE
|W_NOASSNTILDE
))
11141 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11142 goto add_ifs_character
;
11144 goto add_character
;
11147 if ((word
->flags
& (W_ASSIGNMENT
|W_ASSIGNRHS
)) &&
11148 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
11149 string
[sindex
+1] == '~')
11150 internal_tilde
= 1;
11152 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11153 goto add_ifs_character
;
11155 goto add_character
;
11158 /* If the word isn't supposed to be tilde expanded, or we're not
11159 at the start of a word or after an unquoted : or = in an
11160 assignment statement, we don't do tilde expansion. We don't
11161 do tilde expansion if quoted or in an arithmetic context. */
11163 if ((word
->flags
& W_NOTILDE
) ||
11164 (sindex
> 0 && (internal_tilde
== 0)) ||
11165 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
11167 internal_tilde
= 0;
11168 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
11169 goto add_ifs_character
;
11171 goto add_character
;
11174 if (word
->flags
& W_ASSIGNRHS
)
11176 else if (word
->flags
& (W_ASSIGNMENT
|W_TILDEEXP
))
11181 temp
= bash_tilde_find_word (string
+ sindex
, tflag
, &t_index
);
11183 internal_tilde
= 0;
11185 if (temp
&& *temp
&& t_index
> 0)
11187 temp1
= bash_tilde_expand (temp
, tflag
);
11188 if (temp1
&& *temp1
== '~' && STREQ (temp
, temp1
))
11192 goto add_character
; /* tilde expansion failed */
11197 goto add_quoted_string
; /* XXX was add_string */
11202 goto add_character
;
11206 if (expanded_something
)
11207 *expanded_something
= 1;
11208 local_expanded
= 1;
11210 temp_has_dollar_at
= 0;
11211 pflags
= (word
->flags
& W_NOCOMSUB
) ? PF_NOCOMSUB
: 0;
11212 if (word
->flags
& W_NOSPLIT2
)
11213 pflags
|= PF_NOSPLIT2
;
11214 if (word
->flags
& W_ASSIGNRHS
)
11215 pflags
|= PF_ASSIGNRHS
;
11216 if (word
->flags
& W_COMPLETE
)
11217 pflags
|= PF_COMPLETE
;
11219 tword
= param_expand (string
, &sindex
, quoted
, expanded_something
,
11220 &temp_has_dollar_at
, "ed_dollar_at
,
11221 &had_quoted_null
, pflags
);
11222 has_dollar_at
+= temp_has_dollar_at
;
11223 split_on_spaces
+= (tword
->flags
& W_SPLITSPACE
);
11225 if (tword
== &expand_wdesc_error
|| tword
== &expand_wdesc_fatal
)
11229 return ((tword
== &expand_wdesc_error
) ? &expand_word_error
11230 : &expand_word_fatal
);
11232 if (contains_dollar_at
&& has_dollar_at
)
11233 *contains_dollar_at
= 1;
11235 if (tword
&& (tword
->flags
& W_HASQUOTEDNULL
))
11236 had_quoted_null
= 1; /* note for later */
11237 if (tword
&& (tword
->flags
& W_SAWQUOTEDNULL
))
11238 had_quoted_null
= 1; /* XXX */
11240 temp
= tword
? tword
->word
: (char *)NULL
;
11241 dispose_word_desc (tword
);
11243 /* Kill quoted nulls; we will add them back at the end of
11244 expand_word_internal if nothing else in the string */
11245 if (had_quoted_null
&& temp
&& QUOTED_NULL (temp
))
11248 temp
= (char *)NULL
;
11254 case '`': /* Backquoted command substitution. */
11256 t_index
= sindex
++;
11258 temp
= string_extract (string
, &sindex
, "`", (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: SX_REQMATCH
);
11259 /* The test of sindex against t_index is to allow bare instances of
11260 ` to pass through, for backwards compatibility. */
11261 if (temp
== &extract_string_error
|| temp
== &extract_string_fatal
)
11263 if (sindex
- 1 == t_index
)
11266 goto add_character
;
11268 set_exit_status (EXECUTION_FAILURE
);
11269 report_error (_("bad substitution: no closing \"`\" in %s") , string
+t_index
);
11272 return ((temp
== &extract_string_error
) ? &expand_word_error
11273 : &expand_word_fatal
);
11276 if (expanded_something
)
11277 *expanded_something
= 1;
11278 local_expanded
= 1;
11280 if (word
->flags
& W_NOCOMSUB
)
11281 /* sindex + 1 because string[sindex] == '`' */
11282 temp1
= substring (string
, t_index
, sindex
+ 1);
11285 de_backslash (temp
);
11286 tword
= command_substitute (temp
, quoted
, 0);
11287 temp1
= tword
? tword
->word
: (char *)NULL
;
11289 dispose_word_desc (tword
);
11293 goto dollar_add_string
;
11297 if (string
[sindex
+ 1] == '\n')
11303 c
= string
[++sindex
];
11305 /* "However, the double-quote character ( '"' ) shall not be treated
11306 specially within a here-document, except when the double-quote
11307 appears within "$()", "``", or "${}"." */
11308 if ((quoted
& Q_HERE_DOCUMENT
) && (quoted
& Q_DOLBRACE
) && c
== '"')
11309 tflag
= CBSDQUOTE
; /* special case */
11310 else if (quoted
& Q_HERE_DOCUMENT
)
11312 else if (quoted
& Q_DOUBLE_QUOTES
)
11317 /* From Posix discussion on austin-group list: Backslash escaping
11318 a } in ${...} is removed. Issue 0000221 */
11319 if ((quoted
& Q_DOLBRACE
) && c
== RBRACE
)
11321 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11323 /* This is the fix for " $@\ " */
11324 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0) && isexp
== 0 && isifs (c
))
11326 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11327 DEFAULT_ARRAY_SIZE
);
11328 istring
[istring_index
++] = CTLESC
;
11329 istring
[istring_index
++] = '\\';
11330 istring
[istring_index
] = '\0';
11332 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11334 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && c
== 0)
11336 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11337 DEFAULT_ARRAY_SIZE
);
11338 istring
[istring_index
++] = CTLESC
;
11339 istring
[istring_index
++] = '\\';
11340 istring
[istring_index
] = '\0';
11343 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0))
11345 SCOPY_CHAR_I (twochars
, '\\', c
, string
, sindex
, string_size
);
11350 sindex
--; /* add_character: label increments sindex */
11351 goto add_character
;
11355 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11360 /* BEFORE jumping here, we need to increment sindex if appropriate */
11361 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11362 DEFAULT_ARRAY_SIZE
);
11363 istring
[istring_index
++] = twochars
[0];
11364 istring
[istring_index
++] = twochars
[1];
11365 istring
[istring_index
] = '\0';
11370 /* XXX - revisit this */
11371 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && ((quoted
& Q_ARITH
) == 0))
11372 goto add_character
;
11374 t_index
= ++sindex
;
11375 temp
= string_extract_double_quoted (string
, &sindex
, (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: 0);
11377 /* If the quotes surrounded the entire string, then the
11378 whole word was quoted. */
11379 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
11381 : PARTIALLY_QUOTED
;
11385 tword
= alloc_word_desc ();
11386 tword
->word
= temp
;
11388 if (word
->flags
& W_ASSIGNARG
)
11389 tword
->flags
|= word
->flags
& (W_ASSIGNARG
|W_ASSIGNRHS
); /* affects $@ */
11390 if (word
->flags
& W_COMPLETE
)
11391 tword
->flags
|= W_COMPLETE
; /* for command substitutions */
11392 if (word
->flags
& W_NOCOMSUB
)
11393 tword
->flags
|= W_NOCOMSUB
;
11394 if (word
->flags
& W_NOPROCSUB
)
11395 tword
->flags
|= W_NOPROCSUB
;
11397 if (word
->flags
& W_ASSIGNRHS
)
11398 tword
->flags
|= W_ASSIGNRHS
;
11400 temp
= (char *)NULL
;
11402 temp_has_dollar_at
= 0; /* does this quoted (sub)string include $@? */
11403 /* Need to get W_HASQUOTEDNULL flag through this function. */
11404 /* XXX - preserve Q_ARITH here? */
11405 list
= expand_word_internal (tword
, Q_DOUBLE_QUOTES
|(quoted
&Q_ARITH
), 0, &temp_has_dollar_at
, (int *)NULL
);
11406 has_dollar_at
+= temp_has_dollar_at
;
11408 if (list
== &expand_word_error
|| list
== &expand_word_fatal
)
11412 /* expand_word_internal has already freed temp_word->word
11413 for us because of the way it prints error messages. */
11414 tword
->word
= (char *)NULL
;
11415 dispose_word (tword
);
11419 dispose_word (tword
);
11421 /* "$@" (a double-quoted dollar-at) expands into nothing,
11422 not even a NULL word, when there are no positional
11423 parameters. Posix interp 888 says that other parts of the
11424 word that expand to quoted nulls result in quoted nulls, so
11425 we can't just throw the entire word away if we have "$@"
11426 anywhere in it. We use had_quoted_null to keep track */
11427 if (list
== 0 && temp_has_dollar_at
) /* XXX - was has_dollar_at */
11429 quoted_dollar_at
++;
11433 /* If this list comes back with a quoted null from expansion,
11434 we have either "$x" or "$@" with $1 == ''. In either case,
11435 we need to make sure we add a quoted null argument and
11436 disable the special handling that "$@" gets. */
11437 if (list
&& list
->word
&& list
->next
== 0 && (list
->word
->flags
& W_HASQUOTEDNULL
))
11439 if (had_quoted_null
&& temp_has_dollar_at
)
11440 quoted_dollar_at
++;
11441 had_quoted_null
= 1; /* XXX */
11444 /* If we get "$@", we know we have expanded something, so we
11445 need to remember it for the final split on $IFS. This is
11446 a special case; it's the only case where a quoted string
11447 can expand into more than one word. It's going to come back
11448 from the above call to expand_word_internal as a list with
11451 dequote_list (list
);
11453 if (temp_has_dollar_at
) /* XXX - was has_dollar_at */
11455 quoted_dollar_at
++;
11456 if (contains_dollar_at
)
11457 *contains_dollar_at
= 1;
11458 if (expanded_something
)
11459 *expanded_something
= 1;
11460 local_expanded
= 1;
11465 /* What we have is "". This is a minor optimization. */
11467 list
= (WORD_LIST
*)NULL
;
11468 had_quoted_null
= 1; /* note for later */
11471 /* The code above *might* return a list (consider the case of "$@",
11472 where it returns "$1", "$2", etc.). We can't throw away the
11473 rest of the list, and we have to make sure each word gets added
11474 as quoted. We test on tresult->next: if it is non-NULL, we
11475 quote the whole list, save it to a string with string_list, and
11476 add that string. We don't need to quote the results of this
11477 (and it would be wrong, since that would quote the separators
11478 as well), so we go directly to add_string. */
11483 /* Testing quoted_dollar_at makes sure that "$@" is
11484 split correctly when $IFS does not contain a space. */
11485 temp
= quoted_dollar_at
11486 ? string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, 0)
11487 : string_list (quote_list (list
));
11488 dispose_words (list
);
11493 temp
= savestring (list
->word
->word
);
11494 tflag
= list
->word
->flags
;
11495 dispose_words (list
);
11497 /* If the string is not a quoted null string, we want
11498 to remove any embedded unquoted CTLNUL characters.
11499 We do not want to turn quoted null strings back into
11500 the empty string, though. We do this because we
11501 want to remove any quoted nulls from expansions that
11502 contain other characters. For example, if we have
11503 x"$*"y or "x$*y" and there are no positional parameters,
11504 the $* should expand into nothing. */
11505 /* We use the W_HASQUOTEDNULL flag to differentiate the
11506 cases: a quoted null character as above and when
11507 CTLNUL is contained in the (non-null) expansion
11508 of some variable. We use the had_quoted_null flag to
11509 pass the value through this function to its caller. */
11510 if ((tflag
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
) == 0)
11511 remove_quoted_nulls (temp
); /* XXX */
11515 temp
= (char *)NULL
;
11517 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
11518 had_quoted_null
= 1; /* note for later */
11520 /* We do not want to add quoted nulls to strings that are only
11521 partially quoted; we can throw them away. The exception to
11522 this is when we are going to be performing word splitting,
11523 since we have to preserve a null argument if the next character
11524 will cause word splitting. */
11525 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
11529 had_quoted_null
= 1;
11530 goto add_character
;
11532 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
11540 temp
= quote_string (temp
);
11546 /* Add NULL arg. */
11548 sindex
--; /* add_character: label increments sindex */
11549 had_quoted_null
= 1; /* note for later */
11550 goto add_character
;
11556 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
11557 goto add_character
;
11559 t_index
= ++sindex
;
11560 temp
= string_extract_single_quoted (string
, &sindex
, 0);
11562 /* If the entire STRING was surrounded by single quotes,
11563 then the string is wholly quoted. */
11564 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
11566 : PARTIALLY_QUOTED
;
11568 /* If all we had was '', it is a null expansion. */
11572 temp
= (char *)NULL
;
11575 remove_quoted_escapes (temp
); /* ??? */
11577 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
11578 had_quoted_null
= 1; /* note for later */
11580 /* We do not want to add quoted nulls to strings that are only
11581 partially quoted; such nulls are discarded. See above for the
11582 exception, which is when the string is going to be split.
11583 Posix interp 888/1129 */
11584 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
11588 goto add_character
;
11591 if (temp
== 0 && (quoted_state
== PARTIALLY_QUOTED
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
11594 /* If we have a quoted null expansion, add a quoted NULL to istring. */
11598 sindex
--; /* add_character: label increments sindex */
11599 goto add_character
;
11602 goto add_quoted_string
;
11607 /* If we are in a context where the word is not going to be split, but
11608 we need to account for $@ and $* producing one word for each
11609 positional parameter, add quoted spaces so the spaces in the
11610 expansion of "$@", if any, behave correctly. We still may need to
11611 split if we are expanding the rhs of a word expansion. */
11612 if (ifs_is_null
|| split_on_spaces
|| ((word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
|W_ASSIGNRHS
)) && (word
->flags
& W_EXPANDRHS
) == 0))
11614 if (string
[sindex
])
11616 twochars
[0] = CTLESC
;
11623 /* This is the fix for " $@ " */
11625 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (isexp
== 0 && isifs (c
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0))
11627 if ((quoted
&(Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0)
11629 add_quoted_character
:
11630 if (string
[sindex
]) /* from old goto dollar_add_string */
11635 goto add_character
;
11639 #if HANDLE_MULTIBYTE
11640 /* XXX - should make sure that c is actually multibyte,
11641 otherwise we can use the twochars branch */
11642 if (mb_cur_max
> 1)
11645 if (mb_cur_max
> 1)
11647 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
11652 twochars
[0] = CTLESC
;
11659 SADD_MBCHAR (temp
, string
, sindex
, string_size
);
11662 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 1, istring_size
,
11663 DEFAULT_ARRAY_SIZE
);
11664 istring
[istring_index
++] = c
;
11665 istring
[istring_index
] = '\0';
11667 /* Next character. */
11672 finished_with_string
:
11673 /* OK, we're ready to return. If we have a quoted string, and
11674 quoted_dollar_at is not set, we do no splitting at all; otherwise
11675 we split on ' '. The routines that call this will handle what to
11676 do if nothing has been expanded. */
11678 /* Partially and wholly quoted strings which expand to the empty
11679 string are retained as an empty arguments. Unquoted strings
11680 which expand to the empty string are discarded. The single
11681 exception is the case of expanding "$@" when there are no
11682 positional parameters. In that case, we discard the expansion. */
11684 /* Because of how the code that handles "" and '' in partially
11685 quoted strings works, we need to make ISTRING into a QUOTED_NULL
11686 if we saw quoting characters, but the expansion was empty.
11687 "" and '' are tossed away before we get to this point when
11688 processing partially quoted strings. This makes "" and $xxx""
11689 equivalent when xxx is unset. We also look to see whether we
11690 saw a quoted null from a ${} expansion and add one back if we
11693 /* If we expand to nothing and there were no single or double quotes
11694 in the word, we throw it away. Otherwise, we return a NULL word.
11695 The single exception is for $@ surrounded by double quotes when
11696 there are no positional parameters. In that case, we also throw
11699 if (*istring
== '\0')
11702 if (quoted_dollar_at
== 0 && (had_quoted_null
|| quoted_state
== PARTIALLY_QUOTED
))
11704 if (had_quoted_null
|| (quoted_dollar_at
== 0 && quoted_state
== PARTIALLY_QUOTED
))
11707 istring
[0] = CTLNUL
;
11709 tword
= alloc_word_desc ();
11710 tword
->word
= istring
;
11711 istring
= 0; /* avoid later free() */
11712 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11713 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11714 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
11715 tword
->flags
|= W_QUOTED
;
11717 /* According to sh, ksh, and Posix.2, if a word expands into nothing
11718 and a double-quoted "$@" appears anywhere in it, then the entire
11719 word is removed. */
11720 /* XXX - exception appears to be that quoted null strings result in
11722 else if (quoted_state
== UNQUOTED
|| quoted_dollar_at
)
11723 list
= (WORD_LIST
*)NULL
;
11725 list
= (WORD_LIST
*)NULL
;
11727 else if (word
->flags
& W_NOSPLIT
)
11729 tword
= alloc_word_desc ();
11730 tword
->word
= istring
;
11731 if (had_quoted_null
&& QUOTED_NULL (istring
))
11732 tword
->flags
|= W_HASQUOTEDNULL
;
11733 istring
= 0; /* avoid later free() */
11734 if (word
->flags
& W_ASSIGNMENT
)
11735 tword
->flags
|= W_ASSIGNMENT
; /* XXX */
11736 if (word
->flags
& W_COMPASSIGN
)
11737 tword
->flags
|= W_COMPASSIGN
; /* XXX */
11738 if (word
->flags
& W_NOGLOB
)
11739 tword
->flags
|= W_NOGLOB
; /* XXX */
11740 if (word
->flags
& W_NOBRACE
)
11741 tword
->flags
|= W_NOBRACE
; /* XXX */
11742 if (word
->flags
& W_ARRAYREF
)
11743 tword
->flags
|= W_ARRAYREF
;
11744 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
11745 tword
->flags
|= W_QUOTED
;
11746 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11748 else if (word
->flags
& W_ASSIGNRHS
)
11750 list
= list_string (istring
, "", quoted
);
11751 tword
= list
->word
;
11752 if (had_quoted_null
&& QUOTED_NULL (istring
))
11753 tword
->flags
|= W_HASQUOTEDNULL
;
11756 istring
= 0; /* avoid later free() */
11757 goto set_word_flags
;
11763 ifs_chars
= (quoted_dollar_at
|| has_dollar_at
) ? ifs_value
: (char *)NULL
;
11765 /* If we have $@, we need to split the results no matter what. If
11766 IFS is unset or NULL, string_list_dollar_at has separated the
11767 positional parameters with a space, so we split on space (we have
11768 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
11769 string_list_dollar_at has separated the positional parameters
11770 with the first character of $IFS, so we split on $IFS. If
11771 SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
11772 unset or null, and we want to make sure that we split on spaces
11773 regardless of what else has happened to IFS since the expansion,
11774 or we expanded "$@" with IFS null and we need to split the positional
11775 parameters into separate words. */
11776 if (split_on_spaces
)
11778 /* If IFS is not set, and the word is not quoted, we want to split
11779 the individual words on $' \t\n'. We rely on previous steps to
11780 quote the portions of the word that should not be split */
11781 if (ifs_is_set
== 0)
11782 list
= list_string (istring
, " \t\n", 1); /* XXX quoted == 1? */
11784 list
= list_string (istring
, " ", 1); /* XXX quoted == 1? */
11787 /* If we have $@ (has_dollar_at != 0) and we are in a context where we
11788 don't want to split the result (W_NOSPLIT2), and we are not quoted,
11789 we have already separated the arguments with the first character of
11790 $IFS. In this case, we want to return a list with a single word
11791 with the separator possibly replaced with a space (it's what other
11792 shells seem to do).
11793 quoted_dollar_at is internal to this function and is set if we are
11794 passed an argument that is unquoted (quoted == 0) but we encounter a
11795 double-quoted $@ while expanding it. */
11796 else if (has_dollar_at
&& quoted_dollar_at
== 0 && ifs_chars
&& quoted
== 0 && (word
->flags
& W_NOSPLIT2
))
11798 tword
= alloc_word_desc ();
11799 /* Only split and rejoin if we have to */
11800 if (*ifs_chars
&& *ifs_chars
!= ' ')
11802 /* list_string dequotes CTLESCs in the string it's passed, so we
11803 need it to get the space separation right if space isn't the
11804 first character in IFS (but is present) and to remove the
11805 quoting we added back in param_expand(). */
11806 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
11807 /* This isn't exactly right in the case where we're expanding
11808 the RHS of an expansion like ${var-$@} where IFS=: (for
11809 example). The W_NOSPLIT2 means we do the separation with :;
11810 the list_string removes the quotes and breaks the string into
11811 a list, and the string_list rejoins it on spaces. When we
11812 return, we expect to be able to split the results, but the
11813 space separation means the right split doesn't happen. */
11814 tword
->word
= string_list (list
);
11817 tword
->word
= istring
;
11818 if (had_quoted_null
&& QUOTED_NULL (istring
))
11819 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11820 if (tword
->word
!= istring
)
11822 istring
= 0; /* avoid later free() */
11823 goto set_word_flags
;
11825 else if (has_dollar_at
&& ifs_chars
)
11826 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
11829 tword
= alloc_word_desc ();
11830 if (expanded_something
&& *expanded_something
== 0 && has_quoted_ifs
)
11831 tword
->word
= remove_quoted_ifs (istring
);
11833 tword
->word
= istring
;
11834 if (had_quoted_null
&& QUOTED_NULL (istring
)) /* should check for more than one */
11835 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11836 else if (had_quoted_null
)
11837 tword
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
11838 if (tword
->word
!= istring
)
11840 istring
= 0; /* avoid later free() */
11842 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || (quoted_state
== WHOLLY_QUOTED
))
11843 tword
->flags
|= W_QUOTED
;
11844 if (word
->flags
& W_ASSIGNMENT
)
11845 tword
->flags
|= W_ASSIGNMENT
;
11846 if (word
->flags
& W_COMPASSIGN
)
11847 tword
->flags
|= W_COMPASSIGN
;
11848 if (word
->flags
& W_NOGLOB
)
11849 tword
->flags
|= W_NOGLOB
;
11850 if (word
->flags
& W_NOBRACE
)
11851 tword
->flags
|= W_NOBRACE
;
11852 if (word
->flags
& W_ARRAYREF
)
11853 tword
->flags
|= W_ARRAYREF
;
11854 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11862 /* **************************************************************** */
11864 /* Functions for Quote Removal */
11866 /* **************************************************************** */
11868 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
11869 backslash quoting rules for within double quotes or a here document. */
11871 string_quote_removal (string
, quoted
)
11876 char *r
, *result_string
, *temp
, *send
;
11877 int sindex
, tindex
, dquote
;
11881 /* The result can be no longer than the original string. */
11882 slen
= strlen (string
);
11883 send
= string
+ slen
;
11885 r
= result_string
= (char *)xmalloc (slen
+ 1);
11887 for (dquote
= sindex
= 0; c
= string
[sindex
];)
11892 c
= string
[++sindex
];
11898 if (((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
) && (sh_syntaxtab
[c
] & CBSDQUOTE
) == 0)
11903 SCOPY_CHAR_M (r
, string
, send
, sindex
);
11907 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
)
11913 tindex
= sindex
+ 1;
11914 temp
= string_extract_single_quoted (string
, &tindex
, 0);
11925 dquote
= 1 - dquote
;
11931 return (result_string
);
11936 /* Perform quote removal on word WORD. This allocates and returns a new
11939 word_quote_removal (word
, quoted
)
11946 t
= string_quote_removal (word
->word
, quoted
);
11947 w
= alloc_word_desc ();
11948 w
->word
= t
? t
: savestring ("");
11952 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
11953 the members of the list are treated as if they are surrounded by
11954 double quotes. Return a new list, or NULL if LIST is NULL. */
11956 word_list_quote_removal (list
, quoted
)
11960 WORD_LIST
*result
, *t
, *tresult
, *e
;
11962 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
11964 tresult
= make_word_list (word_quote_removal (t
->word
, quoted
), (WORD_LIST
*)NULL
);
11966 result
= (WORD_LIST
*) list_append (result
, tresult
);
11969 result
= e
= tresult
;
11982 /*******************************************
11984 * Functions to perform word splitting *
11986 *******************************************/
11996 ifs_value
= (v
&& value_cell (v
)) ? value_cell (v
) : " \t\n";
11998 ifs_is_set
= ifs_var
!= 0;
11999 ifs_is_null
= ifs_is_set
&& (*ifs_value
== 0);
12001 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
12002 handle multibyte chars in IFS */
12003 memset (ifs_cmap
, '\0', sizeof (ifs_cmap
));
12004 for (t
= ifs_value
; t
&& *t
; t
++)
12010 #if defined (HANDLE_MULTIBYTE)
12011 if (ifs_value
== 0)
12013 ifs_firstc
[0] = '\0'; /* XXX - ? */
12014 ifs_firstc_len
= 1;
12018 if (locale_utf8locale
&& UTF8_SINGLEBYTE (*ifs_value
))
12019 ifs_firstc_len
= (*ifs_value
!= 0) ? 1 : 0;
12023 ifs_len
= strnlen (ifs_value
, MB_CUR_MAX
);
12024 ifs_firstc_len
= MBLEN (ifs_value
, ifs_len
);
12026 if (ifs_firstc_len
== 1 || ifs_firstc_len
== 0 || MB_INVALIDCH (ifs_firstc_len
))
12028 ifs_firstc
[0] = ifs_value
[0];
12029 ifs_firstc
[1] = '\0';
12030 ifs_firstc_len
= 1;
12033 memcpy (ifs_firstc
, ifs_value
, ifs_firstc_len
);
12036 ifs_firstc
= ifs_value
? *ifs_value
: 0;
12046 /* This splits a single word into a WORD LIST on $IFS, but only if the word
12047 is not quoted. list_string () performs quote removal for us, even if we
12048 don't do any splitting. */
12050 word_split (w
, ifs_chars
)
12060 xifs
= ((w
->flags
& W_QUOTED
) || ifs_chars
== 0) ? "" : ifs_chars
;
12061 result
= list_string (w
->word
, xifs
, w
->flags
& W_QUOTED
);
12064 result
= (WORD_LIST
*)NULL
;
12069 /* Perform word splitting on LIST and return the RESULT. It is possible
12070 to return (WORD_LIST *)NULL. */
12072 word_list_split (list
)
12075 WORD_LIST
*result
, *t
, *tresult
, *e
;
12078 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
12080 tresult
= word_split (t
->word
, ifs_value
);
12081 /* POSIX 2.6: "If the complete expansion appropriate for a word results
12082 in an empty field, that empty field shall be deleted from the list
12083 of fields that form the completely expanded command, unless the
12084 original word contained single-quote or double-quote characters."
12085 This is where we handle these words that contain quoted null strings
12086 and other characters that expand to nothing after word splitting. */
12087 if (tresult
== 0 && t
->word
&& (t
->word
->flags
& W_SAWQUOTEDNULL
)) /* XXX */
12089 w
= alloc_word_desc ();
12090 w
->word
= (char *)xmalloc (1);
12092 tresult
= make_word_list (w
, (WORD_LIST
*)NULL
);
12094 #if defined (ARRAY_VARS)
12095 /* pass W_ARRAYREF through for words that are not split and are
12096 identical to the original word. */
12097 if (tresult
&& tresult
->next
== 0 && t
->next
== 0 && (t
->word
->flags
& W_ARRAYREF
) && STREQ (t
->word
->word
, tresult
->word
->word
))
12098 tresult
->word
->flags
|= W_ARRAYREF
;
12101 result
= e
= tresult
;
12112 /**************************************************
12114 * Functions to expand an entire WORD_LIST *
12116 **************************************************/
12118 /* Do any word-expansion-specific cleanup and jump to top_level */
12120 exp_jump_to_top_level (v
)
12123 set_pipestatus_from_exit (last_command_exit_value
);
12125 /* Cleanup code goes here. */
12126 expand_no_split_dollar_star
= 0; /* XXX */
12127 if (expanding_redir
)
12128 undo_partial_redirects ();
12129 expanding_redir
= 0;
12130 assigning_in_environment
= 0;
12132 if (parse_and_execute_level
== 0)
12133 top_level_cleanup (); /* from sig.c */
12135 jump_to_top_level (v
);
12138 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
12139 ELIST, and set ELIST to the new list. */
12140 #define PREPEND_LIST(nlist, elist) \
12141 do { nlist->next = elist; elist = nlist; } while (0)
12143 /* Separate out any initial variable assignments from TLIST. If set -k has
12144 been executed, remove all assignment statements from TLIST. Initial
12145 variable assignments and other environment assignments are placed
12146 on SUBST_ASSIGN_VARLIST. */
12148 separate_out_assignments (tlist
)
12151 register WORD_LIST
*vp
, *lp
;
12154 return ((WORD_LIST
*)NULL
);
12156 if (subst_assign_varlist
)
12157 dispose_words (subst_assign_varlist
); /* Clean up after previous error */
12159 subst_assign_varlist
= (WORD_LIST
*)NULL
;
12162 /* Separate out variable assignments at the start of the command.
12163 Loop invariant: vp->next == lp
12164 Loop postcondition:
12165 lp = list of words left after assignment statements skipped
12166 tlist = original list of words
12168 while (lp
&& (lp
->word
->flags
& W_ASSIGNMENT
))
12174 /* If lp != tlist, we have some initial assignment statements.
12175 We make SUBST_ASSIGN_VARLIST point to the list of assignment
12176 words and TLIST point to the remaining words. */
12179 subst_assign_varlist
= tlist
;
12180 /* ASSERT(vp->next == lp); */
12181 vp
->next
= (WORD_LIST
*)NULL
; /* terminate variable list */
12182 tlist
= lp
; /* remainder of word list */
12185 /* vp == end of variable list */
12186 /* tlist == remainder of original word list without variable assignments */
12188 /* All the words in tlist were assignment statements */
12189 return ((WORD_LIST
*)NULL
);
12191 /* ASSERT(tlist != NULL); */
12192 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
12194 /* If the -k option is in effect, we need to go through the remaining
12195 words, separate out the assignment words, and place them on
12196 SUBST_ASSIGN_VARLIST. */
12197 if (place_keywords_in_env
)
12199 WORD_LIST
*tp
; /* tp == running pointer into tlist */
12204 /* Loop Invariant: tp->next == lp */
12205 /* Loop postcondition: tlist == word list without assignment statements */
12208 if (lp
->word
->flags
& W_ASSIGNMENT
)
12210 /* Found an assignment statement, add this word to end of
12211 subst_assign_varlist (vp). */
12212 if (!subst_assign_varlist
)
12213 subst_assign_varlist
= vp
= lp
;
12220 /* Remove the word pointed to by LP from TLIST. */
12221 tp
->next
= lp
->next
;
12222 /* ASSERT(vp == lp); */
12223 lp
->next
= (WORD_LIST
*)NULL
;
12236 #define WEXP_VARASSIGN 0x001
12237 #define WEXP_BRACEEXP 0x002
12238 #define WEXP_TILDEEXP 0x004
12239 #define WEXP_PARAMEXP 0x008
12240 #define WEXP_PATHEXP 0x010
12242 /* All of the expansions, including variable assignments at the start of
12244 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
12246 /* All of the expansions except variable assignments at the start of
12248 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
12250 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
12251 expansion, command substitution, arithmetic expansion, word splitting, and
12253 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
12255 /* Take the list of words in LIST and do the various substitutions. Return
12256 a new list of words which is the expanded list, and without things like
12257 variable assignments. */
12260 expand_words (list
)
12263 return (expand_word_list_internal (list
, WEXP_ALL
));
12266 /* Same as expand_words (), but doesn't hack variable or environment
12269 expand_words_no_vars (list
)
12272 return (expand_word_list_internal (list
, WEXP_NOVARS
));
12276 expand_words_shellexp (list
)
12279 return (expand_word_list_internal (list
, WEXP_SHELLEXP
));
12283 glob_expand_word_list (tlist
, eflags
)
12287 char **glob_array
, *temp_string
;
12288 register int glob_index
;
12289 WORD_LIST
*glob_list
, *output_list
, *disposables
, *next
;
12293 output_list
= disposables
= (WORD_LIST
*)NULL
;
12294 glob_array
= (char **)NULL
;
12297 /* For each word, either globbing is attempted or the word is
12298 added to orig_list. If globbing succeeds, the results are
12299 added to orig_list and the word (tlist) is added to the list
12300 of disposable words. If globbing fails and failed glob
12301 expansions are left unchanged (the shell default), the
12302 original word is added to orig_list. If globbing fails and
12303 failed glob expansions are removed, the original word is
12304 added to the list of disposable words. orig_list ends up
12305 in reverse order and requires a call to REVERSE_LIST to
12306 be set right. After all words are examined, the disposable
12307 words are freed. */
12308 next
= tlist
->next
;
12310 /* If the word isn't an assignment and contains an unquoted
12311 pattern matching character, then glob it. */
12312 if ((tlist
->word
->flags
& W_NOGLOB
) == 0 &&
12313 unquoted_glob_pattern_p (tlist
->word
->word
))
12315 glob_array
= shell_glob_filename (tlist
->word
->word
, QGLOB_CTLESC
); /* XXX */
12317 /* Handle error cases.
12318 I don't think we should report errors like "No such file
12319 or directory". However, I would like to report errors
12320 like "Read failed". */
12322 if (glob_array
== 0 || GLOB_FAILED (glob_array
))
12324 glob_array
= (char **)xmalloc (sizeof (char *));
12325 glob_array
[0] = (char *)NULL
;
12328 /* Dequote the current word in case we have to use it. */
12329 if (glob_array
[0] == NULL
)
12331 temp_string
= dequote_string (tlist
->word
->word
);
12332 free (tlist
->word
->word
);
12333 tlist
->word
->word
= temp_string
;
12336 /* Make the array into a word list. */
12337 glob_list
= (WORD_LIST
*)NULL
;
12338 for (glob_index
= 0; glob_array
[glob_index
]; glob_index
++)
12340 tword
= make_bare_word (glob_array
[glob_index
]);
12341 glob_list
= make_word_list (tword
, glob_list
);
12346 output_list
= (WORD_LIST
*)list_append (glob_list
, output_list
);
12347 PREPEND_LIST (tlist
, disposables
);
12349 else if (fail_glob_expansion
!= 0)
12351 last_command_exit_value
= EXECUTION_FAILURE
;
12352 report_error (_("no match: %s"), tlist
->word
->word
);
12353 exp_jump_to_top_level (DISCARD
);
12355 else if (allow_null_glob_expansion
== 0)
12357 /* Failed glob expressions are left unchanged. */
12358 PREPEND_LIST (tlist
, output_list
);
12362 /* Failed glob expressions are removed. */
12363 PREPEND_LIST (tlist
, disposables
);
12368 /* Dequote the string. */
12369 temp_string
= dequote_string (tlist
->word
->word
);
12370 free (tlist
->word
->word
);
12371 tlist
->word
->word
= temp_string
;
12372 PREPEND_LIST (tlist
, output_list
);
12375 strvec_dispose (glob_array
);
12376 glob_array
= (char **)NULL
;
12382 dispose_words (disposables
);
12385 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
12387 return (output_list
);
12390 #if defined (BRACE_EXPANSION)
12392 brace_expand_word_list (tlist
, eflags
)
12396 register char **expansions
;
12398 WORD_LIST
*disposables
, *output_list
, *next
;
12402 for (disposables
= output_list
= (WORD_LIST
*)NULL
; tlist
; tlist
= next
)
12404 next
= tlist
->next
;
12406 if (tlist
->word
->flags
& W_NOBRACE
)
12408 /*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
12409 PREPEND_LIST (tlist
, output_list
);
12413 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
12415 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
12416 PREPEND_LIST (tlist
, output_list
);
12420 /* Only do brace expansion if the word has a brace character. If
12421 not, just add the word list element to BRACES and continue. In
12422 the common case, at least when running shell scripts, this will
12423 degenerate to a bunch of calls to `mbschr', and then what is
12424 basically a reversal of TLIST into BRACES, which is corrected
12425 by a call to REVERSE_LIST () on BRACES when the end of TLIST
12427 if (mbschr (tlist
->word
->word
, LBRACE
))
12429 expansions
= brace_expand (tlist
->word
->word
);
12431 for (eindex
= 0; temp_string
= expansions
[eindex
]; eindex
++)
12433 w
= alloc_word_desc ();
12434 w
->word
= temp_string
;
12436 /* If brace expansion didn't change the word, preserve
12437 the flags. We may want to preserve the flags
12438 unconditionally someday -- XXX */
12439 if (STREQ (temp_string
, tlist
->word
->word
))
12440 w
->flags
= tlist
->word
->flags
;
12442 w
= make_word_flags (w
, temp_string
);
12444 output_list
= make_word_list (w
, output_list
);
12448 /* Add TLIST to the list of words to be freed after brace
12449 expansion has been performed. */
12450 PREPEND_LIST (tlist
, disposables
);
12453 PREPEND_LIST (tlist
, output_list
);
12457 dispose_words (disposables
);
12460 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
12462 return (output_list
);
12466 #if defined (ARRAY_VARS)
12467 /* Take WORD, a compound array assignment, and internally run (for example),
12468 'declare -A w', where W is the variable name portion of WORD. OPTION is
12469 the list of options to supply to `declare'. CMD is the declaration command
12470 we are expanding right now; it's unused currently. */
12472 make_internal_declare (word
, option
, cmd
)
12481 w
= make_word (word
);
12483 t
= assignment (w
->word
, 0);
12484 if (w
->word
[t
] == '=')
12487 if (w
->word
[t
- 1] == '+') /* cut off any append op */
12488 w
->word
[t
- 1] = '\0';
12491 wl
= make_word_list (w
, (WORD_LIST
*)NULL
);
12492 wl
= make_word_list (make_word (option
), wl
);
12494 r
= declare_builtin (wl
);
12496 dispose_words (wl
);
12500 /* Expand VALUE in NAME[+]=( VALUE ) to a list of words. FLAGS is 1 if NAME
12501 is an associative array.
12503 If we are processing an indexed array, expand_compound_array_assignment
12504 will expand all the individual words and quote_compound_array_list will
12505 single-quote them. If we are processing an associative array, we use
12506 parse_string_to_word_list to split VALUE into a list of words instead of
12507 faking up a shell variable and calling expand_compound_array_assignment.
12508 expand_and_quote_assoc_word expands and single-quotes each word in VALUE
12509 together so we don't have problems finding the end of the subscript when
12512 Words in VALUE can be individual words, which are expanded and single-quoted,
12513 or words of the form [IND]=VALUE, which end up as explained below, as
12514 ['expanded-ind']='expanded-value'. */
12517 expand_oneword (value
, flags
)
12527 /* Indexed array */
12528 l
= expand_compound_array_assignment ((SHELL_VAR
*)NULL
, value
, flags
);
12529 /* Now we quote the results of the expansion above to prevent double
12531 quote_compound_array_list (l
, flags
);
12536 /* Associative array */
12537 l
= parse_string_to_word_list (value
, 1, "array assign");
12538 #if ASSOC_KVPAIR_ASSIGNMENT
12539 kvpair
= kvpair_assignment_p (l
);
12542 /* For associative arrays, with their arbitrary subscripts, we have to
12543 expand and quote in one step so we don't have to search for the
12544 closing right bracket more than once. */
12545 for (nl
= l
; nl
; nl
= nl
->next
)
12547 #if ASSOC_KVPAIR_ASSIGNMENT
12549 /* keys and values undergo the same set of expansions */
12550 t
= expand_and_quote_kvpair_word (nl
->word
->word
);
12553 if ((nl
->word
->flags
& W_ASSIGNMENT
) == 0)
12554 t
= sh_single_quote (nl
->word
->word
? nl
->word
->word
: "");
12556 t
= expand_and_quote_assoc_word (nl
->word
->word
, flags
);
12557 free (nl
->word
->word
);
12558 nl
->word
->word
= t
;
12564 /* Expand a single compound assignment argument to a declaration builtin.
12565 This word takes the form NAME[+]=( VALUE ). The NAME[+]= is passed through
12566 unchanged. The VALUE is expanded and each word in the result is single-
12567 quoted. Words of the form [key]=value end up as
12568 ['expanded-key']='expanded-value'. Associative arrays have special
12569 handling, see expand_oneword() above. The return value is
12570 NAME[+]=( expanded-and-quoted-VALUE ). */
12572 expand_compound_assignment_word (tlist
, flags
)
12578 char *value
, *temp
;
12580 /*itrace("expand_compound_assignment_word: original word = -%s-", tlist->word->word);*/
12581 t
= assignment (tlist
->word
->word
, 0);
12583 /* value doesn't have the open and close parens */
12585 value
= extract_array_assignment_list (tlist
->word
->word
+ t
+ 1, &oind
);
12586 /* This performs one round of expansion on the index/key and value and
12587 single-quotes each word in the result. */
12588 l
= expand_oneword (value
, flags
);
12591 value
= string_list (l
);
12594 wlen
= STRLEN (value
);
12596 /* Now, let's rebuild the string */
12597 temp
= xmalloc (t
+ 3 + wlen
+ 1); /* name[+]=(value) */
12598 memcpy (temp
, tlist
->word
->word
, ++t
);
12601 memcpy (temp
+ t
, value
, wlen
);
12605 /*itrace("expand_compound_assignment_word: reconstructed word = -%s-", temp);*/
12607 free (tlist
->word
->word
);
12608 tlist
->word
->word
= temp
;
12613 /* Expand and process an argument to a declaration command. We have already
12614 set flags in TLIST->word->flags depending on the declaration command
12615 (declare, local, etc.) and the options supplied to it (-a, -A, etc.).
12616 TLIST->word->word is of the form NAME[+]=( VALUE ).
12618 This does several things, all using pieces of other functions to get the
12619 evaluation sequence right. It's called for compound array assignments with
12620 the W_ASSIGNMENT flag set (basically, valid identifier names on the lhs).
12621 It parses out which flags need to be set for declare to create the variable
12622 correctly, then calls declare internally (make_internal_declare) to make
12623 sure the variable exists with the correct attributes. Before the variable
12624 is created, it calls expand_compound_assignment_word to expand VALUE to a
12625 list of words, appropriately quoted for further evaluation. This preserves
12626 the semantics of word-expansion-before-calling-builtins. Finally, it calls
12627 do_word_assignment to perform the expansion and assignment with the same
12628 expansion semantics as a standalone assignment statement (no word splitting,
12629 etc.) even though the word is single-quoted so all that needs to happen is
12632 expand_declaration_argument (tlist
, wcmd
)
12633 WORD_LIST
*tlist
, *wcmd
;
12635 char opts
[16], omap
[128];
12636 int t
, opti
, oind
, skip
, inheriting
;
12639 inheriting
= localvar_inherit
;
12641 if (tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
|W_CHKLOCAL
|W_ASSIGNARRAY
))
12642 opts
[opti
++] = '-';
12644 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
)) == (W_ASSIGNASSOC
|W_ASSNGLOBAL
))
12646 opts
[opti
++] = 'g';
12647 opts
[opti
++] = 'A';
12649 else if (tlist
->word
->flags
& W_ASSIGNASSOC
)
12651 opts
[opti
++] = 'A';
12653 else if ((tlist
->word
->flags
& (W_ASSIGNARRAY
|W_ASSNGLOBAL
)) == (W_ASSIGNARRAY
|W_ASSNGLOBAL
))
12655 opts
[opti
++] = 'g';
12656 opts
[opti
++] = 'a';
12658 else if (tlist
->word
->flags
& W_ASSIGNARRAY
)
12660 opts
[opti
++] = 'a';
12662 else if (tlist
->word
->flags
& W_ASSNGLOBAL
)
12663 opts
[opti
++] = 'g';
12665 if (tlist
->word
->flags
& W_CHKLOCAL
)
12666 opts
[opti
++] = 'G';
12668 /* If we have special handling note the integer attribute and others
12669 that transform the value upon assignment. What we do is take all
12670 of the option arguments and scan through them looking for options
12671 that cause such transformations, and add them to the `opts' array. */
12673 memset (omap
, '\0', sizeof (omap
));
12674 for (l
= wcmd
->next
; l
!= tlist
; l
= l
->next
)
12678 if (l
->word
->word
[0] != '-' && l
->word
->word
[0] != '+')
12679 break; /* non-option argument */
12680 if (l
->word
->word
[0] == '-' && l
->word
->word
[1] == '-' && l
->word
->word
[2] == 0)
12681 break; /* -- signals end of options */
12682 optchar
= l
->word
->word
[0];
12683 for (oind
= 1; l
->word
->word
[oind
]; oind
++)
12684 switch (l
->word
->word
[oind
])
12692 omap
[l
->word
->word
[oind
]] = 1;
12694 opts
[opti
++] = optchar
;
12701 for (oind
= 0; oind
< sizeof (omap
); oind
++)
12703 opts
[opti
++] = oind
;
12705 /* If there are no -a/-A options, but we have a compound assignment,
12706 we have a choice: we can set opts[0]='-', opts[1]='a', since the
12707 default is to create an indexed array, and call
12708 make_internal_declare with that, or we can just skip the -a and let
12709 declare_builtin deal with it. Once we're here, we're better set
12710 up for the latter, since we don't want to deal with looking up
12711 any existing variable here -- better to let declare_builtin do it.
12712 We need the variable created, though, especially if it's local, so
12713 we get the scoping right before we call do_word_assignment.
12714 To ensure that make_local_declare gets called, we add `--' if there
12715 aren't any options. */
12716 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSIGNARRAY
)) == 0)
12720 opts
[opti
++] = '-';
12721 opts
[opti
++] = '-';
12726 /* This isn't perfect, but it's a start. Improvements later. We expand
12727 tlist->word->word and single-quote the results to avoid multiple
12728 expansions by, say, do_assignment_internal(). We have to weigh the
12729 cost of reconstructing the compound assignment string with its single
12730 quoting and letting the declare builtin handle it. The single quotes
12731 will prevent any unwanted additional expansion or word splitting. */
12732 expand_compound_assignment_word (tlist
, (tlist
->word
->flags
& W_ASSIGNASSOC
) ? 1 : 0);
12737 t
= make_internal_declare (tlist
->word
->word
, opts
, wcmd
? wcmd
->word
->word
: (char *)0);
12738 if (t
!= EXECUTION_SUCCESS
)
12740 last_command_exit_value
= t
;
12741 if (tlist
->word
->flags
& W_FORCELOCAL
) /* non-fatal error */
12744 exp_jump_to_top_level (DISCARD
);
12750 t
= do_word_assignment (tlist
->word
, 0);
12753 last_command_exit_value
= EXECUTION_FAILURE
;
12754 exp_jump_to_top_level (DISCARD
);
12758 /* Now transform the word as ksh93 appears to do and go on */
12759 t
= assignment (tlist
->word
->word
, 0);
12760 tlist
->word
->word
[t
] = '\0';
12761 if (tlist
->word
->word
[t
- 1] == '+')
12762 tlist
->word
->word
[t
- 1] = '\0'; /* cut off append op */
12763 tlist
->word
->flags
&= ~(W_ASSIGNMENT
|W_NOSPLIT
|W_COMPASSIGN
|W_ASSIGNARG
|W_ASSIGNASSOC
|W_ASSIGNARRAY
);
12767 #endif /* ARRAY_VARS */
12770 shell_expand_word_list (tlist
, eflags
)
12774 WORD_LIST
*expanded
, *orig_list
, *new_list
, *next
, *temp_list
, *wcmd
;
12775 int expanded_something
, has_dollar_at
;
12777 /* We do tilde expansion all the time. This is what 1003.2 says. */
12778 wcmd
= new_list
= (WORD_LIST
*)NULL
;
12780 for (orig_list
= tlist
; tlist
; tlist
= next
)
12782 if (wcmd
== 0 && (tlist
->word
->flags
& W_ASSNBLTIN
))
12785 next
= tlist
->next
;
12787 #if defined (ARRAY_VARS)
12788 /* If this is a compound array assignment to a builtin that accepts
12789 such assignments (e.g., `declare'), take the assignment and perform
12790 it separately, handling the semantics of declarations inside shell
12791 functions. This avoids the double-evaluation of such arguments,
12792 because `declare' does some evaluation of compound assignments on
12794 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
12795 expand_declaration_argument (tlist
, wcmd
);
12798 expanded_something
= 0;
12799 expanded
= expand_word_internal
12800 (tlist
->word
, 0, 0, &has_dollar_at
, &expanded_something
);
12802 if (expanded
== &expand_word_error
|| expanded
== &expand_word_fatal
)
12804 /* By convention, each time this error is returned,
12805 tlist->word->word has already been freed. */
12806 tlist
->word
->word
= (char *)NULL
;
12808 /* Dispose our copy of the original list. */
12809 dispose_words (orig_list
);
12810 /* Dispose the new list we're building. */
12811 dispose_words (new_list
);
12813 last_command_exit_value
= EXECUTION_FAILURE
;
12814 if (expanded
== &expand_word_error
)
12815 exp_jump_to_top_level (DISCARD
);
12817 exp_jump_to_top_level (FORCE_EOF
);
12820 /* Don't split words marked W_NOSPLIT. */
12821 if (expanded_something
&& (tlist
->word
->flags
& W_NOSPLIT
) == 0)
12823 temp_list
= word_list_split (expanded
);
12824 dispose_words (expanded
);
12828 /* If no parameter expansion, command substitution, process
12829 substitution, or arithmetic substitution took place, then
12830 do not do word splitting. We still have to remove quoted
12831 null characters from the result. */
12832 word_list_remove_quoted_nulls (expanded
);
12833 temp_list
= expanded
;
12836 expanded
= REVERSE_LIST (temp_list
, WORD_LIST
*);
12837 new_list
= (WORD_LIST
*)list_append (expanded
, new_list
);
12841 dispose_words (orig_list
);
12844 new_list
= REVERSE_LIST (new_list
, WORD_LIST
*);
12849 /* Perform assignment statements optionally preceding a command name COMMAND.
12850 If COMMAND == NULL, is_nullcmd usually == 1. Follow the POSIX rules for
12851 variable assignment errors. */
12853 do_assignment_statements (varlist
, command
, is_nullcmd
)
12854 WORD_LIST
*varlist
;
12858 WORD_LIST
*temp_list
;
12860 sh_wassign_func_t
*assign_func
;
12861 int is_special_builtin
, is_builtin_or_func
, tint
;
12863 /* If the remainder of the words expand to nothing, Posix.2 requires
12864 that the variable and environment assignments affect the shell's
12865 environment (do_word_assignment). */
12866 assign_func
= is_nullcmd
? do_word_assignment
: assign_in_env
;
12867 tempenv_assign_error
= 0;
12869 is_builtin_or_func
= command
&& (find_shell_builtin (command
) || find_function (command
));
12870 /* Posix says that special builtins exit if a variable assignment error
12871 occurs in an assignment preceding it. (XXX - this is old -- current Posix
12872 says that any variable assignment error causes a non-interactive shell
12873 to exit. See the STRICT_POSIX checks below. */
12874 is_special_builtin
= posixly_correct
&& command
&& find_special_builtin (command
);
12876 savecmd
= this_command_name
;
12877 for (temp_list
= varlist
; temp_list
; temp_list
= temp_list
->next
)
12879 this_command_name
= (char *)NULL
;
12880 assigning_in_environment
= is_nullcmd
== 0;
12881 tint
= (*assign_func
) (temp_list
->word
, is_builtin_or_func
);
12882 assigning_in_environment
= 0;
12883 this_command_name
= savecmd
;
12885 /* Variable assignment errors in non-interactive shells running
12886 in posix mode cause the shell to exit. */
12889 if (is_nullcmd
) /* assignment statement */
12891 last_command_exit_value
= EXECUTION_FAILURE
;
12892 #if defined (STRICT_POSIX)
12893 if (posixly_correct
&& interactive_shell
== 0)
12895 if (posixly_correct
&& interactive_shell
== 0 && executing_command_builtin
== 0)
12897 exp_jump_to_top_level (FORCE_EOF
);
12899 exp_jump_to_top_level (DISCARD
);
12901 /* In posix mode, assignment errors in the temporary environment
12902 cause a non-interactive shell executing a special builtin to
12903 exit and a non-interactive shell to otherwise jump back to the
12904 top level. This is what POSIX says to do for variable assignment
12905 errors, and POSIX says errors in assigning to the temporary
12906 environment are treated as variable assignment errors.
12907 (XXX - this is not what current POSIX says - look at the
12908 STRICT_POSIX defines. */
12909 else if (posixly_correct
)
12911 last_command_exit_value
= EXECUTION_FAILURE
;
12912 #if defined (STRICT_POSIX)
12913 exp_jump_to_top_level ((interactive_shell
== 0) ? FORCE_EOF
: DISCARD
);
12915 if (interactive_shell
== 0 && is_special_builtin
)
12916 exp_jump_to_top_level (FORCE_EOF
);
12917 else if (interactive_shell
== 0)
12918 exp_jump_to_top_level (DISCARD
); /* XXX - maybe change later */
12920 exp_jump_to_top_level (DISCARD
);
12924 tempenv_assign_error
++;
12927 return (tempenv_assign_error
);
12930 /* The workhorse for expand_words () and expand_words_no_vars ().
12931 First arg is LIST, a WORD_LIST of words.
12932 Second arg EFLAGS is a flags word controlling which expansions are
12935 This does all of the substitutions: brace expansion, tilde expansion,
12936 parameter expansion, command substitution, arithmetic expansion,
12937 process substitution, word splitting, and pathname expansion, according
12938 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
12939 set, or for which no expansion is done, do not undergo word splitting.
12940 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
12941 with W_NOBRACE set do not undergo brace expansion (see
12942 brace_expand_word_list above). */
12944 expand_word_list_internal (list
, eflags
)
12948 WORD_LIST
*new_list
, *temp_list
;
12950 tempenv_assign_error
= 0;
12952 return ((WORD_LIST
*)NULL
);
12954 garglist
= new_list
= copy_word_list (list
);
12955 if (eflags
& WEXP_VARASSIGN
)
12957 garglist
= new_list
= separate_out_assignments (new_list
);
12960 if (subst_assign_varlist
)
12961 do_assignment_statements (subst_assign_varlist
, (char *)NULL
, 1);
12963 dispose_words (subst_assign_varlist
);
12964 subst_assign_varlist
= (WORD_LIST
*)NULL
;
12966 return ((WORD_LIST
*)NULL
);
12970 /* Begin expanding the words that remain. The expansions take place on
12971 things that aren't really variable assignments. */
12973 #if defined (BRACE_EXPANSION)
12974 /* Do brace expansion on this word if there are any brace characters
12976 if ((eflags
& WEXP_BRACEEXP
) && brace_expansion
&& new_list
)
12977 new_list
= brace_expand_word_list (new_list
, eflags
);
12978 #endif /* BRACE_EXPANSION */
12980 /* Perform the `normal' shell expansions: tilde expansion, parameter and
12981 variable substitution, command substitution, arithmetic expansion,
12982 and word splitting. */
12983 new_list
= shell_expand_word_list (new_list
, eflags
);
12985 /* Okay, we're almost done. Now let's just do some filename
12989 if ((eflags
& WEXP_PATHEXP
) && disallow_filename_globbing
== 0)
12990 /* Glob expand the word list unless globbing has been disabled. */
12991 new_list
= glob_expand_word_list (new_list
, eflags
);
12993 /* Dequote the words, because we're not performing globbing. */
12994 new_list
= dequote_list (new_list
);
12997 if ((eflags
& WEXP_VARASSIGN
) && subst_assign_varlist
)
12999 do_assignment_statements (subst_assign_varlist
, (new_list
&& new_list
->word
) ? new_list
->word
->word
: (char *)NULL
, new_list
== 0);
13001 dispose_words (subst_assign_varlist
);
13002 subst_assign_varlist
= (WORD_LIST
*)NULL
;