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