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