Added gitignore entries needed to ignore derived objects generated from full build...
[bash.git] / subst.c
blob0e83e56e474822ebdbbbdd092fb25d0bce1bd3e8
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-2010 Free Software Foundation, Inc.
9 This file is part of GNU Bash, the Bourne Again SHell.
11 Bash is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 Bash is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with Bash. If not, see <http://www.gnu.org/licenses/>.
25 #include "config.h"
27 #include "bashtypes.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 #include "bashansi.h"
41 #include "posixstat.h"
42 #include "bashintl.h"
44 #include "shell.h"
45 #include "parser.h"
46 #include "flags.h"
47 #include "jobs.h"
48 #include "execute_cmd.h"
49 #include "filecntl.h"
50 #include "trap.h"
51 #include "pathexp.h"
52 #include "mailcheck.h"
54 #include "shmbutil.h"
55 #include "typemax.h"
57 #include "builtins/getopt.h"
58 #include "builtins/common.h"
60 #include "builtins/builtext.h"
62 #include <tilde/tilde.h>
63 #include <glob/strmatch.h>
65 #if !defined (errno)
66 extern int errno;
67 #endif /* !errno */
69 /* The size that strings change by. */
70 #define DEFAULT_INITIAL_ARRAY_SIZE 112
71 #define DEFAULT_ARRAY_SIZE 128
73 /* Variable types. */
74 #define VT_VARIABLE 0
75 #define VT_POSPARMS 1
76 #define VT_ARRAYVAR 2
77 #define VT_ARRAYMEMBER 3
78 #define VT_ASSOCVAR 4
80 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
82 /* Flags for quoted_strchr */
83 #define ST_BACKSL 0x01
84 #define ST_CTLESC 0x02
85 #define ST_SQUOTE 0x04 /* unused yet */
86 #define ST_DQUOTE 0x08 /* unused yet */
88 /* Flags for the `pflags' argument to param_expand() */
89 #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
90 #define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
91 #define PF_NOSPLIT2 0x04 /* same as W_NOSPLIT2 */
93 /* These defs make it easier to use the editor. */
94 #define LBRACE '{'
95 #define RBRACE '}'
96 #define LPAREN '('
97 #define RPAREN ')'
99 #if defined (HANDLE_MULTIBYTE)
100 #define WLPAREN L'('
101 #define WRPAREN L')'
102 #endif
104 /* Evaluates to 1 if C is one of the shell's special parameters whose length
105 can be taken, but is also one of the special expansion characters. */
106 #define VALID_SPECIAL_LENGTH_PARAM(c) \
107 ((c) == '-' || (c) == '?' || (c) == '#')
109 /* Evaluates to 1 if C is one of the shell's special parameters for which an
110 indirect variable reference may be made. */
111 #define VALID_INDIR_PARAM(c) \
112 ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
114 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
115 in ${parameter[:]OPword}. */
116 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
118 /* Evaluates to 1 if this is one of the shell's special variables. */
119 #define SPECIAL_VAR(name, wi) \
120 ((DIGIT (*name) && all_digits (name)) || \
121 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
122 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
124 /* An expansion function that takes a string and a quoted flag and returns
125 a WORD_LIST *. Used as the type of the third argument to
126 expand_string_if_necessary(). */
127 typedef WORD_LIST *EXPFUNC __P((char *, int));
129 /* Process ID of the last command executed within command substitution. */
130 pid_t last_command_subst_pid = NO_PID;
131 pid_t current_command_subst_pid = NO_PID;
133 /* Variables used to keep track of the characters in IFS. */
134 SHELL_VAR *ifs_var;
135 char *ifs_value;
136 unsigned char ifs_cmap[UCHAR_MAX + 1];
138 #if defined (HANDLE_MULTIBYTE)
139 unsigned char ifs_firstc[MB_LEN_MAX];
140 size_t ifs_firstc_len;
141 #else
142 unsigned char ifs_firstc;
143 #endif
145 /* Sentinel to tell when we are performing variable assignments preceding a
146 command name and putting them into the environment. Used to make sure
147 we use the temporary environment when looking up variable values. */
148 int assigning_in_environment;
150 /* Used to hold a list of variable assignments preceding a command. Global
151 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
152 SIGCHLD trap and so it can be saved and restored by the trap handlers. */
153 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
155 /* Extern functions and variables from different files. */
156 extern int last_command_exit_value, last_command_exit_signal;
157 extern int subshell_environment, line_number;
158 extern int subshell_level, parse_and_execute_level, sourcelevel;
159 extern int eof_encountered;
160 extern int return_catch_flag, return_catch_value;
161 extern pid_t dollar_dollar_pid;
162 extern int posixly_correct;
163 extern char *this_command_name;
164 extern struct fd_bitmap *current_fds_to_close;
165 extern int wordexp_only;
166 extern int expanding_redir;
167 extern int tempenv_assign_error;
169 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
170 extern wchar_t *wcsdup __P((const wchar_t *));
171 #endif
173 /* Non-zero means to allow unmatched globbed filenames to expand to
174 a null file. */
175 int allow_null_glob_expansion;
177 /* Non-zero means to throw an error when globbing fails to match anything. */
178 int fail_glob_expansion;
180 #if 0
181 /* Variables to keep track of which words in an expanded word list (the
182 output of expand_word_list_internal) are the result of globbing
183 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
184 (CURRENTLY UNUSED). */
185 char *glob_argv_flags;
186 static int glob_argv_flags_size;
187 #endif
189 static WORD_LIST expand_word_error, expand_word_fatal;
190 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
191 static char expand_param_error, expand_param_fatal;
192 static char extract_string_error, extract_string_fatal;
194 /* Tell the expansion functions to not longjmp back to top_level on fatal
195 errors. Enabled when doing completion and prompt string expansion. */
196 static int no_longjmp_on_fatal_error = 0;
198 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
199 $* on $IFS, primarily when doing assignment statements. */
200 static int expand_no_split_dollar_star = 0;
202 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
203 without any leading variable assignments. */
204 static WORD_LIST *garglist = (WORD_LIST *)NULL;
206 static char *quoted_substring __P((char *, int, int));
207 static int quoted_strlen __P((char *));
208 static char *quoted_strchr __P((char *, int, int));
210 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
211 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
212 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
213 static WORD_LIST *expand_string_internal __P((char *, int));
214 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
215 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
217 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
218 static char *make_quoted_char __P((int));
219 static WORD_LIST *quote_list __P((WORD_LIST *));
221 static int unquoted_substring __P((char *, char *));
222 static int unquoted_member __P((int, char *));
224 #if defined (ARRAY_VARS)
225 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
226 #endif
227 static int do_assignment_internal __P((const WORD_DESC *, int));
229 static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
230 static char *string_extract __P((char *, int *, char *, int));
231 static char *string_extract_double_quoted __P((char *, int *, int));
232 static inline char *string_extract_single_quoted __P((char *, int *));
233 static inline int skip_single_quoted __P((const char *, size_t, int));
234 static int skip_double_quoted __P((char *, size_t, int));
235 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
236 static char *extract_dollar_brace_string __P((char *, int *, int, int));
237 static int skip_matched_pair __P((const char *, int, int, int, int));
239 static char *pos_params __P((char *, int, int, int));
241 static unsigned char *mb_getcharlens __P((char *, int));
243 static char *remove_upattern __P((char *, char *, int));
244 #if defined (HANDLE_MULTIBYTE)
245 static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
246 #endif
247 static char *remove_pattern __P((char *, char *, int));
249 static int match_upattern __P((char *, char *, int, char **, char **));
250 #if defined (HANDLE_MULTIBYTE)
251 static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
252 #endif
253 static int match_pattern __P((char *, char *, int, char **, char **));
254 static int getpatspec __P((int, char *));
255 static char *getpattern __P((char *, int, int));
256 static char *variable_remove_pattern __P((char *, char *, int, int));
257 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
258 static char *parameter_list_remove_pattern __P((int, char *, int, int));
259 #ifdef ARRAY_VARS
260 static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int));
261 #endif
262 static char *parameter_brace_remove_pattern __P((char *, char *, int, char *, int, int, int));
264 static char *process_substitute __P((char *, int));
266 static char *read_comsub __P((int, int, int *));
268 #ifdef ARRAY_VARS
269 static arrayind_t array_length_reference __P((char *));
270 #endif
272 static int valid_brace_expansion_word __P((char *, int));
273 static int chk_atstar __P((char *, int, int *, int *));
274 static int chk_arithsub __P((const char *, int));
276 static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayind_t *));
277 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
278 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
279 static void parameter_brace_expand_error __P((char *, char *));
281 static int valid_length_expression __P((char *));
282 static intmax_t parameter_brace_expand_length __P((char *));
284 static char *skiparith __P((char *, int));
285 static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
286 static int get_var_and_type __P((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **));
287 static char *mb_substring __P((char *, int, int));
288 static char *parameter_brace_substring __P((char *, char *, int, char *, int, int));
290 static int shouldexp_replacement __P((char *));
292 static char *pos_params_pat_subst __P((char *, char *, char *, int));
294 static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int));
296 static char *pos_params_casemod __P((char *, char *, int, int));
297 static char *parameter_brace_casemod __P((char *, char *, int, int, char *, int, int));
299 static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int, int *, int *));
300 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
302 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
304 static WORD_LIST *word_list_split __P((WORD_LIST *));
306 static void exp_jump_to_top_level __P((int));
308 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
309 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
310 #ifdef BRACE_EXPANSION
311 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
312 #endif
313 #if defined (ARRAY_VARS)
314 static int make_internal_declare __P((char *, char *));
315 #endif
316 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
317 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
319 /* **************************************************************** */
320 /* */
321 /* Utility Functions */
322 /* */
323 /* **************************************************************** */
325 #if defined (DEBUG)
326 void
327 dump_word_flags (flags)
328 int flags;
330 int f;
332 f = flags;
333 fprintf (stderr, "%d -> ", f);
334 if (f & W_ASSIGNASSOC)
336 f &= ~W_ASSIGNASSOC;
337 fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : "");
339 if (f & W_HASCTLESC)
341 f &= ~W_HASCTLESC;
342 fprintf (stderr, "W_HASCTLESC%s", f ? "|" : "");
344 if (f & W_NOPROCSUB)
346 f &= ~W_NOPROCSUB;
347 fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : "");
349 if (f & W_DQUOTE)
351 f &= ~W_DQUOTE;
352 fprintf (stderr, "W_DQUOTE%s", f ? "|" : "");
354 if (f & W_HASQUOTEDNULL)
356 f &= ~W_HASQUOTEDNULL;
357 fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : "");
359 if (f & W_ASSIGNARG)
361 f &= ~W_ASSIGNARG;
362 fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : "");
364 if (f & W_ASSNBLTIN)
366 f &= ~W_ASSNBLTIN;
367 fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : "");
369 if (f & W_COMPASSIGN)
371 f &= ~W_COMPASSIGN;
372 fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : "");
374 if (f & W_NOEXPAND)
376 f &= ~W_NOEXPAND;
377 fprintf (stderr, "W_NOEXPAND%s", f ? "|" : "");
379 if (f & W_ITILDE)
381 f &= ~W_ITILDE;
382 fprintf (stderr, "W_ITILDE%s", f ? "|" : "");
384 if (f & W_NOTILDE)
386 f &= ~W_NOTILDE;
387 fprintf (stderr, "W_NOTILDE%s", f ? "|" : "");
389 if (f & W_ASSIGNRHS)
391 f &= ~W_ASSIGNRHS;
392 fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : "");
394 if (f & W_NOCOMSUB)
396 f &= ~W_NOCOMSUB;
397 fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : "");
399 if (f & W_DOLLARSTAR)
401 f &= ~W_DOLLARSTAR;
402 fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : "");
404 if (f & W_DOLLARAT)
406 f &= ~W_DOLLARAT;
407 fprintf (stderr, "W_DOLLARAT%s", f ? "|" : "");
409 if (f & W_TILDEEXP)
411 f &= ~W_TILDEEXP;
412 fprintf (stderr, "W_TILDEEXP%s", f ? "|" : "");
414 if (f & W_NOSPLIT2)
416 f &= ~W_NOSPLIT2;
417 fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : "");
419 if (f & W_NOGLOB)
421 f &= ~W_NOGLOB;
422 fprintf (stderr, "W_NOGLOB%s", f ? "|" : "");
424 if (f & W_NOSPLIT)
426 f &= ~W_NOSPLIT;
427 fprintf (stderr, "W_NOSPLIT%s", f ? "|" : "");
429 if (f & W_GLOBEXP)
431 f &= ~W_GLOBEXP;
432 fprintf (stderr, "W_GLOBEXP%s", f ? "|" : "");
434 if (f & W_ASSIGNMENT)
436 f &= ~W_ASSIGNMENT;
437 fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : "");
439 if (f & W_QUOTED)
441 f &= ~W_QUOTED;
442 fprintf (stderr, "W_QUOTED%s", f ? "|" : "");
444 if (f & W_HASDOLLAR)
446 f &= ~W_HASDOLLAR;
447 fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : "");
449 fprintf (stderr, "\n");
450 fflush (stderr);
452 #endif
454 #ifdef INCLUDE_UNUSED
455 static char *
456 quoted_substring (string, start, end)
457 char *string;
458 int start, end;
460 register int len, l;
461 register char *result, *s, *r;
463 len = end - start;
465 /* Move to string[start], skipping quoted characters. */
466 for (s = string, l = 0; *s && l < start; )
468 if (*s == CTLESC)
470 s++;
471 continue;
473 l++;
474 if (*s == 0)
475 break;
478 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
480 /* Copy LEN characters, including quote characters. */
481 s = string + l;
482 for (l = 0; l < len; s++)
484 if (*s == CTLESC)
485 *r++ = *s++;
486 *r++ = *s;
487 l++;
488 if (*s == 0)
489 break;
491 *r = '\0';
492 return result;
494 #endif
496 #ifdef INCLUDE_UNUSED
497 /* Return the length of S, skipping over quoted characters */
498 static int
499 quoted_strlen (s)
500 char *s;
502 register char *p;
503 int i;
505 i = 0;
506 for (p = s; *p; p++)
508 if (*p == CTLESC)
510 p++;
511 if (*p == 0)
512 return (i + 1);
514 i++;
517 return i;
519 #endif
521 /* Find the first occurrence of character C in string S, obeying shell
522 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
523 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
524 escaped with CTLESC are skipped. */
525 static char *
526 quoted_strchr (s, c, flags)
527 char *s;
528 int c, flags;
530 register char *p;
532 for (p = s; *p; p++)
534 if (((flags & ST_BACKSL) && *p == '\\')
535 || ((flags & ST_CTLESC) && *p == CTLESC))
537 p++;
538 if (*p == '\0')
539 return ((char *)NULL);
540 continue;
542 else if (*p == c)
543 return p;
545 return ((char *)NULL);
548 /* Return 1 if CHARACTER appears in an unquoted portion of
549 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
550 static int
551 unquoted_member (character, string)
552 int character;
553 char *string;
555 size_t slen;
556 int sindex, c;
557 DECLARE_MBSTATE;
559 slen = strlen (string);
560 sindex = 0;
561 while (c = string[sindex])
563 if (c == character)
564 return (1);
566 switch (c)
568 default:
569 ADVANCE_CHAR (string, slen, sindex);
570 break;
572 case '\\':
573 sindex++;
574 if (string[sindex])
575 ADVANCE_CHAR (string, slen, sindex);
576 break;
578 case '\'':
579 sindex = skip_single_quoted (string, slen, ++sindex);
580 break;
582 case '"':
583 sindex = skip_double_quoted (string, slen, ++sindex);
584 break;
587 return (0);
590 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
591 static int
592 unquoted_substring (substr, string)
593 char *substr, *string;
595 size_t slen;
596 int sindex, c, sublen;
597 DECLARE_MBSTATE;
599 if (substr == 0 || *substr == '\0')
600 return (0);
602 slen = strlen (string);
603 sublen = strlen (substr);
604 for (sindex = 0; c = string[sindex]; )
606 if (STREQN (string + sindex, substr, sublen))
607 return (1);
609 switch (c)
611 case '\\':
612 sindex++;
613 if (string[sindex])
614 ADVANCE_CHAR (string, slen, sindex);
615 break;
617 case '\'':
618 sindex = skip_single_quoted (string, slen, ++sindex);
619 break;
621 case '"':
622 sindex = skip_double_quoted (string, slen, ++sindex);
623 break;
625 default:
626 ADVANCE_CHAR (string, slen, sindex);
627 break;
630 return (0);
633 /* Most of the substitutions must be done in parallel. In order
634 to avoid using tons of unclear goto's, I have some functions
635 for manipulating malloc'ed strings. They all take INDX, a
636 pointer to an integer which is the offset into the string
637 where manipulation is taking place. They also take SIZE, a
638 pointer to an integer which is the current length of the
639 character array for this string. */
641 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
642 of space allocated to TARGET. SOURCE can be NULL, in which
643 case nothing happens. Gets rid of SOURCE by freeing it.
644 Returns TARGET in case the location has changed. */
645 INLINE char *
646 sub_append_string (source, target, indx, size)
647 char *source, *target;
648 int *indx, *size;
650 if (source)
652 int srclen, n;
654 srclen = STRLEN (source);
655 if (srclen >= (int)(*size - *indx))
657 n = srclen + *indx;
658 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
659 target = (char *)xrealloc (target, (*size = n));
662 FASTCOPY (source, target + *indx, srclen);
663 *indx += srclen;
664 target[*indx] = '\0';
666 free (source);
668 return (target);
671 #if 0
672 /* UNUSED */
673 /* Append the textual representation of NUMBER to TARGET.
674 INDX and SIZE are as in SUB_APPEND_STRING. */
675 char *
676 sub_append_number (number, target, indx, size)
677 intmax_t number;
678 int *indx, *size;
679 char *target;
681 char *temp;
683 temp = itos (number);
684 return (sub_append_string (temp, target, indx, size));
686 #endif
688 /* Extract a substring from STRING, starting at SINDEX and ending with
689 one of the characters in CHARLIST. Don't make the ending character
690 part of the string. Leave SINDEX pointing at the ending character.
691 Understand about backslashes in the string. If (flags & SX_VARNAME)
692 is non-zero, and array variables have been compiled into the shell,
693 everything between a `[' and a corresponding `]' is skipped over.
694 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
695 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
696 contain a closing character from CHARLIST. */
697 static char *
698 string_extract (string, sindex, charlist, flags)
699 char *string;
700 int *sindex;
701 char *charlist;
702 int flags;
704 register int c, i;
705 int found;
706 size_t slen;
707 char *temp;
708 DECLARE_MBSTATE;
710 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
711 i = *sindex;
712 found = 0;
713 while (c = string[i])
715 if (c == '\\')
717 if (string[i + 1])
718 i++;
719 else
720 break;
722 #if defined (ARRAY_VARS)
723 else if ((flags & SX_VARNAME) && c == '[')
725 int ni;
726 /* If this is an array subscript, skip over it and continue. */
727 ni = skipsubscript (string, i, 0);
728 if (string[ni] == ']')
729 i = ni;
731 #endif
732 else if (MEMBER (c, charlist))
734 found = 1;
735 break;
738 ADVANCE_CHAR (string, slen, i);
741 /* If we had to have a matching delimiter and didn't find one, return an
742 error and let the caller deal with it. */
743 if ((flags & SX_REQMATCH) && found == 0)
745 *sindex = i;
746 return (&extract_string_error);
749 temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
750 *sindex = i;
752 return (temp);
755 /* Extract the contents of STRING as if it is enclosed in double quotes.
756 SINDEX, when passed in, is the offset of the character immediately
757 following the opening double quote; on exit, SINDEX is left pointing after
758 the closing double quote. If STRIPDQ is non-zero, unquoted double
759 quotes are stripped and the string is terminated by a null byte.
760 Backslashes between the embedded double quotes are processed. If STRIPDQ
761 is zero, an unquoted `"' terminates the string. */
762 static char *
763 string_extract_double_quoted (string, sindex, stripdq)
764 char *string;
765 int *sindex, stripdq;
767 size_t slen;
768 char *send;
769 int j, i, t;
770 unsigned char c;
771 char *temp, *ret; /* The new string we return. */
772 int pass_next, backquote, si; /* State variables for the machine. */
773 int dquote;
774 DECLARE_MBSTATE;
776 slen = strlen (string + *sindex) + *sindex;
777 send = string + slen;
779 pass_next = backquote = dquote = 0;
780 temp = (char *)xmalloc (1 + slen - *sindex);
782 j = 0;
783 i = *sindex;
784 while (c = string[i])
786 /* Process a character that was quoted by a backslash. */
787 if (pass_next)
789 /* XXX - take another look at this in light of Interp 221 */
790 /* Posix.2 sez:
792 ``The backslash shall retain its special meaning as an escape
793 character only when followed by one of the characters:
794 $ ` " \ <newline>''.
796 If STRIPDQ is zero, we handle the double quotes here and let
797 expand_word_internal handle the rest. If STRIPDQ is non-zero,
798 we have already been through one round of backslash stripping,
799 and want to strip these backslashes only if DQUOTE is non-zero,
800 indicating that we are inside an embedded double-quoted string. */
802 /* If we are in an embedded quoted string, then don't strip
803 backslashes before characters for which the backslash
804 retains its special meaning, but remove backslashes in
805 front of other characters. If we are not in an
806 embedded quoted string, don't strip backslashes at all.
807 This mess is necessary because the string was already
808 surrounded by double quotes (and sh has some really weird
809 quoting rules).
810 The returned string will be run through expansion as if
811 it were double-quoted. */
812 if ((stripdq == 0 && c != '"') ||
813 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
814 temp[j++] = '\\';
815 pass_next = 0;
817 add_one_character:
818 COPY_CHAR_I (temp, j, string, send, i);
819 continue;
822 /* A backslash protects the next character. The code just above
823 handles preserving the backslash in front of any character but
824 a double quote. */
825 if (c == '\\')
827 pass_next++;
828 i++;
829 continue;
832 /* Inside backquotes, ``the portion of the quoted string from the
833 initial backquote and the characters up to the next backquote
834 that is not preceded by a backslash, having escape characters
835 removed, defines that command''. */
836 if (backquote)
838 if (c == '`')
839 backquote = 0;
840 temp[j++] = c;
841 i++;
842 continue;
845 if (c == '`')
847 temp[j++] = c;
848 backquote++;
849 i++;
850 continue;
853 /* Pass everything between `$(' and the matching `)' or a quoted
854 ${ ... } pair through according to the Posix.2 specification. */
855 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
857 int free_ret = 1;
859 si = i + 2;
860 if (string[i + 1] == LPAREN)
861 ret = extract_command_subst (string, &si, 0);
862 else
863 ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0);
865 temp[j++] = '$';
866 temp[j++] = string[i + 1];
868 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
869 is set. */
870 if (ret == 0 && no_longjmp_on_fatal_error)
872 free_ret = 0;
873 ret = string + i + 2;
876 for (t = 0; ret[t]; t++, j++)
877 temp[j] = ret[t];
878 temp[j] = string[si];
880 if (string[si])
882 j++;
883 i = si + 1;
885 else
886 i = si;
888 if (free_ret)
889 free (ret);
890 continue;
893 /* Add any character but a double quote to the quoted string we're
894 accumulating. */
895 if (c != '"')
896 goto add_one_character;
898 /* c == '"' */
899 if (stripdq)
901 dquote ^= 1;
902 i++;
903 continue;
906 break;
908 temp[j] = '\0';
910 /* Point to after the closing quote. */
911 if (c)
912 i++;
913 *sindex = i;
915 return (temp);
918 /* This should really be another option to string_extract_double_quoted. */
919 static int
920 skip_double_quoted (string, slen, sind)
921 char *string;
922 size_t slen;
923 int sind;
925 int c, i;
926 char *ret;
927 int pass_next, backquote, si;
928 DECLARE_MBSTATE;
930 pass_next = backquote = 0;
931 i = sind;
932 while (c = string[i])
934 if (pass_next)
936 pass_next = 0;
937 ADVANCE_CHAR (string, slen, i);
938 continue;
940 else if (c == '\\')
942 pass_next++;
943 i++;
944 continue;
946 else if (backquote)
948 if (c == '`')
949 backquote = 0;
950 ADVANCE_CHAR (string, slen, i);
951 continue;
953 else if (c == '`')
955 backquote++;
956 i++;
957 continue;
959 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
961 si = i + 2;
962 if (string[i + 1] == LPAREN)
963 ret = extract_command_subst (string, &si, SX_NOALLOC);
964 else
965 ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC);
967 i = si + 1;
968 continue;
970 else if (c != '"')
972 ADVANCE_CHAR (string, slen, i);
973 continue;
975 else
976 break;
979 if (c)
980 i++;
982 return (i);
985 /* Extract the contents of STRING as if it is enclosed in single quotes.
986 SINDEX, when passed in, is the offset of the character immediately
987 following the opening single quote; on exit, SINDEX is left pointing after
988 the closing single quote. */
989 static inline char *
990 string_extract_single_quoted (string, sindex)
991 char *string;
992 int *sindex;
994 register int i;
995 size_t slen;
996 char *t;
997 DECLARE_MBSTATE;
999 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
1000 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
1001 i = *sindex;
1002 while (string[i] && string[i] != '\'')
1003 ADVANCE_CHAR (string, slen, i);
1005 t = substring (string, *sindex, i);
1007 if (string[i])
1008 i++;
1009 *sindex = i;
1011 return (t);
1014 static inline int
1015 skip_single_quoted (string, slen, sind)
1016 const char *string;
1017 size_t slen;
1018 int sind;
1020 register int c;
1021 DECLARE_MBSTATE;
1023 c = sind;
1024 while (string[c] && string[c] != '\'')
1025 ADVANCE_CHAR (string, slen, c);
1027 if (string[c])
1028 c++;
1029 return c;
1032 /* Just like string_extract, but doesn't hack backslashes or any of
1033 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
1034 static char *
1035 string_extract_verbatim (string, slen, sindex, charlist, flags)
1036 char *string;
1037 size_t slen;
1038 int *sindex;
1039 char *charlist;
1040 int flags;
1042 register int i;
1043 #if defined (HANDLE_MULTIBYTE)
1044 size_t clen;
1045 wchar_t *wcharlist;
1046 #endif
1047 int c;
1048 char *temp;
1049 DECLARE_MBSTATE;
1051 if (charlist[0] == '\'' && charlist[1] == '\0')
1053 temp = string_extract_single_quoted (string, sindex);
1054 --*sindex; /* leave *sindex at separator character */
1055 return temp;
1058 i = *sindex;
1059 #if 0
1060 /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
1061 this only if MB_CUR_MAX > 1. */
1062 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
1063 #endif
1064 #if defined (HANDLE_MULTIBYTE)
1065 clen = strlen (charlist);
1066 wcharlist = 0;
1067 #endif
1068 while (c = string[i])
1070 #if defined (HANDLE_MULTIBYTE)
1071 size_t mblength;
1072 #endif
1073 if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
1075 i += 2;
1076 continue;
1078 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
1079 through, to protect the CTLNULs from later calls to
1080 remove_quoted_nulls. */
1081 else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
1083 i += 2;
1084 continue;
1087 #if defined (HANDLE_MULTIBYTE)
1088 mblength = MBLEN (string + i, slen - i);
1089 if (mblength > 1)
1091 wchar_t wc;
1092 mblength = mbtowc (&wc, string + i, slen - i);
1093 if (MB_INVALIDCH (mblength))
1095 if (MEMBER (c, charlist))
1096 break;
1098 else
1100 if (wcharlist == 0)
1102 size_t len;
1103 len = mbstowcs (wcharlist, charlist, 0);
1104 if (len == -1)
1105 len = 0;
1106 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
1107 mbstowcs (wcharlist, charlist, len + 1);
1110 if (wcschr (wcharlist, wc))
1111 break;
1114 else
1115 #endif
1116 if (MEMBER (c, charlist))
1117 break;
1119 ADVANCE_CHAR (string, slen, i);
1122 #if defined (HANDLE_MULTIBYTE)
1123 FREE (wcharlist);
1124 #endif
1126 temp = substring (string, *sindex, i);
1127 *sindex = i;
1129 return (temp);
1132 /* Extract the $( construct in STRING, and return a new string.
1133 Start extracting at (SINDEX) as if we had just seen "$(".
1134 Make (SINDEX) get the position of the matching ")". )
1135 XFLAGS is additional flags to pass to other extraction functions. */
1136 char *
1137 extract_command_subst (string, sindex, xflags)
1138 char *string;
1139 int *sindex;
1140 int xflags;
1142 if (string[*sindex] == LPAREN)
1143 return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
1144 else
1146 xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1147 return (xparse_dolparen (string, string+*sindex, sindex, xflags));
1151 /* Extract the $[ construct in STRING, and return a new string. (])
1152 Start extracting at (SINDEX) as if we had just seen "$[".
1153 Make (SINDEX) get the position of the matching "]". */
1154 char *
1155 extract_arithmetic_subst (string, sindex)
1156 char *string;
1157 int *sindex;
1159 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
1162 #if defined (PROCESS_SUBSTITUTION)
1163 /* Extract the <( or >( construct in STRING, and return a new string.
1164 Start extracting at (SINDEX) as if we had just seen "<(".
1165 Make (SINDEX) get the position of the matching ")". */ /*))*/
1166 char *
1167 extract_process_subst (string, starter, sindex)
1168 char *string;
1169 char *starter;
1170 int *sindex;
1172 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1174 #endif /* PROCESS_SUBSTITUTION */
1176 #if defined (ARRAY_VARS)
1177 /* This can be fooled by unquoted right parens in the passed string. If
1178 each caller verifies that the last character in STRING is a right paren,
1179 we don't even need to call extract_delimited_string. */
1180 char *
1181 extract_array_assignment_list (string, sindex)
1182 char *string;
1183 int *sindex;
1185 int slen;
1186 char *ret;
1188 slen = strlen (string); /* ( */
1189 if (string[slen - 1] == ')')
1191 ret = substring (string, *sindex, slen - 1);
1192 *sindex = slen - 1;
1193 return ret;
1195 return 0;
1197 #endif
1199 /* Extract and create a new string from the contents of STRING, a
1200 character string delimited with OPENER and CLOSER. SINDEX is
1201 the address of an int describing the current offset in STRING;
1202 it should point to just after the first OPENER found. On exit,
1203 SINDEX gets the position of the last character of the matching CLOSER.
1204 If OPENER is more than a single character, ALT_OPENER, if non-null,
1205 contains a character string that can also match CLOSER and thus
1206 needs to be skipped. */
1207 static char *
1208 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1209 char *string;
1210 int *sindex;
1211 char *opener, *alt_opener, *closer;
1212 int flags;
1214 int i, c, si;
1215 size_t slen;
1216 char *t, *result;
1217 int pass_character, nesting_level, in_comment;
1218 int len_closer, len_opener, len_alt_opener;
1219 DECLARE_MBSTATE;
1221 slen = strlen (string + *sindex) + *sindex;
1222 len_opener = STRLEN (opener);
1223 len_alt_opener = STRLEN (alt_opener);
1224 len_closer = STRLEN (closer);
1226 pass_character = in_comment = 0;
1228 nesting_level = 1;
1229 i = *sindex;
1231 while (nesting_level)
1233 c = string[i];
1235 if (c == 0)
1236 break;
1238 if (in_comment)
1240 if (c == '\n')
1241 in_comment = 0;
1242 ADVANCE_CHAR (string, slen, i);
1243 continue;
1246 if (pass_character) /* previous char was backslash */
1248 pass_character = 0;
1249 ADVANCE_CHAR (string, slen, i);
1250 continue;
1253 /* Not exactly right yet; should handle shell metacharacters and
1254 multibyte characters, too. See COMMENT_BEGIN define in parse.y */
1255 if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
1257 in_comment = 1;
1258 ADVANCE_CHAR (string, slen, i);
1259 continue;
1262 if (c == CTLESC || c == '\\')
1264 pass_character++;
1265 i++;
1266 continue;
1269 /* Process a nested command substitution, but only if we're parsing an
1270 arithmetic substitution. */
1271 if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
1273 si = i + 2;
1274 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1275 i = si + 1;
1276 continue;
1279 /* Process a nested OPENER. */
1280 if (STREQN (string + i, opener, len_opener))
1282 si = i + len_opener;
1283 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
1284 i = si + 1;
1285 continue;
1288 /* Process a nested ALT_OPENER */
1289 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1291 si = i + len_alt_opener;
1292 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
1293 i = si + 1;
1294 continue;
1297 /* If the current substring terminates the delimited string, decrement
1298 the nesting level. */
1299 if (STREQN (string + i, closer, len_closer))
1301 i += len_closer - 1; /* move to last byte of the closer */
1302 nesting_level--;
1303 if (nesting_level == 0)
1304 break;
1307 /* Pass old-style command substitution through verbatim. */
1308 if (c == '`')
1310 si = i + 1;
1311 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1312 i = si + 1;
1313 continue;
1316 /* Pass single-quoted and double-quoted strings through verbatim. */
1317 if (c == '\'' || c == '"')
1319 si = i + 1;
1320 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1321 : skip_double_quoted (string, slen, si);
1322 continue;
1325 /* move past this character, which was not special. */
1326 ADVANCE_CHAR (string, slen, i);
1329 if (c == 0 && nesting_level)
1331 if (no_longjmp_on_fatal_error == 0)
1333 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1334 last_command_exit_value = EXECUTION_FAILURE;
1335 exp_jump_to_top_level (DISCARD);
1337 else
1339 *sindex = i;
1340 return (char *)NULL;
1344 si = i - *sindex - len_closer + 1;
1345 if (flags & SX_NOALLOC)
1346 result = (char *)NULL;
1347 else
1349 result = (char *)xmalloc (1 + si);
1350 strncpy (result, string + *sindex, si);
1351 result[si] = '\0';
1353 *sindex = i;
1355 return (result);
1358 /* Extract a parameter expansion expression within ${ and } from STRING.
1359 Obey the Posix.2 rules for finding the ending `}': count braces while
1360 skipping over enclosed quoted strings and command substitutions.
1361 SINDEX is the address of an int describing the current offset in STRING;
1362 it should point to just after the first `{' found. On exit, SINDEX
1363 gets the position of the matching `}'. QUOTED is non-zero if this
1364 occurs inside double quotes. */
1365 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1366 static char *
1367 extract_dollar_brace_string (string, sindex, quoted, flags)
1368 char *string;
1369 int *sindex, quoted, flags;
1371 register int i, c;
1372 size_t slen;
1373 int pass_character, nesting_level, si, dolbrace_state;
1374 char *result, *t;
1375 DECLARE_MBSTATE;
1377 pass_character = 0;
1378 nesting_level = 1;
1379 slen = strlen (string + *sindex) + *sindex;
1381 /* The handling of dolbrace_state needs to agree with the code in parse.y:
1382 parse_matched_pair() */
1383 dolbrace_state = 0;
1384 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1385 dolbrace_state = (flags & SX_POSIXEXP) ? DOLBRACE_QUOTE : DOLBRACE_PARAM;
1387 i = *sindex;
1388 while (c = string[i])
1390 if (pass_character)
1392 pass_character = 0;
1393 ADVANCE_CHAR (string, slen, i);
1394 continue;
1397 /* CTLESCs and backslashes quote the next character. */
1398 if (c == CTLESC || c == '\\')
1400 pass_character++;
1401 i++;
1402 continue;
1405 if (string[i] == '$' && string[i+1] == LBRACE)
1407 nesting_level++;
1408 i += 2;
1409 continue;
1412 if (c == RBRACE)
1414 nesting_level--;
1415 if (nesting_level == 0)
1416 break;
1417 i++;
1418 continue;
1421 /* Pass the contents of old-style command substitutions through
1422 verbatim. */
1423 if (c == '`')
1425 si = i + 1;
1426 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1427 i = si + 1;
1428 continue;
1431 /* Pass the contents of new-style command substitutions and
1432 arithmetic substitutions through verbatim. */
1433 if (string[i] == '$' && string[i+1] == LPAREN)
1435 si = i + 2;
1436 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1437 i = si + 1;
1438 continue;
1441 #if 0
1442 /* Pass the contents of single-quoted and double-quoted strings
1443 through verbatim. */
1444 if (c == '\'' || c == '"')
1446 si = i + 1;
1447 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1448 : skip_double_quoted (string, slen, si);
1449 /* skip_XXX_quoted leaves index one past close quote */
1450 continue;
1452 #else /* XXX - bash-4.2 */
1453 /* Pass the contents of double-quoted strings through verbatim. */
1454 if (c == '"')
1456 si = i + 1;
1457 i = skip_double_quoted (string, slen, si);
1458 /* skip_XXX_quoted leaves index one past close quote */
1459 continue;
1462 if (c == '\'')
1464 /*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
1465 if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
1466 ADVANCE_CHAR (string, slen, i);
1467 else
1469 si = i + 1;
1470 i = skip_single_quoted (string, slen, si);
1473 continue;
1475 #endif
1477 /* move past this character, which was not special. */
1478 ADVANCE_CHAR (string, slen, i);
1480 /* This logic must agree with parse.y:parse_matched_pair, since they
1481 share the same defines. */
1482 if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 1)
1483 dolbrace_state = DOLBRACE_QUOTE;
1484 else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
1485 dolbrace_state = DOLBRACE_QUOTE;
1486 else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1)
1487 dolbrace_state = DOLBRACE_QUOTE;
1488 else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1)
1489 dolbrace_state = DOLBRACE_QUOTE;
1490 else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1)
1491 dolbrace_state = DOLBRACE_QUOTE;
1492 else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0)
1493 dolbrace_state = DOLBRACE_OP;
1494 else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0)
1495 dolbrace_state = DOLBRACE_WORD;
1498 if (c == 0 && nesting_level)
1500 if (no_longjmp_on_fatal_error == 0)
1501 { /* { */
1502 report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1503 last_command_exit_value = EXECUTION_FAILURE;
1504 exp_jump_to_top_level (DISCARD);
1506 else
1508 *sindex = i;
1509 return ((char *)NULL);
1513 result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1514 *sindex = i;
1516 return (result);
1519 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1520 STRING, and returns a pointer to it. */
1521 char *
1522 de_backslash (string)
1523 char *string;
1525 register size_t slen;
1526 register int i, j, prev_i;
1527 DECLARE_MBSTATE;
1529 slen = strlen (string);
1530 i = j = 0;
1532 /* Loop copying string[i] to string[j], i >= j. */
1533 while (i < slen)
1535 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1536 string[i + 1] == '$'))
1537 i++;
1538 prev_i = i;
1539 ADVANCE_CHAR (string, slen, i);
1540 if (j < prev_i)
1541 do string[j++] = string[prev_i++]; while (prev_i < i);
1542 else
1543 j = i;
1545 string[j] = '\0';
1547 return (string);
1550 #if 0
1551 /*UNUSED*/
1552 /* Replace instances of \! in a string with !. */
1553 void
1554 unquote_bang (string)
1555 char *string;
1557 register int i, j;
1558 register char *temp;
1560 temp = (char *)xmalloc (1 + strlen (string));
1562 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1564 if (string[i] == '\\' && string[i + 1] == '!')
1566 temp[j] = '!';
1567 i++;
1570 strcpy (string, temp);
1571 free (temp);
1573 #endif
1575 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1577 /* This function assumes s[i] == open; returns with s[ret] == close; used to
1578 parse array subscripts. FLAGS & 1 means to not attempt to skip over
1579 matched pairs of quotes or backquotes, or skip word expansions; it is
1580 intended to be used after expansion has been performed and during final
1581 assignment parsing (see arrayfunc.c:assign_compound_array_list()). */
1582 static int
1583 skip_matched_pair (string, start, open, close, flags)
1584 const char *string;
1585 int start, open, close, flags;
1587 int i, pass_next, backq, si, c, count;
1588 size_t slen;
1589 char *temp, *ss;
1590 DECLARE_MBSTATE;
1592 slen = strlen (string + start) + start;
1593 no_longjmp_on_fatal_error = 1;
1595 i = start + 1; /* skip over leading bracket */
1596 count = 1;
1597 pass_next = backq = 0;
1598 ss = (char *)string;
1599 while (c = string[i])
1601 if (pass_next)
1603 pass_next = 0;
1604 if (c == 0)
1605 CQ_RETURN(i);
1606 ADVANCE_CHAR (string, slen, i);
1607 continue;
1609 else if (c == '\\')
1611 pass_next = 1;
1612 i++;
1613 continue;
1615 else if (backq)
1617 if (c == '`')
1618 backq = 0;
1619 ADVANCE_CHAR (string, slen, i);
1620 continue;
1622 else if ((flags & 1) == 0 && c == '`')
1624 backq = 1;
1625 i++;
1626 continue;
1628 else if ((flags & 1) == 0 && c == open)
1630 count++;
1631 i++;
1632 continue;
1634 else if (c == close)
1636 count--;
1637 if (count == 0)
1638 break;
1639 i++;
1640 continue;
1642 else if ((flags & 1) == 0 && (c == '\'' || c == '"'))
1644 i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
1645 : skip_double_quoted (ss, slen, ++i);
1646 /* no increment, the skip functions increment past the closing quote. */
1648 else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1650 si = i + 2;
1651 if (string[si] == '\0')
1652 CQ_RETURN(si);
1654 if (string[i+1] == LPAREN)
1655 temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1656 else
1657 temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
1658 i = si;
1659 if (string[i] == '\0') /* don't increment i past EOS in loop */
1660 break;
1661 i++;
1662 continue;
1664 else
1665 ADVANCE_CHAR (string, slen, i);
1668 CQ_RETURN(i);
1671 #if defined (ARRAY_VARS)
1673 skipsubscript (string, start, flags)
1674 const char *string;
1675 int start, flags;
1677 return (skip_matched_pair (string, start, '[', ']', flags));
1679 #endif
1681 /* Skip characters in STRING until we find a character in DELIMS, and return
1682 the index of that character. START is the index into string at which we
1683 begin. This is similar in spirit to strpbrk, but it returns an index into
1684 STRING and takes a starting index. This little piece of code knows quite
1685 a lot of shell syntax. It's very similar to skip_double_quoted and other
1686 functions of that ilk. */
1688 skip_to_delim (string, start, delims, flags)
1689 char *string;
1690 int start;
1691 char *delims;
1692 int flags;
1694 int i, pass_next, backq, si, c, invert, skipquote, skipcmd;
1695 size_t slen;
1696 char *temp, open[3];
1697 DECLARE_MBSTATE;
1699 slen = strlen (string + start) + start;
1700 if (flags & SD_NOJMP)
1701 no_longjmp_on_fatal_error = 1;
1702 invert = (flags & SD_INVERT);
1703 skipcmd = (flags & SD_NOSKIPCMD) == 0;
1705 i = start;
1706 pass_next = backq = 0;
1707 while (c = string[i])
1709 /* If this is non-zero, we should not let quote characters be delimiters
1710 and the current character is a single or double quote. We should not
1711 test whether or not it's a delimiter until after we skip single- or
1712 double-quoted strings. */
1713 skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"'));
1714 if (pass_next)
1716 pass_next = 0;
1717 if (c == 0)
1718 CQ_RETURN(i);
1719 ADVANCE_CHAR (string, slen, i);
1720 continue;
1722 else if (c == '\\')
1724 pass_next = 1;
1725 i++;
1726 continue;
1728 else if (backq)
1730 if (c == '`')
1731 backq = 0;
1732 ADVANCE_CHAR (string, slen, i);
1733 continue;
1735 else if (c == '`')
1737 backq = 1;
1738 i++;
1739 continue;
1741 else if (skipquote == 0 && invert == 0 && member (c, delims))
1742 break;
1743 else if (c == '\'' || c == '"')
1745 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1746 : skip_double_quoted (string, slen, ++i);
1747 /* no increment, the skip functions increment past the closing quote. */
1749 else if (c == '$' && ((skipcmd && string[i+1] == LPAREN) || string[i+1] == LBRACE))
1751 si = i + 2;
1752 if (string[si] == '\0')
1753 CQ_RETURN(si);
1755 if (string[i+1] == LPAREN)
1756 temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1757 else
1758 temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
1759 i = si;
1760 if (string[i] == '\0') /* don't increment i past EOS in loop */
1761 break;
1762 i++;
1763 continue;
1765 #if defined (PROCESS_SUBSTITUTION)
1766 else if (skipcmd && (c == '<' || c == '>') && string[i+1] == LPAREN)
1768 si = i + 2;
1769 if (string[si] == '\0')
1770 CQ_RETURN(si);
1771 temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si);
1772 i = si;
1773 if (string[i] == '\0')
1774 break;
1775 i++;
1776 continue;
1778 #endif /* PROCESS_SUBSTITUTION */
1779 #if defined (EXTENDED_GLOB)
1780 else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@"))
1782 si = i + 2;
1783 if (string[si] == '\0')
1784 CQ_RETURN(si);
1786 open[0] = c;
1787 open[1] = LPAREN;
1788 open[2] = '\0';
1789 temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */
1791 i = si;
1792 if (string[i] == '\0') /* don't increment i past EOS in loop */
1793 break;
1794 i++;
1795 continue;
1797 #endif
1798 else if ((skipquote || invert) && (member (c, delims) == 0))
1799 break;
1800 else
1801 ADVANCE_CHAR (string, slen, i);
1804 CQ_RETURN(i);
1807 #if defined (READLINE)
1808 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1809 an unclosed quoted string), or if the character at EINDEX is quoted
1810 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1811 single and double-quoted string parsing functions should not return an
1812 error if there are unclosed quotes or braces. The characters that this
1813 recognizes need to be the same as the contents of
1814 rl_completer_quote_characters. */
1817 char_is_quoted (string, eindex)
1818 char *string;
1819 int eindex;
1821 int i, pass_next, c;
1822 size_t slen;
1823 DECLARE_MBSTATE;
1825 slen = strlen (string);
1826 no_longjmp_on_fatal_error = 1;
1827 i = pass_next = 0;
1828 while (i <= eindex)
1830 c = string[i];
1832 if (pass_next)
1834 pass_next = 0;
1835 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1836 CQ_RETURN(1);
1837 ADVANCE_CHAR (string, slen, i);
1838 continue;
1840 else if (c == '\\')
1842 pass_next = 1;
1843 i++;
1844 continue;
1846 else if (c == '\'' || c == '"')
1848 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1849 : skip_double_quoted (string, slen, ++i);
1850 if (i > eindex)
1851 CQ_RETURN(1);
1852 /* no increment, the skip_xxx functions go one past end */
1854 else
1855 ADVANCE_CHAR (string, slen, i);
1858 CQ_RETURN(0);
1862 unclosed_pair (string, eindex, openstr)
1863 char *string;
1864 int eindex;
1865 char *openstr;
1867 int i, pass_next, openc, olen;
1868 size_t slen;
1869 DECLARE_MBSTATE;
1871 slen = strlen (string);
1872 olen = strlen (openstr);
1873 i = pass_next = openc = 0;
1874 while (i <= eindex)
1876 if (pass_next)
1878 pass_next = 0;
1879 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1880 return 0;
1881 ADVANCE_CHAR (string, slen, i);
1882 continue;
1884 else if (string[i] == '\\')
1886 pass_next = 1;
1887 i++;
1888 continue;
1890 else if (STREQN (string + i, openstr, olen))
1892 openc = 1 - openc;
1893 i += olen;
1895 else if (string[i] == '\'' || string[i] == '"')
1897 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1898 : skip_double_quoted (string, slen, i);
1899 if (i > eindex)
1900 return 0;
1902 else
1903 ADVANCE_CHAR (string, slen, i);
1905 return (openc);
1908 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1909 individual words. If DELIMS is NULL, the current value of $IFS is used
1910 to split the string, and the function follows the shell field splitting
1911 rules. SENTINEL is an index to look for. NWP, if non-NULL,
1912 gets the number of words in the returned list. CWP, if non-NULL, gets
1913 the index of the word containing SENTINEL. Non-whitespace chars in
1914 DELIMS delimit separate fields. */
1915 WORD_LIST *
1916 split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp)
1917 char *string;
1918 int slen;
1919 char *delims;
1920 int sentinel, flags;
1921 int *nwp, *cwp;
1923 int ts, te, i, nw, cw, ifs_split, dflags;
1924 char *token, *d, *d2;
1925 WORD_LIST *ret, *tl;
1927 if (string == 0 || *string == '\0')
1929 if (nwp)
1930 *nwp = 0;
1931 if (cwp)
1932 *cwp = 0;
1933 return ((WORD_LIST *)NULL);
1936 d = (delims == 0) ? ifs_value : delims;
1937 ifs_split = delims == 0;
1939 /* Make d2 the non-whitespace characters in delims */
1940 d2 = 0;
1941 if (delims)
1943 size_t slength;
1944 #if defined (HANDLE_MULTIBYTE)
1945 size_t mblength = 1;
1946 #endif
1947 DECLARE_MBSTATE;
1949 slength = strlen (delims);
1950 d2 = (char *)xmalloc (slength + 1);
1951 i = ts = 0;
1952 while (delims[i])
1954 #if defined (HANDLE_MULTIBYTE)
1955 mbstate_t state_bak;
1956 state_bak = state;
1957 mblength = MBRLEN (delims + i, slength, &state);
1958 if (MB_INVALIDCH (mblength))
1959 state = state_bak;
1960 else if (mblength > 1)
1962 memcpy (d2 + ts, delims + i, mblength);
1963 ts += mblength;
1964 i += mblength;
1965 slength -= mblength;
1966 continue;
1968 #endif
1969 if (whitespace (delims[i]) == 0)
1970 d2[ts++] = delims[i];
1972 i++;
1973 slength--;
1975 d2[ts] = '\0';
1978 ret = (WORD_LIST *)NULL;
1980 /* Remove sequences of whitespace characters at the start of the string, as
1981 long as those characters are delimiters. */
1982 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1984 if (string[i] == '\0')
1985 return (ret);
1987 ts = i;
1988 nw = 0;
1989 cw = -1;
1990 dflags = flags|SD_NOJMP;
1991 while (1)
1993 te = skip_to_delim (string, ts, d, dflags);
1995 /* If we have a non-whitespace delimiter character, use it to make a
1996 separate field. This is just about what $IFS splitting does and
1997 is closer to the behavior of the shell parser. */
1998 if (ts == te && d2 && member (string[ts], d2))
2000 te = ts + 1;
2001 /* If we're using IFS splitting, the non-whitespace delimiter char
2002 and any additional IFS whitespace delimits a field. */
2003 if (ifs_split)
2004 while (member (string[te], d) && spctabnl (string[te]))
2005 te++;
2006 else
2007 while (member (string[te], d2))
2008 te++;
2011 token = substring (string, ts, te);
2013 ret = add_string_to_list (token, ret);
2014 free (token);
2015 nw++;
2017 if (sentinel >= ts && sentinel <= te)
2018 cw = nw;
2020 /* If the cursor is at whitespace just before word start, set the
2021 sentinel word to the current word. */
2022 if (cwp && cw == -1 && sentinel == ts-1)
2023 cw = nw;
2025 /* If the cursor is at whitespace between two words, make a new, empty
2026 word, add it before (well, after, since the list is in reverse order)
2027 the word we just added, and set the current word to that one. */
2028 if (cwp && cw == -1 && sentinel < ts)
2030 tl = make_word_list (make_word (""), ret->next);
2031 ret->next = tl;
2032 cw = nw;
2033 nw++;
2036 if (string[te] == 0)
2037 break;
2039 i = te;
2040 while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
2041 i++;
2043 if (string[i])
2044 ts = i;
2045 else
2046 break;
2049 /* Special case for SENTINEL at the end of STRING. If we haven't found
2050 the word containing SENTINEL yet, and the index we're looking for is at
2051 the end of STRING (or past the end of the previously-found token,
2052 possible if the end of the line is composed solely of IFS whitespace)
2053 add an additional null argument and set the current word pointer to that. */
2054 if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te))
2056 if (whitespace (string[sentinel - 1]))
2058 token = "";
2059 ret = add_string_to_list (token, ret);
2060 nw++;
2062 cw = nw;
2065 if (nwp)
2066 *nwp = nw;
2067 if (cwp)
2068 *cwp = cw;
2070 return (REVERSE_LIST (ret, WORD_LIST *));
2072 #endif /* READLINE */
2074 #if 0
2075 /* UNUSED */
2076 /* Extract the name of the variable to bind to from the assignment string. */
2077 char *
2078 assignment_name (string)
2079 char *string;
2081 int offset;
2082 char *temp;
2084 offset = assignment (string, 0);
2085 if (offset == 0)
2086 return (char *)NULL;
2087 temp = substring (string, 0, offset);
2088 return (temp);
2090 #endif
2092 /* **************************************************************** */
2093 /* */
2094 /* Functions to convert strings to WORD_LISTs and vice versa */
2095 /* */
2096 /* **************************************************************** */
2098 /* Return a single string of all the words in LIST. SEP is the separator
2099 to put between individual elements of LIST in the output string. */
2100 char *
2101 string_list_internal (list, sep)
2102 WORD_LIST *list;
2103 char *sep;
2105 register WORD_LIST *t;
2106 char *result, *r;
2107 int word_len, sep_len, result_size;
2109 if (list == 0)
2110 return ((char *)NULL);
2112 /* Short-circuit quickly if we don't need to separate anything. */
2113 if (list->next == 0)
2114 return (savestring (list->word->word));
2116 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
2117 sep_len = STRLEN (sep);
2118 result_size = 0;
2120 for (t = list; t; t = t->next)
2122 if (t != list)
2123 result_size += sep_len;
2124 result_size += strlen (t->word->word);
2127 r = result = (char *)xmalloc (result_size + 1);
2129 for (t = list; t; t = t->next)
2131 if (t != list && sep_len)
2133 if (sep_len > 1)
2135 FASTCOPY (sep, r, sep_len);
2136 r += sep_len;
2138 else
2139 *r++ = sep[0];
2142 word_len = strlen (t->word->word);
2143 FASTCOPY (t->word->word, r, word_len);
2144 r += word_len;
2147 *r = '\0';
2148 return (result);
2151 /* Return a single string of all the words present in LIST, separating
2152 each word with a space. */
2153 char *
2154 string_list (list)
2155 WORD_LIST *list;
2157 return (string_list_internal (list, " "));
2160 /* An external interface that can be used by the rest of the shell to
2161 obtain a string containing the first character in $IFS. Handles all
2162 the multibyte complications. If LENP is non-null, it is set to the
2163 length of the returned string. */
2164 char *
2165 ifs_firstchar (lenp)
2166 int *lenp;
2168 char *ret;
2169 int len;
2171 ret = xmalloc (MB_LEN_MAX + 1);
2172 #if defined (HANDLE_MULTIBYTE)
2173 if (ifs_firstc_len == 1)
2175 ret[0] = ifs_firstc[0];
2176 ret[1] = '\0';
2177 len = ret[0] ? 1 : 0;
2179 else
2181 memcpy (ret, ifs_firstc, ifs_firstc_len);
2182 ret[len = ifs_firstc_len] = '\0';
2184 #else
2185 ret[0] = ifs_firstc;
2186 ret[1] = '\0';
2187 len = ret[0] ? 0 : 1;
2188 #endif
2190 if (lenp)
2191 *lenp = len;
2193 return ret;
2196 /* Return a single string of all the words present in LIST, obeying the
2197 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
2198 expansion [of $*] appears within a double quoted string, it expands
2199 to a single field with the value of each parameter separated by the
2200 first character of the IFS variable, or by a <space> if IFS is unset." */
2201 char *
2202 string_list_dollar_star (list)
2203 WORD_LIST *list;
2205 char *ret;
2206 #if defined (HANDLE_MULTIBYTE)
2207 # if defined (__GNUC__)
2208 char sep[MB_CUR_MAX + 1];
2209 # else
2210 char *sep = 0;
2211 # endif
2212 #else
2213 char sep[2];
2214 #endif
2216 #if defined (HANDLE_MULTIBYTE)
2217 # if !defined (__GNUC__)
2218 sep = (char *)xmalloc (MB_CUR_MAX + 1);
2219 # endif /* !__GNUC__ */
2220 if (ifs_firstc_len == 1)
2222 sep[0] = ifs_firstc[0];
2223 sep[1] = '\0';
2225 else
2227 memcpy (sep, ifs_firstc, ifs_firstc_len);
2228 sep[ifs_firstc_len] = '\0';
2230 #else
2231 sep[0] = ifs_firstc;
2232 sep[1] = '\0';
2233 #endif
2235 ret = string_list_internal (list, sep);
2236 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2237 free (sep);
2238 #endif
2239 return ret;
2242 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2243 is non-zero, the $@ appears within double quotes, and we should quote
2244 the list before converting it into a string. If IFS is unset, and the
2245 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2246 in the words in the list, because the default value of $IFS is
2247 <space><tab><newline>, IFS characters in the words in the list should
2248 also be split. If IFS is null, and the word is not quoted, we need
2249 to quote the words in the list to preserve the positional parameters
2250 exactly. */
2251 char *
2252 string_list_dollar_at (list, quoted)
2253 WORD_LIST *list;
2254 int quoted;
2256 char *ifs, *ret;
2257 #if defined (HANDLE_MULTIBYTE)
2258 # if defined (__GNUC__)
2259 char sep[MB_CUR_MAX + 1];
2260 # else
2261 char *sep = 0;
2262 # endif /* !__GNUC__ */
2263 #else
2264 char sep[2];
2265 #endif
2266 WORD_LIST *tlist;
2268 /* XXX this could just be ifs = ifs_value; */
2269 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
2271 #if defined (HANDLE_MULTIBYTE)
2272 # if !defined (__GNUC__)
2273 sep = (char *)xmalloc (MB_CUR_MAX + 1);
2274 # endif /* !__GNUC__ */
2275 if (ifs && *ifs)
2277 if (ifs_firstc_len == 1)
2279 sep[0] = ifs_firstc[0];
2280 sep[1] = '\0';
2282 else
2284 memcpy (sep, ifs_firstc, ifs_firstc_len);
2285 sep[ifs_firstc_len] = '\0';
2288 else
2290 sep[0] = ' ';
2291 sep[1] = '\0';
2293 #else
2294 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
2295 sep[1] = '\0';
2296 #endif
2298 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
2299 it now that quote_escapes quotes spaces */
2300 tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
2301 ? quote_list (list)
2302 : list_quote_escapes (list);
2304 ret = string_list_internal (tlist, sep);
2305 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2306 free (sep);
2307 #endif
2308 return ret;
2311 /* Turn the positional paramters into a string, understanding quoting and
2312 the various subtleties of using the first character of $IFS as the
2313 separator. Calls string_list_dollar_at, string_list_dollar_star, and
2314 string_list as appropriate. */
2315 char *
2316 string_list_pos_params (pchar, list, quoted)
2317 int pchar;
2318 WORD_LIST *list;
2319 int quoted;
2321 char *ret;
2322 WORD_LIST *tlist;
2324 if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
2326 tlist = quote_list (list);
2327 word_list_remove_quoted_nulls (tlist);
2328 ret = string_list_dollar_star (tlist);
2330 else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
2332 tlist = quote_list (list);
2333 word_list_remove_quoted_nulls (tlist);
2334 ret = string_list (tlist);
2336 else if (pchar == '*')
2338 /* Even when unquoted, string_list_dollar_star does the right thing
2339 making sure that the first character of $IFS is used as the
2340 separator. */
2341 ret = string_list_dollar_star (list);
2343 else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
2344 /* We use string_list_dollar_at, but only if the string is quoted, since
2345 that quotes the escapes if it's not, which we don't want. We could
2346 use string_list (the old code did), but that doesn't do the right
2347 thing if the first character of $IFS is not a space. We use
2348 string_list_dollar_star if the string is unquoted so we make sure that
2349 the elements of $@ are separated by the first character of $IFS for
2350 later splitting. */
2351 ret = string_list_dollar_at (list, quoted);
2352 else if (pchar == '@')
2353 ret = string_list_dollar_star (list);
2354 else
2355 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
2357 return ret;
2360 /* Return the list of words present in STRING. Separate the string into
2361 words at any of the characters found in SEPARATORS. If QUOTED is
2362 non-zero then word in the list will have its quoted flag set, otherwise
2363 the quoted flag is left as make_word () deemed fit.
2365 This obeys the P1003.2 word splitting semantics. If `separators' is
2366 exactly <space><tab><newline>, then the splitting algorithm is that of
2367 the Bourne shell, which treats any sequence of characters from `separators'
2368 as a delimiter. If IFS is unset, which results in `separators' being set
2369 to "", no splitting occurs. If separators has some other value, the
2370 following rules are applied (`IFS white space' means zero or more
2371 occurrences of <space>, <tab>, or <newline>, as long as those characters
2372 are in `separators'):
2374 1) IFS white space is ignored at the start and the end of the
2375 string.
2376 2) Each occurrence of a character in `separators' that is not
2377 IFS white space, along with any adjacent occurrences of
2378 IFS white space delimits a field.
2379 3) Any nonzero-length sequence of IFS white space delimits a field.
2382 /* BEWARE! list_string strips null arguments. Don't call it twice and
2383 expect to have "" preserved! */
2385 /* This performs word splitting and quoted null character removal on
2386 STRING. */
2387 #define issep(c) \
2388 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2389 : (c) == (separators)[0]) \
2390 : 0)
2392 WORD_LIST *
2393 list_string (string, separators, quoted)
2394 register char *string, *separators;
2395 int quoted;
2397 WORD_LIST *result;
2398 WORD_DESC *t;
2399 char *current_word, *s;
2400 int sindex, sh_style_split, whitesep, xflags;
2401 size_t slen;
2403 if (!string || !*string)
2404 return ((WORD_LIST *)NULL);
2406 sh_style_split = separators && separators[0] == ' ' &&
2407 separators[1] == '\t' &&
2408 separators[2] == '\n' &&
2409 separators[3] == '\0';
2410 for (xflags = 0, s = ifs_value; s && *s; s++)
2412 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2413 else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2416 slen = 0;
2417 /* Remove sequences of whitespace at the beginning of STRING, as
2418 long as those characters appear in IFS. Do not do this if
2419 STRING is quoted or if there are no separator characters. */
2420 if (!quoted || !separators || !*separators)
2422 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
2424 if (!*s)
2425 return ((WORD_LIST *)NULL);
2427 string = s;
2430 /* OK, now STRING points to a word that does not begin with white space.
2431 The splitting algorithm is:
2432 extract a word, stopping at a separator
2433 skip sequences of spc, tab, or nl as long as they are separators
2434 This obeys the field splitting rules in Posix.2. */
2435 slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
2436 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
2438 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2439 unless multibyte chars are possible. */
2440 current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
2441 if (current_word == 0)
2442 break;
2444 /* If we have a quoted empty string, add a quoted null argument. We
2445 want to preserve the quoted null character iff this is a quoted
2446 empty string; otherwise the quoted null characters are removed
2447 below. */
2448 if (QUOTED_NULL (current_word))
2450 t = alloc_word_desc ();
2451 t->word = make_quoted_char ('\0');
2452 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2453 result = make_word_list (t, result);
2455 else if (current_word[0] != '\0')
2457 /* If we have something, then add it regardless. However,
2458 perform quoted null character removal on the current word. */
2459 remove_quoted_nulls (current_word);
2460 result = add_string_to_list (current_word, result);
2461 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
2462 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2463 result->word->flags |= W_QUOTED;
2466 /* If we're not doing sequences of separators in the traditional
2467 Bourne shell style, then add a quoted null argument. */
2468 else if (!sh_style_split && !spctabnl (string[sindex]))
2470 t = alloc_word_desc ();
2471 t->word = make_quoted_char ('\0');
2472 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2473 result = make_word_list (t, result);
2476 free (current_word);
2478 /* Note whether or not the separator is IFS whitespace, used later. */
2479 whitesep = string[sindex] && spctabnl (string[sindex]);
2481 /* Move past the current separator character. */
2482 if (string[sindex])
2484 DECLARE_MBSTATE;
2485 ADVANCE_CHAR (string, slen, sindex);
2488 /* Now skip sequences of space, tab, or newline characters if they are
2489 in the list of separators. */
2490 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2491 sindex++;
2493 /* If the first separator was IFS whitespace and the current character
2494 is a non-whitespace IFS character, it should be part of the current
2495 field delimiter, not a separate delimiter that would result in an
2496 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2497 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2499 sindex++;
2500 /* An IFS character that is not IFS white space, along with any
2501 adjacent IFS white space, shall delimit a field. (SUSv3) */
2502 while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2503 sindex++;
2506 return (REVERSE_LIST (result, WORD_LIST *));
2509 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2510 ENDPTR is set to the first character after the word. This is used by
2511 the `read' builtin. This is never called with SEPARATORS != $IFS;
2512 it should be simplified.
2514 XXX - this function is very similar to list_string; they should be
2515 combined - XXX */
2516 char *
2517 get_word_from_string (stringp, separators, endptr)
2518 char **stringp, *separators, **endptr;
2520 register char *s;
2521 char *current_word;
2522 int sindex, sh_style_split, whitesep, xflags;
2523 size_t slen;
2525 if (!stringp || !*stringp || !**stringp)
2526 return ((char *)NULL);
2528 sh_style_split = separators && separators[0] == ' ' &&
2529 separators[1] == '\t' &&
2530 separators[2] == '\n' &&
2531 separators[3] == '\0';
2532 for (xflags = 0, s = ifs_value; s && *s; s++)
2534 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2535 if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2538 s = *stringp;
2539 slen = 0;
2541 /* Remove sequences of whitespace at the beginning of STRING, as
2542 long as those characters appear in IFS. */
2543 if (sh_style_split || !separators || !*separators)
2545 for (; *s && spctabnl (*s) && isifs (*s); s++);
2547 /* If the string is nothing but whitespace, update it and return. */
2548 if (!*s)
2550 *stringp = s;
2551 if (endptr)
2552 *endptr = s;
2553 return ((char *)NULL);
2557 /* OK, S points to a word that does not begin with white space.
2558 Now extract a word, stopping at a separator, save a pointer to
2559 the first character after the word, then skip sequences of spc,
2560 tab, or nl as long as they are separators.
2562 This obeys the field splitting rules in Posix.2. */
2563 sindex = 0;
2564 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2565 unless multibyte chars are possible. */
2566 slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2567 current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
2569 /* Set ENDPTR to the first character after the end of the word. */
2570 if (endptr)
2571 *endptr = s + sindex;
2573 /* Note whether or not the separator is IFS whitespace, used later. */
2574 whitesep = s[sindex] && spctabnl (s[sindex]);
2576 /* Move past the current separator character. */
2577 if (s[sindex])
2579 DECLARE_MBSTATE;
2580 ADVANCE_CHAR (s, slen, sindex);
2583 /* Now skip sequences of space, tab, or newline characters if they are
2584 in the list of separators. */
2585 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2586 sindex++;
2588 /* If the first separator was IFS whitespace and the current character is
2589 a non-whitespace IFS character, it should be part of the current field
2590 delimiter, not a separate delimiter that would result in an empty field.
2591 Look at POSIX.2, 3.6.5, (3)(b). */
2592 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2594 sindex++;
2595 /* An IFS character that is not IFS white space, along with any adjacent
2596 IFS white space, shall delimit a field. */
2597 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2598 sindex++;
2601 /* Update STRING to point to the next field. */
2602 *stringp = s + sindex;
2603 return (current_word);
2606 /* Remove IFS white space at the end of STRING. Start at the end
2607 of the string and walk backwards until the beginning of the string
2608 or we find a character that's not IFS white space and not CTLESC.
2609 Only let CTLESC escape a white space character if SAW_ESCAPE is
2610 non-zero. */
2611 char *
2612 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2613 char *string, *separators;
2614 int saw_escape;
2616 char *s;
2618 s = string + STRLEN (string) - 1;
2619 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2620 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2621 s--;
2622 *++s = '\0';
2623 return string;
2626 #if 0
2627 /* UNUSED */
2628 /* Split STRING into words at whitespace. Obeys shell-style quoting with
2629 backslashes, single and double quotes. */
2630 WORD_LIST *
2631 list_string_with_quotes (string)
2632 char *string;
2634 WORD_LIST *list;
2635 char *token, *s;
2636 size_t s_len;
2637 int c, i, tokstart, len;
2639 for (s = string; s && *s && spctabnl (*s); s++)
2641 if (s == 0 || *s == 0)
2642 return ((WORD_LIST *)NULL);
2644 s_len = strlen (s);
2645 tokstart = i = 0;
2646 list = (WORD_LIST *)NULL;
2647 while (1)
2649 c = s[i];
2650 if (c == '\\')
2652 i++;
2653 if (s[i])
2654 i++;
2656 else if (c == '\'')
2657 i = skip_single_quoted (s, s_len, ++i);
2658 else if (c == '"')
2659 i = skip_double_quoted (s, s_len, ++i);
2660 else if (c == 0 || spctabnl (c))
2662 /* We have found the end of a token. Make a word out of it and
2663 add it to the word list. */
2664 token = substring (s, tokstart, i);
2665 list = add_string_to_list (token, list);
2666 free (token);
2667 while (spctabnl (s[i]))
2668 i++;
2669 if (s[i])
2670 tokstart = i;
2671 else
2672 break;
2674 else
2675 i++; /* normal character */
2677 return (REVERSE_LIST (list, WORD_LIST *));
2679 #endif
2681 /********************************************************/
2682 /* */
2683 /* Functions to perform assignment statements */
2684 /* */
2685 /********************************************************/
2687 #if defined (ARRAY_VARS)
2688 static SHELL_VAR *
2689 do_compound_assignment (name, value, flags)
2690 char *name, *value;
2691 int flags;
2693 SHELL_VAR *v;
2694 int mklocal, mkassoc;
2695 WORD_LIST *list;
2697 mklocal = flags & ASS_MKLOCAL;
2698 mkassoc = flags & ASS_MKASSOC;
2700 if (mklocal && variable_context)
2702 v = find_variable (name);
2703 list = expand_compound_array_assignment (v, value, flags);
2704 if (mkassoc)
2705 v = make_local_assoc_variable (name);
2706 else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
2707 v = make_local_array_variable (name);
2708 assign_compound_array_list (v, list, flags);
2710 else
2711 v = assign_array_from_string (name, value, flags);
2713 return (v);
2715 #endif
2717 /* Given STRING, an assignment string, get the value of the right side
2718 of the `=', and bind it to the left side. If EXPAND is true, then
2719 perform parameter expansion, command substitution, and arithmetic
2720 expansion on the right-hand side. Perform tilde expansion in any
2721 case. Do not perform word splitting on the result of expansion. */
2722 static int
2723 do_assignment_internal (word, expand)
2724 const WORD_DESC *word;
2725 int expand;
2727 int offset, appendop, assign_list, aflags, retval;
2728 char *name, *value, *temp;
2729 SHELL_VAR *entry;
2730 #if defined (ARRAY_VARS)
2731 char *t;
2732 int ni;
2733 #endif
2734 const char *string;
2736 if (word == 0 || word->word == 0)
2737 return 0;
2739 appendop = assign_list = aflags = 0;
2740 string = word->word;
2741 offset = assignment (string, 0);
2742 name = savestring (string);
2743 value = (char *)NULL;
2745 if (name[offset] == '=')
2747 if (name[offset - 1] == '+')
2749 appendop = 1;
2750 name[offset - 1] = '\0';
2753 name[offset] = 0; /* might need this set later */
2754 temp = name + offset + 1;
2756 #if defined (ARRAY_VARS)
2757 if (expand && (word->flags & W_COMPASSIGN))
2759 assign_list = ni = 1;
2760 value = extract_array_assignment_list (temp, &ni);
2762 else
2763 #endif
2764 if (expand && temp[0])
2765 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2766 else
2767 value = savestring (temp);
2770 if (value == 0)
2772 value = (char *)xmalloc (1);
2773 value[0] = '\0';
2776 if (echo_command_at_execute)
2778 if (appendop)
2779 name[offset - 1] = '+';
2780 xtrace_print_assignment (name, value, assign_list, 1);
2781 if (appendop)
2782 name[offset - 1] = '\0';
2785 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
2787 if (appendop)
2788 aflags |= ASS_APPEND;
2790 #if defined (ARRAY_VARS)
2791 if (t = mbschr (name, '[')) /*]*/
2793 if (assign_list)
2795 report_error (_("%s: cannot assign list to array member"), name);
2796 ASSIGN_RETURN (0);
2798 entry = assign_array_element (name, value, aflags);
2799 if (entry == 0)
2800 ASSIGN_RETURN (0);
2802 else if (assign_list)
2804 if (word->flags & W_ASSIGNARG)
2805 aflags |= ASS_MKLOCAL;
2806 if (word->flags & W_ASSIGNASSOC)
2807 aflags |= ASS_MKASSOC;
2808 entry = do_compound_assignment (name, value, aflags);
2810 else
2811 #endif /* ARRAY_VARS */
2812 entry = bind_variable (name, value, aflags);
2814 stupidly_hack_special_variables (name);
2816 #if 1
2817 /* Return 1 if the assignment seems to have been performed correctly. */
2818 if (entry == 0 || readonly_p (entry))
2819 retval = 0; /* assignment failure */
2820 else if (noassign_p (entry))
2822 last_command_exit_value = EXECUTION_FAILURE;
2823 retval = 1; /* error status, but not assignment failure */
2825 else
2826 retval = 1;
2828 if (entry && retval != 0 && noassign_p (entry) == 0)
2829 VUNSETATTR (entry, att_invisible);
2831 ASSIGN_RETURN (retval);
2832 #else
2833 if (entry)
2834 VUNSETATTR (entry, att_invisible);
2836 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2837 #endif
2840 /* Perform the assignment statement in STRING, and expand the
2841 right side by doing tilde, command and parameter expansion. */
2843 do_assignment (string)
2844 char *string;
2846 WORD_DESC td;
2848 td.flags = W_ASSIGNMENT;
2849 td.word = string;
2851 return do_assignment_internal (&td, 1);
2855 do_word_assignment (word, flags)
2856 WORD_DESC *word;
2857 int flags;
2859 return do_assignment_internal (word, 1);
2862 /* Given STRING, an assignment string, get the value of the right side
2863 of the `=', and bind it to the left side. Do not perform any word
2864 expansions on the right hand side. */
2866 do_assignment_no_expand (string)
2867 char *string;
2869 WORD_DESC td;
2871 td.flags = W_ASSIGNMENT;
2872 td.word = string;
2874 return (do_assignment_internal (&td, 0));
2877 /***************************************************
2879 * Functions to manage the positional parameters *
2881 ***************************************************/
2883 /* Return the word list that corresponds to `$*'. */
2884 WORD_LIST *
2885 list_rest_of_args ()
2887 register WORD_LIST *list, *args;
2888 int i;
2890 /* Break out of the loop as soon as one of the dollar variables is null. */
2891 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2892 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2894 for (args = rest_of_args; args; args = args->next)
2895 list = make_word_list (make_bare_word (args->word->word), list);
2897 return (REVERSE_LIST (list, WORD_LIST *));
2901 number_of_args ()
2903 register WORD_LIST *list;
2904 int n;
2906 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2908 for (list = rest_of_args; list; list = list->next)
2909 n++;
2910 return n;
2913 /* Return the value of a positional parameter. This handles values > 10. */
2914 char *
2915 get_dollar_var_value (ind)
2916 intmax_t ind;
2918 char *temp;
2919 WORD_LIST *p;
2921 if (ind < 10)
2922 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2923 else /* We want something like ${11} */
2925 ind -= 10;
2926 for (p = rest_of_args; p && ind--; p = p->next)
2928 temp = p ? savestring (p->word->word) : (char *)NULL;
2930 return (temp);
2933 /* Make a single large string out of the dollar digit variables,
2934 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2935 case of "$*" with respect to IFS. */
2936 char *
2937 string_rest_of_args (dollar_star)
2938 int dollar_star;
2940 register WORD_LIST *list;
2941 char *string;
2943 list = list_rest_of_args ();
2944 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2945 dispose_words (list);
2946 return (string);
2949 /* Return a string containing the positional parameters from START to
2950 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2951 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2952 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2953 no quoting chars are added. */
2954 static char *
2955 pos_params (string, start, end, quoted)
2956 char *string;
2957 int start, end, quoted;
2959 WORD_LIST *save, *params, *h, *t;
2960 char *ret;
2961 int i;
2963 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2964 if (start == end)
2965 return ((char *)NULL);
2967 save = params = list_rest_of_args ();
2968 if (save == 0)
2969 return ((char *)NULL);
2971 if (start == 0) /* handle ${@:0[:x]} specially */
2973 t = make_word_list (make_word (dollar_vars[0]), params);
2974 save = params = t;
2977 for (i = start ? 1 : 0; params && i < start; i++)
2978 params = params->next;
2979 if (params == 0)
2980 return ((char *)NULL);
2981 for (h = t = params; params && i < end; i++)
2983 t = params;
2984 params = params->next;
2987 t->next = (WORD_LIST *)NULL;
2989 ret = string_list_pos_params (string[0], h, quoted);
2991 if (t != params)
2992 t->next = params;
2994 dispose_words (save);
2995 return (ret);
2998 /******************************************************************/
2999 /* */
3000 /* Functions to expand strings to strings or WORD_LISTs */
3001 /* */
3002 /******************************************************************/
3004 #if defined (PROCESS_SUBSTITUTION)
3005 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
3006 #else
3007 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
3008 #endif
3010 /* If there are any characters in STRING that require full expansion,
3011 then call FUNC to expand STRING; otherwise just perform quote
3012 removal if necessary. This returns a new string. */
3013 static char *
3014 expand_string_if_necessary (string, quoted, func)
3015 char *string;
3016 int quoted;
3017 EXPFUNC *func;
3019 WORD_LIST *list;
3020 size_t slen;
3021 int i, saw_quote;
3022 char *ret;
3023 DECLARE_MBSTATE;
3025 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
3026 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
3027 i = saw_quote = 0;
3028 while (string[i])
3030 if (EXP_CHAR (string[i]))
3031 break;
3032 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
3033 saw_quote = 1;
3034 ADVANCE_CHAR (string, slen, i);
3037 if (string[i])
3039 list = (*func) (string, quoted);
3040 if (list)
3042 ret = string_list (list);
3043 dispose_words (list);
3045 else
3046 ret = (char *)NULL;
3048 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3049 ret = string_quote_removal (string, quoted);
3050 else
3051 ret = savestring (string);
3053 return ret;
3056 static inline char *
3057 expand_string_to_string_internal (string, quoted, func)
3058 char *string;
3059 int quoted;
3060 EXPFUNC *func;
3062 WORD_LIST *list;
3063 char *ret;
3065 if (string == 0 || *string == '\0')
3066 return ((char *)NULL);
3068 list = (*func) (string, quoted);
3069 if (list)
3071 ret = string_list (list);
3072 dispose_words (list);
3074 else
3075 ret = (char *)NULL;
3077 return (ret);
3080 char *
3081 expand_string_to_string (string, quoted)
3082 char *string;
3083 int quoted;
3085 return (expand_string_to_string_internal (string, quoted, expand_string));
3088 char *
3089 expand_string_unsplit_to_string (string, quoted)
3090 char *string;
3091 int quoted;
3093 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
3096 char *
3097 expand_assignment_string_to_string (string, quoted)
3098 char *string;
3099 int quoted;
3101 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
3104 char *
3105 expand_arith_string (string, quoted)
3106 char *string;
3107 int quoted;
3109 return (expand_string_if_necessary (string, quoted, expand_string));
3112 #if defined (COND_COMMAND)
3113 /* Just remove backslashes in STRING. Returns a new string. */
3114 char *
3115 remove_backslashes (string)
3116 char *string;
3118 char *r, *ret, *s;
3120 r = ret = (char *)xmalloc (strlen (string) + 1);
3121 for (s = string; s && *s; )
3123 if (*s == '\\')
3124 s++;
3125 if (*s == 0)
3126 break;
3127 *r++ = *s++;
3129 *r = '\0';
3130 return ret;
3133 /* This needs better error handling. */
3134 /* Expand W for use as an argument to a unary or binary operator in a
3135 [[...]] expression. If SPECIAL is 1, this is the rhs argument
3136 to the != or == operator, and should be treated as a pattern. In
3137 this case, we quote the string specially for the globbing code. If
3138 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
3139 be quoted appropriately for regcomp/regexec. The caller is responsible
3140 for removing the backslashes if the unquoted word is needed later. */
3141 char *
3142 cond_expand_word (w, special)
3143 WORD_DESC *w;
3144 int special;
3146 char *r, *p;
3147 WORD_LIST *l;
3148 int qflags;
3150 if (w->word == 0 || w->word[0] == '\0')
3151 return ((char *)NULL);
3153 w->flags |= W_NOSPLIT2;
3154 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
3155 if (l)
3157 if (special == 0)
3159 dequote_list (l);
3160 r = string_list (l);
3162 else
3164 qflags = QGLOB_CVTNULL;
3165 if (special == 2)
3166 qflags |= QGLOB_REGEXP;
3167 p = string_list (l);
3168 r = quote_string_for_globbing (p, qflags);
3169 free (p);
3171 dispose_words (l);
3173 else
3174 r = (char *)NULL;
3176 return r;
3178 #endif
3180 /* Call expand_word_internal to expand W and handle error returns.
3181 A convenience function for functions that don't want to handle
3182 any errors or free any memory before aborting. */
3183 static WORD_LIST *
3184 call_expand_word_internal (w, q, i, c, e)
3185 WORD_DESC *w;
3186 int q, i, *c, *e;
3188 WORD_LIST *result;
3190 result = expand_word_internal (w, q, i, c, e);
3191 if (result == &expand_word_error || result == &expand_word_fatal)
3193 /* By convention, each time this error is returned, w->word has
3194 already been freed (it sometimes may not be in the fatal case,
3195 but that doesn't result in a memory leak because we're going
3196 to exit in most cases). */
3197 w->word = (char *)NULL;
3198 last_command_exit_value = EXECUTION_FAILURE;
3199 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
3200 /* NOTREACHED */
3202 else
3203 return (result);
3206 /* Perform parameter expansion, command substitution, and arithmetic
3207 expansion on STRING, as if it were a word. Leave the result quoted. */
3208 static WORD_LIST *
3209 expand_string_internal (string, quoted)
3210 char *string;
3211 int quoted;
3213 WORD_DESC td;
3214 WORD_LIST *tresult;
3216 if (string == 0 || *string == 0)
3217 return ((WORD_LIST *)NULL);
3219 td.flags = 0;
3220 td.word = savestring (string);
3222 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3224 FREE (td.word);
3225 return (tresult);
3228 /* Expand STRING by performing parameter expansion, command substitution,
3229 and arithmetic expansion. Dequote the resulting WORD_LIST before
3230 returning it, but do not perform word splitting. The call to
3231 remove_quoted_nulls () is in here because word splitting normally
3232 takes care of quote removal. */
3233 WORD_LIST *
3234 expand_string_unsplit (string, quoted)
3235 char *string;
3236 int quoted;
3238 WORD_LIST *value;
3240 if (string == 0 || *string == '\0')
3241 return ((WORD_LIST *)NULL);
3243 expand_no_split_dollar_star = 1;
3244 value = expand_string_internal (string, quoted);
3245 expand_no_split_dollar_star = 0;
3247 if (value)
3249 if (value->word)
3251 remove_quoted_nulls (value->word->word);
3252 value->word->flags &= ~W_HASQUOTEDNULL;
3254 dequote_list (value);
3256 return (value);
3259 /* Expand the rhs of an assignment statement */
3260 WORD_LIST *
3261 expand_string_assignment (string, quoted)
3262 char *string;
3263 int quoted;
3265 WORD_DESC td;
3266 WORD_LIST *value;
3268 if (string == 0 || *string == '\0')
3269 return ((WORD_LIST *)NULL);
3271 expand_no_split_dollar_star = 1;
3273 td.flags = W_ASSIGNRHS;
3274 td.word = savestring (string);
3275 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3276 FREE (td.word);
3278 expand_no_split_dollar_star = 0;
3280 if (value)
3282 if (value->word)
3284 remove_quoted_nulls (value->word->word);
3285 value->word->flags &= ~W_HASQUOTEDNULL;
3287 dequote_list (value);
3289 return (value);
3293 /* Expand one of the PS? prompt strings. This is a sort of combination of
3294 expand_string_unsplit and expand_string_internal, but returns the
3295 passed string when an error occurs. Might want to trap other calls
3296 to jump_to_top_level here so we don't endlessly loop. */
3297 WORD_LIST *
3298 expand_prompt_string (string, quoted, wflags)
3299 char *string;
3300 int quoted;
3301 int wflags;
3303 WORD_LIST *value;
3304 WORD_DESC td;
3306 if (string == 0 || *string == 0)
3307 return ((WORD_LIST *)NULL);
3309 td.flags = wflags;
3310 td.word = savestring (string);
3312 no_longjmp_on_fatal_error = 1;
3313 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3314 no_longjmp_on_fatal_error = 0;
3316 if (value == &expand_word_error || value == &expand_word_fatal)
3318 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
3319 return value;
3321 FREE (td.word);
3322 if (value)
3324 if (value->word)
3326 remove_quoted_nulls (value->word->word);
3327 value->word->flags &= ~W_HASQUOTEDNULL;
3329 dequote_list (value);
3331 return (value);
3334 /* Expand STRING just as if you were expanding a word, but do not dequote
3335 the resultant WORD_LIST. This is called only from within this file,
3336 and is used to correctly preserve quoted characters when expanding
3337 things like ${1+"$@"}. This does parameter expansion, command
3338 substitution, arithmetic expansion, and word splitting. */
3339 static WORD_LIST *
3340 expand_string_leave_quoted (string, quoted)
3341 char *string;
3342 int quoted;
3344 WORD_LIST *tlist;
3345 WORD_LIST *tresult;
3347 if (string == 0 || *string == '\0')
3348 return ((WORD_LIST *)NULL);
3350 tlist = expand_string_internal (string, quoted);
3352 if (tlist)
3354 tresult = word_list_split (tlist);
3355 dispose_words (tlist);
3356 return (tresult);
3358 return ((WORD_LIST *)NULL);
3361 /* This does not perform word splitting or dequote the WORD_LIST
3362 it returns. */
3363 static WORD_LIST *
3364 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
3365 char *string;
3366 int quoted, *dollar_at_p, *has_dollar_at;
3368 WORD_DESC td;
3369 WORD_LIST *tresult;
3371 if (string == 0 || *string == '\0')
3372 return (WORD_LIST *)NULL;
3374 td.flags = 0;
3375 td.word = string;
3376 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
3377 return (tresult);
3380 /* Expand STRING just as if you were expanding a word. This also returns
3381 a list of words. Note that filename globbing is *NOT* done for word
3382 or string expansion, just when the shell is expanding a command. This
3383 does parameter expansion, command substitution, arithmetic expansion,
3384 and word splitting. Dequote the resultant WORD_LIST before returning. */
3385 WORD_LIST *
3386 expand_string (string, quoted)
3387 char *string;
3388 int quoted;
3390 WORD_LIST *result;
3392 if (string == 0 || *string == '\0')
3393 return ((WORD_LIST *)NULL);
3395 result = expand_string_leave_quoted (string, quoted);
3396 return (result ? dequote_list (result) : result);
3399 /***************************************************
3401 * Functions to handle quoting chars *
3403 ***************************************************/
3405 /* Conventions:
3407 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
3408 The parser passes CTLNUL as CTLESC CTLNUL. */
3410 /* Quote escape characters in string s, but no other characters. This is
3411 used to protect CTLESC and CTLNUL in variable values from the rest of
3412 the word expansion process after the variable is expanded (word splitting
3413 and filename generation). If IFS is null, we quote spaces as well, just
3414 in case we split on spaces later (in the case of unquoted $@, we will
3415 eventually attempt to split the entire word on spaces). Corresponding
3416 code exists in dequote_escapes. Even if we don't end up splitting on
3417 spaces, quoting spaces is not a problem. This should never be called on
3418 a string that is quoted with single or double quotes or part of a here
3419 document (effectively double-quoted). */
3420 char *
3421 quote_escapes (string)
3422 char *string;
3424 register char *s, *t;
3425 size_t slen;
3426 char *result, *send;
3427 int quote_spaces, skip_ctlesc, skip_ctlnul;
3428 DECLARE_MBSTATE;
3430 slen = strlen (string);
3431 send = string + slen;
3433 quote_spaces = (ifs_value && *ifs_value == 0);
3435 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
3436 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
3438 t = result = (char *)xmalloc ((slen * 2) + 1);
3439 s = string;
3441 while (*s)
3443 if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
3444 *t++ = CTLESC;
3445 COPY_CHAR_P (t, s, send);
3447 *t = '\0';
3448 return (result);
3451 static WORD_LIST *
3452 list_quote_escapes (list)
3453 WORD_LIST *list;
3455 register WORD_LIST *w;
3456 char *t;
3458 for (w = list; w; w = w->next)
3460 t = w->word->word;
3461 w->word->word = quote_escapes (t);
3462 free (t);
3464 return list;
3467 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
3469 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
3470 This is necessary to make unquoted CTLESC and CTLNUL characters in the
3471 data stream pass through properly.
3473 We need to remove doubled CTLESC characters inside quoted strings before
3474 quoting the entire string, so we do not double the number of CTLESC
3475 characters.
3477 Also used by parts of the pattern substitution code. */
3478 char *
3479 dequote_escapes (string)
3480 char *string;
3482 register char *s, *t, *s1;
3483 size_t slen;
3484 char *result, *send;
3485 int quote_spaces;
3486 DECLARE_MBSTATE;
3488 if (string == 0)
3489 return string;
3491 slen = strlen (string);
3492 send = string + slen;
3494 t = result = (char *)xmalloc (slen + 1);
3496 if (strchr (string, CTLESC) == 0)
3497 return (strcpy (result, string));
3499 quote_spaces = (ifs_value && *ifs_value == 0);
3501 s = string;
3502 while (*s)
3504 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
3506 s++;
3507 if (*s == '\0')
3508 break;
3510 COPY_CHAR_P (t, s, send);
3512 *t = '\0';
3513 return result;
3516 /* Return a new string with the quoted representation of character C.
3517 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3518 set in any resultant WORD_DESC where this value is the word. */
3519 static char *
3520 make_quoted_char (c)
3521 int c;
3523 char *temp;
3525 temp = (char *)xmalloc (3);
3526 if (c == 0)
3528 temp[0] = CTLNUL;
3529 temp[1] = '\0';
3531 else
3533 temp[0] = CTLESC;
3534 temp[1] = c;
3535 temp[2] = '\0';
3537 return (temp);
3540 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
3541 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3542 this value is the word. */
3543 char *
3544 quote_string (string)
3545 char *string;
3547 register char *t;
3548 size_t slen;
3549 char *result, *send;
3551 if (*string == 0)
3553 result = (char *)xmalloc (2);
3554 result[0] = CTLNUL;
3555 result[1] = '\0';
3557 else
3559 DECLARE_MBSTATE;
3561 slen = strlen (string);
3562 send = string + slen;
3564 result = (char *)xmalloc ((slen * 2) + 1);
3566 for (t = result; string < send; )
3568 *t++ = CTLESC;
3569 COPY_CHAR_P (t, string, send);
3571 *t = '\0';
3573 return (result);
3576 /* De-quote quoted characters in STRING. */
3577 char *
3578 dequote_string (string)
3579 char *string;
3581 register char *s, *t;
3582 size_t slen;
3583 char *result, *send;
3584 DECLARE_MBSTATE;
3586 slen = strlen (string);
3588 t = result = (char *)xmalloc (slen + 1);
3590 if (QUOTED_NULL (string))
3592 result[0] = '\0';
3593 return (result);
3596 /* If no character in the string can be quoted, don't bother examining
3597 each character. Just return a copy of the string passed to us. */
3598 if (strchr (string, CTLESC) == NULL)
3599 return (strcpy (result, string));
3601 send = string + slen;
3602 s = string;
3603 while (*s)
3605 if (*s == CTLESC)
3607 s++;
3608 if (*s == '\0')
3609 break;
3611 COPY_CHAR_P (t, s, send);
3614 *t = '\0';
3615 return (result);
3618 /* Quote the entire WORD_LIST list. */
3619 static WORD_LIST *
3620 quote_list (list)
3621 WORD_LIST *list;
3623 register WORD_LIST *w;
3624 char *t;
3626 for (w = list; w; w = w->next)
3628 t = w->word->word;
3629 w->word->word = quote_string (t);
3630 if (*t == 0)
3631 w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
3632 w->word->flags |= W_QUOTED;
3633 free (t);
3635 return list;
3638 /* De-quote quoted characters in each word in LIST. */
3639 WORD_LIST *
3640 dequote_list (list)
3641 WORD_LIST *list;
3643 register char *s;
3644 register WORD_LIST *tlist;
3646 for (tlist = list; tlist; tlist = tlist->next)
3648 s = dequote_string (tlist->word->word);
3649 if (QUOTED_NULL (tlist->word->word))
3650 tlist->word->flags &= ~W_HASQUOTEDNULL;
3651 free (tlist->word->word);
3652 tlist->word->word = s;
3654 return list;
3657 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3658 string. */
3659 char *
3660 remove_quoted_escapes (string)
3661 char *string;
3663 char *t;
3665 if (string)
3667 t = dequote_escapes (string);
3668 strcpy (string, t);
3669 free (t);
3672 return (string);
3675 /* Perform quoted null character removal on STRING. We don't allow any
3676 quoted null characters in the middle or at the ends of strings because
3677 of how expand_word_internal works. remove_quoted_nulls () turns
3678 STRING into an empty string iff it only consists of a quoted null,
3679 and removes all unquoted CTLNUL characters. */
3680 char *
3681 remove_quoted_nulls (string)
3682 char *string;
3684 register size_t slen;
3685 register int i, j, prev_i;
3686 DECLARE_MBSTATE;
3688 if (strchr (string, CTLNUL) == 0) /* XXX */
3689 return string; /* XXX */
3691 slen = strlen (string);
3692 i = j = 0;
3694 while (i < slen)
3696 if (string[i] == CTLESC)
3698 /* Old code had j++, but we cannot assume that i == j at this
3699 point -- what if a CTLNUL has already been removed from the
3700 string? We don't want to drop the CTLESC or recopy characters
3701 that we've already copied down. */
3702 i++; string[j++] = CTLESC;
3703 if (i == slen)
3704 break;
3706 else if (string[i] == CTLNUL)
3707 i++;
3709 prev_i = i;
3710 ADVANCE_CHAR (string, slen, i);
3711 if (j < prev_i)
3713 do string[j++] = string[prev_i++]; while (prev_i < i);
3715 else
3716 j = i;
3718 string[j] = '\0';
3720 return (string);
3723 /* Perform quoted null character removal on each element of LIST.
3724 This modifies LIST. */
3725 void
3726 word_list_remove_quoted_nulls (list)
3727 WORD_LIST *list;
3729 register WORD_LIST *t;
3731 for (t = list; t; t = t->next)
3733 remove_quoted_nulls (t->word->word);
3734 t->word->flags &= ~W_HASQUOTEDNULL;
3738 /* **************************************************************** */
3739 /* */
3740 /* Functions for Matching and Removing Patterns */
3741 /* */
3742 /* **************************************************************** */
3744 #if defined (HANDLE_MULTIBYTE)
3745 #if 0 /* Currently unused */
3746 static unsigned char *
3747 mb_getcharlens (string, len)
3748 char *string;
3749 int len;
3751 int i, offset, last;
3752 unsigned char *ret;
3753 char *p;
3754 DECLARE_MBSTATE;
3756 i = offset = 0;
3757 last = 0;
3758 ret = (unsigned char *)xmalloc (len);
3759 memset (ret, 0, len);
3760 while (string[last])
3762 ADVANCE_CHAR (string, len, offset);
3763 ret[last] = offset - last;
3764 last = offset;
3766 return ret;
3768 #endif
3769 #endif
3771 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3772 can have one of 4 values:
3773 RP_LONG_LEFT remove longest matching portion at start of PARAM
3774 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3775 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3776 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3779 #define RP_LONG_LEFT 1
3780 #define RP_SHORT_LEFT 2
3781 #define RP_LONG_RIGHT 3
3782 #define RP_SHORT_RIGHT 4
3784 /* Returns its first argument if nothing matched; new memory otherwise */
3785 static char *
3786 remove_upattern (param, pattern, op)
3787 char *param, *pattern;
3788 int op;
3790 register int len;
3791 register char *end;
3792 register char *p, *ret, c;
3794 len = STRLEN (param);
3795 end = param + len;
3797 switch (op)
3799 case RP_LONG_LEFT: /* remove longest match at start */
3800 for (p = end; p >= param; p--)
3802 c = *p; *p = '\0';
3803 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3805 *p = c;
3806 return (savestring (p));
3808 *p = c;
3811 break;
3813 case RP_SHORT_LEFT: /* remove shortest match at start */
3814 for (p = param; p <= end; p++)
3816 c = *p; *p = '\0';
3817 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3819 *p = c;
3820 return (savestring (p));
3822 *p = c;
3824 break;
3826 case RP_LONG_RIGHT: /* remove longest match at end */
3827 for (p = param; p <= end; p++)
3829 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3831 c = *p; *p = '\0';
3832 ret = savestring (param);
3833 *p = c;
3834 return (ret);
3837 break;
3839 case RP_SHORT_RIGHT: /* remove shortest match at end */
3840 for (p = end; p >= param; p--)
3842 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3844 c = *p; *p = '\0';
3845 ret = savestring (param);
3846 *p = c;
3847 return (ret);
3850 break;
3853 return (param); /* no match, return original string */
3856 #if defined (HANDLE_MULTIBYTE)
3857 /* Returns its first argument if nothing matched; new memory otherwise */
3858 static wchar_t *
3859 remove_wpattern (wparam, wstrlen, wpattern, op)
3860 wchar_t *wparam;
3861 size_t wstrlen;
3862 wchar_t *wpattern;
3863 int op;
3865 wchar_t wc, *ret;
3866 int n;
3868 switch (op)
3870 case RP_LONG_LEFT: /* remove longest match at start */
3871 for (n = wstrlen; n >= 0; n--)
3873 wc = wparam[n]; wparam[n] = L'\0';
3874 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3876 wparam[n] = wc;
3877 return (wcsdup (wparam + n));
3879 wparam[n] = wc;
3881 break;
3883 case RP_SHORT_LEFT: /* remove shortest match at start */
3884 for (n = 0; n <= wstrlen; n++)
3886 wc = wparam[n]; wparam[n] = L'\0';
3887 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3889 wparam[n] = wc;
3890 return (wcsdup (wparam + n));
3892 wparam[n] = wc;
3894 break;
3896 case RP_LONG_RIGHT: /* remove longest match at end */
3897 for (n = 0; n <= wstrlen; n++)
3899 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3901 wc = wparam[n]; wparam[n] = L'\0';
3902 ret = wcsdup (wparam);
3903 wparam[n] = wc;
3904 return (ret);
3907 break;
3909 case RP_SHORT_RIGHT: /* remove shortest match at end */
3910 for (n = wstrlen; n >= 0; n--)
3912 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3914 wc = wparam[n]; wparam[n] = L'\0';
3915 ret = wcsdup (wparam);
3916 wparam[n] = wc;
3917 return (ret);
3920 break;
3923 return (wparam); /* no match, return original string */
3925 #endif /* HANDLE_MULTIBYTE */
3927 static char *
3928 remove_pattern (param, pattern, op)
3929 char *param, *pattern;
3930 int op;
3932 char *xret;
3934 if (param == NULL)
3935 return (param);
3936 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3937 return (savestring (param));
3939 #if defined (HANDLE_MULTIBYTE)
3940 if (MB_CUR_MAX > 1)
3942 wchar_t *ret, *oret;
3943 size_t n;
3944 wchar_t *wparam, *wpattern;
3945 mbstate_t ps;
3947 n = xdupmbstowcs (&wpattern, NULL, pattern);
3948 if (n == (size_t)-1)
3950 xret = remove_upattern (param, pattern, op);
3951 return ((xret == param) ? savestring (param) : xret);
3953 n = xdupmbstowcs (&wparam, NULL, param);
3954 if (n == (size_t)-1)
3956 free (wpattern);
3957 xret = remove_upattern (param, pattern, op);
3958 return ((xret == param) ? savestring (param) : xret);
3960 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3961 /* Don't bother to convert wparam back to multibyte string if nothing
3962 matched; just return copy of original string */
3963 if (ret == wparam)
3965 free (wparam);
3966 free (wpattern);
3967 return (savestring (param));
3970 free (wparam);
3971 free (wpattern);
3973 n = strlen (param);
3974 xret = (char *)xmalloc (n + 1);
3975 memset (&ps, '\0', sizeof (mbstate_t));
3976 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3977 xret[n] = '\0'; /* just to make sure */
3978 free (oret);
3979 return xret;
3981 else
3982 #endif
3984 xret = remove_upattern (param, pattern, op);
3985 return ((xret == param) ? savestring (param) : xret);
3989 /* Match PAT anywhere in STRING and return the match boundaries.
3990 This returns 1 in case of a successful match, 0 otherwise. SP
3991 and EP are pointers into the string where the match begins and
3992 ends, respectively. MTYPE controls what kind of match is attempted.
3993 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3994 of the string, respectively. The longest match is returned. */
3995 static int
3996 match_upattern (string, pat, mtype, sp, ep)
3997 char *string, *pat;
3998 int mtype;
3999 char **sp, **ep;
4001 int c, len, mlen;
4002 register char *p, *p1, *npat;
4003 char *end;
4004 int n1;
4006 /* If the pattern doesn't match anywhere in the string, go ahead and
4007 short-circuit right away. A minor optimization, saves a bunch of
4008 unnecessary calls to strmatch (up to N calls for a string of N
4009 characters) if the match is unsuccessful. To preserve the semantics
4010 of the substring matches below, we make sure that the pattern has
4011 `*' as first and last character, making a new pattern if necessary. */
4012 /* XXX - check this later if I ever implement `**' with special meaning,
4013 since this will potentially result in `**' at the beginning or end */
4014 len = STRLEN (pat);
4015 if (pat[0] != '*' || (pat[0] == '*' && pat[1] == LPAREN && extended_glob) || pat[len - 1] != '*')
4017 p = npat = (char *)xmalloc (len + 3);
4018 p1 = pat;
4019 if (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob))
4020 *p++ = '*';
4021 while (*p1)
4022 *p++ = *p1++;
4023 if (p1[-1] != '*' || p[-2] == '\\')
4024 *p++ = '*';
4025 *p = '\0';
4027 else
4028 npat = pat;
4029 c = strmatch (npat, string, FNMATCH_EXTFLAG);
4030 if (npat != pat)
4031 free (npat);
4032 if (c == FNM_NOMATCH)
4033 return (0);
4035 len = STRLEN (string);
4036 end = string + len;
4038 mlen = umatchlen (pat, len);
4040 switch (mtype)
4042 case MATCH_ANY:
4043 for (p = string; p <= end; p++)
4045 if (match_pattern_char (pat, p))
4047 #if 0
4048 for (p1 = end; p1 >= p; p1--)
4049 #else
4050 p1 = (mlen == -1) ? end : p + mlen;
4051 /* p1 - p = length of portion of string to be considered
4052 p = current position in string
4053 mlen = number of characters consumed by match (-1 for entire string)
4054 end = end of string
4055 we want to break immediately if the potential match len
4056 is greater than the number of characters remaining in the
4057 string
4059 if (p1 > end)
4060 break;
4061 for ( ; p1 >= p; p1--)
4062 #endif
4064 c = *p1; *p1 = '\0';
4065 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
4067 *p1 = c;
4068 *sp = p;
4069 *ep = p1;
4070 return 1;
4072 *p1 = c;
4073 #if 1
4074 /* If MLEN != -1, we have a fixed length pattern. */
4075 if (mlen != -1)
4076 break;
4077 #endif
4082 return (0);
4084 case MATCH_BEG:
4085 if (match_pattern_char (pat, string) == 0)
4086 return (0);
4088 #if 0
4089 for (p = end; p >= string; p--)
4090 #else
4091 for (p = (mlen == -1) ? end : string + mlen; p >= string; p--)
4092 #endif
4094 c = *p; *p = '\0';
4095 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
4097 *p = c;
4098 *sp = string;
4099 *ep = p;
4100 return 1;
4102 *p = c;
4103 #if 1
4104 /* If MLEN != -1, we have a fixed length pattern. */
4105 if (mlen != -1)
4106 break;
4107 #endif
4110 return (0);
4112 case MATCH_END:
4113 #if 0
4114 for (p = string; p <= end; p++)
4115 #else
4116 for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++)
4117 #endif
4119 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
4121 *sp = p;
4122 *ep = end;
4123 return 1;
4125 #if 1
4126 /* If MLEN != -1, we have a fixed length pattern. */
4127 if (mlen != -1)
4128 break;
4129 #endif
4132 return (0);
4135 return (0);
4138 #if defined (HANDLE_MULTIBYTE)
4139 /* Match WPAT anywhere in WSTRING and return the match boundaries.
4140 This returns 1 in case of a successful match, 0 otherwise. Wide
4141 character version. */
4142 static int
4143 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
4144 wchar_t *wstring;
4145 char **indices;
4146 size_t wstrlen;
4147 wchar_t *wpat;
4148 int mtype;
4149 char **sp, **ep;
4151 wchar_t wc, *wp, *nwpat, *wp1;
4152 size_t len;
4153 int mlen;
4154 int n, n1, n2, simple;
4156 simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
4157 #if defined (EXTENDED_GLOB)
4158 if (extended_glob)
4159 simple |= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
4160 #endif
4162 /* If the pattern doesn't match anywhere in the string, go ahead and
4163 short-circuit right away. A minor optimization, saves a bunch of
4164 unnecessary calls to strmatch (up to N calls for a string of N
4165 characters) if the match is unsuccessful. To preserve the semantics
4166 of the substring matches below, we make sure that the pattern has
4167 `*' as first and last character, making a new pattern if necessary. */
4168 len = wcslen (wpat);
4169 if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == WLPAREN && extended_glob) || wpat[len - 1] != L'*')
4171 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
4172 wp1 = wpat;
4173 if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == WLPAREN && extended_glob))
4174 *wp++ = L'*';
4175 while (*wp1 != L'\0')
4176 *wp++ = *wp1++;
4177 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
4178 *wp++ = L'*';
4179 *wp = '\0';
4181 else
4182 nwpat = wpat;
4183 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
4184 if (nwpat != wpat)
4185 free (nwpat);
4186 if (len == FNM_NOMATCH)
4187 return (0);
4189 mlen = wmatchlen (wpat, wstrlen);
4191 /* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
4192 switch (mtype)
4194 case MATCH_ANY:
4195 for (n = 0; n <= wstrlen; n++)
4197 #if 1
4198 n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n);
4199 #else
4200 n2 = match_pattern_wchar (wpat, wstring + n);
4201 #endif
4202 if (n2)
4204 #if 0
4205 for (n1 = wstrlen; n1 >= n; n1--)
4206 #else
4207 n1 = (mlen == -1) ? wstrlen : n + mlen;
4208 if (n1 > wstrlen)
4209 break;
4211 for ( ; n1 >= n; n1--)
4212 #endif
4214 wc = wstring[n1]; wstring[n1] = L'\0';
4215 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
4217 wstring[n1] = wc;
4218 *sp = indices[n];
4219 *ep = indices[n1];
4220 return 1;
4222 wstring[n1] = wc;
4223 #if 1
4224 /* If MLEN != -1, we have a fixed length pattern. */
4225 if (mlen != -1)
4226 break;
4227 #endif
4232 return (0);
4234 case MATCH_BEG:
4235 if (match_pattern_wchar (wpat, wstring) == 0)
4236 return (0);
4238 #if 0
4239 for (n = wstrlen; n >= 0; n--)
4240 #else
4241 for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--)
4242 #endif
4244 wc = wstring[n]; wstring[n] = L'\0';
4245 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
4247 wstring[n] = wc;
4248 *sp = indices[0];
4249 *ep = indices[n];
4250 return 1;
4252 wstring[n] = wc;
4253 #if 1
4254 /* If MLEN != -1, we have a fixed length pattern. */
4255 if (mlen != -1)
4256 break;
4257 #endif
4260 return (0);
4262 case MATCH_END:
4263 #if 0
4264 for (n = 0; n <= wstrlen; n++)
4265 #else
4266 for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++)
4267 #endif
4269 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
4271 *sp = indices[n];
4272 *ep = indices[wstrlen];
4273 return 1;
4275 #if 1
4276 /* If MLEN != -1, we have a fixed length pattern. */
4277 if (mlen != -1)
4278 break;
4279 #endif
4282 return (0);
4285 return (0);
4287 #endif /* HANDLE_MULTIBYTE */
4289 static int
4290 match_pattern (string, pat, mtype, sp, ep)
4291 char *string, *pat;
4292 int mtype;
4293 char **sp, **ep;
4295 #if defined (HANDLE_MULTIBYTE)
4296 int ret;
4297 size_t n;
4298 wchar_t *wstring, *wpat;
4299 char **indices;
4300 size_t slen, plen, mslen, mplen;
4301 #endif
4303 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
4304 return (0);
4306 #if defined (HANDLE_MULTIBYTE)
4307 if (MB_CUR_MAX > 1)
4309 #if 0
4310 slen = STRLEN (string);
4311 mslen = MBSLEN (string);
4312 plen = STRLEN (pat);
4313 mplen = MBSLEN (pat);
4314 if (slen == mslen && plen == mplen)
4315 #else
4316 if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0)
4317 #endif
4318 return (match_upattern (string, pat, mtype, sp, ep));
4320 n = xdupmbstowcs (&wpat, NULL, pat);
4321 if (n == (size_t)-1)
4322 return (match_upattern (string, pat, mtype, sp, ep));
4323 n = xdupmbstowcs (&wstring, &indices, string);
4324 if (n == (size_t)-1)
4326 free (wpat);
4327 return (match_upattern (string, pat, mtype, sp, ep));
4329 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
4331 free (wpat);
4332 free (wstring);
4333 free (indices);
4335 return (ret);
4337 else
4338 #endif
4339 return (match_upattern (string, pat, mtype, sp, ep));
4342 static int
4343 getpatspec (c, value)
4344 int c;
4345 char *value;
4347 if (c == '#')
4348 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
4349 else /* c == '%' */
4350 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
4353 /* Posix.2 says that the WORD should be run through tilde expansion,
4354 parameter expansion, command substitution and arithmetic expansion.
4355 This leaves the result quoted, so quote_string_for_globbing () has
4356 to be called to fix it up for strmatch (). If QUOTED is non-zero,
4357 it means that the entire expression was enclosed in double quotes.
4358 This means that quoting characters in the pattern do not make any
4359 special pattern characters quoted. For example, the `*' in the
4360 following retains its special meaning: "${foo#'*'}". */
4361 static char *
4362 getpattern (value, quoted, expandpat)
4363 char *value;
4364 int quoted, expandpat;
4366 char *pat, *tword;
4367 WORD_LIST *l;
4368 #if 0
4369 int i;
4370 #endif
4371 /* There is a problem here: how to handle single or double quotes in the
4372 pattern string when the whole expression is between double quotes?
4373 POSIX.2 says that enclosing double quotes do not cause the pattern to
4374 be quoted, but does that leave us a problem with @ and array[@] and their
4375 expansions inside a pattern? */
4376 #if 0
4377 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
4379 i = 0;
4380 pat = string_extract_double_quoted (tword, &i, 1);
4381 free (tword);
4382 tword = pat;
4384 #endif
4386 /* expand_string_for_rhs () leaves WORD quoted and does not perform
4387 word splitting. */
4388 l = *value ? expand_string_for_rhs (value,
4389 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
4390 (int *)NULL, (int *)NULL)
4391 : (WORD_LIST *)0;
4392 pat = string_list (l);
4393 dispose_words (l);
4394 if (pat)
4396 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
4397 free (pat);
4398 pat = tword;
4400 return (pat);
4403 #if 0
4404 /* Handle removing a pattern from a string as a result of ${name%[%]value}
4405 or ${name#[#]value}. */
4406 static char *
4407 variable_remove_pattern (value, pattern, patspec, quoted)
4408 char *value, *pattern;
4409 int patspec, quoted;
4411 char *tword;
4413 tword = remove_pattern (value, pattern, patspec);
4415 return (tword);
4417 #endif
4419 static char *
4420 list_remove_pattern (list, pattern, patspec, itype, quoted)
4421 WORD_LIST *list;
4422 char *pattern;
4423 int patspec, itype, quoted;
4425 WORD_LIST *new, *l;
4426 WORD_DESC *w;
4427 char *tword;
4429 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
4431 tword = remove_pattern (l->word->word, pattern, patspec);
4432 w = alloc_word_desc ();
4433 w->word = tword ? tword : savestring ("");
4434 new = make_word_list (w, new);
4437 l = REVERSE_LIST (new, WORD_LIST *);
4438 tword = string_list_pos_params (itype, l, quoted);
4439 dispose_words (l);
4441 return (tword);
4444 static char *
4445 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
4446 int itype;
4447 char *pattern;
4448 int patspec, quoted;
4450 char *ret;
4451 WORD_LIST *list;
4453 list = list_rest_of_args ();
4454 if (list == 0)
4455 return ((char *)NULL);
4456 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4457 dispose_words (list);
4458 return (ret);
4461 #if defined (ARRAY_VARS)
4462 static char *
4463 array_remove_pattern (var, pattern, patspec, varname, quoted)
4464 SHELL_VAR *var;
4465 char *pattern;
4466 int patspec;
4467 char *varname; /* so we can figure out how it's indexed */
4468 int quoted;
4470 ARRAY *a;
4471 HASH_TABLE *h;
4472 int itype;
4473 char *ret;
4474 WORD_LIST *list;
4475 SHELL_VAR *v;
4477 /* compute itype from varname here */
4478 v = array_variable_part (varname, &ret, 0);
4479 itype = ret[0];
4481 a = (v && array_p (v)) ? array_cell (v) : 0;
4482 h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
4484 list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
4485 if (list == 0)
4486 return ((char *)NULL);
4487 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4488 dispose_words (list);
4490 return ret;
4492 #endif /* ARRAY_VARS */
4494 static char *
4495 parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flags)
4496 char *varname, *value;
4497 int ind;
4498 char *patstr;
4499 int rtype, quoted, flags;
4501 int vtype, patspec, starsub;
4502 char *temp1, *val, *pattern;
4503 SHELL_VAR *v;
4505 if (value == 0)
4506 return ((char *)NULL);
4508 this_command_name = varname;
4510 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
4511 if (vtype == -1)
4512 return ((char *)NULL);
4514 starsub = vtype & VT_STARSUB;
4515 vtype &= ~VT_STARSUB;
4517 patspec = getpatspec (rtype, patstr);
4518 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
4519 patstr++;
4521 /* Need to pass getpattern newly-allocated memory in case of expansion --
4522 the expansion code will free the passed string on an error. */
4523 temp1 = savestring (patstr);
4524 pattern = getpattern (temp1, quoted, 1);
4525 free (temp1);
4527 temp1 = (char *)NULL; /* shut up gcc */
4528 switch (vtype)
4530 case VT_VARIABLE:
4531 case VT_ARRAYMEMBER:
4532 temp1 = remove_pattern (val, pattern, patspec);
4533 if (vtype == VT_VARIABLE)
4534 FREE (val);
4535 if (temp1)
4537 val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4538 ? quote_string (temp1)
4539 : quote_escapes (temp1);
4540 free (temp1);
4541 temp1 = val;
4543 break;
4544 #if defined (ARRAY_VARS)
4545 case VT_ARRAYVAR:
4546 temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted);
4547 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4549 val = quote_escapes (temp1);
4550 free (temp1);
4551 temp1 = val;
4553 break;
4554 #endif
4555 case VT_POSPARMS:
4556 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
4557 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4559 val = quote_escapes (temp1);
4560 free (temp1);
4561 temp1 = val;
4563 break;
4566 FREE (pattern);
4567 return temp1;
4570 /*******************************************
4572 * Functions to expand WORD_DESCs *
4574 *******************************************/
4576 /* Expand WORD, performing word splitting on the result. This does
4577 parameter expansion, command substitution, arithmetic expansion,
4578 word splitting, and quote removal. */
4580 WORD_LIST *
4581 expand_word (word, quoted)
4582 WORD_DESC *word;
4583 int quoted;
4585 WORD_LIST *result, *tresult;
4587 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4588 result = word_list_split (tresult);
4589 dispose_words (tresult);
4590 return (result ? dequote_list (result) : result);
4593 /* Expand WORD, but do not perform word splitting on the result. This
4594 does parameter expansion, command substitution, arithmetic expansion,
4595 and quote removal. */
4596 WORD_LIST *
4597 expand_word_unsplit (word, quoted)
4598 WORD_DESC *word;
4599 int quoted;
4601 WORD_LIST *result;
4603 expand_no_split_dollar_star = 1;
4604 #if defined (HANDLE_MULTIBYTE)
4605 if (ifs_firstc[0] == 0)
4606 #else
4607 if (ifs_firstc == 0)
4608 #endif
4609 word->flags |= W_NOSPLIT;
4610 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4611 expand_no_split_dollar_star = 0;
4613 return (result ? dequote_list (result) : result);
4616 /* Perform shell expansions on WORD, but do not perform word splitting or
4617 quote removal on the result. Virtually identical to expand_word_unsplit;
4618 could be combined if implementations don't diverge. */
4619 WORD_LIST *
4620 expand_word_leave_quoted (word, quoted)
4621 WORD_DESC *word;
4622 int quoted;
4624 WORD_LIST *result;
4626 expand_no_split_dollar_star = 1;
4627 #if defined (HANDLE_MULTIBYTE)
4628 if (ifs_firstc[0] == 0)
4629 #else
4630 if (ifs_firstc == 0)
4631 #endif
4632 word->flags |= W_NOSPLIT;
4633 word->flags |= W_NOSPLIT2;
4634 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4635 expand_no_split_dollar_star = 0;
4637 return result;
4640 #if defined (PROCESS_SUBSTITUTION)
4642 /*****************************************************************/
4643 /* */
4644 /* Hacking Process Substitution */
4645 /* */
4646 /*****************************************************************/
4648 #if !defined (HAVE_DEV_FD)
4649 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
4650 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4651 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4652 list. NFIFO is a count of the number of FIFOs in the list. */
4653 #define FIFO_INCR 20
4655 struct temp_fifo {
4656 char *file;
4657 pid_t proc;
4660 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4661 static int nfifo;
4662 static int fifo_list_size;
4664 char *
4665 copy_fifo_list (sizep)
4666 int *sizep;
4668 if (sizep)
4669 *sizep = 0;
4670 return (char *)NULL;
4673 static void
4674 add_fifo_list (pathname)
4675 char *pathname;
4677 if (nfifo >= fifo_list_size - 1)
4679 fifo_list_size += FIFO_INCR;
4680 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4681 fifo_list_size * sizeof (struct temp_fifo));
4684 fifo_list[nfifo].file = savestring (pathname);
4685 nfifo++;
4688 void
4689 unlink_fifo (i)
4690 int i;
4692 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4694 unlink (fifo_list[i].file);
4695 free (fifo_list[i].file);
4696 fifo_list[i].file = (char *)NULL;
4697 fifo_list[i].proc = -1;
4701 void
4702 unlink_fifo_list ()
4704 int saved, i, j;
4706 if (nfifo == 0)
4707 return;
4709 for (i = saved = 0; i < nfifo; i++)
4711 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4713 unlink (fifo_list[i].file);
4714 free (fifo_list[i].file);
4715 fifo_list[i].file = (char *)NULL;
4716 fifo_list[i].proc = -1;
4718 else
4719 saved++;
4722 /* If we didn't remove some of the FIFOs, compact the list. */
4723 if (saved)
4725 for (i = j = 0; i < nfifo; i++)
4726 if (fifo_list[i].file)
4728 fifo_list[j].file = fifo_list[i].file;
4729 fifo_list[j].proc = fifo_list[i].proc;
4730 j++;
4732 nfifo = j;
4734 else
4735 nfifo = 0;
4738 /* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
4739 from some point in the past, and close all open FIFOs in fifo_list
4740 that are not marked as active in LIST. If LIST is NULL, close
4741 everything in fifo_list. LSIZE is the number of elements in LIST, in
4742 case it's larger than fifo_list_size (size of fifo_list). */
4743 void
4744 close_new_fifos (list, lsize)
4745 char *list;
4746 int lsize;
4748 int i;
4750 if (list == 0)
4752 unlink_fifo_list ();
4753 return;
4756 for (i = 0; i < lsize; i++)
4757 if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
4758 unlink_fifo (i);
4760 for (i = lsize; i < fifo_list_size; i++)
4761 unlink_fifo (i);
4765 fifos_pending ()
4767 return nfifo;
4771 num_fifos ()
4773 return nfifo;
4776 static char *
4777 make_named_pipe ()
4779 char *tname;
4781 tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
4782 if (mkfifo (tname, 0600) < 0)
4784 free (tname);
4785 return ((char *)NULL);
4788 add_fifo_list (tname);
4789 return (tname);
4792 #else /* HAVE_DEV_FD */
4794 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4795 has open to children. NFDS is a count of the number of bits currently
4796 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4797 of open files. */
4798 static char *dev_fd_list = (char *)NULL;
4799 static int nfds;
4800 static int totfds; /* The highest possible number of open files. */
4802 char *
4803 copy_fifo_list (sizep)
4804 int *sizep;
4806 char *ret;
4808 if (nfds == 0 || totfds == 0)
4810 if (sizep)
4811 *sizep = 0;
4812 return (char *)NULL;
4815 if (sizep)
4816 *sizep = totfds;
4817 ret = (char *)xmalloc (totfds);
4818 return (memcpy (ret, dev_fd_list, totfds));
4821 static void
4822 add_fifo_list (fd)
4823 int fd;
4825 if (dev_fd_list == 0 || fd >= totfds)
4827 int ofds;
4829 ofds = totfds;
4830 totfds = getdtablesize ();
4831 if (totfds < 0 || totfds > 256)
4832 totfds = 256;
4833 if (fd >= totfds)
4834 totfds = fd + 2;
4836 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4837 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4840 dev_fd_list[fd] = 1;
4841 nfds++;
4845 fifos_pending ()
4847 return 0; /* used for cleanup; not needed with /dev/fd */
4851 num_fifos ()
4853 return nfds;
4856 void
4857 unlink_fifo (fd)
4858 int fd;
4860 if (dev_fd_list[fd])
4862 close (fd);
4863 dev_fd_list[fd] = 0;
4864 nfds--;
4868 void
4869 unlink_fifo_list ()
4871 register int i;
4873 if (nfds == 0)
4874 return;
4876 for (i = 0; nfds && i < totfds; i++)
4877 unlink_fifo (i);
4879 nfds = 0;
4882 /* Take LIST, which is a snapshot copy of dev_fd_list from some point in
4883 the past, and close all open fds in dev_fd_list that are not marked
4884 as open in LIST. If LIST is NULL, close everything in dev_fd_list.
4885 LSIZE is the number of elements in LIST, in case it's larger than
4886 totfds (size of dev_fd_list). */
4887 void
4888 close_new_fifos (list, lsize)
4889 char *list;
4890 int lsize;
4892 int i;
4894 if (list == 0)
4896 unlink_fifo_list ();
4897 return;
4900 for (i = 0; i < lsize; i++)
4901 if (list[i] == 0 && i < totfds && dev_fd_list[i])
4902 unlink_fifo (i);
4904 for (i = lsize; i < totfds; i++)
4905 unlink_fifo (i);
4908 #if defined (NOTDEF)
4909 print_dev_fd_list ()
4911 register int i;
4913 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4914 fflush (stderr);
4916 for (i = 0; i < totfds; i++)
4918 if (dev_fd_list[i])
4919 fprintf (stderr, " %d", i);
4921 fprintf (stderr, "\n");
4923 #endif /* NOTDEF */
4925 static char *
4926 make_dev_fd_filename (fd)
4927 int fd;
4929 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4931 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8);
4933 strcpy (ret, DEV_FD_PREFIX);
4934 p = inttostr (fd, intbuf, sizeof (intbuf));
4935 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4937 add_fifo_list (fd);
4938 return (ret);
4941 #endif /* HAVE_DEV_FD */
4943 /* Return a filename that will open a connection to the process defined by
4944 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4945 a filename in /dev/fd corresponding to a descriptor that is one of the
4946 ends of the pipe. If not defined, we use named pipes on systems that have
4947 them. Systems without /dev/fd and named pipes are out of luck.
4949 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4950 use the read end of the pipe and dup that file descriptor to fd 0 in
4951 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4952 writing or use the write end of the pipe in the child, and dup that
4953 file descriptor to fd 1 in the child. The parent does the opposite. */
4955 static char *
4956 process_substitute (string, open_for_read_in_child)
4957 char *string;
4958 int open_for_read_in_child;
4960 char *pathname;
4961 int fd, result;
4962 pid_t old_pid, pid;
4963 #if defined (HAVE_DEV_FD)
4964 int parent_pipe_fd, child_pipe_fd;
4965 int fildes[2];
4966 #endif /* HAVE_DEV_FD */
4967 #if defined (JOB_CONTROL)
4968 pid_t old_pipeline_pgrp;
4969 #endif
4971 if (!string || !*string || wordexp_only)
4972 return ((char *)NULL);
4974 #if !defined (HAVE_DEV_FD)
4975 pathname = make_named_pipe ();
4976 #else /* HAVE_DEV_FD */
4977 if (pipe (fildes) < 0)
4979 sys_error (_("cannot make pipe for process substitution"));
4980 return ((char *)NULL);
4982 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4983 the pipe in the parent, otherwise the read end. */
4984 parent_pipe_fd = fildes[open_for_read_in_child];
4985 child_pipe_fd = fildes[1 - open_for_read_in_child];
4986 /* Move the parent end of the pipe to some high file descriptor, to
4987 avoid clashes with FDs used by the script. */
4988 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4990 pathname = make_dev_fd_filename (parent_pipe_fd);
4991 #endif /* HAVE_DEV_FD */
4993 if (pathname == 0)
4995 sys_error (_("cannot make pipe for process substitution"));
4996 return ((char *)NULL);
4999 old_pid = last_made_pid;
5001 #if defined (JOB_CONTROL)
5002 old_pipeline_pgrp = pipeline_pgrp;
5003 pipeline_pgrp = shell_pgrp;
5004 save_pipeline (1);
5005 #endif /* JOB_CONTROL */
5007 pid = make_child ((char *)NULL, 1);
5008 if (pid == 0)
5010 reset_terminating_signals (); /* XXX */
5011 free_pushed_string_input ();
5012 /* Cancel traps, in trap.c. */
5013 restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
5014 setup_async_signals ();
5015 subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
5018 #if defined (JOB_CONTROL)
5019 set_sigchld_handler ();
5020 stop_making_children ();
5021 /* XXX - should we only do this in the parent? (as in command subst) */
5022 pipeline_pgrp = old_pipeline_pgrp;
5023 #endif /* JOB_CONTROL */
5025 if (pid < 0)
5027 sys_error (_("cannot make child for process substitution"));
5028 free (pathname);
5029 #if defined (HAVE_DEV_FD)
5030 close (parent_pipe_fd);
5031 close (child_pipe_fd);
5032 #endif /* HAVE_DEV_FD */
5033 return ((char *)NULL);
5036 if (pid > 0)
5038 #if defined (JOB_CONTROL)
5039 restore_pipeline (1);
5040 #endif
5042 #if !defined (HAVE_DEV_FD)
5043 fifo_list[nfifo-1].proc = pid;
5044 #endif
5046 last_made_pid = old_pid;
5048 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
5049 close_pgrp_pipe ();
5050 #endif /* JOB_CONTROL && PGRP_PIPE */
5052 #if defined (HAVE_DEV_FD)
5053 close (child_pipe_fd);
5054 #endif /* HAVE_DEV_FD */
5056 return (pathname);
5059 set_sigint_handler ();
5061 #if defined (JOB_CONTROL)
5062 set_job_control (0);
5063 #endif /* JOB_CONTROL */
5065 #if !defined (HAVE_DEV_FD)
5066 /* Open the named pipe in the child. */
5067 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
5068 if (fd < 0)
5070 /* Two separate strings for ease of translation. */
5071 if (open_for_read_in_child)
5072 sys_error (_("cannot open named pipe %s for reading"), pathname);
5073 else
5074 sys_error (_("cannot open named pipe %s for writing"), pathname);
5076 exit (127);
5078 if (open_for_read_in_child)
5080 if (sh_unset_nodelay_mode (fd) < 0)
5082 sys_error (_("cannot reset nodelay mode for fd %d"), fd);
5083 exit (127);
5086 #else /* HAVE_DEV_FD */
5087 fd = child_pipe_fd;
5088 #endif /* HAVE_DEV_FD */
5090 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
5092 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
5093 open_for_read_in_child ? 0 : 1);
5094 exit (127);
5097 if (fd != (open_for_read_in_child ? 0 : 1))
5098 close (fd);
5100 /* Need to close any files that this process has open to pipes inherited
5101 from its parent. */
5102 if (current_fds_to_close)
5104 close_fd_bitmap (current_fds_to_close);
5105 current_fds_to_close = (struct fd_bitmap *)NULL;
5108 #if defined (HAVE_DEV_FD)
5109 /* Make sure we close the parent's end of the pipe and clear the slot
5110 in the fd list so it is not closed later, if reallocated by, for
5111 instance, pipe(2). */
5112 close (parent_pipe_fd);
5113 dev_fd_list[parent_pipe_fd] = 0;
5114 #endif /* HAVE_DEV_FD */
5116 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
5118 #if !defined (HAVE_DEV_FD)
5119 /* Make sure we close the named pipe in the child before we exit. */
5120 close (open_for_read_in_child ? 0 : 1);
5121 #endif /* !HAVE_DEV_FD */
5123 exit (result);
5124 /*NOTREACHED*/
5126 #endif /* PROCESS_SUBSTITUTION */
5128 /***********************************/
5129 /* */
5130 /* Command Substitution */
5131 /* */
5132 /***********************************/
5134 static char *
5135 read_comsub (fd, quoted, rflag)
5136 int fd, quoted;
5137 int *rflag;
5139 char *istring, buf[128], *bufp, *s;
5140 int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
5141 ssize_t bufn;
5143 istring = (char *)NULL;
5144 istring_index = istring_size = bufn = tflag = 0;
5146 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
5147 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
5149 /* Read the output of the command through the pipe. This may need to be
5150 changed to understand multibyte characters in the future. */
5151 while (1)
5153 if (fd < 0)
5154 break;
5155 if (--bufn <= 0)
5157 bufn = zread (fd, buf, sizeof (buf));
5158 if (bufn <= 0)
5159 break;
5160 bufp = buf;
5162 c = *bufp++;
5164 if (c == 0)
5166 #if 0
5167 internal_warning ("read_comsub: ignored null byte in input");
5168 #endif
5169 continue;
5172 /* Add the character to ISTRING, possibly after resizing it. */
5173 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
5175 /* This is essentially quote_string inline */
5176 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
5177 istring[istring_index++] = CTLESC;
5178 /* Escape CTLESC and CTLNUL in the output to protect those characters
5179 from the rest of the word expansions (word splitting and globbing.)
5180 This is essentially quote_escapes inline. */
5181 else if (skip_ctlesc == 0 && c == CTLESC)
5183 tflag |= W_HASCTLESC;
5184 istring[istring_index++] = CTLESC;
5186 else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
5187 istring[istring_index++] = CTLESC;
5189 istring[istring_index++] = c;
5191 #if 0
5192 #if defined (__CYGWIN__)
5193 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
5195 istring_index--;
5196 istring[istring_index - 1] = '\n';
5198 #endif
5199 #endif
5202 if (istring)
5203 istring[istring_index] = '\0';
5205 /* If we read no output, just return now and save ourselves some
5206 trouble. */
5207 if (istring_index == 0)
5209 FREE (istring);
5210 if (rflag)
5211 *rflag = tflag;
5212 return (char *)NULL;
5215 /* Strip trailing newlines from the output of the command. */
5216 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5218 while (istring_index > 0)
5220 if (istring[istring_index - 1] == '\n')
5222 --istring_index;
5224 /* If the newline was quoted, remove the quoting char. */
5225 if (istring[istring_index - 1] == CTLESC)
5226 --istring_index;
5228 else
5229 break;
5231 istring[istring_index] = '\0';
5233 else
5234 strip_trailing (istring, istring_index - 1, 1);
5236 if (rflag)
5237 *rflag = tflag;
5238 return istring;
5241 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
5242 contained string possibly quoted. */
5243 WORD_DESC *
5244 command_substitute (string, quoted)
5245 char *string;
5246 int quoted;
5248 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
5249 char *istring;
5250 int result, fildes[2], function_value, pflags, rc, tflag;
5251 WORD_DESC *ret;
5253 istring = (char *)NULL;
5255 /* Don't fork () if there is no need to. In the case of no command to
5256 run, just return NULL. */
5257 if (!string || !*string || (string[0] == '\n' && !string[1]))
5258 return ((WORD_DESC *)NULL);
5260 if (wordexp_only && read_but_dont_execute)
5262 last_command_exit_value = EX_WEXPCOMSUB;
5263 jump_to_top_level (EXITPROG);
5266 /* We're making the assumption here that the command substitution will
5267 eventually run a command from the file system. Since we'll run
5268 maybe_make_export_env in this subshell before executing that command,
5269 the parent shell and any other shells it starts will have to remake
5270 the environment. If we make it before we fork, other shells won't
5271 have to. Don't bother if we have any temporary variable assignments,
5272 though, because the export environment will be remade after this
5273 command completes anyway, but do it if all the words to be expanded
5274 are variable assignments. */
5275 if (subst_assign_varlist == 0 || garglist == 0)
5276 maybe_make_export_env (); /* XXX */
5278 /* Flags to pass to parse_and_execute() */
5279 pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0;
5281 /* Pipe the output of executing STRING into the current shell. */
5282 if (pipe (fildes) < 0)
5284 sys_error (_("cannot make pipe for command substitution"));
5285 goto error_exit;
5288 old_pid = last_made_pid;
5289 #if defined (JOB_CONTROL)
5290 old_pipeline_pgrp = pipeline_pgrp;
5291 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
5292 if ((subshell_environment & SUBSHELL_PIPE) == 0)
5293 pipeline_pgrp = shell_pgrp;
5294 cleanup_the_pipeline ();
5295 #endif /* JOB_CONTROL */
5297 old_async_pid = last_asynchronous_pid;
5298 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
5299 last_asynchronous_pid = old_async_pid;
5301 if (pid == 0)
5303 /* Reset the signal handlers in the child, but don't free the
5304 trap strings. Set a flag noting that we have to free the
5305 trap strings if we run trap to change a signal disposition. */
5306 reset_signal_handlers ();
5307 subshell_environment |= SUBSHELL_RESETTRAP;
5310 #if defined (JOB_CONTROL)
5311 /* XXX DO THIS ONLY IN PARENT ? XXX */
5312 set_sigchld_handler ();
5313 stop_making_children ();
5314 if (pid != 0)
5315 pipeline_pgrp = old_pipeline_pgrp;
5316 #else
5317 stop_making_children ();
5318 #endif /* JOB_CONTROL */
5320 if (pid < 0)
5322 sys_error (_("cannot make child for command substitution"));
5323 error_exit:
5325 FREE (istring);
5326 close (fildes[0]);
5327 close (fildes[1]);
5328 return ((WORD_DESC *)NULL);
5331 if (pid == 0)
5333 set_sigint_handler (); /* XXX */
5335 free_pushed_string_input ();
5337 if (dup2 (fildes[1], 1) < 0)
5339 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
5340 exit (EXECUTION_FAILURE);
5343 /* If standard output is closed in the parent shell
5344 (such as after `exec >&-'), file descriptor 1 will be
5345 the lowest available file descriptor, and end up in
5346 fildes[0]. This can happen for stdin and stderr as well,
5347 but stdout is more important -- it will cause no output
5348 to be generated from this command. */
5349 if ((fildes[1] != fileno (stdin)) &&
5350 (fildes[1] != fileno (stdout)) &&
5351 (fildes[1] != fileno (stderr)))
5352 close (fildes[1]);
5354 if ((fildes[0] != fileno (stdin)) &&
5355 (fildes[0] != fileno (stdout)) &&
5356 (fildes[0] != fileno (stderr)))
5357 close (fildes[0]);
5359 #ifdef __CYGWIN__
5360 /* Let stdio know the fd may have changed from text to binary mode, and
5361 make sure to preserve stdout line buffering. */
5362 freopen (NULL, "w", stdout);
5363 sh_setlinebuf (stdout);
5364 #endif /* __CYGWIN__ */
5366 /* The currently executing shell is not interactive. */
5367 interactive = 0;
5369 /* This is a subshell environment. */
5370 subshell_environment |= SUBSHELL_COMSUB;
5372 /* When not in POSIX mode, command substitution does not inherit
5373 the -e flag. */
5374 if (posixly_correct == 0)
5375 exit_immediately_on_error = 0;
5377 remove_quoted_escapes (string);
5379 startup_state = 2; /* see if we can avoid a fork */
5380 /* Give command substitution a place to jump back to on failure,
5381 so we don't go back up to main (). */
5382 result = setjmp (top_level);
5384 /* If we're running a command substitution inside a shell function,
5385 trap `return' so we don't return from the function in the subshell
5386 and go off to never-never land. */
5387 if (result == 0 && return_catch_flag)
5388 function_value = setjmp (return_catch);
5389 else
5390 function_value = 0;
5392 if (result == ERREXIT)
5393 rc = last_command_exit_value;
5394 else if (result == EXITPROG)
5395 rc = last_command_exit_value;
5396 else if (result)
5397 rc = EXECUTION_FAILURE;
5398 else if (function_value)
5399 rc = return_catch_value;
5400 else
5402 subshell_level++;
5403 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
5404 subshell_level--;
5407 last_command_exit_value = rc;
5408 rc = run_exit_trap ();
5409 #if defined (PROCESS_SUBSTITUTION)
5410 unlink_fifo_list ();
5411 #endif
5412 exit (rc);
5414 else
5416 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
5417 close_pgrp_pipe ();
5418 #endif /* JOB_CONTROL && PGRP_PIPE */
5420 close (fildes[1]);
5422 tflag = 0;
5423 istring = read_comsub (fildes[0], quoted, &tflag);
5425 close (fildes[0]);
5427 current_command_subst_pid = pid;
5428 last_command_exit_value = wait_for (pid);
5429 last_command_subst_pid = pid;
5430 last_made_pid = old_pid;
5432 #if defined (JOB_CONTROL)
5433 /* If last_command_exit_value > 128, then the substituted command
5434 was terminated by a signal. If that signal was SIGINT, then send
5435 SIGINT to ourselves. This will break out of loops, for instance. */
5436 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
5437 kill (getpid (), SIGINT);
5439 /* wait_for gives the terminal back to shell_pgrp. If some other
5440 process group should have it, give it away to that group here.
5441 pipeline_pgrp is non-zero only while we are constructing a
5442 pipline, so what we are concerned about is whether or not that
5443 pipeline was started in the background. A pipeline started in
5444 the background should never get the tty back here. */
5445 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
5446 give_terminal_to (pipeline_pgrp, 0);
5447 #endif /* JOB_CONTROL */
5449 ret = alloc_word_desc ();
5450 ret->word = istring;
5451 ret->flags = tflag;
5453 return ret;
5457 /********************************************************
5459 * Utility functions for parameter expansion *
5461 ********************************************************/
5463 #if defined (ARRAY_VARS)
5465 static arrayind_t
5466 array_length_reference (s)
5467 char *s;
5469 int len;
5470 arrayind_t ind;
5471 char *akey;
5472 char *t, c;
5473 ARRAY *array;
5474 HASH_TABLE *h;
5475 SHELL_VAR *var;
5477 var = array_variable_part (s, &t, &len);
5479 /* If unbound variables should generate an error, report one and return
5480 failure. */
5481 if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
5483 c = *--t;
5484 *t = '\0';
5485 last_command_exit_value = EXECUTION_FAILURE;
5486 err_unboundvar (s);
5487 *t = c;
5488 return (-1);
5490 else if (var == 0)
5491 return 0;
5493 /* We support a couple of expansions for variables that are not arrays.
5494 We'll return the length of the value for v[0], and 1 for v[@] or
5495 v[*]. Return 0 for everything else. */
5497 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
5498 h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
5500 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
5502 if (assoc_p (var))
5503 return (h ? assoc_num_elements (h) : 0);
5504 else if (array_p (var))
5505 return (array ? array_num_elements (array) : 0);
5506 else
5507 return (var_isset (var) ? 1 : 0);
5510 if (assoc_p (var))
5512 t[len - 1] = '\0';
5513 akey = expand_assignment_string_to_string (t, 0); /* [ */
5514 t[len - 1] = ']';
5515 if (akey == 0 || *akey == 0)
5517 err_badarraysub (t);
5518 return (-1);
5520 t = assoc_reference (assoc_cell (var), akey);
5522 else
5524 ind = array_expand_index (t, len);
5525 if (ind < 0)
5527 err_badarraysub (t);
5528 return (-1);
5530 if (array_p (var))
5531 t = array_reference (array, ind);
5532 else
5533 t = (ind == 0) ? value_cell (var) : (char *)NULL;
5536 len = MB_STRLEN (t);
5537 return (len);
5539 #endif /* ARRAY_VARS */
5541 static int
5542 valid_brace_expansion_word (name, var_is_special)
5543 char *name;
5544 int var_is_special;
5546 if (DIGIT (*name) && all_digits (name))
5547 return 1;
5548 else if (var_is_special)
5549 return 1;
5550 #if defined (ARRAY_VARS)
5551 else if (valid_array_reference (name))
5552 return 1;
5553 #endif /* ARRAY_VARS */
5554 else if (legal_identifier (name))
5555 return 1;
5556 else
5557 return 0;
5560 static int
5561 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
5562 char *name;
5563 int quoted;
5564 int *quoted_dollar_atp, *contains_dollar_at;
5566 char *temp1;
5568 if (name == 0)
5570 if (quoted_dollar_atp)
5571 *quoted_dollar_atp = 0;
5572 if (contains_dollar_at)
5573 *contains_dollar_at = 0;
5574 return 0;
5577 /* check for $@ and $* */
5578 if (name[0] == '@' && name[1] == 0)
5580 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5581 *quoted_dollar_atp = 1;
5582 if (contains_dollar_at)
5583 *contains_dollar_at = 1;
5584 return 1;
5586 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
5588 if (contains_dollar_at)
5589 *contains_dollar_at = 1;
5590 return 1;
5593 /* Now check for ${array[@]} and ${array[*]} */
5594 #if defined (ARRAY_VARS)
5595 else if (valid_array_reference (name))
5597 temp1 = mbschr (name, '[');
5598 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
5600 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5601 *quoted_dollar_atp = 1;
5602 if (contains_dollar_at)
5603 *contains_dollar_at = 1;
5604 return 1;
5605 } /* [ */
5606 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
5607 which should result in separate words even when IFS is unset. */
5608 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
5610 if (contains_dollar_at)
5611 *contains_dollar_at = 1;
5612 return 1;
5615 #endif
5616 return 0;
5619 /* Parameter expand NAME, and return a new string which is the expansion,
5620 or NULL if there was no expansion.
5621 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
5622 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
5623 NAME was found inside of a double-quoted expression. */
5624 static WORD_DESC *
5625 parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp)
5626 char *name;
5627 int var_is_special, quoted, pflags;
5628 arrayind_t *indp;
5630 WORD_DESC *ret;
5631 char *temp, *tt;
5632 intmax_t arg_index;
5633 SHELL_VAR *var;
5634 int atype, rflags;
5635 arrayind_t ind;
5637 ret = 0;
5638 temp = 0;
5639 rflags = 0;
5641 if (indp)
5642 *indp = INTMAX_MIN;
5644 /* Handle multiple digit arguments, as in ${11}. */
5645 if (legal_number (name, &arg_index))
5647 tt = get_dollar_var_value (arg_index);
5648 if (tt)
5649 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5650 ? quote_string (tt)
5651 : quote_escapes (tt);
5652 else
5653 temp = (char *)NULL;
5654 FREE (tt);
5656 else if (var_is_special) /* ${@} */
5658 int sindex;
5659 tt = (char *)xmalloc (2 + strlen (name));
5660 tt[sindex = 0] = '$';
5661 strcpy (tt + 1, name);
5663 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
5664 (int *)NULL, (int *)NULL, pflags);
5665 free (tt);
5667 #if defined (ARRAY_VARS)
5668 else if (valid_array_reference (name))
5670 temp = array_value (name, quoted, 0, &atype, &ind);
5671 if (atype == 0 && temp)
5673 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5674 ? quote_string (temp)
5675 : quote_escapes (temp);
5676 rflags |= W_ARRAYIND;
5677 if (indp)
5678 *indp = ind;
5680 else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5681 rflags |= W_HASQUOTEDNULL;
5683 #endif
5684 else if (var = find_variable (name))
5686 if (var_isset (var) && invisible_p (var) == 0)
5688 #if defined (ARRAY_VARS)
5689 if (assoc_p (var))
5690 temp = assoc_reference (assoc_cell (var), "0");
5691 else if (array_p (var))
5692 temp = array_reference (array_cell (var), 0);
5693 else
5694 temp = value_cell (var);
5695 #else
5696 temp = value_cell (var);
5697 #endif
5699 if (temp)
5700 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5701 ? quote_string (temp)
5702 : quote_escapes (temp);
5704 else
5705 temp = (char *)NULL;
5707 else
5708 temp = (char *)NULL;
5710 if (ret == 0)
5712 ret = alloc_word_desc ();
5713 ret->word = temp;
5714 ret->flags |= rflags;
5716 return ret;
5719 /* Expand an indirect reference to a variable: ${!NAME} expands to the
5720 value of the variable whose name is the value of NAME. */
5721 static WORD_DESC *
5722 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
5723 char *name;
5724 int var_is_special, quoted;
5725 int *quoted_dollar_atp, *contains_dollar_at;
5727 char *temp, *t;
5728 WORD_DESC *w;
5730 w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
5731 t = w->word;
5732 /* Have to dequote here if necessary */
5733 if (t)
5735 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5736 ? dequote_string (t)
5737 : dequote_escapes (t);
5738 free (t);
5739 t = temp;
5741 dispose_word_desc (w);
5743 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5744 if (t == 0)
5745 return (WORD_DESC *)NULL;
5747 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0, 0);
5748 free (t);
5750 return w;
5753 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5754 depending on the value of C, the separating character. C can be one of
5755 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5756 between double quotes. */
5757 static WORD_DESC *
5758 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5759 char *name, *value;
5760 int c, quoted, *qdollaratp, *hasdollarat;
5762 WORD_DESC *w;
5763 WORD_LIST *l;
5764 char *t, *t1, *temp;
5765 int hasdol;
5767 /* If the entire expression is between double quotes, we want to treat
5768 the value as a double-quoted string, with the exception that we strip
5769 embedded unescaped double quotes (for sh backwards compatibility). */
5770 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5772 hasdol = 0;
5773 temp = string_extract_double_quoted (value, &hasdol, 1);
5775 else
5776 temp = value;
5778 w = alloc_word_desc ();
5779 hasdol = 0;
5780 /* XXX was 0 not quoted */
5781 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5782 : (WORD_LIST *)0;
5783 if (hasdollarat)
5784 *hasdollarat = hasdol || (l && l->next);
5785 if (temp != value)
5786 free (temp);
5787 if (l)
5789 /* The expansion of TEMP returned something. We need to treat things
5790 slightly differently if HASDOL is non-zero. If we have "$@", the
5791 individual words have already been quoted. We need to turn them
5792 into a string with the words separated by the first character of
5793 $IFS without any additional quoting, so string_list_dollar_at won't
5794 do the right thing. We use string_list_dollar_star instead. */
5795 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5797 /* If l->next is not null, we know that TEMP contained "$@", since that
5798 is the only expansion that creates more than one word. */
5799 if (qdollaratp && ((hasdol && quoted) || l->next))
5800 *qdollaratp = 1;
5801 dispose_words (l);
5803 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5805 /* The brace expansion occurred between double quotes and there was
5806 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5807 it does not expand to anything. In this case, we want to return
5808 a quoted empty string. */
5809 temp = make_quoted_char ('\0');
5810 w->flags |= W_HASQUOTEDNULL;
5812 else
5813 temp = (char *)NULL;
5815 if (c == '-' || c == '+')
5817 w->word = temp;
5818 return w;
5821 /* c == '=' */
5822 t = temp ? savestring (temp) : savestring ("");
5823 t1 = dequote_string (t);
5824 free (t);
5825 #if defined (ARRAY_VARS)
5826 if (valid_array_reference (name))
5827 assign_array_element (name, t1, 0);
5828 else
5829 #endif /* ARRAY_VARS */
5830 bind_variable (name, t1, 0);
5832 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
5833 free (temp);
5835 w->word = t1;
5836 return w;
5839 /* Deal with the right hand side of a ${name:?value} expansion in the case
5840 that NAME is null or not set. If VALUE is non-null it is expanded and
5841 used as the error message to print, otherwise a standard message is
5842 printed. */
5843 static void
5844 parameter_brace_expand_error (name, value)
5845 char *name, *value;
5847 WORD_LIST *l;
5848 char *temp;
5850 if (value && *value)
5852 l = expand_string (value, 0);
5853 temp = string_list (l);
5854 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5855 FREE (temp);
5856 dispose_words (l);
5858 else
5859 report_error (_("%s: parameter null or not set"), name);
5861 /* Free the data we have allocated during this expansion, since we
5862 are about to longjmp out. */
5863 free (name);
5864 FREE (value);
5867 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5868 OK to do. */
5869 static int
5870 valid_length_expression (name)
5871 char *name;
5873 return (name[1] == '\0' || /* ${#} */
5874 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5875 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5876 #if defined (ARRAY_VARS)
5877 valid_array_reference (name + 1) || /* ${#a[7]} */
5878 #endif
5879 legal_identifier (name + 1)); /* ${#PS1} */
5882 /* Handle the parameter brace expansion that requires us to return the
5883 length of a parameter. */
5884 static intmax_t
5885 parameter_brace_expand_length (name)
5886 char *name;
5888 char *t, *newname;
5889 intmax_t number, arg_index;
5890 WORD_LIST *list;
5891 #if defined (ARRAY_VARS)
5892 SHELL_VAR *var;
5893 #endif
5895 if (name[1] == '\0') /* ${#} */
5896 number = number_of_args ();
5897 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5898 number = number_of_args ();
5899 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5901 /* Take the lengths of some of the shell's special parameters. */
5902 switch (name[1])
5904 case '-':
5905 t = which_set_flags ();
5906 break;
5907 case '?':
5908 t = itos (last_command_exit_value);
5909 break;
5910 case '$':
5911 t = itos (dollar_dollar_pid);
5912 break;
5913 case '!':
5914 if (last_asynchronous_pid == NO_PID)
5915 t = (char *)NULL; /* XXX - error if set -u set? */
5916 else
5917 t = itos (last_asynchronous_pid);
5918 break;
5919 case '#':
5920 t = itos (number_of_args ());
5921 break;
5923 number = STRLEN (t);
5924 FREE (t);
5926 #if defined (ARRAY_VARS)
5927 else if (valid_array_reference (name + 1))
5928 number = array_length_reference (name + 1);
5929 #endif /* ARRAY_VARS */
5930 else
5932 number = 0;
5934 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5936 t = get_dollar_var_value (arg_index);
5937 if (t == 0 && unbound_vars_is_error)
5938 return INTMAX_MIN;
5939 number = MB_STRLEN (t);
5940 FREE (t);
5942 #if defined (ARRAY_VARS)
5943 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
5945 if (assoc_p (var))
5946 t = assoc_reference (assoc_cell (var), "0");
5947 else
5948 t = array_reference (array_cell (var), 0);
5949 if (t == 0 && unbound_vars_is_error)
5950 return INTMAX_MIN;
5951 number = MB_STRLEN (t);
5953 #endif
5954 else /* ${#PS1} */
5956 newname = savestring (name);
5957 newname[0] = '$';
5958 list = expand_string (newname, Q_DOUBLE_QUOTES);
5959 t = list ? string_list (list) : (char *)NULL;
5960 free (newname);
5961 if (list)
5962 dispose_words (list);
5964 number = t ? MB_STRLEN (t) : 0;
5965 FREE (t);
5969 return (number);
5972 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5973 so we do some ad-hoc parsing of an arithmetic expression to find
5974 the first DELIM, instead of using strchr(3). Two rules:
5975 1. If the substring contains a `(', read until closing `)'.
5976 2. If the substring contains a `?', read past one `:' for each `?'.
5979 static char *
5980 skiparith (substr, delim)
5981 char *substr;
5982 int delim;
5984 size_t sublen;
5985 int skipcol, pcount, i;
5986 DECLARE_MBSTATE;
5988 sublen = strlen (substr);
5989 i = skipcol = pcount = 0;
5990 while (substr[i])
5992 /* Balance parens */
5993 if (substr[i] == LPAREN)
5995 pcount++;
5996 i++;
5997 continue;
5999 if (substr[i] == RPAREN && pcount)
6001 pcount--;
6002 i++;
6003 continue;
6005 if (pcount)
6007 ADVANCE_CHAR (substr, sublen, i);
6008 continue;
6011 /* Skip one `:' for each `?' */
6012 if (substr[i] == ':' && skipcol)
6014 skipcol--;
6015 i++;
6016 continue;
6018 if (substr[i] == delim)
6019 break;
6020 if (substr[i] == '?')
6022 skipcol++;
6023 i++;
6024 continue;
6026 ADVANCE_CHAR (substr, sublen, i);
6029 return (substr + i);
6032 /* Verify and limit the start and end of the desired substring. If
6033 VTYPE == 0, a regular shell variable is being used; if it is 1,
6034 then the positional parameters are being used; if it is 2, then
6035 VALUE is really a pointer to an array variable that should be used.
6036 Return value is 1 if both values were OK, 0 if there was a problem
6037 with an invalid expression, or -1 if the values were out of range. */
6038 static int
6039 verify_substring_values (v, value, substr, vtype, e1p, e2p)
6040 SHELL_VAR *v;
6041 char *value, *substr;
6042 int vtype;
6043 intmax_t *e1p, *e2p;
6045 char *t, *temp1, *temp2;
6046 arrayind_t len;
6047 int expok;
6048 #if defined (ARRAY_VARS)
6049 ARRAY *a;
6050 HASH_TABLE *h;
6051 #endif
6053 /* duplicate behavior of strchr(3) */
6054 t = skiparith (substr, ':');
6055 if (*t && *t == ':')
6056 *t = '\0';
6057 else
6058 t = (char *)0;
6060 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
6061 *e1p = evalexp (temp1, &expok);
6062 free (temp1);
6063 if (expok == 0)
6064 return (0);
6066 len = -1; /* paranoia */
6067 switch (vtype)
6069 case VT_VARIABLE:
6070 case VT_ARRAYMEMBER:
6071 len = MB_STRLEN (value);
6072 break;
6073 case VT_POSPARMS:
6074 len = number_of_args () + 1;
6075 if (*e1p == 0)
6076 len++; /* add one arg if counting from $0 */
6077 break;
6078 #if defined (ARRAY_VARS)
6079 case VT_ARRAYVAR:
6080 /* For arrays, the first value deals with array indices. Negative
6081 offsets count from one past the array's maximum index. Associative
6082 arrays treat the number of elements as the maximum index. */
6083 if (assoc_p (v))
6085 h = assoc_cell (v);
6086 len = assoc_num_elements (h) + (*e1p < 0);
6088 else
6090 a = (ARRAY *)value;
6091 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
6093 break;
6094 #endif
6097 if (len == -1) /* paranoia */
6098 return -1;
6100 if (*e1p < 0) /* negative offsets count from end */
6101 *e1p += len;
6103 if (*e1p > len || *e1p < 0)
6104 return (-1);
6106 #if defined (ARRAY_VARS)
6107 /* For arrays, the second offset deals with the number of elements. */
6108 if (vtype == VT_ARRAYVAR)
6109 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
6110 #endif
6112 if (t)
6114 t++;
6115 temp2 = savestring (t);
6116 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
6117 free (temp2);
6118 t[-1] = ':';
6119 *e2p = evalexp (temp1, &expok);
6120 free (temp1);
6121 if (expok == 0)
6122 return (0);
6123 if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0)
6125 internal_error (_("%s: substring expression < 0"), t);
6126 return (0);
6128 #if defined (ARRAY_VARS)
6129 /* In order to deal with sparse arrays, push the intelligence about how
6130 to deal with the number of elements desired down to the array-
6131 specific functions. */
6132 if (vtype != VT_ARRAYVAR)
6133 #endif
6135 if (*e2p < 0)
6137 *e2p += len;
6138 if (*e2p < 0 || *e2p < *e1p)
6140 internal_error (_("%s: substring expression < 0"), t);
6141 return (0);
6144 else
6145 *e2p += *e1p; /* want E2 chars starting at E1 */
6146 if (*e2p > len)
6147 *e2p = len;
6150 else
6151 *e2p = len;
6153 return (1);
6156 /* Return the type of variable specified by VARNAME (simple variable,
6157 positional param, or array variable). Also return the value specified
6158 by VARNAME (value of a variable or a reference to an array element).
6159 QUOTED is the standard description of quoting state, using Q_* defines.
6160 FLAGS is currently a set of flags to pass to array_value. If IND is
6161 non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
6162 passed to array_value so the array index is not computed again.
6163 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
6164 characters in the value are quoted with CTLESC and takes appropriate
6165 steps. For convenience, *VALP is set to the dequoted VALUE. */
6166 static int
6167 get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
6168 char *varname, *value;
6169 arrayind_t ind;
6170 int quoted, flags;
6171 SHELL_VAR **varp;
6172 char **valp;
6174 int vtype;
6175 char *temp;
6176 #if defined (ARRAY_VARS)
6177 SHELL_VAR *v;
6178 #endif
6179 arrayind_t lind;
6181 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
6182 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
6183 if (vtype == VT_POSPARMS && varname[0] == '*')
6184 vtype |= VT_STARSUB;
6185 *varp = (SHELL_VAR *)NULL;
6187 #if defined (ARRAY_VARS)
6188 if (valid_array_reference (varname))
6190 v = array_variable_part (varname, &temp, (int *)0);
6191 /* If we want to signal array_value to use an already-computed index,
6192 set LIND to that index */
6193 lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
6194 if (v && (array_p (v) || assoc_p (v)))
6195 { /* [ */
6196 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
6198 /* Callers have to differentiate betwen indexed and associative */
6199 vtype = VT_ARRAYVAR;
6200 if (temp[0] == '*')
6201 vtype |= VT_STARSUB;
6202 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
6204 else
6206 vtype = VT_ARRAYMEMBER;
6207 *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
6209 *varp = v;
6211 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
6213 vtype = VT_VARIABLE;
6214 *varp = v;
6215 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6216 *valp = dequote_string (value);
6217 else
6218 *valp = dequote_escapes (value);
6220 else
6222 vtype = VT_ARRAYMEMBER;
6223 *varp = v;
6224 *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
6227 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
6229 vtype = VT_ARRAYMEMBER;
6230 *varp = v;
6231 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
6233 else
6234 #endif
6236 if (value && vtype == VT_VARIABLE)
6238 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6239 *valp = dequote_string (value);
6240 else
6241 *valp = dequote_escapes (value);
6243 else
6244 *valp = value;
6247 return vtype;
6250 /******************************************************/
6251 /* */
6252 /* Functions to extract substrings of variable values */
6253 /* */
6254 /******************************************************/
6256 #if defined (HANDLE_MULTIBYTE)
6257 /* Character-oriented rather than strictly byte-oriented substrings. S and
6258 E, rather being strict indices into STRING, indicate character (possibly
6259 multibyte character) positions that require calculation.
6260 Used by the ${param:offset[:length]} expansion. */
6261 static char *
6262 mb_substring (string, s, e)
6263 char *string;
6264 int s, e;
6266 char *tt;
6267 int start, stop, i, slen;
6268 DECLARE_MBSTATE;
6270 start = 0;
6271 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
6272 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
6274 i = s;
6275 while (string[start] && i--)
6276 ADVANCE_CHAR (string, slen, start);
6277 stop = start;
6278 i = e - s;
6279 while (string[stop] && i--)
6280 ADVANCE_CHAR (string, slen, stop);
6281 tt = substring (string, start, stop);
6282 return tt;
6284 #endif
6286 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
6287 is `@', use the positional parameters; otherwise, use the value of
6288 VARNAME. If VARNAME is an array variable, use the array elements. */
6290 static char *
6291 parameter_brace_substring (varname, value, ind, substr, quoted, flags)
6292 char *varname, *value;
6293 int ind;
6294 char *substr;
6295 int quoted, flags;
6297 intmax_t e1, e2;
6298 int vtype, r, starsub;
6299 char *temp, *val, *tt, *oname;
6300 SHELL_VAR *v;
6302 if (value == 0)
6303 return ((char *)NULL);
6305 oname = this_command_name;
6306 this_command_name = varname;
6308 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
6309 if (vtype == -1)
6311 this_command_name = oname;
6312 return ((char *)NULL);
6315 starsub = vtype & VT_STARSUB;
6316 vtype &= ~VT_STARSUB;
6318 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
6319 this_command_name = oname;
6320 if (r <= 0)
6321 return ((r == 0) ? &expand_param_error : (char *)NULL);
6323 switch (vtype)
6325 case VT_VARIABLE:
6326 case VT_ARRAYMEMBER:
6327 #if defined (HANDLE_MULTIBYTE)
6328 if (MB_CUR_MAX > 1)
6329 tt = mb_substring (val, e1, e2);
6330 else
6331 #endif
6332 tt = substring (val, e1, e2);
6334 if (vtype == VT_VARIABLE)
6335 FREE (val);
6336 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6337 temp = quote_string (tt);
6338 else
6339 temp = tt ? quote_escapes (tt) : (char *)NULL;
6340 FREE (tt);
6341 break;
6342 case VT_POSPARMS:
6343 tt = pos_params (varname, e1, e2, quoted);
6344 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
6346 temp = tt ? quote_escapes (tt) : (char *)NULL;
6347 FREE (tt);
6349 else
6350 temp = tt;
6351 break;
6352 #if defined (ARRAY_VARS)
6353 case VT_ARRAYVAR:
6354 if (assoc_p (v))
6355 /* we convert to list and take first e2 elements starting at e1th
6356 element -- officially undefined for now */
6357 temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
6358 else
6359 /* We want E2 to be the number of elements desired (arrays can be sparse,
6360 so verify_substring_values just returns the numbers specified and we
6361 rely on array_subrange to understand how to deal with them). */
6362 temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
6363 /* array_subrange now calls array_quote_escapes as appropriate, so the
6364 caller no longer needs to. */
6365 break;
6366 #endif
6367 default:
6368 temp = (char *)NULL;
6371 return temp;
6374 /****************************************************************/
6375 /* */
6376 /* Functions to perform pattern substitution on variable values */
6377 /* */
6378 /****************************************************************/
6380 static int
6381 shouldexp_replacement (s)
6382 char *s;
6384 register char *p;
6386 for (p = s; p && *p; p++)
6388 if (*p == '\\')
6389 p++;
6390 else if (*p == '&')
6391 return 1;
6393 return 0;
6396 char *
6397 pat_subst (string, pat, rep, mflags)
6398 char *string, *pat, *rep;
6399 int mflags;
6401 char *ret, *s, *e, *str, *rstr, *mstr;
6402 int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen;
6404 if (string == 0)
6405 return (savestring (""));
6407 mtype = mflags & MATCH_TYPEMASK;
6409 #if 0 /* bash-4.2 ? */
6410 rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0;
6411 #else
6412 rxpand = 0;
6413 #endif
6415 /* Special cases:
6416 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
6417 * with REP and return the result.
6418 * 2. A null pattern with mtype == MATCH_END means to append REP to
6419 * STRING and return the result.
6420 * These don't understand or process `&' in the replacement string.
6422 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
6424 replen = STRLEN (rep);
6425 l = STRLEN (string);
6426 ret = (char *)xmalloc (replen + l + 2);
6427 if (replen == 0)
6428 strcpy (ret, string);
6429 else if (mtype == MATCH_BEG)
6431 strcpy (ret, rep);
6432 strcpy (ret + replen, string);
6434 else
6436 strcpy (ret, string);
6437 strcpy (ret + l, rep);
6439 return (ret);
6442 ret = (char *)xmalloc (rsize = 64);
6443 ret[0] = '\0';
6445 for (replen = STRLEN (rep), rptr = 0, str = string;;)
6447 if (match_pattern (str, pat, mtype, &s, &e) == 0)
6448 break;
6449 l = s - str;
6451 if (rxpand)
6453 int x;
6454 mlen = e - s;
6455 mstr = xmalloc (mlen + 1);
6456 for (x = 0; x < mlen; x++)
6457 mstr[x] = s[x];
6458 mstr[mlen] = '\0';
6459 rstr = strcreplace (rep, '&', mstr, 0);
6460 rslen = strlen (rstr);
6462 else
6464 rstr = rep;
6465 rslen = replen;
6468 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64);
6470 /* OK, now copy the leading unmatched portion of the string (from
6471 str to s) to ret starting at rptr (the current offset). Then copy
6472 the replacement string at ret + rptr + (s - str). Increment
6473 rptr (if necessary) and str and go on. */
6474 if (l)
6476 strncpy (ret + rptr, str, l);
6477 rptr += l;
6479 if (replen)
6481 strncpy (ret + rptr, rstr, rslen);
6482 rptr += rslen;
6484 str = e; /* e == end of match */
6486 if (rstr != rep)
6487 free (rstr);
6489 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
6490 break;
6492 if (s == e)
6494 /* On a zero-length match, make sure we copy one character, since
6495 we increment one character to avoid infinite recursion. */
6496 RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64);
6497 ret[rptr++] = *str++;
6498 e++; /* avoid infinite recursion on zero-length match */
6502 /* Now copy the unmatched portion of the input string */
6503 if (str && *str)
6505 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
6506 strcpy (ret + rptr, str);
6508 else
6509 ret[rptr] = '\0';
6511 return ret;
6514 /* Do pattern match and replacement on the positional parameters. */
6515 static char *
6516 pos_params_pat_subst (string, pat, rep, mflags)
6517 char *string, *pat, *rep;
6518 int mflags;
6520 WORD_LIST *save, *params;
6521 WORD_DESC *w;
6522 char *ret;
6523 int pchar, qflags;
6525 save = params = list_rest_of_args ();
6526 if (save == 0)
6527 return ((char *)NULL);
6529 for ( ; params; params = params->next)
6531 ret = pat_subst (params->word->word, pat, rep, mflags);
6532 w = alloc_word_desc ();
6533 w->word = ret ? ret : savestring ("");
6534 dispose_word (params->word);
6535 params->word = w;
6538 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6539 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6541 #if 0
6542 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
6543 ret = string_list_dollar_star (quote_list (save));
6544 else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
6545 ret = string_list_dollar_star (save);
6546 else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
6547 ret = string_list_dollar_at (save, qflags);
6548 else
6549 ret = string_list_dollar_star (save);
6550 #else
6551 ret = string_list_pos_params (pchar, save, qflags);
6552 #endif
6554 dispose_words (save);
6556 return (ret);
6559 /* Perform pattern substitution on VALUE, which is the expansion of
6560 VARNAME. PATSUB is an expression supplying the pattern to match
6561 and the string to substitute. QUOTED is a flags word containing
6562 the type of quoting currently in effect. */
6563 static char *
6564 parameter_brace_patsub (varname, value, ind, patsub, quoted, flags)
6565 char *varname, *value;
6566 int ind;
6567 char *patsub;
6568 int quoted, flags;
6570 int vtype, mflags, starsub, delim;
6571 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
6572 SHELL_VAR *v;
6574 if (value == 0)
6575 return ((char *)NULL);
6577 this_command_name = varname;
6579 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
6580 if (vtype == -1)
6581 return ((char *)NULL);
6583 starsub = vtype & VT_STARSUB;
6584 vtype &= ~VT_STARSUB;
6586 mflags = 0;
6587 if (patsub && *patsub == '/')
6589 mflags |= MATCH_GLOBREP;
6590 patsub++;
6593 /* Malloc this because expand_string_if_necessary or one of the expansion
6594 functions in its call chain may free it on a substitution error. */
6595 lpatsub = savestring (patsub);
6597 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6598 mflags |= MATCH_QUOTED;
6600 if (starsub)
6601 mflags |= MATCH_STARSUB;
6603 /* If the pattern starts with a `/', make sure we skip over it when looking
6604 for the replacement delimiter. */
6605 #if 0
6606 if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
6607 *rep++ = '\0';
6608 else
6609 rep = (char *)NULL;
6610 #else
6611 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
6612 if (lpatsub[delim] == '/')
6614 lpatsub[delim] = 0;
6615 rep = lpatsub + delim + 1;
6617 else
6618 rep = (char *)NULL;
6619 #endif
6621 if (rep && *rep == '\0')
6622 rep = (char *)NULL;
6624 /* Perform the same expansions on the pattern as performed by the
6625 pattern removal expansions. */
6626 pat = getpattern (lpatsub, quoted, 1);
6628 if (rep)
6630 if ((mflags & MATCH_QUOTED) == 0)
6631 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
6632 else
6633 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
6636 /* ksh93 doesn't allow the match specifier to be a part of the expanded
6637 pattern. This is an extension. Make sure we don't anchor the pattern
6638 at the beginning or end of the string if we're doing global replacement,
6639 though. */
6640 p = pat;
6641 if (mflags & MATCH_GLOBREP)
6642 mflags |= MATCH_ANY;
6643 else if (pat && pat[0] == '#')
6645 mflags |= MATCH_BEG;
6646 p++;
6648 else if (pat && pat[0] == '%')
6650 mflags |= MATCH_END;
6651 p++;
6653 else
6654 mflags |= MATCH_ANY;
6656 /* OK, we now want to substitute REP for PAT in VAL. If
6657 flags & MATCH_GLOBREP is non-zero, the substitution is done
6658 everywhere, otherwise only the first occurrence of PAT is
6659 replaced. The pattern matching code doesn't understand
6660 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6661 values passed in (VT_VARIABLE) so the pattern substitution
6662 code works right. We need to requote special chars after
6663 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6664 other cases if QUOTED == 0, since the posparams and arrays
6665 indexed by * or @ do special things when QUOTED != 0. */
6667 switch (vtype)
6669 case VT_VARIABLE:
6670 case VT_ARRAYMEMBER:
6671 temp = pat_subst (val, p, rep, mflags);
6672 if (vtype == VT_VARIABLE)
6673 FREE (val);
6674 if (temp)
6676 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6677 free (temp);
6678 temp = tt;
6680 break;
6681 case VT_POSPARMS:
6682 temp = pos_params_pat_subst (val, p, rep, mflags);
6683 if (temp && (mflags & MATCH_QUOTED) == 0)
6685 tt = quote_escapes (temp);
6686 free (temp);
6687 temp = tt;
6689 break;
6690 #if defined (ARRAY_VARS)
6691 case VT_ARRAYVAR:
6692 temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6693 : array_patsub (array_cell (v), p, rep, mflags);
6694 /* Don't call quote_escapes anymore; array_patsub calls
6695 array_quote_escapes as appropriate before adding the
6696 space separators; ditto for assoc_patsub. */
6697 break;
6698 #endif
6701 FREE (pat);
6702 FREE (rep);
6703 free (lpatsub);
6705 return temp;
6708 /****************************************************************/
6709 /* */
6710 /* Functions to perform case modification on variable values */
6711 /* */
6712 /****************************************************************/
6714 /* Do case modification on the positional parameters. */
6716 static char *
6717 pos_params_modcase (string, pat, modop, mflags)
6718 char *string, *pat;
6719 int modop;
6720 int mflags;
6722 WORD_LIST *save, *params;
6723 WORD_DESC *w;
6724 char *ret;
6725 int pchar, qflags;
6727 save = params = list_rest_of_args ();
6728 if (save == 0)
6729 return ((char *)NULL);
6731 for ( ; params; params = params->next)
6733 ret = sh_modcase (params->word->word, pat, modop);
6734 w = alloc_word_desc ();
6735 w->word = ret ? ret : savestring ("");
6736 dispose_word (params->word);
6737 params->word = w;
6740 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6741 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6743 ret = string_list_pos_params (pchar, save, qflags);
6744 dispose_words (save);
6746 return (ret);
6749 /* Perform case modification on VALUE, which is the expansion of
6750 VARNAME. MODSPEC is an expression supplying the type of modification
6751 to perform. QUOTED is a flags word containing the type of quoting
6752 currently in effect. */
6753 static char *
6754 parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags)
6755 char *varname, *value;
6756 int ind, modspec;
6757 char *patspec;
6758 int quoted, flags;
6760 int vtype, starsub, modop, mflags, x;
6761 char *val, *temp, *pat, *p, *lpat, *tt;
6762 SHELL_VAR *v;
6764 if (value == 0)
6765 return ((char *)NULL);
6767 this_command_name = varname;
6769 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
6770 if (vtype == -1)
6771 return ((char *)NULL);
6773 starsub = vtype & VT_STARSUB;
6774 vtype &= ~VT_STARSUB;
6776 modop = 0;
6777 mflags = 0;
6778 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6779 mflags |= MATCH_QUOTED;
6780 if (starsub)
6781 mflags |= MATCH_STARSUB;
6783 p = patspec;
6784 if (modspec == '^')
6786 x = p && p[0] == modspec;
6787 modop = x ? CASE_UPPER : CASE_UPFIRST;
6788 p += x;
6790 else if (modspec == ',')
6792 x = p && p[0] == modspec;
6793 modop = x ? CASE_LOWER : CASE_LOWFIRST;
6794 p += x;
6796 else if (modspec == '~')
6798 x = p && p[0] == modspec;
6799 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6800 p += x;
6803 lpat = p ? savestring (p) : 0;
6804 /* Perform the same expansions on the pattern as performed by the
6805 pattern removal expansions. FOR LATER */
6806 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6808 /* OK, now we do the case modification. */
6809 switch (vtype)
6811 case VT_VARIABLE:
6812 case VT_ARRAYMEMBER:
6813 temp = sh_modcase (val, pat, modop);
6814 if (vtype == VT_VARIABLE)
6815 FREE (val);
6816 if (temp)
6818 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6819 free (temp);
6820 temp = tt;
6822 break;
6824 case VT_POSPARMS:
6825 temp = pos_params_modcase (val, pat, modop, mflags);
6826 if (temp && (mflags & MATCH_QUOTED) == 0)
6828 tt = quote_escapes (temp);
6829 free (temp);
6830 temp = tt;
6832 break;
6834 #if defined (ARRAY_VARS)
6835 case VT_ARRAYVAR:
6836 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6837 : array_modcase (array_cell (v), pat, modop, mflags);
6838 /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6839 as appropriate before adding the space separators; ditto for
6840 assoc_modcase. */
6841 break;
6842 #endif
6845 FREE (pat);
6846 free (lpat);
6848 return temp;
6851 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
6852 any occur, this must be a nested command substitution, so return 0.
6853 Otherwise, return 1. A valid arithmetic expression must always have a
6854 ( before a matching ), so any cases where there are more right parens
6855 means that this must not be an arithmetic expression, though the parser
6856 will not accept it without a balanced total number of parens. */
6857 static int
6858 chk_arithsub (s, len)
6859 const char *s;
6860 int len;
6862 int i, count;
6863 DECLARE_MBSTATE;
6865 i = count = 0;
6866 while (i < len)
6868 if (s[i] == LPAREN)
6869 count++;
6870 else if (s[i] == RPAREN)
6872 count--;
6873 if (count < 0)
6874 return 0;
6877 switch (s[i])
6879 default:
6880 ADVANCE_CHAR (s, len, i);
6881 break;
6883 case '\\':
6884 i++;
6885 if (s[i])
6886 ADVANCE_CHAR (s, len, i);
6887 break;
6889 case '\'':
6890 i = skip_single_quoted (s, len, ++i);
6891 break;
6893 case '"':
6894 i = skip_double_quoted ((char *)s, len, ++i);
6895 break;
6899 return (count == 0);
6902 /****************************************************************/
6903 /* */
6904 /* Functions to perform parameter expansion on a string */
6905 /* */
6906 /****************************************************************/
6908 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
6909 static WORD_DESC *
6910 parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
6911 char *string;
6912 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags;
6914 int check_nullness, var_is_set, var_is_null, var_is_special;
6915 int want_substring, want_indir, want_patsub, want_casemod;
6916 char *name, *value, *temp, *temp1;
6917 WORD_DESC *tdesc, *ret;
6918 int t_index, sindex, c, tflag, modspec;
6919 intmax_t number;
6920 arrayind_t ind;
6922 temp = temp1 = value = (char *)NULL;
6923 var_is_set = var_is_null = var_is_special = check_nullness = 0;
6924 want_substring = want_indir = want_patsub = want_casemod = 0;
6926 sindex = *indexp;
6927 t_index = ++sindex;
6928 /* ${#var} doesn't have any of the other parameter expansions on it. */
6929 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
6930 name = string_extract (string, &t_index, "}", SX_VARNAME);
6931 else
6932 #if defined (CASEMOD_EXPANSIONS)
6933 /* To enable case-toggling expansions using the `~' operator character
6934 change the 1 to 0. */
6935 # if defined (CASEMOD_CAPCASE)
6936 name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
6937 # else
6938 name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
6939 # endif /* CASEMOD_CAPCASE */
6940 #else
6941 name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
6942 #endif /* CASEMOD_EXPANSIONS */
6944 ret = 0;
6945 tflag = 0;
6947 ind = INTMAX_MIN;
6949 /* If the name really consists of a special variable, then make sure
6950 that we have the entire name. We don't allow indirect references
6951 to special variables except `#', `?', `@' and `*'. */
6952 if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
6953 (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
6955 t_index++;
6956 free (name);
6957 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
6958 name = (char *)xmalloc (3 + (strlen (temp1)));
6959 *name = string[sindex];
6960 if (string[sindex] == '!')
6962 /* indirect reference of $#, $?, $@, or $* */
6963 name[1] = string[sindex + 1];
6964 strcpy (name + 2, temp1);
6966 else
6967 strcpy (name + 1, temp1);
6968 free (temp1);
6970 sindex = t_index;
6972 /* Find out what character ended the variable name. Then
6973 do the appropriate thing. */
6974 if (c = string[sindex])
6975 sindex++;
6977 /* If c is followed by one of the valid parameter expansion
6978 characters, move past it as normal. If not, assume that
6979 a substring specification is being given, and do not move
6980 past it. */
6981 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
6983 check_nullness++;
6984 if (c = string[sindex])
6985 sindex++;
6987 else if (c == ':' && string[sindex] != RBRACE)
6988 want_substring = 1;
6989 else if (c == '/' && string[sindex] != RBRACE)
6990 want_patsub = 1;
6991 #if defined (CASEMOD_EXPANSIONS)
6992 else if (c == '^' || c == ',' || c == '~')
6994 modspec = c;
6995 want_casemod = 1;
6997 #endif
6999 /* Catch the valid and invalid brace expressions that made it through the
7000 tests above. */
7001 /* ${#-} is a valid expansion and means to take the length of $-.
7002 Similarly for ${#?} and ${##}... */
7003 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
7004 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
7006 name = (char *)xrealloc (name, 3);
7007 name[1] = c;
7008 name[2] = '\0';
7009 c = string[sindex++];
7012 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
7013 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
7014 member (c, "%:=+/") && string[sindex] == RBRACE)
7016 temp = (char *)NULL;
7017 goto bad_substitution;
7020 /* Indirect expansion begins with a `!'. A valid indirect expansion is
7021 either a variable name, one of the positional parameters or a special
7022 variable that expands to one of the positional parameters. */
7023 want_indir = *name == '!' &&
7024 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
7025 || VALID_INDIR_PARAM (name[1]));
7027 /* Determine the value of this variable. */
7029 /* Check for special variables, directly referenced. */
7030 if (SPECIAL_VAR (name, want_indir))
7031 var_is_special++;
7033 /* Check for special expansion things, like the length of a parameter */
7034 if (*name == '#' && name[1])
7036 /* If we are not pointing at the character just after the
7037 closing brace, then we haven't gotten all of the name.
7038 Since it begins with a special character, this is a bad
7039 substitution. Also check NAME for validity before trying
7040 to go on. */
7041 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
7043 temp = (char *)NULL;
7044 goto bad_substitution;
7047 number = parameter_brace_expand_length (name);
7048 if (number == INTMAX_MIN && unbound_vars_is_error)
7050 last_command_exit_value = EXECUTION_FAILURE;
7051 err_unboundvar (name+1);
7052 free (name);
7053 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7055 free (name);
7057 *indexp = sindex;
7058 if (number < 0)
7059 return (&expand_wdesc_error);
7060 else
7062 ret = alloc_word_desc ();
7063 ret->word = itos (number);
7064 return ret;
7068 /* ${@} is identical to $@. */
7069 if (name[0] == '@' && name[1] == '\0')
7071 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7072 *quoted_dollar_atp = 1;
7074 if (contains_dollar_at)
7075 *contains_dollar_at = 1;
7078 /* Process ${!PREFIX*} expansion. */
7079 if (want_indir && string[sindex - 1] == RBRACE &&
7080 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
7081 legal_variable_starter ((unsigned char) name[1]))
7083 char **x;
7084 WORD_LIST *xlist;
7086 temp1 = savestring (name + 1);
7087 number = strlen (temp1);
7088 temp1[number - 1] = '\0';
7089 x = all_variables_matching_prefix (temp1);
7090 xlist = strvec_to_word_list (x, 0, 0);
7091 if (string[sindex - 2] == '*')
7092 temp = string_list_dollar_star (xlist);
7093 else
7095 temp = string_list_dollar_at (xlist, quoted);
7096 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7097 *quoted_dollar_atp = 1;
7098 if (contains_dollar_at)
7099 *contains_dollar_at = 1;
7101 free (x);
7102 dispose_words (xlist);
7103 free (temp1);
7104 *indexp = sindex;
7106 ret = alloc_word_desc ();
7107 ret->word = temp;
7108 return ret;
7111 #if defined (ARRAY_VARS)
7112 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
7113 if (want_indir && string[sindex - 1] == RBRACE &&
7114 string[sindex - 2] == ']' && valid_array_reference (name+1))
7116 char *x, *x1;
7118 temp1 = savestring (name + 1);
7119 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
7120 FREE (x);
7121 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
7123 temp = array_keys (temp1, quoted); /* handles assoc vars too */
7124 if (x1[0] == '@')
7126 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7127 *quoted_dollar_atp = 1;
7128 if (contains_dollar_at)
7129 *contains_dollar_at = 1;
7132 free (temp1);
7133 *indexp = sindex;
7135 ret = alloc_word_desc ();
7136 ret->word = temp;
7137 return ret;
7140 free (temp1);
7142 #endif /* ARRAY_VARS */
7144 /* Make sure that NAME is valid before trying to go on. */
7145 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
7146 var_is_special) == 0)
7148 temp = (char *)NULL;
7149 goto bad_substitution;
7152 if (want_indir)
7153 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
7154 else
7155 tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&PF_NOSPLIT2), &ind);
7157 if (tdesc)
7159 temp = tdesc->word;
7160 tflag = tdesc->flags;
7161 dispose_word_desc (tdesc);
7163 else
7164 temp = (char *)0;
7166 #if defined (ARRAY_VARS)
7167 if (valid_array_reference (name))
7168 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
7169 #endif
7171 var_is_set = temp != (char *)0;
7172 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
7174 /* Get the rest of the stuff inside the braces. */
7175 if (c && c != RBRACE)
7177 /* Extract the contents of the ${ ... } expansion
7178 according to the Posix.2 rules. */
7179 value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#') ? SX_POSIXEXP : 0);
7180 if (string[sindex] == RBRACE)
7181 sindex++;
7182 else
7183 goto bad_substitution;
7185 else
7186 value = (char *)NULL;
7188 *indexp = sindex;
7190 /* All the cases where an expansion can possibly generate an unbound
7191 variable error. */
7192 if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
7194 if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
7196 last_command_exit_value = EXECUTION_FAILURE;
7197 err_unboundvar (name);
7198 FREE (value);
7199 FREE (temp);
7200 free (name);
7201 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7205 /* If this is a substring spec, process it and add the result. */
7206 if (want_substring)
7208 temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7209 FREE (name);
7210 FREE (value);
7211 FREE (temp);
7213 if (temp1 == &expand_param_error)
7214 return (&expand_wdesc_error);
7215 else if (temp1 == &expand_param_fatal)
7216 return (&expand_wdesc_fatal);
7218 ret = alloc_word_desc ();
7219 ret->word = temp1;
7220 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7221 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7222 return ret;
7224 else if (want_patsub)
7226 temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7227 FREE (name);
7228 FREE (value);
7229 FREE (temp);
7231 if (temp1 == &expand_param_error)
7232 return (&expand_wdesc_error);
7233 else if (temp1 == &expand_param_fatal)
7234 return (&expand_wdesc_fatal);
7236 ret = alloc_word_desc ();
7237 ret->word = temp1;
7238 ret = alloc_word_desc ();
7239 ret->word = temp1;
7240 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7241 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7242 return ret;
7244 #if defined (CASEMOD_EXPANSIONS)
7245 else if (want_casemod)
7247 temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7248 FREE (name);
7249 FREE (value);
7250 FREE (temp);
7252 if (temp1 == &expand_param_error)
7253 return (&expand_wdesc_error);
7254 else if (temp1 == &expand_param_fatal)
7255 return (&expand_wdesc_fatal);
7257 ret = alloc_word_desc ();
7258 ret->word = temp1;
7259 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7260 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7261 return ret;
7263 #endif
7265 /* Do the right thing based on which character ended the variable name. */
7266 switch (c)
7268 default:
7269 case '\0':
7270 bad_substitution:
7271 report_error (_("%s: bad substitution"), string ? string : "??");
7272 FREE (value);
7273 FREE (temp);
7274 free (name);
7275 return &expand_wdesc_error;
7277 case RBRACE:
7278 break;
7280 case '#': /* ${param#[#]pattern} */
7281 case '%': /* ${param%[%]pattern} */
7282 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
7284 FREE (value);
7285 break;
7287 temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7288 free (temp);
7289 free (value);
7290 free (name);
7292 ret = alloc_word_desc ();
7293 ret->word = temp1;
7294 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7295 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7296 return ret;
7298 case '-':
7299 case '=':
7300 case '?':
7301 case '+':
7302 if (var_is_set && var_is_null == 0)
7304 /* If the operator is `+', we don't want the value of the named
7305 variable for anything, just the value of the right hand side. */
7306 if (c == '+')
7308 /* XXX -- if we're double-quoted and the named variable is "$@",
7309 we want to turn off any special handling of "$@" --
7310 we're not using it, so whatever is on the rhs applies. */
7311 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7312 *quoted_dollar_atp = 0;
7313 if (contains_dollar_at)
7314 *contains_dollar_at = 0;
7316 FREE (temp);
7317 if (value)
7319 /* From Posix discussion on austin-group list. Issue 221
7320 requires that backslashes escaping `}' inside
7321 double-quoted ${...} be removed. */
7322 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7323 quoted |= Q_DOLBRACE;
7324 ret = parameter_brace_expand_rhs (name, value, c,
7325 quoted,
7326 quoted_dollar_atp,
7327 contains_dollar_at);
7328 /* XXX - fix up later, esp. noting presence of
7329 W_HASQUOTEDNULL in ret->flags */
7330 free (value);
7332 else
7333 temp = (char *)NULL;
7335 else
7337 FREE (value);
7339 /* Otherwise do nothing; just use the value in TEMP. */
7341 else /* VAR not set or VAR is NULL. */
7343 FREE (temp);
7344 temp = (char *)NULL;
7345 if (c == '=' && var_is_special)
7347 report_error (_("$%s: cannot assign in this way"), name);
7348 free (name);
7349 free (value);
7350 return &expand_wdesc_error;
7352 else if (c == '?')
7354 parameter_brace_expand_error (name, value);
7355 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7357 else if (c != '+')
7359 /* XXX -- if we're double-quoted and the named variable is "$@",
7360 we want to turn off any special handling of "$@" --
7361 we're not using it, so whatever is on the rhs applies. */
7362 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7363 *quoted_dollar_atp = 0;
7364 if (contains_dollar_at)
7365 *contains_dollar_at = 0;
7367 /* From Posix discussion on austin-group list. Issue 221 requires
7368 that backslashes escaping `}' inside double-quoted ${...} be
7369 removed. */
7370 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7371 quoted |= Q_DOLBRACE;
7372 ret = parameter_brace_expand_rhs (name, value, c, quoted,
7373 quoted_dollar_atp,
7374 contains_dollar_at);
7375 /* XXX - fix up later, esp. noting presence of
7376 W_HASQUOTEDNULL in tdesc->flags */
7378 free (value);
7381 break;
7383 free (name);
7385 if (ret == 0)
7387 ret = alloc_word_desc ();
7388 ret->flags = tflag;
7389 ret->word = temp;
7391 return (ret);
7394 /* Expand a single ${xxx} expansion. The braces are optional. When
7395 the braces are used, parameter_brace_expand() does the work,
7396 possibly calling param_expand recursively. */
7397 static WORD_DESC *
7398 param_expand (string, sindex, quoted, expanded_something,
7399 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
7400 pflags)
7401 char *string;
7402 int *sindex, quoted, *expanded_something, *contains_dollar_at;
7403 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
7405 char *temp, *temp1, uerror[3];
7406 int zindex, t_index, expok;
7407 unsigned char c;
7408 intmax_t number;
7409 SHELL_VAR *var;
7410 WORD_LIST *list;
7411 WORD_DESC *tdesc, *ret;
7412 int tflag;
7414 zindex = *sindex;
7415 c = string[++zindex];
7417 temp = (char *)NULL;
7418 ret = tdesc = (WORD_DESC *)NULL;
7419 tflag = 0;
7421 /* Do simple cases first. Switch on what follows '$'. */
7422 switch (c)
7424 /* $0 .. $9? */
7425 case '0':
7426 case '1':
7427 case '2':
7428 case '3':
7429 case '4':
7430 case '5':
7431 case '6':
7432 case '7':
7433 case '8':
7434 case '9':
7435 temp1 = dollar_vars[TODIGIT (c)];
7436 if (unbound_vars_is_error && temp1 == (char *)NULL)
7438 uerror[0] = '$';
7439 uerror[1] = c;
7440 uerror[2] = '\0';
7441 last_command_exit_value = EXECUTION_FAILURE;
7442 err_unboundvar (uerror);
7443 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7445 if (temp1)
7446 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7447 ? quote_string (temp1)
7448 : quote_escapes (temp1);
7449 else
7450 temp = (char *)NULL;
7452 break;
7454 /* $$ -- pid of the invoking shell. */
7455 case '$':
7456 temp = itos (dollar_dollar_pid);
7457 break;
7459 /* $# -- number of positional parameters. */
7460 case '#':
7461 temp = itos (number_of_args ());
7462 break;
7464 /* $? -- return value of the last synchronous command. */
7465 case '?':
7466 temp = itos (last_command_exit_value);
7467 break;
7469 /* $- -- flags supplied to the shell on invocation or by `set'. */
7470 case '-':
7471 temp = which_set_flags ();
7472 break;
7474 /* $! -- Pid of the last asynchronous command. */
7475 case '!':
7476 /* If no asynchronous pids have been created, expand to nothing.
7477 If `set -u' has been executed, and no async processes have
7478 been created, this is an expansion error. */
7479 if (last_asynchronous_pid == NO_PID)
7481 if (expanded_something)
7482 *expanded_something = 0;
7483 temp = (char *)NULL;
7484 if (unbound_vars_is_error)
7486 uerror[0] = '$';
7487 uerror[1] = c;
7488 uerror[2] = '\0';
7489 last_command_exit_value = EXECUTION_FAILURE;
7490 err_unboundvar (uerror);
7491 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7494 else
7495 temp = itos (last_asynchronous_pid);
7496 break;
7498 /* The only difference between this and $@ is when the arg is quoted. */
7499 case '*': /* `$*' */
7500 list = list_rest_of_args ();
7502 #if 0
7503 /* According to austin-group posix proposal by Geoff Clare in
7504 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7506 "The shell shall write a message to standard error and
7507 immediately exit when it tries to expand an unset parameter
7508 other than the '@' and '*' special parameters."
7511 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7513 uerror[0] = '$';
7514 uerror[1] = '*';
7515 uerror[2] = '\0';
7516 last_command_exit_value = EXECUTION_FAILURE;
7517 err_unboundvar (uerror);
7518 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7520 #endif
7522 /* If there are no command-line arguments, this should just
7523 disappear if there are other characters in the expansion,
7524 even if it's quoted. */
7525 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7526 temp = (char *)NULL;
7527 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
7529 /* If we have "$*" we want to make a string of the positional
7530 parameters, separated by the first character of $IFS, and
7531 quote the whole string, including the separators. If IFS
7532 is unset, the parameters are separated by ' '; if $IFS is
7533 null, the parameters are concatenated. */
7534 temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
7535 if (temp)
7537 temp1 = quote_string (temp);
7538 if (*temp == 0)
7539 tflag |= W_HASQUOTEDNULL;
7540 free (temp);
7541 temp = temp1;
7544 else
7546 /* We check whether or not we're eventually going to split $* here,
7547 for example when IFS is empty and we are processing the rhs of
7548 an assignment statement. In that case, we don't separate the
7549 arguments at all. Otherwise, if the $* is not quoted it is
7550 identical to $@ */
7551 #if 1
7552 # if defined (HANDLE_MULTIBYTE)
7553 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7554 # else
7555 if (expand_no_split_dollar_star && ifs_firstc == 0)
7556 # endif
7557 temp = string_list_dollar_star (list);
7558 else
7559 temp = string_list_dollar_at (list, quoted);
7560 #else
7561 temp = string_list_dollar_at (list, quoted);
7562 #endif
7563 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7564 *contains_dollar_at = 1;
7567 dispose_words (list);
7568 break;
7570 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7571 means that we have to turn quoting off after we split into
7572 the individually quoted arguments so that the final split
7573 on the first character of $IFS is still done. */
7574 case '@': /* `$@' */
7575 list = list_rest_of_args ();
7577 #if 0
7578 /* According to austin-group posix proposal by Geoff Clare in
7579 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7581 "The shell shall write a message to standard error and
7582 immediately exit when it tries to expand an unset parameter
7583 other than the '@' and '*' special parameters."
7586 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7588 uerror[0] = '$';
7589 uerror[1] = '@';
7590 uerror[2] = '\0';
7591 last_command_exit_value = EXECUTION_FAILURE;
7592 err_unboundvar (uerror);
7593 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7595 #endif
7597 /* We want to flag the fact that we saw this. We can't turn
7598 off quoting entirely, because other characters in the
7599 string might need it (consider "\"$@\""), but we need some
7600 way to signal that the final split on the first character
7601 of $IFS should be done, even though QUOTED is 1. */
7602 /* XXX - should this test include Q_PATQUOTE? */
7603 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7604 *quoted_dollar_at_p = 1;
7605 if (contains_dollar_at)
7606 *contains_dollar_at = 1;
7608 #if 0
7609 if (pflags & PF_NOSPLIT2)
7610 temp = string_list_internal (quoted ? quote_list (list) : list, " ");
7611 else
7612 #endif
7613 /* We want to separate the positional parameters with the first
7614 character of $IFS in case $IFS is something other than a space.
7615 We also want to make sure that splitting is done no matter what --
7616 according to POSIX.2, this expands to a list of the positional
7617 parameters no matter what IFS is set to. */
7618 temp = string_list_dollar_at (list, quoted);
7620 dispose_words (list);
7621 break;
7623 case LBRACE:
7624 tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
7625 quoted_dollar_at_p,
7626 contains_dollar_at);
7628 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7629 return (tdesc);
7630 temp = tdesc ? tdesc->word : (char *)0;
7632 /* XXX */
7633 /* Quoted nulls should be removed if there is anything else
7634 in the string. */
7635 /* Note that we saw the quoted null so we can add one back at
7636 the end of this function if there are no other characters
7637 in the string, discard TEMP, and go on. The exception to
7638 this is when we have "${@}" and $1 is '', since $@ needs
7639 special handling. */
7640 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7642 if (had_quoted_null_p)
7643 *had_quoted_null_p = 1;
7644 if (*quoted_dollar_at_p == 0)
7646 free (temp);
7647 tdesc->word = temp = (char *)NULL;
7652 ret = tdesc;
7653 goto return0;
7655 /* Do command or arithmetic substitution. */
7656 case LPAREN:
7657 /* We have to extract the contents of this paren substitution. */
7658 t_index = zindex + 1;
7659 temp = extract_command_subst (string, &t_index, 0);
7660 zindex = t_index;
7662 /* For Posix.2-style `$(( ))' arithmetic substitution,
7663 extract the expression and pass it to the evaluator. */
7664 if (temp && *temp == LPAREN)
7666 char *temp2;
7667 temp1 = temp + 1;
7668 temp2 = savestring (temp1);
7669 t_index = strlen (temp2) - 1;
7671 if (temp2[t_index] != RPAREN)
7673 free (temp2);
7674 goto comsub;
7677 /* Cut off ending `)' */
7678 temp2[t_index] = '\0';
7680 if (chk_arithsub (temp2, t_index) == 0)
7682 free (temp2);
7683 #if 0
7684 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
7685 #endif
7686 goto comsub;
7689 /* Expand variables found inside the expression. */
7690 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7691 free (temp2);
7693 arithsub:
7694 /* No error messages. */
7695 this_command_name = (char *)NULL;
7696 number = evalexp (temp1, &expok);
7697 free (temp);
7698 free (temp1);
7699 if (expok == 0)
7701 if (interactive_shell == 0 && posixly_correct)
7703 last_command_exit_value = EXECUTION_FAILURE;
7704 return (&expand_wdesc_fatal);
7706 else
7707 return (&expand_wdesc_error);
7709 temp = itos (number);
7710 break;
7713 comsub:
7714 if (pflags & PF_NOCOMSUB)
7715 /* we need zindex+1 because string[zindex] == RPAREN */
7716 temp1 = substring (string, *sindex, zindex+1);
7717 else
7719 tdesc = command_substitute (temp, quoted);
7720 temp1 = tdesc ? tdesc->word : (char *)NULL;
7721 if (tdesc)
7722 dispose_word_desc (tdesc);
7724 FREE (temp);
7725 temp = temp1;
7726 break;
7728 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7729 away in a future bash release. */
7730 case '[':
7731 /* Extract the contents of this arithmetic substitution. */
7732 t_index = zindex + 1;
7733 temp = extract_arithmetic_subst (string, &t_index);
7734 zindex = t_index;
7735 if (temp == 0)
7737 temp = savestring (string);
7738 if (expanded_something)
7739 *expanded_something = 0;
7740 goto return0;
7743 /* Do initial variable expansion. */
7744 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7746 goto arithsub;
7748 default:
7749 /* Find the variable in VARIABLE_LIST. */
7750 temp = (char *)NULL;
7752 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7754 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7756 /* If this isn't a variable name, then just output the `$'. */
7757 if (temp1 == 0 || *temp1 == '\0')
7759 FREE (temp1);
7760 temp = (char *)xmalloc (2);
7761 temp[0] = '$';
7762 temp[1] = '\0';
7763 if (expanded_something)
7764 *expanded_something = 0;
7765 goto return0;
7768 /* If the variable exists, return its value cell. */
7769 var = find_variable (temp1);
7771 if (var && invisible_p (var) == 0 && var_isset (var))
7773 #if defined (ARRAY_VARS)
7774 if (assoc_p (var) || array_p (var))
7776 temp = array_p (var) ? array_reference (array_cell (var), 0)
7777 : assoc_reference (assoc_cell (var), "0");
7778 if (temp)
7779 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7780 ? quote_string (temp)
7781 : quote_escapes (temp);
7782 else if (unbound_vars_is_error)
7783 goto unbound_variable;
7785 else
7786 #endif
7788 temp = value_cell (var);
7790 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7791 ? quote_string (temp)
7792 : quote_escapes (temp);
7795 free (temp1);
7797 goto return0;
7800 temp = (char *)NULL;
7802 unbound_variable:
7803 if (unbound_vars_is_error)
7805 last_command_exit_value = EXECUTION_FAILURE;
7806 err_unboundvar (temp1);
7808 else
7810 free (temp1);
7811 goto return0;
7814 free (temp1);
7815 last_command_exit_value = EXECUTION_FAILURE;
7816 return ((unbound_vars_is_error && interactive_shell == 0)
7817 ? &expand_wdesc_fatal
7818 : &expand_wdesc_error);
7821 if (string[zindex])
7822 zindex++;
7824 return0:
7825 *sindex = zindex;
7827 if (ret == 0)
7829 ret = alloc_word_desc ();
7830 ret->flags = tflag; /* XXX */
7831 ret->word = temp;
7833 return ret;
7836 /* Make a word list which is the result of parameter and variable
7837 expansion, command substitution, arithmetic substitution, and
7838 quote removal of WORD. Return a pointer to a WORD_LIST which is
7839 the result of the expansion. If WORD contains a null word, the
7840 word list returned is also null.
7842 QUOTED contains flag values defined in shell.h.
7844 ISEXP is used to tell expand_word_internal that the word should be
7845 treated as the result of an expansion. This has implications for
7846 how IFS characters in the word are treated.
7848 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7849 they point to an integer value which receives information about expansion.
7850 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7851 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7852 else zero.
7854 This only does word splitting in the case of $@ expansion. In that
7855 case, we split on ' '. */
7857 /* Values for the local variable quoted_state. */
7858 #define UNQUOTED 0
7859 #define PARTIALLY_QUOTED 1
7860 #define WHOLLY_QUOTED 2
7862 static WORD_LIST *
7863 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7864 WORD_DESC *word;
7865 int quoted, isexp;
7866 int *contains_dollar_at;
7867 int *expanded_something;
7869 WORD_LIST *list;
7870 WORD_DESC *tword;
7872 /* The intermediate string that we build while expanding. */
7873 char *istring;
7875 /* The current size of the above object. */
7876 int istring_size;
7878 /* Index into ISTRING. */
7879 int istring_index;
7881 /* Temporary string storage. */
7882 char *temp, *temp1;
7884 /* The text of WORD. */
7885 register char *string;
7887 /* The size of STRING. */
7888 size_t string_size;
7890 /* The index into STRING. */
7891 int sindex;
7893 /* This gets 1 if we see a $@ while quoted. */
7894 int quoted_dollar_at;
7896 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7897 whether WORD contains no quoting characters, a partially quoted
7898 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7899 int quoted_state;
7901 /* State flags */
7902 int had_quoted_null;
7903 int has_dollar_at;
7904 int tflag;
7905 int pflags; /* flags passed to param_expand */
7907 int assignoff; /* If assignment, offset of `=' */
7909 register unsigned char c; /* Current character. */
7910 int t_index; /* For calls to string_extract_xxx. */
7912 char twochars[2];
7914 DECLARE_MBSTATE;
7916 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7917 istring[istring_index = 0] = '\0';
7918 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7919 quoted_state = UNQUOTED;
7921 string = word->word;
7922 if (string == 0)
7923 goto finished_with_string;
7924 /* Don't need the string length for the SADD... and COPY_ macros unless
7925 multibyte characters are possible. */
7926 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7928 if (contains_dollar_at)
7929 *contains_dollar_at = 0;
7931 assignoff = -1;
7933 /* Begin the expansion. */
7935 for (sindex = 0; ;)
7937 c = string[sindex];
7939 /* Case on toplevel character. */
7940 switch (c)
7942 case '\0':
7943 goto finished_with_string;
7945 case CTLESC:
7946 sindex++;
7947 #if HANDLE_MULTIBYTE
7948 if (MB_CUR_MAX > 1 && string[sindex])
7950 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7952 else
7953 #endif
7955 temp = (char *)xmalloc (3);
7956 temp[0] = CTLESC;
7957 temp[1] = c = string[sindex];
7958 temp[2] = '\0';
7961 dollar_add_string:
7962 if (string[sindex])
7963 sindex++;
7965 add_string:
7966 if (temp)
7968 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7969 temp = (char *)0;
7972 break;
7974 #if defined (PROCESS_SUBSTITUTION)
7975 /* Process substitution. */
7976 case '<':
7977 case '>':
7979 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7981 sindex--; /* add_character: label increments sindex */
7982 goto add_character;
7984 else
7985 t_index = sindex + 1; /* skip past both '<' and LPAREN */
7987 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7988 sindex = t_index;
7990 /* If the process substitution specification is `<()', we want to
7991 open the pipe for writing in the child and produce output; if
7992 it is `>()', we want to open the pipe for reading in the child
7993 and consume input. */
7994 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
7996 FREE (temp1);
7998 goto dollar_add_string;
8000 #endif /* PROCESS_SUBSTITUTION */
8002 case '=':
8003 /* Posix.2 section 3.6.1 says that tildes following `=' in words
8004 which are not assignment statements are not expanded. If the
8005 shell isn't in posix mode, though, we perform tilde expansion
8006 on `likely candidate' unquoted assignment statements (flags
8007 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
8008 contains an unquoted :~ or =~. Something to think about: we
8009 now have a flag that says to perform tilde expansion on arguments
8010 to `assignment builtins' like declare and export that look like
8011 assignment statements. We now do tilde expansion on such words
8012 even in POSIX mode. */
8013 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
8015 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8016 goto add_ifs_character;
8017 else
8018 goto add_character;
8020 /* If we're not in posix mode or forcing assignment-statement tilde
8021 expansion, note where the `=' appears in the word and prepare to
8022 do tilde expansion following the first `='. */
8023 if ((word->flags & W_ASSIGNMENT) &&
8024 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8025 assignoff == -1 && sindex > 0)
8026 assignoff = sindex;
8027 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
8028 word->flags |= W_ITILDE;
8029 #if 0
8030 else if ((word->flags & W_ASSIGNMENT) &&
8031 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8032 string[sindex+1] == '~')
8033 word->flags |= W_ITILDE;
8034 #endif
8035 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8036 goto add_ifs_character;
8037 else
8038 goto add_character;
8040 case ':':
8041 if (word->flags & W_NOTILDE)
8043 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8044 goto add_ifs_character;
8045 else
8046 goto add_character;
8049 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
8050 string[sindex+1] == '~')
8051 word->flags |= W_ITILDE;
8053 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8054 goto add_ifs_character;
8055 else
8056 goto add_character;
8058 case '~':
8059 /* If the word isn't supposed to be tilde expanded, or we're not
8060 at the start of a word or after an unquoted : or = in an
8061 assignment statement, we don't do tilde expansion. */
8062 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
8063 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
8064 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8066 word->flags &= ~W_ITILDE;
8067 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
8068 goto add_ifs_character;
8069 else
8070 goto add_character;
8073 if (word->flags & W_ASSIGNRHS)
8074 tflag = 2;
8075 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
8076 tflag = 1;
8077 else
8078 tflag = 0;
8080 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
8082 word->flags &= ~W_ITILDE;
8084 if (temp && *temp && t_index > 0)
8086 temp1 = bash_tilde_expand (temp, tflag);
8087 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
8089 FREE (temp);
8090 FREE (temp1);
8091 goto add_character; /* tilde expansion failed */
8093 free (temp);
8094 temp = temp1;
8095 sindex += t_index;
8096 goto add_quoted_string; /* XXX was add_string */
8098 else
8100 FREE (temp);
8101 goto add_character;
8104 case '$':
8105 if (expanded_something)
8106 *expanded_something = 1;
8108 has_dollar_at = 0;
8109 pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
8110 if (word->flags & W_NOSPLIT2)
8111 pflags |= PF_NOSPLIT2;
8112 tword = param_expand (string, &sindex, quoted, expanded_something,
8113 &has_dollar_at, &quoted_dollar_at,
8114 &had_quoted_null, pflags);
8116 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
8118 free (string);
8119 free (istring);
8120 return ((tword == &expand_wdesc_error) ? &expand_word_error
8121 : &expand_word_fatal);
8123 if (contains_dollar_at && has_dollar_at)
8124 *contains_dollar_at = 1;
8126 if (tword && (tword->flags & W_HASQUOTEDNULL))
8127 had_quoted_null = 1;
8129 temp = tword->word;
8130 dispose_word_desc (tword);
8132 goto add_string;
8133 break;
8135 case '`': /* Backquoted command substitution. */
8137 t_index = sindex++;
8139 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
8140 /* The test of sindex against t_index is to allow bare instances of
8141 ` to pass through, for backwards compatibility. */
8142 if (temp == &extract_string_error || temp == &extract_string_fatal)
8144 if (sindex - 1 == t_index)
8146 sindex = t_index;
8147 goto add_character;
8149 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
8150 free (string);
8151 free (istring);
8152 return ((temp == &extract_string_error) ? &expand_word_error
8153 : &expand_word_fatal);
8156 if (expanded_something)
8157 *expanded_something = 1;
8159 if (word->flags & W_NOCOMSUB)
8160 /* sindex + 1 because string[sindex] == '`' */
8161 temp1 = substring (string, t_index, sindex + 1);
8162 else
8164 de_backslash (temp);
8165 tword = command_substitute (temp, quoted);
8166 temp1 = tword ? tword->word : (char *)NULL;
8167 if (tword)
8168 dispose_word_desc (tword);
8170 FREE (temp);
8171 temp = temp1;
8172 goto dollar_add_string;
8175 case '\\':
8176 if (string[sindex + 1] == '\n')
8178 sindex += 2;
8179 continue;
8182 c = string[++sindex];
8184 if (quoted & Q_HERE_DOCUMENT)
8185 tflag = CBSHDOC;
8186 else if (quoted & Q_DOUBLE_QUOTES)
8187 tflag = CBSDQUOTE;
8188 else
8189 tflag = 0;
8191 /* From Posix discussion on austin-group list: Backslash escaping
8192 a } in ${...} is removed. Issue 0000221 */
8193 if ((quoted & Q_DOLBRACE) && c == RBRACE)
8195 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8197 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
8199 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
8201 else if (c == 0)
8203 c = CTLNUL;
8204 sindex--; /* add_character: label increments sindex */
8205 goto add_character;
8207 else
8209 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8212 sindex++;
8213 add_twochars:
8214 /* BEFORE jumping here, we need to increment sindex if appropriate */
8215 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
8216 DEFAULT_ARRAY_SIZE);
8217 istring[istring_index++] = twochars[0];
8218 istring[istring_index++] = twochars[1];
8219 istring[istring_index] = '\0';
8221 break;
8223 case '"':
8224 #if 0
8225 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8226 #else
8227 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8228 #endif
8229 goto add_character;
8231 t_index = ++sindex;
8232 temp = string_extract_double_quoted (string, &sindex, 0);
8234 /* If the quotes surrounded the entire string, then the
8235 whole word was quoted. */
8236 quoted_state = (t_index == 1 && string[sindex] == '\0')
8237 ? WHOLLY_QUOTED
8238 : PARTIALLY_QUOTED;
8240 if (temp && *temp)
8242 tword = alloc_word_desc ();
8243 tword->word = temp;
8245 temp = (char *)NULL;
8247 has_dollar_at = 0;
8248 /* Need to get W_HASQUOTEDNULL flag through this function. */
8249 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
8251 if (list == &expand_word_error || list == &expand_word_fatal)
8253 free (istring);
8254 free (string);
8255 /* expand_word_internal has already freed temp_word->word
8256 for us because of the way it prints error messages. */
8257 tword->word = (char *)NULL;
8258 dispose_word (tword);
8259 return list;
8262 dispose_word (tword);
8264 /* "$@" (a double-quoted dollar-at) expands into nothing,
8265 not even a NULL word, when there are no positional
8266 parameters. */
8267 if (list == 0 && has_dollar_at)
8269 quoted_dollar_at++;
8270 break;
8273 /* If we get "$@", we know we have expanded something, so we
8274 need to remember it for the final split on $IFS. This is
8275 a special case; it's the only case where a quoted string
8276 can expand into more than one word. It's going to come back
8277 from the above call to expand_word_internal as a list with
8278 a single word, in which all characters are quoted and
8279 separated by blanks. What we want to do is to turn it back
8280 into a list for the next piece of code. */
8281 if (list)
8282 dequote_list (list);
8284 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
8285 had_quoted_null = 1;
8287 if (has_dollar_at)
8289 quoted_dollar_at++;
8290 if (contains_dollar_at)
8291 *contains_dollar_at = 1;
8292 if (expanded_something)
8293 *expanded_something = 1;
8296 else
8298 /* What we have is "". This is a minor optimization. */
8299 FREE (temp);
8300 list = (WORD_LIST *)NULL;
8303 /* The code above *might* return a list (consider the case of "$@",
8304 where it returns "$1", "$2", etc.). We can't throw away the
8305 rest of the list, and we have to make sure each word gets added
8306 as quoted. We test on tresult->next: if it is non-NULL, we
8307 quote the whole list, save it to a string with string_list, and
8308 add that string. We don't need to quote the results of this
8309 (and it would be wrong, since that would quote the separators
8310 as well), so we go directly to add_string. */
8311 if (list)
8313 if (list->next)
8315 #if 0
8316 if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
8317 temp = string_list_internal (quote_list (list), " ");
8318 else
8319 #endif
8320 /* Testing quoted_dollar_at makes sure that "$@" is
8321 split correctly when $IFS does not contain a space. */
8322 temp = quoted_dollar_at
8323 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
8324 : string_list (quote_list (list));
8325 dispose_words (list);
8326 goto add_string;
8328 else
8330 temp = savestring (list->word->word);
8331 tflag = list->word->flags;
8332 dispose_words (list);
8334 /* If the string is not a quoted null string, we want
8335 to remove any embedded unquoted CTLNUL characters.
8336 We do not want to turn quoted null strings back into
8337 the empty string, though. We do this because we
8338 want to remove any quoted nulls from expansions that
8339 contain other characters. For example, if we have
8340 x"$*"y or "x$*y" and there are no positional parameters,
8341 the $* should expand into nothing. */
8342 /* We use the W_HASQUOTEDNULL flag to differentiate the
8343 cases: a quoted null character as above and when
8344 CTLNUL is contained in the (non-null) expansion
8345 of some variable. We use the had_quoted_null flag to
8346 pass the value through this function to its caller. */
8347 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
8348 remove_quoted_nulls (temp); /* XXX */
8351 else
8352 temp = (char *)NULL;
8354 /* We do not want to add quoted nulls to strings that are only
8355 partially quoted; we can throw them away. */
8356 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
8357 continue;
8359 add_quoted_string:
8361 if (temp)
8363 temp1 = temp;
8364 temp = quote_string (temp);
8365 free (temp1);
8366 goto add_string;
8368 else
8370 /* Add NULL arg. */
8371 c = CTLNUL;
8372 sindex--; /* add_character: label increments sindex */
8373 goto add_character;
8376 /* break; */
8378 case '\'':
8379 #if 0
8380 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8381 #else
8382 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8383 #endif
8384 goto add_character;
8386 t_index = ++sindex;
8387 temp = string_extract_single_quoted (string, &sindex);
8389 /* If the entire STRING was surrounded by single quotes,
8390 then the string is wholly quoted. */
8391 quoted_state = (t_index == 1 && string[sindex] == '\0')
8392 ? WHOLLY_QUOTED
8393 : PARTIALLY_QUOTED;
8395 /* If all we had was '', it is a null expansion. */
8396 if (*temp == '\0')
8398 free (temp);
8399 temp = (char *)NULL;
8401 else
8402 remove_quoted_escapes (temp); /* ??? */
8404 /* We do not want to add quoted nulls to strings that are only
8405 partially quoted; such nulls are discarded. */
8406 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
8407 continue;
8409 /* If we have a quoted null expansion, add a quoted NULL to istring. */
8410 if (temp == 0)
8412 c = CTLNUL;
8413 sindex--; /* add_character: label increments sindex */
8414 goto add_character;
8416 else
8417 goto add_quoted_string;
8419 /* break; */
8421 default:
8422 /* This is the fix for " $@ " */
8423 add_ifs_character:
8424 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
8426 if (string[sindex]) /* from old goto dollar_add_string */
8427 sindex++;
8428 if (c == 0)
8430 c = CTLNUL;
8431 goto add_character;
8433 else
8435 #if HANDLE_MULTIBYTE
8436 if (MB_CUR_MAX > 1)
8437 sindex--;
8439 if (MB_CUR_MAX > 1)
8441 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
8443 else
8444 #endif
8446 twochars[0] = CTLESC;
8447 twochars[1] = c;
8448 goto add_twochars;
8453 SADD_MBCHAR (temp, string, sindex, string_size);
8455 add_character:
8456 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
8457 DEFAULT_ARRAY_SIZE);
8458 istring[istring_index++] = c;
8459 istring[istring_index] = '\0';
8461 /* Next character. */
8462 sindex++;
8466 finished_with_string:
8467 /* OK, we're ready to return. If we have a quoted string, and
8468 quoted_dollar_at is not set, we do no splitting at all; otherwise
8469 we split on ' '. The routines that call this will handle what to
8470 do if nothing has been expanded. */
8472 /* Partially and wholly quoted strings which expand to the empty
8473 string are retained as an empty arguments. Unquoted strings
8474 which expand to the empty string are discarded. The single
8475 exception is the case of expanding "$@" when there are no
8476 positional parameters. In that case, we discard the expansion. */
8478 /* Because of how the code that handles "" and '' in partially
8479 quoted strings works, we need to make ISTRING into a QUOTED_NULL
8480 if we saw quoting characters, but the expansion was empty.
8481 "" and '' are tossed away before we get to this point when
8482 processing partially quoted strings. This makes "" and $xxx""
8483 equivalent when xxx is unset. We also look to see whether we
8484 saw a quoted null from a ${} expansion and add one back if we
8485 need to. */
8487 /* If we expand to nothing and there were no single or double quotes
8488 in the word, we throw it away. Otherwise, we return a NULL word.
8489 The single exception is for $@ surrounded by double quotes when
8490 there are no positional parameters. In that case, we also throw
8491 the word away. */
8493 if (*istring == '\0')
8495 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
8497 istring[0] = CTLNUL;
8498 istring[1] = '\0';
8499 tword = make_bare_word (istring);
8500 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8501 list = make_word_list (tword, (WORD_LIST *)NULL);
8502 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8503 tword->flags |= W_QUOTED;
8505 /* According to sh, ksh, and Posix.2, if a word expands into nothing
8506 and a double-quoted "$@" appears anywhere in it, then the entire
8507 word is removed. */
8508 else if (quoted_state == UNQUOTED || quoted_dollar_at)
8509 list = (WORD_LIST *)NULL;
8510 #if 0
8511 else
8513 tword = make_bare_word (istring);
8514 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8515 tword->flags |= W_QUOTED;
8516 list = make_word_list (tword, (WORD_LIST *)NULL);
8518 #else
8519 else
8520 list = (WORD_LIST *)NULL;
8521 #endif
8523 else if (word->flags & W_NOSPLIT)
8525 tword = make_bare_word (istring);
8526 if (word->flags & W_ASSIGNMENT)
8527 tword->flags |= W_ASSIGNMENT; /* XXX */
8528 if (word->flags & W_COMPASSIGN)
8529 tword->flags |= W_COMPASSIGN; /* XXX */
8530 if (word->flags & W_NOGLOB)
8531 tword->flags |= W_NOGLOB; /* XXX */
8532 if (word->flags & W_NOEXPAND)
8533 tword->flags |= W_NOEXPAND; /* XXX */
8534 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8535 tword->flags |= W_QUOTED;
8536 if (had_quoted_null)
8537 tword->flags |= W_HASQUOTEDNULL;
8538 list = make_word_list (tword, (WORD_LIST *)NULL);
8540 else
8542 char *ifs_chars;
8544 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
8546 /* If we have $@, we need to split the results no matter what. If
8547 IFS is unset or NULL, string_list_dollar_at has separated the
8548 positional parameters with a space, so we split on space (we have
8549 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
8550 string_list_dollar_at has separated the positional parameters
8551 with the first character of $IFS, so we split on $IFS. */
8552 if (has_dollar_at && ifs_chars)
8553 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
8554 else
8556 tword = make_bare_word (istring);
8557 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8558 tword->flags |= W_QUOTED;
8559 if (word->flags & W_ASSIGNMENT)
8560 tword->flags |= W_ASSIGNMENT;
8561 if (word->flags & W_COMPASSIGN)
8562 tword->flags |= W_COMPASSIGN;
8563 if (word->flags & W_NOGLOB)
8564 tword->flags |= W_NOGLOB;
8565 if (word->flags & W_NOEXPAND)
8566 tword->flags |= W_NOEXPAND;
8567 if (had_quoted_null)
8568 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8569 list = make_word_list (tword, (WORD_LIST *)NULL);
8573 free (istring);
8574 return (list);
8577 /* **************************************************************** */
8578 /* */
8579 /* Functions for Quote Removal */
8580 /* */
8581 /* **************************************************************** */
8583 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
8584 backslash quoting rules for within double quotes or a here document. */
8585 char *
8586 string_quote_removal (string, quoted)
8587 char *string;
8588 int quoted;
8590 size_t slen;
8591 char *r, *result_string, *temp, *send;
8592 int sindex, tindex, dquote;
8593 unsigned char c;
8594 DECLARE_MBSTATE;
8596 /* The result can be no longer than the original string. */
8597 slen = strlen (string);
8598 send = string + slen;
8600 r = result_string = (char *)xmalloc (slen + 1);
8602 for (dquote = sindex = 0; c = string[sindex];)
8604 switch (c)
8606 case '\\':
8607 c = string[++sindex];
8608 if (c == 0)
8610 *r++ = '\\';
8611 break;
8613 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8614 *r++ = '\\';
8615 /* FALLTHROUGH */
8617 default:
8618 SCOPY_CHAR_M (r, string, send, sindex);
8619 break;
8621 case '\'':
8622 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8624 *r++ = c;
8625 sindex++;
8626 break;
8628 tindex = sindex + 1;
8629 temp = string_extract_single_quoted (string, &tindex);
8630 if (temp)
8632 strcpy (r, temp);
8633 r += strlen (r);
8634 free (temp);
8636 sindex = tindex;
8637 break;
8639 case '"':
8640 dquote = 1 - dquote;
8641 sindex++;
8642 break;
8645 *r = '\0';
8646 return (result_string);
8649 #if 0
8650 /* UNUSED */
8651 /* Perform quote removal on word WORD. This allocates and returns a new
8652 WORD_DESC *. */
8653 WORD_DESC *
8654 word_quote_removal (word, quoted)
8655 WORD_DESC *word;
8656 int quoted;
8658 WORD_DESC *w;
8659 char *t;
8661 t = string_quote_removal (word->word, quoted);
8662 w = alloc_word_desc ();
8663 w->word = t ? t : savestring ("");
8664 return (w);
8667 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8668 the members of the list are treated as if they are surrounded by
8669 double quotes. Return a new list, or NULL if LIST is NULL. */
8670 WORD_LIST *
8671 word_list_quote_removal (list, quoted)
8672 WORD_LIST *list;
8673 int quoted;
8675 WORD_LIST *result, *t, *tresult, *e;
8677 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8679 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8680 #if 0
8681 result = (WORD_LIST *) list_append (result, tresult);
8682 #else
8683 if (result == 0)
8684 result = e = tresult;
8685 else
8687 e->next = tresult;
8688 while (e->next)
8689 e = e->next;
8691 #endif
8693 return (result);
8695 #endif
8697 /*******************************************
8699 * Functions to perform word splitting *
8701 *******************************************/
8703 void
8704 setifs (v)
8705 SHELL_VAR *v;
8707 char *t;
8708 unsigned char uc;
8710 ifs_var = v;
8711 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8713 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8714 handle multibyte chars in IFS */
8715 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8716 for (t = ifs_value ; t && *t; t++)
8718 uc = *t;
8719 ifs_cmap[uc] = 1;
8722 #if defined (HANDLE_MULTIBYTE)
8723 if (ifs_value == 0)
8725 ifs_firstc[0] = '\0';
8726 ifs_firstc_len = 1;
8728 else
8730 size_t ifs_len;
8731 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8732 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8733 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8735 ifs_firstc[0] = ifs_value[0];
8736 ifs_firstc[1] = '\0';
8737 ifs_firstc_len = 1;
8739 else
8740 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8742 #else
8743 ifs_firstc = ifs_value ? *ifs_value : 0;
8744 #endif
8747 char *
8748 getifs ()
8750 return ifs_value;
8753 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8754 is not quoted. list_string () performs quote removal for us, even if we
8755 don't do any splitting. */
8756 WORD_LIST *
8757 word_split (w, ifs_chars)
8758 WORD_DESC *w;
8759 char *ifs_chars;
8761 WORD_LIST *result;
8763 if (w)
8765 char *xifs;
8767 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8768 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8770 else
8771 result = (WORD_LIST *)NULL;
8773 return (result);
8776 /* Perform word splitting on LIST and return the RESULT. It is possible
8777 to return (WORD_LIST *)NULL. */
8778 static WORD_LIST *
8779 word_list_split (list)
8780 WORD_LIST *list;
8782 WORD_LIST *result, *t, *tresult, *e;
8784 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8786 tresult = word_split (t->word, ifs_value);
8787 if (result == 0)
8788 result = e = tresult;
8789 else
8791 e->next = tresult;
8792 while (e->next)
8793 e = e->next;
8796 return (result);
8799 /**************************************************
8801 * Functions to expand an entire WORD_LIST *
8803 **************************************************/
8805 /* Do any word-expansion-specific cleanup and jump to top_level */
8806 static void
8807 exp_jump_to_top_level (v)
8808 int v;
8810 set_pipestatus_from_exit (last_command_exit_value);
8812 /* Cleanup code goes here. */
8813 expand_no_split_dollar_star = 0; /* XXX */
8814 expanding_redir = 0;
8815 assigning_in_environment = 0;
8817 if (parse_and_execute_level == 0)
8818 top_level_cleanup (); /* from sig.c */
8820 jump_to_top_level (v);
8823 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8824 ELIST, and set ELIST to the new list. */
8825 #define PREPEND_LIST(nlist, elist) \
8826 do { nlist->next = elist; elist = nlist; } while (0)
8828 /* Separate out any initial variable assignments from TLIST. If set -k has
8829 been executed, remove all assignment statements from TLIST. Initial
8830 variable assignments and other environment assignments are placed
8831 on SUBST_ASSIGN_VARLIST. */
8832 static WORD_LIST *
8833 separate_out_assignments (tlist)
8834 WORD_LIST *tlist;
8836 register WORD_LIST *vp, *lp;
8838 if (tlist == 0)
8839 return ((WORD_LIST *)NULL);
8841 if (subst_assign_varlist)
8842 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8844 subst_assign_varlist = (WORD_LIST *)NULL;
8845 vp = lp = tlist;
8847 /* Separate out variable assignments at the start of the command.
8848 Loop invariant: vp->next == lp
8849 Loop postcondition:
8850 lp = list of words left after assignment statements skipped
8851 tlist = original list of words
8853 while (lp && (lp->word->flags & W_ASSIGNMENT))
8855 vp = lp;
8856 lp = lp->next;
8859 /* If lp != tlist, we have some initial assignment statements.
8860 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8861 words and TLIST point to the remaining words. */
8862 if (lp != tlist)
8864 subst_assign_varlist = tlist;
8865 /* ASSERT(vp->next == lp); */
8866 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8867 tlist = lp; /* remainder of word list */
8870 /* vp == end of variable list */
8871 /* tlist == remainder of original word list without variable assignments */
8872 if (!tlist)
8873 /* All the words in tlist were assignment statements */
8874 return ((WORD_LIST *)NULL);
8876 /* ASSERT(tlist != NULL); */
8877 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8879 /* If the -k option is in effect, we need to go through the remaining
8880 words, separate out the assignment words, and place them on
8881 SUBST_ASSIGN_VARLIST. */
8882 if (place_keywords_in_env)
8884 WORD_LIST *tp; /* tp == running pointer into tlist */
8886 tp = tlist;
8887 lp = tlist->next;
8889 /* Loop Invariant: tp->next == lp */
8890 /* Loop postcondition: tlist == word list without assignment statements */
8891 while (lp)
8893 if (lp->word->flags & W_ASSIGNMENT)
8895 /* Found an assignment statement, add this word to end of
8896 subst_assign_varlist (vp). */
8897 if (!subst_assign_varlist)
8898 subst_assign_varlist = vp = lp;
8899 else
8901 vp->next = lp;
8902 vp = lp;
8905 /* Remove the word pointed to by LP from TLIST. */
8906 tp->next = lp->next;
8907 /* ASSERT(vp == lp); */
8908 lp->next = (WORD_LIST *)NULL;
8909 lp = tp->next;
8911 else
8913 tp = lp;
8914 lp = lp->next;
8918 return (tlist);
8921 #define WEXP_VARASSIGN 0x001
8922 #define WEXP_BRACEEXP 0x002
8923 #define WEXP_TILDEEXP 0x004
8924 #define WEXP_PARAMEXP 0x008
8925 #define WEXP_PATHEXP 0x010
8927 /* All of the expansions, including variable assignments at the start of
8928 the list. */
8929 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8931 /* All of the expansions except variable assignments at the start of
8932 the list. */
8933 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8935 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8936 expansion, command substitution, arithmetic expansion, word splitting, and
8937 quote removal. */
8938 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8940 /* Take the list of words in LIST and do the various substitutions. Return
8941 a new list of words which is the expanded list, and without things like
8942 variable assignments. */
8944 WORD_LIST *
8945 expand_words (list)
8946 WORD_LIST *list;
8948 return (expand_word_list_internal (list, WEXP_ALL));
8951 /* Same as expand_words (), but doesn't hack variable or environment
8952 variables. */
8953 WORD_LIST *
8954 expand_words_no_vars (list)
8955 WORD_LIST *list;
8957 return (expand_word_list_internal (list, WEXP_NOVARS));
8960 WORD_LIST *
8961 expand_words_shellexp (list)
8962 WORD_LIST *list;
8964 return (expand_word_list_internal (list, WEXP_SHELLEXP));
8967 static WORD_LIST *
8968 glob_expand_word_list (tlist, eflags)
8969 WORD_LIST *tlist;
8970 int eflags;
8972 char **glob_array, *temp_string;
8973 register int glob_index;
8974 WORD_LIST *glob_list, *output_list, *disposables, *next;
8975 WORD_DESC *tword;
8977 output_list = disposables = (WORD_LIST *)NULL;
8978 glob_array = (char **)NULL;
8979 while (tlist)
8981 /* For each word, either globbing is attempted or the word is
8982 added to orig_list. If globbing succeeds, the results are
8983 added to orig_list and the word (tlist) is added to the list
8984 of disposable words. If globbing fails and failed glob
8985 expansions are left unchanged (the shell default), the
8986 original word is added to orig_list. If globbing fails and
8987 failed glob expansions are removed, the original word is
8988 added to the list of disposable words. orig_list ends up
8989 in reverse order and requires a call to REVERSE_LIST to
8990 be set right. After all words are examined, the disposable
8991 words are freed. */
8992 next = tlist->next;
8994 /* If the word isn't an assignment and contains an unquoted
8995 pattern matching character, then glob it. */
8996 if ((tlist->word->flags & W_NOGLOB) == 0 &&
8997 unquoted_glob_pattern_p (tlist->word->word))
8999 glob_array = shell_glob_filename (tlist->word->word);
9001 /* Handle error cases.
9002 I don't think we should report errors like "No such file
9003 or directory". However, I would like to report errors
9004 like "Read failed". */
9006 if (glob_array == 0 || GLOB_FAILED (glob_array))
9008 glob_array = (char **)xmalloc (sizeof (char *));
9009 glob_array[0] = (char *)NULL;
9012 /* Dequote the current word in case we have to use it. */
9013 if (glob_array[0] == NULL)
9015 temp_string = dequote_string (tlist->word->word);
9016 free (tlist->word->word);
9017 tlist->word->word = temp_string;
9020 /* Make the array into a word list. */
9021 glob_list = (WORD_LIST *)NULL;
9022 for (glob_index = 0; glob_array[glob_index]; glob_index++)
9024 tword = make_bare_word (glob_array[glob_index]);
9025 tword->flags |= W_GLOBEXP; /* XXX */
9026 glob_list = make_word_list (tword, glob_list);
9029 if (glob_list)
9031 output_list = (WORD_LIST *)list_append (glob_list, output_list);
9032 PREPEND_LIST (tlist, disposables);
9034 else if (fail_glob_expansion != 0)
9036 report_error (_("no match: %s"), tlist->word->word);
9037 exp_jump_to_top_level (DISCARD);
9039 else if (allow_null_glob_expansion == 0)
9041 /* Failed glob expressions are left unchanged. */
9042 PREPEND_LIST (tlist, output_list);
9044 else
9046 /* Failed glob expressions are removed. */
9047 PREPEND_LIST (tlist, disposables);
9050 else
9052 /* Dequote the string. */
9053 temp_string = dequote_string (tlist->word->word);
9054 free (tlist->word->word);
9055 tlist->word->word = temp_string;
9056 PREPEND_LIST (tlist, output_list);
9059 strvec_dispose (glob_array);
9060 glob_array = (char **)NULL;
9062 tlist = next;
9065 if (disposables)
9066 dispose_words (disposables);
9068 if (output_list)
9069 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9071 return (output_list);
9074 #if defined (BRACE_EXPANSION)
9075 static WORD_LIST *
9076 brace_expand_word_list (tlist, eflags)
9077 WORD_LIST *tlist;
9078 int eflags;
9080 register char **expansions;
9081 char *temp_string;
9082 WORD_LIST *disposables, *output_list, *next;
9083 WORD_DESC *w;
9084 int eindex;
9086 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
9088 next = tlist->next;
9090 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9092 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
9093 PREPEND_LIST (tlist, output_list);
9094 continue;
9097 /* Only do brace expansion if the word has a brace character. If
9098 not, just add the word list element to BRACES and continue. In
9099 the common case, at least when running shell scripts, this will
9100 degenerate to a bunch of calls to `mbschr', and then what is
9101 basically a reversal of TLIST into BRACES, which is corrected
9102 by a call to REVERSE_LIST () on BRACES when the end of TLIST
9103 is reached. */
9104 if (mbschr (tlist->word->word, LBRACE))
9106 expansions = brace_expand (tlist->word->word);
9108 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
9110 w = make_word (temp_string);
9111 /* If brace expansion didn't change the word, preserve
9112 the flags. We may want to preserve the flags
9113 unconditionally someday -- XXX */
9114 if (STREQ (temp_string, tlist->word->word))
9115 w->flags = tlist->word->flags;
9116 output_list = make_word_list (w, output_list);
9117 free (expansions[eindex]);
9119 free (expansions);
9121 /* Add TLIST to the list of words to be freed after brace
9122 expansion has been performed. */
9123 PREPEND_LIST (tlist, disposables);
9125 else
9126 PREPEND_LIST (tlist, output_list);
9129 if (disposables)
9130 dispose_words (disposables);
9132 if (output_list)
9133 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9135 return (output_list);
9137 #endif
9139 #if defined (ARRAY_VARS)
9140 /* Take WORD, a compound associative array assignment, and internally run
9141 'declare -A w', where W is the variable name portion of WORD. */
9142 static int
9143 make_internal_declare (word, option)
9144 char *word;
9145 char *option;
9147 int t;
9148 WORD_LIST *wl;
9149 WORD_DESC *w;
9151 w = make_word (word);
9153 t = assignment (w->word, 0);
9154 w->word[t] = '\0';
9156 wl = make_word_list (w, (WORD_LIST *)NULL);
9157 wl = make_word_list (make_word (option), wl);
9159 return (declare_builtin (wl));
9161 #endif
9163 static WORD_LIST *
9164 shell_expand_word_list (tlist, eflags)
9165 WORD_LIST *tlist;
9166 int eflags;
9168 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
9169 int expanded_something, has_dollar_at;
9170 char *temp_string;
9172 /* We do tilde expansion all the time. This is what 1003.2 says. */
9173 new_list = (WORD_LIST *)NULL;
9174 for (orig_list = tlist; tlist; tlist = next)
9176 temp_string = tlist->word->word;
9178 next = tlist->next;
9180 #if defined (ARRAY_VARS)
9181 /* If this is a compound array assignment to a builtin that accepts
9182 such assignments (e.g., `declare'), take the assignment and perform
9183 it separately, handling the semantics of declarations inside shell
9184 functions. This avoids the double-evaluation of such arguments,
9185 because `declare' does some evaluation of compound assignments on
9186 its own. */
9187 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9189 int t;
9191 if (tlist->word->flags & W_ASSIGNASSOC)
9192 make_internal_declare (tlist->word->word, "-A");
9194 t = do_word_assignment (tlist->word, 0);
9195 if (t == 0)
9197 last_command_exit_value = EXECUTION_FAILURE;
9198 exp_jump_to_top_level (DISCARD);
9201 /* Now transform the word as ksh93 appears to do and go on */
9202 t = assignment (tlist->word->word, 0);
9203 tlist->word->word[t] = '\0';
9204 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
9206 #endif
9208 expanded_something = 0;
9209 expanded = expand_word_internal
9210 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
9212 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
9214 /* By convention, each time this error is returned,
9215 tlist->word->word has already been freed. */
9216 tlist->word->word = (char *)NULL;
9218 /* Dispose our copy of the original list. */
9219 dispose_words (orig_list);
9220 /* Dispose the new list we're building. */
9221 dispose_words (new_list);
9223 last_command_exit_value = EXECUTION_FAILURE;
9224 if (expanded == &expand_word_error)
9225 exp_jump_to_top_level (DISCARD);
9226 else
9227 exp_jump_to_top_level (FORCE_EOF);
9230 /* Don't split words marked W_NOSPLIT. */
9231 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
9233 temp_list = word_list_split (expanded);
9234 dispose_words (expanded);
9236 else
9238 /* If no parameter expansion, command substitution, process
9239 substitution, or arithmetic substitution took place, then
9240 do not do word splitting. We still have to remove quoted
9241 null characters from the result. */
9242 word_list_remove_quoted_nulls (expanded);
9243 temp_list = expanded;
9246 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
9247 new_list = (WORD_LIST *)list_append (expanded, new_list);
9250 if (orig_list)
9251 dispose_words (orig_list);
9253 if (new_list)
9254 new_list = REVERSE_LIST (new_list, WORD_LIST *);
9256 return (new_list);
9259 /* The workhorse for expand_words () and expand_words_no_vars ().
9260 First arg is LIST, a WORD_LIST of words.
9261 Second arg EFLAGS is a flags word controlling which expansions are
9262 performed.
9264 This does all of the substitutions: brace expansion, tilde expansion,
9265 parameter expansion, command substitution, arithmetic expansion,
9266 process substitution, word splitting, and pathname expansion, according
9267 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
9268 set, or for which no expansion is done, do not undergo word splitting.
9269 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
9270 static WORD_LIST *
9271 expand_word_list_internal (list, eflags)
9272 WORD_LIST *list;
9273 int eflags;
9275 WORD_LIST *new_list, *temp_list;
9276 int tint;
9278 if (list == 0)
9279 return ((WORD_LIST *)NULL);
9281 garglist = new_list = copy_word_list (list);
9282 if (eflags & WEXP_VARASSIGN)
9284 garglist = new_list = separate_out_assignments (new_list);
9285 if (new_list == 0)
9287 if (subst_assign_varlist)
9289 /* All the words were variable assignments, so they are placed
9290 into the shell's environment. */
9291 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
9293 this_command_name = (char *)NULL; /* no arithmetic errors */
9294 tint = do_word_assignment (temp_list->word, 0);
9295 /* Variable assignment errors in non-interactive shells
9296 running in Posix.2 mode cause the shell to exit. */
9297 if (tint == 0)
9299 last_command_exit_value = EXECUTION_FAILURE;
9300 if (interactive_shell == 0 && posixly_correct)
9301 exp_jump_to_top_level (FORCE_EOF);
9302 else
9303 exp_jump_to_top_level (DISCARD);
9306 dispose_words (subst_assign_varlist);
9307 subst_assign_varlist = (WORD_LIST *)NULL;
9309 return ((WORD_LIST *)NULL);
9313 /* Begin expanding the words that remain. The expansions take place on
9314 things that aren't really variable assignments. */
9316 #if defined (BRACE_EXPANSION)
9317 /* Do brace expansion on this word if there are any brace characters
9318 in the string. */
9319 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
9320 new_list = brace_expand_word_list (new_list, eflags);
9321 #endif /* BRACE_EXPANSION */
9323 /* Perform the `normal' shell expansions: tilde expansion, parameter and
9324 variable substitution, command substitution, arithmetic expansion,
9325 and word splitting. */
9326 new_list = shell_expand_word_list (new_list, eflags);
9328 /* Okay, we're almost done. Now let's just do some filename
9329 globbing. */
9330 if (new_list)
9332 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
9333 /* Glob expand the word list unless globbing has been disabled. */
9334 new_list = glob_expand_word_list (new_list, eflags);
9335 else
9336 /* Dequote the words, because we're not performing globbing. */
9337 new_list = dequote_list (new_list);
9340 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
9342 sh_wassign_func_t *assign_func;
9343 int is_special_builtin, is_builtin_or_func;
9345 /* If the remainder of the words expand to nothing, Posix.2 requires
9346 that the variable and environment assignments affect the shell's
9347 environment. */
9348 assign_func = new_list ? assign_in_env : do_word_assignment;
9349 tempenv_assign_error = 0;
9351 is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
9352 /* Posix says that special builtins exit if a variable assignment error
9353 occurs in an assignment preceding it. */
9354 is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
9356 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
9358 this_command_name = (char *)NULL;
9359 assigning_in_environment = (assign_func == assign_in_env);
9360 tint = (*assign_func) (temp_list->word, is_builtin_or_func);
9361 assigning_in_environment = 0;
9362 /* Variable assignment errors in non-interactive shells running
9363 in Posix.2 mode cause the shell to exit. */
9364 if (tint == 0)
9366 if (assign_func == do_word_assignment)
9368 last_command_exit_value = EXECUTION_FAILURE;
9369 if (interactive_shell == 0 && posixly_correct && is_special_builtin)
9370 exp_jump_to_top_level (FORCE_EOF);
9371 else
9372 exp_jump_to_top_level (DISCARD);
9374 else
9375 tempenv_assign_error++;
9379 dispose_words (subst_assign_varlist);
9380 subst_assign_varlist = (WORD_LIST *)NULL;
9383 #if 0
9384 tint = list_length (new_list) + 1;
9385 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
9386 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
9387 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
9388 glob_argv_flags[tint] = '\0';
9389 #endif
9391 return (new_list);