improve of cmpl.
[bush.git] / mydoc / var-name / subst.c
blobc13ba9ceb88b2bb255c22719424c2bcbbd877f10
1 /* subst.c -- The part of the shell that does parameter, command, arithmetic,
2 and globbing substitutions. */
4 /* ``Have a little faith, there's magic in the night. You ain't a
5 beauty, but, hey, you're alright.'' */
7 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
9 This file is part of GNU Bush, the Bourne Again SHell.
11 Bush is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 Bush is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with Bush. If not, see <http://www.gnu.org/licenses/>.
25 #include "config.h"
27 #include "bushtypes.h"
28 #include <stdio.h>
29 #include "chartypes.h"
30 #if defined (HAVE_PWD_H)
31 # include <pwd.h>
32 #endif
33 #include <signal.h>
34 #include <errno.h>
36 #if defined (HAVE_UNISTD_H)
37 # include <unistd.h>
38 #endif
40 #define NEED_FPURGE_DECL
42 #include "bushansi.h"
43 #include "posixstat.h"
44 #include "bushintl.h"
46 #include "shell.h"
47 #include "lxrgmr/parser.h"
48 #include "flags.h"
49 #include "jobs.h"
50 #include "runner/execute_cmd.h"
51 #include "filecntl.h"
52 #include "trap.h"
53 #include "impl/pathexp.h"
54 #include "mailcheck.h"
56 #include "shmbutil.h"
57 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
58 # include <mbstr.h> /* mbschr */
59 #endif
60 #include "typemax.h"
62 #include "builtins/getopt.h"
63 #include "builtins/common.h"
65 #include "builtins/builtext.h"
67 #include <tilde/tilde.h>
68 #include <glob/strmatch.h>
70 #if !defined (errno)
71 extern int errno;
72 #endif /* !errno */
74 /* The size that strings change by. */
75 #define DEFAULT_INITIAL_ARRAY_SIZE 112
76 #define DEFAULT_ARRAY_SIZE 128
78 /* Variable types. */
79 #define VT_VARIABLE 0
80 #define VT_POSPARMS 1
81 #define VT_ARRAYVAR 2
82 #define VT_ARRAYMEMBER 3
83 #define VT_ASSOCVAR 4
85 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
87 /* Flags for quoted_strchr */
88 #define ST_BACKSL 0x01
89 #define ST_CTLESC 0x02
90 #define ST_SQUOTE 0x04 /* unused yet */
91 #define ST_DQUOTE 0x08 /* unused yet */
93 /* These defs make it easier to use the editor. */
94 #define LBRACE '{'
95 #define RBRACE '}'
96 #define LPAREN '('
97 #define RPAREN ')'
98 #define LBRACK '['
99 #define RBRACK ']'
101 #if defined (HANDLE_MULTIBYTE)
102 #define WLPAREN L'('
103 #define WRPAREN L')'
104 #endif
106 #define DOLLAR_AT_STAR(c) ((c) == '@' || (c) == '*')
107 #define STR_DOLLAR_AT_STAR(s) (DOLLAR_AT_STAR ((s)[0]) && (s)[1] == '\0')
109 /* Evaluates to 1 if C is one of the shell's special parameters whose length
110 can be taken, but is also one of the special expansion characters. */
111 #define VALID_SPECIAL_LENGTH_PARAM(c) \
112 ((c) == '-' || (c) == '?' || (c) == '#' || (c) == '@')
114 /* Evaluates to 1 if C is one of the shell's special parameters for which an
115 indirect variable reference may be made. */
116 #define VALID_INDIR_PARAM(c) \
117 ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
119 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
120 in ${parameter[:]OPword}. */
121 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
123 /* Evaluates to 1 if this is one of the shell's special variables. */
124 #define SPECIAL_VAR(name, wi) \
125 (*name && ((DIGIT (*name) && all_digits (name)) || \
126 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
127 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1]))))
129 /* This can be used by all of the *_extract_* functions that have a similar
130 structure. It can't just be wrapped in a do...while(0) loop because of
131 the embedded `break'. The dangling else accommodates a trailing semicolon;
132 we could also put in a do ; while (0) */
134 #define CHECK_STRING_OVERRUN(oind, ind, len, ch) \
135 if (ind >= len) \
137 oind = len; \
138 ch = 0; \
139 break; \
141 else \
143 /* An expansion function that takes a string and a quoted flag and returns
144 a WORD_LIST *. Used as the type of the third argument to
145 expand_string_if_necessary(). */
146 typedef WORD_LIST *EXPFUNC PARAMS((char *, int));
148 /* Process ID of the last command executed within command substitution. */
149 pid_t last_command_subst_pid = NO_PID;
150 pid_t current_command_subst_pid = NO_PID;
152 /* Variables used to keep track of the characters in IFS. */
153 SHELL_VAR *ifs_var;
154 char *ifs_value;
155 unsigned char ifs_cmap[UCHAR_MAX + 1];
156 int ifs_is_set, ifs_is_null;
158 #if defined (HANDLE_MULTIBYTE)
159 unsigned char ifs_firstc[MB_LEN_MAX];
160 size_t ifs_firstc_len;
161 #else
162 unsigned char ifs_firstc;
163 #endif
165 /* If non-zero, command substitution inherits the value of errexit option */
166 int inherit_errexit = 0;
168 /* Sentinel to tell when we are performing variable assignments preceding a
169 command name and putting them into the environment. Used to make sure
170 we use the temporary environment when looking up variable values. */
171 int assigning_in_environment;
173 /* Used to hold a list of variable assignments preceding a command. Global
174 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
175 SIGCHLD trap and so it can be saved and restored by the trap handlers. */
176 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
178 /* Tell the expansion functions to not longjmp back to top_level on fatal
179 errors. Enabled when doing completion and prompt string expansion. */
180 int no_longjmp_on_fatal_error = 0;
182 /* Non-zero means to allow unmatched globbed filenames to expand to
183 a null file. */
184 int allow_null_glob_expansion;
186 /* Non-zero means to throw an error when globbing fails to match anything. */
187 int fail_glob_expansion;
189 /* Extern functions and variables from different files. */
190 extern struct fd_bitmap *current_fds_to_close;
191 extern int wordexp_only;
193 #if defined (JOB_CONTROL) && defined (PROCESS_SUBSTITUTION)
194 extern PROCESS *last_procsub_child;
195 #endif
197 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
198 extern wchar_t *wcsdup PARAMS((const wchar_t *));
199 #endif
201 #if 0
202 /* Variables to keep track of which words in an expanded word list (the
203 output of expand_word_list_internal) are the result of globbing
204 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
205 (CURRENTLY UNUSED). */
206 char *glob_argv_flags;
207 static int glob_argv_flags_size;
208 #endif
210 static WORD_LIST *cached_quoted_dollar_at = 0;
212 /* Distinguished error values to return from expansion functions */
213 static WORD_LIST expand_word_error, expand_word_fatal;
214 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
215 static char expand_param_error, expand_param_fatal, expand_param_unset;
216 static char extract_string_error, extract_string_fatal;
218 /* Set by expand_word_unsplit and several of the expand_string_XXX functions;
219 used to inhibit splitting and re-joining $* on $IFS, primarily when doing
220 assignment statements. The idea is that if we're in a context where this
221 is set, we're not going to be performing word splitting, so we use the same
222 rules to expand $* as we would if it appeared within double quotes. */
223 static int expand_no_split_dollar_star = 0;
225 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
226 without any leading variable assignments. */
227 static WORD_LIST *garglist = (WORD_LIST *)NULL;
229 static char *quoted_substring PARAMS((char *, int, int));
230 static int quoted_strlen PARAMS((char *));
231 static char *quoted_strchr PARAMS((char *, int, int));
233 static char *expand_string_if_necessary PARAMS((char *, int, EXPFUNC *));
234 static inline char *expand_string_to_string_internal PARAMS((char *, int, EXPFUNC *));
235 static WORD_LIST *call_expand_word_internal PARAMS((WORD_DESC *, int, int, int *, int *));
236 static WORD_LIST *expand_string_internal PARAMS((char *, int));
237 static WORD_LIST *expand_string_leave_quoted PARAMS((char *, int));
238 static WORD_LIST *expand_string_for_rhs PARAMS((char *, int, int, int, int *, int *));
239 static WORD_LIST *expand_string_for_pat PARAMS((char *, int, int *, int *));
241 static char *quote_escapes_internal PARAMS((const char *, int));
243 static WORD_LIST *list_quote_escapes PARAMS((WORD_LIST *));
244 static WORD_LIST *list_dequote_escapes PARAMS((WORD_LIST *));
246 static char *make_quoted_char PARAMS((int));
247 static WORD_LIST *quote_list PARAMS((WORD_LIST *));
249 static int unquoted_substring PARAMS((char *, char *));
250 static int unquoted_member PARAMS((int, char *));
252 #if defined (ARRAY_VARS)
253 static SHELL_VAR *do_compound_assignment PARAMS((char *, char *, int));
254 #endif
255 static int do_assignment_internal PARAMS((const WORD_DESC *, int));
257 static char *string_extract_verbatim PARAMS((char *, size_t, int *, char *, int));
258 static char *string_extract PARAMS((char *, int *, char *, int));
259 static char *string_extract_double_quoted PARAMS((char *, int *, int));
260 static inline char *string_extract_single_quoted PARAMS((char *, int *));
261 static inline int skip_single_quoted PARAMS((const char *, size_t, int, int));
262 static int skip_double_quoted PARAMS((char *, size_t, int, int));
263 static char *extract_delimited_string PARAMS((char *, int *, char *, char *, char *, int));
264 static char *extract_dollar_brace_string PARAMS((char *, int *, int, int));
265 static int skip_matched_pair PARAMS((const char *, int, int, int, int));
267 static char *pos_params PARAMS((char *, int, int, int, int));
269 static unsigned char *mb_getcharlens PARAMS((char *, int));
271 static char *remove_upattern PARAMS((char *, char *, int));
272 #if defined (HANDLE_MULTIBYTE)
273 static wchar_t *remove_wpattern PARAMS((wchar_t *, size_t, wchar_t *, int));
274 #endif
275 static char *remove_pattern PARAMS((char *, char *, int));
277 static int match_upattern PARAMS((char *, char *, int, char **, char **));
278 #if defined (HANDLE_MULTIBYTE)
279 static int match_wpattern PARAMS((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
280 #endif
281 static int match_pattern PARAMS((char *, char *, int, char **, char **));
282 static int getpatspec PARAMS((int, char *));
283 static char *getpattern PARAMS((char *, int, int));
284 static char *variable_remove_pattern PARAMS((char *, char *, int, int));
285 static char *list_remove_pattern PARAMS((WORD_LIST *, char *, int, int, int));
286 static char *parameter_list_remove_pattern PARAMS((int, char *, int, int));
287 #ifdef ARRAY_VARS
288 static char *array_remove_pattern PARAMS((SHELL_VAR *, char *, int, int, int));
289 #endif
290 static char *parameter_brace_remove_pattern PARAMS((char *, char *, int, char *, int, int, int));
292 static char *string_var_assignment PARAMS((SHELL_VAR *, char *));
293 #if defined (ARRAY_VARS)
294 static char *array_var_assignment PARAMS((SHELL_VAR *, int, int, int));
295 #endif
296 static char *pos_params_assignment PARAMS((WORD_LIST *, int, int));
297 static char *string_transform PARAMS((int, SHELL_VAR *, char *));
298 static char *list_transform PARAMS((int, SHELL_VAR *, WORD_LIST *, int, int));
299 static char *parameter_list_transform PARAMS((int, int, int));
300 #if defined ARRAY_VARS
301 static char *array_transform PARAMS((int, SHELL_VAR *, int, int));
302 #endif
303 static char *parameter_brace_transform PARAMS((char *, char *, int, char *, int, int, int, int));
304 static int valid_parameter_transform PARAMS((char *));
306 static char *process_substitute PARAMS((char *, int));
308 static char *read_comsub PARAMS((int, int, int, int *));
310 #ifdef ARRAY_VARS
311 static arrayind_t array_length_reference PARAMS((char *));
312 #endif
314 static int valid_brace_expansion_word PARAMS((char *, int));
315 static int chk_atstar PARAMS((char *, int, int, int *, int *));
316 static int chk_arithsub PARAMS((const char *, int));
318 static WORD_DESC *parameter_brace_expand_word PARAMS((char *, int, int, int, arrayind_t *));
319 static char *parameter_brace_find_indir PARAMS((char *, int, int, int));
320 static WORD_DESC *parameter_brace_expand_indir PARAMS((char *, int, int, int, int *, int *));
321 static WORD_DESC *parameter_brace_expand_rhs PARAMS((char *, char *, int, int, int, int *, int *));
322 static void parameter_brace_expand_error PARAMS((char *, char *, int));
324 static int valid_length_expression PARAMS((char *));
325 static intmax_t parameter_brace_expand_length PARAMS((char *));
327 static char *skiparith PARAMS((char *, int));
328 static int verify_substring_values PARAMS((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
329 static int get_var_and_type PARAMS((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **));
330 static char *mb_substring PARAMS((char *, int, int));
331 static char *parameter_brace_substring PARAMS((char *, char *, int, char *, int, int, int));
333 static int shouldexp_replacement PARAMS((char *));
335 static char *pos_params_pat_subst PARAMS((char *, char *, char *, int));
337 static char *parameter_brace_patsub PARAMS((char *, char *, int, char *, int, int, int));
339 static char *pos_params_casemod PARAMS((char *, char *, int, int));
340 static char *parameter_brace_casemod PARAMS((char *, char *, int, int, char *, int, int, int));
342 static WORD_DESC *parameter_brace_expand PARAMS((char *, int *, int, int, int *, int *));
343 static WORD_DESC *param_expand PARAMS((char *, int *, int, int *, int *, int *, int *, int));
345 static WORD_LIST *expand_word_internal PARAMS((WORD_DESC *, int, int, int *, int *));
347 static WORD_LIST *word_list_split PARAMS((WORD_LIST *));
349 static void exp_jump_to_top_level PARAMS((int));
351 static WORD_LIST *separate_out_assignments PARAMS((WORD_LIST *));
352 static WORD_LIST *glob_expand_word_list PARAMS((WORD_LIST *, int));
353 #ifdef BRACE_EXPANSION
354 static WORD_LIST *brace_expand_word_list PARAMS((WORD_LIST *, int));
355 #endif
356 #if defined (ARRAY_VARS)
357 static int make_internal_declare PARAMS((char *, char *, char *));
358 static void expand_compound_assignment_word PARAMS((WORD_LIST *, int));
359 static WORD_LIST *expand_declaration_argument PARAMS((WORD_LIST *, WORD_LIST *));
360 #endif
361 static WORD_LIST *shell_expand_word_list PARAMS((WORD_LIST *, int));
362 static WORD_LIST *expand_word_list_internal PARAMS((WORD_LIST *, int));
364 /* **************************************************************** */
365 /* */
366 /* Utility Functions */
367 /* */
368 /* **************************************************************** */
370 #if defined (DEBUG)
371 void
372 dump_word_flags (flags)
373 int flags;
375 int f;
377 f = flags;
378 fprintf (stderr, "%d -> ", f);
379 if (f & W_ARRAYIND)
381 f &= ~W_ARRAYIND;
382 fprintf (stderr, "W_ARRAYIND%s", f ? "|" : "");
384 if (f & W_ASSIGNASSOC)
386 f &= ~W_ASSIGNASSOC;
387 fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : "");
389 if (f & W_ASSIGNARRAY)
391 f &= ~W_ASSIGNARRAY;
392 fprintf (stderr, "W_ASSIGNARRAY%s", f ? "|" : "");
394 if (f & W_SAWQUOTEDNULL)
396 f &= ~W_SAWQUOTEDNULL;
397 fprintf (stderr, "W_SAWQUOTEDNULL%s", f ? "|" : "");
399 if (f & W_NOPROCSUB)
401 f &= ~W_NOPROCSUB;
402 fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : "");
404 if (f & W_DQUOTE)
406 f &= ~W_DQUOTE;
407 fprintf (stderr, "W_DQUOTE%s", f ? "|" : "");
409 if (f & W_HASQUOTEDNULL)
411 f &= ~W_HASQUOTEDNULL;
412 fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : "");
414 if (f & W_ASSIGNARG)
416 f &= ~W_ASSIGNARG;
417 fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : "");
419 if (f & W_ASSNBLTIN)
421 f &= ~W_ASSNBLTIN;
422 fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : "");
424 if (f & W_ASSNGLOBAL)
426 f &= ~W_ASSNGLOBAL;
427 fprintf (stderr, "W_ASSNGLOBAL%s", f ? "|" : "");
429 if (f & W_COMPASSIGN)
431 f &= ~W_COMPASSIGN;
432 fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : "");
434 if (f & W_EXPANDRHS)
436 f &= ~W_EXPANDRHS;
437 fprintf (stderr, "W_EXPANDRHS%s", f ? "|" : "");
439 if (f & W_ITILDE)
441 f &= ~W_ITILDE;
442 fprintf (stderr, "W_ITILDE%s", f ? "|" : "");
444 if (f & W_NOTILDE)
446 f &= ~W_NOTILDE;
447 fprintf (stderr, "W_NOTILDE%s", f ? "|" : "");
449 if (f & W_ASSIGNRHS)
451 f &= ~W_ASSIGNRHS;
452 fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : "");
454 if (f & W_NOASSNTILDE)
456 f &= ~W_NOASSNTILDE;
457 fprintf (stderr, "W_NOASSNTILDE%s", f ? "|" : "");
459 if (f & W_NOCOMSUB)
461 f &= ~W_NOCOMSUB;
462 fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : "");
464 if (f & W_DOLLARSTAR)
466 f &= ~W_DOLLARSTAR;
467 fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : "");
469 if (f & W_DOLLARAT)
471 f &= ~W_DOLLARAT;
472 fprintf (stderr, "W_DOLLARAT%s", f ? "|" : "");
474 if (f & W_TILDEEXP)
476 f &= ~W_TILDEEXP;
477 fprintf (stderr, "W_TILDEEXP%s", f ? "|" : "");
479 if (f & W_NOSPLIT2)
481 f &= ~W_NOSPLIT2;
482 fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : "");
484 if (f & W_NOSPLIT)
486 f &= ~W_NOSPLIT;
487 fprintf (stderr, "W_NOSPLIT%s", f ? "|" : "");
489 if (f & W_NOBRACE)
491 f &= ~W_NOBRACE;
492 fprintf (stderr, "W_NOBRACE%s", f ? "|" : "");
494 if (f & W_NOGLOB)
496 f &= ~W_NOGLOB;
497 fprintf (stderr, "W_NOGLOB%s", f ? "|" : "");
499 if (f & W_SPLITSPACE)
501 f &= ~W_SPLITSPACE;
502 fprintf (stderr, "W_SPLITSPACE%s", f ? "|" : "");
504 if (f & W_ASSIGNMENT)
506 f &= ~W_ASSIGNMENT;
507 fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : "");
509 if (f & W_QUOTED)
511 f &= ~W_QUOTED;
512 fprintf (stderr, "W_QUOTED%s", f ? "|" : "");
514 if (f & W_HASDOLLAR)
516 f &= ~W_HASDOLLAR;
517 fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : "");
519 if (f & W_COMPLETE)
521 f &= ~W_COMPLETE;
522 fprintf (stderr, "W_COMPLETE%s", f ? "|" : "");
524 if (f & W_CHKLOCAL)
526 f &= ~W_CHKLOCAL;
527 fprintf (stderr, "W_CHKLOCAL%s", f ? "|" : "");
529 if (f & W_FORCELOCAL)
531 f &= ~W_FORCELOCAL;
532 fprintf (stderr, "W_FORCELOCAL%s", f ? "|" : "");
535 fprintf (stderr, "\n");
536 fflush (stderr);
538 #endif
540 #ifdef INCLUDE_UNUSED
541 static char *
542 quoted_substring (string, start, end)
543 char *string;
544 int start, end;
546 register int len, l;
547 register char *result, *s, *r;
549 len = end - start;
551 /* Move to string[start], skipping quoted characters. */
552 for (s = string, l = 0; *s && l < start; )
554 if (*s == CTLESC)
556 s++;
557 continue;
559 l++;
560 if (*s == 0)
561 break;
564 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
566 /* Copy LEN characters, including quote characters. */
567 s = string + l;
568 for (l = 0; l < len; s++)
570 if (*s == CTLESC)
571 *r++ = *s++;
572 *r++ = *s;
573 l++;
574 if (*s == 0)
575 break;
577 *r = '\0';
578 return result;
580 #endif
582 #ifdef INCLUDE_UNUSED
583 /* Return the length of S, skipping over quoted characters */
584 static int
585 quoted_strlen (s)
586 char *s;
588 register char *p;
589 int i;
591 i = 0;
592 for (p = s; *p; p++)
594 if (*p == CTLESC)
596 p++;
597 if (*p == 0)
598 return (i + 1);
600 i++;
603 return i;
605 #endif
607 #ifdef INCLUDE_UNUSED
608 /* Find the first occurrence of character C in string S, obeying shell
609 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
610 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
611 escaped with CTLESC are skipped. */
612 static char *
613 quoted_strchr (s, c, flags)
614 char *s;
615 int c, flags;
617 register char *p;
619 for (p = s; *p; p++)
621 if (((flags & ST_BACKSL) && *p == '\\')
622 || ((flags & ST_CTLESC) && *p == CTLESC))
624 p++;
625 if (*p == '\0')
626 return ((char *)NULL);
627 continue;
629 else if (*p == c)
630 return p;
632 return ((char *)NULL);
635 /* Return 1 if CHARACTER appears in an unquoted portion of
636 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
637 static int
638 unquoted_member (character, string)
639 int character;
640 char *string;
642 size_t slen;
643 int sindex, c;
644 DECLARE_MBSTATE;
646 slen = strlen (string);
647 sindex = 0;
648 while (c = string[sindex])
650 if (c == character)
651 return (1);
653 switch (c)
655 default:
656 ADVANCE_CHAR (string, slen, sindex);
657 break;
659 case '\\':
660 sindex++;
661 if (string[sindex])
662 ADVANCE_CHAR (string, slen, sindex);
663 break;
665 case '\'':
666 sindex = skip_single_quoted (string, slen, ++sindex, 0);
667 break;
669 case '"':
670 sindex = skip_double_quoted (string, slen, ++sindex, 0);
671 break;
674 return (0);
677 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
678 static int
679 unquoted_substring (substr, string)
680 char *substr, *string;
682 size_t slen;
683 int sindex, c, sublen;
684 DECLARE_MBSTATE;
686 if (substr == 0 || *substr == '\0')
687 return (0);
689 slen = strlen (string);
690 sublen = strlen (substr);
691 for (sindex = 0; c = string[sindex]; )
693 if (STREQN (string + sindex, substr, sublen))
694 return (1);
696 switch (c)
698 case '\\':
699 sindex++;
700 if (string[sindex])
701 ADVANCE_CHAR (string, slen, sindex);
702 break;
704 case '\'':
705 sindex = skip_single_quoted (string, slen, ++sindex, 0);
706 break;
708 case '"':
709 sindex = skip_double_quoted (string, slen, ++sindex, 0);
710 break;
712 default:
713 ADVANCE_CHAR (string, slen, sindex);
714 break;
717 return (0);
719 #endif
721 /* Most of the substitutions must be done in parallel. In order
722 to avoid using tons of unclear goto's, I have some functions
723 for manipulating malloc'ed strings. They all take INDX, a
724 pointer to an integer which is the offset into the string
725 where manipulation is taking place. They also take SIZE, a
726 pointer to an integer which is the current length of the
727 character array for this string. */
729 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
730 of space allocated to TARGET. SOURCE can be NULL, in which
731 case nothing happens. Gets rid of SOURCE by freeing it.
732 Returns TARGET in case the location has changed. */
733 INLINE char *
734 sub_append_string (source, target, indx, size)
735 char *source, *target;
736 int *indx;
737 size_t *size;
739 if (source)
741 int n;
742 size_t srclen;
744 srclen = STRLEN (source);
745 if (srclen >= (int)(*size - *indx))
747 n = srclen + *indx;
748 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
749 target = (char *)xrealloc (target, (*size = n));
752 FASTCOPY (source, target + *indx, srclen);
753 *indx += srclen;
754 target[*indx] = '\0';
756 free (source);
758 return (target);
761 #if 0
762 /* UNUSED */
763 /* Append the textual representation of NUMBER to TARGET.
764 INDX and SIZE are as in SUB_APPEND_STRING. */
765 char *
766 sub_append_number (number, target, indx, size)
767 intmax_t number;
768 char *target;
769 int *indx;
770 size_t *size;
772 char *temp;
774 temp = itos (number);
775 return (sub_append_string (temp, target, indx, size));
777 #endif
779 /* Extract a substring from STRING, starting at SINDEX and ending with
780 one of the characters in CHARLIST. Don't make the ending character
781 part of the string. Leave SINDEX pointing at the ending character.
782 Understand about backslashes in the string. If (flags & SX_VARNAME)
783 is non-zero, and array variables have been compiled into the shell,
784 everything between a `[' and a corresponding `]' is skipped over.
785 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
786 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
787 contain a closing character from CHARLIST. */
788 static char *
789 string_extract (string, sindex, charlist, flags)
790 char *string;
791 int *sindex;
792 char *charlist;
793 int flags;
795 register int c, i;
796 int found;
797 size_t slen;
798 char *temp;
799 DECLARE_MBSTATE;
801 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
802 i = *sindex;
803 found = 0;
804 while (c = string[i])
806 if (c == '\\')
808 if (string[i + 1])
809 i++;
810 else
811 break;
813 #if defined (ARRAY_VARS)
814 else if ((flags & SX_VARNAME) && c == LBRACK)
816 int ni;
817 /* If this is an array subscript, skip over it and continue. */
818 ni = skipsubscript (string, i, 0);
819 if (string[ni] == RBRACK)
820 i = ni;
822 #endif
823 // else if (c == ':' && string[i+1] == ':' && legal_variable_starter(string[i+2]))
824 else if (c == ':' && string[i+1] == ':' && org_legal_variable_starter(string[i+2]) )
826 i+=2;
827 continue;
829 else if (MEMBER (c, charlist))
831 found = 1;
832 break;
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)
842 *sindex = i;
843 return (&extract_string_error);
846 temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
847 *sindex = i;
849 return (temp);
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. */
859 static char *
860 string_extract_double_quoted (string, sindex, flags)
861 char *string;
862 int *sindex, flags;
864 size_t slen;
865 char *send;
866 int j, i, t;
867 unsigned char c;
868 char *temp, *ret; /* The new string we return. */
869 int pass_next, backquote, si; /* State variables for the machine. */
870 int dquote;
871 int stripdq;
872 DECLARE_MBSTATE;
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);
882 j = 0;
883 i = *sindex;
884 while (c = string[i])
886 /* Process a character that was quoted by a backslash. */
887 if (pass_next)
889 /* XXX - take another look at this in light of Interp 221 */
890 /* Posix.2 sez:
892 ``The backslash shall retain its special meaning as an escape
893 character only when followed by one of the characters:
894 $ ` " \ <newline>''.
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
909 quoting rules).
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)))
914 temp[j++] = '\\';
915 pass_next = 0;
917 add_one_character:
918 COPY_CHAR_I (temp, j, string, send, i);
919 continue;
922 /* A backslash protects the next character. The code just above
923 handles preserving the backslash in front of any character but
924 a double quote. */
925 if (c == '\\')
927 pass_next++;
928 i++;
929 continue;
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''. */
936 if (backquote)
938 if (c == '`')
939 backquote = 0;
940 temp[j++] = c; /* COPY_CHAR_I? */
941 i++;
942 continue;
945 if (c == '`')
947 temp[j++] = c;
948 backquote++;
949 i++;
950 continue;
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)))
957 int free_ret = 1;
959 si = i + 2;
960 if (string[i + 1] == LPAREN)
961 ret = extract_command_subst (string, &si, (flags & SX_COMPLETE));
962 else
963 ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0);
965 temp[j++] = '$';
966 temp[j++] = string[i + 1];
968 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
969 is set. */
970 if (ret == 0 && no_longjmp_on_fatal_error)
972 free_ret = 0;
973 ret = string + i + 2;
976 /* XXX - CHECK_STRING_OVERRUN here? */
977 for (t = 0; ret[t]; t++, j++)
978 temp[j] = ret[t];
979 temp[j] = string[si];
981 if (si < i + 2) /* we went back? */
982 i += 2;
983 else if (string[si])
985 j++;
986 i = si + 1;
988 else
989 i = si;
991 if (free_ret)
992 free (ret);
993 continue;
996 /* Add any character but a double quote to the quoted string we're
997 accumulating. */
998 if (c != '"')
999 goto add_one_character;
1001 /* c == '"' */
1002 if (stripdq)
1004 dquote ^= 1;
1005 i++;
1006 continue;
1009 break;
1011 temp[j] = '\0';
1013 /* Point to after the closing quote. */
1014 if (c)
1015 i++;
1016 *sindex = i;
1018 return (temp);
1021 /* This should really be another option to string_extract_double_quoted. */
1022 static int
1023 skip_double_quoted (string, slen, sind, flags)
1024 char *string;
1025 size_t slen;
1026 int sind;
1027 int flags;
1029 int c, i;
1030 char *ret;
1031 int pass_next, backquote, si;
1032 DECLARE_MBSTATE;
1034 pass_next = backquote = 0;
1035 i = sind;
1036 while (c = string[i])
1038 if (pass_next)
1040 pass_next = 0;
1041 ADVANCE_CHAR (string, slen, i);
1042 continue;
1044 else if (c == '\\')
1046 pass_next++;
1047 i++;
1048 continue;
1050 else if (backquote)
1052 if (c == '`')
1053 backquote = 0;
1054 ADVANCE_CHAR (string, slen, i);
1055 continue;
1057 else if (c == '`')
1059 backquote++;
1060 i++;
1061 continue;
1063 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
1065 si = i + 2;
1066 if (string[i + 1] == LPAREN)
1067 ret = extract_command_subst (string, &si, SX_NOALLOC|(flags&SX_COMPLETE));
1068 else
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);
1074 i = si + 1;
1075 continue;
1077 else if (c != '"')
1079 ADVANCE_CHAR (string, slen, i);
1080 continue;
1082 else
1083 break;
1086 if (c)
1087 i++;
1089 return (i);
1092 /* Extract the contents of STRING as if it is enclosed in single quotes.
1093 SINDEX, when passed in, is the offset of the character immediately
1094 following the opening single quote; on exit, SINDEX is left pointing after
1095 the closing single quote. */
1096 static inline char *
1097 string_extract_single_quoted (string, sindex)
1098 char *string;
1099 int *sindex;
1101 register int i;
1102 size_t slen;
1103 char *t;
1104 DECLARE_MBSTATE;
1106 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
1107 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
1108 i = *sindex;
1109 while (string[i] && string[i] != '\'')
1110 ADVANCE_CHAR (string, slen, i);
1112 t = substring (string, *sindex, i);
1114 if (string[i])
1115 i++;
1116 *sindex = i;
1118 return (t);
1121 /* Skip over a single-quoted string. We overload the SX_COMPLETE flag to mean
1122 that we are splitting out words for completion and have encountered a $'...'
1123 string, which allows backslash-escaped single quotes. */
1124 static inline int
1125 skip_single_quoted (string, slen, sind, flags)
1126 const char *string;
1127 size_t slen;
1128 int sind;
1129 int flags;
1131 register int c;
1132 DECLARE_MBSTATE;
1134 c = sind;
1135 while (string[c] && string[c] != '\'')
1137 if ((flags & SX_COMPLETE) && string[c] == '\\' && string[c+1] == '\'' && string[c+2])
1138 ADVANCE_CHAR (string, slen, c);
1139 ADVANCE_CHAR (string, slen, c);
1142 if (string[c])
1143 c++;
1144 return c;
1147 /* Just like string_extract, but doesn't hack backslashes or any of
1148 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
1149 static char *
1150 string_extract_verbatim (string, slen, sindex, charlist, flags)
1151 char *string;
1152 size_t slen;
1153 int *sindex;
1154 char *charlist;
1155 int flags;
1157 register int i;
1158 #if defined (HANDLE_MULTIBYTE)
1159 wchar_t *wcharlist;
1160 #endif
1161 int c;
1162 char *temp;
1163 DECLARE_MBSTATE;
1165 if ((flags & SX_NOCTLESC) && charlist[0] == '\'' && charlist[1] == '\0')
1167 temp = string_extract_single_quoted (string, sindex);
1168 --*sindex; /* leave *sindex at separator character */
1169 return temp;
1172 /* This can never be called with charlist == NULL. If *charlist == NULL,
1173 we can skip the loop and just return a copy of the string, updating
1174 *sindex */
1175 if (*charlist == 0)
1177 temp = string + *sindex;
1178 c = (*sindex == 0) ? slen : STRLEN (temp);
1179 temp = savestring (temp);
1180 *sindex += c;
1181 return temp;
1184 i = *sindex;
1185 #if defined (HANDLE_MULTIBYTE)
1186 wcharlist = 0;
1187 #endif
1188 while (c = string[i])
1190 #if defined (HANDLE_MULTIBYTE)
1191 size_t mblength;
1192 #endif
1193 if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
1195 i += 2;
1196 CHECK_STRING_OVERRUN (i, i, slen, c);
1197 continue;
1199 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
1200 through, to protect the CTLNULs from later calls to
1201 remove_quoted_nulls. */
1202 else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
1204 i += 2;
1205 CHECK_STRING_OVERRUN (i, i, slen, c);
1206 continue;
1209 #if defined (HANDLE_MULTIBYTE)
1210 if (locale_utf8locale && slen > i && UTF8_SINGLEBYTE (string[i]))
1211 mblength = (string[i] != 0) ? 1 : 0;
1212 else
1213 mblength = MBLEN (string + i, slen - i);
1214 if (mblength > 1)
1216 wchar_t wc;
1217 mblength = mbtowc (&wc, string + i, slen - i);
1218 if (MB_INVALIDCH (mblength))
1220 if (MEMBER (c, charlist))
1221 break;
1223 else
1225 if (wcharlist == 0)
1227 size_t len;
1228 len = mbstowcs (wcharlist, charlist, 0);
1229 if (len == -1)
1230 len = 0;
1231 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
1232 mbstowcs (wcharlist, charlist, len + 1);
1235 if (wcschr (wcharlist, wc))
1236 break;
1239 else
1240 #endif
1241 if (MEMBER (c, charlist))
1242 break;
1244 ADVANCE_CHAR (string, slen, i);
1247 #if defined (HANDLE_MULTIBYTE)
1248 FREE (wcharlist);
1249 #endif
1251 temp = substring (string, *sindex, i);
1252 *sindex = i;
1254 return (temp);
1257 /* Extract the $( construct in STRING, and return a new string.
1258 Start extracting at (SINDEX) as if we had just seen "$(".
1259 Make (SINDEX) get the position of the matching ")". )
1260 XFLAGS is additional flags to pass to other extraction functions. */
1261 char *
1262 extract_command_subst (string, sindex, xflags)
1263 char *string;
1264 int *sindex;
1265 int xflags;
1267 char *ret;
1269 if (string[*sindex] == LPAREN || (xflags & SX_COMPLETE))
1270 return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
1271 else
1273 xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1274 ret = xparse_dolparen (string, string+*sindex, sindex, xflags);
1275 return ret;
1279 /* Extract the $[ construct in STRING, and return a new string. (])
1280 Start extracting at (SINDEX) as if we had just seen "$[".
1281 Make (SINDEX) get the position of the matching "]". */
1282 char *
1283 extract_arithmetic_subst (string, sindex)
1284 char *string;
1285 int *sindex;
1287 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
1290 #if defined (PROCESS_SUBSTITUTION)
1291 /* Extract the <( or >( construct in STRING, and return a new string.
1292 Start extracting at (SINDEX) as if we had just seen "<(".
1293 Make (SINDEX) get the position of the matching ")". */ /*))*/
1294 char *
1295 extract_process_subst (string, starter, sindex, xflags)
1296 char *string;
1297 char *starter;
1298 int *sindex;
1299 int xflags;
1301 #if 0
1302 /* XXX - check xflags&SX_COMPLETE here? */
1303 return (extract_delimited_string (string, sindex, starter, "(", ")", SX_COMMAND));
1304 #else
1305 xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1306 return (xparse_dolparen (string, string+*sindex, sindex, xflags));
1307 #endif
1309 #endif /* PROCESS_SUBSTITUTION */
1311 #if defined (ARRAY_VARS)
1312 /* This can be fooled by unquoted right parens in the passed string. If
1313 each caller verifies that the last character in STRING is a right paren,
1314 we don't even need to call extract_delimited_string. */
1315 char *
1316 extract_array_assignment_list (string, sindex)
1317 char *string;
1318 int *sindex;
1320 int slen;
1321 char *ret;
1323 slen = strlen (string);
1324 if (string[slen - 1] == RPAREN)
1326 ret = substring (string, *sindex, slen - 1);
1327 *sindex = slen - 1;
1328 return ret;
1330 return 0;
1332 #endif
1334 /* Extract and create a new string from the contents of STRING, a
1335 character string delimited with OPENER and CLOSER. SINDEX is
1336 the address of an int describing the current offset in STRING;
1337 it should point to just after the first OPENER found. On exit,
1338 SINDEX gets the position of the last character of the matching CLOSER.
1339 If OPENER is more than a single character, ALT_OPENER, if non-null,
1340 contains a character string that can also match CLOSER and thus
1341 needs to be skipped. */
1342 static char *
1343 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1344 char *string;
1345 int *sindex;
1346 char *opener, *alt_opener, *closer;
1347 int flags;
1349 int i, c, si;
1350 size_t slen;
1351 char *t, *result;
1352 int pass_character, nesting_level, in_comment;
1353 int len_closer, len_opener, len_alt_opener;
1354 DECLARE_MBSTATE;
1356 slen = strlen (string + *sindex) + *sindex;
1357 len_opener = STRLEN (opener);
1358 len_alt_opener = STRLEN (alt_opener);
1359 len_closer = STRLEN (closer);
1361 pass_character = in_comment = 0;
1363 nesting_level = 1;
1364 i = *sindex;
1366 while (nesting_level)
1368 c = string[i];
1370 /* If a recursive call or a call to ADVANCE_CHAR leaves the index beyond
1371 the end of the string, catch it and cut the loop. */
1372 if (i > slen)
1374 i = slen;
1375 c = string[i = slen];
1376 break;
1379 if (c == 0)
1380 break;
1382 if (in_comment)
1384 if (c == '\n')
1385 in_comment = 0;
1386 ADVANCE_CHAR (string, slen, i);
1387 continue;
1390 if (pass_character) /* previous char was backslash */
1392 pass_character = 0;
1393 ADVANCE_CHAR (string, slen, i);
1394 continue;
1397 /* Not exactly right yet; should handle shell metacharacters and
1398 multibyte characters, too. See COMMENT_BEGIN define in parse.y */
1399 if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
1401 in_comment = 1;
1402 ADVANCE_CHAR (string, slen, i);
1403 continue;
1406 if (c == CTLESC || c == '\\')
1408 pass_character++;
1409 i++;
1410 continue;
1413 /* Process a nested command substitution, but only if we're parsing an
1414 arithmetic substitution. */
1415 if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
1417 si = i + 2;
1418 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1419 CHECK_STRING_OVERRUN (i, si, slen, c);
1420 i = si + 1;
1421 continue;
1424 /* Process a nested OPENER. */
1425 if (STREQN (string + i, opener, len_opener))
1427 si = i + len_opener;
1428 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
1429 CHECK_STRING_OVERRUN (i, si, slen, c);
1430 i = si + 1;
1431 continue;
1434 /* Process a nested ALT_OPENER */
1435 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1437 si = i + len_alt_opener;
1438 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
1439 CHECK_STRING_OVERRUN (i, si, slen, c);
1440 i = si + 1;
1441 continue;
1444 /* If the current substring terminates the delimited string, decrement
1445 the nesting level. */
1446 if (STREQN (string + i, closer, len_closer))
1448 i += len_closer - 1; /* move to last byte of the closer */
1449 nesting_level--;
1450 if (nesting_level == 0)
1451 break;
1454 /* Pass old-style command substitution through verbatim. */
1455 if (c == '`')
1457 si = i + 1;
1458 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1459 CHECK_STRING_OVERRUN (i, si, slen, c);
1460 i = si + 1;
1461 continue;
1464 /* Pass single-quoted and double-quoted strings through verbatim. */
1465 if (c == '\'' || c == '"')
1467 si = i + 1;
1468 i = (c == '\'') ? skip_single_quoted (string, slen, si, 0)
1469 : skip_double_quoted (string, slen, si, 0);
1470 continue;
1473 /* move past this character, which was not special. */
1474 ADVANCE_CHAR (string, slen, i);
1477 if (c == 0 && nesting_level)
1479 if (no_longjmp_on_fatal_error == 0)
1481 last_command_exit_value = EXECUTION_FAILURE;
1482 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1483 exp_jump_to_top_level (DISCARD);
1485 else
1487 *sindex = i;
1488 return (char *)NULL;
1492 si = i - *sindex - len_closer + 1;
1493 if (flags & SX_NOALLOC)
1494 result = (char *)NULL;
1495 else
1497 result = (char *)xmalloc (1 + si);
1498 strncpy (result, string + *sindex, si);
1499 result[si] = '\0';
1501 *sindex = i;
1503 return (result);
1506 /* Extract a parameter expansion expression within ${ and } from STRING.
1507 Obey the Posix.2 rules for finding the ending `}': count braces while
1508 skipping over enclosed quoted strings and command substitutions.
1509 SINDEX is the address of an int describing the current offset in STRING;
1510 it should point to just after the first `{' found. On exit, SINDEX
1511 gets the position of the matching `}'. QUOTED is non-zero if this
1512 occurs inside double quotes. */
1513 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1514 static char *
1515 extract_dollar_brace_string (string, sindex, quoted, flags)
1516 char *string;
1517 int *sindex, quoted, flags;
1519 register int i, c;
1520 size_t slen;
1521 int pass_character, nesting_level, si, dolbrace_state;
1522 char *result, *t;
1523 DECLARE_MBSTATE;
1525 pass_character = 0;
1526 nesting_level = 1;
1527 slen = strlen (string + *sindex) + *sindex;
1529 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1530 parse_matched_pair(). The different initial value is to handle the
1531 case where this function is called to parse the word in
1532 ${param op word} (SX_WORD). */
1533 dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM;
1534 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP))
1535 dolbrace_state = DOLBRACE_QUOTE;
1537 i = *sindex;
1538 while (c = string[i])
1540 if (pass_character)
1542 pass_character = 0;
1543 ADVANCE_CHAR (string, slen, i);
1544 continue;
1547 /* CTLESCs and backslashes quote the next character. */
1548 if (c == CTLESC || c == '\\')
1550 pass_character++;
1551 i++;
1552 continue;
1555 if (string[i] == '$' && string[i+1] == LBRACE)
1557 nesting_level++;
1558 i += 2;
1559 continue;
1562 if (c == RBRACE)
1564 nesting_level--;
1565 if (nesting_level == 0)
1566 break;
1567 i++;
1568 continue;
1571 /* Pass the contents of old-style command substitutions through
1572 verbatim. */
1573 if (c == '`')
1575 si = i + 1;
1576 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1578 CHECK_STRING_OVERRUN (i, si, slen, c);
1580 i = si + 1;
1581 continue;
1584 /* Pass the contents of new-style command substitutions and
1585 arithmetic substitutions through verbatim. */
1586 if (string[i] == '$' && string[i+1] == LPAREN)
1588 si = i + 2;
1589 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1591 CHECK_STRING_OVERRUN (i, si, slen, c);
1593 i = si + 1;
1594 continue;
1597 #if defined (PROCESS_SUBSTITUTION)
1598 /* Technically this should only work at the start of a word */
1599 if ((string[i] == '<' || string[i] == '>') && string[i+1] == LPAREN)
1601 si = i + 2;
1602 t = extract_process_subst (string, (string[i] == '<' ? "<(" : ">)"), &si, flags|SX_NOALLOC);
1604 CHECK_STRING_OVERRUN (i, si, slen, c);
1606 i = si + 1;
1607 continue;
1609 #endif
1611 /* Pass the contents of double-quoted strings through verbatim. */
1612 if (c == '"')
1614 si = i + 1;
1615 i = skip_double_quoted (string, slen, si, 0);
1616 /* skip_XXX_quoted leaves index one past close quote */
1617 continue;
1620 if (c == '\'')
1622 /*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
1623 if (posixly_correct && shell_compatibility_level > 42 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
1624 ADVANCE_CHAR (string, slen, i);
1625 else
1627 si = i + 1;
1628 i = skip_single_quoted (string, slen, si, 0);
1631 continue;
1634 #if defined (ARRAY_VARS)
1635 if (c == LBRACK && dolbrace_state == DOLBRACE_PARAM)
1637 si = skipsubscript (string, i, 0);
1638 CHECK_STRING_OVERRUN (i, si, slen, c);
1639 if (string[si] == RBRACK)
1640 c = string[i = si];
1642 #endif
1644 /* move past this character, which was not special. */
1645 ADVANCE_CHAR (string, slen, i);
1647 /* This logic must agree with parse.y:parse_matched_pair, since they
1648 share the same defines. */
1649 if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 1)
1650 dolbrace_state = DOLBRACE_QUOTE;
1651 else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
1652 dolbrace_state = DOLBRACE_QUOTE;
1653 else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1)
1654 dolbrace_state = DOLBRACE_QUOTE2; /* XXX */
1655 else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1)
1656 dolbrace_state = DOLBRACE_QUOTE;
1657 else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1)
1658 dolbrace_state = DOLBRACE_QUOTE;
1659 /* This is intended to handle all of the [:]op expansions and the substring/
1660 length/pattern removal/pattern substitution expansions. */
1661 else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0)
1662 dolbrace_state = DOLBRACE_OP;
1663 else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0)
1664 dolbrace_state = DOLBRACE_WORD;
1667 if (c == 0 && nesting_level)
1669 if (no_longjmp_on_fatal_error == 0)
1670 { /* { */
1671 last_command_exit_value = EXECUTION_FAILURE;
1672 report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1673 exp_jump_to_top_level (DISCARD);
1675 else
1677 *sindex = i;
1678 return ((char *)NULL);
1682 result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1683 *sindex = i;
1685 return (result);
1688 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1689 STRING, and returns a pointer to it. */
1690 char *
1691 de_backslash (string)
1692 char *string;
1694 register size_t slen;
1695 register int i, j, prev_i;
1696 DECLARE_MBSTATE;
1698 slen = strlen (string);
1699 i = j = 0;
1701 /* Loop copying string[i] to string[j], i >= j. */
1702 while (i < slen)
1704 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1705 string[i + 1] == '$'))
1706 i++;
1707 prev_i = i;
1708 ADVANCE_CHAR (string, slen, i);
1709 if (j < prev_i)
1710 do string[j++] = string[prev_i++]; while (prev_i < i);
1711 else
1712 j = i;
1714 string[j] = '\0';
1716 return (string);
1719 #if 0
1720 /*UNUSED*/
1721 /* Replace instances of \! in a string with !. */
1722 void
1723 unquote_bang (string)
1724 char *string;
1726 register int i, j;
1727 register char *temp;
1729 temp = (char *)xmalloc (1 + strlen (string));
1731 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1733 if (string[i] == '\\' && string[i + 1] == '!')
1735 temp[j] = '!';
1736 i++;
1739 strcpy (string, temp);
1740 free (temp);
1742 #endif
1744 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = oldjmp; return (x); } while (0)
1746 /* This function assumes s[i] == open; returns with s[ret] == close; used to
1747 parse array subscripts. FLAGS & 1 means to not attempt to skip over
1748 matched pairs of quotes or backquotes, or skip word expansions; it is
1749 intended to be used after expansion has been performed and during final
1750 assignment parsing (see arrayfunc.c:assign_compound_array_list()) or
1751 during execution by a builtin which has already undergone word expansion. */
1752 static int
1753 skip_matched_pair (string, start, open, close, flags)
1754 const char *string;
1755 int start, open, close, flags;
1757 int i, pass_next, backq, si, c, count, oldjmp;
1758 size_t slen;
1759 char *temp, *ss;
1760 DECLARE_MBSTATE;
1762 slen = strlen (string + start) + start;
1763 oldjmp = no_longjmp_on_fatal_error;
1764 no_longjmp_on_fatal_error = 1;
1766 i = start + 1; /* skip over leading bracket */
1767 count = 1;
1768 pass_next = backq = 0;
1769 ss = (char *)string;
1770 while (c = string[i])
1772 if (pass_next)
1774 pass_next = 0;
1775 if (c == 0)
1776 CQ_RETURN(i);
1777 ADVANCE_CHAR (string, slen, i);
1778 continue;
1780 else if ((flags & 1) == 0 && c == '\\')
1782 pass_next = 1;
1783 i++;
1784 continue;
1786 else if (backq)
1788 if (c == '`')
1789 backq = 0;
1790 ADVANCE_CHAR (string, slen, i);
1791 continue;
1793 else if ((flags & 1) == 0 && c == '`')
1795 backq = 1;
1796 i++;
1797 continue;
1799 else if ((flags & 1) == 0 && c == open)
1801 count++;
1802 i++;
1803 continue;
1805 else if (c == close)
1807 count--;
1808 if (count == 0)
1809 break;
1810 i++;
1811 continue;
1813 else if ((flags & 1) == 0 && (c == '\'' || c == '"'))
1815 i = (c == '\'') ? skip_single_quoted (ss, slen, ++i, 0)
1816 : skip_double_quoted (ss, slen, ++i, 0);
1817 /* no increment, the skip functions increment past the closing quote. */
1819 else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1821 si = i + 2;
1822 if (string[si] == '\0')
1823 CQ_RETURN(si);
1825 /* XXX - extract_command_subst here? */
1826 if (string[i+1] == LPAREN)
1827 temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1828 else
1829 temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
1831 CHECK_STRING_OVERRUN (i, si, slen, c);
1833 i = si;
1834 if (string[i] == '\0') /* don't increment i past EOS in loop */
1835 break;
1836 i++;
1837 continue;
1839 else
1840 ADVANCE_CHAR (string, slen, i);
1843 CQ_RETURN(i);
1846 #if defined (ARRAY_VARS)
1847 /* Flags has 1 as a reserved value, since skip_matched_pair uses it for
1848 skipping over quoted strings and taking the first instance of the
1849 closing character. */
1851 skipsubscript (string, start, flags)
1852 const char *string;
1853 int start, flags;
1855 return (skip_matched_pair (string, start, '[', ']', flags));
1857 #endif
1859 /* Skip characters in STRING until we find a character in DELIMS, and return
1860 the index of that character. START is the index into string at which we
1861 begin. This is similar in spirit to strpbrk, but it returns an index into
1862 STRING and takes a starting index. This little piece of code knows quite
1863 a lot of shell syntax. It's very similar to skip_double_quoted and other
1864 functions of that ilk. */
1866 skip_to_delim (string, start, delims, flags)
1867 char *string;
1868 int start;
1869 char *delims;
1870 int flags;
1872 int i, pass_next, backq, dquote, si, c, oldjmp;
1873 int invert, skipquote, skipcmd, noprocsub, completeflag;
1874 int arithexp, skipcol;
1875 size_t slen;
1876 char *temp, open[3];
1877 DECLARE_MBSTATE;
1879 slen = strlen (string + start) + start;
1880 oldjmp = no_longjmp_on_fatal_error;
1881 if (flags & SD_NOJMP)
1882 no_longjmp_on_fatal_error = 1;
1883 invert = (flags & SD_INVERT);
1884 skipcmd = (flags & SD_NOSKIPCMD) == 0;
1885 noprocsub = (flags & SD_NOPROCSUB);
1886 completeflag = (flags & SD_COMPLETE) ? SX_COMPLETE : 0;
1888 arithexp = (flags & SD_ARITHEXP);
1889 skipcol = 0;
1891 i = start;
1892 pass_next = backq = dquote = 0;
1893 while (c = string[i])
1895 /* If this is non-zero, we should not let quote characters be delimiters
1896 and the current character is a single or double quote. We should not
1897 test whether or not it's a delimiter until after we skip single- or
1898 double-quoted strings. */
1899 skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"'));
1900 if (pass_next)
1902 pass_next = 0;
1903 if (c == 0)
1904 CQ_RETURN(i);
1905 ADVANCE_CHAR (string, slen, i);
1906 continue;
1908 else if (c == '\\')
1910 pass_next = 1;
1911 i++;
1912 continue;
1914 else if (backq)
1916 if (c == '`')
1917 backq = 0;
1918 ADVANCE_CHAR (string, slen, i);
1919 continue;
1921 else if (c == '`')
1923 backq = 1;
1924 i++;
1925 continue;
1927 else if (arithexp && skipcol && c == ':')
1929 skipcol--;
1930 i++;
1931 continue;
1933 else if (arithexp && c == '?')
1935 skipcol++;
1936 i++;
1937 continue;
1939 else if (skipquote == 0 && invert == 0 && member (c, delims))
1940 break;
1941 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
1942 quoted strings when looking for the history expansion character as a
1943 delimiter. */
1944 /* special case for programmable completion which takes place before
1945 parser converts backslash-escaped single quotes between $'...' to
1946 `regular' single-quoted strings. */
1947 else if (completeflag && i > 0 && string[i-1] == '$' && c == '\'')
1948 i = skip_single_quoted (string, slen, ++i, SX_COMPLETE);
1949 else if (c == '\'')
1950 i = skip_single_quoted (string, slen, ++i, 0);
1951 else if (c == '"')
1952 i = skip_double_quoted (string, slen, ++i, completeflag);
1953 else if (c == LPAREN && arithexp)
1955 si = i + 1;
1956 if (string[si] == '\0')
1957 CQ_RETURN(si);
1959 temp = extract_delimited_string (string, &si, "(", "(", ")", SX_NOALLOC); /* ) */
1960 i = si;
1961 if (string[i] == '\0') /* don't increment i past EOS in loop */
1962 break;
1963 i++;
1964 continue;
1966 else if (c == '$' && ((skipcmd && string[i+1] == LPAREN) || string[i+1] == LBRACE))
1968 si = i + 2;
1969 if (string[si] == '\0')
1970 CQ_RETURN(si);
1972 if (string[i+1] == LPAREN)
1973 temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1974 else
1975 temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
1976 CHECK_STRING_OVERRUN (i, si, slen, c);
1977 i = si;
1978 if (string[i] == '\0') /* don't increment i past EOS in loop */
1979 break;
1980 i++;
1981 continue;
1983 #if defined (PROCESS_SUBSTITUTION)
1984 else if (skipcmd && noprocsub == 0 && (c == '<' || c == '>') && string[i+1] == LPAREN)
1986 si = i + 2;
1987 if (string[si] == '\0')
1988 CQ_RETURN(si);
1990 temp = extract_delimited_string (string, &si, (c == '<') ? "<(" : ">(", "(", ")", SX_COMMAND|SX_NOALLOC); /* )) */
1991 CHECK_STRING_OVERRUN (i, si, slen, c);
1992 i = si;
1993 if (string[i] == '\0')
1994 break;
1995 i++;
1996 continue;
1998 #endif /* PROCESS_SUBSTITUTION */
1999 #if defined (EXTENDED_GLOB)
2000 else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@"))
2002 si = i + 2;
2003 if (string[si] == '\0')
2004 CQ_RETURN(si);
2006 open[0] = c;
2007 open[1] = LPAREN;
2008 open[2] = '\0';
2009 temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */
2011 CHECK_STRING_OVERRUN (i, si, slen, c);
2012 i = si;
2013 if (string[i] == '\0') /* don't increment i past EOS in loop */
2014 break;
2015 i++;
2016 continue;
2018 #endif
2019 else if ((flags & SD_GLOB) && c == LBRACK)
2021 si = i + 1;
2022 if (string[si] == '\0')
2023 CQ_RETURN(si);
2025 temp = extract_delimited_string (string, &si, "[", "[", "]", SX_NOALLOC); /* ] */
2027 i = si;
2028 if (string[i] == '\0') /* don't increment i past EOS in loop */
2029 break;
2030 i++;
2031 continue;
2033 else if ((skipquote || invert) && (member (c, delims) == 0))
2034 break;
2035 else
2036 ADVANCE_CHAR (string, slen, i);
2039 CQ_RETURN(i);
2042 #if defined (BANG_HISTORY)
2043 /* Skip to the history expansion character (delims[0]), paying attention to
2044 quoted strings and command and process substitution. This is a stripped-
2045 down version of skip_to_delims. The essential difference is that this
2046 resets the quoting state when starting a command substitution */
2048 skip_to_histexp (string, start, delims, flags)
2049 char *string;
2050 int start;
2051 char *delims;
2052 int flags;
2054 int i, pass_next, backq, dquote, c, oldjmp;
2055 int histexp_comsub, histexp_backq, old_dquote;
2056 size_t slen;
2057 DECLARE_MBSTATE;
2059 slen = strlen (string + start) + start;
2060 oldjmp = no_longjmp_on_fatal_error;
2061 if (flags & SD_NOJMP)
2062 no_longjmp_on_fatal_error = 1;
2064 histexp_comsub = histexp_backq = old_dquote = 0;
2066 i = start;
2067 pass_next = backq = dquote = 0;
2068 while (c = string[i])
2070 if (pass_next)
2072 pass_next = 0;
2073 if (c == 0)
2074 CQ_RETURN(i);
2075 ADVANCE_CHAR (string, slen, i);
2076 continue;
2078 else if (c == '\\')
2080 pass_next = 1;
2081 i++;
2082 continue;
2084 else if (backq && c == '`')
2086 backq = 0;
2087 histexp_backq--;
2088 dquote = old_dquote;
2089 i++;
2090 continue;
2092 else if (c == '`')
2094 backq = 1;
2095 histexp_backq++;
2096 old_dquote = dquote; /* simple - one level for now */
2097 dquote = 0;
2098 i++;
2099 continue;
2101 /* When in double quotes, act as if the double quote is a member of
2102 history_no_expand_chars, like the history library does */
2103 else if (dquote && c == delims[0] && string[i+1] == '"')
2105 i++;
2106 continue;
2108 else if (c == delims[0])
2109 break;
2110 /* the usual case is to use skip_xxx_quoted, but we don't skip over double
2111 quoted strings when looking for the history expansion character as a
2112 delimiter. */
2113 else if (dquote && c == '\'')
2115 i++;
2116 continue;
2118 else if (c == '\'')
2119 i = skip_single_quoted (string, slen, ++i, 0);
2120 /* The posixly_correct test makes posix-mode shells allow double quotes
2121 to quote the history expansion character */
2122 else if (posixly_correct == 0 && c == '"')
2124 dquote = 1 - dquote;
2125 i++;
2126 continue;
2128 else if (c == '"')
2129 i = skip_double_quoted (string, slen, ++i, 0);
2130 #if defined (PROCESS_SUBSTITUTION)
2131 else if ((c == '$' || c == '<' || c == '>') && string[i+1] == LPAREN && string[i+2] != LPAREN)
2132 #else
2133 else if (c == '$' && string[i+1] == LPAREN && string[i+2] != LPAREN)
2134 #endif
2136 if (string[i+2] == '\0')
2137 CQ_RETURN(i+2);
2138 i += 2;
2139 histexp_comsub++;
2140 old_dquote = dquote;
2141 dquote = 0;
2143 else if (histexp_comsub && c == RPAREN)
2145 histexp_comsub--;
2146 dquote = old_dquote;
2147 i++;
2148 continue;
2150 else if (backq) /* placeholder */
2152 ADVANCE_CHAR (string, slen, i);
2153 continue;
2155 else
2156 ADVANCE_CHAR (string, slen, i);
2159 CQ_RETURN(i);
2161 #endif /* BANG_HISTORY */
2163 #if defined (READLINE)
2164 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
2165 an unclosed quoted string), or if the character at EINDEX is quoted
2166 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
2167 single and double-quoted string parsing functions should not return an
2168 error if there are unclosed quotes or braces. The characters that this
2169 recognizes need to be the same as the contents of
2170 rl_completer_quote_characters. */
2173 char_is_quoted (string, eindex)
2174 char *string;
2175 int eindex;
2177 int i, pass_next, c, oldjmp;
2178 size_t slen;
2179 DECLARE_MBSTATE;
2181 slen = strlen (string);
2182 oldjmp = no_longjmp_on_fatal_error;
2183 no_longjmp_on_fatal_error = 1;
2184 i = pass_next = 0;
2185 while (i <= eindex)
2187 c = string[i];
2189 if (pass_next)
2191 pass_next = 0;
2192 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
2193 CQ_RETURN(1);
2194 ADVANCE_CHAR (string, slen, i);
2195 continue;
2197 else if (c == '\\')
2199 pass_next = 1;
2200 i++;
2201 continue;
2203 else if (c == '$' && string[i+1] == '\'' && string[i+2])
2205 i += 2;
2206 i = skip_single_quoted (string, slen, i, SX_COMPLETE);
2207 if (i > eindex)
2208 CQ_RETURN (i);
2210 else if (c == '\'' || c == '"')
2212 i = (c == '\'') ? skip_single_quoted (string, slen, ++i, 0)
2213 : skip_double_quoted (string, slen, ++i, SX_COMPLETE);
2214 if (i > eindex)
2215 CQ_RETURN(1);
2216 /* no increment, the skip_xxx functions go one past end */
2218 else
2219 ADVANCE_CHAR (string, slen, i);
2222 CQ_RETURN(0);
2226 unclosed_pair (string, eindex, openstr)
2227 char *string;
2228 int eindex;
2229 char *openstr;
2231 int i, pass_next, openc, olen;
2232 size_t slen;
2233 DECLARE_MBSTATE;
2235 slen = strlen (string);
2236 olen = strlen (openstr);
2237 i = pass_next = openc = 0;
2238 while (i <= eindex)
2240 if (pass_next)
2242 pass_next = 0;
2243 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
2244 return 0;
2245 ADVANCE_CHAR (string, slen, i);
2246 continue;
2248 else if (string[i] == '\\')
2250 pass_next = 1;
2251 i++;
2252 continue;
2254 else if (STREQN (string + i, openstr, olen))
2256 openc = 1 - openc;
2257 i += olen;
2259 /* XXX - may want to handle $'...' specially here */
2260 else if (string[i] == '\'' || string[i] == '"')
2262 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i, 0)
2263 : skip_double_quoted (string, slen, i, SX_COMPLETE);
2264 if (i > eindex)
2265 return 0;
2267 else
2268 ADVANCE_CHAR (string, slen, i);
2270 return (openc);
2273 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
2274 individual words. If DELIMS is NULL, the current value of $IFS is used
2275 to split the string, and the function follows the shell field splitting
2276 rules. SENTINEL is an index to look for. NWP, if non-NULL,
2277 gets the number of words in the returned list. CWP, if non-NULL, gets
2278 the index of the word containing SENTINEL. Non-whitespace chars in
2279 DELIMS delimit separate fields. This is used by programmable completion. */
2280 WORD_LIST *
2281 split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp)
2282 char *string;
2283 int slen;
2284 char *delims;
2285 int sentinel, flags;
2286 int *nwp, *cwp;
2288 int ts, te, i, nw, cw, ifs_split, dflags;
2289 char *token, *d, *d2;
2290 WORD_LIST *ret, *tl;
2292 if (string == 0 || *string == '\0')
2294 if (nwp)
2295 *nwp = 0;
2296 if (cwp)
2297 *cwp = 0;
2298 return ((WORD_LIST *)NULL);
2301 d = (delims == 0) ? ifs_value : delims;
2302 ifs_split = delims == 0;
2304 /* Make d2 the non-whitespace characters in delims */
2305 d2 = 0;
2306 if (delims)
2308 size_t slength;
2309 #if defined (HANDLE_MULTIBYTE)
2310 size_t mblength = 1;
2311 #endif
2312 DECLARE_MBSTATE;
2314 slength = strlen (delims);
2315 d2 = (char *)xmalloc (slength + 1);
2316 i = ts = 0;
2317 while (delims[i])
2319 #if defined (HANDLE_MULTIBYTE)
2320 mbstate_t state_bak;
2321 state_bak = state;
2322 mblength = MBRLEN (delims + i, slength, &state);
2323 if (MB_INVALIDCH (mblength))
2324 state = state_bak;
2325 else if (mblength > 1)
2327 memcpy (d2 + ts, delims + i, mblength);
2328 ts += mblength;
2329 i += mblength;
2330 slength -= mblength;
2331 continue;
2333 #endif
2334 if (whitespace (delims[i]) == 0)
2335 d2[ts++] = delims[i];
2337 i++;
2338 slength--;
2340 d2[ts] = '\0';
2343 ret = (WORD_LIST *)NULL;
2345 /* Remove sequences of whitespace characters at the start of the string, as
2346 long as those characters are delimiters. */
2347 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
2349 if (string[i] == '\0')
2351 FREE (d2);
2352 return (ret);
2355 ts = i;
2356 nw = 0;
2357 cw = -1;
2358 dflags = flags|SD_NOJMP;
2359 while (1)
2361 te = skip_to_delim (string, ts, d, dflags);
2363 /* If we have a non-whitespace delimiter character, use it to make a
2364 separate field. This is just about what $IFS splitting does and
2365 is closer to the behavior of the shell parser. */
2366 if (ts == te && d2 && member (string[ts], d2))
2368 te = ts + 1;
2369 /* If we're using IFS splitting, the non-whitespace delimiter char
2370 and any additional IFS whitespace delimits a field. */
2371 if (ifs_split)
2372 while (member (string[te], d) && spctabnl (string[te]) && ((flags&SD_NOQUOTEDELIM) == 0 || (string[te] != '\'' && string[te] != '"')))
2373 te++;
2374 else
2375 while (member (string[te], d2) && ((flags&SD_NOQUOTEDELIM) == 0 || (string[te] != '\'' && string[te] != '"')))
2376 te++;
2379 token = substring (string, ts, te);
2381 ret = add_string_to_list (token, ret); /* XXX */
2382 free (token);
2383 nw++;
2385 if (sentinel >= ts && sentinel <= te)
2386 cw = nw;
2388 /* If the cursor is at whitespace just before word start, set the
2389 sentinel word to the current word. */
2390 if (cwp && cw == -1 && sentinel == ts-1)
2391 cw = nw;
2393 /* If the cursor is at whitespace between two words, make a new, empty
2394 word, add it before (well, after, since the list is in reverse order)
2395 the word we just added, and set the current word to that one. */
2396 if (cwp && cw == -1 && sentinel < ts)
2398 tl = make_word_list (make_word (""), ret->next);
2399 ret->next = tl;
2400 cw = nw;
2401 nw++;
2404 if (string[te] == 0)
2405 break;
2407 i = te;
2408 /* XXX - honor SD_NOQUOTEDELIM here */
2409 while (member (string[i], d) && (ifs_split || spctabnl(string[i])) && ((flags&SD_NOQUOTEDELIM) == 0 || (string[te] != '\'' && string[te] != '"')))
2410 i++;
2412 if (string[i])
2413 ts = i;
2414 else
2415 break;
2418 /* Special case for SENTINEL at the end of STRING. If we haven't found
2419 the word containing SENTINEL yet, and the index we're looking for is at
2420 the end of STRING (or past the end of the previously-found token,
2421 possible if the end of the line is composed solely of IFS whitespace)
2422 add an additional null argument and set the current word pointer to that. */
2423 if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te))
2425 if (whitespace (string[sentinel - 1]))
2427 token = "";
2428 ret = add_string_to_list (token, ret);
2429 nw++;
2431 cw = nw;
2434 if (nwp)
2435 *nwp = nw;
2436 if (cwp)
2437 *cwp = cw;
2439 FREE (d2);
2441 return (REVERSE_LIST (ret, WORD_LIST *));
2443 #endif /* READLINE */
2445 #if 0
2446 /* UNUSED */
2447 /* Extract the name of the variable to bind to from the assignment string. */
2448 char *
2449 assignment_name (string)
2450 char *string;
2452 int offset;
2453 char *temp;
2455 offset = assignment (string, 0);
2456 if (offset == 0)
2457 return (char *)NULL;
2458 temp = substring (string, 0, offset);
2459 return (temp);
2461 #endif
2463 /* **************************************************************** */
2464 /* */
2465 /* Functions to convert strings to WORD_LISTs and vice versa */
2466 /* */
2467 /* **************************************************************** */
2469 /* Return a single string of all the words in LIST. SEP is the separator
2470 to put between individual elements of LIST in the output string. */
2471 char *
2472 string_list_internal (list, sep)
2473 WORD_LIST *list;
2474 char *sep;
2476 register WORD_LIST *t;
2477 char *result, *r;
2478 size_t word_len, sep_len, result_size;
2480 if (list == 0)
2481 return ((char *)NULL);
2483 /* Short-circuit quickly if we don't need to separate anything. */
2484 if (list->next == 0)
2485 return (savestring (list->word->word));
2487 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
2488 sep_len = STRLEN (sep);
2489 result_size = 0;
2491 for (t = list; t; t = t->next)
2493 if (t != list)
2494 result_size += sep_len;
2495 result_size += strlen (t->word->word);
2498 r = result = (char *)xmalloc (result_size + 1);
2500 for (t = list; t; t = t->next)
2502 if (t != list && sep_len)
2504 if (sep_len > 1)
2506 FASTCOPY (sep, r, sep_len);
2507 r += sep_len;
2509 else
2510 *r++ = sep[0];
2513 word_len = strlen (t->word->word);
2514 FASTCOPY (t->word->word, r, word_len);
2515 r += word_len;
2518 *r = '\0';
2519 return (result);
2522 /* Return a single string of all the words present in LIST, separating
2523 each word with a space. */
2524 char *
2525 string_list (list)
2526 WORD_LIST *list;
2528 return (string_list_internal (list, " "));
2531 /* An external interface that can be used by the rest of the shell to
2532 obtain a string containing the first character in $IFS. Handles all
2533 the multibyte complications. If LENP is non-null, it is set to the
2534 length of the returned string. */
2535 char *
2536 ifs_firstchar (lenp)
2537 int *lenp;
2539 char *ret;
2540 int len;
2542 ret = xmalloc (MB_LEN_MAX + 1);
2543 #if defined (HANDLE_MULTIBYTE)
2544 if (ifs_firstc_len == 1)
2546 ret[0] = ifs_firstc[0];
2547 ret[1] = '\0';
2548 len = ret[0] ? 1 : 0;
2550 else
2552 memcpy (ret, ifs_firstc, ifs_firstc_len);
2553 ret[len = ifs_firstc_len] = '\0';
2555 #else
2556 ret[0] = ifs_firstc;
2557 ret[1] = '\0';
2558 len = ret[0] ? 0 : 1;
2559 #endif
2561 if (lenp)
2562 *lenp = len;
2564 return ret;
2567 /* Return a single string of all the words present in LIST, obeying the
2568 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
2569 expansion [of $*] appears within a double quoted string, it expands
2570 to a single field with the value of each parameter separated by the
2571 first character of the IFS variable, or by a <space> if IFS is unset." */
2572 /* Posix interpretation 888 changes this when IFS is null by specifying
2573 that when unquoted, this expands to separate arguments */
2574 char *
2575 string_list_dollar_star (list, quoted, flags)
2576 WORD_LIST *list;
2577 int quoted, flags;
2579 char *ret;
2580 #if defined (HANDLE_MULTIBYTE)
2581 # if defined (__GNUC__)
2582 char sep[MB_CUR_MAX + 1];
2583 # else
2584 char *sep = 0;
2585 # endif
2586 #else
2587 char sep[2];
2588 #endif
2590 #if defined (HANDLE_MULTIBYTE)
2591 # if !defined (__GNUC__)
2592 sep = (char *)xmalloc (MB_CUR_MAX + 1);
2593 # endif /* !__GNUC__ */
2594 if (ifs_firstc_len == 1)
2596 sep[0] = ifs_firstc[0];
2597 sep[1] = '\0';
2599 else
2601 memcpy (sep, ifs_firstc, ifs_firstc_len);
2602 sep[ifs_firstc_len] = '\0';
2604 #else
2605 sep[0] = ifs_firstc;
2606 sep[1] = '\0';
2607 #endif
2609 ret = string_list_internal (list, sep);
2610 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2611 free (sep);
2612 #endif
2613 return ret;
2616 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2617 is non-zero, the $@ appears within double quotes, and we should quote
2618 the list before converting it into a string. If IFS is unset, and the
2619 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2620 in the words in the list, because the default value of $IFS is
2621 <space><tab><newline>, IFS characters in the words in the list should
2622 also be split. If IFS is null, and the word is not quoted, we need
2623 to quote the words in the list to preserve the positional parameters
2624 exactly.
2625 Valid values for the FLAGS argument are the PF_ flags in command.h,
2626 the only one we care about is PF_ASSIGNRHS. $@ is supposed to expand
2627 to the positional parameters separated by spaces no matter what IFS is
2628 set to if in a context where word splitting is not performed. The only
2629 one that we didn't handle before is assignment statement arguments to
2630 declaration builtins like `declare'. */
2631 char *
2632 string_list_dollar_at (list, quoted, flags)
2633 WORD_LIST *list;
2634 int quoted;
2635 int flags;
2637 char *ifs, *ret;
2638 #if defined (HANDLE_MULTIBYTE)
2639 # if defined (__GNUC__)
2640 char sep[MB_CUR_MAX + 1];
2641 # else
2642 char *sep = 0;
2643 # endif /* !__GNUC__ */
2644 #else
2645 char sep[2];
2646 #endif
2647 WORD_LIST *tlist;
2649 /* XXX this could just be ifs = ifs_value; */
2650 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
2652 #if defined (HANDLE_MULTIBYTE)
2653 # if !defined (__GNUC__)
2654 sep = (char *)xmalloc (MB_CUR_MAX + 1);
2655 # endif /* !__GNUC__ */
2656 /* XXX - testing PF_ASSIGNRHS to make sure positional parameters are
2657 separated with a space even when word splitting will not occur. */
2658 if (flags & PF_ASSIGNRHS)
2660 sep[0] = ' ';
2661 sep[1] = '\0';
2663 else if (ifs && *ifs)
2665 if (ifs_firstc_len == 1)
2667 sep[0] = ifs_firstc[0];
2668 sep[1] = '\0';
2670 else
2672 memcpy (sep, ifs_firstc, ifs_firstc_len);
2673 sep[ifs_firstc_len] = '\0';
2676 else
2678 sep[0] = ' ';
2679 sep[1] = '\0';
2681 #else /* !HANDLE_MULTIBYTE */
2682 /* XXX - PF_ASSIGNRHS means no word splitting, so we want positional
2683 parameters separated by a space. */
2684 sep[0] = ((flags & PF_ASSIGNRHS) || ifs == 0 || *ifs == 0) ? ' ' : *ifs;
2685 sep[1] = '\0';
2686 #endif /* !HANDLE_MULTIBYTE */
2688 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
2689 it now that quote_escapes quotes spaces */
2690 tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
2691 ? quote_list (list)
2692 : list_quote_escapes (list);
2694 ret = string_list_internal (tlist, sep);
2695 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2696 free (sep);
2697 #endif
2698 return ret;
2701 /* Turn the positional parameters into a string, understanding quoting and
2702 the various subtleties of using the first character of $IFS as the
2703 separator. Calls string_list_dollar_at, string_list_dollar_star, and
2704 string_list as appropriate. */
2705 /* This needs to fully understand the additional contexts where word
2706 splitting does not occur (W_ASSIGNRHS, etc.) */
2707 char *
2708 string_list_pos_params (pchar, list, quoted, pflags)
2709 int pchar;
2710 WORD_LIST *list;
2711 int quoted, pflags;
2713 char *ret;
2714 WORD_LIST *tlist;
2716 if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
2718 tlist = quote_list (list);
2719 word_list_remove_quoted_nulls (tlist);
2720 ret = string_list_dollar_star (tlist, 0, 0);
2722 else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
2724 tlist = quote_list (list);
2725 word_list_remove_quoted_nulls (tlist);
2726 ret = string_list (tlist);
2728 else if (pchar == '*' && quoted == 0 && ifs_is_null) /* XXX */
2729 ret = expand_no_split_dollar_star ? string_list_dollar_star (list, quoted, 0) : string_list_dollar_at (list, quoted, 0); /* Posix interp 888 */
2730 else if (pchar == '*' && quoted == 0 && (pflags & PF_ASSIGNRHS)) /* XXX */
2731 ret = expand_no_split_dollar_star ? string_list_dollar_star (list, quoted, 0) : string_list_dollar_at (list, quoted, 0); /* Posix interp 888 */
2732 else if (pchar == '*')
2734 /* Even when unquoted, string_list_dollar_star does the right thing
2735 making sure that the first character of $IFS is used as the
2736 separator. */
2737 ret = string_list_dollar_star (list, quoted, 0);
2739 else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
2740 /* We use string_list_dollar_at, but only if the string is quoted, since
2741 that quotes the escapes if it's not, which we don't want. We could
2742 use string_list (the old code did), but that doesn't do the right
2743 thing if the first character of $IFS is not a space. We use
2744 string_list_dollar_star if the string is unquoted so we make sure that
2745 the elements of $@ are separated by the first character of $IFS for
2746 later splitting. */
2747 ret = string_list_dollar_at (list, quoted, 0);
2748 else if (pchar == '@' && quoted == 0 && ifs_is_null) /* XXX */
2749 ret = string_list_dollar_at (list, quoted, 0); /* Posix interp 888 */
2750 else if (pchar == '@' && quoted == 0 && (pflags & PF_ASSIGNRHS))
2751 ret = string_list_dollar_at (list, quoted, pflags); /* Posix interp 888 */
2752 else if (pchar == '@')
2753 ret = string_list_dollar_star (list, quoted, 0);
2754 else
2755 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
2757 return ret;
2760 /* Return the list of words present in STRING. Separate the string into
2761 words at any of the characters found in SEPARATORS. If QUOTED is
2762 non-zero then word in the list will have its quoted flag set, otherwise
2763 the quoted flag is left as make_word () deemed fit.
2765 This obeys the P1003.2 word splitting semantics. If `separators' is
2766 exactly <space><tab><newline>, then the splitting algorithm is that of
2767 the Bourne shell, which treats any sequence of characters from `separators'
2768 as a delimiter. If IFS is unset, which results in `separators' being set
2769 to "", no splitting occurs. If separators has some other value, the
2770 following rules are applied (`IFS white space' means zero or more
2771 occurrences of <space>, <tab>, or <newline>, as long as those characters
2772 are in `separators'):
2774 1) IFS white space is ignored at the start and the end of the
2775 string.
2776 2) Each occurrence of a character in `separators' that is not
2777 IFS white space, along with any adjacent occurrences of
2778 IFS white space delimits a field.
2779 3) Any nonzero-length sequence of IFS white space delimits a field.
2782 /* BEWARE! list_string strips null arguments. Don't call it twice and
2783 expect to have "" preserved! */
2785 /* This performs word splitting and quoted null character removal on
2786 STRING. */
2787 #define issep(c) \
2788 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2789 : (c) == (separators)[0]) \
2790 : 0)
2792 /* member of the space character class in the current locale */
2793 #define ifs_whitespace(c) ISSPACE(c)
2795 /* "adjacent IFS white space" */
2796 #define ifs_whitesep(c) ((sh_style_split || separators == 0) ? spctabnl (c) \
2797 : ifs_whitespace (c))
2799 WORD_LIST *
2800 list_string (string, separators, quoted)
2801 register char *string, *separators;
2802 int quoted;
2804 WORD_LIST *result;
2805 WORD_DESC *t;
2806 char *current_word, *s;
2807 int sindex, sh_style_split, whitesep, xflags, free_word;
2808 size_t slen;
2810 if (!string || !*string)
2811 return ((WORD_LIST *)NULL);
2813 sh_style_split = separators && separators[0] == ' ' &&
2814 separators[1] == '\t' &&
2815 separators[2] == '\n' &&
2816 separators[3] == '\0';
2817 for (xflags = 0, s = ifs_value; s && *s; s++)
2819 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2820 else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2823 slen = 0;
2824 /* Remove sequences of whitespace at the beginning of STRING, as
2825 long as those characters appear in IFS. Do not do this if
2826 STRING is quoted or if there are no separator characters. We use the
2827 Posix definition of whitespace as a member of the space character
2828 class in the current locale. */
2829 #if 0
2830 if (!quoted || !separators || !*separators)
2831 #else
2832 /* issep() requires that separators be non-null, and always returns 0 if
2833 separator is the empty string, so don't bother if we get an empty string
2834 for separators. We already returned NULL above if STRING is empty. */
2835 if (!quoted && separators && *separators)
2836 #endif
2838 for (s = string; *s && issep (*s) && ifs_whitespace (*s); s++);
2840 if (!*s)
2841 return ((WORD_LIST *)NULL);
2843 string = s;
2846 /* OK, now STRING points to a word that does not begin with white space.
2847 The splitting algorithm is:
2848 extract a word, stopping at a separator
2849 skip sequences of whitespace characters as long as they are separators
2850 This obeys the field splitting rules in Posix.2. */
2851 slen = STRLEN (string);
2852 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
2854 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
2855 possible, but need it in string_extract_verbatim for bounds checking */
2856 current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
2857 if (current_word == 0)
2858 break;
2860 free_word = 1; /* If non-zero, we free current_word */
2862 /* If we have a quoted empty string, add a quoted null argument. We
2863 want to preserve the quoted null character iff this is a quoted
2864 empty string; otherwise the quoted null characters are removed
2865 below. */
2866 if (QUOTED_NULL (current_word))
2868 t = alloc_word_desc ();
2869 t->word = make_quoted_char ('\0');
2870 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2871 result = make_word_list (t, result);
2873 else if (current_word[0] != '\0')
2875 /* If we have something, then add it regardless. However,
2876 perform quoted null character removal on the current word. */
2877 remove_quoted_nulls (current_word);
2879 /* We don't want to set the word flags based on the string contents
2880 here -- that's mostly for the parser -- so we just allocate a
2881 WORD_DESC *, assign current_word (noting that we don't want to
2882 free it), and skip all of make_word. */
2883 t = alloc_word_desc ();
2884 t->word = current_word;
2885 result = make_word_list (t, result);
2886 free_word = 0;
2887 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
2888 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2889 result->word->flags |= W_QUOTED;
2890 /* If removing quoted null characters leaves an empty word, note
2891 that we saw this for the caller to act on. */
2892 if (current_word == 0 || current_word[0] == '\0')
2893 result->word->flags |= W_SAWQUOTEDNULL;
2896 /* If we're not doing sequences of separators in the traditional
2897 Bourne shell style, then add a quoted null argument. */
2898 else if (!sh_style_split && !ifs_whitespace (string[sindex]))
2900 t = alloc_word_desc ();
2901 t->word = make_quoted_char ('\0');
2902 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2903 result = make_word_list (t, result);
2906 if (free_word)
2907 free (current_word);
2909 /* Note whether or not the separator is IFS whitespace, used later. */
2910 whitesep = string[sindex] && ifs_whitesep (string[sindex]);
2912 /* Move past the current separator character. */
2913 if (string[sindex])
2915 DECLARE_MBSTATE;
2916 ADVANCE_CHAR (string, slen, sindex);
2919 /* Now skip sequences of whitespace characters if they are
2920 in the list of separators. */
2921 while (string[sindex] && ifs_whitesep (string[sindex]) && issep (string[sindex]))
2922 sindex++;
2924 /* If the first separator was IFS whitespace and the current character
2925 is a non-whitespace IFS character, it should be part of the current
2926 field delimiter, not a separate delimiter that would result in an
2927 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2928 if (string[sindex] && whitesep && issep (string[sindex]) && !ifs_whitesep (string[sindex]))
2930 sindex++;
2931 /* An IFS character that is not IFS white space, along with any
2932 adjacent IFS white space, shall delimit a field. (SUSv3) */
2933 while (string[sindex] && ifs_whitesep (string[sindex]) && isifs (string[sindex]))
2934 sindex++;
2937 return (REVERSE_LIST (result, WORD_LIST *));
2940 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2941 ENDPTR is set to the first character after the word. This is used by
2942 the `read' builtin.
2944 This is never called with SEPARATORS != $IFS, and takes advantage of that.
2946 XXX - this function is very similar to list_string; they should be
2947 combined - XXX */
2949 /* character is in $IFS */
2950 #define islocalsep(c) (local_cmap[(unsigned char)(c)] != 0)
2952 char *
2953 get_word_from_string (stringp, separators, endptr)
2954 char **stringp, *separators, **endptr;
2956 register char *s;
2957 char *current_word;
2958 int sindex, sh_style_split, whitesep, xflags;
2959 unsigned char local_cmap[UCHAR_MAX+1]; /* really only need single-byte chars here */
2960 size_t slen;
2962 if (!stringp || !*stringp || !**stringp)
2963 return ((char *)NULL);
2965 sh_style_split = separators && separators[0] == ' ' &&
2966 separators[1] == '\t' &&
2967 separators[2] == '\n' &&
2968 separators[3] == '\0';
2969 memset (local_cmap, '\0', sizeof (local_cmap));
2970 for (xflags = 0, s = separators; s && *s; s++)
2972 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2973 if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2974 local_cmap[(unsigned char)*s] = 1; /* local charmap of separators */
2977 s = *stringp;
2978 slen = 0;
2980 /* Remove sequences of whitespace at the beginning of STRING, as
2981 long as those characters appear in SEPARATORS. This happens if
2982 SEPARATORS == $' \t\n' or if IFS is unset. */
2983 if (sh_style_split || separators == 0)
2984 for (; *s && spctabnl (*s) && islocalsep (*s); s++);
2985 else
2986 for (; *s && ifs_whitespace (*s) && islocalsep (*s); s++);
2988 /* If the string is nothing but whitespace, update it and return. */
2989 if (!*s)
2991 *stringp = s;
2992 if (endptr)
2993 *endptr = s;
2994 return ((char *)NULL);
2997 /* OK, S points to a word that does not begin with white space.
2998 Now extract a word, stopping at a separator, save a pointer to
2999 the first character after the word, then skip sequences of spc,
3000 tab, or nl as long as they are separators.
3002 This obeys the field splitting rules in Posix.2. */
3003 sindex = 0;
3004 /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
3005 possible, but need it in string_extract_verbatim for bounds checking */
3006 slen = STRLEN (s);
3007 current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
3009 /* Set ENDPTR to the first character after the end of the word. */
3010 if (endptr)
3011 *endptr = s + sindex;
3013 /* Note whether or not the separator is IFS whitespace, used later. */
3014 whitesep = s[sindex] && ifs_whitesep (s[sindex]);
3016 /* Move past the current separator character. */
3017 if (s[sindex])
3019 DECLARE_MBSTATE;
3020 ADVANCE_CHAR (s, slen, sindex);
3023 /* Now skip sequences of space, tab, or newline characters if they are
3024 in the list of separators. */
3025 while (s[sindex] && spctabnl (s[sindex]) && islocalsep (s[sindex]))
3026 sindex++;
3028 /* If the first separator was IFS whitespace and the current character is
3029 a non-whitespace IFS character, it should be part of the current field
3030 delimiter, not a separate delimiter that would result in an empty field.
3031 Look at POSIX.2, 3.6.5, (3)(b). */
3032 if (s[sindex] && whitesep && islocalsep (s[sindex]) && !ifs_whitesep (s[sindex]))
3034 sindex++;
3035 /* An IFS character that is not IFS white space, along with any adjacent
3036 IFS white space, shall delimit a field. */
3037 while (s[sindex] && ifs_whitesep (s[sindex]) && islocalsep(s[sindex]))
3038 sindex++;
3041 /* Update STRING to point to the next field. */
3042 *stringp = s + sindex;
3043 return (current_word);
3046 /* Remove IFS white space at the end of STRING. Start at the end
3047 of the string and walk backwards until the beginning of the string
3048 or we find a character that's not IFS white space and not CTLESC.
3049 Only let CTLESC escape a white space character if SAW_ESCAPE is
3050 non-zero. */
3051 char *
3052 strip_trailing_ifs_whitespace (string, separators, saw_escape)
3053 char *string, *separators;
3054 int saw_escape;
3056 char *s;
3058 s = string + STRLEN (string) - 1;
3059 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
3060 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
3061 s--;
3062 *++s = '\0';
3063 return string;
3066 #if 0
3067 /* UNUSED */
3068 /* Split STRING into words at whitespace. Obeys shell-style quoting with
3069 backslashes, single and double quotes. */
3070 WORD_LIST *
3071 list_string_with_quotes (string)
3072 char *string;
3074 WORD_LIST *list;
3075 char *token, *s;
3076 size_t s_len;
3077 int c, i, tokstart, len;
3079 for (s = string; s && *s && spctabnl (*s); s++)
3081 if (s == 0 || *s == 0)
3082 return ((WORD_LIST *)NULL);
3084 s_len = strlen (s);
3085 tokstart = i = 0;
3086 list = (WORD_LIST *)NULL;
3087 while (1)
3089 c = s[i];
3090 if (c == '\\')
3092 i++;
3093 if (s[i])
3094 i++;
3096 else if (c == '\'')
3097 i = skip_single_quoted (s, s_len, ++i, 0);
3098 else if (c == '"')
3099 i = skip_double_quoted (s, s_len, ++i, 0);
3100 else if (c == 0 || spctabnl (c))
3102 /* We have found the end of a token. Make a word out of it and
3103 add it to the word list. */
3104 token = substring (s, tokstart, i);
3105 list = add_string_to_list (token, list);
3106 free (token);
3107 while (spctabnl (s[i]))
3108 i++;
3109 if (s[i])
3110 tokstart = i;
3111 else
3112 break;
3114 else
3115 i++; /* normal character */
3117 return (REVERSE_LIST (list, WORD_LIST *));
3119 #endif
3121 /********************************************************/
3122 /* */
3123 /* Functions to perform assignment statements */
3124 /* */
3125 /********************************************************/
3127 #if defined (ARRAY_VARS)
3128 static SHELL_VAR *
3129 do_compound_assignment (name, value, flags)
3130 char *name, *value;
3131 int flags;
3133 SHELL_VAR *v;
3134 int mklocal, mkassoc, mkglobal, chklocal;
3135 WORD_LIST *list;
3136 char *newname; /* used for local nameref references */
3138 mklocal = flags & ASS_MKLOCAL;
3139 mkassoc = flags & ASS_MKASSOC;
3140 mkglobal = flags & ASS_MKGLOBAL;
3141 chklocal = flags & ASS_CHKLOCAL;
3143 if (mklocal && variable_context)
3145 v = find_variable (name); /* follows namerefs */
3146 newname = (v == 0) ? nameref_transform_name (name, flags) : v->name;
3147 if (v && ((readonly_p (v) && (flags & ASS_FORCE) == 0) || noassign_p (v)))
3149 if (readonly_p (v))
3150 err_readonly (name);
3151 return (v); /* XXX */
3153 list = expand_compound_array_assignment (v, value, flags);
3154 if (mkassoc)
3155 v = make_local_assoc_variable (newname, 0);
3156 else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
3157 v = make_local_array_variable (newname, 0);
3158 if (v)
3159 assign_compound_array_list (v, list, flags);
3160 if (list)
3161 dispose_words (list);
3163 /* In a function but forcing assignment in global context. CHKLOCAL means to
3164 check for an existing local variable first. */
3165 else if (mkglobal && variable_context)
3167 v = chklocal ? find_variable (name) : 0;
3168 if (v && (local_p (v) == 0 || v->context != variable_context))
3169 v = 0;
3170 if (v == 0)
3171 v = find_global_variable (name);
3172 if (v && ((readonly_p (v) && (flags & ASS_FORCE) == 0) || noassign_p (v)))
3174 if (readonly_p (v))
3175 err_readonly (name);
3176 return (v); /* XXX */
3178 /* sanity check */
3179 newname = (v == 0) ? nameref_transform_name (name, flags) : name;
3180 list = expand_compound_array_assignment (v, value, flags);
3181 if (v == 0 && mkassoc)
3182 v = make_new_assoc_variable (newname);
3183 else if (v && mkassoc && assoc_p (v) == 0)
3184 v = convert_var_to_assoc (v);
3185 else if (v == 0)
3186 v = make_new_array_variable (newname);
3187 else if (v && mkassoc == 0 && array_p (v) == 0)
3188 v = convert_var_to_array (v);
3189 if (v)
3190 assign_compound_array_list (v, list, flags);
3191 if (list)
3192 dispose_words (list);
3194 else
3196 v = assign_array_from_string (name, value, flags);
3197 if (v && ((readonly_p (v) && (flags & ASS_FORCE) == 0) || noassign_p (v)))
3199 if (readonly_p (v))
3200 err_readonly (name);
3201 return (v); /* XXX */
3205 return (v);
3207 #endif
3209 /* Given STRING, an assignment string, get the value of the right side
3210 of the `=', and bind it to the left side. If EXPAND is true, then
3211 perform parameter expansion, command substitution, and arithmetic
3212 expansion on the right-hand side. Perform tilde expansion in any
3213 case. Do not perform word splitting on the result of expansion. */
3214 static int
3215 do_assignment_internal (word, expand)
3216 const WORD_DESC *word;
3217 int expand;
3219 int offset, appendop, assign_list, aflags, retval;
3220 char *name, *value, *temp;
3221 SHELL_VAR *entry;
3222 #if defined (ARRAY_VARS)
3223 char *t;
3224 int ni;
3225 #endif
3226 const char *string;
3228 if (word == 0 || word->word == 0)
3229 return 0;
3231 appendop = assign_list = aflags = 0;
3232 string = word->word;
3233 offset = assignment (string, 0);
3234 name = savestring (string);
3235 value = (char *)NULL;
3237 if (name[offset] == '=')
3239 if (name[offset - 1] == '+')
3241 appendop = 1;
3242 name[offset - 1] = '\0';
3245 name[offset] = 0; /* might need this set later */
3246 temp = name + offset + 1;
3248 #if defined (ARRAY_VARS)
3249 if (expand && (word->flags & W_COMPASSIGN))
3251 assign_list = ni = 1;
3252 value = extract_array_assignment_list (temp, &ni);
3254 else
3255 #endif
3256 if (expand && temp[0])
3257 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
3258 else
3259 value = savestring (temp);
3262 if (value == 0)
3264 value = (char *)xmalloc (1);
3265 value[0] = '\0';
3268 if (echo_command_at_execute || debug_info)
3270 if (appendop)
3271 name[offset - 1] = '+';
3272 xtrace_print_assignment (name, value, assign_list, 1);
3273 if (appendop)
3274 name[offset - 1] = '\0';
3277 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
3279 if (appendop)
3280 aflags |= ASS_APPEND;
3282 #if defined (ARRAY_VARS)
3283 if (t = mbschr (name, LBRACK))
3285 if (assign_list)
3287 report_error (_("%s: cannot assign list to array member"), name);
3288 ASSIGN_RETURN (0);
3290 entry = assign_array_element (name, value, aflags);
3291 if (entry == 0)
3292 ASSIGN_RETURN (0);
3294 else if (assign_list)
3296 if ((word->flags & W_ASSIGNARG) && (word->flags & W_CHKLOCAL))
3297 aflags |= ASS_CHKLOCAL;
3298 if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL) == 0)
3299 aflags |= ASS_MKLOCAL;
3300 if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL))
3301 aflags |= ASS_MKGLOBAL;
3302 if (word->flags & W_ASSIGNASSOC)
3303 aflags |= ASS_MKASSOC;
3304 entry = do_compound_assignment (name, value, aflags);
3306 else
3307 #endif /* ARRAY_VARS */
3308 entry = bind_variable (name, value, aflags);
3310 if (entry)
3311 stupidly_hack_special_variables (entry->name); /* might be a nameref */
3312 else
3313 stupidly_hack_special_variables (name);
3315 /* Return 1 if the assignment seems to have been performed correctly. */
3316 if (entry == 0 || readonly_p (entry))
3317 retval = 0; /* assignment failure */
3318 else if (noassign_p (entry))
3320 set_exit_status (EXECUTION_FAILURE);
3321 retval = 1; /* error status, but not assignment failure */
3323 else
3324 retval = 1;
3326 if (entry && retval != 0 && noassign_p (entry) == 0)
3327 VUNSETATTR (entry, att_invisible);
3329 ASSIGN_RETURN (retval);
3332 /* Perform the assignment statement in STRING, and expand the
3333 right side by doing tilde, command and parameter expansion. */
3335 do_assignment (string)
3336 char *string;
3338 WORD_DESC td;
3340 td.flags = W_ASSIGNMENT;
3341 td.word = string;
3343 return do_assignment_internal (&td, 1);
3347 do_word_assignment (word, flags)
3348 WORD_DESC *word;
3349 int flags;
3351 return do_assignment_internal (word, 1);
3354 /* Given STRING, an assignment string, get the value of the right side
3355 of the `=', and bind it to the left side. Do not perform any word
3356 expansions on the right hand side. */
3358 do_assignment_no_expand (string)
3359 char *string;
3361 WORD_DESC td;
3363 td.flags = W_ASSIGNMENT;
3364 td.word = string;
3366 return (do_assignment_internal (&td, 0));
3369 /***************************************************
3371 * Functions to manage the positional parameters *
3373 ***************************************************/
3375 /* Return the word list that corresponds to `$*'. */
3376 WORD_LIST *
3377 list_rest_of_args ()
3379 register WORD_LIST *list, *args;
3380 int i;
3382 /* Break out of the loop as soon as one of the dollar variables is null. */
3383 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
3384 list = make_word_list (make_bare_word (dollar_vars[i]), list);
3386 for (args = rest_of_args; args; args = args->next)
3387 list = make_word_list (make_bare_word (args->word->word), list);
3389 return (REVERSE_LIST (list, WORD_LIST *));
3392 /* Return the value of a positional parameter. This handles values > 10. */
3393 char *
3394 get_dollar_var_value (ind)
3395 intmax_t ind;
3397 char *temp;
3398 WORD_LIST *p;
3400 if (ind < 10)
3401 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
3402 else /* We want something like ${11} */
3404 ind -= 10;
3405 for (p = rest_of_args; p && ind--; p = p->next)
3407 temp = p ? savestring (p->word->word) : (char *)NULL;
3409 return (temp);
3412 /* Make a single large string out of the dollar digit variables,
3413 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
3414 case of "$*" with respect to IFS. */
3415 char *
3416 string_rest_of_args (dollar_star)
3417 int dollar_star;
3419 register WORD_LIST *list;
3420 char *string;
3422 list = list_rest_of_args ();
3423 string = dollar_star ? string_list_dollar_star (list, 0, 0) : string_list (list);
3424 dispose_words (list);
3425 return (string);
3428 /* Return a string containing the positional parameters from START to
3429 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3430 which only makes a difference if QUOTED is non-zero. If QUOTED includes
3431 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
3432 no quoting chars are added. */
3433 static char *
3434 pos_params (string, start, end, quoted, pflags)
3435 char *string;
3436 int start, end, quoted, pflags;
3438 WORD_LIST *save, *params, *h, *t;
3439 char *ret;
3440 int i;
3442 /* see if we can short-circuit. if start == end, we want 0 parameters. */
3443 if (start == end)
3444 return ((char *)NULL);
3446 save = params = list_rest_of_args ();
3447 if (save == 0 && start > 0)
3448 return ((char *)NULL);
3450 if (start == 0) /* handle ${@:0[:x]} specially */
3452 t = make_word_list (make_word (dollar_vars[0]), params);
3453 save = params = t;
3456 for (i = start ? 1 : 0; params && i < start; i++)
3457 params = params->next;
3458 if (params == 0)
3460 dispose_words (save);
3461 return ((char *)NULL);
3463 for (h = t = params; params && i < end; i++)
3465 t = params;
3466 params = params->next;
3468 t->next = (WORD_LIST *)NULL;
3470 ret = string_list_pos_params (string[0], h, quoted, pflags);
3472 if (t != params)
3473 t->next = params;
3475 dispose_words (save);
3476 return (ret);
3479 /******************************************************************/
3480 /* */
3481 /* Functions to expand strings to strings or WORD_LISTs */
3482 /* */
3483 /******************************************************************/
3485 #if defined (PROCESS_SUBSTITUTION)
3486 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
3487 #else
3488 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3489 #endif
3491 /* If there are any characters in STRING that require full expansion,
3492 then call FUNC to expand STRING; otherwise just perform quote
3493 removal if necessary. This returns a new string. */
3494 static char *
3495 expand_string_if_necessary (string, quoted, func)
3496 char *string;
3497 int quoted;
3498 EXPFUNC *func;
3500 WORD_LIST *list;
3501 size_t slen;
3502 int i, saw_quote;
3503 char *ret;
3504 DECLARE_MBSTATE;
3506 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3507 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
3508 i = saw_quote = 0;
3509 while (string[i])
3511 if (EXP_CHAR (string[i]))
3512 break;
3513 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
3514 saw_quote = 1;
3515 ADVANCE_CHAR (string, slen, i);
3518 if (string[i])
3520 list = (*func) (string, quoted);
3521 if (list)
3523 ret = string_list (list);
3524 dispose_words (list);
3526 else
3527 ret = (char *)NULL;
3529 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3530 ret = string_quote_removal (string, quoted);
3531 else
3532 ret = savestring (string);
3534 return ret;
3537 static inline char *
3538 expand_string_to_string_internal (string, quoted, func)
3539 char *string;
3540 int quoted;
3541 EXPFUNC *func;
3543 WORD_LIST *list;
3544 char *ret;
3546 if (string == 0 || *string == '\0')
3547 return ((char *)NULL);
3549 list = (*func) (string, quoted);
3550 if (list)
3552 ret = string_list (list);
3553 dispose_words (list);
3555 else
3556 ret = (char *)NULL;
3558 return (ret);
3561 char *
3562 expand_string_to_string (string, quoted)
3563 char *string;
3564 int quoted;
3566 return (expand_string_to_string_internal (string, quoted, expand_string));
3569 char *
3570 expand_string_unsplit_to_string (string, quoted)
3571 char *string;
3572 int quoted;
3574 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
3577 char *
3578 expand_assignment_string_to_string (string, quoted)
3579 char *string;
3580 int quoted;
3582 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
3585 char *
3586 expand_arith_string (string, quoted)
3587 char *string;
3588 int quoted;
3590 WORD_DESC td;
3591 WORD_LIST *list, *tlist;
3592 size_t slen;
3593 int i, saw_quote;
3594 char *ret;
3595 DECLARE_MBSTATE;
3597 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3598 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
3599 i = saw_quote = 0;
3600 while (string[i])
3602 if (EXP_CHAR (string[i]))
3603 break;
3604 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
3605 saw_quote = 1;
3606 ADVANCE_CHAR (string, slen, i);
3609 if (string[i])
3611 /* This is expanded version of expand_string_internal as it's called by
3612 expand_string_leave_quoted */
3613 td.flags = W_NOPROCSUB|W_NOTILDE; /* don't want process substitution or tilde expansion */
3614 #if 0 /* TAG: bush-5.2 */
3615 if (quoted & Q_ARRAYSUB)
3616 td.flags |= W_NOCOMSUB;
3617 #endif
3618 td.word = savestring (string);
3619 list = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3620 /* This takes care of the calls from expand_string_leave_quoted and
3621 expand_string */
3622 if (list)
3624 tlist = word_list_split (list);
3625 dispose_words (list);
3626 list = tlist;
3627 if (list)
3628 dequote_list (list);
3630 /* This comes from expand_string_if_necessary */
3631 if (list)
3633 ret = string_list (list);
3634 dispose_words (list);
3636 else
3637 ret = (char *)NULL;
3638 FREE (td.word);
3640 else if (saw_quote && (quoted & Q_ARITH))
3641 ret = string_quote_removal (string, quoted);
3642 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3643 ret = string_quote_removal (string, quoted);
3644 else
3645 ret = savestring (string);
3647 return ret;
3650 #if defined (COND_COMMAND)
3651 /* Just remove backslashes in STRING. Returns a new string. */
3652 char *
3653 remove_backslashes (string)
3654 char *string;
3656 char *r, *ret, *s;
3658 r = ret = (char *)xmalloc (strlen (string) + 1);
3659 for (s = string; s && *s; )
3661 if (*s == '\\')
3662 s++;
3663 if (*s == 0)
3664 break;
3665 *r++ = *s++;
3667 *r = '\0';
3668 return ret;
3671 /* This needs better error handling. */
3672 /* Expand W for use as an argument to a unary or binary operator in a
3673 [[...]] expression. If SPECIAL is 1, this is the rhs argument
3674 to the != or == operator, and should be treated as a pattern. In
3675 this case, we quote the string specially for the globbing code. If
3676 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
3677 be quoted appropriately for regcomp/regexec. The caller is responsible
3678 for removing the backslashes if the unquoted word is needed later. In
3679 any case, since we don't perform word splitting, we need to do quoted
3680 null character removal. */
3681 char *
3682 cond_expand_word (w, special)
3683 WORD_DESC *w;
3684 int special;
3686 char *r, *p;
3687 WORD_LIST *l;
3688 int qflags;
3690 if (w->word == 0 || w->word[0] == '\0')
3691 return ((char *)NULL);
3693 expand_no_split_dollar_star = 1;
3694 w->flags |= W_NOSPLIT2;
3695 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
3696 expand_no_split_dollar_star = 0;
3697 if (l)
3699 if (special == 0) /* LHS */
3701 if (l->word)
3702 word_list_remove_quoted_nulls (l);
3703 dequote_list (l);
3704 r = string_list (l);
3706 else
3708 /* Need to figure out whether or not we should call dequote_escapes
3709 or a new dequote_ctlnul function here, and under what
3710 circumstances. */
3711 qflags = QGLOB_CVTNULL|QGLOB_CTLESC;
3712 if (special == 2)
3713 qflags |= QGLOB_REGEXP;
3714 word_list_remove_quoted_nulls (l);
3715 p = string_list (l);
3716 r = quote_string_for_globbing (p, qflags);
3717 free (p);
3719 dispose_words (l);
3721 else
3722 r = (char *)NULL;
3724 return r;
3726 #endif
3728 /* Call expand_word_internal to expand W and handle error returns.
3729 A convenience function for functions that don't want to handle
3730 any errors or free any memory before aborting. */
3731 static WORD_LIST *
3732 call_expand_word_internal (w, q, i, c, e)
3733 WORD_DESC *w;
3734 int q, i, *c, *e;
3736 WORD_LIST *result;
3738 result = expand_word_internal (w, q, i, c, e);
3739 if (result == &expand_word_error || result == &expand_word_fatal)
3741 /* By convention, each time this error is returned, w->word has
3742 already been freed (it sometimes may not be in the fatal case,
3743 but that doesn't result in a memory leak because we're going
3744 to exit in most cases). */
3745 w->word = (char *)NULL;
3746 last_command_exit_value = EXECUTION_FAILURE;
3747 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
3748 /* NOTREACHED */
3749 return (NULL);
3751 else
3752 return (result);
3755 /* Perform parameter expansion, command substitution, and arithmetic
3756 expansion on STRING, as if it were a word. Leave the result quoted.
3757 Since this does not perform word splitting, it leaves quoted nulls
3758 in the result. */
3759 static WORD_LIST *
3760 expand_string_internal (string, quoted)
3761 char *string;
3762 int quoted;
3764 WORD_DESC td;
3765 WORD_LIST *tresult;
3767 if (string == 0 || *string == 0)
3768 return ((WORD_LIST *)NULL);
3770 td.flags = 0;
3771 td.word = savestring (string);
3773 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3775 FREE (td.word);
3776 return (tresult);
3779 /* Expand STRING by performing parameter expansion, command substitution,
3780 and arithmetic expansion. Dequote the resulting WORD_LIST before
3781 returning it, but do not perform word splitting. The call to
3782 remove_quoted_nulls () is in here because word splitting normally
3783 takes care of quote removal. */
3784 WORD_LIST *
3785 expand_string_unsplit (string, quoted)
3786 char *string;
3787 int quoted;
3789 WORD_LIST *value;
3791 if (string == 0 || *string == '\0')
3792 return ((WORD_LIST *)NULL);
3794 expand_no_split_dollar_star = 1;
3795 value = expand_string_internal (string, quoted);
3796 expand_no_split_dollar_star = 0;
3798 if (value)
3800 if (value->word)
3802 remove_quoted_nulls (value->word->word); /* XXX */
3803 value->word->flags &= ~W_HASQUOTEDNULL;
3805 dequote_list (value);
3807 return (value);
3810 /* Expand the rhs of an assignment statement */
3811 WORD_LIST *
3812 expand_string_assignment (string, quoted)
3813 char *string;
3814 int quoted;
3816 WORD_DESC td;
3817 WORD_LIST *value;
3819 if (string == 0 || *string == '\0')
3820 return ((WORD_LIST *)NULL);
3822 expand_no_split_dollar_star = 1;
3824 #if 0
3825 /* Other shells (ksh93) do it this way, which affects how $@ is expanded
3826 in constructs like bar=${@#0} (preserves the spaces resulting from the
3827 expansion of $@ in a context where you don't do word splitting); Posix
3828 interp 888 makes the expansion of $@ in contexts where word splitting
3829 is not performed unspecified. */
3830 td.flags = W_ASSIGNRHS|W_NOSPLIT2; /* Posix interp 888 */
3831 #else
3832 td.flags = W_ASSIGNRHS;
3833 #endif
3834 td.word = savestring (string);
3835 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3836 FREE (td.word);
3838 expand_no_split_dollar_star = 0;
3840 if (value)
3842 if (value->word)
3844 remove_quoted_nulls (value->word->word); /* XXX */
3845 value->word->flags &= ~W_HASQUOTEDNULL;
3847 dequote_list (value);
3849 return (value);
3853 /* Expand one of the PS? prompt strings. This is a sort of combination of
3854 expand_string_unsplit and expand_string_internal, but returns the
3855 passed string when an error occurs. Might want to trap other calls
3856 to jump_to_top_level here so we don't endlessly loop. */
3857 WORD_LIST *
3858 expand_prompt_string (string, quoted, wflags)
3859 char *string;
3860 int quoted;
3861 int wflags;
3863 WORD_LIST *value;
3864 WORD_DESC td;
3866 if (string == 0 || *string == 0)
3867 return ((WORD_LIST *)NULL);
3869 td.flags = wflags;
3870 td.word = savestring (string);
3872 no_longjmp_on_fatal_error = 1;
3873 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3874 no_longjmp_on_fatal_error = 0;
3876 if (value == &expand_word_error || value == &expand_word_fatal)
3878 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
3879 return value;
3881 FREE (td.word);
3882 if (value)
3884 if (value->word)
3886 remove_quoted_nulls (value->word->word); /* XXX */
3887 value->word->flags &= ~W_HASQUOTEDNULL;
3889 dequote_list (value);
3891 return (value);
3894 /* Expand STRING just as if you were expanding a word, but do not dequote
3895 the resultant WORD_LIST. This is called only from within this file,
3896 and is used to correctly preserve quoted characters when expanding
3897 things like ${1+"$@"}. This does parameter expansion, command
3898 substitution, arithmetic expansion, and word splitting. */
3899 static WORD_LIST *
3900 expand_string_leave_quoted (string, quoted)
3901 char *string;
3902 int quoted;
3904 WORD_LIST *tlist;
3905 WORD_LIST *tresult;
3907 if (string == 0 || *string == '\0')
3908 return ((WORD_LIST *)NULL);
3910 tlist = expand_string_internal (string, quoted);
3912 if (tlist)
3914 tresult = word_list_split (tlist);
3915 dispose_words (tlist);
3916 return (tresult);
3918 return ((WORD_LIST *)NULL);
3921 /* This does not perform word splitting or dequote the WORD_LIST
3922 it returns. */
3923 static WORD_LIST *
3924 expand_string_for_rhs (string, quoted, op, pflags, dollar_at_p, expanded_p)
3925 char *string;
3926 int quoted, op, pflags;
3927 int *dollar_at_p, *expanded_p;
3929 WORD_DESC td;
3930 WORD_LIST *tresult;
3931 int old_nosplit;
3933 if (string == 0 || *string == '\0')
3934 return (WORD_LIST *)NULL;
3936 /* We want field splitting to be determined by what is going to be done with
3937 the entire ${parameterOPword} expansion, so we don't want to split the RHS
3938 we expand here. However, the expansion of $* is determined by whether we
3939 are going to eventually perform word splitting, so we want to set this
3940 depending on whether or not are are going to be splitting: if the expansion
3941 is quoted, if the OP is `=', or if IFS is set to the empty string, we
3942 are not going to be splitting, so we set expand_no_split_dollar_star to
3943 note this to callees.
3944 We pass through PF_ASSIGNRHS as W_ASSIGNRHS if this is on the RHS of an
3945 assignment statement. */
3946 /* The updated treatment of $* is the result of Posix interp 888 */
3947 /* This was further clarified on the austin-group list in March, 2017 and
3948 in Posix bug 1129 */
3949 old_nosplit = expand_no_split_dollar_star;
3950 expand_no_split_dollar_star = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || op == '=' || ifs_is_null == 0; /* XXX - was 1 */
3951 td.flags = W_EXPANDRHS; /* expanding RHS of ${paramOPword} */
3952 td.flags |= W_NOSPLIT2; /* no splitting, remove "" and '' */
3953 if (pflags & PF_ASSIGNRHS) /* pass through */
3954 td.flags |= W_ASSIGNRHS;
3955 if (op == '=')
3956 #if 0
3957 td.flags |= W_ASSIGNRHS; /* expand b in ${a=b} like assignment */
3958 #else
3959 td.flags |= W_ASSIGNRHS|W_NOASSNTILDE; /* expand b in ${a=b} like assignment */
3960 #endif
3961 td.word = string;
3962 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, expanded_p);
3963 expand_no_split_dollar_star = old_nosplit;
3965 return (tresult);
3968 /* This does not perform word splitting or dequote the WORD_LIST
3969 it returns and it treats $* as if it were quoted. */
3970 static WORD_LIST *
3971 expand_string_for_pat (string, quoted, dollar_at_p, expanded_p)
3972 char *string;
3973 int quoted, *dollar_at_p, *expanded_p;
3975 WORD_DESC td;
3976 WORD_LIST *tresult;
3977 int oexp;
3979 if (string == 0 || *string == '\0')
3980 return (WORD_LIST *)NULL;
3982 oexp = expand_no_split_dollar_star;
3983 expand_no_split_dollar_star = 1;
3984 td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */
3985 td.word = string;
3986 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, expanded_p);
3987 expand_no_split_dollar_star = oexp;
3989 return (tresult);
3992 /* Expand STRING just as if you were expanding a word. This also returns
3993 a list of words. Note that filename globbing is *NOT* done for word
3994 or string expansion, just when the shell is expanding a command. This
3995 does parameter expansion, command substitution, arithmetic expansion,
3996 and word splitting. Dequote the resultant WORD_LIST before returning. */
3997 WORD_LIST *
3998 expand_string (string, quoted)
3999 char *string;
4000 int quoted;
4002 WORD_LIST *result;
4004 if (string == 0 || *string == '\0')
4005 return ((WORD_LIST *)NULL);
4007 result = expand_string_leave_quoted (string, quoted);
4008 return (result ? dequote_list (result) : result);
4011 /*******************************************
4013 * Functions to expand WORD_DESCs *
4015 *******************************************/
4017 /* Expand WORD, performing word splitting on the result. This does
4018 parameter expansion, command substitution, arithmetic expansion,
4019 word splitting, and quote removal. */
4021 WORD_LIST *
4022 expand_word (word, quoted)
4023 WORD_DESC *word;
4024 int quoted;
4026 WORD_LIST *result, *tresult;
4028 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4029 result = word_list_split (tresult);
4030 dispose_words (tresult);
4031 return (result ? dequote_list (result) : result);
4034 /* Expand WORD, but do not perform word splitting on the result. This
4035 does parameter expansion, command substitution, arithmetic expansion,
4036 and quote removal. */
4037 WORD_LIST *
4038 expand_word_unsplit (word, quoted)
4039 WORD_DESC *word;
4040 int quoted;
4042 WORD_LIST *result;
4044 result = expand_word_leave_quoted (word, quoted);
4045 return (result ? dequote_list (result) : result);
4048 /* Perform shell expansions on WORD, but do not perform word splitting or
4049 quote removal on the result. Virtually identical to expand_word_unsplit;
4050 could be combined if implementations don't diverge. */
4051 WORD_LIST *
4052 expand_word_leave_quoted (word, quoted)
4053 WORD_DESC *word;
4054 int quoted;
4056 WORD_LIST *result;
4058 expand_no_split_dollar_star = 1;
4059 if (ifs_is_null)
4060 word->flags |= W_NOSPLIT;
4061 word->flags |= W_NOSPLIT2;
4062 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4063 expand_no_split_dollar_star = 0;
4065 return result;
4068 /***************************************************
4070 * Functions to handle quoting chars *
4072 ***************************************************/
4074 /* Conventions:
4076 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
4077 The parser passes CTLNUL as CTLESC CTLNUL. */
4079 /* Quote escape characters in string s, but no other characters. This is
4080 used to protect CTLESC and CTLNUL in variable values from the rest of
4081 the word expansion process after the variable is expanded (word splitting
4082 and filename generation). If IFS is null, we quote spaces as well, just
4083 in case we split on spaces later (in the case of unquoted $@, we will
4084 eventually attempt to split the entire word on spaces). Corresponding
4085 code exists in dequote_escapes. Even if we don't end up splitting on
4086 spaces, quoting spaces is not a problem. This should never be called on
4087 a string that is quoted with single or double quotes or part of a here
4088 document (effectively double-quoted).
4089 FLAGS says whether or not we are going to split the result. If we are not,
4090 and there is a CTLESC or CTLNUL in IFS, we need to quote CTLESC and CTLNUL,
4091 respectively, to prevent them from being removed as part of dequoting. */
4092 static char *
4093 quote_escapes_internal (string, flags)
4094 const char *string;
4095 int flags;
4097 const char *s, *send;
4098 char *t, *result;
4099 size_t slen;
4100 int quote_spaces, skip_ctlesc, skip_ctlnul, nosplit;
4101 DECLARE_MBSTATE;
4103 slen = strlen (string);
4104 send = string + slen;
4106 quote_spaces = (ifs_value && *ifs_value == 0);
4107 nosplit = (flags & PF_NOSPLIT2);
4109 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
4111 skip_ctlesc |= (nosplit == 0 && *s == CTLESC);
4112 skip_ctlnul |= (nosplit == 0 && *s == CTLNUL);
4115 t = result = (char *)xmalloc ((slen * 2) + 1);
4116 s = string;
4118 while (*s)
4120 if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
4121 *t++ = CTLESC;
4122 COPY_CHAR_P (t, s, send);
4124 *t = '\0';
4126 return (result);
4129 char *
4130 quote_escapes (string)
4131 const char *string;
4133 return (quote_escapes_internal (string, 0));
4136 char *
4137 quote_rhs (string)
4138 const char *string;
4140 return (quote_escapes_internal (string, PF_NOSPLIT2));
4143 static WORD_LIST *
4144 list_quote_escapes (list)
4145 WORD_LIST *list;
4147 register WORD_LIST *w;
4148 char *t;
4150 for (w = list; w; w = w->next)
4152 t = w->word->word;
4153 w->word->word = quote_escapes (t);
4154 free (t);
4156 return list;
4159 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
4161 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
4162 This is necessary to make unquoted CTLESC and CTLNUL characters in the
4163 data stream pass through properly.
4165 We need to remove doubled CTLESC characters inside quoted strings before
4166 quoting the entire string, so we do not double the number of CTLESC
4167 characters.
4169 Also used by parts of the pattern substitution code. */
4170 char *
4171 dequote_escapes (string)
4172 const char *string;
4174 const char *s, *send;
4175 char *t, *result;
4176 size_t slen;
4177 int quote_spaces;
4178 DECLARE_MBSTATE;
4180 if (string == 0)
4181 return (char *)0;
4183 slen = strlen (string);
4184 send = string + slen;
4186 t = result = (char *)xmalloc (slen + 1);
4188 if (strchr (string, CTLESC) == 0)
4189 return (strcpy (result, string));
4191 quote_spaces = (ifs_value && *ifs_value == 0);
4193 s = string;
4194 while (*s)
4196 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
4198 s++;
4199 if (*s == '\0')
4200 break;
4202 COPY_CHAR_P (t, s, send);
4204 *t = '\0';
4206 return result;
4209 #if defined (INCLUDE_UNUSED)
4210 static WORD_LIST *
4211 list_dequote_escapes (list)
4212 WORD_LIST *list;
4214 register WORD_LIST *w;
4215 char *t;
4217 for (w = list; w; w = w->next)
4219 t = w->word->word;
4220 w->word->word = dequote_escapes (t);
4221 free (t);
4223 return list;
4225 #endif
4227 /* Return a new string with the quoted representation of character C.
4228 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
4229 set in any resultant WORD_DESC where this value is the word. */
4230 static char *
4231 make_quoted_char (c)
4232 int c;
4234 char *temp;
4236 temp = (char *)xmalloc (3);
4237 if (c == 0)
4239 temp[0] = CTLNUL;
4240 temp[1] = '\0';
4242 else
4244 temp[0] = CTLESC;
4245 temp[1] = c;
4246 temp[2] = '\0';
4248 return (temp);
4251 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
4252 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
4253 this value is the word. */
4254 char *
4255 quote_string (string)
4256 char *string;
4258 register char *t;
4259 size_t slen;
4260 char *result, *send;
4262 if (*string == 0)
4264 result = (char *)xmalloc (2);
4265 result[0] = CTLNUL;
4266 result[1] = '\0';
4268 else
4270 DECLARE_MBSTATE;
4272 slen = strlen (string);
4273 send = string + slen;
4275 result = (char *)xmalloc ((slen * 2) + 1);
4277 for (t = result; string < send; )
4279 *t++ = CTLESC;
4280 COPY_CHAR_P (t, string, send);
4282 *t = '\0';
4284 return (result);
4287 /* De-quote quoted characters in STRING. */
4288 char *
4289 dequote_string (string)
4290 char *string;
4292 register char *s, *t;
4293 size_t slen;
4294 char *result, *send;
4295 DECLARE_MBSTATE;
4297 #if defined (DEBUG)
4298 if (string[0] == CTLESC && string[1] == 0)
4299 internal_inform ("dequote_string: string with bare CTLESC");
4300 #endif
4302 slen = STRLEN (string);
4304 t = result = (char *)xmalloc (slen + 1);
4306 if (QUOTED_NULL (string))
4308 result[0] = '\0';
4309 return (result);
4312 /* A string consisting of only a single CTLESC should pass through unchanged */
4313 if (string[0] == CTLESC && string[1] == 0)
4315 result[0] = CTLESC;
4316 result[1] = '\0';
4317 return (result);
4320 /* If no character in the string can be quoted, don't bother examining
4321 each character. Just return a copy of the string passed to us. */
4322 if (strchr (string, CTLESC) == NULL)
4323 return (strcpy (result, string));
4325 send = string + slen;
4326 s = string;
4327 while (*s)
4329 if (*s == CTLESC)
4331 s++;
4332 if (*s == '\0')
4333 break;
4335 COPY_CHAR_P (t, s, send);
4338 *t = '\0';
4339 return (result);
4342 /* Quote the entire WORD_LIST list. */
4343 static WORD_LIST *
4344 quote_list (list)
4345 WORD_LIST *list;
4347 register WORD_LIST *w;
4348 char *t;
4350 for (w = list; w; w = w->next)
4352 t = w->word->word;
4353 w->word->word = quote_string (t);
4354 if (*t == 0)
4355 w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
4356 w->word->flags |= W_QUOTED;
4357 free (t);
4359 return list;
4362 WORD_DESC *
4363 dequote_word (word)
4364 WORD_DESC *word;
4366 register char *s;
4368 s = dequote_string (word->word);
4369 if (QUOTED_NULL (word->word))
4370 word->flags &= ~W_HASQUOTEDNULL;
4371 free (word->word);
4372 word->word = s;
4374 return word;
4377 /* De-quote quoted characters in each word in LIST. */
4378 WORD_LIST *
4379 dequote_list (list)
4380 WORD_LIST *list;
4382 register char *s;
4383 register WORD_LIST *tlist;
4385 for (tlist = list; tlist; tlist = tlist->next)
4387 s = dequote_string (tlist->word->word);
4388 if (QUOTED_NULL (tlist->word->word))
4389 tlist->word->flags &= ~W_HASQUOTEDNULL;
4390 free (tlist->word->word);
4391 tlist->word->word = s;
4393 return list;
4396 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
4397 string. */
4398 char *
4399 remove_quoted_escapes (string)
4400 char *string;
4402 char *t;
4404 if (string)
4406 t = dequote_escapes (string);
4407 strcpy (string, t);
4408 free (t);
4411 return (string);
4414 /* Remove quoted $IFS characters from STRING. Quoted IFS characters are
4415 added to protect them from word splitting, but we need to remove them
4416 if no word splitting takes place. This returns newly-allocated memory,
4417 so callers can use it to replace savestring(). */
4418 char *
4419 remove_quoted_ifs (string)
4420 char *string;
4422 register size_t slen;
4423 register int i, j;
4424 char *ret, *send;
4425 DECLARE_MBSTATE;
4427 slen = strlen (string);
4428 send = string + slen;
4430 i = j = 0;
4431 ret = (char *)xmalloc (slen + 1);
4433 while (i < slen)
4435 if (string[i] == CTLESC)
4437 i++;
4438 if (string[i] == 0 || isifs (string[i]) == 0)
4439 ret[j++] = CTLESC;
4440 if (i == slen)
4441 break;
4444 COPY_CHAR_I (ret, j, string, send, i);
4446 ret[j] = '\0';
4448 return (ret);
4451 char *
4452 remove_quoted_nulls (string)
4453 char *string;
4455 register size_t slen;
4456 register int i, j, prev_i;
4457 DECLARE_MBSTATE;
4459 if (strchr (string, CTLNUL) == 0) /* XXX */
4460 return string; /* XXX */
4462 slen = strlen (string);
4463 i = j = 0;
4465 while (i < slen)
4467 if (string[i] == CTLESC)
4469 /* Old code had j++, but we cannot assume that i == j at this
4470 point -- what if a CTLNUL has already been removed from the
4471 string? We don't want to drop the CTLESC or recopy characters
4472 that we've already copied down. */
4473 i++;
4474 string[j++] = CTLESC;
4475 if (i == slen)
4476 break;
4478 else if (string[i] == CTLNUL)
4480 i++;
4481 continue;
4484 prev_i = i;
4485 ADVANCE_CHAR (string, slen, i); /* COPY_CHAR_I? */
4486 if (j < prev_i)
4488 do string[j++] = string[prev_i++]; while (prev_i < i);
4490 else
4491 j = i;
4493 string[j] = '\0';
4495 return (string);
4498 /* Perform quoted null character removal on each element of LIST.
4499 This modifies LIST. */
4500 void
4501 word_list_remove_quoted_nulls (list)
4502 WORD_LIST *list;
4504 register WORD_LIST *t;
4506 for (t = list; t; t = t->next)
4508 remove_quoted_nulls (t->word->word);
4509 t->word->flags &= ~W_HASQUOTEDNULL;
4513 /* **************************************************************** */
4514 /* */
4515 /* Functions for Matching and Removing Patterns */
4516 /* */
4517 /* **************************************************************** */
4519 #if defined (HANDLE_MULTIBYTE)
4520 # ifdef INCLUDE_UNUSED
4521 static unsigned char *
4522 mb_getcharlens (string, len)
4523 char *string;
4524 int len;
4526 int i, offset, last;
4527 unsigned char *ret;
4528 char *p;
4529 DECLARE_MBSTATE;
4531 i = offset = 0;
4532 last = 0;
4533 ret = (unsigned char *)xmalloc (len);
4534 memset (ret, 0, len);
4535 while (string[last])
4537 ADVANCE_CHAR (string, len, offset);
4538 ret[last] = offset - last;
4539 last = offset;
4541 return ret;
4543 # endif
4544 #endif
4546 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
4547 can have one of 4 values:
4548 RP_LONG_LEFT remove longest matching portion at start of PARAM
4549 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
4550 RP_LONG_RIGHT remove longest matching portion at end of PARAM
4551 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
4554 #define RP_LONG_LEFT 1
4555 #define RP_SHORT_LEFT 2
4556 #define RP_LONG_RIGHT 3
4557 #define RP_SHORT_RIGHT 4
4559 /* Returns its first argument if nothing matched; new memory otherwise */
4560 static char *
4561 remove_upattern (param, pattern, op)
4562 char *param, *pattern;
4563 int op;
4565 register size_t len;
4566 register char *end;
4567 register char *p, *ret, c;
4569 len = STRLEN (param);
4570 end = param + len;
4572 switch (op)
4574 case RP_LONG_LEFT: /* remove longest match at start */
4575 for (p = end; p >= param; p--)
4577 c = *p; *p = '\0';
4578 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4580 *p = c;
4581 return (savestring (p));
4583 *p = c;
4586 break;
4588 case RP_SHORT_LEFT: /* remove shortest match at start */
4589 for (p = param; p <= end; p++)
4591 c = *p; *p = '\0';
4592 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4594 *p = c;
4595 return (savestring (p));
4597 *p = c;
4599 break;
4601 case RP_LONG_RIGHT: /* remove longest match at end */
4602 for (p = param; p <= end; p++)
4604 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4606 c = *p; *p = '\0';
4607 ret = savestring (param);
4608 *p = c;
4609 return (ret);
4612 break;
4614 case RP_SHORT_RIGHT: /* remove shortest match at end */
4615 for (p = end; p >= param; p--)
4617 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4619 c = *p; *p = '\0';
4620 ret = savestring (param);
4621 *p = c;
4622 return (ret);
4625 break;
4628 return (param); /* no match, return original string */
4631 #if defined (HANDLE_MULTIBYTE)
4632 /* Returns its first argument if nothing matched; new memory otherwise */
4633 static wchar_t *
4634 remove_wpattern (wparam, wstrlen, wpattern, op)
4635 wchar_t *wparam;
4636 size_t wstrlen;
4637 wchar_t *wpattern;
4638 int op;
4640 wchar_t wc, *ret;
4641 int n;
4643 switch (op)
4645 case RP_LONG_LEFT: /* remove longest match at start */
4646 for (n = wstrlen; n >= 0; n--)
4648 wc = wparam[n]; wparam[n] = L'\0';
4649 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4651 wparam[n] = wc;
4652 return (wcsdup (wparam + n));
4654 wparam[n] = wc;
4656 break;
4658 case RP_SHORT_LEFT: /* remove shortest match at start */
4659 for (n = 0; n <= wstrlen; n++)
4661 wc = wparam[n]; wparam[n] = L'\0';
4662 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4664 wparam[n] = wc;
4665 return (wcsdup (wparam + n));
4667 wparam[n] = wc;
4669 break;
4671 case RP_LONG_RIGHT: /* remove longest match at end */
4672 for (n = 0; n <= wstrlen; n++)
4674 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4676 wc = wparam[n]; wparam[n] = L'\0';
4677 ret = wcsdup (wparam);
4678 wparam[n] = wc;
4679 return (ret);
4682 break;
4684 case RP_SHORT_RIGHT: /* remove shortest match at end */
4685 for (n = wstrlen; n >= 0; n--)
4687 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
4689 wc = wparam[n]; wparam[n] = L'\0';
4690 ret = wcsdup (wparam);
4691 wparam[n] = wc;
4692 return (ret);
4695 break;
4698 return (wparam); /* no match, return original string */
4700 #endif /* HANDLE_MULTIBYTE */
4702 static char *
4703 remove_pattern (param, pattern, op)
4704 char *param, *pattern;
4705 int op;
4707 char *xret;
4709 if (param == NULL)
4710 return (param);
4711 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
4712 return (savestring (param));
4714 #if defined (HANDLE_MULTIBYTE)
4715 if (MB_CUR_MAX > 1)
4717 wchar_t *ret, *oret;
4718 size_t n;
4719 wchar_t *wparam, *wpattern;
4720 mbstate_t ps;
4722 /* XXX - could optimize here by checking param and pattern for multibyte
4723 chars with mbsmbchar and calling remove_upattern. */
4725 n = xdupmbstowcs (&wpattern, NULL, pattern);
4726 if (n == (size_t)-1)
4728 xret = remove_upattern (param, pattern, op);
4729 return ((xret == param) ? savestring (param) : xret);
4731 n = xdupmbstowcs (&wparam, NULL, param);
4733 if (n == (size_t)-1)
4735 free (wpattern);
4736 xret = remove_upattern (param, pattern, op);
4737 return ((xret == param) ? savestring (param) : xret);
4739 oret = ret = remove_wpattern (wparam, n, wpattern, op);
4740 /* Don't bother to convert wparam back to multibyte string if nothing
4741 matched; just return copy of original string */
4742 if (ret == wparam)
4744 free (wparam);
4745 free (wpattern);
4746 return (savestring (param));
4749 free (wparam);
4750 free (wpattern);
4752 n = strlen (param);
4753 xret = (char *)xmalloc (n + 1);
4754 memset (&ps, '\0', sizeof (mbstate_t));
4755 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
4756 xret[n] = '\0'; /* just to make sure */
4757 free (oret);
4758 return xret;
4760 else
4761 #endif
4763 xret = remove_upattern (param, pattern, op);
4764 return ((xret == param) ? savestring (param) : xret);
4768 /* Match PAT anywhere in STRING and return the match boundaries.
4769 This returns 1 in case of a successful match, 0 otherwise. SP
4770 and EP are pointers into the string where the match begins and
4771 ends, respectively. MTYPE controls what kind of match is attempted.
4772 MATCH_BEG and MATCH_END anchor the match at the beginning and end
4773 of the string, respectively. The longest match is returned. */
4774 static int
4775 match_upattern (string, pat, mtype, sp, ep)
4776 char *string, *pat;
4777 int mtype;
4778 char **sp, **ep;
4780 int c, mlen;
4781 size_t len;
4782 register char *p, *p1, *npat;
4783 char *end;
4785 /* If the pattern doesn't match anywhere in the string, go ahead and
4786 short-circuit right away. A minor optimization, saves a bunch of
4787 unnecessary calls to strmatch (up to N calls for a string of N
4788 characters) if the match is unsuccessful. To preserve the semantics
4789 of the substring matches below, we make sure that the pattern has
4790 `*' as first and last character, making a new pattern if necessary. */
4791 /* XXX - check this later if I ever implement `**' with special meaning,
4792 since this will potentially result in `**' at the beginning or end */
4793 len = STRLEN (pat);
4794 if (pat[0] != '*' || (pat[0] == '*' && pat[1] == LPAREN && extended_glob) || pat[len - 1] != '*')
4796 int unescaped_backslash;
4797 char *pp;
4799 p = npat = (char *)xmalloc (len + 3);
4800 p1 = pat;
4801 if ((mtype != MATCH_BEG) && (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob)))
4802 *p++ = '*';
4803 while (*p1)
4804 *p++ = *p1++;
4805 #if 1
4806 /* Need to also handle a pattern that ends with an unescaped backslash.
4807 For right now, we ignore it because the pattern matching code will
4808 fail the match anyway */
4809 /* If the pattern ends with a `*' we leave it alone if it's preceded by
4810 an even number of backslashes, but if it's escaped by a backslash
4811 we need to add another `*'. */
4812 if ((mtype != MATCH_END) && (p1[-1] == '*' && (unescaped_backslash = p1[-2] == '\\')))
4814 pp = p1 - 3;
4815 while (pp >= pat && *pp-- == '\\')
4816 unescaped_backslash = 1 - unescaped_backslash;
4817 if (unescaped_backslash)
4818 *p++ = '*';
4820 else if (mtype != MATCH_END && p1[-1] != '*')
4821 *p++ = '*';
4822 #else
4823 if (p1[-1] != '*' || p1[-2] == '\\')
4824 *p++ = '*';
4825 #endif
4826 *p = '\0';
4828 else
4829 npat = pat;
4830 c = strmatch (npat, string, FNMATCH_EXTFLAG | FNMATCH_IGNCASE);
4831 if (npat != pat)
4832 free (npat);
4833 if (c == FNM_NOMATCH)
4834 return (0);
4836 len = STRLEN (string);
4837 end = string + len;
4839 mlen = umatchlen (pat, len);
4840 if (mlen > (int)len)
4841 return (0);
4843 switch (mtype)
4845 case MATCH_ANY:
4846 for (p = string; p <= end; p++)
4848 if (match_pattern_char (pat, p, FNMATCH_IGNCASE))
4850 p1 = (mlen == -1) ? end : p + mlen;
4851 /* p1 - p = length of portion of string to be considered
4852 p = current position in string
4853 mlen = number of characters consumed by match (-1 for entire string)
4854 end = end of string
4855 we want to break immediately if the potential match len
4856 is greater than the number of characters remaining in the
4857 string
4859 if (p1 > end)
4860 break;
4861 for ( ; p1 >= p; p1--)
4863 c = *p1; *p1 = '\0';
4864 if (strmatch (pat, p, FNMATCH_EXTFLAG | FNMATCH_IGNCASE) == 0)
4866 *p1 = c;
4867 *sp = p;
4868 *ep = p1;
4869 return 1;
4871 *p1 = c;
4872 #if 1
4873 /* If MLEN != -1, we have a fixed length pattern. */
4874 if (mlen != -1)
4875 break;
4876 #endif
4881 return (0);
4883 case MATCH_BEG:
4884 if (match_pattern_char (pat, string, FNMATCH_IGNCASE) == 0)
4885 return (0);
4887 for (p = (mlen == -1) ? end : string + mlen; p >= string; p--)
4889 c = *p; *p = '\0';
4890 if (strmatch (pat, string, FNMATCH_EXTFLAG | FNMATCH_IGNCASE) == 0)
4892 *p = c;
4893 *sp = string;
4894 *ep = p;
4895 return 1;
4897 *p = c;
4898 /* If MLEN != -1, we have a fixed length pattern. */
4899 if (mlen != -1)
4900 break;
4903 return (0);
4905 case MATCH_END:
4906 for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++)
4908 if (strmatch (pat, p, FNMATCH_EXTFLAG | FNMATCH_IGNCASE) == 0)
4910 *sp = p;
4911 *ep = end;
4912 return 1;
4914 /* If MLEN != -1, we have a fixed length pattern. */
4915 if (mlen != -1)
4916 break;
4919 return (0);
4922 return (0);
4925 #if defined (HANDLE_MULTIBYTE)
4927 #define WFOLD(c) (match_ignore_case && iswupper (c) ? towlower (c) : (c))
4929 /* Match WPAT anywhere in WSTRING and return the match boundaries.
4930 This returns 1 in case of a successful match, 0 otherwise. Wide
4931 character version. */
4932 static int
4933 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
4934 wchar_t *wstring;
4935 char **indices;
4936 size_t wstrlen;
4937 wchar_t *wpat;
4938 int mtype;
4939 char **sp, **ep;
4941 wchar_t wc, *wp, *nwpat, *wp1;
4942 size_t len;
4943 int mlen;
4944 int n, n1, n2, simple;
4946 simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
4947 #if defined (EXTENDED_GLOB)
4948 if (extended_glob)
4949 simple &= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
4950 #endif
4952 /* If the pattern doesn't match anywhere in the string, go ahead and
4953 short-circuit right away. A minor optimization, saves a bunch of
4954 unnecessary calls to strmatch (up to N calls for a string of N
4955 characters) if the match is unsuccessful. To preserve the semantics
4956 of the substring matches below, we make sure that the pattern has
4957 `*' as first and last character, making a new pattern if necessary. */
4958 len = wcslen (wpat);
4959 if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == WLPAREN && extended_glob) || wpat[len - 1] != L'*')
4961 int unescaped_backslash;
4962 wchar_t *wpp;
4964 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
4965 wp1 = wpat;
4966 if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == WLPAREN && extended_glob))
4967 *wp++ = L'*';
4968 while (*wp1 != L'\0')
4969 *wp++ = *wp1++;
4970 #if 1
4971 /* See comments above in match_upattern. */
4972 if (wp1[-1] == L'*' && (unescaped_backslash = wp1[-2] == L'\\'))
4974 wpp = wp1 - 3;
4975 while (wpp >= wpat && *wpp-- == L'\\')
4976 unescaped_backslash = 1 - unescaped_backslash;
4977 if (unescaped_backslash)
4978 *wp++ = L'*';
4980 else if (wp1[-1] != L'*')
4981 *wp++ = L'*';
4982 #else
4983 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
4984 *wp++ = L'*';
4985 #endif
4986 *wp = '\0';
4988 else
4989 nwpat = wpat;
4990 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG | FNMATCH_IGNCASE);
4991 if (nwpat != wpat)
4992 free (nwpat);
4993 if (len == FNM_NOMATCH)
4994 return (0);
4996 mlen = wmatchlen (wpat, wstrlen);
4997 if (mlen > (int)wstrlen)
4998 return (0);
5000 /* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
5001 switch (mtype)
5003 case MATCH_ANY:
5004 for (n = 0; n <= wstrlen; n++)
5006 n2 = simple ? (WFOLD(*wpat) == WFOLD(wstring[n])) : match_pattern_wchar (wpat, wstring + n, FNMATCH_IGNCASE);
5007 if (n2)
5009 n1 = (mlen == -1) ? wstrlen : n + mlen;
5010 if (n1 > wstrlen)
5011 break;
5013 for ( ; n1 >= n; n1--)
5015 wc = wstring[n1]; wstring[n1] = L'\0';
5016 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG | FNMATCH_IGNCASE) == 0)
5018 wstring[n1] = wc;
5019 *sp = indices[n];
5020 *ep = indices[n1];
5021 return 1;
5023 wstring[n1] = wc;
5024 /* If MLEN != -1, we have a fixed length pattern. */
5025 if (mlen != -1)
5026 break;
5031 return (0);
5033 case MATCH_BEG:
5034 if (match_pattern_wchar (wpat, wstring, FNMATCH_IGNCASE) == 0)
5035 return (0);
5037 for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--)
5039 wc = wstring[n]; wstring[n] = L'\0';
5040 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG | FNMATCH_IGNCASE) == 0)
5042 wstring[n] = wc;
5043 *sp = indices[0];
5044 *ep = indices[n];
5045 return 1;
5047 wstring[n] = wc;
5048 /* If MLEN != -1, we have a fixed length pattern. */
5049 if (mlen != -1)
5050 break;
5053 return (0);
5055 case MATCH_END:
5056 for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++)
5058 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG | FNMATCH_IGNCASE) == 0)
5060 *sp = indices[n];
5061 *ep = indices[wstrlen];
5062 return 1;
5064 /* If MLEN != -1, we have a fixed length pattern. */
5065 if (mlen != -1)
5066 break;
5069 return (0);
5072 return (0);
5074 #undef WFOLD
5075 #endif /* HANDLE_MULTIBYTE */
5077 static int
5078 match_pattern (string, pat, mtype, sp, ep)
5079 char *string, *pat;
5080 int mtype;
5081 char **sp, **ep;
5083 #if defined (HANDLE_MULTIBYTE)
5084 int ret;
5085 size_t n;
5086 wchar_t *wstring, *wpat;
5087 char **indices;
5088 #endif
5090 if (string == 0 || pat == 0 || *pat == 0)
5091 return (0);
5093 #if defined (HANDLE_MULTIBYTE)
5094 if (MB_CUR_MAX > 1)
5096 if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0)
5097 return (match_upattern (string, pat, mtype, sp, ep));
5099 n = xdupmbstowcs (&wpat, NULL, pat);
5100 if (n == (size_t)-1)
5101 return (match_upattern (string, pat, mtype, sp, ep));
5102 n = xdupmbstowcs (&wstring, &indices, string);
5103 if (n == (size_t)-1)
5105 free (wpat);
5106 return (match_upattern (string, pat, mtype, sp, ep));
5108 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
5110 free (wpat);
5111 free (wstring);
5112 free (indices);
5114 return (ret);
5116 else
5117 #endif
5118 return (match_upattern (string, pat, mtype, sp, ep));
5121 static int
5122 getpatspec (c, value)
5123 int c;
5124 char *value;
5126 if (c == '#')
5127 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
5128 else /* c == '%' */
5129 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
5132 /* Posix.2 says that the WORD should be run through tilde expansion,
5133 parameter expansion, command substitution and arithmetic expansion.
5134 This leaves the result quoted, so quote_string_for_globbing () has
5135 to be called to fix it up for strmatch (). If QUOTED is non-zero,
5136 it means that the entire expression was enclosed in double quotes.
5137 This means that quoting characters in the pattern do not make any
5138 special pattern characters quoted. For example, the `*' in the
5139 following retains its special meaning: "${foo#'*'}". */
5140 static char *
5141 getpattern (value, quoted, expandpat)
5142 char *value;
5143 int quoted, expandpat;
5145 char *pat, *tword;
5146 WORD_LIST *l;
5147 #if 0
5148 int i;
5149 #endif
5150 /* There is a problem here: how to handle single or double quotes in the
5151 pattern string when the whole expression is between double quotes?
5152 POSIX.2 says that enclosing double quotes do not cause the pattern to
5153 be quoted, but does that leave us a problem with @ and array[@] and their
5154 expansions inside a pattern? */
5155 #if 0
5156 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
5158 i = 0;
5159 pat = string_extract_double_quoted (tword, &i, SX_STRIPDQ);
5160 free (tword);
5161 tword = pat;
5163 #endif
5165 /* expand_string_for_pat () leaves WORD quoted and does not perform
5166 word splitting. */
5167 l = *value ? expand_string_for_pat (value,
5168 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
5169 (int *)NULL, (int *)NULL)
5170 : (WORD_LIST *)0;
5171 if (l)
5172 word_list_remove_quoted_nulls (l);
5173 pat = string_list (l);
5174 dispose_words (l);
5175 if (pat)
5177 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
5178 free (pat);
5179 pat = tword;
5181 return (pat);
5184 #if 0
5185 /* Handle removing a pattern from a string as a result of ${name%[%]value}
5186 or ${name#[#]value}. */
5187 static char *
5188 variable_remove_pattern (value, pattern, patspec, quoted)
5189 char *value, *pattern;
5190 int patspec, quoted;
5192 char *tword;
5194 tword = remove_pattern (value, pattern, patspec);
5196 return (tword);
5198 #endif
5200 static char *
5201 list_remove_pattern (list, pattern, patspec, itype, quoted)
5202 WORD_LIST *list;
5203 char *pattern;
5204 int patspec, itype, quoted;
5206 WORD_LIST *new, *l;
5207 WORD_DESC *w;
5208 char *tword;
5210 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
5212 tword = remove_pattern (l->word->word, pattern, patspec);
5213 w = alloc_word_desc ();
5214 w->word = tword ? tword : savestring ("");
5215 new = make_word_list (w, new);
5218 l = REVERSE_LIST (new, WORD_LIST *);
5219 tword = string_list_pos_params (itype, l, quoted, 0);
5220 dispose_words (l);
5222 return (tword);
5225 static char *
5226 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
5227 int itype;
5228 char *pattern;
5229 int patspec, quoted;
5231 char *ret;
5232 WORD_LIST *list;
5234 list = list_rest_of_args ();
5235 if (list == 0)
5236 return ((char *)NULL);
5237 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
5238 dispose_words (list);
5239 return (ret);
5242 #if defined (ARRAY_VARS)
5243 static char *
5244 array_remove_pattern (var, pattern, patspec, starsub, quoted)
5245 SHELL_VAR *var;
5246 char *pattern;
5247 int patspec;
5248 int starsub; /* so we can figure out how it's indexed */
5249 int quoted;
5251 ARRAY *a;
5252 HASH_TABLE *h;
5253 int itype;
5254 char *ret;
5255 WORD_LIST *list;
5256 SHELL_VAR *v;
5258 v = var; /* XXX - for now */
5260 itype = starsub ? '*' : '@';
5262 a = (v && array_p (v)) ? array_cell (v) : 0;
5263 h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
5265 list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
5266 if (list == 0)
5267 return ((char *)NULL);
5268 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
5269 dispose_words (list);
5271 return ret;
5273 #endif /* ARRAY_VARS */
5275 static char *
5276 parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flags)
5277 char *varname, *value;
5278 int ind;
5279 char *patstr;
5280 int rtype, quoted, flags;
5282 int vtype, patspec, starsub;
5283 char *temp1, *val, *pattern, *oname;
5284 SHELL_VAR *v;
5286 if (value == 0)
5287 return ((char *)NULL);
5289 oname = this_command_name;
5290 this_command_name = varname;
5292 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
5293 if (vtype == -1)
5295 this_command_name = oname;
5296 return ((char *)NULL);
5299 starsub = vtype & VT_STARSUB;
5300 vtype &= ~VT_STARSUB;
5302 patspec = getpatspec (rtype, patstr);
5303 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
5304 patstr++;
5306 /* Need to pass getpattern newly-allocated memory in case of expansion --
5307 the expansion code will free the passed string on an error. */
5308 temp1 = savestring (patstr);
5309 pattern = getpattern (temp1, quoted, 1);
5310 free (temp1);
5312 temp1 = (char *)NULL; /* shut up gcc */
5313 switch (vtype)
5315 case VT_VARIABLE:
5316 case VT_ARRAYMEMBER:
5317 temp1 = remove_pattern (val, pattern, patspec);
5318 if (vtype == VT_VARIABLE)
5319 FREE (val);
5320 if (temp1)
5322 val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5323 ? quote_string (temp1)
5324 : quote_escapes (temp1);
5325 free (temp1);
5326 temp1 = val;
5328 break;
5329 #if defined (ARRAY_VARS)
5330 case VT_ARRAYVAR:
5331 temp1 = array_remove_pattern (v, pattern, patspec, starsub, quoted);
5332 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
5334 val = quote_escapes (temp1);
5335 free (temp1);
5336 temp1 = val;
5338 break;
5339 #endif
5340 case VT_POSPARMS:
5341 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
5342 if (temp1 && quoted == 0 && ifs_is_null)
5344 /* Posix interp 888 */
5346 else if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
5348 val = quote_escapes (temp1);
5349 free (temp1);
5350 temp1 = val;
5352 break;
5355 this_command_name = oname;
5357 FREE (pattern);
5358 return temp1;
5361 #if defined (PROCESS_SUBSTITUTION)
5363 static void reap_some_procsubs PARAMS((int));
5365 /*****************************************************************/
5366 /* */
5367 /* Hacking Process Substitution */
5368 /* */
5369 /*****************************************************************/
5371 #if !defined (HAVE_DEV_FD)
5372 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
5373 of FIFOs the shell has open. unlink_fifo_list will walk the list and
5374 unlink the ones that don't have a living process on the other end.
5375 unlink_all_fifos will walk the list and unconditionally unlink them, trying
5376 to open and close the FIFO first to release any child processes sleeping on
5377 the FIFO. add_fifo_list adds the name of an open FIFO to the list.
5378 NFIFO is a count of the number of FIFOs in the list. */
5379 #define FIFO_INCR 20
5381 /* PROC value of -1 means the process has been reaped and the FIFO needs to
5382 be removed. PROC value of 0 means the slot is unused. */
5383 struct temp_fifo {
5384 char *file;
5385 pid_t proc;
5388 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
5389 static int nfifo;
5390 static int fifo_list_size;
5392 void
5393 clear_fifo_list ()
5395 int i;
5397 for (i = 0; i < fifo_list_size; i++)
5399 if (fifo_list[i].file)
5400 free (fifo_list[i].file);
5401 fifo_list[i].file = NULL;
5402 fifo_list[i].proc = 0;
5404 nfifo = 0;
5407 void *
5408 copy_fifo_list (sizep)
5409 int *sizep;
5411 if (sizep)
5412 *sizep = 0;
5413 return (void *)NULL;
5416 static void
5417 add_fifo_list (pathname)
5418 char *pathname;
5420 int osize, i;
5422 if (nfifo >= fifo_list_size - 1)
5424 osize = fifo_list_size;
5425 fifo_list_size += FIFO_INCR;
5426 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
5427 fifo_list_size * sizeof (struct temp_fifo));
5428 for (i = osize; i < fifo_list_size; i++)
5430 fifo_list[i].file = (char *)NULL;
5431 fifo_list[i].proc = 0; /* unused */
5435 fifo_list[nfifo].file = savestring (pathname);
5436 nfifo++;
5439 void
5440 unlink_fifo (i)
5441 int i;
5443 if ((fifo_list[i].proc == (pid_t)-1) || (fifo_list[i].proc > 0 && (kill(fifo_list[i].proc, 0) == -1)))
5445 unlink (fifo_list[i].file);
5446 free (fifo_list[i].file);
5447 fifo_list[i].file = (char *)NULL;
5448 fifo_list[i].proc = 0;
5452 void
5453 unlink_fifo_list ()
5455 int saved, i, j;
5457 if (nfifo == 0)
5458 return;
5460 for (i = saved = 0; i < nfifo; i++)
5462 if ((fifo_list[i].proc == (pid_t)-1) || (fifo_list[i].proc > 0 && (kill(fifo_list[i].proc, 0) == -1)))
5464 unlink (fifo_list[i].file);
5465 free (fifo_list[i].file);
5466 fifo_list[i].file = (char *)NULL;
5467 fifo_list[i].proc = 0;
5469 else
5470 saved++;
5473 /* If we didn't remove some of the FIFOs, compact the list. */
5474 if (saved)
5476 for (i = j = 0; i < nfifo; i++)
5477 if (fifo_list[i].file)
5479 if (i != j)
5481 fifo_list[j].file = fifo_list[i].file;
5482 fifo_list[j].proc = fifo_list[i].proc;
5483 fifo_list[i].file = (char *)NULL;
5484 fifo_list[i].proc = 0;
5486 j++;
5488 nfifo = j;
5490 else
5491 nfifo = 0;
5494 void
5495 unlink_all_fifos ()
5497 int i, fd;
5499 if (nfifo == 0)
5500 return;
5502 for (i = 0; i < nfifo; i++)
5504 fifo_list[i].proc = (pid_t)-1;
5505 fd = open (fifo_list[i].file, O_RDWR|O_NONBLOCK);
5506 unlink_fifo (i);
5507 if (fd >= 0)
5508 close (fd);
5511 nfifo = 0;
5514 /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
5515 from some point in the past, and close all open FIFOs in fifo_list
5516 that are not marked as active in LIST. If LIST is NULL, close
5517 everything in fifo_list. LSIZE is the number of elements in LIST, in
5518 case it's larger than fifo_list_size (size of fifo_list). */
5519 void
5520 close_new_fifos (list, lsize)
5521 void *list;
5522 int lsize;
5524 int i;
5525 char *plist;
5527 if (list == 0)
5529 unlink_fifo_list ();
5530 return;
5533 for (plist = (char *)list, i = 0; i < lsize; i++)
5534 if (plist[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
5535 unlink_fifo (i);
5537 for (i = lsize; i < fifo_list_size; i++)
5538 unlink_fifo (i);
5542 find_procsub_child (pid)
5543 pid_t pid;
5545 int i;
5547 for (i = 0; i < nfifo; i++)
5548 if (fifo_list[i].proc == pid)
5549 return i;
5550 return -1;
5553 void
5554 set_procsub_status (ind, pid, status)
5555 int ind;
5556 pid_t pid;
5557 int status;
5559 if (ind >= 0 && ind < nfifo)
5560 fifo_list[ind].proc = (pid_t)-1; /* sentinel */
5563 /* If we've marked the process for this procsub as dead, close the
5564 associated file descriptor and delete the FIFO. */
5565 static void
5566 reap_some_procsubs (max)
5567 int max;
5569 int i;
5571 for (i = 0; i < max; i++)
5572 if (fifo_list[i].proc == (pid_t)-1) /* reaped */
5573 unlink_fifo (i);
5576 void
5577 reap_procsubs ()
5579 reap_some_procsubs (nfifo);
5582 #if 0
5583 /* UNUSED */
5584 void
5585 wait_procsubs ()
5587 int i, r;
5589 for (i = 0; i < nfifo; i++)
5591 if (fifo_list[i].proc != (pid_t)-1 && fifo_list[i].proc > 0)
5593 r = wait_for (fifo_list[i].proc, 0);
5594 save_proc_status (fifo_list[i].proc, r);
5595 fifo_list[i].proc = (pid_t)-1;
5599 #endif
5602 fifos_pending ()
5604 return nfifo;
5608 num_fifos ()
5610 return nfifo;
5613 static char *
5614 make_named_pipe ()
5616 char *tname;
5618 tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
5619 if (mkfifo (tname, 0600) < 0)
5621 free (tname);
5622 return ((char *)NULL);
5625 add_fifo_list (tname);
5626 return (tname);
5629 #else /* HAVE_DEV_FD */
5631 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
5632 has open to children. NFDS is a count of the number of bits currently
5633 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
5634 of open files. */
5635 /* dev_fd_list[I] value of -1 means the process has been reaped and file
5636 descriptor I needs to be closed. Value of 0 means the slot is unused. */
5638 static pid_t *dev_fd_list = (pid_t *)NULL;
5639 static int nfds;
5640 static int totfds; /* The highest possible number of open files. */
5642 void
5643 clear_fifo (i)
5644 int i;
5646 if (dev_fd_list[i])
5648 dev_fd_list[i] = 0;
5649 nfds--;
5653 void
5654 clear_fifo_list ()
5656 register int i;
5658 if (nfds == 0)
5659 return;
5661 for (i = 0; nfds && i < totfds; i++)
5662 clear_fifo (i);
5664 nfds = 0;
5667 void *
5668 copy_fifo_list (sizep)
5669 int *sizep;
5671 void *ret;
5673 if (nfds == 0 || totfds == 0)
5675 if (sizep)
5676 *sizep = 0;
5677 return (void *)NULL;
5680 if (sizep)
5681 *sizep = totfds;
5682 ret = xmalloc (totfds * sizeof (pid_t));
5683 return (memcpy (ret, dev_fd_list, totfds * sizeof (pid_t)));
5686 static void
5687 add_fifo_list (fd)
5688 int fd;
5690 if (dev_fd_list == 0 || fd >= totfds)
5692 int ofds;
5694 ofds = totfds;
5695 totfds = getdtablesize ();
5696 if (totfds < 0 || totfds > 256)
5697 totfds = 256;
5698 if (fd >= totfds)
5699 totfds = fd + 2;
5701 dev_fd_list = (pid_t *)xrealloc (dev_fd_list, totfds * sizeof (dev_fd_list[0]));
5702 /* XXX - might need a loop for this */
5703 memset (dev_fd_list + ofds, '\0', (totfds - ofds) * sizeof (pid_t));
5706 dev_fd_list[fd] = 1; /* marker; updated later */
5707 nfds++;
5711 fifos_pending ()
5713 return 0; /* used for cleanup; not needed with /dev/fd */
5717 num_fifos ()
5719 return nfds;
5722 void
5723 unlink_fifo (fd)
5724 int fd;
5726 if (dev_fd_list[fd])
5728 close (fd);
5729 dev_fd_list[fd] = 0;
5730 nfds--;
5734 void
5735 unlink_fifo_list ()
5737 register int i;
5739 if (nfds == 0)
5740 return;
5742 for (i = totfds-1; nfds && i >= 0; i--)
5743 unlink_fifo (i);
5745 nfds = 0;
5748 void
5749 unlink_all_fifos ()
5751 unlink_fifo_list ();
5754 /* Take LIST, which is a snapshot copy of dev_fd_list from some point in
5755 the past, and close all open fds in dev_fd_list that are not marked
5756 as open in LIST. If LIST is NULL, close everything in dev_fd_list.
5757 LSIZE is the number of elements in LIST, in case it's larger than
5758 totfds (size of dev_fd_list). */
5759 void
5760 close_new_fifos (list, lsize)
5761 void *list;
5762 int lsize;
5764 int i;
5765 pid_t *plist;
5767 if (list == 0)
5769 unlink_fifo_list ();
5770 return;
5773 for (plist = (pid_t *)list, i = 0; i < lsize; i++)
5774 if (plist[i] == 0 && i < totfds && dev_fd_list[i])
5775 unlink_fifo (i);
5777 for (i = lsize; i < totfds; i++)
5778 unlink_fifo (i);
5782 find_procsub_child (pid)
5783 pid_t pid;
5785 int i;
5787 if (nfds == 0)
5788 return -1;
5790 for (i = 0; i < totfds; i++)
5791 if (dev_fd_list[i] == pid)
5792 return i;
5794 return -1;
5797 void
5798 set_procsub_status (ind, pid, status)
5799 int ind;
5800 pid_t pid;
5801 int status;
5803 if (ind >= 0 && ind < totfds)
5804 dev_fd_list[ind] = (pid_t)-1; /* sentinel */
5807 /* If we've marked the process for this procsub as dead, close the
5808 associated file descriptor. */
5809 static void
5810 reap_some_procsubs (max)
5811 int max;
5813 int i;
5815 for (i = 0; nfds > 0 && i < max; i++)
5816 if (dev_fd_list[i] == (pid_t)-1)
5817 unlink_fifo (i);
5820 void
5821 reap_procsubs ()
5823 reap_some_procsubs (totfds);
5826 #if 0
5827 /* UNUSED */
5828 void
5829 wait_procsubs ()
5831 int i, r;
5833 for (i = 0; nfds > 0 && i < totfds; i++)
5835 if (dev_fd_list[i] != (pid_t)-1 && dev_fd_list[i] > 0)
5837 r = wait_for (dev_fd_list[i], 0);
5838 save_proc_status (dev_fd_list[i], r);
5839 dev_fd_list[i] = (pid_t)-1;
5843 #endif
5845 #if defined (NOTDEF)
5846 print_dev_fd_list ()
5848 register int i;
5850 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
5851 fflush (stderr);
5853 for (i = 0; i < totfds; i++)
5855 if (dev_fd_list[i])
5856 fprintf (stderr, " %d", i);
5858 fprintf (stderr, "\n");
5860 #endif /* NOTDEF */
5862 static char *
5863 make_dev_fd_filename (fd)
5864 int fd;
5866 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
5868 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8);
5870 strcpy (ret, DEV_FD_PREFIX);
5871 p = inttostr (fd, intbuf, sizeof (intbuf));
5872 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
5874 add_fifo_list (fd);
5875 return (ret);
5878 #endif /* HAVE_DEV_FD */
5880 /* Return a filename that will open a connection to the process defined by
5881 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
5882 a filename in /dev/fd corresponding to a descriptor that is one of the
5883 ends of the pipe. If not defined, we use named pipes on systems that have
5884 them. Systems without /dev/fd and named pipes are out of luck.
5886 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
5887 use the read end of the pipe and dup that file descriptor to fd 0 in
5888 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
5889 writing or use the write end of the pipe in the child, and dup that
5890 file descriptor to fd 1 in the child. The parent does the opposite. */
5892 static char *
5893 process_substitute (string, open_for_read_in_child)
5894 char *string;
5895 int open_for_read_in_child;
5897 char *pathname;
5898 int fd, result, rc, function_value;
5899 pid_t old_pid, pid;
5900 #if defined (HAVE_DEV_FD)
5901 int parent_pipe_fd, child_pipe_fd;
5902 int fildes[2];
5903 #endif /* HAVE_DEV_FD */
5904 #if defined (JOB_CONTROL)
5905 pid_t old_pipeline_pgrp;
5906 #endif
5908 if (!string || !*string || wordexp_only)
5909 return ((char *)NULL);
5911 #if !defined (HAVE_DEV_FD)
5912 pathname = make_named_pipe ();
5913 #else /* HAVE_DEV_FD */
5914 if (pipe (fildes) < 0)
5916 sys_error ("%s", _("cannot make pipe for process substitution"));
5917 return ((char *)NULL);
5919 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
5920 the pipe in the parent, otherwise the read end. */
5921 parent_pipe_fd = fildes[open_for_read_in_child];
5922 child_pipe_fd = fildes[1 - open_for_read_in_child];
5923 /* Move the parent end of the pipe to some high file descriptor, to
5924 avoid clashes with FDs used by the script. */
5925 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
5927 pathname = make_dev_fd_filename (parent_pipe_fd);
5928 #endif /* HAVE_DEV_FD */
5930 if (pathname == 0)
5932 sys_error ("%s", _("cannot make pipe for process substitution"));
5933 return ((char *)NULL);
5936 old_pid = last_made_pid;
5938 #if defined (JOB_CONTROL)
5939 old_pipeline_pgrp = pipeline_pgrp;
5940 if (pipeline_pgrp == 0 || (subshell_environment & (SUBSHELL_PIPE|SUBSHELL_FORK|SUBSHELL_ASYNC)) == 0)
5941 pipeline_pgrp = shell_pgrp;
5942 save_pipeline (1);
5943 #endif /* JOB_CONTROL */
5945 pid = make_child ((char *)NULL, FORK_ASYNC);
5946 if (pid == 0)
5948 #if 0
5949 int old_interactive;
5951 old_interactive = interactive;
5952 #endif
5953 /* The currently-executing shell is not interactive */
5954 interactive = 0;
5956 reset_terminating_signals (); /* XXX */
5957 free_pushed_string_input ();
5958 /* Cancel traps, in trap.c. */
5959 restore_original_signals (); /* XXX - what about special builtins? bush-4.2 */
5960 QUIT; /* catch any interrupts we got post-fork */
5961 setup_async_signals ();
5962 #if 0
5963 if (open_for_read_in_child == 0 && old_interactive && (bush_input.type == st_stdin || bush_input.type == st_stream))
5964 async_redirect_stdin ();
5965 #endif
5967 subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB|SUBSHELL_ASYNC;
5969 /* We don't inherit the verbose option for command substitutions now, so
5970 let's try it for process substitutions. */
5971 change_flag ('v', FLAG_OFF);
5973 /* if we're expanding a redirection, we shouldn't have access to the
5974 temporary environment, but commands in the subshell should have
5975 access to their own temporary environment. */
5976 if (expanding_redir)
5977 flush_temporary_env ();
5980 #if defined (JOB_CONTROL)
5981 set_sigchld_handler ();
5982 stop_making_children ();
5983 /* XXX - should we only do this in the parent? (as in command subst) */
5984 pipeline_pgrp = old_pipeline_pgrp;
5985 #else
5986 stop_making_children ();
5987 #endif /* JOB_CONTROL */
5989 if (pid < 0)
5991 sys_error ("%s", _("cannot make child for process substitution"));
5992 free (pathname);
5993 #if defined (HAVE_DEV_FD)
5994 close (parent_pipe_fd);
5995 close (child_pipe_fd);
5996 #endif /* HAVE_DEV_FD */
5997 #if defined (JOB_CONTROL)
5998 restore_pipeline (1);
5999 #endif
6000 return ((char *)NULL);
6003 if (pid > 0)
6005 #if defined (JOB_CONTROL)
6006 last_procsub_child = restore_pipeline (0);
6007 /* We assume that last_procsub_child->next == last_procsub_child because
6008 of how jobs.c:add_process() works. */
6009 last_procsub_child->next = 0;
6010 procsub_add (last_procsub_child);
6011 #endif
6013 #if defined (HAVE_DEV_FD)
6014 dev_fd_list[parent_pipe_fd] = pid;
6015 #else
6016 fifo_list[nfifo-1].proc = pid;
6017 #endif
6019 last_made_pid = old_pid;
6021 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6022 close_pgrp_pipe ();
6023 #endif /* JOB_CONTROL && PGRP_PIPE */
6025 #if defined (HAVE_DEV_FD)
6026 close (child_pipe_fd);
6027 #endif /* HAVE_DEV_FD */
6029 return (pathname);
6032 set_sigint_handler ();
6034 #if defined (JOB_CONTROL)
6035 /* make sure we don't have any job control */
6036 set_job_control (0);
6038 /* Clear out any existing list of process substitutions */
6039 procsub_clear ();
6041 /* The idea is that we want all the jobs we start from an async process
6042 substitution to be in the same process group, but not the same pgrp
6043 as our parent shell, since we don't want to affect our parent shell's
6044 jobs if we get a SIGHUP and end up calling hangup_all_jobs, for example.
6045 If pipeline_pgrp != shell_pgrp, we assume that there is a job control
6046 shell somewhere in our parent process chain (since make_child initializes
6047 pipeline_pgrp to shell_pgrp if job_control == 0). What we do in this
6048 case is to set pipeline_pgrp to our PID, so all jobs started by this
6049 process have that same pgrp and we are basically the process group leader.
6050 This should not have negative effects on child processes surviving
6051 after we exit, since we wait for the children we create, but that is
6052 something to watch for. */
6054 if (pipeline_pgrp != shell_pgrp)
6055 pipeline_pgrp = getpid ();
6056 #endif /* JOB_CONTROL */
6058 #if !defined (HAVE_DEV_FD)
6059 /* Open the named pipe in the child. */
6060 fd = open (pathname, open_for_read_in_child ? O_RDONLY : O_WRONLY);
6061 if (fd < 0)
6063 /* Two separate strings for ease of translation. */
6064 if (open_for_read_in_child)
6065 sys_error (_("cannot open named pipe %s for reading"), pathname);
6066 else
6067 sys_error (_("cannot open named pipe %s for writing"), pathname);
6069 exit (127);
6071 if (open_for_read_in_child)
6073 if (sh_unset_nodelay_mode (fd) < 0)
6075 sys_error (_("cannot reset nodelay mode for fd %d"), fd);
6076 exit (127);
6079 #else /* HAVE_DEV_FD */
6080 fd = child_pipe_fd;
6081 #endif /* HAVE_DEV_FD */
6083 /* Discard buffered stdio output before replacing the underlying file
6084 descriptor. */
6085 if (open_for_read_in_child == 0)
6086 fpurge (stdout);
6088 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
6090 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
6091 open_for_read_in_child ? 0 : 1);
6092 exit (127);
6095 if (fd != (open_for_read_in_child ? 0 : 1))
6096 close (fd);
6098 /* Need to close any files that this process has open to pipes inherited
6099 from its parent. */
6100 if (current_fds_to_close)
6102 close_fd_bitmap (current_fds_to_close);
6103 current_fds_to_close = (struct fd_bitmap *)NULL;
6106 #if defined (HAVE_DEV_FD)
6107 /* Make sure we close the parent's end of the pipe and clear the slot
6108 in the fd list so it is not closed later, if reallocated by, for
6109 instance, pipe(2). */
6110 close (parent_pipe_fd);
6111 dev_fd_list[parent_pipe_fd] = 0;
6112 #endif /* HAVE_DEV_FD */
6114 /* subshells shouldn't have this flag, which controls using the temporary
6115 environment for variable lookups. We have already flushed the temporary
6116 environment above in the case we're expanding a redirection, so processes
6117 executed by this command need to be able to set it independently of their
6118 parent. */
6119 expanding_redir = 0;
6121 remove_quoted_escapes (string);
6123 #if 0 /* TAG: bush-5.2 */
6124 startup_state = 2; /* see if we can avoid a fork */
6125 parse_and_execute_level = 0;
6126 #endif
6128 /* Give process substitution a place to jump back to on failure,
6129 so we don't go back up to main (). */
6130 result = setjmp_nosigs (top_level);
6132 /* If we're running a process substitution inside a shell function,
6133 trap `return' so we don't return from the function in the subshell
6134 and go off to never-never land. */
6135 if (result == 0 && return_catch_flag)
6136 function_value = setjmp_nosigs (return_catch);
6137 else
6138 function_value = 0;
6140 if (result == ERREXIT)
6141 rc = last_command_exit_value;
6142 else if (result == EXITPROG)
6143 rc = last_command_exit_value;
6144 else if (result)
6145 rc = EXECUTION_FAILURE;
6146 else if (function_value)
6147 rc = return_catch_value;
6148 else
6150 subshell_level++;
6151 rc = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
6152 /* leave subshell level intact for any exit trap */
6155 #if !defined (HAVE_DEV_FD)
6156 /* Make sure we close the named pipe in the child before we exit. */
6157 close (open_for_read_in_child ? 0 : 1);
6158 #endif /* !HAVE_DEV_FD */
6160 last_command_exit_value = rc;
6161 rc = run_exit_trap ();
6162 exit (rc);
6163 /*NOTREACHED*/
6165 #endif /* PROCESS_SUBSTITUTION */
6167 /***********************************/
6168 /* */
6169 /* Command Substitution */
6170 /* */
6171 /***********************************/
6173 static char *
6174 read_comsub (fd, quoted, flags, rflag)
6175 int fd, quoted, flags;
6176 int *rflag;
6178 char *istring, buf[512], *bufp;
6179 int istring_index, c, tflag, skip_ctlesc, skip_ctlnul;
6180 int mb_cur_max;
6181 size_t istring_size;
6182 ssize_t bufn;
6183 int nullbyte;
6184 #if defined (HANDLE_MULTIBYTE)
6185 mbstate_t ps;
6186 wchar_t wc;
6187 size_t mblen;
6188 int i;
6189 #endif
6191 istring = (char *)NULL;
6192 istring_index = istring_size = bufn = tflag = 0;
6194 skip_ctlesc = ifs_cmap[CTLESC];
6195 skip_ctlnul = ifs_cmap[CTLNUL];
6197 mb_cur_max = MB_CUR_MAX;
6198 nullbyte = 0;
6200 /* Read the output of the command through the pipe. */
6201 while (1)
6203 if (fd < 0)
6204 break;
6205 if (--bufn <= 0)
6207 bufn = zread (fd, buf, sizeof (buf));
6208 if (bufn <= 0)
6209 break;
6210 bufp = buf;
6212 c = *bufp++;
6214 if (c == 0)
6216 #if 1
6217 if (nullbyte == 0)
6219 internal_warning ("%s", _("command substitution: ignored null byte in input"));
6220 nullbyte = 1;
6222 #endif
6223 continue;
6226 /* Add the character to ISTRING, possibly after resizing it. */
6227 RESIZE_MALLOCED_BUFFER (istring, istring_index, mb_cur_max+1, istring_size, 512);
6229 /* This is essentially quote_string inline */
6230 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
6231 istring[istring_index++] = CTLESC;
6232 else if ((flags & PF_ASSIGNRHS) && skip_ctlesc && c == CTLESC)
6233 istring[istring_index++] = CTLESC;
6234 /* Escape CTLESC and CTLNUL in the output to protect those characters
6235 from the rest of the word expansions (word splitting and globbing.)
6236 This is essentially quote_escapes inline. */
6237 else if (skip_ctlesc == 0 && c == CTLESC)
6238 istring[istring_index++] = CTLESC;
6239 else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
6240 istring[istring_index++] = CTLESC;
6242 #if defined (HANDLE_MULTIBYTE)
6243 if ((locale_utf8locale && (c & 0x80)) ||
6244 (locale_utf8locale == 0 && mb_cur_max > 1 && (unsigned char)c > 127))
6246 /* read a multibyte character from buf */
6247 /* punt on the hard case for now */
6248 memset (&ps, '\0', sizeof (mbstate_t));
6249 mblen = mbrtowc (&wc, bufp-1, bufn+1, &ps);
6250 if (MB_INVALIDCH (mblen) || mblen == 0 || mblen == 1)
6251 istring[istring_index++] = c;
6252 else
6254 istring[istring_index++] = c;
6255 for (i = 0; i < mblen-1; i++)
6256 istring[istring_index++] = *bufp++;
6257 bufn -= mblen - 1;
6259 continue;
6261 #endif
6263 istring[istring_index++] = c;
6266 if (istring)
6267 istring[istring_index] = '\0';
6269 /* If we read no output, just return now and save ourselves some
6270 trouble. */
6271 if (istring_index == 0)
6273 FREE (istring);
6274 if (rflag)
6275 *rflag = tflag;
6276 return (char *)NULL;
6279 /* Strip trailing newlines from the output of the command. */
6280 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6282 while (istring_index > 0)
6284 if (istring[istring_index - 1] == '\n')
6286 --istring_index;
6288 /* If the newline was quoted, remove the quoting char. */
6289 if (istring[istring_index - 1] == CTLESC)
6290 --istring_index;
6292 else
6293 break;
6295 istring[istring_index] = '\0';
6297 else
6298 strip_trailing (istring, istring_index - 1, 1);
6300 if (rflag)
6301 *rflag = tflag;
6302 return istring;
6305 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
6306 contained string possibly quoted. */
6307 WORD_DESC *
6308 command_substitute (string, quoted, flags)
6309 char *string;
6310 int quoted;
6311 int flags;
6313 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
6314 char *istring, *s;
6315 int result, fildes[2], function_value, pflags, rc, tflag, fork_flags;
6316 WORD_DESC *ret;
6317 sigset_t set, oset;
6319 istring = (char *)NULL;
6321 /* Don't fork () if there is no need to. In the case of no command to
6322 run, just return NULL. */
6323 #if 1
6324 for (s = string; s && *s && (shellblank (*s) || *s == '\n'); s++)
6326 if (s == 0 || *s == 0)
6327 return ((WORD_DESC *)NULL);
6328 #else
6329 if (!string || !*string || (string[0] == '\n' && !string[1]))
6330 return ((WORD_DESC *)NULL);
6331 #endif
6333 if (wordexp_only && read_but_dont_execute)
6335 last_command_exit_value = EX_WEXPCOMSUB;
6336 jump_to_top_level (EXITPROG);
6339 /* We're making the assumption here that the command substitution will
6340 eventually run a command from the file system. Since we'll run
6341 maybe_make_export_env in this subshell before executing that command,
6342 the parent shell and any other shells it starts will have to remake
6343 the environment. If we make it before we fork, other shells won't
6344 have to. Don't bother if we have any temporary variable assignments,
6345 though, because the export environment will be remade after this
6346 command completes anyway, but do it if all the words to be expanded
6347 are variable assignments. */
6348 if (subst_assign_varlist == 0 || garglist == 0)
6349 maybe_make_export_env (); /* XXX */
6351 /* Flags to pass to parse_and_execute() */
6352 pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0;
6354 old_pid = last_made_pid;
6356 /* Pipe the output of executing STRING into the current shell. */
6357 if (pipe (fildes) < 0)
6359 sys_error ("%s", _("cannot make pipe for command substitution"));
6360 goto error_exit;
6363 #if defined (JOB_CONTROL)
6364 old_pipeline_pgrp = pipeline_pgrp;
6365 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
6366 if ((subshell_environment & SUBSHELL_PIPE) == 0)
6367 pipeline_pgrp = shell_pgrp;
6368 cleanup_the_pipeline ();
6369 #endif /* JOB_CONTROL */
6371 old_async_pid = last_asynchronous_pid;
6372 fork_flags = (subshell_environment&SUBSHELL_ASYNC) ? FORK_ASYNC : 0;
6373 pid = make_child ((char *)NULL, fork_flags|FORK_NOTERM);
6374 last_asynchronous_pid = old_async_pid;
6376 if (pid == 0)
6378 /* Reset the signal handlers in the child, but don't free the
6379 trap strings. Set a flag noting that we have to free the
6380 trap strings if we run trap to change a signal disposition. */
6381 reset_signal_handlers ();
6382 if (ISINTERRUPT)
6384 kill (getpid (), SIGINT);
6385 CLRINTERRUPT; /* if we're ignoring SIGINT somehow */
6387 QUIT; /* catch any interrupts we got post-fork */
6388 subshell_environment |= SUBSHELL_RESETTRAP;
6391 #if defined (JOB_CONTROL)
6392 /* XXX DO THIS ONLY IN PARENT ? XXX */
6393 set_sigchld_handler ();
6394 stop_making_children ();
6395 if (pid != 0)
6396 pipeline_pgrp = old_pipeline_pgrp;
6397 #else
6398 stop_making_children ();
6399 #endif /* JOB_CONTROL */
6401 if (pid < 0)
6403 sys_error (_("cannot make child for command substitution"));
6404 error_exit:
6406 last_made_pid = old_pid;
6408 FREE (istring);
6409 close (fildes[0]);
6410 close (fildes[1]);
6411 return ((WORD_DESC *)NULL);
6414 if (pid == 0)
6416 /* The currently executing shell is not interactive. */
6417 interactive = 0;
6419 set_sigint_handler (); /* XXX */
6421 free_pushed_string_input ();
6423 /* Discard buffered stdio output before replacing the underlying file
6424 descriptor. */
6425 fpurge (stdout);
6427 if (dup2 (fildes[1], 1) < 0)
6429 sys_error ("%s", _("command_substitute: cannot duplicate pipe as fd 1"));
6430 exit (EXECUTION_FAILURE);
6433 /* If standard output is closed in the parent shell
6434 (such as after `exec >&-'), file descriptor 1 will be
6435 the lowest available file descriptor, and end up in
6436 fildes[0]. This can happen for stdin and stderr as well,
6437 but stdout is more important -- it will cause no output
6438 to be generated from this command. */
6439 if ((fildes[1] != fileno (stdin)) &&
6440 (fildes[1] != fileno (stdout)) &&
6441 (fildes[1] != fileno (stderr)))
6442 close (fildes[1]);
6444 if ((fildes[0] != fileno (stdin)) &&
6445 (fildes[0] != fileno (stdout)) &&
6446 (fildes[0] != fileno (stderr)))
6447 close (fildes[0]);
6449 #ifdef __CYGWIN__
6450 /* Let stdio know the fd may have changed from text to binary mode, and
6451 make sure to preserve stdout line buffering. */
6452 freopen (NULL, "w", stdout);
6453 sh_setlinebuf (stdout);
6454 #endif /* __CYGWIN__ */
6456 /* This is a subshell environment. */
6457 subshell_environment |= SUBSHELL_COMSUB;
6459 /* Many shells do not appear to inherit the -v option for command
6460 substitutions. */
6461 change_flag ('v', FLAG_OFF);
6463 /* When inherit_errexit option is not enabled, command substitution does
6464 not inherit the -e flag. It is enabled when Posix mode is enabled */
6465 if (inherit_errexit == 0)
6467 builtin_ignoring_errexit = 0;
6468 change_flag ('e', FLAG_OFF);
6470 set_shellopts ();
6472 /* If we are expanding a redirection, we can dispose of any temporary
6473 environment we received, since redirections are not supposed to have
6474 access to the temporary environment. We will have to see whether this
6475 affects temporary environments supplied to `eval', but the temporary
6476 environment gets copied to builtin_env at some point. */
6477 if (expanding_redir)
6479 flush_temporary_env ();
6480 expanding_redir = 0;
6483 remove_quoted_escapes (string);
6485 startup_state = 2; /* see if we can avoid a fork */
6486 parse_and_execute_level = 0;
6488 /* Give command substitution a place to jump back to on failure,
6489 so we don't go back up to main (). */
6490 result = setjmp_nosigs (top_level);
6492 /* If we're running a command substitution inside a shell function,
6493 trap `return' so we don't return from the function in the subshell
6494 and go off to never-never land. */
6495 if (result == 0 && return_catch_flag)
6496 function_value = setjmp_nosigs (return_catch);
6497 else
6498 function_value = 0;
6500 if (result == ERREXIT)
6501 rc = last_command_exit_value;
6502 else if (result == EXITPROG)
6503 rc = last_command_exit_value;
6504 else if (result)
6505 rc = EXECUTION_FAILURE;
6506 else if (function_value)
6507 rc = return_catch_value;
6508 else
6510 subshell_level++;
6511 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
6512 /* leave subshell level intact for any exit trap */
6515 last_command_exit_value = rc;
6516 rc = run_exit_trap ();
6517 #if defined (PROCESS_SUBSTITUTION)
6518 unlink_fifo_list ();
6519 #endif
6520 exit (rc);
6522 else
6524 int dummyfd;
6526 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
6527 close_pgrp_pipe ();
6528 #endif /* JOB_CONTROL && PGRP_PIPE */
6530 close (fildes[1]);
6532 begin_unwind_frame ("read-comsub");
6533 dummyfd = fildes[0];
6534 add_unwind_protect (close, dummyfd);
6536 /* Block SIGINT while we're reading from the pipe. If the child
6537 process gets a SIGINT, it will either handle it or die, and the
6538 read will return. */
6539 BLOCK_SIGNAL (SIGINT, set, oset);
6540 tflag = 0;
6541 istring = read_comsub (fildes[0], quoted, flags, &tflag);
6543 close (fildes[0]);
6544 discard_unwind_frame ("read-comsub");
6545 UNBLOCK_SIGNAL (oset);
6547 current_command_subst_pid = pid;
6548 last_command_exit_value = wait_for (pid, JWAIT_NOTERM);
6549 last_command_subst_pid = pid;
6550 last_made_pid = old_pid;
6552 #if defined (JOB_CONTROL)
6553 /* If last_command_exit_value > 128, then the substituted command
6554 was terminated by a signal. If that signal was SIGINT, then send
6555 SIGINT to ourselves. This will break out of loops, for instance. */
6556 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
6557 kill (getpid (), SIGINT);
6558 #endif /* JOB_CONTROL */
6560 ret = alloc_word_desc ();
6561 ret->word = istring;
6562 ret->flags = tflag;
6564 return ret;
6568 /********************************************************
6570 * Utility functions for parameter expansion *
6572 ********************************************************/
6574 #if defined (ARRAY_VARS)
6576 static arrayind_t
6577 array_length_reference (s)
6578 char *s;
6580 int len;
6581 arrayind_t ind;
6582 char *akey;
6583 char *t, c;
6584 ARRAY *array;
6585 HASH_TABLE *h;
6586 SHELL_VAR *var;
6588 var = array_variable_part (s, 0, &t, &len);
6590 /* If unbound variables should generate an error, report one and return
6591 failure. */
6592 if ((var == 0 || invisible_p (var) || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
6594 c = *--t;
6595 *t = '\0';
6596 set_exit_status (EXECUTION_FAILURE);
6597 err_unboundvar (s);
6598 *t = c;
6599 return (-1);
6601 else if (var == 0 || invisible_p (var))
6602 return 0;
6604 /* We support a couple of expansions for variables that are not arrays.
6605 We'll return the length of the value for v[0], and 1 for v[@] or
6606 v[*]. Return 0 for everything else. */
6608 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
6609 h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
6611 if (ALL_ELEMENT_SUB (t[0]) && t[1] == RBRACK)
6613 if (assoc_p (var))
6614 return (h ? assoc_num_elements (h) : 0);
6615 else if (array_p (var))
6616 return (array ? array_num_elements (array) : 0);
6617 else
6618 return (var_isset (var) ? 1 : 0);
6621 if (assoc_p (var))
6623 t[len - 1] = '\0';
6624 akey = expand_assignment_string_to_string (t, 0); /* [ */
6625 t[len - 1] = RBRACK;
6626 if (akey == 0 || *akey == 0)
6628 err_badarraysub (t);
6629 FREE (akey);
6630 return (-1);
6632 t = assoc_reference (assoc_cell (var), akey);
6633 free (akey);
6635 else
6637 ind = array_expand_index (var, t, len, 0);
6638 /* negative subscripts to indexed arrays count back from end */
6639 if (var && array_p (var) && ind < 0)
6640 ind = array_max_index (array_cell (var)) + 1 + ind;
6641 if (ind < 0)
6643 err_badarraysub (t);
6644 return (-1);
6646 if (array_p (var))
6647 t = array_reference (array, ind);
6648 else
6649 t = (ind == 0) ? value_cell (var) : (char *)NULL;
6652 len = MB_STRLEN (t);
6653 return (len);
6655 #endif /* ARRAY_VARS */
6657 static int
6658 valid_brace_expansion_word (name, var_is_special)
6659 char *name;
6660 int var_is_special;
6662 if (DIGIT (*name) && all_digits (name))
6663 return 1;
6664 else if (var_is_special)
6665 return 1;
6666 #if defined (ARRAY_VARS)
6667 else if (valid_array_reference (name, 0))
6668 return 1;
6669 #endif /* ARRAY_VARS */
6670 else if (legal_identifier (name))
6671 return 1;
6672 else
6673 return 0;
6676 static int
6677 chk_atstar (name, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
6678 char *name;
6679 int quoted, pflags;
6680 int *quoted_dollar_atp, *contains_dollar_at;
6682 char *temp1;
6684 if (name == 0)
6686 if (quoted_dollar_atp)
6687 *quoted_dollar_atp = 0;
6688 if (contains_dollar_at)
6689 *contains_dollar_at = 0;
6690 return 0;
6693 /* check for $@ and $* */
6694 if (name[0] == '@' && name[1] == 0)
6696 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6697 *quoted_dollar_atp = 1;
6698 if (contains_dollar_at)
6699 *contains_dollar_at = 1;
6700 return 1;
6702 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
6704 /* Need more checks here that parallel what string_list_pos_params and
6705 param_expand do. Check expand_no_split_dollar_star and ??? */
6706 if (contains_dollar_at && expand_no_split_dollar_star == 0)
6707 *contains_dollar_at = 1;
6708 return 1;
6711 /* Now check for ${array[@]} and ${array[*]} */
6712 #if defined (ARRAY_VARS)
6713 else if (valid_array_reference (name, 0))
6715 temp1 = mbschr (name, LBRACK);
6716 if (temp1 && temp1[1] == '@' && temp1[2] == RBRACK)
6718 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6719 *quoted_dollar_atp = 1;
6720 if (contains_dollar_at)
6721 *contains_dollar_at = 1;
6722 return 1;
6724 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
6725 which should result in separate words even when IFS is unset. */
6726 if (temp1 && temp1[1] == '*' && temp1[2] == RBRACK && quoted == 0)
6728 if (contains_dollar_at)
6729 *contains_dollar_at = 1;
6730 return 1;
6733 #endif
6734 return 0;
6737 /* Parameter expand NAME, and return a new string which is the expansion,
6738 or NULL if there was no expansion. NAME is as given in ${NAMEcWORD}.
6739 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
6740 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
6741 NAME was found inside of a double-quoted expression. */
6742 static WORD_DESC *
6743 parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp)
6744 char *name;
6745 int var_is_special, quoted, pflags;
6746 arrayind_t *indp;
6748 WORD_DESC *ret;
6749 char *temp, *tt;
6750 intmax_t arg_index;
6751 SHELL_VAR *var;
6752 int atype, rflags;
6753 arrayind_t ind;
6755 ret = 0;
6756 temp = 0;
6757 rflags = 0;
6759 if (indp)
6760 *indp = INTMAX_MIN;
6762 /* Handle multiple digit arguments, as in ${11}. */
6763 if (legal_number (name, &arg_index))
6765 tt = get_dollar_var_value (arg_index);
6766 if (tt)
6767 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6768 ? quote_string (tt)
6769 : quote_escapes (tt);
6770 else
6771 temp = (char *)NULL;
6772 FREE (tt);
6774 else if (var_is_special) /* ${@} */
6776 int sindex;
6777 tt = (char *)xmalloc (2 + strlen (name));
6778 tt[sindex = 0] = '$';
6779 strcpy (tt + 1, name);
6781 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
6782 (int *)NULL, (int *)NULL, pflags);
6783 free (tt);
6785 #if defined (ARRAY_VARS)
6786 else if (valid_array_reference (name, 0))
6788 expand_arrayref:
6789 var = array_variable_part (name, 0, &tt, (int *)0);
6790 /* These are the cases where word splitting will not be performed */
6791 if (pflags & PF_ASSIGNRHS)
6793 if (ALL_ELEMENT_SUB (tt[0]) && tt[1] == RBRACK)
6795 /* Only treat as double quoted if array variable */
6796 if (var && (array_p (var) || assoc_p (var)))
6797 temp = array_value (name, quoted|Q_DOUBLE_QUOTES, AV_ASSIGNRHS, &atype, &ind);
6798 else
6799 temp = array_value (name, quoted, 0, &atype, &ind);
6801 else
6802 temp = array_value (name, quoted, 0, &atype, &ind);
6804 /* Posix interp 888 */
6805 else if (pflags & PF_NOSPLIT2)
6807 /* Special cases, then general case, for each of A[@], A[*], A[n] */
6808 #if defined (HANDLE_MULTIBYTE)
6809 if (tt[0] == '@' && tt[1] == RBRACK && var && quoted == 0 && ifs_is_set && ifs_is_null == 0 && ifs_firstc[0] != ' ')
6810 #else
6811 if (tt[0] == '@' && tt[1] == RBRACK && var && quoted == 0 && ifs_is_set && ifs_is_null == 0 && ifs_firstc != ' ')
6812 #endif
6813 temp = array_value (name, Q_DOUBLE_QUOTES, AV_ASSIGNRHS, &atype, &ind);
6814 else if (tt[0] == '@' && tt[1] == RBRACK)
6815 temp = array_value (name, quoted, 0, &atype, &ind);
6816 else if (tt[0] == '*' && tt[1] == RBRACK && expand_no_split_dollar_star && ifs_is_null)
6817 temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &atype, &ind);
6818 else if (tt[0] == '*' && tt[1] == RBRACK)
6819 temp = array_value (name, quoted, 0, &atype, &ind);
6820 else
6821 temp = array_value (name, quoted, 0, &atype, &ind);
6823 else if (tt[0] == '*' && tt[1] == RBRACK && expand_no_split_dollar_star && ifs_is_null)
6824 temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &atype, &ind);
6825 else
6826 temp = array_value (name, quoted, 0, &atype, &ind);
6827 if (atype == 0 && temp)
6829 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6830 ? quote_string (temp)
6831 : quote_escapes (temp);
6832 rflags |= W_ARRAYIND;
6833 if (indp)
6834 *indp = ind;
6836 else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6837 rflags |= W_HASQUOTEDNULL;
6839 #endif
6840 else if (var = find_variable (name))
6842 if (var_isset (var) && invisible_p (var) == 0)
6844 #if defined (ARRAY_VARS)
6845 /* We avoid a memory leak by saving TT as the memory allocated by
6846 assoc_to_string or array_to_string and leaving it 0 otherwise,
6847 then freeing TT after quoting temp. */
6848 tt = (char *)NULL;
6849 if ((pflags & PF_ALLINDS) && assoc_p (var))
6850 tt = temp = assoc_empty (assoc_cell (var)) ? (char *)NULL : assoc_to_string (assoc_cell (var), " ", quoted);
6851 else if ((pflags & PF_ALLINDS) && array_p (var))
6852 tt = temp = array_empty (array_cell (var)) ? (char *)NULL : array_to_string (array_cell (var), " ", quoted);
6853 else if (assoc_p (var))
6854 temp = assoc_reference (assoc_cell (var), "0");
6855 else if (array_p (var))
6856 temp = array_reference (array_cell (var), 0);
6857 else
6858 temp = value_cell (var);
6859 #else
6860 temp = value_cell (var);
6861 #endif
6863 if (temp)
6864 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6865 ? quote_string (temp)
6866 : ((pflags & PF_ASSIGNRHS) ? quote_rhs (temp)
6867 : quote_escapes (temp));
6868 FREE (tt);
6870 else
6871 temp = (char *)NULL;
6873 else if (var = find_variable_last_nameref (name, 0))
6875 temp = nameref_cell (var);
6876 #if defined (ARRAY_VARS)
6877 /* Handle expanding nameref whose value is x[n] */
6878 if (temp && *temp && valid_array_reference (temp, 0))
6880 name = temp;
6881 goto expand_arrayref;
6883 else
6884 #endif
6885 /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
6886 if (temp && *temp && legal_identifier (temp) == 0)
6888 set_exit_status (EXECUTION_FAILURE);
6889 report_error (_("%s: invalid variable name for name reference"), temp);
6890 temp = &expand_param_error;
6892 else
6893 temp = (char *)NULL;
6895 else
6896 temp = (char *)NULL;
6898 if (ret == 0)
6900 ret = alloc_word_desc ();
6901 ret->word = temp;
6902 ret->flags |= rflags;
6904 return ret;
6907 static char *
6908 parameter_brace_find_indir (name, var_is_special, quoted, find_nameref)
6909 char *name;
6910 int var_is_special, quoted, find_nameref;
6912 char *temp, *t;
6913 WORD_DESC *w;
6914 SHELL_VAR *v;
6915 int pflags, oldex;
6917 if (find_nameref && var_is_special == 0 && (v = find_variable_last_nameref (name, 0)) &&
6918 nameref_p (v) && (t = nameref_cell (v)) && *t)
6919 return (savestring (t));
6921 /* If var_is_special == 0, and name is not an array reference, this does
6922 more expansion than necessary. It should really look up the variable's
6923 value and not try to expand it. */
6924 pflags = PF_IGNUNBOUND;
6925 /* Note that we're not going to be doing word splitting here */
6926 if (var_is_special)
6928 pflags |= PF_ASSIGNRHS; /* suppresses word splitting */
6929 oldex = expand_no_split_dollar_star;
6930 expand_no_split_dollar_star = 1;
6932 w = parameter_brace_expand_word (name, var_is_special, quoted, pflags, 0);
6933 if (var_is_special)
6934 expand_no_split_dollar_star = oldex;
6936 t = w->word;
6937 /* Have to dequote here if necessary */
6938 if (t)
6940 temp = ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || var_is_special)
6941 ? dequote_string (t)
6942 : dequote_escapes (t);
6943 free (t);
6944 t = temp;
6946 dispose_word_desc (w);
6948 return t;
6951 /* Expand an indirect reference to a variable: ${!NAME} expands to the
6952 value of the variable whose name is the value of NAME. */
6953 static WORD_DESC *
6954 parameter_brace_expand_indir (name, var_is_special, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
6955 char *name;
6956 int var_is_special, quoted, pflags;
6957 int *quoted_dollar_atp, *contains_dollar_at;
6959 char *t;
6960 WORD_DESC *w;
6961 SHELL_VAR *v;
6963 /* See if it's a nameref first, behave in ksh93-compatible fashion.
6964 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
6965 bush performs an indirect lookup on foo[0] and expands the result;
6966 ksh93 expands bar[0]. We could do that here -- there are enough usable
6967 primitives to do that -- but do not at this point. */
6968 if (var_is_special == 0 && (v = find_variable_last_nameref (name, 0)))
6970 if (nameref_p (v) && (t = nameref_cell (v)) && *t)
6972 w = alloc_word_desc ();
6973 w->word = savestring (t);
6974 w->flags = 0;
6975 return w;
6979 /* An indirect reference to a positional parameter or a special parameter
6980 is ok. Indirect references to array references, as explained above, are
6981 ok (currently). Only references to unset variables are errors at this
6982 point. */
6983 if (legal_identifier (name) && v == 0)
6985 report_error (_("%s: invalid indirect expansion"), name);
6986 w = alloc_word_desc ();
6987 w->word = &expand_param_error;
6988 w->flags = 0;
6989 return (w);
6992 t = parameter_brace_find_indir (name, var_is_special, quoted, 0);
6994 chk_atstar (t, quoted, pflags, quoted_dollar_atp, contains_dollar_at);
6996 #if defined (ARRAY_VARS)
6997 /* Array references to unset variables are also an error */
6998 if (t == 0 && valid_array_reference (name, 0))
7000 v = array_variable_part (name, 0, (char **)0, (int *)0);
7001 if (v == 0)
7003 report_error (_("%s: invalid indirect expansion"), name);
7004 w = alloc_word_desc ();
7005 w->word = &expand_param_error;
7006 w->flags = 0;
7007 return (w);
7009 else
7010 return (WORD_DESC *)NULL;
7012 #endif
7014 if (t == 0)
7015 return (WORD_DESC *)NULL;
7017 if (valid_brace_expansion_word (t, SPECIAL_VAR (t, 0)) == 0)
7019 report_error (_("%s: invalid variable name"), t);
7020 free (t);
7021 w = alloc_word_desc ();
7022 w->word = &expand_param_error;
7023 w->flags = 0;
7024 return (w);
7027 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, pflags, 0);
7028 free (t);
7030 return w;
7033 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
7034 depending on the value of C, the separating character. C can be one of
7035 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
7036 between double quotes. */
7037 static WORD_DESC *
7038 parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdollarat)
7039 char *name, *value;
7040 int op, quoted, pflags, *qdollaratp, *hasdollarat;
7042 WORD_DESC *w;
7043 WORD_LIST *l, *tl;
7044 char *t, *t1, *temp, *vname;
7045 int l_hasdollat, sindex;
7046 SHELL_VAR *v;
7048 /*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
7049 /* If the entire expression is between double quotes, we want to treat
7050 the value as a double-quoted string, with the exception that we strip
7051 embedded unescaped double quotes (for sh backwards compatibility). */
7052 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
7054 sindex = 0;
7055 temp = string_extract_double_quoted (value, &sindex, SX_STRIPDQ);
7057 else
7058 temp = value;
7060 w = alloc_word_desc ();
7061 l_hasdollat = 0;
7062 l = *temp ? expand_string_for_rhs (temp, quoted, op, pflags, &l_hasdollat, (int *)NULL)
7063 : (WORD_LIST *)0;
7064 if (hasdollarat)
7065 *hasdollarat = l_hasdollat || (l && l->next);
7066 if (temp != value)
7067 free (temp);
7069 /* list_string takes multiple CTLNULs and turns them into an empty word
7070 with W_SAWQUOTEDNULL set. Turn it back into a single CTLNUL for the
7071 rest of this function and the caller. */
7072 for (tl = l; tl; tl = tl->next)
7074 if (tl->word && (tl->word->word == 0 || tl->word->word[0] == 0) &&
7075 (tl->word->flags | W_SAWQUOTEDNULL))
7077 t = make_quoted_char ('\0');
7078 FREE (tl->word->word);
7079 tl->word->word = t;
7080 tl->word->flags |= W_QUOTED|W_HASQUOTEDNULL;
7081 tl->word->flags &= ~W_SAWQUOTEDNULL;
7085 if (l)
7087 /* If l->next is not null, we know that TEMP contained "$@", since that
7088 is the only expansion that creates more than one word. */
7089 if (qdollaratp && ((l_hasdollat && quoted) || l->next))
7091 /*itrace("parameter_brace_expand_rhs: %s:%s: l != NULL, set *qdollaratp", name, value);*/
7092 *qdollaratp = 1;
7095 /* The expansion of TEMP returned something. We need to treat things
7096 slightly differently if L_HASDOLLAT is non-zero. If we have "$@",
7097 the individual words have already been quoted. We need to turn them
7098 into a string with the words separated by the first character of
7099 $IFS without any additional quoting, so string_list_dollar_at won't
7100 do the right thing. If IFS is null, we want "$@" to split into
7101 separate arguments, not be concatenated, so we use string_list_internal
7102 and mark the word to be split on spaces later. We use
7103 string_list_dollar_star for "$@" otherwise. */
7104 if (l->next && ifs_is_null)
7106 temp = string_list_internal (l, " ");
7107 w->flags |= W_SPLITSPACE;
7109 else if (l_hasdollat || l->next)
7110 temp = string_list_dollar_star (l, quoted, 0);
7111 else
7113 temp = string_list (l);
7114 if (temp && (QUOTED_NULL (temp) == 0) && (l->word->flags & W_SAWQUOTEDNULL))
7115 w->flags |= W_SAWQUOTEDNULL; /* XXX */
7118 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
7119 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
7120 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
7121 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7122 (which is more paranoia than anything else), we need to return the
7123 quoted null string and set the flags to indicate it. */
7124 if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL))
7126 w->flags |= W_HASQUOTEDNULL;
7127 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null, turning off qdollaratp", name, value);*/
7128 /* If we return a quoted null with L_HASDOLLARAT, we either have a
7129 construct like "${@-$@}" or "${@-${@-$@}}" with no positional
7130 parameters or a quoted expansion of "$@" with $1 == ''. In either
7131 case, we don't want to enable special handling of $@. */
7132 if (qdollaratp && l_hasdollat)
7133 *qdollaratp = 0;
7135 dispose_words (l);
7137 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && l_hasdollat)
7139 /* Posix interp 221 changed the rules on this. The idea is that
7140 something like "$xxx$@" should expand the same as "${foo-$xxx$@}"
7141 when foo and xxx are unset. The problem is that it's not in any
7142 way backwards compatible and few other shells do it. We're eventually
7143 going to try and split the difference (heh) a little bit here. */
7144 /* l_hasdollat == 1 means we saw a quoted dollar at. */
7146 /* The brace expansion occurred between double quotes and there was
7147 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
7148 it does not expand to anything. In this case, we want to return
7149 a quoted empty string. Posix interp 888 */
7150 temp = make_quoted_char ('\0');
7151 w->flags |= W_HASQUOTEDNULL;
7152 /*itrace("parameter_brace_expand_rhs (%s:%s): returning quoted null", name, value);*/
7154 else
7155 temp = (char *)NULL;
7157 if (op == '-' || op == '+')
7159 w->word = temp;
7160 return w;
7163 /* op == '=' */
7164 t1 = temp ? dequote_string (temp) : savestring ("");
7165 free (temp);
7167 /* bush-4.4/5.0 */
7168 vname = name;
7169 if (*name == '!' &&
7170 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1]) || VALID_INDIR_PARAM (name[1])))
7172 vname = parameter_brace_find_indir (name + 1, SPECIAL_VAR (name, 1), quoted, 1);
7173 if (vname == 0 || *vname == 0)
7175 report_error (_("%s: invalid indirect expansion"), name);
7176 free (vname);
7177 free (t1);
7178 dispose_word (w);
7179 return &expand_wdesc_error;
7181 if (legal_identifier (vname) == 0)
7183 report_error (_("%s: invalid variable name"), vname);
7184 free (vname);
7185 free (t1);
7186 dispose_word (w);
7187 return &expand_wdesc_error;
7191 #if defined (ARRAY_VARS)
7192 if (valid_array_reference (vname, 0))
7193 v = assign_array_element (vname, t1, 0);
7194 else
7195 #endif /* ARRAY_VARS */
7196 v = bind_variable (vname, t1, 0);
7198 if (v == 0 || readonly_p (v) || noassign_p (v)) /* expansion error */
7200 if ((v == 0 || readonly_p (v)) && interactive_shell == 0 && posixly_correct)
7202 last_command_exit_value = EXECUTION_FAILURE;
7203 exp_jump_to_top_level (FORCE_EOF);
7205 else
7207 if (vname != name)
7208 free (vname);
7209 last_command_exit_value = EX_BADUSAGE;
7210 exp_jump_to_top_level (DISCARD);
7214 stupidly_hack_special_variables (vname);
7216 if (vname != name)
7217 free (vname);
7219 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
7221 /* If we are double-quoted or if we are not going to be performing word
7222 splitting, we want to quote the value we return appropriately, like
7223 the other expansions this function handles. */
7224 w->word = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) ? quote_string (t1) : quote_escapes (t1);
7225 /* If we have something that's non-null, that's not a quoted null string,
7226 and we're not going to be performing word splitting (we know we're not
7227 because the operator is `='), we can forget we saw a quoted null. */
7228 if (w->word && w->word[0] && QUOTED_NULL (w->word) == 0)
7229 w->flags &= ~W_SAWQUOTEDNULL;
7230 free (t1);
7232 /* If we convert a null string into a quoted null, make sure the caller
7233 knows it. */
7234 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) && QUOTED_NULL (w->word))
7235 w->flags |= W_HASQUOTEDNULL;
7237 return w;
7240 /* Deal with the right hand side of a ${name:?value} expansion in the case
7241 that NAME is null or not set. If VALUE is non-null it is expanded and
7242 used as the error message to print, otherwise a standard message is
7243 printed. */
7244 static void
7245 parameter_brace_expand_error (name, value, check_null)
7246 char *name, *value;
7247 int check_null;
7249 WORD_LIST *l;
7250 char *temp;
7252 set_exit_status (EXECUTION_FAILURE); /* ensure it's non-zero */
7253 if (value && *value)
7255 l = expand_string (value, 0);
7256 temp = string_list (l);
7257 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
7258 FREE (temp);
7259 dispose_words (l);
7261 else if (check_null == 0)
7262 report_error (_("%s: parameter not set"), name);
7263 else
7264 report_error (_("%s: parameter null or not set"), name);
7266 /* Free the data we have allocated during this expansion, since we
7267 are about to longjmp out. */
7268 free (name);
7269 FREE (value);
7272 /* Return 1 if NAME is something for which parameter_brace_expand_length is
7273 OK to do. */
7274 static int
7275 valid_length_expression (name)
7276 char *name;
7278 return (name[1] == '\0' || /* ${#} */
7279 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
7280 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
7281 #if defined (ARRAY_VARS)
7282 valid_array_reference (name + 1, 0) || /* ${#a[7]} */
7283 #endif
7284 legal_identifier (name + 1)); /* ${#PS1} */
7287 /* Handle the parameter brace expansion that requires us to return the
7288 length of a parameter. */
7289 static intmax_t
7290 parameter_brace_expand_length (name)
7291 char *name;
7293 char *t, *newname;
7294 intmax_t number, arg_index;
7295 WORD_LIST *list;
7296 SHELL_VAR *var;
7298 var = (SHELL_VAR *)NULL;
7300 if (name[1] == '\0') /* ${#} */
7301 number = number_of_args ();
7302 else if (DOLLAR_AT_STAR (name[1]) && name[2] == '\0') /* ${#@}, ${#*} */
7303 number = number_of_args ();
7304 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
7306 /* Take the lengths of some of the shell's special parameters. */
7307 switch (name[1])
7309 case '-':
7310 t = which_set_flags ();
7311 break;
7312 case '?':
7313 t = itos (last_command_exit_value);
7314 break;
7315 case '$':
7316 t = itos (dollar_dollar_pid);
7317 break;
7318 case '!':
7319 if (last_asynchronous_pid == NO_PID)
7320 t = (char *)NULL; /* XXX - error if set -u set? */
7321 else
7322 t = itos (last_asynchronous_pid);
7323 break;
7324 case '#':
7325 t = itos (number_of_args ());
7326 break;
7328 number = STRLEN (t);
7329 FREE (t);
7331 #if defined (ARRAY_VARS)
7332 else if (valid_array_reference (name + 1, 0))
7333 number = array_length_reference (name + 1);
7334 #endif /* ARRAY_VARS */
7335 else
7337 number = 0;
7339 if (legal_number (name + 1, &arg_index)) /* ${#1} */
7341 t = get_dollar_var_value (arg_index);
7342 if (t == 0 && unbound_vars_is_error)
7343 return INTMAX_MIN;
7344 number = MB_STRLEN (t);
7345 FREE (t);
7347 #if defined (ARRAY_VARS)
7348 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
7350 if (assoc_p (var))
7351 t = assoc_reference (assoc_cell (var), "0");
7352 else
7353 t = array_reference (array_cell (var), 0);
7354 if (t == 0 && unbound_vars_is_error)
7355 return INTMAX_MIN;
7356 number = MB_STRLEN (t);
7358 #endif
7359 /* Fast path for the common case of taking the length of a non-dynamic
7360 scalar variable value. */
7361 else if ((var || (var = find_variable (name + 1))) &&
7362 invisible_p (var) == 0 &&
7363 array_p (var) == 0 && assoc_p (var) == 0 &&
7364 var->dynamic_value == 0)
7365 number = value_cell (var) ? MB_STRLEN (value_cell (var)) : 0;
7366 else if (var == 0 && unbound_vars_is_error == 0)
7367 number = 0;
7368 else /* ${#PS1} */
7370 newname = savestring (name);
7371 newname[0] = '$';
7372 list = expand_string (newname, Q_DOUBLE_QUOTES);
7373 t = list ? string_list (list) : (char *)NULL;
7374 free (newname);
7375 if (list)
7376 dispose_words (list);
7378 number = t ? MB_STRLEN (t) : 0;
7379 FREE (t);
7383 return (number);
7386 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
7387 so we do some ad-hoc parsing of an arithmetic expression to find
7388 the first DELIM, instead of using strchr(3). Two rules:
7389 1. If the substring contains a `(', read until closing `)'.
7390 2. If the substring contains a `?', read past one `:' for each `?'.
7391 The SD_ARITHEXP flag to skip_to_delim takes care of doing this.
7394 static char *
7395 skiparith (substr, delim)
7396 char *substr;
7397 int delim;
7399 int i;
7400 char delims[2];
7402 delims[0] = delim;
7403 delims[1] = '\0';
7405 i = skip_to_delim (substr, 0, delims, SD_ARITHEXP);
7406 return (substr + i);
7409 /* Verify and limit the start and end of the desired substring. If
7410 VTYPE == 0, a regular shell variable is being used; if it is 1,
7411 then the positional parameters are being used; if it is 2, then
7412 VALUE is really a pointer to an array variable that should be used.
7413 Return value is 1 if both values were OK, 0 if there was a problem
7414 with an invalid expression, or -1 if the values were out of range. */
7415 static int
7416 verify_substring_values (v, value, substr, vtype, e1p, e2p)
7417 SHELL_VAR *v;
7418 char *value, *substr;
7419 int vtype;
7420 intmax_t *e1p, *e2p;
7422 char *t, *temp1, *temp2;
7423 arrayind_t len;
7424 int expok;
7425 #if defined (ARRAY_VARS)
7426 ARRAY *a;
7427 HASH_TABLE *h;
7428 #endif
7430 /* duplicate behavior of strchr(3) */
7431 t = skiparith (substr, ':');
7432 if (*t && *t == ':')
7433 *t = '\0';
7434 else
7435 t = (char *)0;
7437 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
7438 *e1p = evalexp (temp1, 0, &expok); /* XXX - EXP_EXPANDED? */
7439 free (temp1);
7440 if (expok == 0)
7441 return (0);
7443 len = -1; /* paranoia */
7444 switch (vtype)
7446 case VT_VARIABLE:
7447 case VT_ARRAYMEMBER:
7448 len = MB_STRLEN (value);
7449 break;
7450 case VT_POSPARMS:
7451 len = number_of_args () + 1;
7452 if (*e1p == 0)
7453 len++; /* add one arg if counting from $0 */
7454 break;
7455 #if defined (ARRAY_VARS)
7456 case VT_ARRAYVAR:
7457 /* For arrays, the first value deals with array indices. Negative
7458 offsets count from one past the array's maximum index. Associative
7459 arrays treat the number of elements as the maximum index. */
7460 if (assoc_p (v))
7462 h = assoc_cell (v);
7463 len = assoc_num_elements (h) + (*e1p < 0);
7465 else
7467 a = (ARRAY *)value;
7468 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
7470 break;
7471 #endif
7474 if (len == -1) /* paranoia */
7475 return -1;
7477 if (*e1p < 0) /* negative offsets count from end */
7478 *e1p += len;
7480 if (*e1p > len || *e1p < 0)
7481 return (-1);
7483 #if defined (ARRAY_VARS)
7484 /* For arrays, the second offset deals with the number of elements. */
7485 if (vtype == VT_ARRAYVAR)
7486 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
7487 #endif
7489 if (t)
7491 t++;
7492 temp2 = savestring (t);
7493 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7494 free (temp2);
7495 t[-1] = ':';
7496 *e2p = evalexp (temp1, 0, &expok); /* XXX - EXP_EXPANDED? */
7497 free (temp1);
7498 if (expok == 0)
7499 return (0);
7501 /* Should we allow positional parameter length < 0 to count backwards
7502 from end of positional parameters? */
7503 #if 1
7504 if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0)
7505 #else /* TAG: bush-5.2 */
7506 if (vtype == VT_ARRAYVAR && *e2p < 0)
7507 #endif
7509 internal_error (_("%s: substring expression < 0"), t);
7510 return (0);
7512 #if defined (ARRAY_VARS)
7513 /* In order to deal with sparse arrays, push the intelligence about how
7514 to deal with the number of elements desired down to the array-
7515 specific functions. */
7516 if (vtype != VT_ARRAYVAR)
7517 #endif
7519 if (*e2p < 0)
7521 *e2p += len;
7522 if (*e2p < 0 || *e2p < *e1p)
7524 internal_error (_("%s: substring expression < 0"), t);
7525 return (0);
7528 else
7529 *e2p += *e1p; /* want E2 chars starting at E1 */
7530 if (*e2p > len)
7531 *e2p = len;
7534 else
7535 *e2p = len;
7537 return (1);
7540 /* Return the type of variable specified by VARNAME (simple variable,
7541 positional param, or array variable). Also return the value specified
7542 by VARNAME (value of a variable or a reference to an array element).
7543 QUOTED is the standard description of quoting state, using Q_* defines.
7544 FLAGS is currently a set of flags to pass to array_value. If IND is
7545 non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
7546 passed to array_value so the array index is not computed again.
7547 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
7548 characters in the value are quoted with CTLESC and takes appropriate
7549 steps. For convenience, *VALP is set to the dequoted VALUE. */
7550 static int
7551 get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
7552 char *varname, *value;
7553 arrayind_t ind;
7554 int quoted, flags;
7555 SHELL_VAR **varp;
7556 char **valp;
7558 int vtype, want_indir;
7559 char *temp, *vname;
7560 SHELL_VAR *v;
7561 arrayind_t lind;
7563 want_indir = *varname == '!' &&
7564 (legal_variable_starter ((unsigned char)varname[1]) || DIGIT (varname[1])
7565 || VALID_INDIR_PARAM (varname[1]));
7566 if (want_indir)
7567 vname = parameter_brace_find_indir (varname+1, SPECIAL_VAR (varname, 1), quoted, 1);
7568 /* XXX - what if vname == 0 || *vname == 0 ? */
7569 else
7570 vname = varname;
7572 if (vname == 0)
7574 vtype = VT_VARIABLE;
7575 *varp = (SHELL_VAR *)NULL;
7576 *valp = (char *)NULL;
7577 return (vtype);
7580 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
7581 vtype = STR_DOLLAR_AT_STAR (vname);
7582 if (vtype == VT_POSPARMS && vname[0] == '*')
7583 vtype |= VT_STARSUB;
7584 *varp = (SHELL_VAR *)NULL;
7586 #if defined (ARRAY_VARS)
7587 if (valid_array_reference (vname, 0))
7589 v = array_variable_part (vname, 0, &temp, (int *)0);
7590 /* If we want to signal array_value to use an already-computed index,
7591 set LIND to that index */
7592 lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
7593 if (v && invisible_p (v))
7595 vtype = VT_ARRAYMEMBER;
7596 *varp = (SHELL_VAR *)NULL;
7597 *valp = (char *)NULL;
7599 if (v && (array_p (v) || assoc_p (v)))
7601 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == RBRACK)
7603 /* Callers have to differentiate between indexed and associative */
7604 vtype = VT_ARRAYVAR;
7605 if (temp[0] == '*')
7606 vtype |= VT_STARSUB;
7607 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
7609 else
7611 vtype = VT_ARRAYMEMBER;
7612 *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
7614 *varp = v;
7616 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == RBRACK))
7618 vtype = VT_VARIABLE;
7619 *varp = v;
7620 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
7621 *valp = value ? dequote_string (value) : (char *)NULL;
7622 else
7623 *valp = value ? dequote_escapes (value) : (char *)NULL;
7625 else
7627 vtype = VT_ARRAYMEMBER;
7628 *varp = v;
7629 *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
7632 else if ((v = find_variable (vname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
7634 vtype = VT_ARRAYMEMBER;
7635 *varp = v;
7636 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
7638 else
7639 #endif
7641 if (value && vtype == VT_VARIABLE)
7643 *varp = find_variable (vname);
7644 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
7645 *valp = dequote_string (value);
7646 else
7647 *valp = dequote_escapes (value);
7649 else
7650 *valp = value;
7653 if (want_indir)
7654 free (vname);
7656 return vtype;
7659 /***********************************************************/
7660 /* */
7661 /* Functions to perform transformations on variable values */
7662 /* */
7663 /***********************************************************/
7665 static char *
7666 string_var_assignment (v, s)
7667 SHELL_VAR *v;
7668 char *s;
7670 char flags[MAX_ATTRIBUTES], *ret, *val;
7671 int i;
7673 val = (v && (invisible_p (v) || var_isset (v) == 0)) ? (char *)NULL : sh_quote_reusable (s, 0);
7674 i = var_attribute_string (v, 0, flags);
7675 if (i == 0 && val == 0)
7676 return (char *)NULL;
7678 ret = (char *)xmalloc (i + STRLEN (val) + strlen (v->name) + 16 + MAX_ATTRIBUTES);
7679 if (i > 0 && val == 0)
7680 sprintf (ret, "declare -%s %s", flags, v->name);
7681 else if (i > 0)
7682 sprintf (ret, "declare -%s %s=%s", flags, v->name, val);
7683 else
7684 sprintf (ret, "%s=%s", v->name, val);
7685 free (val);
7686 return ret;
7689 #if defined (ARRAY_VARS)
7690 static char *
7691 array_var_assignment (v, itype, quoted, atype)
7692 SHELL_VAR *v;
7693 int itype, quoted, atype;
7695 char *ret, *val, flags[MAX_ATTRIBUTES];
7696 int i;
7698 if (v == 0)
7699 return (char *)NULL;
7700 if (atype == 2)
7701 val = array_p (v) ? array_to_kvpair (array_cell (v), 0)
7702 : assoc_to_kvpair (assoc_cell (v), 0);
7703 else
7704 val = array_p (v) ? array_to_assign (array_cell (v), 0)
7705 : assoc_to_assign (assoc_cell (v), 0);
7707 if (val == 0 && (invisible_p (v) || var_isset (v) == 0))
7708 ; /* placeholder */
7709 else if (val == 0)
7711 val = (char *)xmalloc (3);
7712 val[0] = LPAREN;
7713 val[1] = RPAREN;
7714 val[2] = 0;
7716 else
7718 ret = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) ? quote_string (val) : quote_escapes (val);
7719 free (val);
7720 val = ret;
7723 if (atype == 2)
7724 return val;
7726 i = var_attribute_string (v, 0, flags);
7727 ret = (char *)xmalloc (i + STRLEN (val) + strlen (v->name) + 16);
7728 if (val)
7729 sprintf (ret, "declare -%s %s=%s", flags, v->name, val);
7730 else
7731 sprintf (ret, "declare -%s %s", flags, v->name);
7732 free (val);
7733 return ret;
7735 #endif
7737 static char *
7738 pos_params_assignment (list, itype, quoted)
7739 WORD_LIST *list;
7740 int itype;
7741 int quoted;
7743 char *temp, *ret;
7745 /* first, we transform the list to quote each word. */
7746 temp = list_transform ('Q', (SHELL_VAR *)0, list, itype, quoted);
7747 ret = (char *)xmalloc (strlen (temp) + 8);
7748 strcpy (ret, "set -- ");
7749 strcpy (ret + 7, temp);
7750 free (temp);
7751 return ret;
7754 static char *
7755 string_transform (xc, v, s)
7756 int xc;
7757 SHELL_VAR *v;
7758 char *s;
7760 char *ret, flags[MAX_ATTRIBUTES], *t;
7761 int i;
7763 if (((xc == 'A' || xc == 'a') && v == 0))
7764 return (char *)NULL;
7765 else if (xc != 'a' && xc != 'A' && s == 0)
7766 return (char *)NULL;
7768 switch (xc)
7770 /* Transformations that interrogate the variable */
7771 case 'a':
7772 i = var_attribute_string (v, 0, flags);
7773 ret = (i > 0) ? savestring (flags) : (char *)NULL;
7774 break;
7775 case 'A':
7776 ret = string_var_assignment (v, s);
7777 break;
7778 case 'K':
7779 ret = sh_quote_reusable (s, 0);
7780 break;
7781 /* Transformations that modify the variable's value */
7782 case 'E':
7783 t = ansiexpand (s, 0, strlen (s), (int *)0);
7784 ret = dequote_escapes (t);
7785 free (t);
7786 break;
7787 case 'P':
7788 ret = decode_prompt_string (s);
7789 break;
7790 case 'Q':
7791 ret = sh_quote_reusable (s, 0);
7792 break;
7793 case 'U':
7794 ret = sh_modcase (s, 0, CASE_UPPER);
7795 break;
7796 case 'u':
7797 ret = sh_modcase (s, 0, CASE_UPFIRST); /* capitalize */
7798 break;
7799 case 'L':
7800 ret = sh_modcase (s, 0, CASE_LOWER);
7801 break;
7802 default:
7803 ret = (char *)NULL;
7804 break;
7806 return ret;
7809 static char *
7810 list_transform (xc, v, list, itype, quoted)
7811 int xc;
7812 SHELL_VAR *v;
7813 WORD_LIST *list;
7814 int itype, quoted;
7816 WORD_LIST *new, *l;
7817 WORD_DESC *w;
7818 char *tword;
7819 int qflags;
7821 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
7823 tword = string_transform (xc, v, l->word->word);
7824 w = alloc_word_desc ();
7825 w->word = tword ? tword : savestring (""); /* XXX */
7826 new = make_word_list (w, new);
7828 l = REVERSE_LIST (new, WORD_LIST *);
7830 qflags = quoted;
7831 /* If we are expanding in a context where word splitting will not be
7832 performed, treat as quoted. This changes how $* will be expanded. */
7833 if (itype == '*' && expand_no_split_dollar_star && ifs_is_null)
7834 qflags |= Q_DOUBLE_QUOTES; /* Posix interp 888 */
7836 tword = string_list_pos_params (itype, l, qflags, 0);
7837 dispose_words (l);
7839 return (tword);
7842 static char *
7843 parameter_list_transform (xc, itype, quoted)
7844 int xc;
7845 int itype;
7846 int quoted;
7848 char *ret;
7849 WORD_LIST *list;
7851 list = list_rest_of_args ();
7852 if (list == 0)
7853 return ((char *)NULL);
7854 if (xc == 'A')
7855 ret = pos_params_assignment (list, itype, quoted);
7856 else
7857 ret = list_transform (xc, (SHELL_VAR *)0, list, itype, quoted);
7858 dispose_words (list);
7859 return (ret);
7862 #if defined (ARRAY_VARS)
7863 static char *
7864 array_transform (xc, var, starsub, quoted)
7865 int xc;
7866 SHELL_VAR *var;
7867 int starsub; /* so we can figure out how it's indexed */
7868 int quoted;
7870 ARRAY *a;
7871 HASH_TABLE *h;
7872 int itype;
7873 char *ret;
7874 WORD_LIST *list;
7875 SHELL_VAR *v;
7877 v = var; /* XXX - for now */
7879 itype = starsub ? '*' : '@';
7881 if (xc == 'A')
7882 return (array_var_assignment (v, itype, quoted, 1));
7883 else if (xc == 'K')
7884 return (array_var_assignment (v, itype, quoted, 2));
7886 /* special case for unset arrays and attributes */
7887 if (xc == 'a' && (invisible_p (v) || var_isset (v) == 0))
7889 char flags[MAX_ATTRIBUTES];
7890 int i;
7892 i = var_attribute_string (v, 0, flags);
7893 return ((i > 0) ? savestring (flags) : (char *)NULL);
7896 a = (v && array_p (v)) ? array_cell (v) : 0;
7897 h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
7899 list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
7900 if (list == 0)
7901 return ((char *)NULL);
7902 ret = list_transform (xc, v, list, itype, quoted);
7903 dispose_words (list);
7905 return ret;
7907 #endif /* ARRAY_VARS */
7909 static int
7910 valid_parameter_transform (xform)
7911 char *xform;
7913 if (xform[1])
7914 return 0;
7916 /* check for valid values of xform[0] */
7917 switch (xform[0])
7919 case 'a': /* expand to a string with just attributes */
7920 case 'A': /* expand as an assignment statement with attributes */
7921 case 'K': /* expand assoc array to list of key/value pairs */
7922 case 'E': /* expand like $'...' */
7923 case 'P': /* expand like prompt string */
7924 case 'Q': /* quote reusably */
7925 case 'U': /* transform to uppercase */
7926 case 'u': /* tranform by capitalizing */
7927 case 'L': /* transform to lowercase */
7928 return 1;
7929 default:
7930 return 0;
7934 static char *
7935 parameter_brace_transform (varname, value, ind, xform, rtype, quoted, pflags, flags)
7936 char *varname, *value;
7937 int ind;
7938 char *xform;
7939 int rtype, quoted, pflags, flags;
7941 int vtype, xc, starsub;
7942 char *temp1, *val, *oname;
7943 SHELL_VAR *v;
7945 xc = xform[0];
7946 if (value == 0 && xc != 'A' && xc != 'a')
7947 return ((char *)NULL);
7949 oname = this_command_name;
7950 this_command_name = varname;
7952 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
7953 if (vtype == -1)
7955 this_command_name = oname;
7956 return ((char *)NULL);
7959 if (valid_parameter_transform (xform) == 0)
7961 this_command_name = oname;
7962 #if 0 /* TAG: bush-5.2 Martin Schulte <gnu@schrader-schulte.de> 10/2020 */
7963 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
7964 #else
7965 return &expand_param_error;
7966 #endif
7969 starsub = vtype & VT_STARSUB;
7970 vtype &= ~VT_STARSUB;
7972 /* If we are asked to display the attributes of an unset variable, V will
7973 be NULL after the call to get_var_and_type. Double-check here. */
7974 if ((xc == 'a' || xc == 'A') && vtype == VT_VARIABLE && varname && v == 0)
7975 v = find_variable (varname);
7977 temp1 = (char *)NULL; /* shut up gcc */
7978 switch (vtype)
7980 case VT_VARIABLE:
7981 case VT_ARRAYMEMBER:
7982 temp1 = string_transform (xc, v, val);
7983 if (vtype == VT_VARIABLE)
7984 FREE (val);
7985 if (temp1)
7987 val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7988 ? quote_string (temp1)
7989 : quote_escapes (temp1);
7990 free (temp1);
7991 temp1 = val;
7993 break;
7994 #if defined (ARRAY_VARS)
7995 case VT_ARRAYVAR:
7996 temp1 = array_transform (xc, v, starsub, quoted);
7997 if (temp1 && quoted == 0 && ifs_is_null)
7999 /* Posix interp 888 */
8001 else if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
8003 val = quote_escapes (temp1);
8004 free (temp1);
8005 temp1 = val;
8007 break;
8008 #endif
8009 case VT_POSPARMS:
8010 temp1 = parameter_list_transform (xc, varname[0], quoted);
8011 if (temp1 && quoted == 0 && ifs_is_null)
8013 /* Posix interp 888 */
8015 else if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
8017 val = quote_escapes (temp1);
8018 free (temp1);
8019 temp1 = val;
8021 break;
8024 this_command_name = oname;
8025 return temp1;
8028 /******************************************************/
8029 /* */
8030 /* Functions to extract substrings of variable values */
8031 /* */
8032 /******************************************************/
8034 #if defined (HANDLE_MULTIBYTE)
8035 /* Character-oriented rather than strictly byte-oriented substrings. S and
8036 E, rather being strict indices into STRING, indicate character (possibly
8037 multibyte character) positions that require calculation.
8038 Used by the ${param:offset[:length]} expansion. */
8039 static char *
8040 mb_substring (string, s, e)
8041 char *string;
8042 int s, e;
8044 char *tt;
8045 int start, stop, i;
8046 size_t slen;
8047 DECLARE_MBSTATE;
8049 start = 0;
8050 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
8051 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
8053 i = s;
8054 while (string[start] && i--)
8055 ADVANCE_CHAR (string, slen, start);
8056 stop = start;
8057 i = e - s;
8058 while (string[stop] && i--)
8059 ADVANCE_CHAR (string, slen, stop);
8060 tt = substring (string, start, stop);
8061 return tt;
8063 #endif
8065 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
8066 is `@', use the positional parameters; otherwise, use the value of
8067 VARNAME. If VARNAME is an array variable, use the array elements. */
8069 static char *
8070 parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags)
8071 char *varname, *value;
8072 int ind;
8073 char *substr;
8074 int quoted, pflags, flags;
8076 intmax_t e1, e2;
8077 int vtype, r, starsub;
8078 char *temp, *val, *tt, *oname;
8079 SHELL_VAR *v;
8081 if (value == 0 && ((varname[0] != '@' && varname[0] != '*') || varname[1]))
8082 return ((char *)NULL);
8084 oname = this_command_name;
8085 this_command_name = varname;
8087 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
8088 if (vtype == -1)
8090 this_command_name = oname;
8091 return ((char *)NULL);
8094 starsub = vtype & VT_STARSUB;
8095 vtype &= ~VT_STARSUB;
8097 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
8098 this_command_name = oname;
8099 if (r <= 0)
8101 if (vtype == VT_VARIABLE)
8102 FREE (val);
8103 return ((r == 0) ? &expand_param_error : (char *)NULL);
8106 switch (vtype)
8108 case VT_VARIABLE:
8109 case VT_ARRAYMEMBER:
8110 #if defined (HANDLE_MULTIBYTE)
8111 if (MB_CUR_MAX > 1)
8112 tt = mb_substring (val, e1, e2);
8113 else
8114 #endif
8115 tt = substring (val, e1, e2);
8117 if (vtype == VT_VARIABLE)
8118 FREE (val);
8119 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
8120 temp = quote_string (tt);
8121 else
8122 temp = tt ? quote_escapes (tt) : (char *)NULL;
8123 FREE (tt);
8124 break;
8125 case VT_POSPARMS:
8126 case VT_ARRAYVAR:
8127 if (vtype == VT_POSPARMS)
8128 tt = pos_params (varname, e1, e2, quoted, pflags);
8129 #if defined (ARRAY_VARS)
8130 /* assoc_subrange and array_subrange both call string_list_pos_params,
8131 so we can treat this case just like VT_POSPARAMS. */
8132 else if (assoc_p (v))
8133 /* we convert to list and take first e2 elements starting at e1th
8134 element -- officially undefined for now */
8135 tt = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted, pflags);
8136 else
8137 /* We want E2 to be the number of elements desired (arrays can be
8138 sparse, so verify_substring_values just returns the numbers
8139 specified and we rely on array_subrange to understand how to
8140 deal with them). */
8141 tt = array_subrange (array_cell (v), e1, e2, starsub, quoted, pflags);
8142 #endif
8143 /* We want to leave this alone in every case where pos_params/
8144 string_list_pos_params quotes the list members */
8145 if (tt && quoted == 0 && ifs_is_null)
8147 temp = tt; /* Posix interp 888 */
8149 else if (tt && quoted == 0 && (pflags & PF_ASSIGNRHS))
8151 temp = tt; /* Posix interp 888 */
8153 else if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
8155 temp = tt ? quote_escapes (tt) : (char *)NULL;
8156 FREE (tt);
8158 else
8159 temp = tt;
8160 break;
8162 default:
8163 temp = (char *)NULL;
8166 return temp;
8169 /****************************************************************/
8170 /* */
8171 /* Functions to perform pattern substitution on variable values */
8172 /* */
8173 /****************************************************************/
8175 #ifdef INCLUDE_UNUSED
8176 static int
8177 shouldexp_replacement (s)
8178 char *s;
8180 register char *p;
8182 for (p = s; p && *p; p++)
8184 if (*p == '\\')
8185 p++;
8186 else if (*p == '&')
8187 return 1;
8189 return 0;
8191 #endif
8193 char *
8194 pat_subst (string, pat, rep, mflags)
8195 char *string, *pat, *rep;
8196 int mflags;
8198 char *ret, *s, *e, *str, *rstr, *mstr, *send;
8199 int rptr, mtype, rxpand, mlen;
8200 size_t rsize, l, replen, rslen;
8201 DECLARE_MBSTATE;
8203 if (string == 0)
8204 return (savestring (""));
8206 mtype = mflags & MATCH_TYPEMASK;
8208 #if 0 /* TAG: bush-5.2? */
8209 rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0;
8210 #else
8211 rxpand = 0;
8212 #endif
8214 /* Special cases:
8215 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
8216 * with REP and return the result.
8217 * 2. A null pattern with mtype == MATCH_END means to append REP to
8218 * STRING and return the result.
8219 * 3. A null STRING with a matching pattern means to append REP to
8220 * STRING and return the result.
8221 * These don't understand or process `&' in the replacement string.
8223 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
8225 replen = STRLEN (rep);
8226 l = STRLEN (string);
8227 ret = (char *)xmalloc (replen + l + 2);
8228 if (replen == 0)
8229 strcpy (ret, string);
8230 else if (mtype == MATCH_BEG)
8232 strcpy (ret, rep);
8233 strcpy (ret + replen, string);
8235 else
8237 strcpy (ret, string);
8238 strcpy (ret + l, rep);
8240 return (ret);
8242 else if (*string == 0 && (match_pattern (string, pat, mtype, &s, &e) != 0))
8244 replen = STRLEN (rep);
8245 ret = (char *)xmalloc (replen + 1);
8246 if (replen == 0)
8247 ret[0] = '\0';
8248 else
8249 strcpy (ret, rep);
8250 return (ret);
8253 ret = (char *)xmalloc (rsize = 64);
8254 ret[0] = '\0';
8255 send = string + strlen (string);
8257 for (replen = STRLEN (rep), rptr = 0, str = string; *str;)
8259 if (match_pattern (str, pat, mtype, &s, &e) == 0)
8260 break;
8261 l = s - str;
8263 if (rep && rxpand)
8265 int x;
8266 mlen = e - s;
8267 mstr = xmalloc (mlen + 1);
8268 for (x = 0; x < mlen; x++)
8269 mstr[x] = s[x];
8270 mstr[mlen] = '\0';
8271 rstr = strcreplace (rep, '&', mstr, 0);
8272 free (mstr);
8273 rslen = strlen (rstr);
8275 else
8277 rstr = rep;
8278 rslen = replen;
8281 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64);
8283 /* OK, now copy the leading unmatched portion of the string (from
8284 str to s) to ret starting at rptr (the current offset). Then copy
8285 the replacement string at ret + rptr + (s - str). Increment
8286 rptr (if necessary) and str and go on. */
8287 if (l)
8289 strncpy (ret + rptr, str, l);
8290 rptr += l;
8292 if (replen)
8294 strncpy (ret + rptr, rstr, rslen);
8295 rptr += rslen;
8297 str = e; /* e == end of match */
8299 if (rstr != rep)
8300 free (rstr);
8302 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
8303 break;
8305 if (s == e)
8307 /* On a zero-length match, make sure we copy one character, since
8308 we increment one character to avoid infinite recursion. */
8309 char *p, *origp, *origs;
8310 size_t clen;
8312 RESIZE_MALLOCED_BUFFER (ret, rptr, locale_mb_cur_max, rsize, 64);
8313 #if defined (HANDLE_MULTIBYTE)
8314 p = origp = ret + rptr;
8315 origs = str;
8316 COPY_CHAR_P (p, str, send);
8317 rptr += p - origp;
8318 e += str - origs;
8319 #else
8320 ret[rptr++] = *str++;
8321 e++; /* avoid infinite recursion on zero-length match */
8322 #endif
8326 /* Now copy the unmatched portion of the input string */
8327 if (str && *str)
8329 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
8330 strcpy (ret + rptr, str);
8332 else
8333 ret[rptr] = '\0';
8335 return ret;
8338 /* Do pattern match and replacement on the positional parameters. */
8339 static char *
8340 pos_params_pat_subst (string, pat, rep, mflags)
8341 char *string, *pat, *rep;
8342 int mflags;
8344 WORD_LIST *save, *params;
8345 WORD_DESC *w;
8346 char *ret;
8347 int pchar, qflags, pflags;
8349 save = params = list_rest_of_args ();
8350 if (save == 0)
8351 return ((char *)NULL);
8353 for ( ; params; params = params->next)
8355 ret = pat_subst (params->word->word, pat, rep, mflags);
8356 w = alloc_word_desc ();
8357 w->word = ret ? ret : savestring ("");
8358 dispose_word (params->word);
8359 params->word = w;
8362 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
8363 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
8364 pflags = (mflags & MATCH_ASSIGNRHS) == MATCH_ASSIGNRHS ? PF_ASSIGNRHS : 0;
8366 /* If we are expanding in a context where word splitting will not be
8367 performed, treat as quoted. This changes how $* will be expanded. */
8368 if (pchar == '*' && (mflags & MATCH_ASSIGNRHS) && expand_no_split_dollar_star && ifs_is_null)
8369 qflags |= Q_DOUBLE_QUOTES; /* Posix interp 888 */
8371 ret = string_list_pos_params (pchar, save, qflags, pflags);
8372 dispose_words (save);
8374 return (ret);
8377 /* Perform pattern substitution on VALUE, which is the expansion of
8378 VARNAME. PATSUB is an expression supplying the pattern to match
8379 and the string to substitute. QUOTED is a flags word containing
8380 the type of quoting currently in effect. */
8381 static char *
8382 parameter_brace_patsub (varname, value, ind, patsub, quoted, pflags, flags)
8383 char *varname, *value;
8384 int ind;
8385 char *patsub;
8386 int quoted, pflags, flags;
8388 int vtype, mflags, starsub, delim;
8389 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt, *oname;
8390 SHELL_VAR *v;
8392 if (value == 0)
8393 return ((char *)NULL);
8395 oname = this_command_name;
8396 this_command_name = varname; /* error messages */
8398 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
8399 if (vtype == -1)
8401 this_command_name = oname;
8402 return ((char *)NULL);
8405 starsub = vtype & VT_STARSUB;
8406 vtype &= ~VT_STARSUB;
8408 mflags = 0;
8409 /* PATSUB is never NULL when this is called. */
8410 if (*patsub == '/')
8412 mflags |= MATCH_GLOBREP;
8413 patsub++;
8416 /* Malloc this because expand_string_if_necessary or one of the expansion
8417 functions in its call chain may free it on a substitution error. */
8418 lpatsub = savestring (patsub);
8420 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8421 mflags |= MATCH_QUOTED;
8423 if (starsub)
8424 mflags |= MATCH_STARSUB;
8426 if (pflags & PF_ASSIGNRHS)
8427 mflags |= MATCH_ASSIGNRHS;
8429 /* If the pattern starts with a `/', make sure we skip over it when looking
8430 for the replacement delimiter. */
8431 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
8432 if (lpatsub[delim] == '/')
8434 lpatsub[delim] = 0;
8435 rep = lpatsub + delim + 1;
8437 else
8438 rep = (char *)NULL;
8440 if (rep && *rep == '\0')
8441 rep = (char *)NULL;
8443 /* Perform the same expansions on the pattern as performed by the
8444 pattern removal expansions. */
8445 pat = getpattern (lpatsub, quoted, 1);
8447 if (rep)
8449 /* We want to perform quote removal on the expanded replacement even if
8450 the entire expansion is double-quoted because the parser and string
8451 extraction functions treated quotes in the replacement string as
8452 special. THIS IS NOT BACKWARDS COMPATIBLE WITH BUSH-4.2. */
8453 if (shell_compatibility_level > 42)
8454 rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
8455 /* This is the bush-4.2 code. */
8456 else if ((mflags & MATCH_QUOTED) == 0)
8457 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
8458 else
8459 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
8462 /* ksh93 doesn't allow the match specifier to be a part of the expanded
8463 pattern. This is an extension. Make sure we don't anchor the pattern
8464 at the beginning or end of the string if we're doing global replacement,
8465 though. */
8466 p = pat;
8467 if (mflags & MATCH_GLOBREP)
8468 mflags |= MATCH_ANY;
8469 else if (pat && pat[0] == '#')
8471 mflags |= MATCH_BEG;
8472 p++;
8474 else if (pat && pat[0] == '%')
8476 mflags |= MATCH_END;
8477 p++;
8479 else
8480 mflags |= MATCH_ANY;
8482 /* OK, we now want to substitute REP for PAT in VAL. If
8483 flags & MATCH_GLOBREP is non-zero, the substitution is done
8484 everywhere, otherwise only the first occurrence of PAT is
8485 replaced. The pattern matching code doesn't understand
8486 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
8487 values passed in (VT_VARIABLE) so the pattern substitution
8488 code works right. We need to requote special chars after
8489 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
8490 other cases if QUOTED == 0, since the posparams and arrays
8491 indexed by * or @ do special things when QUOTED != 0. */
8493 switch (vtype)
8495 case VT_VARIABLE:
8496 case VT_ARRAYMEMBER:
8497 temp = pat_subst (val, p, rep, mflags);
8498 if (vtype == VT_VARIABLE)
8499 FREE (val);
8500 if (temp)
8502 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
8503 free (temp);
8504 temp = tt;
8506 break;
8507 case VT_POSPARMS:
8508 /* This does the right thing for the case where we are not performing
8509 word splitting. MATCH_STARSUB restricts it to ${* /foo/bar}, and
8510 pos_params_pat_subst/string_list_pos_params will do the right thing
8511 in turn for the case where ifs_is_null. Posix interp 888 */
8512 if ((pflags & PF_NOSPLIT2) && (mflags & MATCH_STARSUB))
8513 mflags |= MATCH_ASSIGNRHS;
8514 temp = pos_params_pat_subst (val, p, rep, mflags);
8515 if (temp && quoted == 0 && ifs_is_null)
8517 /* Posix interp 888 */
8519 else if (temp && quoted == 0 && (pflags & PF_ASSIGNRHS))
8521 /* Posix interp 888 */
8523 else if (temp && (mflags & MATCH_QUOTED) == 0)
8525 tt = quote_escapes (temp);
8526 free (temp);
8527 temp = tt;
8529 break;
8530 #if defined (ARRAY_VARS)
8531 case VT_ARRAYVAR:
8532 /* If we are expanding in a context where word splitting will not be
8533 performed, treat as quoted. This changes how ${A[*]} will be
8534 expanded to make it identical to $*. */
8535 if ((mflags & MATCH_STARSUB) && (mflags & MATCH_ASSIGNRHS) && ifs_is_null)
8536 mflags |= MATCH_QUOTED; /* Posix interp 888 */
8538 /* these eventually call string_list_pos_params */
8539 if (assoc_p (v))
8540 temp = assoc_patsub (assoc_cell (v), p, rep, mflags);
8541 else
8542 temp = array_patsub (array_cell (v), p, rep, mflags);
8544 if (temp && quoted == 0 && ifs_is_null)
8546 /* Posix interp 888 */
8548 else if (temp && (mflags & MATCH_QUOTED) == 0)
8550 tt = quote_escapes (temp);
8551 free (temp);
8552 temp = tt;
8554 break;
8555 #endif
8558 FREE (pat);
8559 FREE (rep);
8560 free (lpatsub);
8562 this_command_name = oname;
8564 return temp;
8567 /****************************************************************/
8568 /* */
8569 /* Functions to perform case modification on variable values */
8570 /* */
8571 /****************************************************************/
8573 /* Do case modification on the positional parameters. */
8575 static char *
8576 pos_params_modcase (string, pat, modop, mflags)
8577 char *string, *pat;
8578 int modop;
8579 int mflags;
8581 WORD_LIST *save, *params;
8582 WORD_DESC *w;
8583 char *ret;
8584 int pchar, qflags, pflags;
8586 save = params = list_rest_of_args ();
8587 if (save == 0)
8588 return ((char *)NULL);
8590 for ( ; params; params = params->next)
8592 ret = sh_modcase (params->word->word, pat, modop);
8593 w = alloc_word_desc ();
8594 w->word = ret ? ret : savestring ("");
8595 dispose_word (params->word);
8596 params->word = w;
8599 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
8600 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
8601 pflags = (mflags & MATCH_ASSIGNRHS) == MATCH_ASSIGNRHS ? PF_ASSIGNRHS : 0;
8603 /* If we are expanding in a context where word splitting will not be
8604 performed, treat as quoted. This changes how $* will be expanded. */
8605 if (pchar == '*' && (mflags & MATCH_ASSIGNRHS) && ifs_is_null)
8606 qflags |= Q_DOUBLE_QUOTES; /* Posix interp 888 */
8608 ret = string_list_pos_params (pchar, save, qflags, pflags);
8609 dispose_words (save);
8611 return (ret);
8614 /* Perform case modification on VALUE, which is the expansion of
8615 VARNAME. MODSPEC is an expression supplying the type of modification
8616 to perform. QUOTED is a flags word containing the type of quoting
8617 currently in effect. */
8618 static char *
8619 parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, pflags, flags)
8620 char *varname, *value;
8621 int ind, modspec;
8622 char *patspec;
8623 int quoted, pflags, flags;
8625 int vtype, starsub, modop, mflags, x;
8626 char *val, *temp, *pat, *p, *lpat, *tt, *oname;
8627 SHELL_VAR *v;
8629 if (value == 0)
8630 return ((char *)NULL);
8632 oname = this_command_name;
8633 this_command_name = varname;
8635 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
8636 if (vtype == -1)
8638 this_command_name = oname;
8639 return ((char *)NULL);
8642 starsub = vtype & VT_STARSUB;
8643 vtype &= ~VT_STARSUB;
8645 modop = 0;
8646 mflags = 0;
8647 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8648 mflags |= MATCH_QUOTED;
8649 if (starsub)
8650 mflags |= MATCH_STARSUB;
8651 if (pflags & PF_ASSIGNRHS)
8652 mflags |= MATCH_ASSIGNRHS;
8654 p = patspec;
8655 if (modspec == '^')
8657 x = p && p[0] == modspec;
8658 modop = x ? CASE_UPPER : CASE_UPFIRST;
8659 p += x;
8661 else if (modspec == ',')
8663 x = p && p[0] == modspec;
8664 modop = x ? CASE_LOWER : CASE_LOWFIRST;
8665 p += x;
8667 else if (modspec == '~')
8669 x = p && p[0] == modspec;
8670 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
8671 p += x;
8674 lpat = p ? savestring (p) : 0;
8675 /* Perform the same expansions on the pattern as performed by the
8676 pattern removal expansions. */
8677 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
8679 /* OK, now we do the case modification. */
8680 switch (vtype)
8682 case VT_VARIABLE:
8683 case VT_ARRAYMEMBER:
8684 temp = sh_modcase (val, pat, modop);
8685 if (vtype == VT_VARIABLE)
8686 FREE (val);
8687 if (temp)
8689 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
8690 free (temp);
8691 temp = tt;
8693 break;
8695 case VT_POSPARMS:
8696 temp = pos_params_modcase (val, pat, modop, mflags);
8697 if (temp && quoted == 0 && ifs_is_null)
8699 /* Posix interp 888 */
8701 else if (temp && (mflags & MATCH_QUOTED) == 0)
8703 tt = quote_escapes (temp);
8704 free (temp);
8705 temp = tt;
8707 break;
8709 #if defined (ARRAY_VARS)
8710 case VT_ARRAYVAR:
8711 /* If we are expanding in a context where word splitting will not be
8712 performed, treat as quoted. This changes how ${A[*]} will be
8713 expanded to make it identical to $*. */
8714 if ((mflags & MATCH_STARSUB) && (mflags & MATCH_ASSIGNRHS) && ifs_is_null)
8715 mflags |= MATCH_QUOTED; /* Posix interp 888 */
8717 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
8718 : array_modcase (array_cell (v), pat, modop, mflags);
8720 if (temp && quoted == 0 && ifs_is_null)
8722 /* Posix interp 888 */
8724 else if (temp && (mflags & MATCH_QUOTED) == 0)
8726 tt = quote_escapes (temp);
8727 free (temp);
8728 temp = tt;
8731 break;
8732 #endif
8735 FREE (pat);
8736 free (lpat);
8738 this_command_name = oname;
8740 return temp;
8743 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
8744 any occur, this must be a nested command substitution, so return 0.
8745 Otherwise, return 1. A valid arithmetic expression must always have a
8746 ( before a matching ), so any cases where there are more right parens
8747 means that this must not be an arithmetic expression, though the parser
8748 will not accept it without a balanced total number of parens. */
8749 static int
8750 chk_arithsub (s, len)
8751 const char *s;
8752 int len;
8754 int i, count;
8755 DECLARE_MBSTATE;
8757 i = count = 0;
8758 while (i < len)
8760 if (s[i] == LPAREN)
8761 count++;
8762 else if (s[i] == RPAREN)
8764 count--;
8765 if (count < 0)
8766 return 0;
8769 switch (s[i])
8771 default:
8772 ADVANCE_CHAR (s, len, i);
8773 break;
8775 case '\\':
8776 i++;
8777 if (s[i])
8778 ADVANCE_CHAR (s, len, i);
8779 break;
8781 case '\'':
8782 i = skip_single_quoted (s, len, ++i, 0);
8783 break;
8785 case '"':
8786 i = skip_double_quoted ((char *)s, len, ++i, 0);
8787 break;
8791 return (count == 0);
8794 /****************************************************************/
8795 /* */
8796 /* Functions to perform parameter expansion on a string */
8797 /* */
8798 /****************************************************************/
8800 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
8801 static WORD_DESC *
8802 parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
8803 char *string;
8804 int *indexp, quoted, pflags, *quoted_dollar_atp, *contains_dollar_at;
8806 int check_nullness, var_is_set, var_is_null, var_is_special;
8807 int want_substring, want_indir, want_patsub, want_casemod, want_attributes;
8808 char *name, *value, *temp, *temp1;
8809 WORD_DESC *tdesc, *ret;
8810 int t_index, sindex, c, tflag, modspec, local_pflags, all_element_arrayref;
8811 intmax_t number;
8812 arrayind_t ind;
8814 temp = temp1 = value = (char *)NULL;
8815 var_is_set = var_is_null = var_is_special = check_nullness = 0;
8816 want_substring = want_indir = want_patsub = want_casemod = want_attributes = 0;
8818 local_pflags = 0;
8819 all_element_arrayref = 0;
8821 sindex = *indexp;
8822 t_index = ++sindex;
8823 /* ${#var} doesn't have any of the other parameter expansions on it. */
8824 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
8825 name = string_extract (string, &t_index, "}", SX_VARNAME);
8826 else
8827 #if defined (CASEMOD_EXPANSIONS)
8828 /* To enable case-toggling expansions using the `~' operator character
8829 define CASEMOD_TOGGLECASE in config-top.h */
8830 # if defined (CASEMOD_TOGGLECASE)
8831 name = string_extract (string, &t_index, "#%^,~:-=?+/@}", SX_VARNAME);
8832 # else
8833 name = string_extract (string, &t_index, "#%^,:-=?+/@}", SX_VARNAME);
8834 # endif /* CASEMOD_TOGGLECASE */
8835 #else
8836 name = string_extract (string, &t_index, "#%:-=?+/@}", SX_VARNAME);
8837 #endif /* CASEMOD_EXPANSIONS */
8839 /* Handle ${@[stuff]} now that @ is a word expansion operator. Not exactly
8840 the cleanest code ever. */
8841 if (*name == 0 && sindex == t_index && string[sindex] == '@')
8843 name = (char *)xrealloc (name, 2);
8844 name[0] = '@';
8845 name[1] = '\0';
8846 t_index++;
8848 else if (*name == '!' && t_index > sindex && string[t_index] == '@' && string[t_index+1] == RBRACE)
8850 name = (char *)xrealloc (name, t_index - sindex + 2);
8851 name[t_index - sindex] = '@';
8852 name[t_index - sindex + 1] = '\0';
8853 t_index++;
8856 ret = 0;
8857 tflag = 0;
8859 ind = INTMAX_MIN;
8861 /* If the name really consists of a special variable, then make sure
8862 that we have the entire name. We don't allow indirect references
8863 to special variables except `#', `?', `@' and `*'. This clause is
8864 designed to handle ${#SPECIAL} and ${!SPECIAL}, not anything more
8865 general. */
8866 if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
8867 (sindex == t_index && string[sindex] == '#' && VALID_SPECIAL_LENGTH_PARAM (string[sindex + 1])) ||
8868 (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
8870 t_index++;
8871 temp1 = string_extract (string, &t_index, "#%:-=?+/@}", 0);
8872 name = (char *)xrealloc (name, 3 + (strlen (temp1)));
8873 *name = string[sindex];
8874 if (string[sindex] == '!')
8876 /* indirect reference of $#, $?, $@, or $* */
8877 name[1] = string[sindex + 1];
8878 strcpy (name + 2, temp1);
8880 else
8881 strcpy (name + 1, temp1);
8882 free (temp1);
8884 sindex = t_index;
8886 /* Find out what character ended the variable name. Then
8887 do the appropriate thing. */
8888 if (c = string[sindex])
8889 sindex++;
8891 /* If c is followed by one of the valid parameter expansion
8892 characters, move past it as normal. If not, assume that
8893 a substring specification is being given, and do not move
8894 past it. */
8895 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
8897 check_nullness++;
8898 if (c = string[sindex])
8899 sindex++;
8901 else if (c == ':' && string[sindex] != RBRACE)
8902 want_substring = 1;
8903 else if (c == '/' /* && string[sindex] != RBRACE */) /* XXX */
8904 want_patsub = 1;
8905 #if defined (CASEMOD_EXPANSIONS)
8906 else if (c == '^' || c == ',' || c == '~')
8908 modspec = c;
8909 want_casemod = 1;
8911 #endif
8912 else if (c == '@' && (string[sindex] == 'a' || string[sindex] == 'A') && string[sindex+1] == RBRACE)
8914 /* special case because we do not want to shortcut foo as foo[0] here */
8915 want_attributes = 1;
8916 local_pflags |= PF_ALLINDS;
8919 /* Catch the valid and invalid brace expressions that made it through the
8920 tests above. */
8921 /* ${#-} is a valid expansion and means to take the length of $-.
8922 Similarly for ${#?} and ${##}... */
8923 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
8924 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
8926 name = (char *)xrealloc (name, 3);
8927 name[1] = c;
8928 name[2] = '\0';
8929 c = string[sindex++];
8932 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
8933 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
8934 member (c, "%:=+/") && string[sindex] == RBRACE)
8936 temp = (char *)NULL;
8937 goto bad_substitution; /* XXX - substitution error */
8940 /* Indirect expansion begins with a `!'. A valid indirect expansion is
8941 either a variable name, one of the positional parameters or a special
8942 variable that expands to one of the positional parameters. */
8943 want_indir = *name == '!' &&
8944 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
8945 || VALID_INDIR_PARAM (name[1]));
8947 /* Determine the value of this variable whose name is NAME. */
8949 /* Check for special variables, directly referenced. */
8950 if (SPECIAL_VAR (name, want_indir))
8951 var_is_special++;
8953 /* Check for special expansion things, like the length of a parameter */
8954 if (*name == '#' && name[1])
8956 /* If we are not pointing at the character just after the
8957 closing brace, then we haven't gotten all of the name.
8958 Since it begins with a special character, this is a bad
8959 substitution. Also check NAME for validity before trying
8960 to go on. */
8961 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
8963 temp = (char *)NULL;
8964 goto bad_substitution; /* substitution error */
8967 number = parameter_brace_expand_length (name);
8968 if (number == INTMAX_MIN && unbound_vars_is_error)
8970 set_exit_status (EXECUTION_FAILURE);
8971 err_unboundvar (name+1);
8972 free (name);
8973 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
8975 free (name);
8977 *indexp = sindex;
8978 if (number < 0)
8979 return (&expand_wdesc_error);
8980 else
8982 ret = alloc_word_desc ();
8983 ret->word = itos (number);
8984 return ret;
8988 /* ${@} is identical to $@. */
8989 if (name[0] == '@' && name[1] == '\0')
8991 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
8992 *quoted_dollar_atp = 1;
8994 if (contains_dollar_at)
8995 *contains_dollar_at = 1;
8997 tflag |= W_DOLLARAT;
9000 /* Process ${!PREFIX*} expansion. */
9001 if (want_indir && string[sindex - 1] == RBRACE &&
9002 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
9003 legal_variable_starter ((unsigned char) name[1]))
9005 char **x;
9006 WORD_LIST *xlist;
9008 temp1 = savestring (name + 1);
9009 number = strlen (temp1);
9010 temp1[number - 1] = '\0';
9011 x = all_variables_matching_prefix (temp1);
9012 xlist = strvec_to_word_list (x, 0, 0);
9013 if (string[sindex - 2] == '*')
9014 temp = string_list_dollar_star (xlist, quoted, 0);
9015 else
9017 temp = string_list_dollar_at (xlist, quoted, 0);
9018 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
9019 *quoted_dollar_atp = 1;
9020 if (contains_dollar_at)
9021 *contains_dollar_at = 1;
9023 tflag |= W_DOLLARAT;
9025 free (x);
9026 dispose_words (xlist);
9027 free (temp1);
9028 *indexp = sindex;
9030 free (name);
9032 ret = alloc_word_desc ();
9033 ret->word = temp;
9034 ret->flags = tflag; /* XXX */
9035 return ret;
9038 #if defined (ARRAY_VARS)
9039 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */
9040 if (want_indir && string[sindex - 1] == RBRACE &&
9041 string[sindex - 2] == RBRACK && valid_array_reference (name+1, 0))
9043 char *x, *x1;
9045 temp1 = savestring (name + 1);
9046 x = array_variable_name (temp1, 0, &x1, (int *)0);
9047 FREE (x);
9048 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == RBRACK)
9050 temp = array_keys (temp1, quoted, pflags); /* handles assoc vars too */
9051 if (x1[0] == '@')
9053 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
9054 *quoted_dollar_atp = 1;
9055 if (contains_dollar_at)
9056 *contains_dollar_at = 1;
9058 tflag |= W_DOLLARAT;
9061 free (name);
9062 free (temp1);
9063 *indexp = sindex;
9065 ret = alloc_word_desc ();
9066 ret->word = temp;
9067 ret->flags = tflag; /* XXX */
9068 return ret;
9071 free (temp1);
9073 #endif /* ARRAY_VARS */
9075 /* Make sure that NAME is valid before trying to go on. */
9076 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
9077 var_is_special) == 0)
9079 temp = (char *)NULL;
9080 goto bad_substitution; /* substitution error */
9083 if (want_indir)
9085 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, pflags|local_pflags, quoted_dollar_atp, contains_dollar_at);
9086 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
9088 temp = (char *)NULL;
9089 goto bad_substitution;
9092 /* Turn off the W_ARRAYIND flag because there is no way for this function
9093 to return the index we're supposed to be using. */
9094 if (tdesc && tdesc->flags)
9095 tdesc->flags &= ~W_ARRAYIND;
9097 else
9099 local_pflags |= PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS));
9100 tdesc = parameter_brace_expand_word (name, var_is_special, quoted, local_pflags, &ind);
9103 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
9105 tflag = 0;
9106 tdesc = 0;
9109 if (tdesc)
9111 temp = tdesc->word;
9112 tflag = tdesc->flags;
9113 dispose_word_desc (tdesc);
9115 else
9116 temp = (char *)0;
9118 if (temp == &expand_param_error || temp == &expand_param_fatal)
9120 FREE (name);
9121 FREE (value);
9122 return (temp == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
9125 #if defined (ARRAY_VARS)
9126 if (valid_array_reference (name, 0))
9128 int qflags;
9129 char *t;
9131 qflags = quoted;
9132 /* If in a context where word splitting will not take place, treat as
9133 if double-quoted. Has effects with $* and ${array[*]} */
9135 if (pflags & PF_ASSIGNRHS)
9136 qflags |= Q_DOUBLE_QUOTES;
9137 /* We duplicate a little code here */
9138 t = mbschr (name, LBRACK);
9139 if (t && ALL_ELEMENT_SUB (t[1]) && t[2] == RBRACK)
9141 all_element_arrayref = 1;
9142 if (expand_no_split_dollar_star && t[1] == '*') /* XXX */
9143 qflags |= Q_DOUBLE_QUOTES;
9145 chk_atstar (name, qflags, pflags, quoted_dollar_atp, contains_dollar_at);
9147 #endif
9149 var_is_set = temp != (char *)0;
9150 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
9151 /* XXX - this may not need to be restricted to special variables */
9152 if (check_nullness)
9153 var_is_null |= var_is_set && var_is_special && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp);
9154 #if defined (ARRAY_VARS)
9155 if (check_nullness)
9156 var_is_null |= var_is_set &&
9157 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) &&
9158 QUOTED_NULL (temp) &&
9159 valid_array_reference (name, 0) &&
9160 chk_atstar (name, 0, 0, (int *)0, (int *)0);
9161 #endif
9163 /* Get the rest of the stuff inside the braces. */
9164 if (c && c != RBRACE)
9166 /* Extract the contents of the ${ ... } expansion
9167 according to the Posix.2 rules. */
9168 value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
9169 if (string[sindex] == RBRACE)
9170 sindex++;
9171 else
9172 goto bad_substitution; /* substitution error */
9174 else
9175 value = (char *)NULL;
9177 *indexp = sindex;
9179 /* All the cases where an expansion can possibly generate an unbound
9180 variable error. */
9181 if (want_substring || want_patsub || want_casemod || c == '@' || c == '#' || c == '%' || c == RBRACE)
9183 if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]) && all_element_arrayref == 0)
9185 set_exit_status (EXECUTION_FAILURE);
9186 err_unboundvar (name);
9187 FREE (value);
9188 FREE (temp);
9189 free (name);
9190 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
9194 /* If this is a substring spec, process it and add the result. */
9195 if (want_substring)
9197 temp1 = parameter_brace_substring (name, temp, ind, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
9198 FREE (value);
9199 FREE (temp);
9201 if (temp1 == &expand_param_error || temp1 == &expand_param_fatal)
9203 FREE (name);
9204 return (temp1 == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
9207 ret = alloc_word_desc ();
9208 ret->word = temp1;
9209 /* We test quoted_dollar_atp because we want variants with double-quoted
9210 "$@" to take a different code path. In fact, we make sure at the end
9211 of expand_word_internal that we're only looking at these flags if
9212 quoted_dollar_at == 0. */
9213 if (temp1 &&
9214 (quoted_dollar_atp == 0 || *quoted_dollar_atp == 0) &&
9215 QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9216 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
9217 else if (temp1 && (name[0] == '*' && name[1] == 0) && quoted == 0 &&
9218 (pflags & PF_ASSIGNRHS))
9219 ret->flags |= W_SPLITSPACE; /* Posix interp 888 */
9220 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9221 else if (temp1 && (name[0] == '*' && name[1] == 0) && quoted == 0 && ifs_is_null)
9222 ret->flags |= W_SPLITSPACE; /* Posix interp 888 */
9224 FREE (name);
9225 return ret;
9227 else if (want_patsub)
9229 temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
9230 FREE (value);
9231 FREE (temp);
9233 if (temp1 == &expand_param_error || temp1 == &expand_param_fatal)
9235 FREE (name);
9236 return (temp1 == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
9239 ret = alloc_word_desc ();
9240 ret->word = temp1;
9241 if (temp1 &&
9242 (quoted_dollar_atp == 0 || *quoted_dollar_atp == 0) &&
9243 QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9244 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
9245 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9246 else if (temp1 && (name[0] == '*' && name[1] == 0) && quoted == 0 && ifs_is_null)
9247 ret->flags |= W_SPLITSPACE; /* Posix interp 888 */
9249 FREE (name);
9250 return ret;
9252 #if defined (CASEMOD_EXPANSIONS)
9253 else if (want_casemod)
9255 temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
9256 FREE (value);
9257 FREE (temp);
9259 if (temp1 == &expand_param_error || temp1 == &expand_param_fatal)
9261 FREE (name);
9262 return (temp1 == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
9265 ret = alloc_word_desc ();
9266 ret->word = temp1;
9267 if (temp1 &&
9268 (quoted_dollar_atp == 0 || *quoted_dollar_atp == 0) &&
9269 QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9270 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
9271 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9272 else if (temp1 && (name[0] == '*' && name[1] == 0) && quoted == 0 && ifs_is_null)
9273 ret->flags |= W_SPLITSPACE; /* Posix interp 888 */
9275 FREE (name);
9276 return ret;
9278 #endif
9280 /* Do the right thing based on which character ended the variable name. */
9281 switch (c)
9283 default:
9284 case '\0':
9285 bad_substitution:
9286 set_exit_status (EXECUTION_FAILURE);
9287 report_error (_("%s: bad substitution"), string ? string : "??");
9288 FREE (value);
9289 FREE (temp);
9290 free (name);
9291 if (shell_compatibility_level <= 43)
9292 return &expand_wdesc_error;
9293 else
9294 return ((posixly_correct && interactive_shell == 0) ? &expand_wdesc_fatal : &expand_wdesc_error);
9296 case RBRACE:
9297 break;
9299 case '@':
9300 temp1 = parameter_brace_transform (name, temp, ind, value, c, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
9301 free (temp);
9302 free (value);
9304 if (temp1 == &expand_param_error || temp1 == &expand_param_fatal)
9306 free (name);
9307 set_exit_status (EXECUTION_FAILURE);
9308 report_error (_("%s: bad substitution"), string ? string : "??");
9309 return (temp1 == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
9312 ret = alloc_word_desc ();
9313 ret->word = temp1;
9314 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9315 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
9316 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9317 else if (temp1 && (name[0] == '*' && name[1] == 0) && quoted == 0 && ifs_is_null)
9318 ret->flags |= W_SPLITSPACE; /* Posix interp 888 */
9320 free (name);
9321 return ret;
9323 case '#': /* ${param#[#]pattern} */
9324 case '%': /* ${param%[%]pattern} */
9325 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
9327 FREE (value);
9328 break;
9330 temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
9331 free (temp);
9332 free (value);
9334 ret = alloc_word_desc ();
9335 ret->word = temp1;
9336 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9337 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
9338 /* Special handling for $* when unquoted and $IFS is null. Posix interp 888 */
9339 else if (temp1 && (name[0] == '*' && name[1] == 0) && quoted == 0 && ifs_is_null)
9340 ret->flags |= W_SPLITSPACE; /* Posix interp 888 */
9342 free (name);
9343 return ret;
9345 case '-':
9346 case '=':
9347 case '?':
9348 case '+':
9349 if (var_is_set && var_is_null == 0)
9351 /* If the operator is `+', we don't want the value of the named
9352 variable for anything, just the value of the right hand side. */
9353 if (c == '+')
9355 /* XXX -- if we're double-quoted and the named variable is "$@",
9356 we want to turn off any special handling of "$@" --
9357 we're not using it, so whatever is on the rhs applies. */
9358 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
9359 *quoted_dollar_atp = 0;
9360 if (contains_dollar_at)
9361 *contains_dollar_at = 0;
9363 FREE (temp);
9364 if (value)
9366 /* From Posix discussion on austin-group list. Issue 221
9367 requires that backslashes escaping `}' inside
9368 double-quoted ${...} be removed. */
9369 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
9370 quoted |= Q_DOLBRACE;
9371 ret = parameter_brace_expand_rhs (name, value, c,
9372 quoted,
9373 pflags,
9374 quoted_dollar_atp,
9375 contains_dollar_at);
9376 /* XXX - fix up later, esp. noting presence of
9377 W_HASQUOTEDNULL in ret->flags */
9378 free (value);
9380 else
9381 temp = (char *)NULL;
9383 else
9385 FREE (value);
9387 /* Otherwise do nothing; just use the value in TEMP. */
9389 else /* VAR not set or VAR is NULL. */
9391 FREE (temp);
9392 temp = (char *)NULL;
9393 if (c == '=' && var_is_special)
9395 set_exit_status (EXECUTION_FAILURE);
9396 report_error (_("$%s: cannot assign in this way"), name);
9397 free (name);
9398 free (value);
9399 return &expand_wdesc_error;
9401 else if (c == '?')
9403 parameter_brace_expand_error (name, value, check_nullness);
9404 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
9406 else if (c != '+')
9408 /* XXX -- if we're double-quoted and the named variable is "$@",
9409 we want to turn off any special handling of "$@" --
9410 we're not using it, so whatever is on the rhs applies. */
9411 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
9412 *quoted_dollar_atp = 0;
9413 if (contains_dollar_at)
9414 *contains_dollar_at = 0;
9416 /* From Posix discussion on austin-group list. Issue 221 requires
9417 that backslashes escaping `}' inside double-quoted ${...} be
9418 removed. */
9419 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
9420 quoted |= Q_DOLBRACE;
9421 ret = parameter_brace_expand_rhs (name, value, c, quoted, pflags,
9422 quoted_dollar_atp,
9423 contains_dollar_at);
9424 /* XXX - fix up later, esp. noting presence of
9425 W_HASQUOTEDNULL in tdesc->flags */
9427 free (value);
9430 break;
9432 free (name);
9434 if (ret == 0)
9436 ret = alloc_word_desc ();
9437 ret->flags = tflag;
9438 ret->word = temp;
9440 return (ret);
9443 /* Expand a single ${xxx} expansion. The braces are optional. When
9444 the braces are used, parameter_brace_expand() does the work,
9445 possibly calling param_expand recursively. */
9446 static WORD_DESC *
9447 param_expand (string, sindex, quoted, expanded_something,
9448 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
9449 pflags)
9450 char *string;
9451 int *sindex, quoted, *expanded_something, *contains_dollar_at;
9452 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
9454 char *temp, *temp1, uerror[3], *savecmd;
9455 int zindex, t_index, expok;
9456 unsigned char c;
9457 intmax_t number;
9458 SHELL_VAR *var;
9459 WORD_LIST *list, *l;
9460 WORD_DESC *tdesc, *ret;
9461 int tflag, nullarg;
9463 /*itrace("param_expand: `%s' pflags = %d", string+*sindex, pflags);*/
9464 zindex = *sindex;
9465 c = string[++zindex];
9467 temp = (char *)NULL;
9468 ret = tdesc = (WORD_DESC *)NULL;
9469 tflag = 0;
9471 /* Do simple cases first. Switch on what follows '$'. */
9472 switch (c)
9474 /* $0 .. $9? */
9475 case '0':
9476 case '1':
9477 case '2':
9478 case '3':
9479 case '4':
9480 case '5':
9481 case '6':
9482 case '7':
9483 case '8':
9484 case '9':
9485 temp1 = dollar_vars[TODIGIT (c)];
9486 /* This doesn't get called when (pflags&PF_IGNUNBOUND) != 0 */
9487 if (unbound_vars_is_error && temp1 == (char *)NULL)
9489 uerror[0] = '$';
9490 uerror[1] = c;
9491 uerror[2] = '\0';
9492 set_exit_status (EXECUTION_FAILURE);
9493 err_unboundvar (uerror);
9494 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
9496 if (temp1)
9497 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9498 ? quote_string (temp1)
9499 : quote_escapes (temp1);
9500 else
9501 temp = (char *)NULL;
9503 break;
9505 /* $$ -- pid of the invoking shell. */
9506 case '$':
9507 temp = itos (dollar_dollar_pid);
9508 break;
9510 /* $# -- number of positional parameters. */
9511 case '#':
9512 temp = itos (number_of_args ());
9513 break;
9515 /* $? -- return value of the last synchronous command. */
9516 case '?':
9517 temp = itos (last_command_exit_value);
9518 break;
9520 /* $- -- flags supplied to the shell on invocation or by `set'. */
9521 case '-':
9522 temp = which_set_flags ();
9523 break;
9525 /* $! -- Pid of the last asynchronous command. */
9526 case '!':
9527 /* If no asynchronous pids have been created, expand to nothing.
9528 If `set -u' has been executed, and no async processes have
9529 been created, this is an expansion error. */
9530 if (last_asynchronous_pid == NO_PID)
9532 if (expanded_something)
9533 *expanded_something = 0;
9534 temp = (char *)NULL;
9535 if (unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
9537 uerror[0] = '$';
9538 uerror[1] = c;
9539 uerror[2] = '\0';
9540 set_exit_status (EXECUTION_FAILURE);
9541 err_unboundvar (uerror);
9542 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
9545 else
9546 temp = itos (last_asynchronous_pid);
9547 break;
9549 /* The only difference between this and $@ is when the arg is quoted. */
9550 case '*': /* `$*' */
9551 list = list_rest_of_args ();
9553 #if 0
9554 /* According to austin-group posix proposal by Geoff Clare in
9555 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
9557 "The shell shall write a message to standard error and
9558 immediately exit when it tries to expand an unset parameter
9559 other than the '@' and '*' special parameters."
9562 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
9564 uerror[0] = '$';
9565 uerror[1] = '*';
9566 uerror[2] = '\0';
9567 set_exit_status (EXECUTION_FAILURE);
9568 err_unboundvar (uerror);
9569 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
9571 #endif
9573 /* If there are no command-line arguments, this should just
9574 disappear if there are other characters in the expansion,
9575 even if it's quoted. */
9576 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
9577 temp = (char *)NULL;
9578 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
9580 /* If we have "$*" we want to make a string of the positional
9581 parameters, separated by the first character of $IFS, and
9582 quote the whole string, including the separators. If IFS
9583 is unset, the parameters are separated by ' '; if $IFS is
9584 null, the parameters are concatenated. */
9585 temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list, quoted, 0) : string_list (list);
9586 if (temp)
9588 temp1 = (quoted & Q_DOUBLE_QUOTES) ? quote_string (temp) : temp;
9589 if (*temp == 0)
9590 tflag |= W_HASQUOTEDNULL;
9591 if (temp != temp1)
9592 free (temp);
9593 temp = temp1;
9596 else
9598 /* We check whether or not we're eventually going to split $* here,
9599 for example when IFS is empty and we are processing the rhs of
9600 an assignment statement. In that case, we don't separate the
9601 arguments at all. Otherwise, if the $* is not quoted it is
9602 identical to $@ */
9603 if (expand_no_split_dollar_star && quoted == 0 && ifs_is_set == 0 && (pflags & PF_ASSIGNRHS))
9605 /* Posix interp 888: RHS of assignment, IFS unset: no splitting,
9606 separate with space */
9607 temp1 = string_list_dollar_star (list, quoted, pflags);
9608 temp = temp1 ? quote_string (temp1) : temp1;
9609 /* XXX - tentative - note that we saw a quoted null here */
9610 if (temp1 && *temp1 == 0 && QUOTED_NULL (temp))
9611 tflag |= W_SAWQUOTEDNULL;
9612 FREE (temp1);
9614 else if (expand_no_split_dollar_star && quoted == 0 && ifs_is_null && (pflags & PF_ASSIGNRHS))
9616 /* Posix interp 888: RHS of assignment, IFS set to '' */
9617 temp1 = string_list_dollar_star (list, quoted, pflags);
9618 temp = temp1 ? quote_escapes (temp1) : temp1;
9619 FREE (temp1);
9621 else if (expand_no_split_dollar_star && quoted == 0 && ifs_is_set && ifs_is_null == 0 && (pflags & PF_ASSIGNRHS))
9623 /* Posix interp 888: RHS of assignment, IFS set to non-null value */
9624 temp1 = string_list_dollar_star (list, quoted, pflags);
9625 temp = temp1 ? quote_string (temp1) : temp1;
9627 /* XXX - tentative - note that we saw a quoted null here */
9628 if (temp1 && *temp1 == 0 && QUOTED_NULL (temp))
9629 tflag |= W_SAWQUOTEDNULL;
9630 FREE (temp1);
9632 /* XXX - should we check ifs_is_set here as well? */
9633 # if defined (HANDLE_MULTIBYTE)
9634 else if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
9635 # else
9636 else if (expand_no_split_dollar_star && ifs_firstc == 0)
9637 # endif
9638 /* Posix interp 888: not RHS, no splitting, IFS set to '' */
9639 temp = string_list_dollar_star (list, quoted, 0);
9640 else
9642 temp = string_list_dollar_at (list, quoted, 0);
9643 /* Set W_SPLITSPACE to make sure the individual positional
9644 parameters are split into separate arguments */
9645 #if 0
9646 if (quoted == 0 && (ifs_is_set == 0 || ifs_is_null))
9647 #else /* change with bush-5.0 */
9648 if (quoted == 0 && ifs_is_null)
9649 #endif
9650 tflag |= W_SPLITSPACE;
9651 /* If we're not quoted but we still don't want word splitting, make
9652 we quote the IFS characters to protect them from splitting (e.g.,
9653 when $@ is in the string as well). */
9654 else if (temp && quoted == 0 && ifs_is_set && (pflags & PF_ASSIGNRHS))
9656 temp1 = quote_string (temp);
9657 free (temp);
9658 temp = temp1;
9662 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
9663 *contains_dollar_at = 1;
9666 dispose_words (list);
9667 break;
9669 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
9670 means that we have to turn quoting off after we split into
9671 the individually quoted arguments so that the final split
9672 on the first character of $IFS is still done. */
9673 case '@': /* `$@' */
9674 list = list_rest_of_args ();
9676 #if 0
9677 /* According to austin-group posix proposal by Geoff Clare in
9678 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
9680 "The shell shall write a message to standard error and
9681 immediately exit when it tries to expand an unset parameter
9682 other than the '@' and '*' special parameters."
9685 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
9687 uerror[0] = '$';
9688 uerror[1] = '@';
9689 uerror[2] = '\0';
9690 set_exit_status (EXECUTION_FAILURE);
9691 err_unboundvar (uerror);
9692 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
9694 #endif
9696 for (nullarg = 0, l = list; l; l = l->next)
9698 if (l->word && (l->word->word == 0 || l->word->word[0] == 0))
9699 nullarg = 1;
9702 /* We want to flag the fact that we saw this. We can't turn
9703 off quoting entirely, because other characters in the
9704 string might need it (consider "\"$@\""), but we need some
9705 way to signal that the final split on the first character
9706 of $IFS should be done, even though QUOTED is 1. */
9707 /* XXX - should this test include Q_PATQUOTE? */
9708 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9709 *quoted_dollar_at_p = 1;
9710 if (contains_dollar_at)
9711 *contains_dollar_at = 1;
9713 /* We want to separate the positional parameters with the first
9714 character of $IFS in case $IFS is something other than a space.
9715 We also want to make sure that splitting is done no matter what --
9716 according to POSIX.2, this expands to a list of the positional
9717 parameters no matter what IFS is set to. */
9718 /* XXX - what to do when in a context where word splitting is not
9719 performed? Even when IFS is not the default, posix seems to imply
9720 that we have to expand $@ to all the positional parameters and
9721 separate them with spaces, which are preserved because word splitting
9722 doesn't take place. See below for how we use PF_NOSPLIT2 here. */
9724 /* These are the cases where word splitting will not be performed. */
9725 if (pflags & PF_ASSIGNRHS)
9727 temp = string_list_dollar_at (list, (quoted|Q_DOUBLE_QUOTES), pflags);
9728 if (nullarg)
9729 tflag |= W_HASQUOTEDNULL; /* we know quoting produces quoted nulls */
9732 /* This needs to match what expand_word_internal does with non-quoted $@
9733 does with separating with spaces. Passing Q_DOUBLE_QUOTES means that
9734 the characters in LIST will be quoted, and PF_ASSIGNRHS ensures that
9735 they will separated by spaces. After doing this, we need the special
9736 handling for PF_NOSPLIT2 in expand_word_internal to remove the CTLESC
9737 quotes. */
9738 else if (pflags & PF_NOSPLIT2)
9740 #if defined (HANDLE_MULTIBYTE)
9741 if (quoted == 0 && ifs_is_set && ifs_is_null == 0 && ifs_firstc[0] != ' ')
9742 #else
9743 if (quoted == 0 && ifs_is_set && ifs_is_null == 0 && ifs_firstc != ' ')
9744 #endif
9745 /* Posix interp 888 */
9746 temp = string_list_dollar_at (list, Q_DOUBLE_QUOTES, pflags);
9747 else
9748 temp = string_list_dollar_at (list, quoted, pflags);
9750 else
9751 temp = string_list_dollar_at (list, quoted, pflags);
9753 tflag |= W_DOLLARAT;
9754 dispose_words (list);
9755 break;
9757 case LBRACE:
9758 tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
9759 quoted_dollar_at_p,
9760 contains_dollar_at);
9762 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
9763 return (tdesc);
9764 temp = tdesc ? tdesc->word : (char *)0;
9766 /* XXX */
9767 /* Quoted nulls should be removed if there is anything else
9768 in the string. */
9769 /* Note that we saw the quoted null so we can add one back at
9770 the end of this function if there are no other characters
9771 in the string, discard TEMP, and go on. The exception to
9772 this is when we have "${@}" and $1 is '', since $@ needs
9773 special handling. */
9774 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
9776 if (had_quoted_null_p)
9777 *had_quoted_null_p = 1;
9778 if (*quoted_dollar_at_p == 0)
9780 free (temp);
9781 tdesc->word = temp = (char *)NULL;
9786 ret = tdesc;
9787 goto return0;
9789 /* Do command or arithmetic substitution. */
9790 case LPAREN:
9791 /* We have to extract the contents of this paren substitution. */
9792 t_index = zindex + 1;
9793 /* XXX - might want to check for string[t_index+2] == LPAREN and parse
9794 as arithmetic substitution immediately. */
9795 temp = extract_command_subst (string, &t_index, (pflags&PF_COMPLETE) ? SX_COMPLETE : 0);
9796 zindex = t_index;
9798 /* For Posix.2-style `$(( ))' arithmetic substitution,
9799 extract the expression and pass it to the evaluator. */
9800 if (temp && *temp == LPAREN)
9802 char *temp2;
9803 temp1 = temp + 1;
9804 temp2 = savestring (temp1);
9805 t_index = strlen (temp2) - 1;
9807 if (temp2[t_index] != RPAREN)
9809 free (temp2);
9810 goto comsub;
9813 /* Cut off ending `)' */
9814 temp2[t_index] = '\0';
9816 if (chk_arithsub (temp2, t_index) == 0)
9818 free (temp2);
9819 #if 0
9820 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
9821 #endif
9822 goto comsub;
9825 /* Expand variables found inside the expression. */
9826 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES|Q_ARITH);
9827 free (temp2);
9829 arithsub:
9830 /* No error messages. */
9831 savecmd = this_command_name;
9832 this_command_name = (char *)NULL;
9833 number = evalexp (temp1, EXP_EXPANDED, &expok);
9834 this_command_name = savecmd;
9835 free (temp);
9836 free (temp1);
9837 if (expok == 0)
9839 if (interactive_shell == 0 && posixly_correct)
9841 set_exit_status (EXECUTION_FAILURE);
9842 return (&expand_wdesc_fatal);
9844 else
9845 return (&expand_wdesc_error);
9847 temp = itos (number);
9848 break;
9851 comsub:
9852 if (pflags & PF_NOCOMSUB)
9853 /* we need zindex+1 because string[zindex] == RPAREN */
9854 temp1 = substring (string, *sindex, zindex+1);
9855 else
9857 tdesc = command_substitute (temp, quoted, pflags&PF_ASSIGNRHS);
9858 temp1 = tdesc ? tdesc->word : (char *)NULL;
9859 if (tdesc)
9860 dispose_word_desc (tdesc);
9862 FREE (temp);
9863 temp = temp1;
9864 break;
9866 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
9867 away in a future bush release. */
9868 case '[': /*]*/
9869 /* Extract the contents of this arithmetic substitution. */
9870 t_index = zindex + 1;
9871 temp = extract_arithmetic_subst (string, &t_index);
9872 zindex = t_index;
9873 if (temp == 0)
9875 temp = savestring (string);
9876 if (expanded_something)
9877 *expanded_something = 0;
9878 goto return0;
9881 /* Do initial variable expansion. */
9882 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES|Q_ARITH);
9884 goto arithsub;
9886 default:
9887 /* Find the variable in VARIABLE_LIST. */
9888 temp = (char *)NULL;
9890 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
9892 if (c == ':')
9894 if (string[zindex+1] == ':')
9895 zindex++;
9896 else
9897 break;
9899 zindex++;
9901 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
9903 /* If this isn't a variable name, then just output the `$'. */
9904 if (temp1 == 0 || *temp1 == '\0')
9906 FREE (temp1);
9907 temp = (char *)xmalloc (2);
9908 temp[0] = '$';
9909 temp[1] = '\0';
9910 if (expanded_something)
9911 *expanded_something = 0;
9912 goto return0;
9915 /* If the variable exists, return its value cell. */
9916 var = find_variable (temp1);
9918 if (var && invisible_p (var) == 0 && var_isset (var))
9920 #if defined (ARRAY_VARS)
9921 if (assoc_p (var) || array_p (var))
9923 temp = array_p (var) ? array_reference (array_cell (var), 0)
9924 : assoc_reference (assoc_cell (var), "0");
9925 if (temp)
9926 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9927 ? quote_string (temp)
9928 : quote_escapes (temp);
9929 else if (unbound_vars_is_error)
9930 goto unbound_variable;
9932 else
9933 #endif
9935 temp = value_cell (var);
9937 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
9938 ? quote_string (temp)
9939 : ((pflags & PF_ASSIGNRHS) ? quote_rhs (temp)
9940 : quote_escapes (temp));
9943 free (temp1);
9945 goto return0;
9947 else if (var && (invisible_p (var) || var_isset (var) == 0))
9948 temp = (char *)NULL;
9949 else if ((var = find_variable_last_nameref (temp1, 0)) && var_isset (var) && invisible_p (var) == 0)
9951 temp = nameref_cell (var);
9952 #if defined (ARRAY_VARS)
9953 if (temp && *temp && valid_array_reference (temp, 0))
9955 tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL);
9956 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
9957 return (tdesc);
9958 ret = tdesc;
9959 goto return0;
9961 else
9962 #endif
9963 /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
9964 if (temp && *temp && legal_identifier (temp) == 0)
9966 set_exit_status (EXECUTION_FAILURE);
9967 report_error (_("%s: invalid variable name for name reference"), temp);
9968 return (&expand_wdesc_error); /* XXX */
9970 else
9971 temp = (char *)NULL;
9974 temp = (char *)NULL;
9976 unbound_variable:
9977 if (unbound_vars_is_error)
9979 set_exit_status (EXECUTION_FAILURE);
9980 err_unboundvar (temp1);
9982 else
9984 free (temp1);
9985 goto return0;
9988 free (temp1);
9989 set_exit_status (EXECUTION_FAILURE);
9990 return ((unbound_vars_is_error && interactive_shell == 0)
9991 ? &expand_wdesc_fatal
9992 : &expand_wdesc_error);
9995 if (string[zindex])
9996 zindex++;
9998 return0:
9999 *sindex = zindex;
10001 if (ret == 0)
10003 ret = alloc_word_desc ();
10004 ret->flags = tflag; /* XXX */
10005 ret->word = temp;
10007 return ret;
10010 void
10011 invalidate_cached_quoted_dollar_at ()
10013 dispose_words (cached_quoted_dollar_at);
10014 cached_quoted_dollar_at = 0;
10017 /* Make a word list which is the result of parameter and variable
10018 expansion, command substitution, arithmetic substitution, and
10019 quote removal of WORD. Return a pointer to a WORD_LIST which is
10020 the result of the expansion. If WORD contains a null word, the
10021 word list returned is also null.
10023 QUOTED contains flag values defined in shell.h.
10025 ISEXP is used to tell expand_word_internal that the word should be
10026 treated as the result of an expansion. This has implications for
10027 how IFS characters in the word are treated.
10029 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
10030 they point to an integer value which receives information about expansion.
10031 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
10032 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
10033 else zero.
10035 This only does word splitting in the case of $@ expansion. In that
10036 case, we split on ' '. */
10038 /* Values for the local variable quoted_state. */
10039 #define UNQUOTED 0
10040 #define PARTIALLY_QUOTED 1
10041 #define WHOLLY_QUOTED 2
10043 static WORD_LIST *
10044 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
10045 WORD_DESC *word;
10046 int quoted, isexp;
10047 int *contains_dollar_at;
10048 int *expanded_something;
10050 WORD_LIST *list;
10051 WORD_DESC *tword;
10053 /* The intermediate string that we build while expanding. */
10054 char *istring;
10056 /* The current size of the above object. */
10057 size_t istring_size;
10059 /* Index into ISTRING. */
10060 int istring_index;
10062 /* Temporary string storage. */
10063 char *temp, *temp1;
10065 /* The text of WORD. */
10066 register char *string;
10068 /* The size of STRING. */
10069 size_t string_size;
10071 /* The index into STRING. */
10072 int sindex;
10074 /* This gets 1 if we see a $@ while quoted. */
10075 int quoted_dollar_at;
10077 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
10078 whether WORD contains no quoting characters, a partially quoted
10079 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
10080 int quoted_state;
10082 /* State flags */
10083 int had_quoted_null;
10084 int has_quoted_ifs; /* did we add a quoted $IFS character here? */
10085 int has_dollar_at, temp_has_dollar_at;
10086 int split_on_spaces;
10087 int local_expanded;
10088 int tflag;
10089 int pflags; /* flags passed to param_expand */
10090 int mb_cur_max;
10092 int assignoff; /* If assignment, offset of `=' */
10094 register unsigned char c; /* Current character. */
10095 int t_index; /* For calls to string_extract_xxx. */
10097 char twochars[2];
10099 DECLARE_MBSTATE;
10101 /* OK, let's see if we can optimize a common idiom: "$@" */
10102 if (STREQ (word->word, "\"$@\"") &&
10103 (word->flags == (W_HASDOLLAR|W_QUOTED)) &&
10104 dollar_vars[1]) /* XXX - check IFS here as well? */
10106 if (contains_dollar_at)
10107 *contains_dollar_at = 1;
10108 if (expanded_something)
10109 *expanded_something = 1;
10110 if (cached_quoted_dollar_at)
10111 return (copy_word_list (cached_quoted_dollar_at));
10112 list = list_rest_of_args ();
10113 list = quote_list (list);
10114 cached_quoted_dollar_at = copy_word_list (list);
10115 return (list);
10118 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
10119 istring[istring_index = 0] = '\0';
10120 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
10121 has_quoted_ifs = 0;
10122 split_on_spaces = 0;
10123 quoted_state = UNQUOTED;
10125 string = word->word;
10126 if (string == 0)
10127 goto finished_with_string;
10128 mb_cur_max = MB_CUR_MAX;
10130 /* Don't need the string length for the SADD... and COPY_ macros unless
10131 multibyte characters are possible, but do need it for bounds checking. */
10132 string_size = (mb_cur_max > 1) ? strlen (string) : 1;
10134 if (contains_dollar_at)
10135 *contains_dollar_at = 0;
10137 assignoff = -1;
10139 /* Begin the expansion. */
10141 for (sindex = 0; ;)
10143 c = string[sindex];
10145 /* Case on top-level character. */
10146 switch (c)
10148 case '\0':
10149 goto finished_with_string;
10151 case CTLESC:
10152 sindex++;
10153 #if HANDLE_MULTIBYTE
10154 if (mb_cur_max > 1 && string[sindex])
10156 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
10158 else
10159 #endif
10161 temp = (char *)xmalloc (3);
10162 temp[0] = CTLESC;
10163 temp[1] = c = string[sindex];
10164 temp[2] = '\0';
10167 dollar_add_string:
10168 if (string[sindex])
10169 sindex++;
10171 add_string:
10172 if (temp)
10174 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
10175 temp = (char *)0;
10178 break;
10180 #if defined (PROCESS_SUBSTITUTION)
10181 /* Process substitution. */
10182 case '<':
10183 case '>':
10185 /* XXX - technically this should only be expanded at the start
10186 of a word */
10187 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)))
10189 sindex--; /* add_character: label increments sindex */
10190 goto add_character;
10192 else
10193 t_index = sindex + 1; /* skip past both '<' and LPAREN */
10195 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index, 0); /*))*/
10196 sindex = t_index;
10198 /* If the process substitution specification is `<()', we want to
10199 open the pipe for writing in the child and produce output; if
10200 it is `>()', we want to open the pipe for reading in the child
10201 and consume input. */
10202 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
10204 FREE (temp1);
10206 goto dollar_add_string;
10208 #endif /* PROCESS_SUBSTITUTION */
10210 case '=':
10211 /* Posix.2 section 3.6.1 says that tildes following `=' in words
10212 which are not assignment statements are not expanded. If the
10213 shell isn't in posix mode, though, we perform tilde expansion
10214 on `likely candidate' unquoted assignment statements (flags
10215 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
10216 contains an unquoted :~ or =~. Something to think about: we
10217 now have a flag that says to perform tilde expansion on arguments
10218 to `assignment builtins' like declare and export that look like
10219 assignment statements. We now do tilde expansion on such words
10220 even in POSIX mode. */
10221 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
10223 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
10224 goto add_ifs_character;
10225 else
10226 goto add_character;
10228 /* If we're not in posix mode or forcing assignment-statement tilde
10229 expansion, note where the first `=' appears in the word and prepare
10230 to do tilde expansion following the first `='. We have to keep
10231 track of the first `=' (using assignoff) to avoid being confused
10232 by an `=' in the rhs of the assignment statement. */
10233 if ((word->flags & W_ASSIGNMENT) &&
10234 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
10235 assignoff == -1 && sindex > 0)
10236 assignoff = sindex;
10237 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
10238 word->flags |= W_ITILDE;
10240 if (word->flags & W_ASSIGNARG)
10241 word->flags |= W_ASSIGNRHS; /* affects $@ */
10243 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
10245 has_quoted_ifs++;
10246 goto add_ifs_character;
10248 else
10249 goto add_character;
10251 case ':':
10252 if (word->flags & (W_NOTILDE|W_NOASSNTILDE))
10254 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
10255 goto add_ifs_character;
10256 else
10257 goto add_character;
10260 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS)) &&
10261 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
10262 string[sindex+1] == '~')
10263 word->flags |= W_ITILDE;
10265 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
10266 goto add_ifs_character;
10267 else
10268 goto add_character;
10270 case '~':
10271 /* If the word isn't supposed to be tilde expanded, or we're not
10272 at the start of a word or after an unquoted : or = in an
10273 assignment statement, we don't do tilde expansion. We don't
10274 do tilde expansion if quoted or in an arithmetic context. */
10276 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
10277 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
10278 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
10280 word->flags &= ~W_ITILDE;
10281 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
10282 goto add_ifs_character;
10283 else
10284 goto add_character;
10287 if (word->flags & W_ASSIGNRHS)
10288 tflag = 2;
10289 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
10290 tflag = 1;
10291 else
10292 tflag = 0;
10294 temp = bush_tilde_find_word (string + sindex, tflag, &t_index);
10296 word->flags &= ~W_ITILDE;
10298 if (temp && *temp && t_index > 0)
10300 temp1 = bush_tilde_expand (temp, tflag);
10301 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
10303 FREE (temp);
10304 FREE (temp1);
10305 goto add_character; /* tilde expansion failed */
10307 free (temp);
10308 temp = temp1;
10309 sindex += t_index;
10310 goto add_quoted_string; /* XXX was add_string */
10312 else
10314 FREE (temp);
10315 goto add_character;
10318 case '$':
10319 if (expanded_something)
10320 *expanded_something = 1;
10321 local_expanded = 1;
10323 temp_has_dollar_at = 0;
10324 pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
10325 if (word->flags & W_NOSPLIT2)
10326 pflags |= PF_NOSPLIT2;
10327 if (word->flags & W_ASSIGNRHS)
10328 pflags |= PF_ASSIGNRHS;
10329 if (word->flags & W_COMPLETE)
10330 pflags |= PF_COMPLETE;
10332 tword = param_expand (string, &sindex, quoted, expanded_something,
10333 &temp_has_dollar_at, &quoted_dollar_at,
10334 &had_quoted_null, pflags);
10335 has_dollar_at += temp_has_dollar_at;
10336 split_on_spaces += (tword->flags & W_SPLITSPACE);
10338 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
10340 free (string);
10341 free (istring);
10342 return ((tword == &expand_wdesc_error) ? &expand_word_error
10343 : &expand_word_fatal);
10345 if (contains_dollar_at && has_dollar_at)
10346 *contains_dollar_at = 1;
10348 if (tword && (tword->flags & W_HASQUOTEDNULL))
10349 had_quoted_null = 1; /* note for later */
10350 if (tword && (tword->flags & W_SAWQUOTEDNULL))
10351 had_quoted_null = 1; /* XXX */
10353 temp = tword ? tword->word : (char *)NULL;
10354 dispose_word_desc (tword);
10356 /* Kill quoted nulls; we will add them back at the end of
10357 expand_word_internal if nothing else in the string */
10358 if (had_quoted_null && temp && QUOTED_NULL (temp))
10360 FREE (temp);
10361 temp = (char *)NULL;
10364 goto add_string;
10365 break;
10367 case '`': /* Backquoted command substitution. */
10369 t_index = sindex++;
10371 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
10372 /* The test of sindex against t_index is to allow bare instances of
10373 ` to pass through, for backwards compatibility. */
10374 if (temp == &extract_string_error || temp == &extract_string_fatal)
10376 if (sindex - 1 == t_index)
10378 sindex = t_index;
10379 goto add_character;
10381 set_exit_status (EXECUTION_FAILURE);
10382 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
10383 free (string);
10384 free (istring);
10385 return ((temp == &extract_string_error) ? &expand_word_error
10386 : &expand_word_fatal);
10389 if (expanded_something)
10390 *expanded_something = 1;
10391 local_expanded = 1;
10393 if (word->flags & W_NOCOMSUB)
10394 /* sindex + 1 because string[sindex] == '`' */
10395 temp1 = substring (string, t_index, sindex + 1);
10396 else
10398 de_backslash (temp);
10399 tword = command_substitute (temp, quoted, 0);
10400 temp1 = tword ? tword->word : (char *)NULL;
10401 if (tword)
10402 dispose_word_desc (tword);
10404 FREE (temp);
10405 temp = temp1;
10406 goto dollar_add_string;
10409 case '\\':
10410 if (string[sindex + 1] == '\n')
10412 sindex += 2;
10413 continue;
10416 c = string[++sindex];
10418 /* "However, the double-quote character ( '"' ) shall not be treated
10419 specially within a here-document, except when the double-quote
10420 appears within "$()", "``", or "${}"." */
10421 if ((quoted & Q_HERE_DOCUMENT) && (quoted & Q_DOLBRACE) && c == '"')
10422 tflag = CBSDQUOTE; /* special case */
10423 else if (quoted & Q_HERE_DOCUMENT)
10424 tflag = CBSHDOC;
10425 else if (quoted & Q_DOUBLE_QUOTES)
10426 tflag = CBSDQUOTE;
10427 else
10428 tflag = 0;
10430 /* From Posix discussion on austin-group list: Backslash escaping
10431 a } in ${...} is removed. Issue 0000221 */
10432 if ((quoted & Q_DOLBRACE) && c == RBRACE)
10434 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
10436 /* This is the fix for " $@\ " */
10437 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0) && isexp == 0 && isifs (c))
10439 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
10440 DEFAULT_ARRAY_SIZE);
10441 istring[istring_index++] = CTLESC;
10442 istring[istring_index++] = '\\';
10443 istring[istring_index] = '\0';
10445 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
10447 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && c == 0)
10449 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
10450 DEFAULT_ARRAY_SIZE);
10451 istring[istring_index++] = CTLESC;
10452 istring[istring_index++] = '\\';
10453 istring[istring_index] = '\0';
10454 break;
10456 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
10458 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
10460 else if (c == 0)
10462 c = CTLNUL;
10463 sindex--; /* add_character: label increments sindex */
10464 goto add_character;
10466 else
10468 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
10471 sindex++;
10472 add_twochars:
10473 /* BEFORE jumping here, we need to increment sindex if appropriate */
10474 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
10475 DEFAULT_ARRAY_SIZE);
10476 istring[istring_index++] = twochars[0];
10477 istring[istring_index++] = twochars[1];
10478 istring[istring_index] = '\0';
10480 break;
10482 case '"':
10483 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) && ((quoted & Q_ARITH) == 0))
10484 goto add_character;
10486 t_index = ++sindex;
10487 temp = string_extract_double_quoted (string, &sindex, (word->flags & W_COMPLETE) ? SX_COMPLETE : 0);
10489 /* If the quotes surrounded the entire string, then the
10490 whole word was quoted. */
10491 quoted_state = (t_index == 1 && string[sindex] == '\0')
10492 ? WHOLLY_QUOTED
10493 : PARTIALLY_QUOTED;
10495 if (temp && *temp)
10497 tword = alloc_word_desc ();
10498 tword->word = temp;
10500 if (word->flags & W_ASSIGNARG)
10501 tword->flags |= word->flags & (W_ASSIGNARG|W_ASSIGNRHS); /* affects $@ */
10502 if (word->flags & W_COMPLETE)
10503 tword->flags |= W_COMPLETE; /* for command substitutions */
10504 if (word->flags & W_NOCOMSUB)
10505 tword->flags |= W_NOCOMSUB;
10506 if (word->flags & W_NOPROCSUB)
10507 tword->flags |= W_NOPROCSUB;
10509 if (word->flags & W_ASSIGNRHS)
10510 tword->flags |= W_ASSIGNRHS;
10512 temp = (char *)NULL;
10514 temp_has_dollar_at = 0; /* does this quoted (sub)string include $@? */
10515 /* Need to get W_HASQUOTEDNULL flag through this function. */
10516 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &temp_has_dollar_at, (int *)NULL);
10517 has_dollar_at += temp_has_dollar_at;
10519 if (list == &expand_word_error || list == &expand_word_fatal)
10521 free (istring);
10522 free (string);
10523 /* expand_word_internal has already freed temp_word->word
10524 for us because of the way it prints error messages. */
10525 tword->word = (char *)NULL;
10526 dispose_word (tword);
10527 return list;
10530 dispose_word (tword);
10532 /* "$@" (a double-quoted dollar-at) expands into nothing,
10533 not even a NULL word, when there are no positional
10534 parameters. Posix interp 888 says that other parts of the
10535 word that expand to quoted nulls result in quoted nulls, so
10536 we can't just throw the entire word away if we have "$@"
10537 anywhere in it. We use had_quoted_null to keep track */
10538 if (list == 0 && temp_has_dollar_at) /* XXX - was has_dollar_at */
10540 quoted_dollar_at++;
10541 break;
10544 /* If this list comes back with a quoted null from expansion,
10545 we have either "$x" or "$@" with $1 == ''. In either case,
10546 we need to make sure we add a quoted null argument and
10547 disable the special handling that "$@" gets. */
10548 if (list && list->word && list->next == 0 && (list->word->flags & W_HASQUOTEDNULL))
10550 if (had_quoted_null && temp_has_dollar_at)
10551 quoted_dollar_at++;
10552 had_quoted_null = 1; /* XXX */
10555 /* If we get "$@", we know we have expanded something, so we
10556 need to remember it for the final split on $IFS. This is
10557 a special case; it's the only case where a quoted string
10558 can expand into more than one word. It's going to come back
10559 from the above call to expand_word_internal as a list with
10560 multiple words. */
10561 if (list)
10562 dequote_list (list);
10564 if (temp_has_dollar_at) /* XXX - was has_dollar_at */
10566 quoted_dollar_at++;
10567 if (contains_dollar_at)
10568 *contains_dollar_at = 1;
10569 if (expanded_something)
10570 *expanded_something = 1;
10571 local_expanded = 1;
10574 else
10576 /* What we have is "". This is a minor optimization. */
10577 FREE (temp);
10578 list = (WORD_LIST *)NULL;
10579 had_quoted_null = 1; /* note for later */
10582 /* The code above *might* return a list (consider the case of "$@",
10583 where it returns "$1", "$2", etc.). We can't throw away the
10584 rest of the list, and we have to make sure each word gets added
10585 as quoted. We test on tresult->next: if it is non-NULL, we
10586 quote the whole list, save it to a string with string_list, and
10587 add that string. We don't need to quote the results of this
10588 (and it would be wrong, since that would quote the separators
10589 as well), so we go directly to add_string. */
10590 if (list)
10592 if (list->next)
10594 /* Testing quoted_dollar_at makes sure that "$@" is
10595 split correctly when $IFS does not contain a space. */
10596 temp = quoted_dollar_at
10597 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES, 0)
10598 : string_list (quote_list (list));
10599 dispose_words (list);
10600 goto add_string;
10602 else
10604 temp = savestring (list->word->word);
10605 tflag = list->word->flags;
10606 dispose_words (list);
10608 /* If the string is not a quoted null string, we want
10609 to remove any embedded unquoted CTLNUL characters.
10610 We do not want to turn quoted null strings back into
10611 the empty string, though. We do this because we
10612 want to remove any quoted nulls from expansions that
10613 contain other characters. For example, if we have
10614 x"$*"y or "x$*y" and there are no positional parameters,
10615 the $* should expand into nothing. */
10616 /* We use the W_HASQUOTEDNULL flag to differentiate the
10617 cases: a quoted null character as above and when
10618 CTLNUL is contained in the (non-null) expansion
10619 of some variable. We use the had_quoted_null flag to
10620 pass the value through this function to its caller. */
10621 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
10622 remove_quoted_nulls (temp); /* XXX */
10625 else
10626 temp = (char *)NULL;
10628 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
10629 had_quoted_null = 1; /* note for later */
10631 /* We do not want to add quoted nulls to strings that are only
10632 partially quoted; we can throw them away. The exception to
10633 this is when we are going to be performing word splitting,
10634 since we have to preserve a null argument if the next character
10635 will cause word splitting. */
10636 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && quoted == 0 && (word->flags & (W_NOSPLIT|W_EXPANDRHS|W_ASSIGNRHS)) == W_EXPANDRHS)
10638 c = CTLNUL;
10639 sindex--;
10640 had_quoted_null = 1;
10641 goto add_character;
10643 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
10644 continue;
10646 add_quoted_string:
10648 if (temp)
10650 temp1 = temp;
10651 temp = quote_string (temp);
10652 free (temp1);
10653 goto add_string;
10655 else
10657 /* Add NULL arg. */
10658 c = CTLNUL;
10659 sindex--; /* add_character: label increments sindex */
10660 had_quoted_null = 1; /* note for later */
10661 goto add_character;
10664 /* break; */
10666 case '\'':
10667 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
10668 goto add_character;
10670 t_index = ++sindex;
10671 temp = string_extract_single_quoted (string, &sindex);
10673 /* If the entire STRING was surrounded by single quotes,
10674 then the string is wholly quoted. */
10675 quoted_state = (t_index == 1 && string[sindex] == '\0')
10676 ? WHOLLY_QUOTED
10677 : PARTIALLY_QUOTED;
10679 /* If all we had was '', it is a null expansion. */
10680 if (*temp == '\0')
10682 free (temp);
10683 temp = (char *)NULL;
10685 else
10686 remove_quoted_escapes (temp); /* ??? */
10688 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
10689 had_quoted_null = 1; /* note for later */
10691 /* We do not want to add quoted nulls to strings that are only
10692 partially quoted; such nulls are discarded. See above for the
10693 exception, which is when the string is going to be split.
10694 Posix interp 888/1129 */
10695 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && quoted == 0 && (word->flags & (W_NOSPLIT|W_EXPANDRHS|W_ASSIGNRHS)) == W_EXPANDRHS)
10697 c = CTLNUL;
10698 sindex--;
10699 goto add_character;
10702 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED) && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
10703 continue;
10705 /* If we have a quoted null expansion, add a quoted NULL to istring. */
10706 if (temp == 0)
10708 c = CTLNUL;
10709 sindex--; /* add_character: label increments sindex */
10710 goto add_character;
10712 else
10713 goto add_quoted_string;
10715 /* break; */
10717 case ' ':
10718 /* If we are in a context where the word is not going to be split, but
10719 we need to account for $@ and $* producing one word for each
10720 positional parameter, add quoted spaces so the spaces in the
10721 expansion of "$@", if any, behave correctly. We still may need to
10722 split if we are expanding the rhs of a word expansion. */
10723 if (ifs_is_null || split_on_spaces || ((word->flags & (W_NOSPLIT|W_NOSPLIT2|W_ASSIGNRHS)) && (word->flags & W_EXPANDRHS) == 0))
10725 if (string[sindex])
10726 sindex++;
10727 twochars[0] = CTLESC;
10728 twochars[1] = c;
10729 goto add_twochars;
10731 /* FALLTHROUGH */
10733 default:
10734 /* This is the fix for " $@ " */
10735 add_ifs_character:
10736 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c) && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0))
10738 if ((quoted&(Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0)
10739 has_quoted_ifs++;
10740 add_quoted_character:
10741 if (string[sindex]) /* from old goto dollar_add_string */
10742 sindex++;
10743 if (c == 0)
10745 c = CTLNUL;
10746 goto add_character;
10748 else
10750 #if HANDLE_MULTIBYTE
10751 /* XXX - should make sure that c is actually multibyte,
10752 otherwise we can use the twochars branch */
10753 if (mb_cur_max > 1)
10754 sindex--;
10756 if (mb_cur_max > 1)
10758 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
10760 else
10761 #endif
10763 twochars[0] = CTLESC;
10764 twochars[1] = c;
10765 goto add_twochars;
10770 SADD_MBCHAR (temp, string, sindex, string_size);
10772 add_character:
10773 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
10774 DEFAULT_ARRAY_SIZE);
10775 istring[istring_index++] = c;
10776 istring[istring_index] = '\0';
10778 /* Next character. */
10779 sindex++;
10783 finished_with_string:
10784 /* OK, we're ready to return. If we have a quoted string, and
10785 quoted_dollar_at is not set, we do no splitting at all; otherwise
10786 we split on ' '. The routines that call this will handle what to
10787 do if nothing has been expanded. */
10789 /* Partially and wholly quoted strings which expand to the empty
10790 string are retained as an empty arguments. Unquoted strings
10791 which expand to the empty string are discarded. The single
10792 exception is the case of expanding "$@" when there are no
10793 positional parameters. In that case, we discard the expansion. */
10795 /* Because of how the code that handles "" and '' in partially
10796 quoted strings works, we need to make ISTRING into a QUOTED_NULL
10797 if we saw quoting characters, but the expansion was empty.
10798 "" and '' are tossed away before we get to this point when
10799 processing partially quoted strings. This makes "" and $xxx""
10800 equivalent when xxx is unset. We also look to see whether we
10801 saw a quoted null from a ${} expansion and add one back if we
10802 need to. */
10804 /* If we expand to nothing and there were no single or double quotes
10805 in the word, we throw it away. Otherwise, we return a NULL word.
10806 The single exception is for $@ surrounded by double quotes when
10807 there are no positional parameters. In that case, we also throw
10808 the word away. */
10810 if (*istring == '\0')
10812 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
10814 istring[0] = CTLNUL;
10815 istring[1] = '\0';
10816 tword = alloc_word_desc ();
10817 tword->word = istring;
10818 istring = 0; /* avoid later free() */
10819 tword->flags |= W_HASQUOTEDNULL; /* XXX */
10820 list = make_word_list (tword, (WORD_LIST *)NULL);
10821 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
10822 tword->flags |= W_QUOTED;
10824 /* According to sh, ksh, and Posix.2, if a word expands into nothing
10825 and a double-quoted "$@" appears anywhere in it, then the entire
10826 word is removed. */
10827 /* XXX - exception appears to be that quoted null strings result in
10828 null arguments */
10829 else if (quoted_state == UNQUOTED || quoted_dollar_at)
10830 list = (WORD_LIST *)NULL;
10831 else
10832 list = (WORD_LIST *)NULL;
10834 else if (word->flags & W_NOSPLIT)
10836 tword = alloc_word_desc ();
10837 tword->word = istring;
10838 if (had_quoted_null && QUOTED_NULL (istring))
10839 tword->flags |= W_HASQUOTEDNULL;
10840 istring = 0; /* avoid later free() */
10841 if (word->flags & W_ASSIGNMENT)
10842 tword->flags |= W_ASSIGNMENT; /* XXX */
10843 if (word->flags & W_COMPASSIGN)
10844 tword->flags |= W_COMPASSIGN; /* XXX */
10845 if (word->flags & W_NOGLOB)
10846 tword->flags |= W_NOGLOB; /* XXX */
10847 if (word->flags & W_NOBRACE)
10848 tword->flags |= W_NOBRACE; /* XXX */
10849 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
10850 tword->flags |= W_QUOTED;
10851 list = make_word_list (tword, (WORD_LIST *)NULL);
10853 else if (word->flags & W_ASSIGNRHS)
10855 list = list_string (istring, "", quoted);
10856 tword = list->word;
10857 if (had_quoted_null && QUOTED_NULL (istring))
10858 tword->flags |= W_HASQUOTEDNULL;
10859 free (list);
10860 free (istring);
10861 istring = 0; /* avoid later free() */
10862 goto set_word_flags;
10864 else
10866 char *ifs_chars;
10868 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
10870 /* If we have $@, we need to split the results no matter what. If
10871 IFS is unset or NULL, string_list_dollar_at has separated the
10872 positional parameters with a space, so we split on space (we have
10873 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
10874 string_list_dollar_at has separated the positional parameters
10875 with the first character of $IFS, so we split on $IFS. If
10876 SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
10877 unset or null, and we want to make sure that we split on spaces
10878 regardless of what else has happened to IFS since the expansion,
10879 or we expanded "$@" with IFS null and we need to split the positional
10880 parameters into separate words. */
10881 if (split_on_spaces)
10883 /* If IFS is not set, and the word is not quoted, we want to split
10884 the individual words on $' \t\n'. We rely on previous steps to
10885 quote the portions of the word that should not be split */
10886 if (ifs_is_set == 0)
10887 list = list_string (istring, " \t\n", 1); /* XXX quoted == 1? */
10888 else
10889 list = list_string (istring, " ", 1); /* XXX quoted == 1? */
10892 /* If we have $@ (has_dollar_at != 0) and we are in a context where we
10893 don't want to split the result (W_NOSPLIT2), and we are not quoted,
10894 we have already separated the arguments with the first character of
10895 $IFS. In this case, we want to return a list with a single word
10896 with the separator possibly replaced with a space (it's what other
10897 shells seem to do).
10898 quoted_dollar_at is internal to this function and is set if we are
10899 passed an argument that is unquoted (quoted == 0) but we encounter a
10900 double-quoted $@ while expanding it. */
10901 else if (has_dollar_at && quoted_dollar_at == 0 && ifs_chars && quoted == 0 && (word->flags & W_NOSPLIT2))
10903 tword = alloc_word_desc ();
10904 /* Only split and rejoin if we have to */
10905 if (*ifs_chars && *ifs_chars != ' ')
10907 /* list_string dequotes CTLESCs in the string it's passed, so we
10908 need it to get the space separation right if space isn't the
10909 first character in IFS (but is present) and to remove the
10910 quoting we added back in param_expand(). */
10911 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
10912 /* This isn't exactly right in the case where we're expanding
10913 the RHS of an expansion like ${var-$@} where IFS=: (for
10914 example). The W_NOSPLIT2 means we do the separation with :;
10915 the list_string removes the quotes and breaks the string into
10916 a list, and the string_list rejoins it on spaces. When we
10917 return, we expect to be able to split the results, but the
10918 space separation means the right split doesn't happen. */
10919 tword->word = string_list (list);
10921 else
10922 tword->word = istring;
10923 if (had_quoted_null && QUOTED_NULL (istring))
10924 tword->flags |= W_HASQUOTEDNULL; /* XXX */
10925 if (tword->word != istring)
10926 free (istring);
10927 istring = 0; /* avoid later free() */
10928 goto set_word_flags;
10930 else if (has_dollar_at && ifs_chars)
10931 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
10932 else
10934 tword = alloc_word_desc ();
10935 if (expanded_something && *expanded_something == 0 && has_quoted_ifs)
10936 tword->word = remove_quoted_ifs (istring);
10937 else
10938 tword->word = istring;
10939 if (had_quoted_null && QUOTED_NULL (istring)) /* should check for more than one */
10940 tword->flags |= W_HASQUOTEDNULL; /* XXX */
10941 else if (had_quoted_null)
10942 tword->flags |= W_SAWQUOTEDNULL; /* XXX */
10943 if (tword->word != istring)
10944 free (istring);
10945 istring = 0; /* avoid later free() */
10946 set_word_flags:
10947 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
10948 tword->flags |= W_QUOTED;
10949 if (word->flags & W_ASSIGNMENT)
10950 tword->flags |= W_ASSIGNMENT;
10951 if (word->flags & W_COMPASSIGN)
10952 tword->flags |= W_COMPASSIGN;
10953 if (word->flags & W_NOGLOB)
10954 tword->flags |= W_NOGLOB;
10955 if (word->flags & W_NOBRACE)
10956 tword->flags |= W_NOBRACE;
10957 list = make_word_list (tword, (WORD_LIST *)NULL);
10961 free (istring);
10962 return (list);
10965 /* **************************************************************** */
10966 /* */
10967 /* Functions for Quote Removal */
10968 /* */
10969 /* **************************************************************** */
10971 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
10972 backslash quoting rules for within double quotes or a here document. */
10973 char *
10974 string_quote_removal (string, quoted)
10975 char *string;
10976 int quoted;
10978 size_t slen;
10979 char *r, *result_string, *temp, *send;
10980 int sindex, tindex, dquote;
10981 unsigned char c;
10982 DECLARE_MBSTATE;
10984 /* The result can be no longer than the original string. */
10985 slen = strlen (string);
10986 send = string + slen;
10988 r = result_string = (char *)xmalloc (slen + 1);
10990 for (dquote = sindex = 0; c = string[sindex];)
10992 switch (c)
10994 case '\\':
10995 c = string[++sindex];
10996 if (c == 0)
10998 *r++ = '\\';
10999 break;
11001 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
11002 *r++ = '\\';
11003 /* FALLTHROUGH */
11005 default:
11006 SCOPY_CHAR_M (r, string, send, sindex);
11007 break;
11009 case '\'':
11010 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
11012 *r++ = c;
11013 sindex++;
11014 break;
11016 tindex = sindex + 1;
11017 temp = string_extract_single_quoted (string, &tindex);
11018 if (temp)
11020 strcpy (r, temp);
11021 r += strlen (r);
11022 free (temp);
11024 sindex = tindex;
11025 break;
11027 case '"':
11028 dquote = 1 - dquote;
11029 sindex++;
11030 break;
11033 *r = '\0';
11034 return (result_string);
11037 #if 0
11038 /* UNUSED */
11039 /* Perform quote removal on word WORD. This allocates and returns a new
11040 WORD_DESC *. */
11041 WORD_DESC *
11042 word_quote_removal (word, quoted)
11043 WORD_DESC *word;
11044 int quoted;
11046 WORD_DESC *w;
11047 char *t;
11049 t = string_quote_removal (word->word, quoted);
11050 w = alloc_word_desc ();
11051 w->word = t ? t : savestring ("");
11052 return (w);
11055 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
11056 the members of the list are treated as if they are surrounded by
11057 double quotes. Return a new list, or NULL if LIST is NULL. */
11058 WORD_LIST *
11059 word_list_quote_removal (list, quoted)
11060 WORD_LIST *list;
11061 int quoted;
11063 WORD_LIST *result, *t, *tresult, *e;
11065 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
11067 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
11068 #if 0
11069 result = (WORD_LIST *) list_append (result, tresult);
11070 #else
11071 if (result == 0)
11072 result = e = tresult;
11073 else
11075 e->next = tresult;
11076 while (e->next)
11077 e = e->next;
11079 #endif
11081 return (result);
11083 #endif
11085 /*******************************************
11087 * Functions to perform word splitting *
11089 *******************************************/
11091 void
11092 setifs (v)
11093 SHELL_VAR *v;
11095 char *t;
11096 unsigned char uc;
11098 ifs_var = v;
11099 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
11101 ifs_is_set = ifs_var != 0;
11102 ifs_is_null = ifs_is_set && (*ifs_value == 0);
11104 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
11105 handle multibyte chars in IFS */
11106 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
11107 for (t = ifs_value ; t && *t; t++)
11109 uc = *t;
11110 ifs_cmap[uc] = 1;
11113 #if defined (HANDLE_MULTIBYTE)
11114 if (ifs_value == 0)
11116 ifs_firstc[0] = '\0'; /* XXX - ? */
11117 ifs_firstc_len = 1;
11119 else
11121 if (locale_utf8locale && UTF8_SINGLEBYTE (*ifs_value))
11122 ifs_firstc_len = (*ifs_value != 0) ? 1 : 0;
11123 else
11125 size_t ifs_len;
11126 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
11127 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
11129 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
11131 ifs_firstc[0] = ifs_value[0];
11132 ifs_firstc[1] = '\0';
11133 ifs_firstc_len = 1;
11135 else
11136 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
11138 #else
11139 ifs_firstc = ifs_value ? *ifs_value : 0;
11140 #endif
11143 char *
11144 getifs ()
11146 return ifs_value;
11149 /* This splits a single word into a WORD LIST on $IFS, but only if the word
11150 is not quoted. list_string () performs quote removal for us, even if we
11151 don't do any splitting. */
11152 WORD_LIST *
11153 word_split (w, ifs_chars)
11154 WORD_DESC *w;
11155 char *ifs_chars;
11157 WORD_LIST *result;
11159 if (w)
11161 char *xifs;
11163 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
11164 result = list_string (w->word, xifs, w->flags & W_QUOTED);
11166 else
11167 result = (WORD_LIST *)NULL;
11169 return (result);
11172 /* Perform word splitting on LIST and return the RESULT. It is possible
11173 to return (WORD_LIST *)NULL. */
11174 static WORD_LIST *
11175 word_list_split (list)
11176 WORD_LIST *list;
11178 WORD_LIST *result, *t, *tresult, *e;
11179 WORD_DESC *w;
11181 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
11183 tresult = word_split (t->word, ifs_value);
11184 /* POSIX 2.6: "If the complete expansion appropriate for a word results
11185 in an empty field, that empty field shall be deleted from the list
11186 of fields that form the completely expanded command, unless the
11187 original word contained single-quote or double-quote characters."
11188 This is where we handle these words that contain quoted null strings
11189 and other characters that expand to nothing after word splitting. */
11190 if (tresult == 0 && t->word && (t->word->flags & W_SAWQUOTEDNULL)) /* XXX */
11192 w = alloc_word_desc ();
11193 w->word = (char *)xmalloc (1);
11194 w->word[0] = '\0';
11195 tresult = make_word_list (w, (WORD_LIST *)NULL);
11197 if (result == 0)
11198 result = e = tresult;
11199 else
11201 e->next = tresult;
11202 while (e->next)
11203 e = e->next;
11206 return (result);
11209 /**************************************************
11211 * Functions to expand an entire WORD_LIST *
11213 **************************************************/
11215 /* Do any word-expansion-specific cleanup and jump to top_level */
11216 static void
11217 exp_jump_to_top_level (v)
11218 int v;
11220 set_pipestatus_from_exit (last_command_exit_value);
11222 /* Cleanup code goes here. */
11223 expand_no_split_dollar_star = 0; /* XXX */
11224 if (expanding_redir)
11225 undo_partial_redirects ();
11226 expanding_redir = 0;
11227 assigning_in_environment = 0;
11229 if (parse_and_execute_level == 0)
11230 top_level_cleanup (); /* from sig.c */
11232 jump_to_top_level (v);
11235 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
11236 ELIST, and set ELIST to the new list. */
11237 #define PREPEND_LIST(nlist, elist) \
11238 do { nlist->next = elist; elist = nlist; } while (0)
11240 /* Separate out any initial variable assignments from TLIST. If set -k has
11241 been executed, remove all assignment statements from TLIST. Initial
11242 variable assignments and other environment assignments are placed
11243 on SUBST_ASSIGN_VARLIST. */
11244 static WORD_LIST *
11245 separate_out_assignments (tlist)
11246 WORD_LIST *tlist;
11248 register WORD_LIST *vp, *lp;
11250 if (tlist == 0)
11251 return ((WORD_LIST *)NULL);
11253 if (subst_assign_varlist)
11254 dispose_words (subst_assign_varlist); /* Clean up after previous error */
11256 subst_assign_varlist = (WORD_LIST *)NULL;
11257 vp = lp = tlist;
11259 /* Separate out variable assignments at the start of the command.
11260 Loop invariant: vp->next == lp
11261 Loop postcondition:
11262 lp = list of words left after assignment statements skipped
11263 tlist = original list of words
11265 while (lp && (lp->word->flags & W_ASSIGNMENT))
11267 vp = lp;
11268 lp = lp->next;
11271 /* If lp != tlist, we have some initial assignment statements.
11272 We make SUBST_ASSIGN_VARLIST point to the list of assignment
11273 words and TLIST point to the remaining words. */
11274 if (lp != tlist)
11276 subst_assign_varlist = tlist;
11277 /* ASSERT(vp->next == lp); */
11278 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
11279 tlist = lp; /* remainder of word list */
11282 /* vp == end of variable list */
11283 /* tlist == remainder of original word list without variable assignments */
11284 if (!tlist)
11285 /* All the words in tlist were assignment statements */
11286 return ((WORD_LIST *)NULL);
11288 /* ASSERT(tlist != NULL); */
11289 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
11291 /* If the -k option is in effect, we need to go through the remaining
11292 words, separate out the assignment words, and place them on
11293 SUBST_ASSIGN_VARLIST. */
11294 if (place_keywords_in_env)
11296 WORD_LIST *tp; /* tp == running pointer into tlist */
11298 tp = tlist;
11299 lp = tlist->next;
11301 /* Loop Invariant: tp->next == lp */
11302 /* Loop postcondition: tlist == word list without assignment statements */
11303 while (lp)
11305 if (lp->word->flags & W_ASSIGNMENT)
11307 /* Found an assignment statement, add this word to end of
11308 subst_assign_varlist (vp). */
11309 if (!subst_assign_varlist)
11310 subst_assign_varlist = vp = lp;
11311 else
11313 vp->next = lp;
11314 vp = lp;
11317 /* Remove the word pointed to by LP from TLIST. */
11318 tp->next = lp->next;
11319 /* ASSERT(vp == lp); */
11320 lp->next = (WORD_LIST *)NULL;
11321 lp = tp->next;
11323 else
11325 tp = lp;
11326 lp = lp->next;
11330 return (tlist);
11333 #define WEXP_VARASSIGN 0x001
11334 #define WEXP_BRACEEXP 0x002
11335 #define WEXP_TILDEEXP 0x004
11336 #define WEXP_PARAMEXP 0x008
11337 #define WEXP_PATHEXP 0x010
11339 /* All of the expansions, including variable assignments at the start of
11340 the list. */
11341 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
11343 /* All of the expansions except variable assignments at the start of
11344 the list. */
11345 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
11347 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
11348 expansion, command substitution, arithmetic expansion, word splitting, and
11349 quote removal. */
11350 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
11352 /* Take the list of words in LIST and do the various substitutions. Return
11353 a new list of words which is the expanded list, and without things like
11354 variable assignments. */
11356 WORD_LIST *
11357 expand_words (list)
11358 WORD_LIST *list;
11360 return (expand_word_list_internal (list, WEXP_ALL));
11363 /* Same as expand_words (), but doesn't hack variable or environment
11364 variables. */
11365 WORD_LIST *
11366 expand_words_no_vars (list)
11367 WORD_LIST *list;
11369 return (expand_word_list_internal (list, WEXP_NOVARS));
11372 WORD_LIST *
11373 expand_words_shellexp (list)
11374 WORD_LIST *list;
11376 return (expand_word_list_internal (list, WEXP_SHELLEXP));
11379 static WORD_LIST *
11380 glob_expand_word_list (tlist, eflags)
11381 WORD_LIST *tlist;
11382 int eflags;
11384 char **glob_array, *temp_string;
11385 register int glob_index;
11386 WORD_LIST *glob_list, *output_list, *disposables, *next;
11387 WORD_DESC *tword;
11388 int x;
11390 output_list = disposables = (WORD_LIST *)NULL;
11391 glob_array = (char **)NULL;
11392 while (tlist)
11394 /* For each word, either globbing is attempted or the word is
11395 added to orig_list. If globbing succeeds, the results are
11396 added to orig_list and the word (tlist) is added to the list
11397 of disposable words. If globbing fails and failed glob
11398 expansions are left unchanged (the shell default), the
11399 original word is added to orig_list. If globbing fails and
11400 failed glob expansions are removed, the original word is
11401 added to the list of disposable words. orig_list ends up
11402 in reverse order and requires a call to REVERSE_LIST to
11403 be set right. After all words are examined, the disposable
11404 words are freed. */
11405 next = tlist->next;
11407 /* If the word isn't an assignment and contains an unquoted
11408 pattern matching character, then glob it. */
11409 if ((tlist->word->flags & W_NOGLOB) == 0 &&
11410 unquoted_glob_pattern_p (tlist->word->word))
11412 glob_array = shell_glob_filename (tlist->word->word, QGLOB_CTLESC); /* XXX */
11414 /* Handle error cases.
11415 I don't think we should report errors like "No such file
11416 or directory". However, I would like to report errors
11417 like "Read failed". */
11419 if (glob_array == 0 || GLOB_FAILED (glob_array))
11421 glob_array = (char **)xmalloc (sizeof (char *));
11422 glob_array[0] = (char *)NULL;
11425 /* Dequote the current word in case we have to use it. */
11426 if (glob_array[0] == NULL)
11428 temp_string = dequote_string (tlist->word->word);
11429 free (tlist->word->word);
11430 tlist->word->word = temp_string;
11433 /* Make the array into a word list. */
11434 glob_list = (WORD_LIST *)NULL;
11435 for (glob_index = 0; glob_array[glob_index]; glob_index++)
11437 tword = make_bare_word (glob_array[glob_index]);
11438 glob_list = make_word_list (tword, glob_list);
11441 if (glob_list)
11443 output_list = (WORD_LIST *)list_append (glob_list, output_list);
11444 PREPEND_LIST (tlist, disposables);
11446 else if (fail_glob_expansion != 0)
11448 last_command_exit_value = EXECUTION_FAILURE;
11449 report_error (_("no match: %s"), tlist->word->word);
11450 exp_jump_to_top_level (DISCARD);
11452 else if (allow_null_glob_expansion == 0)
11454 /* Failed glob expressions are left unchanged. */
11455 PREPEND_LIST (tlist, output_list);
11457 else
11459 /* Failed glob expressions are removed. */
11460 PREPEND_LIST (tlist, disposables);
11463 else
11465 /* Dequote the string. */
11466 temp_string = dequote_string (tlist->word->word);
11467 free (tlist->word->word);
11468 tlist->word->word = temp_string;
11469 PREPEND_LIST (tlist, output_list);
11472 strvec_dispose (glob_array);
11473 glob_array = (char **)NULL;
11475 tlist = next;
11478 if (disposables)
11479 dispose_words (disposables);
11481 if (output_list)
11482 output_list = REVERSE_LIST (output_list, WORD_LIST *);
11484 return (output_list);
11487 #if defined (BRACE_EXPANSION)
11488 static WORD_LIST *
11489 brace_expand_word_list (tlist, eflags)
11490 WORD_LIST *tlist;
11491 int eflags;
11493 register char **expansions;
11494 char *temp_string;
11495 WORD_LIST *disposables, *output_list, *next;
11496 WORD_DESC *w;
11497 int eindex;
11499 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
11501 next = tlist->next;
11503 if (tlist->word->flags & W_NOBRACE)
11505 /*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
11506 PREPEND_LIST (tlist, output_list);
11507 continue;
11510 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
11512 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
11513 PREPEND_LIST (tlist, output_list);
11514 continue;
11517 /* Only do brace expansion if the word has a brace character. If
11518 not, just add the word list element to BRACES and continue. In
11519 the common case, at least when running shell scripts, this will
11520 degenerate to a bunch of calls to `mbschr', and then what is
11521 basically a reversal of TLIST into BRACES, which is corrected
11522 by a call to REVERSE_LIST () on BRACES when the end of TLIST
11523 is reached. */
11524 if (mbschr (tlist->word->word, LBRACE))
11526 expansions = brace_expand (tlist->word->word);
11528 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
11530 w = alloc_word_desc ();
11531 w->word = temp_string;
11533 /* If brace expansion didn't change the word, preserve
11534 the flags. We may want to preserve the flags
11535 unconditionally someday -- XXX */
11536 if (STREQ (temp_string, tlist->word->word))
11537 w->flags = tlist->word->flags;
11538 else
11539 w = make_word_flags (w, temp_string);
11541 output_list = make_word_list (w, output_list);
11543 free (expansions);
11545 /* Add TLIST to the list of words to be freed after brace
11546 expansion has been performed. */
11547 PREPEND_LIST (tlist, disposables);
11549 else
11550 PREPEND_LIST (tlist, output_list);
11553 if (disposables)
11554 dispose_words (disposables);
11556 if (output_list)
11557 output_list = REVERSE_LIST (output_list, WORD_LIST *);
11559 return (output_list);
11561 #endif
11563 #if defined (ARRAY_VARS)
11564 /* Take WORD, a compound array assignment, and internally run (for example),
11565 'declare -A w', where W is the variable name portion of WORD. OPTION is
11566 the list of options to supply to `declare'. CMD is the declaration command
11567 we are expanding right now; it's unused currently. */
11568 static int
11569 make_internal_declare (word, option, cmd)
11570 char *word;
11571 char *option;
11572 char *cmd;
11574 int t, r;
11575 WORD_LIST *wl;
11576 WORD_DESC *w;
11578 w = make_word (word);
11580 t = assignment (w->word, 0);
11581 if (w->word[t] == '=')
11583 w->word[t] = '\0';
11584 if (w->word[t - 1] == '+') /* cut off any append op */
11585 w->word[t - 1] = '\0';
11588 wl = make_word_list (w, (WORD_LIST *)NULL);
11589 wl = make_word_list (make_word (option), wl);
11591 r = declare_builtin (wl);
11593 dispose_words (wl);
11594 return r;
11597 /* Expand VALUE in NAME[+]=( VALUE ) to a list of words. FLAGS is 1 if NAME
11598 is an associative array.
11600 If we are processing an indexed array, expand_compound_array_assignment
11601 will expand all the individual words and quote_compound_array_list will
11602 single-quote them. If we are processing an associative array, we use
11603 parse_string_to_word_list to split VALUE into a list of words instead of
11604 faking up a shell variable and calling expand_compound_array_assignment.
11605 expand_and_quote_assoc_word expands and single-quotes each word in VALUE
11606 together so we don't have problems finding the end of the subscript when
11607 quoting it.
11609 Words in VALUE can be individual words, which are expanded and single-quoted,
11610 or words of the form [IND]=VALUE, which end up as explained below, as
11611 ['expanded-ind']='expanded-value'. */
11613 static WORD_LIST *
11614 expand_oneword (value, flags)
11615 char *value;
11616 int flags;
11618 WORD_LIST *l, *nl;
11619 char *t;
11621 if (flags == 0)
11623 /* Indexed array */
11624 l = expand_compound_array_assignment ((SHELL_VAR *)NULL, value, flags);
11625 /* Now we quote the results of the expansion above to prevent double
11626 expansion. */
11627 quote_compound_array_list (l, flags);
11628 return l;
11630 else
11632 /* Associative array */
11633 l = parse_string_to_word_list (value, 1, "array assign");
11634 /* For associative arrays, with their arbitrary subscripts, we have to
11635 expand and quote in one step so we don't have to search for the
11636 closing right bracket more than once. */
11637 for (nl = l; nl; nl = nl->next)
11639 if ((nl->word->flags & W_ASSIGNMENT) == 0)
11640 t = sh_single_quote (nl->word->word ? nl->word->word : "");
11641 else
11642 t = expand_and_quote_assoc_word (nl->word->word, flags);
11643 free (nl->word->word);
11644 nl->word->word = t;
11646 return l;
11650 /* Expand a single compound assignment argument to a declaration builtin.
11651 This word takes the form NAME[+]=( VALUE ). The NAME[+]= is passed through
11652 unchanged. The VALUE is expanded and each word in the result is single-
11653 quoted. Words of the form [key]=value end up as
11654 ['expanded-key']='expanded-value'. Associative arrays have special
11655 handling, see expand_oneword() above. The return value is
11656 NAME[+]=( expanded-and-quoted-VALUE ). */
11657 static void
11658 expand_compound_assignment_word (tlist, flags)
11659 WORD_LIST *tlist;
11660 int flags;
11662 WORD_LIST *l;
11663 int wlen, oind, t;
11664 char *value, *temp;
11666 /*itrace("expand_compound_assignment_word: original word = -%s-", tlist->word->word);*/
11667 t = assignment (tlist->word->word, 0);
11669 /* value doesn't have the open and close parens */
11670 oind = 1;
11671 value = extract_array_assignment_list (tlist->word->word + t + 1, &oind);
11672 /* This performs one round of expansion on the index/key and value and
11673 single-quotes each word in the result. */
11674 l = expand_oneword (value, flags);
11675 free (value);
11677 value = string_list (l);
11678 wlen = STRLEN (value);
11680 /* Now, let's rebuild the string */
11681 temp = xmalloc (t + 3 + wlen + 1); /* name[+]=(value) */
11682 memcpy (temp, tlist->word->word, ++t);
11683 temp[t++] = '(';
11684 if (value)
11685 memcpy (temp + t, value, wlen);
11686 t += wlen;
11687 temp[t++] = ')';
11688 temp[t] = '\0';
11689 /*itrace("expand_compound_assignment_word: reconstructed word = -%s-", temp);*/
11691 free (tlist->word->word);
11692 tlist->word->word = temp;
11694 free (value);
11697 /* Expand and process an argument to a declaration command. We have already
11698 set flags in TLIST->word->flags depending on the declaration command
11699 (declare, local, etc.) and the options supplied to it (-a, -A, etc.).
11700 TLIST->word->word is of the form NAME[+]=( VALUE ).
11702 This does several things, all using pieces of other functions to get the
11703 evaluation sequence right. It's called for compound array assignments with
11704 the W_ASSIGNMENT flag set (basically, valid identifier names on the lhs).
11705 It parses out which flags need to be set for declare to create the variable
11706 correctly, then calls declare internally (make_internal_declare) to make
11707 sure the variable exists with the correct attributes. Before the variable
11708 is created, it calls expand_compound_assignment_word to expand VALUE to a
11709 list of words, appropriately quoted for further evaluation. This preserves
11710 the semantics of word-expansion-before-calling-builtins. Finally, it calls
11711 do_word_assignment to perform the expansion and assignment with the same
11712 expansion semantics as a standalone assignment statement (no word splitting,
11713 etc.) even though the word is single-quoted so all that needs to happen is
11714 quote removal. */
11715 static WORD_LIST *
11716 expand_declaration_argument (tlist, wcmd)
11717 WORD_LIST *tlist, *wcmd;
11719 char opts[16], omap[128];
11720 int t, opti, oind, skip, inheriting;
11721 WORD_LIST *l;
11723 inheriting = localvar_inherit;
11724 opti = 0;
11725 if (tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL|W_CHKLOCAL|W_ASSIGNARRAY))
11726 opts[opti++] = '-';
11728 if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL)) == (W_ASSIGNASSOC|W_ASSNGLOBAL))
11730 opts[opti++] = 'g';
11731 opts[opti++] = 'A';
11733 else if (tlist->word->flags & W_ASSIGNASSOC)
11735 opts[opti++] = 'A';
11737 else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL))
11739 opts[opti++] = 'g';
11740 opts[opti++] = 'a';
11742 else if (tlist->word->flags & W_ASSIGNARRAY)
11744 opts[opti++] = 'a';
11746 else if (tlist->word->flags & W_ASSNGLOBAL)
11747 opts[opti++] = 'g';
11749 if (tlist->word->flags & W_CHKLOCAL)
11750 opts[opti++] = 'G';
11752 /* If we have special handling note the integer attribute and others
11753 that transform the value upon assignment. What we do is take all
11754 of the option arguments and scan through them looking for options
11755 that cause such transformations, and add them to the `opts' array. */
11757 memset (omap, '\0', sizeof (omap));
11758 for (l = wcmd->next; l != tlist; l = l->next)
11760 if (l->word->word[0] != '-')
11761 break; /* non-option argument */
11762 if (l->word->word[0] == '-' && l->word->word[1] == '-' && l->word->word[2] == 0)
11763 break; /* -- signals end of options */
11764 for (oind = 1; l->word->word[oind]; oind++)
11765 switch (l->word->word[oind])
11767 case 'I':
11768 inheriting = 1;
11769 case 'i':
11770 case 'l':
11771 case 'u':
11772 case 'c':
11773 omap[l->word->word[oind]] = 1;
11774 if (opti == 0)
11775 opts[opti++] = '-';
11776 break;
11777 default:
11778 break;
11782 for (oind = 0; oind < sizeof (omap); oind++)
11783 if (omap[oind])
11784 opts[opti++] = oind;
11786 /* If there are no -a/-A options, but we have a compound assignment,
11787 we have a choice: we can set opts[0]='-', opts[1]='a', since the
11788 default is to create an indexed array, and call
11789 make_internal_declare with that, or we can just skip the -a and let
11790 declare_builtin deal with it. Once we're here, we're better set
11791 up for the latter, since we don't want to deal with looking up
11792 any existing variable here -- better to let declare_builtin do it.
11793 We need the variable created, though, especially if it's local, so
11794 we get the scoping right before we call do_word_assignment.
11795 To ensure that make_local_declare gets called, we add `--' if there
11796 aren't any options. */
11797 if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSIGNARRAY)) == 0)
11799 if (opti == 0)
11801 opts[opti++] = '-';
11802 opts[opti++] = '-';
11805 opts[opti] = '\0';
11807 /* This isn't perfect, but it's a start. Improvements later. We expand
11808 tlist->word->word and single-quote the results to avoid multiple
11809 expansions by, say, do_assignment_internal(). We have to weigh the
11810 cost of reconstructing the compound assignment string with its single
11811 quoting and letting the declare builtin handle it. The single quotes
11812 will prevent any unwanted additional expansion or word splitting. */
11813 expand_compound_assignment_word (tlist, (tlist->word->flags & W_ASSIGNASSOC) ? 1 : 0);
11815 skip = 0;
11816 if (opti > 0)
11818 t = make_internal_declare (tlist->word->word, opts, wcmd ? wcmd->word->word : (char *)0);
11819 if (t != EXECUTION_SUCCESS)
11821 last_command_exit_value = t;
11822 if (tlist->word->flags & W_FORCELOCAL) /* non-fatal error */
11823 skip = 1;
11824 else
11825 exp_jump_to_top_level (DISCARD);
11829 if (skip == 0)
11831 t = do_word_assignment (tlist->word, 0);
11832 if (t == 0)
11834 last_command_exit_value = EXECUTION_FAILURE;
11835 exp_jump_to_top_level (DISCARD);
11839 /* Now transform the word as ksh93 appears to do and go on */
11840 t = assignment (tlist->word->word, 0);
11841 tlist->word->word[t] = '\0';
11842 if (tlist->word->word[t - 1] == '+')
11843 tlist->word->word[t - 1] = '\0'; /* cut off append op */
11844 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC|W_ASSIGNARRAY);
11846 return (tlist);
11848 #endif /* ARRAY_VARS */
11850 static WORD_LIST *
11851 shell_expand_word_list (tlist, eflags)
11852 WORD_LIST *tlist;
11853 int eflags;
11855 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list, *wcmd;
11856 int expanded_something, has_dollar_at;
11858 /* We do tilde expansion all the time. This is what 1003.2 says. */
11859 wcmd = new_list = (WORD_LIST *)NULL;
11861 for (orig_list = tlist; tlist; tlist = next)
11863 if (wcmd == 0 && (tlist->word->flags & W_ASSNBLTIN))
11864 wcmd = tlist;
11866 next = tlist->next;
11868 #if defined (ARRAY_VARS)
11869 /* If this is a compound array assignment to a builtin that accepts
11870 such assignments (e.g., `declare'), take the assignment and perform
11871 it separately, handling the semantics of declarations inside shell
11872 functions. This avoids the double-evaluation of such arguments,
11873 because `declare' does some evaluation of compound assignments on
11874 its own. */
11875 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
11876 expand_declaration_argument (tlist, wcmd);
11877 #endif
11879 expanded_something = 0;
11880 expanded = expand_word_internal
11881 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
11883 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
11885 /* By convention, each time this error is returned,
11886 tlist->word->word has already been freed. */
11887 tlist->word->word = (char *)NULL;
11889 /* Dispose our copy of the original list. */
11890 dispose_words (orig_list);
11891 /* Dispose the new list we're building. */
11892 dispose_words (new_list);
11894 last_command_exit_value = EXECUTION_FAILURE;
11895 if (expanded == &expand_word_error)
11896 exp_jump_to_top_level (DISCARD);
11897 else
11898 exp_jump_to_top_level (FORCE_EOF);
11901 /* Don't split words marked W_NOSPLIT. */
11902 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
11904 temp_list = word_list_split (expanded);
11905 dispose_words (expanded);
11907 else
11909 /* If no parameter expansion, command substitution, process
11910 substitution, or arithmetic substitution took place, then
11911 do not do word splitting. We still have to remove quoted
11912 null characters from the result. */
11913 word_list_remove_quoted_nulls (expanded);
11914 temp_list = expanded;
11917 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
11918 new_list = (WORD_LIST *)list_append (expanded, new_list);
11921 if (orig_list)
11922 dispose_words (orig_list);
11924 if (new_list)
11925 new_list = REVERSE_LIST (new_list, WORD_LIST *);
11927 return (new_list);
11930 /* The workhorse for expand_words () and expand_words_no_vars ().
11931 First arg is LIST, a WORD_LIST of words.
11932 Second arg EFLAGS is a flags word controlling which expansions are
11933 performed.
11935 This does all of the substitutions: brace expansion, tilde expansion,
11936 parameter expansion, command substitution, arithmetic expansion,
11937 process substitution, word splitting, and pathname expansion, according
11938 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
11939 set, or for which no expansion is done, do not undergo word splitting.
11940 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
11941 with W_NOBRACE set do not undergo brace expansion (see
11942 brace_expand_word_list above). */
11943 static WORD_LIST *
11944 expand_word_list_internal (list, eflags)
11945 WORD_LIST *list;
11946 int eflags;
11948 WORD_LIST *new_list, *temp_list;
11949 int tint;
11950 char *savecmd;
11952 tempenv_assign_error = 0;
11953 if (list == 0)
11954 return ((WORD_LIST *)NULL);
11956 garglist = new_list = copy_word_list (list);
11957 if (eflags & WEXP_VARASSIGN)
11959 garglist = new_list = separate_out_assignments (new_list);
11960 if (new_list == 0)
11962 if (subst_assign_varlist)
11964 /* All the words were variable assignments, so they are placed
11965 into the shell's environment. */
11966 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
11968 savecmd = this_command_name;
11969 this_command_name = (char *)NULL; /* no arithmetic errors */
11970 tint = do_word_assignment (temp_list->word, 0);
11971 this_command_name = savecmd;
11972 /* Variable assignment errors in non-interactive shells
11973 running in Posix.2 mode cause the shell to exit, unless
11974 they are being run by the `command' builtin. */
11975 if (tint == 0)
11977 last_command_exit_value = EXECUTION_FAILURE;
11978 if (interactive_shell == 0 && posixly_correct && executing_command_builtin == 0)
11979 exp_jump_to_top_level (FORCE_EOF);
11980 else
11981 exp_jump_to_top_level (DISCARD);
11984 dispose_words (subst_assign_varlist);
11985 subst_assign_varlist = (WORD_LIST *)NULL;
11987 return ((WORD_LIST *)NULL);
11991 /* Begin expanding the words that remain. The expansions take place on
11992 things that aren't really variable assignments. */
11994 #if defined (BRACE_EXPANSION)
11995 /* Do brace expansion on this word if there are any brace characters
11996 in the string. */
11997 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
11998 new_list = brace_expand_word_list (new_list, eflags);
11999 #endif /* BRACE_EXPANSION */
12001 /* Perform the `normal' shell expansions: tilde expansion, parameter and
12002 variable substitution, command substitution, arithmetic expansion,
12003 and word splitting. */
12004 new_list = shell_expand_word_list (new_list, eflags);
12006 /* Okay, we're almost done. Now let's just do some filename
12007 globbing. */
12008 if (new_list)
12010 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
12011 /* Glob expand the word list unless globbing has been disabled. */
12012 new_list = glob_expand_word_list (new_list, eflags);
12013 else
12014 /* Dequote the words, because we're not performing globbing. */
12015 new_list = dequote_list (new_list);
12018 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
12020 sh_wassign_func_t *assign_func;
12021 int is_special_builtin, is_builtin_or_func;
12023 /* If the remainder of the words expand to nothing, Posix.2 requires
12024 that the variable and environment assignments affect the shell's
12025 environment. */
12026 assign_func = new_list ? assign_in_env : do_word_assignment;
12027 tempenv_assign_error = 0;
12029 is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
12030 /* Posix says that special builtins exit if a variable assignment error
12031 occurs in an assignment preceding it. */
12032 is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
12034 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
12036 savecmd = this_command_name;
12037 this_command_name = (char *)NULL;
12038 assigning_in_environment = (assign_func == assign_in_env);
12039 tint = (*assign_func) (temp_list->word, is_builtin_or_func);
12040 assigning_in_environment = 0;
12041 this_command_name = savecmd;
12042 /* Variable assignment errors in non-interactive shells running
12043 in Posix.2 mode cause the shell to exit. */
12044 if (tint == 0)
12046 if (assign_func == do_word_assignment)
12048 last_command_exit_value = EXECUTION_FAILURE;
12049 if (interactive_shell == 0 && posixly_correct)
12050 exp_jump_to_top_level (FORCE_EOF);
12051 else
12052 exp_jump_to_top_level (DISCARD);
12054 else if (interactive_shell == 0 && is_special_builtin)
12056 last_command_exit_value = EXECUTION_FAILURE;
12057 exp_jump_to_top_level (FORCE_EOF);
12059 else
12060 tempenv_assign_error++;
12064 dispose_words (subst_assign_varlist);
12065 subst_assign_varlist = (WORD_LIST *)NULL;
12068 return (new_list);