]> git.ipfire.org Git - thirdparty/bash.git/blame - subst.c
commit bash-20121102 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 5391 if (posixly_correct == 0)
26a8e19c
CR
5392 {
5393 exit_immediately_on_error = 0;
5394 set_shellopts ();
5395 }
726f6388
JA
5396
5397 remove_quoted_escapes (string);
5398
ccc6cda3 5399 startup_state = 2; /* see if we can avoid a fork */
726f6388
JA
5400 /* Give command substitution a place to jump back to on failure,
5401 so we don't go back up to main (). */
5402 result = setjmp (top_level);
5403
bb70624e
JA
5404 /* If we're running a command substitution inside a shell function,
5405 trap `return' so we don't return from the function in the subshell
5406 and go off to never-never land. */
5407 if (result == 0 && return_catch_flag)
5408 function_value = setjmp (return_catch);
5409 else
5410 function_value = 0;
5411
d3a24ed2 5412 if (result == ERREXIT)
5e13499c 5413 rc = last_command_exit_value;
d3a24ed2 5414 else if (result == EXITPROG)
5e13499c 5415 rc = last_command_exit_value;
726f6388 5416 else if (result)
5e13499c 5417 rc = EXECUTION_FAILURE;
bb70624e 5418 else if (function_value)
5e13499c 5419 rc = return_catch_value;
726f6388 5420 else
d3a24ed2
CR
5421 {
5422 subshell_level++;
5423 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
5424 subshell_level--;
d3a24ed2 5425 }
5e13499c
CR
5426
5427 last_command_exit_value = rc;
5428 rc = run_exit_trap ();
d3ad40de
CR
5429#if defined (PROCESS_SUBSTITUTION)
5430 unlink_fifo_list ();
5431#endif
5e13499c 5432 exit (rc);
726f6388
JA
5433 }
5434 else
5435 {
726f6388
JA
5436#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
5437 close_pgrp_pipe ();
5438#endif /* JOB_CONTROL && PGRP_PIPE */
5439
5440 close (fildes[1]);
5441
d3ad40de
CR
5442 tflag = 0;
5443 istring = read_comsub (fildes[0], quoted, &tflag);
ccc6cda3 5444
726f6388
JA
5445 close (fildes[0]);
5446
b72432fd 5447 current_command_subst_pid = pid;
726f6388
JA
5448 last_command_exit_value = wait_for (pid);
5449 last_command_subst_pid = pid;
5450 last_made_pid = old_pid;
5451
5452#if defined (JOB_CONTROL)
5453 /* If last_command_exit_value > 128, then the substituted command
5454 was terminated by a signal. If that signal was SIGINT, then send
5455 SIGINT to ourselves. This will break out of loops, for instance. */
d3a24ed2 5456 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
726f6388
JA
5457 kill (getpid (), SIGINT);
5458
5459 /* wait_for gives the terminal back to shell_pgrp. If some other
cce855bc
JA
5460 process group should have it, give it away to that group here.
5461 pipeline_pgrp is non-zero only while we are constructing a
5462 pipline, so what we are concerned about is whether or not that
5463 pipeline was started in the background. A pipeline started in
5464 the background should never get the tty back here. */
28ef6c31 5465 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
28ef6c31 5466 give_terminal_to (pipeline_pgrp, 0);
726f6388
JA
5467#endif /* JOB_CONTROL */
5468
d3ad40de
CR
5469 ret = alloc_word_desc ();
5470 ret->word = istring;
5471 ret->flags = tflag;
5472
5473 return ret;
726f6388
JA
5474 }
5475}
5476
5477/********************************************************
5478 * *
5479 * Utility functions for parameter expansion *
5480 * *
5481 ********************************************************/
5482
ccc6cda3 5483#if defined (ARRAY_VARS)
ccc6cda3 5484
f73dda09 5485static arrayind_t
ccc6cda3
JA
5486array_length_reference (s)
5487 char *s;
5488{
f73dda09
JA
5489 int len;
5490 arrayind_t ind;
fdf670ea 5491 char *akey;
f73dda09 5492 char *t, c;
ccc6cda3 5493 ARRAY *array;
68dfe178 5494 HASH_TABLE *h;
ccc6cda3
JA
5495 SHELL_VAR *var;
5496
5497 var = array_variable_part (s, &t, &len);
726f6388 5498
ccc6cda3
JA
5499 /* If unbound variables should generate an error, report one and return
5500 failure. */
fdf670ea 5501 if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
726f6388 5502 {
f73dda09 5503 c = *--t;
ccc6cda3 5504 *t = '\0';
0d8616ff 5505 last_command_exit_value = EXECUTION_FAILURE;
7117c2d2 5506 err_unboundvar (s);
f73dda09 5507 *t = c;
ccc6cda3 5508 return (-1);
726f6388 5509 }
ccc6cda3
JA
5510 else if (var == 0)
5511 return 0;
726f6388 5512
28ef6c31
JA
5513 /* We support a couple of expansions for variables that are not arrays.
5514 We'll return the length of the value for v[0], and 1 for v[@] or
5515 v[*]. Return 0 for everything else. */
5516
5517 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
68dfe178 5518 h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
726f6388 5519
ccc6cda3 5520 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
ccc6cda3 5521 {
fdf670ea 5522 if (assoc_p (var))
68dfe178 5523 return (h ? assoc_num_elements (h) : 0);
fdf670ea 5524 else if (array_p (var))
68dfe178 5525 return (array ? array_num_elements (array) : 0);
fdf670ea 5526 else
68dfe178 5527 return (var_isset (var) ? 1 : 0);
ccc6cda3 5528 }
ccc6cda3 5529
fdf670ea
CR
5530 if (assoc_p (var))
5531 {
5532 t[len - 1] = '\0';
09767ff0 5533 akey = expand_assignment_string_to_string (t, 0); /* [ */
fdf670ea
CR
5534 t[len - 1] = ']';
5535 if (akey == 0 || *akey == 0)
5536 {
5537 err_badarraysub (t);
631b20c6 5538 FREE (akey);
fdf670ea
CR
5539 return (-1);
5540 }
5541 t = assoc_reference (assoc_cell (var), akey);
631b20c6 5542 free (akey);
fdf670ea 5543 }
28ef6c31 5544 else
fdf670ea 5545 {
d9e1f41e 5546 ind = array_expand_index (var, t, len);
a7ad477f
CR
5547 /* negative subscripts to indexed arrays count back from end */
5548 if (var && array_p (var) && ind < 0)
5549 ind = array_max_index (array_cell (var)) + 1 + ind;
fdf670ea
CR
5550 if (ind < 0)
5551 {
5552 err_badarraysub (t);
5553 return (-1);
5554 }
5555 if (array_p (var))
5556 t = array_reference (array, ind);
5557 else
5558 t = (ind == 0) ? value_cell (var) : (char *)NULL;
5559 }
28ef6c31 5560
30915f17 5561 len = MB_STRLEN (t);
ccc6cda3 5562 return (len);
726f6388 5563}
ccc6cda3 5564#endif /* ARRAY_VARS */
726f6388
JA
5565
5566static int
5567valid_brace_expansion_word (name, var_is_special)
5568 char *name;
5569 int var_is_special;
5570{
f73dda09 5571 if (DIGIT (*name) && all_digits (name))
726f6388
JA
5572 return 1;
5573 else if (var_is_special)
5574 return 1;
ccc6cda3
JA
5575#if defined (ARRAY_VARS)
5576 else if (valid_array_reference (name))
5577 return 1;
5578#endif /* ARRAY_VARS */
726f6388
JA
5579 else if (legal_identifier (name))
5580 return 1;
5581 else
5582 return 0;
5583}
ccc6cda3 5584
d3a24ed2
CR
5585static int
5586chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
5587 char *name;
5588 int quoted;
5589 int *quoted_dollar_atp, *contains_dollar_at;
5590{
5591 char *temp1;
5592
5593 if (name == 0)
5594 {
5595 if (quoted_dollar_atp)
5596 *quoted_dollar_atp = 0;
5597 if (contains_dollar_at)
5598 *contains_dollar_at = 0;
5599 return 0;
5600 }
5601
5602 /* check for $@ and $* */
5603 if (name[0] == '@' && name[1] == 0)
5604 {
5605 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5606 *quoted_dollar_atp = 1;
5607 if (contains_dollar_at)
5608 *contains_dollar_at = 1;
5609 return 1;
5610 }
5611 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
5612 {
5613 if (contains_dollar_at)
5614 *contains_dollar_at = 1;
5615 return 1;
5616 }
5617
5618 /* Now check for ${array[@]} and ${array[*]} */
5619#if defined (ARRAY_VARS)
5620 else if (valid_array_reference (name))
5621 {
d0ca3503 5622 temp1 = mbschr (name, '[');
d3a24ed2
CR
5623 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
5624 {
5625 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5626 *quoted_dollar_atp = 1;
5627 if (contains_dollar_at)
5628 *contains_dollar_at = 1;
5629 return 1;
5630 } /* [ */
5631 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
5632 which should result in separate words even when IFS is unset. */
5633 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
5634 {
5635 if (contains_dollar_at)
5636 *contains_dollar_at = 1;
5637 return 1;
5638 }
5639 }
5640#endif
5641 return 0;
5642}
5643
726f6388
JA
5644/* Parameter expand NAME, and return a new string which is the expansion,
5645 or NULL if there was no expansion.
5646 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
5647 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
5648 NAME was found inside of a double-quoted expression. */
227f982e 5649static WORD_DESC *
5f8cde23 5650parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp)
726f6388 5651 char *name;
1231ac47 5652 int var_is_special, quoted, pflags;
5f8cde23 5653 arrayind_t *indp;
726f6388 5654{
227f982e 5655 WORD_DESC *ret;
ccc6cda3 5656 char *temp, *tt;
7117c2d2 5657 intmax_t arg_index;
ccc6cda3 5658 SHELL_VAR *var;
b1a26c01 5659 int atype, rflags;
5f8cde23 5660 arrayind_t ind;
726f6388 5661
227f982e
CR
5662 ret = 0;
5663 temp = 0;
b1a26c01 5664 rflags = 0;
227f982e 5665
5f8cde23
CR
5666 if (indp)
5667 *indp = INTMAX_MIN;
5668
227f982e 5669 /* Handle multiple digit arguments, as in ${11}. */
f73dda09 5670 if (legal_number (name, &arg_index))
7117c2d2
JA
5671 {
5672 tt = get_dollar_var_value (arg_index);
762a763b
CR
5673 if (tt)
5674 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5675 ? quote_string (tt)
5676 : quote_escapes (tt);
5677 else
5678 temp = (char *)NULL;
7117c2d2
JA
5679 FREE (tt);
5680 }
726f6388
JA
5681 else if (var_is_special) /* ${@} */
5682 {
cce855bc 5683 int sindex;
f73dda09 5684 tt = (char *)xmalloc (2 + strlen (name));
cce855bc 5685 tt[sindex = 0] = '$';
726f6388 5686 strcpy (tt + 1, name);
7117c2d2 5687
227f982e 5688 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
1231ac47 5689 (int *)NULL, (int *)NULL, pflags);
cce855bc 5690 free (tt);
726f6388 5691 }
ccc6cda3
JA
5692#if defined (ARRAY_VARS)
5693 else if (valid_array_reference (name))
5694 {
d42cb8c1 5695expand_arrayref:
631b20c6 5696 /* XXX - does this leak if name[@] or name[*]? */
5f8cde23 5697 temp = array_value (name, quoted, 0, &atype, &ind);
7117c2d2 5698 if (atype == 0 && temp)
5f8cde23
CR
5699 {
5700 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5701 ? quote_string (temp)
5702 : quote_escapes (temp);
5703 rflags |= W_ARRAYIND;
5704 if (indp)
5705 *indp = ind;
5706 }
b1a26c01
CR
5707 else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5708 rflags |= W_HASQUOTEDNULL;
ccc6cda3
JA
5709 }
5710#endif
5711 else if (var = find_variable (name))
5712 {
7117c2d2 5713 if (var_isset (var) && invisible_p (var) == 0)
28ef6c31 5714 {
ccc6cda3 5715#if defined (ARRAY_VARS)
fdf670ea
CR
5716 if (assoc_p (var))
5717 temp = assoc_reference (assoc_cell (var), "0");
5718 else if (array_p (var))
5719 temp = array_reference (array_cell (var), 0);
5720 else
5721 temp = value_cell (var);
ccc6cda3
JA
5722#else
5723 temp = value_cell (var);
5724#endif
5725
5726 if (temp)
762a763b
CR
5727 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
5728 ? quote_string (temp)
5729 : quote_escapes (temp);
28ef6c31 5730 }
ccc6cda3
JA
5731 else
5732 temp = (char *)NULL;
5733 }
d42cb8c1
CR
5734 else if (var = find_variable_last_nameref (name))
5735 {
5736 temp = nameref_cell (var);
15623760
CR
5737#if defined (ARRAY_VARS)
5738 /* Handle expanding nameref whose value is x[n] */
d42cb8c1
CR
5739 if (temp && *temp && valid_array_reference (temp))
5740 {
5741 name = temp;
5742 goto expand_arrayref;
5743 }
d42cb8c1 5744#endif
15623760
CR
5745 /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
5746 else if (temp && *temp && legal_identifier (temp) == 0)
5747 {
5748 last_command_exit_value = EXECUTION_FAILURE;
5749 report_error (_("%s: invalid variable name for name reference"), temp);
5750 temp = &expand_param_error;
5751 }
5752 else
5753 temp = (char *)NULL;
5754 }
726f6388 5755 else
ccc6cda3 5756 temp = (char *)NULL;
726f6388 5757
227f982e
CR
5758 if (ret == 0)
5759 {
5760 ret = alloc_word_desc ();
5761 ret->word = temp;
b1a26c01 5762 ret->flags |= rflags;
227f982e
CR
5763 }
5764 return ret;
726f6388
JA
5765}
5766
ccc6cda3
JA
5767/* Expand an indirect reference to a variable: ${!NAME} expands to the
5768 value of the variable whose name is the value of NAME. */
227f982e 5769static WORD_DESC *
d3a24ed2 5770parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
ccc6cda3
JA
5771 char *name;
5772 int var_is_special, quoted;
d3a24ed2 5773 int *quoted_dollar_atp, *contains_dollar_at;
ccc6cda3
JA
5774{
5775 char *temp, *t;
227f982e 5776 WORD_DESC *w;
d42cb8c1
CR
5777 SHELL_VAR *v;
5778
5779 /* See if it's a nameref first, behave in ksh93-compatible fashion.
5780 There is at least one incompatibility: given ${!foo[0]} where foo=bar,
5781 bash performs an indirect lookup on foo[0] and expands the result;
5782 ksh93 expands bar[0]. We could do that here -- there are enough usable
5783 primitives to do that -- but do not at this point. */
5784 if (var_is_special == 0 && (v = find_variable_last_nameref (name)))
5785 {
5786 if (nameref_p (v) && (t = nameref_cell (v)) && *t)
5787 {
5788 w = alloc_word_desc ();
5789 w->word = savestring (t);
5790 w->flags = 0;
5791 return w;
5792 }
5793 }
ccc6cda3 5794
15623760
CR
5795 /* If var_is_special == 0, and name is not an array reference, this does
5796 more expansion than necessary. It should really look up the variable's
5797 value and not try to expand it. */
5f8cde23 5798 w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
227f982e 5799 t = w->word;
762a763b
CR
5800 /* Have to dequote here if necessary */
5801 if (t)
5802 {
5803 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5804 ? dequote_string (t)
5805 : dequote_escapes (t);
5806 free (t);
5807 t = temp;
5808 }
227f982e
CR
5809 dispose_word_desc (w);
5810
d3a24ed2 5811 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
ccc6cda3 5812 if (t == 0)
227f982e
CR
5813 return (WORD_DESC *)NULL;
5814
5f8cde23 5815 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0, 0);
ccc6cda3 5816 free (t);
227f982e
CR
5817
5818 return w;
ccc6cda3
JA
5819}
5820
726f6388
JA
5821/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
5822 depending on the value of C, the separating character. C can be one of
ccc6cda3
JA
5823 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
5824 between double quotes. */
227f982e 5825static WORD_DESC *
ccc6cda3 5826parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
726f6388 5827 char *name, *value;
ccc6cda3 5828 int c, quoted, *qdollaratp, *hasdollarat;
726f6388 5829{
227f982e 5830 WORD_DESC *w;
726f6388
JA
5831 WORD_LIST *l;
5832 char *t, *t1, *temp;
ccc6cda3 5833 int hasdol;
726f6388 5834
ccc6cda3
JA
5835 /* If the entire expression is between double quotes, we want to treat
5836 the value as a double-quoted string, with the exception that we strip
d3ad40de 5837 embedded unescaped double quotes (for sh backwards compatibility). */
22e63b05 5838 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
726f6388 5839 {
ccc6cda3 5840 hasdol = 0;
22e63b05 5841 temp = string_extract_double_quoted (value, &hasdol, 1);
726f6388 5842 }
22e63b05
CR
5843 else
5844 temp = value;
ccc6cda3 5845
227f982e 5846 w = alloc_word_desc ();
726f6388 5847 hasdol = 0;
ccc6cda3
JA
5848 /* XXX was 0 not quoted */
5849 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
5850 : (WORD_LIST *)0;
5851 if (hasdollarat)
5852 *hasdollarat = hasdol || (l && l->next);
22e63b05
CR
5853 if (temp != value)
5854 free (temp);
726f6388
JA
5855 if (l)
5856 {
ccc6cda3 5857 /* The expansion of TEMP returned something. We need to treat things
12d937f9
CR
5858 slightly differently if HASDOL is non-zero. If we have "$@", the
5859 individual words have already been quoted. We need to turn them
5860 into a string with the words separated by the first character of
5861 $IFS without any additional quoting, so string_list_dollar_at won't
5862 do the right thing. We use string_list_dollar_star instead. */
5863 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
5864
ccc6cda3
JA
5865 /* If l->next is not null, we know that TEMP contained "$@", since that
5866 is the only expansion that creates more than one word. */
12d937f9 5867 if (qdollaratp && ((hasdol && quoted) || l->next))
ccc6cda3 5868 *qdollaratp = 1;
ec860d76
CR
5869 /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
5870 a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
5871 flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
5872 expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5873 (which is more paranoia than anything else), we need to return the
5874 quoted null string and set the flags to indicate it. */
5875 if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL))
5876 {
5877 w->flags |= W_HASQUOTEDNULL;
5878 }
726f6388
JA
5879 dispose_words (l);
5880 }
ccc6cda3 5881 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
726f6388 5882 {
ccc6cda3
JA
5883 /* The brace expansion occurred between double quotes and there was
5884 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
7117c2d2
JA
5885 it does not expand to anything. In this case, we want to return
5886 a quoted empty string. */
d3ad40de 5887 temp = make_quoted_char ('\0');
227f982e 5888 w->flags |= W_HASQUOTEDNULL;
726f6388
JA
5889 }
5890 else
5891 temp = (char *)NULL;
5892
5893 if (c == '-' || c == '+')
227f982e
CR
5894 {
5895 w->word = temp;
5896 return w;
5897 }
726f6388
JA
5898
5899 /* c == '=' */
ccc6cda3 5900 t = temp ? savestring (temp) : savestring ("");
726f6388
JA
5901 t1 = dequote_string (t);
5902 free (t);
d3a24ed2
CR
5903#if defined (ARRAY_VARS)
5904 if (valid_array_reference (name))
d11b8b46 5905 assign_array_element (name, t1, 0);
d3a24ed2
CR
5906 else
5907#endif /* ARRAY_VARS */
d11b8b46 5908 bind_variable (name, t1, 0);
227f982e 5909
9e51a74d 5910 /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
64419627
CR
5911 free (temp);
5912
5913 w->word = t1;
227f982e 5914 return w;
726f6388
JA
5915}
5916
5917/* Deal with the right hand side of a ${name:?value} expansion in the case
5918 that NAME is null or not set. If VALUE is non-null it is expanded and
5919 used as the error message to print, otherwise a standard message is
5920 printed. */
5921static void
5922parameter_brace_expand_error (name, value)
5923 char *name, *value;
5924{
ccc6cda3
JA
5925 WORD_LIST *l;
5926 char *temp;
5927
7f947b68 5928 last_command_exit_value = EXECUTION_FAILURE; /* ensure it's non-zero */
726f6388
JA
5929 if (value && *value)
5930 {
22e63b05 5931 l = expand_string (value, 0);
ccc6cda3
JA
5932 temp = string_list (l);
5933 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5934 FREE (temp);
726f6388
JA
5935 dispose_words (l);
5936 }
5937 else
5e13499c 5938 report_error (_("%s: parameter null or not set"), name);
726f6388
JA
5939
5940 /* Free the data we have allocated during this expansion, since we
5941 are about to longjmp out. */
5942 free (name);
5943 FREE (value);
5944}
5945
5946/* Return 1 if NAME is something for which parameter_brace_expand_length is
5947 OK to do. */
5948static int
5949valid_length_expression (name)
5950 char *name;
5951{
28ef6c31 5952 return (name[1] == '\0' || /* ${#} */
f73dda09
JA
5953 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5954 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
ccc6cda3
JA
5955#if defined (ARRAY_VARS)
5956 valid_array_reference (name + 1) || /* ${#a[7]} */
5957#endif
726f6388
JA
5958 legal_identifier (name + 1)); /* ${#PS1} */
5959}
5960
5961/* Handle the parameter brace expansion that requires us to return the
5962 length of a parameter. */
7117c2d2 5963static intmax_t
726f6388
JA
5964parameter_brace_expand_length (name)
5965 char *name;
5966{
ccc6cda3 5967 char *t, *newname;
7117c2d2 5968 intmax_t number, arg_index;
ccc6cda3
JA
5969 WORD_LIST *list;
5970#if defined (ARRAY_VARS)
5971 SHELL_VAR *var;
5972#endif
5973
5974 if (name[1] == '\0') /* ${#} */
5975 number = number_of_args ();
cce855bc
JA
5976 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5977 number = number_of_args ();
f73dda09 5978 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
cce855bc
JA
5979 {
5980 /* Take the lengths of some of the shell's special parameters. */
5981 switch (name[1])
5982 {
5983 case '-':
5984 t = which_set_flags ();
5985 break;
5986 case '?':
5987 t = itos (last_command_exit_value);
5988 break;
5989 case '$':
5990 t = itos (dollar_dollar_pid);
5991 break;
5992 case '!':
5993 if (last_asynchronous_pid == NO_PID)
e05be32d 5994 t = (char *)NULL; /* XXX - error if set -u set? */
cce855bc 5995 else
f73dda09 5996 t = itos (last_asynchronous_pid);
cce855bc
JA
5997 break;
5998 case '#':
5999 t = itos (number_of_args ());
6000 break;
6001 }
6002 number = STRLEN (t);
6003 FREE (t);
6004 }
ccc6cda3
JA
6005#if defined (ARRAY_VARS)
6006 else if (valid_array_reference (name + 1))
6007 number = array_length_reference (name + 1);
6008#endif /* ARRAY_VARS */
cce855bc 6009 else
ccc6cda3
JA
6010 {
6011 number = 0;
6012
f73dda09 6013 if (legal_number (name + 1, &arg_index)) /* ${#1} */
ccc6cda3 6014 {
f73dda09 6015 t = get_dollar_var_value (arg_index);
e05be32d
CR
6016 if (t == 0 && unbound_vars_is_error)
6017 return INTMAX_MIN;
898cc92e 6018 number = MB_STRLEN (t);
ccc6cda3
JA
6019 FREE (t);
6020 }
6021#if defined (ARRAY_VARS)
fdf670ea 6022 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
ccc6cda3 6023 {
fdf670ea
CR
6024 if (assoc_p (var))
6025 t = assoc_reference (assoc_cell (var), "0");
6026 else
6027 t = array_reference (array_cell (var), 0);
e05be32d
CR
6028 if (t == 0 && unbound_vars_is_error)
6029 return INTMAX_MIN;
898cc92e 6030 number = MB_STRLEN (t);
ccc6cda3
JA
6031 }
6032#endif
6033 else /* ${#PS1} */
6034 {
6035 newname = savestring (name);
6036 newname[0] = '$';
6037 list = expand_string (newname, Q_DOUBLE_QUOTES);
6038 t = list ? string_list (list) : (char *)NULL;
6039 free (newname);
6040 if (list)
6041 dispose_words (list);
6042
adc6cff5 6043 number = t ? MB_STRLEN (t) : 0;
ccc6cda3
JA
6044 FREE (t);
6045 }
6046 }
ccc6cda3
JA
6047
6048 return (number);
6049}
6050
28ef6c31
JA
6051/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
6052 so we do some ad-hoc parsing of an arithmetic expression to find
6053 the first DELIM, instead of using strchr(3). Two rules:
6054 1. If the substring contains a `(', read until closing `)'.
6055 2. If the substring contains a `?', read past one `:' for each `?'.
6056*/
6057
6058static char *
6059skiparith (substr, delim)
6060 char *substr;
6061 int delim;
6062{
7117c2d2
JA
6063 size_t sublen;
6064 int skipcol, pcount, i;
6065 DECLARE_MBSTATE;
28ef6c31 6066
7117c2d2
JA
6067 sublen = strlen (substr);
6068 i = skipcol = pcount = 0;
6069 while (substr[i])
28ef6c31
JA
6070 {
6071 /* Balance parens */
7117c2d2 6072 if (substr[i] == LPAREN)
28ef6c31
JA
6073 {
6074 pcount++;
7117c2d2 6075 i++;
28ef6c31
JA
6076 continue;
6077 }
7117c2d2 6078 if (substr[i] == RPAREN && pcount)
28ef6c31
JA
6079 {
6080 pcount--;
7117c2d2 6081 i++;
28ef6c31
JA
6082 continue;
6083 }
6084 if (pcount)
7117c2d2
JA
6085 {
6086 ADVANCE_CHAR (substr, sublen, i);
6087 continue;
6088 }
28ef6c31
JA
6089
6090 /* Skip one `:' for each `?' */
7117c2d2 6091 if (substr[i] == ':' && skipcol)
28ef6c31
JA
6092 {
6093 skipcol--;
7117c2d2 6094 i++;
28ef6c31
JA
6095 continue;
6096 }
7117c2d2 6097 if (substr[i] == delim)
28ef6c31 6098 break;
7117c2d2 6099 if (substr[i] == '?')
28ef6c31
JA
6100 {
6101 skipcol++;
7117c2d2 6102 i++;
28ef6c31
JA
6103 continue;
6104 }
7117c2d2 6105 ADVANCE_CHAR (substr, sublen, i);
28ef6c31 6106 }
7117c2d2
JA
6107
6108 return (substr + i);
28ef6c31
JA
6109}
6110
ccc6cda3
JA
6111/* Verify and limit the start and end of the desired substring. If
6112 VTYPE == 0, a regular shell variable is being used; if it is 1,
cce855bc 6113 then the positional parameters are being used; if it is 2, then
e8ce775d
JA
6114 VALUE is really a pointer to an array variable that should be used.
6115 Return value is 1 if both values were OK, 0 if there was a problem
6116 with an invalid expression, or -1 if the values were out of range. */
ccc6cda3 6117static int
09767ff0
CR
6118verify_substring_values (v, value, substr, vtype, e1p, e2p)
6119 SHELL_VAR *v;
ccc6cda3 6120 char *value, *substr;
f73dda09 6121 int vtype;
7117c2d2 6122 intmax_t *e1p, *e2p;
ccc6cda3 6123{
bb70624e 6124 char *t, *temp1, *temp2;
f73dda09
JA
6125 arrayind_t len;
6126 int expok;
ccc6cda3
JA
6127#if defined (ARRAY_VARS)
6128 ARRAY *a;
09767ff0 6129 HASH_TABLE *h;
ccc6cda3
JA
6130#endif
6131
28ef6c31
JA
6132 /* duplicate behavior of strchr(3) */
6133 t = skiparith (substr, ':');
6134 if (*t && *t == ':')
7117c2d2 6135 *t = '\0';
28ef6c31
JA
6136 else
6137 t = (char *)0;
f73dda09 6138
d3ad40de 6139 temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
d166f048 6140 *e1p = evalexp (temp1, &expok);
ccc6cda3 6141 free (temp1);
d166f048
JA
6142 if (expok == 0)
6143 return (0);
ccc6cda3 6144
f73dda09 6145 len = -1; /* paranoia */
ccc6cda3
JA
6146 switch (vtype)
6147 {
6148 case VT_VARIABLE:
d166f048 6149 case VT_ARRAYMEMBER:
898cc92e 6150 len = MB_STRLEN (value);
ccc6cda3
JA
6151 break;
6152 case VT_POSPARMS:
6153 len = number_of_args () + 1;
d3ad40de
CR
6154 if (*e1p == 0)
6155 len++; /* add one arg if counting from $0 */
ccc6cda3
JA
6156 break;
6157#if defined (ARRAY_VARS)
6158 case VT_ARRAYVAR:
301e2142 6159 /* For arrays, the first value deals with array indices. Negative
09767ff0
CR
6160 offsets count from one past the array's maximum index. Associative
6161 arrays treat the number of elements as the maximum index. */
6162 if (assoc_p (v))
6163 {
6164 h = assoc_cell (v);
6165 len = assoc_num_elements (h) + (*e1p < 0);
6166 }
6167 else
6168 {
6169 a = (ARRAY *)value;
6170 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
6171 }
ccc6cda3
JA
6172 break;
6173#endif
6174 }
6175
f73dda09
JA
6176 if (len == -1) /* paranoia */
6177 return -1;
6178
ccc6cda3
JA
6179 if (*e1p < 0) /* negative offsets count from end */
6180 *e1p += len;
6181
8ed8525c 6182 if (*e1p > len || *e1p < 0)
e8ce775d 6183 return (-1);
d166f048 6184
5e13499c
CR
6185#if defined (ARRAY_VARS)
6186 /* For arrays, the second offset deals with the number of elements. */
6187 if (vtype == VT_ARRAYVAR)
dd4f3dd8 6188 len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
5e13499c
CR
6189#endif
6190
ccc6cda3
JA
6191 if (t)
6192 {
6193 t++;
bb70624e 6194 temp2 = savestring (t);
d3ad40de 6195 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
bb70624e 6196 free (temp2);
ccc6cda3 6197 t[-1] = ':';
d166f048 6198 *e2p = evalexp (temp1, &expok);
ccc6cda3 6199 free (temp1);
d166f048 6200 if (expok == 0)
28ef6c31 6201 return (0);
348a457e 6202#if 1
67362c60 6203 if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0)
348a457e
CR
6204#else
6205 /* bash-4.3: allow positional parameter length < 0 to count backwards
6206 from end of positional parameters */
6207 if (vtype == VT_ARRAYVAR && *e2p < 0)
6208#endif
28ef6c31 6209 {
5e13499c 6210 internal_error (_("%s: substring expression < 0"), t);
ccc6cda3 6211 return (0);
28ef6c31 6212 }
5e13499c
CR
6213#if defined (ARRAY_VARS)
6214 /* In order to deal with sparse arrays, push the intelligence about how
6215 to deal with the number of elements desired down to the array-
6216 specific functions. */
6217 if (vtype != VT_ARRAYVAR)
6218#endif
6219 {
67362c60
CR
6220 if (*e2p < 0)
6221 {
6222 *e2p += len;
6223 if (*e2p < 0 || *e2p < *e1p)
6224 {
6225 internal_error (_("%s: substring expression < 0"), t);
6226 return (0);
6227 }
6228 }
6229 else
6230 *e2p += *e1p; /* want E2 chars starting at E1 */
5e13499c
CR
6231 if (*e2p > len)
6232 *e2p = len;
6233 }
ccc6cda3
JA
6234 }
6235 else
6236 *e2p = len;
6237
6238 return (1);
6239}
6240
ccc6cda3 6241/* Return the type of variable specified by VARNAME (simple variable,
cce855bc 6242 positional param, or array variable). Also return the value specified
7117c2d2 6243 by VARNAME (value of a variable or a reference to an array element).
5f8cde23
CR
6244 QUOTED is the standard description of quoting state, using Q_* defines.
6245 FLAGS is currently a set of flags to pass to array_value. If IND is
6246 non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
6247 passed to array_value so the array index is not computed again.
7117c2d2
JA
6248 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
6249 characters in the value are quoted with CTLESC and takes appropriate
6250 steps. For convenience, *VALP is set to the dequoted VALUE. */
ccc6cda3 6251static int
5f8cde23 6252get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
ccc6cda3 6253 char *varname, *value;
5f8cde23
CR
6254 arrayind_t ind;
6255 int quoted, flags;
ccc6cda3
JA
6256 SHELL_VAR **varp;
6257 char **valp;
6258{
6259 int vtype;
6260 char *temp;
6261#if defined (ARRAY_VARS)
6262 SHELL_VAR *v;
6263#endif
5f8cde23 6264 arrayind_t lind;
ccc6cda3 6265
7117c2d2
JA
6266 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
6267 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
d3a24ed2
CR
6268 if (vtype == VT_POSPARMS && varname[0] == '*')
6269 vtype |= VT_STARSUB;
ccc6cda3
JA
6270 *varp = (SHELL_VAR *)NULL;
6271
6272#if defined (ARRAY_VARS)
6273 if (valid_array_reference (varname))
6274 {
6275 v = array_variable_part (varname, &temp, (int *)0);
5f8cde23
CR
6276 /* If we want to signal array_value to use an already-computed index,
6277 set LIND to that index */
6278 lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
fdf670ea 6279 if (v && (array_p (v) || assoc_p (v)))
f73dda09
JA
6280 { /* [ */
6281 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
ccc6cda3 6282 {
dd4f3dd8 6283 /* Callers have to differentiate betwen indexed and associative */
ccc6cda3 6284 vtype = VT_ARRAYVAR;
d3a24ed2
CR
6285 if (temp[0] == '*')
6286 vtype |= VT_STARSUB;
fdf670ea 6287 *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
ccc6cda3
JA
6288 }
6289 else
6290 {
d166f048 6291 vtype = VT_ARRAYMEMBER;
5f8cde23 6292 *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
ccc6cda3
JA
6293 }
6294 *varp = v;
6295 }
8fed3589
CR
6296 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
6297 {
6298 vtype = VT_VARIABLE;
6299 *varp = v;
6300 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6301 *valp = dequote_string (value);
6302 else
6303 *valp = dequote_escapes (value);
6304 }
ccc6cda3 6305 else
fdf670ea
CR
6306 {
6307 vtype = VT_ARRAYMEMBER;
6308 *varp = v;
5f8cde23 6309 *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
fdf670ea 6310 }
ccc6cda3 6311 }
fdf670ea 6312 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
ccc6cda3 6313 {
7117c2d2 6314 vtype = VT_ARRAYMEMBER;
ccc6cda3 6315 *varp = v;
fdf670ea 6316 *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
ccc6cda3
JA
6317 }
6318 else
6319#endif
762a763b
CR
6320 {
6321 if (value && vtype == VT_VARIABLE)
6322 {
6323 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6324 *valp = dequote_string (value);
6325 else
6326 *valp = dequote_escapes (value);
6327 }
6328 else
6329 *valp = value;
6330 }
ccc6cda3
JA
6331
6332 return vtype;
6333}
6334
cce855bc
JA
6335/******************************************************/
6336/* */
6337/* Functions to extract substrings of variable values */
6338/* */
6339/******************************************************/
6340
545f34cf
CR
6341#if defined (HANDLE_MULTIBYTE)
6342/* Character-oriented rather than strictly byte-oriented substrings. S and
6343 E, rather being strict indices into STRING, indicate character (possibly
6344 multibyte character) positions that require calculation.
6345 Used by the ${param:offset[:length]} expansion. */
6346static char *
6347mb_substring (string, s, e)
6348 char *string;
6349 int s, e;
6350{
6351 char *tt;
6352 int start, stop, i, slen;
6353 DECLARE_MBSTATE;
6354
6355 start = 0;
da713c23
CR
6356 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
6357 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
545f34cf
CR
6358
6359 i = s;
6360 while (string[start] && i--)
6361 ADVANCE_CHAR (string, slen, start);
6362 stop = start;
6363 i = e - s;
6364 while (string[stop] && i--)
6365 ADVANCE_CHAR (string, slen, stop);
6366 tt = substring (string, start, stop);
6367 return tt;
6368}
6369#endif
6370
ccc6cda3
JA
6371/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
6372 is `@', use the positional parameters; otherwise, use the value of
6373 VARNAME. If VARNAME is an array variable, use the array elements. */
6374
6375static char *
5f8cde23
CR
6376parameter_brace_substring (varname, value, ind, substr, quoted, flags)
6377 char *varname, *value;
6378 int ind;
6379 char *substr;
6380 int quoted, flags;
ccc6cda3 6381{
7117c2d2 6382 intmax_t e1, e2;
d3a24ed2 6383 int vtype, r, starsub;
d3ad40de 6384 char *temp, *val, *tt, *oname;
ccc6cda3
JA
6385 SHELL_VAR *v;
6386
6387 if (value == 0)
6388 return ((char *)NULL);
6389
d3ad40de 6390 oname = this_command_name;
ccc6cda3
JA
6391 this_command_name = varname;
6392
5f8cde23 6393 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
ccc6cda3 6394 if (vtype == -1)
d3ad40de
CR
6395 {
6396 this_command_name = oname;
6397 return ((char *)NULL);
6398 }
ccc6cda3 6399
d3a24ed2
CR
6400 starsub = vtype & VT_STARSUB;
6401 vtype &= ~VT_STARSUB;
6402
09767ff0 6403 r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
d3ad40de 6404 this_command_name = oname;
e8ce775d 6405 if (r <= 0)
631b20c6
CR
6406 {
6407 if (vtype == VT_VARIABLE)
6408 FREE (val);
6409 return ((r == 0) ? &expand_param_error : (char *)NULL);
6410 }
ccc6cda3
JA
6411
6412 switch (vtype)
6413 {
6414 case VT_VARIABLE:
d166f048 6415 case VT_ARRAYMEMBER:
545f34cf
CR
6416#if defined (HANDLE_MULTIBYTE)
6417 if (MB_CUR_MAX > 1)
6418 tt = mb_substring (val, e1, e2);
6419 else
6420#endif
7117c2d2 6421 tt = substring (val, e1, e2);
545f34cf 6422
7117c2d2
JA
6423 if (vtype == VT_VARIABLE)
6424 FREE (val);
6425 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
6426 temp = quote_string (tt);
6427 else
6428 temp = tt ? quote_escapes (tt) : (char *)NULL;
6429 FREE (tt);
ccc6cda3
JA
6430 break;
6431 case VT_POSPARMS:
7117c2d2
JA
6432 tt = pos_params (varname, e1, e2, quoted);
6433 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
6434 {
6435 temp = tt ? quote_escapes (tt) : (char *)NULL;
6436 FREE (tt);
6437 }
6438 else
6439 temp = tt;
ccc6cda3
JA
6440 break;
6441#if defined (ARRAY_VARS)
6442 case VT_ARRAYVAR:
fdf670ea 6443 if (assoc_p (v))
09767ff0
CR
6444 /* we convert to list and take first e2 elements starting at e1th
6445 element -- officially undefined for now */
6446 temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
fdf670ea 6447 else
5e13499c 6448 /* We want E2 to be the number of elements desired (arrays can be sparse,
704a1a2a
CR
6449 so verify_substring_values just returns the numbers specified and we
6450 rely on array_subrange to understand how to deal with them). */
fdf670ea 6451 temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
d3ad40de
CR
6452 /* array_subrange now calls array_quote_escapes as appropriate, so the
6453 caller no longer needs to. */
ccc6cda3
JA
6454 break;
6455#endif
f73dda09
JA
6456 default:
6457 temp = (char *)NULL;
ccc6cda3
JA
6458 }
6459
6460 return temp;
6461}
6462
cce855bc
JA
6463/****************************************************************/
6464/* */
6465/* Functions to perform pattern substitution on variable values */
6466/* */
6467/****************************************************************/
6468
ee56a865
CR
6469static int
6470shouldexp_replacement (s)
6471 char *s;
6472{
6473 register char *p;
6474
6475 for (p = s; p && *p; p++)
6476 {
6477 if (*p == '\\')
6478 p++;
6479 else if (*p == '&')
6480 return 1;
6481 }
6482 return 0;
6483}
6484
ccc6cda3
JA
6485char *
6486pat_subst (string, pat, rep, mflags)
6487 char *string, *pat, *rep;
6488 int mflags;
6489{
ee56a865
CR
6490 char *ret, *s, *e, *str, *rstr, *mstr;
6491 int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen;
ccc6cda3 6492
5f8cde23
CR
6493 if (string == 0)
6494 return (savestring (""));
6495
b72432fd
JA
6496 mtype = mflags & MATCH_TYPEMASK;
6497
e054386f 6498#if 0 /* bash-4.2 ? */
ee56a865 6499 rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0;
e054386f
CR
6500#else
6501 rxpand = 0;
6502#endif
ee56a865 6503
b72432fd
JA
6504 /* Special cases:
6505 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
6506 * with REP and return the result.
6507 * 2. A null pattern with mtype == MATCH_END means to append REP to
6508 * STRING and return the result.
ee56a865 6509 * These don't understand or process `&' in the replacement string.
b72432fd
JA
6510 */
6511 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
6512 {
6513 replen = STRLEN (rep);
5f8cde23 6514 l = STRLEN (string);
f73dda09 6515 ret = (char *)xmalloc (replen + l + 2);
bb70624e
JA
6516 if (replen == 0)
6517 strcpy (ret, string);
6518 else if (mtype == MATCH_BEG)
b72432fd
JA
6519 {
6520 strcpy (ret, rep);
6521 strcpy (ret + replen, string);
6522 }
6523 else
6524 {
6525 strcpy (ret, string);
6526 strcpy (ret + l, rep);
6527 }
6528 return (ret);
6529 }
6530
f73dda09 6531 ret = (char *)xmalloc (rsize = 64);
ccc6cda3
JA
6532 ret[0] = '\0';
6533
ccc6cda3
JA
6534 for (replen = STRLEN (rep), rptr = 0, str = string;;)
6535 {
6536 if (match_pattern (str, pat, mtype, &s, &e) == 0)
6537 break;
6538 l = s - str;
ee56a865
CR
6539
6540 if (rxpand)
6541 {
6542 int x;
6543 mlen = e - s;
6544 mstr = xmalloc (mlen + 1);
6545 for (x = 0; x < mlen; x++)
6546 mstr[x] = s[x];
6547 mstr[mlen] = '\0';
6548 rstr = strcreplace (rep, '&', mstr, 0);
6549 rslen = strlen (rstr);
6550 }
6551 else
6552 {
6553 rstr = rep;
6554 rslen = replen;
6555 }
6556
6557 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64);
ccc6cda3
JA
6558
6559 /* OK, now copy the leading unmatched portion of the string (from
6560 str to s) to ret starting at rptr (the current offset). Then copy
28ef6c31
JA
6561 the replacement string at ret + rptr + (s - str). Increment
6562 rptr (if necessary) and str and go on. */
ccc6cda3
JA
6563 if (l)
6564 {
6565 strncpy (ret + rptr, str, l);
6566 rptr += l;
6567 }
6568 if (replen)
6569 {
ee56a865
CR
6570 strncpy (ret + rptr, rstr, rslen);
6571 rptr += rslen;
ccc6cda3
JA
6572 }
6573 str = e; /* e == end of match */
d3a24ed2 6574
ee56a865
CR
6575 if (rstr != rep)
6576 free (rstr);
6577
ccc6cda3 6578 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
28ef6c31 6579 break;
d3a24ed2
CR
6580
6581 if (s == e)
5ccad779
CR
6582 {
6583 /* On a zero-length match, make sure we copy one character, since
6584 we increment one character to avoid infinite recursion. */
6585 RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64);
6586 ret[rptr++] = *str++;
6587 e++; /* avoid infinite recursion on zero-length match */
6588 }
ccc6cda3
JA
6589 }
6590
6591 /* Now copy the unmatched portion of the input string */
5f8cde23 6592 if (str && *str)
d166f048
JA
6593 {
6594 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
6595 strcpy (ret + rptr, str);
6596 }
ccc6cda3
JA
6597 else
6598 ret[rptr] = '\0';
6599
6600 return ret;
6601}
6602
6603/* Do pattern match and replacement on the positional parameters. */
6604static char *
6605pos_params_pat_subst (string, pat, rep, mflags)
6606 char *string, *pat, *rep;
6607 int mflags;
6608{
6609 WORD_LIST *save, *params;
6610 WORD_DESC *w;
d3ad40de 6611 char *ret;
e33f2203 6612 int pchar, qflags;
ccc6cda3
JA
6613
6614 save = params = list_rest_of_args ();
6615 if (save == 0)
6616 return ((char *)NULL);
6617
6618 for ( ; params; params = params->next)
6619 {
6620 ret = pat_subst (params->word->word, pat, rep, mflags);
227f982e
CR
6621 w = alloc_word_desc ();
6622 w->word = ret ? ret : savestring ("");
ccc6cda3
JA
6623 dispose_word (params->word);
6624 params->word = w;
ccc6cda3
JA
6625 }
6626
e33f2203
CR
6627 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6628 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6629
6630#if 0
d3a24ed2
CR
6631 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
6632 ret = string_list_dollar_star (quote_list (save));
e33f2203
CR
6633 else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
6634 ret = string_list_dollar_star (save);
6635 else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
6636 ret = string_list_dollar_at (save, qflags);
d3a24ed2 6637 else
e33f2203
CR
6638 ret = string_list_dollar_star (save);
6639#else
6640 ret = string_list_pos_params (pchar, save, qflags);
6641#endif
6642
ccc6cda3
JA
6643 dispose_words (save);
6644
6645 return (ret);
6646}
6647
cce855bc
JA
6648/* Perform pattern substitution on VALUE, which is the expansion of
6649 VARNAME. PATSUB is an expression supplying the pattern to match
6650 and the string to substitute. QUOTED is a flags word containing
6651 the type of quoting currently in effect. */
ccc6cda3 6652static char *
5f8cde23
CR
6653parameter_brace_patsub (varname, value, ind, patsub, quoted, flags)
6654 char *varname, *value;
6655 int ind;
6656 char *patsub;
6657 int quoted, flags;
ccc6cda3 6658{
c2a47ea9 6659 int vtype, mflags, starsub, delim;
7117c2d2 6660 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
ccc6cda3
JA
6661 SHELL_VAR *v;
6662
6663 if (value == 0)
6664 return ((char *)NULL);
6665
6666 this_command_name = varname;
6667
5f8cde23 6668 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
ccc6cda3
JA
6669 if (vtype == -1)
6670 return ((char *)NULL);
6671
d3a24ed2
CR
6672 starsub = vtype & VT_STARSUB;
6673 vtype &= ~VT_STARSUB;
6674
ccc6cda3 6675 mflags = 0;
77638cbf
CR
6676 /* PATSUB is never NULL when this is called. */
6677 if (*patsub == '/')
d3ad40de
CR
6678 {
6679 mflags |= MATCH_GLOBREP;
6680 patsub++;
6681 }
7117c2d2
JA
6682
6683 /* Malloc this because expand_string_if_necessary or one of the expansion
6684 functions in its call chain may free it on a substitution error. */
bb70624e 6685 lpatsub = savestring (patsub);
ccc6cda3
JA
6686
6687 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6688 mflags |= MATCH_QUOTED;
6689
d3a24ed2
CR
6690 if (starsub)
6691 mflags |= MATCH_STARSUB;
6692
dc8fbaf9
CR
6693 /* If the pattern starts with a `/', make sure we skip over it when looking
6694 for the replacement delimiter. */
4d8d005b 6695 delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
c2a47ea9
CR
6696 if (lpatsub[delim] == '/')
6697 {
6698 lpatsub[delim] = 0;
6699 rep = lpatsub + delim + 1;
6700 }
6701 else
6702 rep = (char *)NULL;
ccc6cda3
JA
6703
6704 if (rep && *rep == '\0')
6705 rep = (char *)NULL;
6706
5e13499c
CR
6707 /* Perform the same expansions on the pattern as performed by the
6708 pattern removal expansions. */
6709 pat = getpattern (lpatsub, quoted, 1);
bb70624e 6710
ccc6cda3 6711 if (rep)
e73012f1
CR
6712 /* We want to perform quote removal on the expanded replacement even if
6713 the entire expansion is double-quoted because the parser and string
6714 extraction functions treated quotes in the replacement string as
6715 special. */
6716 rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
ccc6cda3 6717
dc8fbaf9 6718 /* ksh93 doesn't allow the match specifier to be a part of the expanded
d3ad40de
CR
6719 pattern. This is an extension. Make sure we don't anchor the pattern
6720 at the beginning or end of the string if we're doing global replacement,
6721 though. */
ccc6cda3 6722 p = pat;
d3ad40de
CR
6723 if (mflags & MATCH_GLOBREP)
6724 mflags |= MATCH_ANY;
dc8fbaf9 6725 else if (pat && pat[0] == '#')
ccc6cda3
JA
6726 {
6727 mflags |= MATCH_BEG;
6728 p++;
6729 }
d166f048 6730 else if (pat && pat[0] == '%')
ccc6cda3
JA
6731 {
6732 mflags |= MATCH_END;
6733 p++;
6734 }
6735 else
6736 mflags |= MATCH_ANY;
6737
cce855bc
JA
6738 /* OK, we now want to substitute REP for PAT in VAL. If
6739 flags & MATCH_GLOBREP is non-zero, the substitution is done
6740 everywhere, otherwise only the first occurrence of PAT is
7117c2d2
JA
6741 replaced. The pattern matching code doesn't understand
6742 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
6743 values passed in (VT_VARIABLE) so the pattern substitution
6744 code works right. We need to requote special chars after
6745 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
6746 other cases if QUOTED == 0, since the posparams and arrays
6747 indexed by * or @ do special things when QUOTED != 0. */
6748
ccc6cda3
JA
6749 switch (vtype)
6750 {
6751 case VT_VARIABLE:
d166f048 6752 case VT_ARRAYMEMBER:
ccc6cda3 6753 temp = pat_subst (val, p, rep, mflags);
7117c2d2
JA
6754 if (vtype == VT_VARIABLE)
6755 FREE (val);
6756 if (temp)
6757 {
e6598ba4 6758 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
7117c2d2
JA
6759 free (temp);
6760 temp = tt;
6761 }
ccc6cda3
JA
6762 break;
6763 case VT_POSPARMS:
6764 temp = pos_params_pat_subst (val, p, rep, mflags);
7117c2d2
JA
6765 if (temp && (mflags & MATCH_QUOTED) == 0)
6766 {
6767 tt = quote_escapes (temp);
6768 free (temp);
6769 temp = tt;
6770 }
ccc6cda3
JA
6771 break;
6772#if defined (ARRAY_VARS)
6773 case VT_ARRAYVAR:
fdf670ea
CR
6774 temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
6775 : array_patsub (array_cell (v), p, rep, mflags);
e6598ba4
CR
6776 /* Don't call quote_escapes anymore; array_patsub calls
6777 array_quote_escapes as appropriate before adding the
fdf670ea 6778 space separators; ditto for assoc_patsub. */
ccc6cda3
JA
6779 break;
6780#endif
6781 }
6782
6783 FREE (pat);
6784 FREE (rep);
bb70624e 6785 free (lpatsub);
ccc6cda3
JA
6786
6787 return temp;
6788}
6789
09767ff0
CR
6790/****************************************************************/
6791/* */
6792/* Functions to perform case modification on variable values */
6793/* */
6794/****************************************************************/
6795
6796/* Do case modification on the positional parameters. */
6797
6798static char *
6799pos_params_modcase (string, pat, modop, mflags)
6800 char *string, *pat;
6801 int modop;
6802 int mflags;
6803{
6804 WORD_LIST *save, *params;
6805 WORD_DESC *w;
6806 char *ret;
6807 int pchar, qflags;
6808
6809 save = params = list_rest_of_args ();
6810 if (save == 0)
6811 return ((char *)NULL);
6812
6813 for ( ; params; params = params->next)
6814 {
6815 ret = sh_modcase (params->word->word, pat, modop);
6816 w = alloc_word_desc ();
6817 w->word = ret ? ret : savestring ("");
6818 dispose_word (params->word);
6819 params->word = w;
6820 }
6821
6822 pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
6823 qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
6824
6825 ret = string_list_pos_params (pchar, save, qflags);
6826 dispose_words (save);
6827
6828 return (ret);
6829}
6830
6831/* Perform case modification on VALUE, which is the expansion of
6832 VARNAME. MODSPEC is an expression supplying the type of modification
6833 to perform. QUOTED is a flags word containing the type of quoting
6834 currently in effect. */
6835static char *
5f8cde23 6836parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags)
09767ff0 6837 char *varname, *value;
5f8cde23 6838 int ind, modspec;
09767ff0 6839 char *patspec;
5f8cde23 6840 int quoted, flags;
09767ff0
CR
6841{
6842 int vtype, starsub, modop, mflags, x;
6843 char *val, *temp, *pat, *p, *lpat, *tt;
6844 SHELL_VAR *v;
6845
6846 if (value == 0)
6847 return ((char *)NULL);
6848
6849 this_command_name = varname;
6850
5f8cde23 6851 vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
09767ff0
CR
6852 if (vtype == -1)
6853 return ((char *)NULL);
6854
6855 starsub = vtype & VT_STARSUB;
6856 vtype &= ~VT_STARSUB;
6857
6858 modop = 0;
6859 mflags = 0;
6860 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6861 mflags |= MATCH_QUOTED;
6862 if (starsub)
6863 mflags |= MATCH_STARSUB;
6864
6865 p = patspec;
6866 if (modspec == '^')
6867 {
6868 x = p && p[0] == modspec;
e141c35a 6869 modop = x ? CASE_UPPER : CASE_UPFIRST;
09767ff0
CR
6870 p += x;
6871 }
6872 else if (modspec == ',')
6873 {
6874 x = p && p[0] == modspec;
e141c35a 6875 modop = x ? CASE_LOWER : CASE_LOWFIRST;
09767ff0
CR
6876 p += x;
6877 }
6878 else if (modspec == '~')
6879 {
6880 x = p && p[0] == modspec;
6881 modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
6882 p += x;
6883 }
6884
6885 lpat = p ? savestring (p) : 0;
6886 /* Perform the same expansions on the pattern as performed by the
6887 pattern removal expansions. FOR LATER */
6888 pat = lpat ? getpattern (lpat, quoted, 1) : 0;
6889
6890 /* OK, now we do the case modification. */
6891 switch (vtype)
6892 {
6893 case VT_VARIABLE:
6894 case VT_ARRAYMEMBER:
6895 temp = sh_modcase (val, pat, modop);
6896 if (vtype == VT_VARIABLE)
6897 FREE (val);
6898 if (temp)
6899 {
6900 tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
6901 free (temp);
6902 temp = tt;
6903 }
6904 break;
6905
6906 case VT_POSPARMS:
6907 temp = pos_params_modcase (val, pat, modop, mflags);
6908 if (temp && (mflags & MATCH_QUOTED) == 0)
6909 {
6910 tt = quote_escapes (temp);
6911 free (temp);
6912 temp = tt;
6913 }
6914 break;
6915
6916#if defined (ARRAY_VARS)
6917 case VT_ARRAYVAR:
6918 temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
6919 : array_modcase (array_cell (v), pat, modop, mflags);
6920 /* Don't call quote_escapes; array_modcase calls array_quote_escapes
6921 as appropriate before adding the space separators; ditto for
6922 assoc_modcase. */
6923 break;
6924#endif
6925 }
6926
6927 FREE (pat);
6928 free (lpat);
6929
6930 return temp;
6931}
6932
d3ad40de
CR
6933/* Check for unbalanced parens in S, which is the contents of $(( ... )). If
6934 any occur, this must be a nested command substitution, so return 0.
6935 Otherwise, return 1. A valid arithmetic expression must always have a
6936 ( before a matching ), so any cases where there are more right parens
6937 means that this must not be an arithmetic expression, though the parser
6938 will not accept it without a balanced total number of parens. */
6939static int
6940chk_arithsub (s, len)
6941 const char *s;
6942 int len;
6943{
6944 int i, count;
6945 DECLARE_MBSTATE;
6946
6947 i = count = 0;
6948 while (i < len)
6949 {
176b12ee 6950 if (s[i] == LPAREN)
d3ad40de 6951 count++;
176b12ee 6952 else if (s[i] == RPAREN)
d3ad40de
CR
6953 {
6954 count--;
6955 if (count < 0)
6956 return 0;
6957 }
6958
6959 switch (s[i])
6960 {
6961 default:
6962 ADVANCE_CHAR (s, len, i);
6963 break;
6964
6965 case '\\':
6966 i++;
6967 if (s[i])
6968 ADVANCE_CHAR (s, len, i);
6969 break;
6970
6971 case '\'':
6972 i = skip_single_quoted (s, len, ++i);
6973 break;
6974
6975 case '"':
6976 i = skip_double_quoted ((char *)s, len, ++i);
6977 break;
6978 }
6979 }
6980
6981 return (count == 0);
6982}
6983
cce855bc
JA
6984/****************************************************************/
6985/* */
6986/* Functions to perform parameter expansion on a string */
6987/* */
6988/****************************************************************/
6989
09767ff0 6990/* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
227f982e 6991static WORD_DESC *
e1e48bba 6992parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
ccc6cda3 6993 char *string;
e1e48bba 6994 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags;
ccc6cda3
JA
6995{
6996 int check_nullness, var_is_set, var_is_null, var_is_special;
09767ff0 6997 int want_substring, want_indir, want_patsub, want_casemod;
ccc6cda3 6998 char *name, *value, *temp, *temp1;
227f982e 6999 WORD_DESC *tdesc, *ret;
09767ff0 7000 int t_index, sindex, c, tflag, modspec;
7117c2d2 7001 intmax_t number;
5f8cde23 7002 arrayind_t ind;
ccc6cda3 7003
c40a57dd 7004 temp = temp1 = value = (char *)NULL;
ccc6cda3 7005 var_is_set = var_is_null = var_is_special = check_nullness = 0;
09767ff0 7006 want_substring = want_indir = want_patsub = want_casemod = 0;
ccc6cda3 7007
cce855bc
JA
7008 sindex = *indexp;
7009 t_index = ++sindex;
11a6f9a9
CR
7010 /* ${#var} doesn't have any of the other parameter expansions on it. */
7011 if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
e6598ba4 7012 name = string_extract (string, &t_index, "}", SX_VARNAME);
11a6f9a9 7013 else
09767ff0
CR
7014#if defined (CASEMOD_EXPANSIONS)
7015 /* To enable case-toggling expansions using the `~' operator character
7016 change the 1 to 0. */
7017# if defined (CASEMOD_CAPCASE)
7018 name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
7019# else
7020 name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
7021# endif /* CASEMOD_CAPCASE */
7022#else
e6598ba4 7023 name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
09767ff0 7024#endif /* CASEMOD_EXPANSIONS */
cce855bc 7025
227f982e
CR
7026 ret = 0;
7027 tflag = 0;
7028
5f8cde23
CR
7029 ind = INTMAX_MIN;
7030
cce855bc
JA
7031 /* If the name really consists of a special variable, then make sure
7032 that we have the entire name. We don't allow indirect references
7033 to special variables except `#', `?', `@' and `*'. */
e05be32d
CR
7034 if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
7035 (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
ccc6cda3
JA
7036 {
7037 t_index++;
ccc6cda3 7038 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
631b20c6 7039 name = (char *)xrealloc (name, 3 + (strlen (temp1)));
ccc6cda3
JA
7040 *name = string[sindex];
7041 if (string[sindex] == '!')
7042 {
28ef6c31
JA
7043 /* indirect reference of $#, $?, $@, or $* */
7044 name[1] = string[sindex + 1];
7045 strcpy (name + 2, temp1);
ccc6cda3 7046 }
cce855bc 7047 else
ccc6cda3
JA
7048 strcpy (name + 1, temp1);
7049 free (temp1);
7050 }
7051 sindex = t_index;
7052
7053 /* Find out what character ended the variable name. Then
7054 do the appropriate thing. */
7055 if (c = string[sindex])
7056 sindex++;
7057
7058 /* If c is followed by one of the valid parameter expansion
7059 characters, move past it as normal. If not, assume that
7060 a substring specification is being given, and do not move
7061 past it. */
28ef6c31 7062 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
ccc6cda3
JA
7063 {
7064 check_nullness++;
7065 if (c = string[sindex])
7066 sindex++;
7067 }
cce855bc 7068 else if (c == ':' && string[sindex] != RBRACE)
ccc6cda3 7069 want_substring = 1;
77638cbf 7070 else if (c == '/' /* && string[sindex] != RBRACE */) /* XXX */
ccc6cda3 7071 want_patsub = 1;
09767ff0
CR
7072#if defined (CASEMOD_EXPANSIONS)
7073 else if (c == '^' || c == ',' || c == '~')
7074 {
7075 modspec = c;
7076 want_casemod = 1;
7077 }
7078#endif
ccc6cda3 7079
cce855bc
JA
7080 /* Catch the valid and invalid brace expressions that made it through the
7081 tests above. */
7082 /* ${#-} is a valid expansion and means to take the length of $-.
7083 Similarly for ${#?} and ${##}... */
7084 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
28ef6c31 7085 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
cce855bc 7086 {
f73dda09 7087 name = (char *)xrealloc (name, 3);
cce855bc
JA
7088 name[1] = c;
7089 name[2] = '\0';
7090 c = string[sindex++];
7091 }
7092
7093 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
7094 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
7095 member (c, "%:=+/") && string[sindex] == RBRACE)
7096 {
7097 temp = (char *)NULL;
7098 goto bad_substitution;
7099 }
e33f2203 7100
cce855bc
JA
7101 /* Indirect expansion begins with a `!'. A valid indirect expansion is
7102 either a variable name, one of the positional parameters or a special
7103 variable that expands to one of the positional parameters. */
7104 want_indir = *name == '!' &&
f73dda09 7105 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
7117c2d2 7106 || VALID_INDIR_PARAM (name[1]));
ccc6cda3
JA
7107
7108 /* Determine the value of this variable. */
7109
cce855bc 7110 /* Check for special variables, directly referenced. */
bb70624e 7111 if (SPECIAL_VAR (name, want_indir))
ccc6cda3
JA
7112 var_is_special++;
7113
cce855bc
JA
7114 /* Check for special expansion things, like the length of a parameter */
7115 if (*name == '#' && name[1])
ccc6cda3 7116 {
cce855bc 7117 /* If we are not pointing at the character just after the
28ef6c31
JA
7118 closing brace, then we haven't gotten all of the name.
7119 Since it begins with a special character, this is a bad
7120 substitution. Also check NAME for validity before trying
7121 to go on. */
cce855bc 7122 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
ccc6cda3
JA
7123 {
7124 temp = (char *)NULL;
7125 goto bad_substitution;
7126 }
7127
7128 number = parameter_brace_expand_length (name);
e05be32d
CR
7129 if (number == INTMAX_MIN && unbound_vars_is_error)
7130 {
7131 last_command_exit_value = EXECUTION_FAILURE;
7132 err_unboundvar (name+1);
7133 free (name);
7134 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7135 }
ccc6cda3
JA
7136 free (name);
7137
7138 *indexp = sindex;
227f982e
CR
7139 if (number < 0)
7140 return (&expand_wdesc_error);
7141 else
7142 {
7143 ret = alloc_word_desc ();
7144 ret->word = itos (number);
7145 return ret;
7146 }
ccc6cda3
JA
7147 }
7148
7149 /* ${@} is identical to $@. */
7150 if (name[0] == '@' && name[1] == '\0')
7151 {
7152 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7153 *quoted_dollar_atp = 1;
7154
7155 if (contains_dollar_at)
7156 *contains_dollar_at = 1;
348a457e
CR
7157
7158 tflag |= W_DOLLARAT;
ccc6cda3
JA
7159 }
7160
d3a24ed2 7161 /* Process ${!PREFIX*} expansion. */
bb70624e
JA
7162 if (want_indir && string[sindex - 1] == RBRACE &&
7163 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
f73dda09 7164 legal_variable_starter ((unsigned char) name[1]))
bb70624e
JA
7165 {
7166 char **x;
7167 WORD_LIST *xlist;
7168
7169 temp1 = savestring (name + 1);
7170 number = strlen (temp1);
7171 temp1[number - 1] = '\0';
7172 x = all_variables_matching_prefix (temp1);
7117c2d2 7173 xlist = strvec_to_word_list (x, 0, 0);
28ef6c31
JA
7174 if (string[sindex - 2] == '*')
7175 temp = string_list_dollar_star (xlist);
7176 else
7177 {
7178 temp = string_list_dollar_at (xlist, quoted);
7179 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7180 *quoted_dollar_atp = 1;
7181 if (contains_dollar_at)
7182 *contains_dollar_at = 1;
348a457e
CR
7183
7184 tflag |= W_DOLLARAT;
28ef6c31 7185 }
bb70624e 7186 free (x);
af98a2a6 7187 dispose_words (xlist);
bb70624e
JA
7188 free (temp1);
7189 *indexp = sindex;
227f982e 7190
631b20c6
CR
7191 free (name);
7192
227f982e
CR
7193 ret = alloc_word_desc ();
7194 ret->word = temp;
348a457e 7195 ret->flags = tflag; /* XXX */
227f982e 7196 return ret;
bb70624e 7197 }
d3a24ed2
CR
7198
7199#if defined (ARRAY_VARS)
5e13499c
CR
7200 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
7201 if (want_indir && string[sindex - 1] == RBRACE &&
7202 string[sindex - 2] == ']' && valid_array_reference (name+1))
d3a24ed2
CR
7203 {
7204 char *x, *x1;
7205
7206 temp1 = savestring (name + 1);
7207 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
7208 FREE (x);
7209 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
7210 {
fdf670ea 7211 temp = array_keys (temp1, quoted); /* handles assoc vars too */
d3a24ed2
CR
7212 if (x1[0] == '@')
7213 {
7214 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7215 *quoted_dollar_atp = 1;
7216 if (contains_dollar_at)
7217 *contains_dollar_at = 1;
348a457e
CR
7218
7219 tflag |= W_DOLLARAT;
d3a24ed2
CR
7220 }
7221
7222 free (temp1);
7223 *indexp = sindex;
227f982e
CR
7224
7225 ret = alloc_word_desc ();
7226 ret->word = temp;
348a457e 7227 ret->flags = tflag; /* XXX */
227f982e 7228 return ret;
d3a24ed2
CR
7229 }
7230
7231 free (temp1);
7232 }
7233#endif /* ARRAY_VARS */
bb70624e 7234
ccc6cda3
JA
7235 /* Make sure that NAME is valid before trying to go on. */
7236 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
7237 var_is_special) == 0)
7238 {
7239 temp = (char *)NULL;
7240 goto bad_substitution;
7241 }
7242
7243 if (want_indir)
227f982e 7244 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
ccc6cda3 7245 else
5f8cde23 7246 tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&PF_NOSPLIT2), &ind);
227f982e
CR
7247
7248 if (tdesc)
7249 {
7250 temp = tdesc->word;
7251 tflag = tdesc->flags;
7252 dispose_word_desc (tdesc);
7253 }
7254 else
7255 temp = (char *)0;
ccc6cda3 7256
15623760
CR
7257 if (temp == &expand_param_error || temp == &expand_param_fatal)
7258 {
7259 FREE (name);
7260 FREE (value);
7261 return (temp == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
7262 }
7263
ccc6cda3 7264#if defined (ARRAY_VARS)
cce855bc 7265 if (valid_array_reference (name))
d3a24ed2 7266 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
ccc6cda3
JA
7267#endif
7268
7269 var_is_set = temp != (char *)0;
7270 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
7271
7272 /* Get the rest of the stuff inside the braces. */
cce855bc 7273 if (c && c != RBRACE)
ccc6cda3
JA
7274 {
7275 /* Extract the contents of the ${ ... } expansion
28ef6c31 7276 according to the Posix.2 rules. */
e192f341 7277 value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
cce855bc 7278 if (string[sindex] == RBRACE)
28ef6c31 7279 sindex++;
ccc6cda3
JA
7280 else
7281 goto bad_substitution;
7282 }
7283 else
7284 value = (char *)NULL;
726f6388 7285
ccc6cda3
JA
7286 *indexp = sindex;
7287
e05be32d
CR
7288 /* All the cases where an expansion can possibly generate an unbound
7289 variable error. */
7290 if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
7291 {
7292 if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
7293 {
7294 last_command_exit_value = EXECUTION_FAILURE;
7295 err_unboundvar (name);
7296 FREE (value);
7297 FREE (temp);
7298 free (name);
7299 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7300 }
7301 }
7302
ccc6cda3
JA
7303 /* If this is a substring spec, process it and add the result. */
7304 if (want_substring)
726f6388 7305 {
5f8cde23 7306 temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
ccc6cda3
JA
7307 FREE (name);
7308 FREE (value);
7309 FREE (temp);
227f982e
CR
7310
7311 if (temp1 == &expand_param_error)
7312 return (&expand_wdesc_error);
7313 else if (temp1 == &expand_param_fatal)
7314 return (&expand_wdesc_fatal);
7315
7316 ret = alloc_word_desc ();
7317 ret->word = temp1;
d3ad40de
CR
7318 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7319 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
227f982e 7320 return ret;
726f6388 7321 }
ccc6cda3 7322 else if (want_patsub)
726f6388 7323 {
5f8cde23 7324 temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
ccc6cda3
JA
7325 FREE (name);
7326 FREE (value);
7327 FREE (temp);
227f982e
CR
7328
7329 if (temp1 == &expand_param_error)
7330 return (&expand_wdesc_error);
7331 else if (temp1 == &expand_param_fatal)
7332 return (&expand_wdesc_fatal);
7333
40c8fbee
CR
7334 ret = alloc_word_desc ();
7335 ret->word = temp1;
7336 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7337 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
227f982e 7338 return ret;
ccc6cda3 7339 }
09767ff0
CR
7340#if defined (CASEMOD_EXPANSIONS)
7341 else if (want_casemod)
7342 {
5f8cde23 7343 temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
09767ff0
CR
7344 FREE (name);
7345 FREE (value);
7346 FREE (temp);
7347
7348 if (temp1 == &expand_param_error)
7349 return (&expand_wdesc_error);
7350 else if (temp1 == &expand_param_fatal)
7351 return (&expand_wdesc_fatal);
7352
7353 ret = alloc_word_desc ();
7354 ret->word = temp1;
40c8fbee
CR
7355 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7356 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
09767ff0
CR
7357 return ret;
7358 }
7359#endif
726f6388 7360
ccc6cda3
JA
7361 /* Do the right thing based on which character ended the variable name. */
7362 switch (c)
7363 {
7364 default:
7365 case '\0':
7366 bad_substitution:
7f947b68 7367 last_command_exit_value = EXECUTION_FAILURE;
5e13499c 7368 report_error (_("%s: bad substitution"), string ? string : "??");
ccc6cda3
JA
7369 FREE (value);
7370 FREE (temp);
7371 free (name);
227f982e 7372 return &expand_wdesc_error;
ccc6cda3 7373
cce855bc 7374 case RBRACE:
ccc6cda3 7375 break;
726f6388 7376
ccc6cda3
JA
7377 case '#': /* ${param#[#]pattern} */
7378 case '%': /* ${param%[%]pattern} */
7379 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
28ef6c31
JA
7380 {
7381 FREE (value);
ccc6cda3 7382 break;
28ef6c31 7383 }
5f8cde23 7384 temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
ccc6cda3
JA
7385 free (temp);
7386 free (value);
3d35553a 7387 free (name);
40c8fbee
CR
7388
7389 ret = alloc_word_desc ();
7390 ret->word = temp1;
7391 if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7392 ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
7393 return ret;
ccc6cda3
JA
7394
7395 case '-':
7396 case '=':
7397 case '?':
7398 case '+':
7399 if (var_is_set && var_is_null == 0)
28ef6c31
JA
7400 {
7401 /* If the operator is `+', we don't want the value of the named
7402 variable for anything, just the value of the right hand side. */
ccc6cda3
JA
7403 if (c == '+')
7404 {
28ef6c31
JA
7405 /* XXX -- if we're double-quoted and the named variable is "$@",
7406 we want to turn off any special handling of "$@" --
7407 we're not using it, so whatever is on the rhs applies. */
7408 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7409 *quoted_dollar_atp = 0;
7410 if (contains_dollar_at)
7411 *contains_dollar_at = 0;
7412
ccc6cda3
JA
7413 FREE (temp);
7414 if (value)
28ef6c31 7415 {
6faad625
CR
7416 /* From Posix discussion on austin-group list. Issue 221
7417 requires that backslashes escaping `}' inside
7418 double-quoted ${...} be removed. */
64419627
CR
7419 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7420 quoted |= Q_DOLBRACE;
227f982e
CR
7421 ret = parameter_brace_expand_rhs (name, value, c,
7422 quoted,
7423 quoted_dollar_atp,
7424 contains_dollar_at);
7425 /* XXX - fix up later, esp. noting presence of
7426 W_HASQUOTEDNULL in ret->flags */
ccc6cda3
JA
7427 free (value);
7428 }
7429 else
28ef6c31 7430 temp = (char *)NULL;
ccc6cda3
JA
7431 }
7432 else
7433 {
7434 FREE (value);
7435 }
7436 /* Otherwise do nothing; just use the value in TEMP. */
726f6388 7437 }
ccc6cda3 7438 else /* VAR not set or VAR is NULL. */
28ef6c31 7439 {
ccc6cda3
JA
7440 FREE (temp);
7441 temp = (char *)NULL;
7442 if (c == '=' && var_is_special)
7443 {
7f947b68 7444 last_command_exit_value = EXECUTION_FAILURE;
5e13499c 7445 report_error (_("$%s: cannot assign in this way"), name);
ccc6cda3
JA
7446 free (name);
7447 free (value);
227f982e 7448 return &expand_wdesc_error;
ccc6cda3
JA
7449 }
7450 else if (c == '?')
7451 {
7452 parameter_brace_expand_error (name, value);
227f982e 7453 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
ccc6cda3
JA
7454 }
7455 else if (c != '+')
28ef6c31
JA
7456 {
7457 /* XXX -- if we're double-quoted and the named variable is "$@",
7458 we want to turn off any special handling of "$@" --
7459 we're not using it, so whatever is on the rhs applies. */
7460 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
7461 *quoted_dollar_atp = 0;
7462 if (contains_dollar_at)
7463 *contains_dollar_at = 0;
7464
6faad625
CR
7465 /* From Posix discussion on austin-group list. Issue 221 requires
7466 that backslashes escaping `}' inside double-quoted ${...} be
7467 removed. */
64419627
CR
7468 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7469 quoted |= Q_DOLBRACE;
227f982e
CR
7470 ret = parameter_brace_expand_rhs (name, value, c, quoted,
7471 quoted_dollar_atp,
7472 contains_dollar_at);
7473 /* XXX - fix up later, esp. noting presence of
7474 W_HASQUOTEDNULL in tdesc->flags */
28ef6c31 7475 }
ccc6cda3 7476 free (value);
726f6388 7477 }
28ef6c31 7478
ccc6cda3 7479 break;
726f6388 7480 }
ccc6cda3 7481 free (name);
227f982e
CR
7482
7483 if (ret == 0)
7484 {
7485 ret = alloc_word_desc ();
7486 ret->flags = tflag;
7487 ret->word = temp;
7488 }
7489 return (ret);
726f6388
JA
7490}
7491
cce855bc
JA
7492/* Expand a single ${xxx} expansion. The braces are optional. When
7493 the braces are used, parameter_brace_expand() does the work,
7494 possibly calling param_expand recursively. */
227f982e 7495static WORD_DESC *
cce855bc
JA
7496param_expand (string, sindex, quoted, expanded_something,
7497 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
7498 pflags)
7499 char *string;
7500 int *sindex, quoted, *expanded_something, *contains_dollar_at;
7501 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
7502{
7117c2d2 7503 char *temp, *temp1, uerror[3];
f73dda09
JA
7504 int zindex, t_index, expok;
7505 unsigned char c;
7117c2d2 7506 intmax_t number;
cce855bc 7507 SHELL_VAR *var;
f73dda09 7508 WORD_LIST *list;
227f982e
CR
7509 WORD_DESC *tdesc, *ret;
7510 int tflag;
cce855bc
JA
7511
7512 zindex = *sindex;
7513 c = string[++zindex];
7514
7515 temp = (char *)NULL;
227f982e
CR
7516 ret = tdesc = (WORD_DESC *)NULL;
7517 tflag = 0;
cce855bc
JA
7518
7519 /* Do simple cases first. Switch on what follows '$'. */
7520 switch (c)
7521 {
7522 /* $0 .. $9? */
7523 case '0':
7524 case '1':
7525 case '2':
7526 case '3':
7527 case '4':
7528 case '5':
7529 case '6':
7530 case '7':
7531 case '8':
7532 case '9':
f73dda09 7533 temp1 = dollar_vars[TODIGIT (c)];
cce855bc
JA
7534 if (unbound_vars_is_error && temp1 == (char *)NULL)
7535 {
7117c2d2
JA
7536 uerror[0] = '$';
7537 uerror[1] = c;
7538 uerror[2] = '\0';
cce855bc 7539 last_command_exit_value = EXECUTION_FAILURE;
0d8616ff 7540 err_unboundvar (uerror);
227f982e 7541 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
cce855bc 7542 }
5ba8ff6e 7543 if (temp1)
762a763b 7544 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
5ba8ff6e
CR
7545 ? quote_string (temp1)
7546 : quote_escapes (temp1);
7547 else
7548 temp = (char *)NULL;
227f982e 7549
cce855bc
JA
7550 break;
7551
7552 /* $$ -- pid of the invoking shell. */
7553 case '$':
7554 temp = itos (dollar_dollar_pid);
7555 break;
7556
7557 /* $# -- number of positional parameters. */
7558 case '#':
7559 temp = itos (number_of_args ());
7560 break;
7561
7562 /* $? -- return value of the last synchronous command. */
7563 case '?':
7564 temp = itos (last_command_exit_value);
7565 break;
7566
7567 /* $- -- flags supplied to the shell on invocation or by `set'. */
7568 case '-':
7569 temp = which_set_flags ();
7570 break;
7571
7572 /* $! -- Pid of the last asynchronous command. */
7573 case '!':
7574 /* If no asynchronous pids have been created, expand to nothing.
7575 If `set -u' has been executed, and no async processes have
7576 been created, this is an expansion error. */
7577 if (last_asynchronous_pid == NO_PID)
7578 {
7579 if (expanded_something)
7580 *expanded_something = 0;
7581 temp = (char *)NULL;
7582 if (unbound_vars_is_error)
7583 {
7117c2d2
JA
7584 uerror[0] = '$';
7585 uerror[1] = c;
7586 uerror[2] = '\0';
cce855bc 7587 last_command_exit_value = EXECUTION_FAILURE;
0d8616ff 7588 err_unboundvar (uerror);
227f982e 7589 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
cce855bc
JA
7590 }
7591 }
7592 else
f73dda09 7593 temp = itos (last_asynchronous_pid);
cce855bc
JA
7594 break;
7595
7596 /* The only difference between this and $@ is when the arg is quoted. */
7597 case '*': /* `$*' */
7598 list = list_rest_of_args ();
7599
12ae1612
CR
7600#if 0
7601 /* According to austin-group posix proposal by Geoff Clare in
7602 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7603
7604 "The shell shall write a message to standard error and
7605 immediately exit when it tries to expand an unset parameter
7606 other than the '@' and '*' special parameters."
7607 */
7608
1231ac47 7609 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
57a3f689
CR
7610 {
7611 uerror[0] = '$';
7612 uerror[1] = '*';
7613 uerror[2] = '\0';
57a3f689 7614 last_command_exit_value = EXECUTION_FAILURE;
0d8616ff 7615 err_unboundvar (uerror);
57a3f689
CR
7616 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7617 }
12ae1612 7618#endif
57a3f689 7619
cce855bc
JA
7620 /* If there are no command-line arguments, this should just
7621 disappear if there are other characters in the expansion,
7622 even if it's quoted. */
7623 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
7624 temp = (char *)NULL;
1231ac47 7625 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
cce855bc
JA
7626 {
7627 /* If we have "$*" we want to make a string of the positional
7628 parameters, separated by the first character of $IFS, and
7629 quote the whole string, including the separators. If IFS
7630 is unset, the parameters are separated by ' '; if $IFS is
7631 null, the parameters are concatenated. */
1231ac47 7632 temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
adc6cff5
CR
7633 if (temp)
7634 {
7635 temp1 = quote_string (temp);
7636 if (*temp == 0)
7637 tflag |= W_HASQUOTEDNULL;
7638 free (temp);
7639 temp = temp1;
7640 }
cce855bc
JA
7641 }
7642 else
28ef6c31 7643 {
227f982e
CR
7644 /* We check whether or not we're eventually going to split $* here,
7645 for example when IFS is empty and we are processing the rhs of
7646 an assignment statement. In that case, we don't separate the
7647 arguments at all. Otherwise, if the $* is not quoted it is
7648 identical to $@ */
7649#if 1
7650# if defined (HANDLE_MULTIBYTE)
7651 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
7652# else
7653 if (expand_no_split_dollar_star && ifs_firstc == 0)
7654# endif
7655 temp = string_list_dollar_star (list);
7656 else
7657 temp = string_list_dollar_at (list, quoted);
7658#else
28ef6c31 7659 temp = string_list_dollar_at (list, quoted);
227f982e 7660#endif
28ef6c31
JA
7661 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
7662 *contains_dollar_at = 1;
7663 }
cce855bc
JA
7664
7665 dispose_words (list);
7666 break;
7667
7668 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
7669 means that we have to turn quoting off after we split into
7670 the individually quoted arguments so that the final split
7671 on the first character of $IFS is still done. */
7672 case '@': /* `$@' */
7673 list = list_rest_of_args ();
7674
12ae1612
CR
7675#if 0
7676 /* According to austin-group posix proposal by Geoff Clare in
7677 <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
7678
7679 "The shell shall write a message to standard error and
7680 immediately exit when it tries to expand an unset parameter
7681 other than the '@' and '*' special parameters."
7682 */
7683
1231ac47 7684 if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
57a3f689
CR
7685 {
7686 uerror[0] = '$';
7687 uerror[1] = '@';
7688 uerror[2] = '\0';
57a3f689 7689 last_command_exit_value = EXECUTION_FAILURE;
0d8616ff 7690 err_unboundvar (uerror);
57a3f689
CR
7691 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
7692 }
12ae1612 7693#endif
57a3f689 7694
cce855bc
JA
7695 /* We want to flag the fact that we saw this. We can't turn
7696 off quoting entirely, because other characters in the
7697 string might need it (consider "\"$@\""), but we need some
7698 way to signal that the final split on the first character
7699 of $IFS should be done, even though QUOTED is 1. */
1231ac47 7700 /* XXX - should this test include Q_PATQUOTE? */
cce855bc
JA
7701 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7702 *quoted_dollar_at_p = 1;
7703 if (contains_dollar_at)
7704 *contains_dollar_at = 1;
7705
7706 /* We want to separate the positional parameters with the first
7707 character of $IFS in case $IFS is something other than a space.
7708 We also want to make sure that splitting is done no matter what --
7709 according to POSIX.2, this expands to a list of the positional
7710 parameters no matter what IFS is set to. */
40647963 7711 temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted);
cce855bc 7712
348a457e 7713 tflag |= W_DOLLARAT;
cce855bc
JA
7714 dispose_words (list);
7715 break;
7716
7717 case LBRACE:
e1e48bba 7718 tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
227f982e
CR
7719 quoted_dollar_at_p,
7720 contains_dollar_at);
7721
227f982e
CR
7722 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7723 return (tdesc);
7724 temp = tdesc ? tdesc->word : (char *)0;
cce855bc
JA
7725
7726 /* XXX */
bb70624e 7727 /* Quoted nulls should be removed if there is anything else
cce855bc
JA
7728 in the string. */
7729 /* Note that we saw the quoted null so we can add one back at
7730 the end of this function if there are no other characters
28ef6c31
JA
7731 in the string, discard TEMP, and go on. The exception to
7732 this is when we have "${@}" and $1 is '', since $@ needs
7733 special handling. */
227f982e 7734 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
cce855bc
JA
7735 {
7736 if (had_quoted_null_p)
7737 *had_quoted_null_p = 1;
28ef6c31
JA
7738 if (*quoted_dollar_at_p == 0)
7739 {
7740 free (temp);
227f982e 7741 tdesc->word = temp = (char *)NULL;
28ef6c31
JA
7742 }
7743
cce855bc
JA
7744 }
7745
227f982e 7746 ret = tdesc;
cce855bc
JA
7747 goto return0;
7748
7749 /* Do command or arithmetic substitution. */
7750 case LPAREN:
7751 /* We have to extract the contents of this paren substitution. */
7752 t_index = zindex + 1;
e33f2203 7753 temp = extract_command_subst (string, &t_index, 0);
cce855bc
JA
7754 zindex = t_index;
7755
7756 /* For Posix.2-style `$(( ))' arithmetic substitution,
28ef6c31 7757 extract the expression and pass it to the evaluator. */
cce855bc
JA
7758 if (temp && *temp == LPAREN)
7759 {
7760 char *temp2;
7761 temp1 = temp + 1;
7762 temp2 = savestring (temp1);
7763 t_index = strlen (temp2) - 1;
7764
7765 if (temp2[t_index] != RPAREN)
7766 {
7767 free (temp2);
7768 goto comsub;
7769 }
7770
7771 /* Cut off ending `)' */
7772 temp2[t_index] = '\0';
7773
d3ad40de
CR
7774 if (chk_arithsub (temp2, t_index) == 0)
7775 {
7776 free (temp2);
984a1947 7777#if 0
ecf57862 7778 internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
984a1947 7779#endif
d3ad40de
CR
7780 goto comsub;
7781 }
7782
cce855bc 7783 /* Expand variables found inside the expression. */
d3ad40de 7784 temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
cce855bc
JA
7785 free (temp2);
7786
7787arithsub:
7788 /* No error messages. */
7789 this_command_name = (char *)NULL;
7790 number = evalexp (temp1, &expok);
7791 free (temp);
7792 free (temp1);
7793 if (expok == 0)
7794 {
7795 if (interactive_shell == 0 && posixly_correct)
7796 {
7797 last_command_exit_value = EXECUTION_FAILURE;
227f982e 7798 return (&expand_wdesc_fatal);
cce855bc
JA
7799 }
7800 else
227f982e 7801 return (&expand_wdesc_error);
cce855bc
JA
7802 }
7803 temp = itos (number);
7804 break;
7805 }
7806
7807comsub:
d3a24ed2
CR
7808 if (pflags & PF_NOCOMSUB)
7809 /* we need zindex+1 because string[zindex] == RPAREN */
7810 temp1 = substring (string, *sindex, zindex+1);
7811 else
d3ad40de
CR
7812 {
7813 tdesc = command_substitute (temp, quoted);
7814 temp1 = tdesc ? tdesc->word : (char *)NULL;
e33f2203
CR
7815 if (tdesc)
7816 dispose_word_desc (tdesc);
d3ad40de 7817 }
cce855bc
JA
7818 FREE (temp);
7819 temp = temp1;
7820 break;
7821
7822 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
7823 away in a future bash release. */
7824 case '[':
bb70624e 7825 /* Extract the contents of this arithmetic substitution. */
cce855bc
JA
7826 t_index = zindex + 1;
7827 temp = extract_arithmetic_subst (string, &t_index);
7828 zindex = t_index;
35bb237e
CR
7829 if (temp == 0)
7830 {
7831 temp = savestring (string);
7832 if (expanded_something)
7833 *expanded_something = 0;
7834 goto return0;
7835 }
cce855bc
JA
7836
7837 /* Do initial variable expansion. */
d3ad40de 7838 temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
cce855bc
JA
7839
7840 goto arithsub;
7841
7842 default:
7843 /* Find the variable in VARIABLE_LIST. */
7844 temp = (char *)NULL;
7845
7846 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
7847 ;
7848 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
7849
7850 /* If this isn't a variable name, then just output the `$'. */
7851 if (temp1 == 0 || *temp1 == '\0')
7852 {
7853 FREE (temp1);
f73dda09 7854 temp = (char *)xmalloc (2);
cce855bc
JA
7855 temp[0] = '$';
7856 temp[1] = '\0';
7857 if (expanded_something)
7858 *expanded_something = 0;
7859 goto return0;
7860 }
7861
7862 /* If the variable exists, return its value cell. */
7863 var = find_variable (temp1);
7864
7117c2d2 7865 if (var && invisible_p (var) == 0 && var_isset (var))
cce855bc
JA
7866 {
7867#if defined (ARRAY_VARS)
fdf670ea 7868 if (assoc_p (var) || array_p (var))
cce855bc 7869 {
fdf670ea
CR
7870 temp = array_p (var) ? array_reference (array_cell (var), 0)
7871 : assoc_reference (assoc_cell (var), "0");
cce855bc 7872 if (temp)
762a763b 7873 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
5ba8ff6e
CR
7874 ? quote_string (temp)
7875 : quote_escapes (temp);
5565fb1a
CR
7876 else if (unbound_vars_is_error)
7877 goto unbound_variable;
cce855bc
JA
7878 }
7879 else
7880#endif
762a763b
CR
7881 {
7882 temp = value_cell (var);
7883
7884 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
7885 ? quote_string (temp)
7886 : quote_escapes (temp);
7887 }
5ba8ff6e 7888
cce855bc 7889 free (temp1);
7117c2d2 7890
cce855bc
JA
7891 goto return0;
7892 }
d42cb8c1
CR
7893 else if (var = find_variable_last_nameref (temp1))
7894 {
7895 temp = nameref_cell (var);
15623760 7896#if defined (ARRAY_VARS)
d42cb8c1
CR
7897 if (temp && *temp && valid_array_reference (temp))
7898 {
f14388d3 7899 tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL);
d42cb8c1
CR
7900 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
7901 return (tdesc);
7902 ret = tdesc;
7903 goto return0;
7904 }
7905 else
15623760
CR
7906#endif
7907 /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
7908 if (temp && *temp && legal_identifier (temp) == 0)
7909 {
7910 last_command_exit_value = EXECUTION_FAILURE;
7911 report_error (_("%s: invalid variable name for name reference"), temp);
7912 return (&expand_wdesc_error); /* XXX */
7913 }
7914 else
d42cb8c1
CR
7915 temp = (char *)NULL;
7916 }
cce855bc
JA
7917
7918 temp = (char *)NULL;
7919
5565fb1a 7920unbound_variable:
cce855bc 7921 if (unbound_vars_is_error)
0d8616ff
CR
7922 {
7923 last_command_exit_value = EXECUTION_FAILURE;
7924 err_unboundvar (temp1);
7925 }
cce855bc
JA
7926 else
7927 {
7928 free (temp1);
7929 goto return0;
7930 }
7931
7932 free (temp1);
7933 last_command_exit_value = EXECUTION_FAILURE;
7934 return ((unbound_vars_is_error && interactive_shell == 0)
227f982e
CR
7935 ? &expand_wdesc_fatal
7936 : &expand_wdesc_error);
cce855bc
JA
7937 }
7938
7939 if (string[zindex])
7940 zindex++;
7941
7942return0:
7943 *sindex = zindex;
227f982e
CR
7944
7945 if (ret == 0)
7946 {
7947 ret = alloc_word_desc ();
7948 ret->flags = tflag; /* XXX */
7949 ret->word = temp;
7950 }
7951 return ret;
cce855bc
JA
7952}
7953
7954/* Make a word list which is the result of parameter and variable
7955 expansion, command substitution, arithmetic substitution, and
7956 quote removal of WORD. Return a pointer to a WORD_LIST which is
7957 the result of the expansion. If WORD contains a null word, the
7958 word list returned is also null.
726f6388 7959
ccc6cda3
JA
7960 QUOTED contains flag values defined in shell.h.
7961
b72432fd
JA
7962 ISEXP is used to tell expand_word_internal that the word should be
7963 treated as the result of an expansion. This has implications for
7964 how IFS characters in the word are treated.
7965
726f6388
JA
7966 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
7967 they point to an integer value which receives information about expansion.
7968 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
7969 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
7970 else zero.
7971
7972 This only does word splitting in the case of $@ expansion. In that
7973 case, we split on ' '. */
7974
7975/* Values for the local variable quoted_state. */
7976#define UNQUOTED 0
7977#define PARTIALLY_QUOTED 1
7978#define WHOLLY_QUOTED 2
7979
7980static WORD_LIST *
b72432fd 7981expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
726f6388 7982 WORD_DESC *word;
b72432fd 7983 int quoted, isexp;
726f6388
JA
7984 int *contains_dollar_at;
7985 int *expanded_something;
7986{
ccc6cda3
JA
7987 WORD_LIST *list;
7988 WORD_DESC *tword;
726f6388
JA
7989
7990 /* The intermediate string that we build while expanding. */
ccc6cda3 7991 char *istring;
726f6388
JA
7992
7993 /* The current size of the above object. */
ccc6cda3 7994 int istring_size;
726f6388
JA
7995
7996 /* Index into ISTRING. */
ccc6cda3 7997 int istring_index;
726f6388
JA
7998
7999 /* Temporary string storage. */
ccc6cda3 8000 char *temp, *temp1;
726f6388
JA
8001
8002 /* The text of WORD. */
ccc6cda3 8003 register char *string;
726f6388 8004
7117c2d2
JA
8005 /* The size of STRING. */
8006 size_t string_size;
8007
726f6388 8008 /* The index into STRING. */
ccc6cda3 8009 int sindex;
726f6388
JA
8010
8011 /* This gets 1 if we see a $@ while quoted. */
ccc6cda3 8012 int quoted_dollar_at;
726f6388
JA
8013
8014 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
8015 whether WORD contains no quoting characters, a partially quoted
8016 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
ccc6cda3
JA
8017 int quoted_state;
8018
22e63b05 8019 /* State flags */
ccc6cda3 8020 int had_quoted_null;
348a457e 8021 int has_dollar_at, temp_has_dollar_at;
28ef6c31 8022 int tflag;
e1e48bba 8023 int pflags; /* flags passed to param_expand */
726f6388 8024
22e63b05
CR
8025 int assignoff; /* If assignment, offset of `=' */
8026
f73dda09 8027 register unsigned char c; /* Current character. */
726f6388 8028 int t_index; /* For calls to string_extract_xxx. */
726f6388 8029
bb70624e 8030 char twochars[2];
b72432fd 8031
7117c2d2
JA
8032 DECLARE_MBSTATE;
8033
f73dda09 8034 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
ccc6cda3 8035 istring[istring_index = 0] = '\0';
cce855bc 8036 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
ccc6cda3
JA
8037 quoted_state = UNQUOTED;
8038
8039 string = word->word;
8040 if (string == 0)
8041 goto finished_with_string;
da713c23
CR
8042 /* Don't need the string length for the SADD... and COPY_ macros unless
8043 multibyte characters are possible. */
8044 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
726f6388
JA
8045
8046 if (contains_dollar_at)
8047 *contains_dollar_at = 0;
8048
22e63b05
CR
8049 assignoff = -1;
8050
726f6388
JA
8051 /* Begin the expansion. */
8052
ccc6cda3 8053 for (sindex = 0; ;)
726f6388
JA
8054 {
8055 c = string[sindex];
8056
8057 /* Case on toplevel character. */
8058 switch (c)
8059 {
8060 case '\0':
8061 goto finished_with_string;
8062
8063 case CTLESC:
7117c2d2
JA
8064 sindex++;
8065#if HANDLE_MULTIBYTE
8066 if (MB_CUR_MAX > 1 && string[sindex])
8067 {
545f34cf 8068 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7117c2d2
JA
8069 }
8070 else
8071#endif
8072 {
8073 temp = (char *)xmalloc (3);
8074 temp[0] = CTLESC;
8075 temp[1] = c = string[sindex];
8076 temp[2] = '\0';
8077 }
726f6388 8078
cce855bc 8079dollar_add_string:
726f6388
JA
8080 if (string[sindex])
8081 sindex++;
8082
cce855bc
JA
8083add_string:
8084 if (temp)
8085 {
8086 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
8087 temp = (char *)0;
8088 }
8089
8090 break;
726f6388
JA
8091
8092#if defined (PROCESS_SUBSTITUTION)
8093 /* Process substitution. */
8094 case '<':
8095 case '>':
8096 {
dc8fbaf9 8097 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
726f6388 8098 {
bb70624e 8099 sindex--; /* add_character: label increments sindex */
726f6388
JA
8100 goto add_character;
8101 }
8102 else
cce855bc 8103 t_index = sindex + 1; /* skip past both '<' and LPAREN */
726f6388 8104
cce855bc 8105 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
ccc6cda3 8106 sindex = t_index;
726f6388
JA
8107
8108 /* If the process substitution specification is `<()', we want to
8109 open the pipe for writing in the child and produce output; if
8110 it is `>()', we want to open the pipe for reading in the child
8111 and consume input. */
ccc6cda3 8112 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
726f6388
JA
8113
8114 FREE (temp1);
8115
8116 goto dollar_add_string;
8117 }
8118#endif /* PROCESS_SUBSTITUTION */
8119
22e63b05
CR
8120 case '=':
8121 /* Posix.2 section 3.6.1 says that tildes following `=' in words
8122 which are not assignment statements are not expanded. If the
8123 shell isn't in posix mode, though, we perform tilde expansion
8124 on `likely candidate' unquoted assignment statements (flags
8125 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
8126 contains an unquoted :~ or =~. Something to think about: we
8127 now have a flag that says to perform tilde expansion on arguments
8128 to `assignment builtins' like declare and export that look like
8129 assignment statements. We now do tilde expansion on such words
8130 even in POSIX mode. */
8131 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
c1d39fb8 8132 {
e1e48bba 8133 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
c1d39fb8
CR
8134 goto add_ifs_character;
8135 else
8136 goto add_character;
8137 }
22e63b05
CR
8138 /* If we're not in posix mode or forcing assignment-statement tilde
8139 expansion, note where the `=' appears in the word and prepare to
8140 do tilde expansion following the first `='. */
8141 if ((word->flags & W_ASSIGNMENT) &&
8142 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8143 assignoff == -1 && sindex > 0)
8144 assignoff = sindex;
8145 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
8146 word->flags |= W_ITILDE;
d90269dd 8147#if 0
22e63b05
CR
8148 else if ((word->flags & W_ASSIGNMENT) &&
8149 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
8150 string[sindex+1] == '~')
8151 word->flags |= W_ITILDE;
d90269dd 8152#endif
e1e48bba 8153 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
c1d39fb8
CR
8154 goto add_ifs_character;
8155 else
8156 goto add_character;
22e63b05
CR
8157
8158 case ':':
8159 if (word->flags & W_NOTILDE)
c1d39fb8 8160 {
e1e48bba 8161 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
c1d39fb8
CR
8162 goto add_ifs_character;
8163 else
8164 goto add_character;
8165 }
cdb32d45
CR
8166
8167 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
22e63b05
CR
8168 string[sindex+1] == '~')
8169 word->flags |= W_ITILDE;
c1d39fb8 8170
e1e48bba 8171 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
c1d39fb8
CR
8172 goto add_ifs_character;
8173 else
8174 goto add_character;
22e63b05
CR
8175
8176 case '~':
8177 /* If the word isn't supposed to be tilde expanded, or we're not
8178 at the start of a word or after an unquoted : or = in an
8179 assignment statement, we don't do tilde expansion. */
da719982 8180 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
22e63b05
CR
8181 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
8182 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8183 {
8184 word->flags &= ~W_ITILDE;
e1e48bba 8185 if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
c1d39fb8
CR
8186 goto add_ifs_character;
8187 else
8188 goto add_character;
22e63b05
CR
8189 }
8190
8191 if (word->flags & W_ASSIGNRHS)
8192 tflag = 2;
cdb32d45 8193 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
22e63b05
CR
8194 tflag = 1;
8195 else
8196 tflag = 0;
8197
8198 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
8199
8200 word->flags &= ~W_ITILDE;
8201
8202 if (temp && *temp && t_index > 0)
8203 {
8204 temp1 = bash_tilde_expand (temp, tflag);
dc8fbaf9
CR
8205 if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
8206 {
8207 FREE (temp);
8208 FREE (temp1);
8209 goto add_character; /* tilde expansion failed */
8210 }
22e63b05
CR
8211 free (temp);
8212 temp = temp1;
8213 sindex += t_index;
866961ad 8214 goto add_quoted_string; /* XXX was add_string */
22e63b05
CR
8215 }
8216 else
8217 {
8218 FREE (temp);
8219 goto add_character;
8220 }
8221
726f6388 8222 case '$':
726f6388
JA
8223 if (expanded_something)
8224 *expanded_something = 1;
8225
348a457e 8226 temp_has_dollar_at = 0;
e1e48bba
CR
8227 pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
8228 if (word->flags & W_NOSPLIT2)
8229 pflags |= PF_NOSPLIT2;
40647963
CR
8230 if (word->flags & W_ASSIGNRHS)
8231 pflags |= PF_ASSIGNRHS;
227f982e 8232 tword = param_expand (string, &sindex, quoted, expanded_something,
348a457e 8233 &temp_has_dollar_at, &quoted_dollar_at,
e1e48bba 8234 &had_quoted_null, pflags);
348a457e 8235 has_dollar_at += temp_has_dollar_at;
726f6388 8236
227f982e 8237 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
726f6388 8238 {
cce855bc
JA
8239 free (string);
8240 free (istring);
227f982e
CR
8241 return ((tword == &expand_wdesc_error) ? &expand_word_error
8242 : &expand_word_fatal);
cce855bc
JA
8243 }
8244 if (contains_dollar_at && has_dollar_at)
8245 *contains_dollar_at = 1;
227f982e
CR
8246
8247 if (tword && (tword->flags & W_HASQUOTEDNULL))
8248 had_quoted_null = 1;
8249
77638cbf 8250 temp = tword ? tword->word : (char *)NULL;
227f982e
CR
8251 dispose_word_desc (tword);
8252
efc2f955
CR
8253 /* Kill quoted nulls; we will add them back at the end of
8254 expand_word_internal if nothing else in the string */
8255 if (had_quoted_null && temp && QUOTED_NULL (temp))
8256 {
8257 FREE (temp);
8258 temp = (char *)NULL;
8259 }
8260
cce855bc
JA
8261 goto add_string;
8262 break;
726f6388 8263
cce855bc
JA
8264 case '`': /* Backquoted command substitution. */
8265 {
d3a24ed2 8266 t_index = sindex++;
726f6388 8267
e6598ba4 8268 temp = string_extract (string, &sindex, "`", SX_REQMATCH);
bc7bed50
CR
8269 /* The test of sindex against t_index is to allow bare instances of
8270 ` to pass through, for backwards compatibility. */
7027abcb
CR
8271 if (temp == &extract_string_error || temp == &extract_string_fatal)
8272 {
bc7bed50
CR
8273 if (sindex - 1 == t_index)
8274 {
8275 sindex = t_index;
8276 goto add_character;
8277 }
7f947b68 8278 last_command_exit_value = EXECUTION_FAILURE;
d3ad40de 8279 report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
7027abcb
CR
8280 free (string);
8281 free (istring);
8282 return ((temp == &extract_string_error) ? &expand_word_error
8283 : &expand_word_fatal);
8284 }
8285
bc7bed50
CR
8286 if (expanded_something)
8287 *expanded_something = 1;
8288
d3a24ed2
CR
8289 if (word->flags & W_NOCOMSUB)
8290 /* sindex + 1 because string[sindex] == '`' */
8291 temp1 = substring (string, t_index, sindex + 1);
8292 else
8293 {
8294 de_backslash (temp);
d3ad40de
CR
8295 tword = command_substitute (temp, quoted);
8296 temp1 = tword ? tword->word : (char *)NULL;
e33f2203
CR
8297 if (tword)
8298 dispose_word_desc (tword);
d3a24ed2 8299 }
cce855bc
JA
8300 FREE (temp);
8301 temp = temp1;
8302 goto dollar_add_string;
8303 }
ccc6cda3 8304
cce855bc
JA
8305 case '\\':
8306 if (string[sindex + 1] == '\n')
8307 {
8308 sindex += 2;
8309 continue;
8310 }
726f6388 8311
cce855bc 8312 c = string[++sindex];
726f6388 8313
cce855bc 8314 if (quoted & Q_HERE_DOCUMENT)
28ef6c31 8315 tflag = CBSHDOC;
cce855bc 8316 else if (quoted & Q_DOUBLE_QUOTES)
28ef6c31 8317 tflag = CBSDQUOTE;
cce855bc 8318 else
28ef6c31
JA
8319 tflag = 0;
8320
64419627 8321 /* From Posix discussion on austin-group list: Backslash escaping
9e51a74d
CR
8322 a } in ${...} is removed. Issue 0000221 */
8323 if ((quoted & Q_DOLBRACE) && c == RBRACE)
64419627
CR
8324 {
8325 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
8326 }
8327 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
cce855bc 8328 {
7117c2d2 8329 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
bb70624e
JA
8330 }
8331 else if (c == 0)
8332 {
8333 c = CTLNUL;
8334 sindex--; /* add_character: label increments sindex */
8335 goto add_character;
cce855bc
JA
8336 }
8337 else
bb70624e 8338 {
7117c2d2 8339 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
bb70624e 8340 }
726f6388 8341
bb70624e
JA
8342 sindex++;
8343add_twochars:
8344 /* BEFORE jumping here, we need to increment sindex if appropriate */
8345 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
8346 DEFAULT_ARRAY_SIZE);
8347 istring[istring_index++] = twochars[0];
8348 istring[istring_index++] = twochars[1];
8349 istring[istring_index] = '\0';
8350
8351 break;
726f6388 8352
cce855bc 8353 case '"':
da719982
CR
8354#if 0
8355 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8356#else
8357 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8358#endif
cce855bc 8359 goto add_character;
ccc6cda3
JA
8360
8361 t_index = ++sindex;
8362 temp = string_extract_double_quoted (string, &sindex, 0);
8363
8364 /* If the quotes surrounded the entire string, then the
8365 whole word was quoted. */
8366 quoted_state = (t_index == 1 && string[sindex] == '\0')
8367 ? WHOLLY_QUOTED
7117c2d2 8368 : PARTIALLY_QUOTED;
ccc6cda3
JA
8369
8370 if (temp && *temp)
726f6388 8371 {
227f982e
CR
8372 tword = alloc_word_desc ();
8373 tword->word = temp;
8374
ccc6cda3
JA
8375 temp = (char *)NULL;
8376
348a457e 8377 temp_has_dollar_at = 0; /* XXX */
227f982e 8378 /* Need to get W_HASQUOTEDNULL flag through this function. */
348a457e
CR
8379 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &temp_has_dollar_at, (int *)NULL);
8380 has_dollar_at += temp_has_dollar_at;
726f6388 8381
ccc6cda3
JA
8382 if (list == &expand_word_error || list == &expand_word_fatal)
8383 {
8384 free (istring);
8385 free (string);
8386 /* expand_word_internal has already freed temp_word->word
8387 for us because of the way it prints error messages. */
8388 tword->word = (char *)NULL;
8389 dispose_word (tword);
8390 return list;
8391 }
726f6388 8392
ccc6cda3 8393 dispose_word (tword);
726f6388 8394
ccc6cda3
JA
8395 /* "$@" (a double-quoted dollar-at) expands into nothing,
8396 not even a NULL word, when there are no positional
8397 parameters. */
cce855bc 8398 if (list == 0 && has_dollar_at)
726f6388 8399 {
ccc6cda3
JA
8400 quoted_dollar_at++;
8401 break;
8402 }
8403
8404 /* If we get "$@", we know we have expanded something, so we
8405 need to remember it for the final split on $IFS. This is
8406 a special case; it's the only case where a quoted string
8407 can expand into more than one word. It's going to come back
8408 from the above call to expand_word_internal as a list with
8409 a single word, in which all characters are quoted and
8410 separated by blanks. What we want to do is to turn it back
8411 into a list for the next piece of code. */
8412 if (list)
8413 dequote_list (list);
8414
227f982e 8415 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
efc2f955 8416 had_quoted_null = 1; /* XXX */
227f982e 8417
cce855bc 8418 if (has_dollar_at)
ccc6cda3
JA
8419 {
8420 quoted_dollar_at++;
8421 if (contains_dollar_at)
8422 *contains_dollar_at = 1;
8423 if (expanded_something)
8424 *expanded_something = 1;
8425 }
8426 }
8427 else
8428 {
8429 /* What we have is "". This is a minor optimization. */
f73dda09 8430 FREE (temp);
ccc6cda3
JA
8431 list = (WORD_LIST *)NULL;
8432 }
8433
8434 /* The code above *might* return a list (consider the case of "$@",
8435 where it returns "$1", "$2", etc.). We can't throw away the
8436 rest of the list, and we have to make sure each word gets added
8437 as quoted. We test on tresult->next: if it is non-NULL, we
8438 quote the whole list, save it to a string with string_list, and
8439 add that string. We don't need to quote the results of this
8440 (and it would be wrong, since that would quote the separators
8441 as well), so we go directly to add_string. */
8442 if (list)
8443 {
8444 if (list->next)
8445 {
e1e48bba 8446#if 0
adc6cff5 8447 if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
e1e48bba
CR
8448 temp = string_list_internal (quote_list (list), " ");
8449 else
8450#endif
bc4cd23c
JA
8451 /* Testing quoted_dollar_at makes sure that "$@" is
8452 split correctly when $IFS does not contain a space. */
8453 temp = quoted_dollar_at
8454 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
8455 : string_list (quote_list (list));
ccc6cda3 8456 dispose_words (list);
726f6388
JA
8457 goto add_string;
8458 }
8459 else
8460 {
ccc6cda3 8461 temp = savestring (list->word->word);
227f982e 8462 tflag = list->word->flags;
ccc6cda3 8463 dispose_words (list);
227f982e 8464
cce855bc
JA
8465 /* If the string is not a quoted null string, we want
8466 to remove any embedded unquoted CTLNUL characters.
8467 We do not want to turn quoted null strings back into
8468 the empty string, though. We do this because we
8469 want to remove any quoted nulls from expansions that
8470 contain other characters. For example, if we have
8471 x"$*"y or "x$*y" and there are no positional parameters,
7117c2d2 8472 the $* should expand into nothing. */
227f982e
CR
8473 /* We use the W_HASQUOTEDNULL flag to differentiate the
8474 cases: a quoted null character as above and when
8475 CTLNUL is contained in the (non-null) expansion
8476 of some variable. We use the had_quoted_null flag to
10590446 8477 pass the value through this function to its caller. */
227f982e 8478 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
cce855bc 8479 remove_quoted_nulls (temp); /* XXX */
726f6388
JA
8480 }
8481 }
ccc6cda3
JA
8482 else
8483 temp = (char *)NULL;
726f6388 8484
ccc6cda3 8485 /* We do not want to add quoted nulls to strings that are only
efc2f955 8486 partially quoted; we can throw them away. The exception to
f4f5e1c2
CR
8487 this is when we are going to be performing word splitting,
8488 since we have to preserve a null argument if the next character
8489 will cause word splitting. */
adc6cff5 8490 if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
cce855bc 8491 continue;
726f6388 8492
ccc6cda3 8493 add_quoted_string:
726f6388 8494
ccc6cda3
JA
8495 if (temp)
8496 {
8497 temp1 = temp;
8498 temp = quote_string (temp);
8499 free (temp1);
bb70624e 8500 goto add_string;
ccc6cda3
JA
8501 }
8502 else
8503 {
8504 /* Add NULL arg. */
bb70624e
JA
8505 c = CTLNUL;
8506 sindex--; /* add_character: label increments sindex */
8507 goto add_character;
ccc6cda3 8508 }
bb70624e 8509
ccc6cda3 8510 /* break; */
726f6388 8511
ccc6cda3 8512 case '\'':
da719982
CR
8513#if 0
8514 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
8515#else
8516 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
8517#endif
ccc6cda3 8518 goto add_character;
726f6388 8519
ccc6cda3
JA
8520 t_index = ++sindex;
8521 temp = string_extract_single_quoted (string, &sindex);
726f6388 8522
ccc6cda3
JA
8523 /* If the entire STRING was surrounded by single quotes,
8524 then the string is wholly quoted. */
8525 quoted_state = (t_index == 1 && string[sindex] == '\0')
8526 ? WHOLLY_QUOTED
7117c2d2 8527 : PARTIALLY_QUOTED;
726f6388 8528
ccc6cda3
JA
8529 /* If all we had was '', it is a null expansion. */
8530 if (*temp == '\0')
8531 {
8532 free (temp);
8533 temp = (char *)NULL;
8534 }
8535 else
7117c2d2 8536 remove_quoted_escapes (temp); /* ??? */
726f6388 8537
ccc6cda3
JA
8538 /* We do not want to add quoted nulls to strings that are only
8539 partially quoted; such nulls are discarded. */
8540 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
8541 continue;
726f6388 8542
bb70624e
JA
8543 /* If we have a quoted null expansion, add a quoted NULL to istring. */
8544 if (temp == 0)
8545 {
8546 c = CTLNUL;
8547 sindex--; /* add_character: label increments sindex */
8548 goto add_character;
8549 }
8550 else
8551 goto add_quoted_string;
8552
ccc6cda3 8553 /* break; */
726f6388
JA
8554
8555 default:
726f6388 8556 /* This is the fix for " $@ " */
c1d39fb8 8557 add_ifs_character:
7117c2d2 8558 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
726f6388 8559 {
bb70624e
JA
8560 if (string[sindex]) /* from old goto dollar_add_string */
8561 sindex++;
8562 if (c == 0)
8563 {
8564 c = CTLNUL;
8565 goto add_character;
8566 }
8567 else
8568 {
7117c2d2 8569#if HANDLE_MULTIBYTE
545f34cf
CR
8570 if (MB_CUR_MAX > 1)
8571 sindex--;
8572
7117c2d2
JA
8573 if (MB_CUR_MAX > 1)
8574 {
545f34cf 8575 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7117c2d2
JA
8576 }
8577 else
8578#endif
8579 {
8580 twochars[0] = CTLESC;
8581 twochars[1] = c;
8582 goto add_twochars;
8583 }
bb70624e 8584 }
726f6388
JA
8585 }
8586
7117c2d2
JA
8587 SADD_MBCHAR (temp, string, sindex, string_size);
8588
726f6388 8589 add_character:
ccc6cda3
JA
8590 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
8591 DEFAULT_ARRAY_SIZE);
726f6388
JA
8592 istring[istring_index++] = c;
8593 istring[istring_index] = '\0';
8594
8595 /* Next character. */
8596 sindex++;
8597 }
8598 }
8599
8600finished_with_string:
726f6388
JA
8601 /* OK, we're ready to return. If we have a quoted string, and
8602 quoted_dollar_at is not set, we do no splitting at all; otherwise
8603 we split on ' '. The routines that call this will handle what to
8604 do if nothing has been expanded. */
ccc6cda3
JA
8605
8606 /* Partially and wholly quoted strings which expand to the empty
8607 string are retained as an empty arguments. Unquoted strings
8608 which expand to the empty string are discarded. The single
8609 exception is the case of expanding "$@" when there are no
8610 positional parameters. In that case, we discard the expansion. */
8611
8612 /* Because of how the code that handles "" and '' in partially
8613 quoted strings works, we need to make ISTRING into a QUOTED_NULL
8614 if we saw quoting characters, but the expansion was empty.
8615 "" and '' are tossed away before we get to this point when
8616 processing partially quoted strings. This makes "" and $xxx""
8617 equivalent when xxx is unset. We also look to see whether we
8618 saw a quoted null from a ${} expansion and add one back if we
8619 need to. */
8620
8621 /* If we expand to nothing and there were no single or double quotes
8622 in the word, we throw it away. Otherwise, we return a NULL word.
8623 The single exception is for $@ surrounded by double quotes when
8624 there are no positional parameters. In that case, we also throw
8625 the word away. */
8626
8627 if (*istring == '\0')
8628 {
8629 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
726f6388 8630 {
726f6388
JA
8631 istring[0] = CTLNUL;
8632 istring[1] = '\0';
ccc6cda3 8633 tword = make_bare_word (istring);
227f982e 8634 tword->flags |= W_HASQUOTEDNULL; /* XXX */
ccc6cda3
JA
8635 list = make_word_list (tword, (WORD_LIST *)NULL);
8636 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8637 tword->flags |= W_QUOTED;
726f6388 8638 }
ccc6cda3
JA
8639 /* According to sh, ksh, and Posix.2, if a word expands into nothing
8640 and a double-quoted "$@" appears anywhere in it, then the entire
8641 word is removed. */
8642 else if (quoted_state == UNQUOTED || quoted_dollar_at)
8643 list = (WORD_LIST *)NULL;
8644#if 0
8645 else
726f6388 8646 {
ccc6cda3 8647 tword = make_bare_word (istring);
ccc6cda3
JA
8648 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
8649 tword->flags |= W_QUOTED;
227f982e 8650 list = make_word_list (tword, (WORD_LIST *)NULL);
726f6388 8651 }
f73dda09
JA
8652#else
8653 else
8654 list = (WORD_LIST *)NULL;
ccc6cda3
JA
8655#endif
8656 }
8657 else if (word->flags & W_NOSPLIT)
8658 {
8659 tword = make_bare_word (istring);
ccc6cda3
JA
8660 if (word->flags & W_ASSIGNMENT)
8661 tword->flags |= W_ASSIGNMENT; /* XXX */
43df7bbb
CR
8662 if (word->flags & W_COMPASSIGN)
8663 tword->flags |= W_COMPASSIGN; /* XXX */
b72432fd
JA
8664 if (word->flags & W_NOGLOB)
8665 tword->flags |= W_NOGLOB; /* XXX */
df0e4bfe
CR
8666 if (word->flags & W_NOBRACE)
8667 tword->flags |= W_NOBRACE; /* XXX */
43df7bbb
CR
8668 if (word->flags & W_NOEXPAND)
8669 tword->flags |= W_NOEXPAND; /* XXX */
ccc6cda3 8670 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
28ef6c31 8671 tword->flags |= W_QUOTED;
efc2f955 8672 if (had_quoted_null && QUOTED_NULL (istring))
227f982e
CR
8673 tword->flags |= W_HASQUOTEDNULL;
8674 list = make_word_list (tword, (WORD_LIST *)NULL);
ccc6cda3
JA
8675 }
8676 else
8677 {
8678 char *ifs_chars;
8679
7117c2d2 8680 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
726f6388 8681
cce855bc
JA
8682 /* If we have $@, we need to split the results no matter what. If
8683 IFS is unset or NULL, string_list_dollar_at has separated the
8684 positional parameters with a space, so we split on space (we have
8685 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
8686 string_list_dollar_at has separated the positional parameters
8687 with the first character of $IFS, so we split on $IFS. */
8688 if (has_dollar_at && ifs_chars)
8689 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
ccc6cda3
JA
8690 else
8691 {
8692 tword = make_bare_word (istring);
ccc6cda3
JA
8693 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
8694 tword->flags |= W_QUOTED;
8695 if (word->flags & W_ASSIGNMENT)
8696 tword->flags |= W_ASSIGNMENT;
43df7bbb
CR
8697 if (word->flags & W_COMPASSIGN)
8698 tword->flags |= W_COMPASSIGN;
b72432fd
JA
8699 if (word->flags & W_NOGLOB)
8700 tword->flags |= W_NOGLOB;
df0e4bfe
CR
8701 if (word->flags & W_NOBRACE)
8702 tword->flags |= W_NOBRACE;
43df7bbb
CR
8703 if (word->flags & W_NOEXPAND)
8704 tword->flags |= W_NOEXPAND;
efc2f955 8705 if (had_quoted_null && QUOTED_NULL (istring))
227f982e
CR
8706 tword->flags |= W_HASQUOTEDNULL; /* XXX */
8707 list = make_word_list (tword, (WORD_LIST *)NULL);
726f6388 8708 }
726f6388 8709 }
726f6388 8710
ccc6cda3
JA
8711 free (istring);
8712 return (list);
726f6388
JA
8713}
8714
8715/* **************************************************************** */
8716/* */
8717/* Functions for Quote Removal */
8718/* */
8719/* **************************************************************** */
8720
8721/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
7117c2d2 8722 backslash quoting rules for within double quotes or a here document. */
726f6388
JA
8723char *
8724string_quote_removal (string, quoted)
8725 char *string;
8726 int quoted;
8727{
7117c2d2
JA
8728 size_t slen;
8729 char *r, *result_string, *temp, *send;
f73dda09
JA
8730 int sindex, tindex, dquote;
8731 unsigned char c;
7117c2d2 8732 DECLARE_MBSTATE;
726f6388
JA
8733
8734 /* The result can be no longer than the original string. */
7117c2d2
JA
8735 slen = strlen (string);
8736 send = string + slen;
8737
8738 r = result_string = (char *)xmalloc (slen + 1);
726f6388 8739
ccc6cda3 8740 for (dquote = sindex = 0; c = string[sindex];)
726f6388
JA
8741 {
8742 switch (c)
8743 {
8744 case '\\':
8745 c = string[++sindex];
33fe8777
CR
8746 if (c == 0)
8747 {
8748 *r++ = '\\';
8749 break;
8750 }
28ef6c31 8751 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
726f6388 8752 *r++ = '\\';
ccc6cda3 8753 /* FALLTHROUGH */
726f6388
JA
8754
8755 default:
7117c2d2 8756 SCOPY_CHAR_M (r, string, send, sindex);
726f6388
JA
8757 break;
8758
8759 case '\'':
ccc6cda3 8760 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
726f6388
JA
8761 {
8762 *r++ = c;
8763 sindex++;
ccc6cda3 8764 break;
726f6388 8765 }
ccc6cda3
JA
8766 tindex = sindex + 1;
8767 temp = string_extract_single_quoted (string, &tindex);
8768 if (temp)
726f6388 8769 {
ccc6cda3
JA
8770 strcpy (r, temp);
8771 r += strlen (r);
8772 free (temp);
726f6388 8773 }
ccc6cda3 8774 sindex = tindex;
726f6388
JA
8775 break;
8776
8777 case '"':
8778 dquote = 1 - dquote;
8779 sindex++;
8780 break;
8781 }
8782 }
8783 *r = '\0';
8784 return (result_string);
8785}
8786
ccc6cda3
JA
8787#if 0
8788/* UNUSED */
726f6388
JA
8789/* Perform quote removal on word WORD. This allocates and returns a new
8790 WORD_DESC *. */
8791WORD_DESC *
8792word_quote_removal (word, quoted)
8793 WORD_DESC *word;
8794 int quoted;
8795{
8796 WORD_DESC *w;
8797 char *t;
8798
8799 t = string_quote_removal (word->word, quoted);
227f982e
CR
8800 w = alloc_word_desc ();
8801 w->word = t ? t : savestring ("");
726f6388
JA
8802 return (w);
8803}
8804
8805/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
8806 the members of the list are treated as if they are surrounded by
8807 double quotes. Return a new list, or NULL if LIST is NULL. */
8808WORD_LIST *
8809word_list_quote_removal (list, quoted)
8810 WORD_LIST *list;
8811 int quoted;
8812{
227f982e 8813 WORD_LIST *result, *t, *tresult, *e;
726f6388 8814
ccc6cda3 8815 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
726f6388 8816 {
7117c2d2 8817 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
227f982e 8818#if 0
726f6388 8819 result = (WORD_LIST *) list_append (result, tresult);
227f982e
CR
8820#else
8821 if (result == 0)
8822 result = e = tresult;
8823 else
8824 {
8825 e->next = tresult;
8826 while (e->next)
8827 e = e->next;
8828 }
8829#endif
726f6388
JA
8830 }
8831 return (result);
8832}
ccc6cda3 8833#endif
726f6388 8834
726f6388
JA
8835/*******************************************
8836 * *
8837 * Functions to perform word splitting *
8838 * *
8839 *******************************************/
8840
7117c2d2
JA
8841void
8842setifs (v)
8843 SHELL_VAR *v;
b72432fd 8844{
7117c2d2
JA
8845 char *t;
8846 unsigned char uc;
8847
8848 ifs_var = v;
cdb32d45 8849 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
b72432fd 8850
633e5c6d
CR
8851 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
8852 handle multibyte chars in IFS */
7117c2d2
JA
8853 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
8854 for (t = ifs_value ; t && *t; t++)
8855 {
8856 uc = *t;
8857 ifs_cmap[uc] = 1;
8858 }
8859
633e5c6d
CR
8860#if defined (HANDLE_MULTIBYTE)
8861 if (ifs_value == 0)
8862 {
8863 ifs_firstc[0] = '\0';
8864 ifs_firstc_len = 1;
8865 }
8866 else
8867 {
8868 size_t ifs_len;
8869 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
8870 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
22e63b05 8871 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
633e5c6d
CR
8872 {
8873 ifs_firstc[0] = ifs_value[0];
8874 ifs_firstc[1] = '\0';
8875 ifs_firstc_len = 1;
8876 }
8877 else
8878 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
8879 }
8880#else
7117c2d2 8881 ifs_firstc = ifs_value ? *ifs_value : 0;
633e5c6d 8882#endif
7117c2d2
JA
8883}
8884
8885char *
8886getifs ()
8887{
8888 return ifs_value;
b72432fd
JA
8889}
8890
726f6388
JA
8891/* This splits a single word into a WORD LIST on $IFS, but only if the word
8892 is not quoted. list_string () performs quote removal for us, even if we
8893 don't do any splitting. */
8894WORD_LIST *
7117c2d2 8895word_split (w, ifs_chars)
726f6388 8896 WORD_DESC *w;
7117c2d2 8897 char *ifs_chars;
726f6388
JA
8898{
8899 WORD_LIST *result;
8900
8901 if (w)
8902 {
7117c2d2 8903 char *xifs;
726f6388 8904
7117c2d2
JA
8905 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
8906 result = list_string (w->word, xifs, w->flags & W_QUOTED);
726f6388
JA
8907 }
8908 else
8909 result = (WORD_LIST *)NULL;
ccc6cda3 8910
726f6388
JA
8911 return (result);
8912}
8913
8914/* Perform word splitting on LIST and return the RESULT. It is possible
8915 to return (WORD_LIST *)NULL. */
8916static WORD_LIST *
8917word_list_split (list)
8918 WORD_LIST *list;
8919{
37c41ab1 8920 WORD_LIST *result, *t, *tresult, *e;
726f6388 8921
ccc6cda3 8922 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
726f6388 8923 {
7117c2d2 8924 tresult = word_split (t->word, ifs_value);
37c41ab1
CR
8925 if (result == 0)
8926 result = e = tresult;
8927 else
8928 {
8929 e->next = tresult;
8930 while (e->next)
8931 e = e->next;
8932 }
726f6388
JA
8933 }
8934 return (result);
8935}
8936
8937/**************************************************
8938 * *
cce855bc 8939 * Functions to expand an entire WORD_LIST *
726f6388
JA
8940 * *
8941 **************************************************/
8942
d3a24ed2
CR
8943/* Do any word-expansion-specific cleanup and jump to top_level */
8944static void
8945exp_jump_to_top_level (v)
8946 int v;
8947{
f11997f8
CR
8948 set_pipestatus_from_exit (last_command_exit_value);
8949
d3a24ed2
CR
8950 /* Cleanup code goes here. */
8951 expand_no_split_dollar_star = 0; /* XXX */
8952 expanding_redir = 0;
d7f49990 8953 assigning_in_environment = 0;
d3a24ed2 8954
2e4498b3
CR
8955 if (parse_and_execute_level == 0)
8956 top_level_cleanup (); /* from sig.c */
8957
d3a24ed2
CR
8958 jump_to_top_level (v);
8959}
8960
cce855bc
JA
8961/* Put NLIST (which is a WORD_LIST * of only one element) at the front of
8962 ELIST, and set ELIST to the new list. */
8963#define PREPEND_LIST(nlist, elist) \
8964 do { nlist->next = elist; elist = nlist; } while (0)
8965
726f6388
JA
8966/* Separate out any initial variable assignments from TLIST. If set -k has
8967 been executed, remove all assignment statements from TLIST. Initial
8968 variable assignments and other environment assignments are placed
bb70624e 8969 on SUBST_ASSIGN_VARLIST. */
726f6388
JA
8970static WORD_LIST *
8971separate_out_assignments (tlist)
8972 WORD_LIST *tlist;
8973{
8974 register WORD_LIST *vp, *lp;
8975
0527c903 8976 if (tlist == 0)
726f6388
JA
8977 return ((WORD_LIST *)NULL);
8978
bb70624e
JA
8979 if (subst_assign_varlist)
8980 dispose_words (subst_assign_varlist); /* Clean up after previous error */
b72432fd 8981
bb70624e 8982 subst_assign_varlist = (WORD_LIST *)NULL;
726f6388
JA
8983 vp = lp = tlist;
8984
8985 /* Separate out variable assignments at the start of the command.
8986 Loop invariant: vp->next == lp
8987 Loop postcondition:
7117c2d2
JA
8988 lp = list of words left after assignment statements skipped
8989 tlist = original list of words
726f6388 8990 */
ccc6cda3 8991 while (lp && (lp->word->flags & W_ASSIGNMENT))
726f6388
JA
8992 {
8993 vp = lp;
8994 lp = lp->next;
8995 }
8996
bb70624e
JA
8997 /* If lp != tlist, we have some initial assignment statements.
8998 We make SUBST_ASSIGN_VARLIST point to the list of assignment
8999 words and TLIST point to the remaining words. */
726f6388
JA
9000 if (lp != tlist)
9001 {
bb70624e 9002 subst_assign_varlist = tlist;
726f6388
JA
9003 /* ASSERT(vp->next == lp); */
9004 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
9005 tlist = lp; /* remainder of word list */
9006 }
9007
9008 /* vp == end of variable list */
9009 /* tlist == remainder of original word list without variable assignments */
9010 if (!tlist)
9011 /* All the words in tlist were assignment statements */
9012 return ((WORD_LIST *)NULL);
9013
9014 /* ASSERT(tlist != NULL); */
ccc6cda3 9015 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
726f6388
JA
9016
9017 /* If the -k option is in effect, we need to go through the remaining
bb70624e
JA
9018 words, separate out the assignment words, and place them on
9019 SUBST_ASSIGN_VARLIST. */
726f6388
JA
9020 if (place_keywords_in_env)
9021 {
9022 WORD_LIST *tp; /* tp == running pointer into tlist */
9023
9024 tp = tlist;
9025 lp = tlist->next;
9026
9027 /* Loop Invariant: tp->next == lp */
9028 /* Loop postcondition: tlist == word list without assignment statements */
9029 while (lp)
9030 {
ccc6cda3 9031 if (lp->word->flags & W_ASSIGNMENT)
726f6388
JA
9032 {
9033 /* Found an assignment statement, add this word to end of
bb70624e
JA
9034 subst_assign_varlist (vp). */
9035 if (!subst_assign_varlist)
9036 subst_assign_varlist = vp = lp;
726f6388
JA
9037 else
9038 {
9039 vp->next = lp;
9040 vp = lp;
9041 }
9042
9043 /* Remove the word pointed to by LP from TLIST. */
9044 tp->next = lp->next;
9045 /* ASSERT(vp == lp); */
9046 lp->next = (WORD_LIST *)NULL;
9047 lp = tp->next;
9048 }
9049 else
9050 {
9051 tp = lp;
9052 lp = lp->next;
9053 }
9054 }
9055 }
9056 return (tlist);
9057}
9058
cce855bc
JA
9059#define WEXP_VARASSIGN 0x001
9060#define WEXP_BRACEEXP 0x002
9061#define WEXP_TILDEEXP 0x004
9062#define WEXP_PARAMEXP 0x008
9063#define WEXP_PATHEXP 0x010
9064
9065/* All of the expansions, including variable assignments at the start of
9066 the list. */
9067#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
9068
9069/* All of the expansions except variable assignments at the start of
9070 the list. */
9071#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
9072
9073/* All of the `shell expansions': brace expansion, tilde expansion, parameter
9074 expansion, command substitution, arithmetic expansion, word splitting, and
9075 quote removal. */
9076#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
9077
726f6388
JA
9078/* Take the list of words in LIST and do the various substitutions. Return
9079 a new list of words which is the expanded list, and without things like
9080 variable assignments. */
9081
9082WORD_LIST *
9083expand_words (list)
9084 WORD_LIST *list;
9085{
cce855bc 9086 return (expand_word_list_internal (list, WEXP_ALL));
726f6388
JA
9087}
9088
9089/* Same as expand_words (), but doesn't hack variable or environment
9090 variables. */
9091WORD_LIST *
9092expand_words_no_vars (list)
9093 WORD_LIST *list;
9094{
cce855bc 9095 return (expand_word_list_internal (list, WEXP_NOVARS));
726f6388
JA
9096}
9097
cce855bc
JA
9098WORD_LIST *
9099expand_words_shellexp (list)
726f6388 9100 WORD_LIST *list;
726f6388 9101{
cce855bc
JA
9102 return (expand_word_list_internal (list, WEXP_SHELLEXP));
9103}
726f6388 9104
cce855bc
JA
9105static WORD_LIST *
9106glob_expand_word_list (tlist, eflags)
9107 WORD_LIST *tlist;
9108 int eflags;
9109{
9110 char **glob_array, *temp_string;
9111 register int glob_index;
9112 WORD_LIST *glob_list, *output_list, *disposables, *next;
9113 WORD_DESC *tword;
726f6388 9114
cce855bc
JA
9115 output_list = disposables = (WORD_LIST *)NULL;
9116 glob_array = (char **)NULL;
9117 while (tlist)
9118 {
9119 /* For each word, either globbing is attempted or the word is
9120 added to orig_list. If globbing succeeds, the results are
9121 added to orig_list and the word (tlist) is added to the list
9122 of disposable words. If globbing fails and failed glob
9123 expansions are left unchanged (the shell default), the
9124 original word is added to orig_list. If globbing fails and
9125 failed glob expansions are removed, the original word is
9126 added to the list of disposable words. orig_list ends up
7117c2d2 9127 in reverse order and requires a call to REVERSE_LIST to
cce855bc
JA
9128 be set right. After all words are examined, the disposable
9129 words are freed. */
9130 next = tlist->next;
726f6388 9131
cce855bc 9132 /* If the word isn't an assignment and contains an unquoted
28ef6c31 9133 pattern matching character, then glob it. */
b72432fd 9134 if ((tlist->word->flags & W_NOGLOB) == 0 &&
cce855bc 9135 unquoted_glob_pattern_p (tlist->word->word))
726f6388 9136 {
cce855bc
JA
9137 glob_array = shell_glob_filename (tlist->word->word);
9138
9139 /* Handle error cases.
9140 I don't think we should report errors like "No such file
9141 or directory". However, I would like to report errors
9142 like "Read failed". */
9143
d3a24ed2 9144 if (glob_array == 0 || GLOB_FAILED (glob_array))
726f6388 9145 {
bb70624e 9146 glob_array = (char **)xmalloc (sizeof (char *));
cce855bc
JA
9147 glob_array[0] = (char *)NULL;
9148 }
9149
9150 /* Dequote the current word in case we have to use it. */
9151 if (glob_array[0] == NULL)
9152 {
9153 temp_string = dequote_string (tlist->word->word);
9154 free (tlist->word->word);
9155 tlist->word->word = temp_string;
9156 }
9157
9158 /* Make the array into a word list. */
9159 glob_list = (WORD_LIST *)NULL;
9160 for (glob_index = 0; glob_array[glob_index]; glob_index++)
9161 {
9162 tword = make_bare_word (glob_array[glob_index]);
9163 tword->flags |= W_GLOBEXP; /* XXX */
9164 glob_list = make_word_list (tword, glob_list);
9165 }
9166
9167 if (glob_list)
9168 {
9169 output_list = (WORD_LIST *)list_append (glob_list, output_list);
9170 PREPEND_LIST (tlist, disposables);
9171 }
d3a24ed2
CR
9172 else if (fail_glob_expansion != 0)
9173 {
7f947b68 9174 last_command_exit_value = EXECUTION_FAILURE;
5e13499c 9175 report_error (_("no match: %s"), tlist->word->word);
c184f645 9176 exp_jump_to_top_level (DISCARD);
d3a24ed2 9177 }
cce855bc
JA
9178 else if (allow_null_glob_expansion == 0)
9179 {
9180 /* Failed glob expressions are left unchanged. */
9181 PREPEND_LIST (tlist, output_list);
9182 }
9183 else
9184 {
9185 /* Failed glob expressions are removed. */
9186 PREPEND_LIST (tlist, disposables);
726f6388 9187 }
726f6388 9188 }
cce855bc
JA
9189 else
9190 {
9191 /* Dequote the string. */
9192 temp_string = dequote_string (tlist->word->word);
9193 free (tlist->word->word);
9194 tlist->word->word = temp_string;
9195 PREPEND_LIST (tlist, output_list);
9196 }
9197
7117c2d2 9198 strvec_dispose (glob_array);
cce855bc
JA
9199 glob_array = (char **)NULL;
9200
9201 tlist = next;
726f6388
JA
9202 }
9203
cce855bc
JA
9204 if (disposables)
9205 dispose_words (disposables);
9206
9207 if (output_list)
9208 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9209
9210 return (output_list);
9211}
726f6388
JA
9212
9213#if defined (BRACE_EXPANSION)
cce855bc
JA
9214static WORD_LIST *
9215brace_expand_word_list (tlist, eflags)
9216 WORD_LIST *tlist;
9217 int eflags;
9218{
9219 register char **expansions;
9220 char *temp_string;
9221 WORD_LIST *disposables, *output_list, *next;
9222 WORD_DESC *w;
9223 int eindex;
9224
9225 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
726f6388 9226 {
cce855bc 9227 next = tlist->next;
726f6388 9228
df0e4bfe
CR
9229 if (tlist->word->flags & W_NOBRACE)
9230 {
9231itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);
9232 PREPEND_LIST (tlist, output_list);
9233 continue;
9234 }
9235
6669f0e5
CR
9236 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9237 {
9238/*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
9239 PREPEND_LIST (tlist, output_list);
9240 continue;
9241 }
df0e4bfe 9242
cce855bc
JA
9243 /* Only do brace expansion if the word has a brace character. If
9244 not, just add the word list element to BRACES and continue. In
9245 the common case, at least when running shell scripts, this will
d0ca3503 9246 degenerate to a bunch of calls to `mbschr', and then what is
cce855bc 9247 basically a reversal of TLIST into BRACES, which is corrected
7117c2d2 9248 by a call to REVERSE_LIST () on BRACES when the end of TLIST
cce855bc 9249 is reached. */
d0ca3503 9250 if (mbschr (tlist->word->word, LBRACE))
726f6388 9251 {
cce855bc 9252 expansions = brace_expand (tlist->word->word);
726f6388 9253
cce855bc 9254 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
726f6388 9255 {
51f7ea36
CR
9256 w = alloc_word_desc ();
9257 w->word = temp_string;
9258
cce855bc
JA
9259 /* If brace expansion didn't change the word, preserve
9260 the flags. We may want to preserve the flags
9261 unconditionally someday -- XXX */
9262 if (STREQ (temp_string, tlist->word->word))
9263 w->flags = tlist->word->flags;
51f7ea36
CR
9264 else
9265 w = make_word_flags (w, temp_string);
9266
cce855bc 9267 output_list = make_word_list (w, output_list);
726f6388 9268 }
cce855bc 9269 free (expansions);
726f6388 9270
cce855bc
JA
9271 /* Add TLIST to the list of words to be freed after brace
9272 expansion has been performed. */
9273 PREPEND_LIST (tlist, disposables);
9274 }
9275 else
9276 PREPEND_LIST (tlist, output_list);
726f6388 9277 }
cce855bc
JA
9278
9279 if (disposables)
9280 dispose_words (disposables);
9281
9282 if (output_list)
9283 output_list = REVERSE_LIST (output_list, WORD_LIST *);
9284
9285 return (output_list);
9286}
9287#endif
9288
fdf670ea
CR
9289#if defined (ARRAY_VARS)
9290/* Take WORD, a compound associative array assignment, and internally run
9291 'declare -A w', where W is the variable name portion of WORD. */
9292static int
9293make_internal_declare (word, option)
9294 char *word;
9295 char *option;
9296{
9297 int t;
9298 WORD_LIST *wl;
9299 WORD_DESC *w;
9300
9301 w = make_word (word);
9302
9303 t = assignment (w->word, 0);
9304 w->word[t] = '\0';
9305
9306 wl = make_word_list (w, (WORD_LIST *)NULL);
9307 wl = make_word_list (make_word (option), wl);
9308
9309 return (declare_builtin (wl));
9310}
9311#endif
9312
cce855bc
JA
9313static WORD_LIST *
9314shell_expand_word_list (tlist, eflags)
9315 WORD_LIST *tlist;
9316 int eflags;
9317{
9318 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
9319 int expanded_something, has_dollar_at;
9320 char *temp_string;
726f6388 9321
726f6388 9322 /* We do tilde expansion all the time. This is what 1003.2 says. */
cce855bc
JA
9323 new_list = (WORD_LIST *)NULL;
9324 for (orig_list = tlist; tlist; tlist = next)
726f6388 9325 {
ccc6cda3 9326 temp_string = tlist->word->word;
726f6388
JA
9327
9328 next = tlist->next;
9329
43df7bbb
CR
9330#if defined (ARRAY_VARS)
9331 /* If this is a compound array assignment to a builtin that accepts
9332 such assignments (e.g., `declare'), take the assignment and perform
9333 it separately, handling the semantics of declarations inside shell
9334 functions. This avoids the double-evaluation of such arguments,
9335 because `declare' does some evaluation of compound assignments on
9336 its own. */
9337 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
9338 {
9339 int t;
9340
fdf670ea
CR
9341 if (tlist->word->flags & W_ASSIGNASSOC)
9342 make_internal_declare (tlist->word->word, "-A");
9343
adc6cff5 9344 t = do_word_assignment (tlist->word, 0);
43df7bbb
CR
9345 if (t == 0)
9346 {
9347 last_command_exit_value = EXECUTION_FAILURE;
9348 exp_jump_to_top_level (DISCARD);
9349 }
9350
9351 /* Now transform the word as ksh93 appears to do and go on */
9352 t = assignment (tlist->word->word, 0);
9353 tlist->word->word[t] = '\0';
fdf670ea 9354 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
43df7bbb
CR
9355 }
9356#endif
9357
ccc6cda3 9358 expanded_something = 0;
726f6388 9359 expanded = expand_word_internal
b72432fd 9360 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
726f6388
JA
9361
9362 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
9363 {
9364 /* By convention, each time this error is returned,
9365 tlist->word->word has already been freed. */
9366 tlist->word->word = (char *)NULL;
ccc6cda3 9367
726f6388
JA
9368 /* Dispose our copy of the original list. */
9369 dispose_words (orig_list);
d166f048 9370 /* Dispose the new list we're building. */
726f6388
JA
9371 dispose_words (new_list);
9372
28ef6c31 9373 last_command_exit_value = EXECUTION_FAILURE;
726f6388 9374 if (expanded == &expand_word_error)
d3a24ed2 9375 exp_jump_to_top_level (DISCARD);
726f6388 9376 else
d3a24ed2 9377 exp_jump_to_top_level (FORCE_EOF);
726f6388
JA
9378 }
9379
ccc6cda3
JA
9380 /* Don't split words marked W_NOSPLIT. */
9381 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
726f6388 9382 {
ccc6cda3 9383 temp_list = word_list_split (expanded);
726f6388
JA
9384 dispose_words (expanded);
9385 }
9386 else
9387 {
9388 /* If no parameter expansion, command substitution, process
9389 substitution, or arithmetic substitution took place, then
9390 do not do word splitting. We still have to remove quoted
9391 null characters from the result. */
9392 word_list_remove_quoted_nulls (expanded);
ccc6cda3 9393 temp_list = expanded;
726f6388
JA
9394 }
9395
ccc6cda3
JA
9396 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
9397 new_list = (WORD_LIST *)list_append (expanded, new_list);
726f6388
JA
9398 }
9399
cce855bc
JA
9400 if (orig_list)
9401 dispose_words (orig_list);
726f6388 9402
726f6388 9403 if (new_list)
cce855bc 9404 new_list = REVERSE_LIST (new_list, WORD_LIST *);
726f6388 9405
cce855bc
JA
9406 return (new_list);
9407}
726f6388 9408
cce855bc
JA
9409/* The workhorse for expand_words () and expand_words_no_vars ().
9410 First arg is LIST, a WORD_LIST of words.
b72432fd
JA
9411 Second arg EFLAGS is a flags word controlling which expansions are
9412 performed.
726f6388 9413
cce855bc
JA
9414 This does all of the substitutions: brace expansion, tilde expansion,
9415 parameter expansion, command substitution, arithmetic expansion,
9416 process substitution, word splitting, and pathname expansion, according
9417 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
9418 set, or for which no expansion is done, do not undergo word splitting.
df0e4bfe
CR
9419 Words with the W_NOGLOB bit set do not undergo pathname expansion; words
9420 with W_NOBRACE set do not undergo brace expansion (see
9421 brace_expand_word_list above). */
cce855bc
JA
9422static WORD_LIST *
9423expand_word_list_internal (list, eflags)
9424 WORD_LIST *list;
9425 int eflags;
9426{
9427 WORD_LIST *new_list, *temp_list;
9428 int tint;
726f6388 9429
cce855bc
JA
9430 if (list == 0)
9431 return ((WORD_LIST *)NULL);
726f6388 9432
bb70624e 9433 garglist = new_list = copy_word_list (list);
cce855bc
JA
9434 if (eflags & WEXP_VARASSIGN)
9435 {
bb70624e 9436 garglist = new_list = separate_out_assignments (new_list);
cce855bc
JA
9437 if (new_list == 0)
9438 {
bb70624e 9439 if (subst_assign_varlist)
cce855bc
JA
9440 {
9441 /* All the words were variable assignments, so they are placed
9442 into the shell's environment. */
bb70624e 9443 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
cce855bc
JA
9444 {
9445 this_command_name = (char *)NULL; /* no arithmetic errors */
adc6cff5 9446 tint = do_word_assignment (temp_list->word, 0);
cce855bc
JA
9447 /* Variable assignment errors in non-interactive shells
9448 running in Posix.2 mode cause the shell to exit. */
28ef6c31 9449 if (tint == 0)
ccc6cda3 9450 {
cce855bc 9451 last_command_exit_value = EXECUTION_FAILURE;
28ef6c31 9452 if (interactive_shell == 0 && posixly_correct)
d3a24ed2 9453 exp_jump_to_top_level (FORCE_EOF);
28ef6c31 9454 else
d3a24ed2 9455 exp_jump_to_top_level (DISCARD);
ccc6cda3 9456 }
726f6388 9457 }
bb70624e
JA
9458 dispose_words (subst_assign_varlist);
9459 subst_assign_varlist = (WORD_LIST *)NULL;
cce855bc
JA
9460 }
9461 return ((WORD_LIST *)NULL);
9462 }
9463 }
726f6388 9464
cce855bc
JA
9465 /* Begin expanding the words that remain. The expansions take place on
9466 things that aren't really variable assignments. */
726f6388 9467
cce855bc
JA
9468#if defined (BRACE_EXPANSION)
9469 /* Do brace expansion on this word if there are any brace characters
9470 in the string. */
9471 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
9472 new_list = brace_expand_word_list (new_list, eflags);
9473#endif /* BRACE_EXPANSION */
726f6388 9474
cce855bc
JA
9475 /* Perform the `normal' shell expansions: tilde expansion, parameter and
9476 variable substitution, command substitution, arithmetic expansion,
9477 and word splitting. */
9478 new_list = shell_expand_word_list (new_list, eflags);
726f6388 9479
cce855bc
JA
9480 /* Okay, we're almost done. Now let's just do some filename
9481 globbing. */
9482 if (new_list)
9483 {
9484 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
9485 /* Glob expand the word list unless globbing has been disabled. */
9486 new_list = glob_expand_word_list (new_list, eflags);
726f6388 9487 else
cce855bc
JA
9488 /* Dequote the words, because we're not performing globbing. */
9489 new_list = dequote_list (new_list);
726f6388
JA
9490 }
9491
bb70624e 9492 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
726f6388 9493 {
43df7bbb 9494 sh_wassign_func_t *assign_func;
adc6cff5 9495 int is_special_builtin, is_builtin_or_func;
726f6388
JA
9496
9497 /* If the remainder of the words expand to nothing, Posix.2 requires
9498 that the variable and environment assignments affect the shell's
9499 environment. */
43df7bbb 9500 assign_func = new_list ? assign_in_env : do_word_assignment;
56299fa5 9501 tempenv_assign_error = 0;
726f6388 9502
adc6cff5 9503 is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
e05be32d
CR
9504 /* Posix says that special builtins exit if a variable assignment error
9505 occurs in an assignment preceding it. */
adc6cff5 9506 is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
e05be32d 9507
bb70624e 9508 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
726f6388 9509 {
ccc6cda3 9510 this_command_name = (char *)NULL;
d7f49990 9511 assigning_in_environment = (assign_func == assign_in_env);
adc6cff5 9512 tint = (*assign_func) (temp_list->word, is_builtin_or_func);
d7f49990 9513 assigning_in_environment = 0;
ccc6cda3
JA
9514 /* Variable assignment errors in non-interactive shells running
9515 in Posix.2 mode cause the shell to exit. */
56299fa5 9516 if (tint == 0)
ccc6cda3 9517 {
43df7bbb 9518 if (assign_func == do_word_assignment)
56299fa5
CR
9519 {
9520 last_command_exit_value = EXECUTION_FAILURE;
e05be32d 9521 if (interactive_shell == 0 && posixly_correct && is_special_builtin)
56299fa5
CR
9522 exp_jump_to_top_level (FORCE_EOF);
9523 else
9524 exp_jump_to_top_level (DISCARD);
9525 }
28ef6c31 9526 else
56299fa5 9527 tempenv_assign_error++;
ccc6cda3 9528 }
726f6388 9529 }
726f6388 9530
bb70624e
JA
9531 dispose_words (subst_assign_varlist);
9532 subst_assign_varlist = (WORD_LIST *)NULL;
726f6388
JA
9533 }
9534
cce855bc 9535#if 0
ccc6cda3
JA
9536 tint = list_length (new_list) + 1;
9537 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
cce855bc
JA
9538 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
9539 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
ccc6cda3 9540 glob_argv_flags[tint] = '\0';
ccc6cda3 9541#endif
726f6388 9542
cce855bc 9543 return (new_list);
ccc6cda3 9544}