]> git.ipfire.org Git - thirdparty/bash.git/blob - subst.c
commit bash-20120914 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 #if defined (ARRAY_VARS)
5732 /* Handle expanding nameref whose value is x[n] */
5733 else if (var = find_variable_last_nameref (name))
5734 {
5735 temp = nameref_cell (var);
5736 if (temp && *temp && valid_array_reference (temp))
5737 {
5738 name = temp;
5739 goto expand_arrayref;
5740 }
5741 temp = (char *)NULL;
5742 }
5743 #endif
5744 else
5745 temp = (char *)NULL;
5746
5747 if (ret == 0)
5748 {
5749 ret = alloc_word_desc ();
5750 ret->word = temp;
5751 ret->flags |= rflags;
5752 }
5753 return ret;
5754 }
5755
5756 /* Expand an indirect reference to a variable: ${!NAME} expands to the
5757 value of the variable whose name is the value of NAME. */
5758 static WORD_DESC *
5759 parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
5760 char *name;
5761 int var_is_special, quoted;
5762 int *quoted_dollar_atp, *contains_dollar_at;
5763 {
5764 char *temp, *t;
5765 WORD_DESC *w;
5766 SHELL_VAR *v;
5767
5768 /* See if it's a nameref first, behave in ksh93-compatible fashion.
5769 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
5770 bash performs an indirect lookup on foo[0] and expands the result;
5771 ksh93 expands bar[0]. We could do that here -- there are enough usable
5772 primitives to do that -- but do not at this point. */
5773 if (var_is_special == 0 && (v = find_variable_last_nameref (name)))
5774 {
5775 if (nameref_p (v) && (t = nameref_cell (v)) && *t)
5776 {
5777 w = alloc_word_desc ();
5778 w->word = savestring (t);
5779 w->flags = 0;
5780 return w;
5781 }
5782 }
5783
5784 w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
5785 t = w->word;
5786 /* Have to dequote here if necessary */
5787 if (t)
5788 {
5789 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5790 ? dequote_string (t)
5791 : dequote_escapes (t);
5792 free (t);
5793 t = temp;
5794 }
5795 dispose_word_desc (w);
5796
5797 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
5798 if (t == 0)
5799 return (WORD_DESC *)NULL;
5800
5801 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0, 0);
5802 free (t);
5803
5804 return w;
5805 }
5806
5807 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5808 depending on the value of C, the separating character. C can be one of
5809 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5810 between double quotes. */
5811 static WORD_DESC *
5812 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
5813 char *name, *value;
5814 int c, quoted, *qdollaratp, *hasdollarat;
5815 {
5816 WORD_DESC *w;
5817 WORD_LIST *l;
5818 char *t, *t1, *temp;
5819 int hasdol;
5820
5821 /* If the entire expression is between double quotes, we want to treat
5822 the value as a double-quoted string, with the exception that we strip
5823 embedded unescaped double quotes (for sh backwards compatibility). */
5824 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
5825 {
5826 hasdol = 0;
5827 temp = string_extract_double_quoted (value, &hasdol, 1);
5828 }
5829 else
5830 temp = value;
5831
5832 w = alloc_word_desc ();
5833 hasdol = 0;
5834 /* XXX was 0 not quoted */
5835 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5836 : (WORD_LIST *)0;
5837 if (hasdollarat)
5838 *hasdollarat = hasdol || (l && l->next);
5839 if (temp != value)
5840 free (temp);
5841 if (l)
5842 {
5843 /* The expansion of TEMP returned something. We need to treat things
5844 slightly differently if HASDOL is non-zero. If we have "$@", the
5845 individual words have already been quoted. We need to turn them
5846 into a string with the words separated by the first character of
5847 $IFS without any additional quoting, so string_list_dollar_at won't
5848 do the right thing. We use string_list_dollar_star instead. */
5849 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5850
5851 /* If l->next is not null, we know that TEMP contained "$@", since that
5852 is the only expansion that creates more than one word. */
5853 if (qdollaratp && ((hasdol && quoted) || l->next))
5854 *qdollaratp = 1;
5855 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
5856 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
5857 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
5858 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5859 (which is more paranoia than anything else), we need to return the
5860 quoted null string and set the flags to indicate it. */
5861 if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL))
5862 {
5863 w->flags |= W_HASQUOTEDNULL;
5864 }
5865 dispose_words (l);
5866 }
5867 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
5868 {
5869 /* The brace expansion occurred between double quotes and there was
5870 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
5871 it does not expand to anything. In this case, we want to return
5872 a quoted empty string. */
5873 temp = make_quoted_char ('\0');
5874 w->flags |= W_HASQUOTEDNULL;
5875 }
5876 else
5877 temp = (char *)NULL;
5878
5879 if (c == '-' || c == '+')
5880 {
5881 w->word = temp;
5882 return w;
5883 }
5884
5885 /* c == '=' */
5886 t = temp ? savestring (temp) : savestring ("");
5887 t1 = dequote_string (t);
5888 free (t);
5889 #if defined (ARRAY_VARS)
5890 if (valid_array_reference (name))
5891 assign_array_element (name, t1, 0);
5892 else
5893 #endif /* ARRAY_VARS */
5894 bind_variable (name, t1, 0);
5895
5896 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
5897 free (temp);
5898
5899 w->word = t1;
5900 return w;
5901 }
5902
5903 /* Deal with the right hand side of a ${name:?value} expansion in the case
5904 that NAME is null or not set. If VALUE is non-null it is expanded and
5905 used as the error message to print, otherwise a standard message is
5906 printed. */
5907 static void
5908 parameter_brace_expand_error (name, value)
5909 char *name, *value;
5910 {
5911 WORD_LIST *l;
5912 char *temp;
5913
5914 last_command_exit_value = EXECUTION_FAILURE; /* ensure it's non-zero */
5915 if (value && *value)
5916 {
5917 l = expand_string (value, 0);
5918 temp = string_list (l);
5919 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5920 FREE (temp);
5921 dispose_words (l);
5922 }
5923 else
5924 report_error (_("%s: parameter null or not set"), name);
5925
5926 /* Free the data we have allocated during this expansion, since we
5927 are about to longjmp out. */
5928 free (name);
5929 FREE (value);
5930 }
5931
5932 /* Return 1 if NAME is something for which parameter_brace_expand_length is
5933 OK to do. */
5934 static int
5935 valid_length_expression (name)
5936 char *name;
5937 {
5938 return (name[1] == '\0' || /* ${#} */
5939 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5940 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5941 #if defined (ARRAY_VARS)
5942 valid_array_reference (name + 1) || /* ${#a[7]} */
5943 #endif
5944 legal_identifier (name + 1)); /* ${#PS1} */
5945 }
5946
5947 /* Handle the parameter brace expansion that requires us to return the
5948 length of a parameter. */
5949 static intmax_t
5950 parameter_brace_expand_length (name)
5951 char *name;
5952 {
5953 char *t, *newname;
5954 intmax_t number, arg_index;
5955 WORD_LIST *list;
5956 #if defined (ARRAY_VARS)
5957 SHELL_VAR *var;
5958 #endif
5959
5960 if (name[1] == '\0') /* ${#} */
5961 number = number_of_args ();
5962 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5963 number = number_of_args ();
5964 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5965 {
5966 /* Take the lengths of some of the shell's special parameters. */
5967 switch (name[1])
5968 {
5969 case '-':
5970 t = which_set_flags ();
5971 break;
5972 case '?':
5973 t = itos (last_command_exit_value);
5974 break;
5975 case '$':
5976 t = itos (dollar_dollar_pid);
5977 break;
5978 case '!':
5979 if (last_asynchronous_pid == NO_PID)
5980 t = (char *)NULL; /* XXX - error if set -u set? */
5981 else
5982 t = itos (last_asynchronous_pid);
5983 break;
5984 case '#':
5985 t = itos (number_of_args ());
5986 break;
5987 }
5988 number = STRLEN (t);
5989 FREE (t);
5990 }
5991 #if defined (ARRAY_VARS)
5992 else if (valid_array_reference (name + 1))
5993 number = array_length_reference (name + 1);
5994 #endif /* ARRAY_VARS */
5995 else
5996 {
5997 number = 0;
5998
5999 if (legal_number (name + 1, &arg_index)) /* ${#1} */
6000 {
6001 t = get_dollar_var_value (arg_index);
6002 if (t == 0 && unbound_vars_is_error)
6003 return INTMAX_MIN;
6004 number = MB_STRLEN (t);
6005 FREE (t);
6006 }
6007 #if defined (ARRAY_VARS)
6008 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
6009 {
6010 if (assoc_p (var))
6011 t = assoc_reference (assoc_cell (var), "0");
6012 else
6013 t = array_reference (array_cell (var), 0);
6014 if (t == 0 && unbound_vars_is_error)
6015 return INTMAX_MIN;
6016 number = MB_STRLEN (t);
6017 }
6018 #endif
6019 else /* ${#PS1} */
6020 {
6021 newname = savestring (name);
6022 newname[0] = '$';
6023 list = expand_string (newname, Q_DOUBLE_QUOTES);
6024 t = list ? string_list (list) : (char *)NULL;
6025 free (newname);
6026 if (list)
6027 dispose_words (list);
6028
6029 number = t ? MB_STRLEN (t) : 0;
6030 FREE (t);
6031 }
6032 }
6033
6034 return (number);
6035 }
6036
6037 /* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
6038 so we do some ad-hoc parsing of an arithmetic expression to find
6039 the first DELIM, instead of using strchr(3). Two rules:
6040 1. If the substring contains a `(', read until closing `)'.
6041 2. If the substring contains a `?', read past one `:' for each `?'.
6042 */
6043
6044 static char *
6045 skiparith (substr, delim)
6046 char *substr;
6047 int delim;
6048 {
6049 size_t sublen;
6050 int skipcol, pcount, i;
6051 DECLARE_MBSTATE;
6052
6053 sublen = strlen (substr);
6054 i = skipcol = pcount = 0;
6055 while (substr[i])
6056 {
6057 /* Balance parens */
6058 if (substr[i] == LPAREN)
6059 {
6060 pcount++;
6061 i++;
6062 continue;
6063 }
6064 if (substr[i] == RPAREN && pcount)
6065 {
6066 pcount--;
6067 i++;
6068 continue;
6069 }
6070 if (pcount)
6071 {
6072 ADVANCE_CHAR (substr, sublen, i);
6073 continue;
6074 }
6075
6076 /* Skip one `:' for each `?' */
6077 if (substr[i] == ':' && skipcol)
6078 {
6079 skipcol--;
6080 i++;
6081 continue;
6082 }
6083 if (substr[i] == delim)
6084 break;
6085 if (substr[i] == '?')
6086 {
6087 skipcol++;
6088 i++;
6089 continue;
6090 }
6091 ADVANCE_CHAR (substr, sublen, i);
6092 }
6093
6094 return (substr + i);
6095 }
6096
6097 /* Verify and limit the start and end of the desired substring. If
6098 VTYPE == 0, a regular shell variable is being used; if it is 1,
6099 then the positional parameters are being used; if it is 2, then
6100 VALUE is really a pointer to an array variable that should be used.
6101 Return value is 1 if both values were OK, 0 if there was a problem
6102 with an invalid expression, or -1 if the values were out of range. */
6103 static int
6104 verify_substring_values (v, value, substr, vtype, e1p, e2p)
6105 SHELL_VAR *v;
6106 char *value, *substr;
6107 int vtype;
6108 intmax_t *e1p, *e2p;
6109 {
6110 char *t, *temp1, *temp2;
6111 arrayind_t len;
6112 int expok;
6113 #if defined (ARRAY_VARS)
6114 ARRAY *a;
6115 HASH_TABLE *h;
6116 #endif
6117
6118 /* duplicate behavior of strchr(3) */
6119 t = skiparith (substr, ':');
6120 if (*t && *t == ':')
6121 *t = '\0';
6122 else
6123 t = (char *)0;
6124
6125 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
6126 *e1p = evalexp (temp1, &expok);
6127 free (temp1);
6128 if (expok == 0)
6129 return (0);
6130
6131 len = -1; /* paranoia */
6132 switch (vtype)
6133 {
6134 case VT_VARIABLE:
6135 case VT_ARRAYMEMBER:
6136 len = MB_STRLEN (value);
6137 break;
6138 case VT_POSPARMS:
6139 len = number_of_args () + 1;
6140 if (*e1p == 0)
6141 len++; /* add one arg if counting from $0 */
6142 break;
6143 #if defined (ARRAY_VARS)
6144 case VT_ARRAYVAR:
6145 /* For arrays, the first value deals with array indices. Negative
6146 offsets count from one past the array's maximum index. Associative
6147 arrays treat the number of elements as the maximum index. */
6148 if (assoc_p (v))
6149 {
6150 h = assoc_cell (v);
6151 len = assoc_num_elements (h) + (*e1p < 0);
6152 }
6153 else
6154 {
6155 a = (ARRAY *)value;
6156 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
6157 }
6158 break;
6159 #endif
6160 }
6161
6162 if (len == -1) /* paranoia */
6163 return -1;
6164
6165 if (*e1p < 0) /* negative offsets count from end */
6166 *e1p += len;
6167
6168 if (*e1p > len || *e1p < 0)
6169 return (-1);
6170
6171 #if defined (ARRAY_VARS)
6172 /* For arrays, the second offset deals with the number of elements. */
6173 if (vtype == VT_ARRAYVAR)
6174 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
6175 #endif
6176
6177 if (t)
6178 {
6179 t++;
6180 temp2 = savestring (t);
6181 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
6182 free (temp2);
6183 t[-1] = ':';
6184 *e2p = evalexp (temp1, &expok);
6185 free (temp1);
6186 if (expok == 0)
6187 return (0);
6188 #if 1
6189 if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0)
6190 #else
6191 /* bash-4.3: allow positional parameter length < 0 to count backwards
6192 from end of positional parameters */
6193 if (vtype == VT_ARRAYVAR && *e2p < 0)
6194 #endif
6195 {
6196 internal_error (_("%s: substring expression < 0"), t);
6197 return (0);
6198 }
6199 #if defined (ARRAY_VARS)
6200 /* In order to deal with sparse arrays, push the intelligence about how
6201 to deal with the number of elements desired down to the array-
6202 specific functions. */
6203 if (vtype != VT_ARRAYVAR)
6204 #endif
6205 {
6206 if (*e2p < 0)
6207 {
6208 *e2p += len;
6209 if (*e2p < 0 || *e2p < *e1p)
6210 {
6211 internal_error (_("%s: substring expression < 0"), t);
6212 return (0);
6213 }
6214 }
6215 else
6216 *e2p += *e1p; /* want E2 chars starting at E1 */
6217 if (*e2p > len)
6218 *e2p = len;
6219 }
6220 }
6221 else
6222 *e2p = len;
6223
6224 return (1);
6225 }
6226
6227 /* Return the type of variable specified by VARNAME (simple variable,
6228 positional param, or array variable). Also return the value specified
6229 by VARNAME (value of a variable or a reference to an array element).
6230 QUOTED is the standard description of quoting state, using Q_* defines.
6231 FLAGS is currently a set of flags to pass to array_value. If IND is
6232 non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
6233 passed to array_value so the array index is not computed again.
6234 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
6235 characters in the value are quoted with CTLESC and takes appropriate
6236 steps. For convenience, *VALP is set to the dequoted VALUE. */
6237 static int
6238 get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
6239 char *varname, *value;
6240 arrayind_t ind;
6241 int quoted, flags;
6242 SHELL_VAR **varp;
6243 char **valp;
6244 {
6245 int vtype;
6246 char *temp;
6247 #if defined (ARRAY_VARS)
6248 SHELL_VAR *v;
6249 #endif
6250 arrayind_t lind;
6251
6252 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
6253 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
6254 if (vtype == VT_POSPARMS && varname[0] == '*')
6255 vtype |= VT_STARSUB;
6256 *varp = (SHELL_VAR *)NULL;
6257
6258 #if defined (ARRAY_VARS)
6259 if (valid_array_reference (varname))
6260 {
6261 v = array_variable_part (varname, &temp, (int *)0);
6262 /* If we want to signal array_value to use an already-computed index,
6263 set LIND to that index */
6264 lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
6265 if (v && (array_p (v) || assoc_p (v)))
6266 { /* [ */
6267 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
6268 {
6269 /* Callers have to differentiate betwen indexed and associative */
6270 vtype = VT_ARRAYVAR;
6271 if (temp[0] == '*')
6272 vtype |= VT_STARSUB;
6273 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
6274 }
6275 else
6276 {
6277 vtype = VT_ARRAYMEMBER;
6278 *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
6279 }
6280 *varp = v;
6281 }
6282 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
6283 {
6284 vtype = VT_VARIABLE;
6285 *varp = v;
6286 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6287 *valp = dequote_string (value);
6288 else
6289 *valp = dequote_escapes (value);
6290 }
6291 else
6292 {
6293 vtype = VT_ARRAYMEMBER;
6294 *varp = v;
6295 *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
6296 }
6297 }
6298 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
6299 {
6300 vtype = VT_ARRAYMEMBER;
6301 *varp = v;
6302 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
6303 }
6304 else
6305 #endif
6306 {
6307 if (value && vtype == VT_VARIABLE)
6308 {
6309 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6310 *valp = dequote_string (value);
6311 else
6312 *valp = dequote_escapes (value);
6313 }
6314 else
6315 *valp = value;
6316 }
6317
6318 return vtype;
6319 }
6320
6321 /******************************************************/
6322 /* */
6323 /* Functions to extract substrings of variable values */
6324 /* */
6325 /******************************************************/
6326
6327 #if defined (HANDLE_MULTIBYTE)
6328 /* Character-oriented rather than strictly byte-oriented substrings. S and
6329 E, rather being strict indices into STRING, indicate character (possibly
6330 multibyte character) positions that require calculation.
6331 Used by the ${param:offset[:length]} expansion. */
6332 static char *
6333 mb_substring (string, s, e)
6334 char *string;
6335 int s, e;
6336 {
6337 char *tt;
6338 int start, stop, i, slen;
6339 DECLARE_MBSTATE;
6340
6341 start = 0;
6342 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
6343 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
6344
6345 i = s;
6346 while (string[start] && i--)
6347 ADVANCE_CHAR (string, slen, start);
6348 stop = start;
6349 i = e - s;
6350 while (string[stop] && i--)
6351 ADVANCE_CHAR (string, slen, stop);
6352 tt = substring (string, start, stop);
6353 return tt;
6354 }
6355 #endif
6356
6357 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
6358 is `@', use the positional parameters; otherwise, use the value of
6359 VARNAME. If VARNAME is an array variable, use the array elements. */
6360
6361 static char *
6362 parameter_brace_substring (varname, value, ind, substr, quoted, flags)
6363 char *varname, *value;
6364 int ind;
6365 char *substr;
6366 int quoted, flags;
6367 {
6368 intmax_t e1, e2;
6369 int vtype, r, starsub;
6370 char *temp, *val, *tt, *oname;
6371 SHELL_VAR *v;
6372
6373 if (value == 0)
6374 return ((char *)NULL);
6375
6376 oname = this_command_name;
6377 this_command_name = varname;
6378
6379 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
6380 if (vtype == -1)
6381 {
6382 this_command_name = oname;
6383 return ((char *)NULL);
6384 }
6385
6386 starsub = vtype & VT_STARSUB;
6387 vtype &= ~VT_STARSUB;
6388
6389 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
6390 this_command_name = oname;
6391 if (r <= 0)
6392 {
6393 if (vtype == VT_VARIABLE)
6394 FREE (val);
6395 return ((r == 0) ? &expand_param_error : (char *)NULL);
6396 }
6397
6398 switch (vtype)
6399 {
6400 case VT_VARIABLE:
6401 case VT_ARRAYMEMBER:
6402 #if defined (HANDLE_MULTIBYTE)
6403 if (MB_CUR_MAX > 1)
6404 tt = mb_substring (val, e1, e2);
6405 else
6406 #endif
6407 tt = substring (val, e1, e2);
6408
6409 if (vtype == VT_VARIABLE)
6410 FREE (val);
6411 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6412 temp = quote_string (tt);
6413 else
6414 temp = tt ? quote_escapes (tt) : (char *)NULL;
6415 FREE (tt);
6416 break;
6417 case VT_POSPARMS:
6418 tt = pos_params (varname, e1, e2, quoted);
6419 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
6420 {
6421 temp = tt ? quote_escapes (tt) : (char *)NULL;
6422 FREE (tt);
6423 }
6424 else
6425 temp = tt;
6426 break;
6427 #if defined (ARRAY_VARS)
6428 case VT_ARRAYVAR:
6429 if (assoc_p (v))
6430 /* we convert to list and take first e2 elements starting at e1th
6431 element -- officially undefined for now */
6432 temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
6433 else
6434 /* We want E2 to be the number of elements desired (arrays can be sparse,
6435 so verify_substring_values just returns the numbers specified and we
6436 rely on array_subrange to understand how to deal with them). */
6437 temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
6438 /* array_subrange now calls array_quote_escapes as appropriate, so the
6439 caller no longer needs to. */
6440 break;
6441 #endif
6442 default:
6443 temp = (char *)NULL;
6444 }
6445
6446 return temp;
6447 }
6448
6449 /****************************************************************/
6450 /* */
6451 /* Functions to perform pattern substitution on variable values */
6452 /* */
6453 /****************************************************************/
6454
6455 static int
6456 shouldexp_replacement (s)
6457 char *s;
6458 {
6459 register char *p;
6460
6461 for (p = s; p && *p; p++)
6462 {
6463 if (*p == '\\')
6464 p++;
6465 else if (*p == '&')
6466 return 1;
6467 }
6468 return 0;
6469 }
6470
6471 char *
6472 pat_subst (string, pat, rep, mflags)
6473 char *string, *pat, *rep;
6474 int mflags;
6475 {
6476 char *ret, *s, *e, *str, *rstr, *mstr;
6477 int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen;
6478
6479 if (string == 0)
6480 return (savestring (""));
6481
6482 mtype = mflags & MATCH_TYPEMASK;
6483
6484 #if 0 /* bash-4.2 ? */
6485 rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0;
6486 #else
6487 rxpand = 0;
6488 #endif
6489
6490 /* Special cases:
6491 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
6492 * with REP and return the result.
6493 * 2. A null pattern with mtype == MATCH_END means to append REP to
6494 * STRING and return the result.
6495 * These don't understand or process `&' in the replacement string.
6496 */
6497 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
6498 {
6499 replen = STRLEN (rep);
6500 l = STRLEN (string);
6501 ret = (char *)xmalloc (replen + l + 2);
6502 if (replen == 0)
6503 strcpy (ret, string);
6504 else if (mtype == MATCH_BEG)
6505 {
6506 strcpy (ret, rep);
6507 strcpy (ret + replen, string);
6508 }
6509 else
6510 {
6511 strcpy (ret, string);
6512 strcpy (ret + l, rep);
6513 }
6514 return (ret);
6515 }
6516
6517 ret = (char *)xmalloc (rsize = 64);
6518 ret[0] = '\0';
6519
6520 for (replen = STRLEN (rep), rptr = 0, str = string;;)
6521 {
6522 if (match_pattern (str, pat, mtype, &s, &e) == 0)
6523 break;
6524 l = s - str;
6525
6526 if (rxpand)
6527 {
6528 int x;
6529 mlen = e - s;
6530 mstr = xmalloc (mlen + 1);
6531 for (x = 0; x < mlen; x++)
6532 mstr[x] = s[x];
6533 mstr[mlen] = '\0';
6534 rstr = strcreplace (rep, '&', mstr, 0);
6535 rslen = strlen (rstr);
6536 }
6537 else
6538 {
6539 rstr = rep;
6540 rslen = replen;
6541 }
6542
6543 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64);
6544
6545 /* OK, now copy the leading unmatched portion of the string (from
6546 str to s) to ret starting at rptr (the current offset). Then copy
6547 the replacement string at ret + rptr + (s - str). Increment
6548 rptr (if necessary) and str and go on. */
6549 if (l)
6550 {
6551 strncpy (ret + rptr, str, l);
6552 rptr += l;
6553 }
6554 if (replen)
6555 {
6556 strncpy (ret + rptr, rstr, rslen);
6557 rptr += rslen;
6558 }
6559 str = e; /* e == end of match */
6560
6561 if (rstr != rep)
6562 free (rstr);
6563
6564 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
6565 break;
6566
6567 if (s == e)
6568 {
6569 /* On a zero-length match, make sure we copy one character, since
6570 we increment one character to avoid infinite recursion. */
6571 RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64);
6572 ret[rptr++] = *str++;
6573 e++; /* avoid infinite recursion on zero-length match */
6574 }
6575 }
6576
6577 /* Now copy the unmatched portion of the input string */
6578 if (str && *str)
6579 {
6580 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
6581 strcpy (ret + rptr, str);
6582 }
6583 else
6584 ret[rptr] = '\0';
6585
6586 return ret;
6587 }
6588
6589 /* Do pattern match and replacement on the positional parameters. */
6590 static char *
6591 pos_params_pat_subst (string, pat, rep, mflags)
6592 char *string, *pat, *rep;
6593 int mflags;
6594 {
6595 WORD_LIST *save, *params;
6596 WORD_DESC *w;
6597 char *ret;
6598 int pchar, qflags;
6599
6600 save = params = list_rest_of_args ();
6601 if (save == 0)
6602 return ((char *)NULL);
6603
6604 for ( ; params; params = params->next)
6605 {
6606 ret = pat_subst (params->word->word, pat, rep, mflags);
6607 w = alloc_word_desc ();
6608 w->word = ret ? ret : savestring ("");
6609 dispose_word (params->word);
6610 params->word = w;
6611 }
6612
6613 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6614 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6615
6616 #if 0
6617 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
6618 ret = string_list_dollar_star (quote_list (save));
6619 else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
6620 ret = string_list_dollar_star (save);
6621 else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
6622 ret = string_list_dollar_at (save, qflags);
6623 else
6624 ret = string_list_dollar_star (save);
6625 #else
6626 ret = string_list_pos_params (pchar, save, qflags);
6627 #endif
6628
6629 dispose_words (save);
6630
6631 return (ret);
6632 }
6633
6634 /* Perform pattern substitution on VALUE, which is the expansion of
6635 VARNAME. PATSUB is an expression supplying the pattern to match
6636 and the string to substitute. QUOTED is a flags word containing
6637 the type of quoting currently in effect. */
6638 static char *
6639 parameter_brace_patsub (varname, value, ind, patsub, quoted, flags)
6640 char *varname, *value;
6641 int ind;
6642 char *patsub;
6643 int quoted, flags;
6644 {
6645 int vtype, mflags, starsub, delim;
6646 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
6647 SHELL_VAR *v;
6648
6649 if (value == 0)
6650 return ((char *)NULL);
6651
6652 this_command_name = varname;
6653
6654 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
6655 if (vtype == -1)
6656 return ((char *)NULL);
6657
6658 starsub = vtype & VT_STARSUB;
6659 vtype &= ~VT_STARSUB;
6660
6661 mflags = 0;
6662 /* PATSUB is never NULL when this is called. */
6663 if (*patsub == '/')
6664 {
6665 mflags |= MATCH_GLOBREP;
6666 patsub++;
6667 }
6668
6669 /* Malloc this because expand_string_if_necessary or one of the expansion
6670 functions in its call chain may free it on a substitution error. */
6671 lpatsub = savestring (patsub);
6672
6673 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6674 mflags |= MATCH_QUOTED;
6675
6676 if (starsub)
6677 mflags |= MATCH_STARSUB;
6678
6679 /* If the pattern starts with a `/', make sure we skip over it when looking
6680 for the replacement delimiter. */
6681 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
6682 if (lpatsub[delim] == '/')
6683 {
6684 lpatsub[delim] = 0;
6685 rep = lpatsub + delim + 1;
6686 }
6687 else
6688 rep = (char *)NULL;
6689
6690 if (rep && *rep == '\0')
6691 rep = (char *)NULL;
6692
6693 /* Perform the same expansions on the pattern as performed by the
6694 pattern removal expansions. */
6695 pat = getpattern (lpatsub, quoted, 1);
6696
6697 if (rep)
6698 /* We want to perform quote removal on the expanded replacement even if
6699 the entire expansion is double-quoted because the parser and string
6700 extraction functions treated quotes in the replacement string as
6701 special. */
6702 rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
6703
6704 /* ksh93 doesn't allow the match specifier to be a part of the expanded
6705 pattern. This is an extension. Make sure we don't anchor the pattern
6706 at the beginning or end of the string if we're doing global replacement,
6707 though. */
6708 p = pat;
6709 if (mflags & MATCH_GLOBREP)
6710 mflags |= MATCH_ANY;
6711 else if (pat && pat[0] == '#')
6712 {
6713 mflags |= MATCH_BEG;
6714 p++;
6715 }
6716 else if (pat && pat[0] == '%')
6717 {
6718 mflags |= MATCH_END;
6719 p++;
6720 }
6721 else
6722 mflags |= MATCH_ANY;
6723
6724 /* OK, we now want to substitute REP for PAT in VAL. If
6725 flags & MATCH_GLOBREP is non-zero, the substitution is done
6726 everywhere, otherwise only the first occurrence of PAT is
6727 replaced. The pattern matching code doesn't understand
6728 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6729 values passed in (VT_VARIABLE) so the pattern substitution
6730 code works right. We need to requote special chars after
6731 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6732 other cases if QUOTED == 0, since the posparams and arrays
6733 indexed by * or @ do special things when QUOTED != 0. */
6734
6735 switch (vtype)
6736 {
6737 case VT_VARIABLE:
6738 case VT_ARRAYMEMBER:
6739 temp = pat_subst (val, p, rep, mflags);
6740 if (vtype == VT_VARIABLE)
6741 FREE (val);
6742 if (temp)
6743 {
6744 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6745 free (temp);
6746 temp = tt;
6747 }
6748 break;
6749 case VT_POSPARMS:
6750 temp = pos_params_pat_subst (val, p, rep, mflags);
6751 if (temp && (mflags & MATCH_QUOTED) == 0)
6752 {
6753 tt = quote_escapes (temp);
6754 free (temp);
6755 temp = tt;
6756 }
6757 break;
6758 #if defined (ARRAY_VARS)
6759 case VT_ARRAYVAR:
6760 temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6761 : array_patsub (array_cell (v), p, rep, mflags);
6762 /* Don't call quote_escapes anymore; array_patsub calls
6763 array_quote_escapes as appropriate before adding the
6764 space separators; ditto for assoc_patsub. */
6765 break;
6766 #endif
6767 }
6768
6769 FREE (pat);
6770 FREE (rep);
6771 free (lpatsub);
6772
6773 return temp;
6774 }
6775
6776 /****************************************************************/
6777 /* */
6778 /* Functions to perform case modification on variable values */
6779 /* */
6780 /****************************************************************/
6781
6782 /* Do case modification on the positional parameters. */
6783
6784 static char *
6785 pos_params_modcase (string, pat, modop, mflags)
6786 char *string, *pat;
6787 int modop;
6788 int mflags;
6789 {
6790 WORD_LIST *save, *params;
6791 WORD_DESC *w;
6792 char *ret;
6793 int pchar, qflags;
6794
6795 save = params = list_rest_of_args ();
6796 if (save == 0)
6797 return ((char *)NULL);
6798
6799 for ( ; params; params = params->next)
6800 {
6801 ret = sh_modcase (params->word->word, pat, modop);
6802 w = alloc_word_desc ();
6803 w->word = ret ? ret : savestring ("");
6804 dispose_word (params->word);
6805 params->word = w;
6806 }
6807
6808 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6809 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6810
6811 ret = string_list_pos_params (pchar, save, qflags);
6812 dispose_words (save);
6813
6814 return (ret);
6815 }
6816
6817 /* Perform case modification on VALUE, which is the expansion of
6818 VARNAME. MODSPEC is an expression supplying the type of modification
6819 to perform. QUOTED is a flags word containing the type of quoting
6820 currently in effect. */
6821 static char *
6822 parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags)
6823 char *varname, *value;
6824 int ind, modspec;
6825 char *patspec;
6826 int quoted, flags;
6827 {
6828 int vtype, starsub, modop, mflags, x;
6829 char *val, *temp, *pat, *p, *lpat, *tt;
6830 SHELL_VAR *v;
6831
6832 if (value == 0)
6833 return ((char *)NULL);
6834
6835 this_command_name = varname;
6836
6837 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
6838 if (vtype == -1)
6839 return ((char *)NULL);
6840
6841 starsub = vtype & VT_STARSUB;
6842 vtype &= ~VT_STARSUB;
6843
6844 modop = 0;
6845 mflags = 0;
6846 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6847 mflags |= MATCH_QUOTED;
6848 if (starsub)
6849 mflags |= MATCH_STARSUB;
6850
6851 p = patspec;
6852 if (modspec == '^')
6853 {
6854 x = p && p[0] == modspec;
6855 modop = x ? CASE_UPPER : CASE_UPFIRST;
6856 p += x;
6857 }
6858 else if (modspec == ',')
6859 {
6860 x = p && p[0] == modspec;
6861 modop = x ? CASE_LOWER : CASE_LOWFIRST;
6862 p += x;
6863 }
6864 else if (modspec == '~')
6865 {
6866 x = p && p[0] == modspec;
6867 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6868 p += x;
6869 }
6870
6871 lpat = p ? savestring (p) : 0;
6872 /* Perform the same expansions on the pattern as performed by the
6873 pattern removal expansions. FOR LATER */
6874 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6875
6876 /* OK, now we do the case modification. */
6877 switch (vtype)
6878 {
6879 case VT_VARIABLE:
6880 case VT_ARRAYMEMBER:
6881 temp = sh_modcase (val, pat, modop);
6882 if (vtype == VT_VARIABLE)
6883 FREE (val);
6884 if (temp)
6885 {
6886 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6887 free (temp);
6888 temp = tt;
6889 }
6890 break;
6891
6892 case VT_POSPARMS:
6893 temp = pos_params_modcase (val, pat, modop, mflags);
6894 if (temp && (mflags & MATCH_QUOTED) == 0)
6895 {
6896 tt = quote_escapes (temp);
6897 free (temp);
6898 temp = tt;
6899 }
6900 break;
6901
6902 #if defined (ARRAY_VARS)
6903 case VT_ARRAYVAR:
6904 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6905 : array_modcase (array_cell (v), pat, modop, mflags);
6906 /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6907 as appropriate before adding the space separators; ditto for
6908 assoc_modcase. */
6909 break;
6910 #endif
6911 }
6912
6913 FREE (pat);
6914 free (lpat);
6915
6916 return temp;
6917 }
6918
6919 /* Check for unbalanced parens in S, which is the contents of $(( ... )). If
6920 any occur, this must be a nested command substitution, so return 0.
6921 Otherwise, return 1. A valid arithmetic expression must always have a
6922 ( before a matching ), so any cases where there are more right parens
6923 means that this must not be an arithmetic expression, though the parser
6924 will not accept it without a balanced total number of parens. */
6925 static int
6926 chk_arithsub (s, len)
6927 const char *s;
6928 int len;
6929 {
6930 int i, count;
6931 DECLARE_MBSTATE;
6932
6933 i = count = 0;
6934 while (i < len)
6935 {
6936 if (s[i] == LPAREN)
6937 count++;
6938 else if (s[i] == RPAREN)
6939 {
6940 count--;
6941 if (count < 0)
6942 return 0;
6943 }
6944
6945 switch (s[i])
6946 {
6947 default:
6948 ADVANCE_CHAR (s, len, i);
6949 break;
6950
6951 case '\\':
6952 i++;
6953 if (s[i])
6954 ADVANCE_CHAR (s, len, i);
6955 break;
6956
6957 case '\'':
6958 i = skip_single_quoted (s, len, ++i);
6959 break;
6960
6961 case '"':
6962 i = skip_double_quoted ((char *)s, len, ++i);
6963 break;
6964 }
6965 }
6966
6967 return (count == 0);
6968 }
6969
6970 /****************************************************************/
6971 /* */
6972 /* Functions to perform parameter expansion on a string */
6973 /* */
6974 /****************************************************************/
6975
6976 /* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
6977 static WORD_DESC *
6978 parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
6979 char *string;
6980 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags;
6981 {
6982 int check_nullness, var_is_set, var_is_null, var_is_special;
6983 int want_substring, want_indir, want_patsub, want_casemod;
6984 char *name, *value, *temp, *temp1;
6985 WORD_DESC *tdesc, *ret;
6986 int t_index, sindex, c, tflag, modspec;
6987 intmax_t number;
6988 arrayind_t ind;
6989
6990 temp = temp1 = value = (char *)NULL;
6991 var_is_set = var_is_null = var_is_special = check_nullness = 0;
6992 want_substring = want_indir = want_patsub = want_casemod = 0;
6993
6994 sindex = *indexp;
6995 t_index = ++sindex;
6996 /* ${#var} doesn't have any of the other parameter expansions on it. */
6997 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
6998 name = string_extract (string, &t_index, "}", SX_VARNAME);
6999 else
7000 #if defined (CASEMOD_EXPANSIONS)
7001 /* To enable case-toggling expansions using the `~' operator character
7002 change the 1 to 0. */
7003 # if defined (CASEMOD_CAPCASE)
7004 name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
7005 # else
7006 name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
7007 # endif /* CASEMOD_CAPCASE */
7008 #else
7009 name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
7010 #endif /* CASEMOD_EXPANSIONS */
7011
7012 ret = 0;
7013 tflag = 0;
7014
7015 ind = INTMAX_MIN;
7016
7017 /* If the name really consists of a special variable, then make sure
7018 that we have the entire name. We don't allow indirect references
7019 to special variables except `#', `?', `@' and `*'. */
7020 if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
7021 (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
7022 {
7023 t_index++;
7024 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
7025 name = (char *)xrealloc (name, 3 + (strlen (temp1)));
7026 *name = string[sindex];
7027 if (string[sindex] == '!')
7028 {
7029 /* indirect reference of $#, $?, $@, or $* */
7030 name[1] = string[sindex + 1];
7031 strcpy (name + 2, temp1);
7032 }
7033 else
7034 strcpy (name + 1, temp1);
7035 free (temp1);
7036 }
7037 sindex = t_index;
7038
7039 /* Find out what character ended the variable name. Then
7040 do the appropriate thing. */
7041 if (c = string[sindex])
7042 sindex++;
7043
7044 /* If c is followed by one of the valid parameter expansion
7045 characters, move past it as normal. If not, assume that
7046 a substring specification is being given, and do not move
7047 past it. */
7048 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
7049 {
7050 check_nullness++;
7051 if (c = string[sindex])
7052 sindex++;
7053 }
7054 else if (c == ':' && string[sindex] != RBRACE)
7055 want_substring = 1;
7056 else if (c == '/' /* && string[sindex] != RBRACE */) /* XXX */
7057 want_patsub = 1;
7058 #if defined (CASEMOD_EXPANSIONS)
7059 else if (c == '^' || c == ',' || c == '~')
7060 {
7061 modspec = c;
7062 want_casemod = 1;
7063 }
7064 #endif
7065
7066 /* Catch the valid and invalid brace expressions that made it through the
7067 tests above. */
7068 /* ${#-} is a valid expansion and means to take the length of $-.
7069 Similarly for ${#?} and ${##}... */
7070 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
7071 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
7072 {
7073 name = (char *)xrealloc (name, 3);
7074 name[1] = c;
7075 name[2] = '\0';
7076 c = string[sindex++];
7077 }
7078
7079 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
7080 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
7081 member (c, "%:=+/") && string[sindex] == RBRACE)
7082 {
7083 temp = (char *)NULL;
7084 goto bad_substitution;
7085 }
7086
7087 /* Indirect expansion begins with a `!'. A valid indirect expansion is
7088 either a variable name, one of the positional parameters or a special
7089 variable that expands to one of the positional parameters. */
7090 want_indir = *name == '!' &&
7091 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
7092 || VALID_INDIR_PARAM (name[1]));
7093
7094 /* Determine the value of this variable. */
7095
7096 /* Check for special variables, directly referenced. */
7097 if (SPECIAL_VAR (name, want_indir))
7098 var_is_special++;
7099
7100 /* Check for special expansion things, like the length of a parameter */
7101 if (*name == '#' && name[1])
7102 {
7103 /* If we are not pointing at the character just after the
7104 closing brace, then we haven't gotten all of the name.
7105 Since it begins with a special character, this is a bad
7106 substitution. Also check NAME for validity before trying
7107 to go on. */
7108 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
7109 {
7110 temp = (char *)NULL;
7111 goto bad_substitution;
7112 }
7113
7114 number = parameter_brace_expand_length (name);
7115 if (number == INTMAX_MIN && unbound_vars_is_error)
7116 {
7117 last_command_exit_value = EXECUTION_FAILURE;
7118 err_unboundvar (name+1);
7119 free (name);
7120 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7121 }
7122 free (name);
7123
7124 *indexp = sindex;
7125 if (number < 0)
7126 return (&expand_wdesc_error);
7127 else
7128 {
7129 ret = alloc_word_desc ();
7130 ret->word = itos (number);
7131 return ret;
7132 }
7133 }
7134
7135 /* ${@} is identical to $@. */
7136 if (name[0] == '@' && name[1] == '\0')
7137 {
7138 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7139 *quoted_dollar_atp = 1;
7140
7141 if (contains_dollar_at)
7142 *contains_dollar_at = 1;
7143
7144 tflag |= W_DOLLARAT;
7145 }
7146
7147 /* Process ${!PREFIX*} expansion. */
7148 if (want_indir && string[sindex - 1] == RBRACE &&
7149 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
7150 legal_variable_starter ((unsigned char) name[1]))
7151 {
7152 char **x;
7153 WORD_LIST *xlist;
7154
7155 temp1 = savestring (name + 1);
7156 number = strlen (temp1);
7157 temp1[number - 1] = '\0';
7158 x = all_variables_matching_prefix (temp1);
7159 xlist = strvec_to_word_list (x, 0, 0);
7160 if (string[sindex - 2] == '*')
7161 temp = string_list_dollar_star (xlist);
7162 else
7163 {
7164 temp = string_list_dollar_at (xlist, quoted);
7165 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7166 *quoted_dollar_atp = 1;
7167 if (contains_dollar_at)
7168 *contains_dollar_at = 1;
7169
7170 tflag |= W_DOLLARAT;
7171 }
7172 free (x);
7173 dispose_words (xlist);
7174 free (temp1);
7175 *indexp = sindex;
7176
7177 free (name);
7178
7179 ret = alloc_word_desc ();
7180 ret->word = temp;
7181 ret->flags = tflag; /* XXX */
7182 return ret;
7183 }
7184
7185 #if defined (ARRAY_VARS)
7186 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
7187 if (want_indir && string[sindex - 1] == RBRACE &&
7188 string[sindex - 2] == ']' && valid_array_reference (name+1))
7189 {
7190 char *x, *x1;
7191
7192 temp1 = savestring (name + 1);
7193 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
7194 FREE (x);
7195 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
7196 {
7197 temp = array_keys (temp1, quoted); /* handles assoc vars too */
7198 if (x1[0] == '@')
7199 {
7200 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7201 *quoted_dollar_atp = 1;
7202 if (contains_dollar_at)
7203 *contains_dollar_at = 1;
7204
7205 tflag |= W_DOLLARAT;
7206 }
7207
7208 free (temp1);
7209 *indexp = sindex;
7210
7211 ret = alloc_word_desc ();
7212 ret->word = temp;
7213 ret->flags = tflag; /* XXX */
7214 return ret;
7215 }
7216
7217 free (temp1);
7218 }
7219 #endif /* ARRAY_VARS */
7220
7221 /* Make sure that NAME is valid before trying to go on. */
7222 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
7223 var_is_special) == 0)
7224 {
7225 temp = (char *)NULL;
7226 goto bad_substitution;
7227 }
7228
7229 if (want_indir)
7230 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
7231 else
7232 tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&PF_NOSPLIT2), &ind);
7233
7234 if (tdesc)
7235 {
7236 temp = tdesc->word;
7237 tflag = tdesc->flags;
7238 dispose_word_desc (tdesc);
7239 }
7240 else
7241 temp = (char *)0;
7242
7243 #if defined (ARRAY_VARS)
7244 if (valid_array_reference (name))
7245 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
7246 #endif
7247
7248 var_is_set = temp != (char *)0;
7249 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
7250
7251 /* Get the rest of the stuff inside the braces. */
7252 if (c && c != RBRACE)
7253 {
7254 /* Extract the contents of the ${ ... } expansion
7255 according to the Posix.2 rules. */
7256 value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
7257 if (string[sindex] == RBRACE)
7258 sindex++;
7259 else
7260 goto bad_substitution;
7261 }
7262 else
7263 value = (char *)NULL;
7264
7265 *indexp = sindex;
7266
7267 /* All the cases where an expansion can possibly generate an unbound
7268 variable error. */
7269 if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
7270 {
7271 if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
7272 {
7273 last_command_exit_value = EXECUTION_FAILURE;
7274 err_unboundvar (name);
7275 FREE (value);
7276 FREE (temp);
7277 free (name);
7278 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7279 }
7280 }
7281
7282 /* If this is a substring spec, process it and add the result. */
7283 if (want_substring)
7284 {
7285 temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7286 FREE (name);
7287 FREE (value);
7288 FREE (temp);
7289
7290 if (temp1 == &expand_param_error)
7291 return (&expand_wdesc_error);
7292 else if (temp1 == &expand_param_fatal)
7293 return (&expand_wdesc_fatal);
7294
7295 ret = alloc_word_desc ();
7296 ret->word = temp1;
7297 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7298 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7299 return ret;
7300 }
7301 else if (want_patsub)
7302 {
7303 temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7304 FREE (name);
7305 FREE (value);
7306 FREE (temp);
7307
7308 if (temp1 == &expand_param_error)
7309 return (&expand_wdesc_error);
7310 else if (temp1 == &expand_param_fatal)
7311 return (&expand_wdesc_fatal);
7312
7313 ret = alloc_word_desc ();
7314 ret->word = temp1;
7315 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7316 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7317 return ret;
7318 }
7319 #if defined (CASEMOD_EXPANSIONS)
7320 else if (want_casemod)
7321 {
7322 temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7323 FREE (name);
7324 FREE (value);
7325 FREE (temp);
7326
7327 if (temp1 == &expand_param_error)
7328 return (&expand_wdesc_error);
7329 else if (temp1 == &expand_param_fatal)
7330 return (&expand_wdesc_fatal);
7331
7332 ret = alloc_word_desc ();
7333 ret->word = temp1;
7334 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7335 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7336 return ret;
7337 }
7338 #endif
7339
7340 /* Do the right thing based on which character ended the variable name. */
7341 switch (c)
7342 {
7343 default:
7344 case '\0':
7345 bad_substitution:
7346 last_command_exit_value = EXECUTION_FAILURE;
7347 report_error (_("%s: bad substitution"), string ? string : "??");
7348 FREE (value);
7349 FREE (temp);
7350 free (name);
7351 return &expand_wdesc_error;
7352
7353 case RBRACE:
7354 break;
7355
7356 case '#': /* ${param#[#]pattern} */
7357 case '%': /* ${param%[%]pattern} */
7358 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
7359 {
7360 FREE (value);
7361 break;
7362 }
7363 temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7364 free (temp);
7365 free (value);
7366 free (name);
7367
7368 ret = alloc_word_desc ();
7369 ret->word = temp1;
7370 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7371 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7372 return ret;
7373
7374 case '-':
7375 case '=':
7376 case '?':
7377 case '+':
7378 if (var_is_set && var_is_null == 0)
7379 {
7380 /* If the operator is `+', we don't want the value of the named
7381 variable for anything, just the value of the right hand side. */
7382 if (c == '+')
7383 {
7384 /* XXX -- if we're double-quoted and the named variable is "$@",
7385 we want to turn off any special handling of "$@" --
7386 we're not using it, so whatever is on the rhs applies. */
7387 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7388 *quoted_dollar_atp = 0;
7389 if (contains_dollar_at)
7390 *contains_dollar_at = 0;
7391
7392 FREE (temp);
7393 if (value)
7394 {
7395 /* From Posix discussion on austin-group list. Issue 221
7396 requires that backslashes escaping `}' inside
7397 double-quoted ${...} be removed. */
7398 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7399 quoted |= Q_DOLBRACE;
7400 ret = parameter_brace_expand_rhs (name, value, c,
7401 quoted,
7402 quoted_dollar_atp,
7403 contains_dollar_at);
7404 /* XXX - fix up later, esp. noting presence of
7405 W_HASQUOTEDNULL in ret->flags */
7406 free (value);
7407 }
7408 else
7409 temp = (char *)NULL;
7410 }
7411 else
7412 {
7413 FREE (value);
7414 }
7415 /* Otherwise do nothing; just use the value in TEMP. */
7416 }
7417 else /* VAR not set or VAR is NULL. */
7418 {
7419 FREE (temp);
7420 temp = (char *)NULL;
7421 if (c == '=' && var_is_special)
7422 {
7423 last_command_exit_value = EXECUTION_FAILURE;
7424 report_error (_("$%s: cannot assign in this way"), name);
7425 free (name);
7426 free (value);
7427 return &expand_wdesc_error;
7428 }
7429 else if (c == '?')
7430 {
7431 parameter_brace_expand_error (name, value);
7432 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7433 }
7434 else if (c != '+')
7435 {
7436 /* XXX -- if we're double-quoted and the named variable is "$@",
7437 we want to turn off any special handling of "$@" --
7438 we're not using it, so whatever is on the rhs applies. */
7439 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7440 *quoted_dollar_atp = 0;
7441 if (contains_dollar_at)
7442 *contains_dollar_at = 0;
7443
7444 /* From Posix discussion on austin-group list. Issue 221 requires
7445 that backslashes escaping `}' inside double-quoted ${...} be
7446 removed. */
7447 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7448 quoted |= Q_DOLBRACE;
7449 ret = parameter_brace_expand_rhs (name, value, c, quoted,
7450 quoted_dollar_atp,
7451 contains_dollar_at);
7452 /* XXX - fix up later, esp. noting presence of
7453 W_HASQUOTEDNULL in tdesc->flags */
7454 }
7455 free (value);
7456 }
7457
7458 break;
7459 }
7460 free (name);
7461
7462 if (ret == 0)
7463 {
7464 ret = alloc_word_desc ();
7465 ret->flags = tflag;
7466 ret->word = temp;
7467 }
7468 return (ret);
7469 }
7470
7471 /* Expand a single ${xxx} expansion. The braces are optional. When
7472 the braces are used, parameter_brace_expand() does the work,
7473 possibly calling param_expand recursively. */
7474 static WORD_DESC *
7475 param_expand (string, sindex, quoted, expanded_something,
7476 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
7477 pflags)
7478 char *string;
7479 int *sindex, quoted, *expanded_something, *contains_dollar_at;
7480 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
7481 {
7482 char *temp, *temp1, uerror[3];
7483 int zindex, t_index, expok;
7484 unsigned char c;
7485 intmax_t number;
7486 SHELL_VAR *var;
7487 WORD_LIST *list;
7488 WORD_DESC *tdesc, *ret;
7489 int tflag;
7490
7491 zindex = *sindex;
7492 c = string[++zindex];
7493
7494 temp = (char *)NULL;
7495 ret = tdesc = (WORD_DESC *)NULL;
7496 tflag = 0;
7497
7498 /* Do simple cases first. Switch on what follows '$'. */
7499 switch (c)
7500 {
7501 /* $0 .. $9? */
7502 case '0':
7503 case '1':
7504 case '2':
7505 case '3':
7506 case '4':
7507 case '5':
7508 case '6':
7509 case '7':
7510 case '8':
7511 case '9':
7512 temp1 = dollar_vars[TODIGIT (c)];
7513 if (unbound_vars_is_error && temp1 == (char *)NULL)
7514 {
7515 uerror[0] = '$';
7516 uerror[1] = c;
7517 uerror[2] = '\0';
7518 last_command_exit_value = EXECUTION_FAILURE;
7519 err_unboundvar (uerror);
7520 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7521 }
7522 if (temp1)
7523 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7524 ? quote_string (temp1)
7525 : quote_escapes (temp1);
7526 else
7527 temp = (char *)NULL;
7528
7529 break;
7530
7531 /* $$ -- pid of the invoking shell. */
7532 case '$':
7533 temp = itos (dollar_dollar_pid);
7534 break;
7535
7536 /* $# -- number of positional parameters. */
7537 case '#':
7538 temp = itos (number_of_args ());
7539 break;
7540
7541 /* $? -- return value of the last synchronous command. */
7542 case '?':
7543 temp = itos (last_command_exit_value);
7544 break;
7545
7546 /* $- -- flags supplied to the shell on invocation or by `set'. */
7547 case '-':
7548 temp = which_set_flags ();
7549 break;
7550
7551 /* $! -- Pid of the last asynchronous command. */
7552 case '!':
7553 /* If no asynchronous pids have been created, expand to nothing.
7554 If `set -u' has been executed, and no async processes have
7555 been created, this is an expansion error. */
7556 if (last_asynchronous_pid == NO_PID)
7557 {
7558 if (expanded_something)
7559 *expanded_something = 0;
7560 temp = (char *)NULL;
7561 if (unbound_vars_is_error)
7562 {
7563 uerror[0] = '$';
7564 uerror[1] = c;
7565 uerror[2] = '\0';
7566 last_command_exit_value = EXECUTION_FAILURE;
7567 err_unboundvar (uerror);
7568 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7569 }
7570 }
7571 else
7572 temp = itos (last_asynchronous_pid);
7573 break;
7574
7575 /* The only difference between this and $@ is when the arg is quoted. */
7576 case '*': /* `$*' */
7577 list = list_rest_of_args ();
7578
7579 #if 0
7580 /* According to austin-group posix proposal by Geoff Clare in
7581 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7582
7583 "The shell shall write a message to standard error and
7584 immediately exit when it tries to expand an unset parameter
7585 other than the '@' and '*' special parameters."
7586 */
7587
7588 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7589 {
7590 uerror[0] = '$';
7591 uerror[1] = '*';
7592 uerror[2] = '\0';
7593 last_command_exit_value = EXECUTION_FAILURE;
7594 err_unboundvar (uerror);
7595 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7596 }
7597 #endif
7598
7599 /* If there are no command-line arguments, this should just
7600 disappear if there are other characters in the expansion,
7601 even if it's quoted. */
7602 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7603 temp = (char *)NULL;
7604 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
7605 {
7606 /* If we have "$*" we want to make a string of the positional
7607 parameters, separated by the first character of $IFS, and
7608 quote the whole string, including the separators. If IFS
7609 is unset, the parameters are separated by ' '; if $IFS is
7610 null, the parameters are concatenated. */
7611 temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
7612 if (temp)
7613 {
7614 temp1 = quote_string (temp);
7615 if (*temp == 0)
7616 tflag |= W_HASQUOTEDNULL;
7617 free (temp);
7618 temp = temp1;
7619 }
7620 }
7621 else
7622 {
7623 /* We check whether or not we're eventually going to split $* here,
7624 for example when IFS is empty and we are processing the rhs of
7625 an assignment statement. In that case, we don't separate the
7626 arguments at all. Otherwise, if the $* is not quoted it is
7627 identical to $@ */
7628 #if 1
7629 # if defined (HANDLE_MULTIBYTE)
7630 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7631 # else
7632 if (expand_no_split_dollar_star && ifs_firstc == 0)
7633 # endif
7634 temp = string_list_dollar_star (list);
7635 else
7636 temp = string_list_dollar_at (list, quoted);
7637 #else
7638 temp = string_list_dollar_at (list, quoted);
7639 #endif
7640 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7641 *contains_dollar_at = 1;
7642 }
7643
7644 dispose_words (list);
7645 break;
7646
7647 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7648 means that we have to turn quoting off after we split into
7649 the individually quoted arguments so that the final split
7650 on the first character of $IFS is still done. */
7651 case '@': /* `$@' */
7652 list = list_rest_of_args ();
7653
7654 #if 0
7655 /* According to austin-group posix proposal by Geoff Clare in
7656 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7657
7658 "The shell shall write a message to standard error and
7659 immediately exit when it tries to expand an unset parameter
7660 other than the '@' and '*' special parameters."
7661 */
7662
7663 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7664 {
7665 uerror[0] = '$';
7666 uerror[1] = '@';
7667 uerror[2] = '\0';
7668 last_command_exit_value = EXECUTION_FAILURE;
7669 err_unboundvar (uerror);
7670 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7671 }
7672 #endif
7673
7674 /* We want to flag the fact that we saw this. We can't turn
7675 off quoting entirely, because other characters in the
7676 string might need it (consider "\"$@\""), but we need some
7677 way to signal that the final split on the first character
7678 of $IFS should be done, even though QUOTED is 1. */
7679 /* XXX - should this test include Q_PATQUOTE? */
7680 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7681 *quoted_dollar_at_p = 1;
7682 if (contains_dollar_at)
7683 *contains_dollar_at = 1;
7684
7685 /* We want to separate the positional parameters with the first
7686 character of $IFS in case $IFS is something other than a space.
7687 We also want to make sure that splitting is done no matter what --
7688 according to POSIX.2, this expands to a list of the positional
7689 parameters no matter what IFS is set to. */
7690 temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted);
7691
7692 tflag |= W_DOLLARAT;
7693 dispose_words (list);
7694 break;
7695
7696 case LBRACE:
7697 tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
7698 quoted_dollar_at_p,
7699 contains_dollar_at);
7700
7701 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7702 return (tdesc);
7703 temp = tdesc ? tdesc->word : (char *)0;
7704
7705 /* XXX */
7706 /* Quoted nulls should be removed if there is anything else
7707 in the string. */
7708 /* Note that we saw the quoted null so we can add one back at
7709 the end of this function if there are no other characters
7710 in the string, discard TEMP, and go on. The exception to
7711 this is when we have "${@}" and $1 is '', since $@ needs
7712 special handling. */
7713 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7714 {
7715 if (had_quoted_null_p)
7716 *had_quoted_null_p = 1;
7717 if (*quoted_dollar_at_p == 0)
7718 {
7719 free (temp);
7720 tdesc->word = temp = (char *)NULL;
7721 }
7722
7723 }
7724
7725 ret = tdesc;
7726 goto return0;
7727
7728 /* Do command or arithmetic substitution. */
7729 case LPAREN:
7730 /* We have to extract the contents of this paren substitution. */
7731 t_index = zindex + 1;
7732 temp = extract_command_subst (string, &t_index, 0);
7733 zindex = t_index;
7734
7735 /* For Posix.2-style `$(( ))' arithmetic substitution,
7736 extract the expression and pass it to the evaluator. */
7737 if (temp && *temp == LPAREN)
7738 {
7739 char *temp2;
7740 temp1 = temp + 1;
7741 temp2 = savestring (temp1);
7742 t_index = strlen (temp2) - 1;
7743
7744 if (temp2[t_index] != RPAREN)
7745 {
7746 free (temp2);
7747 goto comsub;
7748 }
7749
7750 /* Cut off ending `)' */
7751 temp2[t_index] = '\0';
7752
7753 if (chk_arithsub (temp2, t_index) == 0)
7754 {
7755 free (temp2);
7756 #if 0
7757 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
7758 #endif
7759 goto comsub;
7760 }
7761
7762 /* Expand variables found inside the expression. */
7763 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7764 free (temp2);
7765
7766 arithsub:
7767 /* No error messages. */
7768 this_command_name = (char *)NULL;
7769 number = evalexp (temp1, &expok);
7770 free (temp);
7771 free (temp1);
7772 if (expok == 0)
7773 {
7774 if (interactive_shell == 0 && posixly_correct)
7775 {
7776 last_command_exit_value = EXECUTION_FAILURE;
7777 return (&expand_wdesc_fatal);
7778 }
7779 else
7780 return (&expand_wdesc_error);
7781 }
7782 temp = itos (number);
7783 break;
7784 }
7785
7786 comsub:
7787 if (pflags & PF_NOCOMSUB)
7788 /* we need zindex+1 because string[zindex] == RPAREN */
7789 temp1 = substring (string, *sindex, zindex+1);
7790 else
7791 {
7792 tdesc = command_substitute (temp, quoted);
7793 temp1 = tdesc ? tdesc->word : (char *)NULL;
7794 if (tdesc)
7795 dispose_word_desc (tdesc);
7796 }
7797 FREE (temp);
7798 temp = temp1;
7799 break;
7800
7801 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7802 away in a future bash release. */
7803 case '[':
7804 /* Extract the contents of this arithmetic substitution. */
7805 t_index = zindex + 1;
7806 temp = extract_arithmetic_subst (string, &t_index);
7807 zindex = t_index;
7808 if (temp == 0)
7809 {
7810 temp = savestring (string);
7811 if (expanded_something)
7812 *expanded_something = 0;
7813 goto return0;
7814 }
7815
7816 /* Do initial variable expansion. */
7817 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7818
7819 goto arithsub;
7820
7821 default:
7822 /* Find the variable in VARIABLE_LIST. */
7823 temp = (char *)NULL;
7824
7825 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7826 ;
7827 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7828
7829 /* If this isn't a variable name, then just output the `$'. */
7830 if (temp1 == 0 || *temp1 == '\0')
7831 {
7832 FREE (temp1);
7833 temp = (char *)xmalloc (2);
7834 temp[0] = '$';
7835 temp[1] = '\0';
7836 if (expanded_something)
7837 *expanded_something = 0;
7838 goto return0;
7839 }
7840
7841 /* If the variable exists, return its value cell. */
7842 var = find_variable (temp1);
7843
7844 if (var && invisible_p (var) == 0 && var_isset (var))
7845 {
7846 #if defined (ARRAY_VARS)
7847 if (assoc_p (var) || array_p (var))
7848 {
7849 temp = array_p (var) ? array_reference (array_cell (var), 0)
7850 : assoc_reference (assoc_cell (var), "0");
7851 if (temp)
7852 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7853 ? quote_string (temp)
7854 : quote_escapes (temp);
7855 else if (unbound_vars_is_error)
7856 goto unbound_variable;
7857 }
7858 else
7859 #endif
7860 {
7861 temp = value_cell (var);
7862
7863 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7864 ? quote_string (temp)
7865 : quote_escapes (temp);
7866 }
7867
7868 free (temp1);
7869
7870 goto return0;
7871 }
7872 #if defined (ARRAY_VARS)
7873 else if (var = find_variable_last_nameref (temp1))
7874 {
7875 temp = nameref_cell (var);
7876 if (temp && *temp && valid_array_reference (temp))
7877 {
7878 tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL);
7879 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7880 return (tdesc);
7881 ret = tdesc;
7882 goto return0;
7883 }
7884 else
7885 temp = (char *)NULL;
7886 }
7887 #endif
7888
7889 temp = (char *)NULL;
7890
7891 unbound_variable:
7892 if (unbound_vars_is_error)
7893 {
7894 last_command_exit_value = EXECUTION_FAILURE;
7895 err_unboundvar (temp1);
7896 }
7897 else
7898 {
7899 free (temp1);
7900 goto return0;
7901 }
7902
7903 free (temp1);
7904 last_command_exit_value = EXECUTION_FAILURE;
7905 return ((unbound_vars_is_error && interactive_shell == 0)
7906 ? &expand_wdesc_fatal
7907 : &expand_wdesc_error);
7908 }
7909
7910 if (string[zindex])
7911 zindex++;
7912
7913 return0:
7914 *sindex = zindex;
7915
7916 if (ret == 0)
7917 {
7918 ret = alloc_word_desc ();
7919 ret->flags = tflag; /* XXX */
7920 ret->word = temp;
7921 }
7922 return ret;
7923 }
7924
7925 /* Make a word list which is the result of parameter and variable
7926 expansion, command substitution, arithmetic substitution, and
7927 quote removal of WORD. Return a pointer to a WORD_LIST which is
7928 the result of the expansion. If WORD contains a null word, the
7929 word list returned is also null.
7930
7931 QUOTED contains flag values defined in shell.h.
7932
7933 ISEXP is used to tell expand_word_internal that the word should be
7934 treated as the result of an expansion. This has implications for
7935 how IFS characters in the word are treated.
7936
7937 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7938 they point to an integer value which receives information about expansion.
7939 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7940 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7941 else zero.
7942
7943 This only does word splitting in the case of $@ expansion. In that
7944 case, we split on ' '. */
7945
7946 /* Values for the local variable quoted_state. */
7947 #define UNQUOTED 0
7948 #define PARTIALLY_QUOTED 1
7949 #define WHOLLY_QUOTED 2
7950
7951 static WORD_LIST *
7952 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7953 WORD_DESC *word;
7954 int quoted, isexp;
7955 int *contains_dollar_at;
7956 int *expanded_something;
7957 {
7958 WORD_LIST *list;
7959 WORD_DESC *tword;
7960
7961 /* The intermediate string that we build while expanding. */
7962 char *istring;
7963
7964 /* The current size of the above object. */
7965 int istring_size;
7966
7967 /* Index into ISTRING. */
7968 int istring_index;
7969
7970 /* Temporary string storage. */
7971 char *temp, *temp1;
7972
7973 /* The text of WORD. */
7974 register char *string;
7975
7976 /* The size of STRING. */
7977 size_t string_size;
7978
7979 /* The index into STRING. */
7980 int sindex;
7981
7982 /* This gets 1 if we see a $@ while quoted. */
7983 int quoted_dollar_at;
7984
7985 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7986 whether WORD contains no quoting characters, a partially quoted
7987 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7988 int quoted_state;
7989
7990 /* State flags */
7991 int had_quoted_null;
7992 int has_dollar_at, temp_has_dollar_at;
7993 int tflag;
7994 int pflags; /* flags passed to param_expand */
7995
7996 int assignoff; /* If assignment, offset of `=' */
7997
7998 register unsigned char c; /* Current character. */
7999 int t_index; /* For calls to string_extract_xxx. */
8000
8001 char twochars[2];
8002
8003 DECLARE_MBSTATE;
8004
8005 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
8006 istring[istring_index = 0] = '\0';
8007 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
8008 quoted_state = UNQUOTED;
8009
8010 string = word->word;
8011 if (string == 0)
8012 goto finished_with_string;
8013 /* Don't need the string length for the SADD... and COPY_ macros unless
8014 multibyte characters are possible. */
8015 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
8016
8017 if (contains_dollar_at)
8018 *contains_dollar_at = 0;
8019
8020 assignoff = -1;
8021
8022 /* Begin the expansion. */
8023
8024 for (sindex = 0; ;)
8025 {
8026 c = string[sindex];
8027
8028 /* Case on toplevel character. */
8029 switch (c)
8030 {
8031 case '\0':
8032 goto finished_with_string;
8033
8034 case CTLESC:
8035 sindex++;
8036 #if HANDLE_MULTIBYTE
8037 if (MB_CUR_MAX > 1 && string[sindex])
8038 {
8039 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
8040 }
8041 else
8042 #endif
8043 {
8044 temp = (char *)xmalloc (3);
8045 temp[0] = CTLESC;
8046 temp[1] = c = string[sindex];
8047 temp[2] = '\0';
8048 }
8049
8050 dollar_add_string:
8051 if (string[sindex])
8052 sindex++;
8053
8054 add_string:
8055 if (temp)
8056 {
8057 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
8058 temp = (char *)0;
8059 }
8060
8061 break;
8062
8063 #if defined (PROCESS_SUBSTITUTION)
8064 /* Process substitution. */
8065 case '<':
8066 case '>':
8067 {
8068 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
8069 {
8070 sindex--; /* add_character: label increments sindex */
8071 goto add_character;
8072 }
8073 else
8074 t_index = sindex + 1; /* skip past both '<' and LPAREN */
8075
8076 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
8077 sindex = t_index;
8078
8079 /* If the process substitution specification is `<()', we want to
8080 open the pipe for writing in the child and produce output; if
8081 it is `>()', we want to open the pipe for reading in the child
8082 and consume input. */
8083 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
8084
8085 FREE (temp1);
8086
8087 goto dollar_add_string;
8088 }
8089 #endif /* PROCESS_SUBSTITUTION */
8090
8091 case '=':
8092 /* Posix.2 section 3.6.1 says that tildes following `=' in words
8093 which are not assignment statements are not expanded. If the
8094 shell isn't in posix mode, though, we perform tilde expansion
8095 on `likely candidate' unquoted assignment statements (flags
8096 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
8097 contains an unquoted :~ or =~. Something to think about: we
8098 now have a flag that says to perform tilde expansion on arguments
8099 to `assignment builtins' like declare and export that look like
8100 assignment statements. We now do tilde expansion on such words
8101 even in POSIX mode. */
8102 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
8103 {
8104 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8105 goto add_ifs_character;
8106 else
8107 goto add_character;
8108 }
8109 /* If we're not in posix mode or forcing assignment-statement tilde
8110 expansion, note where the `=' appears in the word and prepare to
8111 do tilde expansion following the first `='. */
8112 if ((word->flags & W_ASSIGNMENT) &&
8113 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8114 assignoff == -1 && sindex > 0)
8115 assignoff = sindex;
8116 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
8117 word->flags |= W_ITILDE;
8118 #if 0
8119 else if ((word->flags & W_ASSIGNMENT) &&
8120 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8121 string[sindex+1] == '~')
8122 word->flags |= W_ITILDE;
8123 #endif
8124 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8125 goto add_ifs_character;
8126 else
8127 goto add_character;
8128
8129 case ':':
8130 if (word->flags & W_NOTILDE)
8131 {
8132 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8133 goto add_ifs_character;
8134 else
8135 goto add_character;
8136 }
8137
8138 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
8139 string[sindex+1] == '~')
8140 word->flags |= W_ITILDE;
8141
8142 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8143 goto add_ifs_character;
8144 else
8145 goto add_character;
8146
8147 case '~':
8148 /* If the word isn't supposed to be tilde expanded, or we're not
8149 at the start of a word or after an unquoted : or = in an
8150 assignment statement, we don't do tilde expansion. */
8151 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
8152 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
8153 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8154 {
8155 word->flags &= ~W_ITILDE;
8156 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
8157 goto add_ifs_character;
8158 else
8159 goto add_character;
8160 }
8161
8162 if (word->flags & W_ASSIGNRHS)
8163 tflag = 2;
8164 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
8165 tflag = 1;
8166 else
8167 tflag = 0;
8168
8169 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
8170
8171 word->flags &= ~W_ITILDE;
8172
8173 if (temp && *temp && t_index > 0)
8174 {
8175 temp1 = bash_tilde_expand (temp, tflag);
8176 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
8177 {
8178 FREE (temp);
8179 FREE (temp1);
8180 goto add_character; /* tilde expansion failed */
8181 }
8182 free (temp);
8183 temp = temp1;
8184 sindex += t_index;
8185 goto add_quoted_string; /* XXX was add_string */
8186 }
8187 else
8188 {
8189 FREE (temp);
8190 goto add_character;
8191 }
8192
8193 case '$':
8194 if (expanded_something)
8195 *expanded_something = 1;
8196
8197 temp_has_dollar_at = 0;
8198 pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
8199 if (word->flags & W_NOSPLIT2)
8200 pflags |= PF_NOSPLIT2;
8201 if (word->flags & W_ASSIGNRHS)
8202 pflags |= PF_ASSIGNRHS;
8203 tword = param_expand (string, &sindex, quoted, expanded_something,
8204 &temp_has_dollar_at, &quoted_dollar_at,
8205 &had_quoted_null, pflags);
8206 has_dollar_at += temp_has_dollar_at;
8207
8208 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
8209 {
8210 free (string);
8211 free (istring);
8212 return ((tword == &expand_wdesc_error) ? &expand_word_error
8213 : &expand_word_fatal);
8214 }
8215 if (contains_dollar_at && has_dollar_at)
8216 *contains_dollar_at = 1;
8217
8218 if (tword && (tword->flags & W_HASQUOTEDNULL))
8219 had_quoted_null = 1;
8220
8221 temp = tword ? tword->word : (char *)NULL;
8222 dispose_word_desc (tword);
8223
8224 /* Kill quoted nulls; we will add them back at the end of
8225 expand_word_internal if nothing else in the string */
8226 if (had_quoted_null && temp && QUOTED_NULL (temp))
8227 {
8228 FREE (temp);
8229 temp = (char *)NULL;
8230 }
8231
8232 goto add_string;
8233 break;
8234
8235 case '`': /* Backquoted command substitution. */
8236 {
8237 t_index = sindex++;
8238
8239 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
8240 /* The test of sindex against t_index is to allow bare instances of
8241 ` to pass through, for backwards compatibility. */
8242 if (temp == &extract_string_error || temp == &extract_string_fatal)
8243 {
8244 if (sindex - 1 == t_index)
8245 {
8246 sindex = t_index;
8247 goto add_character;
8248 }
8249 last_command_exit_value = EXECUTION_FAILURE;
8250 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
8251 free (string);
8252 free (istring);
8253 return ((temp == &extract_string_error) ? &expand_word_error
8254 : &expand_word_fatal);
8255 }
8256
8257 if (expanded_something)
8258 *expanded_something = 1;
8259
8260 if (word->flags & W_NOCOMSUB)
8261 /* sindex + 1 because string[sindex] == '`' */
8262 temp1 = substring (string, t_index, sindex + 1);
8263 else
8264 {
8265 de_backslash (temp);
8266 tword = command_substitute (temp, quoted);
8267 temp1 = tword ? tword->word : (char *)NULL;
8268 if (tword)
8269 dispose_word_desc (tword);
8270 }
8271 FREE (temp);
8272 temp = temp1;
8273 goto dollar_add_string;
8274 }
8275
8276 case '\\':
8277 if (string[sindex + 1] == '\n')
8278 {
8279 sindex += 2;
8280 continue;
8281 }
8282
8283 c = string[++sindex];
8284
8285 if (quoted & Q_HERE_DOCUMENT)
8286 tflag = CBSHDOC;
8287 else if (quoted & Q_DOUBLE_QUOTES)
8288 tflag = CBSDQUOTE;
8289 else
8290 tflag = 0;
8291
8292 /* From Posix discussion on austin-group list: Backslash escaping
8293 a } in ${...} is removed. Issue 0000221 */
8294 if ((quoted & Q_DOLBRACE) && c == RBRACE)
8295 {
8296 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8297 }
8298 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
8299 {
8300 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
8301 }
8302 else if (c == 0)
8303 {
8304 c = CTLNUL;
8305 sindex--; /* add_character: label increments sindex */
8306 goto add_character;
8307 }
8308 else
8309 {
8310 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8311 }
8312
8313 sindex++;
8314 add_twochars:
8315 /* BEFORE jumping here, we need to increment sindex if appropriate */
8316 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
8317 DEFAULT_ARRAY_SIZE);
8318 istring[istring_index++] = twochars[0];
8319 istring[istring_index++] = twochars[1];
8320 istring[istring_index] = '\0';
8321
8322 break;
8323
8324 case '"':
8325 #if 0
8326 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8327 #else
8328 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8329 #endif
8330 goto add_character;
8331
8332 t_index = ++sindex;
8333 temp = string_extract_double_quoted (string, &sindex, 0);
8334
8335 /* If the quotes surrounded the entire string, then the
8336 whole word was quoted. */
8337 quoted_state = (t_index == 1 && string[sindex] == '\0')
8338 ? WHOLLY_QUOTED
8339 : PARTIALLY_QUOTED;
8340
8341 if (temp && *temp)
8342 {
8343 tword = alloc_word_desc ();
8344 tword->word = temp;
8345
8346 temp = (char *)NULL;
8347
8348 temp_has_dollar_at = 0; /* XXX */
8349 /* Need to get W_HASQUOTEDNULL flag through this function. */
8350 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &temp_has_dollar_at, (int *)NULL);
8351 has_dollar_at += temp_has_dollar_at;
8352
8353 if (list == &expand_word_error || list == &expand_word_fatal)
8354 {
8355 free (istring);
8356 free (string);
8357 /* expand_word_internal has already freed temp_word->word
8358 for us because of the way it prints error messages. */
8359 tword->word = (char *)NULL;
8360 dispose_word (tword);
8361 return list;
8362 }
8363
8364 dispose_word (tword);
8365
8366 /* "$@" (a double-quoted dollar-at) expands into nothing,
8367 not even a NULL word, when there are no positional
8368 parameters. */
8369 if (list == 0 && has_dollar_at)
8370 {
8371 quoted_dollar_at++;
8372 break;
8373 }
8374
8375 /* If we get "$@", we know we have expanded something, so we
8376 need to remember it for the final split on $IFS. This is
8377 a special case; it's the only case where a quoted string
8378 can expand into more than one word. It's going to come back
8379 from the above call to expand_word_internal as a list with
8380 a single word, in which all characters are quoted and
8381 separated by blanks. What we want to do is to turn it back
8382 into a list for the next piece of code. */
8383 if (list)
8384 dequote_list (list);
8385
8386 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
8387 had_quoted_null = 1; /* XXX */
8388
8389 if (has_dollar_at)
8390 {
8391 quoted_dollar_at++;
8392 if (contains_dollar_at)
8393 *contains_dollar_at = 1;
8394 if (expanded_something)
8395 *expanded_something = 1;
8396 }
8397 }
8398 else
8399 {
8400 /* What we have is "". This is a minor optimization. */
8401 FREE (temp);
8402 list = (WORD_LIST *)NULL;
8403 }
8404
8405 /* The code above *might* return a list (consider the case of "$@",
8406 where it returns "$1", "$2", etc.). We can't throw away the
8407 rest of the list, and we have to make sure each word gets added
8408 as quoted. We test on tresult->next: if it is non-NULL, we
8409 quote the whole list, save it to a string with string_list, and
8410 add that string. We don't need to quote the results of this
8411 (and it would be wrong, since that would quote the separators
8412 as well), so we go directly to add_string. */
8413 if (list)
8414 {
8415 if (list->next)
8416 {
8417 #if 0
8418 if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
8419 temp = string_list_internal (quote_list (list), " ");
8420 else
8421 #endif
8422 /* Testing quoted_dollar_at makes sure that "$@" is
8423 split correctly when $IFS does not contain a space. */
8424 temp = quoted_dollar_at
8425 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
8426 : string_list (quote_list (list));
8427 dispose_words (list);
8428 goto add_string;
8429 }
8430 else
8431 {
8432 temp = savestring (list->word->word);
8433 tflag = list->word->flags;
8434 dispose_words (list);
8435
8436 /* If the string is not a quoted null string, we want
8437 to remove any embedded unquoted CTLNUL characters.
8438 We do not want to turn quoted null strings back into
8439 the empty string, though. We do this because we
8440 want to remove any quoted nulls from expansions that
8441 contain other characters. For example, if we have
8442 x"$*"y or "x$*y" and there are no positional parameters,
8443 the $* should expand into nothing. */
8444 /* We use the W_HASQUOTEDNULL flag to differentiate the
8445 cases: a quoted null character as above and when
8446 CTLNUL is contained in the (non-null) expansion
8447 of some variable. We use the had_quoted_null flag to
8448 pass the value through this function to its caller. */
8449 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
8450 remove_quoted_nulls (temp); /* XXX */
8451 }
8452 }
8453 else
8454 temp = (char *)NULL;
8455
8456 /* We do not want to add quoted nulls to strings that are only
8457 partially quoted; we can throw them away. The exception to
8458 this is when we are going to be performing word splitting,
8459 since we have to preserve a null argument if the next character
8460 will cause word splitting. */
8461 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
8462 continue;
8463
8464 add_quoted_string:
8465
8466 if (temp)
8467 {
8468 temp1 = temp;
8469 temp = quote_string (temp);
8470 free (temp1);
8471 goto add_string;
8472 }
8473 else
8474 {
8475 /* Add NULL arg. */
8476 c = CTLNUL;
8477 sindex--; /* add_character: label increments sindex */
8478 goto add_character;
8479 }
8480
8481 /* break; */
8482
8483 case '\'':
8484 #if 0
8485 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8486 #else
8487 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8488 #endif
8489 goto add_character;
8490
8491 t_index = ++sindex;
8492 temp = string_extract_single_quoted (string, &sindex);
8493
8494 /* If the entire STRING was surrounded by single quotes,
8495 then the string is wholly quoted. */
8496 quoted_state = (t_index == 1 && string[sindex] == '\0')
8497 ? WHOLLY_QUOTED
8498 : PARTIALLY_QUOTED;
8499
8500 /* If all we had was '', it is a null expansion. */
8501 if (*temp == '\0')
8502 {
8503 free (temp);
8504 temp = (char *)NULL;
8505 }
8506 else
8507 remove_quoted_escapes (temp); /* ??? */
8508
8509 /* We do not want to add quoted nulls to strings that are only
8510 partially quoted; such nulls are discarded. */
8511 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
8512 continue;
8513
8514 /* If we have a quoted null expansion, add a quoted NULL to istring. */
8515 if (temp == 0)
8516 {
8517 c = CTLNUL;
8518 sindex--; /* add_character: label increments sindex */
8519 goto add_character;
8520 }
8521 else
8522 goto add_quoted_string;
8523
8524 /* break; */
8525
8526 default:
8527 /* This is the fix for " $@ " */
8528 add_ifs_character:
8529 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
8530 {
8531 if (string[sindex]) /* from old goto dollar_add_string */
8532 sindex++;
8533 if (c == 0)
8534 {
8535 c = CTLNUL;
8536 goto add_character;
8537 }
8538 else
8539 {
8540 #if HANDLE_MULTIBYTE
8541 if (MB_CUR_MAX > 1)
8542 sindex--;
8543
8544 if (MB_CUR_MAX > 1)
8545 {
8546 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
8547 }
8548 else
8549 #endif
8550 {
8551 twochars[0] = CTLESC;
8552 twochars[1] = c;
8553 goto add_twochars;
8554 }
8555 }
8556 }
8557
8558 SADD_MBCHAR (temp, string, sindex, string_size);
8559
8560 add_character:
8561 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
8562 DEFAULT_ARRAY_SIZE);
8563 istring[istring_index++] = c;
8564 istring[istring_index] = '\0';
8565
8566 /* Next character. */
8567 sindex++;
8568 }
8569 }
8570
8571 finished_with_string:
8572 /* OK, we're ready to return. If we have a quoted string, and
8573 quoted_dollar_at is not set, we do no splitting at all; otherwise
8574 we split on ' '. The routines that call this will handle what to
8575 do if nothing has been expanded. */
8576
8577 /* Partially and wholly quoted strings which expand to the empty
8578 string are retained as an empty arguments. Unquoted strings
8579 which expand to the empty string are discarded. The single
8580 exception is the case of expanding "$@" when there are no
8581 positional parameters. In that case, we discard the expansion. */
8582
8583 /* Because of how the code that handles "" and '' in partially
8584 quoted strings works, we need to make ISTRING into a QUOTED_NULL
8585 if we saw quoting characters, but the expansion was empty.
8586 "" and '' are tossed away before we get to this point when
8587 processing partially quoted strings. This makes "" and $xxx""
8588 equivalent when xxx is unset. We also look to see whether we
8589 saw a quoted null from a ${} expansion and add one back if we
8590 need to. */
8591
8592 /* If we expand to nothing and there were no single or double quotes
8593 in the word, we throw it away. Otherwise, we return a NULL word.
8594 The single exception is for $@ surrounded by double quotes when
8595 there are no positional parameters. In that case, we also throw
8596 the word away. */
8597
8598 if (*istring == '\0')
8599 {
8600 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
8601 {
8602 istring[0] = CTLNUL;
8603 istring[1] = '\0';
8604 tword = make_bare_word (istring);
8605 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8606 list = make_word_list (tword, (WORD_LIST *)NULL);
8607 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8608 tword->flags |= W_QUOTED;
8609 }
8610 /* According to sh, ksh, and Posix.2, if a word expands into nothing
8611 and a double-quoted "$@" appears anywhere in it, then the entire
8612 word is removed. */
8613 else if (quoted_state == UNQUOTED || quoted_dollar_at)
8614 list = (WORD_LIST *)NULL;
8615 #if 0
8616 else
8617 {
8618 tword = make_bare_word (istring);
8619 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8620 tword->flags |= W_QUOTED;
8621 list = make_word_list (tword, (WORD_LIST *)NULL);
8622 }
8623 #else
8624 else
8625 list = (WORD_LIST *)NULL;
8626 #endif
8627 }
8628 else if (word->flags & W_NOSPLIT)
8629 {
8630 tword = make_bare_word (istring);
8631 if (word->flags & W_ASSIGNMENT)
8632 tword->flags |= W_ASSIGNMENT; /* XXX */
8633 if (word->flags & W_COMPASSIGN)
8634 tword->flags |= W_COMPASSIGN; /* XXX */
8635 if (word->flags & W_NOGLOB)
8636 tword->flags |= W_NOGLOB; /* XXX */
8637 if (word->flags & W_NOBRACE)
8638 tword->flags |= W_NOBRACE; /* XXX */
8639 if (word->flags & W_NOEXPAND)
8640 tword->flags |= W_NOEXPAND; /* XXX */
8641 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8642 tword->flags |= W_QUOTED;
8643 if (had_quoted_null && QUOTED_NULL (istring))
8644 tword->flags |= W_HASQUOTEDNULL;
8645 list = make_word_list (tword, (WORD_LIST *)NULL);
8646 }
8647 else
8648 {
8649 char *ifs_chars;
8650
8651 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
8652
8653 /* If we have $@, we need to split the results no matter what. If
8654 IFS is unset or NULL, string_list_dollar_at has separated the
8655 positional parameters with a space, so we split on space (we have
8656 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
8657 string_list_dollar_at has separated the positional parameters
8658 with the first character of $IFS, so we split on $IFS. */
8659 if (has_dollar_at && ifs_chars)
8660 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
8661 else
8662 {
8663 tword = make_bare_word (istring);
8664 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8665 tword->flags |= W_QUOTED;
8666 if (word->flags & W_ASSIGNMENT)
8667 tword->flags |= W_ASSIGNMENT;
8668 if (word->flags & W_COMPASSIGN)
8669 tword->flags |= W_COMPASSIGN;
8670 if (word->flags & W_NOGLOB)
8671 tword->flags |= W_NOGLOB;
8672 if (word->flags & W_NOBRACE)
8673 tword->flags |= W_NOBRACE;
8674 if (word->flags & W_NOEXPAND)
8675 tword->flags |= W_NOEXPAND;
8676 if (had_quoted_null && QUOTED_NULL (istring))
8677 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8678 list = make_word_list (tword, (WORD_LIST *)NULL);
8679 }
8680 }
8681
8682 free (istring);
8683 return (list);
8684 }
8685
8686 /* **************************************************************** */
8687 /* */
8688 /* Functions for Quote Removal */
8689 /* */
8690 /* **************************************************************** */
8691
8692 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
8693 backslash quoting rules for within double quotes or a here document. */
8694 char *
8695 string_quote_removal (string, quoted)
8696 char *string;
8697 int quoted;
8698 {
8699 size_t slen;
8700 char *r, *result_string, *temp, *send;
8701 int sindex, tindex, dquote;
8702 unsigned char c;
8703 DECLARE_MBSTATE;
8704
8705 /* The result can be no longer than the original string. */
8706 slen = strlen (string);
8707 send = string + slen;
8708
8709 r = result_string = (char *)xmalloc (slen + 1);
8710
8711 for (dquote = sindex = 0; c = string[sindex];)
8712 {
8713 switch (c)
8714 {
8715 case '\\':
8716 c = string[++sindex];
8717 if (c == 0)
8718 {
8719 *r++ = '\\';
8720 break;
8721 }
8722 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8723 *r++ = '\\';
8724 /* FALLTHROUGH */
8725
8726 default:
8727 SCOPY_CHAR_M (r, string, send, sindex);
8728 break;
8729
8730 case '\'':
8731 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8732 {
8733 *r++ = c;
8734 sindex++;
8735 break;
8736 }
8737 tindex = sindex + 1;
8738 temp = string_extract_single_quoted (string, &tindex);
8739 if (temp)
8740 {
8741 strcpy (r, temp);
8742 r += strlen (r);
8743 free (temp);
8744 }
8745 sindex = tindex;
8746 break;
8747
8748 case '"':
8749 dquote = 1 - dquote;
8750 sindex++;
8751 break;
8752 }
8753 }
8754 *r = '\0';
8755 return (result_string);
8756 }
8757
8758 #if 0
8759 /* UNUSED */
8760 /* Perform quote removal on word WORD. This allocates and returns a new
8761 WORD_DESC *. */
8762 WORD_DESC *
8763 word_quote_removal (word, quoted)
8764 WORD_DESC *word;
8765 int quoted;
8766 {
8767 WORD_DESC *w;
8768 char *t;
8769
8770 t = string_quote_removal (word->word, quoted);
8771 w = alloc_word_desc ();
8772 w->word = t ? t : savestring ("");
8773 return (w);
8774 }
8775
8776 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8777 the members of the list are treated as if they are surrounded by
8778 double quotes. Return a new list, or NULL if LIST is NULL. */
8779 WORD_LIST *
8780 word_list_quote_removal (list, quoted)
8781 WORD_LIST *list;
8782 int quoted;
8783 {
8784 WORD_LIST *result, *t, *tresult, *e;
8785
8786 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8787 {
8788 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8789 #if 0
8790 result = (WORD_LIST *) list_append (result, tresult);
8791 #else
8792 if (result == 0)
8793 result = e = tresult;
8794 else
8795 {
8796 e->next = tresult;
8797 while (e->next)
8798 e = e->next;
8799 }
8800 #endif
8801 }
8802 return (result);
8803 }
8804 #endif
8805
8806 /*******************************************
8807 * *
8808 * Functions to perform word splitting *
8809 * *
8810 *******************************************/
8811
8812 void
8813 setifs (v)
8814 SHELL_VAR *v;
8815 {
8816 char *t;
8817 unsigned char uc;
8818
8819 ifs_var = v;
8820 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8821
8822 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8823 handle multibyte chars in IFS */
8824 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8825 for (t = ifs_value ; t && *t; t++)
8826 {
8827 uc = *t;
8828 ifs_cmap[uc] = 1;
8829 }
8830
8831 #if defined (HANDLE_MULTIBYTE)
8832 if (ifs_value == 0)
8833 {
8834 ifs_firstc[0] = '\0';
8835 ifs_firstc_len = 1;
8836 }
8837 else
8838 {
8839 size_t ifs_len;
8840 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8841 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8842 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8843 {
8844 ifs_firstc[0] = ifs_value[0];
8845 ifs_firstc[1] = '\0';
8846 ifs_firstc_len = 1;
8847 }
8848 else
8849 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8850 }
8851 #else
8852 ifs_firstc = ifs_value ? *ifs_value : 0;
8853 #endif
8854 }
8855
8856 char *
8857 getifs ()
8858 {
8859 return ifs_value;
8860 }
8861
8862 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8863 is not quoted. list_string () performs quote removal for us, even if we
8864 don't do any splitting. */
8865 WORD_LIST *
8866 word_split (w, ifs_chars)
8867 WORD_DESC *w;
8868 char *ifs_chars;
8869 {
8870 WORD_LIST *result;
8871
8872 if (w)
8873 {
8874 char *xifs;
8875
8876 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8877 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8878 }
8879 else
8880 result = (WORD_LIST *)NULL;
8881
8882 return (result);
8883 }
8884
8885 /* Perform word splitting on LIST and return the RESULT. It is possible
8886 to return (WORD_LIST *)NULL. */
8887 static WORD_LIST *
8888 word_list_split (list)
8889 WORD_LIST *list;
8890 {
8891 WORD_LIST *result, *t, *tresult, *e;
8892
8893 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8894 {
8895 tresult = word_split (t->word, ifs_value);
8896 if (result == 0)
8897 result = e = tresult;
8898 else
8899 {
8900 e->next = tresult;
8901 while (e->next)
8902 e = e->next;
8903 }
8904 }
8905 return (result);
8906 }
8907
8908 /**************************************************
8909 * *
8910 * Functions to expand an entire WORD_LIST *
8911 * *
8912 **************************************************/
8913
8914 /* Do any word-expansion-specific cleanup and jump to top_level */
8915 static void
8916 exp_jump_to_top_level (v)
8917 int v;
8918 {
8919 set_pipestatus_from_exit (last_command_exit_value);
8920
8921 /* Cleanup code goes here. */
8922 expand_no_split_dollar_star = 0; /* XXX */
8923 expanding_redir = 0;
8924 assigning_in_environment = 0;
8925
8926 if (parse_and_execute_level == 0)
8927 top_level_cleanup (); /* from sig.c */
8928
8929 jump_to_top_level (v);
8930 }
8931
8932 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8933 ELIST, and set ELIST to the new list. */
8934 #define PREPEND_LIST(nlist, elist) \
8935 do { nlist->next = elist; elist = nlist; } while (0)
8936
8937 /* Separate out any initial variable assignments from TLIST. If set -k has
8938 been executed, remove all assignment statements from TLIST. Initial
8939 variable assignments and other environment assignments are placed
8940 on SUBST_ASSIGN_VARLIST. */
8941 static WORD_LIST *
8942 separate_out_assignments (tlist)
8943 WORD_LIST *tlist;
8944 {
8945 register WORD_LIST *vp, *lp;
8946
8947 if (tlist == 0)
8948 return ((WORD_LIST *)NULL);
8949
8950 if (subst_assign_varlist)
8951 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8952
8953 subst_assign_varlist = (WORD_LIST *)NULL;
8954 vp = lp = tlist;
8955
8956 /* Separate out variable assignments at the start of the command.
8957 Loop invariant: vp->next == lp
8958 Loop postcondition:
8959 lp = list of words left after assignment statements skipped
8960 tlist = original list of words
8961 */
8962 while (lp && (lp->word->flags & W_ASSIGNMENT))
8963 {
8964 vp = lp;
8965 lp = lp->next;
8966 }
8967
8968 /* If lp != tlist, we have some initial assignment statements.
8969 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8970 words and TLIST point to the remaining words. */
8971 if (lp != tlist)
8972 {
8973 subst_assign_varlist = tlist;
8974 /* ASSERT(vp->next == lp); */
8975 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8976 tlist = lp; /* remainder of word list */
8977 }
8978
8979 /* vp == end of variable list */
8980 /* tlist == remainder of original word list without variable assignments */
8981 if (!tlist)
8982 /* All the words in tlist were assignment statements */
8983 return ((WORD_LIST *)NULL);
8984
8985 /* ASSERT(tlist != NULL); */
8986 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8987
8988 /* If the -k option is in effect, we need to go through the remaining
8989 words, separate out the assignment words, and place them on
8990 SUBST_ASSIGN_VARLIST. */
8991 if (place_keywords_in_env)
8992 {
8993 WORD_LIST *tp; /* tp == running pointer into tlist */
8994
8995 tp = tlist;
8996 lp = tlist->next;
8997
8998 /* Loop Invariant: tp->next == lp */
8999 /* Loop postcondition: tlist == word list without assignment statements */
9000 while (lp)
9001 {
9002 if (lp->word->flags & W_ASSIGNMENT)
9003 {
9004 /* Found an assignment statement, add this word to end of
9005 subst_assign_varlist (vp). */
9006 if (!subst_assign_varlist)
9007 subst_assign_varlist = vp = lp;
9008 else
9009 {
9010 vp->next = lp;
9011 vp = lp;
9012 }
9013
9014 /* Remove the word pointed to by LP from TLIST. */
9015 tp->next = lp->next;
9016 /* ASSERT(vp == lp); */
9017 lp->next = (WORD_LIST *)NULL;
9018 lp = tp->next;
9019 }
9020 else
9021 {
9022 tp = lp;
9023 lp = lp->next;
9024 }
9025 }
9026 }
9027 return (tlist);
9028 }
9029
9030 #define WEXP_VARASSIGN 0x001
9031 #define WEXP_BRACEEXP 0x002
9032 #define WEXP_TILDEEXP 0x004
9033 #define WEXP_PARAMEXP 0x008
9034 #define WEXP_PATHEXP 0x010
9035
9036 /* All of the expansions, including variable assignments at the start of
9037 the list. */
9038 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
9039
9040 /* All of the expansions except variable assignments at the start of
9041 the list. */
9042 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
9043
9044 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
9045 expansion, command substitution, arithmetic expansion, word splitting, and
9046 quote removal. */
9047 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
9048
9049 /* Take the list of words in LIST and do the various substitutions. Return
9050 a new list of words which is the expanded list, and without things like
9051 variable assignments. */
9052
9053 WORD_LIST *
9054 expand_words (list)
9055 WORD_LIST *list;
9056 {
9057 return (expand_word_list_internal (list, WEXP_ALL));
9058 }
9059
9060 /* Same as expand_words (), but doesn't hack variable or environment
9061 variables. */
9062 WORD_LIST *
9063 expand_words_no_vars (list)
9064 WORD_LIST *list;
9065 {
9066 return (expand_word_list_internal (list, WEXP_NOVARS));
9067 }
9068
9069 WORD_LIST *
9070 expand_words_shellexp (list)
9071 WORD_LIST *list;
9072 {
9073 return (expand_word_list_internal (list, WEXP_SHELLEXP));
9074 }
9075
9076 static WORD_LIST *
9077 glob_expand_word_list (tlist, eflags)
9078 WORD_LIST *tlist;
9079 int eflags;
9080 {
9081 char **glob_array, *temp_string;
9082 register int glob_index;
9083 WORD_LIST *glob_list, *output_list, *disposables, *next;
9084 WORD_DESC *tword;
9085
9086 output_list = disposables = (WORD_LIST *)NULL;
9087 glob_array = (char **)NULL;
9088 while (tlist)
9089 {
9090 /* For each word, either globbing is attempted or the word is
9091 added to orig_list. If globbing succeeds, the results are
9092 added to orig_list and the word (tlist) is added to the list
9093 of disposable words. If globbing fails and failed glob
9094 expansions are left unchanged (the shell default), the
9095 original word is added to orig_list. If globbing fails and
9096 failed glob expansions are removed, the original word is
9097 added to the list of disposable words. orig_list ends up
9098 in reverse order and requires a call to REVERSE_LIST to
9099 be set right. After all words are examined, the disposable
9100 words are freed. */
9101 next = tlist->next;
9102
9103 /* If the word isn't an assignment and contains an unquoted
9104 pattern matching character, then glob it. */
9105 if ((tlist->word->flags & W_NOGLOB) == 0 &&
9106 unquoted_glob_pattern_p (tlist->word->word))
9107 {
9108 glob_array = shell_glob_filename (tlist->word->word);
9109
9110 /* Handle error cases.
9111 I don't think we should report errors like "No such file
9112 or directory". However, I would like to report errors
9113 like "Read failed". */
9114
9115 if (glob_array == 0 || GLOB_FAILED (glob_array))
9116 {
9117 glob_array = (char **)xmalloc (sizeof (char *));
9118 glob_array[0] = (char *)NULL;
9119 }
9120
9121 /* Dequote the current word in case we have to use it. */
9122 if (glob_array[0] == NULL)
9123 {
9124 temp_string = dequote_string (tlist->word->word);
9125 free (tlist->word->word);
9126 tlist->word->word = temp_string;
9127 }
9128
9129 /* Make the array into a word list. */
9130 glob_list = (WORD_LIST *)NULL;
9131 for (glob_index = 0; glob_array[glob_index]; glob_index++)
9132 {
9133 tword = make_bare_word (glob_array[glob_index]);
9134 tword->flags |= W_GLOBEXP; /* XXX */
9135 glob_list = make_word_list (tword, glob_list);
9136 }
9137
9138 if (glob_list)
9139 {
9140 output_list = (WORD_LIST *)list_append (glob_list, output_list);
9141 PREPEND_LIST (tlist, disposables);
9142 }
9143 else if (fail_glob_expansion != 0)
9144 {
9145 last_command_exit_value = EXECUTION_FAILURE;
9146 report_error (_("no match: %s"), tlist->word->word);
9147 exp_jump_to_top_level (DISCARD);
9148 }
9149 else if (allow_null_glob_expansion == 0)
9150 {
9151 /* Failed glob expressions are left unchanged. */
9152 PREPEND_LIST (tlist, output_list);
9153 }
9154 else
9155 {
9156 /* Failed glob expressions are removed. */
9157 PREPEND_LIST (tlist, disposables);
9158 }
9159 }
9160 else
9161 {
9162 /* Dequote the string. */
9163 temp_string = dequote_string (tlist->word->word);
9164 free (tlist->word->word);
9165 tlist->word->word = temp_string;
9166 PREPEND_LIST (tlist, output_list);
9167 }
9168
9169 strvec_dispose (glob_array);
9170 glob_array = (char **)NULL;
9171
9172 tlist = next;
9173 }
9174
9175 if (disposables)
9176 dispose_words (disposables);
9177
9178 if (output_list)
9179 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9180
9181 return (output_list);
9182 }
9183
9184 #if defined (BRACE_EXPANSION)
9185 static WORD_LIST *
9186 brace_expand_word_list (tlist, eflags)
9187 WORD_LIST *tlist;
9188 int eflags;
9189 {
9190 register char **expansions;
9191 char *temp_string;
9192 WORD_LIST *disposables, *output_list, *next;
9193 WORD_DESC *w;
9194 int eindex;
9195
9196 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
9197 {
9198 next = tlist->next;
9199
9200 if (tlist->word->flags & W_NOBRACE)
9201 {
9202 itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);
9203 PREPEND_LIST (tlist, output_list);
9204 continue;
9205 }
9206
9207 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9208 {
9209 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
9210 PREPEND_LIST (tlist, output_list);
9211 continue;
9212 }
9213
9214 /* Only do brace expansion if the word has a brace character. If
9215 not, just add the word list element to BRACES and continue. In
9216 the common case, at least when running shell scripts, this will
9217 degenerate to a bunch of calls to `mbschr', and then what is
9218 basically a reversal of TLIST into BRACES, which is corrected
9219 by a call to REVERSE_LIST () on BRACES when the end of TLIST
9220 is reached. */
9221 if (mbschr (tlist->word->word, LBRACE))
9222 {
9223 expansions = brace_expand (tlist->word->word);
9224
9225 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
9226 {
9227 w = alloc_word_desc ();
9228 w->word = temp_string;
9229
9230 /* If brace expansion didn't change the word, preserve
9231 the flags. We may want to preserve the flags
9232 unconditionally someday -- XXX */
9233 if (STREQ (temp_string, tlist->word->word))
9234 w->flags = tlist->word->flags;
9235 else
9236 w = make_word_flags (w, temp_string);
9237
9238 output_list = make_word_list (w, output_list);
9239 }
9240 free (expansions);
9241
9242 /* Add TLIST to the list of words to be freed after brace
9243 expansion has been performed. */
9244 PREPEND_LIST (tlist, disposables);
9245 }
9246 else
9247 PREPEND_LIST (tlist, output_list);
9248 }
9249
9250 if (disposables)
9251 dispose_words (disposables);
9252
9253 if (output_list)
9254 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9255
9256 return (output_list);
9257 }
9258 #endif
9259
9260 #if defined (ARRAY_VARS)
9261 /* Take WORD, a compound associative array assignment, and internally run
9262 'declare -A w', where W is the variable name portion of WORD. */
9263 static int
9264 make_internal_declare (word, option)
9265 char *word;
9266 char *option;
9267 {
9268 int t;
9269 WORD_LIST *wl;
9270 WORD_DESC *w;
9271
9272 w = make_word (word);
9273
9274 t = assignment (w->word, 0);
9275 w->word[t] = '\0';
9276
9277 wl = make_word_list (w, (WORD_LIST *)NULL);
9278 wl = make_word_list (make_word (option), wl);
9279
9280 return (declare_builtin (wl));
9281 }
9282 #endif
9283
9284 static WORD_LIST *
9285 shell_expand_word_list (tlist, eflags)
9286 WORD_LIST *tlist;
9287 int eflags;
9288 {
9289 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
9290 int expanded_something, has_dollar_at;
9291 char *temp_string;
9292
9293 /* We do tilde expansion all the time. This is what 1003.2 says. */
9294 new_list = (WORD_LIST *)NULL;
9295 for (orig_list = tlist; tlist; tlist = next)
9296 {
9297 temp_string = tlist->word->word;
9298
9299 next = tlist->next;
9300
9301 #if defined (ARRAY_VARS)
9302 /* If this is a compound array assignment to a builtin that accepts
9303 such assignments (e.g., `declare'), take the assignment and perform
9304 it separately, handling the semantics of declarations inside shell
9305 functions. This avoids the double-evaluation of such arguments,
9306 because `declare' does some evaluation of compound assignments on
9307 its own. */
9308 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9309 {
9310 int t;
9311
9312 if (tlist->word->flags & W_ASSIGNASSOC)
9313 make_internal_declare (tlist->word->word, "-A");
9314
9315 t = do_word_assignment (tlist->word, 0);
9316 if (t == 0)
9317 {
9318 last_command_exit_value = EXECUTION_FAILURE;
9319 exp_jump_to_top_level (DISCARD);
9320 }
9321
9322 /* Now transform the word as ksh93 appears to do and go on */
9323 t = assignment (tlist->word->word, 0);
9324 tlist->word->word[t] = '\0';
9325 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
9326 }
9327 #endif
9328
9329 expanded_something = 0;
9330 expanded = expand_word_internal
9331 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
9332
9333 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
9334 {
9335 /* By convention, each time this error is returned,
9336 tlist->word->word has already been freed. */
9337 tlist->word->word = (char *)NULL;
9338
9339 /* Dispose our copy of the original list. */
9340 dispose_words (orig_list);
9341 /* Dispose the new list we're building. */
9342 dispose_words (new_list);
9343
9344 last_command_exit_value = EXECUTION_FAILURE;
9345 if (expanded == &expand_word_error)
9346 exp_jump_to_top_level (DISCARD);
9347 else
9348 exp_jump_to_top_level (FORCE_EOF);
9349 }
9350
9351 /* Don't split words marked W_NOSPLIT. */
9352 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
9353 {
9354 temp_list = word_list_split (expanded);
9355 dispose_words (expanded);
9356 }
9357 else
9358 {
9359 /* If no parameter expansion, command substitution, process
9360 substitution, or arithmetic substitution took place, then
9361 do not do word splitting. We still have to remove quoted
9362 null characters from the result. */
9363 word_list_remove_quoted_nulls (expanded);
9364 temp_list = expanded;
9365 }
9366
9367 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
9368 new_list = (WORD_LIST *)list_append (expanded, new_list);
9369 }
9370
9371 if (orig_list)
9372 dispose_words (orig_list);
9373
9374 if (new_list)
9375 new_list = REVERSE_LIST (new_list, WORD_LIST *);
9376
9377 return (new_list);
9378 }
9379
9380 /* The workhorse for expand_words () and expand_words_no_vars ().
9381 First arg is LIST, a WORD_LIST of words.
9382 Second arg EFLAGS is a flags word controlling which expansions are
9383 performed.
9384
9385 This does all of the substitutions: brace expansion, tilde expansion,
9386 parameter expansion, command substitution, arithmetic expansion,
9387 process substitution, word splitting, and pathname expansion, according
9388 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
9389 set, or for which no expansion is done, do not undergo word splitting.
9390 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
9391 with W_NOBRACE set do not undergo brace expansion (see
9392 brace_expand_word_list above). */
9393 static WORD_LIST *
9394 expand_word_list_internal (list, eflags)
9395 WORD_LIST *list;
9396 int eflags;
9397 {
9398 WORD_LIST *new_list, *temp_list;
9399 int tint;
9400
9401 if (list == 0)
9402 return ((WORD_LIST *)NULL);
9403
9404 garglist = new_list = copy_word_list (list);
9405 if (eflags & WEXP_VARASSIGN)
9406 {
9407 garglist = new_list = separate_out_assignments (new_list);
9408 if (new_list == 0)
9409 {
9410 if (subst_assign_varlist)
9411 {
9412 /* All the words were variable assignments, so they are placed
9413 into the shell's environment. */
9414 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
9415 {
9416 this_command_name = (char *)NULL; /* no arithmetic errors */
9417 tint = do_word_assignment (temp_list->word, 0);
9418 /* Variable assignment errors in non-interactive shells
9419 running in Posix.2 mode cause the shell to exit. */
9420 if (tint == 0)
9421 {
9422 last_command_exit_value = EXECUTION_FAILURE;
9423 if (interactive_shell == 0 && posixly_correct)
9424 exp_jump_to_top_level (FORCE_EOF);
9425 else
9426 exp_jump_to_top_level (DISCARD);
9427 }
9428 }
9429 dispose_words (subst_assign_varlist);
9430 subst_assign_varlist = (WORD_LIST *)NULL;
9431 }
9432 return ((WORD_LIST *)NULL);
9433 }
9434 }
9435
9436 /* Begin expanding the words that remain. The expansions take place on
9437 things that aren't really variable assignments. */
9438
9439 #if defined (BRACE_EXPANSION)
9440 /* Do brace expansion on this word if there are any brace characters
9441 in the string. */
9442 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
9443 new_list = brace_expand_word_list (new_list, eflags);
9444 #endif /* BRACE_EXPANSION */
9445
9446 /* Perform the `normal' shell expansions: tilde expansion, parameter and
9447 variable substitution, command substitution, arithmetic expansion,
9448 and word splitting. */
9449 new_list = shell_expand_word_list (new_list, eflags);
9450
9451 /* Okay, we're almost done. Now let's just do some filename
9452 globbing. */
9453 if (new_list)
9454 {
9455 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
9456 /* Glob expand the word list unless globbing has been disabled. */
9457 new_list = glob_expand_word_list (new_list, eflags);
9458 else
9459 /* Dequote the words, because we're not performing globbing. */
9460 new_list = dequote_list (new_list);
9461 }
9462
9463 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
9464 {
9465 sh_wassign_func_t *assign_func;
9466 int is_special_builtin, is_builtin_or_func;
9467
9468 /* If the remainder of the words expand to nothing, Posix.2 requires
9469 that the variable and environment assignments affect the shell's
9470 environment. */
9471 assign_func = new_list ? assign_in_env : do_word_assignment;
9472 tempenv_assign_error = 0;
9473
9474 is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
9475 /* Posix says that special builtins exit if a variable assignment error
9476 occurs in an assignment preceding it. */
9477 is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
9478
9479 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
9480 {
9481 this_command_name = (char *)NULL;
9482 assigning_in_environment = (assign_func == assign_in_env);
9483 tint = (*assign_func) (temp_list->word, is_builtin_or_func);
9484 assigning_in_environment = 0;
9485 /* Variable assignment errors in non-interactive shells running
9486 in Posix.2 mode cause the shell to exit. */
9487 if (tint == 0)
9488 {
9489 if (assign_func == do_word_assignment)
9490 {
9491 last_command_exit_value = EXECUTION_FAILURE;
9492 if (interactive_shell == 0 && posixly_correct && is_special_builtin)
9493 exp_jump_to_top_level (FORCE_EOF);
9494 else
9495 exp_jump_to_top_level (DISCARD);
9496 }
9497 else
9498 tempenv_assign_error++;
9499 }
9500 }
9501
9502 dispose_words (subst_assign_varlist);
9503 subst_assign_varlist = (WORD_LIST *)NULL;
9504 }
9505
9506 #if 0
9507 tint = list_length (new_list) + 1;
9508 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
9509 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
9510 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
9511 glob_argv_flags[tint] = '\0';
9512 #endif
9513
9514 return (new_list);
9515 }