Patch-ID: bash40-019
[bash.git] / subst.c
blob590c9357642cfdb7247e71dedddf26c302fb4ac2
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 */
88 #define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
90 /* These defs make it easier to use the editor. */
91 #define LBRACE '{'
92 #define RBRACE '}'
93 #define LPAREN '('
94 #define RPAREN ')'
96 /* Evaluates to 1 if C is one of the shell's special parameters whose length
97 can be taken, but is also one of the special expansion characters. */
98 #define VALID_SPECIAL_LENGTH_PARAM(c) \
99 ((c) == '-' || (c) == '?' || (c) == '#')
101 /* Evaluates to 1 if C is one of the shell's special parameters for which an
102 indirect variable reference may be made. */
103 #define VALID_INDIR_PARAM(c) \
104 ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
106 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
107 in ${parameter[:]OPword}. */
108 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
110 /* Evaluates to 1 if this is one of the shell's special variables. */
111 #define SPECIAL_VAR(name, wi) \
112 ((DIGIT (*name) && all_digits (name)) || \
113 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
114 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
116 /* An expansion function that takes a string and a quoted flag and returns
117 a WORD_LIST *. Used as the type of the third argument to
118 expand_string_if_necessary(). */
119 typedef WORD_LIST *EXPFUNC __P((char *, int));
121 /* Process ID of the last command executed within command substitution. */
122 pid_t last_command_subst_pid = NO_PID;
123 pid_t current_command_subst_pid = NO_PID;
125 /* Variables used to keep track of the characters in IFS. */
126 SHELL_VAR *ifs_var;
127 char *ifs_value;
128 unsigned char ifs_cmap[UCHAR_MAX + 1];
130 #if defined (HANDLE_MULTIBYTE)
131 unsigned char ifs_firstc[MB_LEN_MAX];
132 size_t ifs_firstc_len;
133 #else
134 unsigned char ifs_firstc;
135 #endif
137 int assigning_in_environment;
139 /* Extern functions and variables from different files. */
140 extern int last_command_exit_value, last_command_exit_signal;
141 extern int subshell_environment;
142 extern int subshell_level, parse_and_execute_level;
143 extern int eof_encountered;
144 extern int return_catch_flag, return_catch_value;
145 extern pid_t dollar_dollar_pid;
146 extern int posixly_correct;
147 extern char *this_command_name;
148 extern struct fd_bitmap *current_fds_to_close;
149 extern int wordexp_only;
150 extern int expanding_redir;
151 extern int tempenv_assign_error;
153 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
154 extern wchar_t *wcsdup __P((const wchar_t *));
155 #endif
157 /* Non-zero means to allow unmatched globbed filenames to expand to
158 a null file. */
159 int allow_null_glob_expansion;
161 /* Non-zero means to throw an error when globbing fails to match anything. */
162 int fail_glob_expansion;
164 #if 0
165 /* Variables to keep track of which words in an expanded word list (the
166 output of expand_word_list_internal) are the result of globbing
167 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
168 (CURRENTLY UNUSED). */
169 char *glob_argv_flags;
170 static int glob_argv_flags_size;
171 #endif
173 static WORD_LIST expand_word_error, expand_word_fatal;
174 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
175 static char expand_param_error, expand_param_fatal;
176 static char extract_string_error, extract_string_fatal;
178 /* Tell the expansion functions to not longjmp back to top_level on fatal
179 errors. Enabled when doing completion and prompt string expansion. */
180 static int no_longjmp_on_fatal_error = 0;
182 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
183 $* on $IFS, primarily when doing assignment statements. */
184 static int expand_no_split_dollar_star = 0;
186 /* Used to hold a list of variable assignments preceding a command. Global
187 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
188 SIGCHLD trap. */
189 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
191 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
192 without any leading variable assignments. */
193 static WORD_LIST *garglist = (WORD_LIST *)NULL;
195 static char *quoted_substring __P((char *, int, int));
196 static int quoted_strlen __P((char *));
197 static char *quoted_strchr __P((char *, int, int));
199 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
200 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
201 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
202 static WORD_LIST *expand_string_internal __P((char *, int));
203 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
204 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
206 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
207 static char *make_quoted_char __P((int));
208 static WORD_LIST *quote_list __P((WORD_LIST *));
210 static int unquoted_substring __P((char *, char *));
211 static int unquoted_member __P((int, char *));
213 #if defined (ARRAY_VARS)
214 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
215 #endif
216 static int do_assignment_internal __P((const WORD_DESC *, int));
218 static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
219 static char *string_extract __P((char *, int *, char *, int));
220 static char *string_extract_double_quoted __P((char *, int *, int));
221 static inline char *string_extract_single_quoted __P((char *, int *));
222 static inline int skip_single_quoted __P((const char *, size_t, int));
223 static int skip_double_quoted __P((char *, size_t, int));
224 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
225 static char *extract_dollar_brace_string __P((char *, int *, int, int));
226 static int skip_matched_pair __P((const char *, int, int, int, int));
228 static char *pos_params __P((char *, int, int, int));
230 static unsigned char *mb_getcharlens __P((char *, int));
232 static char *remove_upattern __P((char *, char *, int));
233 #if defined (HANDLE_MULTIBYTE)
234 static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
235 #endif
236 static char *remove_pattern __P((char *, char *, int));
238 static int match_pattern_char __P((char *, char *));
239 static int match_upattern __P((char *, char *, int, char **, char **));
240 #if defined (HANDLE_MULTIBYTE)
241 static int match_pattern_wchar __P((wchar_t *, wchar_t *));
242 static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
243 #endif
244 static int match_pattern __P((char *, char *, int, char **, char **));
245 static int getpatspec __P((int, char *));
246 static char *getpattern __P((char *, int, int));
247 static char *variable_remove_pattern __P((char *, char *, int, int));
248 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
249 static char *parameter_list_remove_pattern __P((int, char *, int, int));
250 #ifdef ARRAY_VARS
251 static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int));
252 #endif
253 static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
255 static char *process_substitute __P((char *, int));
257 static char *read_comsub __P((int, int, int *));
259 #ifdef ARRAY_VARS
260 static arrayind_t array_length_reference __P((char *));
261 #endif
263 static int valid_brace_expansion_word __P((char *, int));
264 static int chk_atstar __P((char *, int, int *, int *));
265 static int chk_arithsub __P((const char *, int));
267 static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
268 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
269 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
270 static void parameter_brace_expand_error __P((char *, char *));
272 static int valid_length_expression __P((char *));
273 static intmax_t parameter_brace_expand_length __P((char *));
275 static char *skiparith __P((char *, int));
276 static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
277 static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
278 static char *mb_substring __P((char *, int, int));
279 static char *parameter_brace_substring __P((char *, char *, char *, int));
281 static char *pos_params_pat_subst __P((char *, char *, char *, int));
283 static char *parameter_brace_patsub __P((char *, char *, char *, int));
285 static char *pos_params_casemod __P((char *, char *, int, int));
286 static char *parameter_brace_casemod __P((char *, char *, int, char *, int));
288 static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
289 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
291 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
293 static WORD_LIST *word_list_split __P((WORD_LIST *));
295 static void exp_jump_to_top_level __P((int));
297 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
298 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
299 #ifdef BRACE_EXPANSION
300 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
301 #endif
302 #if defined (ARRAY_VARS)
303 static int make_internal_declare __P((char *, char *));
304 #endif
305 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
306 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
308 /* **************************************************************** */
309 /* */
310 /* Utility Functions */
311 /* */
312 /* **************************************************************** */
314 #ifdef INCLUDE_UNUSED
315 static char *
316 quoted_substring (string, start, end)
317 char *string;
318 int start, end;
320 register int len, l;
321 register char *result, *s, *r;
323 len = end - start;
325 /* Move to string[start], skipping quoted characters. */
326 for (s = string, l = 0; *s && l < start; )
328 if (*s == CTLESC)
330 s++;
331 continue;
333 l++;
334 if (*s == 0)
335 break;
338 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
340 /* Copy LEN characters, including quote characters. */
341 s = string + l;
342 for (l = 0; l < len; s++)
344 if (*s == CTLESC)
345 *r++ = *s++;
346 *r++ = *s;
347 l++;
348 if (*s == 0)
349 break;
351 *r = '\0';
352 return result;
354 #endif
356 #ifdef INCLUDE_UNUSED
357 /* Return the length of S, skipping over quoted characters */
358 static int
359 quoted_strlen (s)
360 char *s;
362 register char *p;
363 int i;
365 i = 0;
366 for (p = s; *p; p++)
368 if (*p == CTLESC)
370 p++;
371 if (*p == 0)
372 return (i + 1);
374 i++;
377 return i;
379 #endif
381 /* Find the first occurrence of character C in string S, obeying shell
382 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
383 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
384 escaped with CTLESC are skipped. */
385 static char *
386 quoted_strchr (s, c, flags)
387 char *s;
388 int c, flags;
390 register char *p;
392 for (p = s; *p; p++)
394 if (((flags & ST_BACKSL) && *p == '\\')
395 || ((flags & ST_CTLESC) && *p == CTLESC))
397 p++;
398 if (*p == '\0')
399 return ((char *)NULL);
400 continue;
402 else if (*p == c)
403 return p;
405 return ((char *)NULL);
408 /* Return 1 if CHARACTER appears in an unquoted portion of
409 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
410 static int
411 unquoted_member (character, string)
412 int character;
413 char *string;
415 size_t slen;
416 int sindex, c;
417 DECLARE_MBSTATE;
419 slen = strlen (string);
420 sindex = 0;
421 while (c = string[sindex])
423 if (c == character)
424 return (1);
426 switch (c)
428 default:
429 ADVANCE_CHAR (string, slen, sindex);
430 break;
432 case '\\':
433 sindex++;
434 if (string[sindex])
435 ADVANCE_CHAR (string, slen, sindex);
436 break;
438 case '\'':
439 sindex = skip_single_quoted (string, slen, ++sindex);
440 break;
442 case '"':
443 sindex = skip_double_quoted (string, slen, ++sindex);
444 break;
447 return (0);
450 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
451 static int
452 unquoted_substring (substr, string)
453 char *substr, *string;
455 size_t slen;
456 int sindex, c, sublen;
457 DECLARE_MBSTATE;
459 if (substr == 0 || *substr == '\0')
460 return (0);
462 slen = strlen (string);
463 sublen = strlen (substr);
464 for (sindex = 0; c = string[sindex]; )
466 if (STREQN (string + sindex, substr, sublen))
467 return (1);
469 switch (c)
471 case '\\':
472 sindex++;
474 if (string[sindex])
475 ADVANCE_CHAR (string, slen, sindex);
476 break;
478 case '\'':
479 sindex = skip_single_quoted (string, slen, ++sindex);
480 break;
482 case '"':
483 sindex = skip_double_quoted (string, slen, ++sindex);
484 break;
486 default:
487 ADVANCE_CHAR (string, slen, sindex);
488 break;
491 return (0);
494 /* Most of the substitutions must be done in parallel. In order
495 to avoid using tons of unclear goto's, I have some functions
496 for manipulating malloc'ed strings. They all take INDX, a
497 pointer to an integer which is the offset into the string
498 where manipulation is taking place. They also take SIZE, a
499 pointer to an integer which is the current length of the
500 character array for this string. */
502 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
503 of space allocated to TARGET. SOURCE can be NULL, in which
504 case nothing happens. Gets rid of SOURCE by freeing it.
505 Returns TARGET in case the location has changed. */
506 INLINE char *
507 sub_append_string (source, target, indx, size)
508 char *source, *target;
509 int *indx, *size;
511 if (source)
513 int srclen, n;
515 srclen = STRLEN (source);
516 if (srclen >= (int)(*size - *indx))
518 n = srclen + *indx;
519 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
520 target = (char *)xrealloc (target, (*size = n));
523 FASTCOPY (source, target + *indx, srclen);
524 *indx += srclen;
525 target[*indx] = '\0';
527 free (source);
529 return (target);
532 #if 0
533 /* UNUSED */
534 /* Append the textual representation of NUMBER to TARGET.
535 INDX and SIZE are as in SUB_APPEND_STRING. */
536 char *
537 sub_append_number (number, target, indx, size)
538 intmax_t number;
539 int *indx, *size;
540 char *target;
542 char *temp;
544 temp = itos (number);
545 return (sub_append_string (temp, target, indx, size));
547 #endif
549 /* Extract a substring from STRING, starting at SINDEX and ending with
550 one of the characters in CHARLIST. Don't make the ending character
551 part of the string. Leave SINDEX pointing at the ending character.
552 Understand about backslashes in the string. If (flags & SX_VARNAME)
553 is non-zero, and array variables have been compiled into the shell,
554 everything between a `[' and a corresponding `]' is skipped over.
555 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
556 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
557 contain a closing character from CHARLIST. */
558 static char *
559 string_extract (string, sindex, charlist, flags)
560 char *string;
561 int *sindex;
562 char *charlist;
563 int flags;
565 register int c, i;
566 int found;
567 size_t slen;
568 char *temp;
569 DECLARE_MBSTATE;
571 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
572 i = *sindex;
573 found = 0;
574 while (c = string[i])
576 if (c == '\\')
578 if (string[i + 1])
579 i++;
580 else
581 break;
583 #if defined (ARRAY_VARS)
584 else if ((flags & SX_VARNAME) && c == '[')
586 int ni;
587 /* If this is an array subscript, skip over it and continue. */
588 ni = skipsubscript (string, i);
589 if (string[ni] == ']')
590 i = ni;
592 #endif
593 else if (MEMBER (c, charlist))
595 found = 1;
596 break;
599 ADVANCE_CHAR (string, slen, i);
602 /* If we had to have a matching delimiter and didn't find one, return an
603 error and let the caller deal with it. */
604 if ((flags & SX_REQMATCH) && found == 0)
606 *sindex = i;
607 return (&extract_string_error);
610 temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
611 *sindex = i;
613 return (temp);
616 /* Extract the contents of STRING as if it is enclosed in double quotes.
617 SINDEX, when passed in, is the offset of the character immediately
618 following the opening double quote; on exit, SINDEX is left pointing after
619 the closing double quote. If STRIPDQ is non-zero, unquoted double
620 quotes are stripped and the string is terminated by a null byte.
621 Backslashes between the embedded double quotes are processed. If STRIPDQ
622 is zero, an unquoted `"' terminates the string. */
623 static char *
624 string_extract_double_quoted (string, sindex, stripdq)
625 char *string;
626 int *sindex, stripdq;
628 size_t slen;
629 char *send;
630 int j, i, t;
631 unsigned char c;
632 char *temp, *ret; /* The new string we return. */
633 int pass_next, backquote, si; /* State variables for the machine. */
634 int dquote;
635 DECLARE_MBSTATE;
637 slen = strlen (string + *sindex) + *sindex;
638 send = string + slen;
640 pass_next = backquote = dquote = 0;
641 temp = (char *)xmalloc (1 + slen - *sindex);
643 j = 0;
644 i = *sindex;
645 while (c = string[i])
647 /* Process a character that was quoted by a backslash. */
648 if (pass_next)
650 /* Posix.2 sez:
652 ``The backslash shall retain its special meaning as an escape
653 character only when followed by one of the characters:
654 $ ` " \ <newline>''.
656 If STRIPDQ is zero, we handle the double quotes here and let
657 expand_word_internal handle the rest. If STRIPDQ is non-zero,
658 we have already been through one round of backslash stripping,
659 and want to strip these backslashes only if DQUOTE is non-zero,
660 indicating that we are inside an embedded double-quoted string. */
662 /* If we are in an embedded quoted string, then don't strip
663 backslashes before characters for which the backslash
664 retains its special meaning, but remove backslashes in
665 front of other characters. If we are not in an
666 embedded quoted string, don't strip backslashes at all.
667 This mess is necessary because the string was already
668 surrounded by double quotes (and sh has some really weird
669 quoting rules).
670 The returned string will be run through expansion as if
671 it were double-quoted. */
672 if ((stripdq == 0 && c != '"') ||
673 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
674 temp[j++] = '\\';
675 pass_next = 0;
677 add_one_character:
678 COPY_CHAR_I (temp, j, string, send, i);
679 continue;
682 /* A backslash protects the next character. The code just above
683 handles preserving the backslash in front of any character but
684 a double quote. */
685 if (c == '\\')
687 pass_next++;
688 i++;
689 continue;
692 /* Inside backquotes, ``the portion of the quoted string from the
693 initial backquote and the characters up to the next backquote
694 that is not preceded by a backslash, having escape characters
695 removed, defines that command''. */
696 if (backquote)
698 if (c == '`')
699 backquote = 0;
700 temp[j++] = c;
701 i++;
702 continue;
705 if (c == '`')
707 temp[j++] = c;
708 backquote++;
709 i++;
710 continue;
713 /* Pass everything between `$(' and the matching `)' or a quoted
714 ${ ... } pair through according to the Posix.2 specification. */
715 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
717 int free_ret = 1;
719 si = i + 2;
720 if (string[i + 1] == LPAREN)
721 ret = extract_command_subst (string, &si, 0);
722 else
723 ret = extract_dollar_brace_string (string, &si, 1, 0);
725 temp[j++] = '$';
726 temp[j++] = string[i + 1];
728 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
729 is set. */
730 if (ret == 0 && no_longjmp_on_fatal_error)
732 free_ret = 0;
733 ret = string + i + 2;
736 for (t = 0; ret[t]; t++, j++)
737 temp[j] = ret[t];
738 temp[j] = string[si];
740 if (string[si])
742 j++;
743 i = si + 1;
745 else
746 i = si;
748 if (free_ret)
749 free (ret);
750 continue;
753 /* Add any character but a double quote to the quoted string we're
754 accumulating. */
755 if (c != '"')
756 goto add_one_character;
758 /* c == '"' */
759 if (stripdq)
761 dquote ^= 1;
762 i++;
763 continue;
766 break;
768 temp[j] = '\0';
770 /* Point to after the closing quote. */
771 if (c)
772 i++;
773 *sindex = i;
775 return (temp);
778 /* This should really be another option to string_extract_double_quoted. */
779 static int
780 skip_double_quoted (string, slen, sind)
781 char *string;
782 size_t slen;
783 int sind;
785 int c, i;
786 char *ret;
787 int pass_next, backquote, si;
788 DECLARE_MBSTATE;
790 pass_next = backquote = 0;
791 i = sind;
792 while (c = string[i])
794 if (pass_next)
796 pass_next = 0;
797 ADVANCE_CHAR (string, slen, i);
798 continue;
800 else if (c == '\\')
802 pass_next++;
803 i++;
804 continue;
806 else if (backquote)
808 if (c == '`')
809 backquote = 0;
810 ADVANCE_CHAR (string, slen, i);
811 continue;
813 else if (c == '`')
815 backquote++;
816 i++;
817 continue;
819 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
821 si = i + 2;
822 if (string[i + 1] == LPAREN)
823 ret = extract_command_subst (string, &si, SX_NOALLOC);
824 else
825 ret = extract_dollar_brace_string (string, &si, 1, SX_NOALLOC);
827 i = si + 1;
828 continue;
830 else if (c != '"')
832 ADVANCE_CHAR (string, slen, i);
833 continue;
835 else
836 break;
839 if (c)
840 i++;
842 return (i);
845 /* Extract the contents of STRING as if it is enclosed in single quotes.
846 SINDEX, when passed in, is the offset of the character immediately
847 following the opening single quote; on exit, SINDEX is left pointing after
848 the closing single quote. */
849 static inline char *
850 string_extract_single_quoted (string, sindex)
851 char *string;
852 int *sindex;
854 register int i;
855 size_t slen;
856 char *t;
857 DECLARE_MBSTATE;
859 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
860 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
861 i = *sindex;
862 while (string[i] && string[i] != '\'')
863 ADVANCE_CHAR (string, slen, i);
865 t = substring (string, *sindex, i);
867 if (string[i])
868 i++;
869 *sindex = i;
871 return (t);
874 static inline int
875 skip_single_quoted (string, slen, sind)
876 const char *string;
877 size_t slen;
878 int sind;
880 register int c;
881 DECLARE_MBSTATE;
883 c = sind;
884 while (string[c] && string[c] != '\'')
885 ADVANCE_CHAR (string, slen, c);
887 if (string[c])
888 c++;
889 return c;
892 /* Just like string_extract, but doesn't hack backslashes or any of
893 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
894 static char *
895 string_extract_verbatim (string, slen, sindex, charlist, flags)
896 char *string;
897 size_t slen;
898 int *sindex;
899 char *charlist;
900 int flags;
902 register int i = *sindex;
903 #if defined (HANDLE_MULTIBYTE)
904 size_t clen;
905 wchar_t *wcharlist;
906 #endif
907 int c;
908 char *temp;
909 DECLARE_MBSTATE;
911 if (charlist[0] == '\'' && charlist[1] == '\0')
913 temp = string_extract_single_quoted (string, sindex);
914 --*sindex; /* leave *sindex at separator character */
915 return temp;
918 i = *sindex;
919 #if 0
920 /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
921 this only if MB_CUR_MAX > 1. */
922 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
923 #endif
924 #if defined (HANDLE_MULTIBYTE)
925 clen = strlen (charlist);
926 wcharlist = 0;
927 #endif
928 while (c = string[i])
930 #if defined (HANDLE_MULTIBYTE)
931 size_t mblength;
932 #endif
933 if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
935 i += 2;
936 continue;
938 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
939 through, to protect the CTLNULs from later calls to
940 remove_quoted_nulls. */
941 else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
943 i += 2;
944 continue;
947 #if defined (HANDLE_MULTIBYTE)
948 mblength = MBLEN (string + i, slen - i);
949 if (mblength > 1)
951 wchar_t wc;
952 mblength = mbtowc (&wc, string + i, slen - i);
953 if (MB_INVALIDCH (mblength))
955 if (MEMBER (c, charlist))
956 break;
958 else
960 if (wcharlist == 0)
962 size_t len;
963 len = mbstowcs (wcharlist, charlist, 0);
964 if (len == -1)
965 len = 0;
966 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
967 mbstowcs (wcharlist, charlist, len + 1);
970 if (wcschr (wcharlist, wc))
971 break;
974 else
975 #endif
976 if (MEMBER (c, charlist))
977 break;
979 ADVANCE_CHAR (string, slen, i);
982 #if defined (HANDLE_MULTIBYTE)
983 FREE (wcharlist);
984 #endif
986 temp = substring (string, *sindex, i);
987 *sindex = i;
989 return (temp);
992 /* Extract the $( construct in STRING, and return a new string.
993 Start extracting at (SINDEX) as if we had just seen "$(".
994 Make (SINDEX) get the position of the matching ")". )
995 XFLAGS is additional flags to pass to other extraction functions, */
996 char *
997 extract_command_subst (string, sindex, xflags)
998 char *string;
999 int *sindex;
1000 int xflags;
1002 if (string[*sindex] == '(') /*)*/
1003 return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
1004 else
1006 xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1007 return (xparse_dolparen (string, string+*sindex, sindex, xflags));
1011 /* Extract the $[ construct in STRING, and return a new string. (])
1012 Start extracting at (SINDEX) as if we had just seen "$[".
1013 Make (SINDEX) get the position of the matching "]". */
1014 char *
1015 extract_arithmetic_subst (string, sindex)
1016 char *string;
1017 int *sindex;
1019 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
1022 #if defined (PROCESS_SUBSTITUTION)
1023 /* Extract the <( or >( construct in STRING, and return a new string.
1024 Start extracting at (SINDEX) as if we had just seen "<(".
1025 Make (SINDEX) get the position of the matching ")". */ /*))*/
1026 char *
1027 extract_process_subst (string, starter, sindex)
1028 char *string;
1029 char *starter;
1030 int *sindex;
1032 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1034 #endif /* PROCESS_SUBSTITUTION */
1036 #if defined (ARRAY_VARS)
1037 /* This can be fooled by unquoted right parens in the passed string. If
1038 each caller verifies that the last character in STRING is a right paren,
1039 we don't even need to call extract_delimited_string. */
1040 char *
1041 extract_array_assignment_list (string, sindex)
1042 char *string;
1043 int *sindex;
1045 int slen;
1046 char *ret;
1048 slen = strlen (string); /* ( */
1049 if (string[slen - 1] == ')')
1051 ret = substring (string, *sindex, slen - 1);
1052 *sindex = slen - 1;
1053 return ret;
1055 return 0;
1057 #endif
1059 /* Extract and create a new string from the contents of STRING, a
1060 character string delimited with OPENER and CLOSER. SINDEX is
1061 the address of an int describing the current offset in STRING;
1062 it should point to just after the first OPENER found. On exit,
1063 SINDEX gets the position of the last character of the matching CLOSER.
1064 If OPENER is more than a single character, ALT_OPENER, if non-null,
1065 contains a character string that can also match CLOSER and thus
1066 needs to be skipped. */
1067 static char *
1068 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1069 char *string;
1070 int *sindex;
1071 char *opener, *alt_opener, *closer;
1072 int flags;
1074 int i, c, si;
1075 size_t slen;
1076 char *t, *result;
1077 int pass_character, nesting_level, in_comment;
1078 int len_closer, len_opener, len_alt_opener;
1079 DECLARE_MBSTATE;
1081 slen = strlen (string + *sindex) + *sindex;
1082 len_opener = STRLEN (opener);
1083 len_alt_opener = STRLEN (alt_opener);
1084 len_closer = STRLEN (closer);
1086 pass_character = in_comment = 0;
1088 nesting_level = 1;
1089 i = *sindex;
1091 while (nesting_level)
1093 c = string[i];
1095 if (c == 0)
1096 break;
1098 if (in_comment)
1100 if (c == '\n')
1101 in_comment = 0;
1102 ADVANCE_CHAR (string, slen, i);
1103 continue;
1106 if (pass_character) /* previous char was backslash */
1108 pass_character = 0;
1109 ADVANCE_CHAR (string, slen, i);
1110 continue;
1113 /* Not exactly right yet; should handle shell metacharacters and
1114 multibyte characters, too. */
1115 if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
1117 in_comment = 1;
1118 ADVANCE_CHAR (string, slen, i);
1119 continue;
1122 if (c == CTLESC || c == '\\')
1124 pass_character++;
1125 i++;
1126 continue;
1129 /* Process a nested OPENER. */
1130 if (STREQN (string + i, opener, len_opener))
1132 si = i + len_opener;
1133 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
1134 i = si + 1;
1135 continue;
1138 /* Process a nested ALT_OPENER */
1139 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1141 si = i + len_alt_opener;
1142 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
1143 i = si + 1;
1144 continue;
1147 /* If the current substring terminates the delimited string, decrement
1148 the nesting level. */
1149 if (STREQN (string + i, closer, len_closer))
1151 i += len_closer - 1; /* move to last byte of the closer */
1152 nesting_level--;
1153 if (nesting_level == 0)
1154 break;
1157 /* Pass old-style command substitution through verbatim. */
1158 if (c == '`')
1160 si = i + 1;
1161 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1162 i = si + 1;
1163 continue;
1166 /* Pass single-quoted and double-quoted strings through verbatim. */
1167 if (c == '\'' || c == '"')
1169 si = i + 1;
1170 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1171 : skip_double_quoted (string, slen, si);
1172 continue;
1175 /* move past this character, which was not special. */
1176 ADVANCE_CHAR (string, slen, i);
1179 if (c == 0 && nesting_level)
1181 if (no_longjmp_on_fatal_error == 0)
1183 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1184 last_command_exit_value = EXECUTION_FAILURE;
1185 exp_jump_to_top_level (DISCARD);
1187 else
1189 *sindex = i;
1190 return (char *)NULL;
1194 si = i - *sindex - len_closer + 1;
1195 if (flags & SX_NOALLOC)
1196 result = (char *)NULL;
1197 else
1199 result = (char *)xmalloc (1 + si);
1200 strncpy (result, string + *sindex, si);
1201 result[si] = '\0';
1203 *sindex = i;
1205 return (result);
1208 /* Extract a parameter expansion expression within ${ and } from STRING.
1209 Obey the Posix.2 rules for finding the ending `}': count braces while
1210 skipping over enclosed quoted strings and command substitutions.
1211 SINDEX is the address of an int describing the current offset in STRING;
1212 it should point to just after the first `{' found. On exit, SINDEX
1213 gets the position of the matching `}'. QUOTED is non-zero if this
1214 occurs inside double quotes. */
1215 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1216 static char *
1217 extract_dollar_brace_string (string, sindex, quoted, flags)
1218 char *string;
1219 int *sindex, quoted, flags;
1221 register int i, c;
1222 size_t slen;
1223 int pass_character, nesting_level, si;
1224 char *result, *t;
1225 DECLARE_MBSTATE;
1227 pass_character = 0;
1228 nesting_level = 1;
1229 slen = strlen (string + *sindex) + *sindex;
1231 i = *sindex;
1232 while (c = string[i])
1234 if (pass_character)
1236 pass_character = 0;
1237 ADVANCE_CHAR (string, slen, i);
1238 continue;
1241 /* CTLESCs and backslashes quote the next character. */
1242 if (c == CTLESC || c == '\\')
1244 pass_character++;
1245 i++;
1246 continue;
1249 if (string[i] == '$' && string[i+1] == LBRACE)
1251 nesting_level++;
1252 i += 2;
1253 continue;
1256 if (c == RBRACE)
1258 nesting_level--;
1259 if (nesting_level == 0)
1260 break;
1261 i++;
1262 continue;
1265 /* Pass the contents of old-style command substitutions through
1266 verbatim. */
1267 if (c == '`')
1269 si = i + 1;
1270 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1271 i = si + 1;
1272 continue;
1275 /* Pass the contents of new-style command substitutions and
1276 arithmetic substitutions through verbatim. */
1277 if (string[i] == '$' && string[i+1] == LPAREN)
1279 si = i + 2;
1280 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1281 i = si + 1;
1282 continue;
1285 /* Pass the contents of single-quoted and double-quoted strings
1286 through verbatim. */
1287 if (c == '\'' || c == '"')
1289 si = i + 1;
1290 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1291 : skip_double_quoted (string, slen, si);
1292 /* skip_XXX_quoted leaves index one past close quote */
1293 continue;
1296 /* move past this character, which was not special. */
1297 ADVANCE_CHAR (string, slen, i);
1300 if (c == 0 && nesting_level)
1302 if (no_longjmp_on_fatal_error == 0)
1303 { /* { */
1304 report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1305 last_command_exit_value = EXECUTION_FAILURE;
1306 exp_jump_to_top_level (DISCARD);
1308 else
1310 *sindex = i;
1311 return ((char *)NULL);
1315 result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1316 *sindex = i;
1318 return (result);
1321 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1322 STRING, and returns a pointer to it. */
1323 char *
1324 de_backslash (string)
1325 char *string;
1327 register size_t slen;
1328 register int i, j, prev_i;
1329 DECLARE_MBSTATE;
1331 slen = strlen (string);
1332 i = j = 0;
1334 /* Loop copying string[i] to string[j], i >= j. */
1335 while (i < slen)
1337 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1338 string[i + 1] == '$'))
1339 i++;
1340 prev_i = i;
1341 ADVANCE_CHAR (string, slen, i);
1342 if (j < prev_i)
1343 do string[j++] = string[prev_i++]; while (prev_i < i);
1344 else
1345 j = i;
1347 string[j] = '\0';
1349 return (string);
1352 #if 0
1353 /*UNUSED*/
1354 /* Replace instances of \! in a string with !. */
1355 void
1356 unquote_bang (string)
1357 char *string;
1359 register int i, j;
1360 register char *temp;
1362 temp = (char *)xmalloc (1 + strlen (string));
1364 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1366 if (string[i] == '\\' && string[i + 1] == '!')
1368 temp[j] = '!';
1369 i++;
1372 strcpy (string, temp);
1373 free (temp);
1375 #endif
1377 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1379 /* This function assumes s[i] == open; returns with s[ret] == close; used to
1380 parse array subscripts. FLAGS currently unused. */
1381 static int
1382 skip_matched_pair (string, start, open, close, flags)
1383 const char *string;
1384 int start, open, close, flags;
1386 int i, pass_next, backq, si, c, count;
1387 size_t slen;
1388 char *temp, *ss;
1389 DECLARE_MBSTATE;
1391 slen = strlen (string + start) + start;
1392 no_longjmp_on_fatal_error = 1;
1394 i = start + 1; /* skip over leading bracket */
1395 count = 1;
1396 pass_next = backq = 0;
1397 ss = (char *)string;
1398 while (c = string[i])
1400 if (pass_next)
1402 pass_next = 0;
1403 if (c == 0)
1404 CQ_RETURN(i);
1405 ADVANCE_CHAR (string, slen, i);
1406 continue;
1408 else if (c == '\\')
1410 pass_next = 1;
1411 i++;
1412 continue;
1414 else if (backq)
1416 if (c == '`')
1417 backq = 0;
1418 ADVANCE_CHAR (string, slen, i);
1419 continue;
1421 else if (c == '`')
1423 backq = 1;
1424 i++;
1425 continue;
1427 else if (c == open)
1429 count++;
1430 i++;
1431 continue;
1433 else if (c == close)
1435 count--;
1436 if (count == 0)
1437 break;
1438 i++;
1439 continue;
1441 else if (c == '\'' || c == '"')
1443 i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
1444 : skip_double_quoted (ss, slen, ++i);
1445 /* no increment, the skip functions increment past the closing quote. */
1447 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1449 si = i + 2;
1450 if (string[si] == '\0')
1451 CQ_RETURN(si);
1453 if (string[i+1] == LPAREN)
1454 temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1455 else
1456 temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
1457 i = si;
1458 if (string[i] == '\0') /* don't increment i past EOS in loop */
1459 break;
1460 i++;
1461 continue;
1463 else
1464 ADVANCE_CHAR (string, slen, i);
1467 CQ_RETURN(i);
1470 #if defined (ARRAY_VARS)
1472 skipsubscript (string, start)
1473 const char *string;
1474 int start;
1476 return (skip_matched_pair (string, start, '[', ']', 0));
1478 #endif
1480 /* Skip characters in STRING until we find a character in DELIMS, and return
1481 the index of that character. START is the index into string at which we
1482 begin. This is similar in spirit to strpbrk, but it returns an index into
1483 STRING and takes a starting index. This little piece of code knows quite
1484 a lot of shell syntax. It's very similar to skip_double_quoted and other
1485 functions of that ilk. */
1487 skip_to_delim (string, start, delims, flags)
1488 char *string;
1489 int start;
1490 char *delims;
1491 int flags;
1493 int i, pass_next, backq, si, c, invert;
1494 size_t slen;
1495 char *temp;
1496 DECLARE_MBSTATE;
1498 slen = strlen (string + start) + start;
1499 if (flags & SD_NOJMP)
1500 no_longjmp_on_fatal_error = 1;
1501 invert = (flags & SD_INVERT);
1503 i = start;
1504 pass_next = backq = 0;
1505 while (c = string[i])
1507 if (pass_next)
1509 pass_next = 0;
1510 if (c == 0)
1511 CQ_RETURN(i);
1512 ADVANCE_CHAR (string, slen, i);
1513 continue;
1515 else if (c == '\\')
1517 pass_next = 1;
1518 i++;
1519 continue;
1521 else if (backq)
1523 if (c == '`')
1524 backq = 0;
1525 ADVANCE_CHAR (string, slen, i);
1526 continue;
1528 else if (c == '`')
1530 backq = 1;
1531 i++;
1532 continue;
1534 else if (invert == 0 && member (c, delims))
1535 break;
1536 else if (c == '\'' || c == '"')
1538 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1539 : skip_double_quoted (string, slen, ++i);
1540 /* no increment, the skip functions increment past the closing quote. */
1542 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1544 si = i + 2;
1545 if (string[si] == '\0')
1546 CQ_RETURN(si);
1548 if (string[i+1] == LPAREN)
1549 temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1550 else
1551 temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
1552 i = si;
1553 if (string[i] == '\0') /* don't increment i past EOS in loop */
1554 break;
1555 i++;
1556 continue;
1558 else if (invert && (member (c, delims) == 0))
1559 break;
1560 else
1561 ADVANCE_CHAR (string, slen, i);
1564 CQ_RETURN(i);
1567 #if defined (READLINE)
1568 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1569 an unclosed quoted string), or if the character at EINDEX is quoted
1570 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1571 single and double-quoted string parsing functions should not return an
1572 error if there are unclosed quotes or braces. The characters that this
1573 recognizes need to be the same as the contents of
1574 rl_completer_quote_characters. */
1577 char_is_quoted (string, eindex)
1578 char *string;
1579 int eindex;
1581 int i, pass_next, c;
1582 size_t slen;
1583 DECLARE_MBSTATE;
1585 slen = strlen (string);
1586 no_longjmp_on_fatal_error = 1;
1587 i = pass_next = 0;
1588 while (i <= eindex)
1590 c = string[i];
1592 if (pass_next)
1594 pass_next = 0;
1595 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1596 CQ_RETURN(1);
1597 ADVANCE_CHAR (string, slen, i);
1598 continue;
1600 else if (c == '\\')
1602 pass_next = 1;
1603 i++;
1604 continue;
1606 else if (c == '\'' || c == '"')
1608 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1609 : skip_double_quoted (string, slen, ++i);
1610 if (i > eindex)
1611 CQ_RETURN(1);
1612 /* no increment, the skip_xxx functions go one past end */
1614 else
1615 ADVANCE_CHAR (string, slen, i);
1618 CQ_RETURN(0);
1622 unclosed_pair (string, eindex, openstr)
1623 char *string;
1624 int eindex;
1625 char *openstr;
1627 int i, pass_next, openc, olen;
1628 size_t slen;
1629 DECLARE_MBSTATE;
1631 slen = strlen (string);
1632 olen = strlen (openstr);
1633 i = pass_next = openc = 0;
1634 while (i <= eindex)
1636 if (pass_next)
1638 pass_next = 0;
1639 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1640 return 0;
1641 ADVANCE_CHAR (string, slen, i);
1642 continue;
1644 else if (string[i] == '\\')
1646 pass_next = 1;
1647 i++;
1648 continue;
1650 else if (STREQN (string + i, openstr, olen))
1652 openc = 1 - openc;
1653 i += olen;
1655 else if (string[i] == '\'' || string[i] == '"')
1657 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1658 : skip_double_quoted (string, slen, i);
1659 if (i > eindex)
1660 return 0;
1662 else
1663 ADVANCE_CHAR (string, slen, i);
1665 return (openc);
1668 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1669 individual words. If DELIMS is NULL, the current value of $IFS is used
1670 to split the string, and the function follows the shell field splitting
1671 rules. SENTINEL is an index to look for. NWP, if non-NULL,
1672 gets the number of words in the returned list. CWP, if non-NULL, gets
1673 the index of the word containing SENTINEL. Non-whitespace chars in
1674 DELIMS delimit separate fields. */
1675 WORD_LIST *
1676 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1677 char *string;
1678 int slen;
1679 char *delims;
1680 int sentinel;
1681 int *nwp, *cwp;
1683 int ts, te, i, nw, cw, ifs_split;
1684 char *token, *d, *d2;
1685 WORD_LIST *ret, *tl;
1687 if (string == 0 || *string == '\0')
1689 if (nwp)
1690 *nwp = 0;
1691 if (cwp)
1692 *cwp = 0;
1693 return ((WORD_LIST *)NULL);
1696 d = (delims == 0) ? ifs_value : delims;
1697 ifs_split = delims == 0;
1699 /* Make d2 the non-whitespace characters in delims */
1700 d2 = 0;
1701 if (delims)
1703 size_t slength;
1704 #if defined (HANDLE_MULTIBYTE)
1705 size_t mblength = 1;
1706 #endif
1707 DECLARE_MBSTATE;
1709 slength = strlen (delims);
1710 d2 = (char *)xmalloc (slength + 1);
1711 i = ts = 0;
1712 while (delims[i])
1714 #if defined (HANDLE_MULTIBYTE)
1715 mbstate_t state_bak;
1716 state_bak = state;
1717 mblength = MBRLEN (delims + i, slength, &state);
1718 if (MB_INVALIDCH (mblength))
1719 state = state_bak;
1720 else if (mblength > 1)
1722 memcpy (d2 + ts, delims + i, mblength);
1723 ts += mblength;
1724 i += mblength;
1725 slength -= mblength;
1726 continue;
1728 #endif
1729 if (whitespace (delims[i]) == 0)
1730 d2[ts++] = delims[i];
1732 i++;
1733 slength--;
1735 d2[ts] = '\0';
1738 ret = (WORD_LIST *)NULL;
1740 /* Remove sequences of whitspace characters at the start of the string, as
1741 long as those characters are delimiters. */
1742 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1744 if (string[i] == '\0')
1745 return (ret);
1747 ts = i;
1748 nw = 0;
1749 cw = -1;
1750 while (1)
1752 te = skip_to_delim (string, ts, d, SD_NOJMP);
1754 /* If we have a non-whitespace delimiter character, use it to make a
1755 separate field. This is just about what $IFS splitting does and
1756 is closer to the behavior of the shell parser. */
1757 if (ts == te && d2 && member (string[ts], d2))
1759 te = ts + 1;
1760 /* If we're using IFS splitting, the non-whitespace delimiter char
1761 and any additional IFS whitespace delimits a field. */
1762 if (ifs_split)
1763 while (member (string[te], d) && spctabnl (string[te]))
1764 te++;
1765 else
1766 while (member (string[te], d2))
1767 te++;
1770 token = substring (string, ts, te);
1772 ret = add_string_to_list (token, ret);
1773 free (token);
1774 nw++;
1776 if (sentinel >= ts && sentinel <= te)
1777 cw = nw;
1779 /* If the cursor is at whitespace just before word start, set the
1780 sentinel word to the current word. */
1781 if (cwp && cw == -1 && sentinel == ts-1)
1782 cw = nw;
1784 /* If the cursor is at whitespace between two words, make a new, empty
1785 word, add it before (well, after, since the list is in reverse order)
1786 the word we just added, and set the current word to that one. */
1787 if (cwp && cw == -1 && sentinel < ts)
1789 tl = make_word_list (make_word (""), ret->next);
1790 ret->next = tl;
1791 cw = nw;
1792 nw++;
1795 if (string[te] == 0)
1796 break;
1798 i = te;
1799 while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
1800 i++;
1802 if (string[i])
1803 ts = i;
1804 else
1805 break;
1808 /* Special case for SENTINEL at the end of STRING. If we haven't found
1809 the word containing SENTINEL yet, and the index we're looking for is at
1810 the end of STRING, add an additional null argument and set the current
1811 word pointer to that. */
1812 if (cwp && cw == -1 && sentinel >= slen)
1814 if (whitespace (string[sentinel - 1]))
1816 token = "";
1817 ret = add_string_to_list (token, ret);
1818 nw++;
1820 cw = nw;
1823 if (nwp)
1824 *nwp = nw;
1825 if (cwp)
1826 *cwp = cw;
1828 return (REVERSE_LIST (ret, WORD_LIST *));
1830 #endif /* READLINE */
1832 #if 0
1833 /* UNUSED */
1834 /* Extract the name of the variable to bind to from the assignment string. */
1835 char *
1836 assignment_name (string)
1837 char *string;
1839 int offset;
1840 char *temp;
1842 offset = assignment (string, 0);
1843 if (offset == 0)
1844 return (char *)NULL;
1845 temp = substring (string, 0, offset);
1846 return (temp);
1848 #endif
1850 /* **************************************************************** */
1851 /* */
1852 /* Functions to convert strings to WORD_LISTs and vice versa */
1853 /* */
1854 /* **************************************************************** */
1856 /* Return a single string of all the words in LIST. SEP is the separator
1857 to put between individual elements of LIST in the output string. */
1858 char *
1859 string_list_internal (list, sep)
1860 WORD_LIST *list;
1861 char *sep;
1863 register WORD_LIST *t;
1864 char *result, *r;
1865 int word_len, sep_len, result_size;
1867 if (list == 0)
1868 return ((char *)NULL);
1870 /* Short-circuit quickly if we don't need to separate anything. */
1871 if (list->next == 0)
1872 return (savestring (list->word->word));
1874 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1875 sep_len = STRLEN (sep);
1876 result_size = 0;
1878 for (t = list; t; t = t->next)
1880 if (t != list)
1881 result_size += sep_len;
1882 result_size += strlen (t->word->word);
1885 r = result = (char *)xmalloc (result_size + 1);
1887 for (t = list; t; t = t->next)
1889 if (t != list && sep_len)
1891 if (sep_len > 1)
1893 FASTCOPY (sep, r, sep_len);
1894 r += sep_len;
1896 else
1897 *r++ = sep[0];
1900 word_len = strlen (t->word->word);
1901 FASTCOPY (t->word->word, r, word_len);
1902 r += word_len;
1905 *r = '\0';
1906 return (result);
1909 /* Return a single string of all the words present in LIST, separating
1910 each word with a space. */
1911 char *
1912 string_list (list)
1913 WORD_LIST *list;
1915 return (string_list_internal (list, " "));
1918 /* An external interface that can be used by the rest of the shell to
1919 obtain a string containing the first character in $IFS. Handles all
1920 the multibyte complications. If LENP is non-null, it is set to the
1921 length of the returned string. */
1922 char *
1923 ifs_firstchar (lenp)
1924 int *lenp;
1926 char *ret;
1927 int len;
1929 ret = xmalloc (MB_LEN_MAX + 1);
1930 #if defined (HANDLE_MULTIBYTE)
1931 if (ifs_firstc_len == 1)
1933 ret[0] = ifs_firstc[0];
1934 ret[1] = '\0';
1935 len = ret[0] ? 1 : 0;
1937 else
1939 memcpy (ret, ifs_firstc, ifs_firstc_len);
1940 ret[len = ifs_firstc_len] = '\0';
1942 #else
1943 ret[0] = ifs_firstc;
1944 ret[1] = '\0';
1945 len = ret[0] ? 0 : 1;
1946 #endif
1948 if (lenp)
1949 *lenp = len;
1951 return ret;
1954 /* Return a single string of all the words present in LIST, obeying the
1955 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1956 expansion [of $*] appears within a double quoted string, it expands
1957 to a single field with the value of each parameter separated by the
1958 first character of the IFS variable, or by a <space> if IFS is unset." */
1959 char *
1960 string_list_dollar_star (list)
1961 WORD_LIST *list;
1963 char *ret;
1964 #if defined (HANDLE_MULTIBYTE)
1965 # if defined (__GNUC__)
1966 char sep[MB_CUR_MAX + 1];
1967 # else
1968 char *sep = 0;
1969 # endif
1970 #else
1971 char sep[2];
1972 #endif
1974 #if defined (HANDLE_MULTIBYTE)
1975 # if !defined (__GNUC__)
1976 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1977 # endif /* !__GNUC__ */
1978 if (ifs_firstc_len == 1)
1980 sep[0] = ifs_firstc[0];
1981 sep[1] = '\0';
1983 else
1985 memcpy (sep, ifs_firstc, ifs_firstc_len);
1986 sep[ifs_firstc_len] = '\0';
1988 #else
1989 sep[0] = ifs_firstc;
1990 sep[1] = '\0';
1991 #endif
1993 ret = string_list_internal (list, sep);
1994 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1995 free (sep);
1996 #endif
1997 return ret;
2000 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2001 is non-zero, the $@ appears within double quotes, and we should quote
2002 the list before converting it into a string. If IFS is unset, and the
2003 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2004 in the words in the list, because the default value of $IFS is
2005 <space><tab><newline>, IFS characters in the words in the list should
2006 also be split. If IFS is null, and the word is not quoted, we need
2007 to quote the words in the list to preserve the positional parameters
2008 exactly. */
2009 char *
2010 string_list_dollar_at (list, quoted)
2011 WORD_LIST *list;
2012 int quoted;
2014 char *ifs, *ret;
2015 #if defined (HANDLE_MULTIBYTE)
2016 # if defined (__GNUC__)
2017 char sep[MB_CUR_MAX + 1];
2018 # else
2019 char *sep = 0;
2020 # endif /* !__GNUC__ */
2021 #else
2022 char sep[2];
2023 #endif
2024 WORD_LIST *tlist;
2026 /* XXX this could just be ifs = ifs_value; */
2027 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
2029 #if defined (HANDLE_MULTIBYTE)
2030 # if !defined (__GNUC__)
2031 sep = (char *)xmalloc (MB_CUR_MAX + 1);
2032 # endif /* !__GNUC__ */
2033 if (ifs && *ifs)
2035 if (ifs_firstc_len == 1)
2037 sep[0] = ifs_firstc[0];
2038 sep[1] = '\0';
2040 else
2042 memcpy (sep, ifs_firstc, ifs_firstc_len);
2043 sep[ifs_firstc_len] = '\0';
2046 else
2048 sep[0] = ' ';
2049 sep[1] = '\0';
2051 #else
2052 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
2053 sep[1] = '\0';
2054 #endif
2056 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
2057 it now that quote_escapes quotes spaces */
2058 #if 0
2059 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
2060 #else
2061 tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2062 #endif
2063 ? quote_list (list)
2064 : list_quote_escapes (list);
2066 ret = string_list_internal (tlist, sep);
2067 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2068 free (sep);
2069 #endif
2070 return ret;
2073 /* Turn the positional paramters into a string, understanding quoting and
2074 the various subtleties of using the first character of $IFS as the
2075 separator. Calls string_list_dollar_at, string_list_dollar_star, and
2076 string_list as appropriate. */
2077 char *
2078 string_list_pos_params (pchar, list, quoted)
2079 int pchar;
2080 WORD_LIST *list;
2081 int quoted;
2083 char *ret;
2084 WORD_LIST *tlist;
2086 if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
2088 tlist = quote_list (list);
2089 word_list_remove_quoted_nulls (tlist);
2090 ret = string_list_dollar_star (tlist);
2092 else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
2094 tlist = quote_list (list);
2095 word_list_remove_quoted_nulls (tlist);
2096 ret = string_list (tlist);
2098 else if (pchar == '*')
2100 /* Even when unquoted, string_list_dollar_star does the right thing
2101 making sure that the first character of $IFS is used as the
2102 separator. */
2103 ret = string_list_dollar_star (list);
2105 else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
2106 /* We use string_list_dollar_at, but only if the string is quoted, since
2107 that quotes the escapes if it's not, which we don't want. We could
2108 use string_list (the old code did), but that doesn't do the right
2109 thing if the first character of $IFS is not a space. We use
2110 string_list_dollar_star if the string is unquoted so we make sure that
2111 the elements of $@ are separated by the first character of $IFS for
2112 later splitting. */
2113 ret = string_list_dollar_at (list, quoted);
2114 else if (pchar == '@')
2115 ret = string_list_dollar_star (list);
2116 else
2117 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
2119 return ret;
2122 /* Return the list of words present in STRING. Separate the string into
2123 words at any of the characters found in SEPARATORS. If QUOTED is
2124 non-zero then word in the list will have its quoted flag set, otherwise
2125 the quoted flag is left as make_word () deemed fit.
2127 This obeys the P1003.2 word splitting semantics. If `separators' is
2128 exactly <space><tab><newline>, then the splitting algorithm is that of
2129 the Bourne shell, which treats any sequence of characters from `separators'
2130 as a delimiter. If IFS is unset, which results in `separators' being set
2131 to "", no splitting occurs. If separators has some other value, the
2132 following rules are applied (`IFS white space' means zero or more
2133 occurrences of <space>, <tab>, or <newline>, as long as those characters
2134 are in `separators'):
2136 1) IFS white space is ignored at the start and the end of the
2137 string.
2138 2) Each occurrence of a character in `separators' that is not
2139 IFS white space, along with any adjacent occurrences of
2140 IFS white space delimits a field.
2141 3) Any nonzero-length sequence of IFS white space delimits a field.
2144 /* BEWARE! list_string strips null arguments. Don't call it twice and
2145 expect to have "" preserved! */
2147 /* This performs word splitting and quoted null character removal on
2148 STRING. */
2149 #define issep(c) \
2150 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2151 : (c) == (separators)[0]) \
2152 : 0)
2154 WORD_LIST *
2155 list_string (string, separators, quoted)
2156 register char *string, *separators;
2157 int quoted;
2159 WORD_LIST *result;
2160 WORD_DESC *t;
2161 char *current_word, *s;
2162 int sindex, sh_style_split, whitesep, xflags;
2163 size_t slen;
2165 if (!string || !*string)
2166 return ((WORD_LIST *)NULL);
2168 sh_style_split = separators && separators[0] == ' ' &&
2169 separators[1] == '\t' &&
2170 separators[2] == '\n' &&
2171 separators[3] == '\0';
2172 for (xflags = 0, s = ifs_value; s && *s; s++)
2174 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2175 else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2178 slen = 0;
2179 /* Remove sequences of whitespace at the beginning of STRING, as
2180 long as those characters appear in IFS. Do not do this if
2181 STRING is quoted or if there are no separator characters. */
2182 if (!quoted || !separators || !*separators)
2184 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
2186 if (!*s)
2187 return ((WORD_LIST *)NULL);
2189 string = s;
2192 /* OK, now STRING points to a word that does not begin with white space.
2193 The splitting algorithm is:
2194 extract a word, stopping at a separator
2195 skip sequences of spc, tab, or nl as long as they are separators
2196 This obeys the field splitting rules in Posix.2. */
2197 slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
2198 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
2200 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2201 unless multibyte chars are possible. */
2202 current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
2203 if (current_word == 0)
2204 break;
2206 /* If we have a quoted empty string, add a quoted null argument. We
2207 want to preserve the quoted null character iff this is a quoted
2208 empty string; otherwise the quoted null characters are removed
2209 below. */
2210 if (QUOTED_NULL (current_word))
2212 t = alloc_word_desc ();
2213 t->word = make_quoted_char ('\0');
2214 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2215 result = make_word_list (t, result);
2217 else if (current_word[0] != '\0')
2219 /* If we have something, then add it regardless. However,
2220 perform quoted null character removal on the current word. */
2221 remove_quoted_nulls (current_word);
2222 result = add_string_to_list (current_word, result);
2223 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
2224 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2225 result->word->flags |= W_QUOTED;
2228 /* If we're not doing sequences of separators in the traditional
2229 Bourne shell style, then add a quoted null argument. */
2230 else if (!sh_style_split && !spctabnl (string[sindex]))
2232 t = alloc_word_desc ();
2233 t->word = make_quoted_char ('\0');
2234 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2235 result = make_word_list (t, result);
2238 free (current_word);
2240 /* Note whether or not the separator is IFS whitespace, used later. */
2241 whitesep = string[sindex] && spctabnl (string[sindex]);
2243 /* Move past the current separator character. */
2244 if (string[sindex])
2246 DECLARE_MBSTATE;
2247 ADVANCE_CHAR (string, slen, sindex);
2250 /* Now skip sequences of space, tab, or newline characters if they are
2251 in the list of separators. */
2252 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2253 sindex++;
2255 /* If the first separator was IFS whitespace and the current character
2256 is a non-whitespace IFS character, it should be part of the current
2257 field delimiter, not a separate delimiter that would result in an
2258 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2259 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2261 sindex++;
2262 /* An IFS character that is not IFS white space, along with any
2263 adjacent IFS white space, shall delimit a field. (SUSv3) */
2264 while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2265 sindex++;
2268 return (REVERSE_LIST (result, WORD_LIST *));
2271 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2272 ENDPTR is set to the first character after the word. This is used by
2273 the `read' builtin. This is never called with SEPARATORS != $IFS;
2274 it should be simplified.
2276 XXX - this function is very similar to list_string; they should be
2277 combined - XXX */
2278 char *
2279 get_word_from_string (stringp, separators, endptr)
2280 char **stringp, *separators, **endptr;
2282 register char *s;
2283 char *current_word;
2284 int sindex, sh_style_split, whitesep, xflags;
2285 size_t slen;
2287 if (!stringp || !*stringp || !**stringp)
2288 return ((char *)NULL);
2290 sh_style_split = separators && separators[0] == ' ' &&
2291 separators[1] == '\t' &&
2292 separators[2] == '\n' &&
2293 separators[3] == '\0';
2294 for (xflags = 0, s = ifs_value; s && *s; s++)
2296 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2297 if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2300 s = *stringp;
2301 slen = 0;
2303 /* Remove sequences of whitespace at the beginning of STRING, as
2304 long as those characters appear in IFS. */
2305 if (sh_style_split || !separators || !*separators)
2307 for (; *s && spctabnl (*s) && isifs (*s); s++);
2309 /* If the string is nothing but whitespace, update it and return. */
2310 if (!*s)
2312 *stringp = s;
2313 if (endptr)
2314 *endptr = s;
2315 return ((char *)NULL);
2319 /* OK, S points to a word that does not begin with white space.
2320 Now extract a word, stopping at a separator, save a pointer to
2321 the first character after the word, then skip sequences of spc,
2322 tab, or nl as long as they are separators.
2324 This obeys the field splitting rules in Posix.2. */
2325 sindex = 0;
2326 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2327 unless multibyte chars are possible. */
2328 slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2329 current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
2331 /* Set ENDPTR to the first character after the end of the word. */
2332 if (endptr)
2333 *endptr = s + sindex;
2335 /* Note whether or not the separator is IFS whitespace, used later. */
2336 whitesep = s[sindex] && spctabnl (s[sindex]);
2338 /* Move past the current separator character. */
2339 if (s[sindex])
2341 DECLARE_MBSTATE;
2342 ADVANCE_CHAR (s, slen, sindex);
2345 /* Now skip sequences of space, tab, or newline characters if they are
2346 in the list of separators. */
2347 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2348 sindex++;
2350 /* If the first separator was IFS whitespace and the current character is
2351 a non-whitespace IFS character, it should be part of the current field
2352 delimiter, not a separate delimiter that would result in an empty field.
2353 Look at POSIX.2, 3.6.5, (3)(b). */
2354 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2356 sindex++;
2357 /* An IFS character that is not IFS white space, along with any adjacent
2358 IFS white space, shall delimit a field. */
2359 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2360 sindex++;
2363 /* Update STRING to point to the next field. */
2364 *stringp = s + sindex;
2365 return (current_word);
2368 /* Remove IFS white space at the end of STRING. Start at the end
2369 of the string and walk backwards until the beginning of the string
2370 or we find a character that's not IFS white space and not CTLESC.
2371 Only let CTLESC escape a white space character if SAW_ESCAPE is
2372 non-zero. */
2373 char *
2374 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2375 char *string, *separators;
2376 int saw_escape;
2378 char *s;
2380 s = string + STRLEN (string) - 1;
2381 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2382 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2383 s--;
2384 *++s = '\0';
2385 return string;
2388 #if 0
2389 /* UNUSED */
2390 /* Split STRING into words at whitespace. Obeys shell-style quoting with
2391 backslashes, single and double quotes. */
2392 WORD_LIST *
2393 list_string_with_quotes (string)
2394 char *string;
2396 WORD_LIST *list;
2397 char *token, *s;
2398 size_t s_len;
2399 int c, i, tokstart, len;
2401 for (s = string; s && *s && spctabnl (*s); s++)
2403 if (s == 0 || *s == 0)
2404 return ((WORD_LIST *)NULL);
2406 s_len = strlen (s);
2407 tokstart = i = 0;
2408 list = (WORD_LIST *)NULL;
2409 while (1)
2411 c = s[i];
2412 if (c == '\\')
2414 i++;
2415 if (s[i])
2416 i++;
2418 else if (c == '\'')
2419 i = skip_single_quoted (s, s_len, ++i);
2420 else if (c == '"')
2421 i = skip_double_quoted (s, s_len, ++i);
2422 else if (c == 0 || spctabnl (c))
2424 /* We have found the end of a token. Make a word out of it and
2425 add it to the word list. */
2426 token = substring (s, tokstart, i);
2427 list = add_string_to_list (token, list);
2428 free (token);
2429 while (spctabnl (s[i]))
2430 i++;
2431 if (s[i])
2432 tokstart = i;
2433 else
2434 break;
2436 else
2437 i++; /* normal character */
2439 return (REVERSE_LIST (list, WORD_LIST *));
2441 #endif
2443 /********************************************************/
2444 /* */
2445 /* Functions to perform assignment statements */
2446 /* */
2447 /********************************************************/
2449 #if defined (ARRAY_VARS)
2450 static SHELL_VAR *
2451 do_compound_assignment (name, value, flags)
2452 char *name, *value;
2453 int flags;
2455 SHELL_VAR *v;
2456 int mklocal, mkassoc;
2457 WORD_LIST *list;
2459 mklocal = flags & ASS_MKLOCAL;
2460 mkassoc = flags & ASS_MKASSOC;
2462 if (mklocal && variable_context)
2464 v = find_variable (name);
2465 list = expand_compound_array_assignment (v, value, flags);
2466 if (mkassoc)
2467 v = make_local_assoc_variable (name);
2468 else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
2469 v = make_local_array_variable (name);
2470 assign_compound_array_list (v, list, flags);
2472 else
2473 v = assign_array_from_string (name, value, flags);
2475 return (v);
2477 #endif
2479 /* Given STRING, an assignment string, get the value of the right side
2480 of the `=', and bind it to the left side. If EXPAND is true, then
2481 perform parameter expansion, command substitution, and arithmetic
2482 expansion on the right-hand side. Perform tilde expansion in any
2483 case. Do not perform word splitting on the result of expansion. */
2484 static int
2485 do_assignment_internal (word, expand)
2486 const WORD_DESC *word;
2487 int expand;
2489 int offset, tlen, appendop, assign_list, aflags, retval;
2490 char *name, *value;
2491 SHELL_VAR *entry;
2492 #if defined (ARRAY_VARS)
2493 char *t;
2494 int ni;
2495 #endif
2496 const char *string;
2498 if (word == 0 || word->word == 0)
2499 return 0;
2501 appendop = assign_list = aflags = 0;
2502 string = word->word;
2503 offset = assignment (string, 0);
2504 name = savestring (string);
2505 value = (char *)NULL;
2507 if (name[offset] == '=')
2509 char *temp;
2511 if (name[offset - 1] == '+')
2513 appendop = 1;
2514 name[offset - 1] = '\0';
2517 name[offset] = 0; /* might need this set later */
2518 temp = name + offset + 1;
2519 tlen = STRLEN (temp);
2521 #if defined (ARRAY_VARS)
2522 if (expand && (word->flags & W_COMPASSIGN))
2524 assign_list = ni = 1;
2525 value = extract_array_assignment_list (temp, &ni);
2527 else
2528 #endif
2530 if (expand && temp[0])
2531 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2532 else
2533 value = savestring (temp);
2536 if (value == 0)
2538 value = (char *)xmalloc (1);
2539 value[0] = '\0';
2542 if (echo_command_at_execute)
2544 if (appendop)
2545 name[offset - 1] = '+';
2546 xtrace_print_assignment (name, value, assign_list, 1);
2547 if (appendop)
2548 name[offset - 1] = '\0';
2551 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
2553 if (appendop)
2554 aflags |= ASS_APPEND;
2556 #if defined (ARRAY_VARS)
2557 if (t = xstrchr (name, '[')) /*]*/
2559 if (assign_list)
2561 report_error (_("%s: cannot assign list to array member"), name);
2562 ASSIGN_RETURN (0);
2564 entry = assign_array_element (name, value, aflags);
2565 if (entry == 0)
2566 ASSIGN_RETURN (0);
2568 else if (assign_list)
2570 if (word->flags & W_ASSIGNARG)
2571 aflags |= ASS_MKLOCAL;
2572 if (word->flags & W_ASSIGNASSOC)
2573 aflags |= ASS_MKASSOC;
2574 entry = do_compound_assignment (name, value, aflags);
2576 else
2577 #endif /* ARRAY_VARS */
2578 entry = bind_variable (name, value, aflags);
2580 stupidly_hack_special_variables (name);
2582 #if 1
2583 /* Return 1 if the assignment seems to have been performed correctly. */
2584 if (entry == 0 || readonly_p (entry))
2585 retval = 0; /* assignment failure */
2586 else if (noassign_p (entry))
2588 last_command_exit_value = EXECUTION_FAILURE;
2589 retval = 1; /* error status, but not assignment failure */
2591 else
2592 retval = 1;
2594 if (entry && retval != 0 && noassign_p (entry) == 0)
2595 VUNSETATTR (entry, att_invisible);
2597 ASSIGN_RETURN (retval);
2598 #else
2599 if (entry)
2600 VUNSETATTR (entry, att_invisible);
2602 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2603 #endif
2606 /* Perform the assignment statement in STRING, and expand the
2607 right side by doing tilde, command and parameter expansion. */
2609 do_assignment (string)
2610 char *string;
2612 WORD_DESC td;
2614 td.flags = W_ASSIGNMENT;
2615 td.word = string;
2617 return do_assignment_internal (&td, 1);
2621 do_word_assignment (word)
2622 WORD_DESC *word;
2624 return do_assignment_internal (word, 1);
2627 /* Given STRING, an assignment string, get the value of the right side
2628 of the `=', and bind it to the left side. Do not perform any word
2629 expansions on the right hand side. */
2631 do_assignment_no_expand (string)
2632 char *string;
2634 WORD_DESC td;
2636 td.flags = W_ASSIGNMENT;
2637 td.word = string;
2639 return (do_assignment_internal (&td, 0));
2642 /***************************************************
2644 * Functions to manage the positional parameters *
2646 ***************************************************/
2648 /* Return the word list that corresponds to `$*'. */
2649 WORD_LIST *
2650 list_rest_of_args ()
2652 register WORD_LIST *list, *args;
2653 int i;
2655 /* Break out of the loop as soon as one of the dollar variables is null. */
2656 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2657 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2659 for (args = rest_of_args; args; args = args->next)
2660 list = make_word_list (make_bare_word (args->word->word), list);
2662 return (REVERSE_LIST (list, WORD_LIST *));
2666 number_of_args ()
2668 register WORD_LIST *list;
2669 int n;
2671 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2673 for (list = rest_of_args; list; list = list->next)
2674 n++;
2675 return n;
2678 /* Return the value of a positional parameter. This handles values > 10. */
2679 char *
2680 get_dollar_var_value (ind)
2681 intmax_t ind;
2683 char *temp;
2684 WORD_LIST *p;
2686 if (ind < 10)
2687 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2688 else /* We want something like ${11} */
2690 ind -= 10;
2691 for (p = rest_of_args; p && ind--; p = p->next)
2693 temp = p ? savestring (p->word->word) : (char *)NULL;
2695 return (temp);
2698 /* Make a single large string out of the dollar digit variables,
2699 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2700 case of "$*" with respect to IFS. */
2701 char *
2702 string_rest_of_args (dollar_star)
2703 int dollar_star;
2705 register WORD_LIST *list;
2706 char *string;
2708 list = list_rest_of_args ();
2709 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2710 dispose_words (list);
2711 return (string);
2714 /* Return a string containing the positional parameters from START to
2715 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2716 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2717 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2718 no quoting chars are added. */
2719 static char *
2720 pos_params (string, start, end, quoted)
2721 char *string;
2722 int start, end, quoted;
2724 WORD_LIST *save, *params, *h, *t;
2725 char *ret;
2726 int i;
2728 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2729 if (start == end)
2730 return ((char *)NULL);
2732 save = params = list_rest_of_args ();
2733 if (save == 0)
2734 return ((char *)NULL);
2736 if (start == 0) /* handle ${@:0[:x]} specially */
2738 t = make_word_list (make_word (dollar_vars[0]), params);
2739 save = params = t;
2742 for (i = 1; params && i < start; i++)
2743 params = params->next;
2744 if (params == 0)
2745 return ((char *)NULL);
2746 for (h = t = params; params && i < end; i++)
2748 t = params;
2749 params = params->next;
2752 t->next = (WORD_LIST *)NULL;
2754 ret = string_list_pos_params (string[0], h, quoted);
2756 if (t != params)
2757 t->next = params;
2759 dispose_words (save);
2760 return (ret);
2763 /******************************************************************/
2764 /* */
2765 /* Functions to expand strings to strings or WORD_LISTs */
2766 /* */
2767 /******************************************************************/
2769 #if defined (PROCESS_SUBSTITUTION)
2770 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
2771 #else
2772 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
2773 #endif
2775 /* If there are any characters in STRING that require full expansion,
2776 then call FUNC to expand STRING; otherwise just perform quote
2777 removal if necessary. This returns a new string. */
2778 static char *
2779 expand_string_if_necessary (string, quoted, func)
2780 char *string;
2781 int quoted;
2782 EXPFUNC *func;
2784 WORD_LIST *list;
2785 size_t slen;
2786 int i, saw_quote;
2787 char *ret;
2788 DECLARE_MBSTATE;
2790 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
2791 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
2792 i = saw_quote = 0;
2793 while (string[i])
2795 if (EXP_CHAR (string[i]))
2796 break;
2797 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2798 saw_quote = 1;
2799 ADVANCE_CHAR (string, slen, i);
2802 if (string[i])
2804 list = (*func) (string, quoted);
2805 if (list)
2807 ret = string_list (list);
2808 dispose_words (list);
2810 else
2811 ret = (char *)NULL;
2813 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2814 ret = string_quote_removal (string, quoted);
2815 else
2816 ret = savestring (string);
2818 return ret;
2821 static inline char *
2822 expand_string_to_string_internal (string, quoted, func)
2823 char *string;
2824 int quoted;
2825 EXPFUNC *func;
2827 WORD_LIST *list;
2828 char *ret;
2830 if (string == 0 || *string == '\0')
2831 return ((char *)NULL);
2833 list = (*func) (string, quoted);
2834 if (list)
2836 ret = string_list (list);
2837 dispose_words (list);
2839 else
2840 ret = (char *)NULL;
2842 return (ret);
2845 char *
2846 expand_string_to_string (string, quoted)
2847 char *string;
2848 int quoted;
2850 return (expand_string_to_string_internal (string, quoted, expand_string));
2853 char *
2854 expand_string_unsplit_to_string (string, quoted)
2855 char *string;
2856 int quoted;
2858 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2861 char *
2862 expand_assignment_string_to_string (string, quoted)
2863 char *string;
2864 int quoted;
2866 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
2869 char *
2870 expand_arith_string (string, quoted)
2871 char *string;
2872 int quoted;
2874 return (expand_string_if_necessary (string, quoted, expand_string));
2877 #if defined (COND_COMMAND)
2878 /* Just remove backslashes in STRING. Returns a new string. */
2879 char *
2880 remove_backslashes (string)
2881 char *string;
2883 char *r, *ret, *s;
2885 r = ret = (char *)xmalloc (strlen (string) + 1);
2886 for (s = string; s && *s; )
2888 if (*s == '\\')
2889 s++;
2890 if (*s == 0)
2891 break;
2892 *r++ = *s++;
2894 *r = '\0';
2895 return ret;
2898 /* This needs better error handling. */
2899 /* Expand W for use as an argument to a unary or binary operator in a
2900 [[...]] expression. If SPECIAL is 1, this is the rhs argument
2901 to the != or == operator, and should be treated as a pattern. In
2902 this case, we quote the string specially for the globbing code. If
2903 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
2904 be quoted appropriately for regcomp/regexec. The caller is responsible
2905 for removing the backslashes if the unquoted word is needed later. */
2906 char *
2907 cond_expand_word (w, special)
2908 WORD_DESC *w;
2909 int special;
2911 char *r, *p;
2912 WORD_LIST *l;
2913 int qflags;
2915 if (w->word == 0 || w->word[0] == '\0')
2916 return ((char *)NULL);
2918 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2919 if (l)
2921 if (special == 0)
2923 dequote_list (l);
2924 r = string_list (l);
2926 else
2928 qflags = QGLOB_CVTNULL;
2929 if (special == 2)
2930 qflags |= QGLOB_REGEXP;
2931 p = string_list (l);
2932 r = quote_string_for_globbing (p, qflags);
2933 free (p);
2935 dispose_words (l);
2937 else
2938 r = (char *)NULL;
2940 return r;
2942 #endif
2944 /* Call expand_word_internal to expand W and handle error returns.
2945 A convenience function for functions that don't want to handle
2946 any errors or free any memory before aborting. */
2947 static WORD_LIST *
2948 call_expand_word_internal (w, q, i, c, e)
2949 WORD_DESC *w;
2950 int q, i, *c, *e;
2952 WORD_LIST *result;
2954 result = expand_word_internal (w, q, i, c, e);
2955 if (result == &expand_word_error || result == &expand_word_fatal)
2957 /* By convention, each time this error is returned, w->word has
2958 already been freed (it sometimes may not be in the fatal case,
2959 but that doesn't result in a memory leak because we're going
2960 to exit in most cases). */
2961 w->word = (char *)NULL;
2962 last_command_exit_value = EXECUTION_FAILURE;
2963 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2964 /* NOTREACHED */
2966 else
2967 return (result);
2970 /* Perform parameter expansion, command substitution, and arithmetic
2971 expansion on STRING, as if it were a word. Leave the result quoted. */
2972 static WORD_LIST *
2973 expand_string_internal (string, quoted)
2974 char *string;
2975 int quoted;
2977 WORD_DESC td;
2978 WORD_LIST *tresult;
2980 if (string == 0 || *string == 0)
2981 return ((WORD_LIST *)NULL);
2983 td.flags = 0;
2984 td.word = savestring (string);
2986 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2988 FREE (td.word);
2989 return (tresult);
2992 /* Expand STRING by performing parameter expansion, command substitution,
2993 and arithmetic expansion. Dequote the resulting WORD_LIST before
2994 returning it, but do not perform word splitting. The call to
2995 remove_quoted_nulls () is in here because word splitting normally
2996 takes care of quote removal. */
2997 WORD_LIST *
2998 expand_string_unsplit (string, quoted)
2999 char *string;
3000 int quoted;
3002 WORD_LIST *value;
3004 if (string == 0 || *string == '\0')
3005 return ((WORD_LIST *)NULL);
3007 expand_no_split_dollar_star = 1;
3008 value = expand_string_internal (string, quoted);
3009 expand_no_split_dollar_star = 0;
3011 if (value)
3013 if (value->word)
3015 remove_quoted_nulls (value->word->word);
3016 value->word->flags &= ~W_HASQUOTEDNULL;
3018 dequote_list (value);
3020 return (value);
3023 /* Expand the rhs of an assignment statement */
3024 WORD_LIST *
3025 expand_string_assignment (string, quoted)
3026 char *string;
3027 int quoted;
3029 WORD_DESC td;
3030 WORD_LIST *value;
3032 if (string == 0 || *string == '\0')
3033 return ((WORD_LIST *)NULL);
3035 expand_no_split_dollar_star = 1;
3037 td.flags = W_ASSIGNRHS;
3038 td.word = savestring (string);
3039 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3040 FREE (td.word);
3042 expand_no_split_dollar_star = 0;
3044 if (value)
3046 if (value->word)
3048 remove_quoted_nulls (value->word->word);
3049 value->word->flags &= ~W_HASQUOTEDNULL;
3051 dequote_list (value);
3053 return (value);
3057 /* Expand one of the PS? prompt strings. This is a sort of combination of
3058 expand_string_unsplit and expand_string_internal, but returns the
3059 passed string when an error occurs. Might want to trap other calls
3060 to jump_to_top_level here so we don't endlessly loop. */
3061 WORD_LIST *
3062 expand_prompt_string (string, quoted, wflags)
3063 char *string;
3064 int quoted;
3065 int wflags;
3067 WORD_LIST *value;
3068 WORD_DESC td;
3070 if (string == 0 || *string == 0)
3071 return ((WORD_LIST *)NULL);
3073 td.flags = wflags;
3074 td.word = savestring (string);
3076 no_longjmp_on_fatal_error = 1;
3077 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3078 no_longjmp_on_fatal_error = 0;
3080 if (value == &expand_word_error || value == &expand_word_fatal)
3082 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
3083 return value;
3085 FREE (td.word);
3086 if (value)
3088 if (value->word)
3090 remove_quoted_nulls (value->word->word);
3091 value->word->flags &= ~W_HASQUOTEDNULL;
3093 dequote_list (value);
3095 return (value);
3098 /* Expand STRING just as if you were expanding a word, but do not dequote
3099 the resultant WORD_LIST. This is called only from within this file,
3100 and is used to correctly preserve quoted characters when expanding
3101 things like ${1+"$@"}. This does parameter expansion, command
3102 substitution, arithmetic expansion, and word splitting. */
3103 static WORD_LIST *
3104 expand_string_leave_quoted (string, quoted)
3105 char *string;
3106 int quoted;
3108 WORD_LIST *tlist;
3109 WORD_LIST *tresult;
3111 if (string == 0 || *string == '\0')
3112 return ((WORD_LIST *)NULL);
3114 tlist = expand_string_internal (string, quoted);
3116 if (tlist)
3118 tresult = word_list_split (tlist);
3119 dispose_words (tlist);
3120 return (tresult);
3122 return ((WORD_LIST *)NULL);
3125 /* This does not perform word splitting or dequote the WORD_LIST
3126 it returns. */
3127 static WORD_LIST *
3128 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
3129 char *string;
3130 int quoted, *dollar_at_p, *has_dollar_at;
3132 WORD_DESC td;
3133 WORD_LIST *tresult;
3135 if (string == 0 || *string == '\0')
3136 return (WORD_LIST *)NULL;
3138 td.flags = 0;
3139 td.word = string;
3140 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
3141 return (tresult);
3144 /* Expand STRING just as if you were expanding a word. This also returns
3145 a list of words. Note that filename globbing is *NOT* done for word
3146 or string expansion, just when the shell is expanding a command. This
3147 does parameter expansion, command substitution, arithmetic expansion,
3148 and word splitting. Dequote the resultant WORD_LIST before returning. */
3149 WORD_LIST *
3150 expand_string (string, quoted)
3151 char *string;
3152 int quoted;
3154 WORD_LIST *result;
3156 if (string == 0 || *string == '\0')
3157 return ((WORD_LIST *)NULL);
3159 result = expand_string_leave_quoted (string, quoted);
3160 return (result ? dequote_list (result) : result);
3163 /***************************************************
3165 * Functions to handle quoting chars *
3167 ***************************************************/
3169 /* Conventions:
3171 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
3172 The parser passes CTLNUL as CTLESC CTLNUL. */
3174 /* Quote escape characters in string s, but no other characters. This is
3175 used to protect CTLESC and CTLNUL in variable values from the rest of
3176 the word expansion process after the variable is expanded (word splitting
3177 and filename generation). If IFS is null, we quote spaces as well, just
3178 in case we split on spaces later (in the case of unquoted $@, we will
3179 eventually attempt to split the entire word on spaces). Corresponding
3180 code exists in dequote_escapes. Even if we don't end up splitting on
3181 spaces, quoting spaces is not a problem. This should never be called on
3182 a string that is quoted with single or double quotes or part of a here
3183 document (effectively double-quoted). */
3184 char *
3185 quote_escapes (string)
3186 char *string;
3188 register char *s, *t;
3189 size_t slen;
3190 char *result, *send;
3191 int quote_spaces, skip_ctlesc, skip_ctlnul;
3192 DECLARE_MBSTATE;
3194 slen = strlen (string);
3195 send = string + slen;
3197 quote_spaces = (ifs_value && *ifs_value == 0);
3199 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
3200 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
3202 t = result = (char *)xmalloc ((slen * 2) + 1);
3203 s = string;
3205 while (*s)
3207 if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
3208 *t++ = CTLESC;
3209 COPY_CHAR_P (t, s, send);
3211 *t = '\0';
3212 return (result);
3215 static WORD_LIST *
3216 list_quote_escapes (list)
3217 WORD_LIST *list;
3219 register WORD_LIST *w;
3220 char *t;
3222 for (w = list; w; w = w->next)
3224 t = w->word->word;
3225 w->word->word = quote_escapes (t);
3226 free (t);
3228 return list;
3231 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
3233 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
3234 This is necessary to make unquoted CTLESC and CTLNUL characters in the
3235 data stream pass through properly.
3237 We need to remove doubled CTLESC characters inside quoted strings before
3238 quoting the entire string, so we do not double the number of CTLESC
3239 characters.
3241 Also used by parts of the pattern substitution code. */
3242 char *
3243 dequote_escapes (string)
3244 char *string;
3246 register char *s, *t, *s1;
3247 size_t slen;
3248 char *result, *send;
3249 int quote_spaces;
3250 DECLARE_MBSTATE;
3252 if (string == 0)
3253 return string;
3255 slen = strlen (string);
3256 send = string + slen;
3258 t = result = (char *)xmalloc (slen + 1);
3260 if (strchr (string, CTLESC) == 0)
3261 return (strcpy (result, string));
3263 quote_spaces = (ifs_value && *ifs_value == 0);
3265 s = string;
3266 while (*s)
3268 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
3270 s++;
3271 if (*s == '\0')
3272 break;
3274 COPY_CHAR_P (t, s, send);
3276 *t = '\0';
3277 return result;
3280 /* Return a new string with the quoted representation of character C.
3281 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3282 set in any resultant WORD_DESC where this value is the word. */
3283 static char *
3284 make_quoted_char (c)
3285 int c;
3287 char *temp;
3289 temp = (char *)xmalloc (3);
3290 if (c == 0)
3292 temp[0] = CTLNUL;
3293 temp[1] = '\0';
3295 else
3297 temp[0] = CTLESC;
3298 temp[1] = c;
3299 temp[2] = '\0';
3301 return (temp);
3304 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
3305 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3306 this value is the word. */
3307 char *
3308 quote_string (string)
3309 char *string;
3311 register char *t;
3312 size_t slen;
3313 char *result, *send;
3315 if (*string == 0)
3317 result = (char *)xmalloc (2);
3318 result[0] = CTLNUL;
3319 result[1] = '\0';
3321 else
3323 DECLARE_MBSTATE;
3325 slen = strlen (string);
3326 send = string + slen;
3328 result = (char *)xmalloc ((slen * 2) + 1);
3330 for (t = result; string < send; )
3332 *t++ = CTLESC;
3333 COPY_CHAR_P (t, string, send);
3335 *t = '\0';
3337 return (result);
3340 /* De-quote quoted characters in STRING. */
3341 char *
3342 dequote_string (string)
3343 char *string;
3345 register char *s, *t;
3346 size_t slen;
3347 char *result, *send;
3348 DECLARE_MBSTATE;
3350 slen = strlen (string);
3352 t = result = (char *)xmalloc (slen + 1);
3354 if (QUOTED_NULL (string))
3356 result[0] = '\0';
3357 return (result);
3360 /* If no character in the string can be quoted, don't bother examining
3361 each character. Just return a copy of the string passed to us. */
3362 if (strchr (string, CTLESC) == NULL)
3363 return (strcpy (result, string));
3365 send = string + slen;
3366 s = string;
3367 while (*s)
3369 if (*s == CTLESC)
3371 s++;
3372 if (*s == '\0')
3373 break;
3375 COPY_CHAR_P (t, s, send);
3378 *t = '\0';
3379 return (result);
3382 /* Quote the entire WORD_LIST list. */
3383 static WORD_LIST *
3384 quote_list (list)
3385 WORD_LIST *list;
3387 register WORD_LIST *w;
3388 char *t;
3390 for (w = list; w; w = w->next)
3392 t = w->word->word;
3393 w->word->word = quote_string (t);
3394 if (*t == 0)
3395 w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
3396 w->word->flags |= W_QUOTED;
3397 free (t);
3399 return list;
3402 /* De-quote quoted characters in each word in LIST. */
3403 WORD_LIST *
3404 dequote_list (list)
3405 WORD_LIST *list;
3407 register char *s;
3408 register WORD_LIST *tlist;
3410 for (tlist = list; tlist; tlist = tlist->next)
3412 s = dequote_string (tlist->word->word);
3413 if (QUOTED_NULL (tlist->word->word))
3414 tlist->word->flags &= ~W_HASQUOTEDNULL;
3415 free (tlist->word->word);
3416 tlist->word->word = s;
3418 return list;
3421 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3422 string. */
3423 char *
3424 remove_quoted_escapes (string)
3425 char *string;
3427 char *t;
3429 if (string)
3431 t = dequote_escapes (string);
3432 strcpy (string, t);
3433 free (t);
3436 return (string);
3439 /* Perform quoted null character removal on STRING. We don't allow any
3440 quoted null characters in the middle or at the ends of strings because
3441 of how expand_word_internal works. remove_quoted_nulls () turns
3442 STRING into an empty string iff it only consists of a quoted null,
3443 and removes all unquoted CTLNUL characters. */
3444 char *
3445 remove_quoted_nulls (string)
3446 char *string;
3448 register size_t slen;
3449 register int i, j, prev_i;
3450 DECLARE_MBSTATE;
3452 if (strchr (string, CTLNUL) == 0) /* XXX */
3453 return string; /* XXX */
3455 slen = strlen (string);
3456 i = j = 0;
3458 while (i < slen)
3460 if (string[i] == CTLESC)
3462 /* Old code had j++, but we cannot assume that i == j at this
3463 point -- what if a CTLNUL has already been removed from the
3464 string? We don't want to drop the CTLESC or recopy characters
3465 that we've already copied down. */
3466 i++; string[j++] = CTLESC;
3467 if (i == slen)
3468 break;
3470 else if (string[i] == CTLNUL)
3471 i++;
3473 prev_i = i;
3474 ADVANCE_CHAR (string, slen, i);
3475 if (j < prev_i)
3477 do string[j++] = string[prev_i++]; while (prev_i < i);
3479 else
3480 j = i;
3482 string[j] = '\0';
3484 return (string);
3487 /* Perform quoted null character removal on each element of LIST.
3488 This modifies LIST. */
3489 void
3490 word_list_remove_quoted_nulls (list)
3491 WORD_LIST *list;
3493 register WORD_LIST *t;
3495 for (t = list; t; t = t->next)
3497 remove_quoted_nulls (t->word->word);
3498 t->word->flags &= ~W_HASQUOTEDNULL;
3502 /* **************************************************************** */
3503 /* */
3504 /* Functions for Matching and Removing Patterns */
3505 /* */
3506 /* **************************************************************** */
3508 #if defined (HANDLE_MULTIBYTE)
3509 #if 0 /* Currently unused */
3510 static unsigned char *
3511 mb_getcharlens (string, len)
3512 char *string;
3513 int len;
3515 int i, offset, last;
3516 unsigned char *ret;
3517 char *p;
3518 DECLARE_MBSTATE;
3520 i = offset = 0;
3521 last = 0;
3522 ret = (unsigned char *)xmalloc (len);
3523 memset (ret, 0, len);
3524 while (string[last])
3526 ADVANCE_CHAR (string, len, offset);
3527 ret[last] = offset - last;
3528 last = offset;
3530 return ret;
3532 #endif
3533 #endif
3535 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3536 can have one of 4 values:
3537 RP_LONG_LEFT remove longest matching portion at start of PARAM
3538 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3539 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3540 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3543 #define RP_LONG_LEFT 1
3544 #define RP_SHORT_LEFT 2
3545 #define RP_LONG_RIGHT 3
3546 #define RP_SHORT_RIGHT 4
3548 static char *
3549 remove_upattern (param, pattern, op)
3550 char *param, *pattern;
3551 int op;
3553 register int len;
3554 register char *end;
3555 register char *p, *ret, c;
3557 len = STRLEN (param);
3558 end = param + len;
3560 switch (op)
3562 case RP_LONG_LEFT: /* remove longest match at start */
3563 for (p = end; p >= param; p--)
3565 c = *p; *p = '\0';
3566 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3568 *p = c;
3569 return (savestring (p));
3571 *p = c;
3574 break;
3576 case RP_SHORT_LEFT: /* remove shortest match at start */
3577 for (p = param; p <= end; p++)
3579 c = *p; *p = '\0';
3580 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3582 *p = c;
3583 return (savestring (p));
3585 *p = c;
3587 break;
3589 case RP_LONG_RIGHT: /* remove longest match at end */
3590 for (p = param; p <= end; p++)
3592 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3594 c = *p; *p = '\0';
3595 ret = savestring (param);
3596 *p = c;
3597 return (ret);
3600 break;
3602 case RP_SHORT_RIGHT: /* remove shortest match at end */
3603 for (p = end; p >= param; p--)
3605 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3607 c = *p; *p = '\0';
3608 ret = savestring (param);
3609 *p = c;
3610 return (ret);
3613 break;
3616 return (savestring (param)); /* no match, return original string */
3619 #if defined (HANDLE_MULTIBYTE)
3620 static wchar_t *
3621 remove_wpattern (wparam, wstrlen, wpattern, op)
3622 wchar_t *wparam;
3623 size_t wstrlen;
3624 wchar_t *wpattern;
3625 int op;
3627 wchar_t wc, *ret;
3628 int n;
3630 switch (op)
3632 case RP_LONG_LEFT: /* remove longest match at start */
3633 for (n = wstrlen; n >= 0; n--)
3635 wc = wparam[n]; wparam[n] = L'\0';
3636 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3638 wparam[n] = wc;
3639 return (wcsdup (wparam + n));
3641 wparam[n] = wc;
3643 break;
3645 case RP_SHORT_LEFT: /* remove shortest match at start */
3646 for (n = 0; n <= wstrlen; n++)
3648 wc = wparam[n]; wparam[n] = L'\0';
3649 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3651 wparam[n] = wc;
3652 return (wcsdup (wparam + n));
3654 wparam[n] = wc;
3656 break;
3658 case RP_LONG_RIGHT: /* remove longest match at end */
3659 for (n = 0; n <= wstrlen; n++)
3661 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3663 wc = wparam[n]; wparam[n] = L'\0';
3664 ret = wcsdup (wparam);
3665 wparam[n] = wc;
3666 return (ret);
3669 break;
3671 case RP_SHORT_RIGHT: /* remove shortest match at end */
3672 for (n = wstrlen; n >= 0; n--)
3674 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3676 wc = wparam[n]; wparam[n] = L'\0';
3677 ret = wcsdup (wparam);
3678 wparam[n] = wc;
3679 return (ret);
3682 break;
3685 return (wcsdup (wparam)); /* no match, return original string */
3687 #endif /* HANDLE_MULTIBYTE */
3689 static char *
3690 remove_pattern (param, pattern, op)
3691 char *param, *pattern;
3692 int op;
3694 if (param == NULL)
3695 return (param);
3696 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3697 return (savestring (param));
3699 #if defined (HANDLE_MULTIBYTE)
3700 if (MB_CUR_MAX > 1)
3702 wchar_t *ret, *oret;
3703 size_t n;
3704 wchar_t *wparam, *wpattern;
3705 mbstate_t ps;
3706 char *xret;
3708 n = xdupmbstowcs (&wpattern, NULL, pattern);
3709 if (n == (size_t)-1)
3710 return (remove_upattern (param, pattern, op));
3711 n = xdupmbstowcs (&wparam, NULL, param);
3712 if (n == (size_t)-1)
3714 free (wpattern);
3715 return (remove_upattern (param, pattern, op));
3717 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3719 free (wparam);
3720 free (wpattern);
3722 n = strlen (param);
3723 xret = (char *)xmalloc (n + 1);
3724 memset (&ps, '\0', sizeof (mbstate_t));
3725 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3726 xret[n] = '\0'; /* just to make sure */
3727 free (oret);
3728 return xret;
3730 else
3731 #endif
3732 return (remove_upattern (param, pattern, op));
3735 /* Return 1 of the first character of STRING could match the first
3736 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
3737 static int
3738 match_pattern_char (pat, string)
3739 char *pat, *string;
3741 char c;
3743 if (*string == 0)
3744 return (0);
3746 switch (c = *pat++)
3748 default:
3749 return (*string == c);
3750 case '\\':
3751 return (*string == *pat);
3752 case '?':
3753 return (*pat == LPAREN ? 1 : (*string != '\0'));
3754 case '*':
3755 return (1);
3756 case '+':
3757 case '!':
3758 case '@':
3759 return (*pat == LPAREN ? 1 : (*string == c));
3760 case '[':
3761 return (*string != '\0');
3765 /* Match PAT anywhere in STRING and return the match boundaries.
3766 This returns 1 in case of a successful match, 0 otherwise. SP
3767 and EP are pointers into the string where the match begins and
3768 ends, respectively. MTYPE controls what kind of match is attempted.
3769 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3770 of the string, respectively. The longest match is returned. */
3771 static int
3772 match_upattern (string, pat, mtype, sp, ep)
3773 char *string, *pat;
3774 int mtype;
3775 char **sp, **ep;
3777 int c, len;
3778 register char *p, *p1, *npat;
3779 char *end;
3781 /* If the pattern doesn't match anywhere in the string, go ahead and
3782 short-circuit right away. A minor optimization, saves a bunch of
3783 unnecessary calls to strmatch (up to N calls for a string of N
3784 characters) if the match is unsuccessful. To preserve the semantics
3785 of the substring matches below, we make sure that the pattern has
3786 `*' as first and last character, making a new pattern if necessary. */
3787 /* XXX - check this later if I ever implement `**' with special meaning,
3788 since this will potentially result in `**' at the beginning or end */
3789 len = STRLEN (pat);
3790 if (pat[0] != '*' || (pat[0] == '*' && pat[1] == '(' && extended_glob) || pat[len - 1] != '*') /*)*/
3792 p = npat = (char *)xmalloc (len + 3);
3793 p1 = pat;
3794 if (*p1 != '*' || (*p1 == '*' && p1[1] == '(' && extended_glob)) /*)*/
3795 *p++ = '*';
3796 while (*p1)
3797 *p++ = *p1++;
3798 if (p1[-1] != '*' || p[-2] == '\\')
3799 *p++ = '*';
3800 *p = '\0';
3802 else
3803 npat = pat;
3804 c = strmatch (npat, string, FNMATCH_EXTFLAG);
3805 if (npat != pat)
3806 free (npat);
3807 if (c == FNM_NOMATCH)
3808 return (0);
3810 len = STRLEN (string);
3811 end = string + len;
3813 switch (mtype)
3815 case MATCH_ANY:
3816 for (p = string; p <= end; p++)
3818 if (match_pattern_char (pat, p))
3820 for (p1 = end; p1 >= p; p1--)
3822 c = *p1; *p1 = '\0';
3823 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3825 *p1 = c;
3826 *sp = p;
3827 *ep = p1;
3828 return 1;
3830 *p1 = c;
3835 return (0);
3837 case MATCH_BEG:
3838 if (match_pattern_char (pat, string) == 0)
3839 return (0);
3841 for (p = end; p >= string; p--)
3843 c = *p; *p = '\0';
3844 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3846 *p = c;
3847 *sp = string;
3848 *ep = p;
3849 return 1;
3851 *p = c;
3854 return (0);
3856 case MATCH_END:
3857 for (p = string; p <= end; p++)
3859 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3861 *sp = p;
3862 *ep = end;
3863 return 1;
3868 return (0);
3871 return (0);
3874 #if defined (HANDLE_MULTIBYTE)
3875 /* Return 1 of the first character of WSTRING could match the first
3876 character of pattern WPAT. Wide character version. */
3877 static int
3878 match_pattern_wchar (wpat, wstring)
3879 wchar_t *wpat, *wstring;
3881 wchar_t wc;
3883 if (*wstring == 0)
3884 return (0);
3886 switch (wc = *wpat++)
3888 default:
3889 return (*wstring == wc);
3890 case L'\\':
3891 return (*wstring == *wpat);
3892 case L'?':
3893 return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3894 case L'*':
3895 return (1);
3896 case L'+':
3897 case L'!':
3898 case L'@':
3899 return (*wpat == LPAREN ? 1 : (*wstring == wc));
3900 case L'[':
3901 return (*wstring != L'\0');
3905 /* Match WPAT anywhere in WSTRING and return the match boundaries.
3906 This returns 1 in case of a successful match, 0 otherwise. Wide
3907 character version. */
3908 static int
3909 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3910 wchar_t *wstring;
3911 char **indices;
3912 size_t wstrlen;
3913 wchar_t *wpat;
3914 int mtype;
3915 char **sp, **ep;
3917 wchar_t wc, *wp, *nwpat, *wp1;
3918 int len;
3919 #if 0
3920 size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3921 #else
3922 int n, n1;
3923 #endif
3925 /* If the pattern doesn't match anywhere in the string, go ahead and
3926 short-circuit right away. A minor optimization, saves a bunch of
3927 unnecessary calls to strmatch (up to N calls for a string of N
3928 characters) if the match is unsuccessful. To preserve the semantics
3929 of the substring matches below, we make sure that the pattern has
3930 `*' as first and last character, making a new pattern if necessary. */
3931 /* XXX - check this later if I ever implement `**' with special meaning,
3932 since this will potentially result in `**' at the beginning or end */
3933 len = wcslen (wpat);
3934 if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == L'(' && extended_glob) || wpat[len - 1] != L'*') /*)*/
3936 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
3937 wp1 = wpat;
3938 if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == '(' && extended_glob)) /*)*/
3939 *wp++ = L'*';
3940 while (*wp1 != L'\0')
3941 *wp++ = *wp1++;
3942 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3943 *wp++ = L'*';
3944 *wp = '\0';
3946 else
3947 nwpat = wpat;
3948 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3949 if (nwpat != wpat)
3950 free (nwpat);
3951 if (len == FNM_NOMATCH)
3952 return (0);
3954 switch (mtype)
3956 case MATCH_ANY:
3957 for (n = 0; n <= wstrlen; n++)
3959 if (match_pattern_wchar (wpat, wstring + n))
3961 for (n1 = wstrlen; n1 >= n; n1--)
3963 wc = wstring[n1]; wstring[n1] = L'\0';
3964 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3966 wstring[n1] = wc;
3967 *sp = indices[n];
3968 *ep = indices[n1];
3969 return 1;
3971 wstring[n1] = wc;
3976 return (0);
3978 case MATCH_BEG:
3979 if (match_pattern_wchar (wpat, wstring) == 0)
3980 return (0);
3982 for (n = wstrlen; n >= 0; n--)
3984 wc = wstring[n]; wstring[n] = L'\0';
3985 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3987 wstring[n] = wc;
3988 *sp = indices[0];
3989 *ep = indices[n];
3990 return 1;
3992 wstring[n] = wc;
3995 return (0);
3997 case MATCH_END:
3998 for (n = 0; n <= wstrlen; n++)
4000 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
4002 *sp = indices[n];
4003 *ep = indices[wstrlen];
4004 return 1;
4008 return (0);
4011 return (0);
4013 #endif /* HANDLE_MULTIBYTE */
4015 static int
4016 match_pattern (string, pat, mtype, sp, ep)
4017 char *string, *pat;
4018 int mtype;
4019 char **sp, **ep;
4021 #if defined (HANDLE_MULTIBYTE)
4022 int ret;
4023 size_t n;
4024 wchar_t *wstring, *wpat;
4025 char **indices;
4026 #endif
4028 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
4029 return (0);
4031 #if defined (HANDLE_MULTIBYTE)
4032 if (MB_CUR_MAX > 1)
4034 n = xdupmbstowcs (&wpat, NULL, pat);
4035 if (n == (size_t)-1)
4036 return (match_upattern (string, pat, mtype, sp, ep));
4037 n = xdupmbstowcs (&wstring, &indices, string);
4038 if (n == (size_t)-1)
4040 free (wpat);
4041 return (match_upattern (string, pat, mtype, sp, ep));
4043 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
4045 free (wpat);
4046 free (wstring);
4047 free (indices);
4049 return (ret);
4051 else
4052 #endif
4053 return (match_upattern (string, pat, mtype, sp, ep));
4056 static int
4057 getpatspec (c, value)
4058 int c;
4059 char *value;
4061 if (c == '#')
4062 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
4063 else /* c == '%' */
4064 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
4067 /* Posix.2 says that the WORD should be run through tilde expansion,
4068 parameter expansion, command substitution and arithmetic expansion.
4069 This leaves the result quoted, so quote_string_for_globbing () has
4070 to be called to fix it up for strmatch (). If QUOTED is non-zero,
4071 it means that the entire expression was enclosed in double quotes.
4072 This means that quoting characters in the pattern do not make any
4073 special pattern characters quoted. For example, the `*' in the
4074 following retains its special meaning: "${foo#'*'}". */
4075 static char *
4076 getpattern (value, quoted, expandpat)
4077 char *value;
4078 int quoted, expandpat;
4080 char *pat, *tword;
4081 WORD_LIST *l;
4082 #if 0
4083 int i;
4084 #endif
4085 /* There is a problem here: how to handle single or double quotes in the
4086 pattern string when the whole expression is between double quotes?
4087 POSIX.2 says that enclosing double quotes do not cause the pattern to
4088 be quoted, but does that leave us a problem with @ and array[@] and their
4089 expansions inside a pattern? */
4090 #if 0
4091 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
4093 i = 0;
4094 pat = string_extract_double_quoted (tword, &i, 1);
4095 free (tword);
4096 tword = pat;
4098 #endif
4100 /* expand_string_for_rhs () leaves WORD quoted and does not perform
4101 word splitting. */
4102 l = *value ? expand_string_for_rhs (value,
4103 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
4104 (int *)NULL, (int *)NULL)
4105 : (WORD_LIST *)0;
4106 pat = string_list (l);
4107 dispose_words (l);
4108 if (pat)
4110 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
4111 free (pat);
4112 pat = tword;
4114 return (pat);
4117 #if 0
4118 /* Handle removing a pattern from a string as a result of ${name%[%]value}
4119 or ${name#[#]value}. */
4120 static char *
4121 variable_remove_pattern (value, pattern, patspec, quoted)
4122 char *value, *pattern;
4123 int patspec, quoted;
4125 char *tword;
4127 tword = remove_pattern (value, pattern, patspec);
4129 return (tword);
4131 #endif
4133 static char *
4134 list_remove_pattern (list, pattern, patspec, itype, quoted)
4135 WORD_LIST *list;
4136 char *pattern;
4137 int patspec, itype, quoted;
4139 WORD_LIST *new, *l;
4140 WORD_DESC *w;
4141 char *tword;
4143 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
4145 tword = remove_pattern (l->word->word, pattern, patspec);
4146 w = alloc_word_desc ();
4147 w->word = tword ? tword : savestring ("");
4148 new = make_word_list (w, new);
4151 l = REVERSE_LIST (new, WORD_LIST *);
4152 tword = string_list_pos_params (itype, l, quoted);
4153 dispose_words (l);
4155 return (tword);
4158 static char *
4159 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
4160 int itype;
4161 char *pattern;
4162 int patspec, quoted;
4164 char *ret;
4165 WORD_LIST *list;
4167 list = list_rest_of_args ();
4168 if (list == 0)
4169 return ((char *)NULL);
4170 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4171 dispose_words (list);
4172 return (ret);
4175 #if defined (ARRAY_VARS)
4176 static char *
4177 array_remove_pattern (var, pattern, patspec, varname, quoted)
4178 SHELL_VAR *var;
4179 char *pattern;
4180 int patspec;
4181 char *varname; /* so we can figure out how it's indexed */
4182 int quoted;
4184 ARRAY *a;
4185 HASH_TABLE *h;
4186 int itype;
4187 char *ret;
4188 WORD_LIST *list;
4189 SHELL_VAR *v;
4191 /* compute itype from varname here */
4192 v = array_variable_part (varname, &ret, 0);
4193 itype = ret[0];
4195 a = (v && array_p (v)) ? array_cell (v) : 0;
4196 h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
4198 list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
4199 if (list == 0)
4200 return ((char *)NULL);
4201 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4202 dispose_words (list);
4204 return ret;
4206 #endif /* ARRAY_VARS */
4208 static char *
4209 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
4210 char *varname, *value, *patstr;
4211 int rtype, quoted;
4213 int vtype, patspec, starsub;
4214 char *temp1, *val, *pattern;
4215 SHELL_VAR *v;
4217 if (value == 0)
4218 return ((char *)NULL);
4220 this_command_name = varname;
4222 vtype = get_var_and_type (varname, value, quoted, &v, &val);
4223 if (vtype == -1)
4224 return ((char *)NULL);
4226 starsub = vtype & VT_STARSUB;
4227 vtype &= ~VT_STARSUB;
4229 patspec = getpatspec (rtype, patstr);
4230 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
4231 patstr++;
4233 /* Need to pass getpattern newly-allocated memory in case of expansion --
4234 the expansion code will free the passed string on an error. */
4235 temp1 = savestring (patstr);
4236 pattern = getpattern (temp1, quoted, 1);
4237 free (temp1);
4239 temp1 = (char *)NULL; /* shut up gcc */
4240 switch (vtype)
4242 case VT_VARIABLE:
4243 case VT_ARRAYMEMBER:
4244 temp1 = remove_pattern (val, pattern, patspec);
4245 if (vtype == VT_VARIABLE)
4246 FREE (val);
4247 if (temp1)
4249 val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4250 ? quote_string (temp1)
4251 : quote_escapes (temp1);
4252 free (temp1);
4253 temp1 = val;
4255 break;
4256 #if defined (ARRAY_VARS)
4257 case VT_ARRAYVAR:
4258 temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted);
4259 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4261 val = quote_escapes (temp1);
4262 free (temp1);
4263 temp1 = val;
4265 break;
4266 #endif
4267 case VT_POSPARMS:
4268 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
4269 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4271 val = quote_escapes (temp1);
4272 free (temp1);
4273 temp1 = val;
4275 break;
4278 FREE (pattern);
4279 return temp1;
4282 /*******************************************
4284 * Functions to expand WORD_DESCs *
4286 *******************************************/
4288 /* Expand WORD, performing word splitting on the result. This does
4289 parameter expansion, command substitution, arithmetic expansion,
4290 word splitting, and quote removal. */
4292 WORD_LIST *
4293 expand_word (word, quoted)
4294 WORD_DESC *word;
4295 int quoted;
4297 WORD_LIST *result, *tresult;
4299 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4300 result = word_list_split (tresult);
4301 dispose_words (tresult);
4302 return (result ? dequote_list (result) : result);
4305 /* Expand WORD, but do not perform word splitting on the result. This
4306 does parameter expansion, command substitution, arithmetic expansion,
4307 and quote removal. */
4308 WORD_LIST *
4309 expand_word_unsplit (word, quoted)
4310 WORD_DESC *word;
4311 int quoted;
4313 WORD_LIST *result;
4315 expand_no_split_dollar_star = 1;
4316 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4317 expand_no_split_dollar_star = 0;
4319 return (result ? dequote_list (result) : result);
4322 /* Perform shell expansions on WORD, but do not perform word splitting or
4323 quote removal on the result. */
4324 WORD_LIST *
4325 expand_word_leave_quoted (word, quoted)
4326 WORD_DESC *word;
4327 int quoted;
4329 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
4332 #if defined (PROCESS_SUBSTITUTION)
4334 /*****************************************************************/
4335 /* */
4336 /* Hacking Process Substitution */
4337 /* */
4338 /*****************************************************************/
4340 #if !defined (HAVE_DEV_FD)
4341 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
4342 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4343 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4344 list. NFIFO is a count of the number of FIFOs in the list. */
4345 #define FIFO_INCR 20
4347 struct temp_fifo {
4348 char *file;
4349 pid_t proc;
4352 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4353 static int nfifo;
4354 static int fifo_list_size;
4356 static void
4357 add_fifo_list (pathname)
4358 char *pathname;
4360 if (nfifo >= fifo_list_size - 1)
4362 fifo_list_size += FIFO_INCR;
4363 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4364 fifo_list_size * sizeof (struct temp_fifo));
4367 fifo_list[nfifo].file = savestring (pathname);
4368 nfifo++;
4371 void
4372 unlink_fifo_list ()
4374 int saved, i, j;
4376 if (nfifo == 0)
4377 return;
4379 for (i = saved = 0; i < nfifo; i++)
4381 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4383 unlink (fifo_list[i].file);
4384 free (fifo_list[i].file);
4385 fifo_list[i].file = (char *)NULL;
4386 fifo_list[i].proc = -1;
4388 else
4389 saved++;
4392 /* If we didn't remove some of the FIFOs, compact the list. */
4393 if (saved)
4395 for (i = j = 0; i < nfifo; i++)
4396 if (fifo_list[i].file)
4398 fifo_list[j].file = fifo_list[i].file;
4399 fifo_list[j].proc = fifo_list[i].proc;
4400 j++;
4402 nfifo = j;
4404 else
4405 nfifo = 0;
4409 fifos_pending ()
4411 return nfifo;
4414 static char *
4415 make_named_pipe ()
4417 char *tname;
4419 tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
4420 if (mkfifo (tname, 0600) < 0)
4422 free (tname);
4423 return ((char *)NULL);
4426 add_fifo_list (tname);
4427 return (tname);
4430 #else /* HAVE_DEV_FD */
4432 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4433 has open to children. NFDS is a count of the number of bits currently
4434 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4435 of open files. */
4436 static char *dev_fd_list = (char *)NULL;
4437 static int nfds;
4438 static int totfds; /* The highest possible number of open files. */
4440 static void
4441 add_fifo_list (fd)
4442 int fd;
4444 if (!dev_fd_list || fd >= totfds)
4446 int ofds;
4448 ofds = totfds;
4449 totfds = getdtablesize ();
4450 if (totfds < 0 || totfds > 256)
4451 totfds = 256;
4452 if (fd >= totfds)
4453 totfds = fd + 2;
4455 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4456 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4459 dev_fd_list[fd] = 1;
4460 nfds++;
4464 fifos_pending ()
4466 return 0; /* used for cleanup; not needed with /dev/fd */
4469 void
4470 unlink_fifo_list ()
4472 register int i;
4474 if (nfds == 0)
4475 return;
4477 for (i = 0; nfds && i < totfds; i++)
4478 if (dev_fd_list[i])
4480 close (i);
4481 dev_fd_list[i] = 0;
4482 nfds--;
4485 nfds = 0;
4488 #if defined (NOTDEF)
4489 print_dev_fd_list ()
4491 register int i;
4493 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4494 fflush (stderr);
4496 for (i = 0; i < totfds; i++)
4498 if (dev_fd_list[i])
4499 fprintf (stderr, " %d", i);
4501 fprintf (stderr, "\n");
4503 #endif /* NOTDEF */
4505 static char *
4506 make_dev_fd_filename (fd)
4507 int fd;
4509 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4511 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8);
4513 strcpy (ret, DEV_FD_PREFIX);
4514 p = inttostr (fd, intbuf, sizeof (intbuf));
4515 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4517 add_fifo_list (fd);
4518 return (ret);
4521 #endif /* HAVE_DEV_FD */
4523 /* Return a filename that will open a connection to the process defined by
4524 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4525 a filename in /dev/fd corresponding to a descriptor that is one of the
4526 ends of the pipe. If not defined, we use named pipes on systems that have
4527 them. Systems without /dev/fd and named pipes are out of luck.
4529 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4530 use the read end of the pipe and dup that file descriptor to fd 0 in
4531 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4532 writing or use the write end of the pipe in the child, and dup that
4533 file descriptor to fd 1 in the child. The parent does the opposite. */
4535 static char *
4536 process_substitute (string, open_for_read_in_child)
4537 char *string;
4538 int open_for_read_in_child;
4540 char *pathname;
4541 int fd, result;
4542 pid_t old_pid, pid;
4543 #if defined (HAVE_DEV_FD)
4544 int parent_pipe_fd, child_pipe_fd;
4545 int fildes[2];
4546 #endif /* HAVE_DEV_FD */
4547 #if defined (JOB_CONTROL)
4548 pid_t old_pipeline_pgrp;
4549 #endif
4551 if (!string || !*string || wordexp_only)
4552 return ((char *)NULL);
4554 #if !defined (HAVE_DEV_FD)
4555 pathname = make_named_pipe ();
4556 #else /* HAVE_DEV_FD */
4557 if (pipe (fildes) < 0)
4559 sys_error (_("cannot make pipe for process substitution"));
4560 return ((char *)NULL);
4562 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4563 the pipe in the parent, otherwise the read end. */
4564 parent_pipe_fd = fildes[open_for_read_in_child];
4565 child_pipe_fd = fildes[1 - open_for_read_in_child];
4566 /* Move the parent end of the pipe to some high file descriptor, to
4567 avoid clashes with FDs used by the script. */
4568 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4570 pathname = make_dev_fd_filename (parent_pipe_fd);
4571 #endif /* HAVE_DEV_FD */
4573 if (pathname == 0)
4575 sys_error (_("cannot make pipe for process substitution"));
4576 return ((char *)NULL);
4579 old_pid = last_made_pid;
4581 #if defined (JOB_CONTROL)
4582 old_pipeline_pgrp = pipeline_pgrp;
4583 pipeline_pgrp = shell_pgrp;
4584 save_pipeline (1);
4585 #endif /* JOB_CONTROL */
4587 pid = make_child ((char *)NULL, 1);
4588 if (pid == 0)
4590 reset_terminating_signals (); /* XXX */
4591 free_pushed_string_input ();
4592 /* Cancel traps, in trap.c. */
4593 restore_original_signals ();
4594 setup_async_signals ();
4595 subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
4598 #if defined (JOB_CONTROL)
4599 set_sigchld_handler ();
4600 stop_making_children ();
4601 /* XXX - should we only do this in the parent? (as in command subst) */
4602 pipeline_pgrp = old_pipeline_pgrp;
4603 #endif /* JOB_CONTROL */
4605 if (pid < 0)
4607 sys_error (_("cannot make child for process substitution"));
4608 free (pathname);
4609 #if defined (HAVE_DEV_FD)
4610 close (parent_pipe_fd);
4611 close (child_pipe_fd);
4612 #endif /* HAVE_DEV_FD */
4613 return ((char *)NULL);
4616 if (pid > 0)
4618 #if defined (JOB_CONTROL)
4619 restore_pipeline (1);
4620 #endif
4622 #if !defined (HAVE_DEV_FD)
4623 fifo_list[nfifo-1].proc = pid;
4624 #endif
4626 last_made_pid = old_pid;
4628 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4629 close_pgrp_pipe ();
4630 #endif /* JOB_CONTROL && PGRP_PIPE */
4632 #if defined (HAVE_DEV_FD)
4633 close (child_pipe_fd);
4634 #endif /* HAVE_DEV_FD */
4636 return (pathname);
4639 set_sigint_handler ();
4641 #if defined (JOB_CONTROL)
4642 set_job_control (0);
4643 #endif /* JOB_CONTROL */
4645 #if !defined (HAVE_DEV_FD)
4646 /* Open the named pipe in the child. */
4647 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4648 if (fd < 0)
4650 /* Two separate strings for ease of translation. */
4651 if (open_for_read_in_child)
4652 sys_error (_("cannot open named pipe %s for reading"), pathname);
4653 else
4654 sys_error (_("cannot open named pipe %s for writing"), pathname);
4656 exit (127);
4658 if (open_for_read_in_child)
4660 if (sh_unset_nodelay_mode (fd) < 0)
4662 sys_error (_("cannot reset nodelay mode for fd %d"), fd);
4663 exit (127);
4666 #else /* HAVE_DEV_FD */
4667 fd = child_pipe_fd;
4668 #endif /* HAVE_DEV_FD */
4670 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4672 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4673 open_for_read_in_child ? 0 : 1);
4674 exit (127);
4677 if (fd != (open_for_read_in_child ? 0 : 1))
4678 close (fd);
4680 /* Need to close any files that this process has open to pipes inherited
4681 from its parent. */
4682 if (current_fds_to_close)
4684 close_fd_bitmap (current_fds_to_close);
4685 current_fds_to_close = (struct fd_bitmap *)NULL;
4688 #if defined (HAVE_DEV_FD)
4689 /* Make sure we close the parent's end of the pipe and clear the slot
4690 in the fd list so it is not closed later, if reallocated by, for
4691 instance, pipe(2). */
4692 close (parent_pipe_fd);
4693 dev_fd_list[parent_pipe_fd] = 0;
4694 #endif /* HAVE_DEV_FD */
4696 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4698 #if !defined (HAVE_DEV_FD)
4699 /* Make sure we close the named pipe in the child before we exit. */
4700 close (open_for_read_in_child ? 0 : 1);
4701 #endif /* !HAVE_DEV_FD */
4703 exit (result);
4704 /*NOTREACHED*/
4706 #endif /* PROCESS_SUBSTITUTION */
4708 /***********************************/
4709 /* */
4710 /* Command Substitution */
4711 /* */
4712 /***********************************/
4714 static char *
4715 read_comsub (fd, quoted, rflag)
4716 int fd, quoted;
4717 int *rflag;
4719 char *istring, buf[128], *bufp, *s;
4720 int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
4721 ssize_t bufn;
4723 istring = (char *)NULL;
4724 istring_index = istring_size = bufn = tflag = 0;
4726 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
4727 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
4729 #ifdef __CYGWIN__
4730 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
4731 #endif
4733 /* Read the output of the command through the pipe. This may need to be
4734 changed to understand multibyte characters in the future. */
4735 while (1)
4737 if (fd < 0)
4738 break;
4739 if (--bufn <= 0)
4741 bufn = zread (fd, buf, sizeof (buf));
4742 if (bufn <= 0)
4743 break;
4744 bufp = buf;
4746 c = *bufp++;
4748 if (c == 0)
4750 #if 0
4751 internal_warning ("read_comsub: ignored null byte in input");
4752 #endif
4753 continue;
4756 /* Add the character to ISTRING, possibly after resizing it. */
4757 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4759 /* This is essentially quote_string inline */
4760 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
4761 istring[istring_index++] = CTLESC;
4762 /* Escape CTLESC and CTLNUL in the output to protect those characters
4763 from the rest of the word expansions (word splitting and globbing.)
4764 This is essentially quote_escapes inline. */
4765 else if (skip_ctlesc == 0 && c == CTLESC)
4767 tflag |= W_HASCTLESC;
4768 istring[istring_index++] = CTLESC;
4770 else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
4771 istring[istring_index++] = CTLESC;
4773 istring[istring_index++] = c;
4775 #if 0
4776 #if defined (__CYGWIN__)
4777 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4779 istring_index--;
4780 istring[istring_index - 1] = '\n';
4782 #endif
4783 #endif
4786 if (istring)
4787 istring[istring_index] = '\0';
4789 /* If we read no output, just return now and save ourselves some
4790 trouble. */
4791 if (istring_index == 0)
4793 FREE (istring);
4794 if (rflag)
4795 *rflag = tflag;
4796 return (char *)NULL;
4799 /* Strip trailing newlines from the output of the command. */
4800 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4802 while (istring_index > 0)
4804 if (istring[istring_index - 1] == '\n')
4806 --istring_index;
4808 /* If the newline was quoted, remove the quoting char. */
4809 if (istring[istring_index - 1] == CTLESC)
4810 --istring_index;
4812 else
4813 break;
4815 istring[istring_index] = '\0';
4817 else
4818 strip_trailing (istring, istring_index - 1, 1);
4820 if (rflag)
4821 *rflag = tflag;
4822 return istring;
4825 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
4826 contained string possibly quoted. */
4827 WORD_DESC *
4828 command_substitute (string, quoted)
4829 char *string;
4830 int quoted;
4832 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4833 char *istring;
4834 int result, fildes[2], function_value, pflags, rc, tflag;
4835 WORD_DESC *ret;
4837 istring = (char *)NULL;
4839 /* Don't fork () if there is no need to. In the case of no command to
4840 run, just return NULL. */
4841 if (!string || !*string || (string[0] == '\n' && !string[1]))
4842 return ((WORD_DESC *)NULL);
4844 if (wordexp_only && read_but_dont_execute)
4846 last_command_exit_value = 125;
4847 jump_to_top_level (EXITPROG);
4850 /* We're making the assumption here that the command substitution will
4851 eventually run a command from the file system. Since we'll run
4852 maybe_make_export_env in this subshell before executing that command,
4853 the parent shell and any other shells it starts will have to remake
4854 the environment. If we make it before we fork, other shells won't
4855 have to. Don't bother if we have any temporary variable assignments,
4856 though, because the export environment will be remade after this
4857 command completes anyway, but do it if all the words to be expanded
4858 are variable assignments. */
4859 if (subst_assign_varlist == 0 || garglist == 0)
4860 maybe_make_export_env (); /* XXX */
4862 /* Flags to pass to parse_and_execute() */
4863 pflags = interactive ? SEVAL_RESETLINE : 0;
4865 /* Pipe the output of executing STRING into the current shell. */
4866 if (pipe (fildes) < 0)
4868 sys_error (_("cannot make pipe for command substitution"));
4869 goto error_exit;
4872 old_pid = last_made_pid;
4873 #if defined (JOB_CONTROL)
4874 old_pipeline_pgrp = pipeline_pgrp;
4875 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4876 if ((subshell_environment & SUBSHELL_PIPE) == 0)
4877 pipeline_pgrp = shell_pgrp;
4878 cleanup_the_pipeline ();
4879 #endif /* JOB_CONTROL */
4881 old_async_pid = last_asynchronous_pid;
4882 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4883 last_asynchronous_pid = old_async_pid;
4885 if (pid == 0)
4886 /* Reset the signal handlers in the child, but don't free the
4887 trap strings. */
4888 reset_signal_handlers ();
4890 #if defined (JOB_CONTROL)
4891 /* XXX DO THIS ONLY IN PARENT ? XXX */
4892 set_sigchld_handler ();
4893 stop_making_children ();
4894 if (pid != 0)
4895 pipeline_pgrp = old_pipeline_pgrp;
4896 #else
4897 stop_making_children ();
4898 #endif /* JOB_CONTROL */
4900 if (pid < 0)
4902 sys_error (_("cannot make child for command substitution"));
4903 error_exit:
4905 FREE (istring);
4906 close (fildes[0]);
4907 close (fildes[1]);
4908 return ((WORD_DESC *)NULL);
4911 if (pid == 0)
4913 set_sigint_handler (); /* XXX */
4915 free_pushed_string_input ();
4917 if (dup2 (fildes[1], 1) < 0)
4919 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4920 exit (EXECUTION_FAILURE);
4923 /* If standard output is closed in the parent shell
4924 (such as after `exec >&-'), file descriptor 1 will be
4925 the lowest available file descriptor, and end up in
4926 fildes[0]. This can happen for stdin and stderr as well,
4927 but stdout is more important -- it will cause no output
4928 to be generated from this command. */
4929 if ((fildes[1] != fileno (stdin)) &&
4930 (fildes[1] != fileno (stdout)) &&
4931 (fildes[1] != fileno (stderr)))
4932 close (fildes[1]);
4934 if ((fildes[0] != fileno (stdin)) &&
4935 (fildes[0] != fileno (stdout)) &&
4936 (fildes[0] != fileno (stderr)))
4937 close (fildes[0]);
4939 /* The currently executing shell is not interactive. */
4940 interactive = 0;
4942 /* This is a subshell environment. */
4943 subshell_environment |= SUBSHELL_COMSUB;
4945 /* When not in POSIX mode, command substitution does not inherit
4946 the -e flag. */
4947 if (posixly_correct == 0)
4948 exit_immediately_on_error = 0;
4950 remove_quoted_escapes (string);
4952 startup_state = 2; /* see if we can avoid a fork */
4953 /* Give command substitution a place to jump back to on failure,
4954 so we don't go back up to main (). */
4955 result = setjmp (top_level);
4957 /* If we're running a command substitution inside a shell function,
4958 trap `return' so we don't return from the function in the subshell
4959 and go off to never-never land. */
4960 if (result == 0 && return_catch_flag)
4961 function_value = setjmp (return_catch);
4962 else
4963 function_value = 0;
4965 if (result == ERREXIT)
4966 rc = last_command_exit_value;
4967 else if (result == EXITPROG)
4968 rc = last_command_exit_value;
4969 else if (result)
4970 rc = EXECUTION_FAILURE;
4971 else if (function_value)
4972 rc = return_catch_value;
4973 else
4975 subshell_level++;
4976 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4977 subshell_level--;
4980 last_command_exit_value = rc;
4981 rc = run_exit_trap ();
4982 #if defined (PROCESS_SUBSTITUTION)
4983 unlink_fifo_list ();
4984 #endif
4985 exit (rc);
4987 else
4989 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4990 close_pgrp_pipe ();
4991 #endif /* JOB_CONTROL && PGRP_PIPE */
4993 close (fildes[1]);
4995 tflag = 0;
4996 istring = read_comsub (fildes[0], quoted, &tflag);
4998 close (fildes[0]);
5000 current_command_subst_pid = pid;
5001 last_command_exit_value = wait_for (pid);
5002 last_command_subst_pid = pid;
5003 last_made_pid = old_pid;
5005 #if defined (JOB_CONTROL)
5006 /* If last_command_exit_value > 128, then the substituted command
5007 was terminated by a signal. If that signal was SIGINT, then send
5008 SIGINT to ourselves. This will break out of loops, for instance. */
5009 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
5010 kill (getpid (), SIGINT);
5012 /* wait_for gives the terminal back to shell_pgrp. If some other
5013 process group should have it, give it away to that group here.
5014 pipeline_pgrp is non-zero only while we are constructing a
5015 pipline, so what we are concerned about is whether or not that
5016 pipeline was started in the background. A pipeline started in
5017 the background should never get the tty back here. */
5018 #if 0
5019 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
5020 #else
5021 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
5022 #endif
5023 give_terminal_to (pipeline_pgrp, 0);
5024 #endif /* JOB_CONTROL */
5026 ret = alloc_word_desc ();
5027 ret->word = istring;
5028 ret->flags = tflag;
5030 return ret;
5034 /********************************************************
5036 * Utility functions for parameter expansion *
5038 ********************************************************/
5040 #if defined (ARRAY_VARS)
5042 static arrayind_t
5043 array_length_reference (s)
5044 char *s;
5046 int len;
5047 arrayind_t ind;
5048 char *akey;
5049 char *t, c;
5050 ARRAY *array;
5051 SHELL_VAR *var;
5053 var = array_variable_part (s, &t, &len);
5055 /* If unbound variables should generate an error, report one and return
5056 failure. */
5057 if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
5059 c = *--t;
5060 *t = '\0';
5061 err_unboundvar (s);
5062 *t = c;
5063 return (-1);
5065 else if (var == 0)
5066 return 0;
5068 /* We support a couple of expansions for variables that are not arrays.
5069 We'll return the length of the value for v[0], and 1 for v[@] or
5070 v[*]. Return 0 for everything else. */
5072 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
5074 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
5076 if (assoc_p (var))
5077 return (assoc_num_elements (assoc_cell (var)));
5078 else if (array_p (var))
5079 return (array_num_elements (array));
5080 else
5081 return 1;
5084 if (assoc_p (var))
5086 t[len - 1] = '\0';
5087 akey = expand_assignment_string_to_string (t, 0); /* [ */
5088 t[len - 1] = ']';
5089 if (akey == 0 || *akey == 0)
5091 err_badarraysub (t);
5092 return (-1);
5094 t = assoc_reference (assoc_cell (var), akey);
5096 else
5098 ind = array_expand_index (t, len);
5099 if (ind < 0)
5101 err_badarraysub (t);
5102 return (-1);
5104 if (array_p (var))
5105 t = array_reference (array, ind);
5106 else
5107 t = (ind == 0) ? value_cell (var) : (char *)NULL;
5110 len = MB_STRLEN (t);
5111 return (len);
5113 #endif /* ARRAY_VARS */
5115 static int
5116 valid_brace_expansion_word (name, var_is_special)
5117 char *name;
5118 int var_is_special;
5120 if (DIGIT (*name) && all_digits (name))
5121 return 1;
5122 else if (var_is_special)
5123 return 1;
5124 #if defined (ARRAY_VARS)
5125 else if (valid_array_reference (name))
5126 return 1;
5127 #endif /* ARRAY_VARS */
5128 else if (legal_identifier (name))
5129 return 1;
5130 else
5131 return 0;
5134 static int
5135 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
5136 char *name;
5137 int quoted;
5138 int *quoted_dollar_atp, *contains_dollar_at;
5140 char *temp1;
5142 if (name == 0)
5144 if (quoted_dollar_atp)
5145 *quoted_dollar_atp = 0;
5146 if (contains_dollar_at)
5147 *contains_dollar_at = 0;
5148 return 0;
5151 /* check for $@ and $* */
5152 if (name[0] == '@' && name[1] == 0)
5154 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5155 *quoted_dollar_atp = 1;
5156 if (contains_dollar_at)
5157 *contains_dollar_at = 1;
5158 return 1;
5160 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
5162 if (contains_dollar_at)
5163 *contains_dollar_at = 1;
5164 return 1;
5167 /* Now check for ${array[@]} and ${array[*]} */
5168 #if defined (ARRAY_VARS)
5169 else if (valid_array_reference (name))
5171 temp1 = xstrchr (name, '[');
5172 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
5174 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5175 *quoted_dollar_atp = 1;
5176 if (contains_dollar_at)
5177 *contains_dollar_at = 1;
5178 return 1;
5179 } /* [ */
5180 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
5181 which should result in separate words even when IFS is unset. */
5182 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
5184 if (contains_dollar_at)
5185 *contains_dollar_at = 1;
5186 return 1;
5189 #endif
5190 return 0;
5193 /* Parameter expand NAME, and return a new string which is the expansion,
5194 or NULL if there was no expansion.
5195 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
5196 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
5197 NAME was found inside of a double-quoted expression. */
5198 static WORD_DESC *
5199 parameter_brace_expand_word (name, var_is_special, quoted, pflags)
5200 char *name;
5201 int var_is_special, quoted, pflags;
5203 WORD_DESC *ret;
5204 char *temp, *tt;
5205 intmax_t arg_index;
5206 SHELL_VAR *var;
5207 int atype, rflags;
5209 ret = 0;
5210 temp = 0;
5211 rflags = 0;
5213 /* Handle multiple digit arguments, as in ${11}. */
5214 if (legal_number (name, &arg_index))
5216 tt = get_dollar_var_value (arg_index);
5217 if (tt)
5218 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5219 ? quote_string (tt)
5220 : quote_escapes (tt);
5221 else
5222 temp = (char *)NULL;
5223 FREE (tt);
5225 else if (var_is_special) /* ${@} */
5227 int sindex;
5228 tt = (char *)xmalloc (2 + strlen (name));
5229 tt[sindex = 0] = '$';
5230 strcpy (tt + 1, name);
5232 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
5233 (int *)NULL, (int *)NULL, pflags);
5234 free (tt);
5236 #if defined (ARRAY_VARS)
5237 else if (valid_array_reference (name))
5239 temp = array_value (name, quoted, &atype);
5240 if (atype == 0 && temp)
5241 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5242 ? quote_string (temp)
5243 : quote_escapes (temp);
5244 else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5245 rflags |= W_HASQUOTEDNULL;
5247 #endif
5248 else if (var = find_variable (name))
5250 if (var_isset (var) && invisible_p (var) == 0)
5252 #if defined (ARRAY_VARS)
5253 if (assoc_p (var))
5254 temp = assoc_reference (assoc_cell (var), "0");
5255 else if (array_p (var))
5256 temp = array_reference (array_cell (var), 0);
5257 else
5258 temp = value_cell (var);
5259 #else
5260 temp = value_cell (var);
5261 #endif
5263 if (temp)
5264 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5265 ? quote_string (temp)
5266 : quote_escapes (temp);
5268 else
5269 temp = (char *)NULL;
5271 else
5272 temp = (char *)NULL;
5274 if (ret == 0)
5276 ret = alloc_word_desc ();
5277 ret->word = temp;
5278 ret->flags |= rflags;
5280 return ret;
5283 /* Expand an indirect reference to a variable: ${!NAME} expands to the
5284 value of the variable whose name is the value of NAME. */
5285 static WORD_DESC *
5286 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
5287 char *name;
5288 int var_is_special, quoted;
5289 int *quoted_dollar_atp, *contains_dollar_at;
5291 char *temp, *t;
5292 WORD_DESC *w;
5294 w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
5295 t = w->word;
5296 /* Have to dequote here if necessary */
5297 if (t)
5299 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5300 ? dequote_string (t)
5301 : dequote_escapes (t);
5302 free (t);
5303 t = temp;
5305 dispose_word_desc (w);
5307 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5308 if (t == 0)
5309 return (WORD_DESC *)NULL;
5311 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
5312 free (t);
5314 return w;
5317 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5318 depending on the value of C, the separating character. C can be one of
5319 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5320 between double quotes. */
5321 static WORD_DESC *
5322 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5323 char *name, *value;
5324 int c, quoted, *qdollaratp, *hasdollarat;
5326 WORD_DESC *w;
5327 WORD_LIST *l;
5328 char *t, *t1, *temp;
5329 int hasdol;
5331 /* If the entire expression is between double quotes, we want to treat
5332 the value as a double-quoted string, with the exception that we strip
5333 embedded unescaped double quotes (for sh backwards compatibility). */
5334 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5336 hasdol = 0;
5337 temp = string_extract_double_quoted (value, &hasdol, 1);
5339 else
5340 temp = value;
5342 w = alloc_word_desc ();
5343 hasdol = 0;
5344 /* XXX was 0 not quoted */
5345 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5346 : (WORD_LIST *)0;
5347 if (hasdollarat)
5348 *hasdollarat = hasdol || (l && l->next);
5349 if (temp != value)
5350 free (temp);
5351 if (l)
5353 /* The expansion of TEMP returned something. We need to treat things
5354 slightly differently if HASDOL is non-zero. If we have "$@", the
5355 individual words have already been quoted. We need to turn them
5356 into a string with the words separated by the first character of
5357 $IFS without any additional quoting, so string_list_dollar_at won't
5358 do the right thing. We use string_list_dollar_star instead. */
5359 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5361 /* If l->next is not null, we know that TEMP contained "$@", since that
5362 is the only expansion that creates more than one word. */
5363 if (qdollaratp && ((hasdol && quoted) || l->next))
5364 *qdollaratp = 1;
5365 dispose_words (l);
5367 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5369 /* The brace expansion occurred between double quotes and there was
5370 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5371 it does not expand to anything. In this case, we want to return
5372 a quoted empty string. */
5373 temp = make_quoted_char ('\0');
5374 w->flags |= W_HASQUOTEDNULL;
5376 else
5377 temp = (char *)NULL;
5379 if (c == '-' || c == '+')
5381 w->word = temp;
5382 return w;
5385 /* c == '=' */
5386 t = temp ? savestring (temp) : savestring ("");
5387 t1 = dequote_string (t);
5388 free (t);
5389 #if defined (ARRAY_VARS)
5390 if (valid_array_reference (name))
5391 assign_array_element (name, t1, 0);
5392 else
5393 #endif /* ARRAY_VARS */
5394 bind_variable (name, t1, 0);
5395 free (t1);
5397 w->word = temp;
5398 return w;
5401 /* Deal with the right hand side of a ${name:?value} expansion in the case
5402 that NAME is null or not set. If VALUE is non-null it is expanded and
5403 used as the error message to print, otherwise a standard message is
5404 printed. */
5405 static void
5406 parameter_brace_expand_error (name, value)
5407 char *name, *value;
5409 WORD_LIST *l;
5410 char *temp;
5412 if (value && *value)
5414 l = expand_string (value, 0);
5415 temp = string_list (l);
5416 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5417 FREE (temp);
5418 dispose_words (l);
5420 else
5421 report_error (_("%s: parameter null or not set"), name);
5423 /* Free the data we have allocated during this expansion, since we
5424 are about to longjmp out. */
5425 free (name);
5426 FREE (value);
5429 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5430 OK to do. */
5431 static int
5432 valid_length_expression (name)
5433 char *name;
5435 return (name[1] == '\0' || /* ${#} */
5436 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5437 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5438 #if defined (ARRAY_VARS)
5439 valid_array_reference (name + 1) || /* ${#a[7]} */
5440 #endif
5441 legal_identifier (name + 1)); /* ${#PS1} */
5444 #if defined (HANDLE_MULTIBYTE)
5445 size_t
5446 mbstrlen (s)
5447 const char *s;
5449 size_t clen, nc;
5450 mbstate_t mbs, mbsbak;
5452 nc = 0;
5453 memset (&mbs, 0, sizeof (mbs));
5454 mbsbak = mbs;
5455 while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5457 if (MB_INVALIDCH(clen))
5459 clen = 1; /* assume single byte */
5460 mbs = mbsbak;
5463 s += clen;
5464 nc++;
5465 mbsbak = mbs;
5467 return nc;
5469 #endif
5472 /* Handle the parameter brace expansion that requires us to return the
5473 length of a parameter. */
5474 static intmax_t
5475 parameter_brace_expand_length (name)
5476 char *name;
5478 char *t, *newname;
5479 intmax_t number, arg_index;
5480 WORD_LIST *list;
5481 #if defined (ARRAY_VARS)
5482 SHELL_VAR *var;
5483 #endif
5485 if (name[1] == '\0') /* ${#} */
5486 number = number_of_args ();
5487 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5488 number = number_of_args ();
5489 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5491 /* Take the lengths of some of the shell's special parameters. */
5492 switch (name[1])
5494 case '-':
5495 t = which_set_flags ();
5496 break;
5497 case '?':
5498 t = itos (last_command_exit_value);
5499 break;
5500 case '$':
5501 t = itos (dollar_dollar_pid);
5502 break;
5503 case '!':
5504 if (last_asynchronous_pid == NO_PID)
5505 t = (char *)NULL;
5506 else
5507 t = itos (last_asynchronous_pid);
5508 break;
5509 case '#':
5510 t = itos (number_of_args ());
5511 break;
5513 number = STRLEN (t);
5514 FREE (t);
5516 #if defined (ARRAY_VARS)
5517 else if (valid_array_reference (name + 1))
5518 number = array_length_reference (name + 1);
5519 #endif /* ARRAY_VARS */
5520 else
5522 number = 0;
5524 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5526 t = get_dollar_var_value (arg_index);
5527 number = MB_STRLEN (t);
5528 FREE (t);
5530 #if defined (ARRAY_VARS)
5531 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
5533 if (assoc_p (var))
5534 t = assoc_reference (assoc_cell (var), "0");
5535 else
5536 t = array_reference (array_cell (var), 0);
5537 number = MB_STRLEN (t);
5539 #endif
5540 else /* ${#PS1} */
5542 newname = savestring (name);
5543 newname[0] = '$';
5544 list = expand_string (newname, Q_DOUBLE_QUOTES);
5545 t = list ? string_list (list) : (char *)NULL;
5546 free (newname);
5547 if (list)
5548 dispose_words (list);
5550 number = MB_STRLEN (t);
5551 FREE (t);
5555 return (number);
5558 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5559 so we do some ad-hoc parsing of an arithmetic expression to find
5560 the first DELIM, instead of using strchr(3). Two rules:
5561 1. If the substring contains a `(', read until closing `)'.
5562 2. If the substring contains a `?', read past one `:' for each `?'.
5565 static char *
5566 skiparith (substr, delim)
5567 char *substr;
5568 int delim;
5570 size_t sublen;
5571 int skipcol, pcount, i;
5572 DECLARE_MBSTATE;
5574 sublen = strlen (substr);
5575 i = skipcol = pcount = 0;
5576 while (substr[i])
5578 /* Balance parens */
5579 if (substr[i] == LPAREN)
5581 pcount++;
5582 i++;
5583 continue;
5585 if (substr[i] == RPAREN && pcount)
5587 pcount--;
5588 i++;
5589 continue;
5591 if (pcount)
5593 ADVANCE_CHAR (substr, sublen, i);
5594 continue;
5597 /* Skip one `:' for each `?' */
5598 if (substr[i] == ':' && skipcol)
5600 skipcol--;
5601 i++;
5602 continue;
5604 if (substr[i] == delim)
5605 break;
5606 if (substr[i] == '?')
5608 skipcol++;
5609 i++;
5610 continue;
5612 ADVANCE_CHAR (substr, sublen, i);
5615 return (substr + i);
5618 /* Verify and limit the start and end of the desired substring. If
5619 VTYPE == 0, a regular shell variable is being used; if it is 1,
5620 then the positional parameters are being used; if it is 2, then
5621 VALUE is really a pointer to an array variable that should be used.
5622 Return value is 1 if both values were OK, 0 if there was a problem
5623 with an invalid expression, or -1 if the values were out of range. */
5624 static int
5625 verify_substring_values (v, value, substr, vtype, e1p, e2p)
5626 SHELL_VAR *v;
5627 char *value, *substr;
5628 int vtype;
5629 intmax_t *e1p, *e2p;
5631 char *t, *temp1, *temp2;
5632 arrayind_t len;
5633 int expok;
5634 #if defined (ARRAY_VARS)
5635 ARRAY *a;
5636 HASH_TABLE *h;
5637 #endif
5639 /* duplicate behavior of strchr(3) */
5640 t = skiparith (substr, ':');
5641 if (*t && *t == ':')
5642 *t = '\0';
5643 else
5644 t = (char *)0;
5646 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
5647 *e1p = evalexp (temp1, &expok);
5648 free (temp1);
5649 if (expok == 0)
5650 return (0);
5652 len = -1; /* paranoia */
5653 switch (vtype)
5655 case VT_VARIABLE:
5656 case VT_ARRAYMEMBER:
5657 len = MB_STRLEN (value);
5658 break;
5659 case VT_POSPARMS:
5660 len = number_of_args () + 1;
5661 if (*e1p == 0)
5662 len++; /* add one arg if counting from $0 */
5663 break;
5664 #if defined (ARRAY_VARS)
5665 case VT_ARRAYVAR:
5666 /* For arrays, the first value deals with array indices. Negative
5667 offsets count from one past the array's maximum index. Associative
5668 arrays treat the number of elements as the maximum index. */
5669 if (assoc_p (v))
5671 h = assoc_cell (v);
5672 len = assoc_num_elements (h) + (*e1p < 0);
5674 else
5676 a = (ARRAY *)value;
5677 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
5679 break;
5680 #endif
5683 if (len == -1) /* paranoia */
5684 return -1;
5686 if (*e1p < 0) /* negative offsets count from end */
5687 *e1p += len;
5689 if (*e1p > len || *e1p < 0)
5690 return (-1);
5692 #if defined (ARRAY_VARS)
5693 /* For arrays, the second offset deals with the number of elements. */
5694 if (vtype == VT_ARRAYVAR)
5695 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
5696 #endif
5698 if (t)
5700 t++;
5701 temp2 = savestring (t);
5702 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
5703 free (temp2);
5704 t[-1] = ':';
5705 *e2p = evalexp (temp1, &expok);
5706 free (temp1);
5707 if (expok == 0)
5708 return (0);
5709 if (*e2p < 0)
5711 internal_error (_("%s: substring expression < 0"), t);
5712 return (0);
5714 #if defined (ARRAY_VARS)
5715 /* In order to deal with sparse arrays, push the intelligence about how
5716 to deal with the number of elements desired down to the array-
5717 specific functions. */
5718 if (vtype != VT_ARRAYVAR)
5719 #endif
5721 *e2p += *e1p; /* want E2 chars starting at E1 */
5722 if (*e2p > len)
5723 *e2p = len;
5726 else
5727 *e2p = len;
5729 return (1);
5732 /* Return the type of variable specified by VARNAME (simple variable,
5733 positional param, or array variable). Also return the value specified
5734 by VARNAME (value of a variable or a reference to an array element).
5735 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5736 characters in the value are quoted with CTLESC and takes appropriate
5737 steps. For convenience, *VALP is set to the dequoted VALUE. */
5738 static int
5739 get_var_and_type (varname, value, quoted, varp, valp)
5740 char *varname, *value;
5741 int quoted;
5742 SHELL_VAR **varp;
5743 char **valp;
5745 int vtype;
5746 char *temp;
5747 #if defined (ARRAY_VARS)
5748 SHELL_VAR *v;
5749 #endif
5751 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5752 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5753 if (vtype == VT_POSPARMS && varname[0] == '*')
5754 vtype |= VT_STARSUB;
5755 *varp = (SHELL_VAR *)NULL;
5757 #if defined (ARRAY_VARS)
5758 if (valid_array_reference (varname))
5760 v = array_variable_part (varname, &temp, (int *)0);
5761 if (v && (array_p (v) || assoc_p (v)))
5762 { /* [ */
5763 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5765 /* Callers have to differentiate betwen indexed and associative */
5766 vtype = VT_ARRAYVAR;
5767 if (temp[0] == '*')
5768 vtype |= VT_STARSUB;
5769 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
5771 else
5773 vtype = VT_ARRAYMEMBER;
5774 *valp = array_value (varname, 1, (int *)NULL);
5776 *varp = v;
5778 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5780 vtype = VT_VARIABLE;
5781 *varp = v;
5782 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5783 *valp = dequote_string (value);
5784 else
5785 *valp = dequote_escapes (value);
5787 else
5789 vtype = VT_ARRAYMEMBER;
5790 *varp = v;
5791 *valp = array_value (varname, 1, (int *)NULL);
5794 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
5796 vtype = VT_ARRAYMEMBER;
5797 *varp = v;
5798 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
5800 else
5801 #endif
5803 if (value && vtype == VT_VARIABLE)
5805 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5806 *valp = dequote_string (value);
5807 else
5808 *valp = dequote_escapes (value);
5810 else
5811 *valp = value;
5814 return vtype;
5817 /******************************************************/
5818 /* */
5819 /* Functions to extract substrings of variable values */
5820 /* */
5821 /******************************************************/
5823 #if defined (HANDLE_MULTIBYTE)
5824 /* Character-oriented rather than strictly byte-oriented substrings. S and
5825 E, rather being strict indices into STRING, indicate character (possibly
5826 multibyte character) positions that require calculation.
5827 Used by the ${param:offset[:length]} expansion. */
5828 static char *
5829 mb_substring (string, s, e)
5830 char *string;
5831 int s, e;
5833 char *tt;
5834 int start, stop, i, slen;
5835 DECLARE_MBSTATE;
5837 start = 0;
5838 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5839 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5841 i = s;
5842 while (string[start] && i--)
5843 ADVANCE_CHAR (string, slen, start);
5844 stop = start;
5845 i = e - s;
5846 while (string[stop] && i--)
5847 ADVANCE_CHAR (string, slen, stop);
5848 tt = substring (string, start, stop);
5849 return tt;
5851 #endif
5853 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
5854 is `@', use the positional parameters; otherwise, use the value of
5855 VARNAME. If VARNAME is an array variable, use the array elements. */
5857 static char *
5858 parameter_brace_substring (varname, value, substr, quoted)
5859 char *varname, *value, *substr;
5860 int quoted;
5862 intmax_t e1, e2;
5863 int vtype, r, starsub;
5864 char *temp, *val, *tt, *oname;
5865 SHELL_VAR *v;
5867 if (value == 0)
5868 return ((char *)NULL);
5870 oname = this_command_name;
5871 this_command_name = varname;
5873 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5874 if (vtype == -1)
5876 this_command_name = oname;
5877 return ((char *)NULL);
5880 starsub = vtype & VT_STARSUB;
5881 vtype &= ~VT_STARSUB;
5883 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
5884 this_command_name = oname;
5885 if (r <= 0)
5886 return ((r == 0) ? &expand_param_error : (char *)NULL);
5888 switch (vtype)
5890 case VT_VARIABLE:
5891 case VT_ARRAYMEMBER:
5892 #if defined (HANDLE_MULTIBYTE)
5893 if (MB_CUR_MAX > 1)
5894 tt = mb_substring (val, e1, e2);
5895 else
5896 #endif
5897 tt = substring (val, e1, e2);
5899 if (vtype == VT_VARIABLE)
5900 FREE (val);
5901 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5902 temp = quote_string (tt);
5903 else
5904 temp = tt ? quote_escapes (tt) : (char *)NULL;
5905 FREE (tt);
5906 break;
5907 case VT_POSPARMS:
5908 tt = pos_params (varname, e1, e2, quoted);
5909 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5911 temp = tt ? quote_escapes (tt) : (char *)NULL;
5912 FREE (tt);
5914 else
5915 temp = tt;
5916 break;
5917 #if defined (ARRAY_VARS)
5918 case VT_ARRAYVAR:
5919 if (assoc_p (v))
5920 /* we convert to list and take first e2 elements starting at e1th
5921 element -- officially undefined for now */
5922 temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
5923 else
5924 /* We want E2 to be the number of elements desired (arrays can be sparse,
5925 so verify_substring_values just returns the numbers specified and we
5926 rely on array_subrange to understand how to deal with them). */
5927 temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5928 /* array_subrange now calls array_quote_escapes as appropriate, so the
5929 caller no longer needs to. */
5930 break;
5931 #endif
5932 default:
5933 temp = (char *)NULL;
5936 return temp;
5939 /****************************************************************/
5940 /* */
5941 /* Functions to perform pattern substitution on variable values */
5942 /* */
5943 /****************************************************************/
5945 char *
5946 pat_subst (string, pat, rep, mflags)
5947 char *string, *pat, *rep;
5948 int mflags;
5950 char *ret, *s, *e, *str;
5951 int rsize, rptr, l, replen, mtype;
5953 mtype = mflags & MATCH_TYPEMASK;
5955 /* Special cases:
5956 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
5957 * with REP and return the result.
5958 * 2. A null pattern with mtype == MATCH_END means to append REP to
5959 * STRING and return the result.
5961 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5963 replen = STRLEN (rep);
5964 l = strlen (string);
5965 ret = (char *)xmalloc (replen + l + 2);
5966 if (replen == 0)
5967 strcpy (ret, string);
5968 else if (mtype == MATCH_BEG)
5970 strcpy (ret, rep);
5971 strcpy (ret + replen, string);
5973 else
5975 strcpy (ret, string);
5976 strcpy (ret + l, rep);
5978 return (ret);
5981 ret = (char *)xmalloc (rsize = 64);
5982 ret[0] = '\0';
5984 for (replen = STRLEN (rep), rptr = 0, str = string;;)
5986 if (match_pattern (str, pat, mtype, &s, &e) == 0)
5987 break;
5988 l = s - str;
5989 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5991 /* OK, now copy the leading unmatched portion of the string (from
5992 str to s) to ret starting at rptr (the current offset). Then copy
5993 the replacement string at ret + rptr + (s - str). Increment
5994 rptr (if necessary) and str and go on. */
5995 if (l)
5997 strncpy (ret + rptr, str, l);
5998 rptr += l;
6000 if (replen)
6002 strncpy (ret + rptr, rep, replen);
6003 rptr += replen;
6005 str = e; /* e == end of match */
6007 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
6008 break;
6010 if (s == e)
6011 e++, str++; /* avoid infinite recursion on zero-length match */
6014 /* Now copy the unmatched portion of the input string */
6015 if (*str)
6017 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
6018 strcpy (ret + rptr, str);
6020 else
6021 ret[rptr] = '\0';
6023 return ret;
6026 /* Do pattern match and replacement on the positional parameters. */
6027 static char *
6028 pos_params_pat_subst (string, pat, rep, mflags)
6029 char *string, *pat, *rep;
6030 int mflags;
6032 WORD_LIST *save, *params;
6033 WORD_DESC *w;
6034 char *ret;
6035 int pchar, qflags;
6037 save = params = list_rest_of_args ();
6038 if (save == 0)
6039 return ((char *)NULL);
6041 for ( ; params; params = params->next)
6043 ret = pat_subst (params->word->word, pat, rep, mflags);
6044 w = alloc_word_desc ();
6045 w->word = ret ? ret : savestring ("");
6046 dispose_word (params->word);
6047 params->word = w;
6050 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6051 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6053 #if 0
6054 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
6055 ret = string_list_dollar_star (quote_list (save));
6056 else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
6057 ret = string_list_dollar_star (save);
6058 else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
6059 ret = string_list_dollar_at (save, qflags);
6060 else
6061 ret = string_list_dollar_star (save);
6062 #else
6063 ret = string_list_pos_params (pchar, save, qflags);
6064 #endif
6066 dispose_words (save);
6068 return (ret);
6071 /* Perform pattern substitution on VALUE, which is the expansion of
6072 VARNAME. PATSUB is an expression supplying the pattern to match
6073 and the string to substitute. QUOTED is a flags word containing
6074 the type of quoting currently in effect. */
6075 static char *
6076 parameter_brace_patsub (varname, value, patsub, quoted)
6077 char *varname, *value, *patsub;
6078 int quoted;
6080 int vtype, mflags, starsub, delim;
6081 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
6082 SHELL_VAR *v;
6084 if (value == 0)
6085 return ((char *)NULL);
6087 this_command_name = varname;
6089 vtype = get_var_and_type (varname, value, quoted, &v, &val);
6090 if (vtype == -1)
6091 return ((char *)NULL);
6093 starsub = vtype & VT_STARSUB;
6094 vtype &= ~VT_STARSUB;
6096 mflags = 0;
6097 if (patsub && *patsub == '/')
6099 mflags |= MATCH_GLOBREP;
6100 patsub++;
6103 /* Malloc this because expand_string_if_necessary or one of the expansion
6104 functions in its call chain may free it on a substitution error. */
6105 lpatsub = savestring (patsub);
6107 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6108 mflags |= MATCH_QUOTED;
6110 if (starsub)
6111 mflags |= MATCH_STARSUB;
6113 /* If the pattern starts with a `/', make sure we skip over it when looking
6114 for the replacement delimiter. */
6115 #if 0
6116 if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
6117 *rep++ = '\0';
6118 else
6119 rep = (char *)NULL;
6120 #else
6121 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
6122 if (lpatsub[delim] == '/')
6124 lpatsub[delim] = 0;
6125 rep = lpatsub + delim + 1;
6127 else
6128 rep = (char *)NULL;
6129 #endif
6131 if (rep && *rep == '\0')
6132 rep = (char *)NULL;
6134 /* Perform the same expansions on the pattern as performed by the
6135 pattern removal expansions. */
6136 pat = getpattern (lpatsub, quoted, 1);
6138 if (rep)
6140 if ((mflags & MATCH_QUOTED) == 0)
6141 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
6142 else
6143 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
6146 /* ksh93 doesn't allow the match specifier to be a part of the expanded
6147 pattern. This is an extension. Make sure we don't anchor the pattern
6148 at the beginning or end of the string if we're doing global replacement,
6149 though. */
6150 p = pat;
6151 if (mflags & MATCH_GLOBREP)
6152 mflags |= MATCH_ANY;
6153 else if (pat && pat[0] == '#')
6155 mflags |= MATCH_BEG;
6156 p++;
6158 else if (pat && pat[0] == '%')
6160 mflags |= MATCH_END;
6161 p++;
6163 else
6164 mflags |= MATCH_ANY;
6166 /* OK, we now want to substitute REP for PAT in VAL. If
6167 flags & MATCH_GLOBREP is non-zero, the substitution is done
6168 everywhere, otherwise only the first occurrence of PAT is
6169 replaced. The pattern matching code doesn't understand
6170 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6171 values passed in (VT_VARIABLE) so the pattern substitution
6172 code works right. We need to requote special chars after
6173 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6174 other cases if QUOTED == 0, since the posparams and arrays
6175 indexed by * or @ do special things when QUOTED != 0. */
6177 switch (vtype)
6179 case VT_VARIABLE:
6180 case VT_ARRAYMEMBER:
6181 temp = pat_subst (val, p, rep, mflags);
6182 if (vtype == VT_VARIABLE)
6183 FREE (val);
6184 if (temp)
6186 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6187 free (temp);
6188 temp = tt;
6190 break;
6191 case VT_POSPARMS:
6192 temp = pos_params_pat_subst (val, p, rep, mflags);
6193 if (temp && (mflags & MATCH_QUOTED) == 0)
6195 tt = quote_escapes (temp);
6196 free (temp);
6197 temp = tt;
6199 break;
6200 #if defined (ARRAY_VARS)
6201 case VT_ARRAYVAR:
6202 temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6203 : array_patsub (array_cell (v), p, rep, mflags);
6204 /* Don't call quote_escapes anymore; array_patsub calls
6205 array_quote_escapes as appropriate before adding the
6206 space separators; ditto for assoc_patsub. */
6207 break;
6208 #endif
6211 FREE (pat);
6212 FREE (rep);
6213 free (lpatsub);
6215 return temp;
6218 /****************************************************************/
6219 /* */
6220 /* Functions to perform case modification on variable values */
6221 /* */
6222 /****************************************************************/
6224 /* Do case modification on the positional parameters. */
6226 static char *
6227 pos_params_modcase (string, pat, modop, mflags)
6228 char *string, *pat;
6229 int modop;
6230 int mflags;
6232 WORD_LIST *save, *params;
6233 WORD_DESC *w;
6234 char *ret;
6235 int pchar, qflags;
6237 save = params = list_rest_of_args ();
6238 if (save == 0)
6239 return ((char *)NULL);
6241 for ( ; params; params = params->next)
6243 ret = sh_modcase (params->word->word, pat, modop);
6244 w = alloc_word_desc ();
6245 w->word = ret ? ret : savestring ("");
6246 dispose_word (params->word);
6247 params->word = w;
6250 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6251 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6253 ret = string_list_pos_params (pchar, save, qflags);
6254 dispose_words (save);
6256 return (ret);
6259 /* Perform case modification on VALUE, which is the expansion of
6260 VARNAME. MODSPEC is an expression supplying the type of modification
6261 to perform. QUOTED is a flags word containing the type of quoting
6262 currently in effect. */
6263 static char *
6264 parameter_brace_casemod (varname, value, modspec, patspec, quoted)
6265 char *varname, *value;
6266 int modspec;
6267 char *patspec;
6268 int quoted;
6270 int vtype, starsub, modop, mflags, x;
6271 char *val, *temp, *pat, *p, *lpat, *tt;
6272 SHELL_VAR *v;
6274 if (value == 0)
6275 return ((char *)NULL);
6277 this_command_name = varname;
6279 vtype = get_var_and_type (varname, value, quoted, &v, &val);
6280 if (vtype == -1)
6281 return ((char *)NULL);
6283 starsub = vtype & VT_STARSUB;
6284 vtype &= ~VT_STARSUB;
6286 modop = 0;
6287 mflags = 0;
6288 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6289 mflags |= MATCH_QUOTED;
6290 if (starsub)
6291 mflags |= MATCH_STARSUB;
6293 p = patspec;
6294 if (modspec == '^')
6296 x = p && p[0] == modspec;
6297 modop = x ? CASE_UPPER : CASE_UPFIRST;
6298 p += x;
6300 else if (modspec == ',')
6302 x = p && p[0] == modspec;
6303 modop = x ? CASE_LOWER : CASE_LOWFIRST;
6304 p += x;
6306 else if (modspec == '~')
6308 x = p && p[0] == modspec;
6309 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6310 p += x;
6313 lpat = p ? savestring (p) : 0;
6314 /* Perform the same expansions on the pattern as performed by the
6315 pattern removal expansions. FOR LATER */
6316 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6318 /* OK, now we do the case modification. */
6319 switch (vtype)
6321 case VT_VARIABLE:
6322 case VT_ARRAYMEMBER:
6323 temp = sh_modcase (val, pat, modop);
6324 if (vtype == VT_VARIABLE)
6325 FREE (val);
6326 if (temp)
6328 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6329 free (temp);
6330 temp = tt;
6332 break;
6334 case VT_POSPARMS:
6335 temp = pos_params_modcase (val, pat, modop, mflags);
6336 if (temp && (mflags & MATCH_QUOTED) == 0)
6338 tt = quote_escapes (temp);
6339 free (temp);
6340 temp = tt;
6342 break;
6344 #if defined (ARRAY_VARS)
6345 case VT_ARRAYVAR:
6346 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6347 : array_modcase (array_cell (v), pat, modop, mflags);
6348 /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6349 as appropriate before adding the space separators; ditto for
6350 assoc_modcase. */
6351 break;
6352 #endif
6355 FREE (pat);
6356 free (lpat);
6358 return temp;
6361 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
6362 any occur, this must be a nested command substitution, so return 0.
6363 Otherwise, return 1. A valid arithmetic expression must always have a
6364 ( before a matching ), so any cases where there are more right parens
6365 means that this must not be an arithmetic expression, though the parser
6366 will not accept it without a balanced total number of parens. */
6367 static int
6368 chk_arithsub (s, len)
6369 const char *s;
6370 int len;
6372 int i, count;
6373 DECLARE_MBSTATE;
6375 i = count = 0;
6376 while (i < len)
6378 if (s[i] == '(')
6379 count++;
6380 else if (s[i] == ')')
6382 count--;
6383 if (count < 0)
6384 return 0;
6387 switch (s[i])
6389 default:
6390 ADVANCE_CHAR (s, len, i);
6391 break;
6393 case '\\':
6394 i++;
6395 if (s[i])
6396 ADVANCE_CHAR (s, len, i);
6397 break;
6399 case '\'':
6400 i = skip_single_quoted (s, len, ++i);
6401 break;
6403 case '"':
6404 i = skip_double_quoted ((char *)s, len, ++i);
6405 break;
6409 return (count == 0);
6412 /****************************************************************/
6413 /* */
6414 /* Functions to perform parameter expansion on a string */
6415 /* */
6416 /****************************************************************/
6418 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
6419 static WORD_DESC *
6420 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
6421 char *string;
6422 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
6424 int check_nullness, var_is_set, var_is_null, var_is_special;
6425 int want_substring, want_indir, want_patsub, want_casemod;
6426 char *name, *value, *temp, *temp1;
6427 WORD_DESC *tdesc, *ret;
6428 int t_index, sindex, c, tflag, modspec;
6429 intmax_t number;
6431 temp = temp1 = value = (char *)NULL;
6432 var_is_set = var_is_null = var_is_special = check_nullness = 0;
6433 want_substring = want_indir = want_patsub = want_casemod = 0;
6435 sindex = *indexp;
6436 t_index = ++sindex;
6437 /* ${#var} doesn't have any of the other parameter expansions on it. */
6438 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
6439 name = string_extract (string, &t_index, "}", SX_VARNAME);
6440 else
6441 #if defined (CASEMOD_EXPANSIONS)
6442 /* To enable case-toggling expansions using the `~' operator character
6443 change the 1 to 0. */
6444 # if defined (CASEMOD_CAPCASE)
6445 name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
6446 # else
6447 name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
6448 # endif /* CASEMOD_CAPCASE */
6449 #else
6450 name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
6451 #endif /* CASEMOD_EXPANSIONS */
6453 ret = 0;
6454 tflag = 0;
6456 /* If the name really consists of a special variable, then make sure
6457 that we have the entire name. We don't allow indirect references
6458 to special variables except `#', `?', `@' and `*'. */
6459 if ((sindex == t_index &&
6460 (string[t_index] == '-' ||
6461 string[t_index] == '?' ||
6462 string[t_index] == '#')) ||
6463 (sindex == t_index - 1 && string[sindex] == '!' &&
6464 (string[t_index] == '#' ||
6465 string[t_index] == '?' ||
6466 string[t_index] == '@' ||
6467 string[t_index] == '*')))
6469 t_index++;
6470 free (name);
6471 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
6472 name = (char *)xmalloc (3 + (strlen (temp1)));
6473 *name = string[sindex];
6474 if (string[sindex] == '!')
6476 /* indirect reference of $#, $?, $@, or $* */
6477 name[1] = string[sindex + 1];
6478 strcpy (name + 2, temp1);
6480 else
6481 strcpy (name + 1, temp1);
6482 free (temp1);
6484 sindex = t_index;
6486 /* Find out what character ended the variable name. Then
6487 do the appropriate thing. */
6488 if (c = string[sindex])
6489 sindex++;
6491 /* If c is followed by one of the valid parameter expansion
6492 characters, move past it as normal. If not, assume that
6493 a substring specification is being given, and do not move
6494 past it. */
6495 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
6497 check_nullness++;
6498 if (c = string[sindex])
6499 sindex++;
6501 else if (c == ':' && string[sindex] != RBRACE)
6502 want_substring = 1;
6503 else if (c == '/' && string[sindex] != RBRACE)
6504 want_patsub = 1;
6505 #if defined (CASEMOD_EXPANSIONS)
6506 else if (c == '^' || c == ',' || c == '~')
6508 modspec = c;
6509 want_casemod = 1;
6511 #endif
6513 /* Catch the valid and invalid brace expressions that made it through the
6514 tests above. */
6515 /* ${#-} is a valid expansion and means to take the length of $-.
6516 Similarly for ${#?} and ${##}... */
6517 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6518 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
6520 name = (char *)xrealloc (name, 3);
6521 name[1] = c;
6522 name[2] = '\0';
6523 c = string[sindex++];
6526 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
6527 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6528 member (c, "%:=+/") && string[sindex] == RBRACE)
6530 temp = (char *)NULL;
6531 goto bad_substitution;
6534 /* Indirect expansion begins with a `!'. A valid indirect expansion is
6535 either a variable name, one of the positional parameters or a special
6536 variable that expands to one of the positional parameters. */
6537 want_indir = *name == '!' &&
6538 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
6539 || VALID_INDIR_PARAM (name[1]));
6541 /* Determine the value of this variable. */
6543 /* Check for special variables, directly referenced. */
6544 if (SPECIAL_VAR (name, want_indir))
6545 var_is_special++;
6547 /* Check for special expansion things, like the length of a parameter */
6548 if (*name == '#' && name[1])
6550 /* If we are not pointing at the character just after the
6551 closing brace, then we haven't gotten all of the name.
6552 Since it begins with a special character, this is a bad
6553 substitution. Also check NAME for validity before trying
6554 to go on. */
6555 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
6557 temp = (char *)NULL;
6558 goto bad_substitution;
6561 number = parameter_brace_expand_length (name);
6562 free (name);
6564 *indexp = sindex;
6565 if (number < 0)
6566 return (&expand_wdesc_error);
6567 else
6569 ret = alloc_word_desc ();
6570 ret->word = itos (number);
6571 return ret;
6575 /* ${@} is identical to $@. */
6576 if (name[0] == '@' && name[1] == '\0')
6578 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6579 *quoted_dollar_atp = 1;
6581 if (contains_dollar_at)
6582 *contains_dollar_at = 1;
6585 /* Process ${!PREFIX*} expansion. */
6586 if (want_indir && string[sindex - 1] == RBRACE &&
6587 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
6588 legal_variable_starter ((unsigned char) name[1]))
6590 char **x;
6591 WORD_LIST *xlist;
6593 temp1 = savestring (name + 1);
6594 number = strlen (temp1);
6595 temp1[number - 1] = '\0';
6596 x = all_variables_matching_prefix (temp1);
6597 xlist = strvec_to_word_list (x, 0, 0);
6598 if (string[sindex - 2] == '*')
6599 temp = string_list_dollar_star (xlist);
6600 else
6602 temp = string_list_dollar_at (xlist, quoted);
6603 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6604 *quoted_dollar_atp = 1;
6605 if (contains_dollar_at)
6606 *contains_dollar_at = 1;
6608 free (x);
6609 free (xlist);
6610 free (temp1);
6611 *indexp = sindex;
6613 ret = alloc_word_desc ();
6614 ret->word = temp;
6615 return ret;
6618 #if defined (ARRAY_VARS)
6619 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
6620 if (want_indir && string[sindex - 1] == RBRACE &&
6621 string[sindex - 2] == ']' && valid_array_reference (name+1))
6623 char *x, *x1;
6625 temp1 = savestring (name + 1);
6626 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
6627 FREE (x);
6628 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
6630 temp = array_keys (temp1, quoted); /* handles assoc vars too */
6631 if (x1[0] == '@')
6633 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6634 *quoted_dollar_atp = 1;
6635 if (contains_dollar_at)
6636 *contains_dollar_at = 1;
6639 free (temp1);
6640 *indexp = sindex;
6642 ret = alloc_word_desc ();
6643 ret->word = temp;
6644 return ret;
6647 free (temp1);
6649 #endif /* ARRAY_VARS */
6651 /* Make sure that NAME is valid before trying to go on. */
6652 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
6653 var_is_special) == 0)
6655 temp = (char *)NULL;
6656 goto bad_substitution;
6659 if (want_indir)
6660 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6661 else
6662 tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
6664 if (tdesc)
6666 temp = tdesc->word;
6667 tflag = tdesc->flags;
6668 dispose_word_desc (tdesc);
6670 else
6671 temp = (char *)0;
6673 #if defined (ARRAY_VARS)
6674 if (valid_array_reference (name))
6675 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6676 #endif
6678 var_is_set = temp != (char *)0;
6679 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6681 /* Get the rest of the stuff inside the braces. */
6682 if (c && c != RBRACE)
6684 /* Extract the contents of the ${ ... } expansion
6685 according to the Posix.2 rules. */
6686 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6687 if (string[sindex] == RBRACE)
6688 sindex++;
6689 else
6690 goto bad_substitution;
6692 else
6693 value = (char *)NULL;
6695 *indexp = sindex;
6697 /* If this is a substring spec, process it and add the result. */
6698 if (want_substring)
6700 temp1 = parameter_brace_substring (name, temp, value, quoted);
6701 FREE (name);
6702 FREE (value);
6703 FREE (temp);
6705 if (temp1 == &expand_param_error)
6706 return (&expand_wdesc_error);
6707 else if (temp1 == &expand_param_fatal)
6708 return (&expand_wdesc_fatal);
6710 ret = alloc_word_desc ();
6711 ret->word = temp1;
6712 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6713 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6714 return ret;
6716 else if (want_patsub)
6718 temp1 = parameter_brace_patsub (name, temp, value, quoted);
6719 FREE (name);
6720 FREE (value);
6721 FREE (temp);
6723 if (temp1 == &expand_param_error)
6724 return (&expand_wdesc_error);
6725 else if (temp1 == &expand_param_fatal)
6726 return (&expand_wdesc_fatal);
6728 ret = alloc_word_desc ();
6729 ret->word = temp1;
6730 ret = alloc_word_desc ();
6731 ret->word = temp1;
6732 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6733 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6734 return ret;
6736 #if defined (CASEMOD_EXPANSIONS)
6737 else if (want_casemod)
6739 temp1 = parameter_brace_casemod (name, temp, modspec, value, quoted);
6740 FREE (name);
6741 FREE (value);
6742 FREE (temp);
6744 if (temp1 == &expand_param_error)
6745 return (&expand_wdesc_error);
6746 else if (temp1 == &expand_param_fatal)
6747 return (&expand_wdesc_fatal);
6749 ret = alloc_word_desc ();
6750 ret->word = temp1;
6751 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6752 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6753 return ret;
6755 #endif
6757 /* Do the right thing based on which character ended the variable name. */
6758 switch (c)
6760 default:
6761 case '\0':
6762 bad_substitution:
6763 report_error (_("%s: bad substitution"), string ? string : "??");
6764 FREE (value);
6765 FREE (temp);
6766 free (name);
6767 return &expand_wdesc_error;
6769 case RBRACE:
6770 if (var_is_set == 0 && unbound_vars_is_error)
6772 err_unboundvar (name);
6773 FREE (value);
6774 FREE (temp);
6775 free (name);
6776 last_command_exit_value = EXECUTION_FAILURE;
6777 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6779 break;
6781 case '#': /* ${param#[#]pattern} */
6782 case '%': /* ${param%[%]pattern} */
6783 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6785 FREE (value);
6786 break;
6788 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6789 free (temp);
6790 free (value);
6792 ret = alloc_word_desc ();
6793 ret->word = temp1;
6794 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6795 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6796 return ret;
6798 case '-':
6799 case '=':
6800 case '?':
6801 case '+':
6802 if (var_is_set && var_is_null == 0)
6804 /* If the operator is `+', we don't want the value of the named
6805 variable for anything, just the value of the right hand side. */
6807 if (c == '+')
6809 /* XXX -- if we're double-quoted and the named variable is "$@",
6810 we want to turn off any special handling of "$@" --
6811 we're not using it, so whatever is on the rhs applies. */
6812 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6813 *quoted_dollar_atp = 0;
6814 if (contains_dollar_at)
6815 *contains_dollar_at = 0;
6817 FREE (temp);
6818 if (value)
6820 ret = parameter_brace_expand_rhs (name, value, c,
6821 quoted,
6822 quoted_dollar_atp,
6823 contains_dollar_at);
6824 /* XXX - fix up later, esp. noting presence of
6825 W_HASQUOTEDNULL in ret->flags */
6826 free (value);
6828 else
6829 temp = (char *)NULL;
6831 else
6833 FREE (value);
6835 /* Otherwise do nothing; just use the value in TEMP. */
6837 else /* VAR not set or VAR is NULL. */
6839 FREE (temp);
6840 temp = (char *)NULL;
6841 if (c == '=' && var_is_special)
6843 report_error (_("$%s: cannot assign in this way"), name);
6844 free (name);
6845 free (value);
6846 return &expand_wdesc_error;
6848 else if (c == '?')
6850 parameter_brace_expand_error (name, value);
6851 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6853 else if (c != '+')
6855 /* XXX -- if we're double-quoted and the named variable is "$@",
6856 we want to turn off any special handling of "$@" --
6857 we're not using it, so whatever is on the rhs applies. */
6858 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6859 *quoted_dollar_atp = 0;
6860 if (contains_dollar_at)
6861 *contains_dollar_at = 0;
6863 ret = parameter_brace_expand_rhs (name, value, c, quoted,
6864 quoted_dollar_atp,
6865 contains_dollar_at);
6866 /* XXX - fix up later, esp. noting presence of
6867 W_HASQUOTEDNULL in tdesc->flags */
6869 free (value);
6872 break;
6874 free (name);
6876 if (ret == 0)
6878 ret = alloc_word_desc ();
6879 ret->flags = tflag;
6880 ret->word = temp;
6882 return (ret);
6885 /* Expand a single ${xxx} expansion. The braces are optional. When
6886 the braces are used, parameter_brace_expand() does the work,
6887 possibly calling param_expand recursively. */
6888 static WORD_DESC *
6889 param_expand (string, sindex, quoted, expanded_something,
6890 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6891 pflags)
6892 char *string;
6893 int *sindex, quoted, *expanded_something, *contains_dollar_at;
6894 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6896 char *temp, *temp1, uerror[3];
6897 int zindex, t_index, expok;
6898 unsigned char c;
6899 intmax_t number;
6900 SHELL_VAR *var;
6901 WORD_LIST *list;
6902 WORD_DESC *tdesc, *ret;
6903 int tflag;
6905 zindex = *sindex;
6906 c = string[++zindex];
6908 temp = (char *)NULL;
6909 ret = tdesc = (WORD_DESC *)NULL;
6910 tflag = 0;
6912 /* Do simple cases first. Switch on what follows '$'. */
6913 switch (c)
6915 /* $0 .. $9? */
6916 case '0':
6917 case '1':
6918 case '2':
6919 case '3':
6920 case '4':
6921 case '5':
6922 case '6':
6923 case '7':
6924 case '8':
6925 case '9':
6926 temp1 = dollar_vars[TODIGIT (c)];
6927 if (unbound_vars_is_error && temp1 == (char *)NULL)
6929 uerror[0] = '$';
6930 uerror[1] = c;
6931 uerror[2] = '\0';
6932 err_unboundvar (uerror);
6933 last_command_exit_value = EXECUTION_FAILURE;
6934 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6936 if (temp1)
6937 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6938 ? quote_string (temp1)
6939 : quote_escapes (temp1);
6940 else
6941 temp = (char *)NULL;
6943 break;
6945 /* $$ -- pid of the invoking shell. */
6946 case '$':
6947 temp = itos (dollar_dollar_pid);
6948 break;
6950 /* $# -- number of positional parameters. */
6951 case '#':
6952 temp = itos (number_of_args ());
6953 break;
6955 /* $? -- return value of the last synchronous command. */
6956 case '?':
6957 temp = itos (last_command_exit_value);
6958 break;
6960 /* $- -- flags supplied to the shell on invocation or by `set'. */
6961 case '-':
6962 temp = which_set_flags ();
6963 break;
6965 /* $! -- Pid of the last asynchronous command. */
6966 case '!':
6967 /* If no asynchronous pids have been created, expand to nothing.
6968 If `set -u' has been executed, and no async processes have
6969 been created, this is an expansion error. */
6970 if (last_asynchronous_pid == NO_PID)
6972 if (expanded_something)
6973 *expanded_something = 0;
6974 temp = (char *)NULL;
6975 if (unbound_vars_is_error)
6977 uerror[0] = '$';
6978 uerror[1] = c;
6979 uerror[2] = '\0';
6980 err_unboundvar (uerror);
6981 last_command_exit_value = EXECUTION_FAILURE;
6982 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6985 else
6986 temp = itos (last_asynchronous_pid);
6987 break;
6989 /* The only difference between this and $@ is when the arg is quoted. */
6990 case '*': /* `$*' */
6991 list = list_rest_of_args ();
6993 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
6995 uerror[0] = '$';
6996 uerror[1] = '*';
6997 uerror[2] = '\0';
6998 err_unboundvar (uerror);
6999 last_command_exit_value = EXECUTION_FAILURE;
7000 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7003 /* If there are no command-line arguments, this should just
7004 disappear if there are other characters in the expansion,
7005 even if it's quoted. */
7006 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7007 temp = (char *)NULL;
7008 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7010 /* If we have "$*" we want to make a string of the positional
7011 parameters, separated by the first character of $IFS, and
7012 quote the whole string, including the separators. If IFS
7013 is unset, the parameters are separated by ' '; if $IFS is
7014 null, the parameters are concatenated. */
7015 temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
7016 temp1 = quote_string (temp);
7017 if (*temp == 0)
7018 tflag |= W_HASQUOTEDNULL;
7019 free (temp);
7020 temp = temp1;
7022 else
7024 /* We check whether or not we're eventually going to split $* here,
7025 for example when IFS is empty and we are processing the rhs of
7026 an assignment statement. In that case, we don't separate the
7027 arguments at all. Otherwise, if the $* is not quoted it is
7028 identical to $@ */
7029 #if 1
7030 # if defined (HANDLE_MULTIBYTE)
7031 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7032 # else
7033 if (expand_no_split_dollar_star && ifs_firstc == 0)
7034 # endif
7035 temp = string_list_dollar_star (list);
7036 else
7037 temp = string_list_dollar_at (list, quoted);
7038 #else
7039 temp = string_list_dollar_at (list, quoted);
7040 #endif
7041 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7042 *contains_dollar_at = 1;
7045 dispose_words (list);
7046 break;
7048 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7049 means that we have to turn quoting off after we split into
7050 the individually quoted arguments so that the final split
7051 on the first character of $IFS is still done. */
7052 case '@': /* `$@' */
7053 list = list_rest_of_args ();
7055 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7057 uerror[0] = '$';
7058 uerror[1] = '@';
7059 uerror[2] = '\0';
7060 err_unboundvar (uerror);
7061 last_command_exit_value = EXECUTION_FAILURE;
7062 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7065 /* We want to flag the fact that we saw this. We can't turn
7066 off quoting entirely, because other characters in the
7067 string might need it (consider "\"$@\""), but we need some
7068 way to signal that the final split on the first character
7069 of $IFS should be done, even though QUOTED is 1. */
7070 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7071 *quoted_dollar_at_p = 1;
7072 if (contains_dollar_at)
7073 *contains_dollar_at = 1;
7075 /* We want to separate the positional parameters with the first
7076 character of $IFS in case $IFS is something other than a space.
7077 We also want to make sure that splitting is done no matter what --
7078 according to POSIX.2, this expands to a list of the positional
7079 parameters no matter what IFS is set to. */
7080 temp = string_list_dollar_at (list, quoted);
7082 dispose_words (list);
7083 break;
7085 case LBRACE:
7086 tdesc = parameter_brace_expand (string, &zindex, quoted,
7087 quoted_dollar_at_p,
7088 contains_dollar_at);
7090 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7091 return (tdesc);
7092 temp = tdesc ? tdesc->word : (char *)0;
7094 /* XXX */
7095 /* Quoted nulls should be removed if there is anything else
7096 in the string. */
7097 /* Note that we saw the quoted null so we can add one back at
7098 the end of this function if there are no other characters
7099 in the string, discard TEMP, and go on. The exception to
7100 this is when we have "${@}" and $1 is '', since $@ needs
7101 special handling. */
7102 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7104 if (had_quoted_null_p)
7105 *had_quoted_null_p = 1;
7106 if (*quoted_dollar_at_p == 0)
7108 free (temp);
7109 tdesc->word = temp = (char *)NULL;
7114 ret = tdesc;
7115 goto return0;
7117 /* Do command or arithmetic substitution. */
7118 case LPAREN:
7119 /* We have to extract the contents of this paren substitution. */
7120 t_index = zindex + 1;
7121 temp = extract_command_subst (string, &t_index, 0);
7122 zindex = t_index;
7124 /* For Posix.2-style `$(( ))' arithmetic substitution,
7125 extract the expression and pass it to the evaluator. */
7126 if (temp && *temp == LPAREN)
7128 char *temp2;
7129 temp1 = temp + 1;
7130 temp2 = savestring (temp1);
7131 t_index = strlen (temp2) - 1;
7133 if (temp2[t_index] != RPAREN)
7135 free (temp2);
7136 goto comsub;
7139 /* Cut off ending `)' */
7140 temp2[t_index] = '\0';
7142 if (chk_arithsub (temp2, t_index) == 0)
7144 free (temp2);
7145 goto comsub;
7148 /* Expand variables found inside the expression. */
7149 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7150 free (temp2);
7152 arithsub:
7153 /* No error messages. */
7154 this_command_name = (char *)NULL;
7155 number = evalexp (temp1, &expok);
7156 free (temp);
7157 free (temp1);
7158 if (expok == 0)
7160 if (interactive_shell == 0 && posixly_correct)
7162 last_command_exit_value = EXECUTION_FAILURE;
7163 return (&expand_wdesc_fatal);
7165 else
7166 return (&expand_wdesc_error);
7168 temp = itos (number);
7169 break;
7172 comsub:
7173 if (pflags & PF_NOCOMSUB)
7174 /* we need zindex+1 because string[zindex] == RPAREN */
7175 temp1 = substring (string, *sindex, zindex+1);
7176 else
7178 tdesc = command_substitute (temp, quoted);
7179 temp1 = tdesc ? tdesc->word : (char *)NULL;
7180 if (tdesc)
7181 dispose_word_desc (tdesc);
7183 FREE (temp);
7184 temp = temp1;
7185 break;
7187 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7188 away in a future bash release. */
7189 case '[':
7190 /* Extract the contents of this arithmetic substitution. */
7191 t_index = zindex + 1;
7192 temp = extract_arithmetic_subst (string, &t_index);
7193 zindex = t_index;
7194 if (temp == 0)
7196 temp = savestring (string);
7197 if (expanded_something)
7198 *expanded_something = 0;
7199 goto return0;
7202 /* Do initial variable expansion. */
7203 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7205 goto arithsub;
7207 default:
7208 /* Find the variable in VARIABLE_LIST. */
7209 temp = (char *)NULL;
7211 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7213 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7215 /* If this isn't a variable name, then just output the `$'. */
7216 if (temp1 == 0 || *temp1 == '\0')
7218 FREE (temp1);
7219 temp = (char *)xmalloc (2);
7220 temp[0] = '$';
7221 temp[1] = '\0';
7222 if (expanded_something)
7223 *expanded_something = 0;
7224 goto return0;
7227 /* If the variable exists, return its value cell. */
7228 var = find_variable (temp1);
7230 if (var && invisible_p (var) == 0 && var_isset (var))
7232 #if defined (ARRAY_VARS)
7233 if (assoc_p (var) || array_p (var))
7235 temp = array_p (var) ? array_reference (array_cell (var), 0)
7236 : assoc_reference (assoc_cell (var), "0");
7237 if (temp)
7238 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7239 ? quote_string (temp)
7240 : quote_escapes (temp);
7241 else if (unbound_vars_is_error)
7242 goto unbound_variable;
7244 else
7245 #endif
7247 temp = value_cell (var);
7249 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7250 ? quote_string (temp)
7251 : quote_escapes (temp);
7254 free (temp1);
7256 goto return0;
7259 temp = (char *)NULL;
7261 unbound_variable:
7262 if (unbound_vars_is_error)
7263 err_unboundvar (temp1);
7264 else
7266 free (temp1);
7267 goto return0;
7270 free (temp1);
7271 last_command_exit_value = EXECUTION_FAILURE;
7272 return ((unbound_vars_is_error && interactive_shell == 0)
7273 ? &expand_wdesc_fatal
7274 : &expand_wdesc_error);
7277 if (string[zindex])
7278 zindex++;
7280 return0:
7281 *sindex = zindex;
7283 if (ret == 0)
7285 ret = alloc_word_desc ();
7286 ret->flags = tflag; /* XXX */
7287 ret->word = temp;
7289 return ret;
7292 /* Make a word list which is the result of parameter and variable
7293 expansion, command substitution, arithmetic substitution, and
7294 quote removal of WORD. Return a pointer to a WORD_LIST which is
7295 the result of the expansion. If WORD contains a null word, the
7296 word list returned is also null.
7298 QUOTED contains flag values defined in shell.h.
7300 ISEXP is used to tell expand_word_internal that the word should be
7301 treated as the result of an expansion. This has implications for
7302 how IFS characters in the word are treated.
7304 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7305 they point to an integer value which receives information about expansion.
7306 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7307 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7308 else zero.
7310 This only does word splitting in the case of $@ expansion. In that
7311 case, we split on ' '. */
7313 /* Values for the local variable quoted_state. */
7314 #define UNQUOTED 0
7315 #define PARTIALLY_QUOTED 1
7316 #define WHOLLY_QUOTED 2
7318 static WORD_LIST *
7319 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7320 WORD_DESC *word;
7321 int quoted, isexp;
7322 int *contains_dollar_at;
7323 int *expanded_something;
7325 WORD_LIST *list;
7326 WORD_DESC *tword;
7328 /* The intermediate string that we build while expanding. */
7329 char *istring;
7331 /* The current size of the above object. */
7332 int istring_size;
7334 /* Index into ISTRING. */
7335 int istring_index;
7337 /* Temporary string storage. */
7338 char *temp, *temp1;
7340 /* The text of WORD. */
7341 register char *string;
7343 /* The size of STRING. */
7344 size_t string_size;
7346 /* The index into STRING. */
7347 int sindex;
7349 /* This gets 1 if we see a $@ while quoted. */
7350 int quoted_dollar_at;
7352 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7353 whether WORD contains no quoting characters, a partially quoted
7354 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7355 int quoted_state;
7357 /* State flags */
7358 int had_quoted_null;
7359 int has_dollar_at;
7360 int tflag;
7362 int assignoff; /* If assignment, offset of `=' */
7364 register unsigned char c; /* Current character. */
7365 int t_index; /* For calls to string_extract_xxx. */
7367 char twochars[2];
7369 DECLARE_MBSTATE;
7371 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7372 istring[istring_index = 0] = '\0';
7373 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7374 quoted_state = UNQUOTED;
7376 string = word->word;
7377 if (string == 0)
7378 goto finished_with_string;
7379 /* Don't need the string length for the SADD... and COPY_ macros unless
7380 multibyte characters are possible. */
7381 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7383 if (contains_dollar_at)
7384 *contains_dollar_at = 0;
7386 assignoff = -1;
7388 /* Begin the expansion. */
7390 for (sindex = 0; ;)
7392 c = string[sindex];
7394 /* Case on toplevel character. */
7395 switch (c)
7397 case '\0':
7398 goto finished_with_string;
7400 case CTLESC:
7401 sindex++;
7402 #if HANDLE_MULTIBYTE
7403 if (MB_CUR_MAX > 1 && string[sindex])
7405 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7407 else
7408 #endif
7410 temp = (char *)xmalloc (3);
7411 temp[0] = CTLESC;
7412 temp[1] = c = string[sindex];
7413 temp[2] = '\0';
7416 dollar_add_string:
7417 if (string[sindex])
7418 sindex++;
7420 add_string:
7421 if (temp)
7423 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7424 temp = (char *)0;
7427 break;
7429 #if defined (PROCESS_SUBSTITUTION)
7430 /* Process substitution. */
7431 case '<':
7432 case '>':
7434 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7436 sindex--; /* add_character: label increments sindex */
7437 goto add_character;
7439 else
7440 t_index = sindex + 1; /* skip past both '<' and LPAREN */
7442 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7443 sindex = t_index;
7445 /* If the process substitution specification is `<()', we want to
7446 open the pipe for writing in the child and produce output; if
7447 it is `>()', we want to open the pipe for reading in the child
7448 and consume input. */
7449 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
7451 FREE (temp1);
7453 goto dollar_add_string;
7455 #endif /* PROCESS_SUBSTITUTION */
7457 case '=':
7458 /* Posix.2 section 3.6.1 says that tildes following `=' in words
7459 which are not assignment statements are not expanded. If the
7460 shell isn't in posix mode, though, we perform tilde expansion
7461 on `likely candidate' unquoted assignment statements (flags
7462 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
7463 contains an unquoted :~ or =~. Something to think about: we
7464 now have a flag that says to perform tilde expansion on arguments
7465 to `assignment builtins' like declare and export that look like
7466 assignment statements. We now do tilde expansion on such words
7467 even in POSIX mode. */
7468 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
7470 if (isexp == 0 && isifs (c))
7471 goto add_ifs_character;
7472 else
7473 goto add_character;
7475 /* If we're not in posix mode or forcing assignment-statement tilde
7476 expansion, note where the `=' appears in the word and prepare to
7477 do tilde expansion following the first `='. */
7478 if ((word->flags & W_ASSIGNMENT) &&
7479 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7480 assignoff == -1 && sindex > 0)
7481 assignoff = sindex;
7482 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
7483 word->flags |= W_ITILDE;
7484 #if 0
7485 else if ((word->flags & W_ASSIGNMENT) &&
7486 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7487 string[sindex+1] == '~')
7488 word->flags |= W_ITILDE;
7489 #endif
7490 if (isexp == 0 && isifs (c))
7491 goto add_ifs_character;
7492 else
7493 goto add_character;
7495 case ':':
7496 if (word->flags & W_NOTILDE)
7498 if (isexp == 0 && isifs (c))
7499 goto add_ifs_character;
7500 else
7501 goto add_character;
7504 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
7505 string[sindex+1] == '~')
7506 word->flags |= W_ITILDE;
7508 if (isexp == 0 && isifs (c))
7509 goto add_ifs_character;
7510 else
7511 goto add_character;
7513 case '~':
7514 /* If the word isn't supposed to be tilde expanded, or we're not
7515 at the start of a word or after an unquoted : or = in an
7516 assignment statement, we don't do tilde expansion. */
7517 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
7518 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
7519 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7521 word->flags &= ~W_ITILDE;
7522 if (isexp == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
7523 goto add_ifs_character;
7524 else
7525 goto add_character;
7528 if (word->flags & W_ASSIGNRHS)
7529 tflag = 2;
7530 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
7531 tflag = 1;
7532 else
7533 tflag = 0;
7535 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
7537 word->flags &= ~W_ITILDE;
7539 if (temp && *temp && t_index > 0)
7541 temp1 = bash_tilde_expand (temp, tflag);
7542 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
7544 FREE (temp);
7545 FREE (temp1);
7546 goto add_character; /* tilde expansion failed */
7548 free (temp);
7549 temp = temp1;
7550 sindex += t_index;
7551 goto add_quoted_string; /* XXX was add_string */
7553 else
7555 FREE (temp);
7556 goto add_character;
7559 case '$':
7560 if (expanded_something)
7561 *expanded_something = 1;
7563 has_dollar_at = 0;
7564 tword = param_expand (string, &sindex, quoted, expanded_something,
7565 &has_dollar_at, &quoted_dollar_at,
7566 &had_quoted_null,
7567 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
7569 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
7571 free (string);
7572 free (istring);
7573 return ((tword == &expand_wdesc_error) ? &expand_word_error
7574 : &expand_word_fatal);
7576 if (contains_dollar_at && has_dollar_at)
7577 *contains_dollar_at = 1;
7579 if (tword && (tword->flags & W_HASQUOTEDNULL))
7580 had_quoted_null = 1;
7582 temp = tword->word;
7583 dispose_word_desc (tword);
7585 goto add_string;
7586 break;
7588 case '`': /* Backquoted command substitution. */
7590 t_index = sindex++;
7592 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
7593 /* The test of sindex against t_index is to allow bare instances of
7594 ` to pass through, for backwards compatibility. */
7595 if (temp == &extract_string_error || temp == &extract_string_fatal)
7597 if (sindex - 1 == t_index)
7599 sindex = t_index;
7600 goto add_character;
7602 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
7603 free (string);
7604 free (istring);
7605 return ((temp == &extract_string_error) ? &expand_word_error
7606 : &expand_word_fatal);
7609 if (expanded_something)
7610 *expanded_something = 1;
7612 if (word->flags & W_NOCOMSUB)
7613 /* sindex + 1 because string[sindex] == '`' */
7614 temp1 = substring (string, t_index, sindex + 1);
7615 else
7617 de_backslash (temp);
7618 tword = command_substitute (temp, quoted);
7619 temp1 = tword ? tword->word : (char *)NULL;
7620 if (tword)
7621 dispose_word_desc (tword);
7623 FREE (temp);
7624 temp = temp1;
7625 goto dollar_add_string;
7628 case '\\':
7629 if (string[sindex + 1] == '\n')
7631 sindex += 2;
7632 continue;
7635 c = string[++sindex];
7637 if (quoted & Q_HERE_DOCUMENT)
7638 tflag = CBSHDOC;
7639 else if (quoted & Q_DOUBLE_QUOTES)
7640 tflag = CBSDQUOTE;
7641 else
7642 tflag = 0;
7644 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7646 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7648 else if (c == 0)
7650 c = CTLNUL;
7651 sindex--; /* add_character: label increments sindex */
7652 goto add_character;
7654 else
7656 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7659 sindex++;
7660 add_twochars:
7661 /* BEFORE jumping here, we need to increment sindex if appropriate */
7662 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7663 DEFAULT_ARRAY_SIZE);
7664 istring[istring_index++] = twochars[0];
7665 istring[istring_index++] = twochars[1];
7666 istring[istring_index] = '\0';
7668 break;
7670 case '"':
7671 #if 0
7672 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7673 #else
7674 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7675 #endif
7676 goto add_character;
7678 t_index = ++sindex;
7679 temp = string_extract_double_quoted (string, &sindex, 0);
7681 /* If the quotes surrounded the entire string, then the
7682 whole word was quoted. */
7683 quoted_state = (t_index == 1 && string[sindex] == '\0')
7684 ? WHOLLY_QUOTED
7685 : PARTIALLY_QUOTED;
7687 if (temp && *temp)
7689 tword = alloc_word_desc ();
7690 tword->word = temp;
7692 temp = (char *)NULL;
7694 has_dollar_at = 0;
7695 /* Need to get W_HASQUOTEDNULL flag through this function. */
7696 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7698 if (list == &expand_word_error || list == &expand_word_fatal)
7700 free (istring);
7701 free (string);
7702 /* expand_word_internal has already freed temp_word->word
7703 for us because of the way it prints error messages. */
7704 tword->word = (char *)NULL;
7705 dispose_word (tword);
7706 return list;
7709 dispose_word (tword);
7711 /* "$@" (a double-quoted dollar-at) expands into nothing,
7712 not even a NULL word, when there are no positional
7713 parameters. */
7714 if (list == 0 && has_dollar_at)
7716 quoted_dollar_at++;
7717 break;
7720 /* If we get "$@", we know we have expanded something, so we
7721 need to remember it for the final split on $IFS. This is
7722 a special case; it's the only case where a quoted string
7723 can expand into more than one word. It's going to come back
7724 from the above call to expand_word_internal as a list with
7725 a single word, in which all characters are quoted and
7726 separated by blanks. What we want to do is to turn it back
7727 into a list for the next piece of code. */
7728 if (list)
7729 dequote_list (list);
7731 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7732 had_quoted_null = 1;
7734 if (has_dollar_at)
7736 quoted_dollar_at++;
7737 if (contains_dollar_at)
7738 *contains_dollar_at = 1;
7739 if (expanded_something)
7740 *expanded_something = 1;
7743 else
7745 /* What we have is "". This is a minor optimization. */
7746 FREE (temp);
7747 list = (WORD_LIST *)NULL;
7750 /* The code above *might* return a list (consider the case of "$@",
7751 where it returns "$1", "$2", etc.). We can't throw away the
7752 rest of the list, and we have to make sure each word gets added
7753 as quoted. We test on tresult->next: if it is non-NULL, we
7754 quote the whole list, save it to a string with string_list, and
7755 add that string. We don't need to quote the results of this
7756 (and it would be wrong, since that would quote the separators
7757 as well), so we go directly to add_string. */
7758 if (list)
7760 if (list->next)
7762 /* Testing quoted_dollar_at makes sure that "$@" is
7763 split correctly when $IFS does not contain a space. */
7764 temp = quoted_dollar_at
7765 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7766 : string_list (quote_list (list));
7767 dispose_words (list);
7768 goto add_string;
7770 else
7772 temp = savestring (list->word->word);
7773 tflag = list->word->flags;
7774 dispose_words (list);
7776 /* If the string is not a quoted null string, we want
7777 to remove any embedded unquoted CTLNUL characters.
7778 We do not want to turn quoted null strings back into
7779 the empty string, though. We do this because we
7780 want to remove any quoted nulls from expansions that
7781 contain other characters. For example, if we have
7782 x"$*"y or "x$*y" and there are no positional parameters,
7783 the $* should expand into nothing. */
7784 /* We use the W_HASQUOTEDNULL flag to differentiate the
7785 cases: a quoted null character as above and when
7786 CTLNUL is contained in the (non-null) expansion
7787 of some variable. We use the had_quoted_null flag to
7788 pass the value through this function to its caller. */
7789 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7790 remove_quoted_nulls (temp); /* XXX */
7793 else
7794 temp = (char *)NULL;
7796 /* We do not want to add quoted nulls to strings that are only
7797 partially quoted; we can throw them away. */
7798 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7799 continue;
7801 add_quoted_string:
7803 if (temp)
7805 temp1 = temp;
7806 temp = quote_string (temp);
7807 free (temp1);
7808 goto add_string;
7810 else
7812 /* Add NULL arg. */
7813 c = CTLNUL;
7814 sindex--; /* add_character: label increments sindex */
7815 goto add_character;
7818 /* break; */
7820 case '\'':
7821 #if 0
7822 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7823 #else
7824 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7825 #endif
7826 goto add_character;
7828 t_index = ++sindex;
7829 temp = string_extract_single_quoted (string, &sindex);
7831 /* If the entire STRING was surrounded by single quotes,
7832 then the string is wholly quoted. */
7833 quoted_state = (t_index == 1 && string[sindex] == '\0')
7834 ? WHOLLY_QUOTED
7835 : PARTIALLY_QUOTED;
7837 /* If all we had was '', it is a null expansion. */
7838 if (*temp == '\0')
7840 free (temp);
7841 temp = (char *)NULL;
7843 else
7844 remove_quoted_escapes (temp); /* ??? */
7846 /* We do not want to add quoted nulls to strings that are only
7847 partially quoted; such nulls are discarded. */
7848 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7849 continue;
7851 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7852 if (temp == 0)
7854 c = CTLNUL;
7855 sindex--; /* add_character: label increments sindex */
7856 goto add_character;
7858 else
7859 goto add_quoted_string;
7861 /* break; */
7863 default:
7864 /* This is the fix for " $@ " */
7865 add_ifs_character:
7866 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7868 if (string[sindex]) /* from old goto dollar_add_string */
7869 sindex++;
7870 if (c == 0)
7872 c = CTLNUL;
7873 goto add_character;
7875 else
7877 #if HANDLE_MULTIBYTE
7878 if (MB_CUR_MAX > 1)
7879 sindex--;
7881 if (MB_CUR_MAX > 1)
7883 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7885 else
7886 #endif
7888 twochars[0] = CTLESC;
7889 twochars[1] = c;
7890 goto add_twochars;
7895 SADD_MBCHAR (temp, string, sindex, string_size);
7897 add_character:
7898 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7899 DEFAULT_ARRAY_SIZE);
7900 istring[istring_index++] = c;
7901 istring[istring_index] = '\0';
7903 /* Next character. */
7904 sindex++;
7908 finished_with_string:
7909 /* OK, we're ready to return. If we have a quoted string, and
7910 quoted_dollar_at is not set, we do no splitting at all; otherwise
7911 we split on ' '. The routines that call this will handle what to
7912 do if nothing has been expanded. */
7914 /* Partially and wholly quoted strings which expand to the empty
7915 string are retained as an empty arguments. Unquoted strings
7916 which expand to the empty string are discarded. The single
7917 exception is the case of expanding "$@" when there are no
7918 positional parameters. In that case, we discard the expansion. */
7920 /* Because of how the code that handles "" and '' in partially
7921 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7922 if we saw quoting characters, but the expansion was empty.
7923 "" and '' are tossed away before we get to this point when
7924 processing partially quoted strings. This makes "" and $xxx""
7925 equivalent when xxx is unset. We also look to see whether we
7926 saw a quoted null from a ${} expansion and add one back if we
7927 need to. */
7929 /* If we expand to nothing and there were no single or double quotes
7930 in the word, we throw it away. Otherwise, we return a NULL word.
7931 The single exception is for $@ surrounded by double quotes when
7932 there are no positional parameters. In that case, we also throw
7933 the word away. */
7935 if (*istring == '\0')
7937 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7939 istring[0] = CTLNUL;
7940 istring[1] = '\0';
7941 tword = make_bare_word (istring);
7942 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7943 list = make_word_list (tword, (WORD_LIST *)NULL);
7944 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7945 tword->flags |= W_QUOTED;
7947 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7948 and a double-quoted "$@" appears anywhere in it, then the entire
7949 word is removed. */
7950 else if (quoted_state == UNQUOTED || quoted_dollar_at)
7951 list = (WORD_LIST *)NULL;
7952 #if 0
7953 else
7955 tword = make_bare_word (istring);
7956 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7957 tword->flags |= W_QUOTED;
7958 list = make_word_list (tword, (WORD_LIST *)NULL);
7960 #else
7961 else
7962 list = (WORD_LIST *)NULL;
7963 #endif
7965 else if (word->flags & W_NOSPLIT)
7967 tword = make_bare_word (istring);
7968 if (word->flags & W_ASSIGNMENT)
7969 tword->flags |= W_ASSIGNMENT; /* XXX */
7970 if (word->flags & W_COMPASSIGN)
7971 tword->flags |= W_COMPASSIGN; /* XXX */
7972 if (word->flags & W_NOGLOB)
7973 tword->flags |= W_NOGLOB; /* XXX */
7974 if (word->flags & W_NOEXPAND)
7975 tword->flags |= W_NOEXPAND; /* XXX */
7976 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7977 tword->flags |= W_QUOTED;
7978 if (had_quoted_null)
7979 tword->flags |= W_HASQUOTEDNULL;
7980 list = make_word_list (tword, (WORD_LIST *)NULL);
7982 else
7984 char *ifs_chars;
7986 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
7988 /* If we have $@, we need to split the results no matter what. If
7989 IFS is unset or NULL, string_list_dollar_at has separated the
7990 positional parameters with a space, so we split on space (we have
7991 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
7992 string_list_dollar_at has separated the positional parameters
7993 with the first character of $IFS, so we split on $IFS. */
7994 if (has_dollar_at && ifs_chars)
7995 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
7996 else
7998 tword = make_bare_word (istring);
7999 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8000 tword->flags |= W_QUOTED;
8001 if (word->flags & W_ASSIGNMENT)
8002 tword->flags |= W_ASSIGNMENT;
8003 if (word->flags & W_COMPASSIGN)
8004 tword->flags |= W_COMPASSIGN;
8005 if (word->flags & W_NOGLOB)
8006 tword->flags |= W_NOGLOB;
8007 if (word->flags & W_NOEXPAND)
8008 tword->flags |= W_NOEXPAND;
8009 if (had_quoted_null)
8010 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8011 list = make_word_list (tword, (WORD_LIST *)NULL);
8015 free (istring);
8016 return (list);
8019 /* **************************************************************** */
8020 /* */
8021 /* Functions for Quote Removal */
8022 /* */
8023 /* **************************************************************** */
8025 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
8026 backslash quoting rules for within double quotes or a here document. */
8027 char *
8028 string_quote_removal (string, quoted)
8029 char *string;
8030 int quoted;
8032 size_t slen;
8033 char *r, *result_string, *temp, *send;
8034 int sindex, tindex, dquote;
8035 unsigned char c;
8036 DECLARE_MBSTATE;
8038 /* The result can be no longer than the original string. */
8039 slen = strlen (string);
8040 send = string + slen;
8042 r = result_string = (char *)xmalloc (slen + 1);
8044 for (dquote = sindex = 0; c = string[sindex];)
8046 switch (c)
8048 case '\\':
8049 c = string[++sindex];
8050 if (c == 0)
8052 *r++ = '\\';
8053 break;
8055 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8056 *r++ = '\\';
8057 /* FALLTHROUGH */
8059 default:
8060 SCOPY_CHAR_M (r, string, send, sindex);
8061 break;
8063 case '\'':
8064 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8066 *r++ = c;
8067 sindex++;
8068 break;
8070 tindex = sindex + 1;
8071 temp = string_extract_single_quoted (string, &tindex);
8072 if (temp)
8074 strcpy (r, temp);
8075 r += strlen (r);
8076 free (temp);
8078 sindex = tindex;
8079 break;
8081 case '"':
8082 dquote = 1 - dquote;
8083 sindex++;
8084 break;
8087 *r = '\0';
8088 return (result_string);
8091 #if 0
8092 /* UNUSED */
8093 /* Perform quote removal on word WORD. This allocates and returns a new
8094 WORD_DESC *. */
8095 WORD_DESC *
8096 word_quote_removal (word, quoted)
8097 WORD_DESC *word;
8098 int quoted;
8100 WORD_DESC *w;
8101 char *t;
8103 t = string_quote_removal (word->word, quoted);
8104 w = alloc_word_desc ();
8105 w->word = t ? t : savestring ("");
8106 return (w);
8109 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8110 the members of the list are treated as if they are surrounded by
8111 double quotes. Return a new list, or NULL if LIST is NULL. */
8112 WORD_LIST *
8113 word_list_quote_removal (list, quoted)
8114 WORD_LIST *list;
8115 int quoted;
8117 WORD_LIST *result, *t, *tresult, *e;
8119 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8121 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8122 #if 0
8123 result = (WORD_LIST *) list_append (result, tresult);
8124 #else
8125 if (result == 0)
8126 result = e = tresult;
8127 else
8129 e->next = tresult;
8130 while (e->next)
8131 e = e->next;
8133 #endif
8135 return (result);
8137 #endif
8139 /*******************************************
8141 * Functions to perform word splitting *
8143 *******************************************/
8145 void
8146 setifs (v)
8147 SHELL_VAR *v;
8149 char *t;
8150 unsigned char uc;
8152 ifs_var = v;
8153 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8155 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8156 handle multibyte chars in IFS */
8157 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8158 for (t = ifs_value ; t && *t; t++)
8160 uc = *t;
8161 ifs_cmap[uc] = 1;
8164 #if defined (HANDLE_MULTIBYTE)
8165 if (ifs_value == 0)
8167 ifs_firstc[0] = '\0';
8168 ifs_firstc_len = 1;
8170 else
8172 size_t ifs_len;
8173 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8174 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8175 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8177 ifs_firstc[0] = ifs_value[0];
8178 ifs_firstc[1] = '\0';
8179 ifs_firstc_len = 1;
8181 else
8182 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8184 #else
8185 ifs_firstc = ifs_value ? *ifs_value : 0;
8186 #endif
8189 char *
8190 getifs ()
8192 return ifs_value;
8195 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8196 is not quoted. list_string () performs quote removal for us, even if we
8197 don't do any splitting. */
8198 WORD_LIST *
8199 word_split (w, ifs_chars)
8200 WORD_DESC *w;
8201 char *ifs_chars;
8203 WORD_LIST *result;
8205 if (w)
8207 char *xifs;
8209 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8210 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8212 else
8213 result = (WORD_LIST *)NULL;
8215 return (result);
8218 /* Perform word splitting on LIST and return the RESULT. It is possible
8219 to return (WORD_LIST *)NULL. */
8220 static WORD_LIST *
8221 word_list_split (list)
8222 WORD_LIST *list;
8224 WORD_LIST *result, *t, *tresult, *e;
8226 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8228 tresult = word_split (t->word, ifs_value);
8229 if (result == 0)
8230 result = e = tresult;
8231 else
8233 e->next = tresult;
8234 while (e->next)
8235 e = e->next;
8238 return (result);
8241 /**************************************************
8243 * Functions to expand an entire WORD_LIST *
8245 **************************************************/
8247 /* Do any word-expansion-specific cleanup and jump to top_level */
8248 static void
8249 exp_jump_to_top_level (v)
8250 int v;
8252 set_pipestatus_from_exit (last_command_exit_value);
8254 /* Cleanup code goes here. */
8255 expand_no_split_dollar_star = 0; /* XXX */
8256 expanding_redir = 0;
8257 assigning_in_environment = 0;
8259 if (parse_and_execute_level == 0)
8260 top_level_cleanup (); /* from sig.c */
8262 jump_to_top_level (v);
8265 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8266 ELIST, and set ELIST to the new list. */
8267 #define PREPEND_LIST(nlist, elist) \
8268 do { nlist->next = elist; elist = nlist; } while (0)
8270 /* Separate out any initial variable assignments from TLIST. If set -k has
8271 been executed, remove all assignment statements from TLIST. Initial
8272 variable assignments and other environment assignments are placed
8273 on SUBST_ASSIGN_VARLIST. */
8274 static WORD_LIST *
8275 separate_out_assignments (tlist)
8276 WORD_LIST *tlist;
8278 register WORD_LIST *vp, *lp;
8280 if (!tlist)
8281 return ((WORD_LIST *)NULL);
8283 if (subst_assign_varlist)
8284 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8286 subst_assign_varlist = (WORD_LIST *)NULL;
8287 vp = lp = tlist;
8289 /* Separate out variable assignments at the start of the command.
8290 Loop invariant: vp->next == lp
8291 Loop postcondition:
8292 lp = list of words left after assignment statements skipped
8293 tlist = original list of words
8295 while (lp && (lp->word->flags & W_ASSIGNMENT))
8297 vp = lp;
8298 lp = lp->next;
8301 /* If lp != tlist, we have some initial assignment statements.
8302 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8303 words and TLIST point to the remaining words. */
8304 if (lp != tlist)
8306 subst_assign_varlist = tlist;
8307 /* ASSERT(vp->next == lp); */
8308 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8309 tlist = lp; /* remainder of word list */
8312 /* vp == end of variable list */
8313 /* tlist == remainder of original word list without variable assignments */
8314 if (!tlist)
8315 /* All the words in tlist were assignment statements */
8316 return ((WORD_LIST *)NULL);
8318 /* ASSERT(tlist != NULL); */
8319 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8321 /* If the -k option is in effect, we need to go through the remaining
8322 words, separate out the assignment words, and place them on
8323 SUBST_ASSIGN_VARLIST. */
8324 if (place_keywords_in_env)
8326 WORD_LIST *tp; /* tp == running pointer into tlist */
8328 tp = tlist;
8329 lp = tlist->next;
8331 /* Loop Invariant: tp->next == lp */
8332 /* Loop postcondition: tlist == word list without assignment statements */
8333 while (lp)
8335 if (lp->word->flags & W_ASSIGNMENT)
8337 /* Found an assignment statement, add this word to end of
8338 subst_assign_varlist (vp). */
8339 if (!subst_assign_varlist)
8340 subst_assign_varlist = vp = lp;
8341 else
8343 vp->next = lp;
8344 vp = lp;
8347 /* Remove the word pointed to by LP from TLIST. */
8348 tp->next = lp->next;
8349 /* ASSERT(vp == lp); */
8350 lp->next = (WORD_LIST *)NULL;
8351 lp = tp->next;
8353 else
8355 tp = lp;
8356 lp = lp->next;
8360 return (tlist);
8363 #define WEXP_VARASSIGN 0x001
8364 #define WEXP_BRACEEXP 0x002
8365 #define WEXP_TILDEEXP 0x004
8366 #define WEXP_PARAMEXP 0x008
8367 #define WEXP_PATHEXP 0x010
8369 /* All of the expansions, including variable assignments at the start of
8370 the list. */
8371 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8373 /* All of the expansions except variable assignments at the start of
8374 the list. */
8375 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8377 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8378 expansion, command substitution, arithmetic expansion, word splitting, and
8379 quote removal. */
8380 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8382 /* Take the list of words in LIST and do the various substitutions. Return
8383 a new list of words which is the expanded list, and without things like
8384 variable assignments. */
8386 WORD_LIST *
8387 expand_words (list)
8388 WORD_LIST *list;
8390 return (expand_word_list_internal (list, WEXP_ALL));
8393 /* Same as expand_words (), but doesn't hack variable or environment
8394 variables. */
8395 WORD_LIST *
8396 expand_words_no_vars (list)
8397 WORD_LIST *list;
8399 return (expand_word_list_internal (list, WEXP_NOVARS));
8402 WORD_LIST *
8403 expand_words_shellexp (list)
8404 WORD_LIST *list;
8406 return (expand_word_list_internal (list, WEXP_SHELLEXP));
8409 static WORD_LIST *
8410 glob_expand_word_list (tlist, eflags)
8411 WORD_LIST *tlist;
8412 int eflags;
8414 char **glob_array, *temp_string;
8415 register int glob_index;
8416 WORD_LIST *glob_list, *output_list, *disposables, *next;
8417 WORD_DESC *tword;
8419 output_list = disposables = (WORD_LIST *)NULL;
8420 glob_array = (char **)NULL;
8421 while (tlist)
8423 /* For each word, either globbing is attempted or the word is
8424 added to orig_list. If globbing succeeds, the results are
8425 added to orig_list and the word (tlist) is added to the list
8426 of disposable words. If globbing fails and failed glob
8427 expansions are left unchanged (the shell default), the
8428 original word is added to orig_list. If globbing fails and
8429 failed glob expansions are removed, the original word is
8430 added to the list of disposable words. orig_list ends up
8431 in reverse order and requires a call to REVERSE_LIST to
8432 be set right. After all words are examined, the disposable
8433 words are freed. */
8434 next = tlist->next;
8436 /* If the word isn't an assignment and contains an unquoted
8437 pattern matching character, then glob it. */
8438 if ((tlist->word->flags & W_NOGLOB) == 0 &&
8439 unquoted_glob_pattern_p (tlist->word->word))
8441 glob_array = shell_glob_filename (tlist->word->word);
8443 /* Handle error cases.
8444 I don't think we should report errors like "No such file
8445 or directory". However, I would like to report errors
8446 like "Read failed". */
8448 if (glob_array == 0 || GLOB_FAILED (glob_array))
8450 glob_array = (char **)xmalloc (sizeof (char *));
8451 glob_array[0] = (char *)NULL;
8454 /* Dequote the current word in case we have to use it. */
8455 if (glob_array[0] == NULL)
8457 temp_string = dequote_string (tlist->word->word);
8458 free (tlist->word->word);
8459 tlist->word->word = temp_string;
8462 /* Make the array into a word list. */
8463 glob_list = (WORD_LIST *)NULL;
8464 for (glob_index = 0; glob_array[glob_index]; glob_index++)
8466 tword = make_bare_word (glob_array[glob_index]);
8467 tword->flags |= W_GLOBEXP; /* XXX */
8468 glob_list = make_word_list (tword, glob_list);
8471 if (glob_list)
8473 output_list = (WORD_LIST *)list_append (glob_list, output_list);
8474 PREPEND_LIST (tlist, disposables);
8476 else if (fail_glob_expansion != 0)
8478 report_error (_("no match: %s"), tlist->word->word);
8479 exp_jump_to_top_level (DISCARD);
8481 else if (allow_null_glob_expansion == 0)
8483 /* Failed glob expressions are left unchanged. */
8484 PREPEND_LIST (tlist, output_list);
8486 else
8488 /* Failed glob expressions are removed. */
8489 PREPEND_LIST (tlist, disposables);
8492 else
8494 /* Dequote the string. */
8495 temp_string = dequote_string (tlist->word->word);
8496 free (tlist->word->word);
8497 tlist->word->word = temp_string;
8498 PREPEND_LIST (tlist, output_list);
8501 strvec_dispose (glob_array);
8502 glob_array = (char **)NULL;
8504 tlist = next;
8507 if (disposables)
8508 dispose_words (disposables);
8510 if (output_list)
8511 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8513 return (output_list);
8516 #if defined (BRACE_EXPANSION)
8517 static WORD_LIST *
8518 brace_expand_word_list (tlist, eflags)
8519 WORD_LIST *tlist;
8520 int eflags;
8522 register char **expansions;
8523 char *temp_string;
8524 WORD_LIST *disposables, *output_list, *next;
8525 WORD_DESC *w;
8526 int eindex;
8528 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
8530 next = tlist->next;
8532 /* Only do brace expansion if the word has a brace character. If
8533 not, just add the word list element to BRACES and continue. In
8534 the common case, at least when running shell scripts, this will
8535 degenerate to a bunch of calls to `xstrchr', and then what is
8536 basically a reversal of TLIST into BRACES, which is corrected
8537 by a call to REVERSE_LIST () on BRACES when the end of TLIST
8538 is reached. */
8539 if (xstrchr (tlist->word->word, LBRACE))
8541 expansions = brace_expand (tlist->word->word);
8543 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
8545 w = make_word (temp_string);
8546 /* If brace expansion didn't change the word, preserve
8547 the flags. We may want to preserve the flags
8548 unconditionally someday -- XXX */
8549 if (STREQ (temp_string, tlist->word->word))
8550 w->flags = tlist->word->flags;
8551 output_list = make_word_list (w, output_list);
8552 free (expansions[eindex]);
8554 free (expansions);
8556 /* Add TLIST to the list of words to be freed after brace
8557 expansion has been performed. */
8558 PREPEND_LIST (tlist, disposables);
8560 else
8561 PREPEND_LIST (tlist, output_list);
8564 if (disposables)
8565 dispose_words (disposables);
8567 if (output_list)
8568 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8570 return (output_list);
8572 #endif
8574 #if defined (ARRAY_VARS)
8575 /* Take WORD, a compound associative array assignment, and internally run
8576 'declare -A w', where W is the variable name portion of WORD. */
8577 static int
8578 make_internal_declare (word, option)
8579 char *word;
8580 char *option;
8582 int t;
8583 WORD_LIST *wl;
8584 WORD_DESC *w;
8586 w = make_word (word);
8588 t = assignment (w->word, 0);
8589 w->word[t] = '\0';
8591 wl = make_word_list (w, (WORD_LIST *)NULL);
8592 wl = make_word_list (make_word (option), wl);
8594 return (declare_builtin (wl));
8596 #endif
8598 static WORD_LIST *
8599 shell_expand_word_list (tlist, eflags)
8600 WORD_LIST *tlist;
8601 int eflags;
8603 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
8604 int expanded_something, has_dollar_at;
8605 char *temp_string;
8607 /* We do tilde expansion all the time. This is what 1003.2 says. */
8608 new_list = (WORD_LIST *)NULL;
8609 for (orig_list = tlist; tlist; tlist = next)
8611 temp_string = tlist->word->word;
8613 next = tlist->next;
8615 #if defined (ARRAY_VARS)
8616 /* If this is a compound array assignment to a builtin that accepts
8617 such assignments (e.g., `declare'), take the assignment and perform
8618 it separately, handling the semantics of declarations inside shell
8619 functions. This avoids the double-evaluation of such arguments,
8620 because `declare' does some evaluation of compound assignments on
8621 its own. */
8622 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
8624 int t;
8626 if (tlist->word->flags & W_ASSIGNASSOC)
8627 make_internal_declare (tlist->word->word, "-A");
8629 t = do_word_assignment (tlist->word);
8630 if (t == 0)
8632 last_command_exit_value = EXECUTION_FAILURE;
8633 exp_jump_to_top_level (DISCARD);
8636 /* Now transform the word as ksh93 appears to do and go on */
8637 t = assignment (tlist->word->word, 0);
8638 tlist->word->word[t] = '\0';
8639 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
8641 #endif
8643 expanded_something = 0;
8644 expanded = expand_word_internal
8645 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
8647 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
8649 /* By convention, each time this error is returned,
8650 tlist->word->word has already been freed. */
8651 tlist->word->word = (char *)NULL;
8653 /* Dispose our copy of the original list. */
8654 dispose_words (orig_list);
8655 /* Dispose the new list we're building. */
8656 dispose_words (new_list);
8658 last_command_exit_value = EXECUTION_FAILURE;
8659 if (expanded == &expand_word_error)
8660 exp_jump_to_top_level (DISCARD);
8661 else
8662 exp_jump_to_top_level (FORCE_EOF);
8665 /* Don't split words marked W_NOSPLIT. */
8666 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
8668 temp_list = word_list_split (expanded);
8669 dispose_words (expanded);
8671 else
8673 /* If no parameter expansion, command substitution, process
8674 substitution, or arithmetic substitution took place, then
8675 do not do word splitting. We still have to remove quoted
8676 null characters from the result. */
8677 word_list_remove_quoted_nulls (expanded);
8678 temp_list = expanded;
8681 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8682 new_list = (WORD_LIST *)list_append (expanded, new_list);
8685 if (orig_list)
8686 dispose_words (orig_list);
8688 if (new_list)
8689 new_list = REVERSE_LIST (new_list, WORD_LIST *);
8691 return (new_list);
8694 /* The workhorse for expand_words () and expand_words_no_vars ().
8695 First arg is LIST, a WORD_LIST of words.
8696 Second arg EFLAGS is a flags word controlling which expansions are
8697 performed.
8699 This does all of the substitutions: brace expansion, tilde expansion,
8700 parameter expansion, command substitution, arithmetic expansion,
8701 process substitution, word splitting, and pathname expansion, according
8702 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
8703 set, or for which no expansion is done, do not undergo word splitting.
8704 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8705 static WORD_LIST *
8706 expand_word_list_internal (list, eflags)
8707 WORD_LIST *list;
8708 int eflags;
8710 WORD_LIST *new_list, *temp_list;
8711 int tint;
8713 if (list == 0)
8714 return ((WORD_LIST *)NULL);
8716 garglist = new_list = copy_word_list (list);
8717 if (eflags & WEXP_VARASSIGN)
8719 garglist = new_list = separate_out_assignments (new_list);
8720 if (new_list == 0)
8722 if (subst_assign_varlist)
8724 /* All the words were variable assignments, so they are placed
8725 into the shell's environment. */
8726 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8728 this_command_name = (char *)NULL; /* no arithmetic errors */
8729 tint = do_word_assignment (temp_list->word);
8730 /* Variable assignment errors in non-interactive shells
8731 running in Posix.2 mode cause the shell to exit. */
8732 if (tint == 0)
8734 last_command_exit_value = EXECUTION_FAILURE;
8735 if (interactive_shell == 0 && posixly_correct)
8736 exp_jump_to_top_level (FORCE_EOF);
8737 else
8738 exp_jump_to_top_level (DISCARD);
8741 dispose_words (subst_assign_varlist);
8742 subst_assign_varlist = (WORD_LIST *)NULL;
8744 return ((WORD_LIST *)NULL);
8748 /* Begin expanding the words that remain. The expansions take place on
8749 things that aren't really variable assignments. */
8751 #if defined (BRACE_EXPANSION)
8752 /* Do brace expansion on this word if there are any brace characters
8753 in the string. */
8754 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8755 new_list = brace_expand_word_list (new_list, eflags);
8756 #endif /* BRACE_EXPANSION */
8758 /* Perform the `normal' shell expansions: tilde expansion, parameter and
8759 variable substitution, command substitution, arithmetic expansion,
8760 and word splitting. */
8761 new_list = shell_expand_word_list (new_list, eflags);
8763 /* Okay, we're almost done. Now let's just do some filename
8764 globbing. */
8765 if (new_list)
8767 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8768 /* Glob expand the word list unless globbing has been disabled. */
8769 new_list = glob_expand_word_list (new_list, eflags);
8770 else
8771 /* Dequote the words, because we're not performing globbing. */
8772 new_list = dequote_list (new_list);
8775 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8777 sh_wassign_func_t *assign_func;
8779 /* If the remainder of the words expand to nothing, Posix.2 requires
8780 that the variable and environment assignments affect the shell's
8781 environment. */
8782 assign_func = new_list ? assign_in_env : do_word_assignment;
8783 tempenv_assign_error = 0;
8785 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8787 this_command_name = (char *)NULL;
8788 assigning_in_environment = (assign_func == assign_in_env);
8789 tint = (*assign_func) (temp_list->word);
8790 assigning_in_environment = 0;
8791 /* Variable assignment errors in non-interactive shells running
8792 in Posix.2 mode cause the shell to exit. */
8793 if (tint == 0)
8795 if (assign_func == do_word_assignment)
8797 last_command_exit_value = EXECUTION_FAILURE;
8798 if (interactive_shell == 0 && posixly_correct)
8799 exp_jump_to_top_level (FORCE_EOF);
8800 else
8801 exp_jump_to_top_level (DISCARD);
8803 else
8804 tempenv_assign_error++;
8808 dispose_words (subst_assign_varlist);
8809 subst_assign_varlist = (WORD_LIST *)NULL;
8812 #if 0
8813 tint = list_length (new_list) + 1;
8814 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8815 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8816 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8817 glob_argv_flags[tint] = '\0';
8818 #endif
8820 return (new_list);