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