Patch-ID: bash32-008
[bash.git] / subst.c
blob4624c48ec6440d594bcc37393c656fd00538dbdc
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-2006 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 it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
16 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License along
22 with Bash; see the file COPYING. If not, write to the Free Software
23 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
25 #include "config.h"
27 #include "bashtypes.h"
28 #include <stdio.h>
29 #include "chartypes.h"
30 #include <pwd.h>
31 #include <signal.h>
32 #include <errno.h>
34 #if defined (HAVE_UNISTD_H)
35 # include <unistd.h>
36 #endif
38 #include "bashansi.h"
39 #include "posixstat.h"
40 #include "bashintl.h"
42 #include "shell.h"
43 #include "flags.h"
44 #include "jobs.h"
45 #include "execute_cmd.h"
46 #include "filecntl.h"
47 #include "trap.h"
48 #include "pathexp.h"
49 #include "mailcheck.h"
51 #include "shmbutil.h"
53 #include "builtins/getopt.h"
54 #include "builtins/common.h"
56 #include <tilde/tilde.h>
57 #include <glob/strmatch.h>
59 #if !defined (errno)
60 extern int errno;
61 #endif /* !errno */
63 /* The size that strings change by. */
64 #define DEFAULT_INITIAL_ARRAY_SIZE 112
65 #define DEFAULT_ARRAY_SIZE 128
67 /* Variable types. */
68 #define VT_VARIABLE 0
69 #define VT_POSPARMS 1
70 #define VT_ARRAYVAR 2
71 #define VT_ARRAYMEMBER 3
73 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
75 /* Flags for quoted_strchr */
76 #define ST_BACKSL 0x01
77 #define ST_CTLESC 0x02
78 #define ST_SQUOTE 0x04 /* unused yet */
79 #define ST_DQUOTE 0x08 /* unused yet */
81 /* Flags for the string extraction functions. */
82 #define EX_NOALLOC 0x01 /* just skip; don't return substring */
83 #define EX_VARNAME 0x02 /* variable name; for string_extract () */
84 #define EX_REQMATCH 0x04 /* closing/matching delimiter required */
85 #define EX_COMMAND 0x08 /* extracting a shell script/command */
87 /* Flags for the `pflags' argument to param_expand() */
88 #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
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 /* Extern functions and variables from different files. */
138 extern int last_command_exit_value, last_command_exit_signal;
139 extern int subshell_environment;
140 extern int subshell_level;
141 extern int eof_encountered;
142 extern int return_catch_flag, return_catch_value;
143 extern pid_t dollar_dollar_pid;
144 extern int posixly_correct;
145 extern char *this_command_name;
146 extern struct fd_bitmap *current_fds_to_close;
147 extern int wordexp_only;
148 extern int expanding_redir;
149 extern int tempenv_assign_error;
151 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
152 extern wchar_t *wcsdup __P((const wchar_t *));
153 #endif
155 /* Non-zero means to allow unmatched globbed filenames to expand to
156 a null file. */
157 int allow_null_glob_expansion;
159 /* Non-zero means to throw an error when globbing fails to match anything. */
160 int fail_glob_expansion;
162 #if 0
163 /* Variables to keep track of which words in an expanded word list (the
164 output of expand_word_list_internal) are the result of globbing
165 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
166 (CURRENTLY UNUSED). */
167 char *glob_argv_flags;
168 static int glob_argv_flags_size;
169 #endif
171 static WORD_LIST expand_word_error, expand_word_fatal;
172 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
173 static char expand_param_error, expand_param_fatal;
174 static char extract_string_error, extract_string_fatal;
176 /* Tell the expansion functions to not longjmp back to top_level on fatal
177 errors. Enabled when doing completion and prompt string expansion. */
178 static int no_longjmp_on_fatal_error = 0;
180 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
181 $* on $IFS, primarily when doing assignment statements. */
182 static int expand_no_split_dollar_star = 0;
184 /* Used to hold a list of variable assignments preceding a command. Global
185 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
186 SIGCHLD trap. */
187 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
189 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
190 without any leading variable assignments. */
191 static WORD_LIST *garglist = (WORD_LIST *)NULL;
193 static char *quoted_substring __P((char *, int, int));
194 static int quoted_strlen __P((char *));
195 static char *quoted_strchr __P((char *, int, int));
197 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
198 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
199 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
200 static WORD_LIST *expand_string_internal __P((char *, int));
201 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
202 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
204 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
205 static char *dequote_escapes __P((char *));
206 static char *make_quoted_char __P((int));
207 static WORD_LIST *quote_list __P((WORD_LIST *));
208 static char *remove_quoted_escapes __P((char *));
209 static char *remove_quoted_nulls __P((char *));
211 static int unquoted_substring __P((char *, char *));
212 static int unquoted_member __P((int, char *));
214 #if defined (ARRAY_VARS)
215 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
216 #endif
217 static int do_assignment_internal __P((const WORD_DESC *, int));
219 static char *string_extract_verbatim __P((char *, size_t, int *, char *));
220 static char *string_extract __P((char *, int *, char *, int));
221 static char *string_extract_double_quoted __P((char *, int *, int));
222 static inline char *string_extract_single_quoted __P((char *, int *));
223 static inline int skip_single_quoted __P((const char *, size_t, int));
224 static int skip_double_quoted __P((char *, size_t, int));
225 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
226 static char *extract_dollar_brace_string __P((char *, 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((ARRAY *, 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));
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));
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((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 WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
286 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
288 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
290 static WORD_LIST *word_list_split __P((WORD_LIST *));
292 static void exp_jump_to_top_level __P((int));
294 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
295 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
296 #ifdef BRACE_EXPANSION
297 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
298 #endif
299 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
300 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
302 /* **************************************************************** */
303 /* */
304 /* Utility Functions */
305 /* */
306 /* **************************************************************** */
308 #ifdef INCLUDE_UNUSED
309 static char *
310 quoted_substring (string, start, end)
311 char *string;
312 int start, end;
314 register int len, l;
315 register char *result, *s, *r;
317 len = end - start;
319 /* Move to string[start], skipping quoted characters. */
320 for (s = string, l = 0; *s && l < start; )
322 if (*s == CTLESC)
324 s++;
325 continue;
327 l++;
328 if (*s == 0)
329 break;
332 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
334 /* Copy LEN characters, including quote characters. */
335 s = string + l;
336 for (l = 0; l < len; s++)
338 if (*s == CTLESC)
339 *r++ = *s++;
340 *r++ = *s;
341 l++;
342 if (*s == 0)
343 break;
345 *r = '\0';
346 return result;
348 #endif
350 #ifdef INCLUDE_UNUSED
351 /* Return the length of S, skipping over quoted characters */
352 static int
353 quoted_strlen (s)
354 char *s;
356 register char *p;
357 int i;
359 i = 0;
360 for (p = s; *p; p++)
362 if (*p == CTLESC)
364 p++;
365 if (*p == 0)
366 return (i + 1);
368 i++;
371 return i;
373 #endif
375 /* Find the first occurrence of character C in string S, obeying shell
376 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
377 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
378 escaped with CTLESC are skipped. */
379 static char *
380 quoted_strchr (s, c, flags)
381 char *s;
382 int c, flags;
384 register char *p;
386 for (p = s; *p; p++)
388 if (((flags & ST_BACKSL) && *p == '\\')
389 || ((flags & ST_CTLESC) && *p == CTLESC))
391 p++;
392 if (*p == '\0')
393 return ((char *)NULL);
394 continue;
396 else if (*p == c)
397 return p;
399 return ((char *)NULL);
402 /* Return 1 if CHARACTER appears in an unquoted portion of
403 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
404 static int
405 unquoted_member (character, string)
406 int character;
407 char *string;
409 size_t slen;
410 int sindex, c;
411 DECLARE_MBSTATE;
413 slen = strlen (string);
414 sindex = 0;
415 while (c = string[sindex])
417 if (c == character)
418 return (1);
420 switch (c)
422 default:
423 ADVANCE_CHAR (string, slen, sindex);
424 break;
426 case '\\':
427 sindex++;
428 if (string[sindex])
429 ADVANCE_CHAR (string, slen, sindex);
430 break;
432 case '\'':
433 sindex = skip_single_quoted (string, slen, ++sindex);
434 break;
436 case '"':
437 sindex = skip_double_quoted (string, slen, ++sindex);
438 break;
441 return (0);
444 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
445 static int
446 unquoted_substring (substr, string)
447 char *substr, *string;
449 size_t slen;
450 int sindex, c, sublen;
451 DECLARE_MBSTATE;
453 if (substr == 0 || *substr == '\0')
454 return (0);
456 slen = strlen (string);
457 sublen = strlen (substr);
458 for (sindex = 0; c = string[sindex]; )
460 if (STREQN (string + sindex, substr, sublen))
461 return (1);
463 switch (c)
465 case '\\':
466 sindex++;
468 if (string[sindex])
469 ADVANCE_CHAR (string, slen, sindex);
470 break;
472 case '\'':
473 sindex = skip_single_quoted (string, slen, ++sindex);
474 break;
476 case '"':
477 sindex = skip_double_quoted (string, slen, ++sindex);
478 break;
480 default:
481 ADVANCE_CHAR (string, slen, sindex);
482 break;
485 return (0);
488 /* Most of the substitutions must be done in parallel. In order
489 to avoid using tons of unclear goto's, I have some functions
490 for manipulating malloc'ed strings. They all take INDX, a
491 pointer to an integer which is the offset into the string
492 where manipulation is taking place. They also take SIZE, a
493 pointer to an integer which is the current length of the
494 character array for this string. */
496 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
497 of space allocated to TARGET. SOURCE can be NULL, in which
498 case nothing happens. Gets rid of SOURCE by freeing it.
499 Returns TARGET in case the location has changed. */
500 INLINE char *
501 sub_append_string (source, target, indx, size)
502 char *source, *target;
503 int *indx, *size;
505 if (source)
507 int srclen, n;
509 srclen = STRLEN (source);
510 if (srclen >= (int)(*size - *indx))
512 n = srclen + *indx;
513 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
514 target = (char *)xrealloc (target, (*size = n));
517 FASTCOPY (source, target + *indx, srclen);
518 *indx += srclen;
519 target[*indx] = '\0';
521 free (source);
523 return (target);
526 #if 0
527 /* UNUSED */
528 /* Append the textual representation of NUMBER to TARGET.
529 INDX and SIZE are as in SUB_APPEND_STRING. */
530 char *
531 sub_append_number (number, target, indx, size)
532 intmax_t number;
533 int *indx, *size;
534 char *target;
536 char *temp;
538 temp = itos (number);
539 return (sub_append_string (temp, target, indx, size));
541 #endif
543 /* Extract a substring from STRING, starting at SINDEX and ending with
544 one of the characters in CHARLIST. Don't make the ending character
545 part of the string. Leave SINDEX pointing at the ending character.
546 Understand about backslashes in the string. If (flags & EX_VARNAME)
547 is non-zero, and array variables have been compiled into the shell,
548 everything between a `[' and a corresponding `]' is skipped over.
549 If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
550 update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
551 contain a closing character from CHARLIST. */
552 static char *
553 string_extract (string, sindex, charlist, flags)
554 char *string;
555 int *sindex;
556 char *charlist;
557 int flags;
559 register int c, i;
560 int found;
561 size_t slen;
562 char *temp;
563 DECLARE_MBSTATE;
565 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
566 i = *sindex;
567 found = 0;
568 while (c = string[i])
570 if (c == '\\')
572 if (string[i + 1])
573 i++;
574 else
575 break;
577 #if defined (ARRAY_VARS)
578 else if ((flags & EX_VARNAME) && c == '[')
580 int ni;
581 /* If this is an array subscript, skip over it and continue. */
582 ni = skipsubscript (string, i);
583 if (string[ni] == ']')
584 i = ni;
586 #endif
587 else if (MEMBER (c, charlist))
589 found = 1;
590 break;
593 ADVANCE_CHAR (string, slen, i);
596 /* If we had to have a matching delimiter and didn't find one, return an
597 error and let the caller deal with it. */
598 if ((flags & EX_REQMATCH) && found == 0)
600 *sindex = i;
601 return (&extract_string_error);
604 temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
605 *sindex = i;
607 return (temp);
610 /* Extract the contents of STRING as if it is enclosed in double quotes.
611 SINDEX, when passed in, is the offset of the character immediately
612 following the opening double quote; on exit, SINDEX is left pointing after
613 the closing double quote. If STRIPDQ is non-zero, unquoted double
614 quotes are stripped and the string is terminated by a null byte.
615 Backslashes between the embedded double quotes are processed. If STRIPDQ
616 is zero, an unquoted `"' terminates the string. */
617 static char *
618 string_extract_double_quoted (string, sindex, stripdq)
619 char *string;
620 int *sindex, stripdq;
622 size_t slen;
623 char *send;
624 int j, i, t;
625 unsigned char c;
626 char *temp, *ret; /* The new string we return. */
627 int pass_next, backquote, si; /* State variables for the machine. */
628 int dquote;
629 DECLARE_MBSTATE;
631 slen = strlen (string + *sindex) + *sindex;
632 send = string + slen;
634 pass_next = backquote = dquote = 0;
635 temp = (char *)xmalloc (1 + slen - *sindex);
637 j = 0;
638 i = *sindex;
639 while (c = string[i])
641 /* Process a character that was quoted by a backslash. */
642 if (pass_next)
644 /* Posix.2 sez:
646 ``The backslash shall retain its special meaning as an escape
647 character only when followed by one of the characters:
648 $ ` " \ <newline>''.
650 If STRIPDQ is zero, we handle the double quotes here and let
651 expand_word_internal handle the rest. If STRIPDQ is non-zero,
652 we have already been through one round of backslash stripping,
653 and want to strip these backslashes only if DQUOTE is non-zero,
654 indicating that we are inside an embedded double-quoted string. */
656 /* If we are in an embedded quoted string, then don't strip
657 backslashes before characters for which the backslash
658 retains its special meaning, but remove backslashes in
659 front of other characters. If we are not in an
660 embedded quoted string, don't strip backslashes at all.
661 This mess is necessary because the string was already
662 surrounded by double quotes (and sh has some really weird
663 quoting rules).
664 The returned string will be run through expansion as if
665 it were double-quoted. */
666 if ((stripdq == 0 && c != '"') ||
667 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
668 temp[j++] = '\\';
669 pass_next = 0;
671 add_one_character:
672 COPY_CHAR_I (temp, j, string, send, i);
673 continue;
676 /* A backslash protects the next character. The code just above
677 handles preserving the backslash in front of any character but
678 a double quote. */
679 if (c == '\\')
681 pass_next++;
682 i++;
683 continue;
686 /* Inside backquotes, ``the portion of the quoted string from the
687 initial backquote and the characters up to the next backquote
688 that is not preceded by a backslash, having escape characters
689 removed, defines that command''. */
690 if (backquote)
692 if (c == '`')
693 backquote = 0;
694 temp[j++] = c;
695 i++;
696 continue;
699 if (c == '`')
701 temp[j++] = c;
702 backquote++;
703 i++;
704 continue;
707 /* Pass everything between `$(' and the matching `)' or a quoted
708 ${ ... } pair through according to the Posix.2 specification. */
709 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
711 int free_ret = 1;
713 si = i + 2;
714 if (string[i + 1] == LPAREN)
715 ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_COMMAND); /*)*/
716 else
717 ret = extract_dollar_brace_string (string, &si, 1, 0);
719 temp[j++] = '$';
720 temp[j++] = string[i + 1];
722 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
723 is set. */
724 if (ret == 0 && no_longjmp_on_fatal_error)
726 free_ret = 0;
727 ret = string + i + 2;
730 for (t = 0; ret[t]; t++, j++)
731 temp[j] = ret[t];
732 temp[j] = string[si];
734 if (string[si])
736 j++;
737 i = si + 1;
739 else
740 i = si;
742 if (free_ret)
743 free (ret);
744 continue;
747 /* Add any character but a double quote to the quoted string we're
748 accumulating. */
749 if (c != '"')
750 goto add_one_character;
752 /* c == '"' */
753 if (stripdq)
755 dquote ^= 1;
756 i++;
757 continue;
760 break;
762 temp[j] = '\0';
764 /* Point to after the closing quote. */
765 if (c)
766 i++;
767 *sindex = i;
769 return (temp);
772 /* This should really be another option to string_extract_double_quoted. */
773 static int
774 skip_double_quoted (string, slen, sind)
775 char *string;
776 size_t slen;
777 int sind;
779 int c, i;
780 char *ret;
781 int pass_next, backquote, si;
782 DECLARE_MBSTATE;
784 pass_next = backquote = 0;
785 i = sind;
786 while (c = string[i])
788 if (pass_next)
790 pass_next = 0;
791 ADVANCE_CHAR (string, slen, i);
792 continue;
794 else if (c == '\\')
796 pass_next++;
797 i++;
798 continue;
800 else if (backquote)
802 if (c == '`')
803 backquote = 0;
804 ADVANCE_CHAR (string, slen, i);
805 continue;
807 else if (c == '`')
809 backquote++;
810 i++;
811 continue;
813 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
815 si = i + 2;
816 if (string[i + 1] == LPAREN)
817 ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
818 else
819 ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
821 i = si + 1;
822 continue;
824 else if (c != '"')
826 ADVANCE_CHAR (string, slen, i);
827 continue;
829 else
830 break;
833 if (c)
834 i++;
836 return (i);
839 /* Extract the contents of STRING as if it is enclosed in single quotes.
840 SINDEX, when passed in, is the offset of the character immediately
841 following the opening single quote; on exit, SINDEX is left pointing after
842 the closing single quote. */
843 static inline char *
844 string_extract_single_quoted (string, sindex)
845 char *string;
846 int *sindex;
848 register int i;
849 size_t slen;
850 char *t;
851 DECLARE_MBSTATE;
853 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
854 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
855 i = *sindex;
856 while (string[i] && string[i] != '\'')
857 ADVANCE_CHAR (string, slen, i);
859 t = substring (string, *sindex, i);
861 if (string[i])
862 i++;
863 *sindex = i;
865 return (t);
868 static inline int
869 skip_single_quoted (string, slen, sind)
870 const char *string;
871 size_t slen;
872 int sind;
874 register int c;
875 DECLARE_MBSTATE;
877 c = sind;
878 while (string[c] && string[c] != '\'')
879 ADVANCE_CHAR (string, slen, c);
881 if (string[c])
882 c++;
883 return c;
886 /* Just like string_extract, but doesn't hack backslashes or any of
887 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
888 static char *
889 string_extract_verbatim (string, slen, sindex, charlist)
890 char *string;
891 size_t slen;
892 int *sindex;
893 char *charlist;
895 register int i = *sindex;
896 #if defined (HANDLE_MULTIBYTE)
897 size_t clen;
898 wchar_t *wcharlist;
899 #endif
900 int c;
901 char *temp;
902 DECLARE_MBSTATE;
904 if (charlist[0] == '\'' && charlist[1] == '\0')
906 temp = string_extract_single_quoted (string, sindex);
907 --*sindex; /* leave *sindex at separator character */
908 return temp;
911 i = *sindex;
912 #if 0
913 /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
914 this only if MB_CUR_MAX > 1. */
915 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
916 #endif
917 #if defined (HANDLE_MULTIBYTE)
918 clen = strlen (charlist);
919 wcharlist = 0;
920 #endif
921 while (c = string[i])
923 #if defined (HANDLE_MULTIBYTE)
924 size_t mblength;
925 #endif
926 if (c == CTLESC)
928 i += 2;
929 continue;
932 #if defined (HANDLE_MULTIBYTE)
933 mblength = MBLEN (string + i, slen - i);
934 if (mblength > 1)
936 wchar_t wc;
937 mblength = mbtowc (&wc, string + i, slen - i);
938 if (MB_INVALIDCH (mblength))
940 if (MEMBER (c, charlist))
941 break;
943 else
945 if (wcharlist == 0)
947 size_t len;
948 len = mbstowcs (wcharlist, charlist, 0);
949 if (len == -1)
950 len = 0;
951 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
952 mbstowcs (wcharlist, charlist, len + 1);
955 if (wcschr (wcharlist, wc))
956 break;
959 else
960 #endif
961 if (MEMBER (c, charlist))
962 break;
964 ADVANCE_CHAR (string, slen, i);
967 #if defined (HANDLE_MULTIBYTE)
968 FREE (wcharlist);
969 #endif
971 temp = substring (string, *sindex, i);
972 *sindex = i;
974 return (temp);
977 /* Extract the $( construct in STRING, and return a new string.
978 Start extracting at (SINDEX) as if we had just seen "$(".
979 Make (SINDEX) get the position of the matching ")". ) */
980 char *
981 extract_command_subst (string, sindex)
982 char *string;
983 int *sindex;
985 return (extract_delimited_string (string, sindex, "$(", "(", ")", EX_COMMAND)); /*)*/
988 /* Extract the $[ construct in STRING, and return a new string. (])
989 Start extracting at (SINDEX) as if we had just seen "$[".
990 Make (SINDEX) get the position of the matching "]". */
991 char *
992 extract_arithmetic_subst (string, sindex)
993 char *string;
994 int *sindex;
996 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
999 #if defined (PROCESS_SUBSTITUTION)
1000 /* Extract the <( or >( construct in STRING, and return a new string.
1001 Start extracting at (SINDEX) as if we had just seen "<(".
1002 Make (SINDEX) get the position of the matching ")". */ /*))*/
1003 char *
1004 extract_process_subst (string, starter, sindex)
1005 char *string;
1006 char *starter;
1007 int *sindex;
1009 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1011 #endif /* PROCESS_SUBSTITUTION */
1013 #if defined (ARRAY_VARS)
1014 /* This can be fooled by unquoted right parens in the passed string. If
1015 each caller verifies that the last character in STRING is a right paren,
1016 we don't even need to call extract_delimited_string. */
1017 char *
1018 extract_array_assignment_list (string, sindex)
1019 char *string;
1020 int *sindex;
1022 int slen;
1023 char *ret;
1025 slen = strlen (string); /* ( */
1026 if (string[slen - 1] == ')')
1028 ret = substring (string, *sindex, slen - 1);
1029 *sindex = slen - 1;
1030 return ret;
1032 return 0;
1034 #endif
1036 /* Extract and create a new string from the contents of STRING, a
1037 character string delimited with OPENER and CLOSER. SINDEX is
1038 the address of an int describing the current offset in STRING;
1039 it should point to just after the first OPENER found. On exit,
1040 SINDEX gets the position of the last character of the matching CLOSER.
1041 If OPENER is more than a single character, ALT_OPENER, if non-null,
1042 contains a character string that can also match CLOSER and thus
1043 needs to be skipped. */
1044 static char *
1045 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1046 char *string;
1047 int *sindex;
1048 char *opener, *alt_opener, *closer;
1049 int flags;
1051 int i, c, si;
1052 size_t slen;
1053 char *t, *result;
1054 int pass_character, nesting_level, in_comment;
1055 int len_closer, len_opener, len_alt_opener;
1056 DECLARE_MBSTATE;
1058 slen = strlen (string + *sindex) + *sindex;
1059 len_opener = STRLEN (opener);
1060 len_alt_opener = STRLEN (alt_opener);
1061 len_closer = STRLEN (closer);
1063 pass_character = in_comment = 0;
1065 nesting_level = 1;
1066 i = *sindex;
1068 while (nesting_level)
1070 c = string[i];
1072 if (c == 0)
1073 break;
1075 if (in_comment)
1077 if (c == '\n')
1078 in_comment = 0;
1079 ADVANCE_CHAR (string, slen, i);
1080 continue;
1083 if (pass_character) /* previous char was backslash */
1085 pass_character = 0;
1086 ADVANCE_CHAR (string, slen, i);
1087 continue;
1090 /* Not exactly right yet; should handle shell metacharacters and
1091 multibyte characters, too. */
1092 if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
1094 in_comment = 1;
1095 ADVANCE_CHAR (string, slen, i);
1096 continue;
1099 if (c == CTLESC || c == '\\')
1101 pass_character++;
1102 i++;
1103 continue;
1106 /* Process a nested OPENER. */
1107 if (STREQN (string + i, opener, len_opener))
1109 si = i + len_opener;
1110 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
1111 i = si + 1;
1112 continue;
1115 /* Process a nested ALT_OPENER */
1116 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1118 si = i + len_alt_opener;
1119 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
1120 i = si + 1;
1121 continue;
1124 /* If the current substring terminates the delimited string, decrement
1125 the nesting level. */
1126 if (STREQN (string + i, closer, len_closer))
1128 i += len_closer - 1; /* move to last byte of the closer */
1129 nesting_level--;
1130 if (nesting_level == 0)
1131 break;
1134 /* Pass old-style command substitution through verbatim. */
1135 if (c == '`')
1137 si = i + 1;
1138 t = string_extract (string, &si, "`", flags|EX_NOALLOC);
1139 i = si + 1;
1140 continue;
1143 /* Pass single-quoted and double-quoted strings through verbatim. */
1144 if (c == '\'' || c == '"')
1146 si = i + 1;
1147 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1148 : skip_double_quoted (string, slen, si);
1149 continue;
1152 /* move past this character, which was not special. */
1153 ADVANCE_CHAR (string, slen, i);
1156 if (c == 0 && nesting_level)
1158 if (no_longjmp_on_fatal_error == 0)
1160 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1161 last_command_exit_value = EXECUTION_FAILURE;
1162 exp_jump_to_top_level (DISCARD);
1164 else
1166 *sindex = i;
1167 return (char *)NULL;
1171 si = i - *sindex - len_closer + 1;
1172 if (flags & EX_NOALLOC)
1173 result = (char *)NULL;
1174 else
1176 result = (char *)xmalloc (1 + si);
1177 strncpy (result, string + *sindex, si);
1178 result[si] = '\0';
1180 *sindex = i;
1182 return (result);
1185 /* Extract a parameter expansion expression within ${ and } from STRING.
1186 Obey the Posix.2 rules for finding the ending `}': count braces while
1187 skipping over enclosed quoted strings and command substitutions.
1188 SINDEX is the address of an int describing the current offset in STRING;
1189 it should point to just after the first `{' found. On exit, SINDEX
1190 gets the position of the matching `}'. QUOTED is non-zero if this
1191 occurs inside double quotes. */
1192 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1193 static char *
1194 extract_dollar_brace_string (string, sindex, quoted, flags)
1195 char *string;
1196 int *sindex, quoted, flags;
1198 register int i, c;
1199 size_t slen;
1200 int pass_character, nesting_level, si;
1201 char *result, *t;
1202 DECLARE_MBSTATE;
1204 pass_character = 0;
1205 nesting_level = 1;
1206 slen = strlen (string + *sindex) + *sindex;
1208 i = *sindex;
1209 while (c = string[i])
1211 if (pass_character)
1213 pass_character = 0;
1214 ADVANCE_CHAR (string, slen, i);
1215 continue;
1218 /* CTLESCs and backslashes quote the next character. */
1219 if (c == CTLESC || c == '\\')
1221 pass_character++;
1222 i++;
1223 continue;
1226 if (string[i] == '$' && string[i+1] == LBRACE)
1228 nesting_level++;
1229 i += 2;
1230 continue;
1233 if (c == RBRACE)
1235 nesting_level--;
1236 if (nesting_level == 0)
1237 break;
1238 i++;
1239 continue;
1242 /* Pass the contents of old-style command substitutions through
1243 verbatim. */
1244 if (c == '`')
1246 si = i + 1;
1247 t = string_extract (string, &si, "`", flags|EX_NOALLOC);
1248 i = si + 1;
1249 continue;
1252 /* Pass the contents of new-style command substitutions and
1253 arithmetic substitutions through verbatim. */
1254 if (string[i] == '$' && string[i+1] == LPAREN)
1256 si = i + 2;
1257 t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC|EX_COMMAND); /*)*/
1258 i = si + 1;
1259 continue;
1262 /* Pass the contents of single-quoted and double-quoted strings
1263 through verbatim. */
1264 if (c == '\'' || c == '"')
1266 si = i + 1;
1267 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1268 : skip_double_quoted (string, slen, si);
1269 /* skip_XXX_quoted leaves index one past close quote */
1270 continue;
1273 /* move past this character, which was not special. */
1274 ADVANCE_CHAR (string, slen, i);
1277 if (c == 0 && nesting_level)
1279 if (no_longjmp_on_fatal_error == 0)
1280 { /* { */
1281 report_error ("bad substitution: no closing `%s' in %s", "}", string);
1282 last_command_exit_value = EXECUTION_FAILURE;
1283 exp_jump_to_top_level (DISCARD);
1285 else
1287 *sindex = i;
1288 return ((char *)NULL);
1292 result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1293 *sindex = i;
1295 return (result);
1298 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1299 STRING, and returns a pointer to it. */
1300 char *
1301 de_backslash (string)
1302 char *string;
1304 register size_t slen;
1305 register int i, j, prev_i;
1306 DECLARE_MBSTATE;
1308 slen = strlen (string);
1309 i = j = 0;
1311 /* Loop copying string[i] to string[j], i >= j. */
1312 while (i < slen)
1314 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1315 string[i + 1] == '$'))
1316 i++;
1317 prev_i = i;
1318 ADVANCE_CHAR (string, slen, i);
1319 if (j < prev_i)
1320 do string[j++] = string[prev_i++]; while (prev_i < i);
1321 else
1322 j = i;
1324 string[j] = '\0';
1326 return (string);
1329 #if 0
1330 /*UNUSED*/
1331 /* Replace instances of \! in a string with !. */
1332 void
1333 unquote_bang (string)
1334 char *string;
1336 register int i, j;
1337 register char *temp;
1339 temp = (char *)xmalloc (1 + strlen (string));
1341 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1343 if (string[i] == '\\' && string[i + 1] == '!')
1345 temp[j] = '!';
1346 i++;
1349 strcpy (string, temp);
1350 free (temp);
1352 #endif
1354 #if defined (READLINE)
1355 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1356 an unclosed quoted string), or if the character at EINDEX is quoted
1357 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1358 single and double-quoted string parsing functions should not return an
1359 error if there are unclosed quotes or braces. The characters that this
1360 recognizes need to be the same as the contents of
1361 rl_completer_quote_characters. */
1363 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1366 char_is_quoted (string, eindex)
1367 char *string;
1368 int eindex;
1370 int i, pass_next, c;
1371 size_t slen;
1372 DECLARE_MBSTATE;
1374 slen = strlen (string);
1375 no_longjmp_on_fatal_error = 1;
1376 i = pass_next = 0;
1377 while (i <= eindex)
1379 c = string[i];
1381 if (pass_next)
1383 pass_next = 0;
1384 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1385 CQ_RETURN(1);
1386 ADVANCE_CHAR (string, slen, i);
1387 continue;
1389 else if (c == '\\')
1391 pass_next = 1;
1392 i++;
1393 continue;
1395 else if (c == '\'' || c == '"')
1397 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1398 : skip_double_quoted (string, slen, ++i);
1399 if (i > eindex)
1400 CQ_RETURN(1);
1401 /* no increment, the skip_xxx functions go one past end */
1403 else
1404 ADVANCE_CHAR (string, slen, i);
1407 CQ_RETURN(0);
1411 unclosed_pair (string, eindex, openstr)
1412 char *string;
1413 int eindex;
1414 char *openstr;
1416 int i, pass_next, openc, olen;
1417 size_t slen;
1418 DECLARE_MBSTATE;
1420 slen = strlen (string);
1421 olen = strlen (openstr);
1422 i = pass_next = openc = 0;
1423 while (i <= eindex)
1425 if (pass_next)
1427 pass_next = 0;
1428 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1429 return 0;
1430 ADVANCE_CHAR (string, slen, i);
1431 continue;
1433 else if (string[i] == '\\')
1435 pass_next = 1;
1436 i++;
1437 continue;
1439 else if (STREQN (string + i, openstr, olen))
1441 openc = 1 - openc;
1442 i += olen;
1444 else if (string[i] == '\'' || string[i] == '"')
1446 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1447 : skip_double_quoted (string, slen, i);
1448 if (i > eindex)
1449 return 0;
1451 else
1452 ADVANCE_CHAR (string, slen, i);
1454 return (openc);
1457 /* Skip characters in STRING until we find a character in DELIMS, and return
1458 the index of that character. START is the index into string at which we
1459 begin. This is similar in spirit to strpbrk, but it returns an index into
1460 STRING and takes a starting index. This little piece of code knows quite
1461 a lot of shell syntax. It's very similar to skip_double_quoted and other
1462 functions of that ilk. */
1464 skip_to_delim (string, start, delims)
1465 char *string;
1466 int start;
1467 char *delims;
1469 int i, pass_next, backq, si, c;
1470 size_t slen;
1471 char *temp;
1472 DECLARE_MBSTATE;
1474 slen = strlen (string + start) + start;
1475 no_longjmp_on_fatal_error = 1;
1476 i = start;
1477 pass_next = backq = 0;
1478 while (c = string[i])
1480 if (pass_next)
1482 pass_next = 0;
1483 if (c == 0)
1484 CQ_RETURN(i);
1485 ADVANCE_CHAR (string, slen, i);
1486 continue;
1488 else if (c == '\\')
1490 pass_next = 1;
1491 i++;
1492 continue;
1494 else if (backq)
1496 if (c == '`')
1497 backq = 0;
1498 ADVANCE_CHAR (string, slen, i);
1499 continue;
1501 else if (c == '`')
1503 backq = 1;
1504 i++;
1505 continue;
1507 else if (c == '\'' || c == '"')
1509 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1510 : skip_double_quoted (string, slen, ++i);
1511 /* no increment, the skip functions increment past the closing quote. */
1513 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1515 si = i + 2;
1516 if (string[si] == '\0')
1517 CQ_RETURN(si);
1519 if (string[i+1] == LPAREN)
1520 temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
1521 else
1522 temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
1523 i = si;
1524 if (string[i] == '\0') /* don't increment i past EOS in loop */
1525 break;
1526 i++;
1527 continue;
1529 else if (member (c, delims))
1530 break;
1531 else
1532 ADVANCE_CHAR (string, slen, i);
1535 CQ_RETURN(i);
1538 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1539 individual words. If DELIMS is NULL, the current value of $IFS is used
1540 to split the string, and the function follows the shell field splitting
1541 rules. SENTINEL is an index to look for. NWP, if non-NULL,
1542 gets the number of words in the returned list. CWP, if non-NULL, gets
1543 the index of the word containing SENTINEL. Non-whitespace chars in
1544 DELIMS delimit separate fields. */
1545 WORD_LIST *
1546 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1547 char *string;
1548 int slen;
1549 char *delims;
1550 int sentinel;
1551 int *nwp, *cwp;
1553 int ts, te, i, nw, cw, ifs_split;
1554 char *token, *d, *d2;
1555 WORD_LIST *ret, *tl;
1557 if (string == 0 || *string == '\0')
1559 if (nwp)
1560 *nwp = 0;
1561 if (cwp)
1562 *cwp = 0;
1563 return ((WORD_LIST *)NULL);
1566 d = (delims == 0) ? ifs_value : delims;
1567 ifs_split = delims == 0;
1569 /* Make d2 the non-whitespace characters in delims */
1570 d2 = 0;
1571 if (delims)
1573 size_t slength;
1574 #if defined (HANDLE_MULTIBYTE)
1575 size_t mblength = 1;
1576 #endif
1577 DECLARE_MBSTATE;
1579 slength = strlen (delims);
1580 d2 = (char *)xmalloc (slength + 1);
1581 i = ts = 0;
1582 while (delims[i])
1584 #if defined (HANDLE_MULTIBYTE)
1585 mbstate_t state_bak;
1586 state_bak = state;
1587 mblength = MBRLEN (delims + i, slength, &state);
1588 if (MB_INVALIDCH (mblength))
1589 state = state_bak;
1590 else if (mblength > 1)
1592 memcpy (d2 + ts, delims + i, mblength);
1593 ts += mblength;
1594 i += mblength;
1595 slength -= mblength;
1596 continue;
1598 #endif
1599 if (whitespace (delims[i]) == 0)
1600 d2[ts++] = delims[i];
1602 i++;
1603 slength--;
1605 d2[ts] = '\0';
1608 ret = (WORD_LIST *)NULL;
1610 /* Remove sequences of whitspace characters at the start of the string, as
1611 long as those characters are delimiters. */
1612 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1614 if (string[i] == '\0')
1615 return (ret);
1617 ts = i;
1618 nw = 0;
1619 cw = -1;
1620 while (1)
1622 te = skip_to_delim (string, ts, d);
1624 /* If we have a non-whitespace delimiter character, use it to make a
1625 separate field. This is just about what $IFS splitting does and
1626 is closer to the behavior of the shell parser. */
1627 if (ts == te && d2 && member (string[ts], d2))
1629 te = ts + 1;
1630 /* If we're using IFS splitting, the non-whitespace delimiter char
1631 and any additional IFS whitespace delimits a field. */
1632 if (ifs_split)
1633 while (member (string[te], d) && spctabnl (string[te]))
1634 te++;
1635 else
1636 while (member (string[te], d2))
1637 te++;
1640 token = substring (string, ts, te);
1642 ret = add_string_to_list (token, ret);
1643 free (token);
1644 nw++;
1646 if (sentinel >= ts && sentinel <= te)
1647 cw = nw;
1649 /* If the cursor is at whitespace just before word start, set the
1650 sentinel word to the current word. */
1651 if (cwp && cw == -1 && sentinel == ts-1)
1652 cw = nw;
1654 /* If the cursor is at whitespace between two words, make a new, empty
1655 word, add it before (well, after, since the list is in reverse order)
1656 the word we just added, and set the current word to that one. */
1657 if (cwp && cw == -1 && sentinel < ts)
1659 tl = make_word_list (make_word (""), ret->next);
1660 ret->next = tl;
1661 cw = nw;
1662 nw++;
1665 if (string[te] == 0)
1666 break;
1668 i = te;
1669 while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
1670 i++;
1672 if (string[i])
1673 ts = i;
1674 else
1675 break;
1678 /* Special case for SENTINEL at the end of STRING. If we haven't found
1679 the word containing SENTINEL yet, and the index we're looking for is at
1680 the end of STRING, add an additional null argument and set the current
1681 word pointer to that. */
1682 if (cwp && cw == -1 && sentinel >= slen)
1684 if (whitespace (string[sentinel - 1]))
1686 token = "";
1687 ret = add_string_to_list (token, ret);
1688 nw++;
1690 cw = nw;
1693 if (nwp)
1694 *nwp = nw;
1695 if (cwp)
1696 *cwp = cw;
1698 return (REVERSE_LIST (ret, WORD_LIST *));
1700 #endif /* READLINE */
1702 #if 0
1703 /* UNUSED */
1704 /* Extract the name of the variable to bind to from the assignment string. */
1705 char *
1706 assignment_name (string)
1707 char *string;
1709 int offset;
1710 char *temp;
1712 offset = assignment (string, 0);
1713 if (offset == 0)
1714 return (char *)NULL;
1715 temp = substring (string, 0, offset);
1716 return (temp);
1718 #endif
1720 /* **************************************************************** */
1721 /* */
1722 /* Functions to convert strings to WORD_LISTs and vice versa */
1723 /* */
1724 /* **************************************************************** */
1726 /* Return a single string of all the words in LIST. SEP is the separator
1727 to put between individual elements of LIST in the output string. */
1728 char *
1729 string_list_internal (list, sep)
1730 WORD_LIST *list;
1731 char *sep;
1733 register WORD_LIST *t;
1734 char *result, *r;
1735 int word_len, sep_len, result_size;
1737 if (list == 0)
1738 return ((char *)NULL);
1740 /* Short-circuit quickly if we don't need to separate anything. */
1741 if (list->next == 0)
1742 return (savestring (list->word->word));
1744 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1745 sep_len = STRLEN (sep);
1746 result_size = 0;
1748 for (t = list; t; t = t->next)
1750 if (t != list)
1751 result_size += sep_len;
1752 result_size += strlen (t->word->word);
1755 r = result = (char *)xmalloc (result_size + 1);
1757 for (t = list; t; t = t->next)
1759 if (t != list && sep_len)
1761 if (sep_len > 1)
1763 FASTCOPY (sep, r, sep_len);
1764 r += sep_len;
1766 else
1767 *r++ = sep[0];
1770 word_len = strlen (t->word->word);
1771 FASTCOPY (t->word->word, r, word_len);
1772 r += word_len;
1775 *r = '\0';
1776 return (result);
1779 /* Return a single string of all the words present in LIST, separating
1780 each word with a space. */
1781 char *
1782 string_list (list)
1783 WORD_LIST *list;
1785 return (string_list_internal (list, " "));
1788 /* Return a single string of all the words present in LIST, obeying the
1789 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1790 expansion [of $*] appears within a double quoted string, it expands
1791 to a single field with the value of each parameter separated by the
1792 first character of the IFS variable, or by a <space> if IFS is unset." */
1793 char *
1794 string_list_dollar_star (list)
1795 WORD_LIST *list;
1797 char *ret;
1798 #if defined (HANDLE_MULTIBYTE)
1799 # if defined (__GNUC__)
1800 char sep[MB_CUR_MAX + 1];
1801 # else
1802 char *sep = 0;
1803 # endif
1804 #else
1805 char sep[2];
1806 #endif
1808 #if defined (HANDLE_MULTIBYTE)
1809 # if !defined (__GNUC__)
1810 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1811 # endif /* !__GNUC__ */
1812 if (ifs_firstc_len == 1)
1814 sep[0] = ifs_firstc[0];
1815 sep[1] = '\0';
1817 else
1819 memcpy (sep, ifs_firstc, ifs_firstc_len);
1820 sep[ifs_firstc_len] = '\0';
1822 #else
1823 sep[0] = ifs_firstc;
1824 sep[1] = '\0';
1825 #endif
1827 ret = string_list_internal (list, sep);
1828 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1829 free (sep);
1830 #endif
1831 return ret;
1834 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1835 is non-zero, the $@ appears within double quotes, and we should quote
1836 the list before converting it into a string. If IFS is unset, and the
1837 word is not quoted, we just need to quote CTLESC and CTLNUL characters
1838 in the words in the list, because the default value of $IFS is
1839 <space><tab><newline>, IFS characters in the words in the list should
1840 also be split. If IFS is null, and the word is not quoted, we need
1841 to quote the words in the list to preserve the positional parameters
1842 exactly. */
1843 char *
1844 string_list_dollar_at (list, quoted)
1845 WORD_LIST *list;
1846 int quoted;
1848 char *ifs, *ret;
1849 #if defined (HANDLE_MULTIBYTE)
1850 # if defined (__GNUC__)
1851 char sep[MB_CUR_MAX + 1];
1852 # else
1853 char *sep = 0;
1854 # endif /* !__GNUC__ */
1855 #else
1856 char sep[2];
1857 #endif
1858 WORD_LIST *tlist;
1860 /* XXX this could just be ifs = ifs_value; */
1861 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
1863 #if defined (HANDLE_MULTIBYTE)
1864 # if !defined (__GNUC__)
1865 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1866 # endif /* !__GNUC__ */
1867 if (ifs && *ifs)
1869 if (ifs_firstc_len == 1)
1871 sep[0] = ifs_firstc[0];
1872 sep[1] = '\0';
1874 else
1876 memcpy (sep, ifs_firstc, ifs_firstc_len);
1877 sep[ifs_firstc_len] = '\0';
1880 else
1882 sep[0] = ' ';
1883 sep[1] = '\0';
1885 #else
1886 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1887 sep[1] = '\0';
1888 #endif
1890 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1891 ? quote_list (list)
1892 : list_quote_escapes (list);
1894 ret = string_list_internal (tlist, sep);
1895 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1896 free (sep);
1897 #endif
1898 return ret;
1901 /* Return the list of words present in STRING. Separate the string into
1902 words at any of the characters found in SEPARATORS. If QUOTED is
1903 non-zero then word in the list will have its quoted flag set, otherwise
1904 the quoted flag is left as make_word () deemed fit.
1906 This obeys the P1003.2 word splitting semantics. If `separators' is
1907 exactly <space><tab><newline>, then the splitting algorithm is that of
1908 the Bourne shell, which treats any sequence of characters from `separators'
1909 as a delimiter. If IFS is unset, which results in `separators' being set
1910 to "", no splitting occurs. If separators has some other value, the
1911 following rules are applied (`IFS white space' means zero or more
1912 occurrences of <space>, <tab>, or <newline>, as long as those characters
1913 are in `separators'):
1915 1) IFS white space is ignored at the start and the end of the
1916 string.
1917 2) Each occurrence of a character in `separators' that is not
1918 IFS white space, along with any adjacent occurrences of
1919 IFS white space delimits a field.
1920 3) Any nonzero-length sequence of IFS white space delimits a field.
1923 /* BEWARE! list_string strips null arguments. Don't call it twice and
1924 expect to have "" preserved! */
1926 /* This performs word splitting and quoted null character removal on
1927 STRING. */
1928 #define issep(c) \
1929 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
1930 : (c) == (separators)[0]) \
1931 : 0)
1933 WORD_LIST *
1934 list_string (string, separators, quoted)
1935 register char *string, *separators;
1936 int quoted;
1938 WORD_LIST *result;
1939 WORD_DESC *t;
1940 char *current_word, *s;
1941 int sindex, sh_style_split, whitesep;
1942 size_t slen;
1944 if (!string || !*string)
1945 return ((WORD_LIST *)NULL);
1947 sh_style_split = separators && separators[0] == ' ' &&
1948 separators[1] == '\t' &&
1949 separators[2] == '\n' &&
1950 separators[3] == '\0';
1952 slen = 0;
1953 /* Remove sequences of whitespace at the beginning of STRING, as
1954 long as those characters appear in IFS. Do not do this if
1955 STRING is quoted or if there are no separator characters. */
1956 if (!quoted || !separators || !*separators)
1958 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1960 if (!*s)
1961 return ((WORD_LIST *)NULL);
1963 string = s;
1966 /* OK, now STRING points to a word that does not begin with white space.
1967 The splitting algorithm is:
1968 extract a word, stopping at a separator
1969 skip sequences of spc, tab, or nl as long as they are separators
1970 This obeys the field splitting rules in Posix.2. */
1971 slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
1972 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1974 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
1975 unless multibyte chars are possible. */
1976 current_word = string_extract_verbatim (string, slen, &sindex, separators);
1977 if (current_word == 0)
1978 break;
1980 /* If we have a quoted empty string, add a quoted null argument. We
1981 want to preserve the quoted null character iff this is a quoted
1982 empty string; otherwise the quoted null characters are removed
1983 below. */
1984 if (QUOTED_NULL (current_word))
1986 t = alloc_word_desc ();
1987 t->word = make_quoted_char ('\0');
1988 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
1989 result = make_word_list (t, result);
1991 else if (current_word[0] != '\0')
1993 /* If we have something, then add it regardless. However,
1994 perform quoted null character removal on the current word. */
1995 remove_quoted_nulls (current_word);
1996 result = add_string_to_list (current_word, result);
1997 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
1998 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1999 result->word->flags |= W_QUOTED;
2002 /* If we're not doing sequences of separators in the traditional
2003 Bourne shell style, then add a quoted null argument. */
2004 else if (!sh_style_split && !spctabnl (string[sindex]))
2006 t = alloc_word_desc ();
2007 t->word = make_quoted_char ('\0');
2008 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2009 result = make_word_list (t, result);
2012 free (current_word);
2014 /* Note whether or not the separator is IFS whitespace, used later. */
2015 whitesep = string[sindex] && spctabnl (string[sindex]);
2017 /* Move past the current separator character. */
2018 if (string[sindex])
2020 DECLARE_MBSTATE;
2021 ADVANCE_CHAR (string, slen, sindex);
2024 /* Now skip sequences of space, tab, or newline characters if they are
2025 in the list of separators. */
2026 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2027 sindex++;
2029 /* If the first separator was IFS whitespace and the current character
2030 is a non-whitespace IFS character, it should be part of the current
2031 field delimiter, not a separate delimiter that would result in an
2032 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2033 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2035 sindex++;
2036 /* An IFS character that is not IFS white space, along with any
2037 adjacent IFS white space, shall delimit a field. (SUSv3) */
2038 while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2039 sindex++;
2042 return (REVERSE_LIST (result, WORD_LIST *));
2045 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2046 ENDPTR is set to the first character after the word. This is used by
2047 the `read' builtin. This is never called with SEPARATORS != $IFS;
2048 it should be simplified.
2050 XXX - this function is very similar to list_string; they should be
2051 combined - XXX */
2052 char *
2053 get_word_from_string (stringp, separators, endptr)
2054 char **stringp, *separators, **endptr;
2056 register char *s;
2057 char *current_word;
2058 int sindex, sh_style_split, whitesep;
2059 size_t slen;
2061 if (!stringp || !*stringp || !**stringp)
2062 return ((char *)NULL);
2064 s = *stringp;
2066 sh_style_split = separators && separators[0] == ' ' &&
2067 separators[1] == '\t' &&
2068 separators[2] == '\n' &&
2069 separators[3] == '\0';
2071 slen = 0;
2073 /* Remove sequences of whitespace at the beginning of STRING, as
2074 long as those characters appear in IFS. */
2075 if (sh_style_split || !separators || !*separators)
2077 for (; *s && spctabnl (*s) && isifs (*s); s++);
2079 /* If the string is nothing but whitespace, update it and return. */
2080 if (!*s)
2082 *stringp = s;
2083 if (endptr)
2084 *endptr = s;
2085 return ((char *)NULL);
2089 /* OK, S points to a word that does not begin with white space.
2090 Now extract a word, stopping at a separator, save a pointer to
2091 the first character after the word, then skip sequences of spc,
2092 tab, or nl as long as they are separators.
2094 This obeys the field splitting rules in Posix.2. */
2095 sindex = 0;
2096 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2097 unless multibyte chars are possible. */
2098 slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2099 current_word = string_extract_verbatim (s, slen, &sindex, separators);
2101 /* Set ENDPTR to the first character after the end of the word. */
2102 if (endptr)
2103 *endptr = s + sindex;
2105 /* Note whether or not the separator is IFS whitespace, used later. */
2106 whitesep = s[sindex] && spctabnl (s[sindex]);
2108 /* Move past the current separator character. */
2109 if (s[sindex])
2111 DECLARE_MBSTATE;
2112 ADVANCE_CHAR (s, slen, sindex);
2115 /* Now skip sequences of space, tab, or newline characters if they are
2116 in the list of separators. */
2117 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2118 sindex++;
2120 /* If the first separator was IFS whitespace and the current character is
2121 a non-whitespace IFS character, it should be part of the current field
2122 delimiter, not a separate delimiter that would result in an empty field.
2123 Look at POSIX.2, 3.6.5, (3)(b). */
2124 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2126 sindex++;
2127 /* An IFS character that is not IFS white space, along with any adjacent
2128 IFS white space, shall delimit a field. */
2129 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2130 sindex++;
2133 /* Update STRING to point to the next field. */
2134 *stringp = s + sindex;
2135 return (current_word);
2138 /* Remove IFS white space at the end of STRING. Start at the end
2139 of the string and walk backwards until the beginning of the string
2140 or we find a character that's not IFS white space and not CTLESC.
2141 Only let CTLESC escape a white space character if SAW_ESCAPE is
2142 non-zero. */
2143 char *
2144 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2145 char *string, *separators;
2146 int saw_escape;
2148 char *s;
2150 s = string + STRLEN (string) - 1;
2151 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2152 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2153 s--;
2154 *++s = '\0';
2155 return string;
2158 #if 0
2159 /* UNUSED */
2160 /* Split STRING into words at whitespace. Obeys shell-style quoting with
2161 backslashes, single and double quotes. */
2162 WORD_LIST *
2163 list_string_with_quotes (string)
2164 char *string;
2166 WORD_LIST *list;
2167 char *token, *s;
2168 size_t s_len;
2169 int c, i, tokstart, len;
2171 for (s = string; s && *s && spctabnl (*s); s++)
2173 if (s == 0 || *s == 0)
2174 return ((WORD_LIST *)NULL);
2176 s_len = strlen (s);
2177 tokstart = i = 0;
2178 list = (WORD_LIST *)NULL;
2179 while (1)
2181 c = s[i];
2182 if (c == '\\')
2184 i++;
2185 if (s[i])
2186 i++;
2188 else if (c == '\'')
2189 i = skip_single_quoted (s, s_len, ++i);
2190 else if (c == '"')
2191 i = skip_double_quoted (s, s_len, ++i);
2192 else if (c == 0 || spctabnl (c))
2194 /* We have found the end of a token. Make a word out of it and
2195 add it to the word list. */
2196 token = substring (s, tokstart, i);
2197 list = add_string_to_list (token, list);
2198 free (token);
2199 while (spctabnl (s[i]))
2200 i++;
2201 if (s[i])
2202 tokstart = i;
2203 else
2204 break;
2206 else
2207 i++; /* normal character */
2209 return (REVERSE_LIST (list, WORD_LIST *));
2211 #endif
2213 /********************************************************/
2214 /* */
2215 /* Functions to perform assignment statements */
2216 /* */
2217 /********************************************************/
2219 #if defined (ARRAY_VARS)
2220 static SHELL_VAR *
2221 do_compound_assignment (name, value, flags)
2222 char *name, *value;
2223 int flags;
2225 SHELL_VAR *v;
2226 int mklocal;
2227 WORD_LIST *list;
2229 mklocal = flags & ASS_MKLOCAL;
2231 if (mklocal && variable_context)
2233 list = expand_compound_array_assignment (value, flags);
2234 v = find_variable (name);
2235 if (v == 0 || array_p (v) == 0 || v->context != variable_context)
2236 v = make_local_array_variable (name);
2237 assign_compound_array_list (v, list, flags);
2239 else
2240 v = assign_array_from_string (name, value, flags);
2242 return (v);
2244 #endif
2246 /* Given STRING, an assignment string, get the value of the right side
2247 of the `=', and bind it to the left side. If EXPAND is true, then
2248 perform parameter expansion, command substitution, and arithmetic
2249 expansion on the right-hand side. Perform tilde expansion in any
2250 case. Do not perform word splitting on the result of expansion. */
2251 static int
2252 do_assignment_internal (word, expand)
2253 const WORD_DESC *word;
2254 int expand;
2256 int offset, tlen, appendop, assign_list, aflags;
2257 char *name, *value;
2258 SHELL_VAR *entry;
2259 #if defined (ARRAY_VARS)
2260 char *t;
2261 int ni;
2262 #endif
2263 const char *string;
2265 if (word == 0 || word->word == 0)
2266 return 0;
2268 appendop = assign_list = aflags = 0;
2269 string = word->word;
2270 offset = assignment (string, 0);
2271 name = savestring (string);
2272 value = (char *)NULL;
2274 if (name[offset] == '=')
2276 char *temp;
2278 if (name[offset - 1] == '+')
2280 appendop = 1;
2281 name[offset - 1] = '\0';
2284 name[offset] = 0; /* might need this set later */
2285 temp = name + offset + 1;
2286 tlen = STRLEN (temp);
2288 #if defined (ARRAY_VARS)
2289 if (expand && (word->flags & W_COMPASSIGN))
2291 assign_list = ni = 1;
2292 value = extract_array_assignment_list (temp, &ni);
2294 else
2295 #endif
2297 if (expand && temp[0])
2298 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2299 else
2300 value = savestring (temp);
2303 if (value == 0)
2305 value = (char *)xmalloc (1);
2306 value[0] = '\0';
2309 if (echo_command_at_execute)
2311 if (appendop)
2312 name[offset - 1] = '+';
2313 xtrace_print_assignment (name, value, assign_list, 1);
2314 if (appendop)
2315 name[offset - 1] = '\0';
2318 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
2320 if (appendop)
2321 aflags |= ASS_APPEND;
2323 #if defined (ARRAY_VARS)
2324 if (t = xstrchr (name, '[')) /*]*/
2326 if (assign_list)
2328 report_error (_("%s: cannot assign list to array member"), name);
2329 ASSIGN_RETURN (0);
2331 entry = assign_array_element (name, value, aflags);
2332 if (entry == 0)
2333 ASSIGN_RETURN (0);
2335 else if (assign_list)
2337 if (word->flags & W_ASSIGNARG)
2338 aflags |= ASS_MKLOCAL;
2339 entry = do_compound_assignment (name, value, aflags);
2341 else
2342 #endif /* ARRAY_VARS */
2343 entry = bind_variable (name, value, aflags);
2345 stupidly_hack_special_variables (name);
2347 if (entry)
2348 VUNSETATTR (entry, att_invisible);
2350 /* Return 1 if the assignment seems to have been performed correctly. */
2351 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2354 /* Perform the assignment statement in STRING, and expand the
2355 right side by doing tilde, command and parameter expansion. */
2357 do_assignment (string)
2358 char *string;
2360 WORD_DESC td;
2362 td.flags = W_ASSIGNMENT;
2363 td.word = string;
2365 return do_assignment_internal (&td, 1);
2369 do_word_assignment (word)
2370 WORD_DESC *word;
2372 return do_assignment_internal (word, 1);
2375 /* Given STRING, an assignment string, get the value of the right side
2376 of the `=', and bind it to the left side. Do not perform any word
2377 expansions on the right hand side. */
2379 do_assignment_no_expand (string)
2380 char *string;
2382 WORD_DESC td;
2384 td.flags = W_ASSIGNMENT;
2385 td.word = string;
2387 return (do_assignment_internal (&td, 0));
2390 /***************************************************
2392 * Functions to manage the positional parameters *
2394 ***************************************************/
2396 /* Return the word list that corresponds to `$*'. */
2397 WORD_LIST *
2398 list_rest_of_args ()
2400 register WORD_LIST *list, *args;
2401 int i;
2403 /* Break out of the loop as soon as one of the dollar variables is null. */
2404 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2405 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2407 for (args = rest_of_args; args; args = args->next)
2408 list = make_word_list (make_bare_word (args->word->word), list);
2410 return (REVERSE_LIST (list, WORD_LIST *));
2414 number_of_args ()
2416 register WORD_LIST *list;
2417 int n;
2419 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2421 for (list = rest_of_args; list; list = list->next)
2422 n++;
2423 return n;
2426 /* Return the value of a positional parameter. This handles values > 10. */
2427 char *
2428 get_dollar_var_value (ind)
2429 intmax_t ind;
2431 char *temp;
2432 WORD_LIST *p;
2434 if (ind < 10)
2435 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2436 else /* We want something like ${11} */
2438 ind -= 10;
2439 for (p = rest_of_args; p && ind--; p = p->next)
2441 temp = p ? savestring (p->word->word) : (char *)NULL;
2443 return (temp);
2446 /* Make a single large string out of the dollar digit variables,
2447 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2448 case of "$*" with respect to IFS. */
2449 char *
2450 string_rest_of_args (dollar_star)
2451 int dollar_star;
2453 register WORD_LIST *list;
2454 char *string;
2456 list = list_rest_of_args ();
2457 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2458 dispose_words (list);
2459 return (string);
2462 /* Return a string containing the positional parameters from START to
2463 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2464 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2465 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2466 no quoting chars are added. */
2467 static char *
2468 pos_params (string, start, end, quoted)
2469 char *string;
2470 int start, end, quoted;
2472 WORD_LIST *save, *params, *h, *t;
2473 char *ret;
2474 int i;
2476 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2477 if (start == end)
2478 return ((char *)NULL);
2480 save = params = list_rest_of_args ();
2481 if (save == 0)
2482 return ((char *)NULL);
2484 for (i = 1; params && i < start; i++)
2485 params = params->next;
2486 if (params == 0)
2487 return ((char *)NULL);
2488 for (h = t = params; params && i < end; i++)
2490 t = params;
2491 params = params->next;
2494 t->next = (WORD_LIST *)NULL;
2495 if (string[0] == '*')
2497 if (quoted & Q_DOUBLE_QUOTES)
2498 ret = string_list_dollar_star (quote_list (h));
2499 else if (quoted & Q_HERE_DOCUMENT)
2500 ret = string_list (quote_list (h));
2501 else
2502 ret = string_list (h);
2504 else
2505 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
2506 if (t != params)
2507 t->next = params;
2509 dispose_words (save);
2510 return (ret);
2513 /******************************************************************/
2514 /* */
2515 /* Functions to expand strings to strings or WORD_LISTs */
2516 /* */
2517 /******************************************************************/
2519 #if defined (PROCESS_SUBSTITUTION)
2520 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
2521 #else
2522 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
2523 #endif
2525 /* If there are any characters in STRING that require full expansion,
2526 then call FUNC to expand STRING; otherwise just perform quote
2527 removal if necessary. This returns a new string. */
2528 static char *
2529 expand_string_if_necessary (string, quoted, func)
2530 char *string;
2531 int quoted;
2532 EXPFUNC *func;
2534 WORD_LIST *list;
2535 size_t slen;
2536 int i, saw_quote;
2537 char *ret;
2538 DECLARE_MBSTATE;
2540 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
2541 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
2542 i = saw_quote = 0;
2543 while (string[i])
2545 if (EXP_CHAR (string[i]))
2546 break;
2547 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2548 saw_quote = 1;
2549 ADVANCE_CHAR (string, slen, i);
2552 if (string[i])
2554 list = (*func) (string, quoted);
2555 if (list)
2557 ret = string_list (list);
2558 dispose_words (list);
2560 else
2561 ret = (char *)NULL;
2563 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2564 ret = string_quote_removal (string, quoted);
2565 else
2566 ret = savestring (string);
2568 return ret;
2571 static inline char *
2572 expand_string_to_string_internal (string, quoted, func)
2573 char *string;
2574 int quoted;
2575 EXPFUNC *func;
2577 WORD_LIST *list;
2578 char *ret;
2580 if (string == 0 || *string == '\0')
2581 return ((char *)NULL);
2583 list = (*func) (string, quoted);
2584 if (list)
2586 ret = string_list (list);
2587 dispose_words (list);
2589 else
2590 ret = (char *)NULL;
2592 return (ret);
2595 char *
2596 expand_string_to_string (string, quoted)
2597 char *string;
2598 int quoted;
2600 return (expand_string_to_string_internal (string, quoted, expand_string));
2603 char *
2604 expand_string_unsplit_to_string (string, quoted)
2605 char *string;
2606 int quoted;
2608 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2611 char *
2612 expand_assignment_string_to_string (string, quoted)
2613 char *string;
2614 int quoted;
2616 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
2619 char *
2620 expand_arith_string (string, quoted)
2621 char *string;
2623 return (expand_string_if_necessary (string, quoted, expand_string));
2626 #if defined (COND_COMMAND)
2627 /* Just remove backslashes in STRING. Returns a new string. */
2628 char *
2629 remove_backslashes (string)
2630 char *string;
2632 char *r, *ret, *s;
2634 r = ret = (char *)xmalloc (strlen (string) + 1);
2635 for (s = string; s && *s; )
2637 if (*s == '\\')
2638 s++;
2639 if (*s == 0)
2640 break;
2641 *r++ = *s++;
2643 *r = '\0';
2644 return ret;
2647 /* This needs better error handling. */
2648 /* Expand W for use as an argument to a unary or binary operator in a
2649 [[...]] expression. If SPECIAL is nonzero, this is the rhs argument
2650 to the != or == operator, and should be treated as a pattern. In
2651 this case, we quote the string specially for the globbing code. The
2652 caller is responsible for removing the backslashes if the unquoted
2653 words is needed later. */
2654 char *
2655 cond_expand_word (w, special)
2656 WORD_DESC *w;
2657 int special;
2659 char *r, *p;
2660 WORD_LIST *l;
2662 if (w->word == 0 || w->word[0] == '\0')
2663 return ((char *)NULL);
2665 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2666 if (l)
2668 if (special == 0)
2670 dequote_list (l);
2671 r = string_list (l);
2673 else
2675 p = string_list (l);
2676 r = quote_string_for_globbing (p, QGLOB_CVTNULL);
2677 free (p);
2679 dispose_words (l);
2681 else
2682 r = (char *)NULL;
2684 return r;
2686 #endif
2688 /* Call expand_word_internal to expand W and handle error returns.
2689 A convenience function for functions that don't want to handle
2690 any errors or free any memory before aborting. */
2691 static WORD_LIST *
2692 call_expand_word_internal (w, q, i, c, e)
2693 WORD_DESC *w;
2694 int q, i, *c, *e;
2696 WORD_LIST *result;
2698 result = expand_word_internal (w, q, i, c, e);
2699 if (result == &expand_word_error || result == &expand_word_fatal)
2701 /* By convention, each time this error is returned, w->word has
2702 already been freed (it sometimes may not be in the fatal case,
2703 but that doesn't result in a memory leak because we're going
2704 to exit in most cases). */
2705 w->word = (char *)NULL;
2706 last_command_exit_value = EXECUTION_FAILURE;
2707 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2708 /* NOTREACHED */
2710 else
2711 return (result);
2714 /* Perform parameter expansion, command substitution, and arithmetic
2715 expansion on STRING, as if it were a word. Leave the result quoted. */
2716 static WORD_LIST *
2717 expand_string_internal (string, quoted)
2718 char *string;
2719 int quoted;
2721 WORD_DESC td;
2722 WORD_LIST *tresult;
2724 if (string == 0 || *string == 0)
2725 return ((WORD_LIST *)NULL);
2727 td.flags = 0;
2728 td.word = savestring (string);
2730 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2732 FREE (td.word);
2733 return (tresult);
2736 /* Expand STRING by performing parameter expansion, command substitution,
2737 and arithmetic expansion. Dequote the resulting WORD_LIST before
2738 returning it, but do not perform word splitting. The call to
2739 remove_quoted_nulls () is in here because word splitting normally
2740 takes care of quote removal. */
2741 WORD_LIST *
2742 expand_string_unsplit (string, quoted)
2743 char *string;
2744 int quoted;
2746 WORD_LIST *value;
2748 if (string == 0 || *string == '\0')
2749 return ((WORD_LIST *)NULL);
2751 expand_no_split_dollar_star = 1;
2752 value = expand_string_internal (string, quoted);
2753 expand_no_split_dollar_star = 0;
2755 if (value)
2757 if (value->word)
2759 remove_quoted_nulls (value->word->word);
2760 value->word->flags &= ~W_HASQUOTEDNULL;
2762 dequote_list (value);
2764 return (value);
2767 /* Expand the rhs of an assignment statement */
2768 WORD_LIST *
2769 expand_string_assignment (string, quoted)
2770 char *string;
2771 int quoted;
2773 WORD_DESC td;
2774 WORD_LIST *value;
2776 if (string == 0 || *string == '\0')
2777 return ((WORD_LIST *)NULL);
2779 expand_no_split_dollar_star = 1;
2781 td.flags = W_ASSIGNRHS;
2782 td.word = savestring (string);
2783 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2784 FREE (td.word);
2786 expand_no_split_dollar_star = 0;
2788 if (value)
2790 if (value->word)
2792 remove_quoted_nulls (value->word->word);
2793 value->word->flags &= ~W_HASQUOTEDNULL;
2795 dequote_list (value);
2797 return (value);
2801 /* Expand one of the PS? prompt strings. This is a sort of combination of
2802 expand_string_unsplit and expand_string_internal, but returns the
2803 passed string when an error occurs. Might want to trap other calls
2804 to jump_to_top_level here so we don't endlessly loop. */
2805 WORD_LIST *
2806 expand_prompt_string (string, quoted)
2807 char *string;
2808 int quoted;
2810 WORD_LIST *value;
2811 WORD_DESC td;
2813 if (string == 0 || *string == 0)
2814 return ((WORD_LIST *)NULL);
2816 td.flags = 0;
2817 td.word = savestring (string);
2819 no_longjmp_on_fatal_error = 1;
2820 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2821 no_longjmp_on_fatal_error = 0;
2823 if (value == &expand_word_error || value == &expand_word_fatal)
2825 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
2826 return value;
2828 FREE (td.word);
2829 if (value)
2831 if (value->word)
2833 remove_quoted_nulls (value->word->word);
2834 value->word->flags &= ~W_HASQUOTEDNULL;
2836 dequote_list (value);
2838 return (value);
2841 /* Expand STRING just as if you were expanding a word, but do not dequote
2842 the resultant WORD_LIST. This is called only from within this file,
2843 and is used to correctly preserve quoted characters when expanding
2844 things like ${1+"$@"}. This does parameter expansion, command
2845 substitution, arithmetic expansion, and word splitting. */
2846 static WORD_LIST *
2847 expand_string_leave_quoted (string, quoted)
2848 char *string;
2849 int quoted;
2851 WORD_LIST *tlist;
2852 WORD_LIST *tresult;
2854 if (string == 0 || *string == '\0')
2855 return ((WORD_LIST *)NULL);
2857 tlist = expand_string_internal (string, quoted);
2859 if (tlist)
2861 tresult = word_list_split (tlist);
2862 dispose_words (tlist);
2863 return (tresult);
2865 return ((WORD_LIST *)NULL);
2868 /* This does not perform word splitting or dequote the WORD_LIST
2869 it returns. */
2870 static WORD_LIST *
2871 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
2872 char *string;
2873 int quoted, *dollar_at_p, *has_dollar_at;
2875 WORD_DESC td;
2876 WORD_LIST *tresult;
2878 if (string == 0 || *string == '\0')
2879 return (WORD_LIST *)NULL;
2881 td.flags = 0;
2882 td.word = string;
2883 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
2884 return (tresult);
2887 /* Expand STRING just as if you were expanding a word. This also returns
2888 a list of words. Note that filename globbing is *NOT* done for word
2889 or string expansion, just when the shell is expanding a command. This
2890 does parameter expansion, command substitution, arithmetic expansion,
2891 and word splitting. Dequote the resultant WORD_LIST before returning. */
2892 WORD_LIST *
2893 expand_string (string, quoted)
2894 char *string;
2895 int quoted;
2897 WORD_LIST *result;
2899 if (string == 0 || *string == '\0')
2900 return ((WORD_LIST *)NULL);
2902 result = expand_string_leave_quoted (string, quoted);
2903 return (result ? dequote_list (result) : result);
2906 /***************************************************
2908 * Functions to handle quoting chars *
2910 ***************************************************/
2912 /* Conventions:
2914 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
2915 The parser passes CTLNUL as CTLESC CTLNUL. */
2917 /* Quote escape characters in string s, but no other characters. This is
2918 used to protect CTLESC and CTLNUL in variable values from the rest of
2919 the word expansion process after the variable is expanded. */
2920 char *
2921 quote_escapes (string)
2922 char *string;
2924 register char *s, *t;
2925 size_t slen;
2926 char *result, *send;
2927 DECLARE_MBSTATE;
2929 slen = strlen (string);
2930 send = string + slen;
2932 t = result = (char *)xmalloc ((slen * 2) + 1);
2933 s = string;
2935 while (*s)
2937 if (*s == CTLESC || *s == CTLNUL)
2938 *t++ = CTLESC;
2939 COPY_CHAR_P (t, s, send);
2941 *t = '\0';
2942 return (result);
2945 static WORD_LIST *
2946 list_quote_escapes (list)
2947 WORD_LIST *list;
2949 register WORD_LIST *w;
2950 char *t;
2952 for (w = list; w; w = w->next)
2954 t = w->word->word;
2955 w->word->word = quote_escapes (t);
2956 free (t);
2958 return list;
2961 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
2963 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2964 This is necessary to make unquoted CTLESC and CTLNUL characters in the
2965 data stream pass through properly.
2967 We need to remove doubled CTLESC characters inside quoted strings before
2968 quoting the entire string, so we do not double the number of CTLESC
2969 characters.
2971 Also used by parts of the pattern substitution code. */
2972 static char *
2973 dequote_escapes (string)
2974 char *string;
2976 register char *s, *t;
2977 size_t slen;
2978 char *result, *send;
2979 DECLARE_MBSTATE;
2981 if (string == 0)
2982 return string;
2984 slen = strlen (string);
2985 send = string + slen;
2987 t = result = (char *)xmalloc (slen + 1);
2988 s = string;
2990 if (strchr (string, CTLESC) == 0)
2991 return (strcpy (result, s));
2993 while (*s)
2995 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2997 s++;
2998 if (*s == '\0')
2999 break;
3001 COPY_CHAR_P (t, s, send);
3003 *t = '\0';
3004 return result;
3007 /* Return a new string with the quoted representation of character C.
3008 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3009 set in any resultant WORD_DESC where this value is the word. */
3010 static char *
3011 make_quoted_char (c)
3012 int c;
3014 char *temp;
3016 temp = (char *)xmalloc (3);
3017 if (c == 0)
3019 temp[0] = CTLNUL;
3020 temp[1] = '\0';
3022 else
3024 temp[0] = CTLESC;
3025 temp[1] = c;
3026 temp[2] = '\0';
3028 return (temp);
3031 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
3032 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3033 this value is the word. */
3034 char *
3035 quote_string (string)
3036 char *string;
3038 register char *t;
3039 size_t slen;
3040 char *result, *send;
3042 if (*string == 0)
3044 result = (char *)xmalloc (2);
3045 result[0] = CTLNUL;
3046 result[1] = '\0';
3048 else
3050 DECLARE_MBSTATE;
3052 slen = strlen (string);
3053 send = string + slen;
3055 result = (char *)xmalloc ((slen * 2) + 1);
3057 for (t = result; string < send; )
3059 *t++ = CTLESC;
3060 COPY_CHAR_P (t, string, send);
3062 *t = '\0';
3064 return (result);
3067 /* De-quote quoted characters in STRING. */
3068 char *
3069 dequote_string (string)
3070 char *string;
3072 register char *s, *t;
3073 size_t slen;
3074 char *result, *send;
3075 DECLARE_MBSTATE;
3077 slen = strlen (string);
3079 t = result = (char *)xmalloc (slen + 1);
3081 if (QUOTED_NULL (string))
3083 result[0] = '\0';
3084 return (result);
3087 /* If no character in the string can be quoted, don't bother examining
3088 each character. Just return a copy of the string passed to us. */
3089 if (strchr (string, CTLESC) == NULL)
3090 return (strcpy (result, string));
3092 send = string + slen;
3093 s = string;
3094 while (*s)
3096 if (*s == CTLESC)
3098 s++;
3099 if (*s == '\0')
3100 break;
3102 COPY_CHAR_P (t, s, send);
3105 *t = '\0';
3106 return (result);
3109 /* Quote the entire WORD_LIST list. */
3110 static WORD_LIST *
3111 quote_list (list)
3112 WORD_LIST *list;
3114 register WORD_LIST *w;
3115 char *t;
3117 for (w = list; w; w = w->next)
3119 t = w->word->word;
3120 w->word->word = quote_string (t);
3121 free (t);
3122 w->word->flags |= W_QUOTED;
3123 /* XXX - turn on W_HAVEQUOTEDNULL here? */
3125 return list;
3128 /* De-quote quoted characters in each word in LIST. */
3129 WORD_LIST *
3130 dequote_list (list)
3131 WORD_LIST *list;
3133 register char *s;
3134 register WORD_LIST *tlist;
3136 for (tlist = list; tlist; tlist = tlist->next)
3138 s = dequote_string (tlist->word->word);
3139 free (tlist->word->word);
3140 tlist->word->word = s;
3141 /* XXX - turn off W_HAVEQUOTEDNULL here? */
3143 return list;
3146 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3147 string. */
3148 static char *
3149 remove_quoted_escapes (string)
3150 char *string;
3152 char *t;
3154 if (string)
3156 t = dequote_escapes (string);
3157 strcpy (string, t);
3158 free (t);
3161 return (string);
3164 /* Perform quoted null character removal on STRING. We don't allow any
3165 quoted null characters in the middle or at the ends of strings because
3166 of how expand_word_internal works. remove_quoted_nulls () turns
3167 STRING into an empty string iff it only consists of a quoted null,
3168 and removes all unquoted CTLNUL characters. */
3169 static char *
3170 remove_quoted_nulls (string)
3171 char *string;
3173 register size_t slen;
3174 register int i, j, prev_i;
3175 DECLARE_MBSTATE;
3177 if (strchr (string, CTLNUL) == 0) /* XXX */
3178 return string; /* XXX */
3180 slen = strlen (string);
3181 i = j = 0;
3183 while (i < slen)
3185 if (string[i] == CTLESC)
3187 /* Old code had j++, but we cannot assume that i == j at this
3188 point -- what if a CTLNUL has already been removed from the
3189 string? We don't want to drop the CTLESC or recopy characters
3190 that we've already copied down. */
3191 i++; string[j++] = CTLESC;
3192 if (i == slen)
3193 break;
3195 else if (string[i] == CTLNUL)
3196 i++;
3198 prev_i = i;
3199 ADVANCE_CHAR (string, slen, i);
3200 if (j < prev_i)
3202 do string[j++] = string[prev_i++]; while (prev_i < i);
3204 else
3205 j = i;
3207 string[j] = '\0';
3209 return (string);
3212 /* Perform quoted null character removal on each element of LIST.
3213 This modifies LIST. */
3214 void
3215 word_list_remove_quoted_nulls (list)
3216 WORD_LIST *list;
3218 register WORD_LIST *t;
3220 for (t = list; t; t = t->next)
3222 remove_quoted_nulls (t->word->word);
3223 t->word->flags &= ~W_HASQUOTEDNULL;
3227 /* **************************************************************** */
3228 /* */
3229 /* Functions for Matching and Removing Patterns */
3230 /* */
3231 /* **************************************************************** */
3233 #if defined (HANDLE_MULTIBYTE)
3234 #if 0 /* Currently unused */
3235 static unsigned char *
3236 mb_getcharlens (string, len)
3237 char *string;
3238 int len;
3240 int i, offset, last;
3241 unsigned char *ret;
3242 char *p;
3243 DECLARE_MBSTATE;
3245 i = offset = 0;
3246 last = 0;
3247 ret = (unsigned char *)xmalloc (len);
3248 memset (ret, 0, len);
3249 while (string[last])
3251 ADVANCE_CHAR (string, len, offset);
3252 ret[last] = offset - last;
3253 last = offset;
3255 return ret;
3257 #endif
3258 #endif
3260 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3261 can have one of 4 values:
3262 RP_LONG_LEFT remove longest matching portion at start of PARAM
3263 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3264 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3265 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3268 #define RP_LONG_LEFT 1
3269 #define RP_SHORT_LEFT 2
3270 #define RP_LONG_RIGHT 3
3271 #define RP_SHORT_RIGHT 4
3273 static char *
3274 remove_upattern (param, pattern, op)
3275 char *param, *pattern;
3276 int op;
3278 register int len;
3279 register char *end;
3280 register char *p, *ret, c;
3282 len = STRLEN (param);
3283 end = param + len;
3285 switch (op)
3287 case RP_LONG_LEFT: /* remove longest match at start */
3288 for (p = end; p >= param; p--)
3290 c = *p; *p = '\0';
3291 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3293 *p = c;
3294 return (savestring (p));
3296 *p = c;
3299 break;
3301 case RP_SHORT_LEFT: /* remove shortest match at start */
3302 for (p = param; p <= end; p++)
3304 c = *p; *p = '\0';
3305 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3307 *p = c;
3308 return (savestring (p));
3310 *p = c;
3312 break;
3314 case RP_LONG_RIGHT: /* remove longest match at end */
3315 for (p = param; p <= end; p++)
3317 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3319 c = *p; *p = '\0';
3320 ret = savestring (param);
3321 *p = c;
3322 return (ret);
3325 break;
3327 case RP_SHORT_RIGHT: /* remove shortest match at end */
3328 for (p = end; p >= param; p--)
3330 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3332 c = *p; *p = '\0';
3333 ret = savestring (param);
3334 *p = c;
3335 return (ret);
3338 break;
3341 return (savestring (param)); /* no match, return original string */
3344 #if defined (HANDLE_MULTIBYTE)
3345 static wchar_t *
3346 remove_wpattern (wparam, wstrlen, wpattern, op)
3347 wchar_t *wparam;
3348 size_t wstrlen;
3349 wchar_t *wpattern;
3350 int op;
3352 wchar_t wc, *ret;
3353 int n;
3355 switch (op)
3357 case RP_LONG_LEFT: /* remove longest match at start */
3358 for (n = wstrlen; n >= 0; n--)
3360 wc = wparam[n]; wparam[n] = L'\0';
3361 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3363 wparam[n] = wc;
3364 return (wcsdup (wparam + n));
3366 wparam[n] = wc;
3368 break;
3370 case RP_SHORT_LEFT: /* remove shortest match at start */
3371 for (n = 0; n <= wstrlen; n++)
3373 wc = wparam[n]; wparam[n] = L'\0';
3374 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3376 wparam[n] = wc;
3377 return (wcsdup (wparam + n));
3379 wparam[n] = wc;
3381 break;
3383 case RP_LONG_RIGHT: /* remove longest match at end */
3384 for (n = 0; n <= wstrlen; n++)
3386 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3388 wc = wparam[n]; wparam[n] = L'\0';
3389 ret = wcsdup (wparam);
3390 wparam[n] = wc;
3391 return (ret);
3394 break;
3396 case RP_SHORT_RIGHT: /* remove shortest match at end */
3397 for (n = wstrlen; n >= 0; n--)
3399 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3401 wc = wparam[n]; wparam[n] = L'\0';
3402 ret = wcsdup (wparam);
3403 wparam[n] = wc;
3404 return (ret);
3407 break;
3410 return (wcsdup (wparam)); /* no match, return original string */
3412 #endif /* HANDLE_MULTIBYTE */
3414 static char *
3415 remove_pattern (param, pattern, op)
3416 char *param, *pattern;
3417 int op;
3419 if (param == NULL)
3420 return (param);
3421 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3422 return (savestring (param));
3424 #if defined (HANDLE_MULTIBYTE)
3425 if (MB_CUR_MAX > 1)
3427 wchar_t *ret, *oret;
3428 size_t n;
3429 wchar_t *wparam, *wpattern;
3430 mbstate_t ps;
3431 char *xret;
3433 n = xdupmbstowcs (&wpattern, NULL, pattern);
3434 if (n == (size_t)-1)
3435 return (remove_upattern (param, pattern, op));
3436 n = xdupmbstowcs (&wparam, NULL, param);
3437 if (n == (size_t)-1)
3439 free (wpattern);
3440 return (remove_upattern (param, pattern, op));
3442 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3444 free (wparam);
3445 free (wpattern);
3447 n = strlen (param);
3448 xret = (char *)xmalloc (n + 1);
3449 memset (&ps, '\0', sizeof (mbstate_t));
3450 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3451 xret[n] = '\0'; /* just to make sure */
3452 free (oret);
3453 return xret;
3455 else
3456 #endif
3457 return (remove_upattern (param, pattern, op));
3460 /* Return 1 of the first character of STRING could match the first
3461 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
3462 static int
3463 match_pattern_char (pat, string)
3464 char *pat, *string;
3466 char c;
3468 if (*string == 0)
3469 return (0);
3471 switch (c = *pat++)
3473 default:
3474 return (*string == c);
3475 case '\\':
3476 return (*string == *pat);
3477 case '?':
3478 return (*pat == LPAREN ? 1 : (*string != '\0'));
3479 case '*':
3480 return (1);
3481 case '+':
3482 case '!':
3483 case '@':
3484 return (*pat == LPAREN ? 1 : (*string == c));
3485 case '[':
3486 return (*string != '\0');
3490 /* Match PAT anywhere in STRING and return the match boundaries.
3491 This returns 1 in case of a successful match, 0 otherwise. SP
3492 and EP are pointers into the string where the match begins and
3493 ends, respectively. MTYPE controls what kind of match is attempted.
3494 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3495 of the string, respectively. The longest match is returned. */
3496 static int
3497 match_upattern (string, pat, mtype, sp, ep)
3498 char *string, *pat;
3499 int mtype;
3500 char **sp, **ep;
3502 int c, len;
3503 register char *p, *p1, *npat;
3504 char *end;
3506 /* If the pattern doesn't match anywhere in the string, go ahead and
3507 short-circuit right away. A minor optimization, saves a bunch of
3508 unnecessary calls to strmatch (up to N calls for a string of N
3509 characters) if the match is unsuccessful. To preserve the semantics
3510 of the substring matches below, we make sure that the pattern has
3511 `*' as first and last character, making a new pattern if necessary. */
3512 /* XXX - check this later if I ever implement `**' with special meaning,
3513 since this will potentially result in `**' at the beginning or end */
3514 len = STRLEN (pat);
3515 if (pat[0] != '*' || pat[len - 1] != '*')
3517 p = npat = (char *)xmalloc (len + 3);
3518 p1 = pat;
3519 if (*p1 != '*')
3520 *p++ = '*';
3521 while (*p1)
3522 *p++ = *p1++;
3523 if (p1[-1] != '*' || p[-2] == '\\')
3524 *p++ = '*';
3525 *p = '\0';
3527 else
3528 npat = pat;
3529 c = strmatch (npat, string, FNMATCH_EXTFLAG);
3530 if (npat != pat)
3531 free (npat);
3532 if (c == FNM_NOMATCH)
3533 return (0);
3535 len = STRLEN (string);
3536 end = string + len;
3538 switch (mtype)
3540 case MATCH_ANY:
3541 for (p = string; p <= end; p++)
3543 if (match_pattern_char (pat, p))
3545 for (p1 = end; p1 >= p; p1--)
3547 c = *p1; *p1 = '\0';
3548 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3550 *p1 = c;
3551 *sp = p;
3552 *ep = p1;
3553 return 1;
3555 *p1 = c;
3560 return (0);
3562 case MATCH_BEG:
3563 if (match_pattern_char (pat, string) == 0)
3564 return (0);
3566 for (p = end; p >= string; p--)
3568 c = *p; *p = '\0';
3569 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3571 *p = c;
3572 *sp = string;
3573 *ep = p;
3574 return 1;
3576 *p = c;
3579 return (0);
3581 case MATCH_END:
3582 for (p = string; p <= end; p++)
3584 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3586 *sp = p;
3587 *ep = end;
3588 return 1;
3593 return (0);
3596 return (0);
3599 #if defined (HANDLE_MULTIBYTE)
3600 /* Return 1 of the first character of WSTRING could match the first
3601 character of pattern WPAT. Wide character version. */
3602 static int
3603 match_pattern_wchar (wpat, wstring)
3604 wchar_t *wpat, *wstring;
3606 wchar_t wc;
3608 if (*wstring == 0)
3609 return (0);
3611 switch (wc = *wpat++)
3613 default:
3614 return (*wstring == wc);
3615 case L'\\':
3616 return (*wstring == *wpat);
3617 case L'?':
3618 return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3619 case L'*':
3620 return (1);
3621 case L'+':
3622 case L'!':
3623 case L'@':
3624 return (*wpat == LPAREN ? 1 : (*wstring == wc));
3625 case L'[':
3626 return (*wstring != L'\0');
3630 /* Match WPAT anywhere in WSTRING and return the match boundaries.
3631 This returns 1 in case of a successful match, 0 otherwise. Wide
3632 character version. */
3633 static int
3634 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3635 wchar_t *wstring;
3636 char **indices;
3637 size_t wstrlen;
3638 wchar_t *wpat;
3639 int mtype;
3640 char **sp, **ep;
3642 wchar_t wc, *wp, *nwpat, *wp1;
3643 int len;
3644 #if 0
3645 size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3646 #else
3647 int n, n1;
3648 #endif
3650 /* If the pattern doesn't match anywhere in the string, go ahead and
3651 short-circuit right away. A minor optimization, saves a bunch of
3652 unnecessary calls to strmatch (up to N calls for a string of N
3653 characters) if the match is unsuccessful. To preserve the semantics
3654 of the substring matches below, we make sure that the pattern has
3655 `*' as first and last character, making a new pattern if necessary. */
3656 /* XXX - check this later if I ever implement `**' with special meaning,
3657 since this will potentially result in `**' at the beginning or end */
3658 len = wcslen (wpat);
3659 if (wpat[0] != L'*' || wpat[len - 1] != L'*')
3661 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
3662 wp1 = wpat;
3663 if (*wp1 != L'*')
3664 *wp++ = L'*';
3665 while (*wp1 != L'\0')
3666 *wp++ = *wp1++;
3667 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3668 *wp++ = L'*';
3669 *wp = '\0';
3671 else
3672 nwpat = wpat;
3673 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3674 if (nwpat != wpat)
3675 free (nwpat);
3676 if (len == FNM_NOMATCH)
3677 return (0);
3679 switch (mtype)
3681 case MATCH_ANY:
3682 for (n = 0; n <= wstrlen; n++)
3684 if (match_pattern_wchar (wpat, wstring + n))
3686 for (n1 = wstrlen; n1 >= n; n1--)
3688 wc = wstring[n1]; wstring[n1] = L'\0';
3689 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3691 wstring[n1] = wc;
3692 *sp = indices[n];
3693 *ep = indices[n1];
3694 return 1;
3696 wstring[n1] = wc;
3701 return (0);
3703 case MATCH_BEG:
3704 if (match_pattern_wchar (wpat, wstring) == 0)
3705 return (0);
3707 for (n = wstrlen; n >= 0; n--)
3709 wc = wstring[n]; wstring[n] = L'\0';
3710 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3712 wstring[n] = wc;
3713 *sp = indices[0];
3714 *ep = indices[n];
3715 return 1;
3717 wstring[n] = wc;
3720 return (0);
3722 case MATCH_END:
3723 for (n = 0; n <= wstrlen; n++)
3725 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3727 *sp = indices[n];
3728 *ep = indices[wstrlen];
3729 return 1;
3733 return (0);
3736 return (0);
3738 #endif /* HANDLE_MULTIBYTE */
3740 static int
3741 match_pattern (string, pat, mtype, sp, ep)
3742 char *string, *pat;
3743 int mtype;
3744 char **sp, **ep;
3746 #if defined (HANDLE_MULTIBYTE)
3747 int ret;
3748 size_t n;
3749 wchar_t *wstring, *wpat;
3750 char **indices;
3751 #endif
3753 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
3754 return (0);
3756 #if defined (HANDLE_MULTIBYTE)
3757 if (MB_CUR_MAX > 1)
3759 n = xdupmbstowcs (&wpat, NULL, pat);
3760 if (n == (size_t)-1)
3761 return (match_upattern (string, pat, mtype, sp, ep));
3762 n = xdupmbstowcs (&wstring, &indices, string);
3763 if (n == (size_t)-1)
3765 free (wpat);
3766 return (match_upattern (string, pat, mtype, sp, ep));
3768 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
3770 free (wpat);
3771 free (wstring);
3772 free (indices);
3774 return (ret);
3776 else
3777 #endif
3778 return (match_upattern (string, pat, mtype, sp, ep));
3781 static int
3782 getpatspec (c, value)
3783 int c;
3784 char *value;
3786 if (c == '#')
3787 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
3788 else /* c == '%' */
3789 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
3792 /* Posix.2 says that the WORD should be run through tilde expansion,
3793 parameter expansion, command substitution and arithmetic expansion.
3794 This leaves the result quoted, so quote_string_for_globbing () has
3795 to be called to fix it up for strmatch (). If QUOTED is non-zero,
3796 it means that the entire expression was enclosed in double quotes.
3797 This means that quoting characters in the pattern do not make any
3798 special pattern characters quoted. For example, the `*' in the
3799 following retains its special meaning: "${foo#'*'}". */
3800 static char *
3801 getpattern (value, quoted, expandpat)
3802 char *value;
3803 int quoted, expandpat;
3805 char *pat, *tword;
3806 WORD_LIST *l;
3807 #if 0
3808 int i;
3809 #endif
3811 /* There is a problem here: how to handle single or double quotes in the
3812 pattern string when the whole expression is between double quotes?
3813 POSIX.2 says that enclosing double quotes do not cause the pattern to
3814 be quoted, but does that leave us a problem with @ and array[@] and their
3815 expansions inside a pattern? */
3816 #if 0
3817 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
3819 i = 0;
3820 pat = string_extract_double_quoted (tword, &i, 1);
3821 free (tword);
3822 tword = pat;
3824 #endif
3826 /* expand_string_for_rhs () leaves WORD quoted and does not perform
3827 word splitting. */
3828 l = *value ? expand_string_for_rhs (value,
3829 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
3830 (int *)NULL, (int *)NULL)
3831 : (WORD_LIST *)0;
3832 pat = string_list (l);
3833 dispose_words (l);
3834 if (pat)
3836 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
3837 free (pat);
3838 pat = tword;
3840 return (pat);
3843 #if 0
3844 /* Handle removing a pattern from a string as a result of ${name%[%]value}
3845 or ${name#[#]value}. */
3846 static char *
3847 variable_remove_pattern (value, pattern, patspec, quoted)
3848 char *value, *pattern;
3849 int patspec, quoted;
3851 char *tword;
3853 tword = remove_pattern (value, pattern, patspec);
3855 return (tword);
3857 #endif
3859 static char *
3860 list_remove_pattern (list, pattern, patspec, itype, quoted)
3861 WORD_LIST *list;
3862 char *pattern;
3863 int patspec, itype, quoted;
3865 WORD_LIST *new, *l;
3866 WORD_DESC *w;
3867 char *tword;
3869 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
3871 tword = remove_pattern (l->word->word, pattern, patspec);
3872 w = alloc_word_desc ();
3873 w->word = tword ? tword : savestring ("");
3874 new = make_word_list (w, new);
3877 l = REVERSE_LIST (new, WORD_LIST *);
3878 if (itype == '*')
3879 tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
3880 else
3881 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3883 dispose_words (l);
3884 return (tword);
3887 static char *
3888 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
3889 int itype;
3890 char *pattern;
3891 int patspec, quoted;
3893 char *ret;
3894 WORD_LIST *list;
3896 list = list_rest_of_args ();
3897 if (list == 0)
3898 return ((char *)NULL);
3899 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3900 dispose_words (list);
3901 return (ret);
3904 #if defined (ARRAY_VARS)
3905 static char *
3906 array_remove_pattern (a, pattern, patspec, varname, quoted)
3907 ARRAY *a;
3908 char *pattern;
3909 int patspec;
3910 char *varname; /* so we can figure out how it's indexed */
3911 int quoted;
3913 int itype;
3914 char *ret;
3915 WORD_LIST *list;
3916 SHELL_VAR *v;
3918 /* compute itype from varname here */
3919 v = array_variable_part (varname, &ret, 0);
3920 itype = ret[0];
3922 list = array_to_word_list (a);
3923 if (list == 0)
3924 return ((char *)NULL);
3925 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3926 dispose_words (list);
3928 return ret;
3930 #endif /* ARRAY_VARS */
3932 static char *
3933 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
3934 char *varname, *value, *patstr;
3935 int rtype, quoted;
3937 int vtype, patspec, starsub;
3938 char *temp1, *val, *pattern;
3939 SHELL_VAR *v;
3941 if (value == 0)
3942 return ((char *)NULL);
3944 this_command_name = varname;
3946 vtype = get_var_and_type (varname, value, quoted, &v, &val);
3947 if (vtype == -1)
3948 return ((char *)NULL);
3950 starsub = vtype & VT_STARSUB;
3951 vtype &= ~VT_STARSUB;
3953 patspec = getpatspec (rtype, patstr);
3954 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
3955 patstr++;
3957 pattern = getpattern (patstr, quoted, 1);
3959 temp1 = (char *)NULL; /* shut up gcc */
3960 switch (vtype)
3962 case VT_VARIABLE:
3963 case VT_ARRAYMEMBER:
3964 temp1 = remove_pattern (val, pattern, patspec);
3965 if (vtype == VT_VARIABLE)
3966 FREE (val);
3967 if (temp1)
3969 val = quote_escapes (temp1);
3970 free (temp1);
3971 temp1 = val;
3973 break;
3974 #if defined (ARRAY_VARS)
3975 case VT_ARRAYVAR:
3976 temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
3977 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3979 val = quote_escapes (temp1);
3980 free (temp1);
3981 temp1 = val;
3983 break;
3984 #endif
3985 case VT_POSPARMS:
3986 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
3987 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3989 val = quote_escapes (temp1);
3990 free (temp1);
3991 temp1 = val;
3993 break;
3996 FREE (pattern);
3997 return temp1;
4000 /*******************************************
4002 * Functions to expand WORD_DESCs *
4004 *******************************************/
4006 /* Expand WORD, performing word splitting on the result. This does
4007 parameter expansion, command substitution, arithmetic expansion,
4008 word splitting, and quote removal. */
4010 WORD_LIST *
4011 expand_word (word, quoted)
4012 WORD_DESC *word;
4013 int quoted;
4015 WORD_LIST *result, *tresult;
4017 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4018 result = word_list_split (tresult);
4019 dispose_words (tresult);
4020 return (result ? dequote_list (result) : result);
4023 /* Expand WORD, but do not perform word splitting on the result. This
4024 does parameter expansion, command substitution, arithmetic expansion,
4025 and quote removal. */
4026 WORD_LIST *
4027 expand_word_unsplit (word, quoted)
4028 WORD_DESC *word;
4029 int quoted;
4031 WORD_LIST *result;
4033 expand_no_split_dollar_star = 1;
4034 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4035 expand_no_split_dollar_star = 0;
4037 return (result ? dequote_list (result) : result);
4040 /* Perform shell expansions on WORD, but do not perform word splitting or
4041 quote removal on the result. */
4042 WORD_LIST *
4043 expand_word_leave_quoted (word, quoted)
4044 WORD_DESC *word;
4045 int quoted;
4047 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
4050 #if defined (PROCESS_SUBSTITUTION)
4052 /*****************************************************************/
4053 /* */
4054 /* Hacking Process Substitution */
4055 /* */
4056 /*****************************************************************/
4058 #if !defined (HAVE_DEV_FD)
4059 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
4060 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4061 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4062 list. NFIFO is a count of the number of FIFOs in the list. */
4063 #define FIFO_INCR 20
4065 struct temp_fifo {
4066 char *file;
4067 pid_t proc;
4070 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4071 static int nfifo;
4072 static int fifo_list_size;
4074 static void
4075 add_fifo_list (pathname)
4076 char *pathname;
4078 if (nfifo >= fifo_list_size - 1)
4080 fifo_list_size += FIFO_INCR;
4081 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4082 fifo_list_size * sizeof (struct temp_fifo));
4085 fifo_list[nfifo].file = savestring (pathname);
4086 nfifo++;
4089 void
4090 unlink_fifo_list ()
4092 int saved, i, j;
4094 if (nfifo == 0)
4095 return;
4097 for (i = saved = 0; i < nfifo; i++)
4099 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4101 unlink (fifo_list[i].file);
4102 free (fifo_list[i].file);
4103 fifo_list[i].file = (char *)NULL;
4104 fifo_list[i].proc = -1;
4106 else
4107 saved++;
4110 /* If we didn't remove some of the FIFOs, compact the list. */
4111 if (saved)
4113 for (i = j = 0; i < nfifo; i++)
4114 if (fifo_list[i].file)
4116 fifo_list[j].file = fifo_list[i].file;
4117 fifo_list[j].proc = fifo_list[i].proc;
4118 j++;
4120 nfifo = j;
4122 else
4123 nfifo = 0;
4126 static char *
4127 make_named_pipe ()
4129 char *tname;
4131 tname = sh_mktmpname ("sh-np", MT_USERANDOM);
4132 if (mkfifo (tname, 0600) < 0)
4134 free (tname);
4135 return ((char *)NULL);
4138 add_fifo_list (tname);
4139 return (tname);
4142 #else /* HAVE_DEV_FD */
4144 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4145 has open to children. NFDS is a count of the number of bits currently
4146 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4147 of open files. */
4148 static char *dev_fd_list = (char *)NULL;
4149 static int nfds;
4150 static int totfds; /* The highest possible number of open files. */
4152 static void
4153 add_fifo_list (fd)
4154 int fd;
4156 if (!dev_fd_list || fd >= totfds)
4158 int ofds;
4160 ofds = totfds;
4161 totfds = getdtablesize ();
4162 if (totfds < 0 || totfds > 256)
4163 totfds = 256;
4164 if (fd > totfds)
4165 totfds = fd + 2;
4167 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4168 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4171 dev_fd_list[fd] = 1;
4172 nfds++;
4175 void
4176 unlink_fifo_list ()
4178 register int i;
4180 if (nfds == 0)
4181 return;
4183 for (i = 0; nfds && i < totfds; i++)
4184 if (dev_fd_list[i])
4186 close (i);
4187 dev_fd_list[i] = 0;
4188 nfds--;
4191 nfds = 0;
4194 #if defined (NOTDEF)
4195 print_dev_fd_list ()
4197 register int i;
4199 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4200 fflush (stderr);
4202 for (i = 0; i < totfds; i++)
4204 if (dev_fd_list[i])
4205 fprintf (stderr, " %d", i);
4207 fprintf (stderr, "\n");
4209 #endif /* NOTDEF */
4211 static char *
4212 make_dev_fd_filename (fd)
4213 int fd;
4215 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4217 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
4219 strcpy (ret, DEV_FD_PREFIX);
4220 p = inttostr (fd, intbuf, sizeof (intbuf));
4221 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4223 add_fifo_list (fd);
4224 return (ret);
4227 #endif /* HAVE_DEV_FD */
4229 /* Return a filename that will open a connection to the process defined by
4230 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4231 a filename in /dev/fd corresponding to a descriptor that is one of the
4232 ends of the pipe. If not defined, we use named pipes on systems that have
4233 them. Systems without /dev/fd and named pipes are out of luck.
4235 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4236 use the read end of the pipe and dup that file descriptor to fd 0 in
4237 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4238 writing or use the write end of the pipe in the child, and dup that
4239 file descriptor to fd 1 in the child. The parent does the opposite. */
4241 static char *
4242 process_substitute (string, open_for_read_in_child)
4243 char *string;
4244 int open_for_read_in_child;
4246 char *pathname;
4247 int fd, result;
4248 pid_t old_pid, pid;
4249 #if defined (HAVE_DEV_FD)
4250 int parent_pipe_fd, child_pipe_fd;
4251 int fildes[2];
4252 #endif /* HAVE_DEV_FD */
4253 #if defined (JOB_CONTROL)
4254 pid_t old_pipeline_pgrp;
4255 #endif
4257 if (!string || !*string || wordexp_only)
4258 return ((char *)NULL);
4260 #if !defined (HAVE_DEV_FD)
4261 pathname = make_named_pipe ();
4262 #else /* HAVE_DEV_FD */
4263 if (pipe (fildes) < 0)
4265 sys_error (_("cannot make pipe for process substitution"));
4266 return ((char *)NULL);
4268 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4269 the pipe in the parent, otherwise the read end. */
4270 parent_pipe_fd = fildes[open_for_read_in_child];
4271 child_pipe_fd = fildes[1 - open_for_read_in_child];
4272 /* Move the parent end of the pipe to some high file descriptor, to
4273 avoid clashes with FDs used by the script. */
4274 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4276 pathname = make_dev_fd_filename (parent_pipe_fd);
4277 #endif /* HAVE_DEV_FD */
4279 if (!pathname)
4281 sys_error (_("cannot make pipe for process substitution"));
4282 return ((char *)NULL);
4285 old_pid = last_made_pid;
4287 #if defined (JOB_CONTROL)
4288 old_pipeline_pgrp = pipeline_pgrp;
4289 pipeline_pgrp = shell_pgrp;
4290 save_pipeline (1);
4291 #endif /* JOB_CONTROL */
4293 pid = make_child ((char *)NULL, 1);
4294 if (pid == 0)
4296 reset_terminating_signals (); /* XXX */
4297 free_pushed_string_input ();
4298 /* Cancel traps, in trap.c. */
4299 restore_original_signals ();
4300 setup_async_signals ();
4301 subshell_environment |= SUBSHELL_COMSUB;
4304 #if defined (JOB_CONTROL)
4305 set_sigchld_handler ();
4306 stop_making_children ();
4307 pipeline_pgrp = old_pipeline_pgrp;
4308 #endif /* JOB_CONTROL */
4310 if (pid < 0)
4312 sys_error (_("cannot make child for process substitution"));
4313 free (pathname);
4314 #if defined (HAVE_DEV_FD)
4315 close (parent_pipe_fd);
4316 close (child_pipe_fd);
4317 #endif /* HAVE_DEV_FD */
4318 return ((char *)NULL);
4321 if (pid > 0)
4323 #if defined (JOB_CONTROL)
4324 restore_pipeline (1);
4325 #endif
4327 #if !defined (HAVE_DEV_FD)
4328 fifo_list[nfifo-1].proc = pid;
4329 #endif
4331 last_made_pid = old_pid;
4333 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4334 close_pgrp_pipe ();
4335 #endif /* JOB_CONTROL && PGRP_PIPE */
4337 #if defined (HAVE_DEV_FD)
4338 close (child_pipe_fd);
4339 #endif /* HAVE_DEV_FD */
4341 return (pathname);
4344 set_sigint_handler ();
4346 #if defined (JOB_CONTROL)
4347 set_job_control (0);
4348 #endif /* JOB_CONTROL */
4350 #if !defined (HAVE_DEV_FD)
4351 /* Open the named pipe in the child. */
4352 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4353 if (fd < 0)
4355 /* Two separate strings for ease of translation. */
4356 if (open_for_read_in_child)
4357 sys_error (_("cannot open named pipe %s for reading"), pathname);
4358 else
4359 sys_error (_("cannot open named pipe %s for writing"), pathname);
4361 exit (127);
4363 if (open_for_read_in_child)
4365 if (sh_unset_nodelay_mode (fd) < 0)
4367 sys_error (_("cannout reset nodelay mode for fd %d"), fd);
4368 exit (127);
4371 #else /* HAVE_DEV_FD */
4372 fd = child_pipe_fd;
4373 #endif /* HAVE_DEV_FD */
4375 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4377 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4378 open_for_read_in_child ? 0 : 1);
4379 exit (127);
4382 if (fd != (open_for_read_in_child ? 0 : 1))
4383 close (fd);
4385 /* Need to close any files that this process has open to pipes inherited
4386 from its parent. */
4387 if (current_fds_to_close)
4389 close_fd_bitmap (current_fds_to_close);
4390 current_fds_to_close = (struct fd_bitmap *)NULL;
4393 #if defined (HAVE_DEV_FD)
4394 /* Make sure we close the parent's end of the pipe and clear the slot
4395 in the fd list so it is not closed later, if reallocated by, for
4396 instance, pipe(2). */
4397 close (parent_pipe_fd);
4398 dev_fd_list[parent_pipe_fd] = 0;
4399 #endif /* HAVE_DEV_FD */
4401 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4403 #if !defined (HAVE_DEV_FD)
4404 /* Make sure we close the named pipe in the child before we exit. */
4405 close (open_for_read_in_child ? 0 : 1);
4406 #endif /* !HAVE_DEV_FD */
4408 exit (result);
4409 /*NOTREACHED*/
4411 #endif /* PROCESS_SUBSTITUTION */
4413 /***********************************/
4414 /* */
4415 /* Command Substitution */
4416 /* */
4417 /***********************************/
4419 static char *
4420 read_comsub (fd, quoted)
4421 int fd, quoted;
4423 char *istring, buf[128], *bufp;
4424 int istring_index, istring_size, c;
4425 ssize_t bufn;
4427 istring = (char *)NULL;
4428 istring_index = istring_size = bufn = 0;
4430 #ifdef __CYGWIN__
4431 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
4432 #endif
4434 /* Read the output of the command through the pipe. */
4435 while (1)
4437 if (fd < 0)
4438 break;
4439 if (--bufn <= 0)
4441 bufn = zread (fd, buf, sizeof (buf));
4442 if (bufn <= 0)
4443 break;
4444 bufp = buf;
4446 c = *bufp++;
4448 if (c == 0)
4450 #if 0
4451 internal_warning ("read_comsub: ignored null byte in input");
4452 #endif
4453 continue;
4456 /* Add the character to ISTRING, possibly after resizing it. */
4457 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4459 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
4460 istring[istring_index++] = CTLESC;
4462 istring[istring_index++] = c;
4464 #if 0
4465 #if defined (__CYGWIN__)
4466 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4468 istring_index--;
4469 istring[istring_index - 1] = '\n';
4471 #endif
4472 #endif
4475 if (istring)
4476 istring[istring_index] = '\0';
4478 /* If we read no output, just return now and save ourselves some
4479 trouble. */
4480 if (istring_index == 0)
4482 FREE (istring);
4483 return (char *)NULL;
4486 /* Strip trailing newlines from the output of the command. */
4487 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4489 while (istring_index > 0)
4491 if (istring[istring_index - 1] == '\n')
4493 --istring_index;
4495 /* If the newline was quoted, remove the quoting char. */
4496 if (istring[istring_index - 1] == CTLESC)
4497 --istring_index;
4499 else
4500 break;
4502 istring[istring_index] = '\0';
4504 else
4505 strip_trailing (istring, istring_index - 1, 1);
4507 return istring;
4510 /* Perform command substitution on STRING. This returns a string,
4511 possibly quoted. */
4512 char *
4513 command_substitute (string, quoted)
4514 char *string;
4515 int quoted;
4517 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4518 char *istring;
4519 int result, fildes[2], function_value, pflags, rc;
4521 istring = (char *)NULL;
4523 /* Don't fork () if there is no need to. In the case of no command to
4524 run, just return NULL. */
4525 if (!string || !*string || (string[0] == '\n' && !string[1]))
4526 return ((char *)NULL);
4528 if (wordexp_only && read_but_dont_execute)
4530 last_command_exit_value = 125;
4531 jump_to_top_level (EXITPROG);
4534 /* We're making the assumption here that the command substitution will
4535 eventually run a command from the file system. Since we'll run
4536 maybe_make_export_env in this subshell before executing that command,
4537 the parent shell and any other shells it starts will have to remake
4538 the environment. If we make it before we fork, other shells won't
4539 have to. Don't bother if we have any temporary variable assignments,
4540 though, because the export environment will be remade after this
4541 command completes anyway, but do it if all the words to be expanded
4542 are variable assignments. */
4543 if (subst_assign_varlist == 0 || garglist == 0)
4544 maybe_make_export_env (); /* XXX */
4546 /* Flags to pass to parse_and_execute() */
4547 pflags = interactive ? SEVAL_RESETLINE : 0;
4549 /* Pipe the output of executing STRING into the current shell. */
4550 if (pipe (fildes) < 0)
4552 sys_error (_("cannot make pipe for command substitution"));
4553 goto error_exit;
4556 old_pid = last_made_pid;
4557 #if defined (JOB_CONTROL)
4558 old_pipeline_pgrp = pipeline_pgrp;
4559 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4560 if ((subshell_environment & SUBSHELL_PIPE) == 0)
4561 pipeline_pgrp = shell_pgrp;
4562 cleanup_the_pipeline ();
4563 #endif /* JOB_CONTROL */
4565 old_async_pid = last_asynchronous_pid;
4566 #if 0
4567 pid = make_child ((char *)NULL, 0);
4568 #else
4569 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4570 #endif
4571 last_asynchronous_pid = old_async_pid;
4573 if (pid == 0)
4574 /* Reset the signal handlers in the child, but don't free the
4575 trap strings. */
4576 reset_signal_handlers ();
4578 #if defined (JOB_CONTROL)
4579 set_sigchld_handler ();
4580 stop_making_children ();
4581 pipeline_pgrp = old_pipeline_pgrp;
4582 #else
4583 stop_making_children ();
4584 #endif /* JOB_CONTROL */
4586 if (pid < 0)
4588 sys_error (_("cannot make child for command substitution"));
4589 error_exit:
4591 FREE (istring);
4592 close (fildes[0]);
4593 close (fildes[1]);
4594 return ((char *)NULL);
4597 if (pid == 0)
4599 set_sigint_handler (); /* XXX */
4601 free_pushed_string_input ();
4603 if (dup2 (fildes[1], 1) < 0)
4605 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4606 exit (EXECUTION_FAILURE);
4609 /* If standard output is closed in the parent shell
4610 (such as after `exec >&-'), file descriptor 1 will be
4611 the lowest available file descriptor, and end up in
4612 fildes[0]. This can happen for stdin and stderr as well,
4613 but stdout is more important -- it will cause no output
4614 to be generated from this command. */
4615 if ((fildes[1] != fileno (stdin)) &&
4616 (fildes[1] != fileno (stdout)) &&
4617 (fildes[1] != fileno (stderr)))
4618 close (fildes[1]);
4620 if ((fildes[0] != fileno (stdin)) &&
4621 (fildes[0] != fileno (stdout)) &&
4622 (fildes[0] != fileno (stderr)))
4623 close (fildes[0]);
4625 /* The currently executing shell is not interactive. */
4626 interactive = 0;
4628 /* This is a subshell environment. */
4629 subshell_environment |= SUBSHELL_COMSUB;
4631 /* When not in POSIX mode, command substitution does not inherit
4632 the -e flag. */
4633 if (posixly_correct == 0)
4634 exit_immediately_on_error = 0;
4636 remove_quoted_escapes (string);
4638 startup_state = 2; /* see if we can avoid a fork */
4639 /* Give command substitution a place to jump back to on failure,
4640 so we don't go back up to main (). */
4641 result = setjmp (top_level);
4643 /* If we're running a command substitution inside a shell function,
4644 trap `return' so we don't return from the function in the subshell
4645 and go off to never-never land. */
4646 if (result == 0 && return_catch_flag)
4647 function_value = setjmp (return_catch);
4648 else
4649 function_value = 0;
4651 if (result == ERREXIT)
4652 rc = last_command_exit_value;
4653 else if (result == EXITPROG)
4654 rc = last_command_exit_value;
4655 else if (result)
4656 rc = EXECUTION_FAILURE;
4657 else if (function_value)
4658 rc = return_catch_value;
4659 else
4661 subshell_level++;
4662 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4663 subshell_level--;
4666 last_command_exit_value = rc;
4667 rc = run_exit_trap ();
4668 exit (rc);
4670 else
4672 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4673 close_pgrp_pipe ();
4674 #endif /* JOB_CONTROL && PGRP_PIPE */
4676 close (fildes[1]);
4678 istring = read_comsub (fildes[0], quoted);
4680 close (fildes[0]);
4682 current_command_subst_pid = pid;
4683 last_command_exit_value = wait_for (pid);
4684 last_command_subst_pid = pid;
4685 last_made_pid = old_pid;
4687 #if defined (JOB_CONTROL)
4688 /* If last_command_exit_value > 128, then the substituted command
4689 was terminated by a signal. If that signal was SIGINT, then send
4690 SIGINT to ourselves. This will break out of loops, for instance. */
4691 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
4692 kill (getpid (), SIGINT);
4694 /* wait_for gives the terminal back to shell_pgrp. If some other
4695 process group should have it, give it away to that group here.
4696 pipeline_pgrp is non-zero only while we are constructing a
4697 pipline, so what we are concerned about is whether or not that
4698 pipeline was started in the background. A pipeline started in
4699 the background should never get the tty back here. */
4700 #if 0
4701 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
4702 #else
4703 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
4704 #endif
4705 give_terminal_to (pipeline_pgrp, 0);
4706 #endif /* JOB_CONTROL */
4708 return (istring);
4712 /********************************************************
4714 * Utility functions for parameter expansion *
4716 ********************************************************/
4718 #if defined (ARRAY_VARS)
4720 static arrayind_t
4721 array_length_reference (s)
4722 char *s;
4724 int len;
4725 arrayind_t ind;
4726 char *t, c;
4727 ARRAY *array;
4728 SHELL_VAR *var;
4730 var = array_variable_part (s, &t, &len);
4732 /* If unbound variables should generate an error, report one and return
4733 failure. */
4734 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
4736 c = *--t;
4737 *t = '\0';
4738 err_unboundvar (s);
4739 *t = c;
4740 return (-1);
4742 else if (var == 0)
4743 return 0;
4745 /* We support a couple of expansions for variables that are not arrays.
4746 We'll return the length of the value for v[0], and 1 for v[@] or
4747 v[*]. Return 0 for everything else. */
4749 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
4751 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
4752 return (array_p (var) ? array_num_elements (array) : 1);
4754 ind = array_expand_index (t, len);
4755 if (ind < 0)
4757 err_badarraysub (t);
4758 return (-1);
4761 if (array_p (var))
4762 t = array_reference (array, ind);
4763 else
4764 t = (ind == 0) ? value_cell (var) : (char *)NULL;
4766 len = STRLEN (t);
4767 return (len);
4769 #endif /* ARRAY_VARS */
4771 static int
4772 valid_brace_expansion_word (name, var_is_special)
4773 char *name;
4774 int var_is_special;
4776 if (DIGIT (*name) && all_digits (name))
4777 return 1;
4778 else if (var_is_special)
4779 return 1;
4780 #if defined (ARRAY_VARS)
4781 else if (valid_array_reference (name))
4782 return 1;
4783 #endif /* ARRAY_VARS */
4784 else if (legal_identifier (name))
4785 return 1;
4786 else
4787 return 0;
4790 static int
4791 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
4792 char *name;
4793 int quoted;
4794 int *quoted_dollar_atp, *contains_dollar_at;
4796 char *temp1;
4798 if (name == 0)
4800 if (quoted_dollar_atp)
4801 *quoted_dollar_atp = 0;
4802 if (contains_dollar_at)
4803 *contains_dollar_at = 0;
4804 return 0;
4807 /* check for $@ and $* */
4808 if (name[0] == '@' && name[1] == 0)
4810 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4811 *quoted_dollar_atp = 1;
4812 if (contains_dollar_at)
4813 *contains_dollar_at = 1;
4814 return 1;
4816 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
4818 if (contains_dollar_at)
4819 *contains_dollar_at = 1;
4820 return 1;
4823 /* Now check for ${array[@]} and ${array[*]} */
4824 #if defined (ARRAY_VARS)
4825 else if (valid_array_reference (name))
4827 temp1 = xstrchr (name, '[');
4828 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4830 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4831 *quoted_dollar_atp = 1;
4832 if (contains_dollar_at)
4833 *contains_dollar_at = 1;
4834 return 1;
4835 } /* [ */
4836 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4837 which should result in separate words even when IFS is unset. */
4838 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4840 if (contains_dollar_at)
4841 *contains_dollar_at = 1;
4842 return 1;
4845 #endif
4846 return 0;
4849 /* Parameter expand NAME, and return a new string which is the expansion,
4850 or NULL if there was no expansion.
4851 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
4852 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
4853 NAME was found inside of a double-quoted expression. */
4854 static WORD_DESC *
4855 parameter_brace_expand_word (name, var_is_special, quoted)
4856 char *name;
4857 int var_is_special, quoted;
4859 WORD_DESC *ret;
4860 char *temp, *tt;
4861 intmax_t arg_index;
4862 SHELL_VAR *var;
4863 int atype;
4865 ret = 0;
4866 temp = 0;
4868 /* Handle multiple digit arguments, as in ${11}. */
4869 if (legal_number (name, &arg_index))
4871 tt = get_dollar_var_value (arg_index);
4872 if (tt)
4873 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4874 ? quote_string (tt)
4875 : quote_escapes (tt);
4876 else
4877 temp = (char *)NULL;
4878 FREE (tt);
4880 else if (var_is_special) /* ${@} */
4882 int sindex;
4883 tt = (char *)xmalloc (2 + strlen (name));
4884 tt[sindex = 0] = '$';
4885 strcpy (tt + 1, name);
4887 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
4888 (int *)NULL, (int *)NULL, 0);
4889 free (tt);
4891 #if defined (ARRAY_VARS)
4892 else if (valid_array_reference (name))
4894 temp = array_value (name, quoted, &atype);
4895 if (atype == 0 && temp)
4896 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4897 ? quote_string (temp)
4898 : quote_escapes (temp);
4900 #endif
4901 else if (var = find_variable (name))
4903 if (var_isset (var) && invisible_p (var) == 0)
4905 #if defined (ARRAY_VARS)
4906 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
4907 #else
4908 temp = value_cell (var);
4909 #endif
4911 if (temp)
4912 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4913 ? quote_string (temp)
4914 : quote_escapes (temp);
4916 else
4917 temp = (char *)NULL;
4919 else
4920 temp = (char *)NULL;
4922 if (ret == 0)
4924 ret = alloc_word_desc ();
4925 ret->word = temp;
4927 return ret;
4930 /* Expand an indirect reference to a variable: ${!NAME} expands to the
4931 value of the variable whose name is the value of NAME. */
4932 static WORD_DESC *
4933 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
4934 char *name;
4935 int var_is_special, quoted;
4936 int *quoted_dollar_atp, *contains_dollar_at;
4938 char *temp, *t;
4939 WORD_DESC *w;
4941 w = parameter_brace_expand_word (name, var_is_special, quoted);
4942 t = w->word;
4943 /* Have to dequote here if necessary */
4944 if (t)
4946 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
4947 ? dequote_string (t)
4948 : dequote_escapes (t);
4949 free (t);
4950 t = temp;
4952 dispose_word_desc (w);
4954 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
4955 if (t == 0)
4956 return (WORD_DESC *)NULL;
4958 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
4959 free (t);
4961 return w;
4964 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
4965 depending on the value of C, the separating character. C can be one of
4966 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
4967 between double quotes. */
4968 static WORD_DESC *
4969 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
4970 char *name, *value;
4971 int c, quoted, *qdollaratp, *hasdollarat;
4973 WORD_DESC *w;
4974 WORD_LIST *l;
4975 char *t, *t1, *temp;
4976 int hasdol;
4978 /* If the entire expression is between double quotes, we want to treat
4979 the value as a double-quoted string, with the exception that we strip
4980 embedded unescaped double quotes. */
4981 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
4983 hasdol = 0;
4984 temp = string_extract_double_quoted (value, &hasdol, 1);
4986 else
4987 temp = value;
4989 w = alloc_word_desc ();
4990 hasdol = 0;
4991 /* XXX was 0 not quoted */
4992 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
4993 : (WORD_LIST *)0;
4994 if (hasdollarat)
4995 *hasdollarat = hasdol || (l && l->next);
4996 if (temp != value)
4997 free (temp);
4998 if (l)
5000 /* The expansion of TEMP returned something. We need to treat things
5001 slightly differently if HASDOL is non-zero. If we have "$@", the
5002 individual words have already been quoted. We need to turn them
5003 into a string with the words separated by the first character of
5004 $IFS without any additional quoting, so string_list_dollar_at won't
5005 do the right thing. We use string_list_dollar_star instead. */
5006 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5008 /* If l->next is not null, we know that TEMP contained "$@", since that
5009 is the only expansion that creates more than one word. */
5010 if (qdollaratp && ((hasdol && quoted) || l->next))
5011 *qdollaratp = 1;
5012 dispose_words (l);
5014 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5016 /* The brace expansion occurred between double quotes and there was
5017 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5018 it does not expand to anything. In this case, we want to return
5019 a quoted empty string. */
5020 temp = make_quoted_char ('\0');
5021 w->flags |= W_HASQUOTEDNULL;
5023 else
5024 temp = (char *)NULL;
5026 if (c == '-' || c == '+')
5028 w->word = temp;
5029 return w;
5032 /* c == '=' */
5033 t = temp ? savestring (temp) : savestring ("");
5034 t1 = dequote_string (t);
5035 free (t);
5036 #if defined (ARRAY_VARS)
5037 if (valid_array_reference (name))
5038 assign_array_element (name, t1, 0);
5039 else
5040 #endif /* ARRAY_VARS */
5041 bind_variable (name, t1, 0);
5042 free (t1);
5044 w->word = temp;
5045 return w;
5048 /* Deal with the right hand side of a ${name:?value} expansion in the case
5049 that NAME is null or not set. If VALUE is non-null it is expanded and
5050 used as the error message to print, otherwise a standard message is
5051 printed. */
5052 static void
5053 parameter_brace_expand_error (name, value)
5054 char *name, *value;
5056 WORD_LIST *l;
5057 char *temp;
5059 if (value && *value)
5061 l = expand_string (value, 0);
5062 temp = string_list (l);
5063 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5064 FREE (temp);
5065 dispose_words (l);
5067 else
5068 report_error (_("%s: parameter null or not set"), name);
5070 /* Free the data we have allocated during this expansion, since we
5071 are about to longjmp out. */
5072 free (name);
5073 FREE (value);
5076 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5077 OK to do. */
5078 static int
5079 valid_length_expression (name)
5080 char *name;
5082 return (name[1] == '\0' || /* ${#} */
5083 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5084 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5085 #if defined (ARRAY_VARS)
5086 valid_array_reference (name + 1) || /* ${#a[7]} */
5087 #endif
5088 legal_identifier (name + 1)); /* ${#PS1} */
5091 #if defined (HANDLE_MULTIBYTE)
5092 size_t
5093 mbstrlen (s)
5094 const char *s;
5096 size_t clen, nc;
5097 mbstate_t mbs, mbsbak;
5099 nc = 0;
5100 memset (&mbs, 0, sizeof (mbs));
5101 mbsbak = mbs;
5102 while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5104 if (MB_INVALIDCH(clen))
5106 clen = 1; /* assume single byte */
5107 mbs = mbsbak;
5110 s += clen;
5111 nc++;
5112 mbsbak = mbs;
5114 return nc;
5116 #endif
5119 /* Handle the parameter brace expansion that requires us to return the
5120 length of a parameter. */
5121 static intmax_t
5122 parameter_brace_expand_length (name)
5123 char *name;
5125 char *t, *newname;
5126 intmax_t number, arg_index;
5127 WORD_LIST *list;
5128 #if defined (ARRAY_VARS)
5129 SHELL_VAR *var;
5130 #endif
5132 if (name[1] == '\0') /* ${#} */
5133 number = number_of_args ();
5134 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5135 number = number_of_args ();
5136 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5138 /* Take the lengths of some of the shell's special parameters. */
5139 switch (name[1])
5141 case '-':
5142 t = which_set_flags ();
5143 break;
5144 case '?':
5145 t = itos (last_command_exit_value);
5146 break;
5147 case '$':
5148 t = itos (dollar_dollar_pid);
5149 break;
5150 case '!':
5151 if (last_asynchronous_pid == NO_PID)
5152 t = (char *)NULL;
5153 else
5154 t = itos (last_asynchronous_pid);
5155 break;
5156 case '#':
5157 t = itos (number_of_args ());
5158 break;
5160 number = STRLEN (t);
5161 FREE (t);
5163 #if defined (ARRAY_VARS)
5164 else if (valid_array_reference (name + 1))
5165 number = array_length_reference (name + 1);
5166 #endif /* ARRAY_VARS */
5167 else
5169 number = 0;
5171 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5173 t = get_dollar_var_value (arg_index);
5174 number = MB_STRLEN (t);
5175 FREE (t);
5177 #if defined (ARRAY_VARS)
5178 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && array_p (var))
5180 t = array_reference (array_cell (var), 0);
5181 number = MB_STRLEN (t);
5183 #endif
5184 else /* ${#PS1} */
5186 newname = savestring (name);
5187 newname[0] = '$';
5188 list = expand_string (newname, Q_DOUBLE_QUOTES);
5189 t = list ? string_list (list) : (char *)NULL;
5190 free (newname);
5191 if (list)
5192 dispose_words (list);
5194 number = MB_STRLEN (t);
5195 FREE (t);
5199 return (number);
5202 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5203 so we do some ad-hoc parsing of an arithmetic expression to find
5204 the first DELIM, instead of using strchr(3). Two rules:
5205 1. If the substring contains a `(', read until closing `)'.
5206 2. If the substring contains a `?', read past one `:' for each `?'.
5209 static char *
5210 skiparith (substr, delim)
5211 char *substr;
5212 int delim;
5214 size_t sublen;
5215 int skipcol, pcount, i;
5216 DECLARE_MBSTATE;
5218 sublen = strlen (substr);
5219 i = skipcol = pcount = 0;
5220 while (substr[i])
5222 /* Balance parens */
5223 if (substr[i] == LPAREN)
5225 pcount++;
5226 i++;
5227 continue;
5229 if (substr[i] == RPAREN && pcount)
5231 pcount--;
5232 i++;
5233 continue;
5235 if (pcount)
5237 ADVANCE_CHAR (substr, sublen, i);
5238 continue;
5241 /* Skip one `:' for each `?' */
5242 if (substr[i] == ':' && skipcol)
5244 skipcol--;
5245 i++;
5246 continue;
5248 if (substr[i] == delim)
5249 break;
5250 if (substr[i] == '?')
5252 skipcol++;
5253 i++;
5254 continue;
5256 ADVANCE_CHAR (substr, sublen, i);
5259 return (substr + i);
5262 /* Verify and limit the start and end of the desired substring. If
5263 VTYPE == 0, a regular shell variable is being used; if it is 1,
5264 then the positional parameters are being used; if it is 2, then
5265 VALUE is really a pointer to an array variable that should be used.
5266 Return value is 1 if both values were OK, 0 if there was a problem
5267 with an invalid expression, or -1 if the values were out of range. */
5268 static int
5269 verify_substring_values (value, substr, vtype, e1p, e2p)
5270 char *value, *substr;
5271 int vtype;
5272 intmax_t *e1p, *e2p;
5274 char *t, *temp1, *temp2;
5275 arrayind_t len;
5276 int expok;
5277 #if defined (ARRAY_VARS)
5278 ARRAY *a;
5279 #endif
5281 /* duplicate behavior of strchr(3) */
5282 t = skiparith (substr, ':');
5283 if (*t && *t == ':')
5284 *t = '\0';
5285 else
5286 t = (char *)0;
5288 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
5289 *e1p = evalexp (temp1, &expok);
5290 free (temp1);
5291 if (expok == 0)
5292 return (0);
5294 len = -1; /* paranoia */
5295 switch (vtype)
5297 case VT_VARIABLE:
5298 case VT_ARRAYMEMBER:
5299 len = MB_STRLEN (value);
5300 break;
5301 case VT_POSPARMS:
5302 len = number_of_args () + 1;
5303 break;
5304 #if defined (ARRAY_VARS)
5305 case VT_ARRAYVAR:
5306 a = (ARRAY *)value;
5307 /* For arrays, the first value deals with array indices. Negative
5308 offsets count from one past the array's maximum index. */
5309 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
5310 break;
5311 #endif
5314 if (len == -1) /* paranoia */
5315 return -1;
5317 if (*e1p < 0) /* negative offsets count from end */
5318 *e1p += len;
5320 if (*e1p > len || *e1p < 0)
5321 return (-1);
5323 #if defined (ARRAY_VARS)
5324 /* For arrays, the second offset deals with the number of elements. */
5325 if (vtype == VT_ARRAYVAR)
5326 len = array_num_elements (a);
5327 #endif
5329 if (t)
5331 t++;
5332 temp2 = savestring (t);
5333 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
5334 free (temp2);
5335 t[-1] = ':';
5336 *e2p = evalexp (temp1, &expok);
5337 free (temp1);
5338 if (expok == 0)
5339 return (0);
5340 if (*e2p < 0)
5342 internal_error (_("%s: substring expression < 0"), t);
5343 return (0);
5345 #if defined (ARRAY_VARS)
5346 /* In order to deal with sparse arrays, push the intelligence about how
5347 to deal with the number of elements desired down to the array-
5348 specific functions. */
5349 if (vtype != VT_ARRAYVAR)
5350 #endif
5352 *e2p += *e1p; /* want E2 chars starting at E1 */
5353 if (*e2p > len)
5354 *e2p = len;
5357 else
5358 *e2p = len;
5360 return (1);
5363 /* Return the type of variable specified by VARNAME (simple variable,
5364 positional param, or array variable). Also return the value specified
5365 by VARNAME (value of a variable or a reference to an array element).
5366 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5367 characters in the value are quoted with CTLESC and takes appropriate
5368 steps. For convenience, *VALP is set to the dequoted VALUE. */
5369 static int
5370 get_var_and_type (varname, value, quoted, varp, valp)
5371 char *varname, *value;
5372 int quoted;
5373 SHELL_VAR **varp;
5374 char **valp;
5376 int vtype;
5377 char *temp;
5378 #if defined (ARRAY_VARS)
5379 SHELL_VAR *v;
5380 #endif
5382 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5383 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5384 if (vtype == VT_POSPARMS && varname[0] == '*')
5385 vtype |= VT_STARSUB;
5386 *varp = (SHELL_VAR *)NULL;
5388 #if defined (ARRAY_VARS)
5389 if (valid_array_reference (varname))
5391 v = array_variable_part (varname, &temp, (int *)0);
5392 if (v && array_p (v))
5393 { /* [ */
5394 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5396 vtype = VT_ARRAYVAR;
5397 if (temp[0] == '*')
5398 vtype |= VT_STARSUB;
5399 *valp = (char *)array_cell (v);
5401 else
5403 vtype = VT_ARRAYMEMBER;
5404 *valp = array_value (varname, 1, (int *)NULL);
5406 *varp = v;
5408 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5410 vtype = VT_VARIABLE;
5411 *varp = v;
5412 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5413 *valp = dequote_string (value);
5414 else
5415 *valp = dequote_escapes (value);
5417 else
5418 return -1;
5420 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v))
5422 vtype = VT_ARRAYMEMBER;
5423 *varp = v;
5424 *valp = array_reference (array_cell (v), 0);
5426 else
5427 #endif
5429 if (value && vtype == VT_VARIABLE)
5431 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5432 *valp = dequote_string (value);
5433 else
5434 *valp = dequote_escapes (value);
5436 else
5437 *valp = value;
5440 return vtype;
5443 /******************************************************/
5444 /* */
5445 /* Functions to extract substrings of variable values */
5446 /* */
5447 /******************************************************/
5449 #if defined (HANDLE_MULTIBYTE)
5450 /* Character-oriented rather than strictly byte-oriented substrings. S and
5451 E, rather being strict indices into STRING, indicate character (possibly
5452 multibyte character) positions that require calculation.
5453 Used by the ${param:offset[:length]} expansion. */
5454 static char *
5455 mb_substring (string, s, e)
5456 char *string;
5457 int s, e;
5459 char *tt;
5460 int start, stop, i, slen;
5461 DECLARE_MBSTATE;
5463 start = 0;
5464 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5465 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5467 i = s;
5468 while (string[start] && i--)
5469 ADVANCE_CHAR (string, slen, start);
5470 stop = start;
5471 i = e - s;
5472 while (string[stop] && i--)
5473 ADVANCE_CHAR (string, slen, stop);
5474 tt = substring (string, start, stop);
5475 return tt;
5477 #endif
5479 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
5480 is `@', use the positional parameters; otherwise, use the value of
5481 VARNAME. If VARNAME is an array variable, use the array elements. */
5483 static char *
5484 parameter_brace_substring (varname, value, substr, quoted)
5485 char *varname, *value, *substr;
5486 int quoted;
5488 intmax_t e1, e2;
5489 int vtype, r, starsub;
5490 char *temp, *val, *tt, *oname;
5491 SHELL_VAR *v;
5493 if (value == 0)
5494 return ((char *)NULL);
5496 oname = this_command_name;
5497 this_command_name = varname;
5499 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5500 if (vtype == -1)
5502 this_command_name = oname;
5503 return ((char *)NULL);
5506 starsub = vtype & VT_STARSUB;
5507 vtype &= ~VT_STARSUB;
5509 r = verify_substring_values (val, substr, vtype, &e1, &e2);
5510 this_command_name = oname;
5511 if (r <= 0)
5512 return ((r == 0) ? &expand_param_error : (char *)NULL);
5514 switch (vtype)
5516 case VT_VARIABLE:
5517 case VT_ARRAYMEMBER:
5518 #if defined (HANDLE_MULTIBYTE)
5519 if (MB_CUR_MAX > 1)
5520 tt = mb_substring (val, e1, e2);
5521 else
5522 #endif
5523 tt = substring (val, e1, e2);
5525 if (vtype == VT_VARIABLE)
5526 FREE (val);
5527 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5528 temp = quote_string (tt);
5529 else
5530 temp = tt ? quote_escapes (tt) : (char *)NULL;
5531 FREE (tt);
5532 break;
5533 case VT_POSPARMS:
5534 tt = pos_params (varname, e1, e2, quoted);
5535 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5537 temp = tt ? quote_escapes (tt) : (char *)NULL;
5538 FREE (tt);
5540 else
5541 temp = tt;
5542 break;
5543 #if defined (ARRAY_VARS)
5544 case VT_ARRAYVAR:
5545 /* We want E2 to be the number of elements desired (arrays can be sparse,
5546 so verify_substring_values just returns the numbers specified and we
5547 rely on array_subrange to understand how to deal with them). */
5548 tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5549 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5551 temp = tt ? quote_escapes (tt) : (char *)NULL;
5552 FREE (tt);
5554 else
5555 temp = tt;
5556 break;
5557 #endif
5558 default:
5559 temp = (char *)NULL;
5562 return temp;
5565 /****************************************************************/
5566 /* */
5567 /* Functions to perform pattern substitution on variable values */
5568 /* */
5569 /****************************************************************/
5571 char *
5572 pat_subst (string, pat, rep, mflags)
5573 char *string, *pat, *rep;
5574 int mflags;
5576 char *ret, *s, *e, *str;
5577 int rsize, rptr, l, replen, mtype;
5579 mtype = mflags & MATCH_TYPEMASK;
5581 /* Special cases:
5582 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
5583 * with REP and return the result.
5584 * 2. A null pattern with mtype == MATCH_END means to append REP to
5585 * STRING and return the result.
5587 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5589 replen = STRLEN (rep);
5590 l = strlen (string);
5591 ret = (char *)xmalloc (replen + l + 2);
5592 if (replen == 0)
5593 strcpy (ret, string);
5594 else if (mtype == MATCH_BEG)
5596 strcpy (ret, rep);
5597 strcpy (ret + replen, string);
5599 else
5601 strcpy (ret, string);
5602 strcpy (ret + l, rep);
5604 return (ret);
5607 ret = (char *)xmalloc (rsize = 64);
5608 ret[0] = '\0';
5610 for (replen = STRLEN (rep), rptr = 0, str = string;;)
5612 if (match_pattern (str, pat, mtype, &s, &e) == 0)
5613 break;
5614 l = s - str;
5615 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5617 /* OK, now copy the leading unmatched portion of the string (from
5618 str to s) to ret starting at rptr (the current offset). Then copy
5619 the replacement string at ret + rptr + (s - str). Increment
5620 rptr (if necessary) and str and go on. */
5621 if (l)
5623 strncpy (ret + rptr, str, l);
5624 rptr += l;
5626 if (replen)
5628 strncpy (ret + rptr, rep, replen);
5629 rptr += replen;
5631 str = e; /* e == end of match */
5633 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
5634 break;
5636 if (s == e)
5637 e++, str++; /* avoid infinite recursion on zero-length match */
5640 /* Now copy the unmatched portion of the input string */
5641 if (*str)
5643 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
5644 strcpy (ret + rptr, str);
5646 else
5647 ret[rptr] = '\0';
5649 return ret;
5652 /* Do pattern match and replacement on the positional parameters. */
5653 static char *
5654 pos_params_pat_subst (string, pat, rep, mflags)
5655 char *string, *pat, *rep;
5656 int mflags;
5658 WORD_LIST *save, *params;
5659 WORD_DESC *w;
5660 char *ret;
5662 save = params = list_rest_of_args ();
5663 if (save == 0)
5664 return ((char *)NULL);
5666 for ( ; params; params = params->next)
5668 ret = pat_subst (params->word->word, pat, rep, mflags);
5669 w = alloc_word_desc ();
5670 w->word = ret ? ret : savestring ("");
5671 dispose_word (params->word);
5672 params->word = w;
5675 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
5676 ret = string_list_dollar_star (quote_list (save));
5677 else
5678 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
5679 dispose_words (save);
5681 return (ret);
5684 /* Perform pattern substitution on VALUE, which is the expansion of
5685 VARNAME. PATSUB is an expression supplying the pattern to match
5686 and the string to substitute. QUOTED is a flags word containing
5687 the type of quoting currently in effect. */
5688 static char *
5689 parameter_brace_patsub (varname, value, patsub, quoted)
5690 char *varname, *value, *patsub;
5691 int quoted;
5693 int vtype, mflags, starsub;
5694 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
5695 SHELL_VAR *v;
5697 if (value == 0)
5698 return ((char *)NULL);
5700 this_command_name = varname;
5702 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5703 if (vtype == -1)
5704 return ((char *)NULL);
5706 starsub = vtype & VT_STARSUB;
5707 vtype &= ~VT_STARSUB;
5709 mflags = 0;
5710 if (patsub && *patsub == '/')
5712 mflags |= MATCH_GLOBREP;
5713 patsub++;
5716 /* Malloc this because expand_string_if_necessary or one of the expansion
5717 functions in its call chain may free it on a substitution error. */
5718 lpatsub = savestring (patsub);
5720 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5721 mflags |= MATCH_QUOTED;
5723 if (starsub)
5724 mflags |= MATCH_STARSUB;
5726 /* If the pattern starts with a `/', make sure we skip over it when looking
5727 for the replacement delimiter. */
5728 if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
5729 *rep++ = '\0';
5730 else
5731 rep = (char *)NULL;
5733 if (rep && *rep == '\0')
5734 rep = (char *)NULL;
5736 /* Perform the same expansions on the pattern as performed by the
5737 pattern removal expansions. */
5738 pat = getpattern (lpatsub, quoted, 1);
5740 if (rep)
5742 if ((mflags & MATCH_QUOTED) == 0)
5743 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
5744 else
5745 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
5748 /* ksh93 doesn't allow the match specifier to be a part of the expanded
5749 pattern. This is an extension. Make sure we don't anchor the pattern
5750 at the beginning or end of the string if we're doing global replacement,
5751 though. */
5752 p = pat;
5753 if (mflags & MATCH_GLOBREP)
5754 mflags |= MATCH_ANY;
5755 else if (pat && pat[0] == '#')
5757 mflags |= MATCH_BEG;
5758 p++;
5760 else if (pat && pat[0] == '%')
5762 mflags |= MATCH_END;
5763 p++;
5765 else
5766 mflags |= MATCH_ANY;
5768 /* OK, we now want to substitute REP for PAT in VAL. If
5769 flags & MATCH_GLOBREP is non-zero, the substitution is done
5770 everywhere, otherwise only the first occurrence of PAT is
5771 replaced. The pattern matching code doesn't understand
5772 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
5773 values passed in (VT_VARIABLE) so the pattern substitution
5774 code works right. We need to requote special chars after
5775 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
5776 other cases if QUOTED == 0, since the posparams and arrays
5777 indexed by * or @ do special things when QUOTED != 0. */
5779 switch (vtype)
5781 case VT_VARIABLE:
5782 case VT_ARRAYMEMBER:
5783 temp = pat_subst (val, p, rep, mflags);
5784 if (vtype == VT_VARIABLE)
5785 FREE (val);
5786 if (temp)
5788 tt = quote_escapes (temp);
5789 free (temp);
5790 temp = tt;
5792 break;
5793 case VT_POSPARMS:
5794 temp = pos_params_pat_subst (val, p, rep, mflags);
5795 if (temp && (mflags & MATCH_QUOTED) == 0)
5797 tt = quote_escapes (temp);
5798 free (temp);
5799 temp = tt;
5801 break;
5802 #if defined (ARRAY_VARS)
5803 case VT_ARRAYVAR:
5804 temp = array_patsub (array_cell (v), p, rep, mflags);
5805 if (temp && (mflags & MATCH_QUOTED) == 0)
5807 tt = quote_escapes (temp);
5808 free (temp);
5809 temp = tt;
5811 break;
5812 #endif
5815 FREE (pat);
5816 FREE (rep);
5817 free (lpatsub);
5819 return temp;
5822 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
5823 any occur, this must be a nested command substitution, so return 0.
5824 Otherwise, return 1. A valid arithmetic expression must always have a
5825 ( before a matching ), so any cases where there are more right parens
5826 means that this must not be an arithmetic expression, though the parser
5827 will not accept it without a balanced total number of parens. */
5828 static int
5829 chk_arithsub (s, len)
5830 const char *s;
5831 int len;
5833 int i, count;
5834 DECLARE_MBSTATE;
5836 i = count = 0;
5837 while (i < len)
5839 if (s[i] == '(')
5840 count++;
5841 else if (s[i] == ')')
5843 count--;
5844 if (count < 0)
5845 return 0;
5848 switch (s[i])
5850 default:
5851 ADVANCE_CHAR (s, len, i);
5852 break;
5854 case '\\':
5855 i++;
5856 if (s[i])
5857 ADVANCE_CHAR (s, len, i);
5858 break;
5860 case '\'':
5861 i = skip_single_quoted (s, len, ++i);
5862 break;
5864 case '"':
5865 i = skip_double_quoted ((char *)s, len, ++i);
5866 break;
5870 return (count == 0);
5873 /****************************************************************/
5874 /* */
5875 /* Functions to perform parameter expansion on a string */
5876 /* */
5877 /****************************************************************/
5879 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
5880 static WORD_DESC *
5881 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
5882 char *string;
5883 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
5885 int check_nullness, var_is_set, var_is_null, var_is_special;
5886 int want_substring, want_indir, want_patsub;
5887 char *name, *value, *temp, *temp1;
5888 WORD_DESC *tdesc, *ret;
5889 int t_index, sindex, c, tflag;
5890 intmax_t number;
5892 value = (char *)NULL;
5893 var_is_set = var_is_null = var_is_special = check_nullness = 0;
5894 want_substring = want_indir = want_patsub = 0;
5896 sindex = *indexp;
5897 t_index = ++sindex;
5898 /* ${#var} doesn't have any of the other parameter expansions on it. */
5899 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
5900 name = string_extract (string, &t_index, "}", EX_VARNAME);
5901 else
5902 name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
5904 ret = 0;
5905 tflag = 0;
5907 /* If the name really consists of a special variable, then make sure
5908 that we have the entire name. We don't allow indirect references
5909 to special variables except `#', `?', `@' and `*'. */
5910 if ((sindex == t_index &&
5911 (string[t_index] == '-' ||
5912 string[t_index] == '?' ||
5913 string[t_index] == '#')) ||
5914 (sindex == t_index - 1 && string[sindex] == '!' &&
5915 (string[t_index] == '#' ||
5916 string[t_index] == '?' ||
5917 string[t_index] == '@' ||
5918 string[t_index] == '*')))
5920 t_index++;
5921 free (name);
5922 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
5923 name = (char *)xmalloc (3 + (strlen (temp1)));
5924 *name = string[sindex];
5925 if (string[sindex] == '!')
5927 /* indirect reference of $#, $?, $@, or $* */
5928 name[1] = string[sindex + 1];
5929 strcpy (name + 2, temp1);
5931 else
5932 strcpy (name + 1, temp1);
5933 free (temp1);
5935 sindex = t_index;
5937 /* Find out what character ended the variable name. Then
5938 do the appropriate thing. */
5939 if (c = string[sindex])
5940 sindex++;
5942 /* If c is followed by one of the valid parameter expansion
5943 characters, move past it as normal. If not, assume that
5944 a substring specification is being given, and do not move
5945 past it. */
5946 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
5948 check_nullness++;
5949 if (c = string[sindex])
5950 sindex++;
5952 else if (c == ':' && string[sindex] != RBRACE)
5953 want_substring = 1;
5954 else if (c == '/' && string[sindex] != RBRACE)
5955 want_patsub = 1;
5957 /* Catch the valid and invalid brace expressions that made it through the
5958 tests above. */
5959 /* ${#-} is a valid expansion and means to take the length of $-.
5960 Similarly for ${#?} and ${##}... */
5961 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
5962 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
5964 name = (char *)xrealloc (name, 3);
5965 name[1] = c;
5966 name[2] = '\0';
5967 c = string[sindex++];
5970 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
5971 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
5972 member (c, "%:=+/") && string[sindex] == RBRACE)
5974 temp = (char *)NULL;
5975 goto bad_substitution;
5978 /* Indirect expansion begins with a `!'. A valid indirect expansion is
5979 either a variable name, one of the positional parameters or a special
5980 variable that expands to one of the positional parameters. */
5981 want_indir = *name == '!' &&
5982 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
5983 || VALID_INDIR_PARAM (name[1]));
5985 /* Determine the value of this variable. */
5987 /* Check for special variables, directly referenced. */
5988 if (SPECIAL_VAR (name, want_indir))
5989 var_is_special++;
5991 /* Check for special expansion things, like the length of a parameter */
5992 if (*name == '#' && name[1])
5994 /* If we are not pointing at the character just after the
5995 closing brace, then we haven't gotten all of the name.
5996 Since it begins with a special character, this is a bad
5997 substitution. Also check NAME for validity before trying
5998 to go on. */
5999 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
6001 temp = (char *)NULL;
6002 goto bad_substitution;
6005 number = parameter_brace_expand_length (name);
6006 free (name);
6008 *indexp = sindex;
6009 if (number < 0)
6010 return (&expand_wdesc_error);
6011 else
6013 ret = alloc_word_desc ();
6014 ret->word = itos (number);
6015 return ret;
6019 /* ${@} is identical to $@. */
6020 if (name[0] == '@' && name[1] == '\0')
6022 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6023 *quoted_dollar_atp = 1;
6025 if (contains_dollar_at)
6026 *contains_dollar_at = 1;
6029 /* Process ${!PREFIX*} expansion. */
6030 if (want_indir && string[sindex - 1] == RBRACE &&
6031 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
6032 legal_variable_starter ((unsigned char) name[1]))
6034 char **x;
6035 WORD_LIST *xlist;
6037 temp1 = savestring (name + 1);
6038 number = strlen (temp1);
6039 temp1[number - 1] = '\0';
6040 x = all_variables_matching_prefix (temp1);
6041 xlist = strvec_to_word_list (x, 0, 0);
6042 if (string[sindex - 2] == '*')
6043 temp = string_list_dollar_star (xlist);
6044 else
6046 temp = string_list_dollar_at (xlist, quoted);
6047 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6048 *quoted_dollar_atp = 1;
6049 if (contains_dollar_at)
6050 *contains_dollar_at = 1;
6052 free (x);
6053 free (xlist);
6054 free (temp1);
6055 *indexp = sindex;
6057 ret = alloc_word_desc ();
6058 ret->word = temp;
6059 return ret;
6062 #if defined (ARRAY_VARS)
6063 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
6064 if (want_indir && string[sindex - 1] == RBRACE &&
6065 string[sindex - 2] == ']' && valid_array_reference (name+1))
6067 char *x, *x1;
6069 temp1 = savestring (name + 1);
6070 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
6071 FREE (x);
6072 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
6074 temp = array_keys (temp1, quoted);
6075 if (x1[0] == '@')
6077 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6078 *quoted_dollar_atp = 1;
6079 if (contains_dollar_at)
6080 *contains_dollar_at = 1;
6083 free (temp1);
6084 *indexp = sindex;
6086 ret = alloc_word_desc ();
6087 ret->word = temp;
6088 return ret;
6091 free (temp1);
6093 #endif /* ARRAY_VARS */
6095 /* Make sure that NAME is valid before trying to go on. */
6096 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
6097 var_is_special) == 0)
6099 temp = (char *)NULL;
6100 goto bad_substitution;
6103 if (want_indir)
6104 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6105 else
6106 tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
6108 if (tdesc)
6110 temp = tdesc->word;
6111 tflag = tdesc->flags;
6112 dispose_word_desc (tdesc);
6114 else
6115 temp = (char *)0;
6117 #if defined (ARRAY_VARS)
6118 if (valid_array_reference (name))
6119 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6120 #endif
6122 var_is_set = temp != (char *)0;
6123 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6125 /* Get the rest of the stuff inside the braces. */
6126 if (c && c != RBRACE)
6128 /* Extract the contents of the ${ ... } expansion
6129 according to the Posix.2 rules. */
6130 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6131 if (string[sindex] == RBRACE)
6132 sindex++;
6133 else
6134 goto bad_substitution;
6136 else
6137 value = (char *)NULL;
6139 *indexp = sindex;
6141 /* If this is a substring spec, process it and add the result. */
6142 if (want_substring)
6144 temp1 = parameter_brace_substring (name, temp, value, quoted);
6145 FREE (name);
6146 FREE (value);
6147 FREE (temp);
6149 if (temp1 == &expand_param_error)
6150 return (&expand_wdesc_error);
6151 else if (temp1 == &expand_param_fatal)
6152 return (&expand_wdesc_fatal);
6154 ret = alloc_word_desc ();
6155 ret->word = temp1;
6156 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6157 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6158 return ret;
6160 else if (want_patsub)
6162 temp1 = parameter_brace_patsub (name, temp, value, quoted);
6163 FREE (name);
6164 FREE (value);
6165 FREE (temp);
6167 if (temp1 == &expand_param_error)
6168 return (&expand_wdesc_error);
6169 else if (temp1 == &expand_param_fatal)
6170 return (&expand_wdesc_fatal);
6172 ret = alloc_word_desc ();
6173 ret->word = temp1;
6174 return ret;
6177 /* Do the right thing based on which character ended the variable name. */
6178 switch (c)
6180 default:
6181 case '\0':
6182 bad_substitution:
6183 report_error (_("%s: bad substitution"), string ? string : "??");
6184 FREE (value);
6185 FREE (temp);
6186 free (name);
6187 return &expand_wdesc_error;
6189 case RBRACE:
6190 if (var_is_set == 0 && unbound_vars_is_error)
6192 err_unboundvar (name);
6193 FREE (value);
6194 FREE (temp);
6195 free (name);
6196 last_command_exit_value = EXECUTION_FAILURE;
6197 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6199 break;
6201 case '#': /* ${param#[#]pattern} */
6202 case '%': /* ${param%[%]pattern} */
6203 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6205 FREE (value);
6206 break;
6208 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6209 free (temp);
6210 free (value);
6211 temp = temp1;
6212 break;
6214 case '-':
6215 case '=':
6216 case '?':
6217 case '+':
6218 if (var_is_set && var_is_null == 0)
6220 /* If the operator is `+', we don't want the value of the named
6221 variable for anything, just the value of the right hand side. */
6223 if (c == '+')
6225 /* XXX -- if we're double-quoted and the named variable is "$@",
6226 we want to turn off any special handling of "$@" --
6227 we're not using it, so whatever is on the rhs applies. */
6228 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6229 *quoted_dollar_atp = 0;
6230 if (contains_dollar_at)
6231 *contains_dollar_at = 0;
6233 FREE (temp);
6234 if (value)
6236 ret = parameter_brace_expand_rhs (name, value, c,
6237 quoted,
6238 quoted_dollar_atp,
6239 contains_dollar_at);
6240 /* XXX - fix up later, esp. noting presence of
6241 W_HASQUOTEDNULL in ret->flags */
6242 free (value);
6244 else
6245 temp = (char *)NULL;
6247 else
6249 FREE (value);
6251 /* Otherwise do nothing; just use the value in TEMP. */
6253 else /* VAR not set or VAR is NULL. */
6255 FREE (temp);
6256 temp = (char *)NULL;
6257 if (c == '=' && var_is_special)
6259 report_error (_("$%s: cannot assign in this way"), name);
6260 free (name);
6261 free (value);
6262 return &expand_wdesc_error;
6264 else if (c == '?')
6266 parameter_brace_expand_error (name, value);
6267 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6269 else if (c != '+')
6271 /* XXX -- if we're double-quoted and the named variable is "$@",
6272 we want to turn off any special handling of "$@" --
6273 we're not using it, so whatever is on the rhs applies. */
6274 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6275 *quoted_dollar_atp = 0;
6276 if (contains_dollar_at)
6277 *contains_dollar_at = 0;
6279 ret = parameter_brace_expand_rhs (name, value, c, quoted,
6280 quoted_dollar_atp,
6281 contains_dollar_at);
6282 /* XXX - fix up later, esp. noting presence of
6283 W_HASQUOTEDNULL in tdesc->flags */
6285 free (value);
6288 break;
6290 free (name);
6292 if (ret == 0)
6294 ret = alloc_word_desc ();
6295 ret->flags = tflag;
6296 ret->word = temp;
6298 return (ret);
6301 /* Expand a single ${xxx} expansion. The braces are optional. When
6302 the braces are used, parameter_brace_expand() does the work,
6303 possibly calling param_expand recursively. */
6304 static WORD_DESC *
6305 param_expand (string, sindex, quoted, expanded_something,
6306 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6307 pflags)
6308 char *string;
6309 int *sindex, quoted, *expanded_something, *contains_dollar_at;
6310 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6312 char *temp, *temp1, uerror[3];
6313 int zindex, t_index, expok;
6314 unsigned char c;
6315 intmax_t number;
6316 SHELL_VAR *var;
6317 WORD_LIST *list;
6318 WORD_DESC *tdesc, *ret;
6319 int tflag;
6321 zindex = *sindex;
6322 c = string[++zindex];
6324 temp = (char *)NULL;
6325 ret = tdesc = (WORD_DESC *)NULL;
6326 tflag = 0;
6328 /* Do simple cases first. Switch on what follows '$'. */
6329 switch (c)
6331 /* $0 .. $9? */
6332 case '0':
6333 case '1':
6334 case '2':
6335 case '3':
6336 case '4':
6337 case '5':
6338 case '6':
6339 case '7':
6340 case '8':
6341 case '9':
6342 temp1 = dollar_vars[TODIGIT (c)];
6343 if (unbound_vars_is_error && temp1 == (char *)NULL)
6345 uerror[0] = '$';
6346 uerror[1] = c;
6347 uerror[2] = '\0';
6348 err_unboundvar (uerror);
6349 last_command_exit_value = EXECUTION_FAILURE;
6350 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6352 if (temp1)
6353 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6354 ? quote_string (temp1)
6355 : quote_escapes (temp1);
6356 else
6357 temp = (char *)NULL;
6359 break;
6361 /* $$ -- pid of the invoking shell. */
6362 case '$':
6363 temp = itos (dollar_dollar_pid);
6364 break;
6366 /* $# -- number of positional parameters. */
6367 case '#':
6368 temp = itos (number_of_args ());
6369 break;
6371 /* $? -- return value of the last synchronous command. */
6372 case '?':
6373 temp = itos (last_command_exit_value);
6374 break;
6376 /* $- -- flags supplied to the shell on invocation or by `set'. */
6377 case '-':
6378 temp = which_set_flags ();
6379 break;
6381 /* $! -- Pid of the last asynchronous command. */
6382 case '!':
6383 /* If no asynchronous pids have been created, expand to nothing.
6384 If `set -u' has been executed, and no async processes have
6385 been created, this is an expansion error. */
6386 if (last_asynchronous_pid == NO_PID)
6388 if (expanded_something)
6389 *expanded_something = 0;
6390 temp = (char *)NULL;
6391 if (unbound_vars_is_error)
6393 uerror[0] = '$';
6394 uerror[1] = c;
6395 uerror[2] = '\0';
6396 err_unboundvar (uerror);
6397 last_command_exit_value = EXECUTION_FAILURE;
6398 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6401 else
6402 temp = itos (last_asynchronous_pid);
6403 break;
6405 /* The only difference between this and $@ is when the arg is quoted. */
6406 case '*': /* `$*' */
6407 list = list_rest_of_args ();
6409 /* If there are no command-line arguments, this should just
6410 disappear if there are other characters in the expansion,
6411 even if it's quoted. */
6412 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
6413 temp = (char *)NULL;
6414 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6416 /* If we have "$*" we want to make a string of the positional
6417 parameters, separated by the first character of $IFS, and
6418 quote the whole string, including the separators. If IFS
6419 is unset, the parameters are separated by ' '; if $IFS is
6420 null, the parameters are concatenated. */
6421 temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
6422 temp1 = quote_string (temp);
6423 if (*temp == 0)
6424 tflag |= W_HASQUOTEDNULL;
6425 free (temp);
6426 temp = temp1;
6428 else
6430 /* We check whether or not we're eventually going to split $* here,
6431 for example when IFS is empty and we are processing the rhs of
6432 an assignment statement. In that case, we don't separate the
6433 arguments at all. Otherwise, if the $* is not quoted it is
6434 identical to $@ */
6435 #if 1
6436 # if defined (HANDLE_MULTIBYTE)
6437 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
6438 # else
6439 if (expand_no_split_dollar_star && ifs_firstc == 0)
6440 # endif
6441 temp = string_list_dollar_star (list);
6442 else
6443 temp = string_list_dollar_at (list, quoted);
6444 #else
6445 temp = string_list_dollar_at (list, quoted);
6446 #endif
6447 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
6448 *contains_dollar_at = 1;
6451 dispose_words (list);
6452 break;
6454 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
6455 means that we have to turn quoting off after we split into
6456 the individually quoted arguments so that the final split
6457 on the first character of $IFS is still done. */
6458 case '@': /* `$@' */
6459 list = list_rest_of_args ();
6461 /* We want to flag the fact that we saw this. We can't turn
6462 off quoting entirely, because other characters in the
6463 string might need it (consider "\"$@\""), but we need some
6464 way to signal that the final split on the first character
6465 of $IFS should be done, even though QUOTED is 1. */
6466 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6467 *quoted_dollar_at_p = 1;
6468 if (contains_dollar_at)
6469 *contains_dollar_at = 1;
6471 /* We want to separate the positional parameters with the first
6472 character of $IFS in case $IFS is something other than a space.
6473 We also want to make sure that splitting is done no matter what --
6474 according to POSIX.2, this expands to a list of the positional
6475 parameters no matter what IFS is set to. */
6476 temp = string_list_dollar_at (list, quoted);
6478 dispose_words (list);
6479 break;
6481 case LBRACE:
6482 tdesc = parameter_brace_expand (string, &zindex, quoted,
6483 quoted_dollar_at_p,
6484 contains_dollar_at);
6486 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
6487 return (tdesc);
6488 temp = tdesc ? tdesc->word : (char *)0;
6490 /* XXX */
6491 /* Quoted nulls should be removed if there is anything else
6492 in the string. */
6493 /* Note that we saw the quoted null so we can add one back at
6494 the end of this function if there are no other characters
6495 in the string, discard TEMP, and go on. The exception to
6496 this is when we have "${@}" and $1 is '', since $@ needs
6497 special handling. */
6498 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
6500 if (had_quoted_null_p)
6501 *had_quoted_null_p = 1;
6502 if (*quoted_dollar_at_p == 0)
6504 free (temp);
6505 tdesc->word = temp = (char *)NULL;
6510 ret = tdesc;
6511 goto return0;
6513 /* Do command or arithmetic substitution. */
6514 case LPAREN:
6515 /* We have to extract the contents of this paren substitution. */
6516 t_index = zindex + 1;
6517 temp = extract_command_subst (string, &t_index);
6518 zindex = t_index;
6520 /* For Posix.2-style `$(( ))' arithmetic substitution,
6521 extract the expression and pass it to the evaluator. */
6522 if (temp && *temp == LPAREN)
6524 char *temp2;
6525 temp1 = temp + 1;
6526 temp2 = savestring (temp1);
6527 t_index = strlen (temp2) - 1;
6529 if (temp2[t_index] != RPAREN)
6531 free (temp2);
6532 goto comsub;
6535 /* Cut off ending `)' */
6536 temp2[t_index] = '\0';
6538 if (chk_arithsub (temp2, t_index) == 0)
6540 free (temp2);
6541 goto comsub;
6544 /* Expand variables found inside the expression. */
6545 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
6546 free (temp2);
6548 arithsub:
6549 /* No error messages. */
6550 this_command_name = (char *)NULL;
6551 number = evalexp (temp1, &expok);
6552 free (temp);
6553 free (temp1);
6554 if (expok == 0)
6556 if (interactive_shell == 0 && posixly_correct)
6558 last_command_exit_value = EXECUTION_FAILURE;
6559 return (&expand_wdesc_fatal);
6561 else
6562 return (&expand_wdesc_error);
6564 temp = itos (number);
6565 break;
6568 comsub:
6569 if (pflags & PF_NOCOMSUB)
6570 /* we need zindex+1 because string[zindex] == RPAREN */
6571 temp1 = substring (string, *sindex, zindex+1);
6572 else
6573 temp1 = command_substitute (temp, quoted);
6574 FREE (temp);
6575 temp = temp1;
6576 break;
6578 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
6579 away in a future bash release. */
6580 case '[':
6581 /* Extract the contents of this arithmetic substitution. */
6582 t_index = zindex + 1;
6583 temp = extract_arithmetic_subst (string, &t_index);
6584 zindex = t_index;
6586 /* Do initial variable expansion. */
6587 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
6589 goto arithsub;
6591 default:
6592 /* Find the variable in VARIABLE_LIST. */
6593 temp = (char *)NULL;
6595 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
6597 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
6599 /* If this isn't a variable name, then just output the `$'. */
6600 if (temp1 == 0 || *temp1 == '\0')
6602 FREE (temp1);
6603 temp = (char *)xmalloc (2);
6604 temp[0] = '$';
6605 temp[1] = '\0';
6606 if (expanded_something)
6607 *expanded_something = 0;
6608 goto return0;
6611 /* If the variable exists, return its value cell. */
6612 var = find_variable (temp1);
6614 if (var && invisible_p (var) == 0 && var_isset (var))
6616 #if defined (ARRAY_VARS)
6617 if (array_p (var))
6619 temp = array_reference (array_cell (var), 0);
6620 if (temp)
6621 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6622 ? quote_string (temp)
6623 : quote_escapes (temp);
6624 else if (unbound_vars_is_error)
6625 goto unbound_variable;
6627 else
6628 #endif
6630 temp = value_cell (var);
6632 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6633 ? quote_string (temp)
6634 : quote_escapes (temp);
6637 free (temp1);
6639 goto return0;
6642 temp = (char *)NULL;
6644 unbound_variable:
6645 if (unbound_vars_is_error)
6646 err_unboundvar (temp1);
6647 else
6649 free (temp1);
6650 goto return0;
6653 free (temp1);
6654 last_command_exit_value = EXECUTION_FAILURE;
6655 return ((unbound_vars_is_error && interactive_shell == 0)
6656 ? &expand_wdesc_fatal
6657 : &expand_wdesc_error);
6660 if (string[zindex])
6661 zindex++;
6663 return0:
6664 *sindex = zindex;
6666 if (ret == 0)
6668 ret = alloc_word_desc ();
6669 ret->flags = tflag; /* XXX */
6670 ret->word = temp;
6672 return ret;
6675 /* Make a word list which is the result of parameter and variable
6676 expansion, command substitution, arithmetic substitution, and
6677 quote removal of WORD. Return a pointer to a WORD_LIST which is
6678 the result of the expansion. If WORD contains a null word, the
6679 word list returned is also null.
6681 QUOTED contains flag values defined in shell.h.
6683 ISEXP is used to tell expand_word_internal that the word should be
6684 treated as the result of an expansion. This has implications for
6685 how IFS characters in the word are treated.
6687 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
6688 they point to an integer value which receives information about expansion.
6689 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
6690 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
6691 else zero.
6693 This only does word splitting in the case of $@ expansion. In that
6694 case, we split on ' '. */
6696 /* Values for the local variable quoted_state. */
6697 #define UNQUOTED 0
6698 #define PARTIALLY_QUOTED 1
6699 #define WHOLLY_QUOTED 2
6701 static WORD_LIST *
6702 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
6703 WORD_DESC *word;
6704 int quoted, isexp;
6705 int *contains_dollar_at;
6706 int *expanded_something;
6708 WORD_LIST *list;
6709 WORD_DESC *tword;
6711 /* The intermediate string that we build while expanding. */
6712 char *istring;
6714 /* The current size of the above object. */
6715 int istring_size;
6717 /* Index into ISTRING. */
6718 int istring_index;
6720 /* Temporary string storage. */
6721 char *temp, *temp1;
6723 /* The text of WORD. */
6724 register char *string;
6726 /* The size of STRING. */
6727 size_t string_size;
6729 /* The index into STRING. */
6730 int sindex;
6732 /* This gets 1 if we see a $@ while quoted. */
6733 int quoted_dollar_at;
6735 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
6736 whether WORD contains no quoting characters, a partially quoted
6737 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
6738 int quoted_state;
6740 /* State flags */
6741 int had_quoted_null;
6742 int has_dollar_at;
6743 int tflag;
6745 int assignoff; /* If assignment, offset of `=' */
6747 register unsigned char c; /* Current character. */
6748 int t_index; /* For calls to string_extract_xxx. */
6750 char twochars[2];
6752 DECLARE_MBSTATE;
6754 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
6755 istring[istring_index = 0] = '\0';
6756 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
6757 quoted_state = UNQUOTED;
6759 string = word->word;
6760 if (string == 0)
6761 goto finished_with_string;
6762 /* Don't need the string length for the SADD... and COPY_ macros unless
6763 multibyte characters are possible. */
6764 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
6766 if (contains_dollar_at)
6767 *contains_dollar_at = 0;
6769 assignoff = -1;
6771 /* Begin the expansion. */
6773 for (sindex = 0; ;)
6775 c = string[sindex];
6777 /* Case on toplevel character. */
6778 switch (c)
6780 case '\0':
6781 goto finished_with_string;
6783 case CTLESC:
6784 sindex++;
6785 #if HANDLE_MULTIBYTE
6786 if (MB_CUR_MAX > 1 && string[sindex])
6788 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
6790 else
6791 #endif
6793 temp = (char *)xmalloc (3);
6794 temp[0] = CTLESC;
6795 temp[1] = c = string[sindex];
6796 temp[2] = '\0';
6799 dollar_add_string:
6800 if (string[sindex])
6801 sindex++;
6803 add_string:
6804 if (temp)
6806 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
6807 temp = (char *)0;
6810 break;
6812 #if defined (PROCESS_SUBSTITUTION)
6813 /* Process substitution. */
6814 case '<':
6815 case '>':
6817 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
6819 sindex--; /* add_character: label increments sindex */
6820 goto add_character;
6822 else
6823 t_index = sindex + 1; /* skip past both '<' and LPAREN */
6825 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
6826 sindex = t_index;
6828 /* If the process substitution specification is `<()', we want to
6829 open the pipe for writing in the child and produce output; if
6830 it is `>()', we want to open the pipe for reading in the child
6831 and consume input. */
6832 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
6834 FREE (temp1);
6836 goto dollar_add_string;
6838 #endif /* PROCESS_SUBSTITUTION */
6840 case '=':
6841 /* Posix.2 section 3.6.1 says that tildes following `=' in words
6842 which are not assignment statements are not expanded. If the
6843 shell isn't in posix mode, though, we perform tilde expansion
6844 on `likely candidate' unquoted assignment statements (flags
6845 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
6846 contains an unquoted :~ or =~. Something to think about: we
6847 now have a flag that says to perform tilde expansion on arguments
6848 to `assignment builtins' like declare and export that look like
6849 assignment statements. We now do tilde expansion on such words
6850 even in POSIX mode. */
6851 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
6852 goto add_character;
6853 /* If we're not in posix mode or forcing assignment-statement tilde
6854 expansion, note where the `=' appears in the word and prepare to
6855 do tilde expansion following the first `='. */
6856 if ((word->flags & W_ASSIGNMENT) &&
6857 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
6858 assignoff == -1 && sindex > 0)
6859 assignoff = sindex;
6860 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
6861 word->flags |= W_ITILDE;
6862 #if 0
6863 else if ((word->flags & W_ASSIGNMENT) &&
6864 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
6865 string[sindex+1] == '~')
6866 word->flags |= W_ITILDE;
6867 #endif
6868 goto add_character;
6870 case ':':
6871 if (word->flags & W_NOTILDE)
6872 goto add_character;
6874 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
6875 string[sindex+1] == '~')
6876 word->flags |= W_ITILDE;
6877 goto add_character;
6879 case '~':
6880 /* If the word isn't supposed to be tilde expanded, or we're not
6881 at the start of a word or after an unquoted : or = in an
6882 assignment statement, we don't do tilde expansion. */
6883 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
6884 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
6885 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6887 word->flags &= ~W_ITILDE;
6888 goto add_character;
6891 if (word->flags & W_ASSIGNRHS)
6892 tflag = 2;
6893 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
6894 tflag = 1;
6895 else
6896 tflag = 0;
6898 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
6900 word->flags &= ~W_ITILDE;
6902 if (temp && *temp && t_index > 0)
6904 temp1 = bash_tilde_expand (temp, tflag);
6905 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
6907 FREE (temp);
6908 FREE (temp1);
6909 goto add_character; /* tilde expansion failed */
6911 free (temp);
6912 temp = temp1;
6913 sindex += t_index;
6914 goto add_string;
6916 else
6918 FREE (temp);
6919 goto add_character;
6922 case '$':
6923 if (expanded_something)
6924 *expanded_something = 1;
6926 has_dollar_at = 0;
6927 tword = param_expand (string, &sindex, quoted, expanded_something,
6928 &has_dollar_at, &quoted_dollar_at,
6929 &had_quoted_null,
6930 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
6932 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
6934 free (string);
6935 free (istring);
6936 return ((tword == &expand_wdesc_error) ? &expand_word_error
6937 : &expand_word_fatal);
6939 if (contains_dollar_at && has_dollar_at)
6940 *contains_dollar_at = 1;
6942 if (tword && (tword->flags & W_HASQUOTEDNULL))
6943 had_quoted_null = 1;
6945 temp = tword->word;
6946 dispose_word_desc (tword);
6948 goto add_string;
6949 break;
6951 case '`': /* Backquoted command substitution. */
6953 t_index = sindex++;
6955 temp = string_extract (string, &sindex, "`", EX_REQMATCH);
6956 /* The test of sindex against t_index is to allow bare instances of
6957 ` to pass through, for backwards compatibility. */
6958 if (temp == &extract_string_error || temp == &extract_string_fatal)
6960 if (sindex - 1 == t_index)
6962 sindex = t_index;
6963 goto add_character;
6965 report_error ("bad substitution: no closing \"`\" in %s", string+t_index);
6966 free (string);
6967 free (istring);
6968 return ((temp == &extract_string_error) ? &expand_word_error
6969 : &expand_word_fatal);
6972 if (expanded_something)
6973 *expanded_something = 1;
6975 if (word->flags & W_NOCOMSUB)
6976 /* sindex + 1 because string[sindex] == '`' */
6977 temp1 = substring (string, t_index, sindex + 1);
6978 else
6980 de_backslash (temp);
6981 temp1 = command_substitute (temp, quoted);
6983 FREE (temp);
6984 temp = temp1;
6985 goto dollar_add_string;
6988 case '\\':
6989 if (string[sindex + 1] == '\n')
6991 sindex += 2;
6992 continue;
6995 c = string[++sindex];
6997 if (quoted & Q_HERE_DOCUMENT)
6998 tflag = CBSHDOC;
6999 else if (quoted & Q_DOUBLE_QUOTES)
7000 tflag = CBSDQUOTE;
7001 else
7002 tflag = 0;
7004 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7006 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7008 else if (c == 0)
7010 c = CTLNUL;
7011 sindex--; /* add_character: label increments sindex */
7012 goto add_character;
7014 else
7016 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7019 sindex++;
7020 add_twochars:
7021 /* BEFORE jumping here, we need to increment sindex if appropriate */
7022 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7023 DEFAULT_ARRAY_SIZE);
7024 istring[istring_index++] = twochars[0];
7025 istring[istring_index++] = twochars[1];
7026 istring[istring_index] = '\0';
7028 break;
7030 case '"':
7031 #if 0
7032 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7033 #else
7034 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7035 #endif
7036 goto add_character;
7038 t_index = ++sindex;
7039 temp = string_extract_double_quoted (string, &sindex, 0);
7041 /* If the quotes surrounded the entire string, then the
7042 whole word was quoted. */
7043 quoted_state = (t_index == 1 && string[sindex] == '\0')
7044 ? WHOLLY_QUOTED
7045 : PARTIALLY_QUOTED;
7047 if (temp && *temp)
7049 tword = alloc_word_desc ();
7050 tword->word = temp;
7052 temp = (char *)NULL;
7054 has_dollar_at = 0;
7055 /* Need to get W_HASQUOTEDNULL flag through this function. */
7056 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7058 if (list == &expand_word_error || list == &expand_word_fatal)
7060 free (istring);
7061 free (string);
7062 /* expand_word_internal has already freed temp_word->word
7063 for us because of the way it prints error messages. */
7064 tword->word = (char *)NULL;
7065 dispose_word (tword);
7066 return list;
7069 dispose_word (tword);
7071 /* "$@" (a double-quoted dollar-at) expands into nothing,
7072 not even a NULL word, when there are no positional
7073 parameters. */
7074 if (list == 0 && has_dollar_at)
7076 quoted_dollar_at++;
7077 break;
7080 /* If we get "$@", we know we have expanded something, so we
7081 need to remember it for the final split on $IFS. This is
7082 a special case; it's the only case where a quoted string
7083 can expand into more than one word. It's going to come back
7084 from the above call to expand_word_internal as a list with
7085 a single word, in which all characters are quoted and
7086 separated by blanks. What we want to do is to turn it back
7087 into a list for the next piece of code. */
7088 if (list)
7089 dequote_list (list);
7091 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7092 had_quoted_null = 1;
7094 if (has_dollar_at)
7096 quoted_dollar_at++;
7097 if (contains_dollar_at)
7098 *contains_dollar_at = 1;
7099 if (expanded_something)
7100 *expanded_something = 1;
7103 else
7105 /* What we have is "". This is a minor optimization. */
7106 FREE (temp);
7107 list = (WORD_LIST *)NULL;
7110 /* The code above *might* return a list (consider the case of "$@",
7111 where it returns "$1", "$2", etc.). We can't throw away the
7112 rest of the list, and we have to make sure each word gets added
7113 as quoted. We test on tresult->next: if it is non-NULL, we
7114 quote the whole list, save it to a string with string_list, and
7115 add that string. We don't need to quote the results of this
7116 (and it would be wrong, since that would quote the separators
7117 as well), so we go directly to add_string. */
7118 if (list)
7120 if (list->next)
7122 /* Testing quoted_dollar_at makes sure that "$@" is
7123 split correctly when $IFS does not contain a space. */
7124 temp = quoted_dollar_at
7125 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7126 : string_list (quote_list (list));
7127 dispose_words (list);
7128 goto add_string;
7130 else
7132 temp = savestring (list->word->word);
7133 tflag = list->word->flags;
7134 dispose_words (list);
7136 /* If the string is not a quoted null string, we want
7137 to remove any embedded unquoted CTLNUL characters.
7138 We do not want to turn quoted null strings back into
7139 the empty string, though. We do this because we
7140 want to remove any quoted nulls from expansions that
7141 contain other characters. For example, if we have
7142 x"$*"y or "x$*y" and there are no positional parameters,
7143 the $* should expand into nothing. */
7144 /* We use the W_HASQUOTEDNULL flag to differentiate the
7145 cases: a quoted null character as above and when
7146 CTLNUL is contained in the (non-null) expansion
7147 of some variable. We use the had_quoted_null flag to
7148 pass the value through this function to its caller. */
7149 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7150 remove_quoted_nulls (temp); /* XXX */
7153 else
7154 temp = (char *)NULL;
7156 /* We do not want to add quoted nulls to strings that are only
7157 partially quoted; we can throw them away. */
7158 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7159 continue;
7161 add_quoted_string:
7163 if (temp)
7165 temp1 = temp;
7166 temp = quote_string (temp);
7167 free (temp1);
7168 goto add_string;
7170 else
7172 /* Add NULL arg. */
7173 c = CTLNUL;
7174 sindex--; /* add_character: label increments sindex */
7175 goto add_character;
7178 /* break; */
7180 case '\'':
7181 #if 0
7182 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7183 #else
7184 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7185 #endif
7186 goto add_character;
7188 t_index = ++sindex;
7189 temp = string_extract_single_quoted (string, &sindex);
7191 /* If the entire STRING was surrounded by single quotes,
7192 then the string is wholly quoted. */
7193 quoted_state = (t_index == 1 && string[sindex] == '\0')
7194 ? WHOLLY_QUOTED
7195 : PARTIALLY_QUOTED;
7197 /* If all we had was '', it is a null expansion. */
7198 if (*temp == '\0')
7200 free (temp);
7201 temp = (char *)NULL;
7203 else
7204 remove_quoted_escapes (temp); /* ??? */
7206 /* We do not want to add quoted nulls to strings that are only
7207 partially quoted; such nulls are discarded. */
7208 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7209 continue;
7211 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7212 if (temp == 0)
7214 c = CTLNUL;
7215 sindex--; /* add_character: label increments sindex */
7216 goto add_character;
7218 else
7219 goto add_quoted_string;
7221 /* break; */
7223 default:
7224 /* This is the fix for " $@ " */
7225 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7227 if (string[sindex]) /* from old goto dollar_add_string */
7228 sindex++;
7229 if (c == 0)
7231 c = CTLNUL;
7232 goto add_character;
7234 else
7236 #if HANDLE_MULTIBYTE
7237 if (MB_CUR_MAX > 1)
7238 sindex--;
7240 if (MB_CUR_MAX > 1)
7242 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7244 else
7245 #endif
7247 twochars[0] = CTLESC;
7248 twochars[1] = c;
7249 goto add_twochars;
7254 SADD_MBCHAR (temp, string, sindex, string_size);
7256 add_character:
7257 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7258 DEFAULT_ARRAY_SIZE);
7259 istring[istring_index++] = c;
7260 istring[istring_index] = '\0';
7262 /* Next character. */
7263 sindex++;
7267 finished_with_string:
7268 /* OK, we're ready to return. If we have a quoted string, and
7269 quoted_dollar_at is not set, we do no splitting at all; otherwise
7270 we split on ' '. The routines that call this will handle what to
7271 do if nothing has been expanded. */
7273 /* Partially and wholly quoted strings which expand to the empty
7274 string are retained as an empty arguments. Unquoted strings
7275 which expand to the empty string are discarded. The single
7276 exception is the case of expanding "$@" when there are no
7277 positional parameters. In that case, we discard the expansion. */
7279 /* Because of how the code that handles "" and '' in partially
7280 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7281 if we saw quoting characters, but the expansion was empty.
7282 "" and '' are tossed away before we get to this point when
7283 processing partially quoted strings. This makes "" and $xxx""
7284 equivalent when xxx is unset. We also look to see whether we
7285 saw a quoted null from a ${} expansion and add one back if we
7286 need to. */
7288 /* If we expand to nothing and there were no single or double quotes
7289 in the word, we throw it away. Otherwise, we return a NULL word.
7290 The single exception is for $@ surrounded by double quotes when
7291 there are no positional parameters. In that case, we also throw
7292 the word away. */
7294 if (*istring == '\0')
7296 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7298 istring[0] = CTLNUL;
7299 istring[1] = '\0';
7300 tword = make_bare_word (istring);
7301 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7302 list = make_word_list (tword, (WORD_LIST *)NULL);
7303 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7304 tword->flags |= W_QUOTED;
7306 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7307 and a double-quoted "$@" appears anywhere in it, then the entire
7308 word is removed. */
7309 else if (quoted_state == UNQUOTED || quoted_dollar_at)
7310 list = (WORD_LIST *)NULL;
7311 #if 0
7312 else
7314 tword = make_bare_word (istring);
7315 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7316 tword->flags |= W_QUOTED;
7317 list = make_word_list (tword, (WORD_LIST *)NULL);
7319 #else
7320 else
7321 list = (WORD_LIST *)NULL;
7322 #endif
7324 else if (word->flags & W_NOSPLIT)
7326 tword = make_bare_word (istring);
7327 if (word->flags & W_ASSIGNMENT)
7328 tword->flags |= W_ASSIGNMENT; /* XXX */
7329 if (word->flags & W_COMPASSIGN)
7330 tword->flags |= W_COMPASSIGN; /* XXX */
7331 if (word->flags & W_NOGLOB)
7332 tword->flags |= W_NOGLOB; /* XXX */
7333 if (word->flags & W_NOEXPAND)
7334 tword->flags |= W_NOEXPAND; /* XXX */
7335 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7336 tword->flags |= W_QUOTED;
7337 if (had_quoted_null)
7338 tword->flags |= W_HASQUOTEDNULL;
7339 list = make_word_list (tword, (WORD_LIST *)NULL);
7341 else
7343 char *ifs_chars;
7345 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
7347 /* If we have $@, we need to split the results no matter what. If
7348 IFS is unset or NULL, string_list_dollar_at has separated the
7349 positional parameters with a space, so we split on space (we have
7350 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
7351 string_list_dollar_at has separated the positional parameters
7352 with the first character of $IFS, so we split on $IFS. */
7353 if (has_dollar_at && ifs_chars)
7354 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
7355 else
7357 tword = make_bare_word (istring);
7358 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
7359 tword->flags |= W_QUOTED;
7360 if (word->flags & W_ASSIGNMENT)
7361 tword->flags |= W_ASSIGNMENT;
7362 if (word->flags & W_COMPASSIGN)
7363 tword->flags |= W_COMPASSIGN;
7364 if (word->flags & W_NOGLOB)
7365 tword->flags |= W_NOGLOB;
7366 if (word->flags & W_NOEXPAND)
7367 tword->flags |= W_NOEXPAND;
7368 if (had_quoted_null)
7369 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7370 list = make_word_list (tword, (WORD_LIST *)NULL);
7374 free (istring);
7375 return (list);
7378 /* **************************************************************** */
7379 /* */
7380 /* Functions for Quote Removal */
7381 /* */
7382 /* **************************************************************** */
7384 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
7385 backslash quoting rules for within double quotes or a here document. */
7386 char *
7387 string_quote_removal (string, quoted)
7388 char *string;
7389 int quoted;
7391 size_t slen;
7392 char *r, *result_string, *temp, *send;
7393 int sindex, tindex, dquote;
7394 unsigned char c;
7395 DECLARE_MBSTATE;
7397 /* The result can be no longer than the original string. */
7398 slen = strlen (string);
7399 send = string + slen;
7401 r = result_string = (char *)xmalloc (slen + 1);
7403 for (dquote = sindex = 0; c = string[sindex];)
7405 switch (c)
7407 case '\\':
7408 c = string[++sindex];
7409 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
7410 *r++ = '\\';
7411 /* FALLTHROUGH */
7413 default:
7414 SCOPY_CHAR_M (r, string, send, sindex);
7415 break;
7417 case '\'':
7418 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
7420 *r++ = c;
7421 sindex++;
7422 break;
7424 tindex = sindex + 1;
7425 temp = string_extract_single_quoted (string, &tindex);
7426 if (temp)
7428 strcpy (r, temp);
7429 r += strlen (r);
7430 free (temp);
7432 sindex = tindex;
7433 break;
7435 case '"':
7436 dquote = 1 - dquote;
7437 sindex++;
7438 break;
7441 *r = '\0';
7442 return (result_string);
7445 #if 0
7446 /* UNUSED */
7447 /* Perform quote removal on word WORD. This allocates and returns a new
7448 WORD_DESC *. */
7449 WORD_DESC *
7450 word_quote_removal (word, quoted)
7451 WORD_DESC *word;
7452 int quoted;
7454 WORD_DESC *w;
7455 char *t;
7457 t = string_quote_removal (word->word, quoted);
7458 w = alloc_word_desc ();
7459 w->word = t ? t : savestring ("");
7460 return (w);
7463 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
7464 the members of the list are treated as if they are surrounded by
7465 double quotes. Return a new list, or NULL if LIST is NULL. */
7466 WORD_LIST *
7467 word_list_quote_removal (list, quoted)
7468 WORD_LIST *list;
7469 int quoted;
7471 WORD_LIST *result, *t, *tresult, *e;
7473 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7475 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
7476 #if 0
7477 result = (WORD_LIST *) list_append (result, tresult);
7478 #else
7479 if (result == 0)
7480 result = e = tresult;
7481 else
7483 e->next = tresult;
7484 while (e->next)
7485 e = e->next;
7487 #endif
7489 return (result);
7491 #endif
7493 /*******************************************
7495 * Functions to perform word splitting *
7497 *******************************************/
7499 void
7500 setifs (v)
7501 SHELL_VAR *v;
7503 char *t;
7504 unsigned char uc;
7506 ifs_var = v;
7507 #if 0
7508 ifs_value = v ? value_cell (v) : " \t\n";
7509 #else
7510 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
7511 #endif
7513 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
7514 handle multibyte chars in IFS */
7515 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
7516 for (t = ifs_value ; t && *t; t++)
7518 uc = *t;
7519 ifs_cmap[uc] = 1;
7522 #if defined (HANDLE_MULTIBYTE)
7523 if (ifs_value == 0)
7525 ifs_firstc[0] = '\0';
7526 ifs_firstc_len = 1;
7528 else
7530 size_t ifs_len;
7531 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
7532 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
7533 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
7535 ifs_firstc[0] = ifs_value[0];
7536 ifs_firstc[1] = '\0';
7537 ifs_firstc_len = 1;
7539 else
7540 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
7542 #else
7543 ifs_firstc = ifs_value ? *ifs_value : 0;
7544 #endif
7547 char *
7548 getifs ()
7550 return ifs_value;
7553 /* This splits a single word into a WORD LIST on $IFS, but only if the word
7554 is not quoted. list_string () performs quote removal for us, even if we
7555 don't do any splitting. */
7556 WORD_LIST *
7557 word_split (w, ifs_chars)
7558 WORD_DESC *w;
7559 char *ifs_chars;
7561 WORD_LIST *result;
7563 if (w)
7565 char *xifs;
7567 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
7568 result = list_string (w->word, xifs, w->flags & W_QUOTED);
7570 else
7571 result = (WORD_LIST *)NULL;
7573 return (result);
7576 /* Perform word splitting on LIST and return the RESULT. It is possible
7577 to return (WORD_LIST *)NULL. */
7578 static WORD_LIST *
7579 word_list_split (list)
7580 WORD_LIST *list;
7582 WORD_LIST *result, *t, *tresult, *e;
7584 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7586 tresult = word_split (t->word, ifs_value);
7587 if (result == 0)
7588 result = e = tresult;
7589 else
7591 e->next = tresult;
7592 while (e->next)
7593 e = e->next;
7596 return (result);
7599 /**************************************************
7601 * Functions to expand an entire WORD_LIST *
7603 **************************************************/
7605 /* Do any word-expansion-specific cleanup and jump to top_level */
7606 static void
7607 exp_jump_to_top_level (v)
7608 int v;
7610 /* Cleanup code goes here. */
7611 expand_no_split_dollar_star = 0; /* XXX */
7612 expanding_redir = 0;
7614 jump_to_top_level (v);
7617 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
7618 ELIST, and set ELIST to the new list. */
7619 #define PREPEND_LIST(nlist, elist) \
7620 do { nlist->next = elist; elist = nlist; } while (0)
7622 /* Separate out any initial variable assignments from TLIST. If set -k has
7623 been executed, remove all assignment statements from TLIST. Initial
7624 variable assignments and other environment assignments are placed
7625 on SUBST_ASSIGN_VARLIST. */
7626 static WORD_LIST *
7627 separate_out_assignments (tlist)
7628 WORD_LIST *tlist;
7630 register WORD_LIST *vp, *lp;
7632 if (!tlist)
7633 return ((WORD_LIST *)NULL);
7635 if (subst_assign_varlist)
7636 dispose_words (subst_assign_varlist); /* Clean up after previous error */
7638 subst_assign_varlist = (WORD_LIST *)NULL;
7639 vp = lp = tlist;
7641 /* Separate out variable assignments at the start of the command.
7642 Loop invariant: vp->next == lp
7643 Loop postcondition:
7644 lp = list of words left after assignment statements skipped
7645 tlist = original list of words
7647 while (lp && (lp->word->flags & W_ASSIGNMENT))
7649 vp = lp;
7650 lp = lp->next;
7653 /* If lp != tlist, we have some initial assignment statements.
7654 We make SUBST_ASSIGN_VARLIST point to the list of assignment
7655 words and TLIST point to the remaining words. */
7656 if (lp != tlist)
7658 subst_assign_varlist = tlist;
7659 /* ASSERT(vp->next == lp); */
7660 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
7661 tlist = lp; /* remainder of word list */
7664 /* vp == end of variable list */
7665 /* tlist == remainder of original word list without variable assignments */
7666 if (!tlist)
7667 /* All the words in tlist were assignment statements */
7668 return ((WORD_LIST *)NULL);
7670 /* ASSERT(tlist != NULL); */
7671 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
7673 /* If the -k option is in effect, we need to go through the remaining
7674 words, separate out the assignment words, and place them on
7675 SUBST_ASSIGN_VARLIST. */
7676 if (place_keywords_in_env)
7678 WORD_LIST *tp; /* tp == running pointer into tlist */
7680 tp = tlist;
7681 lp = tlist->next;
7683 /* Loop Invariant: tp->next == lp */
7684 /* Loop postcondition: tlist == word list without assignment statements */
7685 while (lp)
7687 if (lp->word->flags & W_ASSIGNMENT)
7689 /* Found an assignment statement, add this word to end of
7690 subst_assign_varlist (vp). */
7691 if (!subst_assign_varlist)
7692 subst_assign_varlist = vp = lp;
7693 else
7695 vp->next = lp;
7696 vp = lp;
7699 /* Remove the word pointed to by LP from TLIST. */
7700 tp->next = lp->next;
7701 /* ASSERT(vp == lp); */
7702 lp->next = (WORD_LIST *)NULL;
7703 lp = tp->next;
7705 else
7707 tp = lp;
7708 lp = lp->next;
7712 return (tlist);
7715 #define WEXP_VARASSIGN 0x001
7716 #define WEXP_BRACEEXP 0x002
7717 #define WEXP_TILDEEXP 0x004
7718 #define WEXP_PARAMEXP 0x008
7719 #define WEXP_PATHEXP 0x010
7721 /* All of the expansions, including variable assignments at the start of
7722 the list. */
7723 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
7725 /* All of the expansions except variable assignments at the start of
7726 the list. */
7727 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
7729 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
7730 expansion, command substitution, arithmetic expansion, word splitting, and
7731 quote removal. */
7732 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
7734 /* Take the list of words in LIST and do the various substitutions. Return
7735 a new list of words which is the expanded list, and without things like
7736 variable assignments. */
7738 WORD_LIST *
7739 expand_words (list)
7740 WORD_LIST *list;
7742 return (expand_word_list_internal (list, WEXP_ALL));
7745 /* Same as expand_words (), but doesn't hack variable or environment
7746 variables. */
7747 WORD_LIST *
7748 expand_words_no_vars (list)
7749 WORD_LIST *list;
7751 return (expand_word_list_internal (list, WEXP_NOVARS));
7754 WORD_LIST *
7755 expand_words_shellexp (list)
7756 WORD_LIST *list;
7758 return (expand_word_list_internal (list, WEXP_SHELLEXP));
7761 static WORD_LIST *
7762 glob_expand_word_list (tlist, eflags)
7763 WORD_LIST *tlist;
7764 int eflags;
7766 char **glob_array, *temp_string;
7767 register int glob_index;
7768 WORD_LIST *glob_list, *output_list, *disposables, *next;
7769 WORD_DESC *tword;
7771 output_list = disposables = (WORD_LIST *)NULL;
7772 glob_array = (char **)NULL;
7773 while (tlist)
7775 /* For each word, either globbing is attempted or the word is
7776 added to orig_list. If globbing succeeds, the results are
7777 added to orig_list and the word (tlist) is added to the list
7778 of disposable words. If globbing fails and failed glob
7779 expansions are left unchanged (the shell default), the
7780 original word is added to orig_list. If globbing fails and
7781 failed glob expansions are removed, the original word is
7782 added to the list of disposable words. orig_list ends up
7783 in reverse order and requires a call to REVERSE_LIST to
7784 be set right. After all words are examined, the disposable
7785 words are freed. */
7786 next = tlist->next;
7788 /* If the word isn't an assignment and contains an unquoted
7789 pattern matching character, then glob it. */
7790 if ((tlist->word->flags & W_NOGLOB) == 0 &&
7791 unquoted_glob_pattern_p (tlist->word->word))
7793 glob_array = shell_glob_filename (tlist->word->word);
7795 /* Handle error cases.
7796 I don't think we should report errors like "No such file
7797 or directory". However, I would like to report errors
7798 like "Read failed". */
7800 if (glob_array == 0 || GLOB_FAILED (glob_array))
7802 glob_array = (char **)xmalloc (sizeof (char *));
7803 glob_array[0] = (char *)NULL;
7806 /* Dequote the current word in case we have to use it. */
7807 if (glob_array[0] == NULL)
7809 temp_string = dequote_string (tlist->word->word);
7810 free (tlist->word->word);
7811 tlist->word->word = temp_string;
7814 /* Make the array into a word list. */
7815 glob_list = (WORD_LIST *)NULL;
7816 for (glob_index = 0; glob_array[glob_index]; glob_index++)
7818 tword = make_bare_word (glob_array[glob_index]);
7819 tword->flags |= W_GLOBEXP; /* XXX */
7820 glob_list = make_word_list (tword, glob_list);
7823 if (glob_list)
7825 output_list = (WORD_LIST *)list_append (glob_list, output_list);
7826 PREPEND_LIST (tlist, disposables);
7828 else if (fail_glob_expansion != 0)
7830 report_error (_("no match: %s"), tlist->word->word);
7831 jump_to_top_level (DISCARD);
7833 else if (allow_null_glob_expansion == 0)
7835 /* Failed glob expressions are left unchanged. */
7836 PREPEND_LIST (tlist, output_list);
7838 else
7840 /* Failed glob expressions are removed. */
7841 PREPEND_LIST (tlist, disposables);
7844 else
7846 /* Dequote the string. */
7847 temp_string = dequote_string (tlist->word->word);
7848 free (tlist->word->word);
7849 tlist->word->word = temp_string;
7850 PREPEND_LIST (tlist, output_list);
7853 strvec_dispose (glob_array);
7854 glob_array = (char **)NULL;
7856 tlist = next;
7859 if (disposables)
7860 dispose_words (disposables);
7862 if (output_list)
7863 output_list = REVERSE_LIST (output_list, WORD_LIST *);
7865 return (output_list);
7868 #if defined (BRACE_EXPANSION)
7869 static WORD_LIST *
7870 brace_expand_word_list (tlist, eflags)
7871 WORD_LIST *tlist;
7872 int eflags;
7874 register char **expansions;
7875 char *temp_string;
7876 WORD_LIST *disposables, *output_list, *next;
7877 WORD_DESC *w;
7878 int eindex;
7880 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
7882 next = tlist->next;
7884 /* Only do brace expansion if the word has a brace character. If
7885 not, just add the word list element to BRACES and continue. In
7886 the common case, at least when running shell scripts, this will
7887 degenerate to a bunch of calls to `xstrchr', and then what is
7888 basically a reversal of TLIST into BRACES, which is corrected
7889 by a call to REVERSE_LIST () on BRACES when the end of TLIST
7890 is reached. */
7891 if (xstrchr (tlist->word->word, LBRACE))
7893 expansions = brace_expand (tlist->word->word);
7895 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
7897 w = make_word (temp_string);
7898 /* If brace expansion didn't change the word, preserve
7899 the flags. We may want to preserve the flags
7900 unconditionally someday -- XXX */
7901 if (STREQ (temp_string, tlist->word->word))
7902 w->flags = tlist->word->flags;
7903 output_list = make_word_list (w, output_list);
7904 free (expansions[eindex]);
7906 free (expansions);
7908 /* Add TLIST to the list of words to be freed after brace
7909 expansion has been performed. */
7910 PREPEND_LIST (tlist, disposables);
7912 else
7913 PREPEND_LIST (tlist, output_list);
7916 if (disposables)
7917 dispose_words (disposables);
7919 if (output_list)
7920 output_list = REVERSE_LIST (output_list, WORD_LIST *);
7922 return (output_list);
7924 #endif
7926 static WORD_LIST *
7927 shell_expand_word_list (tlist, eflags)
7928 WORD_LIST *tlist;
7929 int eflags;
7931 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
7932 int expanded_something, has_dollar_at;
7933 char *temp_string;
7935 /* We do tilde expansion all the time. This is what 1003.2 says. */
7936 new_list = (WORD_LIST *)NULL;
7937 for (orig_list = tlist; tlist; tlist = next)
7939 temp_string = tlist->word->word;
7941 next = tlist->next;
7943 #if defined (ARRAY_VARS)
7944 /* If this is a compound array assignment to a builtin that accepts
7945 such assignments (e.g., `declare'), take the assignment and perform
7946 it separately, handling the semantics of declarations inside shell
7947 functions. This avoids the double-evaluation of such arguments,
7948 because `declare' does some evaluation of compound assignments on
7949 its own. */
7950 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
7952 int t;
7954 t = do_word_assignment (tlist->word);
7955 if (t == 0)
7957 last_command_exit_value = EXECUTION_FAILURE;
7958 exp_jump_to_top_level (DISCARD);
7961 /* Now transform the word as ksh93 appears to do and go on */
7962 t = assignment (tlist->word->word, 0);
7963 tlist->word->word[t] = '\0';
7964 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG);
7966 #endif
7968 expanded_something = 0;
7969 expanded = expand_word_internal
7970 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
7972 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
7974 /* By convention, each time this error is returned,
7975 tlist->word->word has already been freed. */
7976 tlist->word->word = (char *)NULL;
7978 /* Dispose our copy of the original list. */
7979 dispose_words (orig_list);
7980 /* Dispose the new list we're building. */
7981 dispose_words (new_list);
7983 last_command_exit_value = EXECUTION_FAILURE;
7984 if (expanded == &expand_word_error)
7985 exp_jump_to_top_level (DISCARD);
7986 else
7987 exp_jump_to_top_level (FORCE_EOF);
7990 /* Don't split words marked W_NOSPLIT. */
7991 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
7993 temp_list = word_list_split (expanded);
7994 dispose_words (expanded);
7996 else
7998 /* If no parameter expansion, command substitution, process
7999 substitution, or arithmetic substitution took place, then
8000 do not do word splitting. We still have to remove quoted
8001 null characters from the result. */
8002 word_list_remove_quoted_nulls (expanded);
8003 temp_list = expanded;
8006 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8007 new_list = (WORD_LIST *)list_append (expanded, new_list);
8010 if (orig_list)
8011 dispose_words (orig_list);
8013 if (new_list)
8014 new_list = REVERSE_LIST (new_list, WORD_LIST *);
8016 return (new_list);
8019 /* The workhorse for expand_words () and expand_words_no_vars ().
8020 First arg is LIST, a WORD_LIST of words.
8021 Second arg EFLAGS is a flags word controlling which expansions are
8022 performed.
8024 This does all of the substitutions: brace expansion, tilde expansion,
8025 parameter expansion, command substitution, arithmetic expansion,
8026 process substitution, word splitting, and pathname expansion, according
8027 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
8028 set, or for which no expansion is done, do not undergo word splitting.
8029 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8030 static WORD_LIST *
8031 expand_word_list_internal (list, eflags)
8032 WORD_LIST *list;
8033 int eflags;
8035 WORD_LIST *new_list, *temp_list;
8036 int tint;
8038 if (list == 0)
8039 return ((WORD_LIST *)NULL);
8041 garglist = new_list = copy_word_list (list);
8042 if (eflags & WEXP_VARASSIGN)
8044 garglist = new_list = separate_out_assignments (new_list);
8045 if (new_list == 0)
8047 if (subst_assign_varlist)
8049 /* All the words were variable assignments, so they are placed
8050 into the shell's environment. */
8051 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8053 this_command_name = (char *)NULL; /* no arithmetic errors */
8054 tint = do_word_assignment (temp_list->word);
8055 /* Variable assignment errors in non-interactive shells
8056 running in Posix.2 mode cause the shell to exit. */
8057 if (tint == 0)
8059 last_command_exit_value = EXECUTION_FAILURE;
8060 if (interactive_shell == 0 && posixly_correct)
8061 exp_jump_to_top_level (FORCE_EOF);
8062 else
8063 exp_jump_to_top_level (DISCARD);
8066 dispose_words (subst_assign_varlist);
8067 subst_assign_varlist = (WORD_LIST *)NULL;
8069 return ((WORD_LIST *)NULL);
8073 /* Begin expanding the words that remain. The expansions take place on
8074 things that aren't really variable assignments. */
8076 #if defined (BRACE_EXPANSION)
8077 /* Do brace expansion on this word if there are any brace characters
8078 in the string. */
8079 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8080 new_list = brace_expand_word_list (new_list, eflags);
8081 #endif /* BRACE_EXPANSION */
8083 /* Perform the `normal' shell expansions: tilde expansion, parameter and
8084 variable substitution, command substitution, arithmetic expansion,
8085 and word splitting. */
8086 new_list = shell_expand_word_list (new_list, eflags);
8088 /* Okay, we're almost done. Now let's just do some filename
8089 globbing. */
8090 if (new_list)
8092 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8093 /* Glob expand the word list unless globbing has been disabled. */
8094 new_list = glob_expand_word_list (new_list, eflags);
8095 else
8096 /* Dequote the words, because we're not performing globbing. */
8097 new_list = dequote_list (new_list);
8100 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8102 sh_wassign_func_t *assign_func;
8104 /* If the remainder of the words expand to nothing, Posix.2 requires
8105 that the variable and environment assignments affect the shell's
8106 environment. */
8107 assign_func = new_list ? assign_in_env : do_word_assignment;
8108 tempenv_assign_error = 0;
8110 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8112 this_command_name = (char *)NULL;
8113 tint = (*assign_func) (temp_list->word);
8114 /* Variable assignment errors in non-interactive shells running
8115 in Posix.2 mode cause the shell to exit. */
8116 if (tint == 0)
8118 if (assign_func == do_word_assignment)
8120 last_command_exit_value = EXECUTION_FAILURE;
8121 if (interactive_shell == 0 && posixly_correct)
8122 exp_jump_to_top_level (FORCE_EOF);
8123 else
8124 exp_jump_to_top_level (DISCARD);
8126 else
8127 tempenv_assign_error++;
8131 dispose_words (subst_assign_varlist);
8132 subst_assign_varlist = (WORD_LIST *)NULL;
8135 #if 0
8136 tint = list_length (new_list) + 1;
8137 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8138 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8139 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8140 glob_argv_flags[tint] = '\0';
8141 #endif
8143 return (new_list);