]> git.ipfire.org Git - thirdparty/bash.git/blob - subst.c
Bash-4.2 patch 18
[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 report_error (_("%s: bad substitution"), string ? string : "??");
7278 FREE (value);
7279 FREE (temp);
7280 free (name);
7281 return &expand_wdesc_error;
7282
7283 case RBRACE:
7284 break;
7285
7286 case '#': /* ${param#[#]pattern} */
7287 case '%': /* ${param%[%]pattern} */
7288 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
7289 {
7290 FREE (value);
7291 break;
7292 }
7293 temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
7294 free (temp);
7295 free (value);
7296 free (name);
7297
7298 ret = alloc_word_desc ();
7299 ret->word = temp1;
7300 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7301 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7302 return ret;
7303
7304 case '-':
7305 case '=':
7306 case '?':
7307 case '+':
7308 if (var_is_set && var_is_null == 0)
7309 {
7310 /* If the operator is `+', we don't want the value of the named
7311 variable for anything, just the value of the right hand side. */
7312 if (c == '+')
7313 {
7314 /* XXX -- if we're double-quoted and the named variable is "$@",
7315 we want to turn off any special handling of "$@" --
7316 we're not using it, so whatever is on the rhs applies. */
7317 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7318 *quoted_dollar_atp = 0;
7319 if (contains_dollar_at)
7320 *contains_dollar_at = 0;
7321
7322 FREE (temp);
7323 if (value)
7324 {
7325 /* From Posix discussion on austin-group list. Issue 221
7326 requires that backslashes escaping `}' inside
7327 double-quoted ${...} be removed. */
7328 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7329 quoted |= Q_DOLBRACE;
7330 ret = parameter_brace_expand_rhs (name, value, c,
7331 quoted,
7332 quoted_dollar_atp,
7333 contains_dollar_at);
7334 /* XXX - fix up later, esp. noting presence of
7335 W_HASQUOTEDNULL in ret->flags */
7336 free (value);
7337 }
7338 else
7339 temp = (char *)NULL;
7340 }
7341 else
7342 {
7343 FREE (value);
7344 }
7345 /* Otherwise do nothing; just use the value in TEMP. */
7346 }
7347 else /* VAR not set or VAR is NULL. */
7348 {
7349 FREE (temp);
7350 temp = (char *)NULL;
7351 if (c == '=' && var_is_special)
7352 {
7353 report_error (_("$%s: cannot assign in this way"), name);
7354 free (name);
7355 free (value);
7356 return &expand_wdesc_error;
7357 }
7358 else if (c == '?')
7359 {
7360 parameter_brace_expand_error (name, value);
7361 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7362 }
7363 else if (c != '+')
7364 {
7365 /* XXX -- if we're double-quoted and the named variable is "$@",
7366 we want to turn off any special handling of "$@" --
7367 we're not using it, so whatever is on the rhs applies. */
7368 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7369 *quoted_dollar_atp = 0;
7370 if (contains_dollar_at)
7371 *contains_dollar_at = 0;
7372
7373 /* From Posix discussion on austin-group list. Issue 221 requires
7374 that backslashes escaping `}' inside double-quoted ${...} be
7375 removed. */
7376 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7377 quoted |= Q_DOLBRACE;
7378 ret = parameter_brace_expand_rhs (name, value, c, quoted,
7379 quoted_dollar_atp,
7380 contains_dollar_at);
7381 /* XXX - fix up later, esp. noting presence of
7382 W_HASQUOTEDNULL in tdesc->flags */
7383 }
7384 free (value);
7385 }
7386
7387 break;
7388 }
7389 free (name);
7390
7391 if (ret == 0)
7392 {
7393 ret = alloc_word_desc ();
7394 ret->flags = tflag;
7395 ret->word = temp;
7396 }
7397 return (ret);
7398 }
7399
7400 /* Expand a single ${xxx} expansion. The braces are optional. When
7401 the braces are used, parameter_brace_expand() does the work,
7402 possibly calling param_expand recursively. */
7403 static WORD_DESC *
7404 param_expand (string, sindex, quoted, expanded_something,
7405 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
7406 pflags)
7407 char *string;
7408 int *sindex, quoted, *expanded_something, *contains_dollar_at;
7409 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
7410 {
7411 char *temp, *temp1, uerror[3];
7412 int zindex, t_index, expok;
7413 unsigned char c;
7414 intmax_t number;
7415 SHELL_VAR *var;
7416 WORD_LIST *list;
7417 WORD_DESC *tdesc, *ret;
7418 int tflag;
7419
7420 zindex = *sindex;
7421 c = string[++zindex];
7422
7423 temp = (char *)NULL;
7424 ret = tdesc = (WORD_DESC *)NULL;
7425 tflag = 0;
7426
7427 /* Do simple cases first. Switch on what follows '$'. */
7428 switch (c)
7429 {
7430 /* $0 .. $9? */
7431 case '0':
7432 case '1':
7433 case '2':
7434 case '3':
7435 case '4':
7436 case '5':
7437 case '6':
7438 case '7':
7439 case '8':
7440 case '9':
7441 temp1 = dollar_vars[TODIGIT (c)];
7442 if (unbound_vars_is_error && temp1 == (char *)NULL)
7443 {
7444 uerror[0] = '$';
7445 uerror[1] = c;
7446 uerror[2] = '\0';
7447 last_command_exit_value = EXECUTION_FAILURE;
7448 err_unboundvar (uerror);
7449 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7450 }
7451 if (temp1)
7452 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7453 ? quote_string (temp1)
7454 : quote_escapes (temp1);
7455 else
7456 temp = (char *)NULL;
7457
7458 break;
7459
7460 /* $$ -- pid of the invoking shell. */
7461 case '$':
7462 temp = itos (dollar_dollar_pid);
7463 break;
7464
7465 /* $# -- number of positional parameters. */
7466 case '#':
7467 temp = itos (number_of_args ());
7468 break;
7469
7470 /* $? -- return value of the last synchronous command. */
7471 case '?':
7472 temp = itos (last_command_exit_value);
7473 break;
7474
7475 /* $- -- flags supplied to the shell on invocation or by `set'. */
7476 case '-':
7477 temp = which_set_flags ();
7478 break;
7479
7480 /* $! -- Pid of the last asynchronous command. */
7481 case '!':
7482 /* If no asynchronous pids have been created, expand to nothing.
7483 If `set -u' has been executed, and no async processes have
7484 been created, this is an expansion error. */
7485 if (last_asynchronous_pid == NO_PID)
7486 {
7487 if (expanded_something)
7488 *expanded_something = 0;
7489 temp = (char *)NULL;
7490 if (unbound_vars_is_error)
7491 {
7492 uerror[0] = '$';
7493 uerror[1] = c;
7494 uerror[2] = '\0';
7495 last_command_exit_value = EXECUTION_FAILURE;
7496 err_unboundvar (uerror);
7497 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7498 }
7499 }
7500 else
7501 temp = itos (last_asynchronous_pid);
7502 break;
7503
7504 /* The only difference between this and $@ is when the arg is quoted. */
7505 case '*': /* `$*' */
7506 list = list_rest_of_args ();
7507
7508 #if 0
7509 /* According to austin-group posix proposal by Geoff Clare in
7510 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7511
7512 "The shell shall write a message to standard error and
7513 immediately exit when it tries to expand an unset parameter
7514 other than the '@' and '*' special parameters."
7515 */
7516
7517 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7518 {
7519 uerror[0] = '$';
7520 uerror[1] = '*';
7521 uerror[2] = '\0';
7522 last_command_exit_value = EXECUTION_FAILURE;
7523 err_unboundvar (uerror);
7524 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7525 }
7526 #endif
7527
7528 /* If there are no command-line arguments, this should just
7529 disappear if there are other characters in the expansion,
7530 even if it's quoted. */
7531 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7532 temp = (char *)NULL;
7533 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
7534 {
7535 /* If we have "$*" we want to make a string of the positional
7536 parameters, separated by the first character of $IFS, and
7537 quote the whole string, including the separators. If IFS
7538 is unset, the parameters are separated by ' '; if $IFS is
7539 null, the parameters are concatenated. */
7540 temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
7541 if (temp)
7542 {
7543 temp1 = quote_string (temp);
7544 if (*temp == 0)
7545 tflag |= W_HASQUOTEDNULL;
7546 free (temp);
7547 temp = temp1;
7548 }
7549 }
7550 else
7551 {
7552 /* We check whether or not we're eventually going to split $* here,
7553 for example when IFS is empty and we are processing the rhs of
7554 an assignment statement. In that case, we don't separate the
7555 arguments at all. Otherwise, if the $* is not quoted it is
7556 identical to $@ */
7557 #if 1
7558 # if defined (HANDLE_MULTIBYTE)
7559 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7560 # else
7561 if (expand_no_split_dollar_star && ifs_firstc == 0)
7562 # endif
7563 temp = string_list_dollar_star (list);
7564 else
7565 temp = string_list_dollar_at (list, quoted);
7566 #else
7567 temp = string_list_dollar_at (list, quoted);
7568 #endif
7569 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7570 *contains_dollar_at = 1;
7571 }
7572
7573 dispose_words (list);
7574 break;
7575
7576 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7577 means that we have to turn quoting off after we split into
7578 the individually quoted arguments so that the final split
7579 on the first character of $IFS is still done. */
7580 case '@': /* `$@' */
7581 list = list_rest_of_args ();
7582
7583 #if 0
7584 /* According to austin-group posix proposal by Geoff Clare in
7585 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7586
7587 "The shell shall write a message to standard error and
7588 immediately exit when it tries to expand an unset parameter
7589 other than the '@' and '*' special parameters."
7590 */
7591
7592 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
7593 {
7594 uerror[0] = '$';
7595 uerror[1] = '@';
7596 uerror[2] = '\0';
7597 last_command_exit_value = EXECUTION_FAILURE;
7598 err_unboundvar (uerror);
7599 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7600 }
7601 #endif
7602
7603 /* We want to flag the fact that we saw this. We can't turn
7604 off quoting entirely, because other characters in the
7605 string might need it (consider "\"$@\""), but we need some
7606 way to signal that the final split on the first character
7607 of $IFS should be done, even though QUOTED is 1. */
7608 /* XXX - should this test include Q_PATQUOTE? */
7609 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7610 *quoted_dollar_at_p = 1;
7611 if (contains_dollar_at)
7612 *contains_dollar_at = 1;
7613
7614 #if 0
7615 if (pflags & PF_NOSPLIT2)
7616 temp = string_list_internal (quoted ? quote_list (list) : list, " ");
7617 else
7618 #endif
7619 /* We want to separate the positional parameters with the first
7620 character of $IFS in case $IFS is something other than a space.
7621 We also want to make sure that splitting is done no matter what --
7622 according to POSIX.2, this expands to a list of the positional
7623 parameters no matter what IFS is set to. */
7624 temp = string_list_dollar_at (list, quoted);
7625
7626 dispose_words (list);
7627 break;
7628
7629 case LBRACE:
7630 tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
7631 quoted_dollar_at_p,
7632 contains_dollar_at);
7633
7634 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7635 return (tdesc);
7636 temp = tdesc ? tdesc->word : (char *)0;
7637
7638 /* XXX */
7639 /* Quoted nulls should be removed if there is anything else
7640 in the string. */
7641 /* Note that we saw the quoted null so we can add one back at
7642 the end of this function if there are no other characters
7643 in the string, discard TEMP, and go on. The exception to
7644 this is when we have "${@}" and $1 is '', since $@ needs
7645 special handling. */
7646 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
7647 {
7648 if (had_quoted_null_p)
7649 *had_quoted_null_p = 1;
7650 if (*quoted_dollar_at_p == 0)
7651 {
7652 free (temp);
7653 tdesc->word = temp = (char *)NULL;
7654 }
7655
7656 }
7657
7658 ret = tdesc;
7659 goto return0;
7660
7661 /* Do command or arithmetic substitution. */
7662 case LPAREN:
7663 /* We have to extract the contents of this paren substitution. */
7664 t_index = zindex + 1;
7665 temp = extract_command_subst (string, &t_index, 0);
7666 zindex = t_index;
7667
7668 /* For Posix.2-style `$(( ))' arithmetic substitution,
7669 extract the expression and pass it to the evaluator. */
7670 if (temp && *temp == LPAREN)
7671 {
7672 char *temp2;
7673 temp1 = temp + 1;
7674 temp2 = savestring (temp1);
7675 t_index = strlen (temp2) - 1;
7676
7677 if (temp2[t_index] != RPAREN)
7678 {
7679 free (temp2);
7680 goto comsub;
7681 }
7682
7683 /* Cut off ending `)' */
7684 temp2[t_index] = '\0';
7685
7686 if (chk_arithsub (temp2, t_index) == 0)
7687 {
7688 free (temp2);
7689 #if 0
7690 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
7691 #endif
7692 goto comsub;
7693 }
7694
7695 /* Expand variables found inside the expression. */
7696 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
7697 free (temp2);
7698
7699 arithsub:
7700 /* No error messages. */
7701 this_command_name = (char *)NULL;
7702 number = evalexp (temp1, &expok);
7703 free (temp);
7704 free (temp1);
7705 if (expok == 0)
7706 {
7707 if (interactive_shell == 0 && posixly_correct)
7708 {
7709 last_command_exit_value = EXECUTION_FAILURE;
7710 return (&expand_wdesc_fatal);
7711 }
7712 else
7713 return (&expand_wdesc_error);
7714 }
7715 temp = itos (number);
7716 break;
7717 }
7718
7719 comsub:
7720 if (pflags & PF_NOCOMSUB)
7721 /* we need zindex+1 because string[zindex] == RPAREN */
7722 temp1 = substring (string, *sindex, zindex+1);
7723 else
7724 {
7725 tdesc = command_substitute (temp, quoted);
7726 temp1 = tdesc ? tdesc->word : (char *)NULL;
7727 if (tdesc)
7728 dispose_word_desc (tdesc);
7729 }
7730 FREE (temp);
7731 temp = temp1;
7732 break;
7733
7734 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7735 away in a future bash release. */
7736 case '[':
7737 /* Extract the contents of this arithmetic substitution. */
7738 t_index = zindex + 1;
7739 temp = extract_arithmetic_subst (string, &t_index);
7740 zindex = t_index;
7741 if (temp == 0)
7742 {
7743 temp = savestring (string);
7744 if (expanded_something)
7745 *expanded_something = 0;
7746 goto return0;
7747 }
7748
7749 /* Do initial variable expansion. */
7750 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
7751
7752 goto arithsub;
7753
7754 default:
7755 /* Find the variable in VARIABLE_LIST. */
7756 temp = (char *)NULL;
7757
7758 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7759 ;
7760 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7761
7762 /* If this isn't a variable name, then just output the `$'. */
7763 if (temp1 == 0 || *temp1 == '\0')
7764 {
7765 FREE (temp1);
7766 temp = (char *)xmalloc (2);
7767 temp[0] = '$';
7768 temp[1] = '\0';
7769 if (expanded_something)
7770 *expanded_something = 0;
7771 goto return0;
7772 }
7773
7774 /* If the variable exists, return its value cell. */
7775 var = find_variable (temp1);
7776
7777 if (var && invisible_p (var) == 0 && var_isset (var))
7778 {
7779 #if defined (ARRAY_VARS)
7780 if (assoc_p (var) || array_p (var))
7781 {
7782 temp = array_p (var) ? array_reference (array_cell (var), 0)
7783 : assoc_reference (assoc_cell (var), "0");
7784 if (temp)
7785 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7786 ? quote_string (temp)
7787 : quote_escapes (temp);
7788 else if (unbound_vars_is_error)
7789 goto unbound_variable;
7790 }
7791 else
7792 #endif
7793 {
7794 temp = value_cell (var);
7795
7796 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7797 ? quote_string (temp)
7798 : quote_escapes (temp);
7799 }
7800
7801 free (temp1);
7802
7803 goto return0;
7804 }
7805
7806 temp = (char *)NULL;
7807
7808 unbound_variable:
7809 if (unbound_vars_is_error)
7810 {
7811 last_command_exit_value = EXECUTION_FAILURE;
7812 err_unboundvar (temp1);
7813 }
7814 else
7815 {
7816 free (temp1);
7817 goto return0;
7818 }
7819
7820 free (temp1);
7821 last_command_exit_value = EXECUTION_FAILURE;
7822 return ((unbound_vars_is_error && interactive_shell == 0)
7823 ? &expand_wdesc_fatal
7824 : &expand_wdesc_error);
7825 }
7826
7827 if (string[zindex])
7828 zindex++;
7829
7830 return0:
7831 *sindex = zindex;
7832
7833 if (ret == 0)
7834 {
7835 ret = alloc_word_desc ();
7836 ret->flags = tflag; /* XXX */
7837 ret->word = temp;
7838 }
7839 return ret;
7840 }
7841
7842 /* Make a word list which is the result of parameter and variable
7843 expansion, command substitution, arithmetic substitution, and
7844 quote removal of WORD. Return a pointer to a WORD_LIST which is
7845 the result of the expansion. If WORD contains a null word, the
7846 word list returned is also null.
7847
7848 QUOTED contains flag values defined in shell.h.
7849
7850 ISEXP is used to tell expand_word_internal that the word should be
7851 treated as the result of an expansion. This has implications for
7852 how IFS characters in the word are treated.
7853
7854 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7855 they point to an integer value which receives information about expansion.
7856 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7857 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7858 else zero.
7859
7860 This only does word splitting in the case of $@ expansion. In that
7861 case, we split on ' '. */
7862
7863 /* Values for the local variable quoted_state. */
7864 #define UNQUOTED 0
7865 #define PARTIALLY_QUOTED 1
7866 #define WHOLLY_QUOTED 2
7867
7868 static WORD_LIST *
7869 expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
7870 WORD_DESC *word;
7871 int quoted, isexp;
7872 int *contains_dollar_at;
7873 int *expanded_something;
7874 {
7875 WORD_LIST *list;
7876 WORD_DESC *tword;
7877
7878 /* The intermediate string that we build while expanding. */
7879 char *istring;
7880
7881 /* The current size of the above object. */
7882 int istring_size;
7883
7884 /* Index into ISTRING. */
7885 int istring_index;
7886
7887 /* Temporary string storage. */
7888 char *temp, *temp1;
7889
7890 /* The text of WORD. */
7891 register char *string;
7892
7893 /* The size of STRING. */
7894 size_t string_size;
7895
7896 /* The index into STRING. */
7897 int sindex;
7898
7899 /* This gets 1 if we see a $@ while quoted. */
7900 int quoted_dollar_at;
7901
7902 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
7903 whether WORD contains no quoting characters, a partially quoted
7904 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
7905 int quoted_state;
7906
7907 /* State flags */
7908 int had_quoted_null;
7909 int has_dollar_at;
7910 int tflag;
7911 int pflags; /* flags passed to param_expand */
7912
7913 int assignoff; /* If assignment, offset of `=' */
7914
7915 register unsigned char c; /* Current character. */
7916 int t_index; /* For calls to string_extract_xxx. */
7917
7918 char twochars[2];
7919
7920 DECLARE_MBSTATE;
7921
7922 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
7923 istring[istring_index = 0] = '\0';
7924 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
7925 quoted_state = UNQUOTED;
7926
7927 string = word->word;
7928 if (string == 0)
7929 goto finished_with_string;
7930 /* Don't need the string length for the SADD... and COPY_ macros unless
7931 multibyte characters are possible. */
7932 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
7933
7934 if (contains_dollar_at)
7935 *contains_dollar_at = 0;
7936
7937 assignoff = -1;
7938
7939 /* Begin the expansion. */
7940
7941 for (sindex = 0; ;)
7942 {
7943 c = string[sindex];
7944
7945 /* Case on toplevel character. */
7946 switch (c)
7947 {
7948 case '\0':
7949 goto finished_with_string;
7950
7951 case CTLESC:
7952 sindex++;
7953 #if HANDLE_MULTIBYTE
7954 if (MB_CUR_MAX > 1 && string[sindex])
7955 {
7956 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7957 }
7958 else
7959 #endif
7960 {
7961 temp = (char *)xmalloc (3);
7962 temp[0] = CTLESC;
7963 temp[1] = c = string[sindex];
7964 temp[2] = '\0';
7965 }
7966
7967 dollar_add_string:
7968 if (string[sindex])
7969 sindex++;
7970
7971 add_string:
7972 if (temp)
7973 {
7974 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
7975 temp = (char *)0;
7976 }
7977
7978 break;
7979
7980 #if defined (PROCESS_SUBSTITUTION)
7981 /* Process substitution. */
7982 case '<':
7983 case '>':
7984 {
7985 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
7986 {
7987 sindex--; /* add_character: label increments sindex */
7988 goto add_character;
7989 }
7990 else
7991 t_index = sindex + 1; /* skip past both '<' and LPAREN */
7992
7993 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
7994 sindex = t_index;
7995
7996 /* If the process substitution specification is `<()', we want to
7997 open the pipe for writing in the child and produce output; if
7998 it is `>()', we want to open the pipe for reading in the child
7999 and consume input. */
8000 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
8001
8002 FREE (temp1);
8003
8004 goto dollar_add_string;
8005 }
8006 #endif /* PROCESS_SUBSTITUTION */
8007
8008 case '=':
8009 /* Posix.2 section 3.6.1 says that tildes following `=' in words
8010 which are not assignment statements are not expanded. If the
8011 shell isn't in posix mode, though, we perform tilde expansion
8012 on `likely candidate' unquoted assignment statements (flags
8013 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
8014 contains an unquoted :~ or =~. Something to think about: we
8015 now have a flag that says to perform tilde expansion on arguments
8016 to `assignment builtins' like declare and export that look like
8017 assignment statements. We now do tilde expansion on such words
8018 even in POSIX mode. */
8019 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
8020 {
8021 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8022 goto add_ifs_character;
8023 else
8024 goto add_character;
8025 }
8026 /* If we're not in posix mode or forcing assignment-statement tilde
8027 expansion, note where the `=' appears in the word and prepare to
8028 do tilde expansion following the first `='. */
8029 if ((word->flags & W_ASSIGNMENT) &&
8030 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8031 assignoff == -1 && sindex > 0)
8032 assignoff = sindex;
8033 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
8034 word->flags |= W_ITILDE;
8035 #if 0
8036 else if ((word->flags & W_ASSIGNMENT) &&
8037 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8038 string[sindex+1] == '~')
8039 word->flags |= W_ITILDE;
8040 #endif
8041 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8042 goto add_ifs_character;
8043 else
8044 goto add_character;
8045
8046 case ':':
8047 if (word->flags & W_NOTILDE)
8048 {
8049 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8050 goto add_ifs_character;
8051 else
8052 goto add_character;
8053 }
8054
8055 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
8056 string[sindex+1] == '~')
8057 word->flags |= W_ITILDE;
8058
8059 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
8060 goto add_ifs_character;
8061 else
8062 goto add_character;
8063
8064 case '~':
8065 /* If the word isn't supposed to be tilde expanded, or we're not
8066 at the start of a word or after an unquoted : or = in an
8067 assignment statement, we don't do tilde expansion. */
8068 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
8069 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
8070 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8071 {
8072 word->flags &= ~W_ITILDE;
8073 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
8074 goto add_ifs_character;
8075 else
8076 goto add_character;
8077 }
8078
8079 if (word->flags & W_ASSIGNRHS)
8080 tflag = 2;
8081 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
8082 tflag = 1;
8083 else
8084 tflag = 0;
8085
8086 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
8087
8088 word->flags &= ~W_ITILDE;
8089
8090 if (temp && *temp && t_index > 0)
8091 {
8092 temp1 = bash_tilde_expand (temp, tflag);
8093 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
8094 {
8095 FREE (temp);
8096 FREE (temp1);
8097 goto add_character; /* tilde expansion failed */
8098 }
8099 free (temp);
8100 temp = temp1;
8101 sindex += t_index;
8102 goto add_quoted_string; /* XXX was add_string */
8103 }
8104 else
8105 {
8106 FREE (temp);
8107 goto add_character;
8108 }
8109
8110 case '$':
8111 if (expanded_something)
8112 *expanded_something = 1;
8113
8114 has_dollar_at = 0;
8115 pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
8116 if (word->flags & W_NOSPLIT2)
8117 pflags |= PF_NOSPLIT2;
8118 tword = param_expand (string, &sindex, quoted, expanded_something,
8119 &has_dollar_at, &quoted_dollar_at,
8120 &had_quoted_null, pflags);
8121
8122 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
8123 {
8124 free (string);
8125 free (istring);
8126 return ((tword == &expand_wdesc_error) ? &expand_word_error
8127 : &expand_word_fatal);
8128 }
8129 if (contains_dollar_at && has_dollar_at)
8130 *contains_dollar_at = 1;
8131
8132 if (tword && (tword->flags & W_HASQUOTEDNULL))
8133 had_quoted_null = 1;
8134
8135 temp = tword->word;
8136 dispose_word_desc (tword);
8137
8138 goto add_string;
8139 break;
8140
8141 case '`': /* Backquoted command substitution. */
8142 {
8143 t_index = sindex++;
8144
8145 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
8146 /* The test of sindex against t_index is to allow bare instances of
8147 ` to pass through, for backwards compatibility. */
8148 if (temp == &extract_string_error || temp == &extract_string_fatal)
8149 {
8150 if (sindex - 1 == t_index)
8151 {
8152 sindex = t_index;
8153 goto add_character;
8154 }
8155 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
8156 free (string);
8157 free (istring);
8158 return ((temp == &extract_string_error) ? &expand_word_error
8159 : &expand_word_fatal);
8160 }
8161
8162 if (expanded_something)
8163 *expanded_something = 1;
8164
8165 if (word->flags & W_NOCOMSUB)
8166 /* sindex + 1 because string[sindex] == '`' */
8167 temp1 = substring (string, t_index, sindex + 1);
8168 else
8169 {
8170 de_backslash (temp);
8171 tword = command_substitute (temp, quoted);
8172 temp1 = tword ? tword->word : (char *)NULL;
8173 if (tword)
8174 dispose_word_desc (tword);
8175 }
8176 FREE (temp);
8177 temp = temp1;
8178 goto dollar_add_string;
8179 }
8180
8181 case '\\':
8182 if (string[sindex + 1] == '\n')
8183 {
8184 sindex += 2;
8185 continue;
8186 }
8187
8188 c = string[++sindex];
8189
8190 if (quoted & Q_HERE_DOCUMENT)
8191 tflag = CBSHDOC;
8192 else if (quoted & Q_DOUBLE_QUOTES)
8193 tflag = CBSDQUOTE;
8194 else
8195 tflag = 0;
8196
8197 /* From Posix discussion on austin-group list: Backslash escaping
8198 a } in ${...} is removed. Issue 0000221 */
8199 if ((quoted & Q_DOLBRACE) && c == RBRACE)
8200 {
8201 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8202 }
8203 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
8204 {
8205 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
8206 }
8207 else if (c == 0)
8208 {
8209 c = CTLNUL;
8210 sindex--; /* add_character: label increments sindex */
8211 goto add_character;
8212 }
8213 else
8214 {
8215 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8216 }
8217
8218 sindex++;
8219 add_twochars:
8220 /* BEFORE jumping here, we need to increment sindex if appropriate */
8221 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
8222 DEFAULT_ARRAY_SIZE);
8223 istring[istring_index++] = twochars[0];
8224 istring[istring_index++] = twochars[1];
8225 istring[istring_index] = '\0';
8226
8227 break;
8228
8229 case '"':
8230 #if 0
8231 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8232 #else
8233 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8234 #endif
8235 goto add_character;
8236
8237 t_index = ++sindex;
8238 temp = string_extract_double_quoted (string, &sindex, 0);
8239
8240 /* If the quotes surrounded the entire string, then the
8241 whole word was quoted. */
8242 quoted_state = (t_index == 1 && string[sindex] == '\0')
8243 ? WHOLLY_QUOTED
8244 : PARTIALLY_QUOTED;
8245
8246 if (temp && *temp)
8247 {
8248 tword = alloc_word_desc ();
8249 tword->word = temp;
8250
8251 temp = (char *)NULL;
8252
8253 has_dollar_at = 0;
8254 /* Need to get W_HASQUOTEDNULL flag through this function. */
8255 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
8256
8257 if (list == &expand_word_error || list == &expand_word_fatal)
8258 {
8259 free (istring);
8260 free (string);
8261 /* expand_word_internal has already freed temp_word->word
8262 for us because of the way it prints error messages. */
8263 tword->word = (char *)NULL;
8264 dispose_word (tword);
8265 return list;
8266 }
8267
8268 dispose_word (tword);
8269
8270 /* "$@" (a double-quoted dollar-at) expands into nothing,
8271 not even a NULL word, when there are no positional
8272 parameters. */
8273 if (list == 0 && has_dollar_at)
8274 {
8275 quoted_dollar_at++;
8276 break;
8277 }
8278
8279 /* If we get "$@", we know we have expanded something, so we
8280 need to remember it for the final split on $IFS. This is
8281 a special case; it's the only case where a quoted string
8282 can expand into more than one word. It's going to come back
8283 from the above call to expand_word_internal as a list with
8284 a single word, in which all characters are quoted and
8285 separated by blanks. What we want to do is to turn it back
8286 into a list for the next piece of code. */
8287 if (list)
8288 dequote_list (list);
8289
8290 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
8291 had_quoted_null = 1;
8292
8293 if (has_dollar_at)
8294 {
8295 quoted_dollar_at++;
8296 if (contains_dollar_at)
8297 *contains_dollar_at = 1;
8298 if (expanded_something)
8299 *expanded_something = 1;
8300 }
8301 }
8302 else
8303 {
8304 /* What we have is "". This is a minor optimization. */
8305 FREE (temp);
8306 list = (WORD_LIST *)NULL;
8307 }
8308
8309 /* The code above *might* return a list (consider the case of "$@",
8310 where it returns "$1", "$2", etc.). We can't throw away the
8311 rest of the list, and we have to make sure each word gets added
8312 as quoted. We test on tresult->next: if it is non-NULL, we
8313 quote the whole list, save it to a string with string_list, and
8314 add that string. We don't need to quote the results of this
8315 (and it would be wrong, since that would quote the separators
8316 as well), so we go directly to add_string. */
8317 if (list)
8318 {
8319 if (list->next)
8320 {
8321 #if 0
8322 if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
8323 temp = string_list_internal (quote_list (list), " ");
8324 else
8325 #endif
8326 /* Testing quoted_dollar_at makes sure that "$@" is
8327 split correctly when $IFS does not contain a space. */
8328 temp = quoted_dollar_at
8329 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
8330 : string_list (quote_list (list));
8331 dispose_words (list);
8332 goto add_string;
8333 }
8334 else
8335 {
8336 temp = savestring (list->word->word);
8337 tflag = list->word->flags;
8338 dispose_words (list);
8339
8340 /* If the string is not a quoted null string, we want
8341 to remove any embedded unquoted CTLNUL characters.
8342 We do not want to turn quoted null strings back into
8343 the empty string, though. We do this because we
8344 want to remove any quoted nulls from expansions that
8345 contain other characters. For example, if we have
8346 x"$*"y or "x$*y" and there are no positional parameters,
8347 the $* should expand into nothing. */
8348 /* We use the W_HASQUOTEDNULL flag to differentiate the
8349 cases: a quoted null character as above and when
8350 CTLNUL is contained in the (non-null) expansion
8351 of some variable. We use the had_quoted_null flag to
8352 pass the value through this function to its caller. */
8353 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
8354 remove_quoted_nulls (temp); /* XXX */
8355 }
8356 }
8357 else
8358 temp = (char *)NULL;
8359
8360 /* We do not want to add quoted nulls to strings that are only
8361 partially quoted; we can throw them away. */
8362 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
8363 continue;
8364
8365 add_quoted_string:
8366
8367 if (temp)
8368 {
8369 temp1 = temp;
8370 temp = quote_string (temp);
8371 free (temp1);
8372 goto add_string;
8373 }
8374 else
8375 {
8376 /* Add NULL arg. */
8377 c = CTLNUL;
8378 sindex--; /* add_character: label increments sindex */
8379 goto add_character;
8380 }
8381
8382 /* break; */
8383
8384 case '\'':
8385 #if 0
8386 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8387 #else
8388 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8389 #endif
8390 goto add_character;
8391
8392 t_index = ++sindex;
8393 temp = string_extract_single_quoted (string, &sindex);
8394
8395 /* If the entire STRING was surrounded by single quotes,
8396 then the string is wholly quoted. */
8397 quoted_state = (t_index == 1 && string[sindex] == '\0')
8398 ? WHOLLY_QUOTED
8399 : PARTIALLY_QUOTED;
8400
8401 /* If all we had was '', it is a null expansion. */
8402 if (*temp == '\0')
8403 {
8404 free (temp);
8405 temp = (char *)NULL;
8406 }
8407 else
8408 remove_quoted_escapes (temp); /* ??? */
8409
8410 /* We do not want to add quoted nulls to strings that are only
8411 partially quoted; such nulls are discarded. */
8412 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
8413 continue;
8414
8415 /* If we have a quoted null expansion, add a quoted NULL to istring. */
8416 if (temp == 0)
8417 {
8418 c = CTLNUL;
8419 sindex--; /* add_character: label increments sindex */
8420 goto add_character;
8421 }
8422 else
8423 goto add_quoted_string;
8424
8425 /* break; */
8426
8427 default:
8428 /* This is the fix for " $@ " */
8429 add_ifs_character:
8430 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
8431 {
8432 if (string[sindex]) /* from old goto dollar_add_string */
8433 sindex++;
8434 if (c == 0)
8435 {
8436 c = CTLNUL;
8437 goto add_character;
8438 }
8439 else
8440 {
8441 #if HANDLE_MULTIBYTE
8442 if (MB_CUR_MAX > 1)
8443 sindex--;
8444
8445 if (MB_CUR_MAX > 1)
8446 {
8447 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
8448 }
8449 else
8450 #endif
8451 {
8452 twochars[0] = CTLESC;
8453 twochars[1] = c;
8454 goto add_twochars;
8455 }
8456 }
8457 }
8458
8459 SADD_MBCHAR (temp, string, sindex, string_size);
8460
8461 add_character:
8462 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
8463 DEFAULT_ARRAY_SIZE);
8464 istring[istring_index++] = c;
8465 istring[istring_index] = '\0';
8466
8467 /* Next character. */
8468 sindex++;
8469 }
8470 }
8471
8472 finished_with_string:
8473 /* OK, we're ready to return. If we have a quoted string, and
8474 quoted_dollar_at is not set, we do no splitting at all; otherwise
8475 we split on ' '. The routines that call this will handle what to
8476 do if nothing has been expanded. */
8477
8478 /* Partially and wholly quoted strings which expand to the empty
8479 string are retained as an empty arguments. Unquoted strings
8480 which expand to the empty string are discarded. The single
8481 exception is the case of expanding "$@" when there are no
8482 positional parameters. In that case, we discard the expansion. */
8483
8484 /* Because of how the code that handles "" and '' in partially
8485 quoted strings works, we need to make ISTRING into a QUOTED_NULL
8486 if we saw quoting characters, but the expansion was empty.
8487 "" and '' are tossed away before we get to this point when
8488 processing partially quoted strings. This makes "" and $xxx""
8489 equivalent when xxx is unset. We also look to see whether we
8490 saw a quoted null from a ${} expansion and add one back if we
8491 need to. */
8492
8493 /* If we expand to nothing and there were no single or double quotes
8494 in the word, we throw it away. Otherwise, we return a NULL word.
8495 The single exception is for $@ surrounded by double quotes when
8496 there are no positional parameters. In that case, we also throw
8497 the word away. */
8498
8499 if (*istring == '\0')
8500 {
8501 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
8502 {
8503 istring[0] = CTLNUL;
8504 istring[1] = '\0';
8505 tword = make_bare_word (istring);
8506 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8507 list = make_word_list (tword, (WORD_LIST *)NULL);
8508 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8509 tword->flags |= W_QUOTED;
8510 }
8511 /* According to sh, ksh, and Posix.2, if a word expands into nothing
8512 and a double-quoted "$@" appears anywhere in it, then the entire
8513 word is removed. */
8514 else if (quoted_state == UNQUOTED || quoted_dollar_at)
8515 list = (WORD_LIST *)NULL;
8516 #if 0
8517 else
8518 {
8519 tword = make_bare_word (istring);
8520 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8521 tword->flags |= W_QUOTED;
8522 list = make_word_list (tword, (WORD_LIST *)NULL);
8523 }
8524 #else
8525 else
8526 list = (WORD_LIST *)NULL;
8527 #endif
8528 }
8529 else if (word->flags & W_NOSPLIT)
8530 {
8531 tword = make_bare_word (istring);
8532 if (word->flags & W_ASSIGNMENT)
8533 tword->flags |= W_ASSIGNMENT; /* XXX */
8534 if (word->flags & W_COMPASSIGN)
8535 tword->flags |= W_COMPASSIGN; /* XXX */
8536 if (word->flags & W_NOGLOB)
8537 tword->flags |= W_NOGLOB; /* XXX */
8538 if (word->flags & W_NOEXPAND)
8539 tword->flags |= W_NOEXPAND; /* XXX */
8540 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8541 tword->flags |= W_QUOTED;
8542 if (had_quoted_null)
8543 tword->flags |= W_HASQUOTEDNULL;
8544 list = make_word_list (tword, (WORD_LIST *)NULL);
8545 }
8546 else
8547 {
8548 char *ifs_chars;
8549
8550 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
8551
8552 /* If we have $@, we need to split the results no matter what. If
8553 IFS is unset or NULL, string_list_dollar_at has separated the
8554 positional parameters with a space, so we split on space (we have
8555 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
8556 string_list_dollar_at has separated the positional parameters
8557 with the first character of $IFS, so we split on $IFS. */
8558 if (has_dollar_at && ifs_chars)
8559 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
8560 else
8561 {
8562 tword = make_bare_word (istring);
8563 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8564 tword->flags |= W_QUOTED;
8565 if (word->flags & W_ASSIGNMENT)
8566 tword->flags |= W_ASSIGNMENT;
8567 if (word->flags & W_COMPASSIGN)
8568 tword->flags |= W_COMPASSIGN;
8569 if (word->flags & W_NOGLOB)
8570 tword->flags |= W_NOGLOB;
8571 if (word->flags & W_NOEXPAND)
8572 tword->flags |= W_NOEXPAND;
8573 if (had_quoted_null)
8574 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8575 list = make_word_list (tword, (WORD_LIST *)NULL);
8576 }
8577 }
8578
8579 free (istring);
8580 return (list);
8581 }
8582
8583 /* **************************************************************** */
8584 /* */
8585 /* Functions for Quote Removal */
8586 /* */
8587 /* **************************************************************** */
8588
8589 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
8590 backslash quoting rules for within double quotes or a here document. */
8591 char *
8592 string_quote_removal (string, quoted)
8593 char *string;
8594 int quoted;
8595 {
8596 size_t slen;
8597 char *r, *result_string, *temp, *send;
8598 int sindex, tindex, dquote;
8599 unsigned char c;
8600 DECLARE_MBSTATE;
8601
8602 /* The result can be no longer than the original string. */
8603 slen = strlen (string);
8604 send = string + slen;
8605
8606 r = result_string = (char *)xmalloc (slen + 1);
8607
8608 for (dquote = sindex = 0; c = string[sindex];)
8609 {
8610 switch (c)
8611 {
8612 case '\\':
8613 c = string[++sindex];
8614 if (c == 0)
8615 {
8616 *r++ = '\\';
8617 break;
8618 }
8619 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
8620 *r++ = '\\';
8621 /* FALLTHROUGH */
8622
8623 default:
8624 SCOPY_CHAR_M (r, string, send, sindex);
8625 break;
8626
8627 case '\'':
8628 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
8629 {
8630 *r++ = c;
8631 sindex++;
8632 break;
8633 }
8634 tindex = sindex + 1;
8635 temp = string_extract_single_quoted (string, &tindex);
8636 if (temp)
8637 {
8638 strcpy (r, temp);
8639 r += strlen (r);
8640 free (temp);
8641 }
8642 sindex = tindex;
8643 break;
8644
8645 case '"':
8646 dquote = 1 - dquote;
8647 sindex++;
8648 break;
8649 }
8650 }
8651 *r = '\0';
8652 return (result_string);
8653 }
8654
8655 #if 0
8656 /* UNUSED */
8657 /* Perform quote removal on word WORD. This allocates and returns a new
8658 WORD_DESC *. */
8659 WORD_DESC *
8660 word_quote_removal (word, quoted)
8661 WORD_DESC *word;
8662 int quoted;
8663 {
8664 WORD_DESC *w;
8665 char *t;
8666
8667 t = string_quote_removal (word->word, quoted);
8668 w = alloc_word_desc ();
8669 w->word = t ? t : savestring ("");
8670 return (w);
8671 }
8672
8673 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8674 the members of the list are treated as if they are surrounded by
8675 double quotes. Return a new list, or NULL if LIST is NULL. */
8676 WORD_LIST *
8677 word_list_quote_removal (list, quoted)
8678 WORD_LIST *list;
8679 int quoted;
8680 {
8681 WORD_LIST *result, *t, *tresult, *e;
8682
8683 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8684 {
8685 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
8686 #if 0
8687 result = (WORD_LIST *) list_append (result, tresult);
8688 #else
8689 if (result == 0)
8690 result = e = tresult;
8691 else
8692 {
8693 e->next = tresult;
8694 while (e->next)
8695 e = e->next;
8696 }
8697 #endif
8698 }
8699 return (result);
8700 }
8701 #endif
8702
8703 /*******************************************
8704 * *
8705 * Functions to perform word splitting *
8706 * *
8707 *******************************************/
8708
8709 void
8710 setifs (v)
8711 SHELL_VAR *v;
8712 {
8713 char *t;
8714 unsigned char uc;
8715
8716 ifs_var = v;
8717 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
8718
8719 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8720 handle multibyte chars in IFS */
8721 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8722 for (t = ifs_value ; t && *t; t++)
8723 {
8724 uc = *t;
8725 ifs_cmap[uc] = 1;
8726 }
8727
8728 #if defined (HANDLE_MULTIBYTE)
8729 if (ifs_value == 0)
8730 {
8731 ifs_firstc[0] = '\0';
8732 ifs_firstc_len = 1;
8733 }
8734 else
8735 {
8736 size_t ifs_len;
8737 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8738 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
8739 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
8740 {
8741 ifs_firstc[0] = ifs_value[0];
8742 ifs_firstc[1] = '\0';
8743 ifs_firstc_len = 1;
8744 }
8745 else
8746 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8747 }
8748 #else
8749 ifs_firstc = ifs_value ? *ifs_value : 0;
8750 #endif
8751 }
8752
8753 char *
8754 getifs ()
8755 {
8756 return ifs_value;
8757 }
8758
8759 /* This splits a single word into a WORD LIST on $IFS, but only if the word
8760 is not quoted. list_string () performs quote removal for us, even if we
8761 don't do any splitting. */
8762 WORD_LIST *
8763 word_split (w, ifs_chars)
8764 WORD_DESC *w;
8765 char *ifs_chars;
8766 {
8767 WORD_LIST *result;
8768
8769 if (w)
8770 {
8771 char *xifs;
8772
8773 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8774 result = list_string (w->word, xifs, w->flags & W_QUOTED);
8775 }
8776 else
8777 result = (WORD_LIST *)NULL;
8778
8779 return (result);
8780 }
8781
8782 /* Perform word splitting on LIST and return the RESULT. It is possible
8783 to return (WORD_LIST *)NULL. */
8784 static WORD_LIST *
8785 word_list_split (list)
8786 WORD_LIST *list;
8787 {
8788 WORD_LIST *result, *t, *tresult, *e;
8789
8790 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
8791 {
8792 tresult = word_split (t->word, ifs_value);
8793 if (result == 0)
8794 result = e = tresult;
8795 else
8796 {
8797 e->next = tresult;
8798 while (e->next)
8799 e = e->next;
8800 }
8801 }
8802 return (result);
8803 }
8804
8805 /**************************************************
8806 * *
8807 * Functions to expand an entire WORD_LIST *
8808 * *
8809 **************************************************/
8810
8811 /* Do any word-expansion-specific cleanup and jump to top_level */
8812 static void
8813 exp_jump_to_top_level (v)
8814 int v;
8815 {
8816 set_pipestatus_from_exit (last_command_exit_value);
8817
8818 /* Cleanup code goes here. */
8819 expand_no_split_dollar_star = 0; /* XXX */
8820 expanding_redir = 0;
8821 assigning_in_environment = 0;
8822
8823 if (parse_and_execute_level == 0)
8824 top_level_cleanup (); /* from sig.c */
8825
8826 jump_to_top_level (v);
8827 }
8828
8829 /* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8830 ELIST, and set ELIST to the new list. */
8831 #define PREPEND_LIST(nlist, elist) \
8832 do { nlist->next = elist; elist = nlist; } while (0)
8833
8834 /* Separate out any initial variable assignments from TLIST. If set -k has
8835 been executed, remove all assignment statements from TLIST. Initial
8836 variable assignments and other environment assignments are placed
8837 on SUBST_ASSIGN_VARLIST. */
8838 static WORD_LIST *
8839 separate_out_assignments (tlist)
8840 WORD_LIST *tlist;
8841 {
8842 register WORD_LIST *vp, *lp;
8843
8844 if (tlist == 0)
8845 return ((WORD_LIST *)NULL);
8846
8847 if (subst_assign_varlist)
8848 dispose_words (subst_assign_varlist); /* Clean up after previous error */
8849
8850 subst_assign_varlist = (WORD_LIST *)NULL;
8851 vp = lp = tlist;
8852
8853 /* Separate out variable assignments at the start of the command.
8854 Loop invariant: vp->next == lp
8855 Loop postcondition:
8856 lp = list of words left after assignment statements skipped
8857 tlist = original list of words
8858 */
8859 while (lp && (lp->word->flags & W_ASSIGNMENT))
8860 {
8861 vp = lp;
8862 lp = lp->next;
8863 }
8864
8865 /* If lp != tlist, we have some initial assignment statements.
8866 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8867 words and TLIST point to the remaining words. */
8868 if (lp != tlist)
8869 {
8870 subst_assign_varlist = tlist;
8871 /* ASSERT(vp->next == lp); */
8872 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
8873 tlist = lp; /* remainder of word list */
8874 }
8875
8876 /* vp == end of variable list */
8877 /* tlist == remainder of original word list without variable assignments */
8878 if (!tlist)
8879 /* All the words in tlist were assignment statements */
8880 return ((WORD_LIST *)NULL);
8881
8882 /* ASSERT(tlist != NULL); */
8883 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
8884
8885 /* If the -k option is in effect, we need to go through the remaining
8886 words, separate out the assignment words, and place them on
8887 SUBST_ASSIGN_VARLIST. */
8888 if (place_keywords_in_env)
8889 {
8890 WORD_LIST *tp; /* tp == running pointer into tlist */
8891
8892 tp = tlist;
8893 lp = tlist->next;
8894
8895 /* Loop Invariant: tp->next == lp */
8896 /* Loop postcondition: tlist == word list without assignment statements */
8897 while (lp)
8898 {
8899 if (lp->word->flags & W_ASSIGNMENT)
8900 {
8901 /* Found an assignment statement, add this word to end of
8902 subst_assign_varlist (vp). */
8903 if (!subst_assign_varlist)
8904 subst_assign_varlist = vp = lp;
8905 else
8906 {
8907 vp->next = lp;
8908 vp = lp;
8909 }
8910
8911 /* Remove the word pointed to by LP from TLIST. */
8912 tp->next = lp->next;
8913 /* ASSERT(vp == lp); */
8914 lp->next = (WORD_LIST *)NULL;
8915 lp = tp->next;
8916 }
8917 else
8918 {
8919 tp = lp;
8920 lp = lp->next;
8921 }
8922 }
8923 }
8924 return (tlist);
8925 }
8926
8927 #define WEXP_VARASSIGN 0x001
8928 #define WEXP_BRACEEXP 0x002
8929 #define WEXP_TILDEEXP 0x004
8930 #define WEXP_PARAMEXP 0x008
8931 #define WEXP_PATHEXP 0x010
8932
8933 /* All of the expansions, including variable assignments at the start of
8934 the list. */
8935 #define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8936
8937 /* All of the expansions except variable assignments at the start of
8938 the list. */
8939 #define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
8940
8941 /* All of the `shell expansions': brace expansion, tilde expansion, parameter
8942 expansion, command substitution, arithmetic expansion, word splitting, and
8943 quote removal. */
8944 #define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
8945
8946 /* Take the list of words in LIST and do the various substitutions. Return
8947 a new list of words which is the expanded list, and without things like
8948 variable assignments. */
8949
8950 WORD_LIST *
8951 expand_words (list)
8952 WORD_LIST *list;
8953 {
8954 return (expand_word_list_internal (list, WEXP_ALL));
8955 }
8956
8957 /* Same as expand_words (), but doesn't hack variable or environment
8958 variables. */
8959 WORD_LIST *
8960 expand_words_no_vars (list)
8961 WORD_LIST *list;
8962 {
8963 return (expand_word_list_internal (list, WEXP_NOVARS));
8964 }
8965
8966 WORD_LIST *
8967 expand_words_shellexp (list)
8968 WORD_LIST *list;
8969 {
8970 return (expand_word_list_internal (list, WEXP_SHELLEXP));
8971 }
8972
8973 static WORD_LIST *
8974 glob_expand_word_list (tlist, eflags)
8975 WORD_LIST *tlist;
8976 int eflags;
8977 {
8978 char **glob_array, *temp_string;
8979 register int glob_index;
8980 WORD_LIST *glob_list, *output_list, *disposables, *next;
8981 WORD_DESC *tword;
8982
8983 output_list = disposables = (WORD_LIST *)NULL;
8984 glob_array = (char **)NULL;
8985 while (tlist)
8986 {
8987 /* For each word, either globbing is attempted or the word is
8988 added to orig_list. If globbing succeeds, the results are
8989 added to orig_list and the word (tlist) is added to the list
8990 of disposable words. If globbing fails and failed glob
8991 expansions are left unchanged (the shell default), the
8992 original word is added to orig_list. If globbing fails and
8993 failed glob expansions are removed, the original word is
8994 added to the list of disposable words. orig_list ends up
8995 in reverse order and requires a call to REVERSE_LIST to
8996 be set right. After all words are examined, the disposable
8997 words are freed. */
8998 next = tlist->next;
8999
9000 /* If the word isn't an assignment and contains an unquoted
9001 pattern matching character, then glob it. */
9002 if ((tlist->word->flags & W_NOGLOB) == 0 &&
9003 unquoted_glob_pattern_p (tlist->word->word))
9004 {
9005 glob_array = shell_glob_filename (tlist->word->word);
9006
9007 /* Handle error cases.
9008 I don't think we should report errors like "No such file
9009 or directory". However, I would like to report errors
9010 like "Read failed". */
9011
9012 if (glob_array == 0 || GLOB_FAILED (glob_array))
9013 {
9014 glob_array = (char **)xmalloc (sizeof (char *));
9015 glob_array[0] = (char *)NULL;
9016 }
9017
9018 /* Dequote the current word in case we have to use it. */
9019 if (glob_array[0] == NULL)
9020 {
9021 temp_string = dequote_string (tlist->word->word);
9022 free (tlist->word->word);
9023 tlist->word->word = temp_string;
9024 }
9025
9026 /* Make the array into a word list. */
9027 glob_list = (WORD_LIST *)NULL;
9028 for (glob_index = 0; glob_array[glob_index]; glob_index++)
9029 {
9030 tword = make_bare_word (glob_array[glob_index]);
9031 tword->flags |= W_GLOBEXP; /* XXX */
9032 glob_list = make_word_list (tword, glob_list);
9033 }
9034
9035 if (glob_list)
9036 {
9037 output_list = (WORD_LIST *)list_append (glob_list, output_list);
9038 PREPEND_LIST (tlist, disposables);
9039 }
9040 else if (fail_glob_expansion != 0)
9041 {
9042 report_error (_("no match: %s"), tlist->word->word);
9043 exp_jump_to_top_level (DISCARD);
9044 }
9045 else if (allow_null_glob_expansion == 0)
9046 {
9047 /* Failed glob expressions are left unchanged. */
9048 PREPEND_LIST (tlist, output_list);
9049 }
9050 else
9051 {
9052 /* Failed glob expressions are removed. */
9053 PREPEND_LIST (tlist, disposables);
9054 }
9055 }
9056 else
9057 {
9058 /* Dequote the string. */
9059 temp_string = dequote_string (tlist->word->word);
9060 free (tlist->word->word);
9061 tlist->word->word = temp_string;
9062 PREPEND_LIST (tlist, output_list);
9063 }
9064
9065 strvec_dispose (glob_array);
9066 glob_array = (char **)NULL;
9067
9068 tlist = next;
9069 }
9070
9071 if (disposables)
9072 dispose_words (disposables);
9073
9074 if (output_list)
9075 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9076
9077 return (output_list);
9078 }
9079
9080 #if defined (BRACE_EXPANSION)
9081 static WORD_LIST *
9082 brace_expand_word_list (tlist, eflags)
9083 WORD_LIST *tlist;
9084 int eflags;
9085 {
9086 register char **expansions;
9087 char *temp_string;
9088 WORD_LIST *disposables, *output_list, *next;
9089 WORD_DESC *w;
9090 int eindex;
9091
9092 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
9093 {
9094 next = tlist->next;
9095
9096 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9097 {
9098 /*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
9099 PREPEND_LIST (tlist, output_list);
9100 continue;
9101 }
9102
9103 /* Only do brace expansion if the word has a brace character. If
9104 not, just add the word list element to BRACES and continue. In
9105 the common case, at least when running shell scripts, this will
9106 degenerate to a bunch of calls to `mbschr', and then what is
9107 basically a reversal of TLIST into BRACES, which is corrected
9108 by a call to REVERSE_LIST () on BRACES when the end of TLIST
9109 is reached. */
9110 if (mbschr (tlist->word->word, LBRACE))
9111 {
9112 expansions = brace_expand (tlist->word->word);
9113
9114 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
9115 {
9116 w = make_word (temp_string);
9117 /* If brace expansion didn't change the word, preserve
9118 the flags. We may want to preserve the flags
9119 unconditionally someday -- XXX */
9120 if (STREQ (temp_string, tlist->word->word))
9121 w->flags = tlist->word->flags;
9122 output_list = make_word_list (w, output_list);
9123 free (expansions[eindex]);
9124 }
9125 free (expansions);
9126
9127 /* Add TLIST to the list of words to be freed after brace
9128 expansion has been performed. */
9129 PREPEND_LIST (tlist, disposables);
9130 }
9131 else
9132 PREPEND_LIST (tlist, output_list);
9133 }
9134
9135 if (disposables)
9136 dispose_words (disposables);
9137
9138 if (output_list)
9139 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9140
9141 return (output_list);
9142 }
9143 #endif
9144
9145 #if defined (ARRAY_VARS)
9146 /* Take WORD, a compound associative array assignment, and internally run
9147 'declare -A w', where W is the variable name portion of WORD. */
9148 static int
9149 make_internal_declare (word, option)
9150 char *word;
9151 char *option;
9152 {
9153 int t;
9154 WORD_LIST *wl;
9155 WORD_DESC *w;
9156
9157 w = make_word (word);
9158
9159 t = assignment (w->word, 0);
9160 w->word[t] = '\0';
9161
9162 wl = make_word_list (w, (WORD_LIST *)NULL);
9163 wl = make_word_list (make_word (option), wl);
9164
9165 return (declare_builtin (wl));
9166 }
9167 #endif
9168
9169 static WORD_LIST *
9170 shell_expand_word_list (tlist, eflags)
9171 WORD_LIST *tlist;
9172 int eflags;
9173 {
9174 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
9175 int expanded_something, has_dollar_at;
9176 char *temp_string;
9177
9178 /* We do tilde expansion all the time. This is what 1003.2 says. */
9179 new_list = (WORD_LIST *)NULL;
9180 for (orig_list = tlist; tlist; tlist = next)
9181 {
9182 temp_string = tlist->word->word;
9183
9184 next = tlist->next;
9185
9186 #if defined (ARRAY_VARS)
9187 /* If this is a compound array assignment to a builtin that accepts
9188 such assignments (e.g., `declare'), take the assignment and perform
9189 it separately, handling the semantics of declarations inside shell
9190 functions. This avoids the double-evaluation of such arguments,
9191 because `declare' does some evaluation of compound assignments on
9192 its own. */
9193 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9194 {
9195 int t;
9196
9197 if (tlist->word->flags & W_ASSIGNASSOC)
9198 make_internal_declare (tlist->word->word, "-A");
9199
9200 t = do_word_assignment (tlist->word, 0);
9201 if (t == 0)
9202 {
9203 last_command_exit_value = EXECUTION_FAILURE;
9204 exp_jump_to_top_level (DISCARD);
9205 }
9206
9207 /* Now transform the word as ksh93 appears to do and go on */
9208 t = assignment (tlist->word->word, 0);
9209 tlist->word->word[t] = '\0';
9210 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
9211 }
9212 #endif
9213
9214 expanded_something = 0;
9215 expanded = expand_word_internal
9216 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
9217
9218 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
9219 {
9220 /* By convention, each time this error is returned,
9221 tlist->word->word has already been freed. */
9222 tlist->word->word = (char *)NULL;
9223
9224 /* Dispose our copy of the original list. */
9225 dispose_words (orig_list);
9226 /* Dispose the new list we're building. */
9227 dispose_words (new_list);
9228
9229 last_command_exit_value = EXECUTION_FAILURE;
9230 if (expanded == &expand_word_error)
9231 exp_jump_to_top_level (DISCARD);
9232 else
9233 exp_jump_to_top_level (FORCE_EOF);
9234 }
9235
9236 /* Don't split words marked W_NOSPLIT. */
9237 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
9238 {
9239 temp_list = word_list_split (expanded);
9240 dispose_words (expanded);
9241 }
9242 else
9243 {
9244 /* If no parameter expansion, command substitution, process
9245 substitution, or arithmetic substitution took place, then
9246 do not do word splitting. We still have to remove quoted
9247 null characters from the result. */
9248 word_list_remove_quoted_nulls (expanded);
9249 temp_list = expanded;
9250 }
9251
9252 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
9253 new_list = (WORD_LIST *)list_append (expanded, new_list);
9254 }
9255
9256 if (orig_list)
9257 dispose_words (orig_list);
9258
9259 if (new_list)
9260 new_list = REVERSE_LIST (new_list, WORD_LIST *);
9261
9262 return (new_list);
9263 }
9264
9265 /* The workhorse for expand_words () and expand_words_no_vars ().
9266 First arg is LIST, a WORD_LIST of words.
9267 Second arg EFLAGS is a flags word controlling which expansions are
9268 performed.
9269
9270 This does all of the substitutions: brace expansion, tilde expansion,
9271 parameter expansion, command substitution, arithmetic expansion,
9272 process substitution, word splitting, and pathname expansion, according
9273 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
9274 set, or for which no expansion is done, do not undergo word splitting.
9275 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
9276 static WORD_LIST *
9277 expand_word_list_internal (list, eflags)
9278 WORD_LIST *list;
9279 int eflags;
9280 {
9281 WORD_LIST *new_list, *temp_list;
9282 int tint;
9283
9284 if (list == 0)
9285 return ((WORD_LIST *)NULL);
9286
9287 garglist = new_list = copy_word_list (list);
9288 if (eflags & WEXP_VARASSIGN)
9289 {
9290 garglist = new_list = separate_out_assignments (new_list);
9291 if (new_list == 0)
9292 {
9293 if (subst_assign_varlist)
9294 {
9295 /* All the words were variable assignments, so they are placed
9296 into the shell's environment. */
9297 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
9298 {
9299 this_command_name = (char *)NULL; /* no arithmetic errors */
9300 tint = do_word_assignment (temp_list->word, 0);
9301 /* Variable assignment errors in non-interactive shells
9302 running in Posix.2 mode cause the shell to exit. */
9303 if (tint == 0)
9304 {
9305 last_command_exit_value = EXECUTION_FAILURE;
9306 if (interactive_shell == 0 && posixly_correct)
9307 exp_jump_to_top_level (FORCE_EOF);
9308 else
9309 exp_jump_to_top_level (DISCARD);
9310 }
9311 }
9312 dispose_words (subst_assign_varlist);
9313 subst_assign_varlist = (WORD_LIST *)NULL;
9314 }
9315 return ((WORD_LIST *)NULL);
9316 }
9317 }
9318
9319 /* Begin expanding the words that remain. The expansions take place on
9320 things that aren't really variable assignments. */
9321
9322 #if defined (BRACE_EXPANSION)
9323 /* Do brace expansion on this word if there are any brace characters
9324 in the string. */
9325 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
9326 new_list = brace_expand_word_list (new_list, eflags);
9327 #endif /* BRACE_EXPANSION */
9328
9329 /* Perform the `normal' shell expansions: tilde expansion, parameter and
9330 variable substitution, command substitution, arithmetic expansion,
9331 and word splitting. */
9332 new_list = shell_expand_word_list (new_list, eflags);
9333
9334 /* Okay, we're almost done. Now let's just do some filename
9335 globbing. */
9336 if (new_list)
9337 {
9338 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
9339 /* Glob expand the word list unless globbing has been disabled. */
9340 new_list = glob_expand_word_list (new_list, eflags);
9341 else
9342 /* Dequote the words, because we're not performing globbing. */
9343 new_list = dequote_list (new_list);
9344 }
9345
9346 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
9347 {
9348 sh_wassign_func_t *assign_func;
9349 int is_special_builtin, is_builtin_or_func;
9350
9351 /* If the remainder of the words expand to nothing, Posix.2 requires
9352 that the variable and environment assignments affect the shell's
9353 environment. */
9354 assign_func = new_list ? assign_in_env : do_word_assignment;
9355 tempenv_assign_error = 0;
9356
9357 is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
9358 /* Posix says that special builtins exit if a variable assignment error
9359 occurs in an assignment preceding it. */
9360 is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
9361
9362 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
9363 {
9364 this_command_name = (char *)NULL;
9365 assigning_in_environment = (assign_func == assign_in_env);
9366 tint = (*assign_func) (temp_list->word, is_builtin_or_func);
9367 assigning_in_environment = 0;
9368 /* Variable assignment errors in non-interactive shells running
9369 in Posix.2 mode cause the shell to exit. */
9370 if (tint == 0)
9371 {
9372 if (assign_func == do_word_assignment)
9373 {
9374 last_command_exit_value = EXECUTION_FAILURE;
9375 if (interactive_shell == 0 && posixly_correct && is_special_builtin)
9376 exp_jump_to_top_level (FORCE_EOF);
9377 else
9378 exp_jump_to_top_level (DISCARD);
9379 }
9380 else
9381 tempenv_assign_error++;
9382 }
9383 }
9384
9385 dispose_words (subst_assign_varlist);
9386 subst_assign_varlist = (WORD_LIST *)NULL;
9387 }
9388
9389 #if 0
9390 tint = list_length (new_list) + 1;
9391 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
9392 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
9393 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
9394 glob_argv_flags[tint] = '\0';
9395 #endif
9396
9397 return (new_list);
9398 }