GNU Bash 4.0-rc1 as released on ftp.gnu.org.
[bash.git] / subst.c
blob13e960dde562a167d3cb5afb5f11a8713577da62
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-2009 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 "flags.h"
46 #include "jobs.h"
47 #include "execute_cmd.h"
48 #include "filecntl.h"
49 #include "trap.h"
50 #include "pathexp.h"
51 #include "mailcheck.h"
53 #include "shmbutil.h"
55 #include "builtins/getopt.h"
56 #include "builtins/common.h"
58 #include "builtins/builtext.h"
60 #include <tilde/tilde.h>
61 #include <glob/strmatch.h>
63 #if !defined (errno)
64 extern int errno;
65 #endif /* !errno */
67 /* The size that strings change by. */
68 #define DEFAULT_INITIAL_ARRAY_SIZE 112
69 #define DEFAULT_ARRAY_SIZE 128
71 /* Variable types. */
72 #define VT_VARIABLE 0
73 #define VT_POSPARMS 1
74 #define VT_ARRAYVAR 2
75 #define VT_ARRAYMEMBER 3
76 #define VT_ASSOCVAR 4
78 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
80 /* Flags for quoted_strchr */
81 #define ST_BACKSL 0x01
82 #define ST_CTLESC 0x02
83 #define ST_SQUOTE 0x04 /* unused yet */
84 #define ST_DQUOTE 0x08 /* unused yet */
86 /* Flags for the `pflags' argument to param_expand() */
87 #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
89 /* These defs make it easier to use the editor. */
90 #define LBRACE '{'
91 #define RBRACE '}'
92 #define LPAREN '('
93 #define RPAREN ')'
95 /* Evaluates to 1 if C is one of the shell's special parameters whose length
96 can be taken, but is also one of the special expansion characters. */
97 #define VALID_SPECIAL_LENGTH_PARAM(c) \
98 ((c) == '-' || (c) == '?' || (c) == '#')
100 /* Evaluates to 1 if C is one of the shell's special parameters for which an
101 indirect variable reference may be made. */
102 #define VALID_INDIR_PARAM(c) \
103 ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
105 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
106 in ${parameter[:]OPword}. */
107 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
109 /* Evaluates to 1 if this is one of the shell's special variables. */
110 #define SPECIAL_VAR(name, wi) \
111 ((DIGIT (*name) && all_digits (name)) || \
112 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
113 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
115 /* An expansion function that takes a string and a quoted flag and returns
116 a WORD_LIST *. Used as the type of the third argument to
117 expand_string_if_necessary(). */
118 typedef WORD_LIST *EXPFUNC __P((char *, int));
120 /* Process ID of the last command executed within command substitution. */
121 pid_t last_command_subst_pid = NO_PID;
122 pid_t current_command_subst_pid = NO_PID;
124 /* Variables used to keep track of the characters in IFS. */
125 SHELL_VAR *ifs_var;
126 char *ifs_value;
127 unsigned char ifs_cmap[UCHAR_MAX + 1];
129 #if defined (HANDLE_MULTIBYTE)
130 unsigned char ifs_firstc[MB_LEN_MAX];
131 size_t ifs_firstc_len;
132 #else
133 unsigned char ifs_firstc;
134 #endif
136 int assigning_in_environment;
138 /* Extern functions and variables from different files. */
139 extern int last_command_exit_value, last_command_exit_signal;
140 extern int subshell_environment;
141 extern int subshell_level, parse_and_execute_level;
142 extern int eof_encountered;
143 extern int return_catch_flag, return_catch_value;
144 extern pid_t dollar_dollar_pid;
145 extern int posixly_correct;
146 extern char *this_command_name;
147 extern struct fd_bitmap *current_fds_to_close;
148 extern int wordexp_only;
149 extern int expanding_redir;
150 extern int tempenv_assign_error;
152 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
153 extern wchar_t *wcsdup __P((const wchar_t *));
154 #endif
156 /* Non-zero means to allow unmatched globbed filenames to expand to
157 a null file. */
158 int allow_null_glob_expansion;
160 /* Non-zero means to throw an error when globbing fails to match anything. */
161 int fail_glob_expansion;
163 #if 0
164 /* Variables to keep track of which words in an expanded word list (the
165 output of expand_word_list_internal) are the result of globbing
166 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
167 (CURRENTLY UNUSED). */
168 char *glob_argv_flags;
169 static int glob_argv_flags_size;
170 #endif
172 static WORD_LIST expand_word_error, expand_word_fatal;
173 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
174 static char expand_param_error, expand_param_fatal;
175 static char extract_string_error, extract_string_fatal;
177 /* Tell the expansion functions to not longjmp back to top_level on fatal
178 errors. Enabled when doing completion and prompt string expansion. */
179 static int no_longjmp_on_fatal_error = 0;
181 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
182 $* on $IFS, primarily when doing assignment statements. */
183 static int expand_no_split_dollar_star = 0;
185 /* Used to hold a list of variable assignments preceding a command. Global
186 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
187 SIGCHLD trap. */
188 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
190 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
191 without any leading variable assignments. */
192 static WORD_LIST *garglist = (WORD_LIST *)NULL;
194 static char *quoted_substring __P((char *, int, int));
195 static int quoted_strlen __P((char *));
196 static char *quoted_strchr __P((char *, int, int));
198 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
199 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
200 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
201 static WORD_LIST *expand_string_internal __P((char *, int));
202 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
203 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
205 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
206 static char *make_quoted_char __P((int));
207 static WORD_LIST *quote_list __P((WORD_LIST *));
209 static int unquoted_substring __P((char *, char *));
210 static int unquoted_member __P((int, char *));
212 #if defined (ARRAY_VARS)
213 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
214 #endif
215 static int do_assignment_internal __P((const WORD_DESC *, int));
217 static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
218 static char *string_extract __P((char *, int *, char *, int));
219 static char *string_extract_double_quoted __P((char *, int *, int));
220 static inline char *string_extract_single_quoted __P((char *, int *));
221 static inline int skip_single_quoted __P((const char *, size_t, int));
222 static int skip_double_quoted __P((char *, size_t, int));
223 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
224 static char *extract_dollar_brace_string __P((char *, int *, int, int));
226 static char *pos_params __P((char *, int, int, int));
228 static unsigned char *mb_getcharlens __P((char *, int));
230 static char *remove_upattern __P((char *, char *, int));
231 #if defined (HANDLE_MULTIBYTE)
232 static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
233 #endif
234 static char *remove_pattern __P((char *, char *, int));
236 static int match_pattern_char __P((char *, char *));
237 static int match_upattern __P((char *, char *, int, char **, char **));
238 #if defined (HANDLE_MULTIBYTE)
239 static int match_pattern_wchar __P((wchar_t *, wchar_t *));
240 static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
241 #endif
242 static int match_pattern __P((char *, char *, int, char **, char **));
243 static int getpatspec __P((int, char *));
244 static char *getpattern __P((char *, int, int));
245 static char *variable_remove_pattern __P((char *, char *, int, int));
246 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
247 static char *parameter_list_remove_pattern __P((int, char *, int, int));
248 #ifdef ARRAY_VARS
249 static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int));
250 #endif
251 static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
253 static char *process_substitute __P((char *, int));
255 static char *read_comsub __P((int, int, int *));
257 #ifdef ARRAY_VARS
258 static arrayind_t array_length_reference __P((char *));
259 #endif
261 static int valid_brace_expansion_word __P((char *, int));
262 static int chk_atstar __P((char *, int, int *, int *));
263 static int chk_arithsub __P((const char *, int));
265 static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
266 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
267 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
268 static void parameter_brace_expand_error __P((char *, char *));
270 static int valid_length_expression __P((char *));
271 static intmax_t parameter_brace_expand_length __P((char *));
273 static char *skiparith __P((char *, int));
274 static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
275 static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
276 static char *mb_substring __P((char *, int, int));
277 static char *parameter_brace_substring __P((char *, char *, char *, int));
279 static char *pos_params_pat_subst __P((char *, char *, char *, int));
281 static char *parameter_brace_patsub __P((char *, char *, char *, int));
283 static char *pos_params_casemod __P((char *, char *, int, int));
284 static char *parameter_brace_casemod __P((char *, char *, int, char *, int));
286 static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
287 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
289 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
291 static WORD_LIST *word_list_split __P((WORD_LIST *));
293 static void exp_jump_to_top_level __P((int));
295 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
296 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
297 #ifdef BRACE_EXPANSION
298 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
299 #endif
300 #if defined (ARRAY_VARS)
301 static int make_internal_declare __P((char *, char *));
302 #endif
303 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
304 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
306 /* **************************************************************** */
307 /* */
308 /* Utility Functions */
309 /* */
310 /* **************************************************************** */
312 #ifdef INCLUDE_UNUSED
313 static char *
314 quoted_substring (string, start, end)
315 char *string;
316 int start, end;
318 register int len, l;
319 register char *result, *s, *r;
321 len = end - start;
323 /* Move to string[start], skipping quoted characters. */
324 for (s = string, l = 0; *s && l < start; )
326 if (*s == CTLESC)
328 s++;
329 continue;
331 l++;
332 if (*s == 0)
333 break;
336 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
338 /* Copy LEN characters, including quote characters. */
339 s = string + l;
340 for (l = 0; l < len; s++)
342 if (*s == CTLESC)
343 *r++ = *s++;
344 *r++ = *s;
345 l++;
346 if (*s == 0)
347 break;
349 *r = '\0';
350 return result;
352 #endif
354 #ifdef INCLUDE_UNUSED
355 /* Return the length of S, skipping over quoted characters */
356 static int
357 quoted_strlen (s)
358 char *s;
360 register char *p;
361 int i;
363 i = 0;
364 for (p = s; *p; p++)
366 if (*p == CTLESC)
368 p++;
369 if (*p == 0)
370 return (i + 1);
372 i++;
375 return i;
377 #endif
379 /* Find the first occurrence of character C in string S, obeying shell
380 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
381 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
382 escaped with CTLESC are skipped. */
383 static char *
384 quoted_strchr (s, c, flags)
385 char *s;
386 int c, flags;
388 register char *p;
390 for (p = s; *p; p++)
392 if (((flags & ST_BACKSL) && *p == '\\')
393 || ((flags & ST_CTLESC) && *p == CTLESC))
395 p++;
396 if (*p == '\0')
397 return ((char *)NULL);
398 continue;
400 else if (*p == c)
401 return p;
403 return ((char *)NULL);
406 /* Return 1 if CHARACTER appears in an unquoted portion of
407 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
408 static int
409 unquoted_member (character, string)
410 int character;
411 char *string;
413 size_t slen;
414 int sindex, c;
415 DECLARE_MBSTATE;
417 slen = strlen (string);
418 sindex = 0;
419 while (c = string[sindex])
421 if (c == character)
422 return (1);
424 switch (c)
426 default:
427 ADVANCE_CHAR (string, slen, sindex);
428 break;
430 case '\\':
431 sindex++;
432 if (string[sindex])
433 ADVANCE_CHAR (string, slen, sindex);
434 break;
436 case '\'':
437 sindex = skip_single_quoted (string, slen, ++sindex);
438 break;
440 case '"':
441 sindex = skip_double_quoted (string, slen, ++sindex);
442 break;
445 return (0);
448 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
449 static int
450 unquoted_substring (substr, string)
451 char *substr, *string;
453 size_t slen;
454 int sindex, c, sublen;
455 DECLARE_MBSTATE;
457 if (substr == 0 || *substr == '\0')
458 return (0);
460 slen = strlen (string);
461 sublen = strlen (substr);
462 for (sindex = 0; c = string[sindex]; )
464 if (STREQN (string + sindex, substr, sublen))
465 return (1);
467 switch (c)
469 case '\\':
470 sindex++;
472 if (string[sindex])
473 ADVANCE_CHAR (string, slen, sindex);
474 break;
476 case '\'':
477 sindex = skip_single_quoted (string, slen, ++sindex);
478 break;
480 case '"':
481 sindex = skip_double_quoted (string, slen, ++sindex);
482 break;
484 default:
485 ADVANCE_CHAR (string, slen, sindex);
486 break;
489 return (0);
492 /* Most of the substitutions must be done in parallel. In order
493 to avoid using tons of unclear goto's, I have some functions
494 for manipulating malloc'ed strings. They all take INDX, a
495 pointer to an integer which is the offset into the string
496 where manipulation is taking place. They also take SIZE, a
497 pointer to an integer which is the current length of the
498 character array for this string. */
500 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
501 of space allocated to TARGET. SOURCE can be NULL, in which
502 case nothing happens. Gets rid of SOURCE by freeing it.
503 Returns TARGET in case the location has changed. */
504 INLINE char *
505 sub_append_string (source, target, indx, size)
506 char *source, *target;
507 int *indx, *size;
509 if (source)
511 int srclen, n;
513 srclen = STRLEN (source);
514 if (srclen >= (int)(*size - *indx))
516 n = srclen + *indx;
517 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
518 target = (char *)xrealloc (target, (*size = n));
521 FASTCOPY (source, target + *indx, srclen);
522 *indx += srclen;
523 target[*indx] = '\0';
525 free (source);
527 return (target);
530 #if 0
531 /* UNUSED */
532 /* Append the textual representation of NUMBER to TARGET.
533 INDX and SIZE are as in SUB_APPEND_STRING. */
534 char *
535 sub_append_number (number, target, indx, size)
536 intmax_t number;
537 int *indx, *size;
538 char *target;
540 char *temp;
542 temp = itos (number);
543 return (sub_append_string (temp, target, indx, size));
545 #endif
547 /* Extract a substring from STRING, starting at SINDEX and ending with
548 one of the characters in CHARLIST. Don't make the ending character
549 part of the string. Leave SINDEX pointing at the ending character.
550 Understand about backslashes in the string. If (flags & SX_VARNAME)
551 is non-zero, and array variables have been compiled into the shell,
552 everything between a `[' and a corresponding `]' is skipped over.
553 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
554 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
555 contain a closing character from CHARLIST. */
556 static char *
557 string_extract (string, sindex, charlist, flags)
558 char *string;
559 int *sindex;
560 char *charlist;
561 int flags;
563 register int c, i;
564 int found;
565 size_t slen;
566 char *temp;
567 DECLARE_MBSTATE;
569 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
570 i = *sindex;
571 found = 0;
572 while (c = string[i])
574 if (c == '\\')
576 if (string[i + 1])
577 i++;
578 else
579 break;
581 #if defined (ARRAY_VARS)
582 else if ((flags & SX_VARNAME) && c == '[')
584 int ni;
585 /* If this is an array subscript, skip over it and continue. */
586 ni = skipsubscript (string, i);
587 if (string[ni] == ']')
588 i = ni;
590 #endif
591 else if (MEMBER (c, charlist))
593 found = 1;
594 break;
597 ADVANCE_CHAR (string, slen, i);
600 /* If we had to have a matching delimiter and didn't find one, return an
601 error and let the caller deal with it. */
602 if ((flags & SX_REQMATCH) && found == 0)
604 *sindex = i;
605 return (&extract_string_error);
608 temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
609 *sindex = i;
611 return (temp);
614 /* Extract the contents of STRING as if it is enclosed in double quotes.
615 SINDEX, when passed in, is the offset of the character immediately
616 following the opening double quote; on exit, SINDEX is left pointing after
617 the closing double quote. If STRIPDQ is non-zero, unquoted double
618 quotes are stripped and the string is terminated by a null byte.
619 Backslashes between the embedded double quotes are processed. If STRIPDQ
620 is zero, an unquoted `"' terminates the string. */
621 static char *
622 string_extract_double_quoted (string, sindex, stripdq)
623 char *string;
624 int *sindex, stripdq;
626 size_t slen;
627 char *send;
628 int j, i, t;
629 unsigned char c;
630 char *temp, *ret; /* The new string we return. */
631 int pass_next, backquote, si; /* State variables for the machine. */
632 int dquote;
633 DECLARE_MBSTATE;
635 slen = strlen (string + *sindex) + *sindex;
636 send = string + slen;
638 pass_next = backquote = dquote = 0;
639 temp = (char *)xmalloc (1 + slen - *sindex);
641 j = 0;
642 i = *sindex;
643 while (c = string[i])
645 /* Process a character that was quoted by a backslash. */
646 if (pass_next)
648 /* Posix.2 sez:
650 ``The backslash shall retain its special meaning as an escape
651 character only when followed by one of the characters:
652 $ ` " \ <newline>''.
654 If STRIPDQ is zero, we handle the double quotes here and let
655 expand_word_internal handle the rest. If STRIPDQ is non-zero,
656 we have already been through one round of backslash stripping,
657 and want to strip these backslashes only if DQUOTE is non-zero,
658 indicating that we are inside an embedded double-quoted string. */
660 /* If we are in an embedded quoted string, then don't strip
661 backslashes before characters for which the backslash
662 retains its special meaning, but remove backslashes in
663 front of other characters. If we are not in an
664 embedded quoted string, don't strip backslashes at all.
665 This mess is necessary because the string was already
666 surrounded by double quotes (and sh has some really weird
667 quoting rules).
668 The returned string will be run through expansion as if
669 it were double-quoted. */
670 if ((stripdq == 0 && c != '"') ||
671 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
672 temp[j++] = '\\';
673 pass_next = 0;
675 add_one_character:
676 COPY_CHAR_I (temp, j, string, send, i);
677 continue;
680 /* A backslash protects the next character. The code just above
681 handles preserving the backslash in front of any character but
682 a double quote. */
683 if (c == '\\')
685 pass_next++;
686 i++;
687 continue;
690 /* Inside backquotes, ``the portion of the quoted string from the
691 initial backquote and the characters up to the next backquote
692 that is not preceded by a backslash, having escape characters
693 removed, defines that command''. */
694 if (backquote)
696 if (c == '`')
697 backquote = 0;
698 temp[j++] = c;
699 i++;
700 continue;
703 if (c == '`')
705 temp[j++] = c;
706 backquote++;
707 i++;
708 continue;
711 /* Pass everything between `$(' and the matching `)' or a quoted
712 ${ ... } pair through according to the Posix.2 specification. */
713 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
715 int free_ret = 1;
717 si = i + 2;
718 if (string[i + 1] == LPAREN)
719 ret = extract_command_subst (string, &si, 0);
720 else
721 ret = extract_dollar_brace_string (string, &si, 1, 0);
723 temp[j++] = '$';
724 temp[j++] = string[i + 1];
726 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
727 is set. */
728 if (ret == 0 && no_longjmp_on_fatal_error)
730 free_ret = 0;
731 ret = string + i + 2;
734 for (t = 0; ret[t]; t++, j++)
735 temp[j] = ret[t];
736 temp[j] = string[si];
738 if (string[si])
740 j++;
741 i = si + 1;
743 else
744 i = si;
746 if (free_ret)
747 free (ret);
748 continue;
751 /* Add any character but a double quote to the quoted string we're
752 accumulating. */
753 if (c != '"')
754 goto add_one_character;
756 /* c == '"' */
757 if (stripdq)
759 dquote ^= 1;
760 i++;
761 continue;
764 break;
766 temp[j] = '\0';
768 /* Point to after the closing quote. */
769 if (c)
770 i++;
771 *sindex = i;
773 return (temp);
776 /* This should really be another option to string_extract_double_quoted. */
777 static int
778 skip_double_quoted (string, slen, sind)
779 char *string;
780 size_t slen;
781 int sind;
783 int c, i;
784 char *ret;
785 int pass_next, backquote, si;
786 DECLARE_MBSTATE;
788 pass_next = backquote = 0;
789 i = sind;
790 while (c = string[i])
792 if (pass_next)
794 pass_next = 0;
795 ADVANCE_CHAR (string, slen, i);
796 continue;
798 else if (c == '\\')
800 pass_next++;
801 i++;
802 continue;
804 else if (backquote)
806 if (c == '`')
807 backquote = 0;
808 ADVANCE_CHAR (string, slen, i);
809 continue;
811 else if (c == '`')
813 backquote++;
814 i++;
815 continue;
817 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
819 si = i + 2;
820 if (string[i + 1] == LPAREN)
821 ret = extract_command_subst (string, &si, SX_NOALLOC);
822 else
823 ret = extract_dollar_brace_string (string, &si, 1, SX_NOALLOC);
825 i = si + 1;
826 continue;
828 else if (c != '"')
830 ADVANCE_CHAR (string, slen, i);
831 continue;
833 else
834 break;
837 if (c)
838 i++;
840 return (i);
843 /* Extract the contents of STRING as if it is enclosed in single quotes.
844 SINDEX, when passed in, is the offset of the character immediately
845 following the opening single quote; on exit, SINDEX is left pointing after
846 the closing single quote. */
847 static inline char *
848 string_extract_single_quoted (string, sindex)
849 char *string;
850 int *sindex;
852 register int i;
853 size_t slen;
854 char *t;
855 DECLARE_MBSTATE;
857 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
858 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
859 i = *sindex;
860 while (string[i] && string[i] != '\'')
861 ADVANCE_CHAR (string, slen, i);
863 t = substring (string, *sindex, i);
865 if (string[i])
866 i++;
867 *sindex = i;
869 return (t);
872 static inline int
873 skip_single_quoted (string, slen, sind)
874 const char *string;
875 size_t slen;
876 int sind;
878 register int c;
879 DECLARE_MBSTATE;
881 c = sind;
882 while (string[c] && string[c] != '\'')
883 ADVANCE_CHAR (string, slen, c);
885 if (string[c])
886 c++;
887 return c;
890 /* Just like string_extract, but doesn't hack backslashes or any of
891 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
892 static char *
893 string_extract_verbatim (string, slen, sindex, charlist, flags)
894 char *string;
895 size_t slen;
896 int *sindex;
897 char *charlist;
898 int flags;
900 register int i = *sindex;
901 #if defined (HANDLE_MULTIBYTE)
902 size_t clen;
903 wchar_t *wcharlist;
904 #endif
905 int c;
906 char *temp;
907 DECLARE_MBSTATE;
909 if (charlist[0] == '\'' && charlist[1] == '\0')
911 temp = string_extract_single_quoted (string, sindex);
912 --*sindex; /* leave *sindex at separator character */
913 return temp;
916 i = *sindex;
917 #if 0
918 /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
919 this only if MB_CUR_MAX > 1. */
920 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
921 #endif
922 #if defined (HANDLE_MULTIBYTE)
923 clen = strlen (charlist);
924 wcharlist = 0;
925 #endif
926 while (c = string[i])
928 #if defined (HANDLE_MULTIBYTE)
929 size_t mblength;
930 #endif
931 if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
933 i += 2;
934 continue;
936 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
937 through, to protect the CTLNULs from later calls to
938 remove_quoted_nulls. */
939 else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
941 i += 2;
942 continue;
945 #if defined (HANDLE_MULTIBYTE)
946 mblength = MBLEN (string + i, slen - i);
947 if (mblength > 1)
949 wchar_t wc;
950 mblength = mbtowc (&wc, string + i, slen - i);
951 if (MB_INVALIDCH (mblength))
953 if (MEMBER (c, charlist))
954 break;
956 else
958 if (wcharlist == 0)
960 size_t len;
961 len = mbstowcs (wcharlist, charlist, 0);
962 if (len == -1)
963 len = 0;
964 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
965 mbstowcs (wcharlist, charlist, len + 1);
968 if (wcschr (wcharlist, wc))
969 break;
972 else
973 #endif
974 if (MEMBER (c, charlist))
975 break;
977 ADVANCE_CHAR (string, slen, i);
980 #if defined (HANDLE_MULTIBYTE)
981 FREE (wcharlist);
982 #endif
984 temp = substring (string, *sindex, i);
985 *sindex = i;
987 return (temp);
990 /* Extract the $( construct in STRING, and return a new string.
991 Start extracting at (SINDEX) as if we had just seen "$(".
992 Make (SINDEX) get the position of the matching ")". )
993 XFLAGS is additional flags to pass to other extraction functions, */
994 char *
995 extract_command_subst (string, sindex, xflags)
996 char *string;
997 int *sindex;
998 int xflags;
1000 if (string[*sindex] == '(') /*)*/
1001 return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
1002 else
1004 xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1005 return (xparse_dolparen (string, string+*sindex, sindex, xflags));
1009 /* Extract the $[ construct in STRING, and return a new string. (])
1010 Start extracting at (SINDEX) as if we had just seen "$[".
1011 Make (SINDEX) get the position of the matching "]". */
1012 char *
1013 extract_arithmetic_subst (string, sindex)
1014 char *string;
1015 int *sindex;
1017 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
1020 #if defined (PROCESS_SUBSTITUTION)
1021 /* Extract the <( or >( construct in STRING, and return a new string.
1022 Start extracting at (SINDEX) as if we had just seen "<(".
1023 Make (SINDEX) get the position of the matching ")". */ /*))*/
1024 char *
1025 extract_process_subst (string, starter, sindex)
1026 char *string;
1027 char *starter;
1028 int *sindex;
1030 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1032 #endif /* PROCESS_SUBSTITUTION */
1034 #if defined (ARRAY_VARS)
1035 /* This can be fooled by unquoted right parens in the passed string. If
1036 each caller verifies that the last character in STRING is a right paren,
1037 we don't even need to call extract_delimited_string. */
1038 char *
1039 extract_array_assignment_list (string, sindex)
1040 char *string;
1041 int *sindex;
1043 int slen;
1044 char *ret;
1046 slen = strlen (string); /* ( */
1047 if (string[slen - 1] == ')')
1049 ret = substring (string, *sindex, slen - 1);
1050 *sindex = slen - 1;
1051 return ret;
1053 return 0;
1055 #endif
1057 /* Extract and create a new string from the contents of STRING, a
1058 character string delimited with OPENER and CLOSER. SINDEX is
1059 the address of an int describing the current offset in STRING;
1060 it should point to just after the first OPENER found. On exit,
1061 SINDEX gets the position of the last character of the matching CLOSER.
1062 If OPENER is more than a single character, ALT_OPENER, if non-null,
1063 contains a character string that can also match CLOSER and thus
1064 needs to be skipped. */
1065 static char *
1066 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1067 char *string;
1068 int *sindex;
1069 char *opener, *alt_opener, *closer;
1070 int flags;
1072 int i, c, si;
1073 size_t slen;
1074 char *t, *result;
1075 int pass_character, nesting_level, in_comment;
1076 int len_closer, len_opener, len_alt_opener;
1077 DECLARE_MBSTATE;
1079 slen = strlen (string + *sindex) + *sindex;
1080 len_opener = STRLEN (opener);
1081 len_alt_opener = STRLEN (alt_opener);
1082 len_closer = STRLEN (closer);
1084 pass_character = in_comment = 0;
1086 nesting_level = 1;
1087 i = *sindex;
1089 while (nesting_level)
1091 c = string[i];
1093 if (c == 0)
1094 break;
1096 if (in_comment)
1098 if (c == '\n')
1099 in_comment = 0;
1100 ADVANCE_CHAR (string, slen, i);
1101 continue;
1104 if (pass_character) /* previous char was backslash */
1106 pass_character = 0;
1107 ADVANCE_CHAR (string, slen, i);
1108 continue;
1111 /* Not exactly right yet; should handle shell metacharacters and
1112 multibyte characters, too. */
1113 if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
1115 in_comment = 1;
1116 ADVANCE_CHAR (string, slen, i);
1117 continue;
1120 if (c == CTLESC || c == '\\')
1122 pass_character++;
1123 i++;
1124 continue;
1127 /* Process a nested OPENER. */
1128 if (STREQN (string + i, opener, len_opener))
1130 si = i + len_opener;
1131 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
1132 i = si + 1;
1133 continue;
1136 /* Process a nested ALT_OPENER */
1137 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1139 si = i + len_alt_opener;
1140 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
1141 i = si + 1;
1142 continue;
1145 /* If the current substring terminates the delimited string, decrement
1146 the nesting level. */
1147 if (STREQN (string + i, closer, len_closer))
1149 i += len_closer - 1; /* move to last byte of the closer */
1150 nesting_level--;
1151 if (nesting_level == 0)
1152 break;
1155 /* Pass old-style command substitution through verbatim. */
1156 if (c == '`')
1158 si = i + 1;
1159 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1160 i = si + 1;
1161 continue;
1164 /* Pass single-quoted and double-quoted strings through verbatim. */
1165 if (c == '\'' || c == '"')
1167 si = i + 1;
1168 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1169 : skip_double_quoted (string, slen, si);
1170 continue;
1173 /* move past this character, which was not special. */
1174 ADVANCE_CHAR (string, slen, i);
1177 if (c == 0 && nesting_level)
1179 if (no_longjmp_on_fatal_error == 0)
1181 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1182 last_command_exit_value = EXECUTION_FAILURE;
1183 exp_jump_to_top_level (DISCARD);
1185 else
1187 *sindex = i;
1188 return (char *)NULL;
1192 si = i - *sindex - len_closer + 1;
1193 if (flags & SX_NOALLOC)
1194 result = (char *)NULL;
1195 else
1197 result = (char *)xmalloc (1 + si);
1198 strncpy (result, string + *sindex, si);
1199 result[si] = '\0';
1201 *sindex = i;
1203 return (result);
1206 /* Extract a parameter expansion expression within ${ and } from STRING.
1207 Obey the Posix.2 rules for finding the ending `}': count braces while
1208 skipping over enclosed quoted strings and command substitutions.
1209 SINDEX is the address of an int describing the current offset in STRING;
1210 it should point to just after the first `{' found. On exit, SINDEX
1211 gets the position of the matching `}'. QUOTED is non-zero if this
1212 occurs inside double quotes. */
1213 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1214 static char *
1215 extract_dollar_brace_string (string, sindex, quoted, flags)
1216 char *string;
1217 int *sindex, quoted, flags;
1219 register int i, c;
1220 size_t slen;
1221 int pass_character, nesting_level, si;
1222 char *result, *t;
1223 DECLARE_MBSTATE;
1225 pass_character = 0;
1226 nesting_level = 1;
1227 slen = strlen (string + *sindex) + *sindex;
1229 i = *sindex;
1230 while (c = string[i])
1232 if (pass_character)
1234 pass_character = 0;
1235 ADVANCE_CHAR (string, slen, i);
1236 continue;
1239 /* CTLESCs and backslashes quote the next character. */
1240 if (c == CTLESC || c == '\\')
1242 pass_character++;
1243 i++;
1244 continue;
1247 if (string[i] == '$' && string[i+1] == LBRACE)
1249 nesting_level++;
1250 i += 2;
1251 continue;
1254 if (c == RBRACE)
1256 nesting_level--;
1257 if (nesting_level == 0)
1258 break;
1259 i++;
1260 continue;
1263 /* Pass the contents of old-style command substitutions through
1264 verbatim. */
1265 if (c == '`')
1267 si = i + 1;
1268 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1269 i = si + 1;
1270 continue;
1273 /* Pass the contents of new-style command substitutions and
1274 arithmetic substitutions through verbatim. */
1275 if (string[i] == '$' && string[i+1] == LPAREN)
1277 si = i + 2;
1278 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1279 i = si + 1;
1280 continue;
1283 /* Pass the contents of single-quoted and double-quoted strings
1284 through verbatim. */
1285 if (c == '\'' || c == '"')
1287 si = i + 1;
1288 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1289 : skip_double_quoted (string, slen, si);
1290 /* skip_XXX_quoted leaves index one past close quote */
1291 continue;
1294 /* move past this character, which was not special. */
1295 ADVANCE_CHAR (string, slen, i);
1298 if (c == 0 && nesting_level)
1300 if (no_longjmp_on_fatal_error == 0)
1301 { /* { */
1302 report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1303 last_command_exit_value = EXECUTION_FAILURE;
1304 exp_jump_to_top_level (DISCARD);
1306 else
1308 *sindex = i;
1309 return ((char *)NULL);
1313 result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1314 *sindex = i;
1316 return (result);
1319 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1320 STRING, and returns a pointer to it. */
1321 char *
1322 de_backslash (string)
1323 char *string;
1325 register size_t slen;
1326 register int i, j, prev_i;
1327 DECLARE_MBSTATE;
1329 slen = strlen (string);
1330 i = j = 0;
1332 /* Loop copying string[i] to string[j], i >= j. */
1333 while (i < slen)
1335 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1336 string[i + 1] == '$'))
1337 i++;
1338 prev_i = i;
1339 ADVANCE_CHAR (string, slen, i);
1340 if (j < prev_i)
1341 do string[j++] = string[prev_i++]; while (prev_i < i);
1342 else
1343 j = i;
1345 string[j] = '\0';
1347 return (string);
1350 #if 0
1351 /*UNUSED*/
1352 /* Replace instances of \! in a string with !. */
1353 void
1354 unquote_bang (string)
1355 char *string;
1357 register int i, j;
1358 register char *temp;
1360 temp = (char *)xmalloc (1 + strlen (string));
1362 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1364 if (string[i] == '\\' && string[i + 1] == '!')
1366 temp[j] = '!';
1367 i++;
1370 strcpy (string, temp);
1371 free (temp);
1373 #endif
1375 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1377 /* Skip characters in STRING until we find a character in DELIMS, and return
1378 the index of that character. START is the index into string at which we
1379 begin. This is similar in spirit to strpbrk, but it returns an index into
1380 STRING and takes a starting index. This little piece of code knows quite
1381 a lot of shell syntax. It's very similar to skip_double_quoted and other
1382 functions of that ilk. */
1384 skip_to_delim (string, start, delims, flags)
1385 char *string;
1386 int start;
1387 char *delims;
1388 int flags;
1390 int i, pass_next, backq, si, c, invert;
1391 size_t slen;
1392 char *temp;
1393 DECLARE_MBSTATE;
1395 slen = strlen (string + start) + start;
1396 if (flags & SD_NOJMP)
1397 no_longjmp_on_fatal_error = 1;
1398 invert = (flags & SD_INVERT);
1400 i = start;
1401 pass_next = backq = 0;
1402 while (c = string[i])
1404 if (pass_next)
1406 pass_next = 0;
1407 if (c == 0)
1408 CQ_RETURN(i);
1409 ADVANCE_CHAR (string, slen, i);
1410 continue;
1412 else if (c == '\\')
1414 pass_next = 1;
1415 i++;
1416 continue;
1418 else if (backq)
1420 if (c == '`')
1421 backq = 0;
1422 ADVANCE_CHAR (string, slen, i);
1423 continue;
1425 else if (c == '`')
1427 backq = 1;
1428 i++;
1429 continue;
1431 else if (invert == 0 && member (c, delims))
1432 break;
1433 else if (c == '\'' || c == '"')
1435 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1436 : skip_double_quoted (string, slen, ++i);
1437 /* no increment, the skip functions increment past the closing quote. */
1439 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1441 si = i + 2;
1442 if (string[si] == '\0')
1443 CQ_RETURN(si);
1445 if (string[i+1] == LPAREN)
1446 temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1447 else
1448 temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
1449 i = si;
1450 if (string[i] == '\0') /* don't increment i past EOS in loop */
1451 break;
1452 i++;
1453 continue;
1455 else if (invert && (member (c, delims) == 0))
1456 break;
1457 else
1458 ADVANCE_CHAR (string, slen, i);
1461 CQ_RETURN(i);
1464 #if defined (READLINE)
1465 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1466 an unclosed quoted string), or if the character at EINDEX is quoted
1467 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1468 single and double-quoted string parsing functions should not return an
1469 error if there are unclosed quotes or braces. The characters that this
1470 recognizes need to be the same as the contents of
1471 rl_completer_quote_characters. */
1474 char_is_quoted (string, eindex)
1475 char *string;
1476 int eindex;
1478 int i, pass_next, c;
1479 size_t slen;
1480 DECLARE_MBSTATE;
1482 slen = strlen (string);
1483 no_longjmp_on_fatal_error = 1;
1484 i = pass_next = 0;
1485 while (i <= eindex)
1487 c = string[i];
1489 if (pass_next)
1491 pass_next = 0;
1492 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1493 CQ_RETURN(1);
1494 ADVANCE_CHAR (string, slen, i);
1495 continue;
1497 else if (c == '\\')
1499 pass_next = 1;
1500 i++;
1501 continue;
1503 else if (c == '\'' || c == '"')
1505 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1506 : skip_double_quoted (string, slen, ++i);
1507 if (i > eindex)
1508 CQ_RETURN(1);
1509 /* no increment, the skip_xxx functions go one past end */
1511 else
1512 ADVANCE_CHAR (string, slen, i);
1515 CQ_RETURN(0);
1519 unclosed_pair (string, eindex, openstr)
1520 char *string;
1521 int eindex;
1522 char *openstr;
1524 int i, pass_next, openc, olen;
1525 size_t slen;
1526 DECLARE_MBSTATE;
1528 slen = strlen (string);
1529 olen = strlen (openstr);
1530 i = pass_next = openc = 0;
1531 while (i <= eindex)
1533 if (pass_next)
1535 pass_next = 0;
1536 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1537 return 0;
1538 ADVANCE_CHAR (string, slen, i);
1539 continue;
1541 else if (string[i] == '\\')
1543 pass_next = 1;
1544 i++;
1545 continue;
1547 else if (STREQN (string + i, openstr, olen))
1549 openc = 1 - openc;
1550 i += olen;
1552 else if (string[i] == '\'' || string[i] == '"')
1554 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1555 : skip_double_quoted (string, slen, i);
1556 if (i > eindex)
1557 return 0;
1559 else
1560 ADVANCE_CHAR (string, slen, i);
1562 return (openc);
1565 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1566 individual words. If DELIMS is NULL, the current value of $IFS is used
1567 to split the string, and the function follows the shell field splitting
1568 rules. SENTINEL is an index to look for. NWP, if non-NULL,
1569 gets the number of words in the returned list. CWP, if non-NULL, gets
1570 the index of the word containing SENTINEL. Non-whitespace chars in
1571 DELIMS delimit separate fields. */
1572 WORD_LIST *
1573 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1574 char *string;
1575 int slen;
1576 char *delims;
1577 int sentinel;
1578 int *nwp, *cwp;
1580 int ts, te, i, nw, cw, ifs_split;
1581 char *token, *d, *d2;
1582 WORD_LIST *ret, *tl;
1584 if (string == 0 || *string == '\0')
1586 if (nwp)
1587 *nwp = 0;
1588 if (cwp)
1589 *cwp = 0;
1590 return ((WORD_LIST *)NULL);
1593 d = (delims == 0) ? ifs_value : delims;
1594 ifs_split = delims == 0;
1596 /* Make d2 the non-whitespace characters in delims */
1597 d2 = 0;
1598 if (delims)
1600 size_t slength;
1601 #if defined (HANDLE_MULTIBYTE)
1602 size_t mblength = 1;
1603 #endif
1604 DECLARE_MBSTATE;
1606 slength = strlen (delims);
1607 d2 = (char *)xmalloc (slength + 1);
1608 i = ts = 0;
1609 while (delims[i])
1611 #if defined (HANDLE_MULTIBYTE)
1612 mbstate_t state_bak;
1613 state_bak = state;
1614 mblength = MBRLEN (delims + i, slength, &state);
1615 if (MB_INVALIDCH (mblength))
1616 state = state_bak;
1617 else if (mblength > 1)
1619 memcpy (d2 + ts, delims + i, mblength);
1620 ts += mblength;
1621 i += mblength;
1622 slength -= mblength;
1623 continue;
1625 #endif
1626 if (whitespace (delims[i]) == 0)
1627 d2[ts++] = delims[i];
1629 i++;
1630 slength--;
1632 d2[ts] = '\0';
1635 ret = (WORD_LIST *)NULL;
1637 /* Remove sequences of whitspace characters at the start of the string, as
1638 long as those characters are delimiters. */
1639 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1641 if (string[i] == '\0')
1642 return (ret);
1644 ts = i;
1645 nw = 0;
1646 cw = -1;
1647 while (1)
1649 te = skip_to_delim (string, ts, d, SD_NOJMP);
1651 /* If we have a non-whitespace delimiter character, use it to make a
1652 separate field. This is just about what $IFS splitting does and
1653 is closer to the behavior of the shell parser. */
1654 if (ts == te && d2 && member (string[ts], d2))
1656 te = ts + 1;
1657 /* If we're using IFS splitting, the non-whitespace delimiter char
1658 and any additional IFS whitespace delimits a field. */
1659 if (ifs_split)
1660 while (member (string[te], d) && spctabnl (string[te]))
1661 te++;
1662 else
1663 while (member (string[te], d2))
1664 te++;
1667 token = substring (string, ts, te);
1669 ret = add_string_to_list (token, ret);
1670 free (token);
1671 nw++;
1673 if (sentinel >= ts && sentinel <= te)
1674 cw = nw;
1676 /* If the cursor is at whitespace just before word start, set the
1677 sentinel word to the current word. */
1678 if (cwp && cw == -1 && sentinel == ts-1)
1679 cw = nw;
1681 /* If the cursor is at whitespace between two words, make a new, empty
1682 word, add it before (well, after, since the list is in reverse order)
1683 the word we just added, and set the current word to that one. */
1684 if (cwp && cw == -1 && sentinel < ts)
1686 tl = make_word_list (make_word (""), ret->next);
1687 ret->next = tl;
1688 cw = nw;
1689 nw++;
1692 if (string[te] == 0)
1693 break;
1695 i = te;
1696 while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
1697 i++;
1699 if (string[i])
1700 ts = i;
1701 else
1702 break;
1705 /* Special case for SENTINEL at the end of STRING. If we haven't found
1706 the word containing SENTINEL yet, and the index we're looking for is at
1707 the end of STRING, add an additional null argument and set the current
1708 word pointer to that. */
1709 if (cwp && cw == -1 && sentinel >= slen)
1711 if (whitespace (string[sentinel - 1]))
1713 token = "";
1714 ret = add_string_to_list (token, ret);
1715 nw++;
1717 cw = nw;
1720 if (nwp)
1721 *nwp = nw;
1722 if (cwp)
1723 *cwp = cw;
1725 return (REVERSE_LIST (ret, WORD_LIST *));
1727 #endif /* READLINE */
1729 #if 0
1730 /* UNUSED */
1731 /* Extract the name of the variable to bind to from the assignment string. */
1732 char *
1733 assignment_name (string)
1734 char *string;
1736 int offset;
1737 char *temp;
1739 offset = assignment (string, 0);
1740 if (offset == 0)
1741 return (char *)NULL;
1742 temp = substring (string, 0, offset);
1743 return (temp);
1745 #endif
1747 /* **************************************************************** */
1748 /* */
1749 /* Functions to convert strings to WORD_LISTs and vice versa */
1750 /* */
1751 /* **************************************************************** */
1753 /* Return a single string of all the words in LIST. SEP is the separator
1754 to put between individual elements of LIST in the output string. */
1755 char *
1756 string_list_internal (list, sep)
1757 WORD_LIST *list;
1758 char *sep;
1760 register WORD_LIST *t;
1761 char *result, *r;
1762 int word_len, sep_len, result_size;
1764 if (list == 0)
1765 return ((char *)NULL);
1767 /* Short-circuit quickly if we don't need to separate anything. */
1768 if (list->next == 0)
1769 return (savestring (list->word->word));
1771 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1772 sep_len = STRLEN (sep);
1773 result_size = 0;
1775 for (t = list; t; t = t->next)
1777 if (t != list)
1778 result_size += sep_len;
1779 result_size += strlen (t->word->word);
1782 r = result = (char *)xmalloc (result_size + 1);
1784 for (t = list; t; t = t->next)
1786 if (t != list && sep_len)
1788 if (sep_len > 1)
1790 FASTCOPY (sep, r, sep_len);
1791 r += sep_len;
1793 else
1794 *r++ = sep[0];
1797 word_len = strlen (t->word->word);
1798 FASTCOPY (t->word->word, r, word_len);
1799 r += word_len;
1802 *r = '\0';
1803 return (result);
1806 /* Return a single string of all the words present in LIST, separating
1807 each word with a space. */
1808 char *
1809 string_list (list)
1810 WORD_LIST *list;
1812 return (string_list_internal (list, " "));
1815 /* An external interface that can be used by the rest of the shell to
1816 obtain a string containing the first character in $IFS. Handles all
1817 the multibyte complications. If LENP is non-null, it is set to the
1818 length of the returned string. */
1819 char *
1820 ifs_firstchar (lenp)
1821 int *lenp;
1823 char *ret;
1824 int len;
1826 ret = xmalloc (MB_LEN_MAX + 1);
1827 #if defined (HANDLE_MULTIBYTE)
1828 if (ifs_firstc_len == 1)
1830 ret[0] = ifs_firstc[0];
1831 ret[1] = '\0';
1832 len = ret[0] ? 1 : 0;
1834 else
1836 memcpy (ret, ifs_firstc, ifs_firstc_len);
1837 ret[len = ifs_firstc_len] = '\0';
1839 #else
1840 ret[0] = ifs_firstc;
1841 ret[1] = '\0';
1842 len = ret[0] ? 0 : 1;
1843 #endif
1845 if (lenp)
1846 *lenp = len;
1848 return ret;
1851 /* Return a single string of all the words present in LIST, obeying the
1852 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1853 expansion [of $*] appears within a double quoted string, it expands
1854 to a single field with the value of each parameter separated by the
1855 first character of the IFS variable, or by a <space> if IFS is unset." */
1856 char *
1857 string_list_dollar_star (list)
1858 WORD_LIST *list;
1860 char *ret;
1861 #if defined (HANDLE_MULTIBYTE)
1862 # if defined (__GNUC__)
1863 char sep[MB_CUR_MAX + 1];
1864 # else
1865 char *sep = 0;
1866 # endif
1867 #else
1868 char sep[2];
1869 #endif
1871 #if defined (HANDLE_MULTIBYTE)
1872 # if !defined (__GNUC__)
1873 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1874 # endif /* !__GNUC__ */
1875 if (ifs_firstc_len == 1)
1877 sep[0] = ifs_firstc[0];
1878 sep[1] = '\0';
1880 else
1882 memcpy (sep, ifs_firstc, ifs_firstc_len);
1883 sep[ifs_firstc_len] = '\0';
1885 #else
1886 sep[0] = ifs_firstc;
1887 sep[1] = '\0';
1888 #endif
1890 ret = string_list_internal (list, sep);
1891 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1892 free (sep);
1893 #endif
1894 return ret;
1897 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1898 is non-zero, the $@ appears within double quotes, and we should quote
1899 the list before converting it into a string. If IFS is unset, and the
1900 word is not quoted, we just need to quote CTLESC and CTLNUL characters
1901 in the words in the list, because the default value of $IFS is
1902 <space><tab><newline>, IFS characters in the words in the list should
1903 also be split. If IFS is null, and the word is not quoted, we need
1904 to quote the words in the list to preserve the positional parameters
1905 exactly. */
1906 char *
1907 string_list_dollar_at (list, quoted)
1908 WORD_LIST *list;
1909 int quoted;
1911 char *ifs, *ret;
1912 #if defined (HANDLE_MULTIBYTE)
1913 # if defined (__GNUC__)
1914 char sep[MB_CUR_MAX + 1];
1915 # else
1916 char *sep = 0;
1917 # endif /* !__GNUC__ */
1918 #else
1919 char sep[2];
1920 #endif
1921 WORD_LIST *tlist;
1923 /* XXX this could just be ifs = ifs_value; */
1924 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
1926 #if defined (HANDLE_MULTIBYTE)
1927 # if !defined (__GNUC__)
1928 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1929 # endif /* !__GNUC__ */
1930 if (ifs && *ifs)
1932 if (ifs_firstc_len == 1)
1934 sep[0] = ifs_firstc[0];
1935 sep[1] = '\0';
1937 else
1939 memcpy (sep, ifs_firstc, ifs_firstc_len);
1940 sep[ifs_firstc_len] = '\0';
1943 else
1945 sep[0] = ' ';
1946 sep[1] = '\0';
1948 #else
1949 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1950 sep[1] = '\0';
1951 #endif
1953 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
1954 it now that quote_escapes quotes spaces */
1955 #if 0
1956 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1957 #else
1958 tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1959 #endif
1960 ? quote_list (list)
1961 : list_quote_escapes (list);
1963 ret = string_list_internal (tlist, sep);
1964 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1965 free (sep);
1966 #endif
1967 return ret;
1970 /* Turn the positional paramters into a string, understanding quoting and
1971 the various subtleties of using the first character of $IFS as the
1972 separator. Calls string_list_dollar_at, string_list_dollar_star, and
1973 string_list as appropriate. */
1974 char *
1975 string_list_pos_params (pchar, list, quoted)
1976 int pchar;
1977 WORD_LIST *list;
1978 int quoted;
1980 char *ret;
1981 WORD_LIST *tlist;
1983 if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
1985 tlist = quote_list (list);
1986 word_list_remove_quoted_nulls (tlist);
1987 ret = string_list_dollar_star (tlist);
1989 else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
1991 tlist = quote_list (list);
1992 word_list_remove_quoted_nulls (tlist);
1993 ret = string_list (tlist);
1995 else if (pchar == '*')
1997 /* Even when unquoted, string_list_dollar_star does the right thing
1998 making sure that the first character of $IFS is used as the
1999 separator. */
2000 ret = string_list_dollar_star (list);
2002 else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
2003 /* We use string_list_dollar_at, but only if the string is quoted, since
2004 that quotes the escapes if it's not, which we don't want. We could
2005 use string_list (the old code did), but that doesn't do the right
2006 thing if the first character of $IFS is not a space. We use
2007 string_list_dollar_star if the string is unquoted so we make sure that
2008 the elements of $@ are separated by the first character of $IFS for
2009 later splitting. */
2010 ret = string_list_dollar_at (list, quoted);
2011 else if (pchar == '@')
2012 ret = string_list_dollar_star (list);
2013 else
2014 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
2016 return ret;
2019 /* Return the list of words present in STRING. Separate the string into
2020 words at any of the characters found in SEPARATORS. If QUOTED is
2021 non-zero then word in the list will have its quoted flag set, otherwise
2022 the quoted flag is left as make_word () deemed fit.
2024 This obeys the P1003.2 word splitting semantics. If `separators' is
2025 exactly <space><tab><newline>, then the splitting algorithm is that of
2026 the Bourne shell, which treats any sequence of characters from `separators'
2027 as a delimiter. If IFS is unset, which results in `separators' being set
2028 to "", no splitting occurs. If separators has some other value, the
2029 following rules are applied (`IFS white space' means zero or more
2030 occurrences of <space>, <tab>, or <newline>, as long as those characters
2031 are in `separators'):
2033 1) IFS white space is ignored at the start and the end of the
2034 string.
2035 2) Each occurrence of a character in `separators' that is not
2036 IFS white space, along with any adjacent occurrences of
2037 IFS white space delimits a field.
2038 3) Any nonzero-length sequence of IFS white space delimits a field.
2041 /* BEWARE! list_string strips null arguments. Don't call it twice and
2042 expect to have "" preserved! */
2044 /* This performs word splitting and quoted null character removal on
2045 STRING. */
2046 #define issep(c) \
2047 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2048 : (c) == (separators)[0]) \
2049 : 0)
2051 WORD_LIST *
2052 list_string (string, separators, quoted)
2053 register char *string, *separators;
2054 int quoted;
2056 WORD_LIST *result;
2057 WORD_DESC *t;
2058 char *current_word, *s;
2059 int sindex, sh_style_split, whitesep, xflags;
2060 size_t slen;
2062 if (!string || !*string)
2063 return ((WORD_LIST *)NULL);
2065 sh_style_split = separators && separators[0] == ' ' &&
2066 separators[1] == '\t' &&
2067 separators[2] == '\n' &&
2068 separators[3] == '\0';
2069 for (xflags = 0, s = ifs_value; s && *s; s++)
2071 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2072 else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2075 slen = 0;
2076 /* Remove sequences of whitespace at the beginning of STRING, as
2077 long as those characters appear in IFS. Do not do this if
2078 STRING is quoted or if there are no separator characters. */
2079 if (!quoted || !separators || !*separators)
2081 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
2083 if (!*s)
2084 return ((WORD_LIST *)NULL);
2086 string = s;
2089 /* OK, now STRING points to a word that does not begin with white space.
2090 The splitting algorithm is:
2091 extract a word, stopping at a separator
2092 skip sequences of spc, tab, or nl as long as they are separators
2093 This obeys the field splitting rules in Posix.2. */
2094 slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
2095 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
2097 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2098 unless multibyte chars are possible. */
2099 current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
2100 if (current_word == 0)
2101 break;
2103 /* If we have a quoted empty string, add a quoted null argument. We
2104 want to preserve the quoted null character iff this is a quoted
2105 empty string; otherwise the quoted null characters are removed
2106 below. */
2107 if (QUOTED_NULL (current_word))
2109 t = alloc_word_desc ();
2110 t->word = make_quoted_char ('\0');
2111 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2112 result = make_word_list (t, result);
2114 else if (current_word[0] != '\0')
2116 /* If we have something, then add it regardless. However,
2117 perform quoted null character removal on the current word. */
2118 remove_quoted_nulls (current_word);
2119 result = add_string_to_list (current_word, result);
2120 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
2121 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2122 result->word->flags |= W_QUOTED;
2125 /* If we're not doing sequences of separators in the traditional
2126 Bourne shell style, then add a quoted null argument. */
2127 else if (!sh_style_split && !spctabnl (string[sindex]))
2129 t = alloc_word_desc ();
2130 t->word = make_quoted_char ('\0');
2131 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2132 result = make_word_list (t, result);
2135 free (current_word);
2137 /* Note whether or not the separator is IFS whitespace, used later. */
2138 whitesep = string[sindex] && spctabnl (string[sindex]);
2140 /* Move past the current separator character. */
2141 if (string[sindex])
2143 DECLARE_MBSTATE;
2144 ADVANCE_CHAR (string, slen, sindex);
2147 /* Now skip sequences of space, tab, or newline characters if they are
2148 in the list of separators. */
2149 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2150 sindex++;
2152 /* If the first separator was IFS whitespace and the current character
2153 is a non-whitespace IFS character, it should be part of the current
2154 field delimiter, not a separate delimiter that would result in an
2155 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2156 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2158 sindex++;
2159 /* An IFS character that is not IFS white space, along with any
2160 adjacent IFS white space, shall delimit a field. (SUSv3) */
2161 while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2162 sindex++;
2165 return (REVERSE_LIST (result, WORD_LIST *));
2168 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2169 ENDPTR is set to the first character after the word. This is used by
2170 the `read' builtin. This is never called with SEPARATORS != $IFS;
2171 it should be simplified.
2173 XXX - this function is very similar to list_string; they should be
2174 combined - XXX */
2175 char *
2176 get_word_from_string (stringp, separators, endptr)
2177 char **stringp, *separators, **endptr;
2179 register char *s;
2180 char *current_word;
2181 int sindex, sh_style_split, whitesep, xflags;
2182 size_t slen;
2184 if (!stringp || !*stringp || !**stringp)
2185 return ((char *)NULL);
2187 sh_style_split = separators && separators[0] == ' ' &&
2188 separators[1] == '\t' &&
2189 separators[2] == '\n' &&
2190 separators[3] == '\0';
2191 for (xflags = 0, s = ifs_value; s && *s; s++)
2193 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2194 if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2197 s = *stringp;
2198 slen = 0;
2200 /* Remove sequences of whitespace at the beginning of STRING, as
2201 long as those characters appear in IFS. */
2202 if (sh_style_split || !separators || !*separators)
2204 for (; *s && spctabnl (*s) && isifs (*s); s++);
2206 /* If the string is nothing but whitespace, update it and return. */
2207 if (!*s)
2209 *stringp = s;
2210 if (endptr)
2211 *endptr = s;
2212 return ((char *)NULL);
2216 /* OK, S points to a word that does not begin with white space.
2217 Now extract a word, stopping at a separator, save a pointer to
2218 the first character after the word, then skip sequences of spc,
2219 tab, or nl as long as they are separators.
2221 This obeys the field splitting rules in Posix.2. */
2222 sindex = 0;
2223 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2224 unless multibyte chars are possible. */
2225 slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2226 current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
2228 /* Set ENDPTR to the first character after the end of the word. */
2229 if (endptr)
2230 *endptr = s + sindex;
2232 /* Note whether or not the separator is IFS whitespace, used later. */
2233 whitesep = s[sindex] && spctabnl (s[sindex]);
2235 /* Move past the current separator character. */
2236 if (s[sindex])
2238 DECLARE_MBSTATE;
2239 ADVANCE_CHAR (s, slen, sindex);
2242 /* Now skip sequences of space, tab, or newline characters if they are
2243 in the list of separators. */
2244 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2245 sindex++;
2247 /* If the first separator was IFS whitespace and the current character is
2248 a non-whitespace IFS character, it should be part of the current field
2249 delimiter, not a separate delimiter that would result in an empty field.
2250 Look at POSIX.2, 3.6.5, (3)(b). */
2251 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2253 sindex++;
2254 /* An IFS character that is not IFS white space, along with any adjacent
2255 IFS white space, shall delimit a field. */
2256 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2257 sindex++;
2260 /* Update STRING to point to the next field. */
2261 *stringp = s + sindex;
2262 return (current_word);
2265 /* Remove IFS white space at the end of STRING. Start at the end
2266 of the string and walk backwards until the beginning of the string
2267 or we find a character that's not IFS white space and not CTLESC.
2268 Only let CTLESC escape a white space character if SAW_ESCAPE is
2269 non-zero. */
2270 char *
2271 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2272 char *string, *separators;
2273 int saw_escape;
2275 char *s;
2277 s = string + STRLEN (string) - 1;
2278 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2279 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2280 s--;
2281 *++s = '\0';
2282 return string;
2285 #if 0
2286 /* UNUSED */
2287 /* Split STRING into words at whitespace. Obeys shell-style quoting with
2288 backslashes, single and double quotes. */
2289 WORD_LIST *
2290 list_string_with_quotes (string)
2291 char *string;
2293 WORD_LIST *list;
2294 char *token, *s;
2295 size_t s_len;
2296 int c, i, tokstart, len;
2298 for (s = string; s && *s && spctabnl (*s); s++)
2300 if (s == 0 || *s == 0)
2301 return ((WORD_LIST *)NULL);
2303 s_len = strlen (s);
2304 tokstart = i = 0;
2305 list = (WORD_LIST *)NULL;
2306 while (1)
2308 c = s[i];
2309 if (c == '\\')
2311 i++;
2312 if (s[i])
2313 i++;
2315 else if (c == '\'')
2316 i = skip_single_quoted (s, s_len, ++i);
2317 else if (c == '"')
2318 i = skip_double_quoted (s, s_len, ++i);
2319 else if (c == 0 || spctabnl (c))
2321 /* We have found the end of a token. Make a word out of it and
2322 add it to the word list. */
2323 token = substring (s, tokstart, i);
2324 list = add_string_to_list (token, list);
2325 free (token);
2326 while (spctabnl (s[i]))
2327 i++;
2328 if (s[i])
2329 tokstart = i;
2330 else
2331 break;
2333 else
2334 i++; /* normal character */
2336 return (REVERSE_LIST (list, WORD_LIST *));
2338 #endif
2340 /********************************************************/
2341 /* */
2342 /* Functions to perform assignment statements */
2343 /* */
2344 /********************************************************/
2346 #if defined (ARRAY_VARS)
2347 static SHELL_VAR *
2348 do_compound_assignment (name, value, flags)
2349 char *name, *value;
2350 int flags;
2352 SHELL_VAR *v;
2353 int mklocal, mkassoc;
2354 WORD_LIST *list;
2356 mklocal = flags & ASS_MKLOCAL;
2357 mkassoc = flags & ASS_MKASSOC;
2359 if (mklocal && variable_context)
2361 v = find_variable (name);
2362 list = expand_compound_array_assignment (v, value, flags);
2363 if (mkassoc)
2364 v = make_local_assoc_variable (name);
2365 else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
2366 v = make_local_array_variable (name);
2367 assign_compound_array_list (v, list, flags);
2369 else
2370 v = assign_array_from_string (name, value, flags);
2372 return (v);
2374 #endif
2376 /* Given STRING, an assignment string, get the value of the right side
2377 of the `=', and bind it to the left side. If EXPAND is true, then
2378 perform parameter expansion, command substitution, and arithmetic
2379 expansion on the right-hand side. Perform tilde expansion in any
2380 case. Do not perform word splitting on the result of expansion. */
2381 static int
2382 do_assignment_internal (word, expand)
2383 const WORD_DESC *word;
2384 int expand;
2386 int offset, tlen, appendop, assign_list, aflags, retval;
2387 char *name, *value;
2388 SHELL_VAR *entry;
2389 #if defined (ARRAY_VARS)
2390 char *t;
2391 int ni;
2392 #endif
2393 const char *string;
2395 if (word == 0 || word->word == 0)
2396 return 0;
2398 appendop = assign_list = aflags = 0;
2399 string = word->word;
2400 offset = assignment (string, 0);
2401 name = savestring (string);
2402 value = (char *)NULL;
2404 if (name[offset] == '=')
2406 char *temp;
2408 if (name[offset - 1] == '+')
2410 appendop = 1;
2411 name[offset - 1] = '\0';
2414 name[offset] = 0; /* might need this set later */
2415 temp = name + offset + 1;
2416 tlen = STRLEN (temp);
2418 #if defined (ARRAY_VARS)
2419 if (expand && (word->flags & W_COMPASSIGN))
2421 assign_list = ni = 1;
2422 value = extract_array_assignment_list (temp, &ni);
2424 else
2425 #endif
2427 if (expand && temp[0])
2428 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2429 else
2430 value = savestring (temp);
2433 if (value == 0)
2435 value = (char *)xmalloc (1);
2436 value[0] = '\0';
2439 if (echo_command_at_execute)
2441 if (appendop)
2442 name[offset - 1] = '+';
2443 xtrace_print_assignment (name, value, assign_list, 1);
2444 if (appendop)
2445 name[offset - 1] = '\0';
2448 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
2450 if (appendop)
2451 aflags |= ASS_APPEND;
2453 #if defined (ARRAY_VARS)
2454 if (t = xstrchr (name, '[')) /*]*/
2456 if (assign_list)
2458 report_error (_("%s: cannot assign list to array member"), name);
2459 ASSIGN_RETURN (0);
2461 entry = assign_array_element (name, value, aflags);
2462 if (entry == 0)
2463 ASSIGN_RETURN (0);
2465 else if (assign_list)
2467 if (word->flags & W_ASSIGNARG)
2468 aflags |= ASS_MKLOCAL;
2469 if (word->flags & W_ASSIGNASSOC)
2470 aflags |= ASS_MKASSOC;
2471 entry = do_compound_assignment (name, value, aflags);
2473 else
2474 #endif /* ARRAY_VARS */
2475 entry = bind_variable (name, value, aflags);
2477 stupidly_hack_special_variables (name);
2479 #if 1
2480 /* Return 1 if the assignment seems to have been performed correctly. */
2481 if (entry == 0 || readonly_p (entry))
2482 retval = 0; /* assignment failure */
2483 else if (noassign_p (entry))
2485 last_command_exit_value = EXECUTION_FAILURE;
2486 retval = 1; /* error status, but not assignment failure */
2488 else
2489 retval = 1;
2491 if (entry && retval != 0 && noassign_p (entry) == 0)
2492 VUNSETATTR (entry, att_invisible);
2494 ASSIGN_RETURN (retval);
2495 #else
2496 if (entry)
2497 VUNSETATTR (entry, att_invisible);
2499 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2500 #endif
2503 /* Perform the assignment statement in STRING, and expand the
2504 right side by doing tilde, command and parameter expansion. */
2506 do_assignment (string)
2507 char *string;
2509 WORD_DESC td;
2511 td.flags = W_ASSIGNMENT;
2512 td.word = string;
2514 return do_assignment_internal (&td, 1);
2518 do_word_assignment (word)
2519 WORD_DESC *word;
2521 return do_assignment_internal (word, 1);
2524 /* Given STRING, an assignment string, get the value of the right side
2525 of the `=', and bind it to the left side. Do not perform any word
2526 expansions on the right hand side. */
2528 do_assignment_no_expand (string)
2529 char *string;
2531 WORD_DESC td;
2533 td.flags = W_ASSIGNMENT;
2534 td.word = string;
2536 return (do_assignment_internal (&td, 0));
2539 /***************************************************
2541 * Functions to manage the positional parameters *
2543 ***************************************************/
2545 /* Return the word list that corresponds to `$*'. */
2546 WORD_LIST *
2547 list_rest_of_args ()
2549 register WORD_LIST *list, *args;
2550 int i;
2552 /* Break out of the loop as soon as one of the dollar variables is null. */
2553 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2554 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2556 for (args = rest_of_args; args; args = args->next)
2557 list = make_word_list (make_bare_word (args->word->word), list);
2559 return (REVERSE_LIST (list, WORD_LIST *));
2563 number_of_args ()
2565 register WORD_LIST *list;
2566 int n;
2568 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2570 for (list = rest_of_args; list; list = list->next)
2571 n++;
2572 return n;
2575 /* Return the value of a positional parameter. This handles values > 10. */
2576 char *
2577 get_dollar_var_value (ind)
2578 intmax_t ind;
2580 char *temp;
2581 WORD_LIST *p;
2583 if (ind < 10)
2584 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2585 else /* We want something like ${11} */
2587 ind -= 10;
2588 for (p = rest_of_args; p && ind--; p = p->next)
2590 temp = p ? savestring (p->word->word) : (char *)NULL;
2592 return (temp);
2595 /* Make a single large string out of the dollar digit variables,
2596 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2597 case of "$*" with respect to IFS. */
2598 char *
2599 string_rest_of_args (dollar_star)
2600 int dollar_star;
2602 register WORD_LIST *list;
2603 char *string;
2605 list = list_rest_of_args ();
2606 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2607 dispose_words (list);
2608 return (string);
2611 /* Return a string containing the positional parameters from START to
2612 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2613 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2614 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2615 no quoting chars are added. */
2616 static char *
2617 pos_params (string, start, end, quoted)
2618 char *string;
2619 int start, end, quoted;
2621 WORD_LIST *save, *params, *h, *t;
2622 char *ret;
2623 int i;
2625 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2626 if (start == end)
2627 return ((char *)NULL);
2629 save = params = list_rest_of_args ();
2630 if (save == 0)
2631 return ((char *)NULL);
2633 if (start == 0) /* handle ${@:0[:x]} specially */
2635 t = make_word_list (make_word (dollar_vars[0]), params);
2636 save = params = t;
2639 for (i = 1; params && i < start; i++)
2640 params = params->next;
2641 if (params == 0)
2642 return ((char *)NULL);
2643 for (h = t = params; params && i < end; i++)
2645 t = params;
2646 params = params->next;
2649 t->next = (WORD_LIST *)NULL;
2651 ret = string_list_pos_params (string[0], h, quoted);
2653 if (t != params)
2654 t->next = params;
2656 dispose_words (save);
2657 return (ret);
2660 /******************************************************************/
2661 /* */
2662 /* Functions to expand strings to strings or WORD_LISTs */
2663 /* */
2664 /******************************************************************/
2666 #if defined (PROCESS_SUBSTITUTION)
2667 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
2668 #else
2669 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
2670 #endif
2672 /* If there are any characters in STRING that require full expansion,
2673 then call FUNC to expand STRING; otherwise just perform quote
2674 removal if necessary. This returns a new string. */
2675 static char *
2676 expand_string_if_necessary (string, quoted, func)
2677 char *string;
2678 int quoted;
2679 EXPFUNC *func;
2681 WORD_LIST *list;
2682 size_t slen;
2683 int i, saw_quote;
2684 char *ret;
2685 DECLARE_MBSTATE;
2687 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
2688 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
2689 i = saw_quote = 0;
2690 while (string[i])
2692 if (EXP_CHAR (string[i]))
2693 break;
2694 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2695 saw_quote = 1;
2696 ADVANCE_CHAR (string, slen, i);
2699 if (string[i])
2701 list = (*func) (string, quoted);
2702 if (list)
2704 ret = string_list (list);
2705 dispose_words (list);
2707 else
2708 ret = (char *)NULL;
2710 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2711 ret = string_quote_removal (string, quoted);
2712 else
2713 ret = savestring (string);
2715 return ret;
2718 static inline char *
2719 expand_string_to_string_internal (string, quoted, func)
2720 char *string;
2721 int quoted;
2722 EXPFUNC *func;
2724 WORD_LIST *list;
2725 char *ret;
2727 if (string == 0 || *string == '\0')
2728 return ((char *)NULL);
2730 list = (*func) (string, quoted);
2731 if (list)
2733 ret = string_list (list);
2734 dispose_words (list);
2736 else
2737 ret = (char *)NULL;
2739 return (ret);
2742 char *
2743 expand_string_to_string (string, quoted)
2744 char *string;
2745 int quoted;
2747 return (expand_string_to_string_internal (string, quoted, expand_string));
2750 char *
2751 expand_string_unsplit_to_string (string, quoted)
2752 char *string;
2753 int quoted;
2755 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2758 char *
2759 expand_assignment_string_to_string (string, quoted)
2760 char *string;
2761 int quoted;
2763 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
2766 char *
2767 expand_arith_string (string, quoted)
2768 char *string;
2769 int quoted;
2771 return (expand_string_if_necessary (string, quoted, expand_string));
2774 #if defined (COND_COMMAND)
2775 /* Just remove backslashes in STRING. Returns a new string. */
2776 char *
2777 remove_backslashes (string)
2778 char *string;
2780 char *r, *ret, *s;
2782 r = ret = (char *)xmalloc (strlen (string) + 1);
2783 for (s = string; s && *s; )
2785 if (*s == '\\')
2786 s++;
2787 if (*s == 0)
2788 break;
2789 *r++ = *s++;
2791 *r = '\0';
2792 return ret;
2795 /* This needs better error handling. */
2796 /* Expand W for use as an argument to a unary or binary operator in a
2797 [[...]] expression. If SPECIAL is 1, this is the rhs argument
2798 to the != or == operator, and should be treated as a pattern. In
2799 this case, we quote the string specially for the globbing code. If
2800 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
2801 be quoted appropriately for regcomp/regexec. The caller is responsible
2802 for removing the backslashes if the unquoted word is needed later. */
2803 char *
2804 cond_expand_word (w, special)
2805 WORD_DESC *w;
2806 int special;
2808 char *r, *p;
2809 WORD_LIST *l;
2810 int qflags;
2812 if (w->word == 0 || w->word[0] == '\0')
2813 return ((char *)NULL);
2815 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2816 if (l)
2818 if (special == 0)
2820 dequote_list (l);
2821 r = string_list (l);
2823 else
2825 qflags = QGLOB_CVTNULL;
2826 if (special == 2)
2827 qflags |= QGLOB_REGEXP;
2828 p = string_list (l);
2829 r = quote_string_for_globbing (p, qflags);
2830 free (p);
2832 dispose_words (l);
2834 else
2835 r = (char *)NULL;
2837 return r;
2839 #endif
2841 /* Call expand_word_internal to expand W and handle error returns.
2842 A convenience function for functions that don't want to handle
2843 any errors or free any memory before aborting. */
2844 static WORD_LIST *
2845 call_expand_word_internal (w, q, i, c, e)
2846 WORD_DESC *w;
2847 int q, i, *c, *e;
2849 WORD_LIST *result;
2851 result = expand_word_internal (w, q, i, c, e);
2852 if (result == &expand_word_error || result == &expand_word_fatal)
2854 /* By convention, each time this error is returned, w->word has
2855 already been freed (it sometimes may not be in the fatal case,
2856 but that doesn't result in a memory leak because we're going
2857 to exit in most cases). */
2858 w->word = (char *)NULL;
2859 last_command_exit_value = EXECUTION_FAILURE;
2860 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2861 /* NOTREACHED */
2863 else
2864 return (result);
2867 /* Perform parameter expansion, command substitution, and arithmetic
2868 expansion on STRING, as if it were a word. Leave the result quoted. */
2869 static WORD_LIST *
2870 expand_string_internal (string, quoted)
2871 char *string;
2872 int quoted;
2874 WORD_DESC td;
2875 WORD_LIST *tresult;
2877 if (string == 0 || *string == 0)
2878 return ((WORD_LIST *)NULL);
2880 td.flags = 0;
2881 td.word = savestring (string);
2883 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2885 FREE (td.word);
2886 return (tresult);
2889 /* Expand STRING by performing parameter expansion, command substitution,
2890 and arithmetic expansion. Dequote the resulting WORD_LIST before
2891 returning it, but do not perform word splitting. The call to
2892 remove_quoted_nulls () is in here because word splitting normally
2893 takes care of quote removal. */
2894 WORD_LIST *
2895 expand_string_unsplit (string, quoted)
2896 char *string;
2897 int quoted;
2899 WORD_LIST *value;
2901 if (string == 0 || *string == '\0')
2902 return ((WORD_LIST *)NULL);
2904 expand_no_split_dollar_star = 1;
2905 value = expand_string_internal (string, quoted);
2906 expand_no_split_dollar_star = 0;
2908 if (value)
2910 if (value->word)
2912 remove_quoted_nulls (value->word->word);
2913 value->word->flags &= ~W_HASQUOTEDNULL;
2915 dequote_list (value);
2917 return (value);
2920 /* Expand the rhs of an assignment statement */
2921 WORD_LIST *
2922 expand_string_assignment (string, quoted)
2923 char *string;
2924 int quoted;
2926 WORD_DESC td;
2927 WORD_LIST *value;
2929 if (string == 0 || *string == '\0')
2930 return ((WORD_LIST *)NULL);
2932 expand_no_split_dollar_star = 1;
2934 td.flags = W_ASSIGNRHS;
2935 td.word = savestring (string);
2936 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2937 FREE (td.word);
2939 expand_no_split_dollar_star = 0;
2941 if (value)
2943 if (value->word)
2945 remove_quoted_nulls (value->word->word);
2946 value->word->flags &= ~W_HASQUOTEDNULL;
2948 dequote_list (value);
2950 return (value);
2954 /* Expand one of the PS? prompt strings. This is a sort of combination of
2955 expand_string_unsplit and expand_string_internal, but returns the
2956 passed string when an error occurs. Might want to trap other calls
2957 to jump_to_top_level here so we don't endlessly loop. */
2958 WORD_LIST *
2959 expand_prompt_string (string, quoted, wflags)
2960 char *string;
2961 int quoted;
2962 int wflags;
2964 WORD_LIST *value;
2965 WORD_DESC td;
2967 if (string == 0 || *string == 0)
2968 return ((WORD_LIST *)NULL);
2970 td.flags = wflags;
2971 td.word = savestring (string);
2973 no_longjmp_on_fatal_error = 1;
2974 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2975 no_longjmp_on_fatal_error = 0;
2977 if (value == &expand_word_error || value == &expand_word_fatal)
2979 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
2980 return value;
2982 FREE (td.word);
2983 if (value)
2985 if (value->word)
2987 remove_quoted_nulls (value->word->word);
2988 value->word->flags &= ~W_HASQUOTEDNULL;
2990 dequote_list (value);
2992 return (value);
2995 /* Expand STRING just as if you were expanding a word, but do not dequote
2996 the resultant WORD_LIST. This is called only from within this file,
2997 and is used to correctly preserve quoted characters when expanding
2998 things like ${1+"$@"}. This does parameter expansion, command
2999 substitution, arithmetic expansion, and word splitting. */
3000 static WORD_LIST *
3001 expand_string_leave_quoted (string, quoted)
3002 char *string;
3003 int quoted;
3005 WORD_LIST *tlist;
3006 WORD_LIST *tresult;
3008 if (string == 0 || *string == '\0')
3009 return ((WORD_LIST *)NULL);
3011 tlist = expand_string_internal (string, quoted);
3013 if (tlist)
3015 tresult = word_list_split (tlist);
3016 dispose_words (tlist);
3017 return (tresult);
3019 return ((WORD_LIST *)NULL);
3022 /* This does not perform word splitting or dequote the WORD_LIST
3023 it returns. */
3024 static WORD_LIST *
3025 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
3026 char *string;
3027 int quoted, *dollar_at_p, *has_dollar_at;
3029 WORD_DESC td;
3030 WORD_LIST *tresult;
3032 if (string == 0 || *string == '\0')
3033 return (WORD_LIST *)NULL;
3035 td.flags = 0;
3036 td.word = string;
3037 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
3038 return (tresult);
3041 /* Expand STRING just as if you were expanding a word. This also returns
3042 a list of words. Note that filename globbing is *NOT* done for word
3043 or string expansion, just when the shell is expanding a command. This
3044 does parameter expansion, command substitution, arithmetic expansion,
3045 and word splitting. Dequote the resultant WORD_LIST before returning. */
3046 WORD_LIST *
3047 expand_string (string, quoted)
3048 char *string;
3049 int quoted;
3051 WORD_LIST *result;
3053 if (string == 0 || *string == '\0')
3054 return ((WORD_LIST *)NULL);
3056 result = expand_string_leave_quoted (string, quoted);
3057 return (result ? dequote_list (result) : result);
3060 /***************************************************
3062 * Functions to handle quoting chars *
3064 ***************************************************/
3066 /* Conventions:
3068 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
3069 The parser passes CTLNUL as CTLESC CTLNUL. */
3071 /* Quote escape characters in string s, but no other characters. This is
3072 used to protect CTLESC and CTLNUL in variable values from the rest of
3073 the word expansion process after the variable is expanded (word splitting
3074 and filename generation). If IFS is null, we quote spaces as well, just
3075 in case we split on spaces later (in the case of unquoted $@, we will
3076 eventually attempt to split the entire word on spaces). Corresponding
3077 code exists in dequote_escapes. Even if we don't end up splitting on
3078 spaces, quoting spaces is not a problem. This should never be called on
3079 a string that is quoted with single or double quotes or part of a here
3080 document (effectively double-quoted). */
3081 char *
3082 quote_escapes (string)
3083 char *string;
3085 register char *s, *t;
3086 size_t slen;
3087 char *result, *send;
3088 int quote_spaces, skip_ctlesc, skip_ctlnul;
3089 DECLARE_MBSTATE;
3091 slen = strlen (string);
3092 send = string + slen;
3094 quote_spaces = (ifs_value && *ifs_value == 0);
3096 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
3097 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
3099 t = result = (char *)xmalloc ((slen * 2) + 1);
3100 s = string;
3102 while (*s)
3104 if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
3105 *t++ = CTLESC;
3106 COPY_CHAR_P (t, s, send);
3108 *t = '\0';
3109 return (result);
3112 static WORD_LIST *
3113 list_quote_escapes (list)
3114 WORD_LIST *list;
3116 register WORD_LIST *w;
3117 char *t;
3119 for (w = list; w; w = w->next)
3121 t = w->word->word;
3122 w->word->word = quote_escapes (t);
3123 free (t);
3125 return list;
3128 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
3130 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
3131 This is necessary to make unquoted CTLESC and CTLNUL characters in the
3132 data stream pass through properly.
3134 We need to remove doubled CTLESC characters inside quoted strings before
3135 quoting the entire string, so we do not double the number of CTLESC
3136 characters.
3138 Also used by parts of the pattern substitution code. */
3139 char *
3140 dequote_escapes (string)
3141 char *string;
3143 register char *s, *t, *s1;
3144 size_t slen;
3145 char *result, *send;
3146 int quote_spaces;
3147 DECLARE_MBSTATE;
3149 if (string == 0)
3150 return string;
3152 slen = strlen (string);
3153 send = string + slen;
3155 t = result = (char *)xmalloc (slen + 1);
3157 if (strchr (string, CTLESC) == 0)
3158 return (strcpy (result, string));
3160 quote_spaces = (ifs_value && *ifs_value == 0);
3162 s = string;
3163 while (*s)
3165 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
3167 s++;
3168 if (*s == '\0')
3169 break;
3171 COPY_CHAR_P (t, s, send);
3173 *t = '\0';
3174 return result;
3177 /* Return a new string with the quoted representation of character C.
3178 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3179 set in any resultant WORD_DESC where this value is the word. */
3180 static char *
3181 make_quoted_char (c)
3182 int c;
3184 char *temp;
3186 temp = (char *)xmalloc (3);
3187 if (c == 0)
3189 temp[0] = CTLNUL;
3190 temp[1] = '\0';
3192 else
3194 temp[0] = CTLESC;
3195 temp[1] = c;
3196 temp[2] = '\0';
3198 return (temp);
3201 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
3202 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3203 this value is the word. */
3204 char *
3205 quote_string (string)
3206 char *string;
3208 register char *t;
3209 size_t slen;
3210 char *result, *send;
3212 if (*string == 0)
3214 result = (char *)xmalloc (2);
3215 result[0] = CTLNUL;
3216 result[1] = '\0';
3218 else
3220 DECLARE_MBSTATE;
3222 slen = strlen (string);
3223 send = string + slen;
3225 result = (char *)xmalloc ((slen * 2) + 1);
3227 for (t = result; string < send; )
3229 *t++ = CTLESC;
3230 COPY_CHAR_P (t, string, send);
3232 *t = '\0';
3234 return (result);
3237 /* De-quote quoted characters in STRING. */
3238 char *
3239 dequote_string (string)
3240 char *string;
3242 register char *s, *t;
3243 size_t slen;
3244 char *result, *send;
3245 DECLARE_MBSTATE;
3247 slen = strlen (string);
3249 t = result = (char *)xmalloc (slen + 1);
3251 if (QUOTED_NULL (string))
3253 result[0] = '\0';
3254 return (result);
3257 /* If no character in the string can be quoted, don't bother examining
3258 each character. Just return a copy of the string passed to us. */
3259 if (strchr (string, CTLESC) == NULL)
3260 return (strcpy (result, string));
3262 send = string + slen;
3263 s = string;
3264 while (*s)
3266 if (*s == CTLESC)
3268 s++;
3269 if (*s == '\0')
3270 break;
3272 COPY_CHAR_P (t, s, send);
3275 *t = '\0';
3276 return (result);
3279 /* Quote the entire WORD_LIST list. */
3280 static WORD_LIST *
3281 quote_list (list)
3282 WORD_LIST *list;
3284 register WORD_LIST *w;
3285 char *t;
3287 for (w = list; w; w = w->next)
3289 t = w->word->word;
3290 w->word->word = quote_string (t);
3291 if (*t == 0)
3292 w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
3293 w->word->flags |= W_QUOTED;
3294 free (t);
3296 return list;
3299 /* De-quote quoted characters in each word in LIST. */
3300 WORD_LIST *
3301 dequote_list (list)
3302 WORD_LIST *list;
3304 register char *s;
3305 register WORD_LIST *tlist;
3307 for (tlist = list; tlist; tlist = tlist->next)
3309 s = dequote_string (tlist->word->word);
3310 if (QUOTED_NULL (tlist->word->word))
3311 tlist->word->flags &= ~W_HASQUOTEDNULL;
3312 free (tlist->word->word);
3313 tlist->word->word = s;
3315 return list;
3318 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3319 string. */
3320 char *
3321 remove_quoted_escapes (string)
3322 char *string;
3324 char *t;
3326 if (string)
3328 t = dequote_escapes (string);
3329 strcpy (string, t);
3330 free (t);
3333 return (string);
3336 /* Perform quoted null character removal on STRING. We don't allow any
3337 quoted null characters in the middle or at the ends of strings because
3338 of how expand_word_internal works. remove_quoted_nulls () turns
3339 STRING into an empty string iff it only consists of a quoted null,
3340 and removes all unquoted CTLNUL characters. */
3341 char *
3342 remove_quoted_nulls (string)
3343 char *string;
3345 register size_t slen;
3346 register int i, j, prev_i;
3347 DECLARE_MBSTATE;
3349 if (strchr (string, CTLNUL) == 0) /* XXX */
3350 return string; /* XXX */
3352 slen = strlen (string);
3353 i = j = 0;
3355 while (i < slen)
3357 if (string[i] == CTLESC)
3359 /* Old code had j++, but we cannot assume that i == j at this
3360 point -- what if a CTLNUL has already been removed from the
3361 string? We don't want to drop the CTLESC or recopy characters
3362 that we've already copied down. */
3363 i++; string[j++] = CTLESC;
3364 if (i == slen)
3365 break;
3367 else if (string[i] == CTLNUL)
3368 i++;
3370 prev_i = i;
3371 ADVANCE_CHAR (string, slen, i);
3372 if (j < prev_i)
3374 do string[j++] = string[prev_i++]; while (prev_i < i);
3376 else
3377 j = i;
3379 string[j] = '\0';
3381 return (string);
3384 /* Perform quoted null character removal on each element of LIST.
3385 This modifies LIST. */
3386 void
3387 word_list_remove_quoted_nulls (list)
3388 WORD_LIST *list;
3390 register WORD_LIST *t;
3392 for (t = list; t; t = t->next)
3394 remove_quoted_nulls (t->word->word);
3395 t->word->flags &= ~W_HASQUOTEDNULL;
3399 /* **************************************************************** */
3400 /* */
3401 /* Functions for Matching and Removing Patterns */
3402 /* */
3403 /* **************************************************************** */
3405 #if defined (HANDLE_MULTIBYTE)
3406 #if 0 /* Currently unused */
3407 static unsigned char *
3408 mb_getcharlens (string, len)
3409 char *string;
3410 int len;
3412 int i, offset, last;
3413 unsigned char *ret;
3414 char *p;
3415 DECLARE_MBSTATE;
3417 i = offset = 0;
3418 last = 0;
3419 ret = (unsigned char *)xmalloc (len);
3420 memset (ret, 0, len);
3421 while (string[last])
3423 ADVANCE_CHAR (string, len, offset);
3424 ret[last] = offset - last;
3425 last = offset;
3427 return ret;
3429 #endif
3430 #endif
3432 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3433 can have one of 4 values:
3434 RP_LONG_LEFT remove longest matching portion at start of PARAM
3435 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3436 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3437 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3440 #define RP_LONG_LEFT 1
3441 #define RP_SHORT_LEFT 2
3442 #define RP_LONG_RIGHT 3
3443 #define RP_SHORT_RIGHT 4
3445 static char *
3446 remove_upattern (param, pattern, op)
3447 char *param, *pattern;
3448 int op;
3450 register int len;
3451 register char *end;
3452 register char *p, *ret, c;
3454 len = STRLEN (param);
3455 end = param + len;
3457 switch (op)
3459 case RP_LONG_LEFT: /* remove longest match at start */
3460 for (p = end; p >= param; p--)
3462 c = *p; *p = '\0';
3463 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3465 *p = c;
3466 return (savestring (p));
3468 *p = c;
3471 break;
3473 case RP_SHORT_LEFT: /* remove shortest match at start */
3474 for (p = param; p <= end; p++)
3476 c = *p; *p = '\0';
3477 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3479 *p = c;
3480 return (savestring (p));
3482 *p = c;
3484 break;
3486 case RP_LONG_RIGHT: /* remove longest match at end */
3487 for (p = param; p <= end; p++)
3489 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3491 c = *p; *p = '\0';
3492 ret = savestring (param);
3493 *p = c;
3494 return (ret);
3497 break;
3499 case RP_SHORT_RIGHT: /* remove shortest match at end */
3500 for (p = end; p >= param; p--)
3502 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3504 c = *p; *p = '\0';
3505 ret = savestring (param);
3506 *p = c;
3507 return (ret);
3510 break;
3513 return (savestring (param)); /* no match, return original string */
3516 #if defined (HANDLE_MULTIBYTE)
3517 static wchar_t *
3518 remove_wpattern (wparam, wstrlen, wpattern, op)
3519 wchar_t *wparam;
3520 size_t wstrlen;
3521 wchar_t *wpattern;
3522 int op;
3524 wchar_t wc, *ret;
3525 int n;
3527 switch (op)
3529 case RP_LONG_LEFT: /* remove longest match at start */
3530 for (n = wstrlen; n >= 0; n--)
3532 wc = wparam[n]; wparam[n] = L'\0';
3533 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3535 wparam[n] = wc;
3536 return (wcsdup (wparam + n));
3538 wparam[n] = wc;
3540 break;
3542 case RP_SHORT_LEFT: /* remove shortest match at start */
3543 for (n = 0; n <= wstrlen; n++)
3545 wc = wparam[n]; wparam[n] = L'\0';
3546 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3548 wparam[n] = wc;
3549 return (wcsdup (wparam + n));
3551 wparam[n] = wc;
3553 break;
3555 case RP_LONG_RIGHT: /* remove longest match at end */
3556 for (n = 0; n <= wstrlen; n++)
3558 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3560 wc = wparam[n]; wparam[n] = L'\0';
3561 ret = wcsdup (wparam);
3562 wparam[n] = wc;
3563 return (ret);
3566 break;
3568 case RP_SHORT_RIGHT: /* remove shortest match at end */
3569 for (n = wstrlen; n >= 0; n--)
3571 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3573 wc = wparam[n]; wparam[n] = L'\0';
3574 ret = wcsdup (wparam);
3575 wparam[n] = wc;
3576 return (ret);
3579 break;
3582 return (wcsdup (wparam)); /* no match, return original string */
3584 #endif /* HANDLE_MULTIBYTE */
3586 static char *
3587 remove_pattern (param, pattern, op)
3588 char *param, *pattern;
3589 int op;
3591 if (param == NULL)
3592 return (param);
3593 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3594 return (savestring (param));
3596 #if defined (HANDLE_MULTIBYTE)
3597 if (MB_CUR_MAX > 1)
3599 wchar_t *ret, *oret;
3600 size_t n;
3601 wchar_t *wparam, *wpattern;
3602 mbstate_t ps;
3603 char *xret;
3605 n = xdupmbstowcs (&wpattern, NULL, pattern);
3606 if (n == (size_t)-1)
3607 return (remove_upattern (param, pattern, op));
3608 n = xdupmbstowcs (&wparam, NULL, param);
3609 if (n == (size_t)-1)
3611 free (wpattern);
3612 return (remove_upattern (param, pattern, op));
3614 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3616 free (wparam);
3617 free (wpattern);
3619 n = strlen (param);
3620 xret = (char *)xmalloc (n + 1);
3621 memset (&ps, '\0', sizeof (mbstate_t));
3622 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3623 xret[n] = '\0'; /* just to make sure */
3624 free (oret);
3625 return xret;
3627 else
3628 #endif
3629 return (remove_upattern (param, pattern, op));
3632 /* Return 1 of the first character of STRING could match the first
3633 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
3634 static int
3635 match_pattern_char (pat, string)
3636 char *pat, *string;
3638 char c;
3640 if (*string == 0)
3641 return (0);
3643 switch (c = *pat++)
3645 default:
3646 return (*string == c);
3647 case '\\':
3648 return (*string == *pat);
3649 case '?':
3650 return (*pat == LPAREN ? 1 : (*string != '\0'));
3651 case '*':
3652 return (1);
3653 case '+':
3654 case '!':
3655 case '@':
3656 return (*pat == LPAREN ? 1 : (*string == c));
3657 case '[':
3658 return (*string != '\0');
3662 /* Match PAT anywhere in STRING and return the match boundaries.
3663 This returns 1 in case of a successful match, 0 otherwise. SP
3664 and EP are pointers into the string where the match begins and
3665 ends, respectively. MTYPE controls what kind of match is attempted.
3666 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3667 of the string, respectively. The longest match is returned. */
3668 static int
3669 match_upattern (string, pat, mtype, sp, ep)
3670 char *string, *pat;
3671 int mtype;
3672 char **sp, **ep;
3674 int c, len;
3675 register char *p, *p1, *npat;
3676 char *end;
3678 /* If the pattern doesn't match anywhere in the string, go ahead and
3679 short-circuit right away. A minor optimization, saves a bunch of
3680 unnecessary calls to strmatch (up to N calls for a string of N
3681 characters) if the match is unsuccessful. To preserve the semantics
3682 of the substring matches below, we make sure that the pattern has
3683 `*' as first and last character, making a new pattern if necessary. */
3684 /* XXX - check this later if I ever implement `**' with special meaning,
3685 since this will potentially result in `**' at the beginning or end */
3686 len = STRLEN (pat);
3687 if (pat[0] != '*' || (pat[0] == '*' && pat[1] == '(' && extended_glob) || pat[len - 1] != '*') /*)*/
3689 p = npat = (char *)xmalloc (len + 3);
3690 p1 = pat;
3691 if (*p1 != '*' || (*p1 == '*' && p1[1] == '(' && extended_glob)) /*)*/
3692 *p++ = '*';
3693 while (*p1)
3694 *p++ = *p1++;
3695 if (p1[-1] != '*' || p[-2] == '\\')
3696 *p++ = '*';
3697 *p = '\0';
3699 else
3700 npat = pat;
3701 c = strmatch (npat, string, FNMATCH_EXTFLAG);
3702 if (npat != pat)
3703 free (npat);
3704 if (c == FNM_NOMATCH)
3705 return (0);
3707 len = STRLEN (string);
3708 end = string + len;
3710 switch (mtype)
3712 case MATCH_ANY:
3713 for (p = string; p <= end; p++)
3715 if (match_pattern_char (pat, p))
3717 for (p1 = end; p1 >= p; p1--)
3719 c = *p1; *p1 = '\0';
3720 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3722 *p1 = c;
3723 *sp = p;
3724 *ep = p1;
3725 return 1;
3727 *p1 = c;
3732 return (0);
3734 case MATCH_BEG:
3735 if (match_pattern_char (pat, string) == 0)
3736 return (0);
3738 for (p = end; p >= string; p--)
3740 c = *p; *p = '\0';
3741 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3743 *p = c;
3744 *sp = string;
3745 *ep = p;
3746 return 1;
3748 *p = c;
3751 return (0);
3753 case MATCH_END:
3754 for (p = string; p <= end; p++)
3756 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3758 *sp = p;
3759 *ep = end;
3760 return 1;
3765 return (0);
3768 return (0);
3771 #if defined (HANDLE_MULTIBYTE)
3772 /* Return 1 of the first character of WSTRING could match the first
3773 character of pattern WPAT. Wide character version. */
3774 static int
3775 match_pattern_wchar (wpat, wstring)
3776 wchar_t *wpat, *wstring;
3778 wchar_t wc;
3780 if (*wstring == 0)
3781 return (0);
3783 switch (wc = *wpat++)
3785 default:
3786 return (*wstring == wc);
3787 case L'\\':
3788 return (*wstring == *wpat);
3789 case L'?':
3790 return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3791 case L'*':
3792 return (1);
3793 case L'+':
3794 case L'!':
3795 case L'@':
3796 return (*wpat == LPAREN ? 1 : (*wstring == wc));
3797 case L'[':
3798 return (*wstring != L'\0');
3802 /* Match WPAT anywhere in WSTRING and return the match boundaries.
3803 This returns 1 in case of a successful match, 0 otherwise. Wide
3804 character version. */
3805 static int
3806 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3807 wchar_t *wstring;
3808 char **indices;
3809 size_t wstrlen;
3810 wchar_t *wpat;
3811 int mtype;
3812 char **sp, **ep;
3814 wchar_t wc, *wp, *nwpat, *wp1;
3815 int len;
3816 #if 0
3817 size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3818 #else
3819 int n, n1;
3820 #endif
3822 /* If the pattern doesn't match anywhere in the string, go ahead and
3823 short-circuit right away. A minor optimization, saves a bunch of
3824 unnecessary calls to strmatch (up to N calls for a string of N
3825 characters) if the match is unsuccessful. To preserve the semantics
3826 of the substring matches below, we make sure that the pattern has
3827 `*' as first and last character, making a new pattern if necessary. */
3828 /* XXX - check this later if I ever implement `**' with special meaning,
3829 since this will potentially result in `**' at the beginning or end */
3830 len = wcslen (wpat);
3831 if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == L'(' && extended_glob) || wpat[len - 1] != L'*') /*)*/
3833 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
3834 wp1 = wpat;
3835 if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == '(' && extended_glob)) /*)*/
3836 *wp++ = L'*';
3837 while (*wp1 != L'\0')
3838 *wp++ = *wp1++;
3839 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3840 *wp++ = L'*';
3841 *wp = '\0';
3843 else
3844 nwpat = wpat;
3845 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3846 if (nwpat != wpat)
3847 free (nwpat);
3848 if (len == FNM_NOMATCH)
3849 return (0);
3851 switch (mtype)
3853 case MATCH_ANY:
3854 for (n = 0; n <= wstrlen; n++)
3856 if (match_pattern_wchar (wpat, wstring + n))
3858 for (n1 = wstrlen; n1 >= n; n1--)
3860 wc = wstring[n1]; wstring[n1] = L'\0';
3861 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3863 wstring[n1] = wc;
3864 *sp = indices[n];
3865 *ep = indices[n1];
3866 return 1;
3868 wstring[n1] = wc;
3873 return (0);
3875 case MATCH_BEG:
3876 if (match_pattern_wchar (wpat, wstring) == 0)
3877 return (0);
3879 for (n = wstrlen; n >= 0; n--)
3881 wc = wstring[n]; wstring[n] = L'\0';
3882 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3884 wstring[n] = wc;
3885 *sp = indices[0];
3886 *ep = indices[n];
3887 return 1;
3889 wstring[n] = wc;
3892 return (0);
3894 case MATCH_END:
3895 for (n = 0; n <= wstrlen; n++)
3897 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3899 *sp = indices[n];
3900 *ep = indices[wstrlen];
3901 return 1;
3905 return (0);
3908 return (0);
3910 #endif /* HANDLE_MULTIBYTE */
3912 static int
3913 match_pattern (string, pat, mtype, sp, ep)
3914 char *string, *pat;
3915 int mtype;
3916 char **sp, **ep;
3918 #if defined (HANDLE_MULTIBYTE)
3919 int ret;
3920 size_t n;
3921 wchar_t *wstring, *wpat;
3922 char **indices;
3923 #endif
3925 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
3926 return (0);
3928 #if defined (HANDLE_MULTIBYTE)
3929 if (MB_CUR_MAX > 1)
3931 n = xdupmbstowcs (&wpat, NULL, pat);
3932 if (n == (size_t)-1)
3933 return (match_upattern (string, pat, mtype, sp, ep));
3934 n = xdupmbstowcs (&wstring, &indices, string);
3935 if (n == (size_t)-1)
3937 free (wpat);
3938 return (match_upattern (string, pat, mtype, sp, ep));
3940 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
3942 free (wpat);
3943 free (wstring);
3944 free (indices);
3946 return (ret);
3948 else
3949 #endif
3950 return (match_upattern (string, pat, mtype, sp, ep));
3953 static int
3954 getpatspec (c, value)
3955 int c;
3956 char *value;
3958 if (c == '#')
3959 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
3960 else /* c == '%' */
3961 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
3964 /* Posix.2 says that the WORD should be run through tilde expansion,
3965 parameter expansion, command substitution and arithmetic expansion.
3966 This leaves the result quoted, so quote_string_for_globbing () has
3967 to be called to fix it up for strmatch (). If QUOTED is non-zero,
3968 it means that the entire expression was enclosed in double quotes.
3969 This means that quoting characters in the pattern do not make any
3970 special pattern characters quoted. For example, the `*' in the
3971 following retains its special meaning: "${foo#'*'}". */
3972 static char *
3973 getpattern (value, quoted, expandpat)
3974 char *value;
3975 int quoted, expandpat;
3977 char *pat, *tword;
3978 WORD_LIST *l;
3979 #if 0
3980 int i;
3981 #endif
3982 /* There is a problem here: how to handle single or double quotes in the
3983 pattern string when the whole expression is between double quotes?
3984 POSIX.2 says that enclosing double quotes do not cause the pattern to
3985 be quoted, but does that leave us a problem with @ and array[@] and their
3986 expansions inside a pattern? */
3987 #if 0
3988 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
3990 i = 0;
3991 pat = string_extract_double_quoted (tword, &i, 1);
3992 free (tword);
3993 tword = pat;
3995 #endif
3997 /* expand_string_for_rhs () leaves WORD quoted and does not perform
3998 word splitting. */
3999 l = *value ? expand_string_for_rhs (value,
4000 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
4001 (int *)NULL, (int *)NULL)
4002 : (WORD_LIST *)0;
4003 pat = string_list (l);
4004 dispose_words (l);
4005 if (pat)
4007 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
4008 free (pat);
4009 pat = tword;
4011 return (pat);
4014 #if 0
4015 /* Handle removing a pattern from a string as a result of ${name%[%]value}
4016 or ${name#[#]value}. */
4017 static char *
4018 variable_remove_pattern (value, pattern, patspec, quoted)
4019 char *value, *pattern;
4020 int patspec, quoted;
4022 char *tword;
4024 tword = remove_pattern (value, pattern, patspec);
4026 return (tword);
4028 #endif
4030 static char *
4031 list_remove_pattern (list, pattern, patspec, itype, quoted)
4032 WORD_LIST *list;
4033 char *pattern;
4034 int patspec, itype, quoted;
4036 WORD_LIST *new, *l;
4037 WORD_DESC *w;
4038 char *tword;
4040 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
4042 tword = remove_pattern (l->word->word, pattern, patspec);
4043 w = alloc_word_desc ();
4044 w->word = tword ? tword : savestring ("");
4045 new = make_word_list (w, new);
4048 l = REVERSE_LIST (new, WORD_LIST *);
4049 tword = string_list_pos_params (itype, l, quoted);
4050 dispose_words (l);
4052 return (tword);
4055 static char *
4056 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
4057 int itype;
4058 char *pattern;
4059 int patspec, quoted;
4061 char *ret;
4062 WORD_LIST *list;
4064 list = list_rest_of_args ();
4065 if (list == 0)
4066 return ((char *)NULL);
4067 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4068 dispose_words (list);
4069 return (ret);
4072 #if defined (ARRAY_VARS)
4073 static char *
4074 array_remove_pattern (var, pattern, patspec, varname, quoted)
4075 SHELL_VAR *var;
4076 char *pattern;
4077 int patspec;
4078 char *varname; /* so we can figure out how it's indexed */
4079 int quoted;
4081 ARRAY *a;
4082 HASH_TABLE *h;
4083 int itype;
4084 char *ret;
4085 WORD_LIST *list;
4086 SHELL_VAR *v;
4088 /* compute itype from varname here */
4089 v = array_variable_part (varname, &ret, 0);
4090 itype = ret[0];
4092 a = (v && array_p (v)) ? array_cell (v) : 0;
4093 h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
4095 list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
4096 if (list == 0)
4097 return ((char *)NULL);
4098 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4099 dispose_words (list);
4101 return ret;
4103 #endif /* ARRAY_VARS */
4105 static char *
4106 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
4107 char *varname, *value, *patstr;
4108 int rtype, quoted;
4110 int vtype, patspec, starsub;
4111 char *temp1, *val, *pattern;
4112 SHELL_VAR *v;
4114 if (value == 0)
4115 return ((char *)NULL);
4117 this_command_name = varname;
4119 vtype = get_var_and_type (varname, value, quoted, &v, &val);
4120 if (vtype == -1)
4121 return ((char *)NULL);
4123 starsub = vtype & VT_STARSUB;
4124 vtype &= ~VT_STARSUB;
4126 patspec = getpatspec (rtype, patstr);
4127 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
4128 patstr++;
4130 /* Need to pass getpattern newly-allocated memory in case of expansion --
4131 the expansion code will free the passed string on an error. */
4132 temp1 = savestring (patstr);
4133 pattern = getpattern (temp1, quoted, 1);
4134 free (temp1);
4136 temp1 = (char *)NULL; /* shut up gcc */
4137 switch (vtype)
4139 case VT_VARIABLE:
4140 case VT_ARRAYMEMBER:
4141 temp1 = remove_pattern (val, pattern, patspec);
4142 if (vtype == VT_VARIABLE)
4143 FREE (val);
4144 if (temp1)
4146 val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4147 ? quote_string (temp1)
4148 : quote_escapes (temp1);
4149 free (temp1);
4150 temp1 = val;
4152 break;
4153 #if defined (ARRAY_VARS)
4154 case VT_ARRAYVAR:
4155 temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted);
4156 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4158 val = quote_escapes (temp1);
4159 free (temp1);
4160 temp1 = val;
4162 break;
4163 #endif
4164 case VT_POSPARMS:
4165 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
4166 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4168 val = quote_escapes (temp1);
4169 free (temp1);
4170 temp1 = val;
4172 break;
4175 FREE (pattern);
4176 return temp1;
4179 /*******************************************
4181 * Functions to expand WORD_DESCs *
4183 *******************************************/
4185 /* Expand WORD, performing word splitting on the result. This does
4186 parameter expansion, command substitution, arithmetic expansion,
4187 word splitting, and quote removal. */
4189 WORD_LIST *
4190 expand_word (word, quoted)
4191 WORD_DESC *word;
4192 int quoted;
4194 WORD_LIST *result, *tresult;
4196 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4197 result = word_list_split (tresult);
4198 dispose_words (tresult);
4199 return (result ? dequote_list (result) : result);
4202 /* Expand WORD, but do not perform word splitting on the result. This
4203 does parameter expansion, command substitution, arithmetic expansion,
4204 and quote removal. */
4205 WORD_LIST *
4206 expand_word_unsplit (word, quoted)
4207 WORD_DESC *word;
4208 int quoted;
4210 WORD_LIST *result;
4212 expand_no_split_dollar_star = 1;
4213 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4214 expand_no_split_dollar_star = 0;
4216 return (result ? dequote_list (result) : result);
4219 /* Perform shell expansions on WORD, but do not perform word splitting or
4220 quote removal on the result. */
4221 WORD_LIST *
4222 expand_word_leave_quoted (word, quoted)
4223 WORD_DESC *word;
4224 int quoted;
4226 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
4229 #if defined (PROCESS_SUBSTITUTION)
4231 /*****************************************************************/
4232 /* */
4233 /* Hacking Process Substitution */
4234 /* */
4235 /*****************************************************************/
4237 #if !defined (HAVE_DEV_FD)
4238 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
4239 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4240 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4241 list. NFIFO is a count of the number of FIFOs in the list. */
4242 #define FIFO_INCR 20
4244 struct temp_fifo {
4245 char *file;
4246 pid_t proc;
4249 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4250 static int nfifo;
4251 static int fifo_list_size;
4253 static void
4254 add_fifo_list (pathname)
4255 char *pathname;
4257 if (nfifo >= fifo_list_size - 1)
4259 fifo_list_size += FIFO_INCR;
4260 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4261 fifo_list_size * sizeof (struct temp_fifo));
4264 fifo_list[nfifo].file = savestring (pathname);
4265 nfifo++;
4268 void
4269 unlink_fifo_list ()
4271 int saved, i, j;
4273 if (nfifo == 0)
4274 return;
4276 for (i = saved = 0; i < nfifo; i++)
4278 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4280 unlink (fifo_list[i].file);
4281 free (fifo_list[i].file);
4282 fifo_list[i].file = (char *)NULL;
4283 fifo_list[i].proc = -1;
4285 else
4286 saved++;
4289 /* If we didn't remove some of the FIFOs, compact the list. */
4290 if (saved)
4292 for (i = j = 0; i < nfifo; i++)
4293 if (fifo_list[i].file)
4295 fifo_list[j].file = fifo_list[i].file;
4296 fifo_list[j].proc = fifo_list[i].proc;
4297 j++;
4299 nfifo = j;
4301 else
4302 nfifo = 0;
4306 fifos_pending ()
4308 return nfifo;
4311 static char *
4312 make_named_pipe ()
4314 char *tname;
4316 tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
4317 if (mkfifo (tname, 0600) < 0)
4319 free (tname);
4320 return ((char *)NULL);
4323 add_fifo_list (tname);
4324 return (tname);
4327 #else /* HAVE_DEV_FD */
4329 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4330 has open to children. NFDS is a count of the number of bits currently
4331 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4332 of open files. */
4333 static char *dev_fd_list = (char *)NULL;
4334 static int nfds;
4335 static int totfds; /* The highest possible number of open files. */
4337 static void
4338 add_fifo_list (fd)
4339 int fd;
4341 if (!dev_fd_list || fd >= totfds)
4343 int ofds;
4345 ofds = totfds;
4346 totfds = getdtablesize ();
4347 if (totfds < 0 || totfds > 256)
4348 totfds = 256;
4349 if (fd >= totfds)
4350 totfds = fd + 2;
4352 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4353 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4356 dev_fd_list[fd] = 1;
4357 nfds++;
4361 fifos_pending ()
4363 return 0; /* used for cleanup; not needed with /dev/fd */
4366 void
4367 unlink_fifo_list ()
4369 register int i;
4371 if (nfds == 0)
4372 return;
4374 for (i = 0; nfds && i < totfds; i++)
4375 if (dev_fd_list[i])
4377 close (i);
4378 dev_fd_list[i] = 0;
4379 nfds--;
4382 nfds = 0;
4385 #if defined (NOTDEF)
4386 print_dev_fd_list ()
4388 register int i;
4390 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4391 fflush (stderr);
4393 for (i = 0; i < totfds; i++)
4395 if (dev_fd_list[i])
4396 fprintf (stderr, " %d", i);
4398 fprintf (stderr, "\n");
4400 #endif /* NOTDEF */
4402 static char *
4403 make_dev_fd_filename (fd)
4404 int fd;
4406 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4408 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
4410 strcpy (ret, DEV_FD_PREFIX);
4411 p = inttostr (fd, intbuf, sizeof (intbuf));
4412 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4414 add_fifo_list (fd);
4415 return (ret);
4418 #endif /* HAVE_DEV_FD */
4420 /* Return a filename that will open a connection to the process defined by
4421 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4422 a filename in /dev/fd corresponding to a descriptor that is one of the
4423 ends of the pipe. If not defined, we use named pipes on systems that have
4424 them. Systems without /dev/fd and named pipes are out of luck.
4426 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4427 use the read end of the pipe and dup that file descriptor to fd 0 in
4428 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4429 writing or use the write end of the pipe in the child, and dup that
4430 file descriptor to fd 1 in the child. The parent does the opposite. */
4432 static char *
4433 process_substitute (string, open_for_read_in_child)
4434 char *string;
4435 int open_for_read_in_child;
4437 char *pathname;
4438 int fd, result;
4439 pid_t old_pid, pid;
4440 #if defined (HAVE_DEV_FD)
4441 int parent_pipe_fd, child_pipe_fd;
4442 int fildes[2];
4443 #endif /* HAVE_DEV_FD */
4444 #if defined (JOB_CONTROL)
4445 pid_t old_pipeline_pgrp;
4446 #endif
4448 if (!string || !*string || wordexp_only)
4449 return ((char *)NULL);
4451 #if !defined (HAVE_DEV_FD)
4452 pathname = make_named_pipe ();
4453 #else /* HAVE_DEV_FD */
4454 if (pipe (fildes) < 0)
4456 sys_error (_("cannot make pipe for process substitution"));
4457 return ((char *)NULL);
4459 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4460 the pipe in the parent, otherwise the read end. */
4461 parent_pipe_fd = fildes[open_for_read_in_child];
4462 child_pipe_fd = fildes[1 - open_for_read_in_child];
4463 /* Move the parent end of the pipe to some high file descriptor, to
4464 avoid clashes with FDs used by the script. */
4465 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4467 pathname = make_dev_fd_filename (parent_pipe_fd);
4468 #endif /* HAVE_DEV_FD */
4470 if (pathname == 0)
4472 sys_error (_("cannot make pipe for process substitution"));
4473 return ((char *)NULL);
4476 old_pid = last_made_pid;
4478 #if defined (JOB_CONTROL)
4479 old_pipeline_pgrp = pipeline_pgrp;
4480 pipeline_pgrp = shell_pgrp;
4481 save_pipeline (1);
4482 #endif /* JOB_CONTROL */
4484 pid = make_child ((char *)NULL, 1);
4485 if (pid == 0)
4487 reset_terminating_signals (); /* XXX */
4488 free_pushed_string_input ();
4489 /* Cancel traps, in trap.c. */
4490 restore_original_signals ();
4491 setup_async_signals ();
4492 subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
4495 #if defined (JOB_CONTROL)
4496 set_sigchld_handler ();
4497 stop_making_children ();
4498 /* XXX - should we only do this in the parent? (as in command subst) */
4499 pipeline_pgrp = old_pipeline_pgrp;
4500 #endif /* JOB_CONTROL */
4502 if (pid < 0)
4504 sys_error (_("cannot make child for process substitution"));
4505 free (pathname);
4506 #if defined (HAVE_DEV_FD)
4507 close (parent_pipe_fd);
4508 close (child_pipe_fd);
4509 #endif /* HAVE_DEV_FD */
4510 return ((char *)NULL);
4513 if (pid > 0)
4515 #if defined (JOB_CONTROL)
4516 restore_pipeline (1);
4517 #endif
4519 #if !defined (HAVE_DEV_FD)
4520 fifo_list[nfifo-1].proc = pid;
4521 #endif
4523 last_made_pid = old_pid;
4525 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4526 close_pgrp_pipe ();
4527 #endif /* JOB_CONTROL && PGRP_PIPE */
4529 #if defined (HAVE_DEV_FD)
4530 close (child_pipe_fd);
4531 #endif /* HAVE_DEV_FD */
4533 return (pathname);
4536 set_sigint_handler ();
4538 #if defined (JOB_CONTROL)
4539 set_job_control (0);
4540 #endif /* JOB_CONTROL */
4542 #if !defined (HAVE_DEV_FD)
4543 /* Open the named pipe in the child. */
4544 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4545 if (fd < 0)
4547 /* Two separate strings for ease of translation. */
4548 if (open_for_read_in_child)
4549 sys_error (_("cannot open named pipe %s for reading"), pathname);
4550 else
4551 sys_error (_("cannot open named pipe %s for writing"), pathname);
4553 exit (127);
4555 if (open_for_read_in_child)
4557 if (sh_unset_nodelay_mode (fd) < 0)
4559 sys_error (_("cannot reset nodelay mode for fd %d"), fd);
4560 exit (127);
4563 #else /* HAVE_DEV_FD */
4564 fd = child_pipe_fd;
4565 #endif /* HAVE_DEV_FD */
4567 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4569 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4570 open_for_read_in_child ? 0 : 1);
4571 exit (127);
4574 if (fd != (open_for_read_in_child ? 0 : 1))
4575 close (fd);
4577 /* Need to close any files that this process has open to pipes inherited
4578 from its parent. */
4579 if (current_fds_to_close)
4581 close_fd_bitmap (current_fds_to_close);
4582 current_fds_to_close = (struct fd_bitmap *)NULL;
4585 #if defined (HAVE_DEV_FD)
4586 /* Make sure we close the parent's end of the pipe and clear the slot
4587 in the fd list so it is not closed later, if reallocated by, for
4588 instance, pipe(2). */
4589 close (parent_pipe_fd);
4590 dev_fd_list[parent_pipe_fd] = 0;
4591 #endif /* HAVE_DEV_FD */
4593 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4595 #if !defined (HAVE_DEV_FD)
4596 /* Make sure we close the named pipe in the child before we exit. */
4597 close (open_for_read_in_child ? 0 : 1);
4598 #endif /* !HAVE_DEV_FD */
4600 exit (result);
4601 /*NOTREACHED*/
4603 #endif /* PROCESS_SUBSTITUTION */
4605 /***********************************/
4606 /* */
4607 /* Command Substitution */
4608 /* */
4609 /***********************************/
4611 static char *
4612 read_comsub (fd, quoted, rflag)
4613 int fd, quoted;
4614 int *rflag;
4616 char *istring, buf[128], *bufp, *s;
4617 int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
4618 ssize_t bufn;
4620 istring = (char *)NULL;
4621 istring_index = istring_size = bufn = tflag = 0;
4623 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
4624 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
4626 #ifdef __CYGWIN__
4627 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
4628 #endif
4630 /* Read the output of the command through the pipe. This may need to be
4631 changed to understand multibyte characters in the future. */
4632 while (1)
4634 if (fd < 0)
4635 break;
4636 if (--bufn <= 0)
4638 bufn = zread (fd, buf, sizeof (buf));
4639 if (bufn <= 0)
4640 break;
4641 bufp = buf;
4643 c = *bufp++;
4645 if (c == 0)
4647 #if 0
4648 internal_warning ("read_comsub: ignored null byte in input");
4649 #endif
4650 continue;
4653 /* Add the character to ISTRING, possibly after resizing it. */
4654 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4656 /* This is essentially quote_string inline */
4657 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
4658 istring[istring_index++] = CTLESC;
4659 /* Escape CTLESC and CTLNUL in the output to protect those characters
4660 from the rest of the word expansions (word splitting and globbing.)
4661 This is essentially quote_escapes inline. */
4662 else if (skip_ctlesc == 0 && c == CTLESC)
4664 tflag |= W_HASCTLESC;
4665 istring[istring_index++] = CTLESC;
4667 else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
4668 istring[istring_index++] = CTLESC;
4670 istring[istring_index++] = c;
4672 #if 0
4673 #if defined (__CYGWIN__)
4674 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4676 istring_index--;
4677 istring[istring_index - 1] = '\n';
4679 #endif
4680 #endif
4683 if (istring)
4684 istring[istring_index] = '\0';
4686 /* If we read no output, just return now and save ourselves some
4687 trouble. */
4688 if (istring_index == 0)
4690 FREE (istring);
4691 if (rflag)
4692 *rflag = tflag;
4693 return (char *)NULL;
4696 /* Strip trailing newlines from the output of the command. */
4697 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4699 while (istring_index > 0)
4701 if (istring[istring_index - 1] == '\n')
4703 --istring_index;
4705 /* If the newline was quoted, remove the quoting char. */
4706 if (istring[istring_index - 1] == CTLESC)
4707 --istring_index;
4709 else
4710 break;
4712 istring[istring_index] = '\0';
4714 else
4715 strip_trailing (istring, istring_index - 1, 1);
4717 if (rflag)
4718 *rflag = tflag;
4719 return istring;
4722 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
4723 contained string possibly quoted. */
4724 WORD_DESC *
4725 command_substitute (string, quoted)
4726 char *string;
4727 int quoted;
4729 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4730 char *istring;
4731 int result, fildes[2], function_value, pflags, rc, tflag;
4732 WORD_DESC *ret;
4734 istring = (char *)NULL;
4736 /* Don't fork () if there is no need to. In the case of no command to
4737 run, just return NULL. */
4738 if (!string || !*string || (string[0] == '\n' && !string[1]))
4739 return ((WORD_DESC *)NULL);
4741 if (wordexp_only && read_but_dont_execute)
4743 last_command_exit_value = 125;
4744 jump_to_top_level (EXITPROG);
4747 /* We're making the assumption here that the command substitution will
4748 eventually run a command from the file system. Since we'll run
4749 maybe_make_export_env in this subshell before executing that command,
4750 the parent shell and any other shells it starts will have to remake
4751 the environment. If we make it before we fork, other shells won't
4752 have to. Don't bother if we have any temporary variable assignments,
4753 though, because the export environment will be remade after this
4754 command completes anyway, but do it if all the words to be expanded
4755 are variable assignments. */
4756 if (subst_assign_varlist == 0 || garglist == 0)
4757 maybe_make_export_env (); /* XXX */
4759 /* Flags to pass to parse_and_execute() */
4760 pflags = interactive ? SEVAL_RESETLINE : 0;
4762 /* Pipe the output of executing STRING into the current shell. */
4763 if (pipe (fildes) < 0)
4765 sys_error (_("cannot make pipe for command substitution"));
4766 goto error_exit;
4769 old_pid = last_made_pid;
4770 #if defined (JOB_CONTROL)
4771 old_pipeline_pgrp = pipeline_pgrp;
4772 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4773 if ((subshell_environment & SUBSHELL_PIPE) == 0)
4774 pipeline_pgrp = shell_pgrp;
4775 cleanup_the_pipeline ();
4776 #endif /* JOB_CONTROL */
4778 old_async_pid = last_asynchronous_pid;
4779 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4780 last_asynchronous_pid = old_async_pid;
4782 if (pid == 0)
4783 /* Reset the signal handlers in the child, but don't free the
4784 trap strings. */
4785 reset_signal_handlers ();
4787 #if defined (JOB_CONTROL)
4788 /* XXX DO THIS ONLY IN PARENT ? XXX */
4789 set_sigchld_handler ();
4790 stop_making_children ();
4791 if (pid != 0)
4792 pipeline_pgrp = old_pipeline_pgrp;
4793 #else
4794 stop_making_children ();
4795 #endif /* JOB_CONTROL */
4797 if (pid < 0)
4799 sys_error (_("cannot make child for command substitution"));
4800 error_exit:
4802 FREE (istring);
4803 close (fildes[0]);
4804 close (fildes[1]);
4805 return ((WORD_DESC *)NULL);
4808 if (pid == 0)
4810 set_sigint_handler (); /* XXX */
4812 free_pushed_string_input ();
4814 if (dup2 (fildes[1], 1) < 0)
4816 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4817 exit (EXECUTION_FAILURE);
4820 /* If standard output is closed in the parent shell
4821 (such as after `exec >&-'), file descriptor 1 will be
4822 the lowest available file descriptor, and end up in
4823 fildes[0]. This can happen for stdin and stderr as well,
4824 but stdout is more important -- it will cause no output
4825 to be generated from this command. */
4826 if ((fildes[1] != fileno (stdin)) &&
4827 (fildes[1] != fileno (stdout)) &&
4828 (fildes[1] != fileno (stderr)))
4829 close (fildes[1]);
4831 if ((fildes[0] != fileno (stdin)) &&
4832 (fildes[0] != fileno (stdout)) &&
4833 (fildes[0] != fileno (stderr)))
4834 close (fildes[0]);
4836 /* The currently executing shell is not interactive. */
4837 interactive = 0;
4839 /* This is a subshell environment. */
4840 subshell_environment |= SUBSHELL_COMSUB;
4842 /* When not in POSIX mode, command substitution does not inherit
4843 the -e flag. */
4844 if (posixly_correct == 0)
4845 exit_immediately_on_error = 0;
4847 remove_quoted_escapes (string);
4849 startup_state = 2; /* see if we can avoid a fork */
4850 /* Give command substitution a place to jump back to on failure,
4851 so we don't go back up to main (). */
4852 result = setjmp (top_level);
4854 /* If we're running a command substitution inside a shell function,
4855 trap `return' so we don't return from the function in the subshell
4856 and go off to never-never land. */
4857 if (result == 0 && return_catch_flag)
4858 function_value = setjmp (return_catch);
4859 else
4860 function_value = 0;
4862 if (result == ERREXIT)
4863 rc = last_command_exit_value;
4864 else if (result == EXITPROG)
4865 rc = last_command_exit_value;
4866 else if (result)
4867 rc = EXECUTION_FAILURE;
4868 else if (function_value)
4869 rc = return_catch_value;
4870 else
4872 subshell_level++;
4873 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4874 subshell_level--;
4877 last_command_exit_value = rc;
4878 rc = run_exit_trap ();
4879 #if defined (PROCESS_SUBSTITUTION)
4880 unlink_fifo_list ();
4881 #endif
4882 exit (rc);
4884 else
4886 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4887 close_pgrp_pipe ();
4888 #endif /* JOB_CONTROL && PGRP_PIPE */
4890 close (fildes[1]);
4892 tflag = 0;
4893 istring = read_comsub (fildes[0], quoted, &tflag);
4895 close (fildes[0]);
4897 current_command_subst_pid = pid;
4898 last_command_exit_value = wait_for (pid);
4899 last_command_subst_pid = pid;
4900 last_made_pid = old_pid;
4902 #if defined (JOB_CONTROL)
4903 /* If last_command_exit_value > 128, then the substituted command
4904 was terminated by a signal. If that signal was SIGINT, then send
4905 SIGINT to ourselves. This will break out of loops, for instance. */
4906 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
4907 kill (getpid (), SIGINT);
4909 /* wait_for gives the terminal back to shell_pgrp. If some other
4910 process group should have it, give it away to that group here.
4911 pipeline_pgrp is non-zero only while we are constructing a
4912 pipline, so what we are concerned about is whether or not that
4913 pipeline was started in the background. A pipeline started in
4914 the background should never get the tty back here. */
4915 #if 0
4916 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
4917 #else
4918 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
4919 #endif
4920 give_terminal_to (pipeline_pgrp, 0);
4921 #endif /* JOB_CONTROL */
4923 ret = alloc_word_desc ();
4924 ret->word = istring;
4925 ret->flags = tflag;
4927 return ret;
4931 /********************************************************
4933 * Utility functions for parameter expansion *
4935 ********************************************************/
4937 #if defined (ARRAY_VARS)
4939 static arrayind_t
4940 array_length_reference (s)
4941 char *s;
4943 int len;
4944 arrayind_t ind;
4945 char *akey;
4946 char *t, c;
4947 ARRAY *array;
4948 SHELL_VAR *var;
4950 var = array_variable_part (s, &t, &len);
4952 /* If unbound variables should generate an error, report one and return
4953 failure. */
4954 if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
4956 c = *--t;
4957 *t = '\0';
4958 err_unboundvar (s);
4959 *t = c;
4960 return (-1);
4962 else if (var == 0)
4963 return 0;
4965 /* We support a couple of expansions for variables that are not arrays.
4966 We'll return the length of the value for v[0], and 1 for v[@] or
4967 v[*]. Return 0 for everything else. */
4969 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
4971 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
4973 if (assoc_p (var))
4974 return (assoc_num_elements (assoc_cell (var)));
4975 else if (array_p (var))
4976 return (array_num_elements (array));
4977 else
4978 return 1;
4981 if (assoc_p (var))
4983 t[len - 1] = '\0';
4984 akey = expand_assignment_string_to_string (t, 0); /* [ */
4985 t[len - 1] = ']';
4986 if (akey == 0 || *akey == 0)
4988 err_badarraysub (t);
4989 return (-1);
4991 t = assoc_reference (assoc_cell (var), akey);
4993 else
4995 ind = array_expand_index (t, len);
4996 if (ind < 0)
4998 err_badarraysub (t);
4999 return (-1);
5001 if (array_p (var))
5002 t = array_reference (array, ind);
5003 else
5004 t = (ind == 0) ? value_cell (var) : (char *)NULL;
5007 len = MB_STRLEN (t);
5008 return (len);
5010 #endif /* ARRAY_VARS */
5012 static int
5013 valid_brace_expansion_word (name, var_is_special)
5014 char *name;
5015 int var_is_special;
5017 if (DIGIT (*name) && all_digits (name))
5018 return 1;
5019 else if (var_is_special)
5020 return 1;
5021 #if defined (ARRAY_VARS)
5022 else if (valid_array_reference (name))
5023 return 1;
5024 #endif /* ARRAY_VARS */
5025 else if (legal_identifier (name))
5026 return 1;
5027 else
5028 return 0;
5031 static int
5032 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
5033 char *name;
5034 int quoted;
5035 int *quoted_dollar_atp, *contains_dollar_at;
5037 char *temp1;
5039 if (name == 0)
5041 if (quoted_dollar_atp)
5042 *quoted_dollar_atp = 0;
5043 if (contains_dollar_at)
5044 *contains_dollar_at = 0;
5045 return 0;
5048 /* check for $@ and $* */
5049 if (name[0] == '@' && name[1] == 0)
5051 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5052 *quoted_dollar_atp = 1;
5053 if (contains_dollar_at)
5054 *contains_dollar_at = 1;
5055 return 1;
5057 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
5059 if (contains_dollar_at)
5060 *contains_dollar_at = 1;
5061 return 1;
5064 /* Now check for ${array[@]} and ${array[*]} */
5065 #if defined (ARRAY_VARS)
5066 else if (valid_array_reference (name))
5068 temp1 = xstrchr (name, '[');
5069 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
5071 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5072 *quoted_dollar_atp = 1;
5073 if (contains_dollar_at)
5074 *contains_dollar_at = 1;
5075 return 1;
5076 } /* [ */
5077 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
5078 which should result in separate words even when IFS is unset. */
5079 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
5081 if (contains_dollar_at)
5082 *contains_dollar_at = 1;
5083 return 1;
5086 #endif
5087 return 0;
5090 /* Parameter expand NAME, and return a new string which is the expansion,
5091 or NULL if there was no expansion.
5092 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
5093 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
5094 NAME was found inside of a double-quoted expression. */
5095 static WORD_DESC *
5096 parameter_brace_expand_word (name, var_is_special, quoted)
5097 char *name;
5098 int var_is_special, quoted;
5100 WORD_DESC *ret;
5101 char *temp, *tt;
5102 intmax_t arg_index;
5103 SHELL_VAR *var;
5104 int atype, rflags;
5106 ret = 0;
5107 temp = 0;
5108 rflags = 0;
5110 /* Handle multiple digit arguments, as in ${11}. */
5111 if (legal_number (name, &arg_index))
5113 tt = get_dollar_var_value (arg_index);
5114 if (tt)
5115 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5116 ? quote_string (tt)
5117 : quote_escapes (tt);
5118 else
5119 temp = (char *)NULL;
5120 FREE (tt);
5122 else if (var_is_special) /* ${@} */
5124 int sindex;
5125 tt = (char *)xmalloc (2 + strlen (name));
5126 tt[sindex = 0] = '$';
5127 strcpy (tt + 1, name);
5129 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
5130 (int *)NULL, (int *)NULL, 0);
5131 free (tt);
5133 #if defined (ARRAY_VARS)
5134 else if (valid_array_reference (name))
5136 temp = array_value (name, quoted, &atype);
5137 if (atype == 0 && temp)
5138 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5139 ? quote_string (temp)
5140 : quote_escapes (temp);
5141 else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5142 rflags |= W_HASQUOTEDNULL;
5144 #endif
5145 else if (var = find_variable (name))
5147 if (var_isset (var) && invisible_p (var) == 0)
5149 #if defined (ARRAY_VARS)
5150 if (assoc_p (var))
5151 temp = assoc_reference (assoc_cell (var), "0");
5152 else if (array_p (var))
5153 temp = array_reference (array_cell (var), 0);
5154 else
5155 temp = value_cell (var);
5156 #else
5157 temp = value_cell (var);
5158 #endif
5160 if (temp)
5161 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5162 ? quote_string (temp)
5163 : quote_escapes (temp);
5165 else
5166 temp = (char *)NULL;
5168 else
5169 temp = (char *)NULL;
5171 if (ret == 0)
5173 ret = alloc_word_desc ();
5174 ret->word = temp;
5175 ret->flags |= rflags;
5177 return ret;
5180 /* Expand an indirect reference to a variable: ${!NAME} expands to the
5181 value of the variable whose name is the value of NAME. */
5182 static WORD_DESC *
5183 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
5184 char *name;
5185 int var_is_special, quoted;
5186 int *quoted_dollar_atp, *contains_dollar_at;
5188 char *temp, *t;
5189 WORD_DESC *w;
5191 w = parameter_brace_expand_word (name, var_is_special, quoted);
5192 t = w->word;
5193 /* Have to dequote here if necessary */
5194 if (t)
5196 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5197 ? dequote_string (t)
5198 : dequote_escapes (t);
5199 free (t);
5200 t = temp;
5202 dispose_word_desc (w);
5204 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5205 if (t == 0)
5206 return (WORD_DESC *)NULL;
5208 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
5209 free (t);
5211 return w;
5214 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5215 depending on the value of C, the separating character. C can be one of
5216 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5217 between double quotes. */
5218 static WORD_DESC *
5219 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5220 char *name, *value;
5221 int c, quoted, *qdollaratp, *hasdollarat;
5223 WORD_DESC *w;
5224 WORD_LIST *l;
5225 char *t, *t1, *temp;
5226 int hasdol;
5228 /* If the entire expression is between double quotes, we want to treat
5229 the value as a double-quoted string, with the exception that we strip
5230 embedded unescaped double quotes (for sh backwards compatibility). */
5231 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5233 hasdol = 0;
5234 temp = string_extract_double_quoted (value, &hasdol, 1);
5236 else
5237 temp = value;
5239 w = alloc_word_desc ();
5240 hasdol = 0;
5241 /* XXX was 0 not quoted */
5242 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5243 : (WORD_LIST *)0;
5244 if (hasdollarat)
5245 *hasdollarat = hasdol || (l && l->next);
5246 if (temp != value)
5247 free (temp);
5248 if (l)
5250 /* The expansion of TEMP returned something. We need to treat things
5251 slightly differently if HASDOL is non-zero. If we have "$@", the
5252 individual words have already been quoted. We need to turn them
5253 into a string with the words separated by the first character of
5254 $IFS without any additional quoting, so string_list_dollar_at won't
5255 do the right thing. We use string_list_dollar_star instead. */
5256 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5258 /* If l->next is not null, we know that TEMP contained "$@", since that
5259 is the only expansion that creates more than one word. */
5260 if (qdollaratp && ((hasdol && quoted) || l->next))
5261 *qdollaratp = 1;
5262 dispose_words (l);
5264 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5266 /* The brace expansion occurred between double quotes and there was
5267 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5268 it does not expand to anything. In this case, we want to return
5269 a quoted empty string. */
5270 temp = make_quoted_char ('\0');
5271 w->flags |= W_HASQUOTEDNULL;
5273 else
5274 temp = (char *)NULL;
5276 if (c == '-' || c == '+')
5278 w->word = temp;
5279 return w;
5282 /* c == '=' */
5283 t = temp ? savestring (temp) : savestring ("");
5284 t1 = dequote_string (t);
5285 free (t);
5286 #if defined (ARRAY_VARS)
5287 if (valid_array_reference (name))
5288 assign_array_element (name, t1, 0);
5289 else
5290 #endif /* ARRAY_VARS */
5291 bind_variable (name, t1, 0);
5292 free (t1);
5294 w->word = temp;
5295 return w;
5298 /* Deal with the right hand side of a ${name:?value} expansion in the case
5299 that NAME is null or not set. If VALUE is non-null it is expanded and
5300 used as the error message to print, otherwise a standard message is
5301 printed. */
5302 static void
5303 parameter_brace_expand_error (name, value)
5304 char *name, *value;
5306 WORD_LIST *l;
5307 char *temp;
5309 if (value && *value)
5311 l = expand_string (value, 0);
5312 temp = string_list (l);
5313 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5314 FREE (temp);
5315 dispose_words (l);
5317 else
5318 report_error (_("%s: parameter null or not set"), name);
5320 /* Free the data we have allocated during this expansion, since we
5321 are about to longjmp out. */
5322 free (name);
5323 FREE (value);
5326 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5327 OK to do. */
5328 static int
5329 valid_length_expression (name)
5330 char *name;
5332 return (name[1] == '\0' || /* ${#} */
5333 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5334 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5335 #if defined (ARRAY_VARS)
5336 valid_array_reference (name + 1) || /* ${#a[7]} */
5337 #endif
5338 legal_identifier (name + 1)); /* ${#PS1} */
5341 #if defined (HANDLE_MULTIBYTE)
5342 size_t
5343 mbstrlen (s)
5344 const char *s;
5346 size_t clen, nc;
5347 mbstate_t mbs, mbsbak;
5349 nc = 0;
5350 memset (&mbs, 0, sizeof (mbs));
5351 mbsbak = mbs;
5352 while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5354 if (MB_INVALIDCH(clen))
5356 clen = 1; /* assume single byte */
5357 mbs = mbsbak;
5360 s += clen;
5361 nc++;
5362 mbsbak = mbs;
5364 return nc;
5366 #endif
5369 /* Handle the parameter brace expansion that requires us to return the
5370 length of a parameter. */
5371 static intmax_t
5372 parameter_brace_expand_length (name)
5373 char *name;
5375 char *t, *newname;
5376 intmax_t number, arg_index;
5377 WORD_LIST *list;
5378 #if defined (ARRAY_VARS)
5379 SHELL_VAR *var;
5380 #endif
5382 if (name[1] == '\0') /* ${#} */
5383 number = number_of_args ();
5384 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5385 number = number_of_args ();
5386 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5388 /* Take the lengths of some of the shell's special parameters. */
5389 switch (name[1])
5391 case '-':
5392 t = which_set_flags ();
5393 break;
5394 case '?':
5395 t = itos (last_command_exit_value);
5396 break;
5397 case '$':
5398 t = itos (dollar_dollar_pid);
5399 break;
5400 case '!':
5401 if (last_asynchronous_pid == NO_PID)
5402 t = (char *)NULL;
5403 else
5404 t = itos (last_asynchronous_pid);
5405 break;
5406 case '#':
5407 t = itos (number_of_args ());
5408 break;
5410 number = STRLEN (t);
5411 FREE (t);
5413 #if defined (ARRAY_VARS)
5414 else if (valid_array_reference (name + 1))
5415 number = array_length_reference (name + 1);
5416 #endif /* ARRAY_VARS */
5417 else
5419 number = 0;
5421 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5423 t = get_dollar_var_value (arg_index);
5424 number = MB_STRLEN (t);
5425 FREE (t);
5427 #if defined (ARRAY_VARS)
5428 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
5430 if (assoc_p (var))
5431 t = assoc_reference (assoc_cell (var), "0");
5432 else
5433 t = array_reference (array_cell (var), 0);
5434 number = MB_STRLEN (t);
5436 #endif
5437 else /* ${#PS1} */
5439 newname = savestring (name);
5440 newname[0] = '$';
5441 list = expand_string (newname, Q_DOUBLE_QUOTES);
5442 t = list ? string_list (list) : (char *)NULL;
5443 free (newname);
5444 if (list)
5445 dispose_words (list);
5447 number = MB_STRLEN (t);
5448 FREE (t);
5452 return (number);
5455 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5456 so we do some ad-hoc parsing of an arithmetic expression to find
5457 the first DELIM, instead of using strchr(3). Two rules:
5458 1. If the substring contains a `(', read until closing `)'.
5459 2. If the substring contains a `?', read past one `:' for each `?'.
5462 static char *
5463 skiparith (substr, delim)
5464 char *substr;
5465 int delim;
5467 size_t sublen;
5468 int skipcol, pcount, i;
5469 DECLARE_MBSTATE;
5471 sublen = strlen (substr);
5472 i = skipcol = pcount = 0;
5473 while (substr[i])
5475 /* Balance parens */
5476 if (substr[i] == LPAREN)
5478 pcount++;
5479 i++;
5480 continue;
5482 if (substr[i] == RPAREN && pcount)
5484 pcount--;
5485 i++;
5486 continue;
5488 if (pcount)
5490 ADVANCE_CHAR (substr, sublen, i);
5491 continue;
5494 /* Skip one `:' for each `?' */
5495 if (substr[i] == ':' && skipcol)
5497 skipcol--;
5498 i++;
5499 continue;
5501 if (substr[i] == delim)
5502 break;
5503 if (substr[i] == '?')
5505 skipcol++;
5506 i++;
5507 continue;
5509 ADVANCE_CHAR (substr, sublen, i);
5512 return (substr + i);
5515 /* Verify and limit the start and end of the desired substring. If
5516 VTYPE == 0, a regular shell variable is being used; if it is 1,
5517 then the positional parameters are being used; if it is 2, then
5518 VALUE is really a pointer to an array variable that should be used.
5519 Return value is 1 if both values were OK, 0 if there was a problem
5520 with an invalid expression, or -1 if the values were out of range. */
5521 static int
5522 verify_substring_values (v, value, substr, vtype, e1p, e2p)
5523 SHELL_VAR *v;
5524 char *value, *substr;
5525 int vtype;
5526 intmax_t *e1p, *e2p;
5528 char *t, *temp1, *temp2;
5529 arrayind_t len;
5530 int expok;
5531 #if defined (ARRAY_VARS)
5532 ARRAY *a;
5533 HASH_TABLE *h;
5534 #endif
5536 /* duplicate behavior of strchr(3) */
5537 t = skiparith (substr, ':');
5538 if (*t && *t == ':')
5539 *t = '\0';
5540 else
5541 t = (char *)0;
5543 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
5544 *e1p = evalexp (temp1, &expok);
5545 free (temp1);
5546 if (expok == 0)
5547 return (0);
5549 len = -1; /* paranoia */
5550 switch (vtype)
5552 case VT_VARIABLE:
5553 case VT_ARRAYMEMBER:
5554 len = MB_STRLEN (value);
5555 break;
5556 case VT_POSPARMS:
5557 len = number_of_args () + 1;
5558 if (*e1p == 0)
5559 len++; /* add one arg if counting from $0 */
5560 break;
5561 #if defined (ARRAY_VARS)
5562 case VT_ARRAYVAR:
5563 /* For arrays, the first value deals with array indices. Negative
5564 offsets count from one past the array's maximum index. Associative
5565 arrays treat the number of elements as the maximum index. */
5566 if (assoc_p (v))
5568 h = assoc_cell (v);
5569 len = assoc_num_elements (h) + (*e1p < 0);
5571 else
5573 a = (ARRAY *)value;
5574 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
5576 break;
5577 #endif
5580 if (len == -1) /* paranoia */
5581 return -1;
5583 if (*e1p < 0) /* negative offsets count from end */
5584 *e1p += len;
5586 if (*e1p > len || *e1p < 0)
5587 return (-1);
5589 #if defined (ARRAY_VARS)
5590 /* For arrays, the second offset deals with the number of elements. */
5591 if (vtype == VT_ARRAYVAR)
5592 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
5593 #endif
5595 if (t)
5597 t++;
5598 temp2 = savestring (t);
5599 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
5600 free (temp2);
5601 t[-1] = ':';
5602 *e2p = evalexp (temp1, &expok);
5603 free (temp1);
5604 if (expok == 0)
5605 return (0);
5606 if (*e2p < 0)
5608 internal_error (_("%s: substring expression < 0"), t);
5609 return (0);
5611 #if defined (ARRAY_VARS)
5612 /* In order to deal with sparse arrays, push the intelligence about how
5613 to deal with the number of elements desired down to the array-
5614 specific functions. */
5615 if (vtype != VT_ARRAYVAR)
5616 #endif
5618 *e2p += *e1p; /* want E2 chars starting at E1 */
5619 if (*e2p > len)
5620 *e2p = len;
5623 else
5624 *e2p = len;
5626 return (1);
5629 /* Return the type of variable specified by VARNAME (simple variable,
5630 positional param, or array variable). Also return the value specified
5631 by VARNAME (value of a variable or a reference to an array element).
5632 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5633 characters in the value are quoted with CTLESC and takes appropriate
5634 steps. For convenience, *VALP is set to the dequoted VALUE. */
5635 static int
5636 get_var_and_type (varname, value, quoted, varp, valp)
5637 char *varname, *value;
5638 int quoted;
5639 SHELL_VAR **varp;
5640 char **valp;
5642 int vtype;
5643 char *temp;
5644 #if defined (ARRAY_VARS)
5645 SHELL_VAR *v;
5646 #endif
5648 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5649 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5650 if (vtype == VT_POSPARMS && varname[0] == '*')
5651 vtype |= VT_STARSUB;
5652 *varp = (SHELL_VAR *)NULL;
5654 #if defined (ARRAY_VARS)
5655 if (valid_array_reference (varname))
5657 v = array_variable_part (varname, &temp, (int *)0);
5658 if (v && (array_p (v) || assoc_p (v)))
5659 { /* [ */
5660 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5662 /* Callers have to differentiate betwen indexed and associative */
5663 vtype = VT_ARRAYVAR;
5664 if (temp[0] == '*')
5665 vtype |= VT_STARSUB;
5666 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
5668 else
5670 vtype = VT_ARRAYMEMBER;
5671 *valp = array_value (varname, 1, (int *)NULL);
5673 *varp = v;
5675 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5677 vtype = VT_VARIABLE;
5678 *varp = v;
5679 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5680 *valp = dequote_string (value);
5681 else
5682 *valp = dequote_escapes (value);
5684 else
5686 vtype = VT_ARRAYMEMBER;
5687 *varp = v;
5688 *valp = array_value (varname, 1, (int *)NULL);
5691 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
5693 vtype = VT_ARRAYMEMBER;
5694 *varp = v;
5695 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
5697 else
5698 #endif
5700 if (value && vtype == VT_VARIABLE)
5702 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5703 *valp = dequote_string (value);
5704 else
5705 *valp = dequote_escapes (value);
5707 else
5708 *valp = value;
5711 return vtype;
5714 /******************************************************/
5715 /* */
5716 /* Functions to extract substrings of variable values */
5717 /* */
5718 /******************************************************/
5720 #if defined (HANDLE_MULTIBYTE)
5721 /* Character-oriented rather than strictly byte-oriented substrings. S and
5722 E, rather being strict indices into STRING, indicate character (possibly
5723 multibyte character) positions that require calculation.
5724 Used by the ${param:offset[:length]} expansion. */
5725 static char *
5726 mb_substring (string, s, e)
5727 char *string;
5728 int s, e;
5730 char *tt;
5731 int start, stop, i, slen;
5732 DECLARE_MBSTATE;
5734 start = 0;
5735 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5736 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5738 i = s;
5739 while (string[start] && i--)
5740 ADVANCE_CHAR (string, slen, start);
5741 stop = start;
5742 i = e - s;
5743 while (string[stop] && i--)
5744 ADVANCE_CHAR (string, slen, stop);
5745 tt = substring (string, start, stop);
5746 return tt;
5748 #endif
5750 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
5751 is `@', use the positional parameters; otherwise, use the value of
5752 VARNAME. If VARNAME is an array variable, use the array elements. */
5754 static char *
5755 parameter_brace_substring (varname, value, substr, quoted)
5756 char *varname, *value, *substr;
5757 int quoted;
5759 intmax_t e1, e2;
5760 int vtype, r, starsub;
5761 char *temp, *val, *tt, *oname;
5762 SHELL_VAR *v;
5764 if (value == 0)
5765 return ((char *)NULL);
5767 oname = this_command_name;
5768 this_command_name = varname;
5770 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5771 if (vtype == -1)
5773 this_command_name = oname;
5774 return ((char *)NULL);
5777 starsub = vtype & VT_STARSUB;
5778 vtype &= ~VT_STARSUB;
5780 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
5781 this_command_name = oname;
5782 if (r <= 0)
5783 return ((r == 0) ? &expand_param_error : (char *)NULL);
5785 switch (vtype)
5787 case VT_VARIABLE:
5788 case VT_ARRAYMEMBER:
5789 #if defined (HANDLE_MULTIBYTE)
5790 if (MB_CUR_MAX > 1)
5791 tt = mb_substring (val, e1, e2);
5792 else
5793 #endif
5794 tt = substring (val, e1, e2);
5796 if (vtype == VT_VARIABLE)
5797 FREE (val);
5798 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5799 temp = quote_string (tt);
5800 else
5801 temp = tt ? quote_escapes (tt) : (char *)NULL;
5802 FREE (tt);
5803 break;
5804 case VT_POSPARMS:
5805 tt = pos_params (varname, e1, e2, quoted);
5806 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5808 temp = tt ? quote_escapes (tt) : (char *)NULL;
5809 FREE (tt);
5811 else
5812 temp = tt;
5813 break;
5814 #if defined (ARRAY_VARS)
5815 case VT_ARRAYVAR:
5816 if (assoc_p (v))
5817 /* we convert to list and take first e2 elements starting at e1th
5818 element -- officially undefined for now */
5819 temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
5820 else
5821 /* We want E2 to be the number of elements desired (arrays can be sparse,
5822 so verify_substring_values just returns the numbers specified and we
5823 rely on array_subrange to understand how to deal with them). */
5824 temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5825 /* array_subrange now calls array_quote_escapes as appropriate, so the
5826 caller no longer needs to. */
5827 break;
5828 #endif
5829 default:
5830 temp = (char *)NULL;
5833 return temp;
5836 /****************************************************************/
5837 /* */
5838 /* Functions to perform pattern substitution on variable values */
5839 /* */
5840 /****************************************************************/
5842 char *
5843 pat_subst (string, pat, rep, mflags)
5844 char *string, *pat, *rep;
5845 int mflags;
5847 char *ret, *s, *e, *str;
5848 int rsize, rptr, l, replen, mtype;
5850 mtype = mflags & MATCH_TYPEMASK;
5852 /* Special cases:
5853 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
5854 * with REP and return the result.
5855 * 2. A null pattern with mtype == MATCH_END means to append REP to
5856 * STRING and return the result.
5858 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5860 replen = STRLEN (rep);
5861 l = strlen (string);
5862 ret = (char *)xmalloc (replen + l + 2);
5863 if (replen == 0)
5864 strcpy (ret, string);
5865 else if (mtype == MATCH_BEG)
5867 strcpy (ret, rep);
5868 strcpy (ret + replen, string);
5870 else
5872 strcpy (ret, string);
5873 strcpy (ret + l, rep);
5875 return (ret);
5878 ret = (char *)xmalloc (rsize = 64);
5879 ret[0] = '\0';
5881 for (replen = STRLEN (rep), rptr = 0, str = string;;)
5883 if (match_pattern (str, pat, mtype, &s, &e) == 0)
5884 break;
5885 l = s - str;
5886 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5888 /* OK, now copy the leading unmatched portion of the string (from
5889 str to s) to ret starting at rptr (the current offset). Then copy
5890 the replacement string at ret + rptr + (s - str). Increment
5891 rptr (if necessary) and str and go on. */
5892 if (l)
5894 strncpy (ret + rptr, str, l);
5895 rptr += l;
5897 if (replen)
5899 strncpy (ret + rptr, rep, replen);
5900 rptr += replen;
5902 str = e; /* e == end of match */
5904 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
5905 break;
5907 if (s == e)
5908 e++, str++; /* avoid infinite recursion on zero-length match */
5911 /* Now copy the unmatched portion of the input string */
5912 if (*str)
5914 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
5915 strcpy (ret + rptr, str);
5917 else
5918 ret[rptr] = '\0';
5920 return ret;
5923 /* Do pattern match and replacement on the positional parameters. */
5924 static char *
5925 pos_params_pat_subst (string, pat, rep, mflags)
5926 char *string, *pat, *rep;
5927 int mflags;
5929 WORD_LIST *save, *params;
5930 WORD_DESC *w;
5931 char *ret;
5932 int pchar, qflags;
5934 save = params = list_rest_of_args ();
5935 if (save == 0)
5936 return ((char *)NULL);
5938 for ( ; params; params = params->next)
5940 ret = pat_subst (params->word->word, pat, rep, mflags);
5941 w = alloc_word_desc ();
5942 w->word = ret ? ret : savestring ("");
5943 dispose_word (params->word);
5944 params->word = w;
5947 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
5948 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
5950 #if 0
5951 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
5952 ret = string_list_dollar_star (quote_list (save));
5953 else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
5954 ret = string_list_dollar_star (save);
5955 else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
5956 ret = string_list_dollar_at (save, qflags);
5957 else
5958 ret = string_list_dollar_star (save);
5959 #else
5960 ret = string_list_pos_params (pchar, save, qflags);
5961 #endif
5963 dispose_words (save);
5965 return (ret);
5968 /* Perform pattern substitution on VALUE, which is the expansion of
5969 VARNAME. PATSUB is an expression supplying the pattern to match
5970 and the string to substitute. QUOTED is a flags word containing
5971 the type of quoting currently in effect. */
5972 static char *
5973 parameter_brace_patsub (varname, value, patsub, quoted)
5974 char *varname, *value, *patsub;
5975 int quoted;
5977 int vtype, mflags, starsub, delim;
5978 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
5979 SHELL_VAR *v;
5981 if (value == 0)
5982 return ((char *)NULL);
5984 this_command_name = varname;
5986 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5987 if (vtype == -1)
5988 return ((char *)NULL);
5990 starsub = vtype & VT_STARSUB;
5991 vtype &= ~VT_STARSUB;
5993 mflags = 0;
5994 if (patsub && *patsub == '/')
5996 mflags |= MATCH_GLOBREP;
5997 patsub++;
6000 /* Malloc this because expand_string_if_necessary or one of the expansion
6001 functions in its call chain may free it on a substitution error. */
6002 lpatsub = savestring (patsub);
6004 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6005 mflags |= MATCH_QUOTED;
6007 if (starsub)
6008 mflags |= MATCH_STARSUB;
6010 /* If the pattern starts with a `/', make sure we skip over it when looking
6011 for the replacement delimiter. */
6012 #if 0
6013 if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
6014 *rep++ = '\0';
6015 else
6016 rep = (char *)NULL;
6017 #else
6018 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
6019 if (lpatsub[delim] == '/')
6021 lpatsub[delim] = 0;
6022 rep = lpatsub + delim + 1;
6024 else
6025 rep = (char *)NULL;
6026 #endif
6028 if (rep && *rep == '\0')
6029 rep = (char *)NULL;
6031 /* Perform the same expansions on the pattern as performed by the
6032 pattern removal expansions. */
6033 pat = getpattern (lpatsub, quoted, 1);
6035 if (rep)
6037 if ((mflags & MATCH_QUOTED) == 0)
6038 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
6039 else
6040 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
6043 /* ksh93 doesn't allow the match specifier to be a part of the expanded
6044 pattern. This is an extension. Make sure we don't anchor the pattern
6045 at the beginning or end of the string if we're doing global replacement,
6046 though. */
6047 p = pat;
6048 if (mflags & MATCH_GLOBREP)
6049 mflags |= MATCH_ANY;
6050 else if (pat && pat[0] == '#')
6052 mflags |= MATCH_BEG;
6053 p++;
6055 else if (pat && pat[0] == '%')
6057 mflags |= MATCH_END;
6058 p++;
6060 else
6061 mflags |= MATCH_ANY;
6063 /* OK, we now want to substitute REP for PAT in VAL. If
6064 flags & MATCH_GLOBREP is non-zero, the substitution is done
6065 everywhere, otherwise only the first occurrence of PAT is
6066 replaced. The pattern matching code doesn't understand
6067 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6068 values passed in (VT_VARIABLE) so the pattern substitution
6069 code works right. We need to requote special chars after
6070 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6071 other cases if QUOTED == 0, since the posparams and arrays
6072 indexed by * or @ do special things when QUOTED != 0. */
6074 switch (vtype)
6076 case VT_VARIABLE:
6077 case VT_ARRAYMEMBER:
6078 temp = pat_subst (val, p, rep, mflags);
6079 if (vtype == VT_VARIABLE)
6080 FREE (val);
6081 if (temp)
6083 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6084 free (temp);
6085 temp = tt;
6087 break;
6088 case VT_POSPARMS:
6089 temp = pos_params_pat_subst (val, p, rep, mflags);
6090 if (temp && (mflags & MATCH_QUOTED) == 0)
6092 tt = quote_escapes (temp);
6093 free (temp);
6094 temp = tt;
6096 break;
6097 #if defined (ARRAY_VARS)
6098 case VT_ARRAYVAR:
6099 temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6100 : array_patsub (array_cell (v), p, rep, mflags);
6101 /* Don't call quote_escapes anymore; array_patsub calls
6102 array_quote_escapes as appropriate before adding the
6103 space separators; ditto for assoc_patsub. */
6104 break;
6105 #endif
6108 FREE (pat);
6109 FREE (rep);
6110 free (lpatsub);
6112 return temp;
6115 /****************************************************************/
6116 /* */
6117 /* Functions to perform case modification on variable values */
6118 /* */
6119 /****************************************************************/
6121 /* Do case modification on the positional parameters. */
6123 static char *
6124 pos_params_modcase (string, pat, modop, mflags)
6125 char *string, *pat;
6126 int modop;
6127 int mflags;
6129 WORD_LIST *save, *params;
6130 WORD_DESC *w;
6131 char *ret;
6132 int pchar, qflags;
6134 save = params = list_rest_of_args ();
6135 if (save == 0)
6136 return ((char *)NULL);
6138 for ( ; params; params = params->next)
6140 ret = sh_modcase (params->word->word, pat, modop);
6141 w = alloc_word_desc ();
6142 w->word = ret ? ret : savestring ("");
6143 dispose_word (params->word);
6144 params->word = w;
6147 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6148 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6150 ret = string_list_pos_params (pchar, save, qflags);
6151 dispose_words (save);
6153 return (ret);
6156 /* Perform case modification on VALUE, which is the expansion of
6157 VARNAME. MODSPEC is an expression supplying the type of modification
6158 to perform. QUOTED is a flags word containing the type of quoting
6159 currently in effect. */
6160 static char *
6161 parameter_brace_casemod (varname, value, modspec, patspec, quoted)
6162 char *varname, *value;
6163 int modspec;
6164 char *patspec;
6165 int quoted;
6167 int vtype, starsub, modop, mflags, x;
6168 char *val, *temp, *pat, *p, *lpat, *tt;
6169 SHELL_VAR *v;
6171 if (value == 0)
6172 return ((char *)NULL);
6174 this_command_name = varname;
6176 vtype = get_var_and_type (varname, value, quoted, &v, &val);
6177 if (vtype == -1)
6178 return ((char *)NULL);
6180 starsub = vtype & VT_STARSUB;
6181 vtype &= ~VT_STARSUB;
6183 modop = 0;
6184 mflags = 0;
6185 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6186 mflags |= MATCH_QUOTED;
6187 if (starsub)
6188 mflags |= MATCH_STARSUB;
6190 p = patspec;
6191 if (modspec == '^')
6193 x = p && p[0] == modspec;
6194 modop = x ? CASE_UPPER : CASE_CAPITALIZE;
6195 p += x;
6197 else if (modspec == ',')
6199 x = p && p[0] == modspec;
6200 modop = x ? CASE_LOWER : CASE_UNCAP;
6201 p += x;
6203 else if (modspec == '~')
6205 x = p && p[0] == modspec;
6206 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6207 p += x;
6210 lpat = p ? savestring (p) : 0;
6211 /* Perform the same expansions on the pattern as performed by the
6212 pattern removal expansions. FOR LATER */
6213 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6215 /* OK, now we do the case modification. */
6216 switch (vtype)
6218 case VT_VARIABLE:
6219 case VT_ARRAYMEMBER:
6220 temp = sh_modcase (val, pat, modop);
6221 if (vtype == VT_VARIABLE)
6222 FREE (val);
6223 if (temp)
6225 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6226 free (temp);
6227 temp = tt;
6229 break;
6231 case VT_POSPARMS:
6232 temp = pos_params_modcase (val, pat, modop, mflags);
6233 if (temp && (mflags & MATCH_QUOTED) == 0)
6235 tt = quote_escapes (temp);
6236 free (temp);
6237 temp = tt;
6239 break;
6241 #if defined (ARRAY_VARS)
6242 case VT_ARRAYVAR:
6243 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6244 : array_modcase (array_cell (v), pat, modop, mflags);
6245 /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6246 as appropriate before adding the space separators; ditto for
6247 assoc_modcase. */
6248 break;
6249 #endif
6252 FREE (pat);
6253 free (lpat);
6255 return temp;
6258 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
6259 any occur, this must be a nested command substitution, so return 0.
6260 Otherwise, return 1. A valid arithmetic expression must always have a
6261 ( before a matching ), so any cases where there are more right parens
6262 means that this must not be an arithmetic expression, though the parser
6263 will not accept it without a balanced total number of parens. */
6264 static int
6265 chk_arithsub (s, len)
6266 const char *s;
6267 int len;
6269 int i, count;
6270 DECLARE_MBSTATE;
6272 i = count = 0;
6273 while (i < len)
6275 if (s[i] == '(')
6276 count++;
6277 else if (s[i] == ')')
6279 count--;
6280 if (count < 0)
6281 return 0;
6284 switch (s[i])
6286 default:
6287 ADVANCE_CHAR (s, len, i);
6288 break;
6290 case '\\':
6291 i++;
6292 if (s[i])
6293 ADVANCE_CHAR (s, len, i);
6294 break;
6296 case '\'':
6297 i = skip_single_quoted (s, len, ++i);
6298 break;
6300 case '"':
6301 i = skip_double_quoted ((char *)s, len, ++i);
6302 break;
6306 return (count == 0);
6309 /****************************************************************/
6310 /* */
6311 /* Functions to perform parameter expansion on a string */
6312 /* */
6313 /****************************************************************/
6315 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
6316 static WORD_DESC *
6317 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
6318 char *string;
6319 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
6321 int check_nullness, var_is_set, var_is_null, var_is_special;
6322 int want_substring, want_indir, want_patsub, want_casemod;
6323 char *name, *value, *temp, *temp1;
6324 WORD_DESC *tdesc, *ret;
6325 int t_index, sindex, c, tflag, modspec;
6326 intmax_t number;
6328 temp = temp1 = value = (char *)NULL;
6329 var_is_set = var_is_null = var_is_special = check_nullness = 0;
6330 want_substring = want_indir = want_patsub = want_casemod = 0;
6332 sindex = *indexp;
6333 t_index = ++sindex;
6334 /* ${#var} doesn't have any of the other parameter expansions on it. */
6335 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
6336 name = string_extract (string, &t_index, "}", SX_VARNAME);
6337 else
6338 #if defined (CASEMOD_EXPANSIONS)
6339 /* To enable case-toggling expansions using the `~' operator character
6340 change the 1 to 0. */
6341 # if defined (CASEMOD_CAPCASE)
6342 name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
6343 # else
6344 name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
6345 # endif /* CASEMOD_CAPCASE */
6346 #else
6347 name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
6348 #endif /* CASEMOD_EXPANSIONS */
6350 ret = 0;
6351 tflag = 0;
6353 /* If the name really consists of a special variable, then make sure
6354 that we have the entire name. We don't allow indirect references
6355 to special variables except `#', `?', `@' and `*'. */
6356 if ((sindex == t_index &&
6357 (string[t_index] == '-' ||
6358 string[t_index] == '?' ||
6359 string[t_index] == '#')) ||
6360 (sindex == t_index - 1 && string[sindex] == '!' &&
6361 (string[t_index] == '#' ||
6362 string[t_index] == '?' ||
6363 string[t_index] == '@' ||
6364 string[t_index] == '*')))
6366 t_index++;
6367 free (name);
6368 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
6369 name = (char *)xmalloc (3 + (strlen (temp1)));
6370 *name = string[sindex];
6371 if (string[sindex] == '!')
6373 /* indirect reference of $#, $?, $@, or $* */
6374 name[1] = string[sindex + 1];
6375 strcpy (name + 2, temp1);
6377 else
6378 strcpy (name + 1, temp1);
6379 free (temp1);
6381 sindex = t_index;
6383 /* Find out what character ended the variable name. Then
6384 do the appropriate thing. */
6385 if (c = string[sindex])
6386 sindex++;
6388 /* If c is followed by one of the valid parameter expansion
6389 characters, move past it as normal. If not, assume that
6390 a substring specification is being given, and do not move
6391 past it. */
6392 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
6394 check_nullness++;
6395 if (c = string[sindex])
6396 sindex++;
6398 else if (c == ':' && string[sindex] != RBRACE)
6399 want_substring = 1;
6400 else if (c == '/' && string[sindex] != RBRACE)
6401 want_patsub = 1;
6402 #if defined (CASEMOD_EXPANSIONS)
6403 else if (c == '^' || c == ',' || c == '~')
6405 modspec = c;
6406 want_casemod = 1;
6408 #endif
6410 /* Catch the valid and invalid brace expressions that made it through the
6411 tests above. */
6412 /* ${#-} is a valid expansion and means to take the length of $-.
6413 Similarly for ${#?} and ${##}... */
6414 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6415 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
6417 name = (char *)xrealloc (name, 3);
6418 name[1] = c;
6419 name[2] = '\0';
6420 c = string[sindex++];
6423 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
6424 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6425 member (c, "%:=+/") && string[sindex] == RBRACE)
6427 temp = (char *)NULL;
6428 goto bad_substitution;
6431 /* Indirect expansion begins with a `!'. A valid indirect expansion is
6432 either a variable name, one of the positional parameters or a special
6433 variable that expands to one of the positional parameters. */
6434 want_indir = *name == '!' &&
6435 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
6436 || VALID_INDIR_PARAM (name[1]));
6438 /* Determine the value of this variable. */
6440 /* Check for special variables, directly referenced. */
6441 if (SPECIAL_VAR (name, want_indir))
6442 var_is_special++;
6444 /* Check for special expansion things, like the length of a parameter */
6445 if (*name == '#' && name[1])
6447 /* If we are not pointing at the character just after the
6448 closing brace, then we haven't gotten all of the name.
6449 Since it begins with a special character, this is a bad
6450 substitution. Also check NAME for validity before trying
6451 to go on. */
6452 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
6454 temp = (char *)NULL;
6455 goto bad_substitution;
6458 number = parameter_brace_expand_length (name);
6459 free (name);
6461 *indexp = sindex;
6462 if (number < 0)
6463 return (&expand_wdesc_error);
6464 else
6466 ret = alloc_word_desc ();
6467 ret->word = itos (number);
6468 return ret;
6472 /* ${@} is identical to $@. */
6473 if (name[0] == '@' && name[1] == '\0')
6475 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6476 *quoted_dollar_atp = 1;
6478 if (contains_dollar_at)
6479 *contains_dollar_at = 1;
6482 /* Process ${!PREFIX*} expansion. */
6483 if (want_indir && string[sindex - 1] == RBRACE &&
6484 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
6485 legal_variable_starter ((unsigned char) name[1]))
6487 char **x;
6488 WORD_LIST *xlist;
6490 temp1 = savestring (name + 1);
6491 number = strlen (temp1);
6492 temp1[number - 1] = '\0';
6493 x = all_variables_matching_prefix (temp1);
6494 xlist = strvec_to_word_list (x, 0, 0);
6495 if (string[sindex - 2] == '*')
6496 temp = string_list_dollar_star (xlist);
6497 else
6499 temp = string_list_dollar_at (xlist, quoted);
6500 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6501 *quoted_dollar_atp = 1;
6502 if (contains_dollar_at)
6503 *contains_dollar_at = 1;
6505 free (x);
6506 free (xlist);
6507 free (temp1);
6508 *indexp = sindex;
6510 ret = alloc_word_desc ();
6511 ret->word = temp;
6512 return ret;
6515 #if defined (ARRAY_VARS)
6516 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
6517 if (want_indir && string[sindex - 1] == RBRACE &&
6518 string[sindex - 2] == ']' && valid_array_reference (name+1))
6520 char *x, *x1;
6522 temp1 = savestring (name + 1);
6523 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
6524 FREE (x);
6525 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
6527 temp = array_keys (temp1, quoted); /* handles assoc vars too */
6528 if (x1[0] == '@')
6530 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6531 *quoted_dollar_atp = 1;
6532 if (contains_dollar_at)
6533 *contains_dollar_at = 1;
6536 free (temp1);
6537 *indexp = sindex;
6539 ret = alloc_word_desc ();
6540 ret->word = temp;
6541 return ret;
6544 free (temp1);
6546 #endif /* ARRAY_VARS */
6548 /* Make sure that NAME is valid before trying to go on. */
6549 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
6550 var_is_special) == 0)
6552 temp = (char *)NULL;
6553 goto bad_substitution;
6556 if (want_indir)
6557 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6558 else
6559 tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
6561 if (tdesc)
6563 temp = tdesc->word;
6564 tflag = tdesc->flags;
6565 dispose_word_desc (tdesc);
6567 else
6568 temp = (char *)0;
6570 #if defined (ARRAY_VARS)
6571 if (valid_array_reference (name))
6572 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6573 #endif
6575 var_is_set = temp != (char *)0;
6576 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6578 /* Get the rest of the stuff inside the braces. */
6579 if (c && c != RBRACE)
6581 /* Extract the contents of the ${ ... } expansion
6582 according to the Posix.2 rules. */
6583 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6584 if (string[sindex] == RBRACE)
6585 sindex++;
6586 else
6587 goto bad_substitution;
6589 else
6590 value = (char *)NULL;
6592 *indexp = sindex;
6594 /* If this is a substring spec, process it and add the result. */
6595 if (want_substring)
6597 temp1 = parameter_brace_substring (name, temp, value, quoted);
6598 FREE (name);
6599 FREE (value);
6600 FREE (temp);
6602 if (temp1 == &expand_param_error)
6603 return (&expand_wdesc_error);
6604 else if (temp1 == &expand_param_fatal)
6605 return (&expand_wdesc_fatal);
6607 ret = alloc_word_desc ();
6608 ret->word = temp1;
6609 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6610 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6611 return ret;
6613 else if (want_patsub)
6615 temp1 = parameter_brace_patsub (name, temp, value, quoted);
6616 FREE (name);
6617 FREE (value);
6618 FREE (temp);
6620 if (temp1 == &expand_param_error)
6621 return (&expand_wdesc_error);
6622 else if (temp1 == &expand_param_fatal)
6623 return (&expand_wdesc_fatal);
6625 ret = alloc_word_desc ();
6626 ret->word = temp1;
6627 ret = alloc_word_desc ();
6628 ret->word = temp1;
6629 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6630 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6631 return ret;
6633 #if defined (CASEMOD_EXPANSIONS)
6634 else if (want_casemod)
6636 temp1 = parameter_brace_casemod (name, temp, modspec, value, quoted);
6637 FREE (name);
6638 FREE (value);
6639 FREE (temp);
6641 if (temp1 == &expand_param_error)
6642 return (&expand_wdesc_error);
6643 else if (temp1 == &expand_param_fatal)
6644 return (&expand_wdesc_fatal);
6646 ret = alloc_word_desc ();
6647 ret->word = temp1;
6648 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6649 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6650 return ret;
6652 #endif
6654 /* Do the right thing based on which character ended the variable name. */
6655 switch (c)
6657 default:
6658 case '\0':
6659 bad_substitution:
6660 report_error (_("%s: bad substitution"), string ? string : "??");
6661 FREE (value);
6662 FREE (temp);
6663 free (name);
6664 return &expand_wdesc_error;
6666 case RBRACE:
6667 if (var_is_set == 0 && unbound_vars_is_error)
6669 err_unboundvar (name);
6670 FREE (value);
6671 FREE (temp);
6672 free (name);
6673 last_command_exit_value = EXECUTION_FAILURE;
6674 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6676 break;
6678 case '#': /* ${param#[#]pattern} */
6679 case '%': /* ${param%[%]pattern} */
6680 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6682 FREE (value);
6683 break;
6685 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6686 free (temp);
6687 free (value);
6689 ret = alloc_word_desc ();
6690 ret->word = temp1;
6691 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6692 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6693 return ret;
6695 case '-':
6696 case '=':
6697 case '?':
6698 case '+':
6699 if (var_is_set && var_is_null == 0)
6701 /* If the operator is `+', we don't want the value of the named
6702 variable for anything, just the value of the right hand side. */
6704 if (c == '+')
6706 /* XXX -- if we're double-quoted and the named variable is "$@",
6707 we want to turn off any special handling of "$@" --
6708 we're not using it, so whatever is on the rhs applies. */
6709 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6710 *quoted_dollar_atp = 0;
6711 if (contains_dollar_at)
6712 *contains_dollar_at = 0;
6714 FREE (temp);
6715 if (value)
6717 ret = parameter_brace_expand_rhs (name, value, c,
6718 quoted,
6719 quoted_dollar_atp,
6720 contains_dollar_at);
6721 /* XXX - fix up later, esp. noting presence of
6722 W_HASQUOTEDNULL in ret->flags */
6723 free (value);
6725 else
6726 temp = (char *)NULL;
6728 else
6730 FREE (value);
6732 /* Otherwise do nothing; just use the value in TEMP. */
6734 else /* VAR not set or VAR is NULL. */
6736 FREE (temp);
6737 temp = (char *)NULL;
6738 if (c == '=' && var_is_special)
6740 report_error (_("$%s: cannot assign in this way"), name);
6741 free (name);
6742 free (value);
6743 return &expand_wdesc_error;
6745 else if (c == '?')
6747 parameter_brace_expand_error (name, value);
6748 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6750 else if (c != '+')
6752 /* XXX -- if we're double-quoted and the named variable is "$@",
6753 we want to turn off any special handling of "$@" --
6754 we're not using it, so whatever is on the rhs applies. */
6755 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6756 *quoted_dollar_atp = 0;
6757 if (contains_dollar_at)
6758 *contains_dollar_at = 0;
6760 ret = parameter_brace_expand_rhs (name, value, c, quoted,
6761 quoted_dollar_atp,
6762 contains_dollar_at);
6763 /* XXX - fix up later, esp. noting presence of
6764 W_HASQUOTEDNULL in tdesc->flags */
6766 free (value);
6769 break;
6771 free (name);
6773 if (ret == 0)
6775 ret = alloc_word_desc ();
6776 ret->flags = tflag;
6777 ret->word = temp;
6779 return (ret);
6782 /* Expand a single ${xxx} expansion. The braces are optional. When
6783 the braces are used, parameter_brace_expand() does the work,
6784 possibly calling param_expand recursively. */
6785 static WORD_DESC *
6786 param_expand (string, sindex, quoted, expanded_something,
6787 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6788 pflags)
6789 char *string;
6790 int *sindex, quoted, *expanded_something, *contains_dollar_at;
6791 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6793 char *temp, *temp1, uerror[3];
6794 int zindex, t_index, expok;
6795 unsigned char c;
6796 intmax_t number;
6797 SHELL_VAR *var;
6798 WORD_LIST *list;
6799 WORD_DESC *tdesc, *ret;
6800 int tflag;
6802 zindex = *sindex;
6803 c = string[++zindex];
6805 temp = (char *)NULL;
6806 ret = tdesc = (WORD_DESC *)NULL;
6807 tflag = 0;
6809 /* Do simple cases first. Switch on what follows '$'. */
6810 switch (c)
6812 /* $0 .. $9? */
6813 case '0':
6814 case '1':
6815 case '2':
6816 case '3':
6817 case '4':
6818 case '5':
6819 case '6':
6820 case '7':
6821 case '8':
6822 case '9':
6823 temp1 = dollar_vars[TODIGIT (c)];
6824 if (unbound_vars_is_error && temp1 == (char *)NULL)
6826 uerror[0] = '$';
6827 uerror[1] = c;
6828 uerror[2] = '\0';
6829 err_unboundvar (uerror);
6830 last_command_exit_value = EXECUTION_FAILURE;
6831 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6833 if (temp1)
6834 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6835 ? quote_string (temp1)
6836 : quote_escapes (temp1);
6837 else
6838 temp = (char *)NULL;
6840 break;
6842 /* $$ -- pid of the invoking shell. */
6843 case '$':
6844 temp = itos (dollar_dollar_pid);
6845 break;
6847 /* $# -- number of positional parameters. */
6848 case '#':
6849 temp = itos (number_of_args ());
6850 break;
6852 /* $? -- return value of the last synchronous command. */
6853 case '?':
6854 temp = itos (last_command_exit_value);
6855 break;
6857 /* $- -- flags supplied to the shell on invocation or by `set'. */
6858 case '-':
6859 temp = which_set_flags ();
6860 break;
6862 /* $! -- Pid of the last asynchronous command. */
6863 case '!':
6864 /* If no asynchronous pids have been created, expand to nothing.
6865 If `set -u' has been executed, and no async processes have
6866 been created, this is an expansion error. */
6867 if (last_asynchronous_pid == NO_PID)
6869 if (expanded_something)
6870 *expanded_something = 0;
6871 temp = (char *)NULL;
6872 if (unbound_vars_is_error)
6874 uerror[0] = '$';
6875 uerror[1] = c;
6876 uerror[2] = '\0';
6877 err_unboundvar (uerror);
6878 last_command_exit_value = EXECUTION_FAILURE;
6879 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6882 else
6883 temp = itos (last_asynchronous_pid);
6884 break;
6886 /* The only difference between this and $@ is when the arg is quoted. */
6887 case '*': /* `$*' */
6888 list = list_rest_of_args ();
6890 if (list == 0 && unbound_vars_is_error)
6892 uerror[0] = '$';
6893 uerror[1] = '*';
6894 uerror[2] = '\0';
6895 err_unboundvar (uerror);
6896 last_command_exit_value = EXECUTION_FAILURE;
6897 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6900 /* If there are no command-line arguments, this should just
6901 disappear if there are other characters in the expansion,
6902 even if it's quoted. */
6903 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
6904 temp = (char *)NULL;
6905 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6907 /* If we have "$*" we want to make a string of the positional
6908 parameters, separated by the first character of $IFS, and
6909 quote the whole string, including the separators. If IFS
6910 is unset, the parameters are separated by ' '; if $IFS is
6911 null, the parameters are concatenated. */
6912 temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
6913 temp1 = quote_string (temp);
6914 if (*temp == 0)
6915 tflag |= W_HASQUOTEDNULL;
6916 free (temp);
6917 temp = temp1;
6919 else
6921 /* We check whether or not we're eventually going to split $* here,
6922 for example when IFS is empty and we are processing the rhs of
6923 an assignment statement. In that case, we don't separate the
6924 arguments at all. Otherwise, if the $* is not quoted it is
6925 identical to $@ */
6926 #if 1
6927 # if defined (HANDLE_MULTIBYTE)
6928 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
6929 # else
6930 if (expand_no_split_dollar_star && ifs_firstc == 0)
6931 # endif
6932 temp = string_list_dollar_star (list);
6933 else
6934 temp = string_list_dollar_at (list, quoted);
6935 #else
6936 temp = string_list_dollar_at (list, quoted);
6937 #endif
6938 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
6939 *contains_dollar_at = 1;
6942 dispose_words (list);
6943 break;
6945 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
6946 means that we have to turn quoting off after we split into
6947 the individually quoted arguments so that the final split
6948 on the first character of $IFS is still done. */
6949 case '@': /* `$@' */
6950 list = list_rest_of_args ();
6952 if (list == 0 && unbound_vars_is_error)
6954 uerror[0] = '$';
6955 uerror[1] = '@';
6956 uerror[2] = '\0';
6957 err_unboundvar (uerror);
6958 last_command_exit_value = EXECUTION_FAILURE;
6959 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6962 /* We want to flag the fact that we saw this. We can't turn
6963 off quoting entirely, because other characters in the
6964 string might need it (consider "\"$@\""), but we need some
6965 way to signal that the final split on the first character
6966 of $IFS should be done, even though QUOTED is 1. */
6967 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6968 *quoted_dollar_at_p = 1;
6969 if (contains_dollar_at)
6970 *contains_dollar_at = 1;
6972 /* We want to separate the positional parameters with the first
6973 character of $IFS in case $IFS is something other than a space.
6974 We also want to make sure that splitting is done no matter what --
6975 according to POSIX.2, this expands to a list of the positional
6976 parameters no matter what IFS is set to. */
6977 temp = string_list_dollar_at (list, quoted);
6979 dispose_words (list);
6980 break;
6982 case LBRACE:
6983 tdesc = parameter_brace_expand (string, &zindex, quoted,
6984 quoted_dollar_at_p,
6985 contains_dollar_at);
6987 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
6988 return (tdesc);
6989 temp = tdesc ? tdesc->word : (char *)0;
6991 /* XXX */
6992 /* Quoted nulls should be removed if there is anything else
6993 in the string. */
6994 /* Note that we saw the quoted null so we can add one back at
6995 the end of this function if there are no other characters
6996 in the string, discard TEMP, and go on. The exception to
6997 this is when we have "${@}" and $1 is '', since $@ needs
6998 special handling. */
6999 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7001 if (had_quoted_null_p)
7002 *had_quoted_null_p = 1;
7003 if (*quoted_dollar_at_p == 0)
7005 free (temp);
7006 tdesc->word = temp = (char *)NULL;
7011 ret = tdesc;
7012 goto return0;
7014 /* Do command or arithmetic substitution. */
7015 case LPAREN:
7016 /* We have to extract the contents of this paren substitution. */
7017 t_index = zindex + 1;
7018 temp = extract_command_subst (string, &t_index, 0);
7019 zindex = t_index;
7021 /* For Posix.2-style `$(( ))' arithmetic substitution,
7022 extract the expression and pass it to the evaluator. */
7023 if (temp && *temp == LPAREN)
7025 char *temp2;
7026 temp1 = temp + 1;
7027 temp2 = savestring (temp1);
7028 t_index = strlen (temp2) - 1;
7030 if (temp2[t_index] != RPAREN)
7032 free (temp2);
7033 goto comsub;
7036 /* Cut off ending `)' */
7037 temp2[t_index] = '\0';
7039 if (chk_arithsub (temp2, t_index) == 0)
7041 free (temp2);
7042 goto comsub;
7045 /* Expand variables found inside the expression. */
7046 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7047 free (temp2);
7049 arithsub:
7050 /* No error messages. */
7051 this_command_name = (char *)NULL;
7052 number = evalexp (temp1, &expok);
7053 free (temp);
7054 free (temp1);
7055 if (expok == 0)
7057 if (interactive_shell == 0 && posixly_correct)
7059 last_command_exit_value = EXECUTION_FAILURE;
7060 return (&expand_wdesc_fatal);
7062 else
7063 return (&expand_wdesc_error);
7065 temp = itos (number);
7066 break;
7069 comsub:
7070 if (pflags & PF_NOCOMSUB)
7071 /* we need zindex+1 because string[zindex] == RPAREN */
7072 temp1 = substring (string, *sindex, zindex+1);
7073 else
7075 tdesc = command_substitute (temp, quoted);
7076 temp1 = tdesc ? tdesc->word : (char *)NULL;
7077 if (tdesc)
7078 dispose_word_desc (tdesc);
7080 FREE (temp);
7081 temp = temp1;
7082 break;
7084 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7085 away in a future bash release. */
7086 case '[':
7087 /* Extract the contents of this arithmetic substitution. */
7088 t_index = zindex + 1;
7089 temp = extract_arithmetic_subst (string, &t_index);
7090 zindex = t_index;
7091 if (temp == 0)
7093 temp = savestring (string);
7094 if (expanded_something)
7095 *expanded_something = 0;
7096 goto return0;
7099 /* Do initial variable expansion. */
7100 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7102 goto arithsub;
7104 default:
7105 /* Find the variable in VARIABLE_LIST. */
7106 temp = (char *)NULL;
7108 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7110 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7112 /* If this isn't a variable name, then just output the `$'. */
7113 if (temp1 == 0 || *temp1 == '\0')
7115 FREE (temp1);
7116 temp = (char *)xmalloc (2);
7117 temp[0] = '$';
7118 temp[1] = '\0';
7119 if (expanded_something)
7120 *expanded_something = 0;
7121 goto return0;
7124 /* If the variable exists, return its value cell. */
7125 var = find_variable (temp1);
7127 if (var && invisible_p (var) == 0 && var_isset (var))
7129 #if defined (ARRAY_VARS)
7130 if (assoc_p (var) || array_p (var))
7132 temp = array_p (var) ? array_reference (array_cell (var), 0)
7133 : assoc_reference (assoc_cell (var), "0");
7134 if (temp)
7135 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7136 ? quote_string (temp)
7137 : quote_escapes (temp);
7138 else if (unbound_vars_is_error)
7139 goto unbound_variable;
7141 else
7142 #endif
7144 temp = value_cell (var);
7146 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7147 ? quote_string (temp)
7148 : quote_escapes (temp);
7151 free (temp1);
7153 goto return0;
7156 temp = (char *)NULL;
7158 unbound_variable:
7159 if (unbound_vars_is_error)
7160 err_unboundvar (temp1);
7161 else
7163 free (temp1);
7164 goto return0;
7167 free (temp1);
7168 last_command_exit_value = EXECUTION_FAILURE;
7169 return ((unbound_vars_is_error && interactive_shell == 0)
7170 ? &expand_wdesc_fatal
7171 : &expand_wdesc_error);
7174 if (string[zindex])
7175 zindex++;
7177 return0:
7178 *sindex = zindex;
7180 if (ret == 0)
7182 ret = alloc_word_desc ();
7183 ret->flags = tflag; /* XXX */
7184 ret->word = temp;
7186 return ret;
7189 /* Make a word list which is the result of parameter and variable
7190 expansion, command substitution, arithmetic substitution, and
7191 quote removal of WORD. Return a pointer to a WORD_LIST which is
7192 the result of the expansion. If WORD contains a null word, the
7193 word list returned is also null.
7195 QUOTED contains flag values defined in shell.h.
7197 ISEXP is used to tell expand_word_internal that the word should be
7198 treated as the result of an expansion. This has implications for
7199 how IFS characters in the word are treated.
7201 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7202 they point to an integer value which receives information about expansion.
7203 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7204 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7205 else zero.
7207 This only does word splitting in the case of $@ expansion. In that
7208 case, we split on ' '. */
7210 /* Values for the local variable quoted_state. */
7211 #define UNQUOTED 0
7212 #define PARTIALLY_QUOTED 1
7213 #define WHOLLY_QUOTED 2
7215 static WORD_LIST *
7216 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7217 WORD_DESC *word;
7218 int quoted, isexp;
7219 int *contains_dollar_at;
7220 int *expanded_something;
7222 WORD_LIST *list;
7223 WORD_DESC *tword;
7225 /* The intermediate string that we build while expanding. */
7226 char *istring;
7228 /* The current size of the above object. */
7229 int istring_size;
7231 /* Index into ISTRING. */
7232 int istring_index;
7234 /* Temporary string storage. */
7235 char *temp, *temp1;
7237 /* The text of WORD. */
7238 register char *string;
7240 /* The size of STRING. */
7241 size_t string_size;
7243 /* The index into STRING. */
7244 int sindex;
7246 /* This gets 1 if we see a $@ while quoted. */
7247 int quoted_dollar_at;
7249 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7250 whether WORD contains no quoting characters, a partially quoted
7251 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7252 int quoted_state;
7254 /* State flags */
7255 int had_quoted_null;
7256 int has_dollar_at;
7257 int tflag;
7259 int assignoff; /* If assignment, offset of `=' */
7261 register unsigned char c; /* Current character. */
7262 int t_index; /* For calls to string_extract_xxx. */
7264 char twochars[2];
7266 DECLARE_MBSTATE;
7268 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7269 istring[istring_index = 0] = '\0';
7270 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7271 quoted_state = UNQUOTED;
7273 string = word->word;
7274 if (string == 0)
7275 goto finished_with_string;
7276 /* Don't need the string length for the SADD... and COPY_ macros unless
7277 multibyte characters are possible. */
7278 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7280 if (contains_dollar_at)
7281 *contains_dollar_at = 0;
7283 assignoff = -1;
7285 /* Begin the expansion. */
7287 for (sindex = 0; ;)
7289 c = string[sindex];
7291 /* Case on toplevel character. */
7292 switch (c)
7294 case '\0':
7295 goto finished_with_string;
7297 case CTLESC:
7298 sindex++;
7299 #if HANDLE_MULTIBYTE
7300 if (MB_CUR_MAX > 1 && string[sindex])
7302 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7304 else
7305 #endif
7307 temp = (char *)xmalloc (3);
7308 temp[0] = CTLESC;
7309 temp[1] = c = string[sindex];
7310 temp[2] = '\0';
7313 dollar_add_string:
7314 if (string[sindex])
7315 sindex++;
7317 add_string:
7318 if (temp)
7320 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7321 temp = (char *)0;
7324 break;
7326 #if defined (PROCESS_SUBSTITUTION)
7327 /* Process substitution. */
7328 case '<':
7329 case '>':
7331 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7333 sindex--; /* add_character: label increments sindex */
7334 goto add_character;
7336 else
7337 t_index = sindex + 1; /* skip past both '<' and LPAREN */
7339 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7340 sindex = t_index;
7342 /* If the process substitution specification is `<()', we want to
7343 open the pipe for writing in the child and produce output; if
7344 it is `>()', we want to open the pipe for reading in the child
7345 and consume input. */
7346 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
7348 FREE (temp1);
7350 goto dollar_add_string;
7352 #endif /* PROCESS_SUBSTITUTION */
7354 case '=':
7355 /* Posix.2 section 3.6.1 says that tildes following `=' in words
7356 which are not assignment statements are not expanded. If the
7357 shell isn't in posix mode, though, we perform tilde expansion
7358 on `likely candidate' unquoted assignment statements (flags
7359 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
7360 contains an unquoted :~ or =~. Something to think about: we
7361 now have a flag that says to perform tilde expansion on arguments
7362 to `assignment builtins' like declare and export that look like
7363 assignment statements. We now do tilde expansion on such words
7364 even in POSIX mode. */
7365 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
7366 goto add_character;
7367 /* If we're not in posix mode or forcing assignment-statement tilde
7368 expansion, note where the `=' appears in the word and prepare to
7369 do tilde expansion following the first `='. */
7370 if ((word->flags & W_ASSIGNMENT) &&
7371 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7372 assignoff == -1 && sindex > 0)
7373 assignoff = sindex;
7374 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
7375 word->flags |= W_ITILDE;
7376 #if 0
7377 else if ((word->flags & W_ASSIGNMENT) &&
7378 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7379 string[sindex+1] == '~')
7380 word->flags |= W_ITILDE;
7381 #endif
7382 goto add_character;
7384 case ':':
7385 if (word->flags & W_NOTILDE)
7386 goto add_character;
7388 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
7389 string[sindex+1] == '~')
7390 word->flags |= W_ITILDE;
7391 goto add_character;
7393 case '~':
7394 /* If the word isn't supposed to be tilde expanded, or we're not
7395 at the start of a word or after an unquoted : or = in an
7396 assignment statement, we don't do tilde expansion. */
7397 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
7398 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
7399 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7401 word->flags &= ~W_ITILDE;
7402 goto add_character;
7405 if (word->flags & W_ASSIGNRHS)
7406 tflag = 2;
7407 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
7408 tflag = 1;
7409 else
7410 tflag = 0;
7412 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
7414 word->flags &= ~W_ITILDE;
7416 if (temp && *temp && t_index > 0)
7418 temp1 = bash_tilde_expand (temp, tflag);
7419 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
7421 FREE (temp);
7422 FREE (temp1);
7423 goto add_character; /* tilde expansion failed */
7425 free (temp);
7426 temp = temp1;
7427 sindex += t_index;
7428 goto add_quoted_string; /* XXX was add_string */
7430 else
7432 FREE (temp);
7433 goto add_character;
7436 case '$':
7437 if (expanded_something)
7438 *expanded_something = 1;
7440 has_dollar_at = 0;
7441 tword = param_expand (string, &sindex, quoted, expanded_something,
7442 &has_dollar_at, &quoted_dollar_at,
7443 &had_quoted_null,
7444 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
7446 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
7448 free (string);
7449 free (istring);
7450 return ((tword == &expand_wdesc_error) ? &expand_word_error
7451 : &expand_word_fatal);
7453 if (contains_dollar_at && has_dollar_at)
7454 *contains_dollar_at = 1;
7456 if (tword && (tword->flags & W_HASQUOTEDNULL))
7457 had_quoted_null = 1;
7459 temp = tword->word;
7460 dispose_word_desc (tword);
7462 goto add_string;
7463 break;
7465 case '`': /* Backquoted command substitution. */
7467 t_index = sindex++;
7469 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
7470 /* The test of sindex against t_index is to allow bare instances of
7471 ` to pass through, for backwards compatibility. */
7472 if (temp == &extract_string_error || temp == &extract_string_fatal)
7474 if (sindex - 1 == t_index)
7476 sindex = t_index;
7477 goto add_character;
7479 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
7480 free (string);
7481 free (istring);
7482 return ((temp == &extract_string_error) ? &expand_word_error
7483 : &expand_word_fatal);
7486 if (expanded_something)
7487 *expanded_something = 1;
7489 if (word->flags & W_NOCOMSUB)
7490 /* sindex + 1 because string[sindex] == '`' */
7491 temp1 = substring (string, t_index, sindex + 1);
7492 else
7494 de_backslash (temp);
7495 tword = command_substitute (temp, quoted);
7496 temp1 = tword ? tword->word : (char *)NULL;
7497 if (tword)
7498 dispose_word_desc (tword);
7500 FREE (temp);
7501 temp = temp1;
7502 goto dollar_add_string;
7505 case '\\':
7506 if (string[sindex + 1] == '\n')
7508 sindex += 2;
7509 continue;
7512 c = string[++sindex];
7514 if (quoted & Q_HERE_DOCUMENT)
7515 tflag = CBSHDOC;
7516 else if (quoted & Q_DOUBLE_QUOTES)
7517 tflag = CBSDQUOTE;
7518 else
7519 tflag = 0;
7521 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7523 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7525 else if (c == 0)
7527 c = CTLNUL;
7528 sindex--; /* add_character: label increments sindex */
7529 goto add_character;
7531 else
7533 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7536 sindex++;
7537 add_twochars:
7538 /* BEFORE jumping here, we need to increment sindex if appropriate */
7539 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7540 DEFAULT_ARRAY_SIZE);
7541 istring[istring_index++] = twochars[0];
7542 istring[istring_index++] = twochars[1];
7543 istring[istring_index] = '\0';
7545 break;
7547 case '"':
7548 #if 0
7549 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7550 #else
7551 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7552 #endif
7553 goto add_character;
7555 t_index = ++sindex;
7556 temp = string_extract_double_quoted (string, &sindex, 0);
7558 /* If the quotes surrounded the entire string, then the
7559 whole word was quoted. */
7560 quoted_state = (t_index == 1 && string[sindex] == '\0')
7561 ? WHOLLY_QUOTED
7562 : PARTIALLY_QUOTED;
7564 if (temp && *temp)
7566 tword = alloc_word_desc ();
7567 tword->word = temp;
7569 temp = (char *)NULL;
7571 has_dollar_at = 0;
7572 /* Need to get W_HASQUOTEDNULL flag through this function. */
7573 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7575 if (list == &expand_word_error || list == &expand_word_fatal)
7577 free (istring);
7578 free (string);
7579 /* expand_word_internal has already freed temp_word->word
7580 for us because of the way it prints error messages. */
7581 tword->word = (char *)NULL;
7582 dispose_word (tword);
7583 return list;
7586 dispose_word (tword);
7588 /* "$@" (a double-quoted dollar-at) expands into nothing,
7589 not even a NULL word, when there are no positional
7590 parameters. */
7591 if (list == 0 && has_dollar_at)
7593 quoted_dollar_at++;
7594 break;
7597 /* If we get "$@", we know we have expanded something, so we
7598 need to remember it for the final split on $IFS. This is
7599 a special case; it's the only case where a quoted string
7600 can expand into more than one word. It's going to come back
7601 from the above call to expand_word_internal as a list with
7602 a single word, in which all characters are quoted and
7603 separated by blanks. What we want to do is to turn it back
7604 into a list for the next piece of code. */
7605 if (list)
7606 dequote_list (list);
7608 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7609 had_quoted_null = 1;
7611 if (has_dollar_at)
7613 quoted_dollar_at++;
7614 if (contains_dollar_at)
7615 *contains_dollar_at = 1;
7616 if (expanded_something)
7617 *expanded_something = 1;
7620 else
7622 /* What we have is "". This is a minor optimization. */
7623 FREE (temp);
7624 list = (WORD_LIST *)NULL;
7627 /* The code above *might* return a list (consider the case of "$@",
7628 where it returns "$1", "$2", etc.). We can't throw away the
7629 rest of the list, and we have to make sure each word gets added
7630 as quoted. We test on tresult->next: if it is non-NULL, we
7631 quote the whole list, save it to a string with string_list, and
7632 add that string. We don't need to quote the results of this
7633 (and it would be wrong, since that would quote the separators
7634 as well), so we go directly to add_string. */
7635 if (list)
7637 if (list->next)
7639 /* Testing quoted_dollar_at makes sure that "$@" is
7640 split correctly when $IFS does not contain a space. */
7641 temp = quoted_dollar_at
7642 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7643 : string_list (quote_list (list));
7644 dispose_words (list);
7645 goto add_string;
7647 else
7649 temp = savestring (list->word->word);
7650 tflag = list->word->flags;
7651 dispose_words (list);
7653 /* If the string is not a quoted null string, we want
7654 to remove any embedded unquoted CTLNUL characters.
7655 We do not want to turn quoted null strings back into
7656 the empty string, though. We do this because we
7657 want to remove any quoted nulls from expansions that
7658 contain other characters. For example, if we have
7659 x"$*"y or "x$*y" and there are no positional parameters,
7660 the $* should expand into nothing. */
7661 /* We use the W_HASQUOTEDNULL flag to differentiate the
7662 cases: a quoted null character as above and when
7663 CTLNUL is contained in the (non-null) expansion
7664 of some variable. We use the had_quoted_null flag to
7665 pass the value through this function to its caller. */
7666 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7667 remove_quoted_nulls (temp); /* XXX */
7670 else
7671 temp = (char *)NULL;
7673 /* We do not want to add quoted nulls to strings that are only
7674 partially quoted; we can throw them away. */
7675 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7676 continue;
7678 add_quoted_string:
7680 if (temp)
7682 temp1 = temp;
7683 temp = quote_string (temp);
7684 free (temp1);
7685 goto add_string;
7687 else
7689 /* Add NULL arg. */
7690 c = CTLNUL;
7691 sindex--; /* add_character: label increments sindex */
7692 goto add_character;
7695 /* break; */
7697 case '\'':
7698 #if 0
7699 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7700 #else
7701 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7702 #endif
7703 goto add_character;
7705 t_index = ++sindex;
7706 temp = string_extract_single_quoted (string, &sindex);
7708 /* If the entire STRING was surrounded by single quotes,
7709 then the string is wholly quoted. */
7710 quoted_state = (t_index == 1 && string[sindex] == '\0')
7711 ? WHOLLY_QUOTED
7712 : PARTIALLY_QUOTED;
7714 /* If all we had was '', it is a null expansion. */
7715 if (*temp == '\0')
7717 free (temp);
7718 temp = (char *)NULL;
7720 else
7721 remove_quoted_escapes (temp); /* ??? */
7723 /* We do not want to add quoted nulls to strings that are only
7724 partially quoted; such nulls are discarded. */
7725 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7726 continue;
7728 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7729 if (temp == 0)
7731 c = CTLNUL;
7732 sindex--; /* add_character: label increments sindex */
7733 goto add_character;
7735 else
7736 goto add_quoted_string;
7738 /* break; */
7740 default:
7741 /* This is the fix for " $@ " */
7742 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7744 if (string[sindex]) /* from old goto dollar_add_string */
7745 sindex++;
7746 if (c == 0)
7748 c = CTLNUL;
7749 goto add_character;
7751 else
7753 #if HANDLE_MULTIBYTE
7754 if (MB_CUR_MAX > 1)
7755 sindex--;
7757 if (MB_CUR_MAX > 1)
7759 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7761 else
7762 #endif
7764 twochars[0] = CTLESC;
7765 twochars[1] = c;
7766 goto add_twochars;
7771 SADD_MBCHAR (temp, string, sindex, string_size);
7773 add_character:
7774 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7775 DEFAULT_ARRAY_SIZE);
7776 istring[istring_index++] = c;
7777 istring[istring_index] = '\0';
7779 /* Next character. */
7780 sindex++;
7784 finished_with_string:
7785 /* OK, we're ready to return. If we have a quoted string, and
7786 quoted_dollar_at is not set, we do no splitting at all; otherwise
7787 we split on ' '. The routines that call this will handle what to
7788 do if nothing has been expanded. */
7790 /* Partially and wholly quoted strings which expand to the empty
7791 string are retained as an empty arguments. Unquoted strings
7792 which expand to the empty string are discarded. The single
7793 exception is the case of expanding "$@" when there are no
7794 positional parameters. In that case, we discard the expansion. */
7796 /* Because of how the code that handles "" and '' in partially
7797 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7798 if we saw quoting characters, but the expansion was empty.
7799 "" and '' are tossed away before we get to this point when
7800 processing partially quoted strings. This makes "" and $xxx""
7801 equivalent when xxx is unset. We also look to see whether we
7802 saw a quoted null from a ${} expansion and add one back if we
7803 need to. */
7805 /* If we expand to nothing and there were no single or double quotes
7806 in the word, we throw it away. Otherwise, we return a NULL word.
7807 The single exception is for $@ surrounded by double quotes when
7808 there are no positional parameters. In that case, we also throw
7809 the word away. */
7811 if (*istring == '\0')
7813 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7815 istring[0] = CTLNUL;
7816 istring[1] = '\0';
7817 tword = make_bare_word (istring);
7818 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7819 list = make_word_list (tword, (WORD_LIST *)NULL);
7820 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7821 tword->flags |= W_QUOTED;
7823 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7824 and a double-quoted "$@" appears anywhere in it, then the entire
7825 word is removed. */
7826 else if (quoted_state == UNQUOTED || quoted_dollar_at)
7827 list = (WORD_LIST *)NULL;
7828 #if 0
7829 else
7831 tword = make_bare_word (istring);
7832 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7833 tword->flags |= W_QUOTED;
7834 list = make_word_list (tword, (WORD_LIST *)NULL);
7836 #else
7837 else
7838 list = (WORD_LIST *)NULL;
7839 #endif
7841 else if (word->flags & W_NOSPLIT)
7843 tword = make_bare_word (istring);
7844 if (word->flags & W_ASSIGNMENT)
7845 tword->flags |= W_ASSIGNMENT; /* XXX */
7846 if (word->flags & W_COMPASSIGN)
7847 tword->flags |= W_COMPASSIGN; /* XXX */
7848 if (word->flags & W_NOGLOB)
7849 tword->flags |= W_NOGLOB; /* XXX */
7850 if (word->flags & W_NOEXPAND)
7851 tword->flags |= W_NOEXPAND; /* XXX */
7852 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7853 tword->flags |= W_QUOTED;
7854 if (had_quoted_null)
7855 tword->flags |= W_HASQUOTEDNULL;
7856 list = make_word_list (tword, (WORD_LIST *)NULL);
7858 else
7860 char *ifs_chars;
7862 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
7864 /* If we have $@, we need to split the results no matter what. If
7865 IFS is unset or NULL, string_list_dollar_at has separated the
7866 positional parameters with a space, so we split on space (we have
7867 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
7868 string_list_dollar_at has separated the positional parameters
7869 with the first character of $IFS, so we split on $IFS. */
7870 if (has_dollar_at && ifs_chars)
7871 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
7872 else
7874 tword = make_bare_word (istring);
7875 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
7876 tword->flags |= W_QUOTED;
7877 if (word->flags & W_ASSIGNMENT)
7878 tword->flags |= W_ASSIGNMENT;
7879 if (word->flags & W_COMPASSIGN)
7880 tword->flags |= W_COMPASSIGN;
7881 if (word->flags & W_NOGLOB)
7882 tword->flags |= W_NOGLOB;
7883 if (word->flags & W_NOEXPAND)
7884 tword->flags |= W_NOEXPAND;
7885 if (had_quoted_null)
7886 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7887 list = make_word_list (tword, (WORD_LIST *)NULL);
7891 free (istring);
7892 return (list);
7895 /* **************************************************************** */
7896 /* */
7897 /* Functions for Quote Removal */
7898 /* */
7899 /* **************************************************************** */
7901 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
7902 backslash quoting rules for within double quotes or a here document. */
7903 char *
7904 string_quote_removal (string, quoted)
7905 char *string;
7906 int quoted;
7908 size_t slen;
7909 char *r, *result_string, *temp, *send;
7910 int sindex, tindex, dquote;
7911 unsigned char c;
7912 DECLARE_MBSTATE;
7914 /* The result can be no longer than the original string. */
7915 slen = strlen (string);
7916 send = string + slen;
7918 r = result_string = (char *)xmalloc (slen + 1);
7920 for (dquote = sindex = 0; c = string[sindex];)
7922 switch (c)
7924 case '\\':
7925 c = string[++sindex];
7926 if (c == 0)
7928 *r++ = '\\';
7929 break;
7931 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
7932 *r++ = '\\';
7933 /* FALLTHROUGH */
7935 default:
7936 SCOPY_CHAR_M (r, string, send, sindex);
7937 break;
7939 case '\'':
7940 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
7942 *r++ = c;
7943 sindex++;
7944 break;
7946 tindex = sindex + 1;
7947 temp = string_extract_single_quoted (string, &tindex);
7948 if (temp)
7950 strcpy (r, temp);
7951 r += strlen (r);
7952 free (temp);
7954 sindex = tindex;
7955 break;
7957 case '"':
7958 dquote = 1 - dquote;
7959 sindex++;
7960 break;
7963 *r = '\0';
7964 return (result_string);
7967 #if 0
7968 /* UNUSED */
7969 /* Perform quote removal on word WORD. This allocates and returns a new
7970 WORD_DESC *. */
7971 WORD_DESC *
7972 word_quote_removal (word, quoted)
7973 WORD_DESC *word;
7974 int quoted;
7976 WORD_DESC *w;
7977 char *t;
7979 t = string_quote_removal (word->word, quoted);
7980 w = alloc_word_desc ();
7981 w->word = t ? t : savestring ("");
7982 return (w);
7985 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
7986 the members of the list are treated as if they are surrounded by
7987 double quotes. Return a new list, or NULL if LIST is NULL. */
7988 WORD_LIST *
7989 word_list_quote_removal (list, quoted)
7990 WORD_LIST *list;
7991 int quoted;
7993 WORD_LIST *result, *t, *tresult, *e;
7995 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7997 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
7998 #if 0
7999 result = (WORD_LIST *) list_append (result, tresult);
8000 #else
8001 if (result == 0)
8002 result = e = tresult;
8003 else
8005 e->next = tresult;
8006 while (e->next)
8007 e = e->next;
8009 #endif
8011 return (result);
8013 #endif
8015 /*******************************************
8017 * Functions to perform word splitting *
8019 *******************************************/
8021 void
8022 setifs (v)
8023 SHELL_VAR *v;
8025 char *t;
8026 unsigned char uc;
8028 ifs_var = v;
8029 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8031 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8032 handle multibyte chars in IFS */
8033 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8034 for (t = ifs_value ; t && *t; t++)
8036 uc = *t;
8037 ifs_cmap[uc] = 1;
8040 #if defined (HANDLE_MULTIBYTE)
8041 if (ifs_value == 0)
8043 ifs_firstc[0] = '\0';
8044 ifs_firstc_len = 1;
8046 else
8048 size_t ifs_len;
8049 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8050 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8051 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8053 ifs_firstc[0] = ifs_value[0];
8054 ifs_firstc[1] = '\0';
8055 ifs_firstc_len = 1;
8057 else
8058 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8060 #else
8061 ifs_firstc = ifs_value ? *ifs_value : 0;
8062 #endif
8065 char *
8066 getifs ()
8068 return ifs_value;
8071 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8072 is not quoted. list_string () performs quote removal for us, even if we
8073 don't do any splitting. */
8074 WORD_LIST *
8075 word_split (w, ifs_chars)
8076 WORD_DESC *w;
8077 char *ifs_chars;
8079 WORD_LIST *result;
8081 if (w)
8083 char *xifs;
8085 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8086 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8088 else
8089 result = (WORD_LIST *)NULL;
8091 return (result);
8094 /* Perform word splitting on LIST and return the RESULT. It is possible
8095 to return (WORD_LIST *)NULL. */
8096 static WORD_LIST *
8097 word_list_split (list)
8098 WORD_LIST *list;
8100 WORD_LIST *result, *t, *tresult, *e;
8102 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8104 tresult = word_split (t->word, ifs_value);
8105 if (result == 0)
8106 result = e = tresult;
8107 else
8109 e->next = tresult;
8110 while (e->next)
8111 e = e->next;
8114 return (result);
8117 /**************************************************
8119 * Functions to expand an entire WORD_LIST *
8121 **************************************************/
8123 /* Do any word-expansion-specific cleanup and jump to top_level */
8124 static void
8125 exp_jump_to_top_level (v)
8126 int v;
8128 set_pipestatus_from_exit (last_command_exit_value);
8130 /* Cleanup code goes here. */
8131 expand_no_split_dollar_star = 0; /* XXX */
8132 expanding_redir = 0;
8133 assigning_in_environment = 0;
8135 if (parse_and_execute_level == 0)
8136 top_level_cleanup (); /* from sig.c */
8138 jump_to_top_level (v);
8141 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8142 ELIST, and set ELIST to the new list. */
8143 #define PREPEND_LIST(nlist, elist) \
8144 do { nlist->next = elist; elist = nlist; } while (0)
8146 /* Separate out any initial variable assignments from TLIST. If set -k has
8147 been executed, remove all assignment statements from TLIST. Initial
8148 variable assignments and other environment assignments are placed
8149 on SUBST_ASSIGN_VARLIST. */
8150 static WORD_LIST *
8151 separate_out_assignments (tlist)
8152 WORD_LIST *tlist;
8154 register WORD_LIST *vp, *lp;
8156 if (!tlist)
8157 return ((WORD_LIST *)NULL);
8159 if (subst_assign_varlist)
8160 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8162 subst_assign_varlist = (WORD_LIST *)NULL;
8163 vp = lp = tlist;
8165 /* Separate out variable assignments at the start of the command.
8166 Loop invariant: vp->next == lp
8167 Loop postcondition:
8168 lp = list of words left after assignment statements skipped
8169 tlist = original list of words
8171 while (lp && (lp->word->flags & W_ASSIGNMENT))
8173 vp = lp;
8174 lp = lp->next;
8177 /* If lp != tlist, we have some initial assignment statements.
8178 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8179 words and TLIST point to the remaining words. */
8180 if (lp != tlist)
8182 subst_assign_varlist = tlist;
8183 /* ASSERT(vp->next == lp); */
8184 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8185 tlist = lp; /* remainder of word list */
8188 /* vp == end of variable list */
8189 /* tlist == remainder of original word list without variable assignments */
8190 if (!tlist)
8191 /* All the words in tlist were assignment statements */
8192 return ((WORD_LIST *)NULL);
8194 /* ASSERT(tlist != NULL); */
8195 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8197 /* If the -k option is in effect, we need to go through the remaining
8198 words, separate out the assignment words, and place them on
8199 SUBST_ASSIGN_VARLIST. */
8200 if (place_keywords_in_env)
8202 WORD_LIST *tp; /* tp == running pointer into tlist */
8204 tp = tlist;
8205 lp = tlist->next;
8207 /* Loop Invariant: tp->next == lp */
8208 /* Loop postcondition: tlist == word list without assignment statements */
8209 while (lp)
8211 if (lp->word->flags & W_ASSIGNMENT)
8213 /* Found an assignment statement, add this word to end of
8214 subst_assign_varlist (vp). */
8215 if (!subst_assign_varlist)
8216 subst_assign_varlist = vp = lp;
8217 else
8219 vp->next = lp;
8220 vp = lp;
8223 /* Remove the word pointed to by LP from TLIST. */
8224 tp->next = lp->next;
8225 /* ASSERT(vp == lp); */
8226 lp->next = (WORD_LIST *)NULL;
8227 lp = tp->next;
8229 else
8231 tp = lp;
8232 lp = lp->next;
8236 return (tlist);
8239 #define WEXP_VARASSIGN 0x001
8240 #define WEXP_BRACEEXP 0x002
8241 #define WEXP_TILDEEXP 0x004
8242 #define WEXP_PARAMEXP 0x008
8243 #define WEXP_PATHEXP 0x010
8245 /* All of the expansions, including variable assignments at the start of
8246 the list. */
8247 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8249 /* All of the expansions except variable assignments at the start of
8250 the list. */
8251 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8253 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8254 expansion, command substitution, arithmetic expansion, word splitting, and
8255 quote removal. */
8256 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8258 /* Take the list of words in LIST and do the various substitutions. Return
8259 a new list of words which is the expanded list, and without things like
8260 variable assignments. */
8262 WORD_LIST *
8263 expand_words (list)
8264 WORD_LIST *list;
8266 return (expand_word_list_internal (list, WEXP_ALL));
8269 /* Same as expand_words (), but doesn't hack variable or environment
8270 variables. */
8271 WORD_LIST *
8272 expand_words_no_vars (list)
8273 WORD_LIST *list;
8275 return (expand_word_list_internal (list, WEXP_NOVARS));
8278 WORD_LIST *
8279 expand_words_shellexp (list)
8280 WORD_LIST *list;
8282 return (expand_word_list_internal (list, WEXP_SHELLEXP));
8285 static WORD_LIST *
8286 glob_expand_word_list (tlist, eflags)
8287 WORD_LIST *tlist;
8288 int eflags;
8290 char **glob_array, *temp_string;
8291 register int glob_index;
8292 WORD_LIST *glob_list, *output_list, *disposables, *next;
8293 WORD_DESC *tword;
8295 output_list = disposables = (WORD_LIST *)NULL;
8296 glob_array = (char **)NULL;
8297 while (tlist)
8299 /* For each word, either globbing is attempted or the word is
8300 added to orig_list. If globbing succeeds, the results are
8301 added to orig_list and the word (tlist) is added to the list
8302 of disposable words. If globbing fails and failed glob
8303 expansions are left unchanged (the shell default), the
8304 original word is added to orig_list. If globbing fails and
8305 failed glob expansions are removed, the original word is
8306 added to the list of disposable words. orig_list ends up
8307 in reverse order and requires a call to REVERSE_LIST to
8308 be set right. After all words are examined, the disposable
8309 words are freed. */
8310 next = tlist->next;
8312 /* If the word isn't an assignment and contains an unquoted
8313 pattern matching character, then glob it. */
8314 if ((tlist->word->flags & W_NOGLOB) == 0 &&
8315 unquoted_glob_pattern_p (tlist->word->word))
8317 glob_array = shell_glob_filename (tlist->word->word);
8319 /* Handle error cases.
8320 I don't think we should report errors like "No such file
8321 or directory". However, I would like to report errors
8322 like "Read failed". */
8324 if (glob_array == 0 || GLOB_FAILED (glob_array))
8326 glob_array = (char **)xmalloc (sizeof (char *));
8327 glob_array[0] = (char *)NULL;
8330 /* Dequote the current word in case we have to use it. */
8331 if (glob_array[0] == NULL)
8333 temp_string = dequote_string (tlist->word->word);
8334 free (tlist->word->word);
8335 tlist->word->word = temp_string;
8338 /* Make the array into a word list. */
8339 glob_list = (WORD_LIST *)NULL;
8340 for (glob_index = 0; glob_array[glob_index]; glob_index++)
8342 tword = make_bare_word (glob_array[glob_index]);
8343 tword->flags |= W_GLOBEXP; /* XXX */
8344 glob_list = make_word_list (tword, glob_list);
8347 if (glob_list)
8349 output_list = (WORD_LIST *)list_append (glob_list, output_list);
8350 PREPEND_LIST (tlist, disposables);
8352 else if (fail_glob_expansion != 0)
8354 report_error (_("no match: %s"), tlist->word->word);
8355 exp_jump_to_top_level (DISCARD);
8357 else if (allow_null_glob_expansion == 0)
8359 /* Failed glob expressions are left unchanged. */
8360 PREPEND_LIST (tlist, output_list);
8362 else
8364 /* Failed glob expressions are removed. */
8365 PREPEND_LIST (tlist, disposables);
8368 else
8370 /* Dequote the string. */
8371 temp_string = dequote_string (tlist->word->word);
8372 free (tlist->word->word);
8373 tlist->word->word = temp_string;
8374 PREPEND_LIST (tlist, output_list);
8377 strvec_dispose (glob_array);
8378 glob_array = (char **)NULL;
8380 tlist = next;
8383 if (disposables)
8384 dispose_words (disposables);
8386 if (output_list)
8387 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8389 return (output_list);
8392 #if defined (BRACE_EXPANSION)
8393 static WORD_LIST *
8394 brace_expand_word_list (tlist, eflags)
8395 WORD_LIST *tlist;
8396 int eflags;
8398 register char **expansions;
8399 char *temp_string;
8400 WORD_LIST *disposables, *output_list, *next;
8401 WORD_DESC *w;
8402 int eindex;
8404 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
8406 next = tlist->next;
8408 /* Only do brace expansion if the word has a brace character. If
8409 not, just add the word list element to BRACES and continue. In
8410 the common case, at least when running shell scripts, this will
8411 degenerate to a bunch of calls to `xstrchr', and then what is
8412 basically a reversal of TLIST into BRACES, which is corrected
8413 by a call to REVERSE_LIST () on BRACES when the end of TLIST
8414 is reached. */
8415 if (xstrchr (tlist->word->word, LBRACE))
8417 expansions = brace_expand (tlist->word->word);
8419 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
8421 w = make_word (temp_string);
8422 /* If brace expansion didn't change the word, preserve
8423 the flags. We may want to preserve the flags
8424 unconditionally someday -- XXX */
8425 if (STREQ (temp_string, tlist->word->word))
8426 w->flags = tlist->word->flags;
8427 output_list = make_word_list (w, output_list);
8428 free (expansions[eindex]);
8430 free (expansions);
8432 /* Add TLIST to the list of words to be freed after brace
8433 expansion has been performed. */
8434 PREPEND_LIST (tlist, disposables);
8436 else
8437 PREPEND_LIST (tlist, output_list);
8440 if (disposables)
8441 dispose_words (disposables);
8443 if (output_list)
8444 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8446 return (output_list);
8448 #endif
8450 #if defined (ARRAY_VARS)
8451 /* Take WORD, a compound associative array assignment, and internally run
8452 'declare -A w', where W is the variable name portion of WORD. */
8453 static int
8454 make_internal_declare (word, option)
8455 char *word;
8456 char *option;
8458 int t;
8459 WORD_LIST *wl;
8460 WORD_DESC *w;
8462 w = make_word (word);
8464 t = assignment (w->word, 0);
8465 w->word[t] = '\0';
8467 wl = make_word_list (w, (WORD_LIST *)NULL);
8468 wl = make_word_list (make_word (option), wl);
8470 return (declare_builtin (wl));
8472 #endif
8474 static WORD_LIST *
8475 shell_expand_word_list (tlist, eflags)
8476 WORD_LIST *tlist;
8477 int eflags;
8479 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
8480 int expanded_something, has_dollar_at;
8481 char *temp_string;
8483 /* We do tilde expansion all the time. This is what 1003.2 says. */
8484 new_list = (WORD_LIST *)NULL;
8485 for (orig_list = tlist; tlist; tlist = next)
8487 temp_string = tlist->word->word;
8489 next = tlist->next;
8491 #if defined (ARRAY_VARS)
8492 /* If this is a compound array assignment to a builtin that accepts
8493 such assignments (e.g., `declare'), take the assignment and perform
8494 it separately, handling the semantics of declarations inside shell
8495 functions. This avoids the double-evaluation of such arguments,
8496 because `declare' does some evaluation of compound assignments on
8497 its own. */
8498 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
8500 int t;
8502 if (tlist->word->flags & W_ASSIGNASSOC)
8503 make_internal_declare (tlist->word->word, "-A");
8505 t = do_word_assignment (tlist->word);
8506 if (t == 0)
8508 last_command_exit_value = EXECUTION_FAILURE;
8509 exp_jump_to_top_level (DISCARD);
8512 /* Now transform the word as ksh93 appears to do and go on */
8513 t = assignment (tlist->word->word, 0);
8514 tlist->word->word[t] = '\0';
8515 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
8517 #endif
8519 expanded_something = 0;
8520 expanded = expand_word_internal
8521 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
8523 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
8525 /* By convention, each time this error is returned,
8526 tlist->word->word has already been freed. */
8527 tlist->word->word = (char *)NULL;
8529 /* Dispose our copy of the original list. */
8530 dispose_words (orig_list);
8531 /* Dispose the new list we're building. */
8532 dispose_words (new_list);
8534 last_command_exit_value = EXECUTION_FAILURE;
8535 if (expanded == &expand_word_error)
8536 exp_jump_to_top_level (DISCARD);
8537 else
8538 exp_jump_to_top_level (FORCE_EOF);
8541 /* Don't split words marked W_NOSPLIT. */
8542 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
8544 temp_list = word_list_split (expanded);
8545 dispose_words (expanded);
8547 else
8549 /* If no parameter expansion, command substitution, process
8550 substitution, or arithmetic substitution took place, then
8551 do not do word splitting. We still have to remove quoted
8552 null characters from the result. */
8553 word_list_remove_quoted_nulls (expanded);
8554 temp_list = expanded;
8557 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8558 new_list = (WORD_LIST *)list_append (expanded, new_list);
8561 if (orig_list)
8562 dispose_words (orig_list);
8564 if (new_list)
8565 new_list = REVERSE_LIST (new_list, WORD_LIST *);
8567 return (new_list);
8570 /* The workhorse for expand_words () and expand_words_no_vars ().
8571 First arg is LIST, a WORD_LIST of words.
8572 Second arg EFLAGS is a flags word controlling which expansions are
8573 performed.
8575 This does all of the substitutions: brace expansion, tilde expansion,
8576 parameter expansion, command substitution, arithmetic expansion,
8577 process substitution, word splitting, and pathname expansion, according
8578 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
8579 set, or for which no expansion is done, do not undergo word splitting.
8580 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8581 static WORD_LIST *
8582 expand_word_list_internal (list, eflags)
8583 WORD_LIST *list;
8584 int eflags;
8586 WORD_LIST *new_list, *temp_list;
8587 int tint;
8589 if (list == 0)
8590 return ((WORD_LIST *)NULL);
8592 garglist = new_list = copy_word_list (list);
8593 if (eflags & WEXP_VARASSIGN)
8595 garglist = new_list = separate_out_assignments (new_list);
8596 if (new_list == 0)
8598 if (subst_assign_varlist)
8600 /* All the words were variable assignments, so they are placed
8601 into the shell's environment. */
8602 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8604 this_command_name = (char *)NULL; /* no arithmetic errors */
8605 tint = do_word_assignment (temp_list->word);
8606 /* Variable assignment errors in non-interactive shells
8607 running in Posix.2 mode cause the shell to exit. */
8608 if (tint == 0)
8610 last_command_exit_value = EXECUTION_FAILURE;
8611 if (interactive_shell == 0 && posixly_correct)
8612 exp_jump_to_top_level (FORCE_EOF);
8613 else
8614 exp_jump_to_top_level (DISCARD);
8617 dispose_words (subst_assign_varlist);
8618 subst_assign_varlist = (WORD_LIST *)NULL;
8620 return ((WORD_LIST *)NULL);
8624 /* Begin expanding the words that remain. The expansions take place on
8625 things that aren't really variable assignments. */
8627 #if defined (BRACE_EXPANSION)
8628 /* Do brace expansion on this word if there are any brace characters
8629 in the string. */
8630 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8631 new_list = brace_expand_word_list (new_list, eflags);
8632 #endif /* BRACE_EXPANSION */
8634 /* Perform the `normal' shell expansions: tilde expansion, parameter and
8635 variable substitution, command substitution, arithmetic expansion,
8636 and word splitting. */
8637 new_list = shell_expand_word_list (new_list, eflags);
8639 /* Okay, we're almost done. Now let's just do some filename
8640 globbing. */
8641 if (new_list)
8643 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8644 /* Glob expand the word list unless globbing has been disabled. */
8645 new_list = glob_expand_word_list (new_list, eflags);
8646 else
8647 /* Dequote the words, because we're not performing globbing. */
8648 new_list = dequote_list (new_list);
8651 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8653 sh_wassign_func_t *assign_func;
8655 /* If the remainder of the words expand to nothing, Posix.2 requires
8656 that the variable and environment assignments affect the shell's
8657 environment. */
8658 assign_func = new_list ? assign_in_env : do_word_assignment;
8659 tempenv_assign_error = 0;
8661 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8663 this_command_name = (char *)NULL;
8664 assigning_in_environment = (assign_func == assign_in_env);
8665 tint = (*assign_func) (temp_list->word);
8666 assigning_in_environment = 0;
8667 /* Variable assignment errors in non-interactive shells running
8668 in Posix.2 mode cause the shell to exit. */
8669 if (tint == 0)
8671 if (assign_func == do_word_assignment)
8673 last_command_exit_value = EXECUTION_FAILURE;
8674 if (interactive_shell == 0 && posixly_correct)
8675 exp_jump_to_top_level (FORCE_EOF);
8676 else
8677 exp_jump_to_top_level (DISCARD);
8679 else
8680 tempenv_assign_error++;
8684 dispose_words (subst_assign_varlist);
8685 subst_assign_varlist = (WORD_LIST *)NULL;
8688 #if 0
8689 tint = list_length (new_list) + 1;
8690 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8691 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8692 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8693 glob_argv_flags[tint] = '\0';
8694 #endif
8696 return (new_list);