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