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