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