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