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