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