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