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