Patch-ID: bash40-035
[bash.git] / subst.c
blob78f217cabb2a045f6444d07ff56f9deddd1ab5a3
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 dispose_words (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 && ((name[0] != '@' && name[0] != '*') || name[1]))
6772 last_command_exit_value = EXECUTION_FAILURE;
6773 err_unboundvar (name);
6774 FREE (value);
6775 FREE (temp);
6776 free (name);
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 0
6994 /* According to austin-group posix proposal by Geoff Clare in
6995 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
6997 "The shell shall write a message to standard error and
6998 immediately exit when it tries to expand an unset parameter
6999 other than the '@' and '*' special parameters."
7002 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7004 uerror[0] = '$';
7005 uerror[1] = '*';
7006 uerror[2] = '\0';
7007 last_command_exit_value = EXECUTION_FAILURE;
7008 err_unboundvar (uerror);
7009 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7011 #endif
7013 /* If there are no command-line arguments, this should just
7014 disappear if there are other characters in the expansion,
7015 even if it's quoted. */
7016 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7017 temp = (char *)NULL;
7018 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7020 /* If we have "$*" we want to make a string of the positional
7021 parameters, separated by the first character of $IFS, and
7022 quote the whole string, including the separators. If IFS
7023 is unset, the parameters are separated by ' '; if $IFS is
7024 null, the parameters are concatenated. */
7025 temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
7026 temp1 = quote_string (temp);
7027 if (*temp == 0)
7028 tflag |= W_HASQUOTEDNULL;
7029 free (temp);
7030 temp = temp1;
7032 else
7034 /* We check whether or not we're eventually going to split $* here,
7035 for example when IFS is empty and we are processing the rhs of
7036 an assignment statement. In that case, we don't separate the
7037 arguments at all. Otherwise, if the $* is not quoted it is
7038 identical to $@ */
7039 #if 1
7040 # if defined (HANDLE_MULTIBYTE)
7041 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7042 # else
7043 if (expand_no_split_dollar_star && ifs_firstc == 0)
7044 # endif
7045 temp = string_list_dollar_star (list);
7046 else
7047 temp = string_list_dollar_at (list, quoted);
7048 #else
7049 temp = string_list_dollar_at (list, quoted);
7050 #endif
7051 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7052 *contains_dollar_at = 1;
7055 dispose_words (list);
7056 break;
7058 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7059 means that we have to turn quoting off after we split into
7060 the individually quoted arguments so that the final split
7061 on the first character of $IFS is still done. */
7062 case '@': /* `$@' */
7063 list = list_rest_of_args ();
7065 #if 0
7066 /* According to austin-group posix proposal by Geoff Clare in
7067 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7069 "The shell shall write a message to standard error and
7070 immediately exit when it tries to expand an unset parameter
7071 other than the '@' and '*' special parameters."
7074 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7076 uerror[0] = '$';
7077 uerror[1] = '@';
7078 uerror[2] = '\0';
7079 last_command_exit_value = EXECUTION_FAILURE;
7080 err_unboundvar (uerror);
7081 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7083 #endif
7085 /* We want to flag the fact that we saw this. We can't turn
7086 off quoting entirely, because other characters in the
7087 string might need it (consider "\"$@\""), but we need some
7088 way to signal that the final split on the first character
7089 of $IFS should be done, even though QUOTED is 1. */
7090 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7091 *quoted_dollar_at_p = 1;
7092 if (contains_dollar_at)
7093 *contains_dollar_at = 1;
7095 /* We want to separate the positional parameters with the first
7096 character of $IFS in case $IFS is something other than a space.
7097 We also want to make sure that splitting is done no matter what --
7098 according to POSIX.2, this expands to a list of the positional
7099 parameters no matter what IFS is set to. */
7100 temp = string_list_dollar_at (list, quoted);
7102 dispose_words (list);
7103 break;
7105 case LBRACE:
7106 tdesc = parameter_brace_expand (string, &zindex, quoted,
7107 quoted_dollar_at_p,
7108 contains_dollar_at);
7110 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7111 return (tdesc);
7112 temp = tdesc ? tdesc->word : (char *)0;
7114 /* XXX */
7115 /* Quoted nulls should be removed if there is anything else
7116 in the string. */
7117 /* Note that we saw the quoted null so we can add one back at
7118 the end of this function if there are no other characters
7119 in the string, discard TEMP, and go on. The exception to
7120 this is when we have "${@}" and $1 is '', since $@ needs
7121 special handling. */
7122 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7124 if (had_quoted_null_p)
7125 *had_quoted_null_p = 1;
7126 if (*quoted_dollar_at_p == 0)
7128 free (temp);
7129 tdesc->word = temp = (char *)NULL;
7134 ret = tdesc;
7135 goto return0;
7137 /* Do command or arithmetic substitution. */
7138 case LPAREN:
7139 /* We have to extract the contents of this paren substitution. */
7140 t_index = zindex + 1;
7141 temp = extract_command_subst (string, &t_index, 0);
7142 zindex = t_index;
7144 /* For Posix.2-style `$(( ))' arithmetic substitution,
7145 extract the expression and pass it to the evaluator. */
7146 if (temp && *temp == LPAREN)
7148 char *temp2;
7149 temp1 = temp + 1;
7150 temp2 = savestring (temp1);
7151 t_index = strlen (temp2) - 1;
7153 if (temp2[t_index] != RPAREN)
7155 free (temp2);
7156 goto comsub;
7159 /* Cut off ending `)' */
7160 temp2[t_index] = '\0';
7162 if (chk_arithsub (temp2, t_index) == 0)
7164 free (temp2);
7165 goto comsub;
7168 /* Expand variables found inside the expression. */
7169 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7170 free (temp2);
7172 arithsub:
7173 /* No error messages. */
7174 this_command_name = (char *)NULL;
7175 number = evalexp (temp1, &expok);
7176 free (temp);
7177 free (temp1);
7178 if (expok == 0)
7180 if (interactive_shell == 0 && posixly_correct)
7182 last_command_exit_value = EXECUTION_FAILURE;
7183 return (&expand_wdesc_fatal);
7185 else
7186 return (&expand_wdesc_error);
7188 temp = itos (number);
7189 break;
7192 comsub:
7193 if (pflags & PF_NOCOMSUB)
7194 /* we need zindex+1 because string[zindex] == RPAREN */
7195 temp1 = substring (string, *sindex, zindex+1);
7196 else
7198 tdesc = command_substitute (temp, quoted);
7199 temp1 = tdesc ? tdesc->word : (char *)NULL;
7200 if (tdesc)
7201 dispose_word_desc (tdesc);
7203 FREE (temp);
7204 temp = temp1;
7205 break;
7207 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7208 away in a future bash release. */
7209 case '[':
7210 /* Extract the contents of this arithmetic substitution. */
7211 t_index = zindex + 1;
7212 temp = extract_arithmetic_subst (string, &t_index);
7213 zindex = t_index;
7214 if (temp == 0)
7216 temp = savestring (string);
7217 if (expanded_something)
7218 *expanded_something = 0;
7219 goto return0;
7222 /* Do initial variable expansion. */
7223 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7225 goto arithsub;
7227 default:
7228 /* Find the variable in VARIABLE_LIST. */
7229 temp = (char *)NULL;
7231 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7233 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7235 /* If this isn't a variable name, then just output the `$'. */
7236 if (temp1 == 0 || *temp1 == '\0')
7238 FREE (temp1);
7239 temp = (char *)xmalloc (2);
7240 temp[0] = '$';
7241 temp[1] = '\0';
7242 if (expanded_something)
7243 *expanded_something = 0;
7244 goto return0;
7247 /* If the variable exists, return its value cell. */
7248 var = find_variable (temp1);
7250 if (var && invisible_p (var) == 0 && var_isset (var))
7252 #if defined (ARRAY_VARS)
7253 if (assoc_p (var) || array_p (var))
7255 temp = array_p (var) ? array_reference (array_cell (var), 0)
7256 : assoc_reference (assoc_cell (var), "0");
7257 if (temp)
7258 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7259 ? quote_string (temp)
7260 : quote_escapes (temp);
7261 else if (unbound_vars_is_error)
7262 goto unbound_variable;
7264 else
7265 #endif
7267 temp = value_cell (var);
7269 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7270 ? quote_string (temp)
7271 : quote_escapes (temp);
7274 free (temp1);
7276 goto return0;
7279 temp = (char *)NULL;
7281 unbound_variable:
7282 if (unbound_vars_is_error)
7283 err_unboundvar (temp1);
7284 else
7286 free (temp1);
7287 goto return0;
7290 free (temp1);
7291 last_command_exit_value = EXECUTION_FAILURE;
7292 return ((unbound_vars_is_error && interactive_shell == 0)
7293 ? &expand_wdesc_fatal
7294 : &expand_wdesc_error);
7297 if (string[zindex])
7298 zindex++;
7300 return0:
7301 *sindex = zindex;
7303 if (ret == 0)
7305 ret = alloc_word_desc ();
7306 ret->flags = tflag; /* XXX */
7307 ret->word = temp;
7309 return ret;
7312 /* Make a word list which is the result of parameter and variable
7313 expansion, command substitution, arithmetic substitution, and
7314 quote removal of WORD. Return a pointer to a WORD_LIST which is
7315 the result of the expansion. If WORD contains a null word, the
7316 word list returned is also null.
7318 QUOTED contains flag values defined in shell.h.
7320 ISEXP is used to tell expand_word_internal that the word should be
7321 treated as the result of an expansion. This has implications for
7322 how IFS characters in the word are treated.
7324 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7325 they point to an integer value which receives information about expansion.
7326 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7327 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7328 else zero.
7330 This only does word splitting in the case of $@ expansion. In that
7331 case, we split on ' '. */
7333 /* Values for the local variable quoted_state. */
7334 #define UNQUOTED 0
7335 #define PARTIALLY_QUOTED 1
7336 #define WHOLLY_QUOTED 2
7338 static WORD_LIST *
7339 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7340 WORD_DESC *word;
7341 int quoted, isexp;
7342 int *contains_dollar_at;
7343 int *expanded_something;
7345 WORD_LIST *list;
7346 WORD_DESC *tword;
7348 /* The intermediate string that we build while expanding. */
7349 char *istring;
7351 /* The current size of the above object. */
7352 int istring_size;
7354 /* Index into ISTRING. */
7355 int istring_index;
7357 /* Temporary string storage. */
7358 char *temp, *temp1;
7360 /* The text of WORD. */
7361 register char *string;
7363 /* The size of STRING. */
7364 size_t string_size;
7366 /* The index into STRING. */
7367 int sindex;
7369 /* This gets 1 if we see a $@ while quoted. */
7370 int quoted_dollar_at;
7372 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7373 whether WORD contains no quoting characters, a partially quoted
7374 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7375 int quoted_state;
7377 /* State flags */
7378 int had_quoted_null;
7379 int has_dollar_at;
7380 int tflag;
7382 int assignoff; /* If assignment, offset of `=' */
7384 register unsigned char c; /* Current character. */
7385 int t_index; /* For calls to string_extract_xxx. */
7387 char twochars[2];
7389 DECLARE_MBSTATE;
7391 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7392 istring[istring_index = 0] = '\0';
7393 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7394 quoted_state = UNQUOTED;
7396 string = word->word;
7397 if (string == 0)
7398 goto finished_with_string;
7399 /* Don't need the string length for the SADD... and COPY_ macros unless
7400 multibyte characters are possible. */
7401 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7403 if (contains_dollar_at)
7404 *contains_dollar_at = 0;
7406 assignoff = -1;
7408 /* Begin the expansion. */
7410 for (sindex = 0; ;)
7412 c = string[sindex];
7414 /* Case on toplevel character. */
7415 switch (c)
7417 case '\0':
7418 goto finished_with_string;
7420 case CTLESC:
7421 sindex++;
7422 #if HANDLE_MULTIBYTE
7423 if (MB_CUR_MAX > 1 && string[sindex])
7425 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7427 else
7428 #endif
7430 temp = (char *)xmalloc (3);
7431 temp[0] = CTLESC;
7432 temp[1] = c = string[sindex];
7433 temp[2] = '\0';
7436 dollar_add_string:
7437 if (string[sindex])
7438 sindex++;
7440 add_string:
7441 if (temp)
7443 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7444 temp = (char *)0;
7447 break;
7449 #if defined (PROCESS_SUBSTITUTION)
7450 /* Process substitution. */
7451 case '<':
7452 case '>':
7454 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7456 sindex--; /* add_character: label increments sindex */
7457 goto add_character;
7459 else
7460 t_index = sindex + 1; /* skip past both '<' and LPAREN */
7462 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7463 sindex = t_index;
7465 /* If the process substitution specification is `<()', we want to
7466 open the pipe for writing in the child and produce output; if
7467 it is `>()', we want to open the pipe for reading in the child
7468 and consume input. */
7469 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
7471 FREE (temp1);
7473 goto dollar_add_string;
7475 #endif /* PROCESS_SUBSTITUTION */
7477 case '=':
7478 /* Posix.2 section 3.6.1 says that tildes following `=' in words
7479 which are not assignment statements are not expanded. If the
7480 shell isn't in posix mode, though, we perform tilde expansion
7481 on `likely candidate' unquoted assignment statements (flags
7482 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
7483 contains an unquoted :~ or =~. Something to think about: we
7484 now have a flag that says to perform tilde expansion on arguments
7485 to `assignment builtins' like declare and export that look like
7486 assignment statements. We now do tilde expansion on such words
7487 even in POSIX mode. */
7488 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
7490 if (isexp == 0 && isifs (c))
7491 goto add_ifs_character;
7492 else
7493 goto add_character;
7495 /* If we're not in posix mode or forcing assignment-statement tilde
7496 expansion, note where the `=' appears in the word and prepare to
7497 do tilde expansion following the first `='. */
7498 if ((word->flags & W_ASSIGNMENT) &&
7499 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7500 assignoff == -1 && sindex > 0)
7501 assignoff = sindex;
7502 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
7503 word->flags |= W_ITILDE;
7504 #if 0
7505 else if ((word->flags & W_ASSIGNMENT) &&
7506 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7507 string[sindex+1] == '~')
7508 word->flags |= W_ITILDE;
7509 #endif
7510 if (isexp == 0 && isifs (c))
7511 goto add_ifs_character;
7512 else
7513 goto add_character;
7515 case ':':
7516 if (word->flags & W_NOTILDE)
7518 if (isexp == 0 && isifs (c))
7519 goto add_ifs_character;
7520 else
7521 goto add_character;
7524 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
7525 string[sindex+1] == '~')
7526 word->flags |= W_ITILDE;
7528 if (isexp == 0 && isifs (c))
7529 goto add_ifs_character;
7530 else
7531 goto add_character;
7533 case '~':
7534 /* If the word isn't supposed to be tilde expanded, or we're not
7535 at the start of a word or after an unquoted : or = in an
7536 assignment statement, we don't do tilde expansion. */
7537 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
7538 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
7539 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7541 word->flags &= ~W_ITILDE;
7542 if (isexp == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
7543 goto add_ifs_character;
7544 else
7545 goto add_character;
7548 if (word->flags & W_ASSIGNRHS)
7549 tflag = 2;
7550 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
7551 tflag = 1;
7552 else
7553 tflag = 0;
7555 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
7557 word->flags &= ~W_ITILDE;
7559 if (temp && *temp && t_index > 0)
7561 temp1 = bash_tilde_expand (temp, tflag);
7562 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
7564 FREE (temp);
7565 FREE (temp1);
7566 goto add_character; /* tilde expansion failed */
7568 free (temp);
7569 temp = temp1;
7570 sindex += t_index;
7571 goto add_quoted_string; /* XXX was add_string */
7573 else
7575 FREE (temp);
7576 goto add_character;
7579 case '$':
7580 if (expanded_something)
7581 *expanded_something = 1;
7583 has_dollar_at = 0;
7584 tword = param_expand (string, &sindex, quoted, expanded_something,
7585 &has_dollar_at, &quoted_dollar_at,
7586 &had_quoted_null,
7587 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
7589 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
7591 free (string);
7592 free (istring);
7593 return ((tword == &expand_wdesc_error) ? &expand_word_error
7594 : &expand_word_fatal);
7596 if (contains_dollar_at && has_dollar_at)
7597 *contains_dollar_at = 1;
7599 if (tword && (tword->flags & W_HASQUOTEDNULL))
7600 had_quoted_null = 1;
7602 temp = tword->word;
7603 dispose_word_desc (tword);
7605 goto add_string;
7606 break;
7608 case '`': /* Backquoted command substitution. */
7610 t_index = sindex++;
7612 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
7613 /* The test of sindex against t_index is to allow bare instances of
7614 ` to pass through, for backwards compatibility. */
7615 if (temp == &extract_string_error || temp == &extract_string_fatal)
7617 if (sindex - 1 == t_index)
7619 sindex = t_index;
7620 goto add_character;
7622 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
7623 free (string);
7624 free (istring);
7625 return ((temp == &extract_string_error) ? &expand_word_error
7626 : &expand_word_fatal);
7629 if (expanded_something)
7630 *expanded_something = 1;
7632 if (word->flags & W_NOCOMSUB)
7633 /* sindex + 1 because string[sindex] == '`' */
7634 temp1 = substring (string, t_index, sindex + 1);
7635 else
7637 de_backslash (temp);
7638 tword = command_substitute (temp, quoted);
7639 temp1 = tword ? tword->word : (char *)NULL;
7640 if (tword)
7641 dispose_word_desc (tword);
7643 FREE (temp);
7644 temp = temp1;
7645 goto dollar_add_string;
7648 case '\\':
7649 if (string[sindex + 1] == '\n')
7651 sindex += 2;
7652 continue;
7655 c = string[++sindex];
7657 if (quoted & Q_HERE_DOCUMENT)
7658 tflag = CBSHDOC;
7659 else if (quoted & Q_DOUBLE_QUOTES)
7660 tflag = CBSDQUOTE;
7661 else
7662 tflag = 0;
7664 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7666 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7668 else if (c == 0)
7670 c = CTLNUL;
7671 sindex--; /* add_character: label increments sindex */
7672 goto add_character;
7674 else
7676 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7679 sindex++;
7680 add_twochars:
7681 /* BEFORE jumping here, we need to increment sindex if appropriate */
7682 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7683 DEFAULT_ARRAY_SIZE);
7684 istring[istring_index++] = twochars[0];
7685 istring[istring_index++] = twochars[1];
7686 istring[istring_index] = '\0';
7688 break;
7690 case '"':
7691 #if 0
7692 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7693 #else
7694 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7695 #endif
7696 goto add_character;
7698 t_index = ++sindex;
7699 temp = string_extract_double_quoted (string, &sindex, 0);
7701 /* If the quotes surrounded the entire string, then the
7702 whole word was quoted. */
7703 quoted_state = (t_index == 1 && string[sindex] == '\0')
7704 ? WHOLLY_QUOTED
7705 : PARTIALLY_QUOTED;
7707 if (temp && *temp)
7709 tword = alloc_word_desc ();
7710 tword->word = temp;
7712 temp = (char *)NULL;
7714 has_dollar_at = 0;
7715 /* Need to get W_HASQUOTEDNULL flag through this function. */
7716 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7718 if (list == &expand_word_error || list == &expand_word_fatal)
7720 free (istring);
7721 free (string);
7722 /* expand_word_internal has already freed temp_word->word
7723 for us because of the way it prints error messages. */
7724 tword->word = (char *)NULL;
7725 dispose_word (tword);
7726 return list;
7729 dispose_word (tword);
7731 /* "$@" (a double-quoted dollar-at) expands into nothing,
7732 not even a NULL word, when there are no positional
7733 parameters. */
7734 if (list == 0 && has_dollar_at)
7736 quoted_dollar_at++;
7737 break;
7740 /* If we get "$@", we know we have expanded something, so we
7741 need to remember it for the final split on $IFS. This is
7742 a special case; it's the only case where a quoted string
7743 can expand into more than one word. It's going to come back
7744 from the above call to expand_word_internal as a list with
7745 a single word, in which all characters are quoted and
7746 separated by blanks. What we want to do is to turn it back
7747 into a list for the next piece of code. */
7748 if (list)
7749 dequote_list (list);
7751 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7752 had_quoted_null = 1;
7754 if (has_dollar_at)
7756 quoted_dollar_at++;
7757 if (contains_dollar_at)
7758 *contains_dollar_at = 1;
7759 if (expanded_something)
7760 *expanded_something = 1;
7763 else
7765 /* What we have is "". This is a minor optimization. */
7766 FREE (temp);
7767 list = (WORD_LIST *)NULL;
7770 /* The code above *might* return a list (consider the case of "$@",
7771 where it returns "$1", "$2", etc.). We can't throw away the
7772 rest of the list, and we have to make sure each word gets added
7773 as quoted. We test on tresult->next: if it is non-NULL, we
7774 quote the whole list, save it to a string with string_list, and
7775 add that string. We don't need to quote the results of this
7776 (and it would be wrong, since that would quote the separators
7777 as well), so we go directly to add_string. */
7778 if (list)
7780 if (list->next)
7782 /* Testing quoted_dollar_at makes sure that "$@" is
7783 split correctly when $IFS does not contain a space. */
7784 temp = quoted_dollar_at
7785 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7786 : string_list (quote_list (list));
7787 dispose_words (list);
7788 goto add_string;
7790 else
7792 temp = savestring (list->word->word);
7793 tflag = list->word->flags;
7794 dispose_words (list);
7796 /* If the string is not a quoted null string, we want
7797 to remove any embedded unquoted CTLNUL characters.
7798 We do not want to turn quoted null strings back into
7799 the empty string, though. We do this because we
7800 want to remove any quoted nulls from expansions that
7801 contain other characters. For example, if we have
7802 x"$*"y or "x$*y" and there are no positional parameters,
7803 the $* should expand into nothing. */
7804 /* We use the W_HASQUOTEDNULL flag to differentiate the
7805 cases: a quoted null character as above and when
7806 CTLNUL is contained in the (non-null) expansion
7807 of some variable. We use the had_quoted_null flag to
7808 pass the value through this function to its caller. */
7809 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7810 remove_quoted_nulls (temp); /* XXX */
7813 else
7814 temp = (char *)NULL;
7816 /* We do not want to add quoted nulls to strings that are only
7817 partially quoted; we can throw them away. */
7818 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7819 continue;
7821 add_quoted_string:
7823 if (temp)
7825 temp1 = temp;
7826 temp = quote_string (temp);
7827 free (temp1);
7828 goto add_string;
7830 else
7832 /* Add NULL arg. */
7833 c = CTLNUL;
7834 sindex--; /* add_character: label increments sindex */
7835 goto add_character;
7838 /* break; */
7840 case '\'':
7841 #if 0
7842 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7843 #else
7844 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7845 #endif
7846 goto add_character;
7848 t_index = ++sindex;
7849 temp = string_extract_single_quoted (string, &sindex);
7851 /* If the entire STRING was surrounded by single quotes,
7852 then the string is wholly quoted. */
7853 quoted_state = (t_index == 1 && string[sindex] == '\0')
7854 ? WHOLLY_QUOTED
7855 : PARTIALLY_QUOTED;
7857 /* If all we had was '', it is a null expansion. */
7858 if (*temp == '\0')
7860 free (temp);
7861 temp = (char *)NULL;
7863 else
7864 remove_quoted_escapes (temp); /* ??? */
7866 /* We do not want to add quoted nulls to strings that are only
7867 partially quoted; such nulls are discarded. */
7868 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7869 continue;
7871 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7872 if (temp == 0)
7874 c = CTLNUL;
7875 sindex--; /* add_character: label increments sindex */
7876 goto add_character;
7878 else
7879 goto add_quoted_string;
7881 /* break; */
7883 default:
7884 /* This is the fix for " $@ " */
7885 add_ifs_character:
7886 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7888 if (string[sindex]) /* from old goto dollar_add_string */
7889 sindex++;
7890 if (c == 0)
7892 c = CTLNUL;
7893 goto add_character;
7895 else
7897 #if HANDLE_MULTIBYTE
7898 if (MB_CUR_MAX > 1)
7899 sindex--;
7901 if (MB_CUR_MAX > 1)
7903 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7905 else
7906 #endif
7908 twochars[0] = CTLESC;
7909 twochars[1] = c;
7910 goto add_twochars;
7915 SADD_MBCHAR (temp, string, sindex, string_size);
7917 add_character:
7918 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7919 DEFAULT_ARRAY_SIZE);
7920 istring[istring_index++] = c;
7921 istring[istring_index] = '\0';
7923 /* Next character. */
7924 sindex++;
7928 finished_with_string:
7929 /* OK, we're ready to return. If we have a quoted string, and
7930 quoted_dollar_at is not set, we do no splitting at all; otherwise
7931 we split on ' '. The routines that call this will handle what to
7932 do if nothing has been expanded. */
7934 /* Partially and wholly quoted strings which expand to the empty
7935 string are retained as an empty arguments. Unquoted strings
7936 which expand to the empty string are discarded. The single
7937 exception is the case of expanding "$@" when there are no
7938 positional parameters. In that case, we discard the expansion. */
7940 /* Because of how the code that handles "" and '' in partially
7941 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7942 if we saw quoting characters, but the expansion was empty.
7943 "" and '' are tossed away before we get to this point when
7944 processing partially quoted strings. This makes "" and $xxx""
7945 equivalent when xxx is unset. We also look to see whether we
7946 saw a quoted null from a ${} expansion and add one back if we
7947 need to. */
7949 /* If we expand to nothing and there were no single or double quotes
7950 in the word, we throw it away. Otherwise, we return a NULL word.
7951 The single exception is for $@ surrounded by double quotes when
7952 there are no positional parameters. In that case, we also throw
7953 the word away. */
7955 if (*istring == '\0')
7957 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7959 istring[0] = CTLNUL;
7960 istring[1] = '\0';
7961 tword = make_bare_word (istring);
7962 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7963 list = make_word_list (tword, (WORD_LIST *)NULL);
7964 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7965 tword->flags |= W_QUOTED;
7967 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7968 and a double-quoted "$@" appears anywhere in it, then the entire
7969 word is removed. */
7970 else if (quoted_state == UNQUOTED || quoted_dollar_at)
7971 list = (WORD_LIST *)NULL;
7972 #if 0
7973 else
7975 tword = make_bare_word (istring);
7976 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7977 tword->flags |= W_QUOTED;
7978 list = make_word_list (tword, (WORD_LIST *)NULL);
7980 #else
7981 else
7982 list = (WORD_LIST *)NULL;
7983 #endif
7985 else if (word->flags & W_NOSPLIT)
7987 tword = make_bare_word (istring);
7988 if (word->flags & W_ASSIGNMENT)
7989 tword->flags |= W_ASSIGNMENT; /* XXX */
7990 if (word->flags & W_COMPASSIGN)
7991 tword->flags |= W_COMPASSIGN; /* XXX */
7992 if (word->flags & W_NOGLOB)
7993 tword->flags |= W_NOGLOB; /* XXX */
7994 if (word->flags & W_NOEXPAND)
7995 tword->flags |= W_NOEXPAND; /* XXX */
7996 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7997 tword->flags |= W_QUOTED;
7998 if (had_quoted_null)
7999 tword->flags |= W_HASQUOTEDNULL;
8000 list = make_word_list (tword, (WORD_LIST *)NULL);
8002 else
8004 char *ifs_chars;
8006 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
8008 /* If we have $@, we need to split the results no matter what. If
8009 IFS is unset or NULL, string_list_dollar_at has separated the
8010 positional parameters with a space, so we split on space (we have
8011 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
8012 string_list_dollar_at has separated the positional parameters
8013 with the first character of $IFS, so we split on $IFS. */
8014 if (has_dollar_at && ifs_chars)
8015 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
8016 else
8018 tword = make_bare_word (istring);
8019 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8020 tword->flags |= W_QUOTED;
8021 if (word->flags & W_ASSIGNMENT)
8022 tword->flags |= W_ASSIGNMENT;
8023 if (word->flags & W_COMPASSIGN)
8024 tword->flags |= W_COMPASSIGN;
8025 if (word->flags & W_NOGLOB)
8026 tword->flags |= W_NOGLOB;
8027 if (word->flags & W_NOEXPAND)
8028 tword->flags |= W_NOEXPAND;
8029 if (had_quoted_null)
8030 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8031 list = make_word_list (tword, (WORD_LIST *)NULL);
8035 free (istring);
8036 return (list);
8039 /* **************************************************************** */
8040 /* */
8041 /* Functions for Quote Removal */
8042 /* */
8043 /* **************************************************************** */
8045 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
8046 backslash quoting rules for within double quotes or a here document. */
8047 char *
8048 string_quote_removal (string, quoted)
8049 char *string;
8050 int quoted;
8052 size_t slen;
8053 char *r, *result_string, *temp, *send;
8054 int sindex, tindex, dquote;
8055 unsigned char c;
8056 DECLARE_MBSTATE;
8058 /* The result can be no longer than the original string. */
8059 slen = strlen (string);
8060 send = string + slen;
8062 r = result_string = (char *)xmalloc (slen + 1);
8064 for (dquote = sindex = 0; c = string[sindex];)
8066 switch (c)
8068 case '\\':
8069 c = string[++sindex];
8070 if (c == 0)
8072 *r++ = '\\';
8073 break;
8075 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8076 *r++ = '\\';
8077 /* FALLTHROUGH */
8079 default:
8080 SCOPY_CHAR_M (r, string, send, sindex);
8081 break;
8083 case '\'':
8084 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8086 *r++ = c;
8087 sindex++;
8088 break;
8090 tindex = sindex + 1;
8091 temp = string_extract_single_quoted (string, &tindex);
8092 if (temp)
8094 strcpy (r, temp);
8095 r += strlen (r);
8096 free (temp);
8098 sindex = tindex;
8099 break;
8101 case '"':
8102 dquote = 1 - dquote;
8103 sindex++;
8104 break;
8107 *r = '\0';
8108 return (result_string);
8111 #if 0
8112 /* UNUSED */
8113 /* Perform quote removal on word WORD. This allocates and returns a new
8114 WORD_DESC *. */
8115 WORD_DESC *
8116 word_quote_removal (word, quoted)
8117 WORD_DESC *word;
8118 int quoted;
8120 WORD_DESC *w;
8121 char *t;
8123 t = string_quote_removal (word->word, quoted);
8124 w = alloc_word_desc ();
8125 w->word = t ? t : savestring ("");
8126 return (w);
8129 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8130 the members of the list are treated as if they are surrounded by
8131 double quotes. Return a new list, or NULL if LIST is NULL. */
8132 WORD_LIST *
8133 word_list_quote_removal (list, quoted)
8134 WORD_LIST *list;
8135 int quoted;
8137 WORD_LIST *result, *t, *tresult, *e;
8139 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8141 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8142 #if 0
8143 result = (WORD_LIST *) list_append (result, tresult);
8144 #else
8145 if (result == 0)
8146 result = e = tresult;
8147 else
8149 e->next = tresult;
8150 while (e->next)
8151 e = e->next;
8153 #endif
8155 return (result);
8157 #endif
8159 /*******************************************
8161 * Functions to perform word splitting *
8163 *******************************************/
8165 void
8166 setifs (v)
8167 SHELL_VAR *v;
8169 char *t;
8170 unsigned char uc;
8172 ifs_var = v;
8173 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8175 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8176 handle multibyte chars in IFS */
8177 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8178 for (t = ifs_value ; t && *t; t++)
8180 uc = *t;
8181 ifs_cmap[uc] = 1;
8184 #if defined (HANDLE_MULTIBYTE)
8185 if (ifs_value == 0)
8187 ifs_firstc[0] = '\0';
8188 ifs_firstc_len = 1;
8190 else
8192 size_t ifs_len;
8193 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8194 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8195 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8197 ifs_firstc[0] = ifs_value[0];
8198 ifs_firstc[1] = '\0';
8199 ifs_firstc_len = 1;
8201 else
8202 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8204 #else
8205 ifs_firstc = ifs_value ? *ifs_value : 0;
8206 #endif
8209 char *
8210 getifs ()
8212 return ifs_value;
8215 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8216 is not quoted. list_string () performs quote removal for us, even if we
8217 don't do any splitting. */
8218 WORD_LIST *
8219 word_split (w, ifs_chars)
8220 WORD_DESC *w;
8221 char *ifs_chars;
8223 WORD_LIST *result;
8225 if (w)
8227 char *xifs;
8229 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8230 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8232 else
8233 result = (WORD_LIST *)NULL;
8235 return (result);
8238 /* Perform word splitting on LIST and return the RESULT. It is possible
8239 to return (WORD_LIST *)NULL. */
8240 static WORD_LIST *
8241 word_list_split (list)
8242 WORD_LIST *list;
8244 WORD_LIST *result, *t, *tresult, *e;
8246 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8248 tresult = word_split (t->word, ifs_value);
8249 if (result == 0)
8250 result = e = tresult;
8251 else
8253 e->next = tresult;
8254 while (e->next)
8255 e = e->next;
8258 return (result);
8261 /**************************************************
8263 * Functions to expand an entire WORD_LIST *
8265 **************************************************/
8267 /* Do any word-expansion-specific cleanup and jump to top_level */
8268 static void
8269 exp_jump_to_top_level (v)
8270 int v;
8272 set_pipestatus_from_exit (last_command_exit_value);
8274 /* Cleanup code goes here. */
8275 expand_no_split_dollar_star = 0; /* XXX */
8276 expanding_redir = 0;
8277 assigning_in_environment = 0;
8279 if (parse_and_execute_level == 0)
8280 top_level_cleanup (); /* from sig.c */
8282 jump_to_top_level (v);
8285 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8286 ELIST, and set ELIST to the new list. */
8287 #define PREPEND_LIST(nlist, elist) \
8288 do { nlist->next = elist; elist = nlist; } while (0)
8290 /* Separate out any initial variable assignments from TLIST. If set -k has
8291 been executed, remove all assignment statements from TLIST. Initial
8292 variable assignments and other environment assignments are placed
8293 on SUBST_ASSIGN_VARLIST. */
8294 static WORD_LIST *
8295 separate_out_assignments (tlist)
8296 WORD_LIST *tlist;
8298 register WORD_LIST *vp, *lp;
8300 if (!tlist)
8301 return ((WORD_LIST *)NULL);
8303 if (subst_assign_varlist)
8304 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8306 subst_assign_varlist = (WORD_LIST *)NULL;
8307 vp = lp = tlist;
8309 /* Separate out variable assignments at the start of the command.
8310 Loop invariant: vp->next == lp
8311 Loop postcondition:
8312 lp = list of words left after assignment statements skipped
8313 tlist = original list of words
8315 while (lp && (lp->word->flags & W_ASSIGNMENT))
8317 vp = lp;
8318 lp = lp->next;
8321 /* If lp != tlist, we have some initial assignment statements.
8322 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8323 words and TLIST point to the remaining words. */
8324 if (lp != tlist)
8326 subst_assign_varlist = tlist;
8327 /* ASSERT(vp->next == lp); */
8328 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8329 tlist = lp; /* remainder of word list */
8332 /* vp == end of variable list */
8333 /* tlist == remainder of original word list without variable assignments */
8334 if (!tlist)
8335 /* All the words in tlist were assignment statements */
8336 return ((WORD_LIST *)NULL);
8338 /* ASSERT(tlist != NULL); */
8339 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8341 /* If the -k option is in effect, we need to go through the remaining
8342 words, separate out the assignment words, and place them on
8343 SUBST_ASSIGN_VARLIST. */
8344 if (place_keywords_in_env)
8346 WORD_LIST *tp; /* tp == running pointer into tlist */
8348 tp = tlist;
8349 lp = tlist->next;
8351 /* Loop Invariant: tp->next == lp */
8352 /* Loop postcondition: tlist == word list without assignment statements */
8353 while (lp)
8355 if (lp->word->flags & W_ASSIGNMENT)
8357 /* Found an assignment statement, add this word to end of
8358 subst_assign_varlist (vp). */
8359 if (!subst_assign_varlist)
8360 subst_assign_varlist = vp = lp;
8361 else
8363 vp->next = lp;
8364 vp = lp;
8367 /* Remove the word pointed to by LP from TLIST. */
8368 tp->next = lp->next;
8369 /* ASSERT(vp == lp); */
8370 lp->next = (WORD_LIST *)NULL;
8371 lp = tp->next;
8373 else
8375 tp = lp;
8376 lp = lp->next;
8380 return (tlist);
8383 #define WEXP_VARASSIGN 0x001
8384 #define WEXP_BRACEEXP 0x002
8385 #define WEXP_TILDEEXP 0x004
8386 #define WEXP_PARAMEXP 0x008
8387 #define WEXP_PATHEXP 0x010
8389 /* All of the expansions, including variable assignments at the start of
8390 the list. */
8391 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8393 /* All of the expansions except variable assignments at the start of
8394 the list. */
8395 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8397 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8398 expansion, command substitution, arithmetic expansion, word splitting, and
8399 quote removal. */
8400 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8402 /* Take the list of words in LIST and do the various substitutions. Return
8403 a new list of words which is the expanded list, and without things like
8404 variable assignments. */
8406 WORD_LIST *
8407 expand_words (list)
8408 WORD_LIST *list;
8410 return (expand_word_list_internal (list, WEXP_ALL));
8413 /* Same as expand_words (), but doesn't hack variable or environment
8414 variables. */
8415 WORD_LIST *
8416 expand_words_no_vars (list)
8417 WORD_LIST *list;
8419 return (expand_word_list_internal (list, WEXP_NOVARS));
8422 WORD_LIST *
8423 expand_words_shellexp (list)
8424 WORD_LIST *list;
8426 return (expand_word_list_internal (list, WEXP_SHELLEXP));
8429 static WORD_LIST *
8430 glob_expand_word_list (tlist, eflags)
8431 WORD_LIST *tlist;
8432 int eflags;
8434 char **glob_array, *temp_string;
8435 register int glob_index;
8436 WORD_LIST *glob_list, *output_list, *disposables, *next;
8437 WORD_DESC *tword;
8439 output_list = disposables = (WORD_LIST *)NULL;
8440 glob_array = (char **)NULL;
8441 while (tlist)
8443 /* For each word, either globbing is attempted or the word is
8444 added to orig_list. If globbing succeeds, the results are
8445 added to orig_list and the word (tlist) is added to the list
8446 of disposable words. If globbing fails and failed glob
8447 expansions are left unchanged (the shell default), the
8448 original word is added to orig_list. If globbing fails and
8449 failed glob expansions are removed, the original word is
8450 added to the list of disposable words. orig_list ends up
8451 in reverse order and requires a call to REVERSE_LIST to
8452 be set right. After all words are examined, the disposable
8453 words are freed. */
8454 next = tlist->next;
8456 /* If the word isn't an assignment and contains an unquoted
8457 pattern matching character, then glob it. */
8458 if ((tlist->word->flags & W_NOGLOB) == 0 &&
8459 unquoted_glob_pattern_p (tlist->word->word))
8461 glob_array = shell_glob_filename (tlist->word->word);
8463 /* Handle error cases.
8464 I don't think we should report errors like "No such file
8465 or directory". However, I would like to report errors
8466 like "Read failed". */
8468 if (glob_array == 0 || GLOB_FAILED (glob_array))
8470 glob_array = (char **)xmalloc (sizeof (char *));
8471 glob_array[0] = (char *)NULL;
8474 /* Dequote the current word in case we have to use it. */
8475 if (glob_array[0] == NULL)
8477 temp_string = dequote_string (tlist->word->word);
8478 free (tlist->word->word);
8479 tlist->word->word = temp_string;
8482 /* Make the array into a word list. */
8483 glob_list = (WORD_LIST *)NULL;
8484 for (glob_index = 0; glob_array[glob_index]; glob_index++)
8486 tword = make_bare_word (glob_array[glob_index]);
8487 tword->flags |= W_GLOBEXP; /* XXX */
8488 glob_list = make_word_list (tword, glob_list);
8491 if (glob_list)
8493 output_list = (WORD_LIST *)list_append (glob_list, output_list);
8494 PREPEND_LIST (tlist, disposables);
8496 else if (fail_glob_expansion != 0)
8498 report_error (_("no match: %s"), tlist->word->word);
8499 exp_jump_to_top_level (DISCARD);
8501 else if (allow_null_glob_expansion == 0)
8503 /* Failed glob expressions are left unchanged. */
8504 PREPEND_LIST (tlist, output_list);
8506 else
8508 /* Failed glob expressions are removed. */
8509 PREPEND_LIST (tlist, disposables);
8512 else
8514 /* Dequote the string. */
8515 temp_string = dequote_string (tlist->word->word);
8516 free (tlist->word->word);
8517 tlist->word->word = temp_string;
8518 PREPEND_LIST (tlist, output_list);
8521 strvec_dispose (glob_array);
8522 glob_array = (char **)NULL;
8524 tlist = next;
8527 if (disposables)
8528 dispose_words (disposables);
8530 if (output_list)
8531 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8533 return (output_list);
8536 #if defined (BRACE_EXPANSION)
8537 static WORD_LIST *
8538 brace_expand_word_list (tlist, eflags)
8539 WORD_LIST *tlist;
8540 int eflags;
8542 register char **expansions;
8543 char *temp_string;
8544 WORD_LIST *disposables, *output_list, *next;
8545 WORD_DESC *w;
8546 int eindex;
8548 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
8550 next = tlist->next;
8552 /* Only do brace expansion if the word has a brace character. If
8553 not, just add the word list element to BRACES and continue. In
8554 the common case, at least when running shell scripts, this will
8555 degenerate to a bunch of calls to `xstrchr', and then what is
8556 basically a reversal of TLIST into BRACES, which is corrected
8557 by a call to REVERSE_LIST () on BRACES when the end of TLIST
8558 is reached. */
8559 if (xstrchr (tlist->word->word, LBRACE))
8561 expansions = brace_expand (tlist->word->word);
8563 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
8565 w = make_word (temp_string);
8566 /* If brace expansion didn't change the word, preserve
8567 the flags. We may want to preserve the flags
8568 unconditionally someday -- XXX */
8569 if (STREQ (temp_string, tlist->word->word))
8570 w->flags = tlist->word->flags;
8571 output_list = make_word_list (w, output_list);
8572 free (expansions[eindex]);
8574 free (expansions);
8576 /* Add TLIST to the list of words to be freed after brace
8577 expansion has been performed. */
8578 PREPEND_LIST (tlist, disposables);
8580 else
8581 PREPEND_LIST (tlist, output_list);
8584 if (disposables)
8585 dispose_words (disposables);
8587 if (output_list)
8588 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8590 return (output_list);
8592 #endif
8594 #if defined (ARRAY_VARS)
8595 /* Take WORD, a compound associative array assignment, and internally run
8596 'declare -A w', where W is the variable name portion of WORD. */
8597 static int
8598 make_internal_declare (word, option)
8599 char *word;
8600 char *option;
8602 int t;
8603 WORD_LIST *wl;
8604 WORD_DESC *w;
8606 w = make_word (word);
8608 t = assignment (w->word, 0);
8609 w->word[t] = '\0';
8611 wl = make_word_list (w, (WORD_LIST *)NULL);
8612 wl = make_word_list (make_word (option), wl);
8614 return (declare_builtin (wl));
8616 #endif
8618 static WORD_LIST *
8619 shell_expand_word_list (tlist, eflags)
8620 WORD_LIST *tlist;
8621 int eflags;
8623 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
8624 int expanded_something, has_dollar_at;
8625 char *temp_string;
8627 /* We do tilde expansion all the time. This is what 1003.2 says. */
8628 new_list = (WORD_LIST *)NULL;
8629 for (orig_list = tlist; tlist; tlist = next)
8631 temp_string = tlist->word->word;
8633 next = tlist->next;
8635 #if defined (ARRAY_VARS)
8636 /* If this is a compound array assignment to a builtin that accepts
8637 such assignments (e.g., `declare'), take the assignment and perform
8638 it separately, handling the semantics of declarations inside shell
8639 functions. This avoids the double-evaluation of such arguments,
8640 because `declare' does some evaluation of compound assignments on
8641 its own. */
8642 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
8644 int t;
8646 if (tlist->word->flags & W_ASSIGNASSOC)
8647 make_internal_declare (tlist->word->word, "-A");
8649 t = do_word_assignment (tlist->word);
8650 if (t == 0)
8652 last_command_exit_value = EXECUTION_FAILURE;
8653 exp_jump_to_top_level (DISCARD);
8656 /* Now transform the word as ksh93 appears to do and go on */
8657 t = assignment (tlist->word->word, 0);
8658 tlist->word->word[t] = '\0';
8659 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
8661 #endif
8663 expanded_something = 0;
8664 expanded = expand_word_internal
8665 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
8667 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
8669 /* By convention, each time this error is returned,
8670 tlist->word->word has already been freed. */
8671 tlist->word->word = (char *)NULL;
8673 /* Dispose our copy of the original list. */
8674 dispose_words (orig_list);
8675 /* Dispose the new list we're building. */
8676 dispose_words (new_list);
8678 last_command_exit_value = EXECUTION_FAILURE;
8679 if (expanded == &expand_word_error)
8680 exp_jump_to_top_level (DISCARD);
8681 else
8682 exp_jump_to_top_level (FORCE_EOF);
8685 /* Don't split words marked W_NOSPLIT. */
8686 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
8688 temp_list = word_list_split (expanded);
8689 dispose_words (expanded);
8691 else
8693 /* If no parameter expansion, command substitution, process
8694 substitution, or arithmetic substitution took place, then
8695 do not do word splitting. We still have to remove quoted
8696 null characters from the result. */
8697 word_list_remove_quoted_nulls (expanded);
8698 temp_list = expanded;
8701 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8702 new_list = (WORD_LIST *)list_append (expanded, new_list);
8705 if (orig_list)
8706 dispose_words (orig_list);
8708 if (new_list)
8709 new_list = REVERSE_LIST (new_list, WORD_LIST *);
8711 return (new_list);
8714 /* The workhorse for expand_words () and expand_words_no_vars ().
8715 First arg is LIST, a WORD_LIST of words.
8716 Second arg EFLAGS is a flags word controlling which expansions are
8717 performed.
8719 This does all of the substitutions: brace expansion, tilde expansion,
8720 parameter expansion, command substitution, arithmetic expansion,
8721 process substitution, word splitting, and pathname expansion, according
8722 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
8723 set, or for which no expansion is done, do not undergo word splitting.
8724 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8725 static WORD_LIST *
8726 expand_word_list_internal (list, eflags)
8727 WORD_LIST *list;
8728 int eflags;
8730 WORD_LIST *new_list, *temp_list;
8731 int tint;
8733 if (list == 0)
8734 return ((WORD_LIST *)NULL);
8736 garglist = new_list = copy_word_list (list);
8737 if (eflags & WEXP_VARASSIGN)
8739 garglist = new_list = separate_out_assignments (new_list);
8740 if (new_list == 0)
8742 if (subst_assign_varlist)
8744 /* All the words were variable assignments, so they are placed
8745 into the shell's environment. */
8746 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8748 this_command_name = (char *)NULL; /* no arithmetic errors */
8749 tint = do_word_assignment (temp_list->word);
8750 /* Variable assignment errors in non-interactive shells
8751 running in Posix.2 mode cause the shell to exit. */
8752 if (tint == 0)
8754 last_command_exit_value = EXECUTION_FAILURE;
8755 if (interactive_shell == 0 && posixly_correct)
8756 exp_jump_to_top_level (FORCE_EOF);
8757 else
8758 exp_jump_to_top_level (DISCARD);
8761 dispose_words (subst_assign_varlist);
8762 subst_assign_varlist = (WORD_LIST *)NULL;
8764 return ((WORD_LIST *)NULL);
8768 /* Begin expanding the words that remain. The expansions take place on
8769 things that aren't really variable assignments. */
8771 #if defined (BRACE_EXPANSION)
8772 /* Do brace expansion on this word if there are any brace characters
8773 in the string. */
8774 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8775 new_list = brace_expand_word_list (new_list, eflags);
8776 #endif /* BRACE_EXPANSION */
8778 /* Perform the `normal' shell expansions: tilde expansion, parameter and
8779 variable substitution, command substitution, arithmetic expansion,
8780 and word splitting. */
8781 new_list = shell_expand_word_list (new_list, eflags);
8783 /* Okay, we're almost done. Now let's just do some filename
8784 globbing. */
8785 if (new_list)
8787 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8788 /* Glob expand the word list unless globbing has been disabled. */
8789 new_list = glob_expand_word_list (new_list, eflags);
8790 else
8791 /* Dequote the words, because we're not performing globbing. */
8792 new_list = dequote_list (new_list);
8795 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8797 sh_wassign_func_t *assign_func;
8799 /* If the remainder of the words expand to nothing, Posix.2 requires
8800 that the variable and environment assignments affect the shell's
8801 environment. */
8802 assign_func = new_list ? assign_in_env : do_word_assignment;
8803 tempenv_assign_error = 0;
8805 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8807 this_command_name = (char *)NULL;
8808 assigning_in_environment = (assign_func == assign_in_env);
8809 tint = (*assign_func) (temp_list->word);
8810 assigning_in_environment = 0;
8811 /* Variable assignment errors in non-interactive shells running
8812 in Posix.2 mode cause the shell to exit. */
8813 if (tint == 0)
8815 if (assign_func == do_word_assignment)
8817 last_command_exit_value = EXECUTION_FAILURE;
8818 if (interactive_shell == 0 && posixly_correct)
8819 exp_jump_to_top_level (FORCE_EOF);
8820 else
8821 exp_jump_to_top_level (DISCARD);
8823 else
8824 tempenv_assign_error++;
8828 dispose_words (subst_assign_varlist);
8829 subst_assign_varlist = (WORD_LIST *)NULL;
8832 #if 0
8833 tint = list_length (new_list) + 1;
8834 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8835 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8836 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8837 glob_argv_flags[tint] = '\0';
8838 #endif
8840 return (new_list);