1 /* subst.c -- The part of the shell that does parameter, command, arithmetic,
2 and globbing substitutions. */
4 /* ``Have a little faith, there's magic in the night. You ain't a
5 beauty, but, hey, you're alright.'' */
7 /* Copyright (C) 1987-2022 Free Software Foundation, Inc.
9 This file is part of GNU Bash, the Bourne Again SHell.
11 Bash is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 Bash is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with Bash. If not, see <http://www.gnu.org/licenses/>.
27 #include "bashtypes.h"
29 #include "chartypes.h"
30 #if defined (HAVE_PWD_H)
36 #if defined (HAVE_UNISTD_H)
40 #define NEED_FPURGE_DECL
43 #include "posixstat.h"
51 #include "execute_cmd.h"
55 #include "mailcheck.h"
58 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
59 # include <mbstr.h> /* mbschr */
63 #include "builtins/getopt.h"
64 #include "builtins/common.h"
66 #include "builtins/builtext.h"
68 #include <tilde/tilde.h>
69 #include <glob/strmatch.h>
75 /* The size that strings change by. */
76 #define DEFAULT_INITIAL_ARRAY_SIZE 112
77 #define DEFAULT_ARRAY_SIZE 128
83 #define VT_ARRAYMEMBER 3
86 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
88 /* Flags for quoted_strchr */
89 #define ST_BACKSL 0x01
90 #define ST_CTLESC 0x02
91 #define ST_SQUOTE 0x04 /* unused yet */
92 #define ST_DQUOTE 0x08 /* unused yet */
94 /* These defs make it easier to use the editor. */
102 #if defined (HANDLE_MULTIBYTE)
107 #define DOLLAR_AT_STAR(c) ((c) == '@' || (c) == '*')
108 #define STR_DOLLAR_AT_STAR(s) (DOLLAR_AT_STAR ((s)[0]) && (s)[1] == '\0')
110 /* Evaluates to 1 if C is one of the shell's special parameters whose length
111 can be taken, but is also one of the special expansion characters. */
112 #define VALID_SPECIAL_LENGTH_PARAM(c) \
113 ((c) == '-' || (c) == '?' || (c) == '#' || (c) == '@')
115 /* Evaluates to 1 if C is one of the shell's special parameters for which an
116 indirect variable reference may be made. */
117 #define VALID_INDIR_PARAM(c) \
118 ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
120 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
121 in ${parameter[:]OPword}. */
122 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
124 /* Evaluates to 1 if this is one of the shell's special variables. */
125 #define SPECIAL_VAR(name, wi) \
126 (*name && ((DIGIT (*name) && all_digits (name)) || \
127 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
128 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1]))))
130 /* This can be used by all of the *_extract_* functions that have a similar
131 structure. It can't just be wrapped in a do...while(0) loop because of
132 the embedded `break'. The dangling else accommodates a trailing semicolon;
133 we could also put in a do ; while (0) */
135 #define CHECK_STRING_OVERRUN(oind, ind, len, ch) \
144 /* An expansion function that takes a string and a quoted flag and returns
145 a WORD_LIST *. Used as the type of the third argument to
146 expand_string_if_necessary(). */
147 typedef WORD_LIST
*EXPFUNC
PARAMS((char *, int));
149 /* Process ID of the last command executed within command substitution. */
150 pid_t last_command_subst_pid
= NO_PID
;
151 pid_t current_command_subst_pid
= NO_PID
;
153 /* Variables used to keep track of the characters in IFS. */
156 unsigned char ifs_cmap
[UCHAR_MAX
+ 1];
157 int ifs_is_set
, ifs_is_null
;
159 #if defined (HANDLE_MULTIBYTE)
160 unsigned char ifs_firstc
[MB_LEN_MAX
];
161 size_t ifs_firstc_len
;
163 unsigned char ifs_firstc
;
166 /* If non-zero, command substitution inherits the value of errexit option */
167 int inherit_errexit
= 0;
169 /* Sentinel to tell when we are performing variable assignments preceding a
170 command name and putting them into the environment. Used to make sure
171 we use the temporary environment when looking up variable values. */
172 int assigning_in_environment
;
174 /* Used to hold a list of variable assignments preceding a command. Global
175 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
176 SIGCHLD trap and so it can be saved and restored by the trap handlers. */
177 WORD_LIST
*subst_assign_varlist
= (WORD_LIST
*)NULL
;
179 /* Tell the expansion functions to not longjmp back to top_level on fatal
180 errors. Enabled when doing completion and prompt string expansion. */
181 int no_longjmp_on_fatal_error
= 0;
183 /* Non-zero means to allow unmatched globbed filenames to expand to
185 int allow_null_glob_expansion
;
187 /* Non-zero means to throw an error when globbing fails to match anything. */
188 int fail_glob_expansion
;
190 /* If non-zero, perform `&' substitution on the replacement string in the
191 pattern substitution word expansion. */
192 int patsub_replacement
= 1;
194 /* Extern functions and variables from different files. */
195 extern struct fd_bitmap
*current_fds_to_close
;
196 extern int wordexp_only
;
197 extern int singlequote_translations
;
198 extern int extended_quote
;
200 #if defined (JOB_CONTROL) && defined (PROCESS_SUBSTITUTION)
201 extern PROCESS
*last_procsub_child
;
204 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
205 extern wchar_t *wcsdup
PARAMS((const wchar_t *));
209 /* Variables to keep track of which words in an expanded word list (the
210 output of expand_word_list_internal) are the result of globbing
211 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
212 (CURRENTLY UNUSED). */
213 char *glob_argv_flags
;
214 static int glob_argv_flags_size
;
217 static WORD_LIST
*cached_quoted_dollar_at
= 0;
219 /* Distinguished error values to return from expansion functions */
220 static WORD_LIST expand_word_error
, expand_word_fatal
;
221 static WORD_DESC expand_wdesc_error
, expand_wdesc_fatal
;
222 static char expand_param_error
, expand_param_fatal
, expand_param_unset
;
223 static char extract_string_error
, extract_string_fatal
;
225 /* Set by expand_word_unsplit and several of the expand_string_XXX functions;
226 used to inhibit splitting and re-joining $* on $IFS, primarily when doing
227 assignment statements. The idea is that if we're in a context where this
228 is set, we're not going to be performing word splitting, so we use the same
229 rules to expand $* as we would if it appeared within double quotes. */
230 static int expand_no_split_dollar_star
= 0;
232 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
233 without any leading variable assignments. */
234 static WORD_LIST
*garglist
= (WORD_LIST
*)NULL
;
236 static char *quoted_substring
PARAMS((char *, int, int));
237 static int quoted_strlen
PARAMS((char *));
238 static char *quoted_strchr
PARAMS((char *, int, int));
240 static char *expand_string_if_necessary
PARAMS((char *, int, EXPFUNC
*));
241 static inline char *expand_string_to_string_internal
PARAMS((char *, int, EXPFUNC
*));
242 static WORD_LIST
*call_expand_word_internal
PARAMS((WORD_DESC
*, int, int, int *, int *));
243 static WORD_LIST
*expand_string_internal
PARAMS((char *, int));
244 static WORD_LIST
*expand_string_leave_quoted
PARAMS((char *, int));
245 static WORD_LIST
*expand_string_for_rhs
PARAMS((char *, int, int, int, int *, int *));
246 static WORD_LIST
*expand_string_for_pat
PARAMS((char *, int, int *, int *));
248 static char *quote_escapes_internal
PARAMS((const char *, int));
250 static WORD_LIST
*list_quote_escapes
PARAMS((WORD_LIST
*));
251 static WORD_LIST
*list_dequote_escapes
PARAMS((WORD_LIST
*));
253 static char *make_quoted_char
PARAMS((int));
254 static WORD_LIST
*quote_list
PARAMS((WORD_LIST
*));
256 static int unquoted_substring
PARAMS((char *, char *));
257 static int unquoted_member
PARAMS((int, char *));
259 #if defined (ARRAY_VARS)
260 static SHELL_VAR
*do_compound_assignment
PARAMS((char *, char *, int));
262 static int do_assignment_internal
PARAMS((const WORD_DESC
*, int));
264 static char *string_extract_verbatim
PARAMS((char *, size_t, int *, char *, int));
265 static char *string_extract
PARAMS((char *, int *, char *, int));
266 static char *string_extract_double_quoted
PARAMS((char *, int *, int));
267 static inline char *string_extract_single_quoted
PARAMS((char *, int *, int));
268 static inline int skip_single_quoted
PARAMS((const char *, size_t, int, int));
269 static int skip_double_quoted
PARAMS((char *, size_t, int, int));
270 static char *extract_delimited_string
PARAMS((char *, int *, char *, char *, char *, int));
271 static char *extract_heredoc_dolbrace_string
PARAMS((char *, int *, int, int));
272 static char *extract_dollar_brace_string
PARAMS((char *, int *, int, int));
273 static int skip_matched_pair
PARAMS((const char *, int, int, int, int));
275 static char *pos_params
PARAMS((char *, int, int, int, int));
277 static unsigned char *mb_getcharlens
PARAMS((char *, int));
279 static char *remove_upattern
PARAMS((char *, char *, int));
280 #if defined (HANDLE_MULTIBYTE)
281 static wchar_t *remove_wpattern
PARAMS((wchar_t *, size_t, wchar_t *, int));
283 static char *remove_pattern
PARAMS((char *, char *, int));
285 static int match_upattern
PARAMS((char *, char *, int, char **, char **));
286 #if defined (HANDLE_MULTIBYTE)
287 static int match_wpattern
PARAMS((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
289 static int match_pattern
PARAMS((char *, char *, int, char **, char **));
290 static int getpatspec
PARAMS((int, char *));
291 static char *getpattern
PARAMS((char *, int, int));
292 static char *variable_remove_pattern
PARAMS((char *, char *, int, int));
293 static char *list_remove_pattern
PARAMS((WORD_LIST
*, char *, int, int, int));
294 static char *parameter_list_remove_pattern
PARAMS((int, char *, int, int));
296 static char *array_remove_pattern
PARAMS((SHELL_VAR
*, char *, int, int, int));
298 static char *parameter_brace_remove_pattern
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int));
300 static char *string_var_assignment
PARAMS((SHELL_VAR
*, char *));
301 #if defined (ARRAY_VARS)
302 static char *array_var_assignment
PARAMS((SHELL_VAR
*, int, int, int));
304 static char *pos_params_assignment
PARAMS((WORD_LIST
*, int, int));
305 static char *string_transform
PARAMS((int, SHELL_VAR
*, char *));
306 static char *list_transform
PARAMS((int, SHELL_VAR
*, WORD_LIST
*, int, int));
307 static char *parameter_list_transform
PARAMS((int, int, int));
308 #if defined ARRAY_VARS
309 static char *array_transform
PARAMS((int, SHELL_VAR
*, int, int));
311 static char *parameter_brace_transform
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int, int));
312 static int valid_parameter_transform
PARAMS((char *));
314 static char *process_substitute
PARAMS((char *, int));
316 static char *optimize_cat_file
PARAMS((REDIRECT
*, int, int, int *));
317 static char *read_comsub
PARAMS((int, int, int, int *));
320 static arrayind_t array_length_reference
PARAMS((char *));
323 static int valid_brace_expansion_word
PARAMS((char *, int));
324 static int chk_atstar
PARAMS((char *, int, int, int *, int *));
325 static int chk_arithsub
PARAMS((const char *, int));
327 static WORD_DESC
*parameter_brace_expand_word
PARAMS((char *, int, int, int, array_eltstate_t
*));
328 static char *parameter_brace_find_indir
PARAMS((char *, int, int, int));
329 static WORD_DESC
*parameter_brace_expand_indir
PARAMS((char *, int, int, int, int *, int *));
330 static WORD_DESC
*parameter_brace_expand_rhs
PARAMS((char *, char *, int, int, int, int *, int *));
331 static void parameter_brace_expand_error
PARAMS((char *, char *, int));
333 static int valid_length_expression
PARAMS((char *));
334 static intmax_t parameter_brace_expand_length
PARAMS((char *));
336 static char *skiparith
PARAMS((char *, int));
337 static int verify_substring_values
PARAMS((SHELL_VAR
*, char *, char *, int, intmax_t *, intmax_t *));
338 static int get_var_and_type
PARAMS((char *, char *, array_eltstate_t
*, int, int, SHELL_VAR
**, char **));
339 static char *mb_substring
PARAMS((char *, int, int));
340 static char *parameter_brace_substring
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int));
342 static int shouldexp_replacement
PARAMS((char *));
344 static char *pos_params_pat_subst
PARAMS((char *, char *, char *, int));
346 static char *expand_string_for_patsub
PARAMS((char *, int));
347 static char *parameter_brace_patsub
PARAMS((char *, char *, array_eltstate_t
*, char *, int, int, int));
349 static char *pos_params_casemod
PARAMS((char *, char *, int, int));
350 static char *parameter_brace_casemod
PARAMS((char *, char *, array_eltstate_t
*, int, char *, int, int, int));
352 static WORD_DESC
*parameter_brace_expand
PARAMS((char *, int *, int, int, int *, int *));
353 static WORD_DESC
*param_expand
PARAMS((char *, int *, int, int *, int *, int *, int *, int));
355 static WORD_LIST
*expand_word_internal
PARAMS((WORD_DESC
*, int, int, int *, int *));
357 static WORD_LIST
*word_list_split
PARAMS((WORD_LIST
*));
359 static void exp_jump_to_top_level
PARAMS((int));
361 static WORD_LIST
*separate_out_assignments
PARAMS((WORD_LIST
*));
362 static WORD_LIST
*glob_expand_word_list
PARAMS((WORD_LIST
*, int));
363 #ifdef BRACE_EXPANSION
364 static WORD_LIST
*brace_expand_word_list
PARAMS((WORD_LIST
*, int));
366 #if defined (ARRAY_VARS)
367 static int make_internal_declare
PARAMS((char *, char *, char *));
368 static void expand_compound_assignment_word
PARAMS((WORD_LIST
*, int));
369 static WORD_LIST
*expand_declaration_argument
PARAMS((WORD_LIST
*, WORD_LIST
*));
371 static WORD_LIST
*shell_expand_word_list
PARAMS((WORD_LIST
*, int));
372 static WORD_LIST
*expand_word_list_internal
PARAMS((WORD_LIST
*, int));
374 static int do_assignment_statements
PARAMS((WORD_LIST
*, char *, int));
376 /* **************************************************************** */
378 /* Utility Functions */
380 /* **************************************************************** */
384 dump_word_flags (flags
)
390 fprintf (stderr
, "%d -> ", f
);
394 fprintf (stderr
, "W_ARRAYIND%s", f
? "|" : "");
396 if (f
& W_ASSIGNASSOC
)
399 fprintf (stderr
, "W_ASSIGNASSOC%s", f
? "|" : "");
401 if (f
& W_ASSIGNARRAY
)
404 fprintf (stderr
, "W_ASSIGNARRAY%s", f
? "|" : "");
406 if (f
& W_SAWQUOTEDNULL
)
408 f
&= ~W_SAWQUOTEDNULL
;
409 fprintf (stderr
, "W_SAWQUOTEDNULL%s", f
? "|" : "");
414 fprintf (stderr
, "W_NOPROCSUB%s", f
? "|" : "");
419 fprintf (stderr
, "W_DQUOTE%s", f
? "|" : "");
421 if (f
& W_HASQUOTEDNULL
)
423 f
&= ~W_HASQUOTEDNULL
;
424 fprintf (stderr
, "W_HASQUOTEDNULL%s", f
? "|" : "");
429 fprintf (stderr
, "W_ASSIGNARG%s", f
? "|" : "");
434 fprintf (stderr
, "W_ASSNBLTIN%s", f
? "|" : "");
436 if (f
& W_ASSNGLOBAL
)
439 fprintf (stderr
, "W_ASSNGLOBAL%s", f
? "|" : "");
441 if (f
& W_COMPASSIGN
)
444 fprintf (stderr
, "W_COMPASSIGN%s", f
? "|" : "");
449 fprintf (stderr
, "W_EXPANDRHS%s", f
? "|" : "");
454 fprintf (stderr
, "W_NOTILDE%s", f
? "|" : "");
459 fprintf (stderr
, "W_ASSIGNRHS%s", f
? "|" : "");
461 if (f
& W_NOASSNTILDE
)
464 fprintf (stderr
, "W_NOASSNTILDE%s", f
? "|" : "");
469 fprintf (stderr
, "W_NOCOMSUB%s", f
? "|" : "");
474 fprintf (stderr
, "W_ARRAYREF%s", f
? "|" : "");
479 fprintf (stderr
, "W_DOLLARAT%s", f
? "|" : "");
484 fprintf (stderr
, "W_TILDEEXP%s", f
? "|" : "");
489 fprintf (stderr
, "W_NOSPLIT2%s", f
? "|" : "");
494 fprintf (stderr
, "W_NOSPLIT%s", f
? "|" : "");
499 fprintf (stderr
, "W_NOBRACE%s", f
? "|" : "");
504 fprintf (stderr
, "W_NOGLOB%s", f
? "|" : "");
506 if (f
& W_SPLITSPACE
)
509 fprintf (stderr
, "W_SPLITSPACE%s", f
? "|" : "");
511 if (f
& W_ASSIGNMENT
)
514 fprintf (stderr
, "W_ASSIGNMENT%s", f
? "|" : "");
519 fprintf (stderr
, "W_QUOTED%s", f
? "|" : "");
524 fprintf (stderr
, "W_HASDOLLAR%s", f
? "|" : "");
529 fprintf (stderr
, "W_COMPLETE%s", f
? "|" : "");
534 fprintf (stderr
, "W_CHKLOCAL%s", f
? "|" : "");
536 if (f
& W_FORCELOCAL
)
539 fprintf (stderr
, "W_FORCELOCAL%s", f
? "|" : "");
542 fprintf (stderr
, "\n");
547 #ifdef INCLUDE_UNUSED
549 quoted_substring (string
, start
, end
)
554 register char *result
, *s
, *r
;
558 /* Move to string[start], skipping quoted characters. */
559 for (s
= string
, l
= 0; *s
&& l
< start
; )
571 r
= result
= (char *)xmalloc (2*len
+ 1); /* save room for quotes */
573 /* Copy LEN characters, including quote characters. */
575 for (l
= 0; l
< len
; s
++)
589 #ifdef INCLUDE_UNUSED
590 /* Return the length of S, skipping over quoted characters */
614 #ifdef INCLUDE_UNUSED
615 /* Find the first occurrence of character C in string S, obeying shell
616 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
617 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
618 escaped with CTLESC are skipped. */
620 quoted_strchr (s
, c
, flags
)
628 if (((flags
& ST_BACKSL
) && *p
== '\\')
629 || ((flags
& ST_CTLESC
) && *p
== CTLESC
))
633 return ((char *)NULL
);
639 return ((char *)NULL
);
642 /* Return 1 if CHARACTER appears in an unquoted portion of
643 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
645 unquoted_member (character
, string
)
653 slen
= strlen (string
);
655 while (c
= string
[sindex
])
663 ADVANCE_CHAR (string
, slen
, sindex
);
669 ADVANCE_CHAR (string
, slen
, sindex
);
673 sindex
= skip_single_quoted (string
, slen
, ++sindex
, 0);
677 sindex
= skip_double_quoted (string
, slen
, ++sindex
, 0);
684 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
686 unquoted_substring (substr
, string
)
687 char *substr
, *string
;
690 int sindex
, c
, sublen
;
693 if (substr
== 0 || *substr
== '\0')
696 slen
= strlen (string
);
697 sublen
= strlen (substr
);
698 for (sindex
= 0; c
= string
[sindex
]; )
700 if (STREQN (string
+ sindex
, substr
, sublen
))
708 ADVANCE_CHAR (string
, slen
, sindex
);
712 sindex
= skip_single_quoted (string
, slen
, ++sindex
, 0);
716 sindex
= skip_double_quoted (string
, slen
, ++sindex
, 0);
720 ADVANCE_CHAR (string
, slen
, sindex
);
728 /* Most of the substitutions must be done in parallel. In order
729 to avoid using tons of unclear goto's, I have some functions
730 for manipulating malloc'ed strings. They all take INDX, a
731 pointer to an integer which is the offset into the string
732 where manipulation is taking place. They also take SIZE, a
733 pointer to an integer which is the current length of the
734 character array for this string. */
736 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
737 of space allocated to TARGET. SOURCE can be NULL, in which
738 case nothing happens. Gets rid of SOURCE by freeing it.
739 Returns TARGET in case the location has changed. */
741 sub_append_string (source
, target
, indx
, size
)
742 char *source
, *target
;
750 srclen
= STRLEN (source
);
751 if (srclen
>= (*size
- *indx
))
754 n
= (n
+ DEFAULT_ARRAY_SIZE
) - (n
% DEFAULT_ARRAY_SIZE
);
755 target
= (char *)xrealloc (target
, (*size
= n
));
758 FASTCOPY (source
, target
+ *indx
, srclen
);
760 target
[*indx
] = '\0';
769 /* Append the textual representation of NUMBER to TARGET.
770 INDX and SIZE are as in SUB_APPEND_STRING. */
772 sub_append_number (number
, target
, indx
, size
)
780 temp
= itos (number
);
781 return (sub_append_string (temp
, target
, indx
, size
));
785 /* Extract a substring from STRING, starting at SINDEX and ending with
786 one of the characters in CHARLIST. Don't make the ending character
787 part of the string. Leave SINDEX pointing at the ending character.
788 Understand about backslashes in the string. If (flags & SX_VARNAME)
789 is non-zero, and array variables have been compiled into the shell,
790 everything between a `[' and a corresponding `]' is skipped over.
791 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
792 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
793 contain a closing character from CHARLIST. */
795 string_extract (string
, sindex
, charlist
, flags
)
807 slen
= (MB_CUR_MAX
> 1) ? strlen (string
+ *sindex
) + *sindex
: 0;
810 while (c
= string
[i
])
819 #if defined (ARRAY_VARS)
820 else if ((flags
& SX_VARNAME
) && c
== LBRACK
)
823 /* If this is an array subscript, skip over it and continue. */
824 ni
= skipsubscript (string
, i
, 0);
825 if (string
[ni
] == RBRACK
)
829 else if (MEMBER (c
, charlist
))
835 ADVANCE_CHAR (string
, slen
, i
);
838 /* If we had to have a matching delimiter and didn't find one, return an
839 error and let the caller deal with it. */
840 if ((flags
& SX_REQMATCH
) && found
== 0)
843 return (&extract_string_error
);
846 temp
= (flags
& SX_NOALLOC
) ? (char *)NULL
: substring (string
, *sindex
, i
);
852 /* Extract the contents of STRING as if it is enclosed in double quotes.
853 SINDEX, when passed in, is the offset of the character immediately
854 following the opening double quote; on exit, SINDEX is left pointing after
855 the closing double quote. If STRIPDQ is non-zero, unquoted double
856 quotes are stripped and the string is terminated by a null byte.
857 Backslashes between the embedded double quotes are processed. If STRIPDQ
858 is zero, an unquoted `"' terminates the string. */
860 string_extract_double_quoted (string
, sindex
, flags
)
868 char *temp
, *ret
; /* The new string we return. */
869 int pass_next
, backquote
, si
; /* State variables for the machine. */
874 slen
= strlen (string
+ *sindex
) + *sindex
;
875 send
= string
+ slen
;
877 stripdq
= (flags
& SX_STRIPDQ
);
879 pass_next
= backquote
= dquote
= 0;
880 temp
= (char *)xmalloc (1 + slen
- *sindex
);
884 while (c
= string
[i
])
886 /* Process a character that was quoted by a backslash. */
889 /* XXX - take another look at this in light of Interp 221 */
892 ``The backslash shall retain its special meaning as an escape
893 character only when followed by one of the characters:
896 If STRIPDQ is zero, we handle the double quotes here and let
897 expand_word_internal handle the rest. If STRIPDQ is non-zero,
898 we have already been through one round of backslash stripping,
899 and want to strip these backslashes only if DQUOTE is non-zero,
900 indicating that we are inside an embedded double-quoted string. */
902 /* If we are in an embedded quoted string, then don't strip
903 backslashes before characters for which the backslash
904 retains its special meaning, but remove backslashes in
905 front of other characters. If we are not in an
906 embedded quoted string, don't strip backslashes at all.
907 This mess is necessary because the string was already
908 surrounded by double quotes (and sh has some really weird
910 The returned string will be run through expansion as if
911 it were double-quoted. */
912 if ((stripdq
== 0 && c
!= '"') ||
913 (stripdq
&& ((dquote
&& (sh_syntaxtab
[c
] & CBSDQUOTE
)) || dquote
== 0)))
918 COPY_CHAR_I (temp
, j
, string
, send
, i
);
922 /* A backslash protects the next character. The code just above
923 handles preserving the backslash in front of any character but
932 /* Inside backquotes, ``the portion of the quoted string from the
933 initial backquote and the characters up to the next backquote
934 that is not preceded by a backslash, having escape characters
935 removed, defines that command''. */
940 temp
[j
++] = c
; /* COPY_CHAR_I? */
953 /* Pass everything between `$(' and the matching `)' or a quoted
954 ${ ... } pair through according to the Posix.2 specification. */
955 if (c
== '$' && ((string
[i
+ 1] == LPAREN
) || (string
[i
+ 1] == LBRACE
)))
960 if (string
[i
+ 1] == LPAREN
)
961 ret
= extract_command_subst (string
, &si
, (flags
& SX_COMPLETE
));
963 ret
= extract_dollar_brace_string (string
, &si
, Q_DOUBLE_QUOTES
, 0);
966 temp
[j
++] = string
[i
+ 1];
968 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
970 if (ret
== 0 && no_longjmp_on_fatal_error
)
973 ret
= string
+ i
+ 2;
976 /* XXX - CHECK_STRING_OVERRUN here? */
977 for (t
= 0; ret
[t
]; t
++, j
++)
979 temp
[j
] = string
[si
];
981 if (si
< i
+ 2) /* we went back? */
996 /* Add any character but a double quote to the quoted string we're
999 goto add_one_character
;
1013 /* Point to after the closing quote. */
1021 /* This should really be another option to string_extract_double_quoted. */
1023 skip_double_quoted (string
, slen
, sind
, flags
)
1031 int pass_next
, backquote
, si
;
1034 pass_next
= backquote
= 0;
1036 while (c
= string
[i
])
1041 ADVANCE_CHAR (string
, slen
, i
);
1054 ADVANCE_CHAR (string
, slen
, i
);
1063 else if (c
== '$' && ((string
[i
+ 1] == LPAREN
) || (string
[i
+ 1] == LBRACE
)))
1066 if (string
[i
+ 1] == LPAREN
)
1067 ret
= extract_command_subst (string
, &si
, SX_NOALLOC
|(flags
&SX_COMPLETE
));
1069 ret
= extract_dollar_brace_string (string
, &si
, Q_DOUBLE_QUOTES
, SX_NOALLOC
);
1071 /* These can consume the entire string if they are unterminated */
1072 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1079 ADVANCE_CHAR (string
, slen
, i
);
1092 /* Extract the contents of STRING as if it is enclosed in single quotes.
1093 SINDEX, when passed in, is the offset of the character immediately
1094 following the opening single quote; on exit, SINDEX is left pointing after
1095 the closing single quote. ALLOWESC allows the single quote to be quoted by
1096 a backslash; it's not used yet. */
1097 static inline char *
1098 string_extract_single_quoted (string
, sindex
, allowesc
)
1109 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
1110 slen
= (MB_CUR_MAX
> 1) ? strlen (string
+ *sindex
) + *sindex
: 0;
1118 ADVANCE_CHAR (string
, slen
, i
);
1121 if (allowesc
&& string
[i
] == '\\')
1123 else if (string
[i
] == '\'')
1125 ADVANCE_CHAR (string
, slen
, i
);
1128 t
= substring (string
, *sindex
, i
);
1137 /* Skip over a single-quoted string. We overload the SX_COMPLETE flag to mean
1138 that we are splitting out words for completion and have encountered a $'...'
1139 string, which allows backslash-escaped single quotes. */
1141 skip_single_quoted (string
, slen
, sind
, flags
)
1151 while (string
[c
] && string
[c
] != '\'')
1153 if ((flags
& SX_COMPLETE
) && string
[c
] == '\\' && string
[c
+1] == '\'' && string
[c
+2])
1154 ADVANCE_CHAR (string
, slen
, c
);
1155 ADVANCE_CHAR (string
, slen
, c
);
1163 /* Just like string_extract, but doesn't hack backslashes or any of
1164 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
1166 string_extract_verbatim (string
, slen
, sindex
, charlist
, flags
)
1174 #if defined (HANDLE_MULTIBYTE)
1181 if ((flags
& SX_NOCTLESC
) && charlist
[0] == '\'' && charlist
[1] == '\0')
1183 temp
= string_extract_single_quoted (string
, sindex
, 0);
1184 --*sindex
; /* leave *sindex at separator character */
1188 /* This can never be called with charlist == NULL. If *charlist == NULL,
1189 we can skip the loop and just return a copy of the string, updating
1193 temp
= string
+ *sindex
;
1194 c
= (*sindex
== 0) ? slen
: STRLEN (temp
);
1195 temp
= savestring (temp
);
1201 #if defined (HANDLE_MULTIBYTE)
1204 while (c
= string
[i
])
1206 #if defined (HANDLE_MULTIBYTE)
1209 if ((flags
& SX_NOCTLESC
) == 0 && c
== CTLESC
)
1212 CHECK_STRING_OVERRUN (i
, i
, slen
, c
);
1215 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
1216 through, to protect the CTLNULs from later calls to
1217 remove_quoted_nulls. */
1218 else if ((flags
& SX_NOESCCTLNUL
) == 0 && c
== CTLESC
&& string
[i
+1] == CTLNUL
)
1221 CHECK_STRING_OVERRUN (i
, i
, slen
, c
);
1225 #if defined (HANDLE_MULTIBYTE)
1226 if (locale_utf8locale
&& slen
> i
&& UTF8_SINGLEBYTE (string
[i
]))
1227 mblength
= (string
[i
] != 0) ? 1 : 0;
1229 mblength
= MBLEN (string
+ i
, slen
- i
);
1233 mblength
= mbtowc (&wc
, string
+ i
, slen
- i
);
1234 if (MB_INVALIDCH (mblength
))
1236 if (MEMBER (c
, charlist
))
1244 len
= mbstowcs (wcharlist
, charlist
, 0);
1247 wcharlist
= (wchar_t *)xmalloc (sizeof (wchar_t) * (len
+ 1));
1248 mbstowcs (wcharlist
, charlist
, len
+ 1);
1251 if (wcschr (wcharlist
, wc
))
1257 if (MEMBER (c
, charlist
))
1260 ADVANCE_CHAR (string
, slen
, i
);
1263 #if defined (HANDLE_MULTIBYTE)
1267 temp
= substring (string
, *sindex
, i
);
1273 /* Extract the $( construct in STRING, and return a new string.
1274 Start extracting at (SINDEX) as if we had just seen "$(".
1275 Make (SINDEX) get the position of the matching ")". )
1276 XFLAGS is additional flags to pass to other extraction functions. */
1278 extract_command_subst (string
, sindex
, xflags
)
1285 if (string
[*sindex
] == LPAREN
|| (xflags
& SX_COMPLETE
))
1286 return (extract_delimited_string (string
, sindex
, "$(", "(", ")", xflags
|SX_COMMAND
)); /*)*/
1289 xflags
|= (no_longjmp_on_fatal_error
? SX_NOLONGJMP
: 0);
1290 ret
= xparse_dolparen (string
, string
+*sindex
, sindex
, xflags
);
1295 /* Extract the $[ construct in STRING, and return a new string. (])
1296 Start extracting at (SINDEX) as if we had just seen "$[".
1297 Make (SINDEX) get the position of the matching "]". */
1299 extract_arithmetic_subst (string
, sindex
)
1303 return (extract_delimited_string (string
, sindex
, "$[", "[", "]", 0)); /*]*/
1306 #if defined (PROCESS_SUBSTITUTION)
1307 /* Extract the <( or >( construct in STRING, and return a new string.
1308 Start extracting at (SINDEX) as if we had just seen "<(".
1309 Make (SINDEX) get the position of the matching ")". */ /*))*/
1311 extract_process_subst (string
, starter
, sindex
, xflags
)
1318 /* XXX - check xflags&SX_COMPLETE here? */
1319 return (extract_delimited_string (string
, sindex
, starter
, "(", ")", SX_COMMAND
));
1321 xflags
|= (no_longjmp_on_fatal_error
? SX_NOLONGJMP
: 0);
1322 return (xparse_dolparen (string
, string
+*sindex
, sindex
, xflags
));
1325 #endif /* PROCESS_SUBSTITUTION */
1327 #if defined (ARRAY_VARS)
1328 /* This can be fooled by unquoted right parens in the passed string. If
1329 each caller verifies that the last character in STRING is a right paren,
1330 we don't even need to call extract_delimited_string. */
1332 extract_array_assignment_list (string
, sindex
)
1339 slen
= strlen (string
);
1340 if (string
[slen
- 1] == RPAREN
)
1342 ret
= substring (string
, *sindex
, slen
- 1);
1350 /* Extract and create a new string from the contents of STRING, a
1351 character string delimited with OPENER and CLOSER. SINDEX is
1352 the address of an int describing the current offset in STRING;
1353 it should point to just after the first OPENER found. On exit,
1354 SINDEX gets the position of the last character of the matching CLOSER.
1355 If OPENER is more than a single character, ALT_OPENER, if non-null,
1356 contains a character string that can also match CLOSER and thus
1357 needs to be skipped. */
1359 extract_delimited_string (string
, sindex
, opener
, alt_opener
, closer
, flags
)
1362 char *opener
, *alt_opener
, *closer
;
1368 int pass_character
, nesting_level
, in_comment
;
1369 int len_closer
, len_opener
, len_alt_opener
;
1372 slen
= strlen (string
+ *sindex
) + *sindex
;
1373 len_opener
= STRLEN (opener
);
1374 len_alt_opener
= STRLEN (alt_opener
);
1375 len_closer
= STRLEN (closer
);
1377 pass_character
= in_comment
= 0;
1382 while (nesting_level
)
1386 /* If a recursive call or a call to ADVANCE_CHAR leaves the index beyond
1387 the end of the string, catch it and cut the loop. */
1391 c
= string
[i
= slen
];
1402 ADVANCE_CHAR (string
, slen
, i
);
1406 if (pass_character
) /* previous char was backslash */
1409 ADVANCE_CHAR (string
, slen
, i
);
1413 /* Not exactly right yet; should handle shell metacharacters and
1414 multibyte characters, too. See COMMENT_BEGIN define in parse.y */
1415 if ((flags
& SX_COMMAND
) && c
== '#' && (i
== 0 || string
[i
- 1] == '\n' || shellblank (string
[i
- 1])))
1418 ADVANCE_CHAR (string
, slen
, i
);
1422 if (c
== CTLESC
|| c
== '\\')
1429 /* Process a nested command substitution, but only if we're parsing an
1430 arithmetic substitution. */
1431 if ((flags
& SX_COMMAND
) && string
[i
] == '$' && string
[i
+1] == LPAREN
)
1434 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1435 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1440 /* Process a nested OPENER. */
1441 if (STREQN (string
+ i
, opener
, len_opener
))
1443 si
= i
+ len_opener
;
1444 t
= extract_delimited_string (string
, &si
, opener
, alt_opener
, closer
, flags
|SX_NOALLOC
);
1445 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1450 /* Process a nested ALT_OPENER */
1451 if (len_alt_opener
&& STREQN (string
+ i
, alt_opener
, len_alt_opener
))
1453 si
= i
+ len_alt_opener
;
1454 t
= extract_delimited_string (string
, &si
, alt_opener
, alt_opener
, closer
, flags
|SX_NOALLOC
);
1455 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1460 /* If the current substring terminates the delimited string, decrement
1461 the nesting level. */
1462 if (STREQN (string
+ i
, closer
, len_closer
))
1464 i
+= len_closer
- 1; /* move to last byte of the closer */
1466 if (nesting_level
== 0)
1470 /* Pass old-style command substitution through verbatim. */
1474 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1475 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1480 /* Pass single-quoted and double-quoted strings through verbatim. */
1481 if (c
== '\'' || c
== '"')
1484 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, si
, 0)
1485 : skip_double_quoted (string
, slen
, si
, 0);
1489 /* move past this character, which was not special. */
1490 ADVANCE_CHAR (string
, slen
, i
);
1493 if (c
== 0 && nesting_level
)
1495 if (no_longjmp_on_fatal_error
== 0)
1497 last_command_exit_value
= EXECUTION_FAILURE
;
1498 report_error (_("bad substitution: no closing `%s' in %s"), closer
, string
);
1499 exp_jump_to_top_level (DISCARD
);
1504 return (char *)NULL
;
1508 si
= i
- *sindex
- len_closer
+ 1;
1509 if (flags
& SX_NOALLOC
)
1510 result
= (char *)NULL
;
1513 result
= (char *)xmalloc (1 + si
);
1514 strncpy (result
, string
+ *sindex
, si
);
1522 /* A simplified version of extract_dollar_brace_string that exists to handle
1523 $'...' and $"..." quoting in here-documents, since the here-document read
1524 path doesn't. It's separate because we don't want to mess with the fast
1525 common path. We already know we're going to allocate and return a new
1526 string and quoted == Q_HERE_DOCUMENT. We might be able to cut it down
1527 some more, but extracting strings and adding them as we go adds complexity.
1528 This needs to match the logic in parse.y:parse_matched_pair so we get
1529 consistent behavior between here-documents and double-quoted strings. */
1531 extract_heredoc_dolbrace_string (string
, sindex
, quoted
, flags
)
1533 int *sindex
, quoted
, flags
;
1536 size_t slen
, tlen
, result_index
, result_size
;
1537 int pass_character
, nesting_level
, si
, dolbrace_state
;
1538 char *result
, *t
, *send
;
1543 slen
= strlen (string
+ *sindex
) + *sindex
;
1544 send
= string
+ slen
;
1548 result
= xmalloc (result_size
+ 1);
1550 /* This function isn't called if this condition is not true initially. */
1551 dolbrace_state
= DOLBRACE_QUOTE
;
1554 while (c
= string
[i
])
1559 RESIZE_MALLOCED_BUFFER (result
, result_index
, locale_mb_cur_max
+ 1, result_size
, 64);
1560 COPY_CHAR_I (result
, result_index
, string
, send
, i
);
1564 /* CTLESCs and backslashes quote the next character. */
1565 if (c
== CTLESC
|| c
== '\\')
1568 RESIZE_MALLOCED_BUFFER (result
, result_index
, 2, result_size
, 64);
1569 result
[result_index
++] = c
;
1574 /* The entire reason we have this separate function right here. */
1575 if (c
== '$' && string
[i
+1] == '\'')
1580 if ((posixly_correct
|| extended_quote
== 0) && dolbrace_state
!= DOLBRACE_QUOTE
&& dolbrace_state
!= DOLBRACE_QUOTE2
)
1582 RESIZE_MALLOCED_BUFFER (result
, result_index
, 3, result_size
, 64);
1583 result
[result_index
++] = '$';
1584 result
[result_index
++] = '\'';
1590 t
= string_extract_single_quoted (string
, &si
, 1); /* XXX */
1591 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1593 tlen
= si
- i
- 2; /* -2 since si is one after the close quote */
1594 ttrans
= ansiexpand (t
, 0, tlen
, &ttranslen
);
1597 /* needed to correctly quote any embedded single quotes. */
1598 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_QUOTE2
)
1600 t
= sh_single_quote (ttrans
);
1604 else if (extended_quote
) /* dolbrace_state == DOLBRACE_PARAM */
1606 /* This matches what parse.y:parse_matched_pair() does */
1611 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 1, result_size
, 64);
1612 strncpy (result
+ result_index
, t
, tlen
);
1613 result_index
+= tlen
;
1619 #if defined (TRANSLATABLE_STRINGS)
1620 if (c
== '$' && string
[i
+1] == '"')
1626 t
= string_extract_double_quoted (string
, &si
, flags
); /* XXX */
1627 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1629 tlen
= si
- i
- 2; /* -2 since si is one after the close quote */
1630 ttrans
= locale_expand (t
, 0, tlen
, line_number
, &ttranslen
);
1633 t
= singlequote_translations
? sh_single_quote (ttrans
) : sh_mkdoublequoted (ttrans
, ttranslen
, 0);
1637 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 1, result_size
, 64);
1638 strncpy (result
+ result_index
, t
, tlen
);
1639 result_index
+= tlen
;
1644 #endif /* TRANSLATABLE_STRINGS */
1646 if (c
== '$' && string
[i
+1] == LBRACE
)
1649 RESIZE_MALLOCED_BUFFER (result
, result_index
, 3, result_size
, 64);
1650 result
[result_index
++] = c
;
1651 result
[result_index
++] = string
[i
+1];
1653 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_QUOTE2
|| dolbrace_state
== DOLBRACE_WORD
)
1654 dolbrace_state
= DOLBRACE_PARAM
;
1661 if (nesting_level
== 0)
1663 RESIZE_MALLOCED_BUFFER (result
, result_index
, 2, result_size
, 64);
1664 result
[result_index
++] = c
;
1669 /* Pass the contents of old-style command substitutions through
1674 t
= string_extract (string
, &si
, "`", flags
); /* already know (flags & SX_NOALLOC) == 0) */
1675 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1678 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 3, result_size
, 64);
1679 result
[result_index
++] = c
;
1680 strncpy (result
+ result_index
, t
, tlen
);
1681 result_index
+= tlen
;
1682 result
[result_index
++] = string
[si
];
1688 /* Pass the contents of new-style command substitutions and
1689 arithmetic substitutions through verbatim. */
1690 if (string
[i
] == '$' && string
[i
+1] == LPAREN
)
1693 t
= extract_command_subst (string
, &si
, flags
);
1694 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1697 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 4, result_size
, 64);
1698 result
[result_index
++] = c
;
1699 result
[result_index
++] = LPAREN
;
1700 strncpy (result
+ result_index
, t
, tlen
);
1701 result_index
+= tlen
;
1702 result
[result_index
++] = string
[si
];
1708 #if defined (PROCESS_SUBSTITUTION)
1709 /* Technically this should only work at the start of a word */
1710 if ((string
[i
] == '<' || string
[i
] == '>') && string
[i
+1] == LPAREN
)
1713 t
= extract_process_subst (string
, (string
[i
] == '<' ? "<(" : ">)"), &si
, flags
);
1714 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1717 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 4, result_size
, 64);
1718 result
[result_index
++] = c
;
1719 result
[result_index
++] = LPAREN
;
1720 strncpy (result
+ result_index
, t
, tlen
);
1721 result_index
+= tlen
;
1722 result
[result_index
++] = string
[si
];
1729 if (c
== '\'' && posixly_correct
&& shell_compatibility_level
> 42 && dolbrace_state
!= DOLBRACE_QUOTE
)
1731 COPY_CHAR_I (result
, result_index
, string
, send
, i
);
1735 /* Pass the contents of single and double-quoted strings through verbatim. */
1736 if (c
== '"' || c
== '\'')
1740 t
= string_extract_double_quoted (string
, &si
, flags
);
1742 t
= string_extract_single_quoted (string
, &si
, 0);
1743 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1745 tlen
= si
- i
- 2; /* -2 since si is one after the close quote */
1746 RESIZE_MALLOCED_BUFFER (result
, result_index
, tlen
+ 3, result_size
, 64);
1747 result
[result_index
++] = c
;
1748 strncpy (result
+ result_index
, t
, tlen
);
1749 result_index
+= tlen
;
1750 result
[result_index
++] = string
[si
- 1];
1756 /* copy this character, which was not special. */
1757 COPY_CHAR_I (result
, result_index
, string
, send
, i
);
1759 /* This logic must agree with parse.y:parse_matched_pair, since they
1760 share the same defines. */
1761 if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '%' && (i
- *sindex
) > 1)
1762 dolbrace_state
= DOLBRACE_QUOTE
;
1763 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '#' && (i
- *sindex
) > 1)
1764 dolbrace_state
= DOLBRACE_QUOTE
;
1765 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '/' && (i
- *sindex
) > 1)
1766 dolbrace_state
= DOLBRACE_QUOTE2
; /* XXX */
1767 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '^' && (i
- *sindex
) > 1)
1768 dolbrace_state
= DOLBRACE_QUOTE
;
1769 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== ',' && (i
- *sindex
) > 1)
1770 dolbrace_state
= DOLBRACE_QUOTE
;
1771 /* This is intended to handle all of the [:]op expansions and the substring/
1772 length/pattern removal/pattern substitution expansions. */
1773 else if (dolbrace_state
== DOLBRACE_PARAM
&& strchr ("#%^,~:-=?+/", c
) != 0)
1774 dolbrace_state
= DOLBRACE_OP
;
1775 else if (dolbrace_state
== DOLBRACE_OP
&& strchr ("#%^,~:-=?+/", c
) == 0)
1776 dolbrace_state
= DOLBRACE_WORD
;
1779 if (c
== 0 && nesting_level
)
1782 if (no_longjmp_on_fatal_error
== 0)
1784 last_command_exit_value
= EXECUTION_FAILURE
;
1785 report_error (_("bad substitution: no closing `%s' in %s"), "}", string
);
1786 exp_jump_to_top_level (DISCARD
);
1791 return ((char *)NULL
);
1796 result
[result_index
] = '\0';
1801 #define PARAMEXPNEST_MAX 32 // for now
1802 static int dbstate
[PARAMEXPNEST_MAX
];
1804 /* Extract a parameter expansion expression within ${ and } from STRING.
1805 Obey the Posix.2 rules for finding the ending `}': count braces while
1806 skipping over enclosed quoted strings and command substitutions.
1807 SINDEX is the address of an int describing the current offset in STRING;
1808 it should point to just after the first `{' found. On exit, SINDEX
1809 gets the position of the matching `}'. QUOTED is non-zero if this
1810 occurs inside double quotes. */
1811 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1813 extract_dollar_brace_string (string
, sindex
, quoted
, flags
)
1815 int *sindex
, quoted
, flags
;
1819 int pass_character
, nesting_level
, si
, dolbrace_state
;
1823 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1824 parse_matched_pair(). The different initial value is to handle the
1825 case where this function is called to parse the word in
1826 ${param op word} (SX_WORD). */
1827 dolbrace_state
= (flags
& SX_WORD
) ? DOLBRACE_WORD
: DOLBRACE_PARAM
;
1828 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && (flags
& SX_POSIXEXP
))
1829 dolbrace_state
= DOLBRACE_QUOTE
;
1831 if (quoted
== Q_HERE_DOCUMENT
&& dolbrace_state
== DOLBRACE_QUOTE
&& (flags
& SX_NOALLOC
) == 0)
1832 return (extract_heredoc_dolbrace_string (string
, sindex
, quoted
, flags
));
1834 dbstate
[0] = dolbrace_state
;
1838 slen
= strlen (string
+ *sindex
) + *sindex
;
1841 while (c
= string
[i
])
1846 ADVANCE_CHAR (string
, slen
, i
);
1850 /* CTLESCs and backslashes quote the next character. */
1851 if (c
== CTLESC
|| c
== '\\')
1858 if (string
[i
] == '$' && string
[i
+1] == LBRACE
)
1860 if (nesting_level
< PARAMEXPNEST_MAX
)
1861 dbstate
[nesting_level
] = dolbrace_state
;
1864 if (dolbrace_state
== DOLBRACE_QUOTE
|| dolbrace_state
== DOLBRACE_WORD
)
1865 dolbrace_state
= DOLBRACE_PARAM
;
1872 if (nesting_level
== 0)
1874 dolbrace_state
= (nesting_level
< PARAMEXPNEST_MAX
) ? dbstate
[nesting_level
] : dbstate
[0]; /* Guess using initial state */
1879 /* Pass the contents of old-style command substitutions through
1884 t
= string_extract (string
, &si
, "`", flags
|SX_NOALLOC
);
1886 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1892 /* Pass the contents of new-style command substitutions and
1893 arithmetic substitutions through verbatim. */
1894 if (string
[i
] == '$' && string
[i
+1] == LPAREN
)
1897 t
= extract_command_subst (string
, &si
, flags
|SX_NOALLOC
);
1899 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1905 #if defined (PROCESS_SUBSTITUTION)
1906 /* Technically this should only work at the start of a word */
1907 if ((string
[i
] == '<' || string
[i
] == '>') && string
[i
+1] == LPAREN
)
1910 t
= extract_process_subst (string
, (string
[i
] == '<' ? "<(" : ">)"), &si
, flags
|SX_NOALLOC
);
1912 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1919 /* Pass the contents of double-quoted strings through verbatim. */
1923 i
= skip_double_quoted (string
, slen
, si
, 0);
1924 /* skip_XXX_quoted leaves index one past close quote */
1930 /*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
1931 if (posixly_correct
&& shell_compatibility_level
> 42 && dolbrace_state
!= DOLBRACE_QUOTE
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1932 ADVANCE_CHAR (string
, slen
, i
);
1936 i
= skip_single_quoted (string
, slen
, si
, 0);
1942 #if defined (ARRAY_VARS)
1943 if (c
== LBRACK
&& dolbrace_state
== DOLBRACE_PARAM
)
1945 si
= skipsubscript (string
, i
, 0);
1946 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
1947 if (string
[si
] == RBRACK
)
1952 /* move past this character, which was not special. */
1953 ADVANCE_CHAR (string
, slen
, i
);
1955 /* This logic must agree with parse.y:parse_matched_pair, since they
1956 share the same defines. */
1957 if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '%' && (i
- *sindex
) > 1)
1958 dolbrace_state
= DOLBRACE_QUOTE
;
1959 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '#' && (i
- *sindex
) > 1)
1960 dolbrace_state
= DOLBRACE_QUOTE
;
1961 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '/' && (i
- *sindex
) > 1)
1962 dolbrace_state
= DOLBRACE_QUOTE2
; /* XXX */
1963 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== '^' && (i
- *sindex
) > 1)
1964 dolbrace_state
= DOLBRACE_QUOTE
;
1965 else if (dolbrace_state
== DOLBRACE_PARAM
&& c
== ',' && (i
- *sindex
) > 1)
1966 dolbrace_state
= DOLBRACE_QUOTE
;
1967 /* This is intended to handle all of the [:]op expansions and the substring/
1968 length/pattern removal/pattern substitution expansions. */
1969 else if (dolbrace_state
== DOLBRACE_PARAM
&& strchr ("#%^,~:-=?+/", c
) != 0)
1970 dolbrace_state
= DOLBRACE_OP
;
1971 else if (dolbrace_state
== DOLBRACE_OP
&& strchr ("#%^,~:-=?+/", c
) == 0)
1972 dolbrace_state
= DOLBRACE_WORD
;
1975 if (c
== 0 && nesting_level
)
1977 if (no_longjmp_on_fatal_error
== 0)
1979 last_command_exit_value
= EXECUTION_FAILURE
;
1980 report_error (_("bad substitution: no closing `%s' in %s"), "}", string
);
1981 exp_jump_to_top_level (DISCARD
);
1986 return ((char *)NULL
);
1990 result
= (flags
& SX_NOALLOC
) ? (char *)NULL
: substring (string
, *sindex
, i
);
1996 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1997 STRING, and returns a pointer to it. */
1999 de_backslash (string
)
2002 register size_t slen
;
2003 register int i
, j
, prev_i
;
2006 slen
= strlen (string
);
2009 /* Loop copying string[i] to string[j], i >= j. */
2012 if (string
[i
] == '\\' && (string
[i
+ 1] == '`' || string
[i
+ 1] == '\\' ||
2013 string
[i
+ 1] == '$'))
2016 ADVANCE_CHAR (string
, slen
, i
);
2018 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
2029 /* Replace instances of \! in a string with !. */
2031 unquote_bang (string
)
2035 register char *temp
;
2037 temp
= (char *)xmalloc (1 + strlen (string
));
2039 for (i
= 0, j
= 0; (temp
[j
] = string
[i
]); i
++, j
++)
2041 if (string
[i
] == '\\' && string
[i
+ 1] == '!')
2047 strcpy (string
, temp
);
2052 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0)
2054 /* When FLAGS & 2 == 0, this function assumes STRING[I] == OPEN; when
2055 FLAGS & 2 != 0, it assumes STRING[I] points to one character past OPEN;
2056 returns with STRING[RET] == close; used to parse array subscripts.
2057 FLAGS & 1 means not to attempt to skip over matched pairs of quotes or
2058 backquotes, or skip word expansions; it is intended to be used after
2059 expansion has been performed and during final assignment parsing (see
2060 arrayfunc.c:assign_compound_array_list()) or during execution by a builtin
2061 which has already undergone word expansion. */
2063 skip_matched_pair (string
, start
, open
, close
, flags
)
2065 int start
, open
, close
, flags
;
2067 int i
, pass_next
, backq
, si
, c
, count
, oldjmp
;
2072 slen
= strlen (string
+ start
) + start
;
2073 oldjmp
= no_longjmp_on_fatal_error
;
2074 no_longjmp_on_fatal_error
= 1;
2076 /* Move to the first character after a leading OPEN. If FLAGS&2, we assume
2077 that START already points to that character. If not, we need to skip over
2079 i
= (flags
& 2) ? start
: start
+ 1;
2081 pass_next
= backq
= 0;
2082 ss
= (char *)string
;
2083 while (c
= string
[i
])
2090 ADVANCE_CHAR (string
, slen
, i
);
2093 else if ((flags
& 1) == 0 && c
== '\\')
2103 ADVANCE_CHAR (string
, slen
, i
);
2106 else if ((flags
& 1) == 0 && c
== '`')
2112 else if ((flags
& 1) == 0 && c
== open
)
2118 else if (c
== close
)
2126 else if ((flags
& 1) == 0 && (c
== '\'' || c
== '"'))
2128 i
= (c
== '\'') ? skip_single_quoted (ss
, slen
, ++i
, 0)
2129 : skip_double_quoted (ss
, slen
, ++i
, 0);
2130 /* no increment, the skip functions increment past the closing quote. */
2132 else if ((flags
& 1) == 0 && c
== '$' && (string
[i
+1] == LPAREN
|| string
[i
+1] == LBRACE
))
2135 if (string
[si
] == '\0')
2138 /* XXX - extract_command_subst here? */
2139 if (string
[i
+1] == LPAREN
)
2140 temp
= extract_delimited_string (ss
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
); /* ) */
2142 temp
= extract_dollar_brace_string (ss
, &si
, 0, SX_NOALLOC
);
2144 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2147 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2153 ADVANCE_CHAR (string
, slen
, i
);
2159 #if defined (ARRAY_VARS)
2160 /* FLAGS has 1 as a reserved value, since skip_matched_pair uses it for
2161 skipping over quoted strings and taking the first instance of the
2162 closing character. FLAGS & 2 means that STRING[START] points one
2163 character past the open bracket; FLAGS & 2 == 0 means that STRING[START]
2164 points to the open bracket. skip_matched_pair knows how to deal with this. */
2166 skipsubscript (string
, start
, flags
)
2170 return (skip_matched_pair (string
, start
, '[', ']', flags
));
2174 /* Skip characters in STRING until we find a character in DELIMS, and return
2175 the index of that character. START is the index into string at which we
2176 begin. This is similar in spirit to strpbrk, but it returns an index into
2177 STRING and takes a starting index. This little piece of code knows quite
2178 a lot of shell syntax. It's very similar to skip_double_quoted and other
2179 functions of that ilk. */
2181 skip_to_delim (string
, start
, delims
, flags
)
2187 int i
, pass_next
, backq
, dquote
, si
, c
, oldjmp
;
2188 int invert
, skipquote
, skipcmd
, noprocsub
, completeflag
;
2189 int arithexp
, skipcol
;
2191 char *temp
, open
[3];
2194 slen
= strlen (string
+ start
) + start
;
2195 oldjmp
= no_longjmp_on_fatal_error
;
2196 if (flags
& SD_NOJMP
)
2197 no_longjmp_on_fatal_error
= 1;
2198 invert
= (flags
& SD_INVERT
);
2199 skipcmd
= (flags
& SD_NOSKIPCMD
) == 0;
2200 noprocsub
= (flags
& SD_NOPROCSUB
);
2201 completeflag
= (flags
& SD_COMPLETE
) ? SX_COMPLETE
: 0;
2203 arithexp
= (flags
& SD_ARITHEXP
);
2207 pass_next
= backq
= dquote
= 0;
2208 while (c
= string
[i
])
2210 /* If this is non-zero, we should not let quote characters be delimiters
2211 and the current character is a single or double quote. We should not
2212 test whether or not it's a delimiter until after we skip single- or
2213 double-quoted strings. */
2214 skipquote
= ((flags
& SD_NOQUOTEDELIM
) && (c
== '\'' || c
=='"'));
2220 ADVANCE_CHAR (string
, slen
, i
);
2233 ADVANCE_CHAR (string
, slen
, i
);
2242 else if (arithexp
&& skipcol
&& c
== ':')
2248 else if (arithexp
&& c
== '?')
2254 else if (skipquote
== 0 && invert
== 0 && member (c
, delims
))
2256 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2257 quoted strings when looking for the history expansion character as a
2259 /* special case for programmable completion which takes place before
2260 parser converts backslash-escaped single quotes between $'...' to
2261 `regular' single-quoted strings. */
2262 else if (completeflag
&& i
> 0 && string
[i
-1] == '$' && c
== '\'')
2263 i
= skip_single_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2265 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2267 i
= skip_double_quoted (string
, slen
, ++i
, completeflag
);
2268 else if (c
== LPAREN
&& arithexp
)
2271 if (string
[si
] == '\0')
2274 temp
= extract_delimited_string (string
, &si
, "(", "(", ")", SX_NOALLOC
); /* ) */
2276 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2281 else if (c
== '$' && ((skipcmd
&& string
[i
+1] == LPAREN
) || string
[i
+1] == LBRACE
))
2284 if (string
[si
] == '\0')
2287 if (string
[i
+1] == LPAREN
)
2288 temp
= extract_delimited_string (string
, &si
, "$(", "(", ")", SX_NOALLOC
|SX_COMMAND
|completeflag
); /* ) */
2290 temp
= extract_dollar_brace_string (string
, &si
, 0, SX_NOALLOC
);
2291 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2293 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2298 #if defined (PROCESS_SUBSTITUTION)
2299 else if (skipcmd
&& noprocsub
== 0 && (c
== '<' || c
== '>') && string
[i
+1] == LPAREN
)
2302 if (string
[si
] == '\0')
2305 temp
= extract_delimited_string (string
, &si
, (c
== '<') ? "<(" : ">(", "(", ")", SX_COMMAND
|SX_NOALLOC
); /* )) */
2306 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2308 if (string
[i
] == '\0')
2313 #endif /* PROCESS_SUBSTITUTION */
2314 #if defined (EXTENDED_GLOB)
2315 else if ((flags
& SD_EXTGLOB
) && extended_glob
&& string
[i
+1] == LPAREN
&& member (c
, "?*+!@"))
2318 if (string
[si
] == '\0')
2324 temp
= extract_delimited_string (string
, &si
, open
, "(", ")", SX_NOALLOC
); /* ) */
2326 CHECK_STRING_OVERRUN (i
, si
, slen
, c
);
2328 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2334 else if ((flags
& SD_GLOB
) && c
== LBRACK
)
2337 if (string
[si
] == '\0')
2340 temp
= extract_delimited_string (string
, &si
, "[", "[", "]", SX_NOALLOC
); /* ] */
2343 if (string
[i
] == '\0') /* don't increment i past EOS in loop */
2348 else if ((skipquote
|| invert
) && (member (c
, delims
) == 0))
2351 ADVANCE_CHAR (string
, slen
, i
);
2357 #if defined (BANG_HISTORY)
2358 /* Skip to the history expansion character (delims[0]), paying attention to
2359 quoted strings and command and process substitution. This is a stripped-
2360 down version of skip_to_delims. The essential difference is that this
2361 resets the quoting state when starting a command substitution */
2363 skip_to_histexp (string
, start
, delims
, flags
)
2369 int i
, pass_next
, backq
, dquote
, c
, oldjmp
;
2370 int histexp_comsub
, histexp_backq
, old_dquote
;
2374 slen
= strlen (string
+ start
) + start
;
2375 oldjmp
= no_longjmp_on_fatal_error
;
2376 if (flags
& SD_NOJMP
)
2377 no_longjmp_on_fatal_error
= 1;
2379 histexp_comsub
= histexp_backq
= old_dquote
= 0;
2382 pass_next
= backq
= dquote
= 0;
2383 while (c
= string
[i
])
2390 ADVANCE_CHAR (string
, slen
, i
);
2399 else if (backq
&& c
== '`')
2403 dquote
= old_dquote
;
2411 old_dquote
= dquote
; /* simple - one level for now */
2416 /* When in double quotes, act as if the double quote is a member of
2417 history_no_expand_chars, like the history library does */
2418 else if (dquote
&& c
== delims
[0] && string
[i
+1] == '"')
2423 else if (c
== delims
[0])
2425 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2426 quoted strings when looking for the history expansion character as a
2428 else if (dquote
&& c
== '\'')
2434 i
= skip_single_quoted (string
, slen
, ++i
, 0);
2435 /* The posixly_correct test makes posix-mode shells allow double quotes
2436 to quote the history expansion character */
2437 else if (posixly_correct
== 0 && c
== '"')
2439 dquote
= 1 - dquote
;
2444 i
= skip_double_quoted (string
, slen
, ++i
, 0);
2445 #if defined (PROCESS_SUBSTITUTION)
2446 else if ((c
== '$' || c
== '<' || c
== '>') && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2448 else if (c
== '$' && string
[i
+1] == LPAREN
&& string
[i
+2] != LPAREN
)
2451 if (string
[i
+2] == '\0')
2455 old_dquote
= dquote
;
2458 else if (histexp_comsub
&& c
== RPAREN
)
2461 dquote
= old_dquote
;
2465 else if (backq
) /* placeholder */
2467 ADVANCE_CHAR (string
, slen
, i
);
2471 ADVANCE_CHAR (string
, slen
, i
);
2476 #endif /* BANG_HISTORY */
2478 #if defined (READLINE)
2479 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
2480 an unclosed quoted string), or if the character at EINDEX is quoted
2481 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
2482 single and double-quoted string parsing functions should not return an
2483 error if there are unclosed quotes or braces. The characters that this
2484 recognizes need to be the same as the contents of
2485 rl_completer_quote_characters. */
2488 char_is_quoted (string
, eindex
)
2492 int i
, pass_next
, c
, oldjmp
;
2496 slen
= strlen (string
);
2497 oldjmp
= no_longjmp_on_fatal_error
;
2498 no_longjmp_on_fatal_error
= 1;
2501 /* If we have an open quoted string from a previous line, see if it's
2502 closed before string[eindex], so we don't interpret that close quote
2503 as starting a new quoted string. */
2504 if (current_command_line_count
> 0 && dstack
.delimiter_depth
> 0)
2506 c
= dstack
.delimiters
[dstack
.delimiter_depth
- 1];
2508 i
= skip_single_quoted (string
, slen
, 0, 0);
2510 i
= skip_double_quoted (string
, slen
, 0, SX_COMPLETE
);
2522 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2524 ADVANCE_CHAR (string
, slen
, i
);
2533 else if (c
== '$' && string
[i
+1] == '\'' && string
[i
+2])
2536 i
= skip_single_quoted (string
, slen
, i
, SX_COMPLETE
);
2540 else if (c
== '\'' || c
== '"')
2542 i
= (c
== '\'') ? skip_single_quoted (string
, slen
, ++i
, 0)
2543 : skip_double_quoted (string
, slen
, ++i
, SX_COMPLETE
);
2546 /* no increment, the skip_xxx functions go one past end */
2549 ADVANCE_CHAR (string
, slen
, i
);
2556 unclosed_pair (string
, eindex
, openstr
)
2561 int i
, pass_next
, openc
, olen
;
2565 slen
= strlen (string
);
2566 olen
= strlen (openstr
);
2567 i
= pass_next
= openc
= 0;
2573 if (i
>= eindex
) /* XXX was if (i >= eindex - 1) */
2575 ADVANCE_CHAR (string
, slen
, i
);
2578 else if (string
[i
] == '\\')
2584 else if (STREQN (string
+ i
, openstr
, olen
))
2589 /* XXX - may want to handle $'...' specially here */
2590 else if (string
[i
] == '\'' || string
[i
] == '"')
2592 i
= (string
[i
] == '\'') ? skip_single_quoted (string
, slen
, i
, 0)
2593 : skip_double_quoted (string
, slen
, i
, SX_COMPLETE
);
2598 ADVANCE_CHAR (string
, slen
, i
);
2603 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
2604 individual words. If DELIMS is NULL, the current value of $IFS is used
2605 to split the string, and the function follows the shell field splitting
2606 rules. SENTINEL is an index to look for. NWP, if non-NULL,
2607 gets the number of words in the returned list. CWP, if non-NULL, gets
2608 the index of the word containing SENTINEL. Non-whitespace chars in
2609 DELIMS delimit separate fields. This is used by programmable completion. */
2611 split_at_delims (string
, slen
, delims
, sentinel
, flags
, nwp
, cwp
)
2615 int sentinel
, flags
;
2618 int ts
, te
, i
, nw
, cw
, ifs_split
, dflags
;
2619 char *token
, *d
, *d2
;
2620 WORD_LIST
*ret
, *tl
;
2622 if (string
== 0 || *string
== '\0')
2628 return ((WORD_LIST
*)NULL
);
2631 d
= (delims
== 0) ? ifs_value
: (char *)delims
;
2632 ifs_split
= delims
== 0;
2634 /* Make d2 the non-whitespace characters in delims */
2639 #if defined (HANDLE_MULTIBYTE)
2640 size_t mblength
= 1;
2644 slength
= strlen (delims
);
2645 d2
= (char *)xmalloc (slength
+ 1);
2649 #if defined (HANDLE_MULTIBYTE)
2650 mbstate_t state_bak
;
2652 mblength
= MBRLEN (delims
+ i
, slength
, &state
);
2653 if (MB_INVALIDCH (mblength
))
2655 else if (mblength
> 1)
2657 memcpy (d2
+ ts
, delims
+ i
, mblength
);
2660 slength
-= mblength
;
2664 if (whitespace (delims
[i
]) == 0)
2665 d2
[ts
++] = delims
[i
];
2673 ret
= (WORD_LIST
*)NULL
;
2675 /* Remove sequences of whitespace characters at the start of the string, as
2676 long as those characters are delimiters. */
2677 for (i
= 0; member (string
[i
], d
) && spctabnl (string
[i
]); i
++)
2679 if (string
[i
] == '\0')
2688 dflags
= flags
|SD_NOJMP
;
2691 te
= skip_to_delim (string
, ts
, d
, dflags
);
2693 /* If we have a non-whitespace delimiter character, use it to make a
2694 separate field. This is just about what $IFS splitting does and
2695 is closer to the behavior of the shell parser. */
2696 if (ts
== te
&& d2
&& member (string
[ts
], d2
))
2699 /* If we're using IFS splitting, the non-whitespace delimiter char
2700 and any additional IFS whitespace delimits a field. */
2702 while (member (string
[te
], d
) && spctabnl (string
[te
]) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2705 while (member (string
[te
], d2
) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2709 token
= substring (string
, ts
, te
);
2711 ret
= add_string_to_list (token
, ret
); /* XXX */
2715 if (sentinel
>= ts
&& sentinel
<= te
)
2718 /* If the cursor is at whitespace just before word start, set the
2719 sentinel word to the current word. */
2720 if (cwp
&& cw
== -1 && sentinel
== ts
-1)
2723 /* If the cursor is at whitespace between two words, make a new, empty
2724 word, add it before (well, after, since the list is in reverse order)
2725 the word we just added, and set the current word to that one. */
2726 if (cwp
&& cw
== -1 && sentinel
< ts
)
2728 tl
= make_word_list (make_word (""), ret
->next
);
2734 if (string
[te
] == 0)
2738 /* XXX - honor SD_NOQUOTEDELIM here */
2739 while (member (string
[i
], d
) && (ifs_split
|| spctabnl(string
[i
])) && ((flags
&SD_NOQUOTEDELIM
) == 0 || (string
[te
] != '\'' && string
[te
] != '"')))
2748 /* Special case for SENTINEL at the end of STRING. If we haven't found
2749 the word containing SENTINEL yet, and the index we're looking for is at
2750 the end of STRING (or past the end of the previously-found token,
2751 possible if the end of the line is composed solely of IFS whitespace)
2752 add an additional null argument and set the current word pointer to that. */
2753 if (cwp
&& cw
== -1 && (sentinel
>= slen
|| sentinel
>= te
))
2755 if (whitespace (string
[sentinel
- 1]))
2758 ret
= add_string_to_list (token
, ret
);
2771 return (REVERSE_LIST (ret
, WORD_LIST
*));
2773 #endif /* READLINE */
2777 /* Extract the name of the variable to bind to from the assignment string. */
2779 assignment_name (string
)
2785 offset
= assignment (string
, 0);
2787 return (char *)NULL
;
2788 temp
= substring (string
, 0, offset
);
2793 /* **************************************************************** */
2795 /* Functions to convert strings to WORD_LISTs and vice versa */
2797 /* **************************************************************** */
2799 /* Return a single string of all the words in LIST. SEP is the separator
2800 to put between individual elements of LIST in the output string. */
2802 string_list_internal (list
, sep
)
2806 register WORD_LIST
*t
;
2808 size_t word_len
, sep_len
, result_size
;
2811 return ((char *)NULL
);
2813 /* Short-circuit quickly if we don't need to separate anything. */
2814 if (list
->next
== 0)
2815 return (savestring (list
->word
->word
));
2817 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
2818 sep_len
= STRLEN (sep
);
2821 for (t
= list
; t
; t
= t
->next
)
2824 result_size
+= sep_len
;
2825 result_size
+= strlen (t
->word
->word
);
2828 r
= result
= (char *)xmalloc (result_size
+ 1);
2830 for (t
= list
; t
; t
= t
->next
)
2832 if (t
!= list
&& sep_len
)
2836 FASTCOPY (sep
, r
, sep_len
);
2843 word_len
= strlen (t
->word
->word
);
2844 FASTCOPY (t
->word
->word
, r
, word_len
);
2852 /* Return a single string of all the words present in LIST, separating
2853 each word with a space. */
2858 return (string_list_internal (list
, " "));
2861 /* An external interface that can be used by the rest of the shell to
2862 obtain a string containing the first character in $IFS. Handles all
2863 the multibyte complications. If LENP is non-null, it is set to the
2864 length of the returned string. */
2866 ifs_firstchar (lenp
)
2872 ret
= xmalloc (MB_LEN_MAX
+ 1);
2873 #if defined (HANDLE_MULTIBYTE)
2874 if (ifs_firstc_len
== 1)
2876 ret
[0] = ifs_firstc
[0];
2878 len
= ret
[0] ? 1 : 0;
2882 memcpy (ret
, ifs_firstc
, ifs_firstc_len
);
2883 ret
[len
= ifs_firstc_len
] = '\0';
2886 ret
[0] = ifs_firstc
;
2888 len
= ret
[0] ? 0 : 1;
2897 /* Return a single string of all the words present in LIST, obeying the
2898 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
2899 expansion [of $*] appears within a double quoted string, it expands
2900 to a single field with the value of each parameter separated by the
2901 first character of the IFS variable, or by a <space> if IFS is unset." */
2902 /* Posix interpretation 888 changes this when IFS is null by specifying
2903 that when unquoted, this expands to separate arguments */
2905 string_list_dollar_star (list
, quoted
, flags
)
2910 #if defined (HANDLE_MULTIBYTE)
2911 # if defined (__GNUC__)
2912 char sep
[MB_CUR_MAX
+ 1];
2920 #if defined (HANDLE_MULTIBYTE)
2921 # if !defined (__GNUC__)
2922 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2923 # endif /* !__GNUC__ */
2924 if (ifs_firstc_len
== 1)
2926 sep
[0] = ifs_firstc
[0];
2931 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
2932 sep
[ifs_firstc_len
] = '\0';
2935 sep
[0] = ifs_firstc
;
2939 ret
= string_list_internal (list
, sep
);
2940 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2946 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2947 is non-zero, the $@ appears within double quotes, and we should quote
2948 the list before converting it into a string. If IFS is unset, and the
2949 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2950 in the words in the list, because the default value of $IFS is
2951 <space><tab><newline>, IFS characters in the words in the list should
2952 also be split. If IFS is null, and the word is not quoted, we need
2953 to quote the words in the list to preserve the positional parameters
2955 Valid values for the FLAGS argument are the PF_ flags in command.h,
2956 the only one we care about is PF_ASSIGNRHS. $@ is supposed to expand
2957 to the positional parameters separated by spaces no matter what IFS is
2958 set to if in a context where word splitting is not performed. The only
2959 one that we didn't handle before is assignment statement arguments to
2960 declaration builtins like `declare'. */
2962 string_list_dollar_at (list
, quoted
, flags
)
2968 #if defined (HANDLE_MULTIBYTE)
2969 # if defined (__GNUC__)
2970 char sep
[MB_CUR_MAX
+ 1];
2973 # endif /* !__GNUC__ */
2979 /* XXX this could just be ifs = ifs_value; */
2980 ifs
= ifs_var
? value_cell (ifs_var
) : (char *)0;
2982 #if defined (HANDLE_MULTIBYTE)
2983 # if !defined (__GNUC__)
2984 sep
= (char *)xmalloc (MB_CUR_MAX
+ 1);
2985 # endif /* !__GNUC__ */
2986 /* XXX - testing PF_ASSIGNRHS to make sure positional parameters are
2987 separated with a space even when word splitting will not occur. */
2988 if (flags
& PF_ASSIGNRHS
)
2993 else if (ifs
&& *ifs
)
2995 if (ifs_firstc_len
== 1)
2997 sep
[0] = ifs_firstc
[0];
3002 memcpy (sep
, ifs_firstc
, ifs_firstc_len
);
3003 sep
[ifs_firstc_len
] = '\0';
3011 #else /* !HANDLE_MULTIBYTE */
3012 /* XXX - PF_ASSIGNRHS means no word splitting, so we want positional
3013 parameters separated by a space. */
3014 sep
[0] = ((flags
& PF_ASSIGNRHS
) || ifs
== 0 || *ifs
== 0) ? ' ' : *ifs
;
3016 #endif /* !HANDLE_MULTIBYTE */
3018 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
3019 it now that quote_escapes quotes spaces */
3020 tlist
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
3022 : list_quote_escapes (list
);
3024 ret
= string_list_internal (tlist
, sep
);
3025 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
3031 /* Turn the positional parameters into a string, understanding quoting and
3032 the various subtleties of using the first character of $IFS as the
3033 separator. Calls string_list_dollar_at, string_list_dollar_star, and
3034 string_list as appropriate. */
3035 /* This needs to fully understand the additional contexts where word
3036 splitting does not occur (W_ASSIGNRHS, etc.) */
3038 string_list_pos_params (pchar
, list
, quoted
, pflags
)
3046 if (pchar
== '*' && (quoted
& Q_DOUBLE_QUOTES
))
3048 tlist
= quote_list (list
);
3049 word_list_remove_quoted_nulls (tlist
);
3050 ret
= string_list_dollar_star (tlist
, 0, 0);
3052 else if (pchar
== '*' && (quoted
& Q_HERE_DOCUMENT
))
3054 tlist
= quote_list (list
);
3055 word_list_remove_quoted_nulls (tlist
);
3056 ret
= string_list (tlist
);
3058 else if (pchar
== '*' && quoted
== 0 && ifs_is_null
) /* XXX */
3059 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3060 else if (pchar
== '*' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
)) /* XXX */
3061 ret
= expand_no_split_dollar_star
? string_list_dollar_star (list
, quoted
, 0) : string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3062 else if (pchar
== '*')
3064 /* Even when unquoted, string_list_dollar_star does the right thing
3065 making sure that the first character of $IFS is used as the
3067 ret
= string_list_dollar_star (list
, quoted
, 0);
3069 else if (pchar
== '@' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
3070 /* We use string_list_dollar_at, but only if the string is quoted, since
3071 that quotes the escapes if it's not, which we don't want. We could
3072 use string_list (the old code did), but that doesn't do the right
3073 thing if the first character of $IFS is not a space. We use
3074 string_list_dollar_star if the string is unquoted so we make sure that
3075 the elements of $@ are separated by the first character of $IFS for
3077 ret
= string_list_dollar_at (list
, quoted
, 0);
3078 else if (pchar
== '@' && quoted
== 0 && ifs_is_null
) /* XXX */
3079 ret
= string_list_dollar_at (list
, quoted
, 0); /* Posix interp 888 */
3080 else if (pchar
== '@' && quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
3081 ret
= string_list_dollar_at (list
, quoted
, pflags
); /* Posix interp 888 */
3082 else if (pchar
== '@')
3083 ret
= string_list_dollar_star (list
, quoted
, 0);
3085 ret
= string_list ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? quote_list (list
) : list
);
3090 /* Return the list of words present in STRING. Separate the string into
3091 words at any of the characters found in SEPARATORS. If QUOTED is
3092 non-zero then word in the list will have its quoted flag set, otherwise
3093 the quoted flag is left as make_word () deemed fit.
3095 This obeys the P1003.2 word splitting semantics. If `separators' is
3096 exactly <space><tab><newline>, then the splitting algorithm is that of
3097 the Bourne shell, which treats any sequence of characters from `separators'
3098 as a delimiter. If IFS is unset, which results in `separators' being set
3099 to "", no splitting occurs. If separators has some other value, the
3100 following rules are applied (`IFS white space' means zero or more
3101 occurrences of <space>, <tab>, or <newline>, as long as those characters
3102 are in `separators'):
3104 1) IFS white space is ignored at the start and the end of the
3106 2) Each occurrence of a character in `separators' that is not
3107 IFS white space, along with any adjacent occurrences of
3108 IFS white space delimits a field.
3109 3) Any nonzero-length sequence of IFS white space delimits a field.
3112 /* BEWARE! list_string strips null arguments. Don't call it twice and
3113 expect to have "" preserved! */
3115 /* This performs word splitting and quoted null character removal on
3118 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
3119 : (c) == (separators)[0]) \
3122 /* member of the space character class in the current locale */
3123 #define ifs_whitespace(c) ISSPACE(c)
3125 /* "adjacent IFS white space" */
3126 #define ifs_whitesep(c) ((sh_style_split || separators == 0) ? spctabnl (c) \
3127 : ifs_whitespace (c))
3130 list_string (string
, separators
, quoted
)
3131 register char *string
, *separators
;
3136 char *current_word
, *s
;
3137 int sindex
, sh_style_split
, whitesep
, xflags
, free_word
;
3140 if (!string
|| !*string
)
3141 return ((WORD_LIST
*)NULL
);
3143 sh_style_split
= separators
&& separators
[0] == ' ' &&
3144 separators
[1] == '\t' &&
3145 separators
[2] == '\n' &&
3146 separators
[3] == '\0';
3147 for (xflags
= 0, s
= ifs_value
; s
&& *s
; s
++)
3149 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
3150 else if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
3154 /* Remove sequences of whitespace at the beginning of STRING, as
3155 long as those characters appear in IFS. Do not do this if
3156 STRING is quoted or if there are no separator characters. We use the
3157 Posix definition of whitespace as a member of the space character
3158 class in the current locale. */
3160 if (!quoted
|| !separators
|| !*separators
)
3162 /* issep() requires that separators be non-null, and always returns 0 if
3163 separator is the empty string, so don't bother if we get an empty string
3164 for separators. We already returned NULL above if STRING is empty. */
3165 if (!quoted
&& separators
&& *separators
)
3168 for (s
= string
; *s
&& issep (*s
) && ifs_whitespace (*s
); s
++);
3171 return ((WORD_LIST
*)NULL
);
3176 /* OK, now STRING points to a word that does not begin with white space.
3177 The splitting algorithm is:
3178 extract a word, stopping at a separator
3179 skip sequences of whitespace characters as long as they are separators
3180 This obeys the field splitting rules in Posix.2. */
3181 slen
= STRLEN (string
);
3182 for (result
= (WORD_LIST
*)NULL
, sindex
= 0; string
[sindex
]; )
3184 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3185 possible, but need it in string_extract_verbatim for bounds checking */
3186 current_word
= string_extract_verbatim (string
, slen
, &sindex
, separators
, xflags
);
3187 if (current_word
== 0)
3190 free_word
= 1; /* If non-zero, we free current_word */
3192 /* If we have a quoted empty string, add a quoted null argument. We
3193 want to preserve the quoted null character iff this is a quoted
3194 empty string; otherwise the quoted null characters are removed
3196 if (QUOTED_NULL (current_word
))
3198 t
= alloc_word_desc ();
3199 t
->word
= make_quoted_char ('\0');
3200 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
3201 result
= make_word_list (t
, result
);
3203 else if (current_word
[0] != '\0')
3205 /* If we have something, then add it regardless. However,
3206 perform quoted null character removal on the current word. */
3207 remove_quoted_nulls (current_word
);
3209 /* We don't want to set the word flags based on the string contents
3210 here -- that's mostly for the parser -- so we just allocate a
3211 WORD_DESC *, assign current_word (noting that we don't want to
3212 free it), and skip all of make_word. */
3213 t
= alloc_word_desc ();
3214 t
->word
= current_word
;
3215 result
= make_word_list (t
, result
);
3217 result
->word
->flags
&= ~W_HASQUOTEDNULL
; /* just to be sure */
3218 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
3219 result
->word
->flags
|= W_QUOTED
;
3220 /* If removing quoted null characters leaves an empty word, note
3221 that we saw this for the caller to act on. */
3222 if (current_word
== 0 || current_word
[0] == '\0')
3223 result
->word
->flags
|= W_SAWQUOTEDNULL
;
3226 /* If we're not doing sequences of separators in the traditional
3227 Bourne shell style, then add a quoted null argument. */
3228 else if (!sh_style_split
&& !ifs_whitespace (string
[sindex
]))
3230 t
= alloc_word_desc ();
3231 t
->word
= make_quoted_char ('\0');
3232 t
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
3233 result
= make_word_list (t
, result
);
3237 free (current_word
);
3239 /* Note whether or not the separator is IFS whitespace, used later. */
3240 whitesep
= string
[sindex
] && ifs_whitesep (string
[sindex
]);
3242 /* Move past the current separator character. */
3246 ADVANCE_CHAR (string
, slen
, sindex
);
3249 /* Now skip sequences of whitespace characters if they are
3250 in the list of separators. */
3251 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && issep (string
[sindex
]))
3254 /* If the first separator was IFS whitespace and the current character
3255 is a non-whitespace IFS character, it should be part of the current
3256 field delimiter, not a separate delimiter that would result in an
3257 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
3258 if (string
[sindex
] && whitesep
&& issep (string
[sindex
]) && !ifs_whitesep (string
[sindex
]))
3261 /* An IFS character that is not IFS white space, along with any
3262 adjacent IFS white space, shall delimit a field. (SUSv3) */
3263 while (string
[sindex
] && ifs_whitesep (string
[sindex
]) && isifs (string
[sindex
]))
3267 return (REVERSE_LIST (result
, WORD_LIST
*));
3270 /* Parse a single word from STRING, using SEPARATORS to separate fields.
3271 ENDPTR is set to the first character after the word. This is used by
3274 This is never called with SEPARATORS != $IFS, and takes advantage of that.
3276 XXX - this function is very similar to list_string; they should be
3279 /* character is in $IFS */
3280 #define islocalsep(c) (local_cmap[(unsigned char)(c)] != 0)
3283 get_word_from_string (stringp
, separators
, endptr
)
3284 char **stringp
, *separators
, **endptr
;
3288 int sindex
, sh_style_split
, whitesep
, xflags
;
3289 unsigned char local_cmap
[UCHAR_MAX
+1]; /* really only need single-byte chars here */
3292 if (!stringp
|| !*stringp
|| !**stringp
)
3293 return ((char *)NULL
);
3295 sh_style_split
= separators
&& separators
[0] == ' ' &&
3296 separators
[1] == '\t' &&
3297 separators
[2] == '\n' &&
3298 separators
[3] == '\0';
3299 memset (local_cmap
, '\0', sizeof (local_cmap
));
3300 for (xflags
= 0, s
= separators
; s
&& *s
; s
++)
3302 if (*s
== CTLESC
) xflags
|= SX_NOCTLESC
;
3303 if (*s
== CTLNUL
) xflags
|= SX_NOESCCTLNUL
;
3304 local_cmap
[(unsigned char)*s
] = 1; /* local charmap of separators */
3310 /* Remove sequences of whitespace at the beginning of STRING, as
3311 long as those characters appear in SEPARATORS. This happens if
3312 SEPARATORS == $' \t\n' or if IFS is unset. */
3313 if (sh_style_split
|| separators
== 0)
3314 for (; *s
&& spctabnl (*s
) && islocalsep (*s
); s
++);
3316 for (; *s
&& ifs_whitespace (*s
) && islocalsep (*s
); s
++);
3318 /* If the string is nothing but whitespace, update it and return. */
3324 return ((char *)NULL
);
3327 /* OK, S points to a word that does not begin with white space.
3328 Now extract a word, stopping at a separator, save a pointer to
3329 the first character after the word, then skip sequences of spc,
3330 tab, or nl as long as they are separators.
3332 This obeys the field splitting rules in Posix.2. */
3334 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3335 possible, but need it in string_extract_verbatim for bounds checking */
3337 current_word
= string_extract_verbatim (s
, slen
, &sindex
, separators
, xflags
);
3339 /* Set ENDPTR to the first character after the end of the word. */
3341 *endptr
= s
+ sindex
;
3343 /* Note whether or not the separator is IFS whitespace, used later. */
3344 whitesep
= s
[sindex
] && ifs_whitesep (s
[sindex
]);
3346 /* Move past the current separator character. */
3350 ADVANCE_CHAR (s
, slen
, sindex
);
3353 /* Now skip sequences of space, tab, or newline characters if they are
3354 in the list of separators. */
3355 while (s
[sindex
] && spctabnl (s
[sindex
]) && islocalsep (s
[sindex
]))
3358 /* If the first separator was IFS whitespace and the current character is
3359 a non-whitespace IFS character, it should be part of the current field
3360 delimiter, not a separate delimiter that would result in an empty field.
3361 Look at POSIX.2, 3.6.5, (3)(b). */
3362 if (s
[sindex
] && whitesep
&& islocalsep (s
[sindex
]) && !ifs_whitesep (s
[sindex
]))
3365 /* An IFS character that is not IFS white space, along with any adjacent
3366 IFS white space, shall delimit a field. */
3367 while (s
[sindex
] && ifs_whitesep (s
[sindex
]) && islocalsep(s
[sindex
]))
3371 /* Update STRING to point to the next field. */
3372 *stringp
= s
+ sindex
;
3373 return (current_word
);
3376 /* Remove IFS white space at the end of STRING. Start at the end
3377 of the string and walk backwards until the beginning of the string
3378 or we find a character that's not IFS white space and not CTLESC.
3379 Only let CTLESC escape a white space character if SAW_ESCAPE is
3382 strip_trailing_ifs_whitespace (string
, separators
, saw_escape
)
3383 char *string
, *separators
;
3388 s
= string
+ STRLEN (string
) - 1;
3389 while (s
> string
&& ((spctabnl (*s
) && isifs (*s
)) ||
3390 (saw_escape
&& *s
== CTLESC
&& spctabnl (s
[1]))))
3398 /* Split STRING into words at whitespace. Obeys shell-style quoting with
3399 backslashes, single and double quotes. */
3401 list_string_with_quotes (string
)
3407 int c
, i
, tokstart
, len
;
3409 for (s
= string
; s
&& *s
&& spctabnl (*s
); s
++)
3411 if (s
== 0 || *s
== 0)
3412 return ((WORD_LIST
*)NULL
);
3416 list
= (WORD_LIST
*)NULL
;
3427 i
= skip_single_quoted (s
, s_len
, ++i
, 0);
3429 i
= skip_double_quoted (s
, s_len
, ++i
, 0);
3430 else if (c
== 0 || spctabnl (c
))
3432 /* We have found the end of a token. Make a word out of it and
3433 add it to the word list. */
3434 token
= substring (s
, tokstart
, i
);
3435 list
= add_string_to_list (token
, list
);
3437 while (spctabnl (s
[i
]))
3445 i
++; /* normal character */
3447 return (REVERSE_LIST (list
, WORD_LIST
*));
3451 /********************************************************/
3453 /* Functions to perform assignment statements */
3455 /********************************************************/
3457 #if defined (ARRAY_VARS)
3459 do_compound_assignment (name
, value
, flags
)
3464 int mklocal
, mkassoc
, mkglobal
, chklocal
;
3466 char *newname
; /* used for local nameref references */
3468 mklocal
= flags
& ASS_MKLOCAL
;
3469 mkassoc
= flags
& ASS_MKASSOC
;
3470 mkglobal
= flags
& ASS_MKGLOBAL
;
3471 chklocal
= flags
& ASS_CHKLOCAL
;
3473 if (mklocal
&& variable_context
)
3475 v
= find_variable (name
); /* follows namerefs */
3476 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : v
->name
;
3477 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3480 err_readonly (name
);
3481 return (v
); /* XXX */
3483 list
= expand_compound_array_assignment (v
, value
, flags
);
3485 v
= make_local_assoc_variable (newname
, 0);
3486 else if (v
== 0 || (array_p (v
) == 0 && assoc_p (v
) == 0) || v
->context
!= variable_context
)
3487 v
= make_local_array_variable (newname
, 0);
3489 assign_compound_array_list (v
, list
, flags
);
3491 dispose_words (list
);
3493 /* In a function but forcing assignment in global context. CHKLOCAL means to
3494 check for an existing local variable first. */
3495 else if (mkglobal
&& variable_context
)
3497 v
= chklocal
? find_variable (name
) : 0;
3498 if (v
&& (local_p (v
) == 0 || v
->context
!= variable_context
))
3501 v
= find_global_variable (name
);
3502 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3505 err_readonly (name
);
3506 return (v
); /* XXX */
3509 newname
= (v
== 0) ? nameref_transform_name (name
, flags
) : name
;
3510 list
= expand_compound_array_assignment (v
, value
, flags
);
3511 if (v
== 0 && mkassoc
)
3512 v
= make_new_assoc_variable (newname
);
3513 else if (v
&& mkassoc
&& assoc_p (v
) == 0)
3514 v
= convert_var_to_assoc (v
);
3516 v
= make_new_array_variable (newname
);
3517 else if (v
&& mkassoc
== 0 && array_p (v
) == 0)
3518 v
= convert_var_to_array (v
);
3520 assign_compound_array_list (v
, list
, flags
);
3522 dispose_words (list
);
3526 v
= assign_array_from_string (name
, value
, flags
);
3527 if (v
&& ((readonly_p (v
) && (flags
& ASS_FORCE
) == 0) || noassign_p (v
)))
3530 err_readonly (name
);
3531 return (v
); /* XXX */
3539 /* Given STRING, an assignment string, get the value of the right side
3540 of the `=', and bind it to the left side. If EXPAND is true, then
3541 perform parameter expansion, command substitution, and arithmetic
3542 expansion on the right-hand side. Perform tilde expansion in any
3543 case. Do not perform word splitting on the result of expansion. */
3545 do_assignment_internal (word
, expand
)
3546 const WORD_DESC
*word
;
3549 int offset
, appendop
, assign_list
, aflags
, retval
;
3550 char *name
, *value
, *temp
;
3552 #if defined (ARRAY_VARS)
3558 if (word
== 0 || word
->word
== 0)
3561 appendop
= assign_list
= aflags
= 0;
3562 string
= word
->word
;
3563 offset
= assignment (string
, 0);
3564 name
= savestring (string
);
3565 value
= (char *)NULL
;
3567 if (name
[offset
] == '=')
3569 if (name
[offset
- 1] == '+')
3572 name
[offset
- 1] = '\0';
3575 name
[offset
] = 0; /* might need this set later */
3576 temp
= name
+ offset
+ 1;
3578 #if defined (ARRAY_VARS)
3579 if (expand
&& (word
->flags
& W_COMPASSIGN
))
3581 assign_list
= ni
= 1;
3582 value
= extract_array_assignment_list (temp
, &ni
);
3586 if (expand
&& temp
[0])
3587 value
= expand_string_if_necessary (temp
, 0, expand_string_assignment
);
3589 value
= savestring (temp
);
3594 value
= (char *)xmalloc (1);
3598 if (echo_command_at_execute
)
3601 name
[offset
- 1] = '+';
3602 xtrace_print_assignment (name
, value
, assign_list
, 1);
3604 name
[offset
- 1] = '\0';
3607 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
3610 aflags
|= ASS_APPEND
;
3612 #if defined (ARRAY_VARS)
3613 if (t
= mbschr (name
, LBRACK
))
3617 report_error (_("%s: cannot assign list to array member"), name
);
3620 aflags
|= ASS_ALLOWALLSUB
; /* allow a[@]=value for existing associative arrays */
3621 entry
= assign_array_element (name
, value
, aflags
, (array_eltstate_t
*)0);
3625 else if (assign_list
)
3627 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_CHKLOCAL
))
3628 aflags
|= ASS_CHKLOCAL
;
3629 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
) == 0)
3630 aflags
|= ASS_MKLOCAL
;
3631 if ((word
->flags
& W_ASSIGNARG
) && (word
->flags
& W_ASSNGLOBAL
))
3632 aflags
|= ASS_MKGLOBAL
;
3633 if (word
->flags
& W_ASSIGNASSOC
)
3634 aflags
|= ASS_MKASSOC
;
3635 entry
= do_compound_assignment (name
, value
, aflags
);
3638 #endif /* ARRAY_VARS */
3639 entry
= bind_variable (name
, value
, aflags
);
3642 stupidly_hack_special_variables (entry
->name
); /* might be a nameref */
3644 stupidly_hack_special_variables (name
);
3646 /* Return 1 if the assignment seems to have been performed correctly. */
3647 if (entry
== 0 || readonly_p (entry
))
3648 retval
= 0; /* assignment failure */
3649 else if (noassign_p (entry
))
3651 set_exit_status (EXECUTION_FAILURE
);
3652 retval
= 1; /* error status, but not assignment failure */
3657 if (entry
&& retval
!= 0 && noassign_p (entry
) == 0)
3658 VUNSETATTR (entry
, att_invisible
);
3660 ASSIGN_RETURN (retval
);
3663 /* Perform the assignment statement in STRING, and expand the
3664 right side by doing tilde, command and parameter expansion. */
3666 do_assignment (string
)
3671 td
.flags
= W_ASSIGNMENT
;
3674 return do_assignment_internal (&td
, 1);
3678 do_word_assignment (word
, flags
)
3682 return do_assignment_internal (word
, 1);
3685 /* Given STRING, an assignment string, get the value of the right side
3686 of the `=', and bind it to the left side. Do not perform any word
3687 expansions on the right hand side. */
3689 do_assignment_no_expand (string
)
3694 td
.flags
= W_ASSIGNMENT
;
3697 return (do_assignment_internal (&td
, 0));
3700 /***************************************************
3702 * Functions to manage the positional parameters *
3704 ***************************************************/
3706 /* Return the word list that corresponds to `$*'. */
3708 list_rest_of_args ()
3710 register WORD_LIST
*list
, *args
;
3713 /* Break out of the loop as soon as one of the dollar variables is null. */
3714 for (i
= 1, list
= (WORD_LIST
*)NULL
; i
< 10 && dollar_vars
[i
]; i
++)
3715 list
= make_word_list (make_bare_word (dollar_vars
[i
]), list
);
3717 for (args
= rest_of_args
; args
; args
= args
->next
)
3718 list
= make_word_list (make_bare_word (args
->word
->word
), list
);
3720 return (REVERSE_LIST (list
, WORD_LIST
*));
3723 /* Return the value of a positional parameter. This handles values > 10. */
3725 get_dollar_var_value (ind
)
3732 temp
= dollar_vars
[ind
] ? savestring (dollar_vars
[ind
]) : (char *)NULL
;
3733 else /* We want something like ${11} */
3736 for (p
= rest_of_args
; p
&& ind
--; p
= p
->next
)
3738 temp
= p
? savestring (p
->word
->word
) : (char *)NULL
;
3743 /* Make a single large string out of the dollar digit variables,
3744 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
3745 case of "$*" with respect to IFS. */
3747 string_rest_of_args (dollar_star
)
3750 register WORD_LIST
*list
;
3753 list
= list_rest_of_args ();
3754 string
= dollar_star
? string_list_dollar_star (list
, 0, 0) : string_list (list
);
3755 dispose_words (list
);
3759 /* Return a string containing the positional parameters from START to
3760 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3761 which only makes a difference if QUOTED is non-zero. If QUOTED includes
3762 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
3763 no quoting chars are added. */
3765 pos_params (string
, start
, end
, quoted
, pflags
)
3767 int start
, end
, quoted
, pflags
;
3769 WORD_LIST
*save
, *params
, *h
, *t
;
3773 /* see if we can short-circuit. if start == end, we want 0 parameters. */
3775 return ((char *)NULL
);
3777 save
= params
= list_rest_of_args ();
3778 if (save
== 0 && start
> 0)
3779 return ((char *)NULL
);
3781 if (start
== 0) /* handle ${@:0[:x]} specially */
3783 t
= make_word_list (make_word (dollar_vars
[0]), params
);
3787 for (i
= start
? 1 : 0; params
&& i
< start
; i
++)
3788 params
= params
->next
;
3791 dispose_words (save
);
3792 return ((char *)NULL
);
3794 for (h
= t
= params
; params
&& i
< end
; i
++)
3797 params
= params
->next
;
3799 t
->next
= (WORD_LIST
*)NULL
;
3801 ret
= string_list_pos_params (string
[0], h
, quoted
, pflags
);
3806 dispose_words (save
);
3810 /******************************************************************/
3812 /* Functions to expand strings to strings or WORD_LISTs */
3814 /******************************************************************/
3816 #if defined (PROCESS_SUBSTITUTION)
3817 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
3819 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3822 /* We don't perform process substitution in arithmetic expressions, so don't
3823 bother checking for it. */
3824 #define ARITH_EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3826 /* If there are any characters in STRING that require full expansion,
3827 then call FUNC to expand STRING; otherwise just perform quote
3828 removal if necessary. This returns a new string. */
3830 expand_string_if_necessary (string
, quoted
, func
)
3841 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3842 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
3846 if (EXP_CHAR (string
[i
]))
3848 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
3850 ADVANCE_CHAR (string
, slen
, i
);
3855 list
= (*func
) (string
, quoted
);
3858 ret
= string_list (list
);
3859 dispose_words (list
);
3864 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
3865 ret
= string_quote_removal (string
, quoted
);
3867 ret
= savestring (string
);
3872 static inline char *
3873 expand_string_to_string_internal (string
, quoted
, func
)
3881 if (string
== 0 || *string
== '\0')
3882 return ((char *)NULL
);
3884 list
= (*func
) (string
, quoted
);
3887 ret
= string_list (list
);
3888 dispose_words (list
);
3897 expand_string_to_string (string
, quoted
)
3901 return (expand_string_to_string_internal (string
, quoted
, expand_string
));
3905 expand_string_unsplit_to_string (string
, quoted
)
3909 return (expand_string_to_string_internal (string
, quoted
, expand_string_unsplit
));
3913 expand_assignment_string_to_string (string
, quoted
)
3917 return (expand_string_to_string_internal (string
, quoted
, expand_string_assignment
));
3920 /* Kind of like a combination of dequote_string and quote_string_for_globbing;
3921 try to remove CTLESC quoting characters and convert CTLESC escaping a `&'
3922 or a backslash into a backslash. The output of this function must eventually
3923 be processed by strcreplace(). */
3925 quote_string_for_repl (string
, flags
)
3931 const char *s
, *send
;
3934 slen
= strlen (string
);
3935 send
= string
+ slen
;
3937 result
= (char *)xmalloc (slen
* 2 + 1);
3939 if (string
[0] == CTLESC
&& string
[1] == 0)
3946 /* This is awkward. We want to translate CTLESC-\ to \\ if we will
3947 eventually send this string through strcreplace(), which we will do
3948 only if shouldexp_replacement() determines that there is something
3949 to replace. We can either make sure to escape backslashes here and
3950 have shouldexp_replacement() signal that we should send the string to
3951 strcreplace() if it sees an escaped backslash, or we can scan the
3952 string before copying it and turn CTLESC-\ into \\ only if we encounter
3953 a CTLESC-& or a &. This does the former and changes shouldexp_replacement().
3954 If we double the backslashes here, we'll get doubled backslashes in any
3955 result that doesn't get passed to strcreplace(). */
3957 for (s
= string
, t
= result
; *s
; )
3959 /* This function's result has to be processed by strcreplace() */
3960 if (*s
== CTLESC
&& (s
[1] == '&' || s
[1] == '\\'))
3974 COPY_CHAR_P (t
, s
, send
);
3981 /* This does not perform word splitting on the WORD_LIST it returns and
3982 it treats $* as if it were quoted. It dequotes the WORD_LIST, adds
3983 backslash escapes before CTLESC-quoted backslash and `& if
3984 patsub_replacement is enabled. */
3986 expand_string_for_patsub (string
, quoted
)
3993 if (string
== 0 || *string
== '\0')
3994 return (char *)NULL
;
3996 value
= expand_string_for_pat (string
, quoted
, (int *)0, (int *)0);
3998 if (value
&& value
->word
)
4000 remove_quoted_nulls (value
->word
->word
); /* XXX */
4001 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4006 t
= (value
->next
) ? string_list (value
) : value
->word
->word
;
4007 ret
= quote_string_for_repl (t
, quoted
);
4008 if (t
!= value
->word
->word
)
4010 dispose_words (value
);
4019 expand_arith_string (string
, quoted
)
4024 WORD_LIST
*list
, *tlist
;
4030 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
4031 slen
= (MB_CUR_MAX
> 1) ? strlen (string
) : 0;
4035 if (ARITH_EXP_CHAR (string
[i
]))
4037 else if (string
[i
] == '\'' || string
[i
] == '\\' || string
[i
] == '"')
4038 saw_quote
= string
[i
];
4039 ADVANCE_CHAR (string
, slen
, i
);
4044 /* This is expanded version of expand_string_internal as it's called by
4045 expand_string_leave_quoted */
4046 td
.flags
= W_NOPROCSUB
|W_NOTILDE
; /* don't want process substitution or tilde expansion */
4047 #if 0 /* TAG: bash-5.2 */
4048 if (quoted
& Q_ARRAYSUB
)
4049 td
.flags
|= W_NOCOMSUB
;
4051 td
.word
= savestring (string
);
4052 list
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4053 /* This takes care of the calls from expand_string_leave_quoted and
4057 tlist
= word_list_split (list
);
4058 dispose_words (list
);
4061 dequote_list (list
);
4063 /* This comes from expand_string_if_necessary */
4066 ret
= string_list (list
);
4067 dispose_words (list
);
4073 else if (saw_quote
&& (quoted
& Q_ARITH
))
4074 ret
= string_quote_removal (string
, quoted
);
4075 else if (saw_quote
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
4076 ret
= string_quote_removal (string
, quoted
);
4078 ret
= savestring (string
);
4083 #if defined (COND_COMMAND)
4084 /* Just remove backslashes in STRING. Returns a new string. */
4086 remove_backslashes (string
)
4091 r
= ret
= (char *)xmalloc (strlen (string
) + 1);
4092 for (s
= string
; s
&& *s
; )
4104 /* This needs better error handling. */
4105 /* Expand W for use as an argument to a unary or binary operator in a
4106 [[...]] expression. If SPECIAL is 1, this is the rhs argument
4107 to the != or == operator, and should be treated as a pattern. In
4108 this case, we quote the string specially for the globbing code. If
4109 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
4110 be quoted appropriately for regcomp/regexec. If SPECIAL is 3, this is
4111 an array subscript and should be quoted after expansion so it's only
4112 expanded once (Q_ARITH). The caller is responsible
4113 for removing the backslashes if the unquoted word is needed later. In
4114 any case, since we don't perform word splitting, we need to do quoted
4115 null character removal. */
4117 cond_expand_word (w
, special
)
4125 if (w
->word
== 0 || w
->word
[0] == '\0')
4126 return ((char *)NULL
);
4128 expand_no_split_dollar_star
= 1;
4129 w
->flags
|= W_NOSPLIT2
;
4130 qflags
= (special
== 3) ? Q_ARITH
: 0;
4131 l
= call_expand_word_internal (w
, qflags
, 0, (int *)0, (int *)0);
4132 expand_no_split_dollar_star
= 0;
4135 if (special
== 0) /* LHS */
4138 word_list_remove_quoted_nulls (l
);
4140 r
= string_list (l
);
4142 else if (special
== 3) /* arithmetic expression, Q_ARITH */
4145 word_list_remove_quoted_nulls (l
); /* for now */
4147 r
= string_list (l
);
4151 /* Need to figure out whether or not we should call dequote_escapes
4152 or a new dequote_ctlnul function here, and under what
4154 qflags
= QGLOB_CVTNULL
|QGLOB_CTLESC
;
4156 qflags
|= QGLOB_REGEXP
;
4157 word_list_remove_quoted_nulls (l
);
4158 p
= string_list (l
);
4159 r
= quote_string_for_globbing (p
, qflags
);
4171 /* Expand $'...' and $"..." in a string for code paths that don't do it. The
4172 FLAGS argument is 1 if this function should treat CTLESC as a quote
4173 character (e.g., for here-documents) or not (e.g., for shell_expand_line). */
4175 expand_string_dollar_quote (string
, flags
)
4179 size_t slen
, retind
, retsize
;
4180 int sindex
, c
, translen
, peekc
, news
;
4181 char *ret
, *trans
, *send
, *t
;
4184 slen
= strlen (string
);
4185 send
= string
+ slen
;
4189 ret
= xmalloc (retsize
);
4192 while (c
= string
[sindex
])
4197 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 1, retsize
, 64);
4198 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4202 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 2, retsize
, 64);
4203 ret
[retind
++] = string
[sindex
++];
4206 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4212 news
= skip_single_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4214 news
= skip_double_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4215 translen
= news
- sindex
- 1;
4216 RESIZE_MALLOCED_BUFFER (ret
, retind
, translen
+ 3, retsize
, 64);
4220 strncpy (ret
+ retind
, string
+ sindex
, translen
);
4223 if (news
> sindex
&& string
[news
- 1] == c
)
4229 RESIZE_MALLOCED_BUFFER (ret
, retind
, locale_mb_cur_max
+ 2, retsize
, 64);
4231 ret
[retind
++] = string
[sindex
++];
4233 COPY_CHAR_I (ret
, retind
, string
, send
, sindex
);
4237 peekc
= string
[++sindex
];
4238 #if defined (TRANSLATABLE_STRINGS)
4239 if (peekc
!= '\'' && peekc
!= '"')
4244 RESIZE_MALLOCED_BUFFER (ret
, retind
, 2, retsize
, 16);
4248 if (string
[sindex
+ 1] == '\0') /* don't bother */
4250 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4252 ret
[retind
++] = peekc
;
4258 /* SX_COMPLETE is the equivalent of ALLOWESC here */
4259 /* We overload SX_COMPLETE below */
4260 news
= skip_single_quoted (string
, slen
, ++sindex
, SX_COMPLETE
);
4261 /* Check for unclosed string and don't bother if so */
4262 if (news
> sindex
&& string
[news
] == '\0' && string
[news
-1] != peekc
)
4264 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4266 ret
[retind
++] = peekc
;
4269 t
= substring (string
, sindex
, news
- 1);
4270 trans
= ansiexpand (t
, 0, news
-sindex
-1, &translen
);
4272 t
= sh_single_quote (trans
);
4275 #if defined (TRANSLATABLE_STRINGS)
4279 t
= string_extract_double_quoted (string
, &news
, SX_COMPLETE
);
4280 /* Check for unclosed string and don't bother if so */
4281 if (news
> sindex
&& string
[news
] == '\0' && string
[news
-1] != peekc
)
4283 RESIZE_MALLOCED_BUFFER (ret
, retind
, 3, retsize
, 16);
4285 ret
[retind
++] = peekc
;
4289 trans
= locale_expand (t
, 0, news
-sindex
, 0, &translen
);
4291 if (singlequote_translations
&&
4292 ((news
-sindex
-1) != translen
|| STREQN (t
, trans
, translen
) == 0))
4293 t
= sh_single_quote (trans
);
4295 t
= sh_mkdoublequoted (trans
, translen
, 0);
4298 #endif /* TRANSLATABLE_STRINGS */
4301 translen
= strlen (trans
);
4303 RESIZE_MALLOCED_BUFFER (ret
, retind
, translen
+ 1, retsize
, 128);
4304 strcpy (ret
+ retind
, trans
);
4315 /* Call expand_word_internal to expand W and handle error returns.
4316 A convenience function for functions that don't want to handle
4317 any errors or free any memory before aborting. */
4319 call_expand_word_internal (w
, q
, i
, c
, e
)
4325 result
= expand_word_internal (w
, q
, i
, c
, e
);
4326 if (result
== &expand_word_error
|| result
== &expand_word_fatal
)
4328 /* By convention, each time this error is returned, w->word has
4329 already been freed (it sometimes may not be in the fatal case,
4330 but that doesn't result in a memory leak because we're going
4331 to exit in most cases). */
4332 w
->word
= (char *)NULL
;
4333 last_command_exit_value
= EXECUTION_FAILURE
;
4334 exp_jump_to_top_level ((result
== &expand_word_error
) ? DISCARD
: FORCE_EOF
);
4342 /* Perform parameter expansion, command substitution, and arithmetic
4343 expansion on STRING, as if it were a word. Leave the result quoted.
4344 Since this does not perform word splitting, it leaves quoted nulls
4347 expand_string_internal (string
, quoted
)
4354 if (string
== 0 || *string
== 0)
4355 return ((WORD_LIST
*)NULL
);
4358 td
.word
= savestring (string
);
4360 tresult
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4366 /* Expand STRING by performing parameter expansion, command substitution,
4367 and arithmetic expansion. Dequote the resulting WORD_LIST before
4368 returning it, but do not perform word splitting. The call to
4369 remove_quoted_nulls () is in here because word splitting normally
4370 takes care of quote removal. */
4372 expand_string_unsplit (string
, quoted
)
4378 if (string
== 0 || *string
== '\0')
4379 return ((WORD_LIST
*)NULL
);
4381 expand_no_split_dollar_star
= 1;
4382 value
= expand_string_internal (string
, quoted
);
4383 expand_no_split_dollar_star
= 0;
4389 remove_quoted_nulls (value
->word
->word
); /* XXX */
4390 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4392 dequote_list (value
);
4397 /* Expand the rhs of an assignment statement */
4399 expand_string_assignment (string
, quoted
)
4406 if (string
== 0 || *string
== '\0')
4407 return ((WORD_LIST
*)NULL
);
4409 expand_no_split_dollar_star
= 1;
4412 /* Other shells (ksh93) do it this way, which affects how $@ is expanded
4413 in constructs like bar=${@#0} (preserves the spaces resulting from the
4414 expansion of $@ in a context where you don't do word splitting); Posix
4415 interp 888 makes the expansion of $@ in contexts where word splitting
4416 is not performed unspecified. */
4417 td
.flags
= W_ASSIGNRHS
|W_NOSPLIT2
; /* Posix interp 888 */
4419 td
.flags
= W_ASSIGNRHS
;
4421 td
.flags
|= (W_NOGLOB
|W_TILDEEXP
);
4422 td
.word
= savestring (string
);
4423 value
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4426 expand_no_split_dollar_star
= 0;
4432 remove_quoted_nulls (value
->word
->word
); /* XXX */
4433 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4435 dequote_list (value
);
4440 /* Expand one of the PS? prompt strings. This is a sort of combination of
4441 expand_string_unsplit and expand_string_internal, but returns the
4442 passed string when an error occurs. Might want to trap other calls
4443 to jump_to_top_level here so we don't endlessly loop. */
4445 expand_prompt_string (string
, quoted
, wflags
)
4453 if (string
== 0 || *string
== 0)
4454 return ((WORD_LIST
*)NULL
);
4457 td
.word
= savestring (string
);
4459 no_longjmp_on_fatal_error
= 1;
4460 value
= expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4461 no_longjmp_on_fatal_error
= 0;
4463 if (value
== &expand_word_error
|| value
== &expand_word_fatal
)
4465 value
= make_word_list (make_bare_word (string
), (WORD_LIST
*)NULL
);
4473 remove_quoted_nulls (value
->word
->word
); /* XXX */
4474 value
->word
->flags
&= ~W_HASQUOTEDNULL
;
4476 dequote_list (value
);
4481 /* Expand STRING just as if you were expanding a word, but do not dequote
4482 the resultant WORD_LIST. This is called only from within this file,
4483 and is used to correctly preserve quoted characters when expanding
4484 things like ${1+"$@"}. This does parameter expansion, command
4485 substitution, arithmetic expansion, and word splitting. */
4487 expand_string_leave_quoted (string
, quoted
)
4494 if (string
== 0 || *string
== '\0')
4495 return ((WORD_LIST
*)NULL
);
4497 tlist
= expand_string_internal (string
, quoted
);
4501 tresult
= word_list_split (tlist
);
4502 dispose_words (tlist
);
4505 return ((WORD_LIST
*)NULL
);
4508 /* This does not perform word splitting or dequote the WORD_LIST
4511 expand_string_for_rhs (string
, quoted
, op
, pflags
, dollar_at_p
, expanded_p
)
4513 int quoted
, op
, pflags
;
4514 int *dollar_at_p
, *expanded_p
;
4520 if (string
== 0 || *string
== '\0')
4521 return (WORD_LIST
*)NULL
;
4523 /* We want field splitting to be determined by what is going to be done with
4524 the entire ${parameterOPword} expansion, so we don't want to split the RHS
4525 we expand here. However, the expansion of $* is determined by whether we
4526 are going to eventually perform word splitting, so we want to set this
4527 depending on whether or not are are going to be splitting: if the expansion
4528 is quoted, if the OP is `=', or if IFS is set to the empty string, we
4529 are not going to be splitting, so we set expand_no_split_dollar_star to
4530 note this to callees.
4531 We pass through PF_ASSIGNRHS as W_ASSIGNRHS if this is on the RHS of an
4532 assignment statement. */
4533 /* The updated treatment of $* is the result of Posix interp 888 */
4534 /* This was further clarified on the austin-group list in March, 2017 and
4535 in Posix bug 1129 */
4536 old_nosplit
= expand_no_split_dollar_star
;
4537 expand_no_split_dollar_star
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || op
== '=' || ifs_is_null
== 0; /* XXX - was 1 */
4538 td
.flags
= W_EXPANDRHS
; /* expanding RHS of ${paramOPword} */
4539 td
.flags
|= W_NOSPLIT2
; /* no splitting, remove "" and '' */
4540 if (pflags
& PF_ASSIGNRHS
) /* pass through */
4541 td
.flags
|= W_ASSIGNRHS
;
4544 td
.flags
|= W_ASSIGNRHS
; /* expand b in ${a=b} like assignment */
4546 td
.flags
|= W_ASSIGNRHS
|W_NOASSNTILDE
; /* expand b in ${a=b} like assignment */
4548 td
.word
= savestring (string
);
4549 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
4550 expand_no_split_dollar_star
= old_nosplit
;
4556 /* This does not perform word splitting or dequote the WORD_LIST
4557 it returns and it treats $* as if it were quoted. */
4559 expand_string_for_pat (string
, quoted
, dollar_at_p
, expanded_p
)
4561 int quoted
, *dollar_at_p
, *expanded_p
;
4567 if (string
== 0 || *string
== '\0')
4568 return (WORD_LIST
*)NULL
;
4570 oexp
= expand_no_split_dollar_star
;
4571 expand_no_split_dollar_star
= 1;
4572 td
.flags
= W_NOSPLIT2
; /* no splitting, remove "" and '' */
4573 td
.word
= savestring (string
);
4574 tresult
= call_expand_word_internal (&td
, quoted
, 1, dollar_at_p
, expanded_p
);
4575 expand_no_split_dollar_star
= oexp
;
4581 /* Expand STRING just as if you were expanding a word. This also returns
4582 a list of words. Note that filename globbing is *NOT* done for word
4583 or string expansion, just when the shell is expanding a command. This
4584 does parameter expansion, command substitution, arithmetic expansion,
4585 and word splitting. Dequote the resultant WORD_LIST before returning. */
4587 expand_string (string
, quoted
)
4593 if (string
== 0 || *string
== '\0')
4594 return ((WORD_LIST
*)NULL
);
4596 result
= expand_string_leave_quoted (string
, quoted
);
4597 return (result
? dequote_list (result
) : result
);
4600 /*******************************************
4602 * Functions to expand WORD_DESCs *
4604 *******************************************/
4606 /* Expand WORD, performing word splitting on the result. This does
4607 parameter expansion, command substitution, arithmetic expansion,
4608 word splitting, and quote removal. */
4611 expand_word (word
, quoted
)
4615 WORD_LIST
*result
, *tresult
;
4617 tresult
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4618 result
= word_list_split (tresult
);
4619 dispose_words (tresult
);
4620 return (result
? dequote_list (result
) : result
);
4623 /* Expand WORD, but do not perform word splitting on the result. This
4624 does parameter expansion, command substitution, arithmetic expansion,
4625 and quote removal. */
4627 expand_word_unsplit (word
, quoted
)
4633 result
= expand_word_leave_quoted (word
, quoted
);
4634 return (result
? dequote_list (result
) : result
);
4637 /* Perform shell expansions on WORD, but do not perform word splitting or
4638 quote removal on the result. Virtually identical to expand_word_unsplit;
4639 could be combined if implementations don't diverge. */
4641 expand_word_leave_quoted (word
, quoted
)
4647 expand_no_split_dollar_star
= 1;
4649 word
->flags
|= W_NOSPLIT
;
4650 word
->flags
|= W_NOSPLIT2
;
4651 result
= call_expand_word_internal (word
, quoted
, 0, (int *)NULL
, (int *)NULL
);
4652 expand_no_split_dollar_star
= 0;
4657 /***************************************************
4659 * Functions to handle quoting chars *
4661 ***************************************************/
4665 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
4666 The parser passes CTLNUL as CTLESC CTLNUL. */
4668 /* Quote escape characters in string s, but no other characters. This is
4669 used to protect CTLESC and CTLNUL in variable values from the rest of
4670 the word expansion process after the variable is expanded (word splitting
4671 and filename generation). If IFS is null, we quote spaces as well, just
4672 in case we split on spaces later (in the case of unquoted $@, we will
4673 eventually attempt to split the entire word on spaces). Corresponding
4674 code exists in dequote_escapes. Even if we don't end up splitting on
4675 spaces, quoting spaces is not a problem. This should never be called on
4676 a string that is quoted with single or double quotes or part of a here
4677 document (effectively double-quoted).
4678 FLAGS says whether or not we are going to split the result. If we are not,
4679 and there is a CTLESC or CTLNUL in IFS, we need to quote CTLESC and CTLNUL,
4680 respectively, to prevent them from being removed as part of dequoting. */
4682 quote_escapes_internal (string
, flags
)
4686 const char *s
, *send
;
4689 int quote_spaces
, skip_ctlesc
, skip_ctlnul
, nosplit
;
4692 slen
= strlen (string
);
4693 send
= string
+ slen
;
4695 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4696 nosplit
= (flags
& PF_NOSPLIT2
);
4698 for (skip_ctlesc
= skip_ctlnul
= 0, s
= ifs_value
; s
&& *s
; s
++)
4700 skip_ctlesc
|= (nosplit
== 0 && *s
== CTLESC
);
4701 skip_ctlnul
|= (nosplit
== 0 && *s
== CTLNUL
);
4704 t
= result
= (char *)xmalloc ((slen
* 2) + 1);
4709 if ((skip_ctlesc
== 0 && *s
== CTLESC
) || (skip_ctlnul
== 0 && *s
== CTLNUL
) || (quote_spaces
&& *s
== ' '))
4711 COPY_CHAR_P (t
, s
, send
);
4719 quote_escapes (string
)
4722 return (quote_escapes_internal (string
, 0));
4729 return (quote_escapes_internal (string
, PF_NOSPLIT2
));
4733 list_quote_escapes (list
)
4736 register WORD_LIST
*w
;
4739 for (w
= list
; w
; w
= w
->next
)
4742 w
->word
->word
= quote_escapes (t
);
4748 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
4750 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
4751 This is necessary to make unquoted CTLESC and CTLNUL characters in the
4752 data stream pass through properly.
4754 We need to remove doubled CTLESC characters inside quoted strings before
4755 quoting the entire string, so we do not double the number of CTLESC
4758 Also used by parts of the pattern substitution code. */
4760 dequote_escapes (string
)
4763 const char *s
, *send
;
4772 slen
= strlen (string
);
4773 send
= string
+ slen
;
4775 t
= result
= (char *)xmalloc (slen
+ 1);
4777 if (strchr (string
, CTLESC
) == 0)
4778 return (strcpy (result
, string
));
4780 quote_spaces
= (ifs_value
&& *ifs_value
== 0);
4785 if (*s
== CTLESC
&& (s
[1] == CTLESC
|| s
[1] == CTLNUL
|| (quote_spaces
&& s
[1] == ' ')))
4791 COPY_CHAR_P (t
, s
, send
);
4798 #if defined (INCLUDE_UNUSED)
4800 list_dequote_escapes (list
)
4803 register WORD_LIST
*w
;
4806 for (w
= list
; w
; w
= w
->next
)
4809 w
->word
->word
= dequote_escapes (t
);
4816 /* Return a new string with the quoted representation of character C.
4817 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
4818 set in any resultant WORD_DESC where this value is the word. */
4820 make_quoted_char (c
)
4825 temp
= (char *)xmalloc (3);
4840 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
4841 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
4842 this value is the word. */
4844 quote_string (string
)
4849 char *result
, *send
;
4853 result
= (char *)xmalloc (2);
4861 slen
= strlen (string
);
4862 send
= string
+ slen
;
4864 result
= (char *)xmalloc ((slen
* 2) + 1);
4866 for (t
= result
; string
< send
; )
4869 COPY_CHAR_P (t
, string
, send
);
4876 /* De-quote quoted characters in STRING. */
4878 dequote_string (string
)
4881 register char *s
, *t
;
4883 char *result
, *send
;
4886 if (string
[0] == CTLESC
&& string
[1] == 0)
4887 internal_debug ("dequote_string: string with bare CTLESC");
4889 slen
= STRLEN (string
);
4891 t
= result
= (char *)xmalloc (slen
+ 1);
4893 if (QUOTED_NULL (string
))
4899 /* A string consisting of only a single CTLESC should pass through unchanged */
4900 if (string
[0] == CTLESC
&& string
[1] == 0)
4907 /* If no character in the string can be quoted, don't bother examining
4908 each character. Just return a copy of the string passed to us. */
4909 if (strchr (string
, CTLESC
) == NULL
)
4910 return (strcpy (result
, string
));
4912 send
= string
+ slen
;
4922 COPY_CHAR_P (t
, s
, send
);
4929 /* Quote the entire WORD_LIST list. */
4934 register WORD_LIST
*w
;
4937 for (w
= list
; w
; w
= w
->next
)
4940 w
->word
->word
= quote_string (t
);
4942 w
->word
->flags
|= W_HASQUOTEDNULL
; /* XXX - turn on W_HASQUOTEDNULL here? */
4943 w
->word
->flags
|= W_QUOTED
;
4955 s
= dequote_string (word
->word
);
4956 if (QUOTED_NULL (word
->word
))
4957 word
->flags
&= ~W_HASQUOTEDNULL
;
4964 /* De-quote quoted characters in each word in LIST. */
4970 register WORD_LIST
*tlist
;
4972 for (tlist
= list
; tlist
; tlist
= tlist
->next
)
4974 s
= dequote_string (tlist
->word
->word
);
4975 if (QUOTED_NULL (tlist
->word
->word
))
4976 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
4977 free (tlist
->word
->word
);
4978 tlist
->word
->word
= s
;
4983 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
4986 remove_quoted_escapes (string
)
4993 t
= dequote_escapes (string
);
5001 /* Remove quoted $IFS characters from STRING. Quoted IFS characters are
5002 added to protect them from word splitting, but we need to remove them
5003 if no word splitting takes place. This returns newly-allocated memory,
5004 so callers can use it to replace savestring(). */
5006 remove_quoted_ifs (string
)
5009 register size_t slen
;
5014 slen
= strlen (string
);
5015 send
= string
+ slen
;
5018 ret
= (char *)xmalloc (slen
+ 1);
5022 if (string
[i
] == CTLESC
)
5025 if (string
[i
] == 0 || isifs (string
[i
]) == 0)
5031 COPY_CHAR_I (ret
, j
, string
, send
, i
);
5039 remove_quoted_nulls (string
)
5042 register size_t slen
;
5043 register int i
, j
, prev_i
;
5046 if (strchr (string
, CTLNUL
) == 0) /* XXX */
5047 return string
; /* XXX */
5049 slen
= strlen (string
);
5054 if (string
[i
] == CTLESC
)
5056 /* Old code had j++, but we cannot assume that i == j at this
5057 point -- what if a CTLNUL has already been removed from the
5058 string? We don't want to drop the CTLESC or recopy characters
5059 that we've already copied down. */
5061 string
[j
++] = CTLESC
;
5065 else if (string
[i
] == CTLNUL
)
5072 ADVANCE_CHAR (string
, slen
, i
); /* COPY_CHAR_I? */
5075 do string
[j
++] = string
[prev_i
++]; while (prev_i
< i
);
5085 /* Perform quoted null character removal on each element of LIST.
5086 This modifies LIST. */
5088 word_list_remove_quoted_nulls (list
)
5091 register WORD_LIST
*t
;
5093 for (t
= list
; t
; t
= t
->next
)
5095 remove_quoted_nulls (t
->word
->word
);
5096 t
->word
->flags
&= ~W_HASQUOTEDNULL
;
5100 /* **************************************************************** */
5102 /* Functions for Matching and Removing Patterns */
5104 /* **************************************************************** */
5106 #if defined (HANDLE_MULTIBYTE)
5107 # ifdef INCLUDE_UNUSED
5108 static unsigned char *
5109 mb_getcharlens (string
, len
)
5113 int i
, offset
, last
;
5120 ret
= (unsigned char *)xmalloc (len
);
5121 memset (ret
, 0, len
);
5122 while (string
[last
])
5124 ADVANCE_CHAR (string
, len
, offset
);
5125 ret
[last
] = offset
- last
;
5133 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
5134 can have one of 4 values:
5135 RP_LONG_LEFT remove longest matching portion at start of PARAM
5136 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
5137 RP_LONG_RIGHT remove longest matching portion at end of PARAM
5138 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
5141 #define RP_LONG_LEFT 1
5142 #define RP_SHORT_LEFT 2
5143 #define RP_LONG_RIGHT 3
5144 #define RP_SHORT_RIGHT 4
5146 /* Returns its first argument if nothing matched; new memory otherwise */
5148 remove_upattern (param
, pattern
, op
)
5149 char *param
, *pattern
;
5152 register size_t len
;
5154 register char *p
, *ret
, c
;
5156 len
= STRLEN (param
);
5161 case RP_LONG_LEFT
: /* remove longest match at start */
5162 for (p
= end
; p
>= param
; p
--)
5165 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5168 return (savestring (p
));
5175 case RP_SHORT_LEFT
: /* remove shortest match at start */
5176 for (p
= param
; p
<= end
; p
++)
5179 if (strmatch (pattern
, param
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5182 return (savestring (p
));
5188 case RP_LONG_RIGHT
: /* remove longest match at end */
5189 for (p
= param
; p
<= end
; p
++)
5191 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5194 ret
= savestring (param
);
5201 case RP_SHORT_RIGHT
: /* remove shortest match at end */
5202 for (p
= end
; p
>= param
; p
--)
5204 if (strmatch (pattern
, p
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5207 ret
= savestring (param
);
5215 return (param
); /* no match, return original string */
5218 #if defined (HANDLE_MULTIBYTE)
5219 /* Returns its first argument if nothing matched; new memory otherwise */
5221 remove_wpattern (wparam
, wstrlen
, wpattern
, op
)
5232 case RP_LONG_LEFT
: /* remove longest match at start */
5233 for (n
= wstrlen
; n
>= 0; n
--)
5235 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5236 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5239 return (wcsdup (wparam
+ n
));
5245 case RP_SHORT_LEFT
: /* remove shortest match at start */
5246 for (n
= 0; n
<= wstrlen
; n
++)
5248 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5249 if (wcsmatch (wpattern
, wparam
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5252 return (wcsdup (wparam
+ n
));
5258 case RP_LONG_RIGHT
: /* remove longest match at end */
5259 for (n
= 0; n
<= wstrlen
; n
++)
5261 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5263 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5264 ret
= wcsdup (wparam
);
5271 case RP_SHORT_RIGHT
: /* remove shortest match at end */
5272 for (n
= wstrlen
; n
>= 0; n
--)
5274 if (wcsmatch (wpattern
, wparam
+ n
, FNMATCH_EXTFLAG
) != FNM_NOMATCH
)
5276 wc
= wparam
[n
]; wparam
[n
] = L
'\0';
5277 ret
= wcsdup (wparam
);
5285 return (wparam
); /* no match, return original string */
5287 #endif /* HANDLE_MULTIBYTE */
5290 remove_pattern (param
, pattern
, op
)
5291 char *param
, *pattern
;
5298 if (*param
== '\0' || pattern
== NULL
|| *pattern
== '\0') /* minor optimization */
5299 return (savestring (param
));
5301 #if defined (HANDLE_MULTIBYTE)
5304 wchar_t *ret
, *oret
;
5306 wchar_t *wparam
, *wpattern
;
5309 /* XXX - could optimize here by checking param and pattern for multibyte
5310 chars with mbsmbchar and calling remove_upattern. */
5312 n
= xdupmbstowcs (&wpattern
, NULL
, pattern
);
5313 if (n
== (size_t)-1)
5315 xret
= remove_upattern (param
, pattern
, op
);
5316 return ((xret
== param
) ? savestring (param
) : xret
);
5318 n
= xdupmbstowcs (&wparam
, NULL
, param
);
5320 if (n
== (size_t)-1)
5323 xret
= remove_upattern (param
, pattern
, op
);
5324 return ((xret
== param
) ? savestring (param
) : xret
);
5326 oret
= ret
= remove_wpattern (wparam
, n
, wpattern
, op
);
5327 /* Don't bother to convert wparam back to multibyte string if nothing
5328 matched; just return copy of original string */
5333 return (savestring (param
));
5340 xret
= (char *)xmalloc (n
+ 1);
5341 memset (&ps
, '\0', sizeof (mbstate_t));
5342 n
= wcsrtombs (xret
, (const wchar_t **)&ret
, n
, &ps
);
5343 xret
[n
] = '\0'; /* just to make sure */
5350 xret
= remove_upattern (param
, pattern
, op
);
5351 return ((xret
== param
) ? savestring (param
) : xret
);
5355 /* Match PAT anywhere in STRING and return the match boundaries.
5356 This returns 1 in case of a successful match, 0 otherwise. SP
5357 and EP are pointers into the string where the match begins and
5358 ends, respectively. MTYPE controls what kind of match is attempted.
5359 MATCH_BEG and MATCH_END anchor the match at the beginning and end
5360 of the string, respectively. The longest match is returned. */
5362 match_upattern (string
, pat
, mtype
, sp
, ep
)
5369 register char *p
, *p1
, *npat
;
5372 /* If the pattern doesn't match anywhere in the string, go ahead and
5373 short-circuit right away. A minor optimization, saves a bunch of
5374 unnecessary calls to strmatch (up to N calls for a string of N
5375 characters) if the match is unsuccessful. To preserve the semantics
5376 of the substring matches below, we make sure that the pattern has
5377 `*' as first and last character, making a new pattern if necessary. */
5378 /* XXX - check this later if I ever implement `**' with special meaning,
5379 since this will potentially result in `**' at the beginning or end */
5381 if (pat
[0] != '*' || (pat
[0] == '*' && pat
[1] == LPAREN
&& extended_glob
) || pat
[len
- 1] != '*')
5383 int unescaped_backslash
;
5386 p
= npat
= (char *)xmalloc (len
+ 3);
5388 if ((mtype
!= MATCH_BEG
) && (*p1
!= '*' || (*p1
== '*' && p1
[1] == LPAREN
&& extended_glob
)))
5393 /* Need to also handle a pattern that ends with an unescaped backslash.
5394 For right now, we ignore it because the pattern matching code will
5395 fail the match anyway */
5396 /* If the pattern ends with a `*' we leave it alone if it's preceded by
5397 an even number of backslashes, but if it's escaped by a backslash
5398 we need to add another `*'. */
5399 if ((mtype
!= MATCH_END
) && (p1
[-1] == '*' && (unescaped_backslash
= p1
[-2] == '\\')))
5402 while (pp
>= pat
&& *pp
-- == '\\')
5403 unescaped_backslash
= 1 - unescaped_backslash
;
5404 if (unescaped_backslash
)
5407 else if (mtype
!= MATCH_END
&& p1
[-1] != '*')
5410 if (p1
[-1] != '*' || p1
[-2] == '\\')
5417 c
= strmatch (npat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
5420 if (c
== FNM_NOMATCH
)
5423 len
= STRLEN (string
);
5426 mlen
= umatchlen (pat
, len
);
5427 if (mlen
> (int)len
)
5433 for (p
= string
; p
<= end
; p
++)
5435 if (match_pattern_char (pat
, p
, FNMATCH_IGNCASE
))
5437 p1
= (mlen
== -1) ? end
: p
+ mlen
;
5438 /* p1 - p = length of portion of string to be considered
5439 p = current position in string
5440 mlen = number of characters consumed by match (-1 for entire string)
5442 we want to break immediately if the potential match len
5443 is greater than the number of characters remaining in the
5448 for ( ; p1
>= p
; p1
--)
5450 c
= *p1
; *p1
= '\0';
5451 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5460 /* If MLEN != -1, we have a fixed length pattern. */
5471 if (match_pattern_char (pat
, string
, FNMATCH_IGNCASE
) == 0)
5474 for (p
= (mlen
== -1) ? end
: string
+ mlen
; p
>= string
; p
--)
5477 if (strmatch (pat
, string
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5485 /* If MLEN != -1, we have a fixed length pattern. */
5493 for (p
= end
- ((mlen
== -1) ? len
: mlen
); p
<= end
; p
++)
5495 if (strmatch (pat
, p
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5501 /* If MLEN != -1, we have a fixed length pattern. */
5512 #if defined (HANDLE_MULTIBYTE)
5514 #define WFOLD(c) (match_ignore_case && iswupper (c) ? towlower (c) : (c))
5516 /* Match WPAT anywhere in WSTRING and return the match boundaries.
5517 This returns 1 in case of a successful match, 0 otherwise. Wide
5518 character version. */
5520 match_wpattern (wstring
, indices
, wstrlen
, wpat
, mtype
, sp
, ep
)
5528 wchar_t wc
, *wp
, *nwpat
, *wp1
;
5531 int n
, n1
, n2
, simple
;
5533 simple
= (wpat
[0] != L
'\\' && wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'[');
5534 #if defined (EXTENDED_GLOB)
5536 simple
&= (wpat
[1] != L
'(' || (wpat
[0] != L
'*' && wpat
[0] != L
'?' && wpat
[0] != L
'+' && wpat
[0] != L
'!' && wpat
[0] != L
'@')); /*)*/
5539 /* If the pattern doesn't match anywhere in the string, go ahead and
5540 short-circuit right away. A minor optimization, saves a bunch of
5541 unnecessary calls to strmatch (up to N calls for a string of N
5542 characters) if the match is unsuccessful. To preserve the semantics
5543 of the substring matches below, we make sure that the pattern has
5544 `*' as first and last character, making a new pattern if necessary. */
5545 len
= wcslen (wpat
);
5546 if (wpat
[0] != L
'*' || (wpat
[0] == L
'*' && wpat
[1] == WLPAREN
&& extended_glob
) || wpat
[len
- 1] != L
'*')
5548 int unescaped_backslash
;
5551 wp
= nwpat
= (wchar_t *)xmalloc ((len
+ 3) * sizeof (wchar_t));
5553 if (*wp1
!= L
'*' || (*wp1
== '*' && wp1
[1] == WLPAREN
&& extended_glob
))
5555 while (*wp1
!= L
'\0')
5558 /* See comments above in match_upattern. */
5559 if (wp1
[-1] == L
'*' && (unescaped_backslash
= wp1
[-2] == L
'\\'))
5562 while (wpp
>= wpat
&& *wpp
-- == L
'\\')
5563 unescaped_backslash
= 1 - unescaped_backslash
;
5564 if (unescaped_backslash
)
5567 else if (wp1
[-1] != L
'*')
5570 if (wp1
[-1] != L
'*' || wp1
[-2] == L
'\\')
5577 len
= wcsmatch (nwpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
);
5580 if (len
== FNM_NOMATCH
)
5583 mlen
= wmatchlen (wpat
, wstrlen
);
5584 if (mlen
> (int)wstrlen
)
5587 /* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
5591 for (n
= 0; n
<= wstrlen
; n
++)
5593 n2
= simple
? (WFOLD(*wpat
) == WFOLD(wstring
[n
])) : match_pattern_wchar (wpat
, wstring
+ n
, FNMATCH_IGNCASE
);
5596 n1
= (mlen
== -1) ? wstrlen
: n
+ mlen
;
5600 for ( ; n1
>= n
; n1
--)
5602 wc
= wstring
[n1
]; wstring
[n1
] = L
'\0';
5603 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5611 /* If MLEN != -1, we have a fixed length pattern. */
5621 if (match_pattern_wchar (wpat
, wstring
, FNMATCH_IGNCASE
) == 0)
5624 for (n
= (mlen
== -1) ? wstrlen
: mlen
; n
>= 0; n
--)
5626 wc
= wstring
[n
]; wstring
[n
] = L
'\0';
5627 if (wcsmatch (wpat
, wstring
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5635 /* If MLEN != -1, we have a fixed length pattern. */
5643 for (n
= wstrlen
- ((mlen
== -1) ? wstrlen
: mlen
); n
<= wstrlen
; n
++)
5645 if (wcsmatch (wpat
, wstring
+ n
, FNMATCH_EXTFLAG
| FNMATCH_IGNCASE
) == 0)
5648 *ep
= indices
[wstrlen
];
5651 /* If MLEN != -1, we have a fixed length pattern. */
5662 #endif /* HANDLE_MULTIBYTE */
5665 match_pattern (string
, pat
, mtype
, sp
, ep
)
5670 #if defined (HANDLE_MULTIBYTE)
5673 wchar_t *wstring
, *wpat
;
5677 if (string
== 0 || pat
== 0 || *pat
== 0)
5680 #if defined (HANDLE_MULTIBYTE)
5683 if (mbsmbchar (string
) == 0 && mbsmbchar (pat
) == 0)
5684 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5686 n
= xdupmbstowcs (&wpat
, NULL
, pat
);
5687 if (n
== (size_t)-1)
5688 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5689 n
= xdupmbstowcs (&wstring
, &indices
, string
);
5690 if (n
== (size_t)-1)
5693 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5695 ret
= match_wpattern (wstring
, indices
, n
, wpat
, mtype
, sp
, ep
);
5705 return (match_upattern (string
, pat
, mtype
, sp
, ep
));
5709 getpatspec (c
, value
)
5714 return ((*value
== '#') ? RP_LONG_LEFT
: RP_SHORT_LEFT
);
5716 return ((*value
== '%') ? RP_LONG_RIGHT
: RP_SHORT_RIGHT
);
5719 /* Posix.2 says that the WORD should be run through tilde expansion,
5720 parameter expansion, command substitution and arithmetic expansion.
5721 This leaves the result quoted, so quote_string_for_globbing () has
5722 to be called to fix it up for strmatch (). If QUOTED is non-zero,
5723 it means that the entire expression was enclosed in double quotes.
5724 This means that quoting characters in the pattern do not make any
5725 special pattern characters quoted. For example, the `*' in the
5726 following retains its special meaning: "${foo#'*'}". */
5728 getpattern (value
, quoted
, expandpat
)
5730 int quoted
, expandpat
;
5737 /* There is a problem here: how to handle single or double quotes in the
5738 pattern string when the whole expression is between double quotes?
5739 POSIX.2 says that enclosing double quotes do not cause the pattern to
5740 be quoted, but does that leave us a problem with @ and array[@] and their
5741 expansions inside a pattern? */
5743 if (expandpat
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *tword
)
5746 pat
= string_extract_double_quoted (tword
, &i
, SX_STRIPDQ
);
5752 /* expand_string_for_pat () leaves WORD quoted and does not perform
5754 l
= *value
? expand_string_for_pat (value
,
5755 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) ? Q_PATQUOTE
: quoted
,
5756 (int *)NULL
, (int *)NULL
)
5759 word_list_remove_quoted_nulls (l
);
5760 pat
= string_list (l
);
5764 tword
= quote_string_for_globbing (pat
, QGLOB_CVTNULL
);
5772 /* Handle removing a pattern from a string as a result of ${name%[%]value}
5773 or ${name#[#]value}. */
5775 variable_remove_pattern (value
, pattern
, patspec
, quoted
)
5776 char *value
, *pattern
;
5777 int patspec
, quoted
;
5781 tword
= remove_pattern (value
, pattern
, patspec
);
5788 list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
)
5791 int patspec
, itype
, quoted
;
5797 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
5799 tword
= remove_pattern (l
->word
->word
, pattern
, patspec
);
5800 w
= alloc_word_desc ();
5801 w
->word
= tword
? tword
: savestring ("");
5802 new = make_word_list (w
, new);
5805 l
= REVERSE_LIST (new, WORD_LIST
*);
5806 tword
= string_list_pos_params (itype
, l
, quoted
, 0);
5813 parameter_list_remove_pattern (itype
, pattern
, patspec
, quoted
)
5816 int patspec
, quoted
;
5821 list
= list_rest_of_args ();
5823 return ((char *)NULL
);
5824 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5825 dispose_words (list
);
5829 #if defined (ARRAY_VARS)
5831 array_remove_pattern (var
, pattern
, patspec
, starsub
, quoted
)
5835 int starsub
; /* so we can figure out how it's indexed */
5845 v
= var
; /* XXX - for now */
5847 itype
= starsub
? '*' : '@';
5849 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
5850 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
5852 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
5854 return ((char *)NULL
);
5855 ret
= list_remove_pattern (list
, pattern
, patspec
, itype
, quoted
);
5856 dispose_words (list
);
5860 #endif /* ARRAY_VARS */
5863 parameter_brace_remove_pattern (varname
, value
, estatep
, patstr
, rtype
, quoted
, flags
)
5864 char *varname
, *value
;
5865 array_eltstate_t
*estatep
;
5867 int rtype
, quoted
, flags
;
5869 int vtype
, patspec
, starsub
;
5870 char *temp1
, *val
, *pattern
, *oname
;
5874 return ((char *)NULL
);
5876 oname
= this_command_name
;
5877 this_command_name
= varname
;
5879 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
5882 this_command_name
= oname
;
5883 return ((char *)NULL
);
5886 starsub
= vtype
& VT_STARSUB
;
5887 vtype
&= ~VT_STARSUB
;
5889 patspec
= getpatspec (rtype
, patstr
);
5890 if (patspec
== RP_LONG_LEFT
|| patspec
== RP_LONG_RIGHT
)
5893 /* Need to pass getpattern newly-allocated memory in case of expansion --
5894 the expansion code will free the passed string on an error. */
5895 temp1
= savestring (patstr
);
5896 pattern
= getpattern (temp1
, quoted
, 1);
5899 temp1
= (char *)NULL
; /* shut up gcc */
5903 case VT_ARRAYMEMBER
:
5904 temp1
= remove_pattern (val
, pattern
, patspec
);
5905 if (vtype
== VT_VARIABLE
)
5909 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
5910 ? quote_string (temp1
)
5911 : quote_escapes (temp1
);
5916 #if defined (ARRAY_VARS)
5918 temp1
= array_remove_pattern (v
, pattern
, patspec
, starsub
, quoted
);
5919 if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5921 val
= quote_escapes (temp1
);
5928 temp1
= parameter_list_remove_pattern (varname
[0], pattern
, patspec
, quoted
);
5929 if (temp1
&& quoted
== 0 && ifs_is_null
)
5931 /* Posix interp 888 */
5933 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
5935 val
= quote_escapes (temp1
);
5942 this_command_name
= oname
;
5948 #if defined (PROCESS_SUBSTITUTION)
5950 static void reap_some_procsubs
PARAMS((int));
5952 /*****************************************************************/
5954 /* Hacking Process Substitution */
5956 /*****************************************************************/
5958 #if !defined (HAVE_DEV_FD)
5959 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
5960 of FIFOs the shell has open. unlink_fifo_list will walk the list and
5961 unlink the ones that don't have a living process on the other end.
5962 unlink_all_fifos will walk the list and unconditionally unlink them, trying
5963 to open and close the FIFO first to release any child processes sleeping on
5964 the FIFO. add_fifo_list adds the name of an open FIFO to the list.
5965 NFIFO is a count of the number of FIFOs in the list. */
5966 #define FIFO_INCR 20
5968 /* PROC value of -1 means the process has been reaped and the FIFO needs to
5969 be removed. PROC value of 0 means the slot is unused. */
5975 static struct temp_fifo
*fifo_list
= (struct temp_fifo
*)NULL
;
5977 static int fifo_list_size
;
5984 for (i
= 0; i
< fifo_list_size
; i
++)
5986 if (fifo_list
[i
].file
)
5987 free (fifo_list
[i
].file
);
5988 fifo_list
[i
].file
= NULL
;
5989 fifo_list
[i
].proc
= 0;
5995 copy_fifo_list (sizep
)
6000 return (void *)NULL
;
6004 add_fifo_list (pathname
)
6009 if (nfifo
>= fifo_list_size
- 1)
6011 osize
= fifo_list_size
;
6012 fifo_list_size
+= FIFO_INCR
;
6013 fifo_list
= (struct temp_fifo
*)xrealloc (fifo_list
,
6014 fifo_list_size
* sizeof (struct temp_fifo
));
6015 for (i
= osize
; i
< fifo_list_size
; i
++)
6017 fifo_list
[i
].file
= (char *)NULL
;
6018 fifo_list
[i
].proc
= 0; /* unused */
6022 fifo_list
[nfifo
].file
= savestring (pathname
);
6030 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
6032 unlink (fifo_list
[i
].file
);
6033 free (fifo_list
[i
].file
);
6034 fifo_list
[i
].file
= (char *)NULL
;
6035 fifo_list
[i
].proc
= 0;
6047 for (i
= saved
= 0; i
< nfifo
; i
++)
6049 if ((fifo_list
[i
].proc
== (pid_t
)-1) || (fifo_list
[i
].proc
> 0 && (kill(fifo_list
[i
].proc
, 0) == -1)))
6051 unlink (fifo_list
[i
].file
);
6052 free (fifo_list
[i
].file
);
6053 fifo_list
[i
].file
= (char *)NULL
;
6054 fifo_list
[i
].proc
= 0;
6060 /* If we didn't remove some of the FIFOs, compact the list. */
6063 for (i
= j
= 0; i
< nfifo
; i
++)
6064 if (fifo_list
[i
].file
)
6068 fifo_list
[j
].file
= fifo_list
[i
].file
;
6069 fifo_list
[j
].proc
= fifo_list
[i
].proc
;
6070 fifo_list
[i
].file
= (char *)NULL
;
6071 fifo_list
[i
].proc
= 0;
6089 for (i
= 0; i
< nfifo
; i
++)
6091 fifo_list
[i
].proc
= (pid_t
)-1;
6092 #if defined (O_NONBLOCK)
6093 fd
= open (fifo_list
[i
].file
, O_RDWR
|O_NONBLOCK
);
6105 /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
6106 from some point in the past, and close all open FIFOs in fifo_list
6107 that are not marked as active in LIST. If LIST is NULL, close
6108 everything in fifo_list. LSIZE is the number of elements in LIST, in
6109 case it's larger than fifo_list_size (size of fifo_list). */
6111 close_new_fifos (list
, lsize
)
6120 unlink_fifo_list ();
6124 for (plist
= (char *)list
, i
= 0; i
< lsize
; i
++)
6125 if (plist
[i
] == 0 && i
< fifo_list_size
&& fifo_list
[i
].proc
!= -1)
6128 for (i
= lsize
; i
< fifo_list_size
; i
++)
6133 find_procsub_child (pid
)
6138 for (i
= 0; i
< nfifo
; i
++)
6139 if (fifo_list
[i
].proc
== pid
)
6145 set_procsub_status (ind
, pid
, status
)
6150 if (ind
>= 0 && ind
< nfifo
)
6151 fifo_list
[ind
].proc
= (pid_t
)-1; /* sentinel */
6154 /* If we've marked the process for this procsub as dead, close the
6155 associated file descriptor and delete the FIFO. */
6157 reap_some_procsubs (max
)
6162 for (i
= 0; i
< max
; i
++)
6163 if (fifo_list
[i
].proc
== (pid_t
)-1) /* reaped */
6170 reap_some_procsubs (nfifo
);
6180 for (i
= 0; i
< nfifo
; i
++)
6182 if (fifo_list
[i
].proc
!= (pid_t
)-1 && fifo_list
[i
].proc
> 0)
6184 r
= wait_for (fifo_list
[i
].proc
, 0);
6185 save_proc_status (fifo_list
[i
].proc
, r
);
6186 fifo_list
[i
].proc
= (pid_t
)-1;
6209 tname
= sh_mktmpname ("sh-np", MT_USERANDOM
|MT_USETMPDIR
);
6210 if (mkfifo (tname
, 0600) < 0)
6213 return ((char *)NULL
);
6216 add_fifo_list (tname
);
6220 #else /* HAVE_DEV_FD */
6222 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
6223 has open to children. NFDS is a count of the number of bits currently
6224 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
6226 /* dev_fd_list[I] value of -1 means the process has been reaped and file
6227 descriptor I needs to be closed. Value of 0 means the slot is unused. */
6229 static pid_t
*dev_fd_list
= (pid_t
*)NULL
;
6231 static int totfds
; /* The highest possible number of open files. */
6252 for (i
= 0; nfds
&& i
< totfds
; i
++)
6259 copy_fifo_list (sizep
)
6264 if (nfds
== 0 || totfds
== 0)
6268 return (void *)NULL
;
6273 ret
= xmalloc (totfds
* sizeof (pid_t
));
6274 return (memcpy (ret
, dev_fd_list
, totfds
* sizeof (pid_t
)));
6281 if (dev_fd_list
== 0 || fd
>= totfds
)
6286 totfds
= getdtablesize ();
6287 if (totfds
< 0 || totfds
> 256)
6292 dev_fd_list
= (pid_t
*)xrealloc (dev_fd_list
, totfds
* sizeof (dev_fd_list
[0]));
6293 /* XXX - might need a loop for this */
6294 memset (dev_fd_list
+ ofds
, '\0', (totfds
- ofds
) * sizeof (pid_t
));
6297 dev_fd_list
[fd
] = 1; /* marker; updated later */
6304 return 0; /* used for cleanup; not needed with /dev/fd */
6317 if (dev_fd_list
[fd
])
6320 dev_fd_list
[fd
] = 0;
6333 for (i
= totfds
-1; nfds
&& i
>= 0; i
--)
6342 unlink_fifo_list ();
6345 /* Take LIST, which is a snapshot copy of dev_fd_list from some point in
6346 the past, and close all open fds in dev_fd_list that are not marked
6347 as open in LIST. If LIST is NULL, close everything in dev_fd_list.
6348 LSIZE is the number of elements in LIST, in case it's larger than
6349 totfds (size of dev_fd_list). */
6351 close_new_fifos (list
, lsize
)
6360 unlink_fifo_list ();
6364 for (plist
= (pid_t
*)list
, i
= 0; i
< lsize
; i
++)
6365 if (plist
[i
] == 0 && i
< totfds
&& dev_fd_list
[i
])
6368 for (i
= lsize
; i
< totfds
; i
++)
6373 find_procsub_child (pid
)
6381 for (i
= 0; i
< totfds
; i
++)
6382 if (dev_fd_list
[i
] == pid
)
6389 set_procsub_status (ind
, pid
, status
)
6394 if (ind
>= 0 && ind
< totfds
)
6395 dev_fd_list
[ind
] = (pid_t
)-1; /* sentinel */
6398 /* If we've marked the process for this procsub as dead, close the
6399 associated file descriptor. */
6401 reap_some_procsubs (max
)
6406 for (i
= 0; nfds
> 0 && i
< max
; i
++)
6407 if (dev_fd_list
[i
] == (pid_t
)-1)
6414 reap_some_procsubs (totfds
);
6424 for (i
= 0; nfds
> 0 && i
< totfds
; i
++)
6426 if (dev_fd_list
[i
] != (pid_t
)-1 && dev_fd_list
[i
] > 0)
6428 r
= wait_for (dev_fd_list
[i
], 0);
6429 save_proc_status (dev_fd_list
[i
], r
);
6430 dev_fd_list
[i
] = (pid_t
)-1;
6436 #if defined (NOTDEF)
6437 print_dev_fd_list ()
6441 fprintf (stderr
, "pid %ld: dev_fd_list:", (long)getpid ());
6444 for (i
= 0; i
< totfds
; i
++)
6447 fprintf (stderr
, " %d", i
);
6449 fprintf (stderr
, "\n");
6454 make_dev_fd_filename (fd
)
6457 char *ret
, intbuf
[INT_STRLEN_BOUND (int) + 1], *p
;
6459 ret
= (char *)xmalloc (sizeof (DEV_FD_PREFIX
) + 8);
6461 strcpy (ret
, DEV_FD_PREFIX
);
6462 p
= inttostr (fd
, intbuf
, sizeof (intbuf
));
6463 strcpy (ret
+ sizeof (DEV_FD_PREFIX
) - 1, p
);
6469 #endif /* HAVE_DEV_FD */
6471 /* Return a filename that will open a connection to the process defined by
6472 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
6473 a filename in /dev/fd corresponding to a descriptor that is one of the
6474 ends of the pipe. If not defined, we use named pipes on systems that have
6475 them. Systems without /dev/fd and named pipes are out of luck.
6477 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
6478 use the read end of the pipe and dup that file descriptor to fd 0 in
6479 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
6480 writing or use the write end of the pipe in the child, and dup that
6481 file descriptor to fd 1 in the child. The parent does the opposite. */
6484 process_substitute (string
, open_for_read_in_child
)
6486 int open_for_read_in_child
;
6489 int fd
, result
, rc
, function_value
;
6491 #if defined (HAVE_DEV_FD)
6492 int parent_pipe_fd
, child_pipe_fd
;
6494 #endif /* HAVE_DEV_FD */
6495 #if defined (JOB_CONTROL)
6496 pid_t old_pipeline_pgrp
;
6499 if (!string
|| !*string
|| wordexp_only
)
6500 return ((char *)NULL
);
6502 #if !defined (HAVE_DEV_FD)
6503 pathname
= make_named_pipe ();
6504 #else /* HAVE_DEV_FD */
6505 if (pipe (fildes
) < 0)
6507 sys_error ("%s", _("cannot make pipe for process substitution"));
6508 return ((char *)NULL
);
6510 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
6511 the pipe in the parent, otherwise the read end. */
6512 parent_pipe_fd
= fildes
[open_for_read_in_child
];
6513 child_pipe_fd
= fildes
[1 - open_for_read_in_child
];
6514 /* Move the parent end of the pipe to some high file descriptor, to
6515 avoid clashes with FDs used by the script. */
6516 parent_pipe_fd
= move_to_high_fd (parent_pipe_fd
, 1, 64);
6518 pathname
= make_dev_fd_filename (parent_pipe_fd
);
6519 #endif /* HAVE_DEV_FD */
6523 sys_error ("%s", _("cannot make pipe for process substitution"));
6524 return ((char *)NULL
);
6527 old_pid
= last_made_pid
;
6529 #if defined (JOB_CONTROL)
6530 old_pipeline_pgrp
= pipeline_pgrp
;
6531 if (pipeline_pgrp
== 0 || (subshell_environment
& (SUBSHELL_PIPE
|SUBSHELL_FORK
|SUBSHELL_ASYNC
)) == 0)
6532 pipeline_pgrp
= shell_pgrp
;
6534 #endif /* JOB_CONTROL */
6536 pid
= make_child ((char *)NULL
, FORK_ASYNC
);
6540 int old_interactive
;
6542 old_interactive
= interactive
;
6544 /* The currently-executing shell is not interactive */
6547 reset_terminating_signals (); /* XXX */
6548 free_pushed_string_input ();
6549 /* Cancel traps, in trap.c. */
6550 restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
6551 subshell_environment
&= ~SUBSHELL_IGNTRAP
;
6552 QUIT
; /* catch any interrupts we got post-fork */
6553 setup_async_signals ();
6555 if (open_for_read_in_child
== 0 && old_interactive
&& (bash_input
.type
== st_stdin
|| bash_input
.type
== st_stream
))
6556 async_redirect_stdin ();
6559 subshell_environment
|= SUBSHELL_COMSUB
|SUBSHELL_PROCSUB
|SUBSHELL_ASYNC
;
6561 /* We don't inherit the verbose option for command substitutions now, so
6562 let's try it for process substitutions. */
6563 change_flag ('v', FLAG_OFF
);
6565 /* if we're expanding a redirection, we shouldn't have access to the
6566 temporary environment, but commands in the subshell should have
6567 access to their own temporary environment. */
6568 if (expanding_redir
)
6569 flush_temporary_env ();
6572 #if defined (JOB_CONTROL)
6573 set_sigchld_handler ();
6574 stop_making_children ();
6575 /* XXX - should we only do this in the parent? (as in command subst) */
6576 pipeline_pgrp
= old_pipeline_pgrp
;
6578 stop_making_children ();
6579 #endif /* JOB_CONTROL */
6583 sys_error ("%s", _("cannot make child for process substitution"));
6585 #if defined (HAVE_DEV_FD)
6586 close (parent_pipe_fd
);
6587 close (child_pipe_fd
);
6588 #endif /* HAVE_DEV_FD */
6589 #if defined (JOB_CONTROL)
6590 restore_pipeline (1);
6592 return ((char *)NULL
);
6597 #if defined (JOB_CONTROL)
6598 last_procsub_child
= restore_pipeline (0);
6599 /* We assume that last_procsub_child->next == last_procsub_child because
6600 of how jobs.c:add_process() works. */
6601 last_procsub_child
->next
= 0;
6602 procsub_add (last_procsub_child
);
6605 #if defined (HAVE_DEV_FD)
6606 dev_fd_list
[parent_pipe_fd
] = pid
;
6608 fifo_list
[nfifo
-1].proc
= pid
;
6611 last_made_pid
= old_pid
;
6613 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6615 #endif /* JOB_CONTROL && PGRP_PIPE */
6617 #if defined (HAVE_DEV_FD)
6618 close (child_pipe_fd
);
6619 #endif /* HAVE_DEV_FD */
6624 set_sigint_handler ();
6626 #if defined (JOB_CONTROL)
6627 /* make sure we don't have any job control */
6628 set_job_control (0);
6630 /* Clear out any existing list of process substitutions */
6633 /* The idea is that we want all the jobs we start from an async process
6634 substitution to be in the same process group, but not the same pgrp
6635 as our parent shell, since we don't want to affect our parent shell's
6636 jobs if we get a SIGHUP and end up calling hangup_all_jobs, for example.
6637 If pipeline_pgrp != shell_pgrp, we assume that there is a job control
6638 shell somewhere in our parent process chain (since make_child initializes
6639 pipeline_pgrp to shell_pgrp if job_control == 0). What we do in this
6640 case is to set pipeline_pgrp to our PID, so all jobs started by this
6641 process have that same pgrp and we are basically the process group leader.
6642 This should not have negative effects on child processes surviving
6643 after we exit, since we wait for the children we create, but that is
6644 something to watch for. */
6646 if (pipeline_pgrp
!= shell_pgrp
)
6647 pipeline_pgrp
= getpid ();
6648 #endif /* JOB_CONTROL */
6650 #if !defined (HAVE_DEV_FD)
6651 /* Open the named pipe in the child. */
6652 fd
= open (pathname
, open_for_read_in_child
? O_RDONLY
: O_WRONLY
);
6655 /* Two separate strings for ease of translation. */
6656 if (open_for_read_in_child
)
6657 sys_error (_("cannot open named pipe %s for reading"), pathname
);
6659 sys_error (_("cannot open named pipe %s for writing"), pathname
);
6663 if (open_for_read_in_child
)
6665 if (sh_unset_nodelay_mode (fd
) < 0)
6667 sys_error (_("cannot reset nodelay mode for fd %d"), fd
);
6671 #else /* HAVE_DEV_FD */
6673 #endif /* HAVE_DEV_FD */
6675 /* Discard buffered stdio output before replacing the underlying file
6677 if (open_for_read_in_child
== 0)
6680 if (dup2 (fd
, open_for_read_in_child
? 0 : 1) < 0)
6682 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname
,
6683 open_for_read_in_child
? 0 : 1);
6687 if (fd
!= (open_for_read_in_child
? 0 : 1))
6690 /* Need to close any files that this process has open to pipes inherited
6692 if (current_fds_to_close
)
6694 close_fd_bitmap (current_fds_to_close
);
6695 current_fds_to_close
= (struct fd_bitmap
*)NULL
;
6698 #if defined (HAVE_DEV_FD)
6699 /* Make sure we close the parent's end of the pipe and clear the slot
6700 in the fd list so it is not closed later, if reallocated by, for
6701 instance, pipe(2). */
6702 close (parent_pipe_fd
);
6703 dev_fd_list
[parent_pipe_fd
] = 0;
6704 #endif /* HAVE_DEV_FD */
6706 /* subshells shouldn't have this flag, which controls using the temporary
6707 environment for variable lookups. We have already flushed the temporary
6708 environment above in the case we're expanding a redirection, so processes
6709 executed by this command need to be able to set it independently of their
6711 expanding_redir
= 0;
6713 remove_quoted_escapes (string
);
6715 startup_state
= 2; /* see if we can avoid a fork */
6716 parse_and_execute_level
= 0;
6718 /* Give process substitution a place to jump back to on failure,
6719 so we don't go back up to main (). */
6720 result
= setjmp_nosigs (top_level
);
6722 /* If we're running a process substitution inside a shell function,
6723 trap `return' so we don't return from the function in the subshell
6724 and go off to never-never land. */
6725 if (result
== 0 && return_catch_flag
)
6726 function_value
= setjmp_nosigs (return_catch
);
6730 if (result
== ERREXIT
)
6731 rc
= last_command_exit_value
;
6732 else if (result
== EXITPROG
|| result
== EXITBLTIN
)
6733 rc
= last_command_exit_value
;
6735 rc
= EXECUTION_FAILURE
;
6736 else if (function_value
)
6737 rc
= return_catch_value
;
6741 rc
= parse_and_execute (string
, "process substitution", (SEVAL_NONINT
|SEVAL_NOHIST
));
6742 /* leave subshell level intact for any exit trap */
6745 #if !defined (HAVE_DEV_FD)
6746 /* Make sure we close the named pipe in the child before we exit. */
6747 close (open_for_read_in_child
? 0 : 1);
6748 #endif /* !HAVE_DEV_FD */
6750 last_command_exit_value
= rc
;
6751 rc
= run_exit_trap ();
6755 #endif /* PROCESS_SUBSTITUTION */
6757 /***********************************/
6759 /* Command Substitution */
6761 /***********************************/
6763 #define COMSUB_PIPEBUF 4096
6766 optimize_cat_file (r
, quoted
, flags
, flagp
)
6768 int quoted
, flags
, *flagp
;
6773 fd
= open_redir_file (r
, (char **)0);
6775 return &expand_param_error
;
6777 ret
= read_comsub (fd
, quoted
, flags
, flagp
);
6784 read_comsub (fd
, quoted
, flags
, rflag
)
6785 int fd
, quoted
, flags
;
6788 char *istring
, buf
[COMSUB_PIPEBUF
], *bufp
;
6789 int c
, tflag
, skip_ctlesc
, skip_ctlnul
;
6791 size_t istring_index
;
6792 size_t istring_size
;
6795 #if defined (HANDLE_MULTIBYTE)
6802 istring
= (char *)NULL
;
6803 istring_index
= istring_size
= bufn
= tflag
= 0;
6805 skip_ctlesc
= ifs_cmap
[CTLESC
];
6806 skip_ctlnul
= ifs_cmap
[CTLNUL
];
6808 mb_cur_max
= MB_CUR_MAX
;
6811 /* Read the output of the command through the pipe. */
6818 bufn
= zread (fd
, buf
, sizeof (buf
));
6830 internal_warning ("%s", _("command substitution: ignored null byte in input"));
6837 /* Add the character to ISTRING, possibly after resizing it. */
6838 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, mb_cur_max
+1, istring_size
, 512);
6840 /* This is essentially quote_string inline */
6841 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) /* || c == CTLESC || c == CTLNUL */)
6842 istring
[istring_index
++] = CTLESC
;
6843 else if ((flags
& PF_ASSIGNRHS
) && skip_ctlesc
&& c
== CTLESC
)
6844 istring
[istring_index
++] = CTLESC
;
6845 /* Escape CTLESC and CTLNUL in the output to protect those characters
6846 from the rest of the word expansions (word splitting and globbing.)
6847 This is essentially quote_escapes inline. */
6848 else if (skip_ctlesc
== 0 && c
== CTLESC
)
6849 istring
[istring_index
++] = CTLESC
;
6850 else if ((skip_ctlnul
== 0 && c
== CTLNUL
) || (c
== ' ' && (ifs_value
&& *ifs_value
== 0)))
6851 istring
[istring_index
++] = CTLESC
;
6853 #if defined (HANDLE_MULTIBYTE)
6854 if ((locale_utf8locale
&& (c
& 0x80)) ||
6855 (locale_utf8locale
== 0 && mb_cur_max
> 1 && (unsigned char)c
> 127))
6857 /* read a multibyte character from buf */
6858 /* punt on the hard case for now */
6859 memset (&ps
, '\0', sizeof (mbstate_t));
6860 mblen
= mbrtowc (&wc
, bufp
-1, bufn
, &ps
);
6861 if (MB_INVALIDCH (mblen
) || mblen
== 0 || mblen
== 1)
6862 istring
[istring_index
++] = c
;
6865 istring
[istring_index
++] = c
;
6866 for (i
= 0; i
< mblen
-1; i
++)
6867 istring
[istring_index
++] = *bufp
++;
6874 istring
[istring_index
++] = c
;
6878 istring
[istring_index
] = '\0';
6880 /* If we read no output, just return now and save ourselves some
6882 if (istring_index
== 0)
6887 return (char *)NULL
;
6890 /* Strip trailing newlines from the output of the command. */
6891 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
6893 while (istring_index
> 0)
6895 if (istring
[istring_index
- 1] == '\n')
6899 /* If the newline was quoted, remove the quoting char. */
6900 if (istring
[istring_index
- 1] == CTLESC
)
6906 istring
[istring_index
] = '\0';
6909 strip_trailing (istring
, istring_index
- 1, 1);
6916 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
6917 contained string possibly quoted. */
6919 command_substitute (string
, quoted
, flags
)
6924 pid_t pid
, old_pid
, old_pipeline_pgrp
, old_async_pid
;
6926 int result
, fildes
[2], function_value
, pflags
, rc
, tflag
, fork_flags
;
6930 istring
= (char *)NULL
;
6932 /* Don't fork () if there is no need to. In the case of no command to
6933 run, just return NULL. */
6934 for (s
= string
; s
&& *s
&& (shellblank (*s
) || *s
== '\n'); s
++)
6936 if (s
== 0 || *s
== 0)
6937 return ((WORD_DESC
*)NULL
);
6939 if (*s
== '<' && (s
[1] != '<' && s
[1] != '>' && s
[1] != '&'))
6943 cmd
= parse_string_to_command (string
, 0); /* XXX - flags */
6944 if (cmd
&& can_optimize_cat_file (cmd
))
6947 istring
= optimize_cat_file (cmd
->value
.Simple
->redirects
, quoted
, flags
, &tflag
);
6948 if (istring
== &expand_param_error
)
6950 last_command_exit_value
= EXECUTION_FAILURE
;
6954 last_command_exit_value
= EXECUTION_SUCCESS
; /* compat */
6955 last_command_subst_pid
= dollar_dollar_pid
;
6957 dispose_command (cmd
);
6958 ret
= alloc_word_desc ();
6959 ret
->word
= istring
;
6964 dispose_command (cmd
);
6967 if (wordexp_only
&& read_but_dont_execute
)
6969 last_command_exit_value
= EX_WEXPCOMSUB
;
6970 jump_to_top_level (EXITPROG
);
6973 /* We're making the assumption here that the command substitution will
6974 eventually run a command from the file system. Since we'll run
6975 maybe_make_export_env in this subshell before executing that command,
6976 the parent shell and any other shells it starts will have to remake
6977 the environment. If we make it before we fork, other shells won't
6978 have to. Don't bother if we have any temporary variable assignments,
6979 though, because the export environment will be remade after this
6980 command completes anyway, but do it if all the words to be expanded
6981 are variable assignments. */
6982 if (subst_assign_varlist
== 0 || garglist
== 0)
6983 maybe_make_export_env (); /* XXX */
6985 /* Flags to pass to parse_and_execute() */
6986 pflags
= (interactive
&& sourcelevel
== 0) ? SEVAL_RESETLINE
: 0;
6988 old_pid
= last_made_pid
;
6990 /* Pipe the output of executing STRING into the current shell. */
6991 if (pipe (fildes
) < 0)
6993 sys_error ("%s", _("cannot make pipe for command substitution"));
6997 #if defined (JOB_CONTROL)
6998 old_pipeline_pgrp
= pipeline_pgrp
;
6999 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline or
7000 we've already forked to run a disk command (and are expanding redirections,
7002 if ((subshell_environment
& (SUBSHELL_FORK
|SUBSHELL_PIPE
)) == 0)
7003 pipeline_pgrp
= shell_pgrp
;
7004 cleanup_the_pipeline ();
7005 #endif /* JOB_CONTROL */
7007 old_async_pid
= last_asynchronous_pid
;
7008 fork_flags
= (subshell_environment
&SUBSHELL_ASYNC
) ? FORK_ASYNC
: 0;
7009 pid
= make_child ((char *)NULL
, fork_flags
|FORK_NOTERM
);
7010 last_asynchronous_pid
= old_async_pid
;
7014 /* Reset the signal handlers in the child, but don't free the
7015 trap strings. Set a flag noting that we have to free the
7016 trap strings if we run trap to change a signal disposition. */
7017 reset_signal_handlers ();
7020 kill (getpid (), SIGINT
);
7021 CLRINTERRUPT
; /* if we're ignoring SIGINT somehow */
7023 QUIT
; /* catch any interrupts we got post-fork */
7024 subshell_environment
|= SUBSHELL_RESETTRAP
;
7025 subshell_environment
&= ~SUBSHELL_IGNTRAP
;
7028 #if defined (JOB_CONTROL)
7029 /* XXX DO THIS ONLY IN PARENT ? XXX */
7030 set_sigchld_handler ();
7031 stop_making_children ();
7033 pipeline_pgrp
= old_pipeline_pgrp
;
7035 stop_making_children ();
7036 #endif /* JOB_CONTROL */
7040 sys_error (_("cannot make child for command substitution"));
7043 last_made_pid
= old_pid
;
7048 return ((WORD_DESC
*)NULL
);
7053 /* The currently executing shell is not interactive. */
7056 #if defined (JOB_CONTROL)
7057 /* Invariant: in child processes started to run command substitutions,
7058 pipeline_pgrp == shell_pgrp. Other parts of the shell assume this. */
7059 if (pipeline_pgrp
> 0 && pipeline_pgrp
!= shell_pgrp
)
7060 shell_pgrp
= pipeline_pgrp
;
7063 set_sigint_handler (); /* XXX */
7065 free_pushed_string_input ();
7067 /* Discard buffered stdio output before replacing the underlying file
7071 if (dup2 (fildes
[1], 1) < 0)
7073 sys_error ("%s", _("command_substitute: cannot duplicate pipe as fd 1"));
7074 exit (EXECUTION_FAILURE
);
7077 /* If standard output is closed in the parent shell
7078 (such as after `exec >&-'), file descriptor 1 will be
7079 the lowest available file descriptor, and end up in
7080 fildes[0]. This can happen for stdin and stderr as well,
7081 but stdout is more important -- it will cause no output
7082 to be generated from this command. */
7083 if ((fildes
[1] != fileno (stdin
)) &&
7084 (fildes
[1] != fileno (stdout
)) &&
7085 (fildes
[1] != fileno (stderr
)))
7088 if ((fildes
[0] != fileno (stdin
)) &&
7089 (fildes
[0] != fileno (stdout
)) &&
7090 (fildes
[0] != fileno (stderr
)))
7094 /* Let stdio know the fd may have changed from text to binary mode, and
7095 make sure to preserve stdout line buffering. */
7096 freopen (NULL
, "w", stdout
);
7097 sh_setlinebuf (stdout
);
7098 #endif /* __CYGWIN__ */
7100 /* This is a subshell environment. */
7101 subshell_environment
|= SUBSHELL_COMSUB
;
7103 /* Many shells do not appear to inherit the -v option for command
7105 change_flag ('v', FLAG_OFF
);
7107 /* When inherit_errexit option is not enabled, command substitution does
7108 not inherit the -e flag. It is enabled when Posix mode is enabled */
7109 if (inherit_errexit
== 0)
7111 builtin_ignoring_errexit
= 0;
7112 change_flag ('e', FLAG_OFF
);
7116 /* If we are expanding a redirection, we can dispose of any temporary
7117 environment we received, since redirections are not supposed to have
7118 access to the temporary environment. We will have to see whether this
7119 affects temporary environments supplied to `eval', but the temporary
7120 environment gets copied to builtin_env at some point. */
7121 if (expanding_redir
)
7123 flush_temporary_env ();
7124 expanding_redir
= 0;
7127 remove_quoted_escapes (string
);
7129 /* We want to expand aliases on this pass if we are not in posix mode
7130 for backwards compatibility. parse_and_execute() takes care of
7131 setting expand_aliases back to the global value when executing the
7132 parsed string. We only do this for $(...) command substitution,
7133 since that is what parse_comsub handles; `` comsubs are processed
7134 using parse.y:parse_matched_pair(). */
7135 if (expand_aliases
&& (flags
& PF_BACKQUOTE
) == 0)
7136 expand_aliases
= posixly_correct
== 0;
7138 startup_state
= 2; /* see if we can avoid a fork */
7139 parse_and_execute_level
= 0;
7141 /* Give command substitution a place to jump back to on failure,
7142 so we don't go back up to main (). */
7143 result
= setjmp_nosigs (top_level
);
7145 /* If we're running a command substitution inside a shell function,
7146 trap `return' so we don't return from the function in the subshell
7147 and go off to never-never land. */
7148 if (result
== 0 && return_catch_flag
)
7149 function_value
= setjmp_nosigs (return_catch
);
7153 if (result
== ERREXIT
)
7154 rc
= last_command_exit_value
;
7155 else if (result
== EXITPROG
|| result
== EXITBLTIN
)
7156 rc
= last_command_exit_value
;
7158 rc
= EXECUTION_FAILURE
;
7159 else if (function_value
)
7160 rc
= return_catch_value
;
7164 rc
= parse_and_execute (string
, "command substitution", pflags
|SEVAL_NOHIST
);
7165 /* leave subshell level intact for any exit trap */
7168 last_command_exit_value
= rc
;
7169 rc
= run_exit_trap ();
7170 #if defined (PROCESS_SUBSTITUTION)
7171 unlink_fifo_list ();
7179 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
7181 #endif /* JOB_CONTROL && PGRP_PIPE */
7185 begin_unwind_frame ("read-comsub");
7186 dummyfd
= fildes
[0];
7187 add_unwind_protect (close
, dummyfd
);
7189 /* Block SIGINT while we're reading from the pipe. If the child
7190 process gets a SIGINT, it will either handle it or die, and the
7191 read will return. */
7192 BLOCK_SIGNAL (SIGINT
, set
, oset
);
7194 istring
= read_comsub (fildes
[0], quoted
, flags
, &tflag
);
7197 discard_unwind_frame ("read-comsub");
7198 UNBLOCK_SIGNAL (oset
);
7200 current_command_subst_pid
= pid
;
7201 last_command_exit_value
= wait_for (pid
, JWAIT_NOTERM
);
7202 last_command_subst_pid
= pid
;
7203 last_made_pid
= old_pid
;
7205 #if defined (JOB_CONTROL)
7206 /* If last_command_exit_value > 128, then the substituted command
7207 was terminated by a signal. If that signal was SIGINT, then send
7208 SIGINT to ourselves. This will break out of loops, for instance. */
7209 if (last_command_exit_value
== (128 + SIGINT
) && last_command_exit_signal
== SIGINT
)
7210 kill (getpid (), SIGINT
);
7211 #endif /* JOB_CONTROL */
7213 ret
= alloc_word_desc ();
7214 ret
->word
= istring
;
7221 /********************************************************
7223 * Utility functions for parameter expansion *
7225 ********************************************************/
7227 #if defined (ARRAY_VARS)
7230 array_length_reference (s
)
7241 var
= array_variable_part (s
, 0, &t
, &len
);
7243 /* If unbound variables should generate an error, report one and return
7245 if ((var
== 0 || invisible_p (var
) || (assoc_p (var
) == 0 && array_p (var
) == 0)) && unbound_vars_is_error
)
7249 set_exit_status (EXECUTION_FAILURE
);
7254 else if (var
== 0 || invisible_p (var
))
7257 /* We support a couple of expansions for variables that are not arrays.
7258 We'll return the length of the value for v[0], and 1 for v[@] or
7259 v[*]. Return 0 for everything else. */
7261 array
= array_p (var
) ? array_cell (var
) : (ARRAY
*)NULL
;
7262 h
= assoc_p (var
) ? assoc_cell (var
) : (HASH_TABLE
*)NULL
;
7264 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == RBRACK
)
7267 return (h
? assoc_num_elements (h
) : 0);
7268 else if (array_p (var
))
7269 return (array
? array_num_elements (array
) : 0);
7271 return (var_isset (var
) ? 1 : 0);
7277 akey
= expand_subscript_string (t
, 0); /* [ */
7278 t
[len
- 1] = RBRACK
;
7279 if (akey
== 0 || *akey
== 0)
7281 err_badarraysub (t
);
7285 t
= assoc_reference (assoc_cell (var
), akey
);
7290 ind
= array_expand_index (var
, t
, len
, 0);
7291 /* negative subscripts to indexed arrays count back from end */
7292 if (var
&& array_p (var
) && ind
< 0)
7293 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
7296 err_badarraysub (t
);
7300 t
= array_reference (array
, ind
);
7302 t
= (ind
== 0) ? value_cell (var
) : (char *)NULL
;
7305 len
= MB_STRLEN (t
);
7308 #endif /* ARRAY_VARS */
7311 valid_brace_expansion_word (name
, var_is_special
)
7315 if (DIGIT (*name
) && all_digits (name
))
7317 else if (var_is_special
)
7319 #if defined (ARRAY_VARS)
7320 else if (valid_array_reference (name
, 0))
7322 #endif /* ARRAY_VARS */
7323 else if (legal_identifier (name
))
7330 chk_atstar (name
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
7333 int *quoted_dollar_atp
, *contains_dollar_at
;
7339 if (quoted_dollar_atp
)
7340 *quoted_dollar_atp
= 0;
7341 if (contains_dollar_at
)
7342 *contains_dollar_at
= 0;
7346 /* check for $@ and $* */
7347 if (name
[0] == '@' && name
[1] == 0)
7349 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
7350 *quoted_dollar_atp
= 1;
7351 if (contains_dollar_at
)
7352 *contains_dollar_at
= 1;
7355 else if (name
[0] == '*' && name
[1] == '\0' && quoted
== 0)
7357 /* Need more checks here that parallel what string_list_pos_params and
7358 param_expand do. Check expand_no_split_dollar_star and ??? */
7359 if (contains_dollar_at
&& expand_no_split_dollar_star
== 0)
7360 *contains_dollar_at
= 1;
7364 /* Now check for ${array[@]} and ${array[*]} */
7365 #if defined (ARRAY_VARS)
7366 else if (valid_array_reference (name
, 0))
7368 temp1
= mbschr (name
, LBRACK
);
7369 if (temp1
&& temp1
[1] == '@' && temp1
[2] == RBRACK
)
7371 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
7372 *quoted_dollar_atp
= 1;
7373 if (contains_dollar_at
)
7374 *contains_dollar_at
= 1;
7377 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
7378 which should result in separate words even when IFS is unset. */
7379 if (temp1
&& temp1
[1] == '*' && temp1
[2] == RBRACK
&& quoted
== 0)
7381 if (contains_dollar_at
)
7382 *contains_dollar_at
= 1;
7390 /* Parameter expand NAME, and return a new string which is the expansion,
7391 or NULL if there was no expansion. NAME is as given in ${NAMEcWORD}.
7392 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
7393 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
7394 NAME was found inside of a double-quoted expression. */
7396 parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, estatep
)
7398 int var_is_special
, quoted
, pflags
;
7399 array_eltstate_t
*estatep
;
7406 array_eltstate_t es
;
7412 #if defined (ARRAY_VARS)
7414 es
= *estatep
; /* structure copy */
7417 init_eltstate (&es
);
7418 es
.ind
= INTMAX_MIN
;
7422 /* Handle multiple digit arguments, as in ${11}. */
7423 if (legal_number (name
, &arg_index
))
7425 tt
= get_dollar_var_value (arg_index
);
7427 temp
= (*tt
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7429 : quote_escapes (tt
);
7431 temp
= (char *)NULL
;
7434 else if (var_is_special
) /* ${@} */
7437 tt
= (char *)xmalloc (2 + strlen (name
));
7438 tt
[sindex
= 0] = '$';
7439 strcpy (tt
+ 1, name
);
7441 ret
= param_expand (tt
, &sindex
, quoted
, (int *)NULL
, (int *)NULL
,
7442 (int *)NULL
, (int *)NULL
, pflags
);
7444 /* Make sure we note that we saw a quoted null string and pass the flag back
7445 to the caller in addition to the value. */
7446 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && STR_DOLLAR_AT_STAR (name
) &&
7447 ret
&& ret
->word
&& QUOTED_NULL (ret
->word
))
7448 ret
->flags
|= W_HASQUOTEDNULL
;
7452 #if defined (ARRAY_VARS)
7453 else if (valid_array_reference (name
, 0))
7456 var
= array_variable_part (name
, 0, &tt
, (int *)0);
7457 /* These are the cases where word splitting will not be performed */
7458 if (pflags
& PF_ASSIGNRHS
)
7460 if (ALL_ELEMENT_SUB (tt
[0]) && tt
[1] == RBRACK
)
7462 /* Only treat as double quoted if array variable */
7463 if (var
&& (array_p (var
) || assoc_p (var
)))
7464 temp
= array_value (name
, quoted
|Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &es
);
7466 temp
= array_value (name
, quoted
, 0, &es
);
7469 temp
= array_value (name
, quoted
, 0, &es
);
7471 /* Posix interp 888 */
7472 else if (pflags
& PF_NOSPLIT2
)
7474 /* Special cases, then general case, for each of A[@], A[*], A[n] */
7475 #if defined (HANDLE_MULTIBYTE)
7476 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
7478 if (tt
[0] == '@' && tt
[1] == RBRACK
&& var
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
7480 temp
= array_value (name
, Q_DOUBLE_QUOTES
, AV_ASSIGNRHS
, &es
);
7481 else if (tt
[0] == '@' && tt
[1] == RBRACK
)
7482 temp
= array_value (name
, quoted
, 0, &es
);
7483 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
7484 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &es
);
7485 else if (tt
[0] == '*' && tt
[1] == RBRACK
)
7486 temp
= array_value (name
, quoted
, 0, &es
);
7488 temp
= array_value (name
, quoted
, 0, &es
);
7490 else if (tt
[0] == '*' && tt
[1] == RBRACK
&& expand_no_split_dollar_star
&& ifs_is_null
)
7491 temp
= array_value (name
, Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
, 0, &es
);
7493 temp
= array_value (name
, quoted
, 0, &es
);
7494 if (es
.subtype
== 0 && temp
)
7496 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7497 ? quote_string (temp
)
7498 : quote_escapes (temp
);
7499 rflags
|= W_ARRAYIND
;
7501 /* Note that array[*] and array[@] expanded to a quoted null string by
7502 returning the W_HASQUOTEDNULL flag to the caller in addition to TEMP. */
7503 else if (es
.subtype
== 1 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7504 rflags
|= W_HASQUOTEDNULL
;
7505 else if (es
.subtype
== 2 && temp
&& QUOTED_NULL (temp
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7506 rflags
|= W_HASQUOTEDNULL
;
7509 *estatep
= es
; /* structure copy */
7511 flush_eltstate (&es
);
7514 else if (var
= find_variable (name
))
7516 if (var_isset (var
) && invisible_p (var
) == 0)
7518 #if defined (ARRAY_VARS)
7519 /* We avoid a memory leak by saving TT as the memory allocated by
7520 assoc_to_string or array_to_string and leaving it 0 otherwise,
7521 then freeing TT after quoting temp. */
7523 if ((pflags
& PF_ALLINDS
) && assoc_p (var
))
7524 tt
= temp
= assoc_empty (assoc_cell (var
)) ? (char *)NULL
: assoc_to_string (assoc_cell (var
), " ", quoted
);
7525 else if ((pflags
& PF_ALLINDS
) && array_p (var
))
7526 tt
= temp
= array_empty (array_cell (var
)) ? (char *)NULL
: array_to_string (array_cell (var
), " ", quoted
);
7527 else if (assoc_p (var
))
7528 temp
= assoc_reference (assoc_cell (var
), "0");
7529 else if (array_p (var
))
7530 temp
= array_reference (array_cell (var
), 0);
7532 temp
= value_cell (var
);
7534 temp
= value_cell (var
);
7538 temp
= (*temp
&& (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
7539 ? quote_string (temp
)
7540 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
7541 : quote_escapes (temp
));
7545 temp
= (char *)NULL
;
7547 else if (var
= find_variable_last_nameref (name
, 0))
7549 temp
= nameref_cell (var
);
7550 #if defined (ARRAY_VARS)
7551 /* Handle expanding nameref whose value is x[n] */
7552 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
7555 goto expand_arrayref
;
7559 /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
7560 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
7562 set_exit_status (EXECUTION_FAILURE
);
7563 report_error (_("%s: invalid variable name for name reference"), temp
);
7564 temp
= &expand_param_error
;
7567 temp
= (char *)NULL
;
7570 temp
= (char *)NULL
;
7574 ret
= alloc_word_desc ();
7576 ret
->flags
|= rflags
;
7582 parameter_brace_find_indir (name
, var_is_special
, quoted
, find_nameref
)
7584 int var_is_special
, quoted
, find_nameref
;
7591 if (find_nameref
&& var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)) &&
7592 nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
7593 return (savestring (t
));
7595 /* If var_is_special == 0, and name is not an array reference, this does
7596 more expansion than necessary. It should really look up the variable's
7597 value and not try to expand it. */
7598 pflags
= PF_IGNUNBOUND
;
7599 /* Note that we're not going to be doing word splitting here */
7602 pflags
|= PF_ASSIGNRHS
; /* suppresses word splitting */
7603 oldex
= expand_no_split_dollar_star
;
7604 expand_no_split_dollar_star
= 1;
7606 w
= parameter_brace_expand_word (name
, var_is_special
, quoted
, pflags
, 0);
7608 expand_no_split_dollar_star
= oldex
;
7611 /* Have to dequote here if necessary */
7614 temp
= ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || var_is_special
)
7615 ? dequote_string (t
)
7616 : dequote_escapes (t
);
7620 dispose_word_desc (w
);
7625 /* Expand an indirect reference to a variable: ${!NAME} expands to the
7626 value of the variable whose name is the value of NAME. */
7628 parameter_brace_expand_indir (name
, var_is_special
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
7630 int var_is_special
, quoted
, pflags
;
7631 int *quoted_dollar_atp
, *contains_dollar_at
;
7637 /* See if it's a nameref first, behave in ksh93-compatible fashion.
7638 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
7639 bash performs an indirect lookup on foo[0] and expands the result;
7640 ksh93 expands bar[0]. We could do that here -- there are enough usable
7641 primitives to do that -- but do not at this point. */
7642 if (var_is_special
== 0 && (v
= find_variable_last_nameref (name
, 0)))
7644 if (nameref_p (v
) && (t
= nameref_cell (v
)) && *t
)
7646 w
= alloc_word_desc ();
7647 w
->word
= savestring (t
);
7653 /* An indirect reference to a positional parameter or a special parameter
7654 is ok. Indirect references to array references, as explained above, are
7655 ok (currently). Only references to unset variables are errors at this
7657 if (legal_identifier (name
) && v
== 0)
7659 report_error (_("%s: invalid indirect expansion"), name
);
7660 w
= alloc_word_desc ();
7661 w
->word
= &expand_param_error
;
7666 t
= parameter_brace_find_indir (name
, var_is_special
, quoted
, 0);
7668 chk_atstar (t
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
7670 #if defined (ARRAY_VARS)
7671 /* Array references to unset variables are also an error */
7672 if (t
== 0 && valid_array_reference (name
, 0))
7674 v
= array_variable_part (name
, 0, (char **)0, (int *)0);
7677 report_error (_("%s: invalid indirect expansion"), name
);
7678 w
= alloc_word_desc ();
7679 w
->word
= &expand_param_error
;
7684 return (WORD_DESC
*)NULL
;
7689 return (WORD_DESC
*)NULL
;
7691 if (valid_brace_expansion_word (t
, SPECIAL_VAR (t
, 0)) == 0)
7693 report_error (_("%s: invalid variable name"), t
);
7695 w
= alloc_word_desc ();
7696 w
->word
= &expand_param_error
;
7701 w
= parameter_brace_expand_word (t
, SPECIAL_VAR(t
, 0), quoted
, pflags
, 0);
7707 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
7708 depending on the value of C, the separating character. C can be one of
7709 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
7710 between double quotes. */
7712 parameter_brace_expand_rhs (name
, value
, op
, quoted
, pflags
, qdollaratp
, hasdollarat
)
7714 int op
, quoted
, pflags
, *qdollaratp
, *hasdollarat
;
7718 char *t
, *t1
, *temp
, *vname
, *newval
;
7719 int l_hasdollat
, sindex
, arrayref
;
7721 array_eltstate_t es
;
7723 /*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
7724 /* If the entire expression is between double quotes, we want to treat
7725 the value as a double-quoted string, with the exception that we strip
7726 embedded unescaped double quotes (for sh backwards compatibility). */
7727 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && *value
)
7730 temp
= string_extract_double_quoted (value
, &sindex
, SX_STRIPDQ
);
7735 w
= alloc_word_desc ();
7737 l
= *temp
? expand_string_for_rhs (temp
, quoted
, op
, pflags
, &l_hasdollat
, (int *)NULL
)
7740 *hasdollarat
= l_hasdollat
|| (l
&& l
->next
);
7744 /* list_string takes multiple CTLNULs and turns them into an empty word
7745 with W_SAWQUOTEDNULL set. Turn it back into a single CTLNUL for the
7746 rest of this function and the caller. */
7747 for (tl
= l
; tl
; tl
= tl
->next
)
7749 if (tl
->word
&& (tl
->word
->word
== 0 || tl
->word
->word
[0] == 0) &&
7750 (tl
->word
->flags
| W_SAWQUOTEDNULL
))
7752 t
= make_quoted_char ('\0');
7753 FREE (tl
->word
->word
);
7755 tl
->word
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
7756 tl
->word
->flags
&= ~W_SAWQUOTEDNULL
;
7762 /* If l->next is not null, we know that TEMP contained "$@", since that
7763 is the only expansion that creates more than one word. */
7764 if (qdollaratp
&& ((l_hasdollat
&& quoted
) || l
->next
))
7766 /*itrace("parameter_brace_expand_rhs: %s:%s: l != NULL, set *qdollaratp", name, value);*/
7770 /* The expansion of TEMP returned something. We need to treat things
7771 slightly differently if L_HASDOLLAT is non-zero. If we have "$@",
7772 the individual words have already been quoted. We need to turn them
7773 into a string with the words separated by the first character of
7774 $IFS without any additional quoting, so string_list_dollar_at won't
7775 do the right thing. If IFS is null, we want "$@" to split into
7776 separate arguments, not be concatenated, so we use string_list_internal
7777 and mark the word to be split on spaces later. We use
7778 string_list_dollar_star for "$@" otherwise. */
7779 if (l
->next
&& ifs_is_null
)
7781 temp
= string_list_internal (l
, " ");
7782 w
->flags
|= W_SPLITSPACE
;
7784 else if (l_hasdollat
|| l
->next
)
7785 temp
= string_list_dollar_star (l
, quoted
, 0);
7788 temp
= string_list (l
);
7789 if (temp
&& (QUOTED_NULL (temp
) == 0) && (l
->word
->flags
& W_SAWQUOTEDNULL
))
7790 w
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
7793 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
7794 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
7795 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
7796 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7797 (which is more paranoia than anything else), we need to return the
7798 quoted null string and set the flags to indicate it. */
7799 if (l
->next
== 0 && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
) && QUOTED_NULL (l
->word
->word
) && (l
->word
->flags
& W_HASQUOTEDNULL
))
7801 w
->flags
|= W_HASQUOTEDNULL
;
7802 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null, turning off qdollaratp", name, value);*/
7803 /* If we return a quoted null with L_HASDOLLARAT, we either have a
7804 construct like "${@-$@}" or "${@-${@-$@}}" with no positional
7805 parameters or a quoted expansion of "$@" with $1 == ''. In either
7806 case, we don't want to enable special handling of $@. */
7807 if (qdollaratp
&& l_hasdollat
)
7812 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && l_hasdollat
)
7814 /* Posix interp 221 changed the rules on this. The idea is that
7815 something like "$xxx$@" should expand the same as "${foo-$xxx$@}"
7816 when foo and xxx are unset. The problem is that it's not in any
7817 way backwards compatible and few other shells do it. We're eventually
7818 going to try and split the difference (heh) a little bit here. */
7819 /* l_hasdollat == 1 means we saw a quoted dollar at. */
7821 /* The brace expansion occurred between double quotes and there was
7822 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
7823 it does not expand to anything. In this case, we want to return
7824 a quoted empty string. Posix interp 888 */
7825 temp
= make_quoted_char ('\0');
7826 w
->flags
|= W_HASQUOTEDNULL
;
7827 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null", name, value);*/
7830 temp
= (char *)NULL
;
7832 if (op
== '-' || op
== '+')
7839 t1
= temp
? dequote_string (temp
) : savestring ("");
7845 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1]) || VALID_INDIR_PARAM (name
[1])))
7847 vname
= parameter_brace_find_indir (name
+ 1, SPECIAL_VAR (name
, 1), quoted
, 1);
7848 if (vname
== 0 || *vname
== 0)
7850 report_error (_("%s: invalid indirect expansion"), name
);
7854 return &expand_wdesc_error
;
7856 if (legal_identifier (vname
) == 0)
7858 report_error (_("%s: invalid variable name"), vname
);
7862 return &expand_wdesc_error
;
7867 #if defined (ARRAY_VARS)
7868 if (valid_array_reference (vname
, 0))
7870 init_eltstate (&es
);
7871 v
= assign_array_element (vname
, t1
, ASS_ALLOWALLSUB
, &es
);
7876 #endif /* ARRAY_VARS */
7877 v
= bind_variable (vname
, t1
, 0);
7879 if (v
== 0 || readonly_p (v
) || noassign_p (v
)) /* expansion error */
7881 if ((v
== 0 || readonly_p (v
)) && interactive_shell
== 0 && posixly_correct
)
7883 last_command_exit_value
= EXECUTION_FAILURE
;
7884 exp_jump_to_top_level (FORCE_EOF
);
7890 last_command_exit_value
= EX_BADUSAGE
;
7891 exp_jump_to_top_level (DISCARD
);
7895 stupidly_hack_special_variables (vname
);
7897 /* "In all cases, the final value of parameter shall be substituted." */
7898 if (shell_compatibility_level
> 51)
7901 #if defined (ARRAY_VARS)
7905 flush_eltstate (&es
);
7908 t1
= get_variable_value (v
);
7910 t1
= value_cell (v
);
7917 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
7919 /* If we are double-quoted or if we are not going to be performing word
7920 splitting, we want to quote the value we return appropriately, like
7921 the other expansions this function handles. */
7922 w
->word
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (t1
) : quote_escapes (t1
);
7923 /* If we have something that's non-null, but not a quoted null string,
7924 and we're not going to be performing word splitting (we know we're not
7925 because the operator is `='), we can forget we saw a quoted null. */
7926 if (w
->word
&& w
->word
[0] && QUOTED_NULL (w
->word
) == 0)
7927 w
->flags
&= ~W_SAWQUOTEDNULL
;
7929 /* If we convert a null string into a quoted null, make sure the caller
7931 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && QUOTED_NULL (w
->word
))
7932 w
->flags
|= W_HASQUOTEDNULL
;
7937 /* Deal with the right hand side of a ${name:?value} expansion in the case
7938 that NAME is null or not set. If VALUE is non-null it is expanded and
7939 used as the error message to print, otherwise a standard message is
7942 parameter_brace_expand_error (name
, value
, check_null
)
7949 set_exit_status (EXECUTION_FAILURE
); /* ensure it's non-zero */
7950 if (value
&& *value
)
7952 l
= expand_string (value
, 0);
7953 temp
= string_list (l
);
7954 report_error ("%s: %s", name
, temp
? temp
: ""); /* XXX was value not "" */
7958 else if (check_null
== 0)
7959 report_error (_("%s: parameter not set"), name
);
7961 report_error (_("%s: parameter null or not set"), name
);
7963 /* Free the data we have allocated during this expansion, since we
7964 are about to longjmp out. */
7969 /* Return 1 if NAME is something for which parameter_brace_expand_length is
7972 valid_length_expression (name
)
7975 return (name
[1] == '\0' || /* ${#} */
7976 ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0') || /* special param */
7977 (DIGIT (name
[1]) && all_digits (name
+ 1)) || /* ${#11} */
7978 #if defined (ARRAY_VARS)
7979 valid_array_reference (name
+ 1, 0) || /* ${#a[7]} */
7981 legal_identifier (name
+ 1)); /* ${#PS1} */
7984 /* Handle the parameter brace expansion that requires us to return the
7985 length of a parameter. */
7987 parameter_brace_expand_length (name
)
7991 intmax_t number
, arg_index
;
7995 var
= (SHELL_VAR
*)NULL
;
7997 if (name
[1] == '\0') /* ${#} */
7998 number
= number_of_args ();
7999 else if (DOLLAR_AT_STAR (name
[1]) && name
[2] == '\0') /* ${#@}, ${#*} */
8000 number
= number_of_args ();
8001 else if ((sh_syntaxtab
[(unsigned char) name
[1]] & CSPECVAR
) && name
[2] == '\0')
8003 /* Take the lengths of some of the shell's special parameters. */
8007 t
= which_set_flags ();
8010 t
= itos (last_command_exit_value
);
8013 t
= itos (dollar_dollar_pid
);
8016 if (last_asynchronous_pid
== NO_PID
)
8017 t
= (char *)NULL
; /* XXX - error if set -u set? */
8019 t
= itos (last_asynchronous_pid
);
8022 t
= itos (number_of_args ());
8025 number
= STRLEN (t
);
8028 #if defined (ARRAY_VARS)
8029 else if (valid_array_reference (name
+ 1, 0))
8030 number
= array_length_reference (name
+ 1);
8031 #endif /* ARRAY_VARS */
8036 if (legal_number (name
+ 1, &arg_index
)) /* ${#1} */
8038 t
= get_dollar_var_value (arg_index
);
8039 if (t
== 0 && unbound_vars_is_error
)
8041 number
= MB_STRLEN (t
);
8044 #if defined (ARRAY_VARS)
8045 else if ((var
= find_variable (name
+ 1)) && (invisible_p (var
) == 0) && (array_p (var
) || assoc_p (var
)))
8048 t
= assoc_reference (assoc_cell (var
), "0");
8050 t
= array_reference (array_cell (var
), 0);
8051 if (t
== 0 && unbound_vars_is_error
)
8053 number
= MB_STRLEN (t
);
8056 /* Fast path for the common case of taking the length of a non-dynamic
8057 scalar variable value. */
8058 else if ((var
|| (var
= find_variable (name
+ 1))) &&
8059 invisible_p (var
) == 0 &&
8060 array_p (var
) == 0 && assoc_p (var
) == 0 &&
8061 var
->dynamic_value
== 0)
8062 number
= value_cell (var
) ? MB_STRLEN (value_cell (var
)) : 0;
8063 else if (var
== 0 && unbound_vars_is_error
== 0)
8067 newname
= savestring (name
);
8069 list
= expand_string (newname
, Q_DOUBLE_QUOTES
);
8070 t
= list
? string_list (list
) : (char *)NULL
;
8073 dispose_words (list
);
8075 number
= t
? MB_STRLEN (t
) : 0;
8083 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
8084 so we do some ad-hoc parsing of an arithmetic expression to find
8085 the first DELIM, instead of using strchr(3). Two rules:
8086 1. If the substring contains a `(', read until closing `)'.
8087 2. If the substring contains a `?', read past one `:' for each `?'.
8088 The SD_ARITHEXP flag to skip_to_delim takes care of doing this.
8092 skiparith (substr
, delim
)
8102 i
= skip_to_delim (substr
, 0, delims
, SD_ARITHEXP
);
8103 return (substr
+ i
);
8106 /* Verify and limit the start and end of the desired substring. If
8107 VTYPE == 0, a regular shell variable is being used; if it is 1,
8108 then the positional parameters are being used; if it is 2, then
8109 VALUE is really a pointer to an array variable that should be used.
8110 Return value is 1 if both values were OK, 0 if there was a problem
8111 with an invalid expression, or -1 if the values were out of range. */
8113 verify_substring_values (v
, value
, substr
, vtype
, e1p
, e2p
)
8115 char *value
, *substr
;
8117 intmax_t *e1p
, *e2p
;
8119 char *t
, *temp1
, *temp2
;
8122 #if defined (ARRAY_VARS)
8127 /* duplicate behavior of strchr(3) */
8128 t
= skiparith (substr
, ':');
8129 if (*t
&& *t
== ':')
8134 temp1
= expand_arith_string (substr
, Q_DOUBLE_QUOTES
|Q_ARITH
);
8135 eflag
= (shell_compatibility_level
> 51) ? 0 : EXP_EXPANDED
;
8137 *e1p
= evalexp (temp1
, eflag
, &expok
);
8142 len
= -1; /* paranoia */
8146 case VT_ARRAYMEMBER
:
8147 len
= MB_STRLEN (value
);
8150 len
= number_of_args () + 1;
8152 len
++; /* add one arg if counting from $0 */
8154 #if defined (ARRAY_VARS)
8156 /* For arrays, the first value deals with array indices. Negative
8157 offsets count from one past the array's maximum index. Associative
8158 arrays treat the number of elements as the maximum index. */
8162 len
= assoc_num_elements (h
) + (*e1p
< 0);
8167 len
= array_max_index (a
) + (*e1p
< 0); /* arrays index from 0 to n - 1 */
8173 if (len
== -1) /* paranoia */
8176 if (*e1p
< 0) /* negative offsets count from end */
8179 if (*e1p
> len
|| *e1p
< 0)
8182 #if defined (ARRAY_VARS)
8183 /* For arrays, the second offset deals with the number of elements. */
8184 if (vtype
== VT_ARRAYVAR
)
8185 len
= assoc_p (v
) ? assoc_num_elements (h
) : array_num_elements (a
);
8191 temp2
= savestring (t
);
8192 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
8195 *e2p
= evalexp (temp1
, eflag
, &expok
);
8200 /* Should we allow positional parameter length < 0 to count backwards
8201 from end of positional parameters? */
8203 if ((vtype
== VT_ARRAYVAR
|| vtype
== VT_POSPARMS
) && *e2p
< 0)
8204 #else /* XXX - postponed; this isn't really a valuable feature */
8205 if (vtype
== VT_ARRAYVAR
&& *e2p
< 0)
8208 internal_error (_("%s: substring expression < 0"), t
);
8211 #if defined (ARRAY_VARS)
8212 /* In order to deal with sparse arrays, push the intelligence about how
8213 to deal with the number of elements desired down to the array-
8214 specific functions. */
8215 if (vtype
!= VT_ARRAYVAR
)
8221 if (*e2p
< 0 || *e2p
< *e1p
)
8223 internal_error (_("%s: substring expression < 0"), t
);
8228 *e2p
+= *e1p
; /* want E2 chars starting at E1 */
8239 /* Return the type of variable specified by VARNAME (simple variable,
8240 positional param, or array variable). Also return the value specified
8241 by VARNAME (value of a variable or a reference to an array element).
8242 QUOTED is the standard description of quoting state, using Q_* defines.
8243 FLAGS is currently a set of flags to pass to array_value. If IND is
8244 not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
8245 passed to array_value so the array index is not computed again.
8246 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
8247 characters in the value are quoted with CTLESC and takes appropriate
8248 steps. For convenience, *VALP is set to the dequoted VALUE. */
8250 get_var_and_type (varname
, value
, estatep
, quoted
, flags
, varp
, valp
)
8251 char *varname
, *value
;
8252 array_eltstate_t
*estatep
;
8257 int vtype
, want_indir
;
8261 want_indir
= *varname
== '!' &&
8262 (legal_variable_starter ((unsigned char)varname
[1]) || DIGIT (varname
[1])
8263 || VALID_INDIR_PARAM (varname
[1]));
8265 vname
= parameter_brace_find_indir (varname
+1, SPECIAL_VAR (varname
, 1), quoted
, 1);
8266 /* XXX - what if vname == 0 || *vname == 0 ? */
8272 vtype
= VT_VARIABLE
;
8273 *varp
= (SHELL_VAR
*)NULL
;
8274 *valp
= (char *)NULL
;
8278 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
8279 vtype
= STR_DOLLAR_AT_STAR (vname
);
8280 if (vtype
== VT_POSPARMS
&& vname
[0] == '*')
8281 vtype
|= VT_STARSUB
;
8282 *varp
= (SHELL_VAR
*)NULL
;
8284 #if defined (ARRAY_VARS)
8285 if (valid_array_reference (vname
, 0))
8287 v
= array_variable_part (vname
, 0, &temp
, (int *)0);
8288 /* If we want to signal array_value to use an already-computed index,
8289 the caller will set ESTATEP->IND to that index and pass AV_USEIND in
8291 if (estatep
&& (flags
& AV_USEIND
) == 0)
8292 estatep
->ind
= INTMAX_MIN
;
8294 if (v
&& invisible_p (v
))
8296 vtype
= VT_ARRAYMEMBER
;
8297 *varp
= (SHELL_VAR
*)NULL
;
8298 *valp
= (char *)NULL
;
8300 if (v
&& (array_p (v
) || assoc_p (v
)))
8302 if (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
)
8304 /* Callers have to differentiate between indexed and associative */
8305 vtype
= VT_ARRAYVAR
;
8307 vtype
|= VT_STARSUB
;
8308 *valp
= array_p (v
) ? (char *)array_cell (v
) : (char *)assoc_cell (v
);
8312 vtype
= VT_ARRAYMEMBER
;
8313 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, estatep
);
8317 else if (v
&& (ALL_ELEMENT_SUB (temp
[0]) && temp
[1] == RBRACK
))
8319 vtype
= VT_VARIABLE
;
8321 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8322 *valp
= value
? dequote_string (value
) : (char *)NULL
;
8324 *valp
= value
? dequote_escapes (value
) : (char *)NULL
;
8328 vtype
= VT_ARRAYMEMBER
;
8330 *valp
= array_value (vname
, Q_DOUBLE_QUOTES
, flags
, estatep
);
8333 else if ((v
= find_variable (vname
)) && (invisible_p (v
) == 0) && (assoc_p (v
) || array_p (v
)))
8335 vtype
= VT_ARRAYMEMBER
;
8337 *valp
= assoc_p (v
) ? assoc_reference (assoc_cell (v
), "0") : array_reference (array_cell (v
), 0);
8342 if (value
&& vtype
== VT_VARIABLE
)
8344 *varp
= find_variable (vname
);
8345 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8346 *valp
= dequote_string (value
);
8348 *valp
= dequote_escapes (value
);
8360 /***********************************************************/
8362 /* Functions to perform transformations on variable values */
8364 /***********************************************************/
8367 string_var_assignment (v
, s
)
8371 char flags
[MAX_ATTRIBUTES
], *ret
, *val
;
8374 val
= (v
&& (invisible_p (v
) || var_isset (v
) == 0)) ? (char *)NULL
: sh_quote_reusable (s
, 0);
8375 i
= var_attribute_string (v
, 0, flags
);
8376 if (i
== 0 && val
== 0)
8377 return (char *)NULL
;
8379 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16 + MAX_ATTRIBUTES
);
8380 if (i
> 0 && val
== 0)
8381 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
8383 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
8385 sprintf (ret
, "%s=%s", v
->name
, val
);
8390 #if defined (ARRAY_VARS)
8392 array_var_assignment (v
, itype
, quoted
, atype
)
8394 int itype
, quoted
, atype
;
8396 char *ret
, *val
, flags
[MAX_ATTRIBUTES
];
8400 return (char *)NULL
;
8402 val
= array_p (v
) ? array_to_kvpair (array_cell (v
), 0)
8403 : assoc_to_kvpair (assoc_cell (v
), 0);
8405 val
= array_p (v
) ? array_to_assign (array_cell (v
), 0)
8406 : assoc_to_assign (assoc_cell (v
), 0);
8408 if (val
== 0 && (invisible_p (v
) || var_isset (v
) == 0))
8412 val
= (char *)xmalloc (3);
8419 ret
= (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) ? quote_string (val
) : quote_escapes (val
);
8427 i
= var_attribute_string (v
, 0, flags
);
8428 ret
= (char *)xmalloc (i
+ STRLEN (val
) + strlen (v
->name
) + 16);
8430 sprintf (ret
, "declare -%s %s=%s", flags
, v
->name
, val
);
8432 sprintf (ret
, "declare -%s %s", flags
, v
->name
);
8439 pos_params_assignment (list
, itype
, quoted
)
8446 /* first, we transform the list to quote each word. */
8447 temp
= list_transform ('Q', (SHELL_VAR
*)0, list
, itype
, quoted
);
8448 ret
= (char *)xmalloc (strlen (temp
) + 8);
8449 strcpy (ret
, "set -- ");
8450 strcpy (ret
+ 7, temp
);
8456 string_transform (xc
, v
, s
)
8461 char *ret
, flags
[MAX_ATTRIBUTES
], *t
;
8464 if (((xc
== 'A' || xc
== 'a') && v
== 0))
8465 return (char *)NULL
;
8466 else if (xc
!= 'a' && xc
!= 'A' && s
== 0)
8467 return (char *)NULL
;
8471 /* Transformations that interrogate the variable */
8473 i
= var_attribute_string (v
, 0, flags
);
8474 ret
= (i
> 0) ? savestring (flags
) : (char *)NULL
;
8477 ret
= string_var_assignment (v
, s
);
8481 ret
= sh_quote_reusable (s
, 0);
8483 /* Transformations that modify the variable's value */
8485 t
= ansiexpand (s
, 0, strlen (s
), (int *)0);
8486 ret
= dequote_escapes (t
);
8490 ret
= decode_prompt_string (s
);
8493 ret
= sh_quote_reusable (s
, 0);
8496 ret
= sh_modcase (s
, 0, CASE_UPPER
);
8499 ret
= sh_modcase (s
, 0, CASE_UPFIRST
); /* capitalize */
8502 ret
= sh_modcase (s
, 0, CASE_LOWER
);
8512 list_transform (xc
, v
, list
, itype
, quoted
)
8523 for (new = (WORD_LIST
*)NULL
, l
= list
; l
; l
= l
->next
)
8525 tword
= string_transform (xc
, v
, l
->word
->word
);
8526 w
= alloc_word_desc ();
8527 w
->word
= tword
? tword
: savestring (""); /* XXX */
8528 new = make_word_list (w
, new);
8530 l
= REVERSE_LIST (new, WORD_LIST
*);
8533 /* If we are expanding in a context where word splitting will not be
8534 performed, treat as quoted. This changes how $* will be expanded. */
8535 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
8536 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8538 tword
= string_list_pos_params (itype
, l
, qflags
, 0);
8545 parameter_list_transform (xc
, itype
, quoted
)
8553 list
= list_rest_of_args ();
8555 return ((char *)NULL
);
8557 ret
= pos_params_assignment (list
, itype
, quoted
);
8559 ret
= list_transform (xc
, (SHELL_VAR
*)0, list
, itype
, quoted
);
8560 dispose_words (list
);
8564 #if defined (ARRAY_VARS)
8566 array_transform (xc
, var
, starsub
, quoted
)
8569 int starsub
; /* so we can figure out how it's indexed */
8579 v
= var
; /* XXX - for now */
8581 itype
= starsub
? '*' : '@';
8584 return (array_var_assignment (v
, itype
, quoted
, 1));
8586 return (array_var_assignment (v
, itype
, quoted
, 2));
8588 /* special case for unset arrays and attributes */
8589 if (xc
== 'a' && (invisible_p (v
) || var_isset (v
) == 0))
8591 char flags
[MAX_ATTRIBUTES
];
8594 i
= var_attribute_string (v
, 0, flags
);
8595 return ((i
> 0) ? savestring (flags
) : (char *)NULL
);
8598 a
= (v
&& array_p (v
)) ? array_cell (v
) : 0;
8599 h
= (v
&& assoc_p (v
)) ? assoc_cell (v
) : 0;
8605 return ((char *)NULL
);
8606 list
= array_p (v
) ? array_to_kvpair_list (a
) : assoc_to_kvpair_list (h
);
8608 /* If we are expanding in a context where word splitting will not be
8609 performed, treat as quoted. This changes how $* will be expanded. */
8610 if (itype
== '*' && expand_no_split_dollar_star
&& ifs_is_null
)
8611 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
8613 ret
= string_list_pos_params (itype
, list
, qflags
, 0);
8614 dispose_words (list
);
8618 list
= a
? array_to_word_list (a
) : (h
? assoc_to_word_list (h
) : 0);
8620 return ((char *)NULL
);
8621 ret
= list_transform (xc
, v
, list
, itype
, quoted
);
8622 dispose_words (list
);
8626 #endif /* ARRAY_VARS */
8629 valid_parameter_transform (xform
)
8635 /* check for valid values of xform[0] */
8638 case 'a': /* expand to a string with just attributes */
8639 case 'A': /* expand as an assignment statement with attributes */
8640 case 'K': /* expand assoc array to list of key/value pairs */
8641 case 'k': /* XXX - for now */
8642 case 'E': /* expand like $'...' */
8643 case 'P': /* expand like prompt string */
8644 case 'Q': /* quote reusably */
8645 case 'U': /* transform to uppercase */
8646 case 'u': /* transform by capitalizing */
8647 case 'L': /* transform to lowercase */
8655 parameter_brace_transform (varname
, value
, estatep
, xform
, rtype
, quoted
, pflags
, flags
)
8656 char *varname
, *value
;
8657 array_eltstate_t
*estatep
;
8659 int rtype
, quoted
, pflags
, flags
;
8661 int vtype
, xc
, starsub
;
8662 char *temp1
, *val
, *oname
;
8666 if (value
== 0 && xc
!= 'A' && xc
!= 'a')
8667 return ((char *)NULL
);
8669 oname
= this_command_name
;
8670 this_command_name
= varname
;
8672 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
8675 this_command_name
= oname
;
8676 return ((char *)NULL
);
8679 if (xform
[0] == 0 || valid_parameter_transform (xform
) == 0)
8681 this_command_name
= oname
;
8682 if (vtype
== VT_VARIABLE
)
8684 return (interactive_shell
? &expand_param_error
: &expand_param_fatal
);
8687 starsub
= vtype
& VT_STARSUB
;
8688 vtype
&= ~VT_STARSUB
;
8690 /* If we are asked to display the attributes of an unset variable, V will
8691 be NULL after the call to get_var_and_type. Double-check here. */
8692 if ((xc
== 'a' || xc
== 'A') && vtype
== VT_VARIABLE
&& varname
&& v
== 0)
8693 v
= find_variable (varname
);
8695 temp1
= (char *)NULL
; /* shut up gcc */
8699 case VT_ARRAYMEMBER
:
8700 temp1
= string_transform (xc
, v
, val
);
8701 if (vtype
== VT_VARIABLE
)
8705 val
= (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
8706 ? quote_string (temp1
)
8707 : quote_escapes (temp1
);
8712 #if defined (ARRAY_VARS)
8714 temp1
= array_transform (xc
, v
, starsub
, quoted
);
8715 if (temp1
&& quoted
== 0 && ifs_is_null
)
8717 /* Posix interp 888 */
8719 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8721 val
= quote_escapes (temp1
);
8728 temp1
= parameter_list_transform (xc
, varname
[0], quoted
);
8729 if (temp1
&& quoted
== 0 && ifs_is_null
)
8731 /* Posix interp 888 */
8733 else if (temp1
&& ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0))
8735 val
= quote_escapes (temp1
);
8742 this_command_name
= oname
;
8746 /******************************************************/
8748 /* Functions to extract substrings of variable values */
8750 /******************************************************/
8752 #if defined (HANDLE_MULTIBYTE)
8753 /* Character-oriented rather than strictly byte-oriented substrings. S and
8754 E, rather being strict indices into STRING, indicate character (possibly
8755 multibyte character) positions that require calculation.
8756 Used by the ${param:offset[:length]} expansion. */
8758 mb_substring (string
, s
, e
)
8768 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
8769 slen
= (MB_CUR_MAX
> 1) ? STRLEN (string
) : 0;
8772 while (string
[start
] && i
--)
8773 ADVANCE_CHAR (string
, slen
, start
);
8776 while (string
[stop
] && i
--)
8777 ADVANCE_CHAR (string
, slen
, stop
);
8778 tt
= substring (string
, start
, stop
);
8783 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
8784 is `@', use the positional parameters; otherwise, use the value of
8785 VARNAME. If VARNAME is an array variable, use the array elements. */
8788 parameter_brace_substring (varname
, value
, estatep
, substr
, quoted
, pflags
, flags
)
8789 char *varname
, *value
;
8790 array_eltstate_t
*estatep
;
8792 int quoted
, pflags
, flags
;
8795 int vtype
, r
, starsub
;
8796 char *temp
, *val
, *tt
, *oname
;
8799 if (value
== 0 && ((varname
[0] != '@' && varname
[0] != '*') || varname
[1]))
8800 return ((char *)NULL
);
8802 oname
= this_command_name
;
8803 this_command_name
= varname
;
8805 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
8808 this_command_name
= oname
;
8809 return ((char *)NULL
);
8812 starsub
= vtype
& VT_STARSUB
;
8813 vtype
&= ~VT_STARSUB
;
8815 r
= verify_substring_values (v
, val
, substr
, vtype
, &e1
, &e2
);
8816 this_command_name
= oname
;
8819 if (vtype
== VT_VARIABLE
)
8821 return ((r
== 0) ? &expand_param_error
: (char *)NULL
);
8827 case VT_ARRAYMEMBER
:
8828 #if defined (HANDLE_MULTIBYTE)
8830 tt
= mb_substring (val
, e1
, e2
);
8833 tt
= substring (val
, e1
, e2
);
8835 if (vtype
== VT_VARIABLE
)
8837 if (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
))
8838 temp
= quote_string (tt
);
8840 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8845 if (vtype
== VT_POSPARMS
)
8846 tt
= pos_params (varname
, e1
, e2
, quoted
, pflags
);
8847 #if defined (ARRAY_VARS)
8848 /* assoc_subrange and array_subrange both call string_list_pos_params,
8849 so we can treat this case just like VT_POSPARAMS. */
8850 else if (assoc_p (v
))
8851 /* we convert to list and take first e2 elements starting at e1th
8852 element -- officially undefined for now */
8853 tt
= assoc_subrange (assoc_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8855 /* We want E2 to be the number of elements desired (arrays can be
8856 sparse, so verify_substring_values just returns the numbers
8857 specified and we rely on array_subrange to understand how to
8859 tt
= array_subrange (array_cell (v
), e1
, e2
, starsub
, quoted
, pflags
);
8861 /* We want to leave this alone in every case where pos_params/
8862 string_list_pos_params quotes the list members */
8863 if (tt
&& quoted
== 0 && ifs_is_null
)
8865 temp
= tt
; /* Posix interp 888 */
8867 else if (tt
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
8869 temp
= tt
; /* Posix interp 888 */
8871 else if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
8873 temp
= tt
? quote_escapes (tt
) : (char *)NULL
;
8881 temp
= (char *)NULL
;
8887 /****************************************************************/
8889 /* Functions to perform pattern substitution on variable values */
8891 /****************************************************************/
8894 shouldexp_replacement (s
)
8903 while (c
= s
[sindex
])
8910 /* We want to remove this backslash because we treat it as special
8911 in this context. THIS ASSUMES THE STRING IS PROCESSED BY
8912 strcreplace() OR EQUIVALENT that handles removing backslashes
8913 preceding the special character. */
8914 if (s
[sindex
] == '&')
8916 if (s
[sindex
] == '\\')
8921 ADVANCE_CHAR (s
, slen
, sindex
);
8927 pat_subst (string
, pat
, rep
, mflags
)
8928 char *string
, *pat
, *rep
;
8931 char *ret
, *s
, *e
, *str
, *rstr
, *mstr
, *send
;
8932 int rptr
, mtype
, rxpand
, mlen
;
8933 size_t rsize
, l
, replen
, rslen
;
8937 return (savestring (""));
8939 mtype
= mflags
& MATCH_TYPEMASK
;
8940 rxpand
= mflags
& MATCH_EXPREP
;
8943 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
8944 * with REP and return the result.
8945 * 2. A null pattern with mtype == MATCH_END means to append REP to
8946 * STRING and return the result.
8947 * 3. A null STRING with a matching pattern means to append REP to
8948 * STRING and return the result.
8950 * These process `&' in the replacement string, like `sed' does when
8951 * presented with a BRE of `^' or `$'.
8953 if ((pat
== 0 || *pat
== 0) && (mtype
== MATCH_BEG
|| mtype
== MATCH_END
))
8955 rstr
= (mflags
& MATCH_EXPREP
) ? strcreplace (rep
, '&', "", 2) : rep
;
8956 rslen
= STRLEN (rstr
);
8957 l
= STRLEN (string
);
8958 ret
= (char *)xmalloc (rslen
+ l
+ 2);
8960 strcpy (ret
, string
);
8961 else if (mtype
== MATCH_BEG
)
8964 strcpy (ret
+ rslen
, string
);
8968 strcpy (ret
, string
);
8969 strcpy (ret
+ l
, rstr
);
8975 else if (*string
== 0 && (match_pattern (string
, pat
, mtype
, &s
, &e
) != 0))
8976 return (mflags
& MATCH_EXPREP
) ? strcreplace (rep
, '&', "", 2)
8977 : (rep
? savestring (rep
) : savestring (""));
8979 ret
= (char *)xmalloc (rsize
= 64);
8981 send
= string
+ strlen (string
);
8983 for (replen
= STRLEN (rep
), rptr
= 0, str
= string
; *str
;)
8985 if (match_pattern (str
, pat
, mtype
, &s
, &e
) == 0)
8993 mstr
= xmalloc (mlen
+ 1);
8994 for (x
= 0; x
< mlen
; x
++)
8997 rstr
= strcreplace (rep
, '&', mstr
, 2);
8999 rslen
= strlen (rstr
);
9007 RESIZE_MALLOCED_BUFFER (ret
, rptr
, (l
+ rslen
), rsize
, 64);
9009 /* OK, now copy the leading unmatched portion of the string (from
9010 str to s) to ret starting at rptr (the current offset). Then copy
9011 the replacement string at ret + rptr + (s - str). Increment
9012 rptr (if necessary) and str and go on. */
9015 strncpy (ret
+ rptr
, str
, l
);
9020 strncpy (ret
+ rptr
, rstr
, rslen
);
9023 str
= e
; /* e == end of match */
9028 if (((mflags
& MATCH_GLOBREP
) == 0) || mtype
!= MATCH_ANY
)
9033 /* On a zero-length match, make sure we copy one character, since
9034 we increment one character to avoid infinite recursion. */
9035 char *p
, *origp
, *origs
;
9038 RESIZE_MALLOCED_BUFFER (ret
, rptr
, locale_mb_cur_max
, rsize
, 64);
9039 #if defined (HANDLE_MULTIBYTE)
9040 p
= origp
= ret
+ rptr
;
9042 COPY_CHAR_P (p
, str
, send
);
9046 ret
[rptr
++] = *str
++;
9047 e
++; /* avoid infinite recursion on zero-length match */
9052 /* Now copy the unmatched portion of the input string */
9056 RESIZE_MALLOCED_BUFFER (ret
, rptr
, l
, rsize
, 64);
9057 strcpy (ret
+ rptr
, str
);
9065 /* Do pattern match and replacement on the positional parameters. */
9067 pos_params_pat_subst (string
, pat
, rep
, mflags
)
9068 char *string
, *pat
, *rep
;
9071 WORD_LIST
*save
, *params
;
9074 int pchar
, qflags
, pflags
;
9076 save
= params
= list_rest_of_args ();
9078 return ((char *)NULL
);
9080 for ( ; params
; params
= params
->next
)
9082 ret
= pat_subst (params
->word
->word
, pat
, rep
, mflags
);
9083 w
= alloc_word_desc ();
9084 w
->word
= ret
? ret
: savestring ("");
9085 dispose_word (params
->word
);
9089 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
9090 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
9091 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
9093 /* If we are expanding in a context where word splitting will not be
9094 performed, treat as quoted. This changes how $* will be expanded. */
9095 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && expand_no_split_dollar_star
&& ifs_is_null
)
9096 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
9098 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
9099 dispose_words (save
);
9104 /* Perform pattern substitution on VALUE, which is the expansion of
9105 VARNAME. PATSUB is an expression supplying the pattern to match
9106 and the string to substitute. QUOTED is a flags word containing
9107 the type of quoting currently in effect. */
9109 parameter_brace_patsub (varname
, value
, estatep
, patsub
, quoted
, pflags
, flags
)
9110 char *varname
, *value
;
9111 array_eltstate_t
*estatep
;
9113 int quoted
, pflags
, flags
;
9115 int vtype
, mflags
, starsub
, delim
;
9116 char *val
, *temp
, *pat
, *rep
, *p
, *lpatsub
, *tt
, *oname
;
9120 return ((char *)NULL
);
9122 oname
= this_command_name
;
9123 this_command_name
= varname
; /* error messages */
9125 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
9128 this_command_name
= oname
;
9129 return ((char *)NULL
);
9132 starsub
= vtype
& VT_STARSUB
;
9133 vtype
&= ~VT_STARSUB
;
9136 /* PATSUB is never NULL when this is called. */
9139 mflags
|= MATCH_GLOBREP
;
9143 /* Malloc this because expand_string_if_necessary or one of the expansion
9144 functions in its call chain may free it on a substitution error. */
9145 lpatsub
= savestring (patsub
);
9147 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9148 mflags
|= MATCH_QUOTED
;
9151 mflags
|= MATCH_STARSUB
;
9153 if (pflags
& PF_ASSIGNRHS
)
9154 mflags
|= MATCH_ASSIGNRHS
;
9156 /* If the pattern starts with a `/', make sure we skip over it when looking
9157 for the replacement delimiter. */
9158 delim
= skip_to_delim (lpatsub
, ((*patsub
== '/') ? 1 : 0), "/", 0);
9159 if (lpatsub
[delim
] == '/')
9162 rep
= lpatsub
+ delim
+ 1;
9167 if (rep
&& *rep
== '\0')
9170 /* Perform the same expansions on the pattern as performed by the
9171 pattern removal expansions. */
9172 pat
= getpattern (lpatsub
, quoted
, 1);
9176 /* We want to perform quote removal on the expanded replacement even if
9177 the entire expansion is double-quoted because the parser and string
9178 extraction functions treated quotes in the replacement string as
9179 special. THIS IS NOT BACKWARDS COMPATIBLE WITH BASH-4.2. */
9180 if (shell_compatibility_level
> 42 && patsub_replacement
== 0)
9181 rep
= expand_string_if_necessary (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
), expand_string_unsplit
);
9182 else if (shell_compatibility_level
> 42 && patsub_replacement
)
9183 rep
= expand_string_for_patsub (rep
, quoted
& ~(Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
));
9184 /* This is the bash-4.2 code. */
9185 else if ((mflags
& MATCH_QUOTED
) == 0)
9186 rep
= expand_string_if_necessary (rep
, quoted
, expand_string_unsplit
);
9188 rep
= expand_string_to_string_internal (rep
, quoted
, expand_string_unsplit
);
9190 /* Check whether or not to replace `&' in the replacement string after
9191 expanding it, since we want to treat backslashes quoting the `&'
9193 if (patsub_replacement
&& rep
&& *rep
&& shouldexp_replacement (rep
))
9194 mflags
|= MATCH_EXPREP
;
9198 /* ksh93 doesn't allow the match specifier to be a part of the expanded
9199 pattern. This is an extension. Make sure we don't anchor the pattern
9200 at the beginning or end of the string if we're doing global replacement,
9203 if (mflags
& MATCH_GLOBREP
)
9204 mflags
|= MATCH_ANY
;
9205 else if (pat
&& pat
[0] == '#')
9207 mflags
|= MATCH_BEG
;
9210 else if (pat
&& pat
[0] == '%')
9212 mflags
|= MATCH_END
;
9216 mflags
|= MATCH_ANY
;
9218 /* OK, we now want to substitute REP for PAT in VAL. If
9219 flags & MATCH_GLOBREP is non-zero, the substitution is done
9220 everywhere, otherwise only the first occurrence of PAT is
9221 replaced. The pattern matching code doesn't understand
9222 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
9223 values passed in (VT_VARIABLE) so the pattern substitution
9224 code works right. We need to requote special chars after
9225 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
9226 other cases if QUOTED == 0, since the posparams and arrays
9227 indexed by * or @ do special things when QUOTED != 0. */
9232 case VT_ARRAYMEMBER
:
9233 temp
= pat_subst (val
, p
, rep
, mflags
);
9234 if (vtype
== VT_VARIABLE
)
9238 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
9244 /* This does the right thing for the case where we are not performing
9245 word splitting. MATCH_STARSUB restricts it to ${* /foo/bar}, and
9246 pos_params_pat_subst/string_list_pos_params will do the right thing
9247 in turn for the case where ifs_is_null. Posix interp 888 */
9248 if ((pflags
& PF_NOSPLIT2
) && (mflags
& MATCH_STARSUB
))
9249 mflags
|= MATCH_ASSIGNRHS
;
9250 temp
= pos_params_pat_subst (val
, p
, rep
, mflags
);
9251 if (temp
&& quoted
== 0 && ifs_is_null
)
9253 /* Posix interp 888 */
9255 else if (temp
&& quoted
== 0 && (pflags
& PF_ASSIGNRHS
))
9257 /* Posix interp 888 */
9259 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9261 tt
= quote_escapes (temp
);
9266 #if defined (ARRAY_VARS)
9268 /* If we are expanding in a context where word splitting will not be
9269 performed, treat as quoted. This changes how ${A[*]} will be
9270 expanded to make it identical to $*. */
9271 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9272 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
9274 /* these eventually call string_list_pos_params */
9276 temp
= assoc_patsub (assoc_cell (v
), p
, rep
, mflags
);
9278 temp
= array_patsub (array_cell (v
), p
, rep
, mflags
);
9280 if (temp
&& quoted
== 0 && ifs_is_null
)
9282 /* Posix interp 888 */
9284 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9286 tt
= quote_escapes (temp
);
9298 this_command_name
= oname
;
9303 /****************************************************************/
9305 /* Functions to perform case modification on variable values */
9307 /****************************************************************/
9309 /* Do case modification on the positional parameters. */
9312 pos_params_modcase (string
, pat
, modop
, mflags
)
9317 WORD_LIST
*save
, *params
;
9320 int pchar
, qflags
, pflags
;
9322 save
= params
= list_rest_of_args ();
9324 return ((char *)NULL
);
9326 for ( ; params
; params
= params
->next
)
9328 ret
= sh_modcase (params
->word
->word
, pat
, modop
);
9329 w
= alloc_word_desc ();
9330 w
->word
= ret
? ret
: savestring ("");
9331 dispose_word (params
->word
);
9335 pchar
= (mflags
& MATCH_STARSUB
) == MATCH_STARSUB
? '*' : '@';
9336 qflags
= (mflags
& MATCH_QUOTED
) == MATCH_QUOTED
? Q_DOUBLE_QUOTES
: 0;
9337 pflags
= (mflags
& MATCH_ASSIGNRHS
) == MATCH_ASSIGNRHS
? PF_ASSIGNRHS
: 0;
9339 /* If we are expanding in a context where word splitting will not be
9340 performed, treat as quoted. This changes how $* will be expanded. */
9341 if (pchar
== '*' && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9342 qflags
|= Q_DOUBLE_QUOTES
; /* Posix interp 888 */
9344 ret
= string_list_pos_params (pchar
, save
, qflags
, pflags
);
9345 dispose_words (save
);
9350 /* Perform case modification on VALUE, which is the expansion of
9351 VARNAME. MODSPEC is an expression supplying the type of modification
9352 to perform. QUOTED is a flags word containing the type of quoting
9353 currently in effect. */
9355 parameter_brace_casemod (varname
, value
, estatep
, modspec
, patspec
, quoted
, pflags
, flags
)
9356 char *varname
, *value
;
9357 array_eltstate_t
*estatep
;
9360 int quoted
, pflags
, flags
;
9362 int vtype
, starsub
, modop
, mflags
, x
;
9363 char *val
, *temp
, *pat
, *p
, *lpat
, *tt
, *oname
;
9367 return ((char *)NULL
);
9369 oname
= this_command_name
;
9370 this_command_name
= varname
;
9372 vtype
= get_var_and_type (varname
, value
, estatep
, quoted
, flags
, &v
, &val
);
9375 this_command_name
= oname
;
9376 return ((char *)NULL
);
9379 starsub
= vtype
& VT_STARSUB
;
9380 vtype
&= ~VT_STARSUB
;
9384 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
9385 mflags
|= MATCH_QUOTED
;
9387 mflags
|= MATCH_STARSUB
;
9388 if (pflags
& PF_ASSIGNRHS
)
9389 mflags
|= MATCH_ASSIGNRHS
;
9394 x
= p
&& p
[0] == modspec
;
9395 modop
= x
? CASE_UPPER
: CASE_UPFIRST
;
9398 else if (modspec
== ',')
9400 x
= p
&& p
[0] == modspec
;
9401 modop
= x
? CASE_LOWER
: CASE_LOWFIRST
;
9404 else if (modspec
== '~')
9406 x
= p
&& p
[0] == modspec
;
9407 modop
= x
? CASE_TOGGLEALL
: CASE_TOGGLE
;
9411 lpat
= p
? savestring (p
) : 0;
9412 /* Perform the same expansions on the pattern as performed by the
9413 pattern removal expansions. */
9414 pat
= lpat
? getpattern (lpat
, quoted
, 1) : 0;
9416 /* OK, now we do the case modification. */
9420 case VT_ARRAYMEMBER
:
9421 temp
= sh_modcase (val
, pat
, modop
);
9422 if (vtype
== VT_VARIABLE
)
9426 tt
= (mflags
& MATCH_QUOTED
) ? quote_string (temp
) : quote_escapes (temp
);
9433 temp
= pos_params_modcase (val
, pat
, modop
, mflags
);
9434 if (temp
&& quoted
== 0 && ifs_is_null
)
9436 /* Posix interp 888 */
9438 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9440 tt
= quote_escapes (temp
);
9446 #if defined (ARRAY_VARS)
9448 /* If we are expanding in a context where word splitting will not be
9449 performed, treat as quoted. This changes how ${A[*]} will be
9450 expanded to make it identical to $*. */
9451 if ((mflags
& MATCH_STARSUB
) && (mflags
& MATCH_ASSIGNRHS
) && ifs_is_null
)
9452 mflags
|= MATCH_QUOTED
; /* Posix interp 888 */
9454 temp
= assoc_p (v
) ? assoc_modcase (assoc_cell (v
), pat
, modop
, mflags
)
9455 : array_modcase (array_cell (v
), pat
, modop
, mflags
);
9457 if (temp
&& quoted
== 0 && ifs_is_null
)
9459 /* Posix interp 888 */
9461 else if (temp
&& (mflags
& MATCH_QUOTED
) == 0)
9463 tt
= quote_escapes (temp
);
9475 this_command_name
= oname
;
9480 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
9481 any occur, this must be a nested command substitution, so return 0.
9482 Otherwise, return 1. A valid arithmetic expression must always have a
9483 ( before a matching ), so any cases where there are more right parens
9484 means that this must not be an arithmetic expression, though the parser
9485 will not accept it without a balanced total number of parens. */
9487 chk_arithsub (s
, len
)
9499 else if (s
[i
] == RPAREN
)
9509 ADVANCE_CHAR (s
, len
, i
);
9515 ADVANCE_CHAR (s
, len
, i
);
9519 i
= skip_single_quoted (s
, len
, ++i
, 0);
9523 i
= skip_double_quoted ((char *)s
, len
, ++i
, 0);
9528 return (count
== 0);
9531 /****************************************************************/
9533 /* Functions to perform parameter expansion on a string */
9535 /****************************************************************/
9537 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
9539 parameter_brace_expand (string
, indexp
, quoted
, pflags
, quoted_dollar_atp
, contains_dollar_at
)
9541 int *indexp
, quoted
, pflags
, *quoted_dollar_atp
, *contains_dollar_at
;
9543 int check_nullness
, var_is_set
, var_is_null
, var_is_special
;
9544 int want_substring
, want_indir
, want_patsub
, want_casemod
, want_attributes
;
9545 char *name
, *value
, *temp
, *temp1
;
9546 WORD_DESC
*tdesc
, *ret
;
9547 int t_index
, sindex
, c
, tflag
, modspec
, local_pflags
, all_element_arrayref
;
9549 array_eltstate_t es
;
9551 temp
= temp1
= value
= (char *)NULL
;
9552 var_is_set
= var_is_null
= var_is_special
= check_nullness
= 0;
9553 want_substring
= want_indir
= want_patsub
= want_casemod
= want_attributes
= 0;
9556 all_element_arrayref
= 0;
9560 /* ${#var} doesn't have any of the other parameter expansions on it. */
9561 if (string
[t_index
] == '#' && legal_variable_starter (string
[t_index
+1])) /* {{ */
9562 name
= string_extract (string
, &t_index
, "}", SX_VARNAME
);
9564 #if defined (CASEMOD_EXPANSIONS)
9565 /* To enable case-toggling expansions using the `~' operator character
9566 define CASEMOD_TOGGLECASE in config-top.h */
9567 # if defined (CASEMOD_TOGGLECASE)
9568 name
= string_extract (string
, &t_index
, "#%^,~:-=?+/@}", SX_VARNAME
);
9570 name
= string_extract (string
, &t_index
, "#%^,:-=?+/@}", SX_VARNAME
);
9571 # endif /* CASEMOD_TOGGLECASE */
9573 name
= string_extract (string
, &t_index
, "#%:-=?+/@}", SX_VARNAME
);
9574 #endif /* CASEMOD_EXPANSIONS */
9576 /* Handle ${@[stuff]} now that @ is a word expansion operator. Not exactly
9577 the cleanest code ever. */
9578 if (*name
== 0 && sindex
== t_index
&& string
[sindex
] == '@')
9580 name
= (char *)xrealloc (name
, 2);
9585 else if (*name
== '!' && t_index
> sindex
&& string
[t_index
] == '@' && string
[t_index
+1] == RBRACE
)
9587 name
= (char *)xrealloc (name
, t_index
- sindex
+ 2);
9588 name
[t_index
- sindex
] = '@';
9589 name
[t_index
- sindex
+ 1] = '\0';
9596 #if defined (ARRAY_VARS)
9597 init_eltstate (&es
);
9599 es
.ind
= INTMAX_MIN
; /* XXX */
9601 /* If the name really consists of a special variable, then make sure
9602 that we have the entire name. We don't allow indirect references
9603 to special variables except `#', `?', `@' and `*'. This clause is
9604 designed to handle ${#SPECIAL} and ${!SPECIAL}, not anything more
9606 if ((sindex
== t_index
&& VALID_SPECIAL_LENGTH_PARAM (string
[t_index
])) ||
9607 (sindex
== t_index
&& string
[sindex
] == '#' && VALID_SPECIAL_LENGTH_PARAM (string
[sindex
+ 1])) ||
9608 (sindex
== t_index
- 1 && string
[sindex
] == '!' && VALID_INDIR_PARAM (string
[t_index
])))
9611 temp1
= string_extract (string
, &t_index
, "#%:-=?+/@}", 0);
9612 name
= (char *)xrealloc (name
, 3 + (strlen (temp1
)));
9613 *name
= string
[sindex
];
9614 if (string
[sindex
] == '!')
9616 /* indirect reference of $#, $?, $@, or $* */
9617 name
[1] = string
[sindex
+ 1];
9618 strcpy (name
+ 2, temp1
);
9621 strcpy (name
+ 1, temp1
);
9626 /* Find out what character ended the variable name. Then
9627 do the appropriate thing. */
9628 if (c
= string
[sindex
])
9631 /* If c is followed by one of the valid parameter expansion
9632 characters, move past it as normal. If not, assume that
9633 a substring specification is being given, and do not move
9635 if (c
== ':' && VALID_PARAM_EXPAND_CHAR (string
[sindex
]))
9638 if (c
= string
[sindex
])
9641 else if (c
== ':' && string
[sindex
] != RBRACE
)
9643 else if (c
== '/' /* && string[sindex] != RBRACE */) /* XXX */
9645 #if defined (CASEMOD_EXPANSIONS)
9646 else if (c
== '^' || c
== ',' || c
== '~')
9652 else if (c
== '@' && (string
[sindex
] == 'a' || string
[sindex
] == 'A') && string
[sindex
+1] == RBRACE
)
9654 /* special case because we do not want to shortcut foo as foo[0] here */
9655 want_attributes
= 1;
9656 local_pflags
|= PF_ALLINDS
;
9659 /* Catch the valid and invalid brace expressions that made it through the
9661 /* ${#-} is a valid expansion and means to take the length of $-.
9662 Similarly for ${#?} and ${##}... */
9663 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
9664 VALID_SPECIAL_LENGTH_PARAM (c
) && string
[sindex
] == RBRACE
)
9666 name
= (char *)xrealloc (name
, 3);
9669 c
= string
[sindex
++];
9672 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
9673 if (name
[0] == '#' && name
[1] == '\0' && check_nullness
== 0 &&
9674 member (c
, "%:=+/") && string
[sindex
] == RBRACE
)
9676 temp
= (char *)NULL
;
9677 goto bad_substitution
; /* XXX - substitution error */
9680 /* Indirect expansion begins with a `!'. A valid indirect expansion is
9681 either a variable name, one of the positional parameters or a special
9682 variable that expands to one of the positional parameters. */
9683 want_indir
= *name
== '!' &&
9684 (legal_variable_starter ((unsigned char)name
[1]) || DIGIT (name
[1])
9685 || VALID_INDIR_PARAM (name
[1]));
9687 /* Determine the value of this variable whose name is NAME. */
9689 /* Check for special variables, directly referenced. */
9690 if (SPECIAL_VAR (name
, want_indir
))
9693 /* Check for special expansion things, like the length of a parameter */
9694 if (*name
== '#' && name
[1])
9696 /* If we are not pointing at the character just after the
9697 closing brace, then we haven't gotten all of the name.
9698 Since it begins with a special character, this is a bad
9699 substitution. Also check NAME for validity before trying
9701 if (string
[sindex
- 1] != RBRACE
|| (valid_length_expression (name
) == 0))
9703 temp
= (char *)NULL
;
9704 goto bad_substitution
; /* substitution error */
9707 number
= parameter_brace_expand_length (name
);
9708 if (number
== INTMAX_MIN
&& unbound_vars_is_error
)
9710 set_exit_status (EXECUTION_FAILURE
);
9711 err_unboundvar (name
+1);
9713 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9719 return (&expand_wdesc_error
);
9722 ret
= alloc_word_desc ();
9723 ret
->word
= itos (number
);
9728 /* ${@} is identical to $@. */
9729 if (name
[0] == '@' && name
[1] == '\0')
9731 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9732 *quoted_dollar_atp
= 1;
9734 if (contains_dollar_at
)
9735 *contains_dollar_at
= 1;
9737 tflag
|= W_DOLLARAT
;
9740 /* Process ${!PREFIX*} expansion. */
9741 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9742 (string
[sindex
- 2] == '*' || string
[sindex
- 2] == '@') &&
9743 legal_variable_starter ((unsigned char) name
[1]))
9748 temp1
= savestring (name
+ 1);
9749 number
= strlen (temp1
);
9750 temp1
[number
- 1] = '\0';
9751 x
= all_variables_matching_prefix (temp1
);
9752 xlist
= strvec_to_word_list (x
, 0, 0);
9753 if (string
[sindex
- 2] == '*')
9754 temp
= string_list_dollar_star (xlist
, quoted
, 0);
9757 temp
= string_list_dollar_at (xlist
, quoted
, 0);
9758 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9759 *quoted_dollar_atp
= 1;
9760 if (contains_dollar_at
)
9761 *contains_dollar_at
= 1;
9763 tflag
|= W_DOLLARAT
;
9766 dispose_words (xlist
);
9772 ret
= alloc_word_desc ();
9774 ret
->flags
= tflag
; /* XXX */
9778 #if defined (ARRAY_VARS)
9779 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */
9780 if (want_indir
&& string
[sindex
- 1] == RBRACE
&&
9781 string
[sindex
- 2] == RBRACK
&& valid_array_reference (name
+1, 0))
9785 temp1
= savestring (name
+ 1);
9786 x
= array_variable_name (temp1
, 0, &x1
, (int *)0);
9788 if (ALL_ELEMENT_SUB (x1
[0]) && x1
[1] == RBRACK
)
9790 temp
= array_keys (temp1
, quoted
, pflags
); /* handles assoc vars too */
9793 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
9794 *quoted_dollar_atp
= 1;
9795 if (contains_dollar_at
)
9796 *contains_dollar_at
= 1;
9798 tflag
|= W_DOLLARAT
;
9805 ret
= alloc_word_desc ();
9807 ret
->flags
= tflag
; /* XXX */
9813 #endif /* ARRAY_VARS */
9815 /* Make sure that NAME is valid before trying to go on. */
9816 if (valid_brace_expansion_word (want_indir
? name
+ 1 : name
,
9817 var_is_special
) == 0)
9819 temp
= (char *)NULL
;
9820 goto bad_substitution
; /* substitution error */
9825 tdesc
= parameter_brace_expand_indir (name
+ 1, var_is_special
, quoted
, pflags
|local_pflags
, quoted_dollar_atp
, contains_dollar_at
);
9826 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9828 temp
= (char *)NULL
;
9829 goto bad_substitution
;
9832 /* Turn off the W_ARRAYIND flag because there is no way for this function
9833 to return the index we're supposed to be using. */
9834 if (tdesc
&& tdesc
->flags
)
9835 tdesc
->flags
&= ~W_ARRAYIND
;
9837 /* If the indir expansion contains $@/$*, extend the special treatment
9838 of the case of no positional parameters and `set -u' to it. */
9839 if (contains_dollar_at
&& *contains_dollar_at
)
9840 all_element_arrayref
= 1;
9844 local_pflags
|= PF_IGNUNBOUND
|(pflags
&(PF_NOSPLIT2
|PF_ASSIGNRHS
));
9845 tdesc
= parameter_brace_expand_word (name
, var_is_special
, quoted
, local_pflags
, &es
);
9848 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
9857 tflag
= tdesc
->flags
;
9858 dispose_word_desc (tdesc
);
9863 if (temp
== &expand_param_error
|| temp
== &expand_param_fatal
)
9867 return (temp
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9870 #if defined (ARRAY_VARS)
9871 if (valid_array_reference (name
, 0))
9877 /* If in a context where word splitting will not take place, treat as
9878 if double-quoted. Has effects with $* and ${array[*]} */
9880 if (pflags
& PF_ASSIGNRHS
)
9881 qflags
|= Q_DOUBLE_QUOTES
;
9882 /* We duplicate a little code here */
9883 t
= mbschr (name
, LBRACK
);
9884 if (t
&& ALL_ELEMENT_SUB (t
[1]) && t
[2] == RBRACK
)
9886 all_element_arrayref
= 1;
9887 if (expand_no_split_dollar_star
&& t
[1] == '*') /* XXX */
9888 qflags
|= Q_DOUBLE_QUOTES
;
9890 chk_atstar (name
, qflags
, pflags
, quoted_dollar_atp
, contains_dollar_at
);
9894 var_is_set
= temp
!= (char *)0;
9895 var_is_null
= check_nullness
&& (var_is_set
== 0 || *temp
== 0);
9896 /* XXX - this may not need to be restricted to special variables */
9898 var_is_null
|= var_is_set
&& var_is_special
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && QUOTED_NULL (temp
);
9899 #if defined (ARRAY_VARS)
9901 var_is_null
|= var_is_set
&&
9902 (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) &&
9903 QUOTED_NULL (temp
) &&
9904 valid_array_reference (name
, 0) &&
9905 chk_atstar (name
, 0, 0, (int *)0, (int *)0);
9908 /* Get the rest of the stuff inside the braces. */
9909 if (c
&& c
!= RBRACE
)
9911 /* Extract the contents of the ${ ... } expansion
9912 according to the Posix.2 rules. */
9913 value
= extract_dollar_brace_string (string
, &sindex
, quoted
, (c
== '%' || c
== '#' || c
=='/' || c
== '^' || c
== ',' || c
==':') ? SX_POSIXEXP
|SX_WORD
: SX_WORD
);
9914 if (string
[sindex
] == RBRACE
)
9917 goto bad_substitution
; /* substitution error */
9920 value
= (char *)NULL
;
9924 /* All the cases where an expansion can possibly generate an unbound
9926 if (want_substring
|| want_patsub
|| want_casemod
|| c
== '@' || c
== '#' || c
== '%' || c
== RBRACE
)
9928 if (var_is_set
== 0 && unbound_vars_is_error
&& ((name
[0] != '@' && name
[0] != '*') || name
[1]) && all_element_arrayref
== 0)
9930 set_exit_status (EXECUTION_FAILURE
);
9931 err_unboundvar (name
);
9935 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9939 /* If this is a substring spec, process it and add the result. */
9942 temp1
= parameter_brace_substring (name
, temp
, &es
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9945 #if defined (ARRAY_VARS)
9946 flush_eltstate (&es
);
9949 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9952 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9955 ret
= alloc_word_desc ();
9957 /* We test quoted_dollar_atp because we want variants with double-quoted
9958 "$@" to take a different code path. In fact, we make sure at the end
9959 of expand_word_internal that we're only looking at these flags if
9960 quoted_dollar_at == 0. */
9962 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9963 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9964 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9965 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 &&
9966 (pflags
& PF_ASSIGNRHS
))
9967 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9968 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9969 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9970 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
9975 else if (want_patsub
)
9977 temp1
= parameter_brace_patsub (name
, temp
, &es
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
9980 #if defined (ARRAY_VARS)
9981 flush_eltstate (&es
);
9984 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
9987 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
9990 ret
= alloc_word_desc ();
9993 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
9994 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
9995 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
9996 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9997 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
9998 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10003 #if defined (CASEMOD_EXPANSIONS)
10004 else if (want_casemod
)
10006 temp1
= parameter_brace_casemod (name
, temp
, &es
, modspec
, value
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10009 #if defined (ARRAY_VARS)
10010 flush_eltstate (&es
);
10013 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
10016 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10019 ret
= alloc_word_desc ();
10022 (quoted_dollar_atp
== 0 || *quoted_dollar_atp
== 0) &&
10023 QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10024 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10025 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10026 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10027 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10034 /* Do the right thing based on which character ended the variable name. */
10040 set_exit_status (EXECUTION_FAILURE
);
10041 report_error (_("%s: bad substitution"), string
? string
: "??");
10045 #if defined (ARRAY_VARS)
10046 flush_eltstate (&es
);
10048 if (shell_compatibility_level
<= 43)
10049 return &expand_wdesc_error
;
10051 return ((posixly_correct
&& interactive_shell
== 0) ? &expand_wdesc_fatal
: &expand_wdesc_error
);
10057 temp1
= parameter_brace_transform (name
, temp
, &es
, value
, c
, quoted
, pflags
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10060 #if defined (ARRAY_VARS)
10061 flush_eltstate (&es
);
10064 if (temp1
== &expand_param_error
|| temp1
== &expand_param_fatal
)
10067 set_exit_status (EXECUTION_FAILURE
);
10068 report_error (_("%s: bad substitution"), string
? string
: "??");
10069 return (temp1
== &expand_param_error
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10072 ret
= alloc_word_desc ();
10074 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10075 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10076 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10077 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10078 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10083 case '#': /* ${param#[#]pattern} */
10084 case '%': /* ${param%[%]pattern} */
10085 if (value
== 0 || *value
== '\0' || temp
== 0 || *temp
== '\0')
10090 temp1
= parameter_brace_remove_pattern (name
, temp
, &es
, value
, c
, quoted
, (tflag
& W_ARRAYIND
) ? AV_USEIND
: 0);
10093 #if defined (ARRAY_VARS)
10094 flush_eltstate (&es
);
10097 ret
= alloc_word_desc ();
10099 if (temp1
&& QUOTED_NULL (temp1
) && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10100 ret
->flags
|= W_QUOTED
|W_HASQUOTEDNULL
;
10101 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
10102 else if (temp1
&& (name
[0] == '*' && name
[1] == 0) && quoted
== 0 && ifs_is_null
)
10103 ret
->flags
|= W_SPLITSPACE
; /* Posix interp 888 */
10112 if (var_is_set
&& var_is_null
== 0)
10114 /* If the operator is `+', we don't want the value of the named
10115 variable for anything, just the value of the right hand side. */
10118 /* XXX -- if we're double-quoted and the named variable is "$@",
10119 we want to turn off any special handling of "$@" --
10120 we're not using it, so whatever is on the rhs applies. */
10121 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
10122 *quoted_dollar_atp
= 0;
10123 if (contains_dollar_at
)
10124 *contains_dollar_at
= 0;
10129 /* From Posix discussion on austin-group list. Issue 221
10130 requires that backslashes escaping `}' inside
10131 double-quoted ${...} be removed. */
10132 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10133 quoted
|= Q_DOLBRACE
;
10134 ret
= parameter_brace_expand_rhs (name
, value
, c
,
10138 contains_dollar_at
);
10139 /* XXX - fix up later, esp. noting presence of
10140 W_HASQUOTEDNULL in ret->flags */
10144 temp
= (char *)NULL
;
10150 /* Otherwise do nothing; just use the value in TEMP. */
10152 else /* VAR not set or VAR is NULL. */
10154 /* If we're freeing a quoted null here, we need to remember we saw
10155 it so we can restore it later if needed, or the caller can note it.
10156 The check against `+' doesn't really matter, since the other cases
10157 don't use or return TFLAG, but it's good for clarity. */
10158 if (c
== '+' && temp
&& QUOTED_NULL (temp
) &&
10159 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
10160 tflag
|= W_HASQUOTEDNULL
;
10163 temp
= (char *)NULL
;
10164 if (c
== '=' && var_is_special
)
10166 set_exit_status (EXECUTION_FAILURE
);
10167 report_error (_("$%s: cannot assign in this way"), name
);
10170 #if defined (ARRAY_VARS)
10171 flush_eltstate (&es
);
10173 return &expand_wdesc_error
;
10177 parameter_brace_expand_error (name
, value
, check_nullness
);
10178 #if defined (ARRAY_VARS)
10179 flush_eltstate (&es
);
10181 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10185 /* XXX -- if we're double-quoted and the named variable is "$@",
10186 we want to turn off any special handling of "$@" --
10187 we're not using it, so whatever is on the rhs applies. */
10188 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && quoted_dollar_atp
)
10189 *quoted_dollar_atp
= 0;
10190 if (contains_dollar_at
)
10191 *contains_dollar_at
= 0;
10193 /* From Posix discussion on austin-group list. Issue 221 requires
10194 that backslashes escaping `}' inside double-quoted ${...} be
10196 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
10197 quoted
|= Q_DOLBRACE
;
10198 ret
= parameter_brace_expand_rhs (name
, value
, c
, quoted
, pflags
,
10200 contains_dollar_at
);
10201 /* XXX - fix up later, esp. noting presence of
10202 W_HASQUOTEDNULL in tdesc->flags */
10210 #if defined (ARRAY_VARS)
10211 flush_eltstate (&es
);
10216 ret
= alloc_word_desc ();
10217 ret
->flags
= tflag
;
10223 /* Expand a single ${xxx} expansion. The braces are optional. When
10224 the braces are used, parameter_brace_expand() does the work,
10225 possibly calling param_expand recursively. */
10227 param_expand (string
, sindex
, quoted
, expanded_something
,
10228 contains_dollar_at
, quoted_dollar_at_p
, had_quoted_null_p
,
10231 int *sindex
, quoted
, *expanded_something
, *contains_dollar_at
;
10232 int *quoted_dollar_at_p
, *had_quoted_null_p
, pflags
;
10234 char *temp
, *temp1
, uerror
[3], *savecmd
;
10235 int zindex
, t_index
, expok
, eflag
;
10239 WORD_LIST
*list
, *l
;
10240 WORD_DESC
*tdesc
, *ret
;
10241 int tflag
, nullarg
;
10243 /*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
10245 c
= string
[++zindex
];
10247 temp
= (char *)NULL
;
10248 ret
= tdesc
= (WORD_DESC
*)NULL
;
10251 /* Do simple cases first. Switch on what follows '$'. */
10265 temp1
= dollar_vars
[TODIGIT (c
)];
10266 /* This doesn't get called when (pflags&PF_IGNUNBOUND) != 0 */
10267 if (unbound_vars_is_error
&& temp1
== (char *)NULL
)
10272 set_exit_status (EXECUTION_FAILURE
);
10273 err_unboundvar (uerror
);
10274 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10277 temp
= (*temp1
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10278 ? quote_string (temp1
)
10279 : quote_escapes (temp1
);
10281 temp
= (char *)NULL
;
10285 /* $$ -- pid of the invoking shell. */
10287 temp
= itos (dollar_dollar_pid
);
10290 /* $# -- number of positional parameters. */
10292 temp
= itos (number_of_args ());
10295 /* $? -- return value of the last synchronous command. */
10297 temp
= itos (last_command_exit_value
);
10300 /* $- -- flags supplied to the shell on invocation or by `set'. */
10302 temp
= which_set_flags ();
10305 /* $! -- Pid of the last asynchronous command. */
10307 /* If no asynchronous pids have been created, expand to nothing.
10308 If `set -u' has been executed, and no async processes have
10309 been created, this is an expansion error. */
10310 if (last_asynchronous_pid
== NO_PID
)
10312 if (expanded_something
)
10313 *expanded_something
= 0;
10314 temp
= (char *)NULL
;
10315 if (unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10320 set_exit_status (EXECUTION_FAILURE
);
10321 err_unboundvar (uerror
);
10322 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10326 temp
= itos (last_asynchronous_pid
);
10329 /* The only difference between this and $@ is when the arg is quoted. */
10330 case '*': /* `$*' */
10331 list
= list_rest_of_args ();
10334 /* According to austin-group posix proposal by Geoff Clare in
10335 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
10337 "The shell shall write a message to standard error and
10338 immediately exit when it tries to expand an unset parameter
10339 other than the '@' and '*' special parameters."
10342 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10347 set_exit_status (EXECUTION_FAILURE
);
10348 err_unboundvar (uerror
);
10349 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10353 /* If there are no command-line arguments, this should just
10354 disappear if there are other characters in the expansion,
10355 even if it's quoted. */
10356 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && list
== 0)
10357 temp
= (char *)NULL
;
10358 else if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
|Q_PATQUOTE
))
10360 /* If we have "$*" we want to make a string of the positional
10361 parameters, separated by the first character of $IFS, and
10362 quote the whole string, including the separators. If IFS
10363 is unset, the parameters are separated by ' '; if $IFS is
10364 null, the parameters are concatenated. */
10365 temp
= (quoted
& (Q_DOUBLE_QUOTES
|Q_PATQUOTE
)) ? string_list_dollar_star (list
, quoted
, 0) : string_list (list
);
10368 temp1
= (quoted
& Q_DOUBLE_QUOTES
) ? quote_string (temp
) : temp
;
10370 tflag
|= W_HASQUOTEDNULL
;
10378 /* We check whether or not we're eventually going to split $* here,
10379 for example when IFS is empty and we are processing the rhs of
10380 an assignment statement. In that case, we don't separate the
10381 arguments at all. Otherwise, if the $* is not quoted it is
10383 if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
== 0 && (pflags
& PF_ASSIGNRHS
))
10385 /* Posix interp 888: RHS of assignment, IFS unset: no splitting,
10386 separate with space */
10387 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10388 temp
= temp1
? quote_string (temp1
) : temp1
;
10389 /* XXX - tentative - note that we saw a quoted null here */
10390 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
10391 tflag
|= W_SAWQUOTEDNULL
;
10394 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_null
&& (pflags
& PF_ASSIGNRHS
))
10396 /* Posix interp 888: RHS of assignment, IFS set to '' */
10397 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10398 temp
= temp1
? quote_escapes (temp1
) : temp1
;
10401 else if (expand_no_split_dollar_star
&& quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && (pflags
& PF_ASSIGNRHS
))
10403 /* Posix interp 888: RHS of assignment, IFS set to non-null value */
10404 temp1
= string_list_dollar_star (list
, quoted
, pflags
);
10405 temp
= temp1
? quote_string (temp1
) : temp1
;
10407 /* XXX - tentative - note that we saw a quoted null here */
10408 if (temp1
&& *temp1
== 0 && QUOTED_NULL (temp
))
10409 tflag
|= W_SAWQUOTEDNULL
;
10412 /* XXX - should we check ifs_is_set here as well? */
10413 # if defined (HANDLE_MULTIBYTE)
10414 else if (expand_no_split_dollar_star
&& ifs_firstc
[0] == 0)
10416 else if (expand_no_split_dollar_star
&& ifs_firstc
== 0)
10418 /* Posix interp 888: not RHS, no splitting, IFS set to '' */
10419 temp
= string_list_dollar_star (list
, quoted
, 0);
10422 temp
= string_list_dollar_at (list
, quoted
, 0);
10423 /* Set W_SPLITSPACE to make sure the individual positional
10424 parameters are split into separate arguments */
10426 if (quoted
== 0 && (ifs_is_set
== 0 || ifs_is_null
))
10427 #else /* change with bash-5.0 */
10428 if (quoted
== 0 && ifs_is_null
)
10430 tflag
|= W_SPLITSPACE
;
10431 /* If we're not quoted but we still don't want word splitting, make
10432 we quote the IFS characters to protect them from splitting (e.g.,
10433 when $@ is in the string as well). */
10434 else if (temp
&& quoted
== 0 && ifs_is_set
&& (pflags
& PF_ASSIGNRHS
))
10436 temp1
= quote_string (temp
);
10442 if (expand_no_split_dollar_star
== 0 && contains_dollar_at
)
10443 *contains_dollar_at
= 1;
10446 dispose_words (list
);
10449 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
10450 means that we have to turn quoting off after we split into
10451 the individually quoted arguments so that the final split
10452 on the first character of $IFS is still done. */
10453 case '@': /* `$@' */
10454 list
= list_rest_of_args ();
10457 /* According to austin-group posix proposal by Geoff Clare in
10458 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
10460 "The shell shall write a message to standard error and
10461 immediately exit when it tries to expand an unset parameter
10462 other than the '@' and '*' special parameters."
10465 if (list
== 0 && unbound_vars_is_error
&& (pflags
& PF_IGNUNBOUND
) == 0)
10470 set_exit_status (EXECUTION_FAILURE
);
10471 err_unboundvar (uerror
);
10472 return (interactive_shell
? &expand_wdesc_error
: &expand_wdesc_fatal
);
10476 for (nullarg
= 0, l
= list
; l
; l
= l
->next
)
10478 if (l
->word
&& (l
->word
->word
== 0 || l
->word
->word
[0] == 0))
10482 /* We want to flag the fact that we saw this. We can't turn
10483 off quoting entirely, because other characters in the
10484 string might need it (consider "\"$@\""), but we need some
10485 way to signal that the final split on the first character
10486 of $IFS should be done, even though QUOTED is 1. */
10487 /* XXX - should this test include Q_PATQUOTE? */
10488 if (quoted_dollar_at_p
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10489 *quoted_dollar_at_p
= 1;
10490 if (contains_dollar_at
)
10491 *contains_dollar_at
= 1;
10493 /* We want to separate the positional parameters with the first
10494 character of $IFS in case $IFS is something other than a space.
10495 We also want to make sure that splitting is done no matter what --
10496 according to POSIX.2, this expands to a list of the positional
10497 parameters no matter what IFS is set to. */
10498 /* XXX - what to do when in a context where word splitting is not
10499 performed? Even when IFS is not the default, posix seems to imply
10500 that we have to expand $@ to all the positional parameters and
10501 separate them with spaces, which are preserved because word splitting
10502 doesn't take place. See below for how we use PF_NOSPLIT2 here. */
10504 /* These are the cases where word splitting will not be performed. */
10505 if (pflags
& PF_ASSIGNRHS
)
10507 temp
= string_list_dollar_at (list
, (quoted
|Q_DOUBLE_QUOTES
), pflags
);
10509 tflag
|= W_HASQUOTEDNULL
; /* we know quoting produces quoted nulls */
10512 /* This needs to match what expand_word_internal does with non-quoted $@
10513 does with separating with spaces. Passing Q_DOUBLE_QUOTES means that
10514 the characters in LIST will be quoted, and PF_ASSIGNRHS ensures that
10515 they will separated by spaces. After doing this, we need the special
10516 handling for PF_NOSPLIT2 in expand_word_internal to remove the CTLESC
10518 else if (pflags
& PF_NOSPLIT2
)
10520 #if defined (HANDLE_MULTIBYTE)
10521 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
[0] != ' ')
10523 if (quoted
== 0 && ifs_is_set
&& ifs_is_null
== 0 && ifs_firstc
!= ' ')
10525 /* Posix interp 888 */
10526 temp
= string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, pflags
);
10528 temp
= string_list_dollar_at (list
, quoted
, pflags
);
10531 temp
= string_list_dollar_at (list
, quoted
, pflags
);
10533 tflag
|= W_DOLLARAT
;
10534 dispose_words (list
);
10538 tdesc
= parameter_brace_expand (string
, &zindex
, quoted
, pflags
,
10539 quoted_dollar_at_p
,
10540 contains_dollar_at
);
10542 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
10544 temp
= tdesc
? tdesc
->word
: (char *)0;
10547 /* Quoted nulls should be removed if there is anything else
10549 /* Note that we saw the quoted null so we can add one back at
10550 the end of this function if there are no other characters
10551 in the string, discard TEMP, and go on. The exception to
10552 this is when we have "${@}" and $1 is '', since $@ needs
10553 special handling. */
10554 if (tdesc
&& tdesc
->word
&& (tdesc
->flags
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
))
10556 if (had_quoted_null_p
)
10557 *had_quoted_null_p
= 1;
10558 if (*quoted_dollar_at_p
== 0)
10561 tdesc
->word
= temp
= (char *)NULL
;
10569 /* Do command or arithmetic substitution. */
10571 /* We have to extract the contents of this paren substitution. */
10572 t_index
= zindex
+ 1;
10573 /* XXX - might want to check for string[t_index+2] == LPAREN and parse
10574 as arithmetic substitution immediately. */
10575 temp
= extract_command_subst (string
, &t_index
, (pflags
&PF_COMPLETE
) ? SX_COMPLETE
: 0);
10578 /* For Posix.2-style `$(( ))' arithmetic substitution,
10579 extract the expression and pass it to the evaluator. */
10580 if (temp
&& *temp
== LPAREN
)
10584 temp2
= savestring (temp1
);
10585 t_index
= strlen (temp2
) - 1;
10587 if (temp2
[t_index
] != RPAREN
)
10593 /* Cut off ending `)' */
10594 temp2
[t_index
] = '\0';
10596 if (chk_arithsub (temp2
, t_index
) == 0)
10600 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
10605 /* Expand variables found inside the expression. */
10606 temp1
= expand_arith_string (temp2
, Q_DOUBLE_QUOTES
|Q_ARITH
);
10610 /* No error messages. */
10611 savecmd
= this_command_name
;
10612 this_command_name
= (char *)NULL
;
10614 eflag
= (shell_compatibility_level
> 51) ? 0 : EXP_EXPANDED
;
10615 number
= evalexp (temp1
, eflag
, &expok
);
10616 this_command_name
= savecmd
;
10621 if (interactive_shell
== 0 && posixly_correct
)
10623 set_exit_status (EXECUTION_FAILURE
);
10624 return (&expand_wdesc_fatal
);
10627 return (&expand_wdesc_error
);
10629 temp
= itos (number
);
10634 if (pflags
& PF_NOCOMSUB
)
10635 /* we need zindex+1 because string[zindex] == RPAREN */
10636 temp1
= substring (string
, *sindex
, zindex
+1);
10639 tdesc
= command_substitute (temp
, quoted
, pflags
&PF_ASSIGNRHS
);
10640 temp1
= tdesc
? tdesc
->word
: (char *)NULL
;
10642 dispose_word_desc (tdesc
);
10648 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
10649 away in a future bash release. */
10651 /* Extract the contents of this arithmetic substitution. */
10652 t_index
= zindex
+ 1;
10653 temp
= extract_arithmetic_subst (string
, &t_index
);
10657 temp
= savestring (string
);
10658 if (expanded_something
)
10659 *expanded_something
= 0;
10663 /* Do initial variable expansion. */
10664 temp1
= expand_arith_string (temp
, Q_DOUBLE_QUOTES
|Q_ARITH
);
10669 /* Find the variable in VARIABLE_LIST. */
10670 temp
= (char *)NULL
;
10672 for (t_index
= zindex
; (c
= string
[zindex
]) && legal_variable_char (c
); zindex
++)
10674 temp1
= (zindex
> t_index
) ? substring (string
, t_index
, zindex
) : (char *)NULL
;
10676 /* If this isn't a variable name, then just output the `$'. */
10677 if (temp1
== 0 || *temp1
== '\0')
10680 temp
= (char *)xmalloc (2);
10683 if (expanded_something
)
10684 *expanded_something
= 0;
10688 /* If the variable exists, return its value cell. */
10689 var
= find_variable (temp1
);
10691 if (var
&& invisible_p (var
) == 0 && var_isset (var
))
10693 #if defined (ARRAY_VARS)
10694 if (assoc_p (var
) || array_p (var
))
10696 temp
= array_p (var
) ? array_reference (array_cell (var
), 0)
10697 : assoc_reference (assoc_cell (var
), "0");
10699 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10700 ? quote_string (temp
)
10701 : quote_escapes (temp
);
10702 else if (unbound_vars_is_error
)
10703 goto unbound_variable
;
10708 temp
= value_cell (var
);
10710 temp
= (*temp
&& (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
10711 ? quote_string (temp
)
10712 : ((pflags
& PF_ASSIGNRHS
) ? quote_rhs (temp
)
10713 : quote_escapes (temp
));
10720 else if (var
&& (invisible_p (var
) || var_isset (var
) == 0))
10721 temp
= (char *)NULL
;
10722 else if ((var
= find_variable_last_nameref (temp1
, 0)) && var_isset (var
) && invisible_p (var
) == 0)
10724 temp
= nameref_cell (var
);
10725 #if defined (ARRAY_VARS)
10726 if (temp
&& *temp
&& valid_array_reference (temp
, 0))
10728 chk_atstar (temp
, quoted
, pflags
, quoted_dollar_at_p
, contains_dollar_at
);
10729 tdesc
= parameter_brace_expand_word (temp
, SPECIAL_VAR (temp
, 0), quoted
, pflags
, 0);
10730 if (tdesc
== &expand_wdesc_error
|| tdesc
== &expand_wdesc_fatal
)
10737 /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
10738 if (temp
&& *temp
&& legal_identifier (temp
) == 0)
10740 set_exit_status (EXECUTION_FAILURE
);
10741 report_error (_("%s: invalid variable name for name reference"), temp
);
10742 return (&expand_wdesc_error
); /* XXX */
10745 temp
= (char *)NULL
;
10748 temp
= (char *)NULL
;
10751 if (unbound_vars_is_error
)
10753 set_exit_status (EXECUTION_FAILURE
);
10754 err_unboundvar (temp1
);
10763 set_exit_status (EXECUTION_FAILURE
);
10764 return ((unbound_vars_is_error
&& interactive_shell
== 0)
10765 ? &expand_wdesc_fatal
10766 : &expand_wdesc_error
);
10769 if (string
[zindex
])
10777 ret
= alloc_word_desc ();
10778 ret
->flags
= tflag
; /* XXX */
10784 #if defined (ARRAY_VARS)
10785 /* Characters that need to be backslash-quoted after expanding array subscripts */
10786 static char abstab
[256] = { '\1' };
10788 /* Run an array subscript through the appropriate word expansions. */
10790 expand_subscript_string (string
, quoted
)
10799 if (string
== 0 || *string
== 0)
10800 return (char *)NULL
;
10802 oe
= expand_no_split_dollar_star
;
10803 ret
= (char *)NULL
;
10805 td
.flags
= W_NOPROCSUB
|W_NOTILDE
|W_NOSPLIT2
; /* XXX - W_NOCOMSUB? */
10806 td
.word
= savestring (string
); /* in case it's freed on error */
10808 expand_no_split_dollar_star
= 1;
10809 tlist
= call_expand_word_internal (&td
, quoted
, 0, (int *)NULL
, (int *)NULL
);
10810 expand_no_split_dollar_star
= oe
;
10816 remove_quoted_nulls (tlist
->word
->word
);
10817 tlist
->word
->flags
&= ~W_HASQUOTEDNULL
;
10819 dequote_list (tlist
);
10820 ret
= string_list (tlist
);
10821 dispose_words (tlist
);
10828 /* Expand the subscript in STRING, which is an array reference. To ensure we
10829 only expand it once, we quote the characters that would start another
10830 expansion and the bracket characters that are special to array subscripts. */
10832 expand_array_subscript (string
, sindex
, quoted
, flags
)
10837 char *ret
, *exp
, *t
;
10842 slen
= STRLEN (string
);
10844 if (abstab
[0] == '\1')
10846 /* These are basically the characters that start shell expansions plus
10847 the characters that delimit subscripts. */
10848 memset (abstab
, '\0', sizeof (abstab
));
10849 abstab
[LBRACK
] = abstab
[RBRACK
] = 1;
10850 abstab
['$'] = abstab
['`'] = abstab
['~'] = 1;
10851 abstab
['\\'] = abstab
['\''] = 1;
10852 abstab
['"'] = 1; /* XXX */
10853 /* We don't quote `@' or `*' in the subscript at all. */
10856 /* string[si] == LBRACK */
10857 ni
= skipsubscript (string
, si
, 0);
10858 /* These checks mirror the ones in valid_array_reference. The check for
10859 (ni - si) == 1 checks for empty subscripts. We don't check that the
10860 subscript is a separate word if we're parsing an arithmetic expression. */
10861 if (ni
>= slen
|| string
[ni
] != RBRACK
|| (ni
- si
) == 1 ||
10862 (string
[ni
+1] != '\0' && (quoted
& Q_ARITH
) == 0))
10864 /* let's check and see what fails this check */
10865 INTERNAL_DEBUG (("expand_array_subscript: bad subscript string: `%s'", string
+si
));
10866 ret
= (char *)xmalloc (2); /* badly-formed subscript */
10867 ret
[0] = string
[si
];
10873 /* STRING[ni] == RBRACK */
10874 exp
= substring (string
, si
+1, ni
);
10875 t
= expand_subscript_string (exp
, quoted
& ~(Q_ARITH
|Q_DOUBLE_QUOTES
));
10877 exp
= t
? sh_backslash_quote (t
, abstab
, 0) : savestring ("");
10880 slen
= STRLEN (exp
);
10881 ret
= xmalloc (slen
+ 2 + 1);
10883 strcpy (ret
+ 1, exp
);
10884 ret
[slen
+ 1] = ']';
10885 ret
[slen
+ 2] = '\0';
10895 invalidate_cached_quoted_dollar_at ()
10897 dispose_words (cached_quoted_dollar_at
);
10898 cached_quoted_dollar_at
= 0;
10901 /* Make a word list which is the result of parameter and variable
10902 expansion, command substitution, arithmetic substitution, and
10903 quote removal of WORD. Return a pointer to a WORD_LIST which is
10904 the result of the expansion. If WORD contains a null word, the
10905 word list returned is also null.
10907 QUOTED contains flag values defined in shell.h.
10909 ISEXP is used to tell expand_word_internal that the word should be
10910 treated as the result of an expansion. This has implications for
10911 how IFS characters in the word are treated.
10913 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
10914 they point to an integer value which receives information about expansion.
10915 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
10916 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
10919 This only does word splitting in the case of $@ expansion. In that
10920 case, we split on ' '. */
10922 /* Values for the local variable quoted_state. */
10924 #define PARTIALLY_QUOTED 1
10925 #define WHOLLY_QUOTED 2
10928 expand_word_internal (word
, quoted
, isexp
, contains_dollar_at
, expanded_something
)
10931 int *contains_dollar_at
;
10932 int *expanded_something
;
10937 /* The intermediate string that we build while expanding. */
10940 /* The current size of the above object. */
10941 size_t istring_size
;
10943 /* Index into ISTRING. */
10944 size_t istring_index
;
10946 /* Temporary string storage. */
10947 char *temp
, *temp1
;
10949 /* The text of WORD. */
10950 register char *string
;
10952 /* The size of STRING. */
10953 size_t string_size
;
10955 /* The index into STRING. */
10958 /* This gets 1 if we see a $@ while quoted. */
10959 int quoted_dollar_at
;
10961 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
10962 whether WORD contains no quoting characters, a partially quoted
10963 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
10967 int had_quoted_null
;
10968 int has_quoted_ifs
; /* did we add a quoted $IFS character here? */
10969 int has_dollar_at
, temp_has_dollar_at
;
10970 int internal_tilde
;
10971 int split_on_spaces
;
10972 int local_expanded
;
10974 int pflags
; /* flags passed to param_expand */
10977 int assignoff
; /* If assignment, offset of `=' */
10979 register unsigned char c
; /* Current character. */
10980 int t_index
; /* For calls to string_extract_xxx. */
10986 /* OK, let's see if we can optimize a common idiom: "$@". This needs to make sure
10987 that all of the flags callers care about (e.g., W_HASQUOTEDNULL) are set in
10989 if (STREQ (word
->word
, "\"$@\"") &&
10990 (word
->flags
== (W_HASDOLLAR
|W_QUOTED
)) &&
10991 dollar_vars
[1]) /* XXX - check IFS here as well? */
10993 if (contains_dollar_at
)
10994 *contains_dollar_at
= 1;
10995 if (expanded_something
)
10996 *expanded_something
= 1;
10997 if (cached_quoted_dollar_at
)
10998 return (copy_word_list (cached_quoted_dollar_at
));
10999 list
= list_rest_of_args ();
11000 list
= quote_list (list
);
11001 cached_quoted_dollar_at
= copy_word_list (list
);
11005 istring
= (char *)xmalloc (istring_size
= DEFAULT_INITIAL_ARRAY_SIZE
);
11006 istring
[istring_index
= 0] = '\0';
11007 quoted_dollar_at
= had_quoted_null
= has_dollar_at
= 0;
11008 has_quoted_ifs
= 0;
11009 split_on_spaces
= 0;
11010 internal_tilde
= 0; /* expanding =~ or :~ */
11011 quoted_state
= UNQUOTED
;
11013 string
= word
->word
;
11015 goto finished_with_string
;
11016 mb_cur_max
= MB_CUR_MAX
;
11018 /* Don't need the string length for the SADD... and COPY_ macros unless
11019 multibyte characters are possible, but do need it for bounds checking. */
11020 string_size
= (mb_cur_max
> 1) ? strlen (string
) : 1;
11022 if (contains_dollar_at
)
11023 *contains_dollar_at
= 0;
11027 /* Begin the expansion. */
11029 for (sindex
= 0; ;)
11031 c
= string
[sindex
];
11033 /* Case on top-level character. */
11037 goto finished_with_string
;
11041 #if HANDLE_MULTIBYTE
11042 if (mb_cur_max
> 1 && string
[sindex
])
11044 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
11049 temp
= (char *)xmalloc (3);
11051 temp
[1] = c
= string
[sindex
];
11056 if (string
[sindex
])
11062 istring
= sub_append_string (temp
, istring
, &istring_index
, &istring_size
);
11068 #if defined (PROCESS_SUBSTITUTION)
11069 /* Process substitution. */
11073 /* XXX - technically this should only be expanded at the start
11075 if (string
[++sindex
] != LPAREN
|| (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (word
->flags
& W_NOPROCSUB
))
11077 sindex
--; /* add_character: label increments sindex */
11078 goto add_character
;
11081 t_index
= sindex
+ 1; /* skip past both '<' and LPAREN */
11083 temp1
= extract_process_subst (string
, (c
== '<') ? "<(" : ">(", &t_index
, 0); /*))*/
11086 /* If the process substitution specification is `<()', we want to
11087 open the pipe for writing in the child and produce output; if
11088 it is `>()', we want to open the pipe for reading in the child
11089 and consume input. */
11090 temp
= temp1
? process_substitute (temp1
, (c
== '>')) : (char *)0;
11094 goto dollar_add_string
;
11096 #endif /* PROCESS_SUBSTITUTION */
11098 #if defined (ARRAY_VARS)
11100 if ((quoted
& Q_ARITH
) == 0 || shell_compatibility_level
<= 51)
11102 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
11103 goto add_ifs_character
;
11105 goto add_character
;
11109 temp
= expand_array_subscript (string
, &sindex
, quoted
, word
->flags
);
11115 /* Posix.2 section 3.6.1 says that tildes following `=' in words
11116 which are not assignment statements are not expanded. If the
11117 shell isn't in posix mode, though, we perform tilde expansion
11118 on `likely candidate' unquoted assignment statements (flags
11119 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
11120 contains an unquoted :~ or =~. Something to think about: we
11121 now have a flag that says to perform tilde expansion on arguments
11122 to `assignment builtins' like declare and export that look like
11123 assignment statements. We now do tilde expansion on such words
11124 even in POSIX mode. */
11125 if (word
->flags
& (W_ASSIGNRHS
|W_NOTILDE
))
11127 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11128 goto add_ifs_character
;
11130 goto add_character
;
11132 /* If we're not in posix mode or forcing assignment-statement tilde
11133 expansion, note where the first `=' appears in the word and prepare
11134 to do tilde expansion following the first `='. We have to keep
11135 track of the first `=' (using assignoff) to avoid being confused
11136 by an `=' in the rhs of the assignment statement. */
11137 if ((word
->flags
& W_ASSIGNMENT
) &&
11138 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
11139 assignoff
== -1 && sindex
> 0)
11140 assignoff
= sindex
;
11141 if (sindex
== assignoff
&& string
[sindex
+1] == '~') /* XXX */
11142 internal_tilde
= 1;
11144 if (word
->flags
& W_ASSIGNARG
)
11145 word
->flags
|= W_ASSIGNRHS
; /* affects $@ */
11147 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11150 goto add_ifs_character
;
11153 goto add_character
;
11156 if (word
->flags
& (W_NOTILDE
|W_NOASSNTILDE
))
11158 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11159 goto add_ifs_character
;
11161 goto add_character
;
11164 if ((word
->flags
& (W_ASSIGNMENT
|W_ASSIGNRHS
)) &&
11165 (posixly_correct
== 0 || (word
->flags
& W_TILDEEXP
)) &&
11166 string
[sindex
+1] == '~')
11167 internal_tilde
= 1;
11169 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
))
11170 goto add_ifs_character
;
11172 goto add_character
;
11175 /* If the word isn't supposed to be tilde expanded, or we're not
11176 at the start of a word or after an unquoted : or = in an
11177 assignment statement, we don't do tilde expansion. We don't
11178 do tilde expansion if quoted or in an arithmetic context. */
11180 if ((word
->flags
& W_NOTILDE
) ||
11181 (sindex
> 0 && (internal_tilde
== 0)) ||
11182 (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
11184 internal_tilde
= 0;
11185 if (isexp
== 0 && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0 && isifs (c
) && (quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) == 0)
11186 goto add_ifs_character
;
11188 goto add_character
;
11191 if (word
->flags
& W_ASSIGNRHS
)
11193 else if (word
->flags
& (W_ASSIGNMENT
|W_TILDEEXP
))
11198 temp
= bash_tilde_find_word (string
+ sindex
, tflag
, &t_index
);
11200 internal_tilde
= 0;
11202 if (temp
&& *temp
&& t_index
> 0)
11204 temp1
= bash_tilde_expand (temp
, tflag
);
11205 if (temp1
&& *temp1
== '~' && STREQ (temp
, temp1
))
11209 goto add_character
; /* tilde expansion failed */
11214 goto add_quoted_string
; /* XXX was add_string */
11219 goto add_character
;
11223 if (expanded_something
)
11224 *expanded_something
= 1;
11225 local_expanded
= 1;
11227 temp_has_dollar_at
= 0;
11228 pflags
= (word
->flags
& W_NOCOMSUB
) ? PF_NOCOMSUB
: 0;
11229 if (word
->flags
& W_NOSPLIT2
)
11230 pflags
|= PF_NOSPLIT2
;
11231 if (word
->flags
& W_ASSIGNRHS
)
11232 pflags
|= PF_ASSIGNRHS
;
11233 if (word
->flags
& W_COMPLETE
)
11234 pflags
|= PF_COMPLETE
;
11236 tword
= param_expand (string
, &sindex
, quoted
, expanded_something
,
11237 &temp_has_dollar_at
, "ed_dollar_at
,
11238 &had_quoted_null
, pflags
);
11239 has_dollar_at
+= temp_has_dollar_at
;
11240 split_on_spaces
+= (tword
->flags
& W_SPLITSPACE
);
11242 if (tword
== &expand_wdesc_error
|| tword
== &expand_wdesc_fatal
)
11246 return ((tword
== &expand_wdesc_error
) ? &expand_word_error
11247 : &expand_word_fatal
);
11249 if (contains_dollar_at
&& has_dollar_at
)
11250 *contains_dollar_at
= 1;
11252 if (tword
&& (tword
->flags
& W_HASQUOTEDNULL
))
11253 had_quoted_null
= 1; /* note for later */
11254 if (tword
&& (tword
->flags
& W_SAWQUOTEDNULL
))
11255 had_quoted_null
= 1; /* XXX */
11257 temp
= tword
? tword
->word
: (char *)NULL
;
11258 dispose_word_desc (tword
);
11260 /* Kill quoted nulls; we will add them back at the end of
11261 expand_word_internal if nothing else in the string */
11262 if (had_quoted_null
&& temp
&& QUOTED_NULL (temp
))
11265 temp
= (char *)NULL
;
11271 case '`': /* Backquoted command substitution. */
11273 t_index
= sindex
++;
11275 temp
= string_extract (string
, &sindex
, "`", (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: SX_REQMATCH
);
11276 /* The test of sindex against t_index is to allow bare instances of
11277 ` to pass through, for backwards compatibility. */
11278 if (temp
== &extract_string_error
|| temp
== &extract_string_fatal
)
11280 if (sindex
- 1 == t_index
)
11283 goto add_character
;
11285 set_exit_status (EXECUTION_FAILURE
);
11286 report_error (_("bad substitution: no closing \"`\" in %s") , string
+t_index
);
11289 return ((temp
== &extract_string_error
) ? &expand_word_error
11290 : &expand_word_fatal
);
11293 if (expanded_something
)
11294 *expanded_something
= 1;
11295 local_expanded
= 1;
11297 if (word
->flags
& W_NOCOMSUB
)
11298 /* sindex + 1 because string[sindex] == '`' */
11299 temp1
= substring (string
, t_index
, sindex
+ 1);
11302 de_backslash (temp
);
11303 tword
= command_substitute (temp
, quoted
, PF_BACKQUOTE
);
11304 temp1
= tword
? tword
->word
: (char *)NULL
;
11306 dispose_word_desc (tword
);
11310 goto dollar_add_string
;
11314 if (string
[sindex
+ 1] == '\n')
11320 c
= string
[++sindex
];
11322 /* "However, the double-quote character ( '"' ) shall not be treated
11323 specially within a here-document, except when the double-quote
11324 appears within "$()", "``", or "${}"." */
11325 if ((quoted
& Q_HERE_DOCUMENT
) && (quoted
& Q_DOLBRACE
) && c
== '"')
11326 tflag
= CBSDQUOTE
; /* special case */
11327 else if (quoted
& Q_HERE_DOCUMENT
)
11329 else if (quoted
& Q_DOUBLE_QUOTES
)
11334 /* From Posix discussion on austin-group list: Backslash escaping
11335 a } in ${...} is removed. Issue 0000221 */
11336 if ((quoted
& Q_DOLBRACE
) && c
== RBRACE
)
11338 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11340 /* This is the fix for " $@\ " */
11341 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0) && isexp
== 0 && isifs (c
))
11343 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11344 DEFAULT_ARRAY_SIZE
);
11345 istring
[istring_index
++] = CTLESC
;
11346 istring
[istring_index
++] = '\\';
11347 istring
[istring_index
] = '\0';
11349 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11351 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && c
== 0)
11353 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11354 DEFAULT_ARRAY_SIZE
);
11355 istring
[istring_index
++] = CTLESC
;
11356 istring
[istring_index
++] = '\\';
11357 istring
[istring_index
] = '\0';
11360 else if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) && ((sh_syntaxtab
[c
] & tflag
) == 0))
11362 SCOPY_CHAR_I (twochars
, '\\', c
, string
, sindex
, string_size
);
11367 sindex
--; /* add_character: label increments sindex */
11368 goto add_character
;
11372 SCOPY_CHAR_I (twochars
, CTLESC
, c
, string
, sindex
, string_size
);
11377 /* BEFORE jumping here, we need to increment sindex if appropriate */
11378 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 2, istring_size
,
11379 DEFAULT_ARRAY_SIZE
);
11380 istring
[istring_index
++] = twochars
[0];
11381 istring
[istring_index
++] = twochars
[1];
11382 istring
[istring_index
] = '\0';
11387 /* XXX - revisit this */
11388 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) && ((quoted
& Q_ARITH
) == 0))
11389 goto add_character
;
11391 t_index
= ++sindex
;
11392 temp
= string_extract_double_quoted (string
, &sindex
, (word
->flags
& W_COMPLETE
) ? SX_COMPLETE
: 0);
11394 /* If the quotes surrounded the entire string, then the
11395 whole word was quoted. */
11396 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
11398 : PARTIALLY_QUOTED
;
11402 tword
= alloc_word_desc ();
11403 tword
->word
= temp
;
11405 if (word
->flags
& W_ASSIGNARG
)
11406 tword
->flags
|= word
->flags
& (W_ASSIGNARG
|W_ASSIGNRHS
); /* affects $@ */
11407 if (word
->flags
& W_COMPLETE
)
11408 tword
->flags
|= W_COMPLETE
; /* for command substitutions */
11409 if (word
->flags
& W_NOCOMSUB
)
11410 tword
->flags
|= W_NOCOMSUB
;
11411 if (word
->flags
& W_NOPROCSUB
)
11412 tword
->flags
|= W_NOPROCSUB
;
11414 if (word
->flags
& W_ASSIGNRHS
)
11415 tword
->flags
|= W_ASSIGNRHS
;
11417 temp
= (char *)NULL
;
11419 temp_has_dollar_at
= 0; /* does this quoted (sub)string include $@? */
11420 /* Need to get W_HASQUOTEDNULL flag through this function. */
11421 /* XXX - preserve Q_ARITH here? */
11422 list
= expand_word_internal (tword
, Q_DOUBLE_QUOTES
|(quoted
&Q_ARITH
), 0, &temp_has_dollar_at
, (int *)NULL
);
11423 has_dollar_at
+= temp_has_dollar_at
;
11425 if (list
== &expand_word_error
|| list
== &expand_word_fatal
)
11429 /* expand_word_internal has already freed temp_word->word
11430 for us because of the way it prints error messages. */
11431 tword
->word
= (char *)NULL
;
11432 dispose_word (tword
);
11436 dispose_word (tword
);
11438 /* "$@" (a double-quoted dollar-at) expands into nothing,
11439 not even a NULL word, when there are no positional
11440 parameters. Posix interp 888 says that other parts of the
11441 word that expand to quoted nulls result in quoted nulls, so
11442 we can't just throw the entire word away if we have "$@"
11443 anywhere in it. We use had_quoted_null to keep track */
11444 if (list
== 0 && temp_has_dollar_at
) /* XXX - was has_dollar_at */
11446 quoted_dollar_at
++;
11450 /* If this list comes back with a quoted null from expansion,
11451 we have either "$x" or "$@" with $1 == ''. In either case,
11452 we need to make sure we add a quoted null argument and
11453 disable the special handling that "$@" gets. */
11454 if (list
&& list
->word
&& list
->next
== 0 && (list
->word
->flags
& W_HASQUOTEDNULL
))
11456 if (had_quoted_null
&& temp_has_dollar_at
)
11457 quoted_dollar_at
++;
11458 had_quoted_null
= 1; /* XXX */
11461 /* If we get "$@", we know we have expanded something, so we
11462 need to remember it for the final split on $IFS. This is
11463 a special case; it's the only case where a quoted string
11464 can expand into more than one word. It's going to come back
11465 from the above call to expand_word_internal as a list with
11468 dequote_list (list
);
11470 if (temp_has_dollar_at
) /* XXX - was has_dollar_at */
11472 quoted_dollar_at
++;
11473 if (contains_dollar_at
)
11474 *contains_dollar_at
= 1;
11475 if (expanded_something
)
11476 *expanded_something
= 1;
11477 local_expanded
= 1;
11482 /* What we have is "". This is a minor optimization. */
11484 list
= (WORD_LIST
*)NULL
;
11485 had_quoted_null
= 1; /* note for later */
11488 /* The code above *might* return a list (consider the case of "$@",
11489 where it returns "$1", "$2", etc.). We can't throw away the
11490 rest of the list, and we have to make sure each word gets added
11491 as quoted. We test on tresult->next: if it is non-NULL, we
11492 quote the whole list, save it to a string with string_list, and
11493 add that string. We don't need to quote the results of this
11494 (and it would be wrong, since that would quote the separators
11495 as well), so we go directly to add_string. */
11500 /* Testing quoted_dollar_at makes sure that "$@" is
11501 split correctly when $IFS does not contain a space. */
11502 temp
= quoted_dollar_at
11503 ? string_list_dollar_at (list
, Q_DOUBLE_QUOTES
, 0)
11504 : string_list (quote_list (list
));
11505 dispose_words (list
);
11510 temp
= savestring (list
->word
->word
);
11511 tflag
= list
->word
->flags
;
11512 dispose_words (list
);
11514 /* If the string is not a quoted null string, we want
11515 to remove any embedded unquoted CTLNUL characters.
11516 We do not want to turn quoted null strings back into
11517 the empty string, though. We do this because we
11518 want to remove any quoted nulls from expansions that
11519 contain other characters. For example, if we have
11520 x"$*"y or "x$*y" and there are no positional parameters,
11521 the $* should expand into nothing. */
11522 /* We use the W_HASQUOTEDNULL flag to differentiate the
11523 cases: a quoted null character as above and when
11524 CTLNUL is contained in the (non-null) expansion
11525 of some variable. We use the had_quoted_null flag to
11526 pass the value through this function to its caller. */
11527 if ((tflag
& W_HASQUOTEDNULL
) && QUOTED_NULL (temp
) == 0)
11528 remove_quoted_nulls (temp
); /* XXX */
11532 temp
= (char *)NULL
;
11534 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
11535 had_quoted_null
= 1; /* note for later */
11537 /* We do not want to add quoted nulls to strings that are only
11538 partially quoted; we can throw them away. The exception to
11539 this is when we are going to be performing word splitting,
11540 since we have to preserve a null argument if the next character
11541 will cause word splitting. */
11542 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
11546 had_quoted_null
= 1;
11547 goto add_character
;
11549 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
11557 temp
= quote_string (temp
);
11563 /* Add NULL arg. */
11565 sindex
--; /* add_character: label increments sindex */
11566 had_quoted_null
= 1; /* note for later */
11567 goto add_character
;
11573 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)))
11574 goto add_character
;
11576 t_index
= ++sindex
;
11577 temp
= string_extract_single_quoted (string
, &sindex
, 0);
11579 /* If the entire STRING was surrounded by single quotes,
11580 then the string is wholly quoted. */
11581 quoted_state
= (t_index
== 1 && string
[sindex
] == '\0')
11583 : PARTIALLY_QUOTED
;
11585 /* If all we had was '', it is a null expansion. */
11589 temp
= (char *)NULL
;
11592 remove_quoted_escapes (temp
); /* ??? */
11594 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
)
11595 had_quoted_null
= 1; /* note for later */
11597 /* We do not want to add quoted nulls to strings that are only
11598 partially quoted; such nulls are discarded. See above for the
11599 exception, which is when the string is going to be split.
11600 Posix interp 888/1129 */
11601 if (temp
== 0 && quoted_state
== PARTIALLY_QUOTED
&& quoted
== 0 && (word
->flags
& (W_NOSPLIT
|W_EXPANDRHS
|W_ASSIGNRHS
)) == W_EXPANDRHS
)
11605 goto add_character
;
11608 if (temp
== 0 && (quoted_state
== PARTIALLY_QUOTED
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)))
11611 /* If we have a quoted null expansion, add a quoted NULL to istring. */
11615 sindex
--; /* add_character: label increments sindex */
11616 goto add_character
;
11619 goto add_quoted_string
;
11624 /* If we are in a context where the word is not going to be split, but
11625 we need to account for $@ and $* producing one word for each
11626 positional parameter, add quoted spaces so the spaces in the
11627 expansion of "$@", if any, behave correctly. We still may need to
11628 split if we are expanding the rhs of a word expansion. */
11629 if (ifs_is_null
|| split_on_spaces
|| ((word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
|W_ASSIGNRHS
)) && (word
->flags
& W_EXPANDRHS
) == 0))
11631 if (string
[sindex
])
11633 twochars
[0] = CTLESC
;
11640 /* This is the fix for " $@ " */
11642 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || (isexp
== 0 && isifs (c
) && (word
->flags
& (W_NOSPLIT
|W_NOSPLIT2
)) == 0))
11644 if ((quoted
&(Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) == 0)
11646 add_quoted_character
:
11647 if (string
[sindex
]) /* from old goto dollar_add_string */
11652 goto add_character
;
11656 #if HANDLE_MULTIBYTE
11657 /* XXX - should make sure that c is actually multibyte,
11658 otherwise we can use the twochars branch */
11659 if (mb_cur_max
> 1)
11662 if (mb_cur_max
> 1)
11664 SADD_MBQCHAR_BODY(temp
, string
, sindex
, string_size
);
11669 twochars
[0] = CTLESC
;
11676 SADD_MBCHAR (temp
, string
, sindex
, string_size
);
11679 RESIZE_MALLOCED_BUFFER (istring
, istring_index
, 1, istring_size
,
11680 DEFAULT_ARRAY_SIZE
);
11681 istring
[istring_index
++] = c
;
11682 istring
[istring_index
] = '\0';
11684 /* Next character. */
11689 finished_with_string
:
11690 /* OK, we're ready to return. If we have a quoted string, and
11691 quoted_dollar_at is not set, we do no splitting at all; otherwise
11692 we split on ' '. The routines that call this will handle what to
11693 do if nothing has been expanded. */
11695 /* Partially and wholly quoted strings which expand to the empty
11696 string are retained as an empty arguments. Unquoted strings
11697 which expand to the empty string are discarded. The single
11698 exception is the case of expanding "$@" when there are no
11699 positional parameters. In that case, we discard the expansion. */
11701 /* Because of how the code that handles "" and '' in partially
11702 quoted strings works, we need to make ISTRING into a QUOTED_NULL
11703 if we saw quoting characters, but the expansion was empty.
11704 "" and '' are tossed away before we get to this point when
11705 processing partially quoted strings. This makes "" and $xxx""
11706 equivalent when xxx is unset. We also look to see whether we
11707 saw a quoted null from a ${} expansion and add one back if we
11710 /* If we expand to nothing and there were no single or double quotes
11711 in the word, we throw it away. Otherwise, we return a NULL word.
11712 The single exception is for $@ surrounded by double quotes when
11713 there are no positional parameters. In that case, we also throw
11716 if (*istring
== '\0')
11719 if (quoted_dollar_at
== 0 && (had_quoted_null
|| quoted_state
== PARTIALLY_QUOTED
))
11721 if (had_quoted_null
|| (quoted_dollar_at
== 0 && quoted_state
== PARTIALLY_QUOTED
))
11724 istring
[0] = CTLNUL
;
11726 tword
= alloc_word_desc ();
11727 tword
->word
= istring
;
11728 istring
= 0; /* avoid later free() */
11729 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11730 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11731 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
11732 tword
->flags
|= W_QUOTED
;
11734 /* According to sh, ksh, and Posix.2, if a word expands into nothing
11735 and a double-quoted "$@" appears anywhere in it, then the entire
11736 word is removed. */
11737 /* XXX - exception appears to be that quoted null strings result in
11739 else if (quoted_state
== UNQUOTED
|| quoted_dollar_at
)
11740 list
= (WORD_LIST
*)NULL
;
11742 list
= (WORD_LIST
*)NULL
;
11744 else if (word
->flags
& W_NOSPLIT
)
11746 tword
= alloc_word_desc ();
11747 tword
->word
= istring
;
11748 if (had_quoted_null
&& QUOTED_NULL (istring
))
11749 tword
->flags
|= W_HASQUOTEDNULL
;
11750 istring
= 0; /* avoid later free() */
11751 if (word
->flags
& W_ASSIGNMENT
)
11752 tword
->flags
|= W_ASSIGNMENT
; /* XXX */
11753 if (word
->flags
& W_COMPASSIGN
)
11754 tword
->flags
|= W_COMPASSIGN
; /* XXX */
11755 if (word
->flags
& W_NOGLOB
)
11756 tword
->flags
|= W_NOGLOB
; /* XXX */
11757 if (word
->flags
& W_NOBRACE
)
11758 tword
->flags
|= W_NOBRACE
; /* XXX */
11759 if (word
->flags
& W_ARRAYREF
)
11760 tword
->flags
|= W_ARRAYREF
;
11761 if (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
))
11762 tword
->flags
|= W_QUOTED
;
11763 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11765 else if (word
->flags
& W_ASSIGNRHS
)
11767 list
= list_string (istring
, "", quoted
);
11768 tword
= list
->word
;
11769 if (had_quoted_null
&& QUOTED_NULL (istring
))
11770 tword
->flags
|= W_HASQUOTEDNULL
;
11773 istring
= 0; /* avoid later free() */
11774 goto set_word_flags
;
11780 ifs_chars
= (quoted_dollar_at
|| has_dollar_at
) ? ifs_value
: (char *)NULL
;
11782 /* If we have $@, we need to split the results no matter what. If
11783 IFS is unset or NULL, string_list_dollar_at has separated the
11784 positional parameters with a space, so we split on space (we have
11785 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
11786 string_list_dollar_at has separated the positional parameters
11787 with the first character of $IFS, so we split on $IFS. If
11788 SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
11789 unset or null, and we want to make sure that we split on spaces
11790 regardless of what else has happened to IFS since the expansion,
11791 or we expanded "$@" with IFS null and we need to split the positional
11792 parameters into separate words. */
11793 if (split_on_spaces
)
11795 /* If IFS is not set, and the word is not quoted, we want to split
11796 the individual words on $' \t\n'. We rely on previous steps to
11797 quote the portions of the word that should not be split */
11798 if (ifs_is_set
== 0)
11799 list
= list_string (istring
, " \t\n", 1); /* XXX quoted == 1? */
11801 list
= list_string (istring
, " ", 1); /* XXX quoted == 1? */
11804 /* If we have $@ (has_dollar_at != 0) and we are in a context where we
11805 don't want to split the result (W_NOSPLIT2), and we are not quoted,
11806 we have already separated the arguments with the first character of
11807 $IFS. In this case, we want to return a list with a single word
11808 with the separator possibly replaced with a space (it's what other
11809 shells seem to do).
11810 quoted_dollar_at is internal to this function and is set if we are
11811 passed an argument that is unquoted (quoted == 0) but we encounter a
11812 double-quoted $@ while expanding it. */
11813 else if (has_dollar_at
&& quoted_dollar_at
== 0 && ifs_chars
&& quoted
== 0 && (word
->flags
& W_NOSPLIT2
))
11815 tword
= alloc_word_desc ();
11816 /* Only split and rejoin if we have to */
11817 if (*ifs_chars
&& *ifs_chars
!= ' ')
11819 /* list_string dequotes CTLESCs in the string it's passed, so we
11820 need it to get the space separation right if space isn't the
11821 first character in IFS (but is present) and to remove the
11822 quoting we added back in param_expand(). */
11823 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
11824 /* This isn't exactly right in the case where we're expanding
11825 the RHS of an expansion like ${var-$@} where IFS=: (for
11826 example). The W_NOSPLIT2 means we do the separation with :;
11827 the list_string removes the quotes and breaks the string into
11828 a list, and the string_list rejoins it on spaces. When we
11829 return, we expect to be able to split the results, but the
11830 space separation means the right split doesn't happen. */
11831 tword
->word
= string_list (list
);
11834 tword
->word
= istring
;
11835 if (had_quoted_null
&& QUOTED_NULL (istring
))
11836 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11837 if (tword
->word
!= istring
)
11839 istring
= 0; /* avoid later free() */
11840 goto set_word_flags
;
11842 else if (has_dollar_at
&& ifs_chars
)
11843 list
= list_string (istring
, *ifs_chars
? ifs_chars
: " ", 1);
11846 tword
= alloc_word_desc ();
11847 if (expanded_something
&& *expanded_something
== 0 && has_quoted_ifs
)
11848 tword
->word
= remove_quoted_ifs (istring
);
11850 tword
->word
= istring
;
11851 if (had_quoted_null
&& QUOTED_NULL (istring
)) /* should check for more than one */
11852 tword
->flags
|= W_HASQUOTEDNULL
; /* XXX */
11853 else if (had_quoted_null
)
11854 tword
->flags
|= W_SAWQUOTEDNULL
; /* XXX */
11855 if (tword
->word
!= istring
)
11857 istring
= 0; /* avoid later free() */
11859 if ((quoted
& (Q_DOUBLE_QUOTES
|Q_HERE_DOCUMENT
)) || (quoted_state
== WHOLLY_QUOTED
))
11860 tword
->flags
|= W_QUOTED
;
11861 if (word
->flags
& W_ASSIGNMENT
)
11862 tword
->flags
|= W_ASSIGNMENT
;
11863 if (word
->flags
& W_COMPASSIGN
)
11864 tword
->flags
|= W_COMPASSIGN
;
11865 if (word
->flags
& W_NOGLOB
)
11866 tword
->flags
|= W_NOGLOB
;
11867 if (word
->flags
& W_NOBRACE
)
11868 tword
->flags
|= W_NOBRACE
;
11869 if (word
->flags
& W_ARRAYREF
)
11870 tword
->flags
|= W_ARRAYREF
;
11871 list
= make_word_list (tword
, (WORD_LIST
*)NULL
);
11879 /* **************************************************************** */
11881 /* Functions for Quote Removal */
11883 /* **************************************************************** */
11885 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
11886 backslash quoting rules for within double quotes or a here document. */
11888 string_quote_removal (string
, quoted
)
11893 char *r
, *result_string
, *temp
, *send
;
11894 int sindex
, tindex
, dquote
;
11898 /* The result can be no longer than the original string. */
11899 slen
= strlen (string
);
11900 send
= string
+ slen
;
11902 r
= result_string
= (char *)xmalloc (slen
+ 1);
11904 for (dquote
= sindex
= 0; c
= string
[sindex
];)
11909 c
= string
[++sindex
];
11915 if (((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
) && (sh_syntaxtab
[c
] & CBSDQUOTE
) == 0)
11920 SCOPY_CHAR_M (r
, string
, send
, sindex
);
11924 if ((quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)) || dquote
)
11930 tindex
= sindex
+ 1;
11931 temp
= string_extract_single_quoted (string
, &tindex
, 0);
11942 dquote
= 1 - dquote
;
11948 return (result_string
);
11953 /* Perform quote removal on word WORD. This allocates and returns a new
11956 word_quote_removal (word
, quoted
)
11963 t
= string_quote_removal (word
->word
, quoted
);
11964 w
= alloc_word_desc ();
11965 w
->word
= t
? t
: savestring ("");
11969 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
11970 the members of the list are treated as if they are surrounded by
11971 double quotes. Return a new list, or NULL if LIST is NULL. */
11973 word_list_quote_removal (list
, quoted
)
11977 WORD_LIST
*result
, *t
, *tresult
, *e
;
11979 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
11981 tresult
= make_word_list (word_quote_removal (t
->word
, quoted
), (WORD_LIST
*)NULL
);
11983 result
= (WORD_LIST
*) list_append (result
, tresult
);
11986 result
= e
= tresult
;
11999 /*******************************************
12001 * Functions to perform word splitting *
12003 *******************************************/
12013 ifs_value
= (v
&& value_cell (v
)) ? value_cell (v
) : " \t\n";
12015 ifs_is_set
= ifs_var
!= 0;
12016 ifs_is_null
= ifs_is_set
&& (*ifs_value
== 0);
12018 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
12019 handle multibyte chars in IFS */
12020 memset (ifs_cmap
, '\0', sizeof (ifs_cmap
));
12021 for (t
= ifs_value
; t
&& *t
; t
++)
12027 #if defined (HANDLE_MULTIBYTE)
12028 if (ifs_value
== 0)
12030 ifs_firstc
[0] = '\0'; /* XXX - ? */
12031 ifs_firstc_len
= 1;
12035 if (locale_utf8locale
&& UTF8_SINGLEBYTE (*ifs_value
))
12036 ifs_firstc_len
= (*ifs_value
!= 0) ? 1 : 0;
12040 ifs_len
= strnlen (ifs_value
, MB_CUR_MAX
);
12041 ifs_firstc_len
= MBLEN (ifs_value
, ifs_len
);
12043 if (ifs_firstc_len
== 1 || ifs_firstc_len
== 0 || MB_INVALIDCH (ifs_firstc_len
))
12045 ifs_firstc
[0] = ifs_value
[0];
12046 ifs_firstc
[1] = '\0';
12047 ifs_firstc_len
= 1;
12050 memcpy (ifs_firstc
, ifs_value
, ifs_firstc_len
);
12053 ifs_firstc
= ifs_value
? *ifs_value
: 0;
12063 /* This splits a single word into a WORD LIST on $IFS, but only if the word
12064 is not quoted. list_string () performs quote removal for us, even if we
12065 don't do any splitting. */
12067 word_split (w
, ifs_chars
)
12077 xifs
= ((w
->flags
& W_QUOTED
) || ifs_chars
== 0) ? "" : ifs_chars
;
12078 result
= list_string (w
->word
, xifs
, w
->flags
& W_QUOTED
);
12081 result
= (WORD_LIST
*)NULL
;
12086 /* Perform word splitting on LIST and return the RESULT. It is possible
12087 to return (WORD_LIST *)NULL. */
12089 word_list_split (list
)
12092 WORD_LIST
*result
, *t
, *tresult
, *e
;
12095 for (t
= list
, result
= (WORD_LIST
*)NULL
; t
; t
= t
->next
)
12097 tresult
= word_split (t
->word
, ifs_value
);
12098 /* POSIX 2.6: "If the complete expansion appropriate for a word results
12099 in an empty field, that empty field shall be deleted from the list
12100 of fields that form the completely expanded command, unless the
12101 original word contained single-quote or double-quote characters."
12102 This is where we handle these words that contain quoted null strings
12103 and other characters that expand to nothing after word splitting. */
12104 if (tresult
== 0 && t
->word
&& (t
->word
->flags
& W_SAWQUOTEDNULL
)) /* XXX */
12106 w
= alloc_word_desc ();
12107 w
->word
= (char *)xmalloc (1);
12109 tresult
= make_word_list (w
, (WORD_LIST
*)NULL
);
12111 #if defined (ARRAY_VARS)
12112 /* pass W_ARRAYREF through for words that are not split and are
12113 identical to the original word. */
12114 if (tresult
&& tresult
->next
== 0 && t
->next
== 0 && (t
->word
->flags
& W_ARRAYREF
) && STREQ (t
->word
->word
, tresult
->word
->word
))
12115 tresult
->word
->flags
|= W_ARRAYREF
;
12118 result
= e
= tresult
;
12129 /**************************************************
12131 * Functions to expand an entire WORD_LIST *
12133 **************************************************/
12135 /* Do any word-expansion-specific cleanup and jump to top_level */
12137 exp_jump_to_top_level (v
)
12140 set_pipestatus_from_exit (last_command_exit_value
);
12142 /* Cleanup code goes here. */
12143 expand_no_split_dollar_star
= 0; /* XXX */
12144 if (expanding_redir
)
12145 undo_partial_redirects ();
12146 expanding_redir
= 0;
12147 assigning_in_environment
= 0;
12149 if (parse_and_execute_level
== 0)
12150 top_level_cleanup (); /* from sig.c */
12152 jump_to_top_level (v
);
12155 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
12156 ELIST, and set ELIST to the new list. */
12157 #define PREPEND_LIST(nlist, elist) \
12158 do { nlist->next = elist; elist = nlist; } while (0)
12160 /* Separate out any initial variable assignments from TLIST. If set -k has
12161 been executed, remove all assignment statements from TLIST. Initial
12162 variable assignments and other environment assignments are placed
12163 on SUBST_ASSIGN_VARLIST. */
12165 separate_out_assignments (tlist
)
12168 register WORD_LIST
*vp
, *lp
;
12171 return ((WORD_LIST
*)NULL
);
12173 if (subst_assign_varlist
)
12174 dispose_words (subst_assign_varlist
); /* Clean up after previous error */
12176 subst_assign_varlist
= (WORD_LIST
*)NULL
;
12179 /* Separate out variable assignments at the start of the command.
12180 Loop invariant: vp->next == lp
12181 Loop postcondition:
12182 lp = list of words left after assignment statements skipped
12183 tlist = original list of words
12185 while (lp
&& (lp
->word
->flags
& W_ASSIGNMENT
))
12191 /* If lp != tlist, we have some initial assignment statements.
12192 We make SUBST_ASSIGN_VARLIST point to the list of assignment
12193 words and TLIST point to the remaining words. */
12196 subst_assign_varlist
= tlist
;
12197 /* ASSERT(vp->next == lp); */
12198 vp
->next
= (WORD_LIST
*)NULL
; /* terminate variable list */
12199 tlist
= lp
; /* remainder of word list */
12202 /* vp == end of variable list */
12203 /* tlist == remainder of original word list without variable assignments */
12205 /* All the words in tlist were assignment statements */
12206 return ((WORD_LIST
*)NULL
);
12208 /* ASSERT(tlist != NULL); */
12209 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
12211 /* If the -k option is in effect, we need to go through the remaining
12212 words, separate out the assignment words, and place them on
12213 SUBST_ASSIGN_VARLIST. */
12214 if (place_keywords_in_env
)
12216 WORD_LIST
*tp
; /* tp == running pointer into tlist */
12221 /* Loop Invariant: tp->next == lp */
12222 /* Loop postcondition: tlist == word list without assignment statements */
12225 if (lp
->word
->flags
& W_ASSIGNMENT
)
12227 /* Found an assignment statement, add this word to end of
12228 subst_assign_varlist (vp). */
12229 if (!subst_assign_varlist
)
12230 subst_assign_varlist
= vp
= lp
;
12237 /* Remove the word pointed to by LP from TLIST. */
12238 tp
->next
= lp
->next
;
12239 /* ASSERT(vp == lp); */
12240 lp
->next
= (WORD_LIST
*)NULL
;
12253 #define WEXP_VARASSIGN 0x001
12254 #define WEXP_BRACEEXP 0x002
12255 #define WEXP_TILDEEXP 0x004
12256 #define WEXP_PARAMEXP 0x008
12257 #define WEXP_PATHEXP 0x010
12259 /* All of the expansions, including variable assignments at the start of
12261 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
12263 /* All of the expansions except variable assignments at the start of
12265 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
12267 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
12268 expansion, command substitution, arithmetic expansion, word splitting, and
12270 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
12272 /* Take the list of words in LIST and do the various substitutions. Return
12273 a new list of words which is the expanded list, and without things like
12274 variable assignments. */
12277 expand_words (list
)
12280 return (expand_word_list_internal (list
, WEXP_ALL
));
12283 /* Same as expand_words (), but doesn't hack variable or environment
12286 expand_words_no_vars (list
)
12289 return (expand_word_list_internal (list
, WEXP_NOVARS
));
12293 expand_words_shellexp (list
)
12296 return (expand_word_list_internal (list
, WEXP_SHELLEXP
));
12300 glob_expand_word_list (tlist
, eflags
)
12304 char **glob_array
, *temp_string
;
12305 register int glob_index
;
12306 WORD_LIST
*glob_list
, *output_list
, *disposables
, *next
;
12310 output_list
= disposables
= (WORD_LIST
*)NULL
;
12311 glob_array
= (char **)NULL
;
12314 /* For each word, either globbing is attempted or the word is
12315 added to orig_list. If globbing succeeds, the results are
12316 added to orig_list and the word (tlist) is added to the list
12317 of disposable words. If globbing fails and failed glob
12318 expansions are left unchanged (the shell default), the
12319 original word is added to orig_list. If globbing fails and
12320 failed glob expansions are removed, the original word is
12321 added to the list of disposable words. orig_list ends up
12322 in reverse order and requires a call to REVERSE_LIST to
12323 be set right. After all words are examined, the disposable
12324 words are freed. */
12325 next
= tlist
->next
;
12327 /* If the word isn't an assignment and contains an unquoted
12328 pattern matching character, then glob it. */
12329 if ((tlist
->word
->flags
& W_NOGLOB
) == 0 &&
12330 unquoted_glob_pattern_p (tlist
->word
->word
))
12332 glob_array
= shell_glob_filename (tlist
->word
->word
, QGLOB_CTLESC
); /* XXX */
12334 /* Handle error cases.
12335 I don't think we should report errors like "No such file
12336 or directory". However, I would like to report errors
12337 like "Read failed". */
12339 if (glob_array
== 0 || GLOB_FAILED (glob_array
))
12341 glob_array
= (char **)xmalloc (sizeof (char *));
12342 glob_array
[0] = (char *)NULL
;
12345 /* Dequote the current word in case we have to use it. */
12346 if (glob_array
[0] == NULL
)
12348 temp_string
= dequote_string (tlist
->word
->word
);
12349 free (tlist
->word
->word
);
12350 tlist
->word
->word
= temp_string
;
12353 /* Make the array into a word list. */
12354 glob_list
= (WORD_LIST
*)NULL
;
12355 for (glob_index
= 0; glob_array
[glob_index
]; glob_index
++)
12357 tword
= make_bare_word (glob_array
[glob_index
]);
12358 glob_list
= make_word_list (tword
, glob_list
);
12363 output_list
= (WORD_LIST
*)list_append (glob_list
, output_list
);
12364 PREPEND_LIST (tlist
, disposables
);
12366 else if (fail_glob_expansion
!= 0)
12368 last_command_exit_value
= EXECUTION_FAILURE
;
12369 report_error (_("no match: %s"), tlist
->word
->word
);
12370 exp_jump_to_top_level (DISCARD
);
12372 else if (allow_null_glob_expansion
== 0)
12374 /* Failed glob expressions are left unchanged. */
12375 PREPEND_LIST (tlist
, output_list
);
12379 /* Failed glob expressions are removed. */
12380 PREPEND_LIST (tlist
, disposables
);
12385 /* Dequote the string. */
12386 temp_string
= dequote_string (tlist
->word
->word
);
12387 free (tlist
->word
->word
);
12388 tlist
->word
->word
= temp_string
;
12389 PREPEND_LIST (tlist
, output_list
);
12392 strvec_dispose (glob_array
);
12393 glob_array
= (char **)NULL
;
12399 dispose_words (disposables
);
12402 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
12404 return (output_list
);
12407 #if defined (BRACE_EXPANSION)
12409 brace_expand_word_list (tlist
, eflags
)
12413 register char **expansions
;
12415 WORD_LIST
*disposables
, *output_list
, *next
;
12419 for (disposables
= output_list
= (WORD_LIST
*)NULL
; tlist
; tlist
= next
)
12421 next
= tlist
->next
;
12423 if (tlist
->word
->flags
& W_NOBRACE
)
12425 /*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
12426 PREPEND_LIST (tlist
, output_list
);
12430 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
12432 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
12433 PREPEND_LIST (tlist
, output_list
);
12437 /* Only do brace expansion if the word has a brace character. If
12438 not, just add the word list element to BRACES and continue. In
12439 the common case, at least when running shell scripts, this will
12440 degenerate to a bunch of calls to `mbschr', and then what is
12441 basically a reversal of TLIST into BRACES, which is corrected
12442 by a call to REVERSE_LIST () on BRACES when the end of TLIST
12444 if (mbschr (tlist
->word
->word
, LBRACE
))
12446 expansions
= brace_expand (tlist
->word
->word
);
12448 for (eindex
= 0; temp_string
= expansions
[eindex
]; eindex
++)
12450 w
= alloc_word_desc ();
12451 w
->word
= temp_string
;
12453 /* If brace expansion didn't change the word, preserve
12454 the flags. We may want to preserve the flags
12455 unconditionally someday -- XXX */
12456 if (STREQ (temp_string
, tlist
->word
->word
))
12457 w
->flags
= tlist
->word
->flags
;
12459 w
= make_word_flags (w
, temp_string
);
12461 output_list
= make_word_list (w
, output_list
);
12465 /* Add TLIST to the list of words to be freed after brace
12466 expansion has been performed. */
12467 PREPEND_LIST (tlist
, disposables
);
12470 PREPEND_LIST (tlist
, output_list
);
12474 dispose_words (disposables
);
12477 output_list
= REVERSE_LIST (output_list
, WORD_LIST
*);
12479 return (output_list
);
12483 #if defined (ARRAY_VARS)
12484 /* Take WORD, a compound array assignment, and internally run (for example),
12485 'declare -A w', where W is the variable name portion of WORD. OPTION is
12486 the list of options to supply to `declare'. CMD is the declaration command
12487 we are expanding right now; it's unused currently. */
12489 make_internal_declare (word
, option
, cmd
)
12498 w
= make_word (word
);
12500 t
= assignment (w
->word
, 0);
12501 if (w
->word
[t
] == '=')
12504 if (w
->word
[t
- 1] == '+') /* cut off any append op */
12505 w
->word
[t
- 1] = '\0';
12508 wl
= make_word_list (w
, (WORD_LIST
*)NULL
);
12509 wl
= make_word_list (make_word (option
), wl
);
12511 r
= declare_builtin (wl
);
12513 dispose_words (wl
);
12517 /* Expand VALUE in NAME[+]=( VALUE ) to a list of words. FLAGS is 1 if NAME
12518 is an associative array.
12520 If we are processing an indexed array, expand_compound_array_assignment
12521 will expand all the individual words and quote_compound_array_list will
12522 single-quote them. If we are processing an associative array, we use
12523 parse_string_to_word_list to split VALUE into a list of words instead of
12524 faking up a shell variable and calling expand_compound_array_assignment.
12525 expand_and_quote_assoc_word expands and single-quotes each word in VALUE
12526 together so we don't have problems finding the end of the subscript when
12529 Words in VALUE can be individual words, which are expanded and single-quoted,
12530 or words of the form [IND]=VALUE, which end up as explained below, as
12531 ['expanded-ind']='expanded-value'. */
12534 expand_oneword (value
, flags
)
12544 /* Indexed array */
12545 l
= expand_compound_array_assignment ((SHELL_VAR
*)NULL
, value
, flags
);
12546 /* Now we quote the results of the expansion above to prevent double
12548 quote_compound_array_list (l
, flags
);
12553 /* Associative array */
12554 l
= parse_string_to_word_list (value
, 1, "array assign");
12555 #if ASSOC_KVPAIR_ASSIGNMENT
12556 kvpair
= kvpair_assignment_p (l
);
12559 /* For associative arrays, with their arbitrary subscripts, we have to
12560 expand and quote in one step so we don't have to search for the
12561 closing right bracket more than once. */
12562 for (nl
= l
; nl
; nl
= nl
->next
)
12564 #if ASSOC_KVPAIR_ASSIGNMENT
12566 /* keys and values undergo the same set of expansions */
12567 t
= expand_and_quote_kvpair_word (nl
->word
->word
);
12570 if ((nl
->word
->flags
& W_ASSIGNMENT
) == 0)
12571 t
= sh_single_quote (nl
->word
->word
? nl
->word
->word
: "");
12573 t
= expand_and_quote_assoc_word (nl
->word
->word
, flags
);
12574 free (nl
->word
->word
);
12575 nl
->word
->word
= t
;
12581 /* Expand a single compound assignment argument to a declaration builtin.
12582 This word takes the form NAME[+]=( VALUE ). The NAME[+]= is passed through
12583 unchanged. The VALUE is expanded and each word in the result is single-
12584 quoted. Words of the form [key]=value end up as
12585 ['expanded-key']='expanded-value'. Associative arrays have special
12586 handling, see expand_oneword() above. The return value is
12587 NAME[+]=( expanded-and-quoted-VALUE ). */
12589 expand_compound_assignment_word (tlist
, flags
)
12595 char *value
, *temp
;
12597 /*itrace("expand_compound_assignment_word: original word = -%s-", tlist->word->word);*/
12598 t
= assignment (tlist
->word
->word
, 0);
12600 /* value doesn't have the open and close parens */
12602 value
= extract_array_assignment_list (tlist
->word
->word
+ t
+ 1, &oind
);
12603 /* This performs one round of expansion on the index/key and value and
12604 single-quotes each word in the result. */
12605 l
= expand_oneword (value
, flags
);
12608 value
= string_list (l
);
12611 wlen
= STRLEN (value
);
12613 /* Now, let's rebuild the string */
12614 temp
= xmalloc (t
+ 3 + wlen
+ 1); /* name[+]=(value) */
12615 memcpy (temp
, tlist
->word
->word
, ++t
);
12618 memcpy (temp
+ t
, value
, wlen
);
12622 /*itrace("expand_compound_assignment_word: reconstructed word = -%s-", temp);*/
12624 free (tlist
->word
->word
);
12625 tlist
->word
->word
= temp
;
12630 /* Expand and process an argument to a declaration command. We have already
12631 set flags in TLIST->word->flags depending on the declaration command
12632 (declare, local, etc.) and the options supplied to it (-a, -A, etc.).
12633 TLIST->word->word is of the form NAME[+]=( VALUE ).
12635 This does several things, all using pieces of other functions to get the
12636 evaluation sequence right. It's called for compound array assignments with
12637 the W_ASSIGNMENT flag set (basically, valid identifier names on the lhs).
12638 It parses out which flags need to be set for declare to create the variable
12639 correctly, then calls declare internally (make_internal_declare) to make
12640 sure the variable exists with the correct attributes. Before the variable
12641 is created, it calls expand_compound_assignment_word to expand VALUE to a
12642 list of words, appropriately quoted for further evaluation. This preserves
12643 the semantics of word-expansion-before-calling-builtins. Finally, it calls
12644 do_word_assignment to perform the expansion and assignment with the same
12645 expansion semantics as a standalone assignment statement (no word splitting,
12646 etc.) even though the word is single-quoted so all that needs to happen is
12649 expand_declaration_argument (tlist
, wcmd
)
12650 WORD_LIST
*tlist
, *wcmd
;
12652 char opts
[16], omap
[128];
12653 int t
, opti
, oind
, skip
, inheriting
;
12656 inheriting
= localvar_inherit
;
12658 if (tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
|W_CHKLOCAL
|W_ASSIGNARRAY
))
12659 opts
[opti
++] = '-';
12661 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSNGLOBAL
)) == (W_ASSIGNASSOC
|W_ASSNGLOBAL
))
12663 opts
[opti
++] = 'g';
12664 opts
[opti
++] = 'A';
12666 else if (tlist
->word
->flags
& W_ASSIGNASSOC
)
12668 opts
[opti
++] = 'A';
12670 else if ((tlist
->word
->flags
& (W_ASSIGNARRAY
|W_ASSNGLOBAL
)) == (W_ASSIGNARRAY
|W_ASSNGLOBAL
))
12672 opts
[opti
++] = 'g';
12673 opts
[opti
++] = 'a';
12675 else if (tlist
->word
->flags
& W_ASSIGNARRAY
)
12677 opts
[opti
++] = 'a';
12679 else if (tlist
->word
->flags
& W_ASSNGLOBAL
)
12680 opts
[opti
++] = 'g';
12682 if (tlist
->word
->flags
& W_CHKLOCAL
)
12683 opts
[opti
++] = 'G';
12685 /* If we have special handling note the integer attribute and others
12686 that transform the value upon assignment. What we do is take all
12687 of the option arguments and scan through them looking for options
12688 that cause such transformations, and add them to the `opts' array. */
12690 memset (omap
, '\0', sizeof (omap
));
12691 for (l
= wcmd
->next
; l
!= tlist
; l
= l
->next
)
12695 if (l
->word
->word
[0] != '-' && l
->word
->word
[0] != '+')
12696 break; /* non-option argument */
12697 if (l
->word
->word
[0] == '-' && l
->word
->word
[1] == '-' && l
->word
->word
[2] == 0)
12698 break; /* -- signals end of options */
12699 optchar
= l
->word
->word
[0];
12700 for (oind
= 1; l
->word
->word
[oind
]; oind
++)
12701 switch (l
->word
->word
[oind
])
12709 omap
[l
->word
->word
[oind
]] = 1;
12711 opts
[opti
++] = optchar
;
12718 for (oind
= 0; oind
< sizeof (omap
); oind
++)
12720 opts
[opti
++] = oind
;
12722 /* If there are no -a/-A options, but we have a compound assignment,
12723 we have a choice: we can set opts[0]='-', opts[1]='a', since the
12724 default is to create an indexed array, and call
12725 make_internal_declare with that, or we can just skip the -a and let
12726 declare_builtin deal with it. Once we're here, we're better set
12727 up for the latter, since we don't want to deal with looking up
12728 any existing variable here -- better to let declare_builtin do it.
12729 We need the variable created, though, especially if it's local, so
12730 we get the scoping right before we call do_word_assignment.
12731 To ensure that make_local_declare gets called, we add `--' if there
12732 aren't any options. */
12733 if ((tlist
->word
->flags
& (W_ASSIGNASSOC
|W_ASSIGNARRAY
)) == 0)
12737 opts
[opti
++] = '-';
12738 opts
[opti
++] = '-';
12743 /* This isn't perfect, but it's a start. Improvements later. We expand
12744 tlist->word->word and single-quote the results to avoid multiple
12745 expansions by, say, do_assignment_internal(). We have to weigh the
12746 cost of reconstructing the compound assignment string with its single
12747 quoting and letting the declare builtin handle it. The single quotes
12748 will prevent any unwanted additional expansion or word splitting. */
12749 expand_compound_assignment_word (tlist
, (tlist
->word
->flags
& W_ASSIGNASSOC
) ? 1 : 0);
12754 t
= make_internal_declare (tlist
->word
->word
, opts
, wcmd
? wcmd
->word
->word
: (char *)0);
12755 if (t
!= EXECUTION_SUCCESS
)
12757 last_command_exit_value
= t
;
12758 if (tlist
->word
->flags
& W_FORCELOCAL
) /* non-fatal error */
12761 exp_jump_to_top_level (DISCARD
);
12767 t
= do_word_assignment (tlist
->word
, 0);
12770 last_command_exit_value
= EXECUTION_FAILURE
;
12771 exp_jump_to_top_level (DISCARD
);
12775 /* Now transform the word as ksh93 appears to do and go on */
12776 t
= assignment (tlist
->word
->word
, 0);
12777 tlist
->word
->word
[t
] = '\0';
12778 if (tlist
->word
->word
[t
- 1] == '+')
12779 tlist
->word
->word
[t
- 1] = '\0'; /* cut off append op */
12780 tlist
->word
->flags
&= ~(W_ASSIGNMENT
|W_NOSPLIT
|W_COMPASSIGN
|W_ASSIGNARG
|W_ASSIGNASSOC
|W_ASSIGNARRAY
);
12784 #endif /* ARRAY_VARS */
12787 shell_expand_word_list (tlist
, eflags
)
12791 WORD_LIST
*expanded
, *orig_list
, *new_list
, *next
, *temp_list
, *wcmd
;
12792 int expanded_something
, has_dollar_at
;
12794 /* We do tilde expansion all the time. This is what 1003.2 says. */
12795 wcmd
= new_list
= (WORD_LIST
*)NULL
;
12797 for (orig_list
= tlist
; tlist
; tlist
= next
)
12799 if (wcmd
== 0 && (tlist
->word
->flags
& W_ASSNBLTIN
))
12802 next
= tlist
->next
;
12804 #if defined (ARRAY_VARS)
12805 /* If this is a compound array assignment to a builtin that accepts
12806 such assignments (e.g., `declare'), take the assignment and perform
12807 it separately, handling the semantics of declarations inside shell
12808 functions. This avoids the double-evaluation of such arguments,
12809 because `declare' does some evaluation of compound assignments on
12811 if ((tlist
->word
->flags
& (W_COMPASSIGN
|W_ASSIGNARG
)) == (W_COMPASSIGN
|W_ASSIGNARG
))
12812 expand_declaration_argument (tlist
, wcmd
);
12815 expanded_something
= 0;
12816 expanded
= expand_word_internal
12817 (tlist
->word
, 0, 0, &has_dollar_at
, &expanded_something
);
12819 if (expanded
== &expand_word_error
|| expanded
== &expand_word_fatal
)
12821 /* By convention, each time this error is returned,
12822 tlist->word->word has already been freed. */
12823 tlist
->word
->word
= (char *)NULL
;
12825 /* Dispose our copy of the original list. */
12826 dispose_words (orig_list
);
12827 /* Dispose the new list we're building. */
12828 dispose_words (new_list
);
12830 last_command_exit_value
= EXECUTION_FAILURE
;
12831 if (expanded
== &expand_word_error
)
12832 exp_jump_to_top_level (DISCARD
);
12834 exp_jump_to_top_level (FORCE_EOF
);
12837 /* Don't split words marked W_NOSPLIT. */
12838 if (expanded_something
&& (tlist
->word
->flags
& W_NOSPLIT
) == 0)
12840 temp_list
= word_list_split (expanded
);
12841 dispose_words (expanded
);
12845 /* If no parameter expansion, command substitution, process
12846 substitution, or arithmetic substitution took place, then
12847 do not do word splitting. We still have to remove quoted
12848 null characters from the result. */
12849 word_list_remove_quoted_nulls (expanded
);
12850 temp_list
= expanded
;
12853 expanded
= REVERSE_LIST (temp_list
, WORD_LIST
*);
12854 new_list
= (WORD_LIST
*)list_append (expanded
, new_list
);
12858 dispose_words (orig_list
);
12861 new_list
= REVERSE_LIST (new_list
, WORD_LIST
*);
12866 /* Perform assignment statements optionally preceding a command name COMMAND.
12867 If COMMAND == NULL, is_nullcmd usually == 1. Follow the POSIX rules for
12868 variable assignment errors. */
12870 do_assignment_statements (varlist
, command
, is_nullcmd
)
12871 WORD_LIST
*varlist
;
12875 WORD_LIST
*temp_list
;
12877 sh_wassign_func_t
*assign_func
;
12878 int is_special_builtin
, is_builtin_or_func
, tint
;
12880 /* If the remainder of the words expand to nothing, Posix.2 requires
12881 that the variable and environment assignments affect the shell's
12882 environment (do_word_assignment). */
12883 assign_func
= is_nullcmd
? do_word_assignment
: assign_in_env
;
12884 tempenv_assign_error
= 0;
12886 is_builtin_or_func
= command
&& (find_shell_builtin (command
) || find_function (command
));
12887 /* Posix says that special builtins exit if a variable assignment error
12888 occurs in an assignment preceding it. (XXX - this is old -- current Posix
12889 says that any variable assignment error causes a non-interactive shell
12890 to exit. See the STRICT_POSIX checks below. */
12891 is_special_builtin
= posixly_correct
&& command
&& find_special_builtin (command
);
12893 savecmd
= this_command_name
;
12894 for (temp_list
= varlist
; temp_list
; temp_list
= temp_list
->next
)
12896 this_command_name
= (char *)NULL
;
12897 assigning_in_environment
= is_nullcmd
== 0;
12898 tint
= (*assign_func
) (temp_list
->word
, is_builtin_or_func
);
12899 assigning_in_environment
= 0;
12900 this_command_name
= savecmd
;
12902 /* Variable assignment errors in non-interactive shells running
12903 in posix mode cause the shell to exit. */
12906 if (is_nullcmd
) /* assignment statement */
12908 last_command_exit_value
= EXECUTION_FAILURE
;
12909 #if defined (STRICT_POSIX)
12910 if (posixly_correct
&& interactive_shell
== 0)
12912 if (posixly_correct
&& interactive_shell
== 0 && executing_command_builtin
== 0)
12914 exp_jump_to_top_level (FORCE_EOF
);
12916 exp_jump_to_top_level (DISCARD
);
12918 /* In posix mode, assignment errors in the temporary environment
12919 cause a non-interactive shell executing a special builtin to
12920 exit and a non-interactive shell to otherwise jump back to the
12921 top level. This is what POSIX says to do for variable assignment
12922 errors, and POSIX says errors in assigning to the temporary
12923 environment are treated as variable assignment errors.
12924 (XXX - this is not what current POSIX says - look at the
12925 STRICT_POSIX defines. */
12926 else if (posixly_correct
)
12928 last_command_exit_value
= EXECUTION_FAILURE
;
12929 #if defined (STRICT_POSIX)
12930 exp_jump_to_top_level ((interactive_shell
== 0) ? FORCE_EOF
: DISCARD
);
12932 if (interactive_shell
== 0 && is_special_builtin
)
12933 exp_jump_to_top_level (FORCE_EOF
);
12934 else if (interactive_shell
== 0)
12935 exp_jump_to_top_level (DISCARD
); /* XXX - maybe change later */
12937 exp_jump_to_top_level (DISCARD
);
12941 tempenv_assign_error
++;
12944 return (tempenv_assign_error
);
12947 /* The workhorse for expand_words () and expand_words_no_vars ().
12948 First arg is LIST, a WORD_LIST of words.
12949 Second arg EFLAGS is a flags word controlling which expansions are
12952 This does all of the substitutions: brace expansion, tilde expansion,
12953 parameter expansion, command substitution, arithmetic expansion,
12954 process substitution, word splitting, and pathname expansion, according
12955 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
12956 set, or for which no expansion is done, do not undergo word splitting.
12957 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
12958 with W_NOBRACE set do not undergo brace expansion (see
12959 brace_expand_word_list above). */
12961 expand_word_list_internal (list
, eflags
)
12965 WORD_LIST
*new_list
, *temp_list
;
12967 tempenv_assign_error
= 0;
12969 return ((WORD_LIST
*)NULL
);
12971 garglist
= new_list
= copy_word_list (list
);
12972 if (eflags
& WEXP_VARASSIGN
)
12974 garglist
= new_list
= separate_out_assignments (new_list
);
12977 if (subst_assign_varlist
)
12978 do_assignment_statements (subst_assign_varlist
, (char *)NULL
, 1);
12980 dispose_words (subst_assign_varlist
);
12981 subst_assign_varlist
= (WORD_LIST
*)NULL
;
12983 return ((WORD_LIST
*)NULL
);
12987 /* Begin expanding the words that remain. The expansions take place on
12988 things that aren't really variable assignments. */
12990 #if defined (BRACE_EXPANSION)
12991 /* Do brace expansion on this word if there are any brace characters
12993 if ((eflags
& WEXP_BRACEEXP
) && brace_expansion
&& new_list
)
12994 new_list
= brace_expand_word_list (new_list
, eflags
);
12995 #endif /* BRACE_EXPANSION */
12997 /* Perform the `normal' shell expansions: tilde expansion, parameter and
12998 variable substitution, command substitution, arithmetic expansion,
12999 and word splitting. */
13000 new_list
= shell_expand_word_list (new_list
, eflags
);
13002 /* Okay, we're almost done. Now let's just do some filename
13006 if ((eflags
& WEXP_PATHEXP
) && disallow_filename_globbing
== 0)
13007 /* Glob expand the word list unless globbing has been disabled. */
13008 new_list
= glob_expand_word_list (new_list
, eflags
);
13010 /* Dequote the words, because we're not performing globbing. */
13011 new_list
= dequote_list (new_list
);
13014 if ((eflags
& WEXP_VARASSIGN
) && subst_assign_varlist
)
13016 do_assignment_statements (subst_assign_varlist
, (new_list
&& new_list
->word
) ? new_list
->word
->word
: (char *)NULL
, new_list
== 0);
13018 dispose_words (subst_assign_varlist
);
13019 subst_assign_varlist
= (WORD_LIST
*)NULL
;