]> git.ipfire.org Git - thirdparty/bash.git/blob - subst.c
commit bash-20090618 snapshot
[thirdparty/bash.git] / subst.c
1 /* subst.c -- The part of the shell that does parameter, command, arithmetic,
2 and globbing substitutions. */
3
4 /* ``Have a little faith, there's magic in the night. You ain't a
5 beauty, but, hey, you're alright.'' */
6
7 /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
8
9 This file is part of GNU Bash, the Bourne Again SHell.
10
11 Bash is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 Bash is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with Bash. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "config.h"
26
27 #include "bashtypes.h"
28 #include <stdio.h>
29 #include "chartypes.h"
30 #if defined (HAVE_PWD_H)
31 # include <pwd.h>
32 #endif
33 #include <signal.h>
34 #include <errno.h>
35
36 #if defined (HAVE_UNISTD_H)
37 # include <unistd.h>
38 #endif
39
40 #include "bashansi.h"
41 #include "posixstat.h"
42 #include "bashintl.h"
43
44 #include "shell.h"
45 #include "flags.h"
46 #include "jobs.h"
47 #include "execute_cmd.h"
48 #include "filecntl.h"
49 #include "trap.h"
50 #include "pathexp.h"
51 #include "mailcheck.h"
52
53 #include "shmbutil.h"
54
55 #include "builtins/getopt.h"
56 #include "builtins/common.h"
57
58 #include "builtins/builtext.h"
59
60 #include <tilde/tilde.h>
61 #include <glob/strmatch.h>
62
63 #if !defined (errno)
64 extern int errno;
65 #endif /* !errno */
66
67 /* The size that strings change by. */
68 #define DEFAULT_INITIAL_ARRAY_SIZE 112
69 #define DEFAULT_ARRAY_SIZE 128
70
71 /* Variable types. */
72 #define VT_VARIABLE 0
73 #define VT_POSPARMS 1
74 #define VT_ARRAYVAR 2
75 #define VT_ARRAYMEMBER 3
76 #define VT_ASSOCVAR 4
77
78 #define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
79
80 /* Flags for quoted_strchr */
81 #define ST_BACKSL 0x01
82 #define ST_CTLESC 0x02
83 #define ST_SQUOTE 0x04 /* unused yet */
84 #define ST_DQUOTE 0x08 /* unused yet */
85
86 /* Flags for the `pflags' argument to param_expand() */
87 #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
88 #define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
89
90 /* These defs make it easier to use the editor. */
91 #define LBRACE '{'
92 #define RBRACE '}'
93 #define LPAREN '('
94 #define RPAREN ')'
95
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) == '#')
100
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) == '*')
105
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)
109
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])))
115
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));
120
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;
124
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];
129
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
136
137 int assigning_in_environment;
138
139 /* Extern functions and variables from different files. */
140 extern int last_command_exit_value, last_command_exit_signal;
141 extern int subshell_environment;
142 extern int subshell_level, parse_and_execute_level;
143 extern int eof_encountered;
144 extern int return_catch_flag, return_catch_value;
145 extern pid_t dollar_dollar_pid;
146 extern int posixly_correct;
147 extern char *this_command_name;
148 extern struct fd_bitmap *current_fds_to_close;
149 extern int wordexp_only;
150 extern int expanding_redir;
151 extern int tempenv_assign_error;
152
153 #if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
154 extern wchar_t *wcsdup __P((const wchar_t *));
155 #endif
156
157 /* Non-zero means to allow unmatched globbed filenames to expand to
158 a null file. */
159 int allow_null_glob_expansion;
160
161 /* Non-zero means to throw an error when globbing fails to match anything. */
162 int fail_glob_expansion;
163
164 #if 0
165 /* Variables to keep track of which words in an expanded word list (the
166 output of expand_word_list_internal) are the result of globbing
167 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
168 (CURRENTLY UNUSED). */
169 char *glob_argv_flags;
170 static int glob_argv_flags_size;
171 #endif
172
173 static WORD_LIST expand_word_error, expand_word_fatal;
174 static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
175 static char expand_param_error, expand_param_fatal;
176 static char extract_string_error, extract_string_fatal;
177
178 /* Tell the expansion functions to not longjmp back to top_level on fatal
179 errors. Enabled when doing completion and prompt string expansion. */
180 static int no_longjmp_on_fatal_error = 0;
181
182 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
183 $* on $IFS, primarily when doing assignment statements. */
184 static int expand_no_split_dollar_star = 0;
185
186 /* Used to hold a list of variable assignments preceding a command. Global
187 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
188 SIGCHLD trap. */
189 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
190
191 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
192 without any leading variable assignments. */
193 static WORD_LIST *garglist = (WORD_LIST *)NULL;
194
195 static char *quoted_substring __P((char *, int, int));
196 static int quoted_strlen __P((char *));
197 static char *quoted_strchr __P((char *, int, int));
198
199 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
200 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
201 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
202 static WORD_LIST *expand_string_internal __P((char *, int));
203 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
204 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
205
206 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
207 static char *make_quoted_char __P((int));
208 static WORD_LIST *quote_list __P((WORD_LIST *));
209
210 static int unquoted_substring __P((char *, char *));
211 static int unquoted_member __P((int, char *));
212
213 #if defined (ARRAY_VARS)
214 static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
215 #endif
216 static int do_assignment_internal __P((const WORD_DESC *, int));
217
218 static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
219 static char *string_extract __P((char *, int *, char *, int));
220 static char *string_extract_double_quoted __P((char *, int *, int));
221 static inline char *string_extract_single_quoted __P((char *, int *));
222 static inline int skip_single_quoted __P((const char *, size_t, int));
223 static int skip_double_quoted __P((char *, size_t, int));
224 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
225 static char *extract_dollar_brace_string __P((char *, int *, int, int));
226 static int skip_matched_pair __P((const char *, int, int, int, int));
227
228 static char *pos_params __P((char *, int, int, int));
229
230 static unsigned char *mb_getcharlens __P((char *, int));
231
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));
237
238 static int match_pattern_char __P((char *, char *));
239 static int match_upattern __P((char *, char *, int, char **, char **));
240 #if defined (HANDLE_MULTIBYTE)
241 static int match_pattern_wchar __P((wchar_t *, wchar_t *));
242 static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
243 #endif
244 static int match_pattern __P((char *, char *, int, char **, char **));
245 static int getpatspec __P((int, char *));
246 static char *getpattern __P((char *, int, int));
247 static char *variable_remove_pattern __P((char *, char *, int, int));
248 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
249 static char *parameter_list_remove_pattern __P((int, char *, int, int));
250 #ifdef ARRAY_VARS
251 static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int));
252 #endif
253 static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
254
255 static char *process_substitute __P((char *, int));
256
257 static char *read_comsub __P((int, int, int *));
258
259 #ifdef ARRAY_VARS
260 static arrayind_t array_length_reference __P((char *));
261 #endif
262
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));
266
267 static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
268 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
269 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
270 static void parameter_brace_expand_error __P((char *, char *));
271
272 static int valid_length_expression __P((char *));
273 static intmax_t parameter_brace_expand_length __P((char *));
274
275 static char *skiparith __P((char *, int));
276 static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
277 static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
278 static char *mb_substring __P((char *, int, int));
279 static char *parameter_brace_substring __P((char *, char *, char *, int));
280
281 static char *pos_params_pat_subst __P((char *, char *, char *, int));
282
283 static char *parameter_brace_patsub __P((char *, char *, char *, int));
284
285 static char *pos_params_casemod __P((char *, char *, int, int));
286 static char *parameter_brace_casemod __P((char *, char *, int, char *, int));
287
288 static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
289 static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
290
291 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
292
293 static WORD_LIST *word_list_split __P((WORD_LIST *));
294
295 static void exp_jump_to_top_level __P((int));
296
297 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
298 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
299 #ifdef BRACE_EXPANSION
300 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
301 #endif
302 #if defined (ARRAY_VARS)
303 static int make_internal_declare __P((char *, char *));
304 #endif
305 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
306 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
307
308 /* **************************************************************** */
309 /* */
310 /* Utility Functions */
311 /* */
312 /* **************************************************************** */
313
314 #ifdef INCLUDE_UNUSED
315 static char *
316 quoted_substring (string, start, end)
317 char *string;
318 int start, end;
319 {
320 register int len, l;
321 register char *result, *s, *r;
322
323 len = end - start;
324
325 /* Move to string[start], skipping quoted characters. */
326 for (s = string, l = 0; *s && l < start; )
327 {
328 if (*s == CTLESC)
329 {
330 s++;
331 continue;
332 }
333 l++;
334 if (*s == 0)
335 break;
336 }
337
338 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
339
340 /* Copy LEN characters, including quote characters. */
341 s = string + l;
342 for (l = 0; l < len; s++)
343 {
344 if (*s == CTLESC)
345 *r++ = *s++;
346 *r++ = *s;
347 l++;
348 if (*s == 0)
349 break;
350 }
351 *r = '\0';
352 return result;
353 }
354 #endif
355
356 #ifdef INCLUDE_UNUSED
357 /* Return the length of S, skipping over quoted characters */
358 static int
359 quoted_strlen (s)
360 char *s;
361 {
362 register char *p;
363 int i;
364
365 i = 0;
366 for (p = s; *p; p++)
367 {
368 if (*p == CTLESC)
369 {
370 p++;
371 if (*p == 0)
372 return (i + 1);
373 }
374 i++;
375 }
376
377 return i;
378 }
379 #endif
380
381 /* Find the first occurrence of character C in string S, obeying shell
382 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
383 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
384 escaped with CTLESC are skipped. */
385 static char *
386 quoted_strchr (s, c, flags)
387 char *s;
388 int c, flags;
389 {
390 register char *p;
391
392 for (p = s; *p; p++)
393 {
394 if (((flags & ST_BACKSL) && *p == '\\')
395 || ((flags & ST_CTLESC) && *p == CTLESC))
396 {
397 p++;
398 if (*p == '\0')
399 return ((char *)NULL);
400 continue;
401 }
402 else if (*p == c)
403 return p;
404 }
405 return ((char *)NULL);
406 }
407
408 /* Return 1 if CHARACTER appears in an unquoted portion of
409 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
410 static int
411 unquoted_member (character, string)
412 int character;
413 char *string;
414 {
415 size_t slen;
416 int sindex, c;
417 DECLARE_MBSTATE;
418
419 slen = strlen (string);
420 sindex = 0;
421 while (c = string[sindex])
422 {
423 if (c == character)
424 return (1);
425
426 switch (c)
427 {
428 default:
429 ADVANCE_CHAR (string, slen, sindex);
430 break;
431
432 case '\\':
433 sindex++;
434 if (string[sindex])
435 ADVANCE_CHAR (string, slen, sindex);
436 break;
437
438 case '\'':
439 sindex = skip_single_quoted (string, slen, ++sindex);
440 break;
441
442 case '"':
443 sindex = skip_double_quoted (string, slen, ++sindex);
444 break;
445 }
446 }
447 return (0);
448 }
449
450 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
451 static int
452 unquoted_substring (substr, string)
453 char *substr, *string;
454 {
455 size_t slen;
456 int sindex, c, sublen;
457 DECLARE_MBSTATE;
458
459 if (substr == 0 || *substr == '\0')
460 return (0);
461
462 slen = strlen (string);
463 sublen = strlen (substr);
464 for (sindex = 0; c = string[sindex]; )
465 {
466 if (STREQN (string + sindex, substr, sublen))
467 return (1);
468
469 switch (c)
470 {
471 case '\\':
472 sindex++;
473
474 if (string[sindex])
475 ADVANCE_CHAR (string, slen, sindex);
476 break;
477
478 case '\'':
479 sindex = skip_single_quoted (string, slen, ++sindex);
480 break;
481
482 case '"':
483 sindex = skip_double_quoted (string, slen, ++sindex);
484 break;
485
486 default:
487 ADVANCE_CHAR (string, slen, sindex);
488 break;
489 }
490 }
491 return (0);
492 }
493
494 /* Most of the substitutions must be done in parallel. In order
495 to avoid using tons of unclear goto's, I have some functions
496 for manipulating malloc'ed strings. They all take INDX, a
497 pointer to an integer which is the offset into the string
498 where manipulation is taking place. They also take SIZE, a
499 pointer to an integer which is the current length of the
500 character array for this string. */
501
502 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
503 of space allocated to TARGET. SOURCE can be NULL, in which
504 case nothing happens. Gets rid of SOURCE by freeing it.
505 Returns TARGET in case the location has changed. */
506 INLINE char *
507 sub_append_string (source, target, indx, size)
508 char *source, *target;
509 int *indx, *size;
510 {
511 if (source)
512 {
513 int srclen, n;
514
515 srclen = STRLEN (source);
516 if (srclen >= (int)(*size - *indx))
517 {
518 n = srclen + *indx;
519 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
520 target = (char *)xrealloc (target, (*size = n));
521 }
522
523 FASTCOPY (source, target + *indx, srclen);
524 *indx += srclen;
525 target[*indx] = '\0';
526
527 free (source);
528 }
529 return (target);
530 }
531
532 #if 0
533 /* UNUSED */
534 /* Append the textual representation of NUMBER to TARGET.
535 INDX and SIZE are as in SUB_APPEND_STRING. */
536 char *
537 sub_append_number (number, target, indx, size)
538 intmax_t number;
539 int *indx, *size;
540 char *target;
541 {
542 char *temp;
543
544 temp = itos (number);
545 return (sub_append_string (temp, target, indx, size));
546 }
547 #endif
548
549 /* Extract a substring from STRING, starting at SINDEX and ending with
550 one of the characters in CHARLIST. Don't make the ending character
551 part of the string. Leave SINDEX pointing at the ending character.
552 Understand about backslashes in the string. If (flags & SX_VARNAME)
553 is non-zero, and array variables have been compiled into the shell,
554 everything between a `[' and a corresponding `]' is skipped over.
555 If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
556 update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must
557 contain a closing character from CHARLIST. */
558 static char *
559 string_extract (string, sindex, charlist, flags)
560 char *string;
561 int *sindex;
562 char *charlist;
563 int flags;
564 {
565 register int c, i;
566 int found;
567 size_t slen;
568 char *temp;
569 DECLARE_MBSTATE;
570
571 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
572 i = *sindex;
573 found = 0;
574 while (c = string[i])
575 {
576 if (c == '\\')
577 {
578 if (string[i + 1])
579 i++;
580 else
581 break;
582 }
583 #if defined (ARRAY_VARS)
584 else if ((flags & SX_VARNAME) && c == '[')
585 {
586 int ni;
587 /* If this is an array subscript, skip over it and continue. */
588 ni = skipsubscript (string, i);
589 if (string[ni] == ']')
590 i = ni;
591 }
592 #endif
593 else if (MEMBER (c, charlist))
594 {
595 found = 1;
596 break;
597 }
598
599 ADVANCE_CHAR (string, slen, i);
600 }
601
602 /* If we had to have a matching delimiter and didn't find one, return an
603 error and let the caller deal with it. */
604 if ((flags & SX_REQMATCH) && found == 0)
605 {
606 *sindex = i;
607 return (&extract_string_error);
608 }
609
610 temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
611 *sindex = i;
612
613 return (temp);
614 }
615
616 /* Extract the contents of STRING as if it is enclosed in double quotes.
617 SINDEX, when passed in, is the offset of the character immediately
618 following the opening double quote; on exit, SINDEX is left pointing after
619 the closing double quote. If STRIPDQ is non-zero, unquoted double
620 quotes are stripped and the string is terminated by a null byte.
621 Backslashes between the embedded double quotes are processed. If STRIPDQ
622 is zero, an unquoted `"' terminates the string. */
623 static char *
624 string_extract_double_quoted (string, sindex, stripdq)
625 char *string;
626 int *sindex, stripdq;
627 {
628 size_t slen;
629 char *send;
630 int j, i, t;
631 unsigned char c;
632 char *temp, *ret; /* The new string we return. */
633 int pass_next, backquote, si; /* State variables for the machine. */
634 int dquote;
635 DECLARE_MBSTATE;
636
637 slen = strlen (string + *sindex) + *sindex;
638 send = string + slen;
639
640 pass_next = backquote = dquote = 0;
641 temp = (char *)xmalloc (1 + slen - *sindex);
642
643 j = 0;
644 i = *sindex;
645 while (c = string[i])
646 {
647 /* Process a character that was quoted by a backslash. */
648 if (pass_next)
649 {
650 /* Posix.2 sez:
651
652 ``The backslash shall retain its special meaning as an escape
653 character only when followed by one of the characters:
654 $ ` " \ <newline>''.
655
656 If STRIPDQ is zero, we handle the double quotes here and let
657 expand_word_internal handle the rest. If STRIPDQ is non-zero,
658 we have already been through one round of backslash stripping,
659 and want to strip these backslashes only if DQUOTE is non-zero,
660 indicating that we are inside an embedded double-quoted string. */
661
662 /* If we are in an embedded quoted string, then don't strip
663 backslashes before characters for which the backslash
664 retains its special meaning, but remove backslashes in
665 front of other characters. If we are not in an
666 embedded quoted string, don't strip backslashes at all.
667 This mess is necessary because the string was already
668 surrounded by double quotes (and sh has some really weird
669 quoting rules).
670 The returned string will be run through expansion as if
671 it were double-quoted. */
672 if ((stripdq == 0 && c != '"') ||
673 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
674 temp[j++] = '\\';
675 pass_next = 0;
676
677 add_one_character:
678 COPY_CHAR_I (temp, j, string, send, i);
679 continue;
680 }
681
682 /* A backslash protects the next character. The code just above
683 handles preserving the backslash in front of any character but
684 a double quote. */
685 if (c == '\\')
686 {
687 pass_next++;
688 i++;
689 continue;
690 }
691
692 /* Inside backquotes, ``the portion of the quoted string from the
693 initial backquote and the characters up to the next backquote
694 that is not preceded by a backslash, having escape characters
695 removed, defines that command''. */
696 if (backquote)
697 {
698 if (c == '`')
699 backquote = 0;
700 temp[j++] = c;
701 i++;
702 continue;
703 }
704
705 if (c == '`')
706 {
707 temp[j++] = c;
708 backquote++;
709 i++;
710 continue;
711 }
712
713 /* Pass everything between `$(' and the matching `)' or a quoted
714 ${ ... } pair through according to the Posix.2 specification. */
715 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
716 {
717 int free_ret = 1;
718
719 si = i + 2;
720 if (string[i + 1] == LPAREN)
721 ret = extract_command_subst (string, &si, 0);
722 else
723 ret = extract_dollar_brace_string (string, &si, 1, 0);
724
725 temp[j++] = '$';
726 temp[j++] = string[i + 1];
727
728 /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
729 is set. */
730 if (ret == 0 && no_longjmp_on_fatal_error)
731 {
732 free_ret = 0;
733 ret = string + i + 2;
734 }
735
736 for (t = 0; ret[t]; t++, j++)
737 temp[j] = ret[t];
738 temp[j] = string[si];
739
740 if (string[si])
741 {
742 j++;
743 i = si + 1;
744 }
745 else
746 i = si;
747
748 if (free_ret)
749 free (ret);
750 continue;
751 }
752
753 /* Add any character but a double quote to the quoted string we're
754 accumulating. */
755 if (c != '"')
756 goto add_one_character;
757
758 /* c == '"' */
759 if (stripdq)
760 {
761 dquote ^= 1;
762 i++;
763 continue;
764 }
765
766 break;
767 }
768 temp[j] = '\0';
769
770 /* Point to after the closing quote. */
771 if (c)
772 i++;
773 *sindex = i;
774
775 return (temp);
776 }
777
778 /* This should really be another option to string_extract_double_quoted. */
779 static int
780 skip_double_quoted (string, slen, sind)
781 char *string;
782 size_t slen;
783 int sind;
784 {
785 int c, i;
786 char *ret;
787 int pass_next, backquote, si;
788 DECLARE_MBSTATE;
789
790 pass_next = backquote = 0;
791 i = sind;
792 while (c = string[i])
793 {
794 if (pass_next)
795 {
796 pass_next = 0;
797 ADVANCE_CHAR (string, slen, i);
798 continue;
799 }
800 else if (c == '\\')
801 {
802 pass_next++;
803 i++;
804 continue;
805 }
806 else if (backquote)
807 {
808 if (c == '`')
809 backquote = 0;
810 ADVANCE_CHAR (string, slen, i);
811 continue;
812 }
813 else if (c == '`')
814 {
815 backquote++;
816 i++;
817 continue;
818 }
819 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
820 {
821 si = i + 2;
822 if (string[i + 1] == LPAREN)
823 ret = extract_command_subst (string, &si, SX_NOALLOC);
824 else
825 ret = extract_dollar_brace_string (string, &si, 1, SX_NOALLOC);
826
827 i = si + 1;
828 continue;
829 }
830 else if (c != '"')
831 {
832 ADVANCE_CHAR (string, slen, i);
833 continue;
834 }
835 else
836 break;
837 }
838
839 if (c)
840 i++;
841
842 return (i);
843 }
844
845 /* Extract the contents of STRING as if it is enclosed in single quotes.
846 SINDEX, when passed in, is the offset of the character immediately
847 following the opening single quote; on exit, SINDEX is left pointing after
848 the closing single quote. */
849 static inline char *
850 string_extract_single_quoted (string, sindex)
851 char *string;
852 int *sindex;
853 {
854 register int i;
855 size_t slen;
856 char *t;
857 DECLARE_MBSTATE;
858
859 /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
860 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
861 i = *sindex;
862 while (string[i] && string[i] != '\'')
863 ADVANCE_CHAR (string, slen, i);
864
865 t = substring (string, *sindex, i);
866
867 if (string[i])
868 i++;
869 *sindex = i;
870
871 return (t);
872 }
873
874 static inline int
875 skip_single_quoted (string, slen, sind)
876 const char *string;
877 size_t slen;
878 int sind;
879 {
880 register int c;
881 DECLARE_MBSTATE;
882
883 c = sind;
884 while (string[c] && string[c] != '\'')
885 ADVANCE_CHAR (string, slen, c);
886
887 if (string[c])
888 c++;
889 return c;
890 }
891
892 /* Just like string_extract, but doesn't hack backslashes or any of
893 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
894 static char *
895 string_extract_verbatim (string, slen, sindex, charlist, flags)
896 char *string;
897 size_t slen;
898 int *sindex;
899 char *charlist;
900 int flags;
901 {
902 register int i = *sindex;
903 #if defined (HANDLE_MULTIBYTE)
904 size_t clen;
905 wchar_t *wcharlist;
906 #endif
907 int c;
908 char *temp;
909 DECLARE_MBSTATE;
910
911 if (charlist[0] == '\'' && charlist[1] == '\0')
912 {
913 temp = string_extract_single_quoted (string, sindex);
914 --*sindex; /* leave *sindex at separator character */
915 return temp;
916 }
917
918 i = *sindex;
919 #if 0
920 /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
921 this only if MB_CUR_MAX > 1. */
922 slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
923 #endif
924 #if defined (HANDLE_MULTIBYTE)
925 clen = strlen (charlist);
926 wcharlist = 0;
927 #endif
928 while (c = string[i])
929 {
930 #if defined (HANDLE_MULTIBYTE)
931 size_t mblength;
932 #endif
933 if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
934 {
935 i += 2;
936 continue;
937 }
938 /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
939 through, to protect the CTLNULs from later calls to
940 remove_quoted_nulls. */
941 else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
942 {
943 i += 2;
944 continue;
945 }
946
947 #if defined (HANDLE_MULTIBYTE)
948 mblength = MBLEN (string + i, slen - i);
949 if (mblength > 1)
950 {
951 wchar_t wc;
952 mblength = mbtowc (&wc, string + i, slen - i);
953 if (MB_INVALIDCH (mblength))
954 {
955 if (MEMBER (c, charlist))
956 break;
957 }
958 else
959 {
960 if (wcharlist == 0)
961 {
962 size_t len;
963 len = mbstowcs (wcharlist, charlist, 0);
964 if (len == -1)
965 len = 0;
966 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
967 mbstowcs (wcharlist, charlist, len + 1);
968 }
969
970 if (wcschr (wcharlist, wc))
971 break;
972 }
973 }
974 else
975 #endif
976 if (MEMBER (c, charlist))
977 break;
978
979 ADVANCE_CHAR (string, slen, i);
980 }
981
982 #if defined (HANDLE_MULTIBYTE)
983 FREE (wcharlist);
984 #endif
985
986 temp = substring (string, *sindex, i);
987 *sindex = i;
988
989 return (temp);
990 }
991
992 /* Extract the $( construct in STRING, and return a new string.
993 Start extracting at (SINDEX) as if we had just seen "$(".
994 Make (SINDEX) get the position of the matching ")". )
995 XFLAGS is additional flags to pass to other extraction functions, */
996 char *
997 extract_command_subst (string, sindex, xflags)
998 char *string;
999 int *sindex;
1000 int xflags;
1001 {
1002 if (string[*sindex] == '(') /*)*/
1003 return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
1004 else
1005 {
1006 xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
1007 return (xparse_dolparen (string, string+*sindex, sindex, xflags));
1008 }
1009 }
1010
1011 /* Extract the $[ construct in STRING, and return a new string. (])
1012 Start extracting at (SINDEX) as if we had just seen "$[".
1013 Make (SINDEX) get the position of the matching "]". */
1014 char *
1015 extract_arithmetic_subst (string, sindex)
1016 char *string;
1017 int *sindex;
1018 {
1019 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
1020 }
1021
1022 #if defined (PROCESS_SUBSTITUTION)
1023 /* Extract the <( or >( construct in STRING, and return a new string.
1024 Start extracting at (SINDEX) as if we had just seen "<(".
1025 Make (SINDEX) get the position of the matching ")". */ /*))*/
1026 char *
1027 extract_process_subst (string, starter, sindex)
1028 char *string;
1029 char *starter;
1030 int *sindex;
1031 {
1032 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
1033 }
1034 #endif /* PROCESS_SUBSTITUTION */
1035
1036 #if defined (ARRAY_VARS)
1037 /* This can be fooled by unquoted right parens in the passed string. If
1038 each caller verifies that the last character in STRING is a right paren,
1039 we don't even need to call extract_delimited_string. */
1040 char *
1041 extract_array_assignment_list (string, sindex)
1042 char *string;
1043 int *sindex;
1044 {
1045 int slen;
1046 char *ret;
1047
1048 slen = strlen (string); /* ( */
1049 if (string[slen - 1] == ')')
1050 {
1051 ret = substring (string, *sindex, slen - 1);
1052 *sindex = slen - 1;
1053 return ret;
1054 }
1055 return 0;
1056 }
1057 #endif
1058
1059 /* Extract and create a new string from the contents of STRING, a
1060 character string delimited with OPENER and CLOSER. SINDEX is
1061 the address of an int describing the current offset in STRING;
1062 it should point to just after the first OPENER found. On exit,
1063 SINDEX gets the position of the last character of the matching CLOSER.
1064 If OPENER is more than a single character, ALT_OPENER, if non-null,
1065 contains a character string that can also match CLOSER and thus
1066 needs to be skipped. */
1067 static char *
1068 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
1069 char *string;
1070 int *sindex;
1071 char *opener, *alt_opener, *closer;
1072 int flags;
1073 {
1074 int i, c, si;
1075 size_t slen;
1076 char *t, *result;
1077 int pass_character, nesting_level, in_comment;
1078 int len_closer, len_opener, len_alt_opener;
1079 DECLARE_MBSTATE;
1080
1081 slen = strlen (string + *sindex) + *sindex;
1082 len_opener = STRLEN (opener);
1083 len_alt_opener = STRLEN (alt_opener);
1084 len_closer = STRLEN (closer);
1085
1086 pass_character = in_comment = 0;
1087
1088 nesting_level = 1;
1089 i = *sindex;
1090
1091 while (nesting_level)
1092 {
1093 c = string[i];
1094
1095 if (c == 0)
1096 break;
1097
1098 if (in_comment)
1099 {
1100 if (c == '\n')
1101 in_comment = 0;
1102 ADVANCE_CHAR (string, slen, i);
1103 continue;
1104 }
1105
1106 if (pass_character) /* previous char was backslash */
1107 {
1108 pass_character = 0;
1109 ADVANCE_CHAR (string, slen, i);
1110 continue;
1111 }
1112
1113 /* Not exactly right yet; should handle shell metacharacters and
1114 multibyte characters, too. See COMMENT_BEGIN define in parse.y */
1115 if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
1116 {
1117 in_comment = 1;
1118 ADVANCE_CHAR (string, slen, i);
1119 continue;
1120 }
1121
1122 if (c == CTLESC || c == '\\')
1123 {
1124 pass_character++;
1125 i++;
1126 continue;
1127 }
1128
1129 /* Process a nested OPENER. */
1130 if (STREQN (string + i, opener, len_opener))
1131 {
1132 si = i + len_opener;
1133 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
1134 i = si + 1;
1135 continue;
1136 }
1137
1138 /* Process a nested ALT_OPENER */
1139 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
1140 {
1141 si = i + len_alt_opener;
1142 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
1143 i = si + 1;
1144 continue;
1145 }
1146
1147 /* If the current substring terminates the delimited string, decrement
1148 the nesting level. */
1149 if (STREQN (string + i, closer, len_closer))
1150 {
1151 i += len_closer - 1; /* move to last byte of the closer */
1152 nesting_level--;
1153 if (nesting_level == 0)
1154 break;
1155 }
1156
1157 /* Pass old-style command substitution through verbatim. */
1158 if (c == '`')
1159 {
1160 si = i + 1;
1161 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1162 i = si + 1;
1163 continue;
1164 }
1165
1166 /* Pass single-quoted and double-quoted strings through verbatim. */
1167 if (c == '\'' || c == '"')
1168 {
1169 si = i + 1;
1170 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1171 : skip_double_quoted (string, slen, si);
1172 continue;
1173 }
1174
1175 /* move past this character, which was not special. */
1176 ADVANCE_CHAR (string, slen, i);
1177 }
1178
1179 if (c == 0 && nesting_level)
1180 {
1181 if (no_longjmp_on_fatal_error == 0)
1182 {
1183 report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
1184 last_command_exit_value = EXECUTION_FAILURE;
1185 exp_jump_to_top_level (DISCARD);
1186 }
1187 else
1188 {
1189 *sindex = i;
1190 return (char *)NULL;
1191 }
1192 }
1193
1194 si = i - *sindex - len_closer + 1;
1195 if (flags & SX_NOALLOC)
1196 result = (char *)NULL;
1197 else
1198 {
1199 result = (char *)xmalloc (1 + si);
1200 strncpy (result, string + *sindex, si);
1201 result[si] = '\0';
1202 }
1203 *sindex = i;
1204
1205 return (result);
1206 }
1207
1208 /* Extract a parameter expansion expression within ${ and } from STRING.
1209 Obey the Posix.2 rules for finding the ending `}': count braces while
1210 skipping over enclosed quoted strings and command substitutions.
1211 SINDEX is the address of an int describing the current offset in STRING;
1212 it should point to just after the first `{' found. On exit, SINDEX
1213 gets the position of the matching `}'. QUOTED is non-zero if this
1214 occurs inside double quotes. */
1215 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1216 static char *
1217 extract_dollar_brace_string (string, sindex, quoted, flags)
1218 char *string;
1219 int *sindex, quoted, flags;
1220 {
1221 register int i, c;
1222 size_t slen;
1223 int pass_character, nesting_level, si;
1224 char *result, *t;
1225 DECLARE_MBSTATE;
1226
1227 pass_character = 0;
1228 nesting_level = 1;
1229 slen = strlen (string + *sindex) + *sindex;
1230
1231 i = *sindex;
1232 while (c = string[i])
1233 {
1234 if (pass_character)
1235 {
1236 pass_character = 0;
1237 ADVANCE_CHAR (string, slen, i);
1238 continue;
1239 }
1240
1241 /* CTLESCs and backslashes quote the next character. */
1242 if (c == CTLESC || c == '\\')
1243 {
1244 pass_character++;
1245 i++;
1246 continue;
1247 }
1248
1249 if (string[i] == '$' && string[i+1] == LBRACE)
1250 {
1251 nesting_level++;
1252 i += 2;
1253 continue;
1254 }
1255
1256 if (c == RBRACE)
1257 {
1258 nesting_level--;
1259 if (nesting_level == 0)
1260 break;
1261 i++;
1262 continue;
1263 }
1264
1265 /* Pass the contents of old-style command substitutions through
1266 verbatim. */
1267 if (c == '`')
1268 {
1269 si = i + 1;
1270 t = string_extract (string, &si, "`", flags|SX_NOALLOC);
1271 i = si + 1;
1272 continue;
1273 }
1274
1275 /* Pass the contents of new-style command substitutions and
1276 arithmetic substitutions through verbatim. */
1277 if (string[i] == '$' && string[i+1] == LPAREN)
1278 {
1279 si = i + 2;
1280 t = extract_command_subst (string, &si, flags|SX_NOALLOC);
1281 i = si + 1;
1282 continue;
1283 }
1284
1285 /* Pass the contents of single-quoted and double-quoted strings
1286 through verbatim. */
1287 if (c == '\'' || c == '"')
1288 {
1289 si = i + 1;
1290 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1291 : skip_double_quoted (string, slen, si);
1292 /* skip_XXX_quoted leaves index one past close quote */
1293 continue;
1294 }
1295
1296 /* move past this character, which was not special. */
1297 ADVANCE_CHAR (string, slen, i);
1298 }
1299
1300 if (c == 0 && nesting_level)
1301 {
1302 if (no_longjmp_on_fatal_error == 0)
1303 { /* { */
1304 report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
1305 last_command_exit_value = EXECUTION_FAILURE;
1306 exp_jump_to_top_level (DISCARD);
1307 }
1308 else
1309 {
1310 *sindex = i;
1311 return ((char *)NULL);
1312 }
1313 }
1314
1315 result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1316 *sindex = i;
1317
1318 return (result);
1319 }
1320
1321 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1322 STRING, and returns a pointer to it. */
1323 char *
1324 de_backslash (string)
1325 char *string;
1326 {
1327 register size_t slen;
1328 register int i, j, prev_i;
1329 DECLARE_MBSTATE;
1330
1331 slen = strlen (string);
1332 i = j = 0;
1333
1334 /* Loop copying string[i] to string[j], i >= j. */
1335 while (i < slen)
1336 {
1337 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1338 string[i + 1] == '$'))
1339 i++;
1340 prev_i = i;
1341 ADVANCE_CHAR (string, slen, i);
1342 if (j < prev_i)
1343 do string[j++] = string[prev_i++]; while (prev_i < i);
1344 else
1345 j = i;
1346 }
1347 string[j] = '\0';
1348
1349 return (string);
1350 }
1351
1352 #if 0
1353 /*UNUSED*/
1354 /* Replace instances of \! in a string with !. */
1355 void
1356 unquote_bang (string)
1357 char *string;
1358 {
1359 register int i, j;
1360 register char *temp;
1361
1362 temp = (char *)xmalloc (1 + strlen (string));
1363
1364 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1365 {
1366 if (string[i] == '\\' && string[i + 1] == '!')
1367 {
1368 temp[j] = '!';
1369 i++;
1370 }
1371 }
1372 strcpy (string, temp);
1373 free (temp);
1374 }
1375 #endif
1376
1377 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1378
1379 /* This function assumes s[i] == open; returns with s[ret] == close; used to
1380 parse array subscripts. FLAGS currently unused. */
1381 static int
1382 skip_matched_pair (string, start, open, close, flags)
1383 const char *string;
1384 int start, open, close, flags;
1385 {
1386 int i, pass_next, backq, si, c, count;
1387 size_t slen;
1388 char *temp, *ss;
1389 DECLARE_MBSTATE;
1390
1391 slen = strlen (string + start) + start;
1392 no_longjmp_on_fatal_error = 1;
1393
1394 i = start + 1; /* skip over leading bracket */
1395 count = 1;
1396 pass_next = backq = 0;
1397 ss = (char *)string;
1398 while (c = string[i])
1399 {
1400 if (pass_next)
1401 {
1402 pass_next = 0;
1403 if (c == 0)
1404 CQ_RETURN(i);
1405 ADVANCE_CHAR (string, slen, i);
1406 continue;
1407 }
1408 else if (c == '\\')
1409 {
1410 pass_next = 1;
1411 i++;
1412 continue;
1413 }
1414 else if (backq)
1415 {
1416 if (c == '`')
1417 backq = 0;
1418 ADVANCE_CHAR (string, slen, i);
1419 continue;
1420 }
1421 else if (c == '`')
1422 {
1423 backq = 1;
1424 i++;
1425 continue;
1426 }
1427 else if (c == open)
1428 {
1429 count++;
1430 i++;
1431 continue;
1432 }
1433 else if (c == close)
1434 {
1435 count--;
1436 if (count == 0)
1437 break;
1438 i++;
1439 continue;
1440 }
1441 else if (c == '\'' || c == '"')
1442 {
1443 i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
1444 : skip_double_quoted (ss, slen, ++i);
1445 /* no increment, the skip functions increment past the closing quote. */
1446 }
1447 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1448 {
1449 si = i + 2;
1450 if (string[si] == '\0')
1451 CQ_RETURN(si);
1452
1453 if (string[i+1] == LPAREN)
1454 temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1455 else
1456 temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
1457 i = si;
1458 if (string[i] == '\0') /* don't increment i past EOS in loop */
1459 break;
1460 i++;
1461 continue;
1462 }
1463 else
1464 ADVANCE_CHAR (string, slen, i);
1465 }
1466
1467 CQ_RETURN(i);
1468 }
1469
1470 #if defined (ARRAY_VARS)
1471 int
1472 skipsubscript (string, start)
1473 const char *string;
1474 int start;
1475 {
1476 return (skip_matched_pair (string, start, '[', ']', 0));
1477 }
1478 #endif
1479
1480 /* Skip characters in STRING until we find a character in DELIMS, and return
1481 the index of that character. START is the index into string at which we
1482 begin. This is similar in spirit to strpbrk, but it returns an index into
1483 STRING and takes a starting index. This little piece of code knows quite
1484 a lot of shell syntax. It's very similar to skip_double_quoted and other
1485 functions of that ilk. */
1486 int
1487 skip_to_delim (string, start, delims, flags)
1488 char *string;
1489 int start;
1490 char *delims;
1491 int flags;
1492 {
1493 int i, pass_next, backq, si, c, invert;
1494 size_t slen;
1495 char *temp;
1496 DECLARE_MBSTATE;
1497
1498 slen = strlen (string + start) + start;
1499 if (flags & SD_NOJMP)
1500 no_longjmp_on_fatal_error = 1;
1501 invert = (flags & SD_INVERT);
1502
1503 i = start;
1504 pass_next = backq = 0;
1505 while (c = string[i])
1506 {
1507 if (pass_next)
1508 {
1509 pass_next = 0;
1510 if (c == 0)
1511 CQ_RETURN(i);
1512 ADVANCE_CHAR (string, slen, i);
1513 continue;
1514 }
1515 else if (c == '\\')
1516 {
1517 pass_next = 1;
1518 i++;
1519 continue;
1520 }
1521 else if (backq)
1522 {
1523 if (c == '`')
1524 backq = 0;
1525 ADVANCE_CHAR (string, slen, i);
1526 continue;
1527 }
1528 else if (c == '`')
1529 {
1530 backq = 1;
1531 i++;
1532 continue;
1533 }
1534 else if (invert == 0 && member (c, delims))
1535 break;
1536 else if (c == '\'' || c == '"')
1537 {
1538 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1539 : skip_double_quoted (string, slen, ++i);
1540 /* no increment, the skip functions increment past the closing quote. */
1541 }
1542 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1543 {
1544 si = i + 2;
1545 if (string[si] == '\0')
1546 CQ_RETURN(si);
1547
1548 if (string[i+1] == LPAREN)
1549 temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
1550 else
1551 temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
1552 i = si;
1553 if (string[i] == '\0') /* don't increment i past EOS in loop */
1554 break;
1555 i++;
1556 continue;
1557 }
1558 else if (invert && (member (c, delims) == 0))
1559 break;
1560 else
1561 ADVANCE_CHAR (string, slen, i);
1562 }
1563
1564 CQ_RETURN(i);
1565 }
1566
1567 #if defined (READLINE)
1568 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1569 an unclosed quoted string), or if the character at EINDEX is quoted
1570 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1571 single and double-quoted string parsing functions should not return an
1572 error if there are unclosed quotes or braces. The characters that this
1573 recognizes need to be the same as the contents of
1574 rl_completer_quote_characters. */
1575
1576 int
1577 char_is_quoted (string, eindex)
1578 char *string;
1579 int eindex;
1580 {
1581 int i, pass_next, c;
1582 size_t slen;
1583 DECLARE_MBSTATE;
1584
1585 slen = strlen (string);
1586 no_longjmp_on_fatal_error = 1;
1587 i = pass_next = 0;
1588 while (i <= eindex)
1589 {
1590 c = string[i];
1591
1592 if (pass_next)
1593 {
1594 pass_next = 0;
1595 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1596 CQ_RETURN(1);
1597 ADVANCE_CHAR (string, slen, i);
1598 continue;
1599 }
1600 else if (c == '\\')
1601 {
1602 pass_next = 1;
1603 i++;
1604 continue;
1605 }
1606 else if (c == '\'' || c == '"')
1607 {
1608 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1609 : skip_double_quoted (string, slen, ++i);
1610 if (i > eindex)
1611 CQ_RETURN(1);
1612 /* no increment, the skip_xxx functions go one past end */
1613 }
1614 else
1615 ADVANCE_CHAR (string, slen, i);
1616 }
1617
1618 CQ_RETURN(0);
1619 }
1620
1621 int
1622 unclosed_pair (string, eindex, openstr)
1623 char *string;
1624 int eindex;
1625 char *openstr;
1626 {
1627 int i, pass_next, openc, olen;
1628 size_t slen;
1629 DECLARE_MBSTATE;
1630
1631 slen = strlen (string);
1632 olen = strlen (openstr);
1633 i = pass_next = openc = 0;
1634 while (i <= eindex)
1635 {
1636 if (pass_next)
1637 {
1638 pass_next = 0;
1639 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1640 return 0;
1641 ADVANCE_CHAR (string, slen, i);
1642 continue;
1643 }
1644 else if (string[i] == '\\')
1645 {
1646 pass_next = 1;
1647 i++;
1648 continue;
1649 }
1650 else if (STREQN (string + i, openstr, olen))
1651 {
1652 openc = 1 - openc;
1653 i += olen;
1654 }
1655 else if (string[i] == '\'' || string[i] == '"')
1656 {
1657 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1658 : skip_double_quoted (string, slen, i);
1659 if (i > eindex)
1660 return 0;
1661 }
1662 else
1663 ADVANCE_CHAR (string, slen, i);
1664 }
1665 return (openc);
1666 }
1667
1668 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1669 individual words. If DELIMS is NULL, the current value of $IFS is used
1670 to split the string, and the function follows the shell field splitting
1671 rules. SENTINEL is an index to look for. NWP, if non-NULL,
1672 gets the number of words in the returned list. CWP, if non-NULL, gets
1673 the index of the word containing SENTINEL. Non-whitespace chars in
1674 DELIMS delimit separate fields. */
1675 WORD_LIST *
1676 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1677 char *string;
1678 int slen;
1679 char *delims;
1680 int sentinel;
1681 int *nwp, *cwp;
1682 {
1683 int ts, te, i, nw, cw, ifs_split;
1684 char *token, *d, *d2;
1685 WORD_LIST *ret, *tl;
1686
1687 if (string == 0 || *string == '\0')
1688 {
1689 if (nwp)
1690 *nwp = 0;
1691 if (cwp)
1692 *cwp = 0;
1693 return ((WORD_LIST *)NULL);
1694 }
1695
1696 d = (delims == 0) ? ifs_value : delims;
1697 ifs_split = delims == 0;
1698
1699 /* Make d2 the non-whitespace characters in delims */
1700 d2 = 0;
1701 if (delims)
1702 {
1703 size_t slength;
1704 #if defined (HANDLE_MULTIBYTE)
1705 size_t mblength = 1;
1706 #endif
1707 DECLARE_MBSTATE;
1708
1709 slength = strlen (delims);
1710 d2 = (char *)xmalloc (slength + 1);
1711 i = ts = 0;
1712 while (delims[i])
1713 {
1714 #if defined (HANDLE_MULTIBYTE)
1715 mbstate_t state_bak;
1716 state_bak = state;
1717 mblength = MBRLEN (delims + i, slength, &state);
1718 if (MB_INVALIDCH (mblength))
1719 state = state_bak;
1720 else if (mblength > 1)
1721 {
1722 memcpy (d2 + ts, delims + i, mblength);
1723 ts += mblength;
1724 i += mblength;
1725 slength -= mblength;
1726 continue;
1727 }
1728 #endif
1729 if (whitespace (delims[i]) == 0)
1730 d2[ts++] = delims[i];
1731
1732 i++;
1733 slength--;
1734 }
1735 d2[ts] = '\0';
1736 }
1737
1738 ret = (WORD_LIST *)NULL;
1739
1740 /* Remove sequences of whitspace characters at the start of the string, as
1741 long as those characters are delimiters. */
1742 for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
1743 ;
1744 if (string[i] == '\0')
1745 return (ret);
1746
1747 ts = i;
1748 nw = 0;
1749 cw = -1;
1750 while (1)
1751 {
1752 te = skip_to_delim (string, ts, d, SD_NOJMP);
1753
1754 /* If we have a non-whitespace delimiter character, use it to make a
1755 separate field. This is just about what $IFS splitting does and
1756 is closer to the behavior of the shell parser. */
1757 if (ts == te && d2 && member (string[ts], d2))
1758 {
1759 te = ts + 1;
1760 /* If we're using IFS splitting, the non-whitespace delimiter char
1761 and any additional IFS whitespace delimits a field. */
1762 if (ifs_split)
1763 while (member (string[te], d) && spctabnl (string[te]))
1764 te++;
1765 else
1766 while (member (string[te], d2))
1767 te++;
1768 }
1769
1770 token = substring (string, ts, te);
1771
1772 ret = add_string_to_list (token, ret);
1773 free (token);
1774 nw++;
1775
1776 if (sentinel >= ts && sentinel <= te)
1777 cw = nw;
1778
1779 /* If the cursor is at whitespace just before word start, set the
1780 sentinel word to the current word. */
1781 if (cwp && cw == -1 && sentinel == ts-1)
1782 cw = nw;
1783
1784 /* If the cursor is at whitespace between two words, make a new, empty
1785 word, add it before (well, after, since the list is in reverse order)
1786 the word we just added, and set the current word to that one. */
1787 if (cwp && cw == -1 && sentinel < ts)
1788 {
1789 tl = make_word_list (make_word (""), ret->next);
1790 ret->next = tl;
1791 cw = nw;
1792 nw++;
1793 }
1794
1795 if (string[te] == 0)
1796 break;
1797
1798 i = te;
1799 while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
1800 i++;
1801
1802 if (string[i])
1803 ts = i;
1804 else
1805 break;
1806 }
1807
1808 /* Special case for SENTINEL at the end of STRING. If we haven't found
1809 the word containing SENTINEL yet, and the index we're looking for is at
1810 the end of STRING, add an additional null argument and set the current
1811 word pointer to that. */
1812 if (cwp && cw == -1 && sentinel >= slen)
1813 {
1814 if (whitespace (string[sentinel - 1]))
1815 {
1816 token = "";
1817 ret = add_string_to_list (token, ret);
1818 nw++;
1819 }
1820 cw = nw;
1821 }
1822
1823 if (nwp)
1824 *nwp = nw;
1825 if (cwp)
1826 *cwp = cw;
1827
1828 return (REVERSE_LIST (ret, WORD_LIST *));
1829 }
1830 #endif /* READLINE */
1831
1832 #if 0
1833 /* UNUSED */
1834 /* Extract the name of the variable to bind to from the assignment string. */
1835 char *
1836 assignment_name (string)
1837 char *string;
1838 {
1839 int offset;
1840 char *temp;
1841
1842 offset = assignment (string, 0);
1843 if (offset == 0)
1844 return (char *)NULL;
1845 temp = substring (string, 0, offset);
1846 return (temp);
1847 }
1848 #endif
1849
1850 /* **************************************************************** */
1851 /* */
1852 /* Functions to convert strings to WORD_LISTs and vice versa */
1853 /* */
1854 /* **************************************************************** */
1855
1856 /* Return a single string of all the words in LIST. SEP is the separator
1857 to put between individual elements of LIST in the output string. */
1858 char *
1859 string_list_internal (list, sep)
1860 WORD_LIST *list;
1861 char *sep;
1862 {
1863 register WORD_LIST *t;
1864 char *result, *r;
1865 int word_len, sep_len, result_size;
1866
1867 if (list == 0)
1868 return ((char *)NULL);
1869
1870 /* Short-circuit quickly if we don't need to separate anything. */
1871 if (list->next == 0)
1872 return (savestring (list->word->word));
1873
1874 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1875 sep_len = STRLEN (sep);
1876 result_size = 0;
1877
1878 for (t = list; t; t = t->next)
1879 {
1880 if (t != list)
1881 result_size += sep_len;
1882 result_size += strlen (t->word->word);
1883 }
1884
1885 r = result = (char *)xmalloc (result_size + 1);
1886
1887 for (t = list; t; t = t->next)
1888 {
1889 if (t != list && sep_len)
1890 {
1891 if (sep_len > 1)
1892 {
1893 FASTCOPY (sep, r, sep_len);
1894 r += sep_len;
1895 }
1896 else
1897 *r++ = sep[0];
1898 }
1899
1900 word_len = strlen (t->word->word);
1901 FASTCOPY (t->word->word, r, word_len);
1902 r += word_len;
1903 }
1904
1905 *r = '\0';
1906 return (result);
1907 }
1908
1909 /* Return a single string of all the words present in LIST, separating
1910 each word with a space. */
1911 char *
1912 string_list (list)
1913 WORD_LIST *list;
1914 {
1915 return (string_list_internal (list, " "));
1916 }
1917
1918 /* An external interface that can be used by the rest of the shell to
1919 obtain a string containing the first character in $IFS. Handles all
1920 the multibyte complications. If LENP is non-null, it is set to the
1921 length of the returned string. */
1922 char *
1923 ifs_firstchar (lenp)
1924 int *lenp;
1925 {
1926 char *ret;
1927 int len;
1928
1929 ret = xmalloc (MB_LEN_MAX + 1);
1930 #if defined (HANDLE_MULTIBYTE)
1931 if (ifs_firstc_len == 1)
1932 {
1933 ret[0] = ifs_firstc[0];
1934 ret[1] = '\0';
1935 len = ret[0] ? 1 : 0;
1936 }
1937 else
1938 {
1939 memcpy (ret, ifs_firstc, ifs_firstc_len);
1940 ret[len = ifs_firstc_len] = '\0';
1941 }
1942 #else
1943 ret[0] = ifs_firstc;
1944 ret[1] = '\0';
1945 len = ret[0] ? 0 : 1;
1946 #endif
1947
1948 if (lenp)
1949 *lenp = len;
1950
1951 return ret;
1952 }
1953
1954 /* Return a single string of all the words present in LIST, obeying the
1955 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1956 expansion [of $*] appears within a double quoted string, it expands
1957 to a single field with the value of each parameter separated by the
1958 first character of the IFS variable, or by a <space> if IFS is unset." */
1959 char *
1960 string_list_dollar_star (list)
1961 WORD_LIST *list;
1962 {
1963 char *ret;
1964 #if defined (HANDLE_MULTIBYTE)
1965 # if defined (__GNUC__)
1966 char sep[MB_CUR_MAX + 1];
1967 # else
1968 char *sep = 0;
1969 # endif
1970 #else
1971 char sep[2];
1972 #endif
1973
1974 #if defined (HANDLE_MULTIBYTE)
1975 # if !defined (__GNUC__)
1976 sep = (char *)xmalloc (MB_CUR_MAX + 1);
1977 # endif /* !__GNUC__ */
1978 if (ifs_firstc_len == 1)
1979 {
1980 sep[0] = ifs_firstc[0];
1981 sep[1] = '\0';
1982 }
1983 else
1984 {
1985 memcpy (sep, ifs_firstc, ifs_firstc_len);
1986 sep[ifs_firstc_len] = '\0';
1987 }
1988 #else
1989 sep[0] = ifs_firstc;
1990 sep[1] = '\0';
1991 #endif
1992
1993 ret = string_list_internal (list, sep);
1994 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
1995 free (sep);
1996 #endif
1997 return ret;
1998 }
1999
2000 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2001 is non-zero, the $@ appears within double quotes, and we should quote
2002 the list before converting it into a string. If IFS is unset, and the
2003 word is not quoted, we just need to quote CTLESC and CTLNUL characters
2004 in the words in the list, because the default value of $IFS is
2005 <space><tab><newline>, IFS characters in the words in the list should
2006 also be split. If IFS is null, and the word is not quoted, we need
2007 to quote the words in the list to preserve the positional parameters
2008 exactly. */
2009 char *
2010 string_list_dollar_at (list, quoted)
2011 WORD_LIST *list;
2012 int quoted;
2013 {
2014 char *ifs, *ret;
2015 #if defined (HANDLE_MULTIBYTE)
2016 # if defined (__GNUC__)
2017 char sep[MB_CUR_MAX + 1];
2018 # else
2019 char *sep = 0;
2020 # endif /* !__GNUC__ */
2021 #else
2022 char sep[2];
2023 #endif
2024 WORD_LIST *tlist;
2025
2026 /* XXX this could just be ifs = ifs_value; */
2027 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
2028
2029 #if defined (HANDLE_MULTIBYTE)
2030 # if !defined (__GNUC__)
2031 sep = (char *)xmalloc (MB_CUR_MAX + 1);
2032 # endif /* !__GNUC__ */
2033 if (ifs && *ifs)
2034 {
2035 if (ifs_firstc_len == 1)
2036 {
2037 sep[0] = ifs_firstc[0];
2038 sep[1] = '\0';
2039 }
2040 else
2041 {
2042 memcpy (sep, ifs_firstc, ifs_firstc_len);
2043 sep[ifs_firstc_len] = '\0';
2044 }
2045 }
2046 else
2047 {
2048 sep[0] = ' ';
2049 sep[1] = '\0';
2050 }
2051 #else
2052 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
2053 sep[1] = '\0';
2054 #endif
2055
2056 /* XXX -- why call quote_list if ifs == 0? we can get away without doing
2057 it now that quote_escapes quotes spaces */
2058 #if 0
2059 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
2060 #else
2061 tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
2062 #endif
2063 ? quote_list (list)
2064 : list_quote_escapes (list);
2065
2066 ret = string_list_internal (tlist, sep);
2067 #if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
2068 free (sep);
2069 #endif
2070 return ret;
2071 }
2072
2073 /* Turn the positional paramters into a string, understanding quoting and
2074 the various subtleties of using the first character of $IFS as the
2075 separator. Calls string_list_dollar_at, string_list_dollar_star, and
2076 string_list as appropriate. */
2077 char *
2078 string_list_pos_params (pchar, list, quoted)
2079 int pchar;
2080 WORD_LIST *list;
2081 int quoted;
2082 {
2083 char *ret;
2084 WORD_LIST *tlist;
2085
2086 if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
2087 {
2088 tlist = quote_list (list);
2089 word_list_remove_quoted_nulls (tlist);
2090 ret = string_list_dollar_star (tlist);
2091 }
2092 else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
2093 {
2094 tlist = quote_list (list);
2095 word_list_remove_quoted_nulls (tlist);
2096 ret = string_list (tlist);
2097 }
2098 else if (pchar == '*')
2099 {
2100 /* Even when unquoted, string_list_dollar_star does the right thing
2101 making sure that the first character of $IFS is used as the
2102 separator. */
2103 ret = string_list_dollar_star (list);
2104 }
2105 else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
2106 /* We use string_list_dollar_at, but only if the string is quoted, since
2107 that quotes the escapes if it's not, which we don't want. We could
2108 use string_list (the old code did), but that doesn't do the right
2109 thing if the first character of $IFS is not a space. We use
2110 string_list_dollar_star if the string is unquoted so we make sure that
2111 the elements of $@ are separated by the first character of $IFS for
2112 later splitting. */
2113 ret = string_list_dollar_at (list, quoted);
2114 else if (pchar == '@')
2115 ret = string_list_dollar_star (list);
2116 else
2117 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
2118
2119 return ret;
2120 }
2121
2122 /* Return the list of words present in STRING. Separate the string into
2123 words at any of the characters found in SEPARATORS. If QUOTED is
2124 non-zero then word in the list will have its quoted flag set, otherwise
2125 the quoted flag is left as make_word () deemed fit.
2126
2127 This obeys the P1003.2 word splitting semantics. If `separators' is
2128 exactly <space><tab><newline>, then the splitting algorithm is that of
2129 the Bourne shell, which treats any sequence of characters from `separators'
2130 as a delimiter. If IFS is unset, which results in `separators' being set
2131 to "", no splitting occurs. If separators has some other value, the
2132 following rules are applied (`IFS white space' means zero or more
2133 occurrences of <space>, <tab>, or <newline>, as long as those characters
2134 are in `separators'):
2135
2136 1) IFS white space is ignored at the start and the end of the
2137 string.
2138 2) Each occurrence of a character in `separators' that is not
2139 IFS white space, along with any adjacent occurrences of
2140 IFS white space delimits a field.
2141 3) Any nonzero-length sequence of IFS white space delimits a field.
2142 */
2143
2144 /* BEWARE! list_string strips null arguments. Don't call it twice and
2145 expect to have "" preserved! */
2146
2147 /* This performs word splitting and quoted null character removal on
2148 STRING. */
2149 #define issep(c) \
2150 (((separators)[0]) ? ((separators)[1] ? isifs(c) \
2151 : (c) == (separators)[0]) \
2152 : 0)
2153
2154 WORD_LIST *
2155 list_string (string, separators, quoted)
2156 register char *string, *separators;
2157 int quoted;
2158 {
2159 WORD_LIST *result;
2160 WORD_DESC *t;
2161 char *current_word, *s;
2162 int sindex, sh_style_split, whitesep, xflags;
2163 size_t slen;
2164
2165 if (!string || !*string)
2166 return ((WORD_LIST *)NULL);
2167
2168 sh_style_split = separators && separators[0] == ' ' &&
2169 separators[1] == '\t' &&
2170 separators[2] == '\n' &&
2171 separators[3] == '\0';
2172 for (xflags = 0, s = ifs_value; s && *s; s++)
2173 {
2174 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2175 else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2176 }
2177
2178 slen = 0;
2179 /* Remove sequences of whitespace at the beginning of STRING, as
2180 long as those characters appear in IFS. Do not do this if
2181 STRING is quoted or if there are no separator characters. */
2182 if (!quoted || !separators || !*separators)
2183 {
2184 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
2185
2186 if (!*s)
2187 return ((WORD_LIST *)NULL);
2188
2189 string = s;
2190 }
2191
2192 /* OK, now STRING points to a word that does not begin with white space.
2193 The splitting algorithm is:
2194 extract a word, stopping at a separator
2195 skip sequences of spc, tab, or nl as long as they are separators
2196 This obeys the field splitting rules in Posix.2. */
2197 slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
2198 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
2199 {
2200 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2201 unless multibyte chars are possible. */
2202 current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
2203 if (current_word == 0)
2204 break;
2205
2206 /* If we have a quoted empty string, add a quoted null argument. We
2207 want to preserve the quoted null character iff this is a quoted
2208 empty string; otherwise the quoted null characters are removed
2209 below. */
2210 if (QUOTED_NULL (current_word))
2211 {
2212 t = alloc_word_desc ();
2213 t->word = make_quoted_char ('\0');
2214 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2215 result = make_word_list (t, result);
2216 }
2217 else if (current_word[0] != '\0')
2218 {
2219 /* If we have something, then add it regardless. However,
2220 perform quoted null character removal on the current word. */
2221 remove_quoted_nulls (current_word);
2222 result = add_string_to_list (current_word, result);
2223 result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
2224 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
2225 result->word->flags |= W_QUOTED;
2226 }
2227
2228 /* If we're not doing sequences of separators in the traditional
2229 Bourne shell style, then add a quoted null argument. */
2230 else if (!sh_style_split && !spctabnl (string[sindex]))
2231 {
2232 t = alloc_word_desc ();
2233 t->word = make_quoted_char ('\0');
2234 t->flags |= W_QUOTED|W_HASQUOTEDNULL;
2235 result = make_word_list (t, result);
2236 }
2237
2238 free (current_word);
2239
2240 /* Note whether or not the separator is IFS whitespace, used later. */
2241 whitesep = string[sindex] && spctabnl (string[sindex]);
2242
2243 /* Move past the current separator character. */
2244 if (string[sindex])
2245 {
2246 DECLARE_MBSTATE;
2247 ADVANCE_CHAR (string, slen, sindex);
2248 }
2249
2250 /* Now skip sequences of space, tab, or newline characters if they are
2251 in the list of separators. */
2252 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
2253 sindex++;
2254
2255 /* If the first separator was IFS whitespace and the current character
2256 is a non-whitespace IFS character, it should be part of the current
2257 field delimiter, not a separate delimiter that would result in an
2258 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
2259 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
2260 {
2261 sindex++;
2262 /* An IFS character that is not IFS white space, along with any
2263 adjacent IFS white space, shall delimit a field. (SUSv3) */
2264 while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
2265 sindex++;
2266 }
2267 }
2268 return (REVERSE_LIST (result, WORD_LIST *));
2269 }
2270
2271 /* Parse a single word from STRING, using SEPARATORS to separate fields.
2272 ENDPTR is set to the first character after the word. This is used by
2273 the `read' builtin. This is never called with SEPARATORS != $IFS;
2274 it should be simplified.
2275
2276 XXX - this function is very similar to list_string; they should be
2277 combined - XXX */
2278 char *
2279 get_word_from_string (stringp, separators, endptr)
2280 char **stringp, *separators, **endptr;
2281 {
2282 register char *s;
2283 char *current_word;
2284 int sindex, sh_style_split, whitesep, xflags;
2285 size_t slen;
2286
2287 if (!stringp || !*stringp || !**stringp)
2288 return ((char *)NULL);
2289
2290 sh_style_split = separators && separators[0] == ' ' &&
2291 separators[1] == '\t' &&
2292 separators[2] == '\n' &&
2293 separators[3] == '\0';
2294 for (xflags = 0, s = ifs_value; s && *s; s++)
2295 {
2296 if (*s == CTLESC) xflags |= SX_NOCTLESC;
2297 if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
2298 }
2299
2300 s = *stringp;
2301 slen = 0;
2302
2303 /* Remove sequences of whitespace at the beginning of STRING, as
2304 long as those characters appear in IFS. */
2305 if (sh_style_split || !separators || !*separators)
2306 {
2307 for (; *s && spctabnl (*s) && isifs (*s); s++);
2308
2309 /* If the string is nothing but whitespace, update it and return. */
2310 if (!*s)
2311 {
2312 *stringp = s;
2313 if (endptr)
2314 *endptr = s;
2315 return ((char *)NULL);
2316 }
2317 }
2318
2319 /* OK, S points to a word that does not begin with white space.
2320 Now extract a word, stopping at a separator, save a pointer to
2321 the first character after the word, then skip sequences of spc,
2322 tab, or nl as long as they are separators.
2323
2324 This obeys the field splitting rules in Posix.2. */
2325 sindex = 0;
2326 /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
2327 unless multibyte chars are possible. */
2328 slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
2329 current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
2330
2331 /* Set ENDPTR to the first character after the end of the word. */
2332 if (endptr)
2333 *endptr = s + sindex;
2334
2335 /* Note whether or not the separator is IFS whitespace, used later. */
2336 whitesep = s[sindex] && spctabnl (s[sindex]);
2337
2338 /* Move past the current separator character. */
2339 if (s[sindex])
2340 {
2341 DECLARE_MBSTATE;
2342 ADVANCE_CHAR (s, slen, sindex);
2343 }
2344
2345 /* Now skip sequences of space, tab, or newline characters if they are
2346 in the list of separators. */
2347 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2348 sindex++;
2349
2350 /* If the first separator was IFS whitespace and the current character is
2351 a non-whitespace IFS character, it should be part of the current field
2352 delimiter, not a separate delimiter that would result in an empty field.
2353 Look at POSIX.2, 3.6.5, (3)(b). */
2354 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
2355 {
2356 sindex++;
2357 /* An IFS character that is not IFS white space, along with any adjacent
2358 IFS white space, shall delimit a field. */
2359 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
2360 sindex++;
2361 }
2362
2363 /* Update STRING to point to the next field. */
2364 *stringp = s + sindex;
2365 return (current_word);
2366 }
2367
2368 /* Remove IFS white space at the end of STRING. Start at the end
2369 of the string and walk backwards until the beginning of the string
2370 or we find a character that's not IFS white space and not CTLESC.
2371 Only let CTLESC escape a white space character if SAW_ESCAPE is
2372 non-zero. */
2373 char *
2374 strip_trailing_ifs_whitespace (string, separators, saw_escape)
2375 char *string, *separators;
2376 int saw_escape;
2377 {
2378 char *s;
2379
2380 s = string + STRLEN (string) - 1;
2381 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
2382 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
2383 s--;
2384 *++s = '\0';
2385 return string;
2386 }
2387
2388 #if 0
2389 /* UNUSED */
2390 /* Split STRING into words at whitespace. Obeys shell-style quoting with
2391 backslashes, single and double quotes. */
2392 WORD_LIST *
2393 list_string_with_quotes (string)
2394 char *string;
2395 {
2396 WORD_LIST *list;
2397 char *token, *s;
2398 size_t s_len;
2399 int c, i, tokstart, len;
2400
2401 for (s = string; s && *s && spctabnl (*s); s++)
2402 ;
2403 if (s == 0 || *s == 0)
2404 return ((WORD_LIST *)NULL);
2405
2406 s_len = strlen (s);
2407 tokstart = i = 0;
2408 list = (WORD_LIST *)NULL;
2409 while (1)
2410 {
2411 c = s[i];
2412 if (c == '\\')
2413 {
2414 i++;
2415 if (s[i])
2416 i++;
2417 }
2418 else if (c == '\'')
2419 i = skip_single_quoted (s, s_len, ++i);
2420 else if (c == '"')
2421 i = skip_double_quoted (s, s_len, ++i);
2422 else if (c == 0 || spctabnl (c))
2423 {
2424 /* We have found the end of a token. Make a word out of it and
2425 add it to the word list. */
2426 token = substring (s, tokstart, i);
2427 list = add_string_to_list (token, list);
2428 free (token);
2429 while (spctabnl (s[i]))
2430 i++;
2431 if (s[i])
2432 tokstart = i;
2433 else
2434 break;
2435 }
2436 else
2437 i++; /* normal character */
2438 }
2439 return (REVERSE_LIST (list, WORD_LIST *));
2440 }
2441 #endif
2442
2443 /********************************************************/
2444 /* */
2445 /* Functions to perform assignment statements */
2446 /* */
2447 /********************************************************/
2448
2449 #if defined (ARRAY_VARS)
2450 static SHELL_VAR *
2451 do_compound_assignment (name, value, flags)
2452 char *name, *value;
2453 int flags;
2454 {
2455 SHELL_VAR *v;
2456 int mklocal, mkassoc;
2457 WORD_LIST *list;
2458
2459 mklocal = flags & ASS_MKLOCAL;
2460 mkassoc = flags & ASS_MKASSOC;
2461
2462 if (mklocal && variable_context)
2463 {
2464 v = find_variable (name);
2465 list = expand_compound_array_assignment (v, value, flags);
2466 if (mkassoc)
2467 v = make_local_assoc_variable (name);
2468 else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
2469 v = make_local_array_variable (name);
2470 assign_compound_array_list (v, list, flags);
2471 }
2472 else
2473 v = assign_array_from_string (name, value, flags);
2474
2475 return (v);
2476 }
2477 #endif
2478
2479 /* Given STRING, an assignment string, get the value of the right side
2480 of the `=', and bind it to the left side. If EXPAND is true, then
2481 perform parameter expansion, command substitution, and arithmetic
2482 expansion on the right-hand side. Perform tilde expansion in any
2483 case. Do not perform word splitting on the result of expansion. */
2484 static int
2485 do_assignment_internal (word, expand)
2486 const WORD_DESC *word;
2487 int expand;
2488 {
2489 int offset, tlen, appendop, assign_list, aflags, retval;
2490 char *name, *value;
2491 SHELL_VAR *entry;
2492 #if defined (ARRAY_VARS)
2493 char *t;
2494 int ni;
2495 #endif
2496 const char *string;
2497
2498 if (word == 0 || word->word == 0)
2499 return 0;
2500
2501 appendop = assign_list = aflags = 0;
2502 string = word->word;
2503 offset = assignment (string, 0);
2504 name = savestring (string);
2505 value = (char *)NULL;
2506
2507 if (name[offset] == '=')
2508 {
2509 char *temp;
2510
2511 if (name[offset - 1] == '+')
2512 {
2513 appendop = 1;
2514 name[offset - 1] = '\0';
2515 }
2516
2517 name[offset] = 0; /* might need this set later */
2518 temp = name + offset + 1;
2519 tlen = STRLEN (temp);
2520
2521 #if defined (ARRAY_VARS)
2522 if (expand && (word->flags & W_COMPASSIGN))
2523 {
2524 assign_list = ni = 1;
2525 value = extract_array_assignment_list (temp, &ni);
2526 }
2527 else
2528 #endif
2529
2530 if (expand && temp[0])
2531 value = expand_string_if_necessary (temp, 0, expand_string_assignment);
2532 else
2533 value = savestring (temp);
2534 }
2535
2536 if (value == 0)
2537 {
2538 value = (char *)xmalloc (1);
2539 value[0] = '\0';
2540 }
2541
2542 if (echo_command_at_execute)
2543 {
2544 if (appendop)
2545 name[offset - 1] = '+';
2546 xtrace_print_assignment (name, value, assign_list, 1);
2547 if (appendop)
2548 name[offset - 1] = '\0';
2549 }
2550
2551 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
2552
2553 if (appendop)
2554 aflags |= ASS_APPEND;
2555
2556 #if defined (ARRAY_VARS)
2557 if (t = mbschr (name, '[')) /*]*/
2558 {
2559 if (assign_list)
2560 {
2561 report_error (_("%s: cannot assign list to array member"), name);
2562 ASSIGN_RETURN (0);
2563 }
2564 entry = assign_array_element (name, value, aflags);
2565 if (entry == 0)
2566 ASSIGN_RETURN (0);
2567 }
2568 else if (assign_list)
2569 {
2570 if (word->flags & W_ASSIGNARG)
2571 aflags |= ASS_MKLOCAL;
2572 if (word->flags & W_ASSIGNASSOC)
2573 aflags |= ASS_MKASSOC;
2574 entry = do_compound_assignment (name, value, aflags);
2575 }
2576 else
2577 #endif /* ARRAY_VARS */
2578 entry = bind_variable (name, value, aflags);
2579
2580 stupidly_hack_special_variables (name);
2581
2582 #if 1
2583 /* Return 1 if the assignment seems to have been performed correctly. */
2584 if (entry == 0 || readonly_p (entry))
2585 retval = 0; /* assignment failure */
2586 else if (noassign_p (entry))
2587 {
2588 last_command_exit_value = EXECUTION_FAILURE;
2589 retval = 1; /* error status, but not assignment failure */
2590 }
2591 else
2592 retval = 1;
2593
2594 if (entry && retval != 0 && noassign_p (entry) == 0)
2595 VUNSETATTR (entry, att_invisible);
2596
2597 ASSIGN_RETURN (retval);
2598 #else
2599 if (entry)
2600 VUNSETATTR (entry, att_invisible);
2601
2602 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2603 #endif
2604 }
2605
2606 /* Perform the assignment statement in STRING, and expand the
2607 right side by doing tilde, command and parameter expansion. */
2608 int
2609 do_assignment (string)
2610 char *string;
2611 {
2612 WORD_DESC td;
2613
2614 td.flags = W_ASSIGNMENT;
2615 td.word = string;
2616
2617 return do_assignment_internal (&td, 1);
2618 }
2619
2620 int
2621 do_word_assignment (word)
2622 WORD_DESC *word;
2623 {
2624 return do_assignment_internal (word, 1);
2625 }
2626
2627 /* Given STRING, an assignment string, get the value of the right side
2628 of the `=', and bind it to the left side. Do not perform any word
2629 expansions on the right hand side. */
2630 int
2631 do_assignment_no_expand (string)
2632 char *string;
2633 {
2634 WORD_DESC td;
2635
2636 td.flags = W_ASSIGNMENT;
2637 td.word = string;
2638
2639 return (do_assignment_internal (&td, 0));
2640 }
2641
2642 /***************************************************
2643 * *
2644 * Functions to manage the positional parameters *
2645 * *
2646 ***************************************************/
2647
2648 /* Return the word list that corresponds to `$*'. */
2649 WORD_LIST *
2650 list_rest_of_args ()
2651 {
2652 register WORD_LIST *list, *args;
2653 int i;
2654
2655 /* Break out of the loop as soon as one of the dollar variables is null. */
2656 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2657 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2658
2659 for (args = rest_of_args; args; args = args->next)
2660 list = make_word_list (make_bare_word (args->word->word), list);
2661
2662 return (REVERSE_LIST (list, WORD_LIST *));
2663 }
2664
2665 int
2666 number_of_args ()
2667 {
2668 register WORD_LIST *list;
2669 int n;
2670
2671 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2672 ;
2673 for (list = rest_of_args; list; list = list->next)
2674 n++;
2675 return n;
2676 }
2677
2678 /* Return the value of a positional parameter. This handles values > 10. */
2679 char *
2680 get_dollar_var_value (ind)
2681 intmax_t ind;
2682 {
2683 char *temp;
2684 WORD_LIST *p;
2685
2686 if (ind < 10)
2687 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2688 else /* We want something like ${11} */
2689 {
2690 ind -= 10;
2691 for (p = rest_of_args; p && ind--; p = p->next)
2692 ;
2693 temp = p ? savestring (p->word->word) : (char *)NULL;
2694 }
2695 return (temp);
2696 }
2697
2698 /* Make a single large string out of the dollar digit variables,
2699 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2700 case of "$*" with respect to IFS. */
2701 char *
2702 string_rest_of_args (dollar_star)
2703 int dollar_star;
2704 {
2705 register WORD_LIST *list;
2706 char *string;
2707
2708 list = list_rest_of_args ();
2709 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2710 dispose_words (list);
2711 return (string);
2712 }
2713
2714 /* Return a string containing the positional parameters from START to
2715 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2716 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2717 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2718 no quoting chars are added. */
2719 static char *
2720 pos_params (string, start, end, quoted)
2721 char *string;
2722 int start, end, quoted;
2723 {
2724 WORD_LIST *save, *params, *h, *t;
2725 char *ret;
2726 int i;
2727
2728 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2729 if (start == end)
2730 return ((char *)NULL);
2731
2732 save = params = list_rest_of_args ();
2733 if (save == 0)
2734 return ((char *)NULL);
2735
2736 if (start == 0) /* handle ${@:0[:x]} specially */
2737 {
2738 t = make_word_list (make_word (dollar_vars[0]), params);
2739 save = params = t;
2740 }
2741
2742 for (i = 1; params && i < start; i++)
2743 params = params->next;
2744 if (params == 0)
2745 return ((char *)NULL);
2746 for (h = t = params; params && i < end; i++)
2747 {
2748 t = params;
2749 params = params->next;
2750 }
2751
2752 t->next = (WORD_LIST *)NULL;
2753
2754 ret = string_list_pos_params (string[0], h, quoted);
2755
2756 if (t != params)
2757 t->next = params;
2758
2759 dispose_words (save);
2760 return (ret);
2761 }
2762
2763 /******************************************************************/
2764 /* */
2765 /* Functions to expand strings to strings or WORD_LISTs */
2766 /* */
2767 /******************************************************************/
2768
2769 #if defined (PROCESS_SUBSTITUTION)
2770 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
2771 #else
2772 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
2773 #endif
2774
2775 /* If there are any characters in STRING that require full expansion,
2776 then call FUNC to expand STRING; otherwise just perform quote
2777 removal if necessary. This returns a new string. */
2778 static char *
2779 expand_string_if_necessary (string, quoted, func)
2780 char *string;
2781 int quoted;
2782 EXPFUNC *func;
2783 {
2784 WORD_LIST *list;
2785 size_t slen;
2786 int i, saw_quote;
2787 char *ret;
2788 DECLARE_MBSTATE;
2789
2790 /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
2791 slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
2792 i = saw_quote = 0;
2793 while (string[i])
2794 {
2795 if (EXP_CHAR (string[i]))
2796 break;
2797 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2798 saw_quote = 1;
2799 ADVANCE_CHAR (string, slen, i);
2800 }
2801
2802 if (string[i])
2803 {
2804 list = (*func) (string, quoted);
2805 if (list)
2806 {
2807 ret = string_list (list);
2808 dispose_words (list);
2809 }
2810 else
2811 ret = (char *)NULL;
2812 }
2813 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2814 ret = string_quote_removal (string, quoted);
2815 else
2816 ret = savestring (string);
2817
2818 return ret;
2819 }
2820
2821 static inline char *
2822 expand_string_to_string_internal (string, quoted, func)
2823 char *string;
2824 int quoted;
2825 EXPFUNC *func;
2826 {
2827 WORD_LIST *list;
2828 char *ret;
2829
2830 if (string == 0 || *string == '\0')
2831 return ((char *)NULL);
2832
2833 list = (*func) (string, quoted);
2834 if (list)
2835 {
2836 ret = string_list (list);
2837 dispose_words (list);
2838 }
2839 else
2840 ret = (char *)NULL;
2841
2842 return (ret);
2843 }
2844
2845 char *
2846 expand_string_to_string (string, quoted)
2847 char *string;
2848 int quoted;
2849 {
2850 return (expand_string_to_string_internal (string, quoted, expand_string));
2851 }
2852
2853 char *
2854 expand_string_unsplit_to_string (string, quoted)
2855 char *string;
2856 int quoted;
2857 {
2858 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2859 }
2860
2861 char *
2862 expand_assignment_string_to_string (string, quoted)
2863 char *string;
2864 int quoted;
2865 {
2866 return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
2867 }
2868
2869 char *
2870 expand_arith_string (string, quoted)
2871 char *string;
2872 int quoted;
2873 {
2874 return (expand_string_if_necessary (string, quoted, expand_string));
2875 }
2876
2877 #if defined (COND_COMMAND)
2878 /* Just remove backslashes in STRING. Returns a new string. */
2879 char *
2880 remove_backslashes (string)
2881 char *string;
2882 {
2883 char *r, *ret, *s;
2884
2885 r = ret = (char *)xmalloc (strlen (string) + 1);
2886 for (s = string; s && *s; )
2887 {
2888 if (*s == '\\')
2889 s++;
2890 if (*s == 0)
2891 break;
2892 *r++ = *s++;
2893 }
2894 *r = '\0';
2895 return ret;
2896 }
2897
2898 /* This needs better error handling. */
2899 /* Expand W for use as an argument to a unary or binary operator in a
2900 [[...]] expression. If SPECIAL is 1, this is the rhs argument
2901 to the != or == operator, and should be treated as a pattern. In
2902 this case, we quote the string specially for the globbing code. If
2903 SPECIAL is 2, this is an rhs argument for the =~ operator, and should
2904 be quoted appropriately for regcomp/regexec. The caller is responsible
2905 for removing the backslashes if the unquoted word is needed later. */
2906 char *
2907 cond_expand_word (w, special)
2908 WORD_DESC *w;
2909 int special;
2910 {
2911 char *r, *p;
2912 WORD_LIST *l;
2913 int qflags;
2914
2915 if (w->word == 0 || w->word[0] == '\0')
2916 return ((char *)NULL);
2917
2918 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2919 if (l)
2920 {
2921 if (special == 0)
2922 {
2923 dequote_list (l);
2924 r = string_list (l);
2925 }
2926 else
2927 {
2928 qflags = QGLOB_CVTNULL;
2929 if (special == 2)
2930 qflags |= QGLOB_REGEXP;
2931 p = string_list (l);
2932 r = quote_string_for_globbing (p, qflags);
2933 free (p);
2934 }
2935 dispose_words (l);
2936 }
2937 else
2938 r = (char *)NULL;
2939
2940 return r;
2941 }
2942 #endif
2943
2944 /* Call expand_word_internal to expand W and handle error returns.
2945 A convenience function for functions that don't want to handle
2946 any errors or free any memory before aborting. */
2947 static WORD_LIST *
2948 call_expand_word_internal (w, q, i, c, e)
2949 WORD_DESC *w;
2950 int q, i, *c, *e;
2951 {
2952 WORD_LIST *result;
2953
2954 result = expand_word_internal (w, q, i, c, e);
2955 if (result == &expand_word_error || result == &expand_word_fatal)
2956 {
2957 /* By convention, each time this error is returned, w->word has
2958 already been freed (it sometimes may not be in the fatal case,
2959 but that doesn't result in a memory leak because we're going
2960 to exit in most cases). */
2961 w->word = (char *)NULL;
2962 last_command_exit_value = EXECUTION_FAILURE;
2963 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2964 /* NOTREACHED */
2965 }
2966 else
2967 return (result);
2968 }
2969
2970 /* Perform parameter expansion, command substitution, and arithmetic
2971 expansion on STRING, as if it were a word. Leave the result quoted. */
2972 static WORD_LIST *
2973 expand_string_internal (string, quoted)
2974 char *string;
2975 int quoted;
2976 {
2977 WORD_DESC td;
2978 WORD_LIST *tresult;
2979
2980 if (string == 0 || *string == 0)
2981 return ((WORD_LIST *)NULL);
2982
2983 td.flags = 0;
2984 td.word = savestring (string);
2985
2986 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2987
2988 FREE (td.word);
2989 return (tresult);
2990 }
2991
2992 /* Expand STRING by performing parameter expansion, command substitution,
2993 and arithmetic expansion. Dequote the resulting WORD_LIST before
2994 returning it, but do not perform word splitting. The call to
2995 remove_quoted_nulls () is in here because word splitting normally
2996 takes care of quote removal. */
2997 WORD_LIST *
2998 expand_string_unsplit (string, quoted)
2999 char *string;
3000 int quoted;
3001 {
3002 WORD_LIST *value;
3003
3004 if (string == 0 || *string == '\0')
3005 return ((WORD_LIST *)NULL);
3006
3007 expand_no_split_dollar_star = 1;
3008 value = expand_string_internal (string, quoted);
3009 expand_no_split_dollar_star = 0;
3010
3011 if (value)
3012 {
3013 if (value->word)
3014 {
3015 remove_quoted_nulls (value->word->word);
3016 value->word->flags &= ~W_HASQUOTEDNULL;
3017 }
3018 dequote_list (value);
3019 }
3020 return (value);
3021 }
3022
3023 /* Expand the rhs of an assignment statement */
3024 WORD_LIST *
3025 expand_string_assignment (string, quoted)
3026 char *string;
3027 int quoted;
3028 {
3029 WORD_DESC td;
3030 WORD_LIST *value;
3031
3032 if (string == 0 || *string == '\0')
3033 return ((WORD_LIST *)NULL);
3034
3035 expand_no_split_dollar_star = 1;
3036
3037 td.flags = W_ASSIGNRHS;
3038 td.word = savestring (string);
3039 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3040 FREE (td.word);
3041
3042 expand_no_split_dollar_star = 0;
3043
3044 if (value)
3045 {
3046 if (value->word)
3047 {
3048 remove_quoted_nulls (value->word->word);
3049 value->word->flags &= ~W_HASQUOTEDNULL;
3050 }
3051 dequote_list (value);
3052 }
3053 return (value);
3054 }
3055
3056
3057 /* Expand one of the PS? prompt strings. This is a sort of combination of
3058 expand_string_unsplit and expand_string_internal, but returns the
3059 passed string when an error occurs. Might want to trap other calls
3060 to jump_to_top_level here so we don't endlessly loop. */
3061 WORD_LIST *
3062 expand_prompt_string (string, quoted, wflags)
3063 char *string;
3064 int quoted;
3065 int wflags;
3066 {
3067 WORD_LIST *value;
3068 WORD_DESC td;
3069
3070 if (string == 0 || *string == 0)
3071 return ((WORD_LIST *)NULL);
3072
3073 td.flags = wflags;
3074 td.word = savestring (string);
3075
3076 no_longjmp_on_fatal_error = 1;
3077 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
3078 no_longjmp_on_fatal_error = 0;
3079
3080 if (value == &expand_word_error || value == &expand_word_fatal)
3081 {
3082 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
3083 return value;
3084 }
3085 FREE (td.word);
3086 if (value)
3087 {
3088 if (value->word)
3089 {
3090 remove_quoted_nulls (value->word->word);
3091 value->word->flags &= ~W_HASQUOTEDNULL;
3092 }
3093 dequote_list (value);
3094 }
3095 return (value);
3096 }
3097
3098 /* Expand STRING just as if you were expanding a word, but do not dequote
3099 the resultant WORD_LIST. This is called only from within this file,
3100 and is used to correctly preserve quoted characters when expanding
3101 things like ${1+"$@"}. This does parameter expansion, command
3102 substitution, arithmetic expansion, and word splitting. */
3103 static WORD_LIST *
3104 expand_string_leave_quoted (string, quoted)
3105 char *string;
3106 int quoted;
3107 {
3108 WORD_LIST *tlist;
3109 WORD_LIST *tresult;
3110
3111 if (string == 0 || *string == '\0')
3112 return ((WORD_LIST *)NULL);
3113
3114 tlist = expand_string_internal (string, quoted);
3115
3116 if (tlist)
3117 {
3118 tresult = word_list_split (tlist);
3119 dispose_words (tlist);
3120 return (tresult);
3121 }
3122 return ((WORD_LIST *)NULL);
3123 }
3124
3125 /* This does not perform word splitting or dequote the WORD_LIST
3126 it returns. */
3127 static WORD_LIST *
3128 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
3129 char *string;
3130 int quoted, *dollar_at_p, *has_dollar_at;
3131 {
3132 WORD_DESC td;
3133 WORD_LIST *tresult;
3134
3135 if (string == 0 || *string == '\0')
3136 return (WORD_LIST *)NULL;
3137
3138 td.flags = 0;
3139 td.word = string;
3140 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
3141 return (tresult);
3142 }
3143
3144 /* Expand STRING just as if you were expanding a word. This also returns
3145 a list of words. Note that filename globbing is *NOT* done for word
3146 or string expansion, just when the shell is expanding a command. This
3147 does parameter expansion, command substitution, arithmetic expansion,
3148 and word splitting. Dequote the resultant WORD_LIST before returning. */
3149 WORD_LIST *
3150 expand_string (string, quoted)
3151 char *string;
3152 int quoted;
3153 {
3154 WORD_LIST *result;
3155
3156 if (string == 0 || *string == '\0')
3157 return ((WORD_LIST *)NULL);
3158
3159 result = expand_string_leave_quoted (string, quoted);
3160 return (result ? dequote_list (result) : result);
3161 }
3162
3163 /***************************************************
3164 * *
3165 * Functions to handle quoting chars *
3166 * *
3167 ***************************************************/
3168
3169 /* Conventions:
3170
3171 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
3172 The parser passes CTLNUL as CTLESC CTLNUL. */
3173
3174 /* Quote escape characters in string s, but no other characters. This is
3175 used to protect CTLESC and CTLNUL in variable values from the rest of
3176 the word expansion process after the variable is expanded (word splitting
3177 and filename generation). If IFS is null, we quote spaces as well, just
3178 in case we split on spaces later (in the case of unquoted $@, we will
3179 eventually attempt to split the entire word on spaces). Corresponding
3180 code exists in dequote_escapes. Even if we don't end up splitting on
3181 spaces, quoting spaces is not a problem. This should never be called on
3182 a string that is quoted with single or double quotes or part of a here
3183 document (effectively double-quoted). */
3184 char *
3185 quote_escapes (string)
3186 char *string;
3187 {
3188 register char *s, *t;
3189 size_t slen;
3190 char *result, *send;
3191 int quote_spaces, skip_ctlesc, skip_ctlnul;
3192 DECLARE_MBSTATE;
3193
3194 slen = strlen (string);
3195 send = string + slen;
3196
3197 quote_spaces = (ifs_value && *ifs_value == 0);
3198
3199 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
3200 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
3201
3202 t = result = (char *)xmalloc ((slen * 2) + 1);
3203 s = string;
3204
3205 while (*s)
3206 {
3207 if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
3208 *t++ = CTLESC;
3209 COPY_CHAR_P (t, s, send);
3210 }
3211 *t = '\0';
3212 return (result);
3213 }
3214
3215 static WORD_LIST *
3216 list_quote_escapes (list)
3217 WORD_LIST *list;
3218 {
3219 register WORD_LIST *w;
3220 char *t;
3221
3222 for (w = list; w; w = w->next)
3223 {
3224 t = w->word->word;
3225 w->word->word = quote_escapes (t);
3226 free (t);
3227 }
3228 return list;
3229 }
3230
3231 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
3232
3233 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
3234 This is necessary to make unquoted CTLESC and CTLNUL characters in the
3235 data stream pass through properly.
3236
3237 We need to remove doubled CTLESC characters inside quoted strings before
3238 quoting the entire string, so we do not double the number of CTLESC
3239 characters.
3240
3241 Also used by parts of the pattern substitution code. */
3242 char *
3243 dequote_escapes (string)
3244 char *string;
3245 {
3246 register char *s, *t, *s1;
3247 size_t slen;
3248 char *result, *send;
3249 int quote_spaces;
3250 DECLARE_MBSTATE;
3251
3252 if (string == 0)
3253 return string;
3254
3255 slen = strlen (string);
3256 send = string + slen;
3257
3258 t = result = (char *)xmalloc (slen + 1);
3259
3260 if (strchr (string, CTLESC) == 0)
3261 return (strcpy (result, string));
3262
3263 quote_spaces = (ifs_value && *ifs_value == 0);
3264
3265 s = string;
3266 while (*s)
3267 {
3268 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
3269 {
3270 s++;
3271 if (*s == '\0')
3272 break;
3273 }
3274 COPY_CHAR_P (t, s, send);
3275 }
3276 *t = '\0';
3277 return result;
3278 }
3279
3280 /* Return a new string with the quoted representation of character C.
3281 This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
3282 set in any resultant WORD_DESC where this value is the word. */
3283 static char *
3284 make_quoted_char (c)
3285 int c;
3286 {
3287 char *temp;
3288
3289 temp = (char *)xmalloc (3);
3290 if (c == 0)
3291 {
3292 temp[0] = CTLNUL;
3293 temp[1] = '\0';
3294 }
3295 else
3296 {
3297 temp[0] = CTLESC;
3298 temp[1] = c;
3299 temp[2] = '\0';
3300 }
3301 return (temp);
3302 }
3303
3304 /* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
3305 the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
3306 this value is the word. */
3307 char *
3308 quote_string (string)
3309 char *string;
3310 {
3311 register char *t;
3312 size_t slen;
3313 char *result, *send;
3314
3315 if (*string == 0)
3316 {
3317 result = (char *)xmalloc (2);
3318 result[0] = CTLNUL;
3319 result[1] = '\0';
3320 }
3321 else
3322 {
3323 DECLARE_MBSTATE;
3324
3325 slen = strlen (string);
3326 send = string + slen;
3327
3328 result = (char *)xmalloc ((slen * 2) + 1);
3329
3330 for (t = result; string < send; )
3331 {
3332 *t++ = CTLESC;
3333 COPY_CHAR_P (t, string, send);
3334 }
3335 *t = '\0';
3336 }
3337 return (result);
3338 }
3339
3340 /* De-quote quoted characters in STRING. */
3341 char *
3342 dequote_string (string)
3343 char *string;
3344 {
3345 register char *s, *t;
3346 size_t slen;
3347 char *result, *send;
3348 DECLARE_MBSTATE;
3349
3350 slen = strlen (string);
3351
3352 t = result = (char *)xmalloc (slen + 1);
3353
3354 if (QUOTED_NULL (string))
3355 {
3356 result[0] = '\0';
3357 return (result);
3358 }
3359
3360 /* If no character in the string can be quoted, don't bother examining
3361 each character. Just return a copy of the string passed to us. */
3362 if (strchr (string, CTLESC) == NULL)
3363 return (strcpy (result, string));
3364
3365 send = string + slen;
3366 s = string;
3367 while (*s)
3368 {
3369 if (*s == CTLESC)
3370 {
3371 s++;
3372 if (*s == '\0')
3373 break;
3374 }
3375 COPY_CHAR_P (t, s, send);
3376 }
3377
3378 *t = '\0';
3379 return (result);
3380 }
3381
3382 /* Quote the entire WORD_LIST list. */
3383 static WORD_LIST *
3384 quote_list (list)
3385 WORD_LIST *list;
3386 {
3387 register WORD_LIST *w;
3388 char *t;
3389
3390 for (w = list; w; w = w->next)
3391 {
3392 t = w->word->word;
3393 w->word->word = quote_string (t);
3394 if (*t == 0)
3395 w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
3396 w->word->flags |= W_QUOTED;
3397 free (t);
3398 }
3399 return list;
3400 }
3401
3402 /* De-quote quoted characters in each word in LIST. */
3403 WORD_LIST *
3404 dequote_list (list)
3405 WORD_LIST *list;
3406 {
3407 register char *s;
3408 register WORD_LIST *tlist;
3409
3410 for (tlist = list; tlist; tlist = tlist->next)
3411 {
3412 s = dequote_string (tlist->word->word);
3413 if (QUOTED_NULL (tlist->word->word))
3414 tlist->word->flags &= ~W_HASQUOTEDNULL;
3415 free (tlist->word->word);
3416 tlist->word->word = s;
3417 }
3418 return list;
3419 }
3420
3421 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3422 string. */
3423 char *
3424 remove_quoted_escapes (string)
3425 char *string;
3426 {
3427 char *t;
3428
3429 if (string)
3430 {
3431 t = dequote_escapes (string);
3432 strcpy (string, t);
3433 free (t);
3434 }
3435
3436 return (string);
3437 }
3438
3439 /* Perform quoted null character removal on STRING. We don't allow any
3440 quoted null characters in the middle or at the ends of strings because
3441 of how expand_word_internal works. remove_quoted_nulls () turns
3442 STRING into an empty string iff it only consists of a quoted null,
3443 and removes all unquoted CTLNUL characters. */
3444 char *
3445 remove_quoted_nulls (string)
3446 char *string;
3447 {
3448 register size_t slen;
3449 register int i, j, prev_i;
3450 DECLARE_MBSTATE;
3451
3452 if (strchr (string, CTLNUL) == 0) /* XXX */
3453 return string; /* XXX */
3454
3455 slen = strlen (string);
3456 i = j = 0;
3457
3458 while (i < slen)
3459 {
3460 if (string[i] == CTLESC)
3461 {
3462 /* Old code had j++, but we cannot assume that i == j at this
3463 point -- what if a CTLNUL has already been removed from the
3464 string? We don't want to drop the CTLESC or recopy characters
3465 that we've already copied down. */
3466 i++; string[j++] = CTLESC;
3467 if (i == slen)
3468 break;
3469 }
3470 else if (string[i] == CTLNUL)
3471 i++;
3472
3473 prev_i = i;
3474 ADVANCE_CHAR (string, slen, i);
3475 if (j < prev_i)
3476 {
3477 do string[j++] = string[prev_i++]; while (prev_i < i);
3478 }
3479 else
3480 j = i;
3481 }
3482 string[j] = '\0';
3483
3484 return (string);
3485 }
3486
3487 /* Perform quoted null character removal on each element of LIST.
3488 This modifies LIST. */
3489 void
3490 word_list_remove_quoted_nulls (list)
3491 WORD_LIST *list;
3492 {
3493 register WORD_LIST *t;
3494
3495 for (t = list; t; t = t->next)
3496 {
3497 remove_quoted_nulls (t->word->word);
3498 t->word->flags &= ~W_HASQUOTEDNULL;
3499 }
3500 }
3501
3502 /* **************************************************************** */
3503 /* */
3504 /* Functions for Matching and Removing Patterns */
3505 /* */
3506 /* **************************************************************** */
3507
3508 #if defined (HANDLE_MULTIBYTE)
3509 #if 0 /* Currently unused */
3510 static unsigned char *
3511 mb_getcharlens (string, len)
3512 char *string;
3513 int len;
3514 {
3515 int i, offset, last;
3516 unsigned char *ret;
3517 char *p;
3518 DECLARE_MBSTATE;
3519
3520 i = offset = 0;
3521 last = 0;
3522 ret = (unsigned char *)xmalloc (len);
3523 memset (ret, 0, len);
3524 while (string[last])
3525 {
3526 ADVANCE_CHAR (string, len, offset);
3527 ret[last] = offset - last;
3528 last = offset;
3529 }
3530 return ret;
3531 }
3532 #endif
3533 #endif
3534
3535 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3536 can have one of 4 values:
3537 RP_LONG_LEFT remove longest matching portion at start of PARAM
3538 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3539 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3540 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3541 */
3542
3543 #define RP_LONG_LEFT 1
3544 #define RP_SHORT_LEFT 2
3545 #define RP_LONG_RIGHT 3
3546 #define RP_SHORT_RIGHT 4
3547
3548 static char *
3549 remove_upattern (param, pattern, op)
3550 char *param, *pattern;
3551 int op;
3552 {
3553 register int len;
3554 register char *end;
3555 register char *p, *ret, c;
3556
3557 len = STRLEN (param);
3558 end = param + len;
3559
3560 switch (op)
3561 {
3562 case RP_LONG_LEFT: /* remove longest match at start */
3563 for (p = end; p >= param; p--)
3564 {
3565 c = *p; *p = '\0';
3566 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3567 {
3568 *p = c;
3569 return (savestring (p));
3570 }
3571 *p = c;
3572
3573 }
3574 break;
3575
3576 case RP_SHORT_LEFT: /* remove shortest match at start */
3577 for (p = param; p <= end; p++)
3578 {
3579 c = *p; *p = '\0';
3580 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3581 {
3582 *p = c;
3583 return (savestring (p));
3584 }
3585 *p = c;
3586 }
3587 break;
3588
3589 case RP_LONG_RIGHT: /* remove longest match at end */
3590 for (p = param; p <= end; p++)
3591 {
3592 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3593 {
3594 c = *p; *p = '\0';
3595 ret = savestring (param);
3596 *p = c;
3597 return (ret);
3598 }
3599 }
3600 break;
3601
3602 case RP_SHORT_RIGHT: /* remove shortest match at end */
3603 for (p = end; p >= param; p--)
3604 {
3605 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3606 {
3607 c = *p; *p = '\0';
3608 ret = savestring (param);
3609 *p = c;
3610 return (ret);
3611 }
3612 }
3613 break;
3614 }
3615
3616 return (savestring (param)); /* no match, return original string */
3617 }
3618
3619 #if defined (HANDLE_MULTIBYTE)
3620 static wchar_t *
3621 remove_wpattern (wparam, wstrlen, wpattern, op)
3622 wchar_t *wparam;
3623 size_t wstrlen;
3624 wchar_t *wpattern;
3625 int op;
3626 {
3627 wchar_t wc, *ret;
3628 int n;
3629
3630 switch (op)
3631 {
3632 case RP_LONG_LEFT: /* remove longest match at start */
3633 for (n = wstrlen; n >= 0; n--)
3634 {
3635 wc = wparam[n]; wparam[n] = L'\0';
3636 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3637 {
3638 wparam[n] = wc;
3639 return (wcsdup (wparam + n));
3640 }
3641 wparam[n] = wc;
3642 }
3643 break;
3644
3645 case RP_SHORT_LEFT: /* remove shortest match at start */
3646 for (n = 0; n <= wstrlen; n++)
3647 {
3648 wc = wparam[n]; wparam[n] = L'\0';
3649 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3650 {
3651 wparam[n] = wc;
3652 return (wcsdup (wparam + n));
3653 }
3654 wparam[n] = wc;
3655 }
3656 break;
3657
3658 case RP_LONG_RIGHT: /* remove longest match at end */
3659 for (n = 0; n <= wstrlen; n++)
3660 {
3661 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3662 {
3663 wc = wparam[n]; wparam[n] = L'\0';
3664 ret = wcsdup (wparam);
3665 wparam[n] = wc;
3666 return (ret);
3667 }
3668 }
3669 break;
3670
3671 case RP_SHORT_RIGHT: /* remove shortest match at end */
3672 for (n = wstrlen; n >= 0; n--)
3673 {
3674 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3675 {
3676 wc = wparam[n]; wparam[n] = L'\0';
3677 ret = wcsdup (wparam);
3678 wparam[n] = wc;
3679 return (ret);
3680 }
3681 }
3682 break;
3683 }
3684
3685 return (wcsdup (wparam)); /* no match, return original string */
3686 }
3687 #endif /* HANDLE_MULTIBYTE */
3688
3689 static char *
3690 remove_pattern (param, pattern, op)
3691 char *param, *pattern;
3692 int op;
3693 {
3694 if (param == NULL)
3695 return (param);
3696 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3697 return (savestring (param));
3698
3699 #if defined (HANDLE_MULTIBYTE)
3700 if (MB_CUR_MAX > 1)
3701 {
3702 wchar_t *ret, *oret;
3703 size_t n;
3704 wchar_t *wparam, *wpattern;
3705 mbstate_t ps;
3706 char *xret;
3707
3708 n = xdupmbstowcs (&wpattern, NULL, pattern);
3709 if (n == (size_t)-1)
3710 return (remove_upattern (param, pattern, op));
3711 n = xdupmbstowcs (&wparam, NULL, param);
3712 if (n == (size_t)-1)
3713 {
3714 free (wpattern);
3715 return (remove_upattern (param, pattern, op));
3716 }
3717 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3718
3719 free (wparam);
3720 free (wpattern);
3721
3722 n = strlen (param);
3723 xret = (char *)xmalloc (n + 1);
3724 memset (&ps, '\0', sizeof (mbstate_t));
3725 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3726 xret[n] = '\0'; /* just to make sure */
3727 free (oret);
3728 return xret;
3729 }
3730 else
3731 #endif
3732 return (remove_upattern (param, pattern, op));
3733 }
3734
3735 /* Return 1 of the first character of STRING could match the first
3736 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
3737 static int
3738 match_pattern_char (pat, string)
3739 char *pat, *string;
3740 {
3741 char c;
3742
3743 if (*string == 0)
3744 return (0);
3745
3746 switch (c = *pat++)
3747 {
3748 default:
3749 return (*string == c);
3750 case '\\':
3751 return (*string == *pat);
3752 case '?':
3753 return (*pat == LPAREN ? 1 : (*string != '\0'));
3754 case '*':
3755 return (1);
3756 case '+':
3757 case '!':
3758 case '@':
3759 return (*pat == LPAREN ? 1 : (*string == c));
3760 case '[':
3761 return (*string != '\0');
3762 }
3763 }
3764
3765 /* Match PAT anywhere in STRING and return the match boundaries.
3766 This returns 1 in case of a successful match, 0 otherwise. SP
3767 and EP are pointers into the string where the match begins and
3768 ends, respectively. MTYPE controls what kind of match is attempted.
3769 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3770 of the string, respectively. The longest match is returned. */
3771 static int
3772 match_upattern (string, pat, mtype, sp, ep)
3773 char *string, *pat;
3774 int mtype;
3775 char **sp, **ep;
3776 {
3777 int c, len;
3778 register char *p, *p1, *npat;
3779 char *end;
3780
3781 /* If the pattern doesn't match anywhere in the string, go ahead and
3782 short-circuit right away. A minor optimization, saves a bunch of
3783 unnecessary calls to strmatch (up to N calls for a string of N
3784 characters) if the match is unsuccessful. To preserve the semantics
3785 of the substring matches below, we make sure that the pattern has
3786 `*' as first and last character, making a new pattern if necessary. */
3787 /* XXX - check this later if I ever implement `**' with special meaning,
3788 since this will potentially result in `**' at the beginning or end */
3789 len = STRLEN (pat);
3790 if (pat[0] != '*' || (pat[0] == '*' && pat[1] == '(' && extended_glob) || pat[len - 1] != '*') /*)*/
3791 {
3792 p = npat = (char *)xmalloc (len + 3);
3793 p1 = pat;
3794 if (*p1 != '*' || (*p1 == '*' && p1[1] == '(' && extended_glob)) /*)*/
3795 *p++ = '*';
3796 while (*p1)
3797 *p++ = *p1++;
3798 if (p1[-1] != '*' || p[-2] == '\\')
3799 *p++ = '*';
3800 *p = '\0';
3801 }
3802 else
3803 npat = pat;
3804 c = strmatch (npat, string, FNMATCH_EXTFLAG);
3805 if (npat != pat)
3806 free (npat);
3807 if (c == FNM_NOMATCH)
3808 return (0);
3809
3810 len = STRLEN (string);
3811 end = string + len;
3812
3813 switch (mtype)
3814 {
3815 case MATCH_ANY:
3816 for (p = string; p <= end; p++)
3817 {
3818 if (match_pattern_char (pat, p))
3819 {
3820 for (p1 = end; p1 >= p; p1--)
3821 {
3822 c = *p1; *p1 = '\0';
3823 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3824 {
3825 *p1 = c;
3826 *sp = p;
3827 *ep = p1;
3828 return 1;
3829 }
3830 *p1 = c;
3831 }
3832 }
3833 }
3834
3835 return (0);
3836
3837 case MATCH_BEG:
3838 if (match_pattern_char (pat, string) == 0)
3839 return (0);
3840
3841 for (p = end; p >= string; p--)
3842 {
3843 c = *p; *p = '\0';
3844 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3845 {
3846 *p = c;
3847 *sp = string;
3848 *ep = p;
3849 return 1;
3850 }
3851 *p = c;
3852 }
3853
3854 return (0);
3855
3856 case MATCH_END:
3857 for (p = string; p <= end; p++)
3858 {
3859 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3860 {
3861 *sp = p;
3862 *ep = end;
3863 return 1;
3864 }
3865
3866 }
3867
3868 return (0);
3869 }
3870
3871 return (0);
3872 }
3873
3874 #if defined (HANDLE_MULTIBYTE)
3875 /* Return 1 of the first character of WSTRING could match the first
3876 character of pattern WPAT. Wide character version. */
3877 static int
3878 match_pattern_wchar (wpat, wstring)
3879 wchar_t *wpat, *wstring;
3880 {
3881 wchar_t wc;
3882
3883 if (*wstring == 0)
3884 return (0);
3885
3886 switch (wc = *wpat++)
3887 {
3888 default:
3889 return (*wstring == wc);
3890 case L'\\':
3891 return (*wstring == *wpat);
3892 case L'?':
3893 return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3894 case L'*':
3895 return (1);
3896 case L'+':
3897 case L'!':
3898 case L'@':
3899 return (*wpat == LPAREN ? 1 : (*wstring == wc));
3900 case L'[':
3901 return (*wstring != L'\0');
3902 }
3903 }
3904
3905 /* Match WPAT anywhere in WSTRING and return the match boundaries.
3906 This returns 1 in case of a successful match, 0 otherwise. Wide
3907 character version. */
3908 static int
3909 match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3910 wchar_t *wstring;
3911 char **indices;
3912 size_t wstrlen;
3913 wchar_t *wpat;
3914 int mtype;
3915 char **sp, **ep;
3916 {
3917 wchar_t wc, *wp, *nwpat, *wp1;
3918 int len;
3919 #if 0
3920 size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3921 #else
3922 int n, n1;
3923 #endif
3924
3925 /* If the pattern doesn't match anywhere in the string, go ahead and
3926 short-circuit right away. A minor optimization, saves a bunch of
3927 unnecessary calls to strmatch (up to N calls for a string of N
3928 characters) if the match is unsuccessful. To preserve the semantics
3929 of the substring matches below, we make sure that the pattern has
3930 `*' as first and last character, making a new pattern if necessary. */
3931 /* XXX - check this later if I ever implement `**' with special meaning,
3932 since this will potentially result in `**' at the beginning or end */
3933 len = wcslen (wpat);
3934 if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == L'(' && extended_glob) || wpat[len - 1] != L'*') /*)*/
3935 {
3936 wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
3937 wp1 = wpat;
3938 if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == '(' && extended_glob)) /*)*/
3939 *wp++ = L'*';
3940 while (*wp1 != L'\0')
3941 *wp++ = *wp1++;
3942 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3943 *wp++ = L'*';
3944 *wp = '\0';
3945 }
3946 else
3947 nwpat = wpat;
3948 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3949 if (nwpat != wpat)
3950 free (nwpat);
3951 if (len == FNM_NOMATCH)
3952 return (0);
3953
3954 switch (mtype)
3955 {
3956 case MATCH_ANY:
3957 for (n = 0; n <= wstrlen; n++)
3958 {
3959 if (match_pattern_wchar (wpat, wstring + n))
3960 {
3961 for (n1 = wstrlen; n1 >= n; n1--)
3962 {
3963 wc = wstring[n1]; wstring[n1] = L'\0';
3964 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3965 {
3966 wstring[n1] = wc;
3967 *sp = indices[n];
3968 *ep = indices[n1];
3969 return 1;
3970 }
3971 wstring[n1] = wc;
3972 }
3973 }
3974 }
3975
3976 return (0);
3977
3978 case MATCH_BEG:
3979 if (match_pattern_wchar (wpat, wstring) == 0)
3980 return (0);
3981
3982 for (n = wstrlen; n >= 0; n--)
3983 {
3984 wc = wstring[n]; wstring[n] = L'\0';
3985 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3986 {
3987 wstring[n] = wc;
3988 *sp = indices[0];
3989 *ep = indices[n];
3990 return 1;
3991 }
3992 wstring[n] = wc;
3993 }
3994
3995 return (0);
3996
3997 case MATCH_END:
3998 for (n = 0; n <= wstrlen; n++)
3999 {
4000 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
4001 {
4002 *sp = indices[n];
4003 *ep = indices[wstrlen];
4004 return 1;
4005 }
4006 }
4007
4008 return (0);
4009 }
4010
4011 return (0);
4012 }
4013 #endif /* HANDLE_MULTIBYTE */
4014
4015 static int
4016 match_pattern (string, pat, mtype, sp, ep)
4017 char *string, *pat;
4018 int mtype;
4019 char **sp, **ep;
4020 {
4021 #if defined (HANDLE_MULTIBYTE)
4022 int ret;
4023 size_t n;
4024 wchar_t *wstring, *wpat;
4025 char **indices;
4026 #endif
4027
4028 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
4029 return (0);
4030
4031 #if defined (HANDLE_MULTIBYTE)
4032 if (MB_CUR_MAX > 1)
4033 {
4034 n = xdupmbstowcs (&wpat, NULL, pat);
4035 if (n == (size_t)-1)
4036 return (match_upattern (string, pat, mtype, sp, ep));
4037 n = xdupmbstowcs (&wstring, &indices, string);
4038 if (n == (size_t)-1)
4039 {
4040 free (wpat);
4041 return (match_upattern (string, pat, mtype, sp, ep));
4042 }
4043 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
4044
4045 free (wpat);
4046 free (wstring);
4047 free (indices);
4048
4049 return (ret);
4050 }
4051 else
4052 #endif
4053 return (match_upattern (string, pat, mtype, sp, ep));
4054 }
4055
4056 static int
4057 getpatspec (c, value)
4058 int c;
4059 char *value;
4060 {
4061 if (c == '#')
4062 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
4063 else /* c == '%' */
4064 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
4065 }
4066
4067 /* Posix.2 says that the WORD should be run through tilde expansion,
4068 parameter expansion, command substitution and arithmetic expansion.
4069 This leaves the result quoted, so quote_string_for_globbing () has
4070 to be called to fix it up for strmatch (). If QUOTED is non-zero,
4071 it means that the entire expression was enclosed in double quotes.
4072 This means that quoting characters in the pattern do not make any
4073 special pattern characters quoted. For example, the `*' in the
4074 following retains its special meaning: "${foo#'*'}". */
4075 static char *
4076 getpattern (value, quoted, expandpat)
4077 char *value;
4078 int quoted, expandpat;
4079 {
4080 char *pat, *tword;
4081 WORD_LIST *l;
4082 #if 0
4083 int i;
4084 #endif
4085 /* There is a problem here: how to handle single or double quotes in the
4086 pattern string when the whole expression is between double quotes?
4087 POSIX.2 says that enclosing double quotes do not cause the pattern to
4088 be quoted, but does that leave us a problem with @ and array[@] and their
4089 expansions inside a pattern? */
4090 #if 0
4091 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
4092 {
4093 i = 0;
4094 pat = string_extract_double_quoted (tword, &i, 1);
4095 free (tword);
4096 tword = pat;
4097 }
4098 #endif
4099
4100 /* expand_string_for_rhs () leaves WORD quoted and does not perform
4101 word splitting. */
4102 l = *value ? expand_string_for_rhs (value,
4103 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
4104 (int *)NULL, (int *)NULL)
4105 : (WORD_LIST *)0;
4106 pat = string_list (l);
4107 dispose_words (l);
4108 if (pat)
4109 {
4110 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
4111 free (pat);
4112 pat = tword;
4113 }
4114 return (pat);
4115 }
4116
4117 #if 0
4118 /* Handle removing a pattern from a string as a result of ${name%[%]value}
4119 or ${name#[#]value}. */
4120 static char *
4121 variable_remove_pattern (value, pattern, patspec, quoted)
4122 char *value, *pattern;
4123 int patspec, quoted;
4124 {
4125 char *tword;
4126
4127 tword = remove_pattern (value, pattern, patspec);
4128
4129 return (tword);
4130 }
4131 #endif
4132
4133 static char *
4134 list_remove_pattern (list, pattern, patspec, itype, quoted)
4135 WORD_LIST *list;
4136 char *pattern;
4137 int patspec, itype, quoted;
4138 {
4139 WORD_LIST *new, *l;
4140 WORD_DESC *w;
4141 char *tword;
4142
4143 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
4144 {
4145 tword = remove_pattern (l->word->word, pattern, patspec);
4146 w = alloc_word_desc ();
4147 w->word = tword ? tword : savestring ("");
4148 new = make_word_list (w, new);
4149 }
4150
4151 l = REVERSE_LIST (new, WORD_LIST *);
4152 tword = string_list_pos_params (itype, l, quoted);
4153 dispose_words (l);
4154
4155 return (tword);
4156 }
4157
4158 static char *
4159 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
4160 int itype;
4161 char *pattern;
4162 int patspec, quoted;
4163 {
4164 char *ret;
4165 WORD_LIST *list;
4166
4167 list = list_rest_of_args ();
4168 if (list == 0)
4169 return ((char *)NULL);
4170 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4171 dispose_words (list);
4172 return (ret);
4173 }
4174
4175 #if defined (ARRAY_VARS)
4176 static char *
4177 array_remove_pattern (var, pattern, patspec, varname, quoted)
4178 SHELL_VAR *var;
4179 char *pattern;
4180 int patspec;
4181 char *varname; /* so we can figure out how it's indexed */
4182 int quoted;
4183 {
4184 ARRAY *a;
4185 HASH_TABLE *h;
4186 int itype;
4187 char *ret;
4188 WORD_LIST *list;
4189 SHELL_VAR *v;
4190
4191 /* compute itype from varname here */
4192 v = array_variable_part (varname, &ret, 0);
4193 itype = ret[0];
4194
4195 a = (v && array_p (v)) ? array_cell (v) : 0;
4196 h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
4197
4198 list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
4199 if (list == 0)
4200 return ((char *)NULL);
4201 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
4202 dispose_words (list);
4203
4204 return ret;
4205 }
4206 #endif /* ARRAY_VARS */
4207
4208 static char *
4209 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
4210 char *varname, *value, *patstr;
4211 int rtype, quoted;
4212 {
4213 int vtype, patspec, starsub;
4214 char *temp1, *val, *pattern;
4215 SHELL_VAR *v;
4216
4217 if (value == 0)
4218 return ((char *)NULL);
4219
4220 this_command_name = varname;
4221
4222 vtype = get_var_and_type (varname, value, quoted, &v, &val);
4223 if (vtype == -1)
4224 return ((char *)NULL);
4225
4226 starsub = vtype & VT_STARSUB;
4227 vtype &= ~VT_STARSUB;
4228
4229 patspec = getpatspec (rtype, patstr);
4230 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
4231 patstr++;
4232
4233 /* Need to pass getpattern newly-allocated memory in case of expansion --
4234 the expansion code will free the passed string on an error. */
4235 temp1 = savestring (patstr);
4236 pattern = getpattern (temp1, quoted, 1);
4237 free (temp1);
4238
4239 temp1 = (char *)NULL; /* shut up gcc */
4240 switch (vtype)
4241 {
4242 case VT_VARIABLE:
4243 case VT_ARRAYMEMBER:
4244 temp1 = remove_pattern (val, pattern, patspec);
4245 if (vtype == VT_VARIABLE)
4246 FREE (val);
4247 if (temp1)
4248 {
4249 val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4250 ? quote_string (temp1)
4251 : quote_escapes (temp1);
4252 free (temp1);
4253 temp1 = val;
4254 }
4255 break;
4256 #if defined (ARRAY_VARS)
4257 case VT_ARRAYVAR:
4258 temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted);
4259 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4260 {
4261 val = quote_escapes (temp1);
4262 free (temp1);
4263 temp1 = val;
4264 }
4265 break;
4266 #endif
4267 case VT_POSPARMS:
4268 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
4269 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
4270 {
4271 val = quote_escapes (temp1);
4272 free (temp1);
4273 temp1 = val;
4274 }
4275 break;
4276 }
4277
4278 FREE (pattern);
4279 return temp1;
4280 }
4281
4282 /*******************************************
4283 * *
4284 * Functions to expand WORD_DESCs *
4285 * *
4286 *******************************************/
4287
4288 /* Expand WORD, performing word splitting on the result. This does
4289 parameter expansion, command substitution, arithmetic expansion,
4290 word splitting, and quote removal. */
4291
4292 WORD_LIST *
4293 expand_word (word, quoted)
4294 WORD_DESC *word;
4295 int quoted;
4296 {
4297 WORD_LIST *result, *tresult;
4298
4299 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4300 result = word_list_split (tresult);
4301 dispose_words (tresult);
4302 return (result ? dequote_list (result) : result);
4303 }
4304
4305 /* Expand WORD, but do not perform word splitting on the result. This
4306 does parameter expansion, command substitution, arithmetic expansion,
4307 and quote removal. */
4308 WORD_LIST *
4309 expand_word_unsplit (word, quoted)
4310 WORD_DESC *word;
4311 int quoted;
4312 {
4313 WORD_LIST *result;
4314
4315 expand_no_split_dollar_star = 1;
4316 #if defined (HANDLE_MULTIBYTE)
4317 if (ifs_firstc[0] == 0)
4318 #else
4319 if (ifs_firstc == 0)
4320 #endif
4321 word->flags |= W_NOSPLIT;
4322 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4323 expand_no_split_dollar_star = 0;
4324
4325 return (result ? dequote_list (result) : result);
4326 }
4327
4328 /* Perform shell expansions on WORD, but do not perform word splitting or
4329 quote removal on the result. Virtually identical to expand_word_unsplit;
4330 could be combined if implementations don't diverge. */
4331 WORD_LIST *
4332 expand_word_leave_quoted (word, quoted)
4333 WORD_DESC *word;
4334 int quoted;
4335 {
4336 WORD_LIST *result;
4337
4338 expand_no_split_dollar_star = 1;
4339 #if defined (HANDLE_MULTIBYTE)
4340 if (ifs_firstc[0] == 0)
4341 #else
4342 if (ifs_firstc == 0)
4343 #endif
4344 word->flags |= W_NOSPLIT;
4345 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
4346 expand_no_split_dollar_star = 0;
4347
4348 return result;
4349 }
4350
4351 #if defined (PROCESS_SUBSTITUTION)
4352
4353 /*****************************************************************/
4354 /* */
4355 /* Hacking Process Substitution */
4356 /* */
4357 /*****************************************************************/
4358
4359 #if !defined (HAVE_DEV_FD)
4360 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
4361 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4362 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4363 list. NFIFO is a count of the number of FIFOs in the list. */
4364 #define FIFO_INCR 20
4365
4366 struct temp_fifo {
4367 char *file;
4368 pid_t proc;
4369 };
4370
4371 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4372 static int nfifo;
4373 static int fifo_list_size;
4374
4375 static void
4376 add_fifo_list (pathname)
4377 char *pathname;
4378 {
4379 if (nfifo >= fifo_list_size - 1)
4380 {
4381 fifo_list_size += FIFO_INCR;
4382 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4383 fifo_list_size * sizeof (struct temp_fifo));
4384 }
4385
4386 fifo_list[nfifo].file = savestring (pathname);
4387 nfifo++;
4388 }
4389
4390 void
4391 unlink_fifo_list ()
4392 {
4393 int saved, i, j;
4394
4395 if (nfifo == 0)
4396 return;
4397
4398 for (i = saved = 0; i < nfifo; i++)
4399 {
4400 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4401 {
4402 unlink (fifo_list[i].file);
4403 free (fifo_list[i].file);
4404 fifo_list[i].file = (char *)NULL;
4405 fifo_list[i].proc = -1;
4406 }
4407 else
4408 saved++;
4409 }
4410
4411 /* If we didn't remove some of the FIFOs, compact the list. */
4412 if (saved)
4413 {
4414 for (i = j = 0; i < nfifo; i++)
4415 if (fifo_list[i].file)
4416 {
4417 fifo_list[j].file = fifo_list[i].file;
4418 fifo_list[j].proc = fifo_list[i].proc;
4419 j++;
4420 }
4421 nfifo = j;
4422 }
4423 else
4424 nfifo = 0;
4425 }
4426
4427 int
4428 fifos_pending ()
4429 {
4430 return nfifo;
4431 }
4432
4433 static char *
4434 make_named_pipe ()
4435 {
4436 char *tname;
4437
4438 tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
4439 if (mkfifo (tname, 0600) < 0)
4440 {
4441 free (tname);
4442 return ((char *)NULL);
4443 }
4444
4445 add_fifo_list (tname);
4446 return (tname);
4447 }
4448
4449 #else /* HAVE_DEV_FD */
4450
4451 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4452 has open to children. NFDS is a count of the number of bits currently
4453 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4454 of open files. */
4455 static char *dev_fd_list = (char *)NULL;
4456 static int nfds;
4457 static int totfds; /* The highest possible number of open files. */
4458
4459 static void
4460 add_fifo_list (fd)
4461 int fd;
4462 {
4463 if (!dev_fd_list || fd >= totfds)
4464 {
4465 int ofds;
4466
4467 ofds = totfds;
4468 totfds = getdtablesize ();
4469 if (totfds < 0 || totfds > 256)
4470 totfds = 256;
4471 if (fd >= totfds)
4472 totfds = fd + 2;
4473
4474 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4475 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4476 }
4477
4478 dev_fd_list[fd] = 1;
4479 nfds++;
4480 }
4481
4482 int
4483 fifos_pending ()
4484 {
4485 return 0; /* used for cleanup; not needed with /dev/fd */
4486 }
4487
4488 void
4489 unlink_fifo_list ()
4490 {
4491 register int i;
4492
4493 if (nfds == 0)
4494 return;
4495
4496 for (i = 0; nfds && i < totfds; i++)
4497 if (dev_fd_list[i])
4498 {
4499 close (i);
4500 dev_fd_list[i] = 0;
4501 nfds--;
4502 }
4503
4504 nfds = 0;
4505 }
4506
4507 #if defined (NOTDEF)
4508 print_dev_fd_list ()
4509 {
4510 register int i;
4511
4512 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4513 fflush (stderr);
4514
4515 for (i = 0; i < totfds; i++)
4516 {
4517 if (dev_fd_list[i])
4518 fprintf (stderr, " %d", i);
4519 }
4520 fprintf (stderr, "\n");
4521 }
4522 #endif /* NOTDEF */
4523
4524 static char *
4525 make_dev_fd_filename (fd)
4526 int fd;
4527 {
4528 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4529
4530 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8);
4531
4532 strcpy (ret, DEV_FD_PREFIX);
4533 p = inttostr (fd, intbuf, sizeof (intbuf));
4534 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4535
4536 add_fifo_list (fd);
4537 return (ret);
4538 }
4539
4540 #endif /* HAVE_DEV_FD */
4541
4542 /* Return a filename that will open a connection to the process defined by
4543 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4544 a filename in /dev/fd corresponding to a descriptor that is one of the
4545 ends of the pipe. If not defined, we use named pipes on systems that have
4546 them. Systems without /dev/fd and named pipes are out of luck.
4547
4548 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4549 use the read end of the pipe and dup that file descriptor to fd 0 in
4550 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4551 writing or use the write end of the pipe in the child, and dup that
4552 file descriptor to fd 1 in the child. The parent does the opposite. */
4553
4554 static char *
4555 process_substitute (string, open_for_read_in_child)
4556 char *string;
4557 int open_for_read_in_child;
4558 {
4559 char *pathname;
4560 int fd, result;
4561 pid_t old_pid, pid;
4562 #if defined (HAVE_DEV_FD)
4563 int parent_pipe_fd, child_pipe_fd;
4564 int fildes[2];
4565 #endif /* HAVE_DEV_FD */
4566 #if defined (JOB_CONTROL)
4567 pid_t old_pipeline_pgrp;
4568 #endif
4569
4570 if (!string || !*string || wordexp_only)
4571 return ((char *)NULL);
4572
4573 #if !defined (HAVE_DEV_FD)
4574 pathname = make_named_pipe ();
4575 #else /* HAVE_DEV_FD */
4576 if (pipe (fildes) < 0)
4577 {
4578 sys_error (_("cannot make pipe for process substitution"));
4579 return ((char *)NULL);
4580 }
4581 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4582 the pipe in the parent, otherwise the read end. */
4583 parent_pipe_fd = fildes[open_for_read_in_child];
4584 child_pipe_fd = fildes[1 - open_for_read_in_child];
4585 /* Move the parent end of the pipe to some high file descriptor, to
4586 avoid clashes with FDs used by the script. */
4587 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4588
4589 pathname = make_dev_fd_filename (parent_pipe_fd);
4590 #endif /* HAVE_DEV_FD */
4591
4592 if (pathname == 0)
4593 {
4594 sys_error (_("cannot make pipe for process substitution"));
4595 return ((char *)NULL);
4596 }
4597
4598 old_pid = last_made_pid;
4599
4600 #if defined (JOB_CONTROL)
4601 old_pipeline_pgrp = pipeline_pgrp;
4602 pipeline_pgrp = shell_pgrp;
4603 save_pipeline (1);
4604 #endif /* JOB_CONTROL */
4605
4606 pid = make_child ((char *)NULL, 1);
4607 if (pid == 0)
4608 {
4609 reset_terminating_signals (); /* XXX */
4610 free_pushed_string_input ();
4611 /* Cancel traps, in trap.c. */
4612 restore_original_signals ();
4613 setup_async_signals ();
4614 subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
4615 }
4616
4617 #if defined (JOB_CONTROL)
4618 set_sigchld_handler ();
4619 stop_making_children ();
4620 /* XXX - should we only do this in the parent? (as in command subst) */
4621 pipeline_pgrp = old_pipeline_pgrp;
4622 #endif /* JOB_CONTROL */
4623
4624 if (pid < 0)
4625 {
4626 sys_error (_("cannot make child for process substitution"));
4627 free (pathname);
4628 #if defined (HAVE_DEV_FD)
4629 close (parent_pipe_fd);
4630 close (child_pipe_fd);
4631 #endif /* HAVE_DEV_FD */
4632 return ((char *)NULL);
4633 }
4634
4635 if (pid > 0)
4636 {
4637 #if defined (JOB_CONTROL)
4638 restore_pipeline (1);
4639 #endif
4640
4641 #if !defined (HAVE_DEV_FD)
4642 fifo_list[nfifo-1].proc = pid;
4643 #endif
4644
4645 last_made_pid = old_pid;
4646
4647 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4648 close_pgrp_pipe ();
4649 #endif /* JOB_CONTROL && PGRP_PIPE */
4650
4651 #if defined (HAVE_DEV_FD)
4652 close (child_pipe_fd);
4653 #endif /* HAVE_DEV_FD */
4654
4655 return (pathname);
4656 }
4657
4658 set_sigint_handler ();
4659
4660 #if defined (JOB_CONTROL)
4661 set_job_control (0);
4662 #endif /* JOB_CONTROL */
4663
4664 #if !defined (HAVE_DEV_FD)
4665 /* Open the named pipe in the child. */
4666 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4667 if (fd < 0)
4668 {
4669 /* Two separate strings for ease of translation. */
4670 if (open_for_read_in_child)
4671 sys_error (_("cannot open named pipe %s for reading"), pathname);
4672 else
4673 sys_error (_("cannot open named pipe %s for writing"), pathname);
4674
4675 exit (127);
4676 }
4677 if (open_for_read_in_child)
4678 {
4679 if (sh_unset_nodelay_mode (fd) < 0)
4680 {
4681 sys_error (_("cannot reset nodelay mode for fd %d"), fd);
4682 exit (127);
4683 }
4684 }
4685 #else /* HAVE_DEV_FD */
4686 fd = child_pipe_fd;
4687 #endif /* HAVE_DEV_FD */
4688
4689 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4690 {
4691 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4692 open_for_read_in_child ? 0 : 1);
4693 exit (127);
4694 }
4695
4696 if (fd != (open_for_read_in_child ? 0 : 1))
4697 close (fd);
4698
4699 /* Need to close any files that this process has open to pipes inherited
4700 from its parent. */
4701 if (current_fds_to_close)
4702 {
4703 close_fd_bitmap (current_fds_to_close);
4704 current_fds_to_close = (struct fd_bitmap *)NULL;
4705 }
4706
4707 #if defined (HAVE_DEV_FD)
4708 /* Make sure we close the parent's end of the pipe and clear the slot
4709 in the fd list so it is not closed later, if reallocated by, for
4710 instance, pipe(2). */
4711 close (parent_pipe_fd);
4712 dev_fd_list[parent_pipe_fd] = 0;
4713 #endif /* HAVE_DEV_FD */
4714
4715 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4716
4717 #if !defined (HAVE_DEV_FD)
4718 /* Make sure we close the named pipe in the child before we exit. */
4719 close (open_for_read_in_child ? 0 : 1);
4720 #endif /* !HAVE_DEV_FD */
4721
4722 exit (result);
4723 /*NOTREACHED*/
4724 }
4725 #endif /* PROCESS_SUBSTITUTION */
4726
4727 /***********************************/
4728 /* */
4729 /* Command Substitution */
4730 /* */
4731 /***********************************/
4732
4733 static char *
4734 read_comsub (fd, quoted, rflag)
4735 int fd, quoted;
4736 int *rflag;
4737 {
4738 char *istring, buf[128], *bufp, *s;
4739 int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
4740 ssize_t bufn;
4741
4742 istring = (char *)NULL;
4743 istring_index = istring_size = bufn = tflag = 0;
4744
4745 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
4746 skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
4747
4748 #ifdef __CYGWIN__
4749 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
4750 #endif
4751
4752 /* Read the output of the command through the pipe. This may need to be
4753 changed to understand multibyte characters in the future. */
4754 while (1)
4755 {
4756 if (fd < 0)
4757 break;
4758 if (--bufn <= 0)
4759 {
4760 bufn = zread (fd, buf, sizeof (buf));
4761 if (bufn <= 0)
4762 break;
4763 bufp = buf;
4764 }
4765 c = *bufp++;
4766
4767 if (c == 0)
4768 {
4769 #if 0
4770 internal_warning ("read_comsub: ignored null byte in input");
4771 #endif
4772 continue;
4773 }
4774
4775 /* Add the character to ISTRING, possibly after resizing it. */
4776 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4777
4778 /* This is essentially quote_string inline */
4779 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
4780 istring[istring_index++] = CTLESC;
4781 /* Escape CTLESC and CTLNUL in the output to protect those characters
4782 from the rest of the word expansions (word splitting and globbing.)
4783 This is essentially quote_escapes inline. */
4784 else if (skip_ctlesc == 0 && c == CTLESC)
4785 {
4786 tflag |= W_HASCTLESC;
4787 istring[istring_index++] = CTLESC;
4788 }
4789 else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
4790 istring[istring_index++] = CTLESC;
4791
4792 istring[istring_index++] = c;
4793
4794 #if 0
4795 #if defined (__CYGWIN__)
4796 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4797 {
4798 istring_index--;
4799 istring[istring_index - 1] = '\n';
4800 }
4801 #endif
4802 #endif
4803 }
4804
4805 if (istring)
4806 istring[istring_index] = '\0';
4807
4808 /* If we read no output, just return now and save ourselves some
4809 trouble. */
4810 if (istring_index == 0)
4811 {
4812 FREE (istring);
4813 if (rflag)
4814 *rflag = tflag;
4815 return (char *)NULL;
4816 }
4817
4818 /* Strip trailing newlines from the output of the command. */
4819 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4820 {
4821 while (istring_index > 0)
4822 {
4823 if (istring[istring_index - 1] == '\n')
4824 {
4825 --istring_index;
4826
4827 /* If the newline was quoted, remove the quoting char. */
4828 if (istring[istring_index - 1] == CTLESC)
4829 --istring_index;
4830 }
4831 else
4832 break;
4833 }
4834 istring[istring_index] = '\0';
4835 }
4836 else
4837 strip_trailing (istring, istring_index - 1, 1);
4838
4839 if (rflag)
4840 *rflag = tflag;
4841 return istring;
4842 }
4843
4844 /* Perform command substitution on STRING. This returns a WORD_DESC * with the
4845 contained string possibly quoted. */
4846 WORD_DESC *
4847 command_substitute (string, quoted)
4848 char *string;
4849 int quoted;
4850 {
4851 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4852 char *istring;
4853 int result, fildes[2], function_value, pflags, rc, tflag;
4854 WORD_DESC *ret;
4855
4856 istring = (char *)NULL;
4857
4858 /* Don't fork () if there is no need to. In the case of no command to
4859 run, just return NULL. */
4860 if (!string || !*string || (string[0] == '\n' && !string[1]))
4861 return ((WORD_DESC *)NULL);
4862
4863 if (wordexp_only && read_but_dont_execute)
4864 {
4865 last_command_exit_value = 125;
4866 jump_to_top_level (EXITPROG);
4867 }
4868
4869 /* We're making the assumption here that the command substitution will
4870 eventually run a command from the file system. Since we'll run
4871 maybe_make_export_env in this subshell before executing that command,
4872 the parent shell and any other shells it starts will have to remake
4873 the environment. If we make it before we fork, other shells won't
4874 have to. Don't bother if we have any temporary variable assignments,
4875 though, because the export environment will be remade after this
4876 command completes anyway, but do it if all the words to be expanded
4877 are variable assignments. */
4878 if (subst_assign_varlist == 0 || garglist == 0)
4879 maybe_make_export_env (); /* XXX */
4880
4881 /* Flags to pass to parse_and_execute() */
4882 pflags = interactive ? SEVAL_RESETLINE : 0;
4883
4884 /* Pipe the output of executing STRING into the current shell. */
4885 if (pipe (fildes) < 0)
4886 {
4887 sys_error (_("cannot make pipe for command substitution"));
4888 goto error_exit;
4889 }
4890
4891 old_pid = last_made_pid;
4892 #if defined (JOB_CONTROL)
4893 old_pipeline_pgrp = pipeline_pgrp;
4894 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4895 if ((subshell_environment & SUBSHELL_PIPE) == 0)
4896 pipeline_pgrp = shell_pgrp;
4897 cleanup_the_pipeline ();
4898 #endif /* JOB_CONTROL */
4899
4900 old_async_pid = last_asynchronous_pid;
4901 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4902 last_asynchronous_pid = old_async_pid;
4903
4904 if (pid == 0)
4905 /* Reset the signal handlers in the child, but don't free the
4906 trap strings. */
4907 reset_signal_handlers ();
4908
4909 #if defined (JOB_CONTROL)
4910 /* XXX DO THIS ONLY IN PARENT ? XXX */
4911 set_sigchld_handler ();
4912 stop_making_children ();
4913 if (pid != 0)
4914 pipeline_pgrp = old_pipeline_pgrp;
4915 #else
4916 stop_making_children ();
4917 #endif /* JOB_CONTROL */
4918
4919 if (pid < 0)
4920 {
4921 sys_error (_("cannot make child for command substitution"));
4922 error_exit:
4923
4924 FREE (istring);
4925 close (fildes[0]);
4926 close (fildes[1]);
4927 return ((WORD_DESC *)NULL);
4928 }
4929
4930 if (pid == 0)
4931 {
4932 set_sigint_handler (); /* XXX */
4933
4934 free_pushed_string_input ();
4935
4936 if (dup2 (fildes[1], 1) < 0)
4937 {
4938 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4939 exit (EXECUTION_FAILURE);
4940 }
4941
4942 /* If standard output is closed in the parent shell
4943 (such as after `exec >&-'), file descriptor 1 will be
4944 the lowest available file descriptor, and end up in
4945 fildes[0]. This can happen for stdin and stderr as well,
4946 but stdout is more important -- it will cause no output
4947 to be generated from this command. */
4948 if ((fildes[1] != fileno (stdin)) &&
4949 (fildes[1] != fileno (stdout)) &&
4950 (fildes[1] != fileno (stderr)))
4951 close (fildes[1]);
4952
4953 if ((fildes[0] != fileno (stdin)) &&
4954 (fildes[0] != fileno (stdout)) &&
4955 (fildes[0] != fileno (stderr)))
4956 close (fildes[0]);
4957
4958 /* The currently executing shell is not interactive. */
4959 interactive = 0;
4960
4961 /* This is a subshell environment. */
4962 subshell_environment |= SUBSHELL_COMSUB;
4963
4964 /* When not in POSIX mode, command substitution does not inherit
4965 the -e flag. */
4966 if (posixly_correct == 0)
4967 exit_immediately_on_error = 0;
4968
4969 remove_quoted_escapes (string);
4970
4971 startup_state = 2; /* see if we can avoid a fork */
4972 /* Give command substitution a place to jump back to on failure,
4973 so we don't go back up to main (). */
4974 result = setjmp (top_level);
4975
4976 /* If we're running a command substitution inside a shell function,
4977 trap `return' so we don't return from the function in the subshell
4978 and go off to never-never land. */
4979 if (result == 0 && return_catch_flag)
4980 function_value = setjmp (return_catch);
4981 else
4982 function_value = 0;
4983
4984 if (result == ERREXIT)
4985 rc = last_command_exit_value;
4986 else if (result == EXITPROG)
4987 rc = last_command_exit_value;
4988 else if (result)
4989 rc = EXECUTION_FAILURE;
4990 else if (function_value)
4991 rc = return_catch_value;
4992 else
4993 {
4994 subshell_level++;
4995 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4996 subshell_level--;
4997 }
4998
4999 last_command_exit_value = rc;
5000 rc = run_exit_trap ();
5001 #if defined (PROCESS_SUBSTITUTION)
5002 unlink_fifo_list ();
5003 #endif
5004 exit (rc);
5005 }
5006 else
5007 {
5008 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
5009 close_pgrp_pipe ();
5010 #endif /* JOB_CONTROL && PGRP_PIPE */
5011
5012 close (fildes[1]);
5013
5014 tflag = 0;
5015 istring = read_comsub (fildes[0], quoted, &tflag);
5016
5017 close (fildes[0]);
5018
5019 current_command_subst_pid = pid;
5020 last_command_exit_value = wait_for (pid);
5021 last_command_subst_pid = pid;
5022 last_made_pid = old_pid;
5023
5024 #if defined (JOB_CONTROL)
5025 /* If last_command_exit_value > 128, then the substituted command
5026 was terminated by a signal. If that signal was SIGINT, then send
5027 SIGINT to ourselves. This will break out of loops, for instance. */
5028 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
5029 kill (getpid (), SIGINT);
5030
5031 /* wait_for gives the terminal back to shell_pgrp. If some other
5032 process group should have it, give it away to that group here.
5033 pipeline_pgrp is non-zero only while we are constructing a
5034 pipline, so what we are concerned about is whether or not that
5035 pipeline was started in the background. A pipeline started in
5036 the background should never get the tty back here. */
5037 #if 0
5038 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
5039 #else
5040 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
5041 #endif
5042 give_terminal_to (pipeline_pgrp, 0);
5043 #endif /* JOB_CONTROL */
5044
5045 ret = alloc_word_desc ();
5046 ret->word = istring;
5047 ret->flags = tflag;
5048
5049 return ret;
5050 }
5051 }
5052
5053 /********************************************************
5054 * *
5055 * Utility functions for parameter expansion *
5056 * *
5057 ********************************************************/
5058
5059 #if defined (ARRAY_VARS)
5060
5061 static arrayind_t
5062 array_length_reference (s)
5063 char *s;
5064 {
5065 int len;
5066 arrayind_t ind;
5067 char *akey;
5068 char *t, c;
5069 ARRAY *array;
5070 SHELL_VAR *var;
5071
5072 var = array_variable_part (s, &t, &len);
5073
5074 /* If unbound variables should generate an error, report one and return
5075 failure. */
5076 if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
5077 {
5078 c = *--t;
5079 *t = '\0';
5080 last_command_exit_value = EXECUTION_FAILURE;
5081 err_unboundvar (s);
5082 *t = c;
5083 return (-1);
5084 }
5085 else if (var == 0)
5086 return 0;
5087
5088 /* We support a couple of expansions for variables that are not arrays.
5089 We'll return the length of the value for v[0], and 1 for v[@] or
5090 v[*]. Return 0 for everything else. */
5091
5092 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
5093
5094 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
5095 {
5096 if (assoc_p (var))
5097 return (assoc_num_elements (assoc_cell (var)));
5098 else if (array_p (var))
5099 return (array_num_elements (array));
5100 else
5101 return 1;
5102 }
5103
5104 if (assoc_p (var))
5105 {
5106 t[len - 1] = '\0';
5107 akey = expand_assignment_string_to_string (t, 0); /* [ */
5108 t[len - 1] = ']';
5109 if (akey == 0 || *akey == 0)
5110 {
5111 err_badarraysub (t);
5112 return (-1);
5113 }
5114 t = assoc_reference (assoc_cell (var), akey);
5115 }
5116 else
5117 {
5118 ind = array_expand_index (t, len);
5119 if (ind < 0)
5120 {
5121 err_badarraysub (t);
5122 return (-1);
5123 }
5124 if (array_p (var))
5125 t = array_reference (array, ind);
5126 else
5127 t = (ind == 0) ? value_cell (var) : (char *)NULL;
5128 }
5129
5130 len = MB_STRLEN (t);
5131 return (len);
5132 }
5133 #endif /* ARRAY_VARS */
5134
5135 static int
5136 valid_brace_expansion_word (name, var_is_special)
5137 char *name;
5138 int var_is_special;
5139 {
5140 if (DIGIT (*name) && all_digits (name))
5141 return 1;
5142 else if (var_is_special)
5143 return 1;
5144 #if defined (ARRAY_VARS)
5145 else if (valid_array_reference (name))
5146 return 1;
5147 #endif /* ARRAY_VARS */
5148 else if (legal_identifier (name))
5149 return 1;
5150 else
5151 return 0;
5152 }
5153
5154 static int
5155 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
5156 char *name;
5157 int quoted;
5158 int *quoted_dollar_atp, *contains_dollar_at;
5159 {
5160 char *temp1;
5161
5162 if (name == 0)
5163 {
5164 if (quoted_dollar_atp)
5165 *quoted_dollar_atp = 0;
5166 if (contains_dollar_at)
5167 *contains_dollar_at = 0;
5168 return 0;
5169 }
5170
5171 /* check for $@ and $* */
5172 if (name[0] == '@' && name[1] == 0)
5173 {
5174 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5175 *quoted_dollar_atp = 1;
5176 if (contains_dollar_at)
5177 *contains_dollar_at = 1;
5178 return 1;
5179 }
5180 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
5181 {
5182 if (contains_dollar_at)
5183 *contains_dollar_at = 1;
5184 return 1;
5185 }
5186
5187 /* Now check for ${array[@]} and ${array[*]} */
5188 #if defined (ARRAY_VARS)
5189 else if (valid_array_reference (name))
5190 {
5191 temp1 = mbschr (name, '[');
5192 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
5193 {
5194 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5195 *quoted_dollar_atp = 1;
5196 if (contains_dollar_at)
5197 *contains_dollar_at = 1;
5198 return 1;
5199 } /* [ */
5200 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
5201 which should result in separate words even when IFS is unset. */
5202 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
5203 {
5204 if (contains_dollar_at)
5205 *contains_dollar_at = 1;
5206 return 1;
5207 }
5208 }
5209 #endif
5210 return 0;
5211 }
5212
5213 /* Parameter expand NAME, and return a new string which is the expansion,
5214 or NULL if there was no expansion.
5215 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
5216 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
5217 NAME was found inside of a double-quoted expression. */
5218 static WORD_DESC *
5219 parameter_brace_expand_word (name, var_is_special, quoted, pflags)
5220 char *name;
5221 int var_is_special, quoted, pflags;
5222 {
5223 WORD_DESC *ret;
5224 char *temp, *tt;
5225 intmax_t arg_index;
5226 SHELL_VAR *var;
5227 int atype, rflags;
5228
5229 ret = 0;
5230 temp = 0;
5231 rflags = 0;
5232
5233 /* Handle multiple digit arguments, as in ${11}. */
5234 if (legal_number (name, &arg_index))
5235 {
5236 tt = get_dollar_var_value (arg_index);
5237 if (tt)
5238 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5239 ? quote_string (tt)
5240 : quote_escapes (tt);
5241 else
5242 temp = (char *)NULL;
5243 FREE (tt);
5244 }
5245 else if (var_is_special) /* ${@} */
5246 {
5247 int sindex;
5248 tt = (char *)xmalloc (2 + strlen (name));
5249 tt[sindex = 0] = '$';
5250 strcpy (tt + 1, name);
5251
5252 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
5253 (int *)NULL, (int *)NULL, pflags);
5254 free (tt);
5255 }
5256 #if defined (ARRAY_VARS)
5257 else if (valid_array_reference (name))
5258 {
5259 temp = array_value (name, quoted, &atype);
5260 if (atype == 0 && temp)
5261 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5262 ? quote_string (temp)
5263 : quote_escapes (temp);
5264 else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5265 rflags |= W_HASQUOTEDNULL;
5266 }
5267 #endif
5268 else if (var = find_variable (name))
5269 {
5270 if (var_isset (var) && invisible_p (var) == 0)
5271 {
5272 #if defined (ARRAY_VARS)
5273 if (assoc_p (var))
5274 temp = assoc_reference (assoc_cell (var), "0");
5275 else if (array_p (var))
5276 temp = array_reference (array_cell (var), 0);
5277 else
5278 temp = value_cell (var);
5279 #else
5280 temp = value_cell (var);
5281 #endif
5282
5283 if (temp)
5284 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5285 ? quote_string (temp)
5286 : quote_escapes (temp);
5287 }
5288 else
5289 temp = (char *)NULL;
5290 }
5291 else
5292 temp = (char *)NULL;
5293
5294 if (ret == 0)
5295 {
5296 ret = alloc_word_desc ();
5297 ret->word = temp;
5298 ret->flags |= rflags;
5299 }
5300 return ret;
5301 }
5302
5303 /* Expand an indirect reference to a variable: ${!NAME} expands to the
5304 value of the variable whose name is the value of NAME. */
5305 static WORD_DESC *
5306 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
5307 char *name;
5308 int var_is_special, quoted;
5309 int *quoted_dollar_atp, *contains_dollar_at;
5310 {
5311 char *temp, *t;
5312 WORD_DESC *w;
5313
5314 w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
5315 t = w->word;
5316 /* Have to dequote here if necessary */
5317 if (t)
5318 {
5319 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5320 ? dequote_string (t)
5321 : dequote_escapes (t);
5322 free (t);
5323 t = temp;
5324 }
5325 dispose_word_desc (w);
5326
5327 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5328 if (t == 0)
5329 return (WORD_DESC *)NULL;
5330
5331 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
5332 free (t);
5333
5334 return w;
5335 }
5336
5337 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5338 depending on the value of C, the separating character. C can be one of
5339 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5340 between double quotes. */
5341 static WORD_DESC *
5342 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5343 char *name, *value;
5344 int c, quoted, *qdollaratp, *hasdollarat;
5345 {
5346 WORD_DESC *w;
5347 WORD_LIST *l;
5348 char *t, *t1, *temp;
5349 int hasdol;
5350
5351 /* If the entire expression is between double quotes, we want to treat
5352 the value as a double-quoted string, with the exception that we strip
5353 embedded unescaped double quotes (for sh backwards compatibility). */
5354 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5355 {
5356 hasdol = 0;
5357 temp = string_extract_double_quoted (value, &hasdol, 1);
5358 }
5359 else
5360 temp = value;
5361
5362 w = alloc_word_desc ();
5363 hasdol = 0;
5364 /* XXX was 0 not quoted */
5365 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5366 : (WORD_LIST *)0;
5367 if (hasdollarat)
5368 *hasdollarat = hasdol || (l && l->next);
5369 if (temp != value)
5370 free (temp);
5371 if (l)
5372 {
5373 /* The expansion of TEMP returned something. We need to treat things
5374 slightly differently if HASDOL is non-zero. If we have "$@", the
5375 individual words have already been quoted. We need to turn them
5376 into a string with the words separated by the first character of
5377 $IFS without any additional quoting, so string_list_dollar_at won't
5378 do the right thing. We use string_list_dollar_star instead. */
5379 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5380
5381 /* If l->next is not null, we know that TEMP contained "$@", since that
5382 is the only expansion that creates more than one word. */
5383 if (qdollaratp && ((hasdol && quoted) || l->next))
5384 *qdollaratp = 1;
5385 dispose_words (l);
5386 }
5387 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5388 {
5389 /* The brace expansion occurred between double quotes and there was
5390 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5391 it does not expand to anything. In this case, we want to return
5392 a quoted empty string. */
5393 temp = make_quoted_char ('\0');
5394 w->flags |= W_HASQUOTEDNULL;
5395 }
5396 else
5397 temp = (char *)NULL;
5398
5399 if (c == '-' || c == '+')
5400 {
5401 w->word = temp;
5402 return w;
5403 }
5404
5405 /* c == '=' */
5406 t = temp ? savestring (temp) : savestring ("");
5407 t1 = dequote_string (t);
5408 free (t);
5409 #if defined (ARRAY_VARS)
5410 if (valid_array_reference (name))
5411 assign_array_element (name, t1, 0);
5412 else
5413 #endif /* ARRAY_VARS */
5414 bind_variable (name, t1, 0);
5415 free (t1);
5416
5417 w->word = temp;
5418 return w;
5419 }
5420
5421 /* Deal with the right hand side of a ${name:?value} expansion in the case
5422 that NAME is null or not set. If VALUE is non-null it is expanded and
5423 used as the error message to print, otherwise a standard message is
5424 printed. */
5425 static void
5426 parameter_brace_expand_error (name, value)
5427 char *name, *value;
5428 {
5429 WORD_LIST *l;
5430 char *temp;
5431
5432 if (value && *value)
5433 {
5434 l = expand_string (value, 0);
5435 temp = string_list (l);
5436 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5437 FREE (temp);
5438 dispose_words (l);
5439 }
5440 else
5441 report_error (_("%s: parameter null or not set"), name);
5442
5443 /* Free the data we have allocated during this expansion, since we
5444 are about to longjmp out. */
5445 free (name);
5446 FREE (value);
5447 }
5448
5449 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5450 OK to do. */
5451 static int
5452 valid_length_expression (name)
5453 char *name;
5454 {
5455 return (name[1] == '\0' || /* ${#} */
5456 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5457 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5458 #if defined (ARRAY_VARS)
5459 valid_array_reference (name + 1) || /* ${#a[7]} */
5460 #endif
5461 legal_identifier (name + 1)); /* ${#PS1} */
5462 }
5463
5464 #if defined (HANDLE_MULTIBYTE)
5465 size_t
5466 mbstrlen (s)
5467 const char *s;
5468 {
5469 size_t clen, nc;
5470 mbstate_t mbs, mbsbak;
5471
5472 nc = 0;
5473 memset (&mbs, 0, sizeof (mbs));
5474 mbsbak = mbs;
5475 while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5476 {
5477 if (MB_INVALIDCH(clen))
5478 {
5479 clen = 1; /* assume single byte */
5480 mbs = mbsbak;
5481 }
5482
5483 s += clen;
5484 nc++;
5485 mbsbak = mbs;
5486 }
5487 return nc;
5488 }
5489 #endif
5490
5491
5492 /* Handle the parameter brace expansion that requires us to return the
5493 length of a parameter. */
5494 static intmax_t
5495 parameter_brace_expand_length (name)
5496 char *name;
5497 {
5498 char *t, *newname;
5499 intmax_t number, arg_index;
5500 WORD_LIST *list;
5501 #if defined (ARRAY_VARS)
5502 SHELL_VAR *var;
5503 #endif
5504
5505 if (name[1] == '\0') /* ${#} */
5506 number = number_of_args ();
5507 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5508 number = number_of_args ();
5509 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5510 {
5511 /* Take the lengths of some of the shell's special parameters. */
5512 switch (name[1])
5513 {
5514 case '-':
5515 t = which_set_flags ();
5516 break;
5517 case '?':
5518 t = itos (last_command_exit_value);
5519 break;
5520 case '$':
5521 t = itos (dollar_dollar_pid);
5522 break;
5523 case '!':
5524 if (last_asynchronous_pid == NO_PID)
5525 t = (char *)NULL;
5526 else
5527 t = itos (last_asynchronous_pid);
5528 break;
5529 case '#':
5530 t = itos (number_of_args ());
5531 break;
5532 }
5533 number = STRLEN (t);
5534 FREE (t);
5535 }
5536 #if defined (ARRAY_VARS)
5537 else if (valid_array_reference (name + 1))
5538 number = array_length_reference (name + 1);
5539 #endif /* ARRAY_VARS */
5540 else
5541 {
5542 number = 0;
5543
5544 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5545 {
5546 t = get_dollar_var_value (arg_index);
5547 number = MB_STRLEN (t);
5548 FREE (t);
5549 }
5550 #if defined (ARRAY_VARS)
5551 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
5552 {
5553 if (assoc_p (var))
5554 t = assoc_reference (assoc_cell (var), "0");
5555 else
5556 t = array_reference (array_cell (var), 0);
5557 number = MB_STRLEN (t);
5558 }
5559 #endif
5560 else /* ${#PS1} */
5561 {
5562 newname = savestring (name);
5563 newname[0] = '$';
5564 list = expand_string (newname, Q_DOUBLE_QUOTES);
5565 t = list ? string_list (list) : (char *)NULL;
5566 free (newname);
5567 if (list)
5568 dispose_words (list);
5569
5570 number = MB_STRLEN (t);
5571 FREE (t);
5572 }
5573 }
5574
5575 return (number);
5576 }
5577
5578 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5579 so we do some ad-hoc parsing of an arithmetic expression to find
5580 the first DELIM, instead of using strchr(3). Two rules:
5581 1. If the substring contains a `(', read until closing `)'.
5582 2. If the substring contains a `?', read past one `:' for each `?'.
5583 */
5584
5585 static char *
5586 skiparith (substr, delim)
5587 char *substr;
5588 int delim;
5589 {
5590 size_t sublen;
5591 int skipcol, pcount, i;
5592 DECLARE_MBSTATE;
5593
5594 sublen = strlen (substr);
5595 i = skipcol = pcount = 0;
5596 while (substr[i])
5597 {
5598 /* Balance parens */
5599 if (substr[i] == LPAREN)
5600 {
5601 pcount++;
5602 i++;
5603 continue;
5604 }
5605 if (substr[i] == RPAREN && pcount)
5606 {
5607 pcount--;
5608 i++;
5609 continue;
5610 }
5611 if (pcount)
5612 {
5613 ADVANCE_CHAR (substr, sublen, i);
5614 continue;
5615 }
5616
5617 /* Skip one `:' for each `?' */
5618 if (substr[i] == ':' && skipcol)
5619 {
5620 skipcol--;
5621 i++;
5622 continue;
5623 }
5624 if (substr[i] == delim)
5625 break;
5626 if (substr[i] == '?')
5627 {
5628 skipcol++;
5629 i++;
5630 continue;
5631 }
5632 ADVANCE_CHAR (substr, sublen, i);
5633 }
5634
5635 return (substr + i);
5636 }
5637
5638 /* Verify and limit the start and end of the desired substring. If
5639 VTYPE == 0, a regular shell variable is being used; if it is 1,
5640 then the positional parameters are being used; if it is 2, then
5641 VALUE is really a pointer to an array variable that should be used.
5642 Return value is 1 if both values were OK, 0 if there was a problem
5643 with an invalid expression, or -1 if the values were out of range. */
5644 static int
5645 verify_substring_values (v, value, substr, vtype, e1p, e2p)
5646 SHELL_VAR *v;
5647 char *value, *substr;
5648 int vtype;
5649 intmax_t *e1p, *e2p;
5650 {
5651 char *t, *temp1, *temp2;
5652 arrayind_t len;
5653 int expok;
5654 #if defined (ARRAY_VARS)
5655 ARRAY *a;
5656 HASH_TABLE *h;
5657 #endif
5658
5659 /* duplicate behavior of strchr(3) */
5660 t = skiparith (substr, ':');
5661 if (*t && *t == ':')
5662 *t = '\0';
5663 else
5664 t = (char *)0;
5665
5666 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
5667 *e1p = evalexp (temp1, &expok);
5668 free (temp1);
5669 if (expok == 0)
5670 return (0);
5671
5672 len = -1; /* paranoia */
5673 switch (vtype)
5674 {
5675 case VT_VARIABLE:
5676 case VT_ARRAYMEMBER:
5677 len = MB_STRLEN (value);
5678 break;
5679 case VT_POSPARMS:
5680 len = number_of_args () + 1;
5681 if (*e1p == 0)
5682 len++; /* add one arg if counting from $0 */
5683 break;
5684 #if defined (ARRAY_VARS)
5685 case VT_ARRAYVAR:
5686 /* For arrays, the first value deals with array indices. Negative
5687 offsets count from one past the array's maximum index. Associative
5688 arrays treat the number of elements as the maximum index. */
5689 if (assoc_p (v))
5690 {
5691 h = assoc_cell (v);
5692 len = assoc_num_elements (h) + (*e1p < 0);
5693 }
5694 else
5695 {
5696 a = (ARRAY *)value;
5697 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
5698 }
5699 break;
5700 #endif
5701 }
5702
5703 if (len == -1) /* paranoia */
5704 return -1;
5705
5706 if (*e1p < 0) /* negative offsets count from end */
5707 *e1p += len;
5708
5709 if (*e1p > len || *e1p < 0)
5710 return (-1);
5711
5712 #if defined (ARRAY_VARS)
5713 /* For arrays, the second offset deals with the number of elements. */
5714 if (vtype == VT_ARRAYVAR)
5715 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
5716 #endif
5717
5718 if (t)
5719 {
5720 t++;
5721 temp2 = savestring (t);
5722 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
5723 free (temp2);
5724 t[-1] = ':';
5725 *e2p = evalexp (temp1, &expok);
5726 free (temp1);
5727 if (expok == 0)
5728 return (0);
5729 if (*e2p < 0)
5730 {
5731 internal_error (_("%s: substring expression < 0"), t);
5732 return (0);
5733 }
5734 #if defined (ARRAY_VARS)
5735 /* In order to deal with sparse arrays, push the intelligence about how
5736 to deal with the number of elements desired down to the array-
5737 specific functions. */
5738 if (vtype != VT_ARRAYVAR)
5739 #endif
5740 {
5741 *e2p += *e1p; /* want E2 chars starting at E1 */
5742 if (*e2p > len)
5743 *e2p = len;
5744 }
5745 }
5746 else
5747 *e2p = len;
5748
5749 return (1);
5750 }
5751
5752 /* Return the type of variable specified by VARNAME (simple variable,
5753 positional param, or array variable). Also return the value specified
5754 by VARNAME (value of a variable or a reference to an array element).
5755 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5756 characters in the value are quoted with CTLESC and takes appropriate
5757 steps. For convenience, *VALP is set to the dequoted VALUE. */
5758 static int
5759 get_var_and_type (varname, value, quoted, varp, valp)
5760 char *varname, *value;
5761 int quoted;
5762 SHELL_VAR **varp;
5763 char **valp;
5764 {
5765 int vtype;
5766 char *temp;
5767 #if defined (ARRAY_VARS)
5768 SHELL_VAR *v;
5769 #endif
5770
5771 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5772 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5773 if (vtype == VT_POSPARMS && varname[0] == '*')
5774 vtype |= VT_STARSUB;
5775 *varp = (SHELL_VAR *)NULL;
5776
5777 #if defined (ARRAY_VARS)
5778 if (valid_array_reference (varname))
5779 {
5780 v = array_variable_part (varname, &temp, (int *)0);
5781 if (v && (array_p (v) || assoc_p (v)))
5782 { /* [ */
5783 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5784 {
5785 /* Callers have to differentiate betwen indexed and associative */
5786 vtype = VT_ARRAYVAR;
5787 if (temp[0] == '*')
5788 vtype |= VT_STARSUB;
5789 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
5790 }
5791 else
5792 {
5793 vtype = VT_ARRAYMEMBER;
5794 *valp = array_value (varname, 1, (int *)NULL);
5795 }
5796 *varp = v;
5797 }
5798 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5799 {
5800 vtype = VT_VARIABLE;
5801 *varp = v;
5802 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5803 *valp = dequote_string (value);
5804 else
5805 *valp = dequote_escapes (value);
5806 }
5807 else
5808 {
5809 vtype = VT_ARRAYMEMBER;
5810 *varp = v;
5811 *valp = array_value (varname, 1, (int *)NULL);
5812 }
5813 }
5814 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
5815 {
5816 vtype = VT_ARRAYMEMBER;
5817 *varp = v;
5818 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
5819 }
5820 else
5821 #endif
5822 {
5823 if (value && vtype == VT_VARIABLE)
5824 {
5825 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5826 *valp = dequote_string (value);
5827 else
5828 *valp = dequote_escapes (value);
5829 }
5830 else
5831 *valp = value;
5832 }
5833
5834 return vtype;
5835 }
5836
5837 /******************************************************/
5838 /* */
5839 /* Functions to extract substrings of variable values */
5840 /* */
5841 /******************************************************/
5842
5843 #if defined (HANDLE_MULTIBYTE)
5844 /* Character-oriented rather than strictly byte-oriented substrings. S and
5845 E, rather being strict indices into STRING, indicate character (possibly
5846 multibyte character) positions that require calculation.
5847 Used by the ${param:offset[:length]} expansion. */
5848 static char *
5849 mb_substring (string, s, e)
5850 char *string;
5851 int s, e;
5852 {
5853 char *tt;
5854 int start, stop, i, slen;
5855 DECLARE_MBSTATE;
5856
5857 start = 0;
5858 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5859 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5860
5861 i = s;
5862 while (string[start] && i--)
5863 ADVANCE_CHAR (string, slen, start);
5864 stop = start;
5865 i = e - s;
5866 while (string[stop] && i--)
5867 ADVANCE_CHAR (string, slen, stop);
5868 tt = substring (string, start, stop);
5869 return tt;
5870 }
5871 #endif
5872
5873 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
5874 is `@', use the positional parameters; otherwise, use the value of
5875 VARNAME. If VARNAME is an array variable, use the array elements. */
5876
5877 static char *
5878 parameter_brace_substring (varname, value, substr, quoted)
5879 char *varname, *value, *substr;
5880 int quoted;
5881 {
5882 intmax_t e1, e2;
5883 int vtype, r, starsub;
5884 char *temp, *val, *tt, *oname;
5885 SHELL_VAR *v;
5886
5887 if (value == 0)
5888 return ((char *)NULL);
5889
5890 oname = this_command_name;
5891 this_command_name = varname;
5892
5893 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5894 if (vtype == -1)
5895 {
5896 this_command_name = oname;
5897 return ((char *)NULL);
5898 }
5899
5900 starsub = vtype & VT_STARSUB;
5901 vtype &= ~VT_STARSUB;
5902
5903 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
5904 this_command_name = oname;
5905 if (r <= 0)
5906 return ((r == 0) ? &expand_param_error : (char *)NULL);
5907
5908 switch (vtype)
5909 {
5910 case VT_VARIABLE:
5911 case VT_ARRAYMEMBER:
5912 #if defined (HANDLE_MULTIBYTE)
5913 if (MB_CUR_MAX > 1)
5914 tt = mb_substring (val, e1, e2);
5915 else
5916 #endif
5917 tt = substring (val, e1, e2);
5918
5919 if (vtype == VT_VARIABLE)
5920 FREE (val);
5921 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5922 temp = quote_string (tt);
5923 else
5924 temp = tt ? quote_escapes (tt) : (char *)NULL;
5925 FREE (tt);
5926 break;
5927 case VT_POSPARMS:
5928 tt = pos_params (varname, e1, e2, quoted);
5929 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5930 {
5931 temp = tt ? quote_escapes (tt) : (char *)NULL;
5932 FREE (tt);
5933 }
5934 else
5935 temp = tt;
5936 break;
5937 #if defined (ARRAY_VARS)
5938 case VT_ARRAYVAR:
5939 if (assoc_p (v))
5940 /* we convert to list and take first e2 elements starting at e1th
5941 element -- officially undefined for now */
5942 temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
5943 else
5944 /* We want E2 to be the number of elements desired (arrays can be sparse,
5945 so verify_substring_values just returns the numbers specified and we
5946 rely on array_subrange to understand how to deal with them). */
5947 temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5948 /* array_subrange now calls array_quote_escapes as appropriate, so the
5949 caller no longer needs to. */
5950 break;
5951 #endif
5952 default:
5953 temp = (char *)NULL;
5954 }
5955
5956 return temp;
5957 }
5958
5959 /****************************************************************/
5960 /* */
5961 /* Functions to perform pattern substitution on variable values */
5962 /* */
5963 /****************************************************************/
5964
5965 char *
5966 pat_subst (string, pat, rep, mflags)
5967 char *string, *pat, *rep;
5968 int mflags;
5969 {
5970 char *ret, *s, *e, *str;
5971 int rsize, rptr, l, replen, mtype;
5972
5973 mtype = mflags & MATCH_TYPEMASK;
5974
5975 /* Special cases:
5976 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
5977 * with REP and return the result.
5978 * 2. A null pattern with mtype == MATCH_END means to append REP to
5979 * STRING and return the result.
5980 */
5981 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5982 {
5983 replen = STRLEN (rep);
5984 l = strlen (string);
5985 ret = (char *)xmalloc (replen + l + 2);
5986 if (replen == 0)
5987 strcpy (ret, string);
5988 else if (mtype == MATCH_BEG)
5989 {
5990 strcpy (ret, rep);
5991 strcpy (ret + replen, string);
5992 }
5993 else
5994 {
5995 strcpy (ret, string);
5996 strcpy (ret + l, rep);
5997 }
5998 return (ret);
5999 }
6000
6001 ret = (char *)xmalloc (rsize = 64);
6002 ret[0] = '\0';
6003
6004 for (replen = STRLEN (rep), rptr = 0, str = string;;)
6005 {
6006 if (match_pattern (str, pat, mtype, &s, &e) == 0)
6007 break;
6008 l = s - str;
6009 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
6010
6011 /* OK, now copy the leading unmatched portion of the string (from
6012 str to s) to ret starting at rptr (the current offset). Then copy
6013 the replacement string at ret + rptr + (s - str). Increment
6014 rptr (if necessary) and str and go on. */
6015 if (l)
6016 {
6017 strncpy (ret + rptr, str, l);
6018 rptr += l;
6019 }
6020 if (replen)
6021 {
6022 strncpy (ret + rptr, rep, replen);
6023 rptr += replen;
6024 }
6025 str = e; /* e == end of match */
6026
6027 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
6028 break;
6029
6030 if (s == e)
6031 {
6032 /* On a zero-length match, make sure we copy one character, since
6033 we increment one character to avoid infinite recursion. */
6034 RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64);
6035 ret[rptr++] = *str++;
6036 e++; /* avoid infinite recursion on zero-length match */
6037 }
6038 }
6039
6040 /* Now copy the unmatched portion of the input string */
6041 if (*str)
6042 {
6043 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
6044 strcpy (ret + rptr, str);
6045 }
6046 else
6047 ret[rptr] = '\0';
6048
6049 return ret;
6050 }
6051
6052 /* Do pattern match and replacement on the positional parameters. */
6053 static char *
6054 pos_params_pat_subst (string, pat, rep, mflags)
6055 char *string, *pat, *rep;
6056 int mflags;
6057 {
6058 WORD_LIST *save, *params;
6059 WORD_DESC *w;
6060 char *ret;
6061 int pchar, qflags;
6062
6063 save = params = list_rest_of_args ();
6064 if (save == 0)
6065 return ((char *)NULL);
6066
6067 for ( ; params; params = params->next)
6068 {
6069 ret = pat_subst (params->word->word, pat, rep, mflags);
6070 w = alloc_word_desc ();
6071 w->word = ret ? ret : savestring ("");
6072 dispose_word (params->word);
6073 params->word = w;
6074 }
6075
6076 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6077 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6078
6079 #if 0
6080 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
6081 ret = string_list_dollar_star (quote_list (save));
6082 else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
6083 ret = string_list_dollar_star (save);
6084 else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
6085 ret = string_list_dollar_at (save, qflags);
6086 else
6087 ret = string_list_dollar_star (save);
6088 #else
6089 ret = string_list_pos_params (pchar, save, qflags);
6090 #endif
6091
6092 dispose_words (save);
6093
6094 return (ret);
6095 }
6096
6097 /* Perform pattern substitution on VALUE, which is the expansion of
6098 VARNAME. PATSUB is an expression supplying the pattern to match
6099 and the string to substitute. QUOTED is a flags word containing
6100 the type of quoting currently in effect. */
6101 static char *
6102 parameter_brace_patsub (varname, value, patsub, quoted)
6103 char *varname, *value, *patsub;
6104 int quoted;
6105 {
6106 int vtype, mflags, starsub, delim;
6107 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
6108 SHELL_VAR *v;
6109
6110 if (value == 0)
6111 return ((char *)NULL);
6112
6113 this_command_name = varname;
6114
6115 vtype = get_var_and_type (varname, value, quoted, &v, &val);
6116 if (vtype == -1)
6117 return ((char *)NULL);
6118
6119 starsub = vtype & VT_STARSUB;
6120 vtype &= ~VT_STARSUB;
6121
6122 mflags = 0;
6123 if (patsub && *patsub == '/')
6124 {
6125 mflags |= MATCH_GLOBREP;
6126 patsub++;
6127 }
6128
6129 /* Malloc this because expand_string_if_necessary or one of the expansion
6130 functions in its call chain may free it on a substitution error. */
6131 lpatsub = savestring (patsub);
6132
6133 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6134 mflags |= MATCH_QUOTED;
6135
6136 if (starsub)
6137 mflags |= MATCH_STARSUB;
6138
6139 /* If the pattern starts with a `/', make sure we skip over it when looking
6140 for the replacement delimiter. */
6141 #if 0
6142 if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
6143 *rep++ = '\0';
6144 else
6145 rep = (char *)NULL;
6146 #else
6147 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
6148 if (lpatsub[delim] == '/')
6149 {
6150 lpatsub[delim] = 0;
6151 rep = lpatsub + delim + 1;
6152 }
6153 else
6154 rep = (char *)NULL;
6155 #endif
6156
6157 if (rep && *rep == '\0')
6158 rep = (char *)NULL;
6159
6160 /* Perform the same expansions on the pattern as performed by the
6161 pattern removal expansions. */
6162 pat = getpattern (lpatsub, quoted, 1);
6163
6164 if (rep)
6165 {
6166 if ((mflags & MATCH_QUOTED) == 0)
6167 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
6168 else
6169 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
6170 }
6171
6172 /* ksh93 doesn't allow the match specifier to be a part of the expanded
6173 pattern. This is an extension. Make sure we don't anchor the pattern
6174 at the beginning or end of the string if we're doing global replacement,
6175 though. */
6176 p = pat;
6177 if (mflags & MATCH_GLOBREP)
6178 mflags |= MATCH_ANY;
6179 else if (pat && pat[0] == '#')
6180 {
6181 mflags |= MATCH_BEG;
6182 p++;
6183 }
6184 else if (pat && pat[0] == '%')
6185 {
6186 mflags |= MATCH_END;
6187 p++;
6188 }
6189 else
6190 mflags |= MATCH_ANY;
6191
6192 /* OK, we now want to substitute REP for PAT in VAL. If
6193 flags & MATCH_GLOBREP is non-zero, the substitution is done
6194 everywhere, otherwise only the first occurrence of PAT is
6195 replaced. The pattern matching code doesn't understand
6196 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6197 values passed in (VT_VARIABLE) so the pattern substitution
6198 code works right. We need to requote special chars after
6199 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6200 other cases if QUOTED == 0, since the posparams and arrays
6201 indexed by * or @ do special things when QUOTED != 0. */
6202
6203 switch (vtype)
6204 {
6205 case VT_VARIABLE:
6206 case VT_ARRAYMEMBER:
6207 temp = pat_subst (val, p, rep, mflags);
6208 if (vtype == VT_VARIABLE)
6209 FREE (val);
6210 if (temp)
6211 {
6212 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6213 free (temp);
6214 temp = tt;
6215 }
6216 break;
6217 case VT_POSPARMS:
6218 temp = pos_params_pat_subst (val, p, rep, mflags);
6219 if (temp && (mflags & MATCH_QUOTED) == 0)
6220 {
6221 tt = quote_escapes (temp);
6222 free (temp);
6223 temp = tt;
6224 }
6225 break;
6226 #if defined (ARRAY_VARS)
6227 case VT_ARRAYVAR:
6228 temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6229 : array_patsub (array_cell (v), p, rep, mflags);
6230 /* Don't call quote_escapes anymore; array_patsub calls
6231 array_quote_escapes as appropriate before adding the
6232 space separators; ditto for assoc_patsub. */
6233 break;
6234 #endif
6235 }
6236
6237 FREE (pat);
6238 FREE (rep);
6239 free (lpatsub);
6240
6241 return temp;
6242 }
6243
6244 /****************************************************************/
6245 /* */
6246 /* Functions to perform case modification on variable values */
6247 /* */
6248 /****************************************************************/
6249
6250 /* Do case modification on the positional parameters. */
6251
6252 static char *
6253 pos_params_modcase (string, pat, modop, mflags)
6254 char *string, *pat;
6255 int modop;
6256 int mflags;
6257 {
6258 WORD_LIST *save, *params;
6259 WORD_DESC *w;
6260 char *ret;
6261 int pchar, qflags;
6262
6263 save = params = list_rest_of_args ();
6264 if (save == 0)
6265 return ((char *)NULL);
6266
6267 for ( ; params; params = params->next)
6268 {
6269 ret = sh_modcase (params->word->word, pat, modop);
6270 w = alloc_word_desc ();
6271 w->word = ret ? ret : savestring ("");
6272 dispose_word (params->word);
6273 params->word = w;
6274 }
6275
6276 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6277 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6278
6279 ret = string_list_pos_params (pchar, save, qflags);
6280 dispose_words (save);
6281
6282 return (ret);
6283 }
6284
6285 /* Perform case modification on VALUE, which is the expansion of
6286 VARNAME. MODSPEC is an expression supplying the type of modification
6287 to perform. QUOTED is a flags word containing the type of quoting
6288 currently in effect. */
6289 static char *
6290 parameter_brace_casemod (varname, value, modspec, patspec, quoted)
6291 char *varname, *value;
6292 int modspec;
6293 char *patspec;
6294 int quoted;
6295 {
6296 int vtype, starsub, modop, mflags, x;
6297 char *val, *temp, *pat, *p, *lpat, *tt;
6298 SHELL_VAR *v;
6299
6300 if (value == 0)
6301 return ((char *)NULL);
6302
6303 this_command_name = varname;
6304
6305 vtype = get_var_and_type (varname, value, quoted, &v, &val);
6306 if (vtype == -1)
6307 return ((char *)NULL);
6308
6309 starsub = vtype & VT_STARSUB;
6310 vtype &= ~VT_STARSUB;
6311
6312 modop = 0;
6313 mflags = 0;
6314 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6315 mflags |= MATCH_QUOTED;
6316 if (starsub)
6317 mflags |= MATCH_STARSUB;
6318
6319 p = patspec;
6320 if (modspec == '^')
6321 {
6322 x = p && p[0] == modspec;
6323 modop = x ? CASE_UPPER : CASE_UPFIRST;
6324 p += x;
6325 }
6326 else if (modspec == ',')
6327 {
6328 x = p && p[0] == modspec;
6329 modop = x ? CASE_LOWER : CASE_LOWFIRST;
6330 p += x;
6331 }
6332 else if (modspec == '~')
6333 {
6334 x = p && p[0] == modspec;
6335 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6336 p += x;
6337 }
6338
6339 lpat = p ? savestring (p) : 0;
6340 /* Perform the same expansions on the pattern as performed by the
6341 pattern removal expansions. FOR LATER */
6342 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6343
6344 /* OK, now we do the case modification. */
6345 switch (vtype)
6346 {
6347 case VT_VARIABLE:
6348 case VT_ARRAYMEMBER:
6349 temp = sh_modcase (val, pat, modop);
6350 if (vtype == VT_VARIABLE)
6351 FREE (val);
6352 if (temp)
6353 {
6354 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6355 free (temp);
6356 temp = tt;
6357 }
6358 break;
6359
6360 case VT_POSPARMS:
6361 temp = pos_params_modcase (val, pat, modop, mflags);
6362 if (temp && (mflags & MATCH_QUOTED) == 0)
6363 {
6364 tt = quote_escapes (temp);
6365 free (temp);
6366 temp = tt;
6367 }
6368 break;
6369
6370 #if defined (ARRAY_VARS)
6371 case VT_ARRAYVAR:
6372 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6373 : array_modcase (array_cell (v), pat, modop, mflags);
6374 /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6375 as appropriate before adding the space separators; ditto for
6376 assoc_modcase. */
6377 break;
6378 #endif
6379 }
6380
6381 FREE (pat);
6382 free (lpat);
6383
6384 return temp;
6385 }
6386
6387 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
6388 any occur, this must be a nested command substitution, so return 0.
6389 Otherwise, return 1. A valid arithmetic expression must always have a
6390 ( before a matching ), so any cases where there are more right parens
6391 means that this must not be an arithmetic expression, though the parser
6392 will not accept it without a balanced total number of parens. */
6393 static int
6394 chk_arithsub (s, len)
6395 const char *s;
6396 int len;
6397 {
6398 int i, count;
6399 DECLARE_MBSTATE;
6400
6401 i = count = 0;
6402 while (i < len)
6403 {
6404 if (s[i] == '(')
6405 count++;
6406 else if (s[i] == ')')
6407 {
6408 count--;
6409 if (count < 0)
6410 return 0;
6411 }
6412
6413 switch (s[i])
6414 {
6415 default:
6416 ADVANCE_CHAR (s, len, i);
6417 break;
6418
6419 case '\\':
6420 i++;
6421 if (s[i])
6422 ADVANCE_CHAR (s, len, i);
6423 break;
6424
6425 case '\'':
6426 i = skip_single_quoted (s, len, ++i);
6427 break;
6428
6429 case '"':
6430 i = skip_double_quoted ((char *)s, len, ++i);
6431 break;
6432 }
6433 }
6434
6435 return (count == 0);
6436 }
6437
6438 /****************************************************************/
6439 /* */
6440 /* Functions to perform parameter expansion on a string */
6441 /* */
6442 /****************************************************************/
6443
6444 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
6445 static WORD_DESC *
6446 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
6447 char *string;
6448 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
6449 {
6450 int check_nullness, var_is_set, var_is_null, var_is_special;
6451 int want_substring, want_indir, want_patsub, want_casemod;
6452 char *name, *value, *temp, *temp1;
6453 WORD_DESC *tdesc, *ret;
6454 int t_index, sindex, c, tflag, modspec;
6455 intmax_t number;
6456
6457 temp = temp1 = value = (char *)NULL;
6458 var_is_set = var_is_null = var_is_special = check_nullness = 0;
6459 want_substring = want_indir = want_patsub = want_casemod = 0;
6460
6461 sindex = *indexp;
6462 t_index = ++sindex;
6463 /* ${#var} doesn't have any of the other parameter expansions on it. */
6464 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
6465 name = string_extract (string, &t_index, "}", SX_VARNAME);
6466 else
6467 #if defined (CASEMOD_EXPANSIONS)
6468 /* To enable case-toggling expansions using the `~' operator character
6469 change the 1 to 0. */
6470 # if defined (CASEMOD_CAPCASE)
6471 name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
6472 # else
6473 name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
6474 # endif /* CASEMOD_CAPCASE */
6475 #else
6476 name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
6477 #endif /* CASEMOD_EXPANSIONS */
6478
6479 ret = 0;
6480 tflag = 0;
6481
6482 /* If the name really consists of a special variable, then make sure
6483 that we have the entire name. We don't allow indirect references
6484 to special variables except `#', `?', `@' and `*'. */
6485 if ((sindex == t_index &&
6486 (string[t_index] == '-' ||
6487 string[t_index] == '?' ||
6488 string[t_index] == '#')) ||
6489 (sindex == t_index - 1 && string[sindex] == '!' &&
6490 (string[t_index] == '#' ||
6491 string[t_index] == '?' ||
6492 string[t_index] == '@' ||
6493 string[t_index] == '*')))
6494 {
6495 t_index++;
6496 free (name);
6497 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
6498 name = (char *)xmalloc (3 + (strlen (temp1)));
6499 *name = string[sindex];
6500 if (string[sindex] == '!')
6501 {
6502 /* indirect reference of $#, $?, $@, or $* */
6503 name[1] = string[sindex + 1];
6504 strcpy (name + 2, temp1);
6505 }
6506 else
6507 strcpy (name + 1, temp1);
6508 free (temp1);
6509 }
6510 sindex = t_index;
6511
6512 /* Find out what character ended the variable name. Then
6513 do the appropriate thing. */
6514 if (c = string[sindex])
6515 sindex++;
6516
6517 /* If c is followed by one of the valid parameter expansion
6518 characters, move past it as normal. If not, assume that
6519 a substring specification is being given, and do not move
6520 past it. */
6521 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
6522 {
6523 check_nullness++;
6524 if (c = string[sindex])
6525 sindex++;
6526 }
6527 else if (c == ':' && string[sindex] != RBRACE)
6528 want_substring = 1;
6529 else if (c == '/' && string[sindex] != RBRACE)
6530 want_patsub = 1;
6531 #if defined (CASEMOD_EXPANSIONS)
6532 else if (c == '^' || c == ',' || c == '~')
6533 {
6534 modspec = c;
6535 want_casemod = 1;
6536 }
6537 #endif
6538
6539 /* Catch the valid and invalid brace expressions that made it through the
6540 tests above. */
6541 /* ${#-} is a valid expansion and means to take the length of $-.
6542 Similarly for ${#?} and ${##}... */
6543 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6544 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
6545 {
6546 name = (char *)xrealloc (name, 3);
6547 name[1] = c;
6548 name[2] = '\0';
6549 c = string[sindex++];
6550 }
6551
6552 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
6553 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
6554 member (c, "%:=+/") && string[sindex] == RBRACE)
6555 {
6556 temp = (char *)NULL;
6557 goto bad_substitution;
6558 }
6559
6560 /* Indirect expansion begins with a `!'. A valid indirect expansion is
6561 either a variable name, one of the positional parameters or a special
6562 variable that expands to one of the positional parameters. */
6563 want_indir = *name == '!' &&
6564 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
6565 || VALID_INDIR_PARAM (name[1]));
6566
6567 /* Determine the value of this variable. */
6568
6569 /* Check for special variables, directly referenced. */
6570 if (SPECIAL_VAR (name, want_indir))
6571 var_is_special++;
6572
6573 /* Check for special expansion things, like the length of a parameter */
6574 if (*name == '#' && name[1])
6575 {
6576 /* If we are not pointing at the character just after the
6577 closing brace, then we haven't gotten all of the name.
6578 Since it begins with a special character, this is a bad
6579 substitution. Also check NAME for validity before trying
6580 to go on. */
6581 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
6582 {
6583 temp = (char *)NULL;
6584 goto bad_substitution;
6585 }
6586
6587 number = parameter_brace_expand_length (name);
6588 free (name);
6589
6590 *indexp = sindex;
6591 if (number < 0)
6592 return (&expand_wdesc_error);
6593 else
6594 {
6595 ret = alloc_word_desc ();
6596 ret->word = itos (number);
6597 return ret;
6598 }
6599 }
6600
6601 /* ${@} is identical to $@. */
6602 if (name[0] == '@' && name[1] == '\0')
6603 {
6604 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6605 *quoted_dollar_atp = 1;
6606
6607 if (contains_dollar_at)
6608 *contains_dollar_at = 1;
6609 }
6610
6611 /* Process ${!PREFIX*} expansion. */
6612 if (want_indir && string[sindex - 1] == RBRACE &&
6613 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
6614 legal_variable_starter ((unsigned char) name[1]))
6615 {
6616 char **x;
6617 WORD_LIST *xlist;
6618
6619 temp1 = savestring (name + 1);
6620 number = strlen (temp1);
6621 temp1[number - 1] = '\0';
6622 x = all_variables_matching_prefix (temp1);
6623 xlist = strvec_to_word_list (x, 0, 0);
6624 if (string[sindex - 2] == '*')
6625 temp = string_list_dollar_star (xlist);
6626 else
6627 {
6628 temp = string_list_dollar_at (xlist, quoted);
6629 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6630 *quoted_dollar_atp = 1;
6631 if (contains_dollar_at)
6632 *contains_dollar_at = 1;
6633 }
6634 free (x);
6635 free (xlist);
6636 free (temp1);
6637 *indexp = sindex;
6638
6639 ret = alloc_word_desc ();
6640 ret->word = temp;
6641 return ret;
6642 }
6643
6644 #if defined (ARRAY_VARS)
6645 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
6646 if (want_indir && string[sindex - 1] == RBRACE &&
6647 string[sindex - 2] == ']' && valid_array_reference (name+1))
6648 {
6649 char *x, *x1;
6650
6651 temp1 = savestring (name + 1);
6652 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
6653 FREE (x);
6654 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
6655 {
6656 temp = array_keys (temp1, quoted); /* handles assoc vars too */
6657 if (x1[0] == '@')
6658 {
6659 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6660 *quoted_dollar_atp = 1;
6661 if (contains_dollar_at)
6662 *contains_dollar_at = 1;
6663 }
6664
6665 free (temp1);
6666 *indexp = sindex;
6667
6668 ret = alloc_word_desc ();
6669 ret->word = temp;
6670 return ret;
6671 }
6672
6673 free (temp1);
6674 }
6675 #endif /* ARRAY_VARS */
6676
6677 /* Make sure that NAME is valid before trying to go on. */
6678 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
6679 var_is_special) == 0)
6680 {
6681 temp = (char *)NULL;
6682 goto bad_substitution;
6683 }
6684
6685 if (want_indir)
6686 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6687 else
6688 tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
6689
6690 if (tdesc)
6691 {
6692 temp = tdesc->word;
6693 tflag = tdesc->flags;
6694 dispose_word_desc (tdesc);
6695 }
6696 else
6697 temp = (char *)0;
6698
6699 #if defined (ARRAY_VARS)
6700 if (valid_array_reference (name))
6701 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6702 #endif
6703
6704 var_is_set = temp != (char *)0;
6705 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6706
6707 /* Get the rest of the stuff inside the braces. */
6708 if (c && c != RBRACE)
6709 {
6710 /* Extract the contents of the ${ ... } expansion
6711 according to the Posix.2 rules. */
6712 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6713 if (string[sindex] == RBRACE)
6714 sindex++;
6715 else
6716 goto bad_substitution;
6717 }
6718 else
6719 value = (char *)NULL;
6720
6721 *indexp = sindex;
6722
6723 /* If this is a substring spec, process it and add the result. */
6724 if (want_substring)
6725 {
6726 temp1 = parameter_brace_substring (name, temp, value, quoted);
6727 FREE (name);
6728 FREE (value);
6729 FREE (temp);
6730
6731 if (temp1 == &expand_param_error)
6732 return (&expand_wdesc_error);
6733 else if (temp1 == &expand_param_fatal)
6734 return (&expand_wdesc_fatal);
6735
6736 ret = alloc_word_desc ();
6737 ret->word = temp1;
6738 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6739 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6740 return ret;
6741 }
6742 else if (want_patsub)
6743 {
6744 temp1 = parameter_brace_patsub (name, temp, value, quoted);
6745 FREE (name);
6746 FREE (value);
6747 FREE (temp);
6748
6749 if (temp1 == &expand_param_error)
6750 return (&expand_wdesc_error);
6751 else if (temp1 == &expand_param_fatal)
6752 return (&expand_wdesc_fatal);
6753
6754 ret = alloc_word_desc ();
6755 ret->word = temp1;
6756 ret = alloc_word_desc ();
6757 ret->word = temp1;
6758 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6759 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6760 return ret;
6761 }
6762 #if defined (CASEMOD_EXPANSIONS)
6763 else if (want_casemod)
6764 {
6765 temp1 = parameter_brace_casemod (name, temp, modspec, value, quoted);
6766 FREE (name);
6767 FREE (value);
6768 FREE (temp);
6769
6770 if (temp1 == &expand_param_error)
6771 return (&expand_wdesc_error);
6772 else if (temp1 == &expand_param_fatal)
6773 return (&expand_wdesc_fatal);
6774
6775 ret = alloc_word_desc ();
6776 ret->word = temp1;
6777 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6778 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6779 return ret;
6780 }
6781 #endif
6782
6783 /* Do the right thing based on which character ended the variable name. */
6784 switch (c)
6785 {
6786 default:
6787 case '\0':
6788 bad_substitution:
6789 report_error (_("%s: bad substitution"), string ? string : "??");
6790 FREE (value);
6791 FREE (temp);
6792 free (name);
6793 return &expand_wdesc_error;
6794
6795 case RBRACE:
6796 if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
6797 {
6798 last_command_exit_value = EXECUTION_FAILURE;
6799 err_unboundvar (name);
6800 FREE (value);
6801 FREE (temp);
6802 free (name);
6803 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6804 }
6805 break;
6806
6807 case '#': /* ${param#[#]pattern} */
6808 case '%': /* ${param%[%]pattern} */
6809 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6810 {
6811 FREE (value);
6812 break;
6813 }
6814 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6815 free (temp);
6816 free (value);
6817
6818 ret = alloc_word_desc ();
6819 ret->word = temp1;
6820 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6821 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
6822 return ret;
6823
6824 case '-':
6825 case '=':
6826 case '?':
6827 case '+':
6828 if (var_is_set && var_is_null == 0)
6829 {
6830 /* If the operator is `+', we don't want the value of the named
6831 variable for anything, just the value of the right hand side. */
6832
6833 if (c == '+')
6834 {
6835 /* XXX -- if we're double-quoted and the named variable is "$@",
6836 we want to turn off any special handling of "$@" --
6837 we're not using it, so whatever is on the rhs applies. */
6838 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6839 *quoted_dollar_atp = 0;
6840 if (contains_dollar_at)
6841 *contains_dollar_at = 0;
6842
6843 FREE (temp);
6844 if (value)
6845 {
6846 ret = parameter_brace_expand_rhs (name, value, c,
6847 quoted,
6848 quoted_dollar_atp,
6849 contains_dollar_at);
6850 /* XXX - fix up later, esp. noting presence of
6851 W_HASQUOTEDNULL in ret->flags */
6852 free (value);
6853 }
6854 else
6855 temp = (char *)NULL;
6856 }
6857 else
6858 {
6859 FREE (value);
6860 }
6861 /* Otherwise do nothing; just use the value in TEMP. */
6862 }
6863 else /* VAR not set or VAR is NULL. */
6864 {
6865 FREE (temp);
6866 temp = (char *)NULL;
6867 if (c == '=' && var_is_special)
6868 {
6869 report_error (_("$%s: cannot assign in this way"), name);
6870 free (name);
6871 free (value);
6872 return &expand_wdesc_error;
6873 }
6874 else if (c == '?')
6875 {
6876 parameter_brace_expand_error (name, value);
6877 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6878 }
6879 else if (c != '+')
6880 {
6881 /* XXX -- if we're double-quoted and the named variable is "$@",
6882 we want to turn off any special handling of "$@" --
6883 we're not using it, so whatever is on the rhs applies. */
6884 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6885 *quoted_dollar_atp = 0;
6886 if (contains_dollar_at)
6887 *contains_dollar_at = 0;
6888
6889 ret = parameter_brace_expand_rhs (name, value, c, quoted,
6890 quoted_dollar_atp,
6891 contains_dollar_at);
6892 /* XXX - fix up later, esp. noting presence of
6893 W_HASQUOTEDNULL in tdesc->flags */
6894 }
6895 free (value);
6896 }
6897
6898 break;
6899 }
6900 free (name);
6901
6902 if (ret == 0)
6903 {
6904 ret = alloc_word_desc ();
6905 ret->flags = tflag;
6906 ret->word = temp;
6907 }
6908 return (ret);
6909 }
6910
6911 /* Expand a single ${xxx} expansion. The braces are optional. When
6912 the braces are used, parameter_brace_expand() does the work,
6913 possibly calling param_expand recursively. */
6914 static WORD_DESC *
6915 param_expand (string, sindex, quoted, expanded_something,
6916 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6917 pflags)
6918 char *string;
6919 int *sindex, quoted, *expanded_something, *contains_dollar_at;
6920 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6921 {
6922 char *temp, *temp1, uerror[3];
6923 int zindex, t_index, expok;
6924 unsigned char c;
6925 intmax_t number;
6926 SHELL_VAR *var;
6927 WORD_LIST *list;
6928 WORD_DESC *tdesc, *ret;
6929 int tflag;
6930
6931 zindex = *sindex;
6932 c = string[++zindex];
6933
6934 temp = (char *)NULL;
6935 ret = tdesc = (WORD_DESC *)NULL;
6936 tflag = 0;
6937
6938 /* Do simple cases first. Switch on what follows '$'. */
6939 switch (c)
6940 {
6941 /* $0 .. $9? */
6942 case '0':
6943 case '1':
6944 case '2':
6945 case '3':
6946 case '4':
6947 case '5':
6948 case '6':
6949 case '7':
6950 case '8':
6951 case '9':
6952 temp1 = dollar_vars[TODIGIT (c)];
6953 if (unbound_vars_is_error && temp1 == (char *)NULL)
6954 {
6955 uerror[0] = '$';
6956 uerror[1] = c;
6957 uerror[2] = '\0';
6958 last_command_exit_value = EXECUTION_FAILURE;
6959 err_unboundvar (uerror);
6960 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6961 }
6962 if (temp1)
6963 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6964 ? quote_string (temp1)
6965 : quote_escapes (temp1);
6966 else
6967 temp = (char *)NULL;
6968
6969 break;
6970
6971 /* $$ -- pid of the invoking shell. */
6972 case '$':
6973 temp = itos (dollar_dollar_pid);
6974 break;
6975
6976 /* $# -- number of positional parameters. */
6977 case '#':
6978 temp = itos (number_of_args ());
6979 break;
6980
6981 /* $? -- return value of the last synchronous command. */
6982 case '?':
6983 temp = itos (last_command_exit_value);
6984 break;
6985
6986 /* $- -- flags supplied to the shell on invocation or by `set'. */
6987 case '-':
6988 temp = which_set_flags ();
6989 break;
6990
6991 /* $! -- Pid of the last asynchronous command. */
6992 case '!':
6993 /* If no asynchronous pids have been created, expand to nothing.
6994 If `set -u' has been executed, and no async processes have
6995 been created, this is an expansion error. */
6996 if (last_asynchronous_pid == NO_PID)
6997 {
6998 if (expanded_something)
6999 *expanded_something = 0;
7000 temp = (char *)NULL;
7001 if (unbound_vars_is_error)
7002 {
7003 uerror[0] = '$';
7004 uerror[1] = c;
7005 uerror[2] = '\0';
7006 last_command_exit_value = EXECUTION_FAILURE;
7007 err_unboundvar (uerror);
7008 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7009 }
7010 }
7011 else
7012 temp = itos (last_asynchronous_pid);
7013 break;
7014
7015 /* The only difference between this and $@ is when the arg is quoted. */
7016 case '*': /* `$*' */
7017 list = list_rest_of_args ();
7018
7019 #if 0
7020 /* According to austin-group posix proposal by Geoff Clare in
7021 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7022
7023 "The shell shall write a message to standard error and
7024 immediately exit when it tries to expand an unset parameter
7025 other than the '@' and '*' special parameters."
7026 */
7027
7028 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7029 {
7030 uerror[0] = '$';
7031 uerror[1] = '*';
7032 uerror[2] = '\0';
7033 last_command_exit_value = EXECUTION_FAILURE;
7034 err_unboundvar (uerror);
7035 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7036 }
7037 #endif
7038
7039 /* If there are no command-line arguments, this should just
7040 disappear if there are other characters in the expansion,
7041 even if it's quoted. */
7042 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7043 temp = (char *)NULL;
7044 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
7045 {
7046 /* If we have "$*" we want to make a string of the positional
7047 parameters, separated by the first character of $IFS, and
7048 quote the whole string, including the separators. If IFS
7049 is unset, the parameters are separated by ' '; if $IFS is
7050 null, the parameters are concatenated. */
7051 temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
7052 temp1 = quote_string (temp);
7053 if (*temp == 0)
7054 tflag |= W_HASQUOTEDNULL;
7055 free (temp);
7056 temp = temp1;
7057 }
7058 else
7059 {
7060 /* We check whether or not we're eventually going to split $* here,
7061 for example when IFS is empty and we are processing the rhs of
7062 an assignment statement. In that case, we don't separate the
7063 arguments at all. Otherwise, if the $* is not quoted it is
7064 identical to $@ */
7065 #if 1
7066 # if defined (HANDLE_MULTIBYTE)
7067 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7068 # else
7069 if (expand_no_split_dollar_star && ifs_firstc == 0)
7070 # endif
7071 temp = string_list_dollar_star (list);
7072 else
7073 temp = string_list_dollar_at (list, quoted);
7074 #else
7075 temp = string_list_dollar_at (list, quoted);
7076 #endif
7077 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7078 *contains_dollar_at = 1;
7079 }
7080
7081 dispose_words (list);
7082 break;
7083
7084 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7085 means that we have to turn quoting off after we split into
7086 the individually quoted arguments so that the final split
7087 on the first character of $IFS is still done. */
7088 case '@': /* `$@' */
7089 list = list_rest_of_args ();
7090
7091 #if 0
7092 /* According to austin-group posix proposal by Geoff Clare in
7093 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7094
7095 "The shell shall write a message to standard error and
7096 immediately exit when it tries to expand an unset parameter
7097 other than the '@' and '*' special parameters."
7098 */
7099
7100 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7101 {
7102 uerror[0] = '$';
7103 uerror[1] = '@';
7104 uerror[2] = '\0';
7105 last_command_exit_value = EXECUTION_FAILURE;
7106 err_unboundvar (uerror);
7107 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7108 }
7109 #endif
7110
7111 /* We want to flag the fact that we saw this. We can't turn
7112 off quoting entirely, because other characters in the
7113 string might need it (consider "\"$@\""), but we need some
7114 way to signal that the final split on the first character
7115 of $IFS should be done, even though QUOTED is 1. */
7116 /* XXX - should this test include Q_PATQUOTE? */
7117 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7118 *quoted_dollar_at_p = 1;
7119 if (contains_dollar_at)
7120 *contains_dollar_at = 1;
7121
7122 /* We want to separate the positional parameters with the first
7123 character of $IFS in case $IFS is something other than a space.
7124 We also want to make sure that splitting is done no matter what --
7125 according to POSIX.2, this expands to a list of the positional
7126 parameters no matter what IFS is set to. */
7127 temp = string_list_dollar_at (list, quoted);
7128
7129 dispose_words (list);
7130 break;
7131
7132 case LBRACE:
7133 tdesc = parameter_brace_expand (string, &zindex, quoted,
7134 quoted_dollar_at_p,
7135 contains_dollar_at);
7136
7137 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7138 return (tdesc);
7139 temp = tdesc ? tdesc->word : (char *)0;
7140
7141 /* XXX */
7142 /* Quoted nulls should be removed if there is anything else
7143 in the string. */
7144 /* Note that we saw the quoted null so we can add one back at
7145 the end of this function if there are no other characters
7146 in the string, discard TEMP, and go on. The exception to
7147 this is when we have "${@}" and $1 is '', since $@ needs
7148 special handling. */
7149 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7150 {
7151 if (had_quoted_null_p)
7152 *had_quoted_null_p = 1;
7153 if (*quoted_dollar_at_p == 0)
7154 {
7155 free (temp);
7156 tdesc->word = temp = (char *)NULL;
7157 }
7158
7159 }
7160
7161 ret = tdesc;
7162 goto return0;
7163
7164 /* Do command or arithmetic substitution. */
7165 case LPAREN:
7166 /* We have to extract the contents of this paren substitution. */
7167 t_index = zindex + 1;
7168 temp = extract_command_subst (string, &t_index, 0);
7169 zindex = t_index;
7170
7171 /* For Posix.2-style `$(( ))' arithmetic substitution,
7172 extract the expression and pass it to the evaluator. */
7173 if (temp && *temp == LPAREN)
7174 {
7175 char *temp2;
7176 temp1 = temp + 1;
7177 temp2 = savestring (temp1);
7178 t_index = strlen (temp2) - 1;
7179
7180 if (temp2[t_index] != RPAREN)
7181 {
7182 free (temp2);
7183 goto comsub;
7184 }
7185
7186 /* Cut off ending `)' */
7187 temp2[t_index] = '\0';
7188
7189 if (chk_arithsub (temp2, t_index) == 0)
7190 {
7191 free (temp2);
7192 goto comsub;
7193 }
7194
7195 /* Expand variables found inside the expression. */
7196 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7197 free (temp2);
7198
7199 arithsub:
7200 /* No error messages. */
7201 this_command_name = (char *)NULL;
7202 number = evalexp (temp1, &expok);
7203 free (temp);
7204 free (temp1);
7205 if (expok == 0)
7206 {
7207 if (interactive_shell == 0 && posixly_correct)
7208 {
7209 last_command_exit_value = EXECUTION_FAILURE;
7210 return (&expand_wdesc_fatal);
7211 }
7212 else
7213 return (&expand_wdesc_error);
7214 }
7215 temp = itos (number);
7216 break;
7217 }
7218
7219 comsub:
7220 if (pflags & PF_NOCOMSUB)
7221 /* we need zindex+1 because string[zindex] == RPAREN */
7222 temp1 = substring (string, *sindex, zindex+1);
7223 else
7224 {
7225 tdesc = command_substitute (temp, quoted);
7226 temp1 = tdesc ? tdesc->word : (char *)NULL;
7227 if (tdesc)
7228 dispose_word_desc (tdesc);
7229 }
7230 FREE (temp);
7231 temp = temp1;
7232 break;
7233
7234 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7235 away in a future bash release. */
7236 case '[':
7237 /* Extract the contents of this arithmetic substitution. */
7238 t_index = zindex + 1;
7239 temp = extract_arithmetic_subst (string, &t_index);
7240 zindex = t_index;
7241 if (temp == 0)
7242 {
7243 temp = savestring (string);
7244 if (expanded_something)
7245 *expanded_something = 0;
7246 goto return0;
7247 }
7248
7249 /* Do initial variable expansion. */
7250 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7251
7252 goto arithsub;
7253
7254 default:
7255 /* Find the variable in VARIABLE_LIST. */
7256 temp = (char *)NULL;
7257
7258 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7259 ;
7260 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7261
7262 /* If this isn't a variable name, then just output the `$'. */
7263 if (temp1 == 0 || *temp1 == '\0')
7264 {
7265 FREE (temp1);
7266 temp = (char *)xmalloc (2);
7267 temp[0] = '$';
7268 temp[1] = '\0';
7269 if (expanded_something)
7270 *expanded_something = 0;
7271 goto return0;
7272 }
7273
7274 /* If the variable exists, return its value cell. */
7275 var = find_variable (temp1);
7276
7277 if (var && invisible_p (var) == 0 && var_isset (var))
7278 {
7279 #if defined (ARRAY_VARS)
7280 if (assoc_p (var) || array_p (var))
7281 {
7282 temp = array_p (var) ? array_reference (array_cell (var), 0)
7283 : assoc_reference (assoc_cell (var), "0");
7284 if (temp)
7285 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7286 ? quote_string (temp)
7287 : quote_escapes (temp);
7288 else if (unbound_vars_is_error)
7289 goto unbound_variable;
7290 }
7291 else
7292 #endif
7293 {
7294 temp = value_cell (var);
7295
7296 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7297 ? quote_string (temp)
7298 : quote_escapes (temp);
7299 }
7300
7301 free (temp1);
7302
7303 goto return0;
7304 }
7305
7306 temp = (char *)NULL;
7307
7308 unbound_variable:
7309 if (unbound_vars_is_error)
7310 {
7311 last_command_exit_value = EXECUTION_FAILURE;
7312 err_unboundvar (temp1);
7313 }
7314 else
7315 {
7316 free (temp1);
7317 goto return0;
7318 }
7319
7320 free (temp1);
7321 last_command_exit_value = EXECUTION_FAILURE;
7322 return ((unbound_vars_is_error && interactive_shell == 0)
7323 ? &expand_wdesc_fatal
7324 : &expand_wdesc_error);
7325 }
7326
7327 if (string[zindex])
7328 zindex++;
7329
7330 return0:
7331 *sindex = zindex;
7332
7333 if (ret == 0)
7334 {
7335 ret = alloc_word_desc ();
7336 ret->flags = tflag; /* XXX */
7337 ret->word = temp;
7338 }
7339 return ret;
7340 }
7341
7342 /* Make a word list which is the result of parameter and variable
7343 expansion, command substitution, arithmetic substitution, and
7344 quote removal of WORD. Return a pointer to a WORD_LIST which is
7345 the result of the expansion. If WORD contains a null word, the
7346 word list returned is also null.
7347
7348 QUOTED contains flag values defined in shell.h.
7349
7350 ISEXP is used to tell expand_word_internal that the word should be
7351 treated as the result of an expansion. This has implications for
7352 how IFS characters in the word are treated.
7353
7354 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7355 they point to an integer value which receives information about expansion.
7356 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7357 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7358 else zero.
7359
7360 This only does word splitting in the case of $@ expansion. In that
7361 case, we split on ' '. */
7362
7363 /* Values for the local variable quoted_state. */
7364 #define UNQUOTED 0
7365 #define PARTIALLY_QUOTED 1
7366 #define WHOLLY_QUOTED 2
7367
7368 static WORD_LIST *
7369 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7370 WORD_DESC *word;
7371 int quoted, isexp;
7372 int *contains_dollar_at;
7373 int *expanded_something;
7374 {
7375 WORD_LIST *list;
7376 WORD_DESC *tword;
7377
7378 /* The intermediate string that we build while expanding. */
7379 char *istring;
7380
7381 /* The current size of the above object. */
7382 int istring_size;
7383
7384 /* Index into ISTRING. */
7385 int istring_index;
7386
7387 /* Temporary string storage. */
7388 char *temp, *temp1;
7389
7390 /* The text of WORD. */
7391 register char *string;
7392
7393 /* The size of STRING. */
7394 size_t string_size;
7395
7396 /* The index into STRING. */
7397 int sindex;
7398
7399 /* This gets 1 if we see a $@ while quoted. */
7400 int quoted_dollar_at;
7401
7402 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7403 whether WORD contains no quoting characters, a partially quoted
7404 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7405 int quoted_state;
7406
7407 /* State flags */
7408 int had_quoted_null;
7409 int has_dollar_at;
7410 int tflag;
7411
7412 int assignoff; /* If assignment, offset of `=' */
7413
7414 register unsigned char c; /* Current character. */
7415 int t_index; /* For calls to string_extract_xxx. */
7416
7417 char twochars[2];
7418
7419 DECLARE_MBSTATE;
7420
7421 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7422 istring[istring_index = 0] = '\0';
7423 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7424 quoted_state = UNQUOTED;
7425
7426 string = word->word;
7427 if (string == 0)
7428 goto finished_with_string;
7429 /* Don't need the string length for the SADD... and COPY_ macros unless
7430 multibyte characters are possible. */
7431 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7432
7433 if (contains_dollar_at)
7434 *contains_dollar_at = 0;
7435
7436 assignoff = -1;
7437
7438 /* Begin the expansion. */
7439
7440 for (sindex = 0; ;)
7441 {
7442 c = string[sindex];
7443
7444 /* Case on toplevel character. */
7445 switch (c)
7446 {
7447 case '\0':
7448 goto finished_with_string;
7449
7450 case CTLESC:
7451 sindex++;
7452 #if HANDLE_MULTIBYTE
7453 if (MB_CUR_MAX > 1 && string[sindex])
7454 {
7455 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7456 }
7457 else
7458 #endif
7459 {
7460 temp = (char *)xmalloc (3);
7461 temp[0] = CTLESC;
7462 temp[1] = c = string[sindex];
7463 temp[2] = '\0';
7464 }
7465
7466 dollar_add_string:
7467 if (string[sindex])
7468 sindex++;
7469
7470 add_string:
7471 if (temp)
7472 {
7473 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7474 temp = (char *)0;
7475 }
7476
7477 break;
7478
7479 #if defined (PROCESS_SUBSTITUTION)
7480 /* Process substitution. */
7481 case '<':
7482 case '>':
7483 {
7484 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7485 {
7486 sindex--; /* add_character: label increments sindex */
7487 goto add_character;
7488 }
7489 else
7490 t_index = sindex + 1; /* skip past both '<' and LPAREN */
7491
7492 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7493 sindex = t_index;
7494
7495 /* If the process substitution specification is `<()', we want to
7496 open the pipe for writing in the child and produce output; if
7497 it is `>()', we want to open the pipe for reading in the child
7498 and consume input. */
7499 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
7500
7501 FREE (temp1);
7502
7503 goto dollar_add_string;
7504 }
7505 #endif /* PROCESS_SUBSTITUTION */
7506
7507 case '=':
7508 /* Posix.2 section 3.6.1 says that tildes following `=' in words
7509 which are not assignment statements are not expanded. If the
7510 shell isn't in posix mode, though, we perform tilde expansion
7511 on `likely candidate' unquoted assignment statements (flags
7512 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
7513 contains an unquoted :~ or =~. Something to think about: we
7514 now have a flag that says to perform tilde expansion on arguments
7515 to `assignment builtins' like declare and export that look like
7516 assignment statements. We now do tilde expansion on such words
7517 even in POSIX mode. */
7518 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
7519 {
7520 if (isexp == 0 && isifs (c))
7521 goto add_ifs_character;
7522 else
7523 goto add_character;
7524 }
7525 /* If we're not in posix mode or forcing assignment-statement tilde
7526 expansion, note where the `=' appears in the word and prepare to
7527 do tilde expansion following the first `='. */
7528 if ((word->flags & W_ASSIGNMENT) &&
7529 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7530 assignoff == -1 && sindex > 0)
7531 assignoff = sindex;
7532 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
7533 word->flags |= W_ITILDE;
7534 #if 0
7535 else if ((word->flags & W_ASSIGNMENT) &&
7536 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
7537 string[sindex+1] == '~')
7538 word->flags |= W_ITILDE;
7539 #endif
7540 if (isexp == 0 && isifs (c))
7541 goto add_ifs_character;
7542 else
7543 goto add_character;
7544
7545 case ':':
7546 if (word->flags & W_NOTILDE)
7547 {
7548 if (isexp == 0 && isifs (c))
7549 goto add_ifs_character;
7550 else
7551 goto add_character;
7552 }
7553
7554 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
7555 string[sindex+1] == '~')
7556 word->flags |= W_ITILDE;
7557
7558 if (isexp == 0 && isifs (c))
7559 goto add_ifs_character;
7560 else
7561 goto add_character;
7562
7563 case '~':
7564 /* If the word isn't supposed to be tilde expanded, or we're not
7565 at the start of a word or after an unquoted : or = in an
7566 assignment statement, we don't do tilde expansion. */
7567 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
7568 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
7569 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7570 {
7571 word->flags &= ~W_ITILDE;
7572 if (isexp == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
7573 goto add_ifs_character;
7574 else
7575 goto add_character;
7576 }
7577
7578 if (word->flags & W_ASSIGNRHS)
7579 tflag = 2;
7580 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
7581 tflag = 1;
7582 else
7583 tflag = 0;
7584
7585 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
7586
7587 word->flags &= ~W_ITILDE;
7588
7589 if (temp && *temp && t_index > 0)
7590 {
7591 temp1 = bash_tilde_expand (temp, tflag);
7592 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
7593 {
7594 FREE (temp);
7595 FREE (temp1);
7596 goto add_character; /* tilde expansion failed */
7597 }
7598 free (temp);
7599 temp = temp1;
7600 sindex += t_index;
7601 goto add_quoted_string; /* XXX was add_string */
7602 }
7603 else
7604 {
7605 FREE (temp);
7606 goto add_character;
7607 }
7608
7609 case '$':
7610 if (expanded_something)
7611 *expanded_something = 1;
7612
7613 has_dollar_at = 0;
7614 tword = param_expand (string, &sindex, quoted, expanded_something,
7615 &has_dollar_at, &quoted_dollar_at,
7616 &had_quoted_null,
7617 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
7618
7619 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
7620 {
7621 free (string);
7622 free (istring);
7623 return ((tword == &expand_wdesc_error) ? &expand_word_error
7624 : &expand_word_fatal);
7625 }
7626 if (contains_dollar_at && has_dollar_at)
7627 *contains_dollar_at = 1;
7628
7629 if (tword && (tword->flags & W_HASQUOTEDNULL))
7630 had_quoted_null = 1;
7631
7632 temp = tword->word;
7633 dispose_word_desc (tword);
7634
7635 goto add_string;
7636 break;
7637
7638 case '`': /* Backquoted command substitution. */
7639 {
7640 t_index = sindex++;
7641
7642 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
7643 /* The test of sindex against t_index is to allow bare instances of
7644 ` to pass through, for backwards compatibility. */
7645 if (temp == &extract_string_error || temp == &extract_string_fatal)
7646 {
7647 if (sindex - 1 == t_index)
7648 {
7649 sindex = t_index;
7650 goto add_character;
7651 }
7652 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
7653 free (string);
7654 free (istring);
7655 return ((temp == &extract_string_error) ? &expand_word_error
7656 : &expand_word_fatal);
7657 }
7658
7659 if (expanded_something)
7660 *expanded_something = 1;
7661
7662 if (word->flags & W_NOCOMSUB)
7663 /* sindex + 1 because string[sindex] == '`' */
7664 temp1 = substring (string, t_index, sindex + 1);
7665 else
7666 {
7667 de_backslash (temp);
7668 tword = command_substitute (temp, quoted);
7669 temp1 = tword ? tword->word : (char *)NULL;
7670 if (tword)
7671 dispose_word_desc (tword);
7672 }
7673 FREE (temp);
7674 temp = temp1;
7675 goto dollar_add_string;
7676 }
7677
7678 case '\\':
7679 if (string[sindex + 1] == '\n')
7680 {
7681 sindex += 2;
7682 continue;
7683 }
7684
7685 c = string[++sindex];
7686
7687 if (quoted & Q_HERE_DOCUMENT)
7688 tflag = CBSHDOC;
7689 else if (quoted & Q_DOUBLE_QUOTES)
7690 tflag = CBSDQUOTE;
7691 else
7692 tflag = 0;
7693
7694 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
7695 {
7696 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
7697 }
7698 else if (c == 0)
7699 {
7700 c = CTLNUL;
7701 sindex--; /* add_character: label increments sindex */
7702 goto add_character;
7703 }
7704 else
7705 {
7706 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
7707 }
7708
7709 sindex++;
7710 add_twochars:
7711 /* BEFORE jumping here, we need to increment sindex if appropriate */
7712 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
7713 DEFAULT_ARRAY_SIZE);
7714 istring[istring_index++] = twochars[0];
7715 istring[istring_index++] = twochars[1];
7716 istring[istring_index] = '\0';
7717
7718 break;
7719
7720 case '"':
7721 #if 0
7722 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7723 #else
7724 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7725 #endif
7726 goto add_character;
7727
7728 t_index = ++sindex;
7729 temp = string_extract_double_quoted (string, &sindex, 0);
7730
7731 /* If the quotes surrounded the entire string, then the
7732 whole word was quoted. */
7733 quoted_state = (t_index == 1 && string[sindex] == '\0')
7734 ? WHOLLY_QUOTED
7735 : PARTIALLY_QUOTED;
7736
7737 if (temp && *temp)
7738 {
7739 tword = alloc_word_desc ();
7740 tword->word = temp;
7741
7742 temp = (char *)NULL;
7743
7744 has_dollar_at = 0;
7745 /* Need to get W_HASQUOTEDNULL flag through this function. */
7746 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
7747
7748 if (list == &expand_word_error || list == &expand_word_fatal)
7749 {
7750 free (istring);
7751 free (string);
7752 /* expand_word_internal has already freed temp_word->word
7753 for us because of the way it prints error messages. */
7754 tword->word = (char *)NULL;
7755 dispose_word (tword);
7756 return list;
7757 }
7758
7759 dispose_word (tword);
7760
7761 /* "$@" (a double-quoted dollar-at) expands into nothing,
7762 not even a NULL word, when there are no positional
7763 parameters. */
7764 if (list == 0 && has_dollar_at)
7765 {
7766 quoted_dollar_at++;
7767 break;
7768 }
7769
7770 /* If we get "$@", we know we have expanded something, so we
7771 need to remember it for the final split on $IFS. This is
7772 a special case; it's the only case where a quoted string
7773 can expand into more than one word. It's going to come back
7774 from the above call to expand_word_internal as a list with
7775 a single word, in which all characters are quoted and
7776 separated by blanks. What we want to do is to turn it back
7777 into a list for the next piece of code. */
7778 if (list)
7779 dequote_list (list);
7780
7781 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
7782 had_quoted_null = 1;
7783
7784 if (has_dollar_at)
7785 {
7786 quoted_dollar_at++;
7787 if (contains_dollar_at)
7788 *contains_dollar_at = 1;
7789 if (expanded_something)
7790 *expanded_something = 1;
7791 }
7792 }
7793 else
7794 {
7795 /* What we have is "". This is a minor optimization. */
7796 FREE (temp);
7797 list = (WORD_LIST *)NULL;
7798 }
7799
7800 /* The code above *might* return a list (consider the case of "$@",
7801 where it returns "$1", "$2", etc.). We can't throw away the
7802 rest of the list, and we have to make sure each word gets added
7803 as quoted. We test on tresult->next: if it is non-NULL, we
7804 quote the whole list, save it to a string with string_list, and
7805 add that string. We don't need to quote the results of this
7806 (and it would be wrong, since that would quote the separators
7807 as well), so we go directly to add_string. */
7808 if (list)
7809 {
7810 if (list->next)
7811 {
7812 /* Testing quoted_dollar_at makes sure that "$@" is
7813 split correctly when $IFS does not contain a space. */
7814 temp = quoted_dollar_at
7815 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7816 : string_list (quote_list (list));
7817 dispose_words (list);
7818 goto add_string;
7819 }
7820 else
7821 {
7822 temp = savestring (list->word->word);
7823 tflag = list->word->flags;
7824 dispose_words (list);
7825
7826 /* If the string is not a quoted null string, we want
7827 to remove any embedded unquoted CTLNUL characters.
7828 We do not want to turn quoted null strings back into
7829 the empty string, though. We do this because we
7830 want to remove any quoted nulls from expansions that
7831 contain other characters. For example, if we have
7832 x"$*"y or "x$*y" and there are no positional parameters,
7833 the $* should expand into nothing. */
7834 /* We use the W_HASQUOTEDNULL flag to differentiate the
7835 cases: a quoted null character as above and when
7836 CTLNUL is contained in the (non-null) expansion
7837 of some variable. We use the had_quoted_null flag to
7838 pass the value through this function to its caller. */
7839 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7840 remove_quoted_nulls (temp); /* XXX */
7841 }
7842 }
7843 else
7844 temp = (char *)NULL;
7845
7846 /* We do not want to add quoted nulls to strings that are only
7847 partially quoted; we can throw them away. */
7848 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7849 continue;
7850
7851 add_quoted_string:
7852
7853 if (temp)
7854 {
7855 temp1 = temp;
7856 temp = quote_string (temp);
7857 free (temp1);
7858 goto add_string;
7859 }
7860 else
7861 {
7862 /* Add NULL arg. */
7863 c = CTLNUL;
7864 sindex--; /* add_character: label increments sindex */
7865 goto add_character;
7866 }
7867
7868 /* break; */
7869
7870 case '\'':
7871 #if 0
7872 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7873 #else
7874 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7875 #endif
7876 goto add_character;
7877
7878 t_index = ++sindex;
7879 temp = string_extract_single_quoted (string, &sindex);
7880
7881 /* If the entire STRING was surrounded by single quotes,
7882 then the string is wholly quoted. */
7883 quoted_state = (t_index == 1 && string[sindex] == '\0')
7884 ? WHOLLY_QUOTED
7885 : PARTIALLY_QUOTED;
7886
7887 /* If all we had was '', it is a null expansion. */
7888 if (*temp == '\0')
7889 {
7890 free (temp);
7891 temp = (char *)NULL;
7892 }
7893 else
7894 remove_quoted_escapes (temp); /* ??? */
7895
7896 /* We do not want to add quoted nulls to strings that are only
7897 partially quoted; such nulls are discarded. */
7898 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7899 continue;
7900
7901 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7902 if (temp == 0)
7903 {
7904 c = CTLNUL;
7905 sindex--; /* add_character: label increments sindex */
7906 goto add_character;
7907 }
7908 else
7909 goto add_quoted_string;
7910
7911 /* break; */
7912
7913 default:
7914 /* This is the fix for " $@ " */
7915 add_ifs_character:
7916 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7917 {
7918 if (string[sindex]) /* from old goto dollar_add_string */
7919 sindex++;
7920 if (c == 0)
7921 {
7922 c = CTLNUL;
7923 goto add_character;
7924 }
7925 else
7926 {
7927 #if HANDLE_MULTIBYTE
7928 if (MB_CUR_MAX > 1)
7929 sindex--;
7930
7931 if (MB_CUR_MAX > 1)
7932 {
7933 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7934 }
7935 else
7936 #endif
7937 {
7938 twochars[0] = CTLESC;
7939 twochars[1] = c;
7940 goto add_twochars;
7941 }
7942 }
7943 }
7944
7945 SADD_MBCHAR (temp, string, sindex, string_size);
7946
7947 add_character:
7948 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7949 DEFAULT_ARRAY_SIZE);
7950 istring[istring_index++] = c;
7951 istring[istring_index] = '\0';
7952
7953 /* Next character. */
7954 sindex++;
7955 }
7956 }
7957
7958 finished_with_string:
7959 /* OK, we're ready to return. If we have a quoted string, and
7960 quoted_dollar_at is not set, we do no splitting at all; otherwise
7961 we split on ' '. The routines that call this will handle what to
7962 do if nothing has been expanded. */
7963
7964 /* Partially and wholly quoted strings which expand to the empty
7965 string are retained as an empty arguments. Unquoted strings
7966 which expand to the empty string are discarded. The single
7967 exception is the case of expanding "$@" when there are no
7968 positional parameters. In that case, we discard the expansion. */
7969
7970 /* Because of how the code that handles "" and '' in partially
7971 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7972 if we saw quoting characters, but the expansion was empty.
7973 "" and '' are tossed away before we get to this point when
7974 processing partially quoted strings. This makes "" and $xxx""
7975 equivalent when xxx is unset. We also look to see whether we
7976 saw a quoted null from a ${} expansion and add one back if we
7977 need to. */
7978
7979 /* If we expand to nothing and there were no single or double quotes
7980 in the word, we throw it away. Otherwise, we return a NULL word.
7981 The single exception is for $@ surrounded by double quotes when
7982 there are no positional parameters. In that case, we also throw
7983 the word away. */
7984
7985 if (*istring == '\0')
7986 {
7987 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7988 {
7989 istring[0] = CTLNUL;
7990 istring[1] = '\0';
7991 tword = make_bare_word (istring);
7992 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7993 list = make_word_list (tword, (WORD_LIST *)NULL);
7994 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7995 tword->flags |= W_QUOTED;
7996 }
7997 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7998 and a double-quoted "$@" appears anywhere in it, then the entire
7999 word is removed. */
8000 else if (quoted_state == UNQUOTED || quoted_dollar_at)
8001 list = (WORD_LIST *)NULL;
8002 #if 0
8003 else
8004 {
8005 tword = make_bare_word (istring);
8006 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8007 tword->flags |= W_QUOTED;
8008 list = make_word_list (tword, (WORD_LIST *)NULL);
8009 }
8010 #else
8011 else
8012 list = (WORD_LIST *)NULL;
8013 #endif
8014 }
8015 else if (word->flags & W_NOSPLIT)
8016 {
8017 tword = make_bare_word (istring);
8018 if (word->flags & W_ASSIGNMENT)
8019 tword->flags |= W_ASSIGNMENT; /* XXX */
8020 if (word->flags & W_COMPASSIGN)
8021 tword->flags |= W_COMPASSIGN; /* XXX */
8022 if (word->flags & W_NOGLOB)
8023 tword->flags |= W_NOGLOB; /* XXX */
8024 if (word->flags & W_NOEXPAND)
8025 tword->flags |= W_NOEXPAND; /* XXX */
8026 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8027 tword->flags |= W_QUOTED;
8028 if (had_quoted_null)
8029 tword->flags |= W_HASQUOTEDNULL;
8030 list = make_word_list (tword, (WORD_LIST *)NULL);
8031 }
8032 else
8033 {
8034 char *ifs_chars;
8035
8036 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
8037
8038 /* If we have $@, we need to split the results no matter what. If
8039 IFS is unset or NULL, string_list_dollar_at has separated the
8040 positional parameters with a space, so we split on space (we have
8041 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
8042 string_list_dollar_at has separated the positional parameters
8043 with the first character of $IFS, so we split on $IFS. */
8044 if (has_dollar_at && ifs_chars)
8045 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
8046 else
8047 {
8048 tword = make_bare_word (istring);
8049 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8050 tword->flags |= W_QUOTED;
8051 if (word->flags & W_ASSIGNMENT)
8052 tword->flags |= W_ASSIGNMENT;
8053 if (word->flags & W_COMPASSIGN)
8054 tword->flags |= W_COMPASSIGN;
8055 if (word->flags & W_NOGLOB)
8056 tword->flags |= W_NOGLOB;
8057 if (word->flags & W_NOEXPAND)
8058 tword->flags |= W_NOEXPAND;
8059 if (had_quoted_null)
8060 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8061 list = make_word_list (tword, (WORD_LIST *)NULL);
8062 }
8063 }
8064
8065 free (istring);
8066 return (list);
8067 }
8068
8069 /* **************************************************************** */
8070 /* */
8071 /* Functions for Quote Removal */
8072 /* */
8073 /* **************************************************************** */
8074
8075 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
8076 backslash quoting rules for within double quotes or a here document. */
8077 char *
8078 string_quote_removal (string, quoted)
8079 char *string;
8080 int quoted;
8081 {
8082 size_t slen;
8083 char *r, *result_string, *temp, *send;
8084 int sindex, tindex, dquote;
8085 unsigned char c;
8086 DECLARE_MBSTATE;
8087
8088 /* The result can be no longer than the original string. */
8089 slen = strlen (string);
8090 send = string + slen;
8091
8092 r = result_string = (char *)xmalloc (slen + 1);
8093
8094 for (dquote = sindex = 0; c = string[sindex];)
8095 {
8096 switch (c)
8097 {
8098 case '\\':
8099 c = string[++sindex];
8100 if (c == 0)
8101 {
8102 *r++ = '\\';
8103 break;
8104 }
8105 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8106 *r++ = '\\';
8107 /* FALLTHROUGH */
8108
8109 default:
8110 SCOPY_CHAR_M (r, string, send, sindex);
8111 break;
8112
8113 case '\'':
8114 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8115 {
8116 *r++ = c;
8117 sindex++;
8118 break;
8119 }
8120 tindex = sindex + 1;
8121 temp = string_extract_single_quoted (string, &tindex);
8122 if (temp)
8123 {
8124 strcpy (r, temp);
8125 r += strlen (r);
8126 free (temp);
8127 }
8128 sindex = tindex;
8129 break;
8130
8131 case '"':
8132 dquote = 1 - dquote;
8133 sindex++;
8134 break;
8135 }
8136 }
8137 *r = '\0';
8138 return (result_string);
8139 }
8140
8141 #if 0
8142 /* UNUSED */
8143 /* Perform quote removal on word WORD. This allocates and returns a new
8144 WORD_DESC *. */
8145 WORD_DESC *
8146 word_quote_removal (word, quoted)
8147 WORD_DESC *word;
8148 int quoted;
8149 {
8150 WORD_DESC *w;
8151 char *t;
8152
8153 t = string_quote_removal (word->word, quoted);
8154 w = alloc_word_desc ();
8155 w->word = t ? t : savestring ("");
8156 return (w);
8157 }
8158
8159 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8160 the members of the list are treated as if they are surrounded by
8161 double quotes. Return a new list, or NULL if LIST is NULL. */
8162 WORD_LIST *
8163 word_list_quote_removal (list, quoted)
8164 WORD_LIST *list;
8165 int quoted;
8166 {
8167 WORD_LIST *result, *t, *tresult, *e;
8168
8169 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8170 {
8171 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8172 #if 0
8173 result = (WORD_LIST *) list_append (result, tresult);
8174 #else
8175 if (result == 0)
8176 result = e = tresult;
8177 else
8178 {
8179 e->next = tresult;
8180 while (e->next)
8181 e = e->next;
8182 }
8183 #endif
8184 }
8185 return (result);
8186 }
8187 #endif
8188
8189 /*******************************************
8190 * *
8191 * Functions to perform word splitting *
8192 * *
8193 *******************************************/
8194
8195 void
8196 setifs (v)
8197 SHELL_VAR *v;
8198 {
8199 char *t;
8200 unsigned char uc;
8201
8202 ifs_var = v;
8203 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8204
8205 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8206 handle multibyte chars in IFS */
8207 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8208 for (t = ifs_value ; t && *t; t++)
8209 {
8210 uc = *t;
8211 ifs_cmap[uc] = 1;
8212 }
8213
8214 #if defined (HANDLE_MULTIBYTE)
8215 if (ifs_value == 0)
8216 {
8217 ifs_firstc[0] = '\0';
8218 ifs_firstc_len = 1;
8219 }
8220 else
8221 {
8222 size_t ifs_len;
8223 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8224 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8225 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8226 {
8227 ifs_firstc[0] = ifs_value[0];
8228 ifs_firstc[1] = '\0';
8229 ifs_firstc_len = 1;
8230 }
8231 else
8232 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8233 }
8234 #else
8235 ifs_firstc = ifs_value ? *ifs_value : 0;
8236 #endif
8237 }
8238
8239 char *
8240 getifs ()
8241 {
8242 return ifs_value;
8243 }
8244
8245 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8246 is not quoted. list_string () performs quote removal for us, even if we
8247 don't do any splitting. */
8248 WORD_LIST *
8249 word_split (w, ifs_chars)
8250 WORD_DESC *w;
8251 char *ifs_chars;
8252 {
8253 WORD_LIST *result;
8254
8255 if (w)
8256 {
8257 char *xifs;
8258
8259 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8260 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8261 }
8262 else
8263 result = (WORD_LIST *)NULL;
8264
8265 return (result);
8266 }
8267
8268 /* Perform word splitting on LIST and return the RESULT. It is possible
8269 to return (WORD_LIST *)NULL. */
8270 static WORD_LIST *
8271 word_list_split (list)
8272 WORD_LIST *list;
8273 {
8274 WORD_LIST *result, *t, *tresult, *e;
8275
8276 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8277 {
8278 tresult = word_split (t->word, ifs_value);
8279 if (result == 0)
8280 result = e = tresult;
8281 else
8282 {
8283 e->next = tresult;
8284 while (e->next)
8285 e = e->next;
8286 }
8287 }
8288 return (result);
8289 }
8290
8291 /**************************************************
8292 * *
8293 * Functions to expand an entire WORD_LIST *
8294 * *
8295 **************************************************/
8296
8297 /* Do any word-expansion-specific cleanup and jump to top_level */
8298 static void
8299 exp_jump_to_top_level (v)
8300 int v;
8301 {
8302 set_pipestatus_from_exit (last_command_exit_value);
8303
8304 /* Cleanup code goes here. */
8305 expand_no_split_dollar_star = 0; /* XXX */
8306 expanding_redir = 0;
8307 assigning_in_environment = 0;
8308
8309 if (parse_and_execute_level == 0)
8310 top_level_cleanup (); /* from sig.c */
8311
8312 jump_to_top_level (v);
8313 }
8314
8315 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8316 ELIST, and set ELIST to the new list. */
8317 #define PREPEND_LIST(nlist, elist) \
8318 do { nlist->next = elist; elist = nlist; } while (0)
8319
8320 /* Separate out any initial variable assignments from TLIST. If set -k has
8321 been executed, remove all assignment statements from TLIST. Initial
8322 variable assignments and other environment assignments are placed
8323 on SUBST_ASSIGN_VARLIST. */
8324 static WORD_LIST *
8325 separate_out_assignments (tlist)
8326 WORD_LIST *tlist;
8327 {
8328 register WORD_LIST *vp, *lp;
8329
8330 if (!tlist)
8331 return ((WORD_LIST *)NULL);
8332
8333 if (subst_assign_varlist)
8334 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8335
8336 subst_assign_varlist = (WORD_LIST *)NULL;
8337 vp = lp = tlist;
8338
8339 /* Separate out variable assignments at the start of the command.
8340 Loop invariant: vp->next == lp
8341 Loop postcondition:
8342 lp = list of words left after assignment statements skipped
8343 tlist = original list of words
8344 */
8345 while (lp && (lp->word->flags & W_ASSIGNMENT))
8346 {
8347 vp = lp;
8348 lp = lp->next;
8349 }
8350
8351 /* If lp != tlist, we have some initial assignment statements.
8352 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8353 words and TLIST point to the remaining words. */
8354 if (lp != tlist)
8355 {
8356 subst_assign_varlist = tlist;
8357 /* ASSERT(vp->next == lp); */
8358 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8359 tlist = lp; /* remainder of word list */
8360 }
8361
8362 /* vp == end of variable list */
8363 /* tlist == remainder of original word list without variable assignments */
8364 if (!tlist)
8365 /* All the words in tlist were assignment statements */
8366 return ((WORD_LIST *)NULL);
8367
8368 /* ASSERT(tlist != NULL); */
8369 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8370
8371 /* If the -k option is in effect, we need to go through the remaining
8372 words, separate out the assignment words, and place them on
8373 SUBST_ASSIGN_VARLIST. */
8374 if (place_keywords_in_env)
8375 {
8376 WORD_LIST *tp; /* tp == running pointer into tlist */
8377
8378 tp = tlist;
8379 lp = tlist->next;
8380
8381 /* Loop Invariant: tp->next == lp */
8382 /* Loop postcondition: tlist == word list without assignment statements */
8383 while (lp)
8384 {
8385 if (lp->word->flags & W_ASSIGNMENT)
8386 {
8387 /* Found an assignment statement, add this word to end of
8388 subst_assign_varlist (vp). */
8389 if (!subst_assign_varlist)
8390 subst_assign_varlist = vp = lp;
8391 else
8392 {
8393 vp->next = lp;
8394 vp = lp;
8395 }
8396
8397 /* Remove the word pointed to by LP from TLIST. */
8398 tp->next = lp->next;
8399 /* ASSERT(vp == lp); */
8400 lp->next = (WORD_LIST *)NULL;
8401 lp = tp->next;
8402 }
8403 else
8404 {
8405 tp = lp;
8406 lp = lp->next;
8407 }
8408 }
8409 }
8410 return (tlist);
8411 }
8412
8413 #define WEXP_VARASSIGN 0x001
8414 #define WEXP_BRACEEXP 0x002
8415 #define WEXP_TILDEEXP 0x004
8416 #define WEXP_PARAMEXP 0x008
8417 #define WEXP_PATHEXP 0x010
8418
8419 /* All of the expansions, including variable assignments at the start of
8420 the list. */
8421 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8422
8423 /* All of the expansions except variable assignments at the start of
8424 the list. */
8425 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8426
8427 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8428 expansion, command substitution, arithmetic expansion, word splitting, and
8429 quote removal. */
8430 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8431
8432 /* Take the list of words in LIST and do the various substitutions. Return
8433 a new list of words which is the expanded list, and without things like
8434 variable assignments. */
8435
8436 WORD_LIST *
8437 expand_words (list)
8438 WORD_LIST *list;
8439 {
8440 return (expand_word_list_internal (list, WEXP_ALL));
8441 }
8442
8443 /* Same as expand_words (), but doesn't hack variable or environment
8444 variables. */
8445 WORD_LIST *
8446 expand_words_no_vars (list)
8447 WORD_LIST *list;
8448 {
8449 return (expand_word_list_internal (list, WEXP_NOVARS));
8450 }
8451
8452 WORD_LIST *
8453 expand_words_shellexp (list)
8454 WORD_LIST *list;
8455 {
8456 return (expand_word_list_internal (list, WEXP_SHELLEXP));
8457 }
8458
8459 static WORD_LIST *
8460 glob_expand_word_list (tlist, eflags)
8461 WORD_LIST *tlist;
8462 int eflags;
8463 {
8464 char **glob_array, *temp_string;
8465 register int glob_index;
8466 WORD_LIST *glob_list, *output_list, *disposables, *next;
8467 WORD_DESC *tword;
8468
8469 output_list = disposables = (WORD_LIST *)NULL;
8470 glob_array = (char **)NULL;
8471 while (tlist)
8472 {
8473 /* For each word, either globbing is attempted or the word is
8474 added to orig_list. If globbing succeeds, the results are
8475 added to orig_list and the word (tlist) is added to the list
8476 of disposable words. If globbing fails and failed glob
8477 expansions are left unchanged (the shell default), the
8478 original word is added to orig_list. If globbing fails and
8479 failed glob expansions are removed, the original word is
8480 added to the list of disposable words. orig_list ends up
8481 in reverse order and requires a call to REVERSE_LIST to
8482 be set right. After all words are examined, the disposable
8483 words are freed. */
8484 next = tlist->next;
8485
8486 /* If the word isn't an assignment and contains an unquoted
8487 pattern matching character, then glob it. */
8488 if ((tlist->word->flags & W_NOGLOB) == 0 &&
8489 unquoted_glob_pattern_p (tlist->word->word))
8490 {
8491 glob_array = shell_glob_filename (tlist->word->word);
8492
8493 /* Handle error cases.
8494 I don't think we should report errors like "No such file
8495 or directory". However, I would like to report errors
8496 like "Read failed". */
8497
8498 if (glob_array == 0 || GLOB_FAILED (glob_array))
8499 {
8500 glob_array = (char **)xmalloc (sizeof (char *));
8501 glob_array[0] = (char *)NULL;
8502 }
8503
8504 /* Dequote the current word in case we have to use it. */
8505 if (glob_array[0] == NULL)
8506 {
8507 temp_string = dequote_string (tlist->word->word);
8508 free (tlist->word->word);
8509 tlist->word->word = temp_string;
8510 }
8511
8512 /* Make the array into a word list. */
8513 glob_list = (WORD_LIST *)NULL;
8514 for (glob_index = 0; glob_array[glob_index]; glob_index++)
8515 {
8516 tword = make_bare_word (glob_array[glob_index]);
8517 tword->flags |= W_GLOBEXP; /* XXX */
8518 glob_list = make_word_list (tword, glob_list);
8519 }
8520
8521 if (glob_list)
8522 {
8523 output_list = (WORD_LIST *)list_append (glob_list, output_list);
8524 PREPEND_LIST (tlist, disposables);
8525 }
8526 else if (fail_glob_expansion != 0)
8527 {
8528 report_error (_("no match: %s"), tlist->word->word);
8529 exp_jump_to_top_level (DISCARD);
8530 }
8531 else if (allow_null_glob_expansion == 0)
8532 {
8533 /* Failed glob expressions are left unchanged. */
8534 PREPEND_LIST (tlist, output_list);
8535 }
8536 else
8537 {
8538 /* Failed glob expressions are removed. */
8539 PREPEND_LIST (tlist, disposables);
8540 }
8541 }
8542 else
8543 {
8544 /* Dequote the string. */
8545 temp_string = dequote_string (tlist->word->word);
8546 free (tlist->word->word);
8547 tlist->word->word = temp_string;
8548 PREPEND_LIST (tlist, output_list);
8549 }
8550
8551 strvec_dispose (glob_array);
8552 glob_array = (char **)NULL;
8553
8554 tlist = next;
8555 }
8556
8557 if (disposables)
8558 dispose_words (disposables);
8559
8560 if (output_list)
8561 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8562
8563 return (output_list);
8564 }
8565
8566 #if defined (BRACE_EXPANSION)
8567 static WORD_LIST *
8568 brace_expand_word_list (tlist, eflags)
8569 WORD_LIST *tlist;
8570 int eflags;
8571 {
8572 register char **expansions;
8573 char *temp_string;
8574 WORD_LIST *disposables, *output_list, *next;
8575 WORD_DESC *w;
8576 int eindex;
8577
8578 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
8579 {
8580 next = tlist->next;
8581
8582 /* Only do brace expansion if the word has a brace character. If
8583 not, just add the word list element to BRACES and continue. In
8584 the common case, at least when running shell scripts, this will
8585 degenerate to a bunch of calls to `mbschr', and then what is
8586 basically a reversal of TLIST into BRACES, which is corrected
8587 by a call to REVERSE_LIST () on BRACES when the end of TLIST
8588 is reached. */
8589 if (mbschr (tlist->word->word, LBRACE))
8590 {
8591 expansions = brace_expand (tlist->word->word);
8592
8593 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
8594 {
8595 w = make_word (temp_string);
8596 /* If brace expansion didn't change the word, preserve
8597 the flags. We may want to preserve the flags
8598 unconditionally someday -- XXX */
8599 if (STREQ (temp_string, tlist->word->word))
8600 w->flags = tlist->word->flags;
8601 output_list = make_word_list (w, output_list);
8602 free (expansions[eindex]);
8603 }
8604 free (expansions);
8605
8606 /* Add TLIST to the list of words to be freed after brace
8607 expansion has been performed. */
8608 PREPEND_LIST (tlist, disposables);
8609 }
8610 else
8611 PREPEND_LIST (tlist, output_list);
8612 }
8613
8614 if (disposables)
8615 dispose_words (disposables);
8616
8617 if (output_list)
8618 output_list = REVERSE_LIST (output_list, WORD_LIST *);
8619
8620 return (output_list);
8621 }
8622 #endif
8623
8624 #if defined (ARRAY_VARS)
8625 /* Take WORD, a compound associative array assignment, and internally run
8626 'declare -A w', where W is the variable name portion of WORD. */
8627 static int
8628 make_internal_declare (word, option)
8629 char *word;
8630 char *option;
8631 {
8632 int t;
8633 WORD_LIST *wl;
8634 WORD_DESC *w;
8635
8636 w = make_word (word);
8637
8638 t = assignment (w->word, 0);
8639 w->word[t] = '\0';
8640
8641 wl = make_word_list (w, (WORD_LIST *)NULL);
8642 wl = make_word_list (make_word (option), wl);
8643
8644 return (declare_builtin (wl));
8645 }
8646 #endif
8647
8648 static WORD_LIST *
8649 shell_expand_word_list (tlist, eflags)
8650 WORD_LIST *tlist;
8651 int eflags;
8652 {
8653 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
8654 int expanded_something, has_dollar_at;
8655 char *temp_string;
8656
8657 /* We do tilde expansion all the time. This is what 1003.2 says. */
8658 new_list = (WORD_LIST *)NULL;
8659 for (orig_list = tlist; tlist; tlist = next)
8660 {
8661 temp_string = tlist->word->word;
8662
8663 next = tlist->next;
8664
8665 #if defined (ARRAY_VARS)
8666 /* If this is a compound array assignment to a builtin that accepts
8667 such assignments (e.g., `declare'), take the assignment and perform
8668 it separately, handling the semantics of declarations inside shell
8669 functions. This avoids the double-evaluation of such arguments,
8670 because `declare' does some evaluation of compound assignments on
8671 its own. */
8672 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
8673 {
8674 int t;
8675
8676 if (tlist->word->flags & W_ASSIGNASSOC)
8677 make_internal_declare (tlist->word->word, "-A");
8678
8679 t = do_word_assignment (tlist->word);
8680 if (t == 0)
8681 {
8682 last_command_exit_value = EXECUTION_FAILURE;
8683 exp_jump_to_top_level (DISCARD);
8684 }
8685
8686 /* Now transform the word as ksh93 appears to do and go on */
8687 t = assignment (tlist->word->word, 0);
8688 tlist->word->word[t] = '\0';
8689 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
8690 }
8691 #endif
8692
8693 expanded_something = 0;
8694 expanded = expand_word_internal
8695 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
8696
8697 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
8698 {
8699 /* By convention, each time this error is returned,
8700 tlist->word->word has already been freed. */
8701 tlist->word->word = (char *)NULL;
8702
8703 /* Dispose our copy of the original list. */
8704 dispose_words (orig_list);
8705 /* Dispose the new list we're building. */
8706 dispose_words (new_list);
8707
8708 last_command_exit_value = EXECUTION_FAILURE;
8709 if (expanded == &expand_word_error)
8710 exp_jump_to_top_level (DISCARD);
8711 else
8712 exp_jump_to_top_level (FORCE_EOF);
8713 }
8714
8715 /* Don't split words marked W_NOSPLIT. */
8716 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
8717 {
8718 temp_list = word_list_split (expanded);
8719 dispose_words (expanded);
8720 }
8721 else
8722 {
8723 /* If no parameter expansion, command substitution, process
8724 substitution, or arithmetic substitution took place, then
8725 do not do word splitting. We still have to remove quoted
8726 null characters from the result. */
8727 word_list_remove_quoted_nulls (expanded);
8728 temp_list = expanded;
8729 }
8730
8731 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
8732 new_list = (WORD_LIST *)list_append (expanded, new_list);
8733 }
8734
8735 if (orig_list)
8736 dispose_words (orig_list);
8737
8738 if (new_list)
8739 new_list = REVERSE_LIST (new_list, WORD_LIST *);
8740
8741 return (new_list);
8742 }
8743
8744 /* The workhorse for expand_words () and expand_words_no_vars ().
8745 First arg is LIST, a WORD_LIST of words.
8746 Second arg EFLAGS is a flags word controlling which expansions are
8747 performed.
8748
8749 This does all of the substitutions: brace expansion, tilde expansion,
8750 parameter expansion, command substitution, arithmetic expansion,
8751 process substitution, word splitting, and pathname expansion, according
8752 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
8753 set, or for which no expansion is done, do not undergo word splitting.
8754 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
8755 static WORD_LIST *
8756 expand_word_list_internal (list, eflags)
8757 WORD_LIST *list;
8758 int eflags;
8759 {
8760 WORD_LIST *new_list, *temp_list;
8761 int tint;
8762
8763 if (list == 0)
8764 return ((WORD_LIST *)NULL);
8765
8766 garglist = new_list = copy_word_list (list);
8767 if (eflags & WEXP_VARASSIGN)
8768 {
8769 garglist = new_list = separate_out_assignments (new_list);
8770 if (new_list == 0)
8771 {
8772 if (subst_assign_varlist)
8773 {
8774 /* All the words were variable assignments, so they are placed
8775 into the shell's environment. */
8776 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8777 {
8778 this_command_name = (char *)NULL; /* no arithmetic errors */
8779 tint = do_word_assignment (temp_list->word);
8780 /* Variable assignment errors in non-interactive shells
8781 running in Posix.2 mode cause the shell to exit. */
8782 if (tint == 0)
8783 {
8784 last_command_exit_value = EXECUTION_FAILURE;
8785 if (interactive_shell == 0 && posixly_correct)
8786 exp_jump_to_top_level (FORCE_EOF);
8787 else
8788 exp_jump_to_top_level (DISCARD);
8789 }
8790 }
8791 dispose_words (subst_assign_varlist);
8792 subst_assign_varlist = (WORD_LIST *)NULL;
8793 }
8794 return ((WORD_LIST *)NULL);
8795 }
8796 }
8797
8798 /* Begin expanding the words that remain. The expansions take place on
8799 things that aren't really variable assignments. */
8800
8801 #if defined (BRACE_EXPANSION)
8802 /* Do brace expansion on this word if there are any brace characters
8803 in the string. */
8804 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
8805 new_list = brace_expand_word_list (new_list, eflags);
8806 #endif /* BRACE_EXPANSION */
8807
8808 /* Perform the `normal' shell expansions: tilde expansion, parameter and
8809 variable substitution, command substitution, arithmetic expansion,
8810 and word splitting. */
8811 new_list = shell_expand_word_list (new_list, eflags);
8812
8813 /* Okay, we're almost done. Now let's just do some filename
8814 globbing. */
8815 if (new_list)
8816 {
8817 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
8818 /* Glob expand the word list unless globbing has been disabled. */
8819 new_list = glob_expand_word_list (new_list, eflags);
8820 else
8821 /* Dequote the words, because we're not performing globbing. */
8822 new_list = dequote_list (new_list);
8823 }
8824
8825 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
8826 {
8827 sh_wassign_func_t *assign_func;
8828
8829 /* If the remainder of the words expand to nothing, Posix.2 requires
8830 that the variable and environment assignments affect the shell's
8831 environment. */
8832 assign_func = new_list ? assign_in_env : do_word_assignment;
8833 tempenv_assign_error = 0;
8834
8835 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8836 {
8837 this_command_name = (char *)NULL;
8838 assigning_in_environment = (assign_func == assign_in_env);
8839 tint = (*assign_func) (temp_list->word);
8840 assigning_in_environment = 0;
8841 /* Variable assignment errors in non-interactive shells running
8842 in Posix.2 mode cause the shell to exit. */
8843 if (tint == 0)
8844 {
8845 if (assign_func == do_word_assignment)
8846 {
8847 last_command_exit_value = EXECUTION_FAILURE;
8848 if (interactive_shell == 0 && posixly_correct)
8849 exp_jump_to_top_level (FORCE_EOF);
8850 else
8851 exp_jump_to_top_level (DISCARD);
8852 }
8853 else
8854 tempenv_assign_error++;
8855 }
8856 }
8857
8858 dispose_words (subst_assign_varlist);
8859 subst_assign_varlist = (WORD_LIST *)NULL;
8860 }
8861
8862 #if 0
8863 tint = list_length (new_list) + 1;
8864 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8865 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8866 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8867 glob_argv_flags[tint] = '\0';
8868 #endif
8869
8870 return (new_list);
8871 }