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