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