]> git.ipfire.org Git - thirdparty/bash.git/blob - subst.c
Imported from ../bash-2.05b.tar.gz.
[thirdparty/bash.git] / subst.c
1 /* subst.c -- The part of the shell that does parameter, command, and
2 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-2002 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 it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
14 version.
15
16 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
20
21 You should have received a copy of the GNU General Public License along
22 with Bash; see the file COPYING. If not, write to the Free Software
23 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
24
25 #include "config.h"
26
27 #include "bashtypes.h"
28 #include <stdio.h>
29 #include "chartypes.h"
30 #include <pwd.h>
31 #include <signal.h>
32 #include <errno.h>
33
34 #if defined (HAVE_UNISTD_H)
35 # include <unistd.h>
36 #endif
37
38 #include "bashansi.h"
39 #include "posixstat.h"
40
41 #include "shell.h"
42 #include "flags.h"
43 #include "jobs.h"
44 #include "execute_cmd.h"
45 #include "filecntl.h"
46 #include "trap.h"
47 #include "pathexp.h"
48 #include "mailcheck.h"
49
50 #include "shmbutil.h"
51
52 #include "builtins/getopt.h"
53 #include "builtins/common.h"
54
55 #include <tilde/tilde.h>
56 #include <glob/strmatch.h>
57
58 #if !defined (errno)
59 extern int errno;
60 #endif /* !errno */
61
62 /* The size that strings change by. */
63 #define DEFAULT_INITIAL_ARRAY_SIZE 112
64 #define DEFAULT_ARRAY_SIZE 128
65
66 /* Variable types. */
67 #define VT_VARIABLE 0
68 #define VT_POSPARMS 1
69 #define VT_ARRAYVAR 2
70 #define VT_ARRAYMEMBER 3
71
72 /* Flags for quoted_strchr */
73 #define ST_BACKSL 0x01
74 #define ST_CTLESC 0x02
75 #define ST_SQUOTE 0x04 /* unused yet */
76 #define ST_DQUOTE 0x08 /* unused yet */
77
78 /* Flags for the string extraction functions. */
79 #define EX_NOALLOC 0x01 /* just skip; don't return substring */
80 #define EX_VARNAME 0x02 /* variable name; for string_extract () */
81
82 /* These defs make it easier to use the editor. */
83 #define LBRACE '{'
84 #define RBRACE '}'
85 #define LPAREN '('
86 #define RPAREN ')'
87
88 /* Evaluates to 1 if C is one of the shell's special parameters whose length
89 can be taken, but is also one of the special expansion characters. */
90 #define VALID_SPECIAL_LENGTH_PARAM(c) \
91 ((c) == '-' || (c) == '?' || (c) == '#')
92
93 /* Evaluates to 1 if C is one of the shell's special parameters for which an
94 indirect variable reference may be made. */
95 #define VALID_INDIR_PARAM(c) \
96 ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
97
98 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
99 in ${parameter[:]OPword}. */
100 #define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
101
102 /* Evaluates to 1 if this is one of the shell's special variables. */
103 #define SPECIAL_VAR(name, wi) \
104 ((DIGIT (*name) && all_digits (name)) || \
105 (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
106 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
107
108 /* An expansion function that takes a string and a quoted flag and returns
109 a WORD_LIST *. Used as the type of the third argument to
110 expand_string_if_necessary(). */
111 typedef WORD_LIST *EXPFUNC __P((char *, int));
112
113 /* Process ID of the last command executed within command substitution. */
114 pid_t last_command_subst_pid = NO_PID;
115 pid_t current_command_subst_pid = NO_PID;
116
117 /* Variables used to keep track of the characters in IFS. */
118 SHELL_VAR *ifs_var;
119 char *ifs_value;
120 unsigned char ifs_cmap[UCHAR_MAX + 1];
121 unsigned char ifs_firstc;
122
123 /* Extern functions and variables from different files. */
124 extern int last_command_exit_value;
125 extern int subshell_environment;
126 extern int eof_encountered;
127 extern int return_catch_flag, return_catch_value;
128 extern pid_t dollar_dollar_pid;
129 extern int posixly_correct;
130 extern char *this_command_name;
131 extern struct fd_bitmap *current_fds_to_close;
132 extern int wordexp_only;
133
134 /* Non-zero means to allow unmatched globbed filenames to expand to
135 a null file. */
136 int allow_null_glob_expansion;
137
138 #if 0
139 /* Variables to keep track of which words in an expanded word list (the
140 output of expand_word_list_internal) are the result of globbing
141 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
142 (CURRENTLY UNUSED). */
143 char *glob_argv_flags;
144 static int glob_argv_flags_size;
145 #endif
146
147 static WORD_LIST expand_word_error, expand_word_fatal;
148 static char expand_param_error, expand_param_fatal;
149
150 /* Tell the expansion functions to not longjmp back to top_level on fatal
151 errors. Enabled when doing completion and prompt string expansion. */
152 static int no_longjmp_on_fatal_error = 0;
153
154 /* Set by expand_word_unsplit; used to inhibit splitting and re-joining
155 $* on $IFS, primarily when doing assignment statements. */
156 static int expand_no_split_dollar_star = 0;
157
158 /* Used to hold a list of variable assignments preceding a command. Global
159 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
160 SIGCHLD trap. */
161 WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
162
163 /* A WORD_LIST of words to be expanded by expand_word_list_internal,
164 without any leading variable assignments. */
165 static WORD_LIST *garglist = (WORD_LIST *)NULL;
166
167 static char *quoted_substring __P((char *, int, int));
168 static int quoted_strlen __P((char *));
169 static char *quoted_strchr __P((char *, int, int));
170
171 static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
172 static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
173 static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
174 static WORD_LIST *expand_string_internal __P((char *, int));
175 static WORD_LIST *expand_string_leave_quoted __P((char *, int));
176 static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
177
178 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
179 static char *dequote_escapes __P((char *));
180 static char *make_quoted_char __P((int));
181 static WORD_LIST *quote_list __P((WORD_LIST *));
182 static WORD_LIST *dequote_list __P((WORD_LIST *));
183 static char *remove_quoted_escapes __P((char *));
184 static char *remove_quoted_nulls __P((char *));
185
186 static int unquoted_substring __P((char *, char *));
187 static int unquoted_member __P((int, char *));
188
189 static int do_assignment_internal __P((const char *, int));
190
191 static char *string_extract_verbatim __P((char *, int *, char *));
192 static char *string_extract __P((char *, int *, char *, int));
193 static char *string_extract_double_quoted __P((char *, int *, int));
194 static inline char *string_extract_single_quoted __P((char *, int *));
195 static inline int skip_single_quoted __P((char *, size_t, int));
196 static int skip_double_quoted __P((char *, size_t, int));
197 static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
198 static char *extract_dollar_brace_string __P((char *, int *, int, int));
199
200 static char *pos_params __P((char *, int, int, int));
201
202 static char *remove_pattern __P((char *, char *, int));
203 static int match_pattern_char __P((char *, char *));
204 static int match_pattern __P((char *, char *, int, char **, char **));
205 static int getpatspec __P((int, char *));
206 static char *getpattern __P((char *, int, int));
207 static char *variable_remove_pattern __P((char *, char *, int, int));
208 static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
209 static char *parameter_list_remove_pattern __P((int, char *, int, int));
210 #ifdef ARRAY_VARS
211 static char *array_remove_pattern __P((ARRAY *, char *, int, char *, int));
212 #endif
213 static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
214
215 static char *process_substitute __P((char *, int));
216
217 static char *read_comsub __P((int, int));
218
219 #ifdef ARRAY_VARS
220 static arrayind_t array_length_reference __P((char *));
221 #endif
222
223 static int valid_brace_expansion_word __P((char *, int));
224 static char *parameter_brace_expand_word __P((char *, int, int));
225 static char *parameter_brace_expand_indir __P((char *, int, int));
226 static char *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
227 static void parameter_brace_expand_error __P((char *, char *));
228
229 static int valid_length_expression __P((char *));
230 static intmax_t parameter_brace_expand_length __P((char *));
231
232 static char *skiparith __P((char *, int));
233 static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
234 static int get_var_and_type __P((char *, char *, SHELL_VAR **, char **));
235 static char *parameter_brace_substring __P((char *, char *, char *, int));
236
237 static char *pos_params_pat_subst __P((char *, char *, char *, int));
238
239 static char *parameter_brace_patsub __P((char *, char *, char *, int));
240
241 static char *parameter_brace_expand __P((char *, int *, int, int *, int *));
242 static char *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
243
244 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
245
246 static WORD_LIST *word_list_split __P((WORD_LIST *));
247
248 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
249 static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
250 #ifdef BRACE_EXPANSION
251 static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
252 #endif
253 static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
254 static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
255
256 /* **************************************************************** */
257 /* */
258 /* Utility Functions */
259 /* */
260 /* **************************************************************** */
261
262 #ifdef INCLUDE_UNUSED
263 static char *
264 quoted_substring (string, start, end)
265 char *string;
266 int start, end;
267 {
268 register int len, l;
269 register char *result, *s, *r;
270
271 len = end - start;
272
273 /* Move to string[start], skipping quoted characters. */
274 for (s = string, l = 0; *s && l < start; )
275 {
276 if (*s == CTLESC)
277 {
278 s++;
279 continue;
280 }
281 l++;
282 if (*s == 0)
283 break;
284 }
285
286 r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
287
288 /* Copy LEN characters, including quote characters. */
289 s = string + l;
290 for (l = 0; l < len; s++)
291 {
292 if (*s == CTLESC)
293 *r++ = *s++;
294 *r++ = *s;
295 l++;
296 if (*s == 0)
297 break;
298 }
299 *r = '\0';
300 return result;
301 }
302 #endif
303
304 #ifdef INCLUDE_UNUSED
305 /* Return the length of S, skipping over quoted characters */
306 static int
307 quoted_strlen (s)
308 char *s;
309 {
310 register char *p;
311 int i;
312
313 i = 0;
314 for (p = s; *p; p++)
315 {
316 if (*p == CTLESC)
317 {
318 p++;
319 if (*p == 0)
320 return (i + 1);
321 }
322 i++;
323 }
324
325 return i;
326 }
327 #endif
328
329 /* Find the first occurrence of character C in string S, obeying shell
330 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
331 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
332 escaped with CTLESC are skipped. */
333 static char *
334 quoted_strchr (s, c, flags)
335 char *s;
336 int c, flags;
337 {
338 register char *p;
339
340 for (p = s; *p; p++)
341 {
342 if (((flags & ST_BACKSL) && *p == '\\')
343 || ((flags & ST_CTLESC) && *p == CTLESC))
344 {
345 p++;
346 if (*p == '\0')
347 return ((char *)NULL);
348 continue;
349 }
350 else if (*p == c)
351 return p;
352 }
353 return ((char *)NULL);
354 }
355
356 /* Return 1 if CHARACTER appears in an unquoted portion of
357 STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
358 static int
359 unquoted_member (character, string)
360 int character;
361 char *string;
362 {
363 size_t slen;
364 int sindex, c;
365 DECLARE_MBSTATE;
366
367 slen = strlen (string);
368 sindex = 0;
369 while (c = string[sindex])
370 {
371 if (c == character)
372 return (1);
373
374 switch (c)
375 {
376 default:
377 ADVANCE_CHAR (string, slen, sindex);
378 break;
379
380 case '\\':
381 sindex++;
382 if (string[sindex])
383 ADVANCE_CHAR (string, slen, sindex);
384 break;
385
386 case '\'':
387 sindex = skip_single_quoted (string, slen, ++sindex);
388 break;
389
390 case '"':
391 sindex = skip_double_quoted (string, slen, ++sindex);
392 break;
393 }
394 }
395 return (0);
396 }
397
398 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
399 static int
400 unquoted_substring (substr, string)
401 char *substr, *string;
402 {
403 size_t slen;
404 int sindex, c, sublen;
405 DECLARE_MBSTATE;
406
407 if (substr == 0 || *substr == '\0')
408 return (0);
409
410 slen = strlen (string);
411 sublen = strlen (substr);
412 for (sindex = 0; c = string[sindex]; )
413 {
414 if (STREQN (string + sindex, substr, sublen))
415 return (1);
416
417 switch (c)
418 {
419 case '\\':
420 sindex++;
421
422 if (string[sindex])
423 ADVANCE_CHAR (string, slen, sindex);
424 break;
425
426 case '\'':
427 sindex = skip_single_quoted (string, slen, ++sindex);
428 break;
429
430 case '"':
431 sindex = skip_double_quoted (string, slen, ++sindex);
432 break;
433
434 default:
435 ADVANCE_CHAR (string, slen, sindex);
436 break;
437 }
438 }
439 return (0);
440 }
441
442 /* Most of the substitutions must be done in parallel. In order
443 to avoid using tons of unclear goto's, I have some functions
444 for manipulating malloc'ed strings. They all take INDX, a
445 pointer to an integer which is the offset into the string
446 where manipulation is taking place. They also take SIZE, a
447 pointer to an integer which is the current length of the
448 character array for this string. */
449
450 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
451 of space allocated to TARGET. SOURCE can be NULL, in which
452 case nothing happens. Gets rid of SOURCE by freeing it.
453 Returns TARGET in case the location has changed. */
454 INLINE char *
455 sub_append_string (source, target, indx, size)
456 char *source, *target;
457 int *indx, *size;
458 {
459 if (source)
460 {
461 int srclen, n;
462
463 srclen = STRLEN (source);
464 if (srclen >= (int)(*size - *indx))
465 {
466 n = srclen + *indx;
467 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
468 target = (char *)xrealloc (target, (*size = n));
469 }
470
471 FASTCOPY (source, target + *indx, srclen);
472 *indx += srclen;
473 target[*indx] = '\0';
474
475 free (source);
476 }
477 return (target);
478 }
479
480 #if 0
481 /* UNUSED */
482 /* Append the textual representation of NUMBER to TARGET.
483 INDX and SIZE are as in SUB_APPEND_STRING. */
484 char *
485 sub_append_number (number, target, indx, size)
486 intmax_t number;
487 int *indx, *size;
488 char *target;
489 {
490 char *temp;
491
492 temp = itos (number);
493 return (sub_append_string (temp, target, indx, size));
494 }
495 #endif
496
497 /* Extract a substring from STRING, starting at SINDEX and ending with
498 one of the characters in CHARLIST. Don't make the ending character
499 part of the string. Leave SINDEX pointing at the ending character.
500 Understand about backslashes in the string. If (flags & EX_VARNAME)
501 is non-zero, and array variables have been compiled into the shell,
502 everything between a `[' and a corresponding `]' is skipped over.
503 If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
504 update SINDEX. */
505 static char *
506 string_extract (string, sindex, charlist, flags)
507 char *string;
508 int *sindex;
509 char *charlist;
510 int flags;
511 {
512 register int c, i;
513 size_t slen;
514 char *temp;
515 DECLARE_MBSTATE;
516
517 slen = strlen (string + *sindex) + *sindex;
518 i = *sindex;
519 while (c = string[i])
520 {
521 if (c == '\\')
522 {
523 if (string[i + 1])
524 i++;
525 else
526 break;
527 }
528 #if defined (ARRAY_VARS)
529 else if ((flags & EX_VARNAME) && c == '[')
530 {
531 int ni;
532 /* If this is an array subscript, skip over it and continue. */
533 ni = skipsubscript (string, i);
534 if (string[ni] == ']')
535 i = ni;
536 }
537 #endif
538 else if (MEMBER (c, charlist))
539 break;
540
541 ADVANCE_CHAR (string, slen, i);
542 }
543
544 temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
545 *sindex = i;
546 return (temp);
547 }
548
549 /* Extract the contents of STRING as if it is enclosed in double quotes.
550 SINDEX, when passed in, is the offset of the character immediately
551 following the opening double quote; on exit, SINDEX is left pointing after
552 the closing double quote. If STRIPDQ is non-zero, unquoted double
553 quotes are stripped and the string is terminated by a null byte.
554 Backslashes between the embedded double quotes are processed. If STRIPDQ
555 is zero, an unquoted `"' terminates the string. */
556 static char *
557 string_extract_double_quoted (string, sindex, stripdq)
558 char *string;
559 int *sindex, stripdq;
560 {
561 size_t slen;
562 char *send;
563 int j, i, t;
564 unsigned char c;
565 char *temp, *ret; /* The new string we return. */
566 int pass_next, backquote, si; /* State variables for the machine. */
567 int dquote;
568 DECLARE_MBSTATE;
569
570 slen = strlen (string + *sindex) + *sindex;
571 send = string + slen;
572
573 pass_next = backquote = dquote = 0;
574 temp = (char *)xmalloc (1 + slen - *sindex);
575
576 j = 0;
577 i = *sindex;
578 while (c = string[i])
579 {
580 /* Process a character that was quoted by a backslash. */
581 if (pass_next)
582 {
583 /* Posix.2 sez:
584
585 ``The backslash shall retain its special meaning as an escape
586 character only when followed by one of the characters:
587 $ ` " \ <newline>''.
588
589 If STRIPDQ is zero, we handle the double quotes here and let
590 expand_word_internal handle the rest. If STRIPDQ is non-zero,
591 we have already been through one round of backslash stripping,
592 and want to strip these backslashes only if DQUOTE is non-zero,
593 indicating that we are inside an embedded double-quoted string. */
594
595 /* If we are in an embedded quoted string, then don't strip
596 backslashes before characters for which the backslash
597 retains its special meaning, but remove backslashes in
598 front of other characters. If we are not in an
599 embedded quoted string, don't strip backslashes at all.
600 This mess is necessary because the string was already
601 surrounded by double quotes (and sh has some really weird
602 quoting rules).
603 The returned string will be run through expansion as if
604 it were double-quoted. */
605 if ((stripdq == 0 && c != '"') ||
606 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
607 temp[j++] = '\\';
608 pass_next = 0;
609
610 add_one_character:
611 COPY_CHAR_I (temp, j, string, send, i);
612 continue;
613 }
614
615 /* A backslash protects the next character. The code just above
616 handles preserving the backslash in front of any character but
617 a double quote. */
618 if (c == '\\')
619 {
620 pass_next++;
621 i++;
622 continue;
623 }
624
625 /* Inside backquotes, ``the portion of the quoted string from the
626 initial backquote and the characters up to the next backquote
627 that is not preceded by a backslash, having escape characters
628 removed, defines that command''. */
629 if (backquote)
630 {
631 if (c == '`')
632 backquote = 0;
633 temp[j++] = c;
634 i++;
635 continue;
636 }
637
638 if (c == '`')
639 {
640 temp[j++] = c;
641 backquote++;
642 i++;
643 continue;
644 }
645
646 /* Pass everything between `$(' and the matching `)' or a quoted
647 ${ ... } pair through according to the Posix.2 specification. */
648 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
649 {
650 si = i + 2;
651 if (string[i + 1] == LPAREN)
652 ret = extract_delimited_string (string, &si, "$(", "(", ")", 0); /*)*/
653 else
654 ret = extract_dollar_brace_string (string, &si, 1, 0);
655
656 temp[j++] = '$';
657 temp[j++] = string[i + 1];
658
659 for (t = 0; ret[t]; t++, j++)
660 temp[j] = ret[t];
661 temp[j++] = string[si];
662
663 i = si + 1;
664 free (ret);
665 continue;
666 }
667
668 /* Add any character but a double quote to the quoted string we're
669 accumulating. */
670 if (c != '"')
671 goto add_one_character;
672
673 /* c == '"' */
674 if (stripdq)
675 {
676 dquote ^= 1;
677 i++;
678 continue;
679 }
680
681 break;
682 }
683 temp[j] = '\0';
684
685 /* Point to after the closing quote. */
686 if (c)
687 i++;
688 *sindex = i;
689
690 return (temp);
691 }
692
693 /* This should really be another option to string_extract_double_quoted. */
694 static int
695 skip_double_quoted (string, slen, sind)
696 char *string;
697 size_t slen;
698 int sind;
699 {
700 int c, i;
701 char *ret;
702 int pass_next, backquote, si;
703 DECLARE_MBSTATE;
704
705 pass_next = backquote = 0;
706 i = sind;
707 while (c = string[i])
708 {
709 if (pass_next)
710 {
711 pass_next = 0;
712 ADVANCE_CHAR (string, slen, i);
713 continue;
714 }
715 else if (c == '\\')
716 {
717 pass_next++;
718 i++;
719 continue;
720 }
721 else if (backquote)
722 {
723 if (c == '`')
724 backquote = 0;
725 ADVANCE_CHAR (string, slen, i);
726 continue;
727 }
728 else if (c == '`')
729 {
730 backquote++;
731 i++;
732 continue;
733 }
734 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
735 {
736 si = i + 2;
737 if (string[i + 1] == LPAREN)
738 ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC);
739 else
740 ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
741
742 i = si + 1;
743 continue;
744 }
745 else if (c != '"')
746 {
747 ADVANCE_CHAR (string, slen, i);
748 continue;
749 }
750 else
751 break;
752 }
753
754 if (c)
755 i++;
756
757 return (i);
758 }
759
760 /* Extract the contents of STRING as if it is enclosed in single quotes.
761 SINDEX, when passed in, is the offset of the character immediately
762 following the opening single quote; on exit, SINDEX is left pointing after
763 the closing single quote. */
764 static inline char *
765 string_extract_single_quoted (string, sindex)
766 char *string;
767 int *sindex;
768 {
769 register int i;
770 size_t slen;
771 char *t;
772 DECLARE_MBSTATE;
773
774 slen = strlen (string + *sindex) + *sindex;
775 i = *sindex;
776 while (string[i] && string[i] != '\'')
777 ADVANCE_CHAR (string, slen, i);
778
779 t = substring (string, *sindex, i);
780
781 if (string[i])
782 i++;
783 *sindex = i;
784
785 return (t);
786 }
787
788 static inline int
789 skip_single_quoted (string, slen, sind)
790 char *string;
791 size_t slen;
792 int sind;
793 {
794 register int c;
795 DECLARE_MBSTATE;
796
797 c = sind;
798 while (string[c] && string[c] != '\'')
799 ADVANCE_CHAR (string, slen, c);
800
801 if (string[c])
802 c++;
803 return c;
804 }
805
806 /* Just like string_extract, but doesn't hack backslashes or any of
807 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
808 static char *
809 string_extract_verbatim (string, sindex, charlist)
810 char *string;
811 int *sindex;
812 char *charlist;
813 {
814 register int i = *sindex;
815 int c;
816 char *temp;
817
818 if (charlist[0] == '\'' && charlist[1] == '\0')
819 {
820 temp = string_extract_single_quoted (string, sindex);
821 --*sindex; /* leave *sindex at separator character */
822 return temp;
823 }
824
825 for (i = *sindex; c = string[i]; i++)
826 {
827 if (c == CTLESC)
828 {
829 i++;
830 continue;
831 }
832
833 if (MEMBER (c, charlist))
834 break;
835 }
836
837 temp = substring (string, *sindex, i);
838 *sindex = i;
839
840 return (temp);
841 }
842
843 /* Extract the $( construct in STRING, and return a new string.
844 Start extracting at (SINDEX) as if we had just seen "$(".
845 Make (SINDEX) get the position of the matching ")". */
846 char *
847 extract_command_subst (string, sindex)
848 char *string;
849 int *sindex;
850 {
851 return (extract_delimited_string (string, sindex, "$(", "(", ")", 0));
852 }
853
854 /* Extract the $[ construct in STRING, and return a new string. (])
855 Start extracting at (SINDEX) as if we had just seen "$[".
856 Make (SINDEX) get the position of the matching "]". */
857 char *
858 extract_arithmetic_subst (string, sindex)
859 char *string;
860 int *sindex;
861 {
862 return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
863 }
864
865 #if defined (PROCESS_SUBSTITUTION)
866 /* Extract the <( or >( construct in STRING, and return a new string.
867 Start extracting at (SINDEX) as if we had just seen "<(".
868 Make (SINDEX) get the position of the matching ")". */ /*))*/
869 char *
870 extract_process_subst (string, starter, sindex)
871 char *string;
872 char *starter;
873 int *sindex;
874 {
875 return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
876 }
877 #endif /* PROCESS_SUBSTITUTION */
878
879 #if defined (ARRAY_VARS)
880 char *
881 extract_array_assignment_list (string, sindex)
882 char *string;
883 int *sindex;
884 {
885 return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")", 0));
886 }
887 #endif
888
889 /* Extract and create a new string from the contents of STRING, a
890 character string delimited with OPENER and CLOSER. SINDEX is
891 the address of an int describing the current offset in STRING;
892 it should point to just after the first OPENER found. On exit,
893 SINDEX gets the position of the last character of the matching CLOSER.
894 If OPENER is more than a single character, ALT_OPENER, if non-null,
895 contains a character string that can also match CLOSER and thus
896 needs to be skipped. */
897 static char *
898 extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
899 char *string;
900 int *sindex;
901 char *opener, *alt_opener, *closer;
902 int flags;
903 {
904 int i, c, si;
905 size_t slen;
906 char *t, *result;
907 int pass_character, nesting_level;
908 int len_closer, len_opener, len_alt_opener;
909 DECLARE_MBSTATE;
910
911 slen = strlen (string + *sindex) + *sindex;
912 len_opener = STRLEN (opener);
913 len_alt_opener = STRLEN (alt_opener);
914 len_closer = STRLEN (closer);
915
916 pass_character = 0;
917
918 nesting_level = 1;
919 i = *sindex;
920
921 while (nesting_level)
922 {
923 c = string[i];
924
925 if (c == 0)
926 break;
927
928 if (pass_character) /* previous char was backslash */
929 {
930 pass_character = 0;
931 ADVANCE_CHAR (string, slen, i);
932 continue;
933 }
934
935 if (c == CTLESC || c == '\\')
936 {
937 pass_character++;
938 i++;
939 continue;
940 }
941
942 /* Process a nested OPENER. */
943 if (STREQN (string + i, opener, len_opener))
944 {
945 si = i + len_opener;
946 t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
947 i = si + 1;
948 continue;
949 }
950
951 /* Process a nested ALT_OPENER */
952 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
953 {
954 si = i + len_alt_opener;
955 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
956 i = si + 1;
957 continue;
958 }
959
960 /* If the current substring terminates the delimited string, decrement
961 the nesting level. */
962 if (STREQN (string + i, closer, len_closer))
963 {
964 i += len_closer - 1; /* move to last byte of the closer */
965 nesting_level--;
966 if (nesting_level == 0)
967 break;
968 }
969
970 /* Pass old-style command substitution through verbatim. */
971 if (c == '`')
972 {
973 si = i + 1;
974 t = string_extract (string, &si, "`", flags|EX_NOALLOC);
975 i = si + 1;
976 continue;
977 }
978
979 /* Pass single-quoted and double-quoted strings through verbatim. */
980 if (c == '\'' || c == '"')
981 {
982 si = i + 1;
983 i = (c == '\'') ? skip_single_quoted (string, slen, si)
984 : skip_double_quoted (string, slen, si);
985 continue;
986 }
987
988 /* move past this character, which was not special. */
989 ADVANCE_CHAR (string, slen, i);
990 }
991
992 if (c == 0 && nesting_level && no_longjmp_on_fatal_error == 0)
993 {
994 report_error ("bad substitution: no `%s' in %s", closer, string);
995 last_command_exit_value = EXECUTION_FAILURE;
996 jump_to_top_level (DISCARD);
997 }
998
999 si = i - *sindex - len_closer + 1;
1000 if (flags & EX_NOALLOC)
1001 result = (char *)NULL;
1002 else
1003 {
1004 result = (char *)xmalloc (1 + si);
1005 strncpy (result, string + *sindex, si);
1006 result[si] = '\0';
1007 }
1008 *sindex = i;
1009
1010 return (result);
1011 }
1012
1013 /* Extract a parameter expansion expression within ${ and } from STRING.
1014 Obey the Posix.2 rules for finding the ending `}': count braces while
1015 skipping over enclosed quoted strings and command substitutions.
1016 SINDEX is the address of an int describing the current offset in STRING;
1017 it should point to just after the first `{' found. On exit, SINDEX
1018 gets the position of the matching `}'. QUOTED is non-zero if this
1019 occurs inside double quotes. */
1020 /* XXX -- this is very similar to extract_delimited_string -- XXX */
1021 static char *
1022 extract_dollar_brace_string (string, sindex, quoted, flags)
1023 char *string;
1024 int *sindex, quoted, flags;
1025 {
1026 register int i, c;
1027 size_t slen;
1028 int pass_character, nesting_level, si;
1029 char *result, *t;
1030 DECLARE_MBSTATE;
1031
1032 pass_character = 0;
1033 nesting_level = 1;
1034 slen = strlen (string + *sindex) + *sindex;
1035
1036 i = *sindex;
1037 while (c = string[i])
1038 {
1039 if (pass_character)
1040 {
1041 pass_character = 0;
1042 ADVANCE_CHAR (string, slen, i);
1043 continue;
1044 }
1045
1046 /* CTLESCs and backslashes quote the next character. */
1047 if (c == CTLESC || c == '\\')
1048 {
1049 pass_character++;
1050 i++;
1051 continue;
1052 }
1053
1054 if (string[i] == '$' && string[i+1] == LBRACE)
1055 {
1056 nesting_level++;
1057 i += 2;
1058 continue;
1059 }
1060
1061 if (c == RBRACE)
1062 {
1063 nesting_level--;
1064 if (nesting_level == 0)
1065 break;
1066 i++;
1067 continue;
1068 }
1069
1070 /* Pass the contents of old-style command substitutions through
1071 verbatim. */
1072 if (c == '`')
1073 {
1074 si = i + 1;
1075 t = string_extract (string, &si, "`", flags|EX_NOALLOC);
1076 i = si + 1;
1077 continue;
1078 }
1079
1080 /* Pass the contents of new-style command substitutions and
1081 arithmetic substitutions through verbatim. */
1082 if (string[i] == '$' && string[i+1] == LPAREN)
1083 {
1084 si = i + 2;
1085 t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC); /*)*/
1086 i = si + 1;
1087 continue;
1088 }
1089
1090 /* Pass the contents of single-quoted and double-quoted strings
1091 through verbatim. */
1092 if (c == '\'' || c == '"')
1093 {
1094 si = i + 1;
1095 i = (c == '\'') ? skip_single_quoted (string, slen, si)
1096 : skip_double_quoted (string, slen, si);
1097 /* skip_XXX_quoted leaves index one past close quote */
1098 continue;
1099 }
1100
1101 /* move past this character, which was not special. */
1102 ADVANCE_CHAR (string, slen, i);
1103 }
1104
1105 if (c == 0 && nesting_level && no_longjmp_on_fatal_error == 0)
1106 {
1107 report_error ("bad substitution: no ending `}' in %s", string);
1108 last_command_exit_value = EXECUTION_FAILURE;
1109 jump_to_top_level (DISCARD);
1110 }
1111
1112 result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
1113 *sindex = i;
1114
1115 return (result);
1116 }
1117
1118 /* Remove backslashes which are quoting backquotes from STRING. Modifies
1119 STRING, and returns a pointer to it. */
1120 char *
1121 de_backslash (string)
1122 char *string;
1123 {
1124 register size_t slen;
1125 register int i, j, prev_i;
1126 DECLARE_MBSTATE;
1127
1128 slen = strlen (string);
1129 i = j = 0;
1130
1131 /* Loop copying string[i] to string[j], i >= j. */
1132 while (i < slen)
1133 {
1134 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
1135 string[i + 1] == '$'))
1136 i++;
1137 prev_i = i;
1138 ADVANCE_CHAR (string, slen, i);
1139 if (j < prev_i)
1140 do string[j++] = string[prev_i++]; while (prev_i < i);
1141 else
1142 j = i;
1143 }
1144 string[j] = '\0';
1145
1146 return (string);
1147 }
1148
1149 #if 0
1150 /*UNUSED*/
1151 /* Replace instances of \! in a string with !. */
1152 void
1153 unquote_bang (string)
1154 char *string;
1155 {
1156 register int i, j;
1157 register char *temp;
1158
1159 temp = (char *)xmalloc (1 + strlen (string));
1160
1161 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1162 {
1163 if (string[i] == '\\' && string[i + 1] == '!')
1164 {
1165 temp[j] = '!';
1166 i++;
1167 }
1168 }
1169 strcpy (string, temp);
1170 free (temp);
1171 }
1172 #endif
1173
1174 #if defined (READLINE)
1175 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1176 an unclosed quoted string), or if the character at EINDEX is quoted
1177 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
1178 single and double-quoted string parsing functions should not return an
1179 error if there are unclosed quotes or braces. The characters that this
1180 recognizes need to be the same as the contents of
1181 rl_completer_quote_characters. */
1182
1183 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
1184
1185 int
1186 char_is_quoted (string, eindex)
1187 char *string;
1188 int eindex;
1189 {
1190 int i, pass_next, c;
1191 size_t slen;
1192 DECLARE_MBSTATE;
1193
1194 slen = strlen (string);
1195 no_longjmp_on_fatal_error = 1;
1196 i = pass_next = 0;
1197 while (i <= eindex)
1198 {
1199 c = string[i];
1200
1201 if (pass_next)
1202 {
1203 pass_next = 0;
1204 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1205 CQ_RETURN(1);
1206 ADVANCE_CHAR (string, slen, i);
1207 continue;
1208 }
1209 else if (c == '\\')
1210 {
1211 pass_next = 1;
1212 i++;
1213 continue;
1214 }
1215 else if (c == '\'' || c == '"')
1216 {
1217 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1218 : skip_double_quoted (string, slen, ++i);
1219 if (i > eindex)
1220 CQ_RETURN(1);
1221 /* no increment, the skip_xxx functions go one past end */
1222 }
1223 else
1224 ADVANCE_CHAR (string, slen, i);
1225 }
1226
1227 CQ_RETURN(0);
1228 }
1229
1230 int
1231 unclosed_pair (string, eindex, openstr)
1232 char *string;
1233 int eindex;
1234 char *openstr;
1235 {
1236 int i, pass_next, openc, olen;
1237 size_t slen;
1238 DECLARE_MBSTATE;
1239
1240 slen = strlen (string);
1241 olen = strlen (openstr);
1242 i = pass_next = openc = 0;
1243 while (i <= eindex)
1244 {
1245 if (pass_next)
1246 {
1247 pass_next = 0;
1248 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1249 return 0;
1250 ADVANCE_CHAR (string, slen, i);
1251 continue;
1252 }
1253 else if (string[i] == '\\')
1254 {
1255 pass_next = 1;
1256 i++;
1257 continue;
1258 }
1259 else if (STREQN (string + i, openstr, olen))
1260 {
1261 openc = 1 - openc;
1262 i += olen;
1263 }
1264 else if (string[i] == '\'' || string[i] == '"')
1265 {
1266 i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
1267 : skip_double_quoted (string, slen, i);
1268 if (i > eindex)
1269 return 0;
1270 }
1271 else
1272 ADVANCE_CHAR (string, slen, i);
1273 }
1274 return (openc);
1275 }
1276
1277 /* Skip characters in STRING until we find a character in DELIMS, and return
1278 the index of that character. START is the index into string at which we
1279 begin. This is similar in spirit to strpbrk, but it returns an index into
1280 STRING and takes a starting index. This little piece of code knows quite
1281 a lot of shell syntax. It's very similar to skip_double_quoted and other
1282 functions of that ilk. */
1283 int
1284 skip_to_delim (string, start, delims)
1285 char *string;
1286 int start;
1287 char *delims;
1288 {
1289 int i, pass_next, backq, si, c;
1290 size_t slen;
1291 char *temp;
1292 DECLARE_MBSTATE;
1293
1294 slen = strlen (string + start) + start;
1295 no_longjmp_on_fatal_error = 1;
1296 i = start;
1297 pass_next = backq = 0;
1298 while (c = string[i])
1299 {
1300 if (pass_next)
1301 {
1302 pass_next = 0;
1303 if (c == 0)
1304 CQ_RETURN(i);
1305 ADVANCE_CHAR (string, slen, i);
1306 continue;
1307 }
1308 else if (c == '\\')
1309 {
1310 pass_next = 1;
1311 i++;
1312 continue;
1313 }
1314 else if (backq)
1315 {
1316 if (c == '`')
1317 backq = 0;
1318 ADVANCE_CHAR (string, slen, i);
1319 continue;
1320 }
1321 else if (c == '`')
1322 {
1323 backq = 1;
1324 i++;
1325 continue;
1326 }
1327 else if (c == '\'' || c == '"')
1328 {
1329 i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
1330 : skip_double_quoted (string, slen, ++i);
1331 /* no increment, the skip functions increment past the closing quote. */
1332 }
1333 else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1334 {
1335 si = i + 2;
1336 if (string[si] == '\0')
1337 CQ_RETURN(si);
1338
1339 if (string[i+1] == LPAREN)
1340 temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
1341 else
1342 temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
1343 i = si;
1344 if (string[i] == '\0') /* don't increment i past EOS in loop */
1345 break;
1346 i++;
1347 continue;
1348 }
1349 else if (member (c, delims))
1350 break;
1351 else
1352 ADVANCE_CHAR (string, slen, i);
1353 }
1354
1355 CQ_RETURN(i);
1356 }
1357
1358 /* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1359 individual words. If DELIMS is NULL, the current value of $IFS is used
1360 to split the string. SENTINEL is an index to look for. NWP, if non-NULL
1361 gets the number of words in the returned list. CWP, if non-NULL, gets
1362 the index of the word containing SENTINEL. Non-whitespace chars in
1363 DELIMS delimit separate fields. */
1364 WORD_LIST *
1365 split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1366 char *string;
1367 int slen;
1368 char *delims;
1369 int sentinel;
1370 int *nwp, *cwp;
1371 {
1372 int ts, te, i, nw, cw;
1373 char *token, *d, *d2;
1374 WORD_LIST *ret, *tl;
1375
1376 if (string == 0 || *string == '\0')
1377 {
1378 if (nwp)
1379 *nwp = 0;
1380 if (cwp)
1381 *cwp = 0;
1382 return ((WORD_LIST *)NULL);
1383 }
1384
1385 d = (delims == 0) ? ifs_value : delims;
1386
1387 /* Make d2 the non-whitespace characters in delims */
1388 d2 = 0;
1389 if (delims)
1390 {
1391 d2 = (char *)xmalloc (strlen (delims) + 1);
1392 for (i = ts = 0; delims[i]; i++)
1393 {
1394 if (whitespace(delims[i]) == 0)
1395 d2[ts++] = delims[i];
1396 }
1397 d2[ts] = '\0';
1398 }
1399
1400 ret = (WORD_LIST *)NULL;
1401
1402 for (i = 0; member (string[i], d) && spctabnl(string[i]); i++)
1403 ;
1404 if (string[i] == '\0')
1405 return (ret);
1406
1407 ts = i;
1408 nw = 0;
1409 cw = -1;
1410 while (1)
1411 {
1412 te = skip_to_delim (string, ts, d);
1413
1414 /* If we have a non-whitespace delimiter character, use it to make a
1415 separate field. This is just about what $IFS splitting does and
1416 is closer to the behavior of the shell parser. */
1417 if (ts == te && d2 && member (string[ts], d2))
1418 {
1419 te = ts + 1;
1420 while (member (string[te], d2))
1421 te++;
1422 }
1423
1424 token = substring (string, ts, te);
1425
1426 ret = add_string_to_list (token, ret);
1427 free (token);
1428 nw++;
1429
1430 if (sentinel >= ts && sentinel <= te)
1431 cw = nw;
1432
1433 /* If the cursor is at whitespace just before word start, set the
1434 sentinel word to the current word. */
1435 if (cwp && cw == -1 && sentinel == ts-1)
1436 cw = nw;
1437
1438 /* If the cursor is at whitespace between two words, make a new, empty
1439 word, add it before (well, after, since the list is in reverse order)
1440 the word we just added, and set the current word to that one. */
1441 if (cwp && cw == -1 && sentinel < ts)
1442 {
1443 tl = make_word_list (make_word (""), ret->next);
1444 ret->next = tl;
1445 cw = nw;
1446 nw++;
1447 }
1448
1449 if (string[te] == 0)
1450 break;
1451
1452 i = te /* + member (string[te], d) */;
1453 while (member (string[i], d) && spctabnl(string[i]))
1454 i++;
1455
1456 if (string[i])
1457 ts = i;
1458 else
1459 break;
1460 }
1461
1462 /* Special case for SENTINEL at the end of STRING. If we haven't found
1463 the word containing SENTINEL yet, and the index we're looking for is at
1464 the end of STRING, add an additional null argument and set the current
1465 word pointer to that. */
1466 if (cwp && cw == -1 && sentinel >= slen)
1467 {
1468 if (whitespace (string[sentinel - 1]))
1469 {
1470 token = "";
1471 ret = add_string_to_list (token, ret);
1472 nw++;
1473 }
1474 cw = nw;
1475 }
1476
1477 if (nwp)
1478 *nwp = nw;
1479 if (cwp)
1480 *cwp = cw;
1481
1482 return (REVERSE_LIST (ret, WORD_LIST *));
1483 }
1484 #endif /* READLINE */
1485
1486 #if 0
1487 /* UNUSED */
1488 /* Extract the name of the variable to bind to from the assignment string. */
1489 char *
1490 assignment_name (string)
1491 char *string;
1492 {
1493 int offset;
1494 char *temp;
1495
1496 offset = assignment (string);
1497 if (offset == 0)
1498 return (char *)NULL;
1499 temp = substring (string, 0, offset);
1500 return (temp);
1501 }
1502 #endif
1503
1504 /* **************************************************************** */
1505 /* */
1506 /* Functions to convert strings to WORD_LISTs and vice versa */
1507 /* */
1508 /* **************************************************************** */
1509
1510 /* Return a single string of all the words in LIST. SEP is the separator
1511 to put between individual elements of LIST in the output string. */
1512 char *
1513 string_list_internal (list, sep)
1514 WORD_LIST *list;
1515 char *sep;
1516 {
1517 register WORD_LIST *t;
1518 char *result, *r;
1519 int word_len, sep_len, result_size;
1520
1521 if (list == 0)
1522 return ((char *)NULL);
1523
1524 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1525 sep_len = STRLEN (sep);
1526 result_size = 0;
1527
1528 for (t = list; t; t = t->next)
1529 {
1530 if (t != list)
1531 result_size += sep_len;
1532 result_size += strlen (t->word->word);
1533 }
1534
1535 r = result = (char *)xmalloc (result_size + 1);
1536
1537 for (t = list; t; t = t->next)
1538 {
1539 if (t != list && sep_len)
1540 {
1541 if (sep_len > 1)
1542 {
1543 FASTCOPY (sep, r, sep_len);
1544 r += sep_len;
1545 }
1546 else
1547 *r++ = sep[0];
1548 }
1549
1550 word_len = strlen (t->word->word);
1551 FASTCOPY (t->word->word, r, word_len);
1552 r += word_len;
1553 }
1554
1555 *r = '\0';
1556 return (result);
1557 }
1558
1559 /* Return a single string of all the words present in LIST, separating
1560 each word with a space. */
1561 char *
1562 string_list (list)
1563 WORD_LIST *list;
1564 {
1565 return (string_list_internal (list, " "));
1566 }
1567
1568 /* Return a single string of all the words present in LIST, obeying the
1569 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1570 expansion [of $*] appears within a double quoted string, it expands
1571 to a single field with the value of each parameter separated by the
1572 first character of the IFS variable, or by a <space> if IFS is unset." */
1573 char *
1574 string_list_dollar_star (list)
1575 WORD_LIST *list;
1576 {
1577 char sep[2];
1578
1579 sep[0] = ifs_firstc;
1580 sep[1] = '\0';
1581
1582 return (string_list_internal (list, sep));
1583 }
1584
1585 /* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1586 is non-zero, the $@ appears within double quotes, and we should quote
1587 the list before converting it into a string. If IFS is unset, and the
1588 word is not quoted, we just need to quote CTLESC and CTLNUL characters
1589 in the words in the list, because the default value of $IFS is
1590 <space><tab><newline>, IFS characters in the words in the list should
1591 also be split. If IFS is null, and the word is not quoted, we need
1592 to quote the words in the list to preserve the positional parameters
1593 exactly. */
1594 char *
1595 string_list_dollar_at (list, quoted)
1596 WORD_LIST *list;
1597 int quoted;
1598 {
1599 char *ifs, sep[2];
1600 WORD_LIST *tlist;
1601
1602 /* XXX this could just be ifs = ifs_value; */
1603 ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
1604
1605 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1606 sep[1] = '\0';
1607
1608 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1609 ? quote_list (list)
1610 : list_quote_escapes (list);
1611 return (string_list_internal (tlist, sep));
1612 }
1613
1614 /* Return the list of words present in STRING. Separate the string into
1615 words at any of the characters found in SEPARATORS. If QUOTED is
1616 non-zero then word in the list will have its quoted flag set, otherwise
1617 the quoted flag is left as make_word () deemed fit.
1618
1619 This obeys the P1003.2 word splitting semantics. If `separators' is
1620 exactly <space><tab><newline>, then the splitting algorithm is that of
1621 the Bourne shell, which treats any sequence of characters from `separators'
1622 as a delimiter. If IFS is unset, which results in `separators' being set
1623 to "", no splitting occurs. If separators has some other value, the
1624 following rules are applied (`IFS white space' means zero or more
1625 occurrences of <space>, <tab>, or <newline>, as long as those characters
1626 are in `separators'):
1627
1628 1) IFS white space is ignored at the start and the end of the
1629 string.
1630 2) Each occurrence of a character in `separators' that is not
1631 IFS white space, along with any adjacent occurrences of
1632 IFS white space delimits a field.
1633 3) Any nonzero-length sequence of IFS white space delimits a field.
1634 */
1635
1636 /* BEWARE! list_string strips null arguments. Don't call it twice and
1637 expect to have "" preserved! */
1638
1639 /* This performs word splitting and quoted null character removal on
1640 STRING. */
1641 #if 0
1642 #define issep(c) ((separators)[1] ? (member ((c), separators)) : (c) == (separators)[0])
1643 #else
1644 #define issep(c) ((separators)[1] ? isifs(c) : (c) == (separators)[0])
1645 #endif
1646
1647 WORD_LIST *
1648 list_string (string, separators, quoted)
1649 register char *string, *separators;
1650 int quoted;
1651 {
1652 WORD_LIST *result;
1653 WORD_DESC *t;
1654 char *current_word, *s;
1655 int sindex, sh_style_split, whitesep;
1656
1657 if (!string || !*string)
1658 return ((WORD_LIST *)NULL);
1659
1660 sh_style_split = separators && separators[0] == ' ' &&
1661 separators[1] == '\t' &&
1662 separators[2] == '\n' &&
1663 separators[3] == '\0';
1664
1665 /* Remove sequences of whitespace at the beginning of STRING, as
1666 long as those characters appear in IFS. Do not do this if
1667 STRING is quoted or if there are no separator characters. */
1668 if (!quoted || !separators || !*separators)
1669 {
1670 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1671
1672 if (!*s)
1673 return ((WORD_LIST *)NULL);
1674
1675 string = s;
1676 }
1677
1678 /* OK, now STRING points to a word that does not begin with white space.
1679 The splitting algorithm is:
1680 extract a word, stopping at a separator
1681 skip sequences of spc, tab, or nl as long as they are separators
1682 This obeys the field splitting rules in Posix.2. */
1683 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1684 {
1685 current_word = string_extract_verbatim (string, &sindex, separators);
1686 if (current_word == 0)
1687 break;
1688
1689 /* If we have a quoted empty string, add a quoted null argument. We
1690 want to preserve the quoted null character iff this is a quoted
1691 empty string; otherwise the quoted null characters are removed
1692 below. */
1693 if (QUOTED_NULL (current_word))
1694 {
1695 t = make_bare_word ("");
1696 t->flags |= W_QUOTED;
1697 free (t->word);
1698 t->word = make_quoted_char ('\0');
1699 result = make_word_list (t, result);
1700 }
1701 else if (current_word[0] != '\0')
1702 {
1703 /* If we have something, then add it regardless. However,
1704 perform quoted null character removal on the current word. */
1705 remove_quoted_nulls (current_word);
1706 result = add_string_to_list (current_word, result);
1707 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1708 result->word->flags |= W_QUOTED;
1709 }
1710
1711 /* If we're not doing sequences of separators in the traditional
1712 Bourne shell style, then add a quoted null argument. */
1713 else if (!sh_style_split && !spctabnl (string[sindex]))
1714 {
1715 t = make_bare_word ("");
1716 t->flags |= W_QUOTED;
1717 free (t->word);
1718 t->word = make_quoted_char ('\0');
1719 result = make_word_list (t, result);
1720 }
1721
1722 free (current_word);
1723
1724 /* Note whether or not the separator is IFS whitespace, used later. */
1725 whitesep = string[sindex] && spctabnl (string[sindex]);
1726
1727 /* Move past the current separator character. */
1728 if (string[sindex])
1729 sindex++;
1730
1731 /* Now skip sequences of space, tab, or newline characters if they are
1732 in the list of separators. */
1733 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1734 sindex++;
1735
1736 /* If the first separator was IFS whitespace and the current character
1737 is a non-whitespace IFS character, it should be part of the current
1738 field delimiter, not a separate delimiter that would result in an
1739 empty field. Look at POSIX.2, 3.6.5, (3)(b). */
1740 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
1741 sindex++;
1742 }
1743 return (REVERSE_LIST (result, WORD_LIST *));
1744 }
1745
1746 /* Parse a single word from STRING, using SEPARATORS to separate fields.
1747 ENDPTR is set to the first character after the word. This is used by
1748 the `read' builtin. This is never called with SEPARATORS != $IFS;
1749 it should be simplified.
1750
1751 XXX - this function is very similar to list_string; they should be
1752 combined - XXX */
1753 char *
1754 get_word_from_string (stringp, separators, endptr)
1755 char **stringp, *separators, **endptr;
1756 {
1757 register char *s;
1758 char *current_word;
1759 int sindex, sh_style_split, whitesep;
1760
1761 if (!stringp || !*stringp || !**stringp)
1762 return ((char *)NULL);
1763
1764 s = *stringp;
1765
1766 sh_style_split = separators && separators[0] == ' ' &&
1767 separators[1] == '\t' &&
1768 separators[2] == '\n' &&
1769 separators[3] == '\0';
1770
1771 /* Remove sequences of whitespace at the beginning of STRING, as
1772 long as those characters appear in IFS. */
1773 if (sh_style_split || !separators || !*separators)
1774 {
1775 for (; *s && spctabnl (*s) && isifs (*s); s++);
1776
1777 /* If the string is nothing but whitespace, update it and return. */
1778 if (!*s)
1779 {
1780 *stringp = s;
1781 if (endptr)
1782 *endptr = s;
1783 return ((char *)NULL);
1784 }
1785 }
1786
1787 /* OK, S points to a word that does not begin with white space.
1788 Now extract a word, stopping at a separator, save a pointer to
1789 the first character after the word, then skip sequences of spc,
1790 tab, or nl as long as they are separators.
1791
1792 This obeys the field splitting rules in Posix.2. */
1793 sindex = 0;
1794 current_word = string_extract_verbatim (s, &sindex, separators);
1795
1796 /* Set ENDPTR to the first character after the end of the word. */
1797 if (endptr)
1798 *endptr = s + sindex;
1799
1800 /* Note whether or not the separator is IFS whitespace, used later. */
1801 whitesep = s[sindex] && spctabnl (s[sindex]);
1802
1803 /* Move past the current separator character. */
1804 if (s[sindex])
1805 sindex++;
1806
1807 /* Now skip sequences of space, tab, or newline characters if they are
1808 in the list of separators. */
1809 while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
1810 sindex++;
1811
1812 /* If the first separator was IFS whitespace and the current character is
1813 a non-whitespace IFS character, it should be part of the current field
1814 delimiter, not a separate delimiter that would result in an empty field.
1815 Look at POSIX.2, 3.6.5, (3)(b). */
1816 if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
1817 sindex++;
1818
1819 /* Update STRING to point to the next field. */
1820 *stringp = s + sindex;
1821 return (current_word);
1822 }
1823
1824 /* Remove IFS white space at the end of STRING. Start at the end
1825 of the string and walk backwards until the beginning of the string
1826 or we find a character that's not IFS white space and not CTLESC.
1827 Only let CTLESC escape a white space character if SAW_ESCAPE is
1828 non-zero. */
1829 char *
1830 strip_trailing_ifs_whitespace (string, separators, saw_escape)
1831 char *string, *separators;
1832 int saw_escape;
1833 {
1834 char *s;
1835
1836 s = string + STRLEN (string) - 1;
1837 while (s > string && ((spctabnl (*s) && isifs (*s)) ||
1838 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1839 s--;
1840 *++s = '\0';
1841 return string;
1842 }
1843
1844 #if 0
1845 /* UNUSED */
1846 /* Split STRING into words at whitespace. Obeys shell-style quoting with
1847 backslashes, single and double quotes. */
1848 WORD_LIST *
1849 list_string_with_quotes (string)
1850 char *string;
1851 {
1852 WORD_LIST *list;
1853 char *token, *s;
1854 size_t s_len;
1855 int c, i, tokstart, len;
1856
1857 for (s = string; s && *s && spctabnl (*s); s++)
1858 ;
1859 if (s == 0 || *s == 0)
1860 return ((WORD_LIST *)NULL);
1861
1862 s_len = strlen (s);
1863 tokstart = i = 0;
1864 list = (WORD_LIST *)NULL;
1865 while (1)
1866 {
1867 c = s[i];
1868 if (c == '\\')
1869 {
1870 i++;
1871 if (s[i])
1872 i++;
1873 }
1874 else if (c == '\'')
1875 i = skip_single_quoted (s, s_len, ++i);
1876 else if (c == '"')
1877 i = skip_double_quoted (s, s_len, ++i);
1878 else if (c == 0 || spctabnl (c))
1879 {
1880 /* We have found the end of a token. Make a word out of it and
1881 add it to the word list. */
1882 token = substring (s, tokstart, i);
1883 list = add_string_to_list (token, list);
1884 free (token);
1885 while (spctabnl (s[i]))
1886 i++;
1887 if (s[i])
1888 tokstart = i;
1889 else
1890 break;
1891 }
1892 else
1893 i++; /* normal character */
1894 }
1895 return (REVERSE_LIST (list, WORD_LIST *));
1896 }
1897 #endif
1898
1899 /********************************************************/
1900 /* */
1901 /* Functions to perform assignment statements */
1902 /* */
1903 /********************************************************/
1904
1905 /* Given STRING, an assignment string, get the value of the right side
1906 of the `=', and bind it to the left side. If EXPAND is true, then
1907 perform parameter expansion, command substitution, and arithmetic
1908 expansion on the right-hand side. Perform tilde expansion in any
1909 case. Do not perform word splitting on the result of expansion. */
1910 static int
1911 do_assignment_internal (string, expand)
1912 const char *string;
1913 int expand;
1914 {
1915 int offset;
1916 char *name, *value;
1917 SHELL_VAR *entry;
1918 #if defined (ARRAY_VARS)
1919 char *t;
1920 int ni, assign_list = 0;
1921 #endif
1922
1923 offset = assignment (string);
1924 name = savestring (string);
1925 value = (char *)NULL;
1926
1927 if (name[offset] == '=')
1928 {
1929 char *temp;
1930
1931 name[offset] = 0;
1932 temp = name + offset + 1;
1933
1934 #if defined (ARRAY_VARS)
1935 if (expand && temp[0] == LPAREN && xstrchr (temp, RPAREN))
1936 {
1937 assign_list = ni = 1;
1938 value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")", 0);
1939 }
1940 else
1941 #endif
1942
1943 /* Perform tilde expansion. */
1944 if (expand && temp[0])
1945 {
1946 temp = (xstrchr (temp, '~') && unquoted_member ('~', temp))
1947 ? bash_tilde_expand (temp, 1)
1948 : savestring (temp);
1949
1950 value = expand_string_if_necessary (temp, 0, expand_string_unsplit);
1951 free (temp);
1952 }
1953 else
1954 value = savestring (temp);
1955 }
1956
1957 if (value == 0)
1958 {
1959 value = (char *)xmalloc (1);
1960 value[0] = '\0';
1961 }
1962
1963 if (echo_command_at_execute)
1964 {
1965 #if defined (ARRAY_VARS)
1966 if (assign_list)
1967 fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
1968 else
1969 #endif
1970 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1971 }
1972
1973 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
1974
1975 #if defined (ARRAY_VARS)
1976 if (t = xstrchr (name, '[')) /*]*/
1977 {
1978 if (assign_list)
1979 {
1980 report_error ("%s: cannot assign list to array member", name);
1981 ASSIGN_RETURN (0);
1982 }
1983 entry = assign_array_element (name, value);
1984 if (entry == 0)
1985 ASSIGN_RETURN (0);
1986 }
1987 else if (assign_list)
1988 entry = assign_array_from_string (name, value);
1989 else
1990 #endif /* ARRAY_VARS */
1991 entry = bind_variable (name, value);
1992
1993 stupidly_hack_special_variables (name);
1994
1995 if (entry)
1996 VUNSETATTR (entry, att_invisible);
1997
1998 /* Return 1 if the assignment seems to have been performed correctly. */
1999 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
2000 }
2001
2002 /* Perform the assignment statement in STRING, and expand the
2003 right side by doing command and parameter expansion. */
2004 int
2005 do_assignment (string)
2006 const char *string;
2007 {
2008 return do_assignment_internal (string, 1);
2009 }
2010
2011 /* Given STRING, an assignment string, get the value of the right side
2012 of the `=', and bind it to the left side. Do not do command and
2013 parameter substitution on the right hand side. */
2014 int
2015 do_assignment_no_expand (string)
2016 const char *string;
2017 {
2018 return do_assignment_internal (string, 0);
2019 }
2020
2021 /***************************************************
2022 * *
2023 * Functions to manage the positional parameters *
2024 * *
2025 ***************************************************/
2026
2027 /* Return the word list that corresponds to `$*'. */
2028 WORD_LIST *
2029 list_rest_of_args ()
2030 {
2031 register WORD_LIST *list, *args;
2032 int i;
2033
2034 /* Break out of the loop as soon as one of the dollar variables is null. */
2035 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
2036 list = make_word_list (make_bare_word (dollar_vars[i]), list);
2037
2038 for (args = rest_of_args; args; args = args->next)
2039 list = make_word_list (make_bare_word (args->word->word), list);
2040
2041 return (REVERSE_LIST (list, WORD_LIST *));
2042 }
2043
2044 int
2045 number_of_args ()
2046 {
2047 register WORD_LIST *list;
2048 int n;
2049
2050 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
2051 ;
2052 for (list = rest_of_args; list; list = list->next)
2053 n++;
2054 return n;
2055 }
2056
2057 /* Return the value of a positional parameter. This handles values > 10. */
2058 char *
2059 get_dollar_var_value (ind)
2060 intmax_t ind;
2061 {
2062 char *temp;
2063 WORD_LIST *p;
2064
2065 if (ind < 10)
2066 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2067 else /* We want something like ${11} */
2068 {
2069 ind -= 10;
2070 for (p = rest_of_args; p && ind--; p = p->next)
2071 ;
2072 temp = p ? savestring (p->word->word) : (char *)NULL;
2073 }
2074 return (temp);
2075 }
2076
2077 /* Make a single large string out of the dollar digit variables,
2078 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
2079 case of "$*" with respect to IFS. */
2080 char *
2081 string_rest_of_args (dollar_star)
2082 int dollar_star;
2083 {
2084 register WORD_LIST *list;
2085 char *string;
2086
2087 list = list_rest_of_args ();
2088 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
2089 dispose_words (list);
2090 return (string);
2091 }
2092
2093 /* Return a string containing the positional parameters from START to
2094 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
2095 which only makes a difference if QUOTED is non-zero. If QUOTED includes
2096 Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
2097 no quoting chars are added. */
2098 static char *
2099 pos_params (string, start, end, quoted)
2100 char *string;
2101 int start, end, quoted;
2102 {
2103 WORD_LIST *save, *params, *h, *t;
2104 char *ret;
2105 int i;
2106
2107 /* see if we can short-circuit. if start == end, we want 0 parameters. */
2108 if (start == end)
2109 return ((char *)NULL);
2110
2111 save = params = list_rest_of_args ();
2112 if (save == 0)
2113 return ((char *)NULL);
2114
2115 for (i = 1; params && i < start; i++)
2116 params = params->next;
2117 if (params == 0)
2118 return ((char *)NULL);
2119 for (h = t = params; params && i < end; i++)
2120 {
2121 t = params;
2122 params = params->next;
2123 }
2124
2125 t->next = (WORD_LIST *)NULL;
2126 if (string[0] == '*')
2127 ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (quote_list (h)) : string_list (h);
2128 else
2129 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
2130 if (t != params)
2131 t->next = params;
2132
2133 dispose_words (save);
2134 return (ret);
2135 }
2136
2137 /******************************************************************/
2138 /* */
2139 /* Functions to expand strings to strings or WORD_LISTs */
2140 /* */
2141 /******************************************************************/
2142
2143 #if defined (PROCESS_SUBSTITUTION)
2144 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
2145 #else
2146 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
2147 #endif
2148
2149 /* If there are any characters in STRING that require full expansion,
2150 then call FUNC to expand STRING; otherwise just perform quote
2151 removal if necessary. This returns a new string. */
2152 static char *
2153 expand_string_if_necessary (string, quoted, func)
2154 char *string;
2155 int quoted;
2156 EXPFUNC *func;
2157 {
2158 WORD_LIST *list;
2159 size_t slen;
2160 int i, saw_quote;
2161 char *ret;
2162 DECLARE_MBSTATE;
2163
2164 slen = strlen (string);
2165 i = saw_quote = 0;
2166 while (string[i])
2167 {
2168 if (EXP_CHAR (string[i]))
2169 break;
2170 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
2171 saw_quote = 1;
2172 ADVANCE_CHAR (string, slen, i);
2173 }
2174
2175 if (string[i])
2176 {
2177 list = (*func) (string, quoted);
2178 if (list)
2179 {
2180 ret = string_list (list);
2181 dispose_words (list);
2182 }
2183 else
2184 ret = (char *)NULL;
2185 }
2186 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2187 ret = string_quote_removal (string, quoted);
2188 else
2189 ret = savestring (string);
2190
2191 return ret;
2192 }
2193
2194 static inline char *
2195 expand_string_to_string_internal (string, quoted, func)
2196 char *string;
2197 int quoted;
2198 EXPFUNC *func;
2199 {
2200 WORD_LIST *list;
2201 char *ret;
2202
2203 if (string == 0 || *string == '\0')
2204 return ((char *)NULL);
2205
2206 list = (*func) (string, quoted);
2207 if (list)
2208 {
2209 ret = string_list (list);
2210 dispose_words (list);
2211 }
2212 else
2213 ret = (char *)NULL;
2214
2215 return (ret);
2216 }
2217
2218 char *
2219 expand_string_to_string (string, quoted)
2220 char *string;
2221 int quoted;
2222 {
2223 return (expand_string_to_string_internal (string, quoted, expand_string));
2224 }
2225
2226 char *
2227 expand_string_unsplit_to_string (string, quoted)
2228 char *string;
2229 int quoted;
2230 {
2231 return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
2232 }
2233
2234 #if defined (COND_COMMAND)
2235 /* Just remove backslashes in STRING. Returns a new string. */
2236 char *
2237 remove_backslashes (string)
2238 char *string;
2239 {
2240 char *r, *ret, *s;
2241
2242 r = ret = (char *)xmalloc (strlen (string) + 1);
2243 for (s = string; s && *s; )
2244 {
2245 if (*s == '\\')
2246 s++;
2247 if (*s == 0)
2248 break;
2249 *r++ = *s++;
2250 }
2251 *r = '\0';
2252 return ret;
2253 }
2254
2255 /* This needs better error handling. */
2256 /* Expand W for use as an argument to a unary or binary operator in a
2257 [[...]] expression. If SPECIAL is nonzero, this is the rhs argument
2258 to the != or == operator, and should be treated as a pattern. In
2259 this case, we quote the string specially for the globbing code. The
2260 caller is responsible for removing the backslashes if the unquoted
2261 words is needed later. */
2262 char *
2263 cond_expand_word (w, special)
2264 WORD_DESC *w;
2265 int special;
2266 {
2267 char *r, *p;
2268 WORD_LIST *l;
2269
2270 if (w->word == 0 || w->word[0] == '\0')
2271 return ((char *)NULL);
2272
2273 if (xstrchr (w->word, '~') && unquoted_member ('~', w->word))
2274 {
2275 p = bash_tilde_expand (w->word, 0);
2276 free (w->word);
2277 w->word = p;
2278 }
2279
2280 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2281 if (l)
2282 {
2283 if (special == 0)
2284 {
2285 dequote_list (l);
2286 r = string_list (l);
2287 }
2288 else
2289 {
2290 p = string_list (l);
2291 r = quote_string_for_globbing (p, QGLOB_CVTNULL);
2292 free (p);
2293 }
2294 dispose_words (l);
2295 }
2296 else
2297 r = (char *)NULL;
2298
2299 return r;
2300 }
2301 #endif
2302
2303 /* Call expand_word_internal to expand W and handle error returns.
2304 A convenience function for functions that don't want to handle
2305 any errors or free any memory before aborting. */
2306 static WORD_LIST *
2307 call_expand_word_internal (w, q, i, c, e)
2308 WORD_DESC *w;
2309 int q, i, *c, *e;
2310 {
2311 WORD_LIST *result;
2312
2313 result = expand_word_internal (w, q, i, c, e);
2314 if (result == &expand_word_error || result == &expand_word_fatal)
2315 {
2316 expand_no_split_dollar_star = 0; /* XXX */
2317 /* By convention, each time this error is returned, w->word has
2318 already been freed (it sometimes may not be in the fatal case,
2319 but that doesn't result in a memory leak because we're going
2320 to exit in most cases). */
2321 w->word = (char *)NULL;
2322 last_command_exit_value = EXECUTION_FAILURE;
2323 jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2324 /* NOTREACHED */
2325 }
2326 else
2327 return (result);
2328 }
2329
2330 /* Perform parameter expansion, command substitution, and arithmetic
2331 expansion on STRING, as if it were a word. Leave the result quoted. */
2332 static WORD_LIST *
2333 expand_string_internal (string, quoted)
2334 char *string;
2335 int quoted;
2336 {
2337 WORD_DESC td;
2338 WORD_LIST *tresult;
2339
2340 if (string == 0 || *string == 0)
2341 return ((WORD_LIST *)NULL);
2342
2343 td.flags = 0;
2344 td.word = savestring (string);
2345
2346 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2347
2348 FREE (td.word);
2349 return (tresult);
2350 }
2351
2352 /* Expand STRING by performing parameter expansion, command substitution,
2353 and arithmetic expansion. Dequote the resulting WORD_LIST before
2354 returning it, but do not perform word splitting. The call to
2355 remove_quoted_nulls () is in here because word splitting normally
2356 takes care of quote removal. */
2357 WORD_LIST *
2358 expand_string_unsplit (string, quoted)
2359 char *string;
2360 int quoted;
2361 {
2362 WORD_LIST *value;
2363
2364 if (string == 0 || *string == '\0')
2365 return ((WORD_LIST *)NULL);
2366
2367 expand_no_split_dollar_star = 1;
2368 value = expand_string_internal (string, quoted);
2369 expand_no_split_dollar_star = 0;
2370
2371 if (value)
2372 {
2373 if (value->word)
2374 remove_quoted_nulls (value->word->word);
2375 dequote_list (value);
2376 }
2377 return (value);
2378 }
2379
2380
2381 /* Expand one of the PS? prompt strings. This is a sort of combination of
2382 expand_string_unsplit and expand_string_internal, but returns the
2383 passed string when an error occurs. Might want to trap other calls
2384 to jump_to_top_level here so we don't endlessly loop. */
2385 WORD_LIST *
2386 expand_prompt_string (string, quoted)
2387 char *string;
2388 int quoted;
2389 {
2390 WORD_LIST *value;
2391 WORD_DESC td;
2392
2393 if (string == 0 || *string == 0)
2394 return ((WORD_LIST *)NULL);
2395
2396 td.flags = 0;
2397 td.word = savestring (string);
2398
2399 no_longjmp_on_fatal_error = 1;
2400 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2401 no_longjmp_on_fatal_error = 0;
2402
2403 if (value == &expand_word_error || value == &expand_word_fatal)
2404 {
2405 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
2406 return value;
2407 }
2408 FREE (td.word);
2409 if (value)
2410 {
2411 if (value->word)
2412 remove_quoted_nulls (value->word->word);
2413 dequote_list (value);
2414 }
2415 return (value);
2416 }
2417
2418 /* Expand STRING just as if you were expanding a word, but do not dequote
2419 the resultant WORD_LIST. This is called only from within this file,
2420 and is used to correctly preserve quoted characters when expanding
2421 things like ${1+"$@"}. This does parameter expansion, command
2422 substitution, arithmetic expansion, and word splitting. */
2423 static WORD_LIST *
2424 expand_string_leave_quoted (string, quoted)
2425 char *string;
2426 int quoted;
2427 {
2428 WORD_LIST *tlist;
2429 WORD_LIST *tresult;
2430
2431 if (string == 0 || *string == '\0')
2432 return ((WORD_LIST *)NULL);
2433
2434 tlist = expand_string_internal (string, quoted);
2435
2436 if (tlist)
2437 {
2438 tresult = word_list_split (tlist);
2439 dispose_words (tlist);
2440 return (tresult);
2441 }
2442 return ((WORD_LIST *)NULL);
2443 }
2444
2445 /* This does not perform word splitting or dequote the WORD_LIST
2446 it returns. */
2447 static WORD_LIST *
2448 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
2449 char *string;
2450 int quoted, *dollar_at_p, *has_dollar_at;
2451 {
2452 WORD_DESC td;
2453 WORD_LIST *tresult;
2454
2455 if (string == 0 || *string == '\0')
2456 return (WORD_LIST *)NULL;
2457
2458 td.flags = 0;
2459 td.word = string;
2460 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
2461 return (tresult);
2462 }
2463
2464 /* Expand STRING just as if you were expanding a word. This also returns
2465 a list of words. Note that filename globbing is *NOT* done for word
2466 or string expansion, just when the shell is expanding a command. This
2467 does parameter expansion, command substitution, arithmetic expansion,
2468 and word splitting. Dequote the resultant WORD_LIST before returning. */
2469 WORD_LIST *
2470 expand_string (string, quoted)
2471 char *string;
2472 int quoted;
2473 {
2474 WORD_LIST *result;
2475
2476 if (string == 0 || *string == '\0')
2477 return ((WORD_LIST *)NULL);
2478
2479 result = expand_string_leave_quoted (string, quoted);
2480 return (result ? dequote_list (result) : result);
2481 }
2482
2483 /***************************************************
2484 * *
2485 * Functions to handle quoting chars *
2486 * *
2487 ***************************************************/
2488
2489 /* Conventions:
2490
2491 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
2492 The parser passes CTLNUL as CTLESC CTLNUL. */
2493
2494 /* Quote escape characters in string s, but no other characters. This is
2495 used to protect CTLESC and CTLNUL in variable values from the rest of
2496 the word expansion process after the variable is expanded. */
2497 char *
2498 quote_escapes (string)
2499 char *string;
2500 {
2501 register char *s, *t;
2502 size_t slen;
2503 char *result, *send;
2504 DECLARE_MBSTATE;
2505
2506 slen = strlen (string);
2507 send = string + slen;
2508
2509 t = result = (char *)xmalloc ((slen * 2) + 1);
2510 s = string;
2511
2512 while (*s)
2513 {
2514 if (*s == CTLESC || *s == CTLNUL)
2515 *t++ = CTLESC;
2516 COPY_CHAR_P (t, s, send);
2517 }
2518 *t = '\0';
2519 return (result);
2520 }
2521
2522 static WORD_LIST *
2523 list_quote_escapes (list)
2524 WORD_LIST *list;
2525 {
2526 register WORD_LIST *w;
2527 char *t;
2528
2529 for (w = list; w; w = w->next)
2530 {
2531 t = w->word->word;
2532 w->word->word = quote_escapes (t);
2533 free (t);
2534 }
2535 return list;
2536 }
2537
2538 /* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
2539
2540 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2541 This is necessary to make unquoted CTLESC and CTLNUL characters in the
2542 data stream pass through properly.
2543
2544 We need to remove doubled CTLESC characters inside quoted strings before
2545 quoting the entire string, so we do not double the number of CTLESC
2546 characters.
2547
2548 Also used by parts of the pattern substitution code. */
2549 static char *
2550 dequote_escapes (string)
2551 char *string;
2552 {
2553 register char *s, *t;
2554 size_t slen;
2555 char *result, *send;
2556 DECLARE_MBSTATE;
2557
2558 if (string == 0)
2559 return string;
2560
2561 slen = strlen (string);
2562 send = string + slen;
2563
2564 t = result = (char *)xmalloc (slen + 1);
2565 s = string;
2566
2567 if (strchr (string, CTLESC) == 0)
2568 return (strcpy (result, s));
2569
2570 while (*s)
2571 {
2572 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2573 {
2574 s++;
2575 if (*s == '\0')
2576 break;
2577 }
2578 COPY_CHAR_P (t, s, send);
2579 }
2580 *t = '\0';
2581 return result;
2582 }
2583
2584 /* Return a new string with the quoted representation of character C. */
2585 static char *
2586 make_quoted_char (c)
2587 int c;
2588 {
2589 char *temp;
2590
2591 temp = (char *)xmalloc (3);
2592 if (c == 0)
2593 {
2594 temp[0] = CTLNUL;
2595 temp[1] = '\0';
2596 }
2597 else
2598 {
2599 temp[0] = CTLESC;
2600 temp[1] = c;
2601 temp[2] = '\0';
2602 }
2603 return (temp);
2604 }
2605
2606 /* Quote STRING. Return a new string. */
2607 char *
2608 quote_string (string)
2609 char *string;
2610 {
2611 register char *t;
2612 size_t slen;
2613 char *result, *send;
2614
2615 if (*string == 0)
2616 {
2617 result = (char *)xmalloc (2);
2618 result[0] = CTLNUL;
2619 result[1] = '\0';
2620 }
2621 else
2622 {
2623 DECLARE_MBSTATE;
2624
2625 slen = strlen (string);
2626 send = string + slen;
2627
2628 result = (char *)xmalloc ((slen * 2) + 1);
2629
2630 for (t = result; string < send; )
2631 {
2632 *t++ = CTLESC;
2633 COPY_CHAR_P (t, string, send);
2634 }
2635 *t = '\0';
2636 }
2637 return (result);
2638 }
2639
2640 /* De-quoted quoted characters in STRING. */
2641 char *
2642 dequote_string (string)
2643 char *string;
2644 {
2645 register char *s, *t;
2646 size_t slen;
2647 char *result, *send;
2648 DECLARE_MBSTATE;
2649
2650 slen = strlen (string);
2651
2652 t = result = (char *)xmalloc (slen + 1);
2653
2654 if (QUOTED_NULL (string))
2655 {
2656 result[0] = '\0';
2657 return (result);
2658 }
2659
2660 /* If no character in the string can be quoted, don't bother examining
2661 each character. Just return a copy of the string passed to us. */
2662 if (strchr (string, CTLESC) == NULL)
2663 return (strcpy (result, string));
2664
2665 send = string + slen;
2666 s = string;
2667 while (*s)
2668 {
2669 if (*s == CTLESC)
2670 {
2671 s++;
2672 if (*s == '\0')
2673 break;
2674 }
2675 COPY_CHAR_P (t, s, send);
2676 }
2677
2678 *t = '\0';
2679 return (result);
2680 }
2681
2682 /* Quote the entire WORD_LIST list. */
2683 static WORD_LIST *
2684 quote_list (list)
2685 WORD_LIST *list;
2686 {
2687 register WORD_LIST *w;
2688 char *t;
2689
2690 for (w = list; w; w = w->next)
2691 {
2692 t = w->word->word;
2693 w->word->word = quote_string (t);
2694 free (t);
2695 w->word->flags |= W_QUOTED;
2696 }
2697 return list;
2698 }
2699
2700 static WORD_LIST *
2701 dequote_list (list)
2702 WORD_LIST *list;
2703 {
2704 register char *s;
2705 register WORD_LIST *tlist;
2706
2707 for (tlist = list; tlist; tlist = tlist->next)
2708 {
2709 s = dequote_string (tlist->word->word);
2710 free (tlist->word->word);
2711 tlist->word->word = s;
2712 }
2713 return list;
2714 }
2715
2716 /* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
2717 string. */
2718 static char *
2719 remove_quoted_escapes (string)
2720 char *string;
2721 {
2722 char *t;
2723
2724 if (string)
2725 {
2726 t = dequote_escapes (string);
2727 strcpy (string, t);
2728 free (t);
2729 }
2730
2731 return (string);
2732 }
2733
2734 /* Perform quoted null character removal on STRING. We don't allow any
2735 quoted null characters in the middle or at the ends of strings because
2736 of how expand_word_internal works. remove_quoted_nulls () turns
2737 STRING into an empty string iff it only consists of a quoted null,
2738 and removes all unquoted CTLNUL characters. */
2739 static char *
2740 remove_quoted_nulls (string)
2741 char *string;
2742 {
2743 register size_t slen;
2744 register int i, j, prev_i;
2745 DECLARE_MBSTATE;
2746
2747 if (strchr (string, CTLNUL) == 0) /* XXX */
2748 return string; /* XXX */
2749
2750 slen = strlen (string);
2751 i = j = 0;
2752
2753 while (i < slen)
2754 {
2755 if (string[i] == CTLESC)
2756 {
2757 i++; j++;
2758 if (i == slen)
2759 break;
2760 }
2761 else if (string[i] == CTLNUL)
2762 i++;
2763
2764 prev_i = i;
2765 ADVANCE_CHAR (string, slen, i);
2766 if (j < prev_i)
2767 {
2768 do string[j++] = string[prev_i++]; while (prev_i < i);
2769 }
2770 else
2771 j = i;
2772 }
2773 string[j] = '\0';
2774
2775 return (string);
2776 }
2777
2778 /* Perform quoted null character removal on each element of LIST.
2779 This modifies LIST. */
2780 void
2781 word_list_remove_quoted_nulls (list)
2782 WORD_LIST *list;
2783 {
2784 register WORD_LIST *t;
2785
2786 for (t = list; t; t = t->next)
2787 remove_quoted_nulls (t->word->word);
2788 }
2789
2790 /* **************************************************************** */
2791 /* */
2792 /* Functions for Matching and Removing Patterns */
2793 /* */
2794 /* **************************************************************** */
2795
2796 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
2797 can have one of 4 values:
2798 RP_LONG_LEFT remove longest matching portion at start of PARAM
2799 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
2800 RP_LONG_RIGHT remove longest matching portion at end of PARAM
2801 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
2802 */
2803
2804 #define RP_LONG_LEFT 1
2805 #define RP_SHORT_LEFT 2
2806 #define RP_LONG_RIGHT 3
2807 #define RP_SHORT_RIGHT 4
2808
2809 static char *
2810 remove_pattern (param, pattern, op)
2811 char *param, *pattern;
2812 int op;
2813 {
2814 register int len;
2815 register char *end;
2816 register char *p, *ret, c;
2817
2818 if (param == NULL || *param == '\0')
2819 return (param);
2820 if (pattern == NULL || *pattern == '\0') /* minor optimization */
2821 return (savestring (param));
2822
2823 len = STRLEN (param);
2824 end = param + len;
2825
2826 switch (op)
2827 {
2828 case RP_LONG_LEFT: /* remove longest match at start */
2829 for (p = end; p >= param; p--)
2830 {
2831 c = *p; *p = '\0';
2832 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2833 {
2834 *p = c;
2835 return (savestring (p));
2836 }
2837 *p = c;
2838 }
2839 break;
2840
2841 case RP_SHORT_LEFT: /* remove shortest match at start */
2842 for (p = param; p <= end; p++)
2843 {
2844 c = *p; *p = '\0';
2845 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2846 {
2847 *p = c;
2848 return (savestring (p));
2849 }
2850 *p = c;
2851 }
2852 break;
2853
2854 case RP_LONG_RIGHT: /* remove longest match at end */
2855 for (p = param; p <= end; p++)
2856 {
2857 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2858 {
2859 c = *p; *p = '\0';
2860 ret = savestring (param);
2861 *p = c;
2862 return (ret);
2863 }
2864 }
2865 break;
2866
2867 case RP_SHORT_RIGHT: /* remove shortest match at end */
2868 for (p = end; p >= param; p--)
2869 {
2870 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
2871 {
2872 c = *p; *p = '\0';
2873 ret = savestring (param);
2874 *p = c;
2875 return (ret);
2876 }
2877 }
2878 break;
2879 }
2880 return (savestring (param)); /* no match, return original string */
2881 }
2882
2883 /* Return 1 of the first character of STRING could match the first
2884 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
2885 static int
2886 match_pattern_char (pat, string)
2887 char *pat, *string;
2888 {
2889 char c;
2890
2891 if (*string == 0)
2892 return (0);
2893
2894 switch (c = *pat++)
2895 {
2896 default:
2897 return (*string == c);
2898 case '\\':
2899 return (*string == *pat);
2900 case '?':
2901 return (*pat == LPAREN ? 1 : (*string != '\0'));
2902 case '*':
2903 return (1);
2904 case '+':
2905 case '!':
2906 case '@':
2907 return (*pat == LPAREN ? 1 : (*string == c));
2908 case '[':
2909 return (*string != '\0');
2910 }
2911 }
2912
2913 /* Match PAT anywhere in STRING and return the match boundaries.
2914 This returns 1 in case of a successful match, 0 otherwise. SP
2915 and EP are pointers into the string where the match begins and
2916 ends, respectively. MTYPE controls what kind of match is attempted.
2917 MATCH_BEG and MATCH_END anchor the match at the beginning and end
2918 of the string, respectively. The longest match is returned. */
2919 static int
2920 match_pattern (string, pat, mtype, sp, ep)
2921 char *string, *pat;
2922 int mtype;
2923 char **sp, **ep;
2924 {
2925 int c;
2926 register char *p, *p1;
2927 char *end;
2928
2929 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
2930 return (0);
2931
2932 end = string + STRLEN (string);
2933
2934 switch (mtype)
2935 {
2936 case MATCH_ANY:
2937 for (p = string; p <= end; p++)
2938 {
2939 if (match_pattern_char (pat, p))
2940 {
2941 for (p1 = end; p1 >= p; p1--)
2942 {
2943 c = *p1; *p1 = '\0';
2944 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
2945 {
2946 *p1 = c;
2947 *sp = p;
2948 *ep = p1;
2949 return 1;
2950 }
2951 *p1 = c;
2952 }
2953 }
2954 }
2955 return (0);
2956
2957 case MATCH_BEG:
2958 if (match_pattern_char (pat, string) == 0)
2959 return (0);
2960 for (p = end; p >= string; p--)
2961 {
2962 c = *p; *p = '\0';
2963 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
2964 {
2965 *p = c;
2966 *sp = string;
2967 *ep = p;
2968 return 1;
2969 }
2970 *p = c;
2971 }
2972 return (0);
2973
2974 case MATCH_END:
2975 for (p = string; p <= end; p++)
2976 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
2977 {
2978 *sp = p;
2979 *ep = end;
2980 return 1;
2981 }
2982 return (0);
2983 }
2984
2985 return (0);
2986 }
2987
2988 static int
2989 getpatspec (c, value)
2990 int c;
2991 char *value;
2992 {
2993 if (c == '#')
2994 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
2995 else /* c == '%' */
2996 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
2997 }
2998
2999 /* Posix.2 says that the WORD should be run through tilde expansion,
3000 parameter expansion, command substitution and arithmetic expansion.
3001 This leaves the result quoted, so quote_string_for_globbing () has
3002 to be called to fix it up for strmatch (). If QUOTED is non-zero,
3003 it means that the entire expression was enclosed in double quotes.
3004 This means that quoting characters in the pattern do not make any
3005 special pattern characters quoted. For example, the `*' in the
3006 following retains its special meaning: "${foo#'*'}". */
3007 static char *
3008 getpattern (value, quoted, expandpat)
3009 char *value;
3010 int quoted, expandpat;
3011 {
3012 char *pat, *tword;
3013 WORD_LIST *l;
3014 int i;
3015
3016 tword = xstrchr (value, '~') ? bash_tilde_expand (value, 0) : savestring (value);
3017
3018 /* There is a problem here: how to handle single or double quotes in the
3019 pattern string when the whole expression is between double quotes?
3020 POSIX.2 says that enclosing double quotes do not cause the pattern to
3021 be quoted, but does that leave us a problem with @ and array[@] and their
3022 expansions inside a pattern? */
3023 #if 0
3024 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
3025 {
3026 i = 0;
3027 pat = string_extract_double_quoted (tword, &i, 1);
3028 free (tword);
3029 tword = pat;
3030 }
3031 #endif
3032
3033 /* expand_string_for_rhs () leaves WORD quoted and does not perform
3034 word splitting. */
3035 l = *tword ? expand_string_for_rhs (tword,
3036 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
3037 (int *)NULL, (int *)NULL)
3038 : (WORD_LIST *)0;
3039 free (tword);
3040 pat = string_list (l);
3041 dispose_words (l);
3042 if (pat)
3043 {
3044 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
3045 free (pat);
3046 pat = tword;
3047 }
3048 return (pat);
3049 }
3050
3051 #if 0
3052 /* Handle removing a pattern from a string as a result of ${name%[%]value}
3053 or ${name#[#]value}. */
3054 static char *
3055 variable_remove_pattern (value, pattern, patspec, quoted)
3056 char *value, *pattern;
3057 int patspec, quoted;
3058 {
3059 char *tword;
3060
3061 tword = remove_pattern (value, pattern, patspec);
3062
3063 return (tword);
3064 }
3065 #endif
3066
3067 static char *
3068 list_remove_pattern (list, pattern, patspec, itype, quoted)
3069 WORD_LIST *list;
3070 char *pattern;
3071 int patspec, itype, quoted;
3072 {
3073 WORD_LIST *new, *l;
3074 WORD_DESC *w;
3075 char *tword;
3076
3077 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
3078 {
3079 tword = remove_pattern (l->word->word, pattern, patspec);
3080 w = make_bare_word (tword);
3081 free (tword);
3082 new = make_word_list (w, new);
3083 }
3084
3085 l = REVERSE_LIST (new, WORD_LIST *);
3086 if (itype == '*')
3087 tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
3088 else
3089 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3090
3091 dispose_words (l);
3092 return (tword);
3093 }
3094
3095 static char *
3096 parameter_list_remove_pattern (itype, pattern, patspec, quoted)
3097 int itype;
3098 char *pattern;
3099 int patspec, quoted;
3100 {
3101 char *ret;
3102 WORD_LIST *list;
3103
3104 list = list_rest_of_args ();
3105 if (list == 0)
3106 return ((char *)NULL);
3107 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3108 dispose_words (list);
3109 return (ret);
3110 }
3111
3112 #if defined (ARRAY_VARS)
3113 static char *
3114 array_remove_pattern (a, pattern, patspec, varname, quoted)
3115 ARRAY *a;
3116 char *pattern;
3117 int patspec;
3118 char *varname; /* so we can figure out how it's indexed */
3119 int quoted;
3120 {
3121 int itype;
3122 char *ret;
3123 WORD_LIST *list;
3124 SHELL_VAR *v;
3125
3126 /* compute itype from varname here */
3127 v = array_variable_part (varname, &ret, 0);
3128 itype = ret[0];
3129
3130 list = array_to_word_list (a);
3131 if (list == 0)
3132 return ((char *)NULL);
3133 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3134 dispose_words (list);
3135
3136 return ret;
3137 }
3138 #endif /* ARRAY_VARS */
3139
3140 static char *
3141 parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
3142 char *varname, *value, *patstr;
3143 int rtype, quoted;
3144 {
3145 int vtype, patspec;
3146 char *temp1, *val, *pattern;
3147 SHELL_VAR *v;
3148
3149 if (value == 0)
3150 return ((char *)NULL);
3151
3152 this_command_name = varname;
3153
3154 vtype = get_var_and_type (varname, value, &v, &val);
3155 if (vtype == -1)
3156 return ((char *)NULL);
3157
3158 patspec = getpatspec (rtype, patstr);
3159 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
3160 patstr++;
3161
3162 pattern = getpattern (patstr, quoted, 1);
3163
3164 temp1 = (char *)NULL; /* shut up gcc */
3165 switch (vtype)
3166 {
3167 case VT_VARIABLE:
3168 case VT_ARRAYMEMBER:
3169 temp1 = remove_pattern (val, pattern, patspec);
3170 if (vtype == VT_VARIABLE)
3171 FREE (val);
3172 if (temp1)
3173 {
3174 val = quote_escapes (temp1);
3175 free (temp1);
3176 temp1 = val;
3177 }
3178 break;
3179 #if defined (ARRAY_VARS)
3180 case VT_ARRAYVAR:
3181 temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
3182 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3183 {
3184 val = quote_escapes (temp1);
3185 free (temp1);
3186 temp1 = val;
3187 }
3188 break;
3189 #endif
3190 case VT_POSPARMS:
3191 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
3192 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3193 {
3194 val = quote_escapes (temp1);
3195 free (temp1);
3196 temp1 = val;
3197 }
3198 break;
3199 }
3200
3201 FREE (pattern);
3202 return temp1;
3203 }
3204
3205 /*******************************************
3206 * *
3207 * Functions to expand WORD_DESCs *
3208 * *
3209 *******************************************/
3210
3211 /* Expand WORD, performing word splitting on the result. This does
3212 parameter expansion, command substitution, arithmetic expansion,
3213 word splitting, and quote removal. */
3214
3215 WORD_LIST *
3216 expand_word (word, quoted)
3217 WORD_DESC *word;
3218 int quoted;
3219 {
3220 WORD_LIST *result, *tresult;
3221
3222 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
3223 result = word_list_split (tresult);
3224 dispose_words (tresult);
3225 return (result ? dequote_list (result) : result);
3226 }
3227
3228 /* Expand WORD, but do not perform word splitting on the result. This
3229 does parameter expansion, command substitution, arithmetic expansion,
3230 and quote removal. */
3231 WORD_LIST *
3232 expand_word_unsplit (word, quoted)
3233 WORD_DESC *word;
3234 int quoted;
3235 {
3236 WORD_LIST *result;
3237
3238 expand_no_split_dollar_star = 1;
3239 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
3240 expand_no_split_dollar_star = 0;
3241
3242 return (result ? dequote_list (result) : result);
3243 }
3244
3245 /* Perform shell expansions on WORD, but do not perform word splitting or
3246 quote removal on the result. */
3247 WORD_LIST *
3248 expand_word_leave_quoted (word, quoted)
3249 WORD_DESC *word;
3250 int quoted;
3251 {
3252 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
3253 }
3254
3255 #if defined (PROCESS_SUBSTITUTION)
3256
3257 /*****************************************************************/
3258 /* */
3259 /* Hacking Process Substitution */
3260 /* */
3261 /*****************************************************************/
3262
3263 #if !defined (HAVE_DEV_FD)
3264 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
3265 of FIFOs the shell has open. unlink_fifo_list will walk the list and
3266 unlink all of them. add_fifo_list adds the name of an open FIFO to the
3267 list. NFIFO is a count of the number of FIFOs in the list. */
3268 #define FIFO_INCR 20
3269
3270 struct temp_fifo {
3271 char *file;
3272 pid_t proc;
3273 };
3274
3275 static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
3276 static int nfifo;
3277 static int fifo_list_size;
3278
3279 static void
3280 add_fifo_list (pathname)
3281 char *pathname;
3282 {
3283 if (nfifo >= fifo_list_size - 1)
3284 {
3285 fifo_list_size += FIFO_INCR;
3286 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
3287 fifo_list_size * sizeof (struct temp_fifo));
3288 }
3289
3290 fifo_list[nfifo].file = savestring (pathname);
3291 nfifo++;
3292 }
3293
3294 void
3295 unlink_fifo_list ()
3296 {
3297 int saved, i, j;
3298
3299 if (nfifo == 0)
3300 return;
3301
3302 for (i = saved = 0; i < nfifo; i++)
3303 {
3304 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
3305 {
3306 unlink (fifo_list[i].file);
3307 free (fifo_list[i].file);
3308 fifo_list[i].file = (char *)NULL;
3309 fifo_list[i].proc = -1;
3310 }
3311 else
3312 saved++;
3313 }
3314
3315 /* If we didn't remove some of the FIFOs, compact the list. */
3316 if (saved)
3317 {
3318 for (i = j = 0; i < nfifo; i++)
3319 if (fifo_list[i].file)
3320 {
3321 fifo_list[j].file = fifo_list[i].file;
3322 fifo_list[j].proc = fifo_list[i].proc;
3323 j++;
3324 }
3325 nfifo = j;
3326 }
3327 else
3328 nfifo = 0;
3329 }
3330
3331 static char *
3332 make_named_pipe ()
3333 {
3334 char *tname;
3335
3336 tname = sh_mktmpname ("sh-np", MT_USERANDOM);
3337 if (mkfifo (tname, 0600) < 0)
3338 {
3339 free (tname);
3340 return ((char *)NULL);
3341 }
3342
3343 add_fifo_list (tname);
3344 return (tname);
3345 }
3346
3347 #else /* HAVE_DEV_FD */
3348
3349 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
3350 has open to children. NFDS is a count of the number of bits currently
3351 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
3352 of open files. */
3353 static char *dev_fd_list = (char *)NULL;
3354 static int nfds;
3355 static int totfds; /* The highest possible number of open files. */
3356
3357 static void
3358 add_fifo_list (fd)
3359 int fd;
3360 {
3361 if (!dev_fd_list || fd >= totfds)
3362 {
3363 int ofds;
3364
3365 ofds = totfds;
3366 totfds = getdtablesize ();
3367 if (totfds < 0 || totfds > 256)
3368 totfds = 256;
3369 if (fd > totfds)
3370 totfds = fd + 2;
3371
3372 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
3373 memset (dev_fd_list + ofds, '\0', totfds - ofds);
3374 }
3375
3376 dev_fd_list[fd] = 1;
3377 nfds++;
3378 }
3379
3380 void
3381 unlink_fifo_list ()
3382 {
3383 register int i;
3384
3385 if (nfds == 0)
3386 return;
3387
3388 for (i = 0; nfds && i < totfds; i++)
3389 if (dev_fd_list[i])
3390 {
3391 close (i);
3392 dev_fd_list[i] = 0;
3393 nfds--;
3394 }
3395
3396 nfds = 0;
3397 }
3398
3399 #if defined (NOTDEF)
3400 print_dev_fd_list ()
3401 {
3402 register int i;
3403
3404 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
3405 fflush (stderr);
3406
3407 for (i = 0; i < totfds; i++)
3408 {
3409 if (dev_fd_list[i])
3410 fprintf (stderr, " %d", i);
3411 }
3412 fprintf (stderr, "\n");
3413 }
3414 #endif /* NOTDEF */
3415
3416 static char *
3417 make_dev_fd_filename (fd)
3418 int fd;
3419 {
3420 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
3421
3422 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
3423
3424 strcpy (ret, DEV_FD_PREFIX);
3425 p = inttostr (fd, intbuf, sizeof (intbuf));
3426 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
3427
3428 add_fifo_list (fd);
3429 return (ret);
3430 }
3431
3432 #endif /* HAVE_DEV_FD */
3433
3434 /* Return a filename that will open a connection to the process defined by
3435 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
3436 a filename in /dev/fd corresponding to a descriptor that is one of the
3437 ends of the pipe. If not defined, we use named pipes on systems that have
3438 them. Systems without /dev/fd and named pipes are out of luck.
3439
3440 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
3441 use the read end of the pipe and dup that file descriptor to fd 0 in
3442 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
3443 writing or use the write end of the pipe in the child, and dup that
3444 file descriptor to fd 1 in the child. The parent does the opposite. */
3445
3446 static char *
3447 process_substitute (string, open_for_read_in_child)
3448 char *string;
3449 int open_for_read_in_child;
3450 {
3451 char *pathname;
3452 int fd, result;
3453 pid_t old_pid, pid;
3454 #if defined (HAVE_DEV_FD)
3455 int parent_pipe_fd, child_pipe_fd;
3456 int fildes[2];
3457 #endif /* HAVE_DEV_FD */
3458 #if defined (JOB_CONTROL)
3459 pid_t old_pipeline_pgrp;
3460 #endif
3461
3462 if (!string || !*string || wordexp_only)
3463 return ((char *)NULL);
3464
3465 #if !defined (HAVE_DEV_FD)
3466 pathname = make_named_pipe ();
3467 #else /* HAVE_DEV_FD */
3468 if (pipe (fildes) < 0)
3469 {
3470 sys_error ("cannot make pipe for process substitution");
3471 return ((char *)NULL);
3472 }
3473 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
3474 the pipe in the parent, otherwise the read end. */
3475 parent_pipe_fd = fildes[open_for_read_in_child];
3476 child_pipe_fd = fildes[1 - open_for_read_in_child];
3477 /* Move the parent end of the pipe to some high file descriptor, to
3478 avoid clashes with FDs used by the script. */
3479 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
3480
3481 pathname = make_dev_fd_filename (parent_pipe_fd);
3482 #endif /* HAVE_DEV_FD */
3483
3484 if (!pathname)
3485 {
3486 sys_error ("cannot make pipe for process substitution");
3487 return ((char *)NULL);
3488 }
3489
3490 old_pid = last_made_pid;
3491
3492 #if defined (JOB_CONTROL)
3493 old_pipeline_pgrp = pipeline_pgrp;
3494 pipeline_pgrp = shell_pgrp;
3495 save_pipeline (1);
3496 #endif /* JOB_CONTROL */
3497
3498 pid = make_child ((char *)NULL, 1);
3499 if (pid == 0)
3500 {
3501 reset_terminating_signals (); /* XXX */
3502 /* Cancel traps, in trap.c. */
3503 restore_original_signals ();
3504 setup_async_signals ();
3505 subshell_environment |= SUBSHELL_COMSUB;
3506 }
3507
3508 #if defined (JOB_CONTROL)
3509 set_sigchld_handler ();
3510 stop_making_children ();
3511 pipeline_pgrp = old_pipeline_pgrp;
3512 #endif /* JOB_CONTROL */
3513
3514 if (pid < 0)
3515 {
3516 sys_error ("cannot make child for process substitution");
3517 free (pathname);
3518 #if defined (HAVE_DEV_FD)
3519 close (parent_pipe_fd);
3520 close (child_pipe_fd);
3521 #endif /* HAVE_DEV_FD */
3522 return ((char *)NULL);
3523 }
3524
3525 if (pid > 0)
3526 {
3527 #if defined (JOB_CONTROL)
3528 restore_pipeline (1);
3529 #endif
3530
3531 #if !defined (HAVE_DEV_FD)
3532 fifo_list[nfifo-1].proc = pid;
3533 #endif
3534
3535 last_made_pid = old_pid;
3536
3537 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
3538 close_pgrp_pipe ();
3539 #endif /* JOB_CONTROL && PGRP_PIPE */
3540
3541 #if defined (HAVE_DEV_FD)
3542 close (child_pipe_fd);
3543 #endif /* HAVE_DEV_FD */
3544
3545 return (pathname);
3546 }
3547
3548 set_sigint_handler ();
3549
3550 #if defined (JOB_CONTROL)
3551 set_job_control (0);
3552 #endif /* JOB_CONTROL */
3553
3554 #if !defined (HAVE_DEV_FD)
3555 /* Open the named pipe in the child. */
3556 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
3557 if (fd < 0)
3558 {
3559 sys_error ("cannot open named pipe %s for %s", pathname,
3560 open_for_read_in_child ? "reading" : "writing");
3561 exit (127);
3562 }
3563 if (open_for_read_in_child)
3564 {
3565 if (sh_unset_nodelay_mode (fd) < 0)
3566 {
3567 sys_error ("cannout reset nodelay mode for fd %d", fd);
3568 exit (127);
3569 }
3570 }
3571 #else /* HAVE_DEV_FD */
3572 fd = child_pipe_fd;
3573 #endif /* HAVE_DEV_FD */
3574
3575 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
3576 {
3577 sys_error ("cannot duplicate named pipe %s as fd %d", pathname,
3578 open_for_read_in_child ? 0 : 1);
3579 exit (127);
3580 }
3581
3582 if (fd != (open_for_read_in_child ? 0 : 1))
3583 close (fd);
3584
3585 /* Need to close any files that this process has open to pipes inherited
3586 from its parent. */
3587 if (current_fds_to_close)
3588 {
3589 close_fd_bitmap (current_fds_to_close);
3590 current_fds_to_close = (struct fd_bitmap *)NULL;
3591 }
3592
3593 #if defined (HAVE_DEV_FD)
3594 /* Make sure we close the parent's end of the pipe and clear the slot
3595 in the fd list so it is not closed later, if reallocated by, for
3596 instance, pipe(2). */
3597 close (parent_pipe_fd);
3598 dev_fd_list[parent_pipe_fd] = 0;
3599 #endif /* HAVE_DEV_FD */
3600
3601 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
3602
3603 #if !defined (HAVE_DEV_FD)
3604 /* Make sure we close the named pipe in the child before we exit. */
3605 close (open_for_read_in_child ? 0 : 1);
3606 #endif /* !HAVE_DEV_FD */
3607
3608 exit (result);
3609 /*NOTREACHED*/
3610 }
3611 #endif /* PROCESS_SUBSTITUTION */
3612
3613 /***********************************/
3614 /* */
3615 /* Command Substitution */
3616 /* */
3617 /***********************************/
3618
3619 static char *
3620 read_comsub (fd, quoted)
3621 int fd, quoted;
3622 {
3623 char *istring, buf[128], *bufp;
3624 int istring_index, istring_size, c;
3625 ssize_t bufn;
3626
3627 istring = (char *)NULL;
3628 istring_index = istring_size = bufn = 0;
3629
3630 #ifdef __CYGWIN__
3631 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
3632 #endif
3633
3634 /* Read the output of the command through the pipe. */
3635 while (1)
3636 {
3637 if (fd < 0)
3638 break;
3639 if (--bufn <= 0)
3640 {
3641 bufn = zread (fd, buf, sizeof (buf));
3642 if (bufn <= 0)
3643 break;
3644 bufp = buf;
3645 }
3646 c = *bufp++;
3647
3648 if (c == 0)
3649 {
3650 #if 0
3651 internal_warning ("read_comsub: ignored null byte in input");
3652 #endif
3653 continue;
3654 }
3655
3656 /* Add the character to ISTRING, possibly after resizing it. */
3657 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
3658
3659 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
3660 istring[istring_index++] = CTLESC;
3661
3662 istring[istring_index++] = c;
3663
3664 #if 0
3665 #if defined (__CYGWIN__)
3666 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
3667 {
3668 istring_index--;
3669 istring[istring_index - 1] = '\n';
3670 }
3671 #endif
3672 #endif
3673 }
3674
3675 if (istring)
3676 istring[istring_index] = '\0';
3677
3678 /* If we read no output, just return now and save ourselves some
3679 trouble. */
3680 if (istring_index == 0)
3681 {
3682 FREE (istring);
3683 return (char *)NULL;
3684 }
3685
3686 /* Strip trailing newlines from the output of the command. */
3687 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
3688 {
3689 while (istring_index > 0)
3690 {
3691 if (istring[istring_index - 1] == '\n')
3692 {
3693 --istring_index;
3694
3695 /* If the newline was quoted, remove the quoting char. */
3696 if (istring[istring_index - 1] == CTLESC)
3697 --istring_index;
3698 }
3699 else
3700 break;
3701 }
3702 istring[istring_index] = '\0';
3703 }
3704 else
3705 strip_trailing (istring, istring_index - 1, 1);
3706
3707 return istring;
3708 }
3709
3710 /* Perform command substitution on STRING. This returns a string,
3711 possibly quoted. */
3712 char *
3713 command_substitute (string, quoted)
3714 char *string;
3715 int quoted;
3716 {
3717 pid_t pid, old_pid, old_pipeline_pgrp;
3718 char *istring;
3719 int result, fildes[2], function_value;
3720
3721 istring = (char *)NULL;
3722
3723 /* Don't fork () if there is no need to. In the case of no command to
3724 run, just return NULL. */
3725 if (!string || !*string || (string[0] == '\n' && !string[1]))
3726 return ((char *)NULL);
3727
3728 if (wordexp_only && read_but_dont_execute)
3729 {
3730 last_command_exit_value = 125;
3731 jump_to_top_level (EXITPROG);
3732 }
3733
3734 /* We're making the assumption here that the command substitution will
3735 eventually run a command from the file system. Since we'll run
3736 maybe_make_export_env in this subshell before executing that command,
3737 the parent shell and any other shells it starts will have to remake
3738 the environment. If we make it before we fork, other shells won't
3739 have to. Don't bother if we have any temporary variable assignments,
3740 though, because the export environment will be remade after this
3741 command completes anyway, but do it if all the words to be expanded
3742 are variable assignments. */
3743 if (subst_assign_varlist == 0 || garglist == 0)
3744 maybe_make_export_env (); /* XXX */
3745
3746 /* Pipe the output of executing STRING into the current shell. */
3747 if (pipe (fildes) < 0)
3748 {
3749 sys_error ("cannot make pipe for command substitution");
3750 goto error_exit;
3751 }
3752
3753 old_pid = last_made_pid;
3754 #if defined (JOB_CONTROL)
3755 old_pipeline_pgrp = pipeline_pgrp;
3756 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
3757 if ((subshell_environment & SUBSHELL_PIPE) == 0)
3758 pipeline_pgrp = shell_pgrp;
3759 cleanup_the_pipeline ();
3760 #endif
3761
3762 pid = make_child ((char *)NULL, 0);
3763 if (pid == 0)
3764 /* Reset the signal handlers in the child, but don't free the
3765 trap strings. */
3766 reset_signal_handlers ();
3767
3768 #if defined (JOB_CONTROL)
3769 set_sigchld_handler ();
3770 stop_making_children ();
3771 pipeline_pgrp = old_pipeline_pgrp;
3772 #else
3773 stop_making_children ();
3774 #endif /* JOB_CONTROL */
3775
3776 if (pid < 0)
3777 {
3778 sys_error ("cannot make child for command substitution");
3779 error_exit:
3780
3781 FREE (istring);
3782 close (fildes[0]);
3783 close (fildes[1]);
3784 return ((char *)NULL);
3785 }
3786
3787 if (pid == 0)
3788 {
3789 set_sigint_handler (); /* XXX */
3790
3791 if (dup2 (fildes[1], 1) < 0)
3792 {
3793 sys_error ("command_substitute: cannot duplicate pipe as fd 1");
3794 exit (EXECUTION_FAILURE);
3795 }
3796
3797 /* If standard output is closed in the parent shell
3798 (such as after `exec >&-'), file descriptor 1 will be
3799 the lowest available file descriptor, and end up in
3800 fildes[0]. This can happen for stdin and stderr as well,
3801 but stdout is more important -- it will cause no output
3802 to be generated from this command. */
3803 if ((fildes[1] != fileno (stdin)) &&
3804 (fildes[1] != fileno (stdout)) &&
3805 (fildes[1] != fileno (stderr)))
3806 close (fildes[1]);
3807
3808 if ((fildes[0] != fileno (stdin)) &&
3809 (fildes[0] != fileno (stdout)) &&
3810 (fildes[0] != fileno (stderr)))
3811 close (fildes[0]);
3812
3813 /* The currently executing shell is not interactive. */
3814 interactive = 0;
3815
3816 /* This is a subshell environment. */
3817 subshell_environment |= SUBSHELL_COMSUB;
3818
3819 /* When not in POSIX mode, command substitution does not inherit
3820 the -e flag. */
3821 if (posixly_correct == 0)
3822 exit_immediately_on_error = 0;
3823
3824 remove_quoted_escapes (string);
3825
3826 startup_state = 2; /* see if we can avoid a fork */
3827 /* Give command substitution a place to jump back to on failure,
3828 so we don't go back up to main (). */
3829 result = setjmp (top_level);
3830
3831 /* If we're running a command substitution inside a shell function,
3832 trap `return' so we don't return from the function in the subshell
3833 and go off to never-never land. */
3834 if (result == 0 && return_catch_flag)
3835 function_value = setjmp (return_catch);
3836 else
3837 function_value = 0;
3838
3839 if (result == EXITPROG)
3840 exit (last_command_exit_value);
3841 else if (result)
3842 exit (EXECUTION_FAILURE);
3843 else if (function_value)
3844 exit (return_catch_value);
3845 else
3846 exit (parse_and_execute (string, "command substitution", SEVAL_NOHIST));
3847 }
3848 else
3849 {
3850 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
3851 close_pgrp_pipe ();
3852 #endif /* JOB_CONTROL && PGRP_PIPE */
3853
3854 close (fildes[1]);
3855
3856 istring = read_comsub (fildes[0], quoted);
3857
3858 close (fildes[0]);
3859
3860 current_command_subst_pid = pid;
3861 last_command_exit_value = wait_for (pid);
3862 last_command_subst_pid = pid;
3863 last_made_pid = old_pid;
3864
3865 #if defined (JOB_CONTROL)
3866 /* If last_command_exit_value > 128, then the substituted command
3867 was terminated by a signal. If that signal was SIGINT, then send
3868 SIGINT to ourselves. This will break out of loops, for instance. */
3869 if (last_command_exit_value == (128 + SIGINT))
3870 kill (getpid (), SIGINT);
3871
3872 /* wait_for gives the terminal back to shell_pgrp. If some other
3873 process group should have it, give it away to that group here.
3874 pipeline_pgrp is non-zero only while we are constructing a
3875 pipline, so what we are concerned about is whether or not that
3876 pipeline was started in the background. A pipeline started in
3877 the background should never get the tty back here. */
3878 #if 0
3879 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
3880 #else
3881 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
3882 #endif
3883 give_terminal_to (pipeline_pgrp, 0);
3884 #endif /* JOB_CONTROL */
3885
3886 return (istring);
3887 }
3888 }
3889
3890 /********************************************************
3891 * *
3892 * Utility functions for parameter expansion *
3893 * *
3894 ********************************************************/
3895
3896 #if defined (ARRAY_VARS)
3897
3898 static arrayind_t
3899 array_length_reference (s)
3900 char *s;
3901 {
3902 int len;
3903 arrayind_t ind;
3904 char *t, c;
3905 ARRAY *array;
3906 SHELL_VAR *var;
3907
3908 var = array_variable_part (s, &t, &len);
3909
3910 /* If unbound variables should generate an error, report one and return
3911 failure. */
3912 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
3913 {
3914 c = *--t;
3915 *t = '\0';
3916 err_unboundvar (s);
3917 *t = c;
3918 return (-1);
3919 }
3920 else if (var == 0)
3921 return 0;
3922
3923 /* We support a couple of expansions for variables that are not arrays.
3924 We'll return the length of the value for v[0], and 1 for v[@] or
3925 v[*]. Return 0 for everything else. */
3926
3927 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
3928
3929 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3930 return (array_p (var) ? array_num_elements (array) : 1);
3931
3932 ind = array_expand_index (t, len);
3933 if (ind < 0)
3934 {
3935 err_badarraysub (t);
3936 return (-1);
3937 }
3938
3939 if (array_p (var))
3940 t = array_reference (array, ind);
3941 else
3942 t = (ind == 0) ? value_cell (var) : (char *)NULL;
3943
3944 len = STRLEN (t);
3945 return (len);
3946 }
3947 #endif /* ARRAY_VARS */
3948
3949 static int
3950 valid_brace_expansion_word (name, var_is_special)
3951 char *name;
3952 int var_is_special;
3953 {
3954 if (DIGIT (*name) && all_digits (name))
3955 return 1;
3956 else if (var_is_special)
3957 return 1;
3958 #if defined (ARRAY_VARS)
3959 else if (valid_array_reference (name))
3960 return 1;
3961 #endif /* ARRAY_VARS */
3962 else if (legal_identifier (name))
3963 return 1;
3964 else
3965 return 0;
3966 }
3967
3968 /* Parameter expand NAME, and return a new string which is the expansion,
3969 or NULL if there was no expansion.
3970 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
3971 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
3972 NAME was found inside of a double-quoted expression. */
3973 static char *
3974 parameter_brace_expand_word (name, var_is_special, quoted)
3975 char *name;
3976 int var_is_special, quoted;
3977 {
3978 char *temp, *tt;
3979 intmax_t arg_index;
3980 SHELL_VAR *var;
3981 int atype;
3982
3983 /* Handle multiple digit arguments, as in ${11}. */
3984
3985 if (legal_number (name, &arg_index))
3986 {
3987 tt = get_dollar_var_value (arg_index);
3988 temp = tt ? quote_escapes (tt) : (char *)NULL;
3989 FREE (tt);
3990 }
3991 else if (var_is_special) /* ${@} */
3992 {
3993 int sindex;
3994 tt = (char *)xmalloc (2 + strlen (name));
3995 tt[sindex = 0] = '$';
3996 strcpy (tt + 1, name);
3997
3998 temp = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
3999 (int *)NULL, (int *)NULL, 0);
4000 free (tt);
4001 }
4002 #if defined (ARRAY_VARS)
4003 else if (valid_array_reference (name))
4004 {
4005 temp = array_value (name, quoted, &atype);
4006 if (atype == 0 && temp)
4007 temp = quote_escapes (temp);
4008 }
4009 #endif
4010 else if (var = find_variable (name))
4011 {
4012 if (var_isset (var) && invisible_p (var) == 0)
4013 {
4014 #if defined (ARRAY_VARS)
4015 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
4016 #else
4017 temp = value_cell (var);
4018 #endif
4019
4020 if (temp)
4021 temp = quote_escapes (temp);
4022 }
4023 else
4024 temp = (char *)NULL;
4025 }
4026 else
4027 temp = (char *)NULL;
4028
4029 return (temp);
4030 }
4031
4032 /* Expand an indirect reference to a variable: ${!NAME} expands to the
4033 value of the variable whose name is the value of NAME. */
4034 static char *
4035 parameter_brace_expand_indir (name, var_is_special, quoted)
4036 char *name;
4037 int var_is_special, quoted;
4038 {
4039 char *temp, *t;
4040
4041 t = parameter_brace_expand_word (name, var_is_special, quoted);
4042 if (t == 0)
4043 return (t);
4044 temp = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
4045 free (t);
4046 return temp;
4047 }
4048
4049 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
4050 depending on the value of C, the separating character. C can be one of
4051 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
4052 between double quotes. */
4053 static char *
4054 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
4055 char *name, *value;
4056 int c, quoted, *qdollaratp, *hasdollarat;
4057 {
4058 WORD_LIST *l;
4059 char *t, *t1, *temp;
4060 int hasdol;
4061
4062 /* XXX - Should we tilde expand in an assignment context if C is `='? */
4063 if (*value == '~')
4064 temp = bash_tilde_expand (value, 0);
4065 else if (xstrchr (value, '~') && unquoted_substring ("=~", value))
4066 temp = bash_tilde_expand (value, 1);
4067 else
4068 temp = savestring (value);
4069
4070 /* If the entire expression is between double quotes, we want to treat
4071 the value as a double-quoted string, with the exception that we strip
4072 embedded unescaped double quotes. */
4073 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *temp)
4074 {
4075 hasdol = 0;
4076 t = string_extract_double_quoted (temp, &hasdol, 1);
4077 free (temp);
4078 temp = t;
4079 }
4080
4081 hasdol = 0;
4082 /* XXX was 0 not quoted */
4083 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
4084 : (WORD_LIST *)0;
4085 if (hasdollarat)
4086 *hasdollarat = hasdol || (l && l->next);
4087 free (temp);
4088 if (l)
4089 {
4090 /* The expansion of TEMP returned something. We need to treat things
4091 slightly differently if HASDOL is non-zero. */
4092 temp = string_list (l);
4093 /* If l->next is not null, we know that TEMP contained "$@", since that
4094 is the only expansion that creates more than one word. */
4095 if ((hasdol && quoted) || l->next)
4096 *qdollaratp = 1;
4097 dispose_words (l);
4098 }
4099 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
4100 {
4101 /* The brace expansion occurred between double quotes and there was
4102 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
4103 it does not expand to anything. In this case, we want to return
4104 a quoted empty string. */
4105 temp = (char *)xmalloc (2);
4106 temp[0] = CTLNUL;
4107 temp[1] = '\0';
4108 }
4109 else
4110 temp = (char *)NULL;
4111
4112 if (c == '-' || c == '+')
4113 return (temp);
4114
4115 /* c == '=' */
4116 t = temp ? savestring (temp) : savestring ("");
4117 t1 = dequote_string (t);
4118 free (t);
4119 bind_variable (name, t1);
4120 free (t1);
4121 return (temp);
4122 }
4123
4124 /* Deal with the right hand side of a ${name:?value} expansion in the case
4125 that NAME is null or not set. If VALUE is non-null it is expanded and
4126 used as the error message to print, otherwise a standard message is
4127 printed. */
4128 static void
4129 parameter_brace_expand_error (name, value)
4130 char *name, *value;
4131 {
4132 WORD_LIST *l;
4133 char *temp;
4134
4135 if (value && *value)
4136 {
4137 if (*value == '~')
4138 temp = bash_tilde_expand (value, 0);
4139 else if (xstrchr (value, '~') && unquoted_substring ("=~", value))
4140 temp = bash_tilde_expand (value, 1);
4141 else
4142 temp = savestring (value);
4143
4144 l = expand_string (temp, 0);
4145 FREE (temp);
4146 temp = string_list (l);
4147 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
4148 FREE (temp);
4149 dispose_words (l);
4150 }
4151 else
4152 report_error ("%s: parameter null or not set", name);
4153
4154 /* Free the data we have allocated during this expansion, since we
4155 are about to longjmp out. */
4156 free (name);
4157 FREE (value);
4158 }
4159
4160 /* Return 1 if NAME is something for which parameter_brace_expand_length is
4161 OK to do. */
4162 static int
4163 valid_length_expression (name)
4164 char *name;
4165 {
4166 return (name[1] == '\0' || /* ${#} */
4167 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
4168 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
4169 #if defined (ARRAY_VARS)
4170 valid_array_reference (name + 1) || /* ${#a[7]} */
4171 #endif
4172 legal_identifier (name + 1)); /* ${#PS1} */
4173 }
4174
4175 /* Handle the parameter brace expansion that requires us to return the
4176 length of a parameter. */
4177 static intmax_t
4178 parameter_brace_expand_length (name)
4179 char *name;
4180 {
4181 char *t, *newname;
4182 intmax_t number, arg_index;
4183 WORD_LIST *list;
4184 #if defined (ARRAY_VARS)
4185 SHELL_VAR *var;
4186 #endif
4187
4188 if (name[1] == '\0') /* ${#} */
4189 number = number_of_args ();
4190 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
4191 number = number_of_args ();
4192 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
4193 {
4194 /* Take the lengths of some of the shell's special parameters. */
4195 switch (name[1])
4196 {
4197 case '-':
4198 t = which_set_flags ();
4199 break;
4200 case '?':
4201 t = itos (last_command_exit_value);
4202 break;
4203 case '$':
4204 t = itos (dollar_dollar_pid);
4205 break;
4206 case '!':
4207 if (last_asynchronous_pid == NO_PID)
4208 t = (char *)NULL;
4209 else
4210 t = itos (last_asynchronous_pid);
4211 break;
4212 case '#':
4213 t = itos (number_of_args ());
4214 break;
4215 }
4216 number = STRLEN (t);
4217 FREE (t);
4218 }
4219 #if defined (ARRAY_VARS)
4220 else if (valid_array_reference (name + 1))
4221 number = array_length_reference (name + 1);
4222 #endif /* ARRAY_VARS */
4223 else
4224 {
4225 number = 0;
4226
4227 if (legal_number (name + 1, &arg_index)) /* ${#1} */
4228 {
4229 t = get_dollar_var_value (arg_index);
4230 number = STRLEN (t);
4231 FREE (t);
4232 }
4233 #if defined (ARRAY_VARS)
4234 else if ((var = find_variable (name + 1)) && array_p (var))
4235 {
4236 t = array_reference (array_cell (var), 0);
4237 number = STRLEN (t);
4238 }
4239 #endif
4240 else /* ${#PS1} */
4241 {
4242 newname = savestring (name);
4243 newname[0] = '$';
4244 list = expand_string (newname, Q_DOUBLE_QUOTES);
4245 t = list ? string_list (list) : (char *)NULL;
4246 free (newname);
4247 if (list)
4248 dispose_words (list);
4249
4250 number = STRLEN (t);
4251 FREE (t);
4252 }
4253 }
4254
4255 return (number);
4256 }
4257
4258 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
4259 so we do some ad-hoc parsing of an arithmetic expression to find
4260 the first DELIM, instead of using strchr(3). Two rules:
4261 1. If the substring contains a `(', read until closing `)'.
4262 2. If the substring contains a `?', read past one `:' for each `?'.
4263 */
4264
4265 static char *
4266 skiparith (substr, delim)
4267 char *substr;
4268 int delim;
4269 {
4270 size_t sublen;
4271 int skipcol, pcount, i;
4272 DECLARE_MBSTATE;
4273
4274 sublen = strlen (substr);
4275 i = skipcol = pcount = 0;
4276 while (substr[i])
4277 {
4278 /* Balance parens */
4279 if (substr[i] == LPAREN)
4280 {
4281 pcount++;
4282 i++;
4283 continue;
4284 }
4285 if (substr[i] == RPAREN && pcount)
4286 {
4287 pcount--;
4288 i++;
4289 continue;
4290 }
4291 if (pcount)
4292 {
4293 ADVANCE_CHAR (substr, sublen, i);
4294 continue;
4295 }
4296
4297 /* Skip one `:' for each `?' */
4298 if (substr[i] == ':' && skipcol)
4299 {
4300 skipcol--;
4301 i++;
4302 continue;
4303 }
4304 if (substr[i] == delim)
4305 break;
4306 if (substr[i] == '?')
4307 {
4308 skipcol++;
4309 i++;
4310 continue;
4311 }
4312 ADVANCE_CHAR (substr, sublen, i);
4313 }
4314
4315 return (substr + i);
4316 }
4317
4318 /* Verify and limit the start and end of the desired substring. If
4319 VTYPE == 0, a regular shell variable is being used; if it is 1,
4320 then the positional parameters are being used; if it is 2, then
4321 VALUE is really a pointer to an array variable that should be used.
4322 Return value is 1 if both values were OK, 0 if there was a problem
4323 with an invalid expression, or -1 if the values were out of range. */
4324 static int
4325 verify_substring_values (value, substr, vtype, e1p, e2p)
4326 char *value, *substr;
4327 int vtype;
4328 intmax_t *e1p, *e2p;
4329 {
4330 char *t, *temp1, *temp2;
4331 arrayind_t len;
4332 int expok;
4333 #if defined (ARRAY_VARS)
4334 ARRAY *a;
4335 #endif
4336
4337 /* duplicate behavior of strchr(3) */
4338 t = skiparith (substr, ':');
4339 if (*t && *t == ':')
4340 *t = '\0';
4341 else
4342 t = (char *)0;
4343
4344 temp1 = expand_string_if_necessary (substr, Q_DOUBLE_QUOTES, expand_string);
4345 *e1p = evalexp (temp1, &expok);
4346 free (temp1);
4347 if (expok == 0)
4348 return (0);
4349
4350 len = -1; /* paranoia */
4351 switch (vtype)
4352 {
4353 case VT_VARIABLE:
4354 case VT_ARRAYMEMBER:
4355 len = strlen (value);
4356 break;
4357 case VT_POSPARMS:
4358 len = number_of_args () + 1;
4359 break;
4360 #if defined (ARRAY_VARS)
4361 case VT_ARRAYVAR:
4362 a = (ARRAY *)value;
4363 len = array_num_elements (a) + 1;
4364 break;
4365 #endif
4366 }
4367
4368 if (len == -1) /* paranoia */
4369 return -1;
4370
4371 if (*e1p < 0) /* negative offsets count from end */
4372 *e1p += len;
4373
4374 if (*e1p >= len || *e1p < 0)
4375 return (-1);
4376
4377 if (t)
4378 {
4379 t++;
4380 temp2 = savestring (t);
4381 temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
4382 free (temp2);
4383 t[-1] = ':';
4384 *e2p = evalexp (temp1, &expok);
4385 free (temp1);
4386 if (expok == 0)
4387 return (0);
4388 if (*e2p < 0)
4389 {
4390 internal_error ("%s: substring expression < 0", t);
4391 return (0);
4392 }
4393 *e2p += *e1p; /* want E2 chars starting at E1 */
4394 if (*e2p > len)
4395 *e2p = len;
4396 }
4397 else
4398 *e2p = len;
4399
4400 return (1);
4401 }
4402
4403 /* Return the type of variable specified by VARNAME (simple variable,
4404 positional param, or array variable). Also return the value specified
4405 by VARNAME (value of a variable or a reference to an array element).
4406 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
4407 characters in the value are quoted with CTLESC and takes appropriate
4408 steps. For convenience, *VALP is set to the dequoted VALUE. */
4409 static int
4410 get_var_and_type (varname, value, varp, valp)
4411 char *varname, *value;
4412 SHELL_VAR **varp;
4413 char **valp;
4414 {
4415 int vtype;
4416 char *temp;
4417 #if defined (ARRAY_VARS)
4418 SHELL_VAR *v;
4419 #endif
4420
4421 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
4422 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
4423 *varp = (SHELL_VAR *)NULL;
4424
4425 #if defined (ARRAY_VARS)
4426 if (valid_array_reference (varname))
4427 {
4428 v = array_variable_part (varname, &temp, (int *)0);
4429 if (v && array_p (v))
4430 { /* [ */
4431 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
4432 {
4433 vtype = VT_ARRAYVAR;
4434 *valp = (char *)array_cell (v);
4435 }
4436 else
4437 {
4438 vtype = VT_ARRAYMEMBER;
4439 *valp = array_value (varname, 1, (int *)NULL);
4440 }
4441 *varp = v;
4442 }
4443 else
4444 return -1;
4445 }
4446 else if ((v = find_variable (varname)) && array_p (v))
4447 {
4448 vtype = VT_ARRAYMEMBER;
4449 *varp = v;
4450 *valp = array_reference (array_cell (v), 0);
4451 }
4452 else
4453 #endif
4454 *valp = (value && vtype == VT_VARIABLE) ? dequote_escapes (value) : value;
4455
4456 return vtype;
4457 }
4458
4459 /******************************************************/
4460 /* */
4461 /* Functions to extract substrings of variable values */
4462 /* */
4463 /******************************************************/
4464
4465 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
4466 is `@', use the positional parameters; otherwise, use the value of
4467 VARNAME. If VARNAME is an array variable, use the array elements. */
4468
4469 static char *
4470 parameter_brace_substring (varname, value, substr, quoted)
4471 char *varname, *value, *substr;
4472 int quoted;
4473 {
4474 intmax_t e1, e2;
4475 int vtype, r;
4476 char *temp, *val, *tt;
4477 SHELL_VAR *v;
4478
4479 if (value == 0)
4480 return ((char *)NULL);
4481
4482 this_command_name = varname;
4483
4484 vtype = get_var_and_type (varname, value, &v, &val);
4485 if (vtype == -1)
4486 return ((char *)NULL);
4487
4488 r = verify_substring_values (val, substr, vtype, &e1, &e2);
4489 if (r <= 0)
4490 return ((r == 0) ? &expand_param_error : (char *)NULL);
4491
4492 switch (vtype)
4493 {
4494 case VT_VARIABLE:
4495 case VT_ARRAYMEMBER:
4496 tt = substring (val, e1, e2);
4497 if (vtype == VT_VARIABLE)
4498 FREE (val);
4499 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
4500 temp = quote_string (tt);
4501 else
4502 temp = tt ? quote_escapes (tt) : (char *)NULL;
4503 FREE (tt);
4504 break;
4505 case VT_POSPARMS:
4506 tt = pos_params (varname, e1, e2, quoted);
4507 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
4508 {
4509 temp = tt ? quote_escapes (tt) : (char *)NULL;
4510 FREE (tt);
4511 }
4512 else
4513 temp = tt;
4514 break;
4515 #if defined (ARRAY_VARS)
4516 case VT_ARRAYVAR:
4517 tt = array_subrange (array_cell (v), e1, e2, quoted);
4518 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
4519 {
4520 temp = tt ? quote_escapes (tt) : (char *)NULL;
4521 FREE (tt);
4522 }
4523 else
4524 temp = tt;
4525 break;
4526 #endif
4527 default:
4528 temp = (char *)NULL;
4529 }
4530
4531 return temp;
4532 }
4533
4534 /****************************************************************/
4535 /* */
4536 /* Functions to perform pattern substitution on variable values */
4537 /* */
4538 /****************************************************************/
4539
4540 char *
4541 pat_subst (string, pat, rep, mflags)
4542 char *string, *pat, *rep;
4543 int mflags;
4544 {
4545 char *ret, *s, *e, *str;
4546 int rsize, rptr, l, replen, mtype;
4547
4548 mtype = mflags & MATCH_TYPEMASK;
4549
4550 /* Special cases:
4551 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
4552 * with REP and return the result.
4553 * 2. A null pattern with mtype == MATCH_END means to append REP to
4554 * STRING and return the result.
4555 */
4556 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
4557 {
4558 replen = STRLEN (rep);
4559 l = strlen (string);
4560 ret = (char *)xmalloc (replen + l + 2);
4561 if (replen == 0)
4562 strcpy (ret, string);
4563 else if (mtype == MATCH_BEG)
4564 {
4565 strcpy (ret, rep);
4566 strcpy (ret + replen, string);
4567 }
4568 else
4569 {
4570 strcpy (ret, string);
4571 strcpy (ret + l, rep);
4572 }
4573 return (ret);
4574 }
4575
4576 ret = (char *)xmalloc (rsize = 64);
4577 ret[0] = '\0';
4578
4579 for (replen = STRLEN (rep), rptr = 0, str = string;;)
4580 {
4581 if (match_pattern (str, pat, mtype, &s, &e) == 0)
4582 break;
4583 l = s - str;
4584 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
4585
4586 /* OK, now copy the leading unmatched portion of the string (from
4587 str to s) to ret starting at rptr (the current offset). Then copy
4588 the replacement string at ret + rptr + (s - str). Increment
4589 rptr (if necessary) and str and go on. */
4590 if (l)
4591 {
4592 strncpy (ret + rptr, str, l);
4593 rptr += l;
4594 }
4595 if (replen)
4596 {
4597 strncpy (ret + rptr, rep, replen);
4598 rptr += replen;
4599 }
4600 if (s == e)
4601 e++; /* avoid infinite recursion on zero-length match */
4602 str = e; /* e == end of match */
4603 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
4604 break;
4605 }
4606
4607 /* Now copy the unmatched portion of the input string */
4608 if (*str)
4609 {
4610 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
4611 strcpy (ret + rptr, str);
4612 }
4613 else
4614 ret[rptr] = '\0';
4615
4616 return ret;
4617 }
4618
4619 /* Do pattern match and replacement on the positional parameters. */
4620 static char *
4621 pos_params_pat_subst (string, pat, rep, mflags)
4622 char *string, *pat, *rep;
4623 int mflags;
4624 {
4625 WORD_LIST *save, *params;
4626 WORD_DESC *w;
4627 char *ret, *tt;
4628
4629 save = params = list_rest_of_args ();
4630 if (save == 0)
4631 return ((char *)NULL);
4632
4633 for ( ; params; params = params->next)
4634 {
4635 ret = pat_subst (params->word->word, pat, rep, mflags);
4636 w = make_bare_word (ret);
4637 dispose_word (params->word);
4638 params->word = w;
4639 FREE (ret);
4640 }
4641
4642 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
4643 dispose_words (save);
4644
4645 return (ret);
4646 }
4647
4648 /* Perform pattern substitution on VALUE, which is the expansion of
4649 VARNAME. PATSUB is an expression supplying the pattern to match
4650 and the string to substitute. QUOTED is a flags word containing
4651 the type of quoting currently in effect. */
4652 static char *
4653 parameter_brace_patsub (varname, value, patsub, quoted)
4654 char *varname, *value, *patsub;
4655 int quoted;
4656 {
4657 int vtype, mflags;
4658 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
4659 SHELL_VAR *v;
4660
4661 if (value == 0)
4662 return ((char *)NULL);
4663
4664 this_command_name = varname;
4665
4666 vtype = get_var_and_type (varname, value, &v, &val);
4667 if (vtype == -1)
4668 return ((char *)NULL);
4669
4670 mflags = 0;
4671 if (*patsub == '/')
4672 {
4673 mflags |= MATCH_GLOBREP;
4674 patsub++;
4675 }
4676
4677 /* Malloc this because expand_string_if_necessary or one of the expansion
4678 functions in its call chain may free it on a substitution error. */
4679 lpatsub = savestring (patsub);
4680
4681 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4682 mflags |= MATCH_QUOTED;
4683
4684 if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
4685 *rep++ = '\0';
4686 else
4687 rep = (char *)NULL;
4688
4689 if (rep && *rep == '\0')
4690 rep = (char *)NULL;
4691
4692 /* Expand PAT and REP for command, variable and parameter, arithmetic,
4693 and process substitution. Also perform quote removal. Do not
4694 perform word splitting or filename generation. */
4695 pat = expand_string_if_necessary (lpatsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit);
4696
4697 if (rep)
4698 {
4699 if ((mflags & MATCH_QUOTED) == 0)
4700 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
4701 else
4702 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
4703 }
4704
4705 p = pat;
4706 if (pat && pat[0] == '#')
4707 {
4708 mflags |= MATCH_BEG;
4709 p++;
4710 }
4711 else if (pat && pat[0] == '%')
4712 {
4713 mflags |= MATCH_END;
4714 p++;
4715 }
4716 else
4717 mflags |= MATCH_ANY;
4718
4719 /* OK, we now want to substitute REP for PAT in VAL. If
4720 flags & MATCH_GLOBREP is non-zero, the substitution is done
4721 everywhere, otherwise only the first occurrence of PAT is
4722 replaced. The pattern matching code doesn't understand
4723 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
4724 values passed in (VT_VARIABLE) so the pattern substitution
4725 code works right. We need to requote special chars after
4726 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
4727 other cases if QUOTED == 0, since the posparams and arrays
4728 indexed by * or @ do special things when QUOTED != 0. */
4729
4730 switch (vtype)
4731 {
4732 case VT_VARIABLE:
4733 case VT_ARRAYMEMBER:
4734 temp = pat_subst (val, p, rep, mflags);
4735 if (vtype == VT_VARIABLE)
4736 FREE (val);
4737 if (temp)
4738 {
4739 tt = quote_escapes (temp);
4740 free (temp);
4741 temp = tt;
4742 }
4743 break;
4744 case VT_POSPARMS:
4745 temp = pos_params_pat_subst (val, p, rep, mflags);
4746 if (temp && (mflags & MATCH_QUOTED) == 0)
4747 {
4748 tt = quote_escapes (temp);
4749 free (temp);
4750 temp = tt;
4751 }
4752 break;
4753 #if defined (ARRAY_VARS)
4754 case VT_ARRAYVAR:
4755 temp = array_patsub (array_cell (v), p, rep, mflags);
4756 if (temp && (mflags & MATCH_QUOTED) == 0)
4757 {
4758 tt = quote_escapes (temp);
4759 free (temp);
4760 temp = tt;
4761 }
4762 break;
4763 #endif
4764 }
4765
4766 FREE (pat);
4767 FREE (rep);
4768 free (lpatsub);
4769
4770 return temp;
4771 }
4772
4773 /****************************************************************/
4774 /* */
4775 /* Functions to perform parameter expansion on a string */
4776 /* */
4777 /****************************************************************/
4778
4779 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
4780 static char *
4781 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
4782 char *string;
4783 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
4784 {
4785 int check_nullness, var_is_set, var_is_null, var_is_special;
4786 int want_substring, want_indir, want_patsub;
4787 char *name, *value, *temp, *temp1;
4788 int t_index, sindex, c;
4789 intmax_t number;
4790
4791 value = (char *)NULL;
4792 var_is_set = var_is_null = var_is_special = check_nullness = 0;
4793 want_substring = want_indir = want_patsub = 0;
4794
4795 sindex = *indexp;
4796 t_index = ++sindex;
4797 name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
4798
4799 /* If the name really consists of a special variable, then make sure
4800 that we have the entire name. We don't allow indirect references
4801 to special variables except `#', `?', `@' and `*'. */
4802 if ((sindex == t_index &&
4803 (string[t_index] == '-' ||
4804 string[t_index] == '?' ||
4805 string[t_index] == '#')) ||
4806 (sindex == t_index - 1 && string[sindex] == '!' &&
4807 (string[t_index] == '#' ||
4808 string[t_index] == '?' ||
4809 string[t_index] == '@' ||
4810 string[t_index] == '*')))
4811 {
4812 t_index++;
4813 free (name);
4814 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
4815 name = (char *)xmalloc (3 + (strlen (temp1)));
4816 *name = string[sindex];
4817 if (string[sindex] == '!')
4818 {
4819 /* indirect reference of $#, $?, $@, or $* */
4820 name[1] = string[sindex + 1];
4821 strcpy (name + 2, temp1);
4822 }
4823 else
4824 strcpy (name + 1, temp1);
4825 free (temp1);
4826 }
4827 sindex = t_index;
4828
4829 /* Find out what character ended the variable name. Then
4830 do the appropriate thing. */
4831 if (c = string[sindex])
4832 sindex++;
4833
4834 /* If c is followed by one of the valid parameter expansion
4835 characters, move past it as normal. If not, assume that
4836 a substring specification is being given, and do not move
4837 past it. */
4838 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
4839 {
4840 check_nullness++;
4841 if (c = string[sindex])
4842 sindex++;
4843 }
4844 else if (c == ':' && string[sindex] != RBRACE)
4845 want_substring = 1;
4846 else if (c == '/' && string[sindex] != RBRACE)
4847 want_patsub = 1;
4848
4849 /* Catch the valid and invalid brace expressions that made it through the
4850 tests above. */
4851 /* ${#-} is a valid expansion and means to take the length of $-.
4852 Similarly for ${#?} and ${##}... */
4853 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4854 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
4855 {
4856 name = (char *)xrealloc (name, 3);
4857 name[1] = c;
4858 name[2] = '\0';
4859 c = string[sindex++];
4860 }
4861
4862 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
4863 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4864 member (c, "%:=+/") && string[sindex] == RBRACE)
4865 {
4866 temp = (char *)NULL;
4867 goto bad_substitution;
4868 }
4869
4870 /* Indirect expansion begins with a `!'. A valid indirect expansion is
4871 either a variable name, one of the positional parameters or a special
4872 variable that expands to one of the positional parameters. */
4873 want_indir = *name == '!' &&
4874 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
4875 || VALID_INDIR_PARAM (name[1]));
4876
4877 /* Determine the value of this variable. */
4878
4879 /* Check for special variables, directly referenced. */
4880 if (SPECIAL_VAR (name, want_indir))
4881 var_is_special++;
4882
4883 /* Check for special expansion things, like the length of a parameter */
4884 if (*name == '#' && name[1])
4885 {
4886 /* If we are not pointing at the character just after the
4887 closing brace, then we haven't gotten all of the name.
4888 Since it begins with a special character, this is a bad
4889 substitution. Also check NAME for validity before trying
4890 to go on. */
4891 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
4892 {
4893 temp = (char *)NULL;
4894 goto bad_substitution;
4895 }
4896
4897 number = parameter_brace_expand_length (name);
4898 free (name);
4899
4900 *indexp = sindex;
4901 return ((number < 0) ? &expand_param_error : itos (number));
4902 }
4903
4904 /* ${@} is identical to $@. */
4905 if (name[0] == '@' && name[1] == '\0')
4906 {
4907 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4908 *quoted_dollar_atp = 1;
4909
4910 if (contains_dollar_at)
4911 *contains_dollar_at = 1;
4912 }
4913
4914 /* Process ${PREFIX*} expansion. */
4915 if (want_indir && string[sindex - 1] == RBRACE &&
4916 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
4917 legal_variable_starter ((unsigned char) name[1]))
4918 {
4919 char **x;
4920 WORD_LIST *xlist;
4921
4922 temp1 = savestring (name + 1);
4923 number = strlen (temp1);
4924 temp1[number - 1] = '\0';
4925 x = all_variables_matching_prefix (temp1);
4926 xlist = strvec_to_word_list (x, 0, 0);
4927 if (string[sindex - 2] == '*')
4928 temp = string_list_dollar_star (xlist);
4929 else
4930 {
4931 temp = string_list_dollar_at (xlist, quoted);
4932 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4933 *quoted_dollar_atp = 1;
4934 if (contains_dollar_at)
4935 *contains_dollar_at = 1;
4936 }
4937 free (x);
4938 free (xlist);
4939 free (temp1);
4940 *indexp = sindex;
4941 return (temp);
4942 }
4943
4944 /* Make sure that NAME is valid before trying to go on. */
4945 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
4946 var_is_special) == 0)
4947 {
4948 temp = (char *)NULL;
4949 goto bad_substitution;
4950 }
4951
4952 if (want_indir)
4953 temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted);
4954 else
4955 temp = parameter_brace_expand_word (name, var_is_special, quoted);
4956
4957 #if defined (ARRAY_VARS)
4958 if (valid_array_reference (name))
4959 {
4960 temp1 = xstrchr (name, '[');
4961 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4962 {
4963 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4964 *quoted_dollar_atp = 1;
4965 if (contains_dollar_at)
4966 *contains_dollar_at = 1;
4967 } /* [ */
4968 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4969 which should result in separate words even when IFS is unset. */
4970 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4971 {
4972 if (contains_dollar_at)
4973 *contains_dollar_at = 1;
4974 }
4975 }
4976 #endif
4977
4978 var_is_set = temp != (char *)0;
4979 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
4980
4981 /* Get the rest of the stuff inside the braces. */
4982 if (c && c != RBRACE)
4983 {
4984 /* Extract the contents of the ${ ... } expansion
4985 according to the Posix.2 rules. */
4986 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
4987 if (string[sindex] == RBRACE)
4988 sindex++;
4989 else
4990 goto bad_substitution;
4991 }
4992 else
4993 value = (char *)NULL;
4994
4995 *indexp = sindex;
4996
4997 /* If this is a substring spec, process it and add the result. */
4998 if (want_substring)
4999 {
5000 temp1 = parameter_brace_substring (name, temp, value, quoted);
5001 FREE (name);
5002 FREE (value);
5003 FREE (temp);
5004 return (temp1);
5005 }
5006 else if (want_patsub)
5007 {
5008 temp1 = parameter_brace_patsub (name, temp, value, quoted);
5009 FREE (name);
5010 FREE (value);
5011 FREE (temp);
5012 return (temp1);
5013 }
5014
5015 /* Do the right thing based on which character ended the variable name. */
5016 switch (c)
5017 {
5018 default:
5019 case '\0':
5020 bad_substitution:
5021 report_error ("%s: bad substitution", string ? string : "??");
5022 FREE (value);
5023 FREE (temp);
5024 free (name);
5025 return &expand_param_error;
5026
5027 case RBRACE:
5028 if (var_is_set == 0 && unbound_vars_is_error)
5029 {
5030 err_unboundvar (name);
5031 FREE (value);
5032 FREE (temp);
5033 free (name);
5034 last_command_exit_value = EXECUTION_FAILURE;
5035 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5036 }
5037 break;
5038
5039 case '#': /* ${param#[#]pattern} */
5040 case '%': /* ${param%[%]pattern} */
5041 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
5042 {
5043 FREE (value);
5044 break;
5045 }
5046 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
5047 free (temp);
5048 free (value);
5049 temp = temp1;
5050 break;
5051
5052 case '-':
5053 case '=':
5054 case '?':
5055 case '+':
5056 if (var_is_set && var_is_null == 0)
5057 {
5058 /* If the operator is `+', we don't want the value of the named
5059 variable for anything, just the value of the right hand side. */
5060
5061 if (c == '+')
5062 {
5063 /* XXX -- if we're double-quoted and the named variable is "$@",
5064 we want to turn off any special handling of "$@" --
5065 we're not using it, so whatever is on the rhs applies. */
5066 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5067 *quoted_dollar_atp = 0;
5068 if (contains_dollar_at)
5069 *contains_dollar_at = 0;
5070
5071 FREE (temp);
5072 if (value)
5073 {
5074 temp = parameter_brace_expand_rhs (name, value, c,
5075 quoted,
5076 quoted_dollar_atp,
5077 contains_dollar_at);
5078 free (value);
5079 }
5080 else
5081 temp = (char *)NULL;
5082 }
5083 else
5084 {
5085 FREE (value);
5086 }
5087 /* Otherwise do nothing; just use the value in TEMP. */
5088 }
5089 else /* VAR not set or VAR is NULL. */
5090 {
5091 FREE (temp);
5092 temp = (char *)NULL;
5093 if (c == '=' && var_is_special)
5094 {
5095 report_error ("$%s: cannot assign in this way", name);
5096 free (name);
5097 free (value);
5098 return &expand_param_error;
5099 }
5100 else if (c == '?')
5101 {
5102 parameter_brace_expand_error (name, value);
5103 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5104 }
5105 else if (c != '+')
5106 {
5107 /* XXX -- if we're double-quoted and the named variable is "$@",
5108 we want to turn off any special handling of "$@" --
5109 we're not using it, so whatever is on the rhs applies. */
5110 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5111 *quoted_dollar_atp = 0;
5112 if (contains_dollar_at)
5113 *contains_dollar_at = 0;
5114
5115 temp = parameter_brace_expand_rhs (name, value, c, quoted,
5116 quoted_dollar_atp,
5117 contains_dollar_at);
5118 }
5119 free (value);
5120 }
5121
5122 break;
5123 }
5124 free (name);
5125 return (temp);
5126 }
5127
5128 /* Expand a single ${xxx} expansion. The braces are optional. When
5129 the braces are used, parameter_brace_expand() does the work,
5130 possibly calling param_expand recursively. */
5131 static char *
5132 param_expand (string, sindex, quoted, expanded_something,
5133 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
5134 pflags)
5135 char *string;
5136 int *sindex, quoted, *expanded_something, *contains_dollar_at;
5137 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
5138 {
5139 char *temp, *temp1, uerror[3];
5140 int zindex, t_index, expok;
5141 unsigned char c;
5142 intmax_t number;
5143 SHELL_VAR *var;
5144 WORD_LIST *list;
5145
5146 zindex = *sindex;
5147 c = string[++zindex];
5148
5149 temp = (char *)NULL;
5150
5151 /* Do simple cases first. Switch on what follows '$'. */
5152 switch (c)
5153 {
5154 /* $0 .. $9? */
5155 case '0':
5156 case '1':
5157 case '2':
5158 case '3':
5159 case '4':
5160 case '5':
5161 case '6':
5162 case '7':
5163 case '8':
5164 case '9':
5165 temp1 = dollar_vars[TODIGIT (c)];
5166 if (unbound_vars_is_error && temp1 == (char *)NULL)
5167 {
5168 uerror[0] = '$';
5169 uerror[1] = c;
5170 uerror[2] = '\0';
5171 err_unboundvar (uerror);
5172 last_command_exit_value = EXECUTION_FAILURE;
5173 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5174 }
5175 temp = temp1 ? quote_escapes (temp1) : (char *)NULL;
5176 break;
5177
5178 /* $$ -- pid of the invoking shell. */
5179 case '$':
5180 temp = itos (dollar_dollar_pid);
5181 break;
5182
5183 /* $# -- number of positional parameters. */
5184 case '#':
5185 temp = itos (number_of_args ());
5186 break;
5187
5188 /* $? -- return value of the last synchronous command. */
5189 case '?':
5190 temp = itos (last_command_exit_value);
5191 break;
5192
5193 /* $- -- flags supplied to the shell on invocation or by `set'. */
5194 case '-':
5195 temp = which_set_flags ();
5196 break;
5197
5198 /* $! -- Pid of the last asynchronous command. */
5199 case '!':
5200 /* If no asynchronous pids have been created, expand to nothing.
5201 If `set -u' has been executed, and no async processes have
5202 been created, this is an expansion error. */
5203 if (last_asynchronous_pid == NO_PID)
5204 {
5205 if (expanded_something)
5206 *expanded_something = 0;
5207 temp = (char *)NULL;
5208 if (unbound_vars_is_error)
5209 {
5210 uerror[0] = '$';
5211 uerror[1] = c;
5212 uerror[2] = '\0';
5213 err_unboundvar (uerror);
5214 last_command_exit_value = EXECUTION_FAILURE;
5215 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5216 }
5217 }
5218 else
5219 temp = itos (last_asynchronous_pid);
5220 break;
5221
5222 /* The only difference between this and $@ is when the arg is quoted. */
5223 case '*': /* `$*' */
5224 list = list_rest_of_args ();
5225
5226 /* If there are no command-line arguments, this should just
5227 disappear if there are other characters in the expansion,
5228 even if it's quoted. */
5229 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
5230 temp = (char *)NULL;
5231 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5232 {
5233 /* If we have "$*" we want to make a string of the positional
5234 parameters, separated by the first character of $IFS, and
5235 quote the whole string, including the separators. If IFS
5236 is unset, the parameters are separated by ' '; if $IFS is
5237 null, the parameters are concatenated. */
5238 temp = string_list_dollar_star (list);
5239 temp1 = quote_string (temp);
5240 free (temp);
5241 temp = temp1;
5242 }
5243 else
5244 {
5245 /* If the $* is not quoted it is identical to $@ */
5246 temp = string_list_dollar_at (list, quoted);
5247 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
5248 *contains_dollar_at = 1;
5249 }
5250
5251 dispose_words (list);
5252 break;
5253
5254 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
5255 means that we have to turn quoting off after we split into
5256 the individually quoted arguments so that the final split
5257 on the first character of $IFS is still done. */
5258 case '@': /* `$@' */
5259 list = list_rest_of_args ();
5260
5261 /* We want to flag the fact that we saw this. We can't turn
5262 off quoting entirely, because other characters in the
5263 string might need it (consider "\"$@\""), but we need some
5264 way to signal that the final split on the first character
5265 of $IFS should be done, even though QUOTED is 1. */
5266 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
5267 *quoted_dollar_at_p = 1;
5268 if (contains_dollar_at)
5269 *contains_dollar_at = 1;
5270
5271 /* We want to separate the positional parameters with the first
5272 character of $IFS in case $IFS is something other than a space.
5273 We also want to make sure that splitting is done no matter what --
5274 according to POSIX.2, this expands to a list of the positional
5275 parameters no matter what IFS is set to. */
5276 temp = string_list_dollar_at (list, quoted);
5277
5278 dispose_words (list);
5279 break;
5280
5281 case LBRACE:
5282 temp = parameter_brace_expand (string, &zindex, quoted,
5283 quoted_dollar_at_p,
5284 contains_dollar_at);
5285 if (temp == &expand_param_error || temp == &expand_param_fatal)
5286 return (temp);
5287
5288 /* XXX */
5289 /* Quoted nulls should be removed if there is anything else
5290 in the string. */
5291 /* Note that we saw the quoted null so we can add one back at
5292 the end of this function if there are no other characters
5293 in the string, discard TEMP, and go on. The exception to
5294 this is when we have "${@}" and $1 is '', since $@ needs
5295 special handling. */
5296 if (temp && QUOTED_NULL (temp))
5297 {
5298 if (had_quoted_null_p)
5299 *had_quoted_null_p = 1;
5300 if (*quoted_dollar_at_p == 0)
5301 {
5302 free (temp);
5303 temp = (char *)NULL;
5304 }
5305
5306 }
5307
5308 goto return0;
5309
5310 /* Do command or arithmetic substitution. */
5311 case LPAREN:
5312 /* We have to extract the contents of this paren substitution. */
5313 t_index = zindex + 1;
5314 temp = extract_command_subst (string, &t_index);
5315 zindex = t_index;
5316
5317 /* For Posix.2-style `$(( ))' arithmetic substitution,
5318 extract the expression and pass it to the evaluator. */
5319 if (temp && *temp == LPAREN)
5320 {
5321 char *temp2;
5322 temp1 = temp + 1;
5323 temp2 = savestring (temp1);
5324 t_index = strlen (temp2) - 1;
5325
5326 if (temp2[t_index] != RPAREN)
5327 {
5328 free (temp2);
5329 goto comsub;
5330 }
5331
5332 /* Cut off ending `)' */
5333 temp2[t_index] = '\0';
5334
5335 /* Expand variables found inside the expression. */
5336 temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
5337 free (temp2);
5338
5339 arithsub:
5340 /* No error messages. */
5341 this_command_name = (char *)NULL;
5342 number = evalexp (temp1, &expok);
5343 free (temp);
5344 free (temp1);
5345 if (expok == 0)
5346 {
5347 if (interactive_shell == 0 && posixly_correct)
5348 {
5349 last_command_exit_value = EXECUTION_FAILURE;
5350 return (&expand_param_fatal);
5351 }
5352 else
5353 return (&expand_param_error);
5354 }
5355 temp = itos (number);
5356 break;
5357 }
5358
5359 comsub:
5360 temp1 = command_substitute (temp, quoted);
5361 FREE (temp);
5362 temp = temp1;
5363 break;
5364
5365 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
5366 away in a future bash release. */
5367 case '[':
5368 /* Extract the contents of this arithmetic substitution. */
5369 t_index = zindex + 1;
5370 temp = extract_arithmetic_subst (string, &t_index);
5371 zindex = t_index;
5372
5373 /* Do initial variable expansion. */
5374 temp1 = expand_string_if_necessary (temp, Q_DOUBLE_QUOTES, expand_string);
5375
5376 goto arithsub;
5377
5378 default:
5379 /* Find the variable in VARIABLE_LIST. */
5380 temp = (char *)NULL;
5381
5382 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
5383 ;
5384 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
5385
5386 /* If this isn't a variable name, then just output the `$'. */
5387 if (temp1 == 0 || *temp1 == '\0')
5388 {
5389 FREE (temp1);
5390 temp = (char *)xmalloc (2);
5391 temp[0] = '$';
5392 temp[1] = '\0';
5393 if (expanded_something)
5394 *expanded_something = 0;
5395 goto return0;
5396 }
5397
5398 /* If the variable exists, return its value cell. */
5399 var = find_variable (temp1);
5400
5401 if (var && invisible_p (var) == 0 && var_isset (var))
5402 {
5403 #if defined (ARRAY_VARS)
5404 if (array_p (var))
5405 {
5406 temp = array_reference (array_cell (var), 0);
5407 if (temp)
5408 temp = quote_escapes (temp);
5409 }
5410 else
5411 #endif
5412 temp = quote_escapes (value_cell (var));
5413 free (temp1);
5414
5415 goto return0;
5416 }
5417
5418 temp = (char *)NULL;
5419
5420 if (unbound_vars_is_error)
5421 err_unboundvar (temp1);
5422 else
5423 {
5424 free (temp1);
5425 goto return0;
5426 }
5427
5428 free (temp1);
5429 last_command_exit_value = EXECUTION_FAILURE;
5430 return ((unbound_vars_is_error && interactive_shell == 0)
5431 ? &expand_param_fatal
5432 : &expand_param_error);
5433 }
5434
5435 if (string[zindex])
5436 zindex++;
5437
5438 return0:
5439 *sindex = zindex;
5440 return (temp);
5441 }
5442
5443 /* Make a word list which is the result of parameter and variable
5444 expansion, command substitution, arithmetic substitution, and
5445 quote removal of WORD. Return a pointer to a WORD_LIST which is
5446 the result of the expansion. If WORD contains a null word, the
5447 word list returned is also null.
5448
5449 QUOTED contains flag values defined in shell.h.
5450
5451 ISEXP is used to tell expand_word_internal that the word should be
5452 treated as the result of an expansion. This has implications for
5453 how IFS characters in the word are treated.
5454
5455 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
5456 they point to an integer value which receives information about expansion.
5457 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
5458 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
5459 else zero.
5460
5461 This only does word splitting in the case of $@ expansion. In that
5462 case, we split on ' '. */
5463
5464 /* Values for the local variable quoted_state. */
5465 #define UNQUOTED 0
5466 #define PARTIALLY_QUOTED 1
5467 #define WHOLLY_QUOTED 2
5468
5469 static WORD_LIST *
5470 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
5471 WORD_DESC *word;
5472 int quoted, isexp;
5473 int *contains_dollar_at;
5474 int *expanded_something;
5475 {
5476 WORD_LIST *list;
5477 WORD_DESC *tword;
5478
5479 /* The intermediate string that we build while expanding. */
5480 char *istring;
5481
5482 /* The current size of the above object. */
5483 int istring_size;
5484
5485 /* Index into ISTRING. */
5486 int istring_index;
5487
5488 /* Temporary string storage. */
5489 char *temp, *temp1;
5490
5491 /* The text of WORD. */
5492 register char *string;
5493
5494 /* The size of STRING. */
5495 size_t string_size;
5496
5497 /* The index into STRING. */
5498 int sindex;
5499
5500 /* This gets 1 if we see a $@ while quoted. */
5501 int quoted_dollar_at;
5502
5503 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
5504 whether WORD contains no quoting characters, a partially quoted
5505 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
5506 int quoted_state;
5507
5508 int had_quoted_null;
5509 int has_dollar_at;
5510 int tflag;
5511
5512 register unsigned char c; /* Current character. */
5513 int t_index; /* For calls to string_extract_xxx. */
5514
5515 char twochars[2];
5516
5517 DECLARE_MBSTATE;
5518
5519 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
5520 istring[istring_index = 0] = '\0';
5521 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
5522 quoted_state = UNQUOTED;
5523
5524 string = word->word;
5525 if (string == 0)
5526 goto finished_with_string;
5527 string_size = strlen (string);
5528
5529 if (contains_dollar_at)
5530 *contains_dollar_at = 0;
5531
5532 /* Begin the expansion. */
5533
5534 for (sindex = 0; ;)
5535 {
5536 c = string[sindex];
5537
5538 /* Case on toplevel character. */
5539 switch (c)
5540 {
5541 case '\0':
5542 goto finished_with_string;
5543
5544 case CTLESC:
5545 sindex++;
5546 #if HANDLE_MULTIBYTE
5547 if (MB_CUR_MAX > 1 && string[sindex])
5548 {
5549 int i;
5550 mbstate_t state_bak;
5551 size_t mblength;
5552
5553 state_bak = state;
5554 mblength = mbrlen (string + sindex, string_size - sindex, &state);
5555 if (mblength == (size_t)-1 || mblength == (size_t)-2)
5556 {
5557 state = state_bak;
5558 mblength = 1;
5559 }
5560 if (mblength < 1)
5561 mblength = 1;
5562 temp = (char *)xmalloc (mblength + 2);
5563 temp[0] = CTLESC;
5564 for (i = 0; i < mblength; i++)
5565 temp[i+1] = string[sindex++];
5566 temp[mblength + 1] = '\0';
5567
5568 goto add_string;
5569 }
5570 else
5571 #endif
5572 {
5573 temp = (char *)xmalloc (3);
5574 temp[0] = CTLESC;
5575 temp[1] = c = string[sindex];
5576 temp[2] = '\0';
5577 }
5578
5579 dollar_add_string:
5580 if (string[sindex])
5581 sindex++;
5582
5583 add_string:
5584 if (temp)
5585 {
5586 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
5587 temp = (char *)0;
5588 }
5589
5590 break;
5591
5592 #if defined (PROCESS_SUBSTITUTION)
5593 /* Process substitution. */
5594 case '<':
5595 case '>':
5596 {
5597 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
5598 {
5599 sindex--; /* add_character: label increments sindex */
5600 goto add_character;
5601 }
5602 else
5603 t_index = sindex + 1; /* skip past both '<' and LPAREN */
5604
5605 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
5606 sindex = t_index;
5607
5608 /* If the process substitution specification is `<()', we want to
5609 open the pipe for writing in the child and produce output; if
5610 it is `>()', we want to open the pipe for reading in the child
5611 and consume input. */
5612 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
5613
5614 FREE (temp1);
5615
5616 goto dollar_add_string;
5617 }
5618 #endif /* PROCESS_SUBSTITUTION */
5619
5620 case '$':
5621 if (expanded_something)
5622 *expanded_something = 1;
5623
5624 has_dollar_at = 0;
5625 temp = param_expand (string, &sindex, quoted, expanded_something,
5626 &has_dollar_at, &quoted_dollar_at,
5627 &had_quoted_null, 0);
5628
5629 if (temp == &expand_param_error || temp == &expand_param_fatal)
5630 {
5631 free (string);
5632 free (istring);
5633 return ((temp == &expand_param_error) ? &expand_word_error
5634 : &expand_word_fatal);
5635 }
5636 if (contains_dollar_at && has_dollar_at)
5637 *contains_dollar_at = 1;
5638 goto add_string;
5639 break;
5640
5641 case '`': /* Backquoted command substitution. */
5642 {
5643 sindex++;
5644
5645 if (expanded_something)
5646 *expanded_something = 1;
5647
5648 temp = string_extract (string, &sindex, "`", 0);
5649 de_backslash (temp);
5650 temp1 = command_substitute (temp, quoted);
5651 FREE (temp);
5652 temp = temp1;
5653 goto dollar_add_string;
5654 }
5655
5656 case '\\':
5657 if (string[sindex + 1] == '\n')
5658 {
5659 sindex += 2;
5660 continue;
5661 }
5662
5663 c = string[++sindex];
5664
5665 if (quoted & Q_HERE_DOCUMENT)
5666 tflag = CBSHDOC;
5667 else if (quoted & Q_DOUBLE_QUOTES)
5668 tflag = CBSDQUOTE;
5669 else
5670 tflag = 0;
5671
5672 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
5673 {
5674 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
5675 }
5676 else if (c == 0)
5677 {
5678 c = CTLNUL;
5679 sindex--; /* add_character: label increments sindex */
5680 goto add_character;
5681 }
5682 else
5683 {
5684 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
5685 }
5686
5687 sindex++;
5688 add_twochars:
5689 /* BEFORE jumping here, we need to increment sindex if appropriate */
5690 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
5691 DEFAULT_ARRAY_SIZE);
5692 istring[istring_index++] = twochars[0];
5693 istring[istring_index++] = twochars[1];
5694 istring[istring_index] = '\0';
5695
5696 break;
5697
5698 case '"':
5699 #if 0
5700 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_PATQUOTE))
5701 #else
5702 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5703 #endif
5704 goto add_character;
5705
5706 t_index = ++sindex;
5707 temp = string_extract_double_quoted (string, &sindex, 0);
5708
5709 /* If the quotes surrounded the entire string, then the
5710 whole word was quoted. */
5711 quoted_state = (t_index == 1 && string[sindex] == '\0')
5712 ? WHOLLY_QUOTED
5713 : PARTIALLY_QUOTED;
5714
5715 if (temp && *temp)
5716 {
5717 tword = make_word (temp); /* XXX */
5718 free (temp);
5719 temp = (char *)NULL;
5720
5721 has_dollar_at = 0;
5722 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
5723
5724 if (list == &expand_word_error || list == &expand_word_fatal)
5725 {
5726 free (istring);
5727 free (string);
5728 /* expand_word_internal has already freed temp_word->word
5729 for us because of the way it prints error messages. */
5730 tword->word = (char *)NULL;
5731 dispose_word (tword);
5732 return list;
5733 }
5734
5735 dispose_word (tword);
5736
5737 /* "$@" (a double-quoted dollar-at) expands into nothing,
5738 not even a NULL word, when there are no positional
5739 parameters. */
5740 if (list == 0 && has_dollar_at)
5741 {
5742 quoted_dollar_at++;
5743 break;
5744 }
5745
5746 /* If we get "$@", we know we have expanded something, so we
5747 need to remember it for the final split on $IFS. This is
5748 a special case; it's the only case where a quoted string
5749 can expand into more than one word. It's going to come back
5750 from the above call to expand_word_internal as a list with
5751 a single word, in which all characters are quoted and
5752 separated by blanks. What we want to do is to turn it back
5753 into a list for the next piece of code. */
5754 if (list)
5755 dequote_list (list);
5756
5757 if (has_dollar_at)
5758 {
5759 quoted_dollar_at++;
5760 if (contains_dollar_at)
5761 *contains_dollar_at = 1;
5762 if (expanded_something)
5763 *expanded_something = 1;
5764 }
5765 }
5766 else
5767 {
5768 /* What we have is "". This is a minor optimization. */
5769 FREE (temp);
5770 list = (WORD_LIST *)NULL;
5771 }
5772
5773 /* The code above *might* return a list (consider the case of "$@",
5774 where it returns "$1", "$2", etc.). We can't throw away the
5775 rest of the list, and we have to make sure each word gets added
5776 as quoted. We test on tresult->next: if it is non-NULL, we
5777 quote the whole list, save it to a string with string_list, and
5778 add that string. We don't need to quote the results of this
5779 (and it would be wrong, since that would quote the separators
5780 as well), so we go directly to add_string. */
5781 if (list)
5782 {
5783 if (list->next)
5784 {
5785 /* Testing quoted_dollar_at makes sure that "$@" is
5786 split correctly when $IFS does not contain a space. */
5787 temp = quoted_dollar_at
5788 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
5789 : string_list (quote_list (list));
5790 dispose_words (list);
5791 goto add_string;
5792 }
5793 else
5794 {
5795 temp = savestring (list->word->word);
5796 dispose_words (list);
5797 #if 1
5798 /* If the string is not a quoted null string, we want
5799 to remove any embedded unquoted CTLNUL characters.
5800 We do not want to turn quoted null strings back into
5801 the empty string, though. We do this because we
5802 want to remove any quoted nulls from expansions that
5803 contain other characters. For example, if we have
5804 x"$*"y or "x$*y" and there are no positional parameters,
5805 the $* should expand into nothing. */
5806 /* HOWEVER, this fails if the string contains a literal
5807 CTLNUL or CTLNUL is contained in the (non-null) expansion
5808 of some variable. I'm not sure what to do about this
5809 yet. */
5810 if (QUOTED_NULL (temp) == 0)
5811 remove_quoted_nulls (temp); /* XXX */
5812 #endif
5813 }
5814 }
5815 else
5816 temp = (char *)NULL;
5817
5818 /* We do not want to add quoted nulls to strings that are only
5819 partially quoted; we can throw them away. */
5820 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
5821 continue;
5822
5823 add_quoted_string:
5824
5825 if (temp)
5826 {
5827 temp1 = temp;
5828 temp = quote_string (temp);
5829 free (temp1);
5830 goto add_string;
5831 }
5832 else
5833 {
5834 /* Add NULL arg. */
5835 c = CTLNUL;
5836 sindex--; /* add_character: label increments sindex */
5837 goto add_character;
5838 }
5839
5840 /* break; */
5841
5842 case '\'':
5843 #if 0
5844 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_PATQUOTE))
5845 #else
5846 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5847 #endif
5848 goto add_character;
5849
5850 t_index = ++sindex;
5851 temp = string_extract_single_quoted (string, &sindex);
5852
5853 /* If the entire STRING was surrounded by single quotes,
5854 then the string is wholly quoted. */
5855 quoted_state = (t_index == 1 && string[sindex] == '\0')
5856 ? WHOLLY_QUOTED
5857 : PARTIALLY_QUOTED;
5858
5859 /* If all we had was '', it is a null expansion. */
5860 if (*temp == '\0')
5861 {
5862 free (temp);
5863 temp = (char *)NULL;
5864 }
5865 else
5866 remove_quoted_escapes (temp); /* ??? */
5867
5868 /* We do not want to add quoted nulls to strings that are only
5869 partially quoted; such nulls are discarded. */
5870 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
5871 continue;
5872
5873 /* If we have a quoted null expansion, add a quoted NULL to istring. */
5874 if (temp == 0)
5875 {
5876 c = CTLNUL;
5877 sindex--; /* add_character: label increments sindex */
5878 goto add_character;
5879 }
5880 else
5881 goto add_quoted_string;
5882
5883 /* break; */
5884
5885 default:
5886 /* This is the fix for " $@ " */
5887 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
5888 {
5889 if (string[sindex]) /* from old goto dollar_add_string */
5890 sindex++;
5891 if (c == 0)
5892 {
5893 c = CTLNUL;
5894 goto add_character;
5895 }
5896 else
5897 {
5898 #if HANDLE_MULTIBYTE
5899 /* XXX - I'd like to use SCOPY_CHAR_I here. */
5900 if (MB_CUR_MAX > 1)
5901 {
5902 int i;
5903 mbstate_t state_bak;
5904 size_t mblength;
5905
5906 sindex--;
5907 state_bak = state;
5908 mblength = mbrlen (string + sindex, string_size - sindex, &state);
5909 if (mblength == (size_t)-1 || mblength == (size_t)-2)
5910 {
5911 state = state_bak;
5912 mblength = 1;
5913 }
5914 if (mblength < 1)
5915 mblength = 1;
5916
5917 temp = (char *)xmalloc (mblength + 2);
5918 temp[0] = CTLESC;
5919 for (i = 0; i < mblength; i++)
5920 temp[i + 1] = string[sindex++];
5921 temp[mblength + 1] = '\0';
5922
5923 goto add_string;
5924 }
5925 else
5926 #endif
5927 {
5928 twochars[0] = CTLESC;
5929 twochars[1] = c;
5930 goto add_twochars;
5931 }
5932 }
5933 }
5934
5935 SADD_MBCHAR (temp, string, sindex, string_size);
5936
5937 add_character:
5938 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
5939 DEFAULT_ARRAY_SIZE);
5940 istring[istring_index++] = c;
5941 istring[istring_index] = '\0';
5942
5943 /* Next character. */
5944 sindex++;
5945 }
5946 }
5947
5948 finished_with_string:
5949 /* OK, we're ready to return. If we have a quoted string, and
5950 quoted_dollar_at is not set, we do no splitting at all; otherwise
5951 we split on ' '. The routines that call this will handle what to
5952 do if nothing has been expanded. */
5953
5954 /* Partially and wholly quoted strings which expand to the empty
5955 string are retained as an empty arguments. Unquoted strings
5956 which expand to the empty string are discarded. The single
5957 exception is the case of expanding "$@" when there are no
5958 positional parameters. In that case, we discard the expansion. */
5959
5960 /* Because of how the code that handles "" and '' in partially
5961 quoted strings works, we need to make ISTRING into a QUOTED_NULL
5962 if we saw quoting characters, but the expansion was empty.
5963 "" and '' are tossed away before we get to this point when
5964 processing partially quoted strings. This makes "" and $xxx""
5965 equivalent when xxx is unset. We also look to see whether we
5966 saw a quoted null from a ${} expansion and add one back if we
5967 need to. */
5968
5969 /* If we expand to nothing and there were no single or double quotes
5970 in the word, we throw it away. Otherwise, we return a NULL word.
5971 The single exception is for $@ surrounded by double quotes when
5972 there are no positional parameters. In that case, we also throw
5973 the word away. */
5974
5975 if (*istring == '\0')
5976 {
5977 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
5978 {
5979 istring[0] = CTLNUL;
5980 istring[1] = '\0';
5981 tword = make_bare_word (istring);
5982 list = make_word_list (tword, (WORD_LIST *)NULL);
5983 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5984 tword->flags |= W_QUOTED;
5985 }
5986 /* According to sh, ksh, and Posix.2, if a word expands into nothing
5987 and a double-quoted "$@" appears anywhere in it, then the entire
5988 word is removed. */
5989 else if (quoted_state == UNQUOTED || quoted_dollar_at)
5990 list = (WORD_LIST *)NULL;
5991 #if 0
5992 else
5993 {
5994 tword = make_bare_word (istring);
5995 list = make_word_list (tword, (WORD_LIST *)NULL);
5996 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5997 tword->flags |= W_QUOTED;
5998 }
5999 #else
6000 else
6001 list = (WORD_LIST *)NULL;
6002 #endif
6003 }
6004 else if (word->flags & W_NOSPLIT)
6005 {
6006 tword = make_bare_word (istring);
6007 list = make_word_list (tword, (WORD_LIST *)NULL);
6008 if (word->flags & W_ASSIGNMENT)
6009 tword->flags |= W_ASSIGNMENT; /* XXX */
6010 if (word->flags & W_NOGLOB)
6011 tword->flags |= W_NOGLOB; /* XXX */
6012 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6013 tword->flags |= W_QUOTED;
6014 }
6015 else
6016 {
6017 char *ifs_chars;
6018
6019 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
6020
6021 /* If we have $@, we need to split the results no matter what. If
6022 IFS is unset or NULL, string_list_dollar_at has separated the
6023 positional parameters with a space, so we split on space (we have
6024 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
6025 string_list_dollar_at has separated the positional parameters
6026 with the first character of $IFS, so we split on $IFS. */
6027 if (has_dollar_at && ifs_chars)
6028 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
6029 else
6030 {
6031 tword = make_bare_word (istring);
6032 list = make_word_list (tword, (WORD_LIST *)NULL);
6033 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
6034 tword->flags |= W_QUOTED;
6035 if (word->flags & W_ASSIGNMENT)
6036 tword->flags |= W_ASSIGNMENT;
6037 if (word->flags & W_NOGLOB)
6038 tword->flags |= W_NOGLOB;
6039 }
6040 }
6041
6042 free (istring);
6043 return (list);
6044 }
6045
6046 /* **************************************************************** */
6047 /* */
6048 /* Functions for Quote Removal */
6049 /* */
6050 /* **************************************************************** */
6051
6052 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
6053 backslash quoting rules for within double quotes or a here document. */
6054 char *
6055 string_quote_removal (string, quoted)
6056 char *string;
6057 int quoted;
6058 {
6059 size_t slen;
6060 char *r, *result_string, *temp, *send;
6061 int sindex, tindex, dquote;
6062 unsigned char c;
6063 DECLARE_MBSTATE;
6064
6065 /* The result can be no longer than the original string. */
6066 slen = strlen (string);
6067 send = string + slen;
6068
6069 r = result_string = (char *)xmalloc (slen + 1);
6070
6071 for (dquote = sindex = 0; c = string[sindex];)
6072 {
6073 switch (c)
6074 {
6075 case '\\':
6076 c = string[++sindex];
6077 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
6078 *r++ = '\\';
6079 /* FALLTHROUGH */
6080
6081 default:
6082 SCOPY_CHAR_M (r, string, send, sindex);
6083 break;
6084
6085 case '\'':
6086 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
6087 {
6088 *r++ = c;
6089 sindex++;
6090 break;
6091 }
6092 tindex = sindex + 1;
6093 temp = string_extract_single_quoted (string, &tindex);
6094 if (temp)
6095 {
6096 strcpy (r, temp);
6097 r += strlen (r);
6098 free (temp);
6099 }
6100 sindex = tindex;
6101 break;
6102
6103 case '"':
6104 dquote = 1 - dquote;
6105 sindex++;
6106 break;
6107 }
6108 }
6109 *r = '\0';
6110 return (result_string);
6111 }
6112
6113 #if 0
6114 /* UNUSED */
6115 /* Perform quote removal on word WORD. This allocates and returns a new
6116 WORD_DESC *. */
6117 WORD_DESC *
6118 word_quote_removal (word, quoted)
6119 WORD_DESC *word;
6120 int quoted;
6121 {
6122 WORD_DESC *w;
6123 char *t;
6124
6125 t = string_quote_removal (word->word, quoted);
6126 w = make_bare_word (t);
6127 free (t);
6128 return (w);
6129 }
6130
6131 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
6132 the members of the list are treated as if they are surrounded by
6133 double quotes. Return a new list, or NULL if LIST is NULL. */
6134 WORD_LIST *
6135 word_list_quote_removal (list, quoted)
6136 WORD_LIST *list;
6137 int quoted;
6138 {
6139 WORD_LIST *result, *t, *tresult;
6140
6141 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
6142 {
6143 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
6144 result = (WORD_LIST *) list_append (result, tresult);
6145 }
6146 return (result);
6147 }
6148 #endif
6149
6150 /*******************************************
6151 * *
6152 * Functions to perform word splitting *
6153 * *
6154 *******************************************/
6155
6156 void
6157 setifs (v)
6158 SHELL_VAR *v;
6159 {
6160 char *t;
6161 unsigned char uc;
6162
6163 ifs_var = v;
6164 ifs_value = v ? value_cell (v) : " \t\n";
6165
6166 /* Should really merge ifs_cmap with sh_syntaxtab. */
6167 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
6168 for (t = ifs_value ; t && *t; t++)
6169 {
6170 uc = *t;
6171 ifs_cmap[uc] = 1;
6172 }
6173
6174 ifs_firstc = ifs_value ? *ifs_value : 0;
6175 }
6176
6177 char *
6178 getifs ()
6179 {
6180 return ifs_value;
6181 }
6182
6183 /* This splits a single word into a WORD LIST on $IFS, but only if the word
6184 is not quoted. list_string () performs quote removal for us, even if we
6185 don't do any splitting. */
6186 WORD_LIST *
6187 word_split (w, ifs_chars)
6188 WORD_DESC *w;
6189 char *ifs_chars;
6190 {
6191 WORD_LIST *result;
6192
6193 if (w)
6194 {
6195 char *xifs;
6196
6197 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
6198 result = list_string (w->word, xifs, w->flags & W_QUOTED);
6199 }
6200 else
6201 result = (WORD_LIST *)NULL;
6202
6203 return (result);
6204 }
6205
6206 /* Perform word splitting on LIST and return the RESULT. It is possible
6207 to return (WORD_LIST *)NULL. */
6208 static WORD_LIST *
6209 word_list_split (list)
6210 WORD_LIST *list;
6211 {
6212 WORD_LIST *result, *t, *tresult;
6213
6214 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
6215 {
6216 tresult = word_split (t->word, ifs_value);
6217 result = (WORD_LIST *) list_append (result, tresult);
6218 }
6219 return (result);
6220 }
6221
6222 /**************************************************
6223 * *
6224 * Functions to expand an entire WORD_LIST *
6225 * *
6226 **************************************************/
6227
6228 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
6229 ELIST, and set ELIST to the new list. */
6230 #define PREPEND_LIST(nlist, elist) \
6231 do { nlist->next = elist; elist = nlist; } while (0)
6232
6233 /* Separate out any initial variable assignments from TLIST. If set -k has
6234 been executed, remove all assignment statements from TLIST. Initial
6235 variable assignments and other environment assignments are placed
6236 on SUBST_ASSIGN_VARLIST. */
6237 static WORD_LIST *
6238 separate_out_assignments (tlist)
6239 WORD_LIST *tlist;
6240 {
6241 register WORD_LIST *vp, *lp;
6242
6243 if (!tlist)
6244 return ((WORD_LIST *)NULL);
6245
6246 if (subst_assign_varlist)
6247 dispose_words (subst_assign_varlist); /* Clean up after previous error */
6248
6249 subst_assign_varlist = (WORD_LIST *)NULL;
6250 vp = lp = tlist;
6251
6252 /* Separate out variable assignments at the start of the command.
6253 Loop invariant: vp->next == lp
6254 Loop postcondition:
6255 lp = list of words left after assignment statements skipped
6256 tlist = original list of words
6257 */
6258 while (lp && (lp->word->flags & W_ASSIGNMENT))
6259 {
6260 vp = lp;
6261 lp = lp->next;
6262 }
6263
6264 /* If lp != tlist, we have some initial assignment statements.
6265 We make SUBST_ASSIGN_VARLIST point to the list of assignment
6266 words and TLIST point to the remaining words. */
6267 if (lp != tlist)
6268 {
6269 subst_assign_varlist = tlist;
6270 /* ASSERT(vp->next == lp); */
6271 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
6272 tlist = lp; /* remainder of word list */
6273 }
6274
6275 /* vp == end of variable list */
6276 /* tlist == remainder of original word list without variable assignments */
6277 if (!tlist)
6278 /* All the words in tlist were assignment statements */
6279 return ((WORD_LIST *)NULL);
6280
6281 /* ASSERT(tlist != NULL); */
6282 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
6283
6284 /* If the -k option is in effect, we need to go through the remaining
6285 words, separate out the assignment words, and place them on
6286 SUBST_ASSIGN_VARLIST. */
6287 if (place_keywords_in_env)
6288 {
6289 WORD_LIST *tp; /* tp == running pointer into tlist */
6290
6291 tp = tlist;
6292 lp = tlist->next;
6293
6294 /* Loop Invariant: tp->next == lp */
6295 /* Loop postcondition: tlist == word list without assignment statements */
6296 while (lp)
6297 {
6298 if (lp->word->flags & W_ASSIGNMENT)
6299 {
6300 /* Found an assignment statement, add this word to end of
6301 subst_assign_varlist (vp). */
6302 if (!subst_assign_varlist)
6303 subst_assign_varlist = vp = lp;
6304 else
6305 {
6306 vp->next = lp;
6307 vp = lp;
6308 }
6309
6310 /* Remove the word pointed to by LP from TLIST. */
6311 tp->next = lp->next;
6312 /* ASSERT(vp == lp); */
6313 lp->next = (WORD_LIST *)NULL;
6314 lp = tp->next;
6315 }
6316 else
6317 {
6318 tp = lp;
6319 lp = lp->next;
6320 }
6321 }
6322 }
6323 return (tlist);
6324 }
6325
6326 #define WEXP_VARASSIGN 0x001
6327 #define WEXP_BRACEEXP 0x002
6328 #define WEXP_TILDEEXP 0x004
6329 #define WEXP_PARAMEXP 0x008
6330 #define WEXP_PATHEXP 0x010
6331
6332 /* All of the expansions, including variable assignments at the start of
6333 the list. */
6334 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
6335
6336 /* All of the expansions except variable assignments at the start of
6337 the list. */
6338 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
6339
6340 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
6341 expansion, command substitution, arithmetic expansion, word splitting, and
6342 quote removal. */
6343 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
6344
6345 /* Take the list of words in LIST and do the various substitutions. Return
6346 a new list of words which is the expanded list, and without things like
6347 variable assignments. */
6348
6349 WORD_LIST *
6350 expand_words (list)
6351 WORD_LIST *list;
6352 {
6353 return (expand_word_list_internal (list, WEXP_ALL));
6354 }
6355
6356 /* Same as expand_words (), but doesn't hack variable or environment
6357 variables. */
6358 WORD_LIST *
6359 expand_words_no_vars (list)
6360 WORD_LIST *list;
6361 {
6362 return (expand_word_list_internal (list, WEXP_NOVARS));
6363 }
6364
6365 WORD_LIST *
6366 expand_words_shellexp (list)
6367 WORD_LIST *list;
6368 {
6369 return (expand_word_list_internal (list, WEXP_SHELLEXP));
6370 }
6371
6372 static WORD_LIST *
6373 glob_expand_word_list (tlist, eflags)
6374 WORD_LIST *tlist;
6375 int eflags;
6376 {
6377 char **glob_array, *temp_string;
6378 register int glob_index;
6379 WORD_LIST *glob_list, *output_list, *disposables, *next;
6380 WORD_DESC *tword;
6381
6382 output_list = disposables = (WORD_LIST *)NULL;
6383 glob_array = (char **)NULL;
6384 while (tlist)
6385 {
6386 /* For each word, either globbing is attempted or the word is
6387 added to orig_list. If globbing succeeds, the results are
6388 added to orig_list and the word (tlist) is added to the list
6389 of disposable words. If globbing fails and failed glob
6390 expansions are left unchanged (the shell default), the
6391 original word is added to orig_list. If globbing fails and
6392 failed glob expansions are removed, the original word is
6393 added to the list of disposable words. orig_list ends up
6394 in reverse order and requires a call to REVERSE_LIST to
6395 be set right. After all words are examined, the disposable
6396 words are freed. */
6397 next = tlist->next;
6398
6399 /* If the word isn't an assignment and contains an unquoted
6400 pattern matching character, then glob it. */
6401 if ((tlist->word->flags & W_NOGLOB) == 0 &&
6402 unquoted_glob_pattern_p (tlist->word->word))
6403 {
6404 glob_array = shell_glob_filename (tlist->word->word);
6405
6406 /* Handle error cases.
6407 I don't think we should report errors like "No such file
6408 or directory". However, I would like to report errors
6409 like "Read failed". */
6410
6411 if (GLOB_FAILED (glob_array))
6412 {
6413 glob_array = (char **)xmalloc (sizeof (char *));
6414 glob_array[0] = (char *)NULL;
6415 }
6416
6417 /* Dequote the current word in case we have to use it. */
6418 if (glob_array[0] == NULL)
6419 {
6420 temp_string = dequote_string (tlist->word->word);
6421 free (tlist->word->word);
6422 tlist->word->word = temp_string;
6423 }
6424
6425 /* Make the array into a word list. */
6426 glob_list = (WORD_LIST *)NULL;
6427 for (glob_index = 0; glob_array[glob_index]; glob_index++)
6428 {
6429 tword = make_bare_word (glob_array[glob_index]);
6430 tword->flags |= W_GLOBEXP; /* XXX */
6431 glob_list = make_word_list (tword, glob_list);
6432 }
6433
6434 if (glob_list)
6435 {
6436 output_list = (WORD_LIST *)list_append (glob_list, output_list);
6437 PREPEND_LIST (tlist, disposables);
6438 }
6439 else if (allow_null_glob_expansion == 0)
6440 {
6441 /* Failed glob expressions are left unchanged. */
6442 PREPEND_LIST (tlist, output_list);
6443 }
6444 else
6445 {
6446 /* Failed glob expressions are removed. */
6447 PREPEND_LIST (tlist, disposables);
6448 }
6449 }
6450 else
6451 {
6452 /* Dequote the string. */
6453 temp_string = dequote_string (tlist->word->word);
6454 free (tlist->word->word);
6455 tlist->word->word = temp_string;
6456 PREPEND_LIST (tlist, output_list);
6457 }
6458
6459 strvec_dispose (glob_array);
6460 glob_array = (char **)NULL;
6461
6462 tlist = next;
6463 }
6464
6465 if (disposables)
6466 dispose_words (disposables);
6467
6468 if (output_list)
6469 output_list = REVERSE_LIST (output_list, WORD_LIST *);
6470
6471 return (output_list);
6472 }
6473
6474 #if defined (BRACE_EXPANSION)
6475 static WORD_LIST *
6476 brace_expand_word_list (tlist, eflags)
6477 WORD_LIST *tlist;
6478 int eflags;
6479 {
6480 register char **expansions;
6481 char *temp_string;
6482 WORD_LIST *disposables, *output_list, *next;
6483 WORD_DESC *w;
6484 int eindex;
6485
6486 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
6487 {
6488 next = tlist->next;
6489
6490 /* Only do brace expansion if the word has a brace character. If
6491 not, just add the word list element to BRACES and continue. In
6492 the common case, at least when running shell scripts, this will
6493 degenerate to a bunch of calls to `xstrchr', and then what is
6494 basically a reversal of TLIST into BRACES, which is corrected
6495 by a call to REVERSE_LIST () on BRACES when the end of TLIST
6496 is reached. */
6497 if (xstrchr (tlist->word->word, LBRACE))
6498 {
6499 expansions = brace_expand (tlist->word->word);
6500
6501 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
6502 {
6503 w = make_word (temp_string);
6504 /* If brace expansion didn't change the word, preserve
6505 the flags. We may want to preserve the flags
6506 unconditionally someday -- XXX */
6507 if (STREQ (temp_string, tlist->word->word))
6508 w->flags = tlist->word->flags;
6509 output_list = make_word_list (w, output_list);
6510 free (expansions[eindex]);
6511 }
6512 free (expansions);
6513
6514 /* Add TLIST to the list of words to be freed after brace
6515 expansion has been performed. */
6516 PREPEND_LIST (tlist, disposables);
6517 }
6518 else
6519 PREPEND_LIST (tlist, output_list);
6520 }
6521
6522 if (disposables)
6523 dispose_words (disposables);
6524
6525 if (output_list)
6526 output_list = REVERSE_LIST (output_list, WORD_LIST *);
6527
6528 return (output_list);
6529 }
6530 #endif
6531
6532 static WORD_LIST *
6533 shell_expand_word_list (tlist, eflags)
6534 WORD_LIST *tlist;
6535 int eflags;
6536 {
6537 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
6538 int expanded_something, has_dollar_at;
6539 char *temp_string;
6540
6541 /* We do tilde expansion all the time. This is what 1003.2 says. */
6542 new_list = (WORD_LIST *)NULL;
6543 for (orig_list = tlist; tlist; tlist = next)
6544 {
6545 temp_string = tlist->word->word;
6546
6547 next = tlist->next;
6548
6549 /* Posix.2 section 3.6.1 says that tildes following `=' in words
6550 which are not assignment statements are not expanded. If the
6551 shell isn't in posix mode, though, we perform tilde expansion
6552 on `likely candidate' unquoted assignment statements (flags
6553 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
6554 contains an unquoted :~ or =~. Something to think about: we
6555 now have a flag that says to perform tilde expansion on arguments
6556 to `assignment builtins' like declare and export that look like
6557 assignment statements. We now do tilde expansion on such words
6558 even in POSIX mode. */
6559 if (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
6560 (posixly_correct == 0 || (tlist->word->flags & W_TILDEEXP)) &&
6561 (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string)))
6562 {
6563 tlist->word->word = bash_tilde_expand (temp_string, 1);
6564 free (temp_string);
6565 }
6566 else if (temp_string[0] == '~')
6567 {
6568 tlist->word->word = bash_tilde_expand (temp_string, 0);
6569 free (temp_string);
6570 }
6571
6572 expanded_something = 0;
6573 expanded = expand_word_internal
6574 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
6575
6576 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
6577 {
6578 /* By convention, each time this error is returned,
6579 tlist->word->word has already been freed. */
6580 tlist->word->word = (char *)NULL;
6581
6582 /* Dispose our copy of the original list. */
6583 dispose_words (orig_list);
6584 /* Dispose the new list we're building. */
6585 dispose_words (new_list);
6586
6587 last_command_exit_value = EXECUTION_FAILURE;
6588 if (expanded == &expand_word_error)
6589 jump_to_top_level (DISCARD);
6590 else
6591 jump_to_top_level (FORCE_EOF);
6592 }
6593
6594 /* Don't split words marked W_NOSPLIT. */
6595 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
6596 {
6597 temp_list = word_list_split (expanded);
6598 dispose_words (expanded);
6599 }
6600 else
6601 {
6602 /* If no parameter expansion, command substitution, process
6603 substitution, or arithmetic substitution took place, then
6604 do not do word splitting. We still have to remove quoted
6605 null characters from the result. */
6606 word_list_remove_quoted_nulls (expanded);
6607 temp_list = expanded;
6608 }
6609
6610 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
6611 new_list = (WORD_LIST *)list_append (expanded, new_list);
6612 }
6613
6614 if (orig_list)
6615 dispose_words (orig_list);
6616
6617 if (new_list)
6618 new_list = REVERSE_LIST (new_list, WORD_LIST *);
6619
6620 return (new_list);
6621 }
6622
6623 /* The workhorse for expand_words () and expand_words_no_vars ().
6624 First arg is LIST, a WORD_LIST of words.
6625 Second arg EFLAGS is a flags word controlling which expansions are
6626 performed.
6627
6628 This does all of the substitutions: brace expansion, tilde expansion,
6629 parameter expansion, command substitution, arithmetic expansion,
6630 process substitution, word splitting, and pathname expansion, according
6631 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
6632 set, or for which no expansion is done, do not undergo word splitting.
6633 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
6634 static WORD_LIST *
6635 expand_word_list_internal (list, eflags)
6636 WORD_LIST *list;
6637 int eflags;
6638 {
6639 WORD_LIST *new_list, *temp_list;
6640 int tint;
6641
6642 if (list == 0)
6643 return ((WORD_LIST *)NULL);
6644
6645 garglist = new_list = copy_word_list (list);
6646 if (eflags & WEXP_VARASSIGN)
6647 {
6648 garglist = new_list = separate_out_assignments (new_list);
6649 if (new_list == 0)
6650 {
6651 if (subst_assign_varlist)
6652 {
6653 /* All the words were variable assignments, so they are placed
6654 into the shell's environment. */
6655 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
6656 {
6657 this_command_name = (char *)NULL; /* no arithmetic errors */
6658 tint = do_assignment (temp_list->word->word);
6659 /* Variable assignment errors in non-interactive shells
6660 running in Posix.2 mode cause the shell to exit. */
6661 if (tint == 0)
6662 {
6663 last_command_exit_value = EXECUTION_FAILURE;
6664 if (interactive_shell == 0 && posixly_correct)
6665 jump_to_top_level (FORCE_EOF);
6666 else
6667 jump_to_top_level (DISCARD);
6668 }
6669 }
6670 dispose_words (subst_assign_varlist);
6671 subst_assign_varlist = (WORD_LIST *)NULL;
6672 }
6673 return ((WORD_LIST *)NULL);
6674 }
6675 }
6676
6677 /* Begin expanding the words that remain. The expansions take place on
6678 things that aren't really variable assignments. */
6679
6680 #if defined (BRACE_EXPANSION)
6681 /* Do brace expansion on this word if there are any brace characters
6682 in the string. */
6683 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
6684 new_list = brace_expand_word_list (new_list, eflags);
6685 #endif /* BRACE_EXPANSION */
6686
6687 /* Perform the `normal' shell expansions: tilde expansion, parameter and
6688 variable substitution, command substitution, arithmetic expansion,
6689 and word splitting. */
6690 new_list = shell_expand_word_list (new_list, eflags);
6691
6692 /* Okay, we're almost done. Now let's just do some filename
6693 globbing. */
6694 if (new_list)
6695 {
6696 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
6697 /* Glob expand the word list unless globbing has been disabled. */
6698 new_list = glob_expand_word_list (new_list, eflags);
6699 else
6700 /* Dequote the words, because we're not performing globbing. */
6701 new_list = dequote_list (new_list);
6702 }
6703
6704 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
6705 {
6706 sh_assign_func_t *assign_func;
6707
6708 /* If the remainder of the words expand to nothing, Posix.2 requires
6709 that the variable and environment assignments affect the shell's
6710 environment. */
6711 assign_func = new_list ? assign_in_env : do_assignment;
6712
6713 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
6714 {
6715 this_command_name = (char *)NULL;
6716 tint = (*assign_func) (temp_list->word->word);
6717 /* Variable assignment errors in non-interactive shells running
6718 in Posix.2 mode cause the shell to exit. */
6719 if (tint == 0 && assign_func == do_assignment)
6720 {
6721 last_command_exit_value = EXECUTION_FAILURE;
6722 if (interactive_shell == 0 && posixly_correct)
6723 jump_to_top_level (FORCE_EOF);
6724 else
6725 jump_to_top_level (DISCARD);
6726 }
6727 }
6728
6729 dispose_words (subst_assign_varlist);
6730 subst_assign_varlist = (WORD_LIST *)NULL;
6731 }
6732
6733 #if 0
6734 tint = list_length (new_list) + 1;
6735 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
6736 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
6737 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
6738 glob_argv_flags[tint] = '\0';
6739 #endif
6740
6741 return (new_list);
6742 }