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