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