]> git.ipfire.org Git - thirdparty/bash.git/blame - subst.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / subst.c
CommitLineData
726f6388
JA
1/* subst.c -- The part of the shell that does parameter, command, and
2 globbing substitutions. */
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
726f6388
JA
7/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
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>
29#include <pwd.h>
30#include <signal.h>
31#include <errno.h>
ccc6cda3
JA
32
33#if defined (HAVE_UNISTD_H)
34# include <unistd.h>
35#endif
726f6388
JA
36
37#include "bashansi.h"
38#include "posixstat.h"
39
40#include "shell.h"
41#include "flags.h"
42#include "jobs.h"
43#include "execute_cmd.h"
44#include "filecntl.h"
ccc6cda3
JA
45#include "trap.h"
46#include "pathexp.h"
47#include "mailcheck.h"
48
d166f048
JA
49#if !defined (HAVE_RESTARTABLE_SYSCALLS) /* for getc_with_restart */
50#include "input.h"
51#endif
52
ccc6cda3
JA
53#include "builtins/getopt.h"
54#include "builtins/common.h"
726f6388 55
cce855bc 56#include <tilde/tilde.h>
726f6388 57#include <glob/fnmatch.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
ccc6cda3
JA
73/* Flags for quoted_strchr */
74#define ST_BACKSL 0x01
75#define ST_CTLESC 0x02
76
cce855bc
JA
77/* These defs make it easier to use the editor. */
78#define LBRACE '{'
79#define RBRACE '}'
80#define LPAREN '('
81#define RPAREN ')'
726f6388 82
28ef6c31
JA
83/* Evaluates to 1 if C is one of the shell's special parameters whose length
84 can be taken, but is also one of the special expansion characters. */
85#define VALID_SPECIAL_LENGTH_PARAM(c) \
86 ((c) == '-' || (c) == '?' || (c) == '#')
87
88/* Evaluates to 1 if C is one of the shell's special parameters for which an
89 indirect variable reference may be made. */
90#define VALID_INDIR_PARAM(c) \
91 ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
92
93/* Evaluates to 1 if C is one of the OP characters that follows the parameter
94 in ${parameter[:]OPword}. */
95#define VALID_PARAM_EXPAND_CHAR(c) \
96 ((c) == '-' || (c) == '=' || (c) == '?' || (c) == '+')
97
bb70624e
JA
98/* Evaluates to 1 if this is one of the shell's special variables. */
99#define SPECIAL_VAR(name, wi) \
28ef6c31
JA
100 ((isdigit (*name) && all_digits (name)) || \
101 (name[1] == '\0' && (sh_syntaxtab[*name] & CSPECVAR)) || \
102 (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
bb70624e 103
726f6388
JA
104/* Process ID of the last command executed within command substitution. */
105pid_t last_command_subst_pid = NO_PID;
b72432fd 106pid_t current_command_subst_pid = NO_PID;
726f6388
JA
107
108/* Extern functions and variables from different files. */
109extern int last_command_exit_value, interactive, interactive_shell;
ccc6cda3 110extern int subshell_environment, startup_state;
bb70624e 111extern int return_catch_flag, return_catch_value;
ccc6cda3 112extern int dollar_dollar_pid;
726f6388 113extern int posixly_correct;
726f6388 114extern char *this_command_name;
ccc6cda3 115extern struct fd_bitmap *current_fds_to_close;
cce855bc 116extern int wordexp_only;
726f6388 117
ccc6cda3
JA
118extern void getopts_reset ();
119
120/* Non-zero means to allow unmatched globbed filenames to expand to
121 a null file. */
122int allow_null_glob_expansion;
123
124/* Variables to keep track of which words in an expanded word list (the
125 output of expand_word_list_internal) are the result of globbing
126 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c. */
127char *glob_argv_flags;
128static int glob_argv_flags_size;
726f6388
JA
129
130static WORD_LIST expand_word_error, expand_word_fatal;
131static char expand_param_error, expand_param_fatal;
132
28ef6c31
JA
133/* Tell the expansion functions to not longjmp back to top_level on fatal
134 errors. Enabled when doing completion and prompt string expansion. */
135static int no_longjmp_on_fatal_error = 0;
136
137/* Set by expand_word_unsplit; used to inhibit splitting and re-joining
138 $* on $IFS, primarily when doing assignment statements. */
139static int expand_no_split_dollar_star = 0;
bb70624e
JA
140
141/* Used to hold a list of variable assignments preceding a command. Global
142 so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
143 SIGCHLD trap. */
144WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
28ef6c31 145
bb70624e
JA
146/* A WORD_LIST of words to be expanded by expand_word_list_internal,
147 without any leading variable assignments. */
148static WORD_LIST *garglist = (WORD_LIST *)NULL;
b72432fd 149
cce855bc
JA
150static char *make_quoted_char ();
151static void remove_quoted_nulls ();
152static char *param_expand ();
153static char *maybe_expand_string ();
154static WORD_LIST *call_expand_word_internal ();
726f6388 155static WORD_LIST *expand_string_internal ();
ccc6cda3 156static WORD_LIST *expand_word_internal (), *expand_word_list_internal ();
726f6388 157static WORD_LIST *expand_string_leave_quoted ();
ccc6cda3 158static WORD_LIST *expand_string_for_rhs ();
b72432fd 159static char *getifs ();
726f6388 160static WORD_LIST *word_list_split ();
ccc6cda3 161static WORD_LIST *quote_list (), *dequote_list ();
cce855bc
JA
162static char *quote_escapes ();
163static WORD_LIST *list_quote_escapes ();
726f6388 164static int unquoted_substring (), unquoted_member ();
726f6388
JA
165static int do_assignment_internal ();
166static char *string_extract_verbatim (), *string_extract ();
167static char *string_extract_double_quoted (), *string_extract_single_quoted ();
cce855bc
JA
168static char *string_list_dollar_at (), *string_list_dollar_star ();
169static inline int skip_single_quoted (), skip_double_quoted ();
726f6388
JA
170static char *extract_delimited_string ();
171static char *extract_dollar_brace_string ();
172
173/* **************************************************************** */
174/* */
175/* Utility Functions */
176/* */
177/* **************************************************************** */
178
179/* Cons a new string from STRING starting at START and ending at END,
180 not including END. */
181char *
182substring (string, start, end)
183 char *string;
184 int start, end;
185{
ccc6cda3
JA
186 register int len;
187 register char *result;
726f6388 188
ccc6cda3
JA
189 len = end - start;
190 result = xmalloc (len + 1);
726f6388
JA
191 strncpy (result, string + start, len);
192 result[len] = '\0';
193 return (result);
194}
195
ccc6cda3
JA
196static char *
197quoted_substring (string, start, end)
198 char *string;
199 int start, end;
200{
201 register int len, l;
202 register char *result, *s, *r;
203
204 len = end - start;
205
206 /* Move to string[start], skipping quoted characters. */
207 for (s = string, l = 0; *s && l < start; )
208 {
209 if (*s == CTLESC)
210 {
28ef6c31
JA
211 s++;
212 continue;
ccc6cda3
JA
213 }
214 l++;
215 if (*s == 0)
28ef6c31 216 break;
ccc6cda3
JA
217 }
218
219 r = result = xmalloc (2*len + 1); /* save room for quotes */
220
221 /* Copy LEN characters, including quote characters. */
222 s = string + l;
223 for (l = 0; l < len; s++)
224 {
225 if (*s == CTLESC)
28ef6c31 226 *r++ = *s++;
ccc6cda3
JA
227 *r++ = *s;
228 l++;
229 if (*s == 0)
28ef6c31 230 break;
ccc6cda3
JA
231 }
232 *r = '\0';
233 return result;
234}
235
236/* Find the first occurrence of character C in string S, obeying shell
237 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
238 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
239 escaped with CTLESC are skipped. */
240static inline char *
241quoted_strchr (s, c, flags)
242 char *s;
243 int c, flags;
244{
245 register char *p;
246
247 for (p = s; *p; p++)
248 {
249 if (((flags & ST_BACKSL) && *p == '\\')
250 || ((flags & ST_CTLESC) && *p == CTLESC))
251 {
252 p++;
253 if (*p == '\0')
254 return ((char *)NULL);
255 continue;
256 }
257 else if (*p == c)
258 return p;
259 }
260 return ((char *)NULL);
261}
262
cce855bc
JA
263/* Return 1 if CHARACTER appears in an unquoted portion of
264 STRING. Return 0 otherwise. */
265static int
266unquoted_member (character, string)
267 int character;
726f6388
JA
268 char *string;
269{
cce855bc 270 int sindex, c;
726f6388 271
cce855bc 272 for (sindex = 0; c = string[sindex]; )
726f6388 273 {
cce855bc
JA
274 if (c == character)
275 return (1);
276
277 switch (c)
ccc6cda3 278 {
cce855bc
JA
279 default:
280 sindex++;
281 break;
282
283 case '\\':
284 sindex++;
285 if (string[sindex])
286 sindex++;
287 break;
288
289 case '\'':
290 sindex = skip_single_quoted (string, ++sindex);
291 break;
292
293 case '"':
294 sindex = skip_double_quoted (string, ++sindex);
295 break;
ccc6cda3 296 }
726f6388 297 }
cce855bc 298 return (0);
726f6388
JA
299}
300
cce855bc
JA
301/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
302static int
303unquoted_substring (substr, string)
304 char *substr, *string;
726f6388 305{
cce855bc 306 int sindex, c, sublen;
726f6388 307
cce855bc
JA
308 if (substr == 0 || *substr == '\0')
309 return (0);
310
311 sublen = strlen (substr);
312 for (sindex = 0; c = string[sindex]; )
726f6388 313 {
cce855bc
JA
314 if (STREQN (string + sindex, substr, sublen))
315 return (1);
316
317 switch (c)
318 {
319 case '\\':
320 sindex++;
321
322 if (string[sindex])
323 sindex++;
324 break;
325
326 case '\'':
327 sindex = skip_single_quoted (string, ++sindex);
328 break;
329
330 case '"':
331 sindex = skip_double_quoted (string, ++sindex);
332 break;
333
334 default:
335 sindex++;
336 break;
337 }
726f6388 338 }
cce855bc 339 return (0);
ccc6cda3 340}
726f6388 341
cce855bc
JA
342/* Most of the substitutions must be done in parallel. In order
343 to avoid using tons of unclear goto's, I have some functions
344 for manipulating malloc'ed strings. They all take INDX, a
345 pointer to an integer which is the offset into the string
346 where manipulation is taking place. They also take SIZE, a
347 pointer to an integer which is the current length of the
348 character array for this string. */
726f6388 349
cce855bc
JA
350/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
351 of space allocated to TARGET. SOURCE can be NULL, in which
352 case nothing happens. Gets rid of SOURCE by freeing it.
353 Returns TARGET in case the location has changed. */
354inline char *
355sub_append_string (source, target, indx, size)
356 char *source, *target;
357 int *indx, *size;
358{
359 if (source)
726f6388 360 {
cce855bc
JA
361 int srclen, n;
362
363 srclen = STRLEN (source);
364 if (srclen >= (int)(*size - *indx))
726f6388 365 {
cce855bc
JA
366 n = srclen + *indx;
367 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
368 target = xrealloc (target, (*size = n));
726f6388 369 }
cce855bc
JA
370
371 FASTCOPY (source, target + *indx, srclen);
372 *indx += srclen;
373 target[*indx] = '\0';
374
375 free (source);
726f6388 376 }
cce855bc
JA
377 return (target);
378}
379
380#if 0
381/* UNUSED */
382/* Append the textual representation of NUMBER to TARGET.
383 INDX and SIZE are as in SUB_APPEND_STRING. */
384char *
385sub_append_number (number, target, indx, size)
386 int number, *indx, *size;
387 char *target;
388{
389 char *temp;
390
391 temp = itos (number);
392 return (sub_append_string (temp, target, indx, size));
726f6388 393}
d166f048 394#endif
726f6388
JA
395
396/* Extract a substring from STRING, starting at SINDEX and ending with
397 one of the characters in CHARLIST. Don't make the ending character
398 part of the string. Leave SINDEX pointing at the ending character.
ccc6cda3
JA
399 Understand about backslashes in the string. If VARNAME is non-zero,
400 and array variables have been compiled into the shell, everything
401 between a `[' and a corresponding `]' is skipped over. */
726f6388 402static char *
ccc6cda3 403string_extract (string, sindex, charlist, varname)
726f6388 404 char *string, *charlist;
ccc6cda3 405 int *sindex, varname;
726f6388 406{
ccc6cda3 407 register int c, i;
726f6388
JA
408 char *temp;
409
ccc6cda3 410 for (i = *sindex; c = string[i]; i++)
726f6388
JA
411 {
412 if (c == '\\')
413 if (string[i + 1])
414 i++;
415 else
416 break;
ccc6cda3
JA
417#if defined (ARRAY_VARS)
418 else if (varname && c == '[')
419 {
420 int ni;
421 /* If this is an array subscript, skip over it and continue. */
422 ni = skipsubscript (string, i);
423 if (string[ni] == ']')
424 i = ni;
425 }
426#endif
427 else if (MEMBER (c, charlist))
726f6388 428 break;
726f6388 429 }
bb70624e
JA
430
431 temp = substring (string, *sindex, i);
726f6388
JA
432 *sindex = i;
433 return (temp);
434}
435
ccc6cda3
JA
436/* Extract the contents of STRING as if it is enclosed in double quotes.
437 SINDEX, when passed in, is the offset of the character immediately
438 following the opening double quote; on exit, SINDEX is left pointing after
439 the closing double quote. If STRIPDQ is non-zero, unquoted double
440 quotes are stripped and the string is terminated by a null byte.
441 Backslashes between the embedded double quotes are processed. If STRIPDQ
442 is zero, an unquoted `"' terminates the string. */
443static inline char *
444string_extract_double_quoted (string, sindex, stripdq)
726f6388 445 char *string;
ccc6cda3 446 int *sindex, stripdq;
726f6388 447{
ccc6cda3
JA
448 int c, j, i, t;
449 char *temp, *ret; /* The new string we return. */
450 int pass_next, backquote, si; /* State variables for the machine. */
451 int dquote;
726f6388 452
ccc6cda3
JA
453 pass_next = backquote = dquote = 0;
454 temp = xmalloc (1 + strlen (string) - *sindex);
726f6388 455
ccc6cda3 456 for (j = 0, i = *sindex; c = string[i]; i++)
726f6388 457 {
ccc6cda3
JA
458 /* Process a character that was quoted by a backslash. */
459 if (pass_next)
726f6388 460 {
ccc6cda3 461 /* Posix.2 sez:
726f6388 462
ccc6cda3
JA
463 ``The backslash shall retain its special meaning as an escape
464 character only when followed by one of the characters:
465 $ ` " \ <newline>''.
726f6388 466
ccc6cda3
JA
467 If STRIPDQ is zero, we handle the double quotes here and let
468 expand_word_internal handle the rest. If STRIPDQ is non-zero,
469 we have already been through one round of backslash stripping,
470 and want to strip these backslashes only if DQUOTE is non-zero,
471 indicating that we are inside an embedded double-quoted string. */
472
473 /* If we are in an embedded quoted string, then don't strip
474 backslashes before characters for which the backslash
475 retains its special meaning, but remove backslashes in
476 front of other characters. If we are not in an
477 embedded quoted string, don't strip backslashes at all.
478 This mess is necessary because the string was already
479 surrounded by double quotes (and sh has some really weird
480 quoting rules).
481 The returned string will be run through expansion as if
482 it were double-quoted. */
483 if ((stripdq == 0 && c != '"') ||
28ef6c31 484 (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
ccc6cda3
JA
485 temp[j++] = '\\';
486 temp[j++] = c;
487 pass_next = 0;
488 continue;
489 }
726f6388 490
ccc6cda3
JA
491 /* A backslash protects the next character. The code just above
492 handles preserving the backslash in front of any character but
493 a double quote. */
494 if (c == '\\')
726f6388 495 {
ccc6cda3 496 pass_next++;
726f6388
JA
497 continue;
498 }
499
ccc6cda3
JA
500 /* Inside backquotes, ``the portion of the quoted string from the
501 initial backquote and the characters up to the next backquote
502 that is not preceded by a backslash, having escape characters
503 removed, defines that command''. */
504 if (backquote)
726f6388 505 {
ccc6cda3
JA
506 if (c == '`')
507 backquote = 0;
508 temp[j++] = c;
726f6388
JA
509 continue;
510 }
511
ccc6cda3 512 if (c == '`')
726f6388 513 {
ccc6cda3
JA
514 temp[j++] = c;
515 backquote++;
516 continue;
726f6388
JA
517 }
518
ccc6cda3
JA
519 /* Pass everything between `$(' and the matching `)' or a quoted
520 ${ ... } pair through according to the Posix.2 specification. */
cce855bc 521 if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
726f6388 522 {
ccc6cda3 523 si = i + 2;
cce855bc
JA
524 if (string[i + 1] == LPAREN)
525 ret = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
ccc6cda3
JA
526 else
527 ret = extract_dollar_brace_string (string, &si, 1);
726f6388 528
ccc6cda3
JA
529 temp[j++] = '$';
530 temp[j++] = string[i + 1];
726f6388 531
ccc6cda3
JA
532 for (t = 0; ret[t]; t++, j++)
533 temp[j] = ret[t];
534 temp[j++] = string[si];
726f6388 535
ccc6cda3
JA
536 i = si;
537 free (ret);
538 continue;
726f6388
JA
539 }
540
ccc6cda3 541 /* Add any character but a double quote to the quoted string we're
28ef6c31 542 accumulating. */
ccc6cda3 543 if (c != '"')
726f6388 544 {
ccc6cda3 545 temp[j++] = c;
726f6388
JA
546 continue;
547 }
ccc6cda3
JA
548
549 /* c == '"' */
550 if (stripdq)
726f6388 551 {
ccc6cda3
JA
552 dquote ^= 1;
553 continue;
726f6388 554 }
ccc6cda3
JA
555
556 break;
726f6388 557 }
ccc6cda3 558 temp[j] = '\0';
726f6388 559
ccc6cda3
JA
560 /* Point to after the closing quote. */
561 if (c)
562 i++;
726f6388
JA
563 *sindex = i;
564
ccc6cda3
JA
565 return (temp);
566}
567
568/* This should really be another option to string_extract_double_quoted. */
569static inline int
570skip_double_quoted (string, sind)
571 char *string;
572 int sind;
573{
574 int c, j, i;
575 char *ret;
576 int pass_next, backquote, si;
577
578 pass_next = backquote = 0;
579
580 for (j = 0, i = sind; c = string[i]; i++)
726f6388 581 {
ccc6cda3
JA
582 if (pass_next)
583 {
584 pass_next = 0;
585 continue;
586 }
587 else if (c == '\\')
588 {
589 pass_next++;
590 continue;
591 }
592 else if (backquote)
593 {
594 if (c == '`')
595 backquote = 0;
596 continue;
597 }
598 else if (c == '`')
599 {
600 backquote++;
601 continue;
602 }
cce855bc 603 else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
ccc6cda3
JA
604 {
605 si = i + 2;
cce855bc 606 if (string[i + 1] == LPAREN)
ccc6cda3
JA
607 ret = extract_delimited_string (string, &si, "$(", "(", ")");
608 else
609 ret = extract_dollar_brace_string (string, &si, 0);
610
611 i = si;
612 free (ret);
613 continue;
614 }
615 else if (c != '"')
616 continue;
617 else
618 break;
726f6388 619 }
ccc6cda3
JA
620
621 if (c)
622 i++;
623
624 return (i);
726f6388
JA
625}
626
ccc6cda3
JA
627/* Extract the contents of STRING as if it is enclosed in single quotes.
628 SINDEX, when passed in, is the offset of the character immediately
629 following the opening single quote; on exit, SINDEX is left pointing after
630 the closing single quote. */
631static inline char *
632string_extract_single_quoted (string, sindex)
633 char *string;
634 int *sindex;
635{
636 register int i, j;
637 char *t;
638
639 for (i = *sindex; string[i] && string[i] != '\''; i++)
640 ;
641
bb70624e 642 t = substring (string, *sindex, i);
ccc6cda3
JA
643
644 if (string[i])
645 i++;
646 *sindex = i;
647
648 return (t);
649}
650
651static inline int
652skip_single_quoted (string, sind)
653 char *string;
654 int sind;
655{
28ef6c31 656 register int c;
ccc6cda3 657
28ef6c31 658 for (c = sind; string[c] && string[c] != '\''; c++)
ccc6cda3 659 ;
28ef6c31
JA
660 if (string[c])
661 c++;
662 return c;
ccc6cda3
JA
663}
664
665/* Just like string_extract, but doesn't hack backslashes or any of
bb70624e 666 that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
726f6388 667static char *
ccc6cda3
JA
668string_extract_verbatim (string, sindex, charlist)
669 char *string, *charlist;
670 int *sindex;
671{
672 register int i = *sindex;
673 int c;
674 char *temp;
675
676 if (charlist[0] == '\'' && charlist[1] == '\0')
677 {
678 temp = string_extract_single_quoted (string, sindex);
679 --*sindex; /* leave *sindex at separator character */
680 return temp;
681 }
682
683 for (i = *sindex; c = string[i]; i++)
684 {
685 if (c == CTLESC)
686 {
687 i++;
688 continue;
689 }
690
691 if (MEMBER (c, charlist))
692 break;
693 }
694
bb70624e 695 temp = substring (string, *sindex, i);
ccc6cda3
JA
696 *sindex = i;
697
698 return (temp);
699}
700
701/* Extract the $( construct in STRING, and return a new string.
702 Start extracting at (SINDEX) as if we had just seen "$(".
703 Make (SINDEX) get the position of the matching ")". */
704char *
705extract_command_subst (string, sindex)
726f6388
JA
706 char *string;
707 int *sindex;
708{
ccc6cda3
JA
709 return (extract_delimited_string (string, sindex, "$(", "(", ")"));
710}
711
28ef6c31 712/* Extract the $[ construct in STRING, and return a new string. (])
ccc6cda3
JA
713 Start extracting at (SINDEX) as if we had just seen "$[".
714 Make (SINDEX) get the position of the matching "]". */
715char *
716extract_arithmetic_subst (string, sindex)
717 char *string;
718 int *sindex;
719{
28ef6c31 720 return (extract_delimited_string (string, sindex, "$[", "[", "]")); /*]*/
ccc6cda3
JA
721}
722
723#if defined (PROCESS_SUBSTITUTION)
724/* Extract the <( or >( construct in STRING, and return a new string.
725 Start extracting at (SINDEX) as if we had just seen "<(".
cce855bc 726 Make (SINDEX) get the position of the matching ")". */ /*))*/
ccc6cda3
JA
727char *
728extract_process_subst (string, starter, sindex)
729 char *string;
730 char *starter;
731 int *sindex;
732{
733 return (extract_delimited_string (string, sindex, starter, "(", ")"));
734}
735#endif /* PROCESS_SUBSTITUTION */
736
737#if defined (ARRAY_VARS)
738char *
739extract_array_assignment_list (string, sindex)
740 char *string;
741 int *sindex;
742{
743 return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")"));
744}
745#endif
746
747/* Extract and create a new string from the contents of STRING, a
748 character string delimited with OPENER and CLOSER. SINDEX is
749 the address of an int describing the current offset in STRING;
750 it should point to just after the first OPENER found. On exit,
751 SINDEX gets the position of the last character of the matching CLOSER.
752 If OPENER is more than a single character, ALT_OPENER, if non-null,
753 contains a character string that can also match CLOSER and thus
754 needs to be skipped. */
755static char *
756extract_delimited_string (string, sindex, opener, alt_opener, closer)
757 char *string;
758 int *sindex;
759 char *opener, *alt_opener, *closer;
760{
761 int i, c, si;
762 char *t, *result;
726f6388 763 int pass_character, nesting_level;
ccc6cda3
JA
764 int len_closer, len_opener, len_alt_opener;
765
766 len_opener = STRLEN (opener);
767 len_alt_opener = STRLEN (alt_opener);
768 len_closer = STRLEN (closer);
726f6388 769
ccc6cda3 770 pass_character = 0;
726f6388
JA
771
772 nesting_level = 1;
ccc6cda3 773 i = *sindex;
726f6388 774
ccc6cda3 775 while (nesting_level)
726f6388 776 {
ccc6cda3
JA
777 c = string[i];
778
779 if (c == 0)
28ef6c31 780 break;
ccc6cda3
JA
781
782 if (pass_character) /* previous char was backslash */
726f6388
JA
783 {
784 pass_character = 0;
ccc6cda3 785 i++;
726f6388
JA
786 continue;
787 }
788
789 if (c == CTLESC)
790 {
791 pass_character++;
ccc6cda3 792 i++;
726f6388
JA
793 continue;
794 }
795
726f6388
JA
796 if (c == '\\')
797 {
ccc6cda3
JA
798 pass_character++;
799 i++;
800 continue;
726f6388
JA
801 }
802
ccc6cda3
JA
803 /* Process a nested OPENER. */
804 if (STREQN (string + i, opener, len_opener))
726f6388 805 {
ccc6cda3
JA
806 si = i + len_opener;
807 t = extract_delimited_string (string, &si, opener, alt_opener, closer);
808 i = si + 1;
809 FREE (t);
810 continue;
726f6388
JA
811 }
812
ccc6cda3
JA
813 /* Process a nested ALT_OPENER */
814 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
726f6388 815 {
ccc6cda3
JA
816 si = i + len_alt_opener;
817 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer);
818 i = si + 1;
819 FREE (t);
726f6388
JA
820 continue;
821 }
ccc6cda3
JA
822
823 /* If the current substring terminates the delimited string, decrement
824 the nesting level. */
825 if (STREQN (string + i, closer, len_closer))
726f6388 826 {
ccc6cda3
JA
827 i += len_closer - 1; /* move to last char of the closer */
828 nesting_level--;
829 if (nesting_level == 0)
830 break;
726f6388 831 }
ccc6cda3
JA
832
833 /* Pass old-style command substitution through verbatim. */
834 if (c == '`')
28ef6c31
JA
835 {
836 si = i + 1;
837 t = string_extract (string, &si, "`", 0);
838 i = si + 1;
839 FREE (t);
840 continue;
841 }
ccc6cda3
JA
842
843 /* Pass single-quoted strings through verbatim. */
844 if (c == '\'')
28ef6c31
JA
845 {
846 si = i + 1;
847 i = skip_single_quoted (string, si);
848 continue;
849 }
ccc6cda3
JA
850
851 /* Pass embedded double-quoted strings through verbatim as well. */
852 if (c == '"')
28ef6c31
JA
853 {
854 si = i + 1;
855 i = skip_double_quoted (string, si);
856 continue;
857 }
ccc6cda3
JA
858
859 i++; /* move past this character, which was not special. */
726f6388
JA
860 }
861
bb70624e 862#if 0
ccc6cda3 863 if (c == 0 && nesting_level)
bb70624e 864#else
28ef6c31 865 if (c == 0 && nesting_level && no_longjmp_on_fatal_error == 0)
bb70624e 866#endif
726f6388 867 {
ccc6cda3 868 report_error ("bad substitution: no `%s' in %s", closer, string);
28ef6c31 869 last_command_exit_value = EXECUTION_FAILURE;
ccc6cda3 870 jump_to_top_level (DISCARD);
726f6388 871 }
ccc6cda3 872
cce855bc
JA
873 si = i - *sindex - len_closer + 1;
874 result = xmalloc (1 + si);
875 strncpy (result, string + *sindex, si);
876 result[si] = '\0';
877 *sindex = i;
878
726f6388
JA
879 return (result);
880}
881
ccc6cda3
JA
882/* Extract a parameter expansion expression within ${ and } from STRING.
883 Obey the Posix.2 rules for finding the ending `}': count braces while
884 skipping over enclosed quoted strings and command substitutions.
885 SINDEX is the address of an int describing the current offset in STRING;
886 it should point to just after the first `{' found. On exit, SINDEX
887 gets the position of the matching `}'. QUOTED is non-zero if this
888 occurs inside double quotes. */
889/* XXX -- this is very similar to extract_delimited_string -- XXX */
726f6388 890static char *
ccc6cda3 891extract_dollar_brace_string (string, sindex, quoted)
726f6388 892 char *string;
ccc6cda3 893 int *sindex, quoted;
726f6388 894{
ccc6cda3
JA
895 register int i, c, l;
896 int pass_character, nesting_level, si;
897 char *result, *t;
726f6388 898
ccc6cda3 899 pass_character = 0;
726f6388 900
ccc6cda3
JA
901 nesting_level = 1;
902
903 for (i = *sindex; (c = string[i]); i++)
726f6388 904 {
ccc6cda3 905 if (pass_character)
726f6388 906 {
ccc6cda3
JA
907 pass_character = 0;
908 continue;
909 }
726f6388 910
cce855bc
JA
911 /* CTLESCs and backslashes quote the next character. */
912 if (c == CTLESC || c == '\\')
726f6388 913 {
ccc6cda3 914 pass_character++;
726f6388
JA
915 continue;
916 }
917
cce855bc 918 if (string[i] == '$' && string[i+1] == LBRACE)
726f6388 919 {
ccc6cda3
JA
920 nesting_level++;
921 i++;
726f6388
JA
922 continue;
923 }
924
cce855bc 925 if (c == RBRACE)
726f6388 926 {
ccc6cda3
JA
927 nesting_level--;
928 if (nesting_level == 0)
929 break;
726f6388
JA
930 continue;
931 }
932
ccc6cda3
JA
933 /* Pass the contents of old-style command substitutions through
934 verbatim. */
935 if (c == '`')
726f6388 936 {
ccc6cda3
JA
937 si = i + 1;
938 t = string_extract (string, &si, "`", 0);
939 i = si;
940 free (t);
941 continue;
942 }
726f6388 943
cce855bc
JA
944 /* Pass the contents of new-style command substitutions and
945 arithmetic substitutions through verbatim. */
946 if (string[i] == '$' && string[i+1] == LPAREN)
ccc6cda3 947 {
726f6388 948 si = i + 2;
cce855bc 949 t = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
726f6388 950 i = si;
ccc6cda3 951 free (t);
726f6388
JA
952 continue;
953 }
954
cce855bc
JA
955 /* Pass the contents of single-quoted and double-quoted strings
956 through verbatim. */
957 if (c == '\'' || c == '"')
ccc6cda3
JA
958 {
959 si = i + 1;
cce855bc
JA
960 i = (c == '\'') ? skip_single_quoted (string, si)
961 : skip_double_quoted (string, si);
962 /* skip_XXX_quoted leaves index one past close quote */
ccc6cda3
JA
963 i--;
964 continue;
965 }
cce855bc 966 }
726f6388 967
28ef6c31 968 if (c == 0 && nesting_level && no_longjmp_on_fatal_error == 0)
cce855bc
JA
969 {
970 report_error ("bad substitution: no ending `}' in %s", string);
28ef6c31 971 last_command_exit_value = EXECUTION_FAILURE;
cce855bc 972 jump_to_top_level (DISCARD);
726f6388 973 }
726f6388 974
bb70624e 975 result = substring (string, *sindex, i);
726f6388
JA
976 *sindex = i;
977
ccc6cda3 978 return (result);
726f6388
JA
979}
980
ccc6cda3
JA
981/* Remove backslashes which are quoting backquotes from STRING. Modifies
982 STRING, and returns a pointer to it. */
983char *
984de_backslash (string)
726f6388 985 char *string;
ccc6cda3
JA
986{
987 register int i, l;
726f6388 988
ccc6cda3
JA
989 for (i = 0, l = strlen (string); i < l; i++)
990 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
991 string[i + 1] == '$'))
992 strcpy (string + i, string + i + 1); /* XXX - should be memmove */
993 return (string);
994}
726f6388 995
ccc6cda3 996#if 0
cce855bc 997/*UNUSED*/
ccc6cda3
JA
998/* Replace instances of \! in a string with !. */
999void
1000unquote_bang (string)
1001 char *string;
1002{
1003 register int i, j;
1004 register char *temp;
726f6388 1005
ccc6cda3 1006 temp = xmalloc (1 + strlen (string));
726f6388 1007
ccc6cda3
JA
1008 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
1009 {
1010 if (string[i] == '\\' && string[i + 1] == '!')
1011 {
1012 temp[j] = '!';
1013 i++;
1014 }
1015 }
1016 strcpy (string, temp);
1017 free (temp);
726f6388 1018}
ccc6cda3 1019#endif
726f6388 1020
ccc6cda3 1021#if defined (READLINE)
726f6388
JA
1022/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
1023 an unclosed quoted string), or if the character at EINDEX is quoted
28ef6c31 1024 by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
b72432fd
JA
1025 single and double-quoted string parsing functions should not return an
1026 error if there are unclosed quotes or braces. */
1027
28ef6c31 1028#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
b72432fd 1029
726f6388
JA
1030int
1031char_is_quoted (string, eindex)
1032 char *string;
1033 int eindex;
1034{
1035 int i, pass_next, quoted;
726f6388 1036
28ef6c31 1037 no_longjmp_on_fatal_error = 1;
726f6388
JA
1038 for (i = pass_next = quoted = 0; i <= eindex; i++)
1039 {
1040 if (pass_next)
1041 {
1042 pass_next = 0;
1043 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
b72432fd 1044 CQ_RETURN(1);
726f6388
JA
1045 continue;
1046 }
ccc6cda3
JA
1047 else if (string[i] == '\'' || string[i] == '"')
1048 {
1049 i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
1050 : skip_double_quoted (string, ++i);
1051 if (i > eindex)
b72432fd 1052 CQ_RETURN(1);
ccc6cda3
JA
1053 i--; /* the skip functions increment past the closing quote. */
1054 }
726f6388 1055 else if (string[i] == '\\')
ccc6cda3
JA
1056 {
1057 pass_next = 1;
1058 continue;
1059 }
726f6388 1060 }
b72432fd 1061 CQ_RETURN(0);
726f6388
JA
1062}
1063
726f6388
JA
1064int
1065unclosed_pair (string, eindex, openstr)
1066 char *string;
1067 int eindex;
1068 char *openstr;
1069{
ccc6cda3 1070 int i, pass_next, openc, olen;
726f6388
JA
1071
1072 olen = strlen (openstr);
1073 for (i = pass_next = openc = 0; i <= eindex; i++)
1074 {
1075 if (pass_next)
1076 {
1077 pass_next = 0;
1078 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1079 return 0;
1080 continue;
1081 }
1082 else if (STREQN (string + i, openstr, olen))
1083 {
1084 openc = 1 - openc;
1085 i += olen - 1;
1086 }
ccc6cda3 1087 else if (string[i] == '\'' || string[i] == '"')
726f6388 1088 {
ccc6cda3
JA
1089 i = (string[i] == '\'') ? skip_single_quoted (string, i)
1090 : skip_double_quoted (string, i);
726f6388
JA
1091 if (i > eindex)
1092 return 0;
1093 }
1094 else if (string[i] == '\\')
1095 {
1096 pass_next = 1;
1097 continue;
1098 }
1099 }
1100 return (openc);
1101}
bb70624e
JA
1102
1103/* Skip characters in STRING until we find a character in DELIMS, and return
1104 the index of that character. START is the index into string at which we
1105 begin. This is similar in spirit to strpbrk, but it returns an index into
1106 STRING and takes a starting index. This little piece of code knows quite
1107 a lot of shell syntax. It's very similar to skip_double_quoted and other
1108 functions of that ilk. */
1109int
1110skip_to_delim (string, start, delims)
1111 char *string;
1112 int start;
1113 char *delims;
1114{
1115 int i, pass_next, backq, si;
1116 char *temp;
1117
28ef6c31 1118 no_longjmp_on_fatal_error = 1;
bb70624e
JA
1119 for (i = start, pass_next = backq = 0; string[i]; i++)
1120 {
1121 if (pass_next)
1122 {
1123 pass_next = 0;
1124 if (string[i] == 0)
1125 CQ_RETURN(i);
1126 continue;
1127 }
1128 else if (string[i] == '\\')
1129 {
1130 pass_next = 1;
1131 continue;
1132 }
1133 else if (backq)
1134 {
1135 if (string[i] == '`')
1136 backq = 0;
1137 continue;
1138 }
1139 else if (string[i] == '`')
1140 {
1141 backq = 1;
1142 continue;
1143 }
1144 else if (string[i] == '\'' || string[i] == '"')
1145 {
1146 i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
1147 : skip_double_quoted (string, ++i);
1148 i--; /* the skip functions increment past the closing quote. */
1149 }
1150 else if (string[i] == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
1151 {
1152 si = i + 2;
1153 if (string[si] == '\0')
1154 break;
1155 if (string[i+1] == LPAREN)
1156 temp = extract_delimited_string (string, &si, "$(", "(", ")"); /* ) */
1157 else
1158 temp = extract_dollar_brace_string (string, &si, 0);
1159 i = si;
1160 free (temp);
1161 continue;
1162 }
1163 else if (member (string[i], delims))
28ef6c31 1164 break;
bb70624e
JA
1165 }
1166 CQ_RETURN(i);
1167}
1168
1169/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
1170 individual words. If DELIMS is NULL, the current value of $IFS is used
1171 to split the string. SENTINEL is an index to look for. NWP, if non-NULL
1172 gets the number of words in the returned list. CWP, if non-NULL, gets
1173 the index of the word containing SENTINEL. Non-whitespace chars in
1174 DELIMS delimit separate fields. */
1175WORD_LIST *
1176split_at_delims (string, slen, delims, sentinel, nwp, cwp)
1177 char *string;
1178 int slen;
1179 char *delims;
1180 int sentinel;
1181 int *nwp, *cwp;
1182{
1183 int ts, te, i, nw, cw, peekc;
1184 char *token, *s, *d, *d2;
1185 WORD_LIST *ret, *tl;
1186
1187 if (string == 0 || *string == '\0')
1188 {
1189 if (nwp)
1190 *nwp = 0;
1191 if (cwp)
1192 *cwp = 0;
1193 return ((WORD_LIST *)NULL);
1194 }
1195
1196 d = (delims == 0) ? getifs () : delims;
1197
1198 /* Make d2 the non-whitespace characters in delims */
1199 d2 = 0;
1200 if (delims)
1201 {
1202 d2 = xmalloc (strlen (delims) + 1);
1203 for (i = ts = 0; delims[i]; i++)
1204 {
1205 if (whitespace(delims[i]) == 0)
1206 d2[ts++] = delims[i];
1207 }
1208 d2[ts] = '\0';
1209 }
1210
1211 ret = (WORD_LIST *)NULL;
1212
28ef6c31 1213 for (i = 0; member (string[i], d) && (whitespace(string[i]) || string[i] == '\n'); i++)
bb70624e
JA
1214 ;
1215 if (string[i] == '\0')
1216 return (ret);
1217
1218 ts = i;
1219 nw = 0;
1220 cw = -1;
1221 while (1)
1222 {
1223 te = skip_to_delim (string, ts, d);
1224
1225 /* If we have a non-whitespace delimiter character, use it to make a
1226 separate field. This is just about what $IFS splitting does and
1227 is closer to the behavior of the shell parser. */
28ef6c31 1228 if (ts == te && d2 && member (string[ts], d2))
bb70624e
JA
1229 {
1230 te = ts + 1;
28ef6c31 1231 while (member (string[te], d2))
bb70624e
JA
1232 te++;
1233 }
1234
1235 token = substring (string, ts, te);
1236
1237 ret = add_string_to_list (token, ret);
1238 free (token);
1239 nw++;
1240
1241 if (sentinel >= ts && sentinel <= te)
1242 cw = nw;
1243
1244 /* If the cursor is at whitespace just before word start, set the
28ef6c31 1245 sentinel word to the current word. */
bb70624e
JA
1246 if (cwp && cw == -1 && sentinel == ts-1)
1247 cw = nw;
1248
1249 /* If the cursor is at whitespace between two words, make a new, empty
28ef6c31
JA
1250 word, add it before (well, after, since the list is in reverse order)
1251 the word we just added, and set the current word to that one. */
bb70624e 1252 if (cwp && cw == -1 && sentinel < ts)
28ef6c31
JA
1253 {
1254 tl = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
1255 tl->word = make_word ("");
1256 tl->next = ret->next;
1257 ret->next = tl;
1258 cw = nw;
1259 nw++;
1260 }
bb70624e
JA
1261
1262 if (string[te] == 0)
1263 break;
1264
28ef6c31 1265 i = te + member (string[te], d);
bb70624e
JA
1266 while (member (string[i], d) && whitespace(string[i]))
1267 i++;
1268
1269 if (string[i])
1270 ts = i;
1271 else
1272 break;
1273 }
1274
1275 /* Special case for SENTINEL at the end of STRING. If we haven't found
1276 the word containing SENTINEL yet, and the index we're looking for is at
1277 the end of STRING, add an additional null argument and set the current
1278 word pointer to that. */
1279 if (cwp && cw == -1 && sentinel >= slen)
1280 {
1281 if (whitespace (string[sentinel - 1]))
28ef6c31
JA
1282 {
1283 token = "";
1284 ret = add_string_to_list (token, ret);
1285 nw++;
1286 }
bb70624e
JA
1287 cw = nw;
1288 }
1289
1290 if (nwp)
1291 *nwp = nw;
1292 if (cwp)
1293 *cwp = cw;
1294
1295 return (REVERSE_LIST (ret, WORD_LIST *));
1296}
726f6388
JA
1297#endif /* READLINE */
1298
ccc6cda3
JA
1299#if 0
1300/* UNUSED */
726f6388
JA
1301/* Extract the name of the variable to bind to from the assignment string. */
1302char *
1303assignment_name (string)
1304 char *string;
1305{
ccc6cda3 1306 int offset;
726f6388
JA
1307 char *temp;
1308
ccc6cda3
JA
1309 offset = assignment (string);
1310 if (offset == 0)
726f6388 1311 return (char *)NULL;
bb70624e 1312 temp = substring (string, 0, offset);
726f6388
JA
1313 return (temp);
1314}
ccc6cda3 1315#endif
726f6388 1316
cce855bc
JA
1317/* **************************************************************** */
1318/* */
1319/* Functions to convert strings to WORD_LISTs and vice versa */
1320/* */
1321/* **************************************************************** */
1322
726f6388
JA
1323/* Return a single string of all the words in LIST. SEP is the separator
1324 to put between individual elements of LIST in the output string. */
1325static char *
1326string_list_internal (list, sep)
1327 WORD_LIST *list;
1328 char *sep;
1329{
1330 register WORD_LIST *t;
1331 char *result, *r;
1332 int word_len, sep_len, result_size;
1333
ccc6cda3 1334 if (list == 0)
726f6388
JA
1335 return ((char *)NULL);
1336
1337 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1338 sep_len = STRLEN (sep);
1339 result_size = 0;
1340
1341 for (t = list; t; t = t->next)
1342 {
1343 if (t != list)
1344 result_size += sep_len;
1345 result_size += strlen (t->word->word);
1346 }
1347
1348 r = result = xmalloc (result_size + 1);
1349
1350 for (t = list; t; t = t->next)
1351 {
1352 if (t != list && sep_len)
1353 {
ccc6cda3
JA
1354 if (sep_len > 1)
1355 {
1356 FASTCOPY (sep, r, sep_len);
1357 r += sep_len;
1358 }
1359 else
1360 *r++ = sep[0];
726f6388
JA
1361 }
1362
1363 word_len = strlen (t->word->word);
1364 FASTCOPY (t->word->word, r, word_len);
1365 r += word_len;
1366 }
1367
ccc6cda3 1368 *r = '\0';
726f6388
JA
1369 return (result);
1370}
1371
1372/* Return a single string of all the words present in LIST, separating
1373 each word with a space. */
1374char *
1375string_list (list)
1376 WORD_LIST *list;
1377{
1378 return (string_list_internal (list, " "));
1379}
1380
1381/* Return a single string of all the words present in LIST, obeying the
1382 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1383 expansion [of $*] appears within a double quoted string, it expands
1384 to a single field with the value of each parameter separated by the
1385 first character of the IFS variable, or by a <space> if IFS is unset." */
cce855bc 1386static char *
726f6388
JA
1387string_list_dollar_star (list)
1388 WORD_LIST *list;
1389{
ccc6cda3 1390 char *ifs, sep[2];
726f6388 1391
ccc6cda3 1392 ifs = get_string_value ("IFS");
726f6388 1393
cce855bc 1394 sep[0] = (ifs == 0) ? ' ' : *ifs;
726f6388
JA
1395 sep[1] = '\0';
1396
1397 return (string_list_internal (list, sep));
1398}
1399
cce855bc
JA
1400/* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
1401 is non-zero, the $@ appears within double quotes, and we should quote
1402 the list before converting it into a string. If IFS is unset, and the
1403 word is not quoted, we just need to quote CTLESC and CTLNUL characters
1404 in the words in the list, because the default value of $IFS is
1405 <space><tab><newline>, IFS characters in the words in the list should
1406 also be split. If IFS is null, and the word is not quoted, we need
1407 to quote the words in the list to preserve the positional parameters
1408 exactly. */
1409static char *
1410string_list_dollar_at (list, quoted)
1411 WORD_LIST *list;
1412 int quoted;
1413{
1414 char *ifs, sep[2];
1415 WORD_LIST *tlist;
1416
1417 ifs = get_string_value ("IFS");
1418
1419 sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
1420 sep[1] = '\0';
1421
1422 tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
1423 ? quote_list (list)
1424 : list_quote_escapes (list);
1425 return (string_list_internal (tlist, sep));
1426}
1427
726f6388
JA
1428/* Return the list of words present in STRING. Separate the string into
1429 words at any of the characters found in SEPARATORS. If QUOTED is
1430 non-zero then word in the list will have its quoted flag set, otherwise
1431 the quoted flag is left as make_word () deemed fit.
1432
1433 This obeys the P1003.2 word splitting semantics. If `separators' is
1434 exactly <space><tab><newline>, then the splitting algorithm is that of
1435 the Bourne shell, which treats any sequence of characters from `separators'
1436 as a delimiter. If IFS is unset, which results in `separators' being set
1437 to "", no splitting occurs. If separators has some other value, the
1438 following rules are applied (`IFS white space' means zero or more
1439 occurrences of <space>, <tab>, or <newline>, as long as those characters
1440 are in `separators'):
1441
1442 1) IFS white space is ignored at the start and the end of the
1443 string.
1444 2) Each occurrence of a character in `separators' that is not
1445 IFS white space, along with any adjacent occurrences of
1446 IFS white space delimits a field.
1447 3) Any nonzero-length sequence of IFS white space delimits a field.
1448 */
1449
1450/* BEWARE! list_string strips null arguments. Don't call it twice and
1451 expect to have "" preserved! */
1452
726f6388
JA
1453/* This performs word splitting and quoted null character removal on
1454 STRING. */
726f6388
JA
1455#define issep(c) (member ((c), separators))
1456
1457WORD_LIST *
1458list_string (string, separators, quoted)
1459 register char *string, *separators;
1460 int quoted;
1461{
ccc6cda3
JA
1462 WORD_LIST *result;
1463 WORD_DESC *t;
1464 char *current_word, *s;
28ef6c31 1465 int sindex, sh_style_split, whitesep;
726f6388
JA
1466
1467 if (!string || !*string)
1468 return ((WORD_LIST *)NULL);
1469
1470 sh_style_split =
1471 separators && *separators && (STREQ (separators, " \t\n"));
1472
1473 /* Remove sequences of whitespace at the beginning of STRING, as
1474 long as those characters appear in IFS. Do not do this if
1475 STRING is quoted or if there are no separator characters. */
1476 if (!quoted || !separators || !*separators)
1477 {
1478 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1479
1480 if (!*s)
1481 return ((WORD_LIST *)NULL);
1482
1483 string = s;
1484 }
1485
1486 /* OK, now STRING points to a word that does not begin with white space.
1487 The splitting algorithm is:
1488 extract a word, stopping at a separator
1489 skip sequences of spc, tab, or nl as long as they are separators
1490 This obeys the field splitting rules in Posix.2. */
ccc6cda3 1491 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
726f6388
JA
1492 {
1493 current_word = string_extract_verbatim (string, &sindex, separators);
ccc6cda3 1494 if (current_word == 0)
726f6388
JA
1495 break;
1496
1497 /* If we have a quoted empty string, add a quoted null argument. We
1498 want to preserve the quoted null character iff this is a quoted
1499 empty string; otherwise the quoted null characters are removed
1500 below. */
1501 if (QUOTED_NULL (current_word))
1502 {
ccc6cda3
JA
1503 t = make_bare_word ("");
1504 t->flags |= W_QUOTED;
726f6388
JA
1505 free (t->word);
1506 t->word = make_quoted_char ('\0');
1507 result = make_word_list (t, result);
1508 }
ccc6cda3 1509 else if (current_word[0] != '\0')
726f6388
JA
1510 {
1511 /* If we have something, then add it regardless. However,
1512 perform quoted null character removal on the current word. */
1513 remove_quoted_nulls (current_word);
cce855bc 1514 result = add_string_to_list (current_word, result);
ccc6cda3
JA
1515 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1516 result->word->flags |= W_QUOTED;
726f6388
JA
1517 }
1518
1519 /* If we're not doing sequences of separators in the traditional
1520 Bourne shell style, then add a quoted null argument. */
726f6388
JA
1521 else if (!sh_style_split && !spctabnl (string[sindex]))
1522 {
ccc6cda3
JA
1523 t = make_bare_word ("");
1524 t->flags |= W_QUOTED;
1525 free (t->word);
1526 t->word = make_quoted_char ('\0');
1527 result = make_word_list (t, result);
726f6388
JA
1528 }
1529
1530 free (current_word);
1531
28ef6c31
JA
1532 /* Note whether or not the separator is IFS whitespace, used later. */
1533 whitesep = string[sindex] && spctabnl (string[sindex]);
1534
726f6388
JA
1535 /* Move past the current separator character. */
1536 if (string[sindex])
1537 sindex++;
1538
1539 /* Now skip sequences of space, tab, or newline characters if they are
1540 in the list of separators. */
1541 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1542 sindex++;
28ef6c31
JA
1543
1544 /* If the first separator was IFS whitespace and the current character is
1545 a non-whitespace IFS character, it should be part of the current field
1546 delimiter, not a separate delimiter that would result in an empty field.
1547 Look at POSIX.2, 3.6.5, (3)(b). */
1548 if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
1549 sindex++;
726f6388
JA
1550 }
1551 return (REVERSE_LIST (result, WORD_LIST *));
1552}
1553
1554/* Parse a single word from STRING, using SEPARATORS to separate fields.
1555 ENDPTR is set to the first character after the word. This is used by
1556 the `read' builtin.
1557 XXX - this function is very similar to list_string; they should be
1558 combined - XXX */
1559char *
1560get_word_from_string (stringp, separators, endptr)
1561 char **stringp, *separators, **endptr;
1562{
1563 register char *s;
1564 char *current_word;
28ef6c31 1565 int sindex, sh_style_split, whitesep;
726f6388
JA
1566
1567 if (!stringp || !*stringp || !**stringp)
1568 return ((char *)NULL);
ccc6cda3 1569
726f6388
JA
1570 s = *stringp;
1571
1572 sh_style_split =
1573 separators && *separators && (STREQ (separators, " \t\n"));
1574
1575 /* Remove sequences of whitespace at the beginning of STRING, as
1576 long as those characters appear in IFS. */
1577 if (sh_style_split || !separators || !*separators)
1578 {
1579 for (; *s && spctabnl (*s) && issep (*s); s++);
1580
1581 /* If the string is nothing but whitespace, update it and return. */
1582 if (!*s)
1583 {
1584 *stringp = s;
1585 if (endptr)
1586 *endptr = s;
1587 return ((char *)NULL);
1588 }
1589 }
1590
1591 /* OK, S points to a word that does not begin with white space.
1592 Now extract a word, stopping at a separator, save a pointer to
1593 the first character after the word, then skip sequences of spc,
1594 tab, or nl as long as they are separators.
ccc6cda3 1595
726f6388
JA
1596 This obeys the field splitting rules in Posix.2. */
1597 sindex = 0;
1598 current_word = string_extract_verbatim (s, &sindex, separators);
1599
1600 /* Set ENDPTR to the first character after the end of the word. */
1601 if (endptr)
1602 *endptr = s + sindex;
1603
28ef6c31
JA
1604 /* Note whether or not the separator is IFS whitespace, used later. */
1605 whitesep = s[sindex] && spctabnl (s[sindex]);
1606
726f6388
JA
1607 /* Move past the current separator character. */
1608 if (s[sindex])
1609 sindex++;
1610
1611 /* Now skip sequences of space, tab, or newline characters if they are
1612 in the list of separators. */
1613 while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1614 sindex++;
1615
28ef6c31
JA
1616 /* If the first separator was IFS whitespace and the current character is
1617 a non-whitespace IFS character, it should be part of the current field
1618 delimiter, not a separate delimiter that would result in an empty field.
1619 Look at POSIX.2, 3.6.5, (3)(b). */
1620 if (s[sindex] && whitesep && issep (s[sindex]) && !spctabnl (s[sindex]))
1621 sindex++;
1622
726f6388
JA
1623 /* Update STRING to point to the next field. */
1624 *stringp = s + sindex;
1625 return (current_word);
1626}
1627
1628/* Remove IFS white space at the end of STRING. Start at the end
1629 of the string and walk backwards until the beginning of the string
1630 or we find a character that's not IFS white space and not CTLESC.
1631 Only let CTLESC escape a white space character if SAW_ESCAPE is
1632 non-zero. */
1633char *
1634strip_trailing_ifs_whitespace (string, separators, saw_escape)
1635 char *string, *separators;
1636 int saw_escape;
1637{
1638 char *s;
ccc6cda3 1639
726f6388
JA
1640 s = string + STRLEN (string) - 1;
1641 while (s > string && ((spctabnl (*s) && issep (*s)) ||
1642 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1643 s--;
1644 *++s = '\0';
1645 return string;
1646}
1647
bb70624e
JA
1648#if 0
1649/* UNUSED */
1650/* Split STRING into words at whitespace. Obeys shell-style quoting with
1651 backslashes, single and double quotes. */
ccc6cda3
JA
1652WORD_LIST *
1653list_string_with_quotes (string)
1654 char *string;
1655{
1656 WORD_LIST *list;
1657 char *token, *s;
1658 int c, i, tokstart, len;
1659
1660 for (s = string; s && *s && spctabnl (*s); s++)
1661 ;
1662 if (s == 0 || *s == 0)
1663 return ((WORD_LIST *)NULL);
1664
1665 tokstart = i = 0;
1666 list = (WORD_LIST *)NULL;
1667 while (1)
1668 {
1669 c = s[i];
1670 if (c == '\\')
1671 {
1672 i++;
1673 if (s[i])
1674 i++;
1675 }
1676 else if (c == '\'')
28ef6c31 1677 i = skip_single_quoted (s, ++i);
ccc6cda3
JA
1678 else if (c == '"')
1679 i = skip_double_quoted (s, ++i);
1680 else if (c == 0 || spctabnl (c))
1681 {
1682 /* We have found the end of a token. Make a word out of it and
1683 add it to the word list. */
bb70624e 1684 token = substring (s, tokstart, i);
cce855bc 1685 list = add_string_to_list (token, list);
ccc6cda3
JA
1686 free (token);
1687 while (spctabnl (s[i]))
1688 i++;
1689 if (s[i])
1690 tokstart = i;
1691 else
1692 break;
1693 }
1694 else
1695 i++; /* normal character */
1696 }
1697 return (REVERSE_LIST (list, WORD_LIST *));
1698}
bb70624e 1699#endif
d166f048 1700
cce855bc
JA
1701/********************************************************/
1702/* */
1703/* Functions to perform assignment statements */
1704/* */
1705/********************************************************/
d166f048 1706
ccc6cda3
JA
1707#if defined (ARRAY_VARS)
1708SHELL_VAR *
1709do_array_element_assignment (name, value)
1710 char *name, *value;
1711{
1712 char *t;
1713 int ind, ni;
1714 SHELL_VAR *entry;
1715
1716 t = strchr (name, '[');
1717 if (t == 0)
1718 return ((SHELL_VAR *)NULL);
1719 ind = t - name;
1720 ni = skipsubscript (name, ind);
1721 if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= ind + 1))
1722 {
1723 report_error ("%s: bad array subscript", name);
1724 return ((SHELL_VAR *)NULL);
1725 }
1726 *t++ = '\0';
1727 ind = array_expand_index (t, ni - ind);
1728 if (ind < 0)
1729 {
28ef6c31 1730 t[-1] = '['; /* restore original name ] */
ccc6cda3
JA
1731 report_error ("%s: bad array subscript", name);
1732 return ((SHELL_VAR *)NULL);
1733 }
1734 entry = bind_array_variable (name, ind, value);
28ef6c31 1735 t[-1] = '['; /* restore original name ] */
ccc6cda3
JA
1736 return (entry);
1737}
1738#endif /* ARRAY_VARS */
1739
726f6388
JA
1740/* Given STRING, an assignment string, get the value of the right side
1741 of the `=', and bind it to the left side. If EXPAND is true, then
1742 perform parameter expansion, command substitution, and arithmetic
1743 expansion on the right-hand side. Perform tilde expansion in any
1744 case. Do not perform word splitting on the result of expansion. */
1745static int
1746do_assignment_internal (string, expand)
1747 char *string;
1748 int expand;
1749{
ccc6cda3
JA
1750 int offset;
1751 char *name, *value;
1752 SHELL_VAR *entry;
1753#if defined (ARRAY_VARS)
1754 char *t;
1755 int ni, assign_list = 0;
1756#endif
1757
1758 offset = assignment (string);
1759 name = savestring (string);
1760 value = (char *)NULL;
726f6388
JA
1761
1762 if (name[offset] == '=')
1763 {
1764 char *temp;
1765
1766 name[offset] = 0;
1767 temp = name + offset + 1;
1768
ccc6cda3 1769#if defined (ARRAY_VARS)
cce855bc 1770 if (expand && temp[0] == LPAREN && strchr (temp, RPAREN))
726f6388 1771 {
ccc6cda3
JA
1772 assign_list = ni = 1;
1773 value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")");
1774 }
1775 else
1776#endif
1777
1778 /* Perform tilde expansion. */
1779 if (expand && temp[0])
28ef6c31 1780 {
ccc6cda3
JA
1781 temp = (strchr (temp, '~') && unquoted_member ('~', temp))
1782 ? bash_tilde_expand (temp)
1783 : savestring (temp);
726f6388
JA
1784
1785 value = maybe_expand_string (temp, 0, expand_string_unsplit);
1786 free (temp);
1787 }
1788 else
1789 value = savestring (temp);
1790 }
1791
1792 if (value == 0)
d166f048
JA
1793 {
1794 value = xmalloc (1);
1795 value[0] = '\0';
1796 }
726f6388 1797
726f6388 1798 if (echo_command_at_execute)
ccc6cda3
JA
1799#if defined (ARRAY_VARS)
1800 if (assign_list)
1801 fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
1802 else
1803#endif
726f6388
JA
1804 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1805
d166f048 1806#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
ccc6cda3
JA
1807
1808#if defined (ARRAY_VARS)
28ef6c31 1809 if (t = strchr (name, '[')) /*]*/
ccc6cda3
JA
1810 {
1811 if (assign_list)
1812 {
1813 report_error ("%s: cannot assign list to array member", name);
1814 ASSIGN_RETURN (0);
1815 }
1816 entry = do_array_element_assignment (name, value);
1817 if (entry == 0)
28ef6c31 1818 ASSIGN_RETURN (0);
ccc6cda3
JA
1819 }
1820 else if (assign_list)
1821 entry = assign_array_from_string (name, value);
1822 else
1823#endif /* ARRAY_VARS */
1824 entry = bind_variable (name, value);
1825
726f6388
JA
1826 stupidly_hack_special_variables (name);
1827
1828 if (entry)
bb70624e 1829 VUNSETATTR (entry, att_invisible);
726f6388 1830
726f6388 1831 /* Return 1 if the assignment seems to have been performed correctly. */
28ef6c31 1832 ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
726f6388
JA
1833}
1834
1835/* Perform the assignment statement in STRING, and expand the
1836 right side by doing command and parameter expansion. */
ccc6cda3 1837int
726f6388
JA
1838do_assignment (string)
1839 char *string;
1840{
1841 return do_assignment_internal (string, 1);
1842}
1843
1844/* Given STRING, an assignment string, get the value of the right side
1845 of the `=', and bind it to the left side. Do not do command and
1846 parameter substitution on the right hand side. */
ccc6cda3 1847int
726f6388
JA
1848do_assignment_no_expand (string)
1849 char *string;
1850{
1851 return do_assignment_internal (string, 0);
1852}
1853
cce855bc
JA
1854/***************************************************
1855 * *
1856 * Functions to manage the positional parameters *
1857 * *
1858 ***************************************************/
726f6388
JA
1859
1860/* Return the word list that corresponds to `$*'. */
1861WORD_LIST *
1862list_rest_of_args ()
1863{
ccc6cda3 1864 register WORD_LIST *list, *args;
726f6388
JA
1865 int i;
1866
1867 /* Break out of the loop as soon as one of the dollar variables is null. */
ccc6cda3
JA
1868 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
1869 list = make_word_list (make_bare_word (dollar_vars[i]), list);
1870
1871 for (args = rest_of_args; args; args = args->next)
1872 list = make_word_list (make_bare_word (args->word->word), list);
726f6388 1873
726f6388
JA
1874 return (REVERSE_LIST (list, WORD_LIST *));
1875}
1876
ccc6cda3
JA
1877int
1878number_of_args ()
1879{
1880 register WORD_LIST *list;
1881 int n;
1882
1883 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
1884 ;
1885 for (list = rest_of_args; list; list = list->next)
1886 n++;
1887 return n;
1888}
1889
cce855bc
JA
1890/* Return the value of a positional parameter. This handles values > 10. */
1891char *
1892get_dollar_var_value (ind)
1893 int ind;
1894{
1895 char *temp;
1896 WORD_LIST *p;
1897
1898 if (ind < 10)
1899 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
1900 else /* We want something like ${11} */
1901 {
1902 ind -= 10;
1903 for (p = rest_of_args; p && ind--; p = p->next)
28ef6c31 1904 ;
cce855bc
JA
1905 temp = p ? savestring (p->word->word) : (char *)NULL;
1906 }
1907 return (temp);
1908}
1909
726f6388
JA
1910/* Make a single large string out of the dollar digit variables,
1911 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
1912 case of "$*" with respect to IFS. */
1913char *
1914string_rest_of_args (dollar_star)
1915 int dollar_star;
1916{
ccc6cda3 1917 register WORD_LIST *list;
726f6388
JA
1918 char *string;
1919
ccc6cda3 1920 list = list_rest_of_args ();
726f6388
JA
1921 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1922 dispose_words (list);
1923 return (string);
1924}
1925
cce855bc
JA
1926/* Return a string containing the positional parameters from START to
1927 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
1928 which only makes a difference if QUOTED is non-zero. */
1929static char *
1930pos_params (string, start, end, quoted)
1931 char *string;
1932 int start, end, quoted;
726f6388 1933{
cce855bc
JA
1934 WORD_LIST *save, *params, *h, *t;
1935 char *ret;
1936 int i;
726f6388 1937
bb70624e
JA
1938 /* see if we can short-circuit. if start == end, we want 0 parameters. */
1939 if (start == end)
1940 return ((char *)NULL);
1941
cce855bc
JA
1942 save = params = list_rest_of_args ();
1943 if (save == 0)
1944 return ((char *)NULL);
1945
1946 for (i = 1; params && i < start; i++)
1947 params = params->next;
1948 if (params == 0)
1949 return ((char *)NULL);
1950 for (h = t = params; params && i < end; i++)
d166f048 1951 {
cce855bc
JA
1952 t = params;
1953 params = params->next;
d166f048 1954 }
726f6388 1955
cce855bc
JA
1956 t->next = (WORD_LIST *)NULL;
1957 if (string[0] == '*')
1958 ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h);
1959 else
1960 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
bb70624e
JA
1961 if (t != params)
1962 t->next = params;
726f6388 1963
cce855bc
JA
1964 dispose_words (save);
1965 return (ret);
1966}
1967
1968/******************************************************************/
1969/* */
1970/* Functions to expand strings to strings or WORD_LISTs */
1971/* */
1972/******************************************************************/
1973
1974#if defined (PROCESS_SUBSTITUTION)
1975#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1976#else
1977#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1978#endif
1979
1980/* If there are any characters in STRING that require full expansion,
1981 then call FUNC to expand STRING; otherwise just perform quote
1982 removal if necessary. This returns a new string. */
1983static char *
1984maybe_expand_string (string, quoted, func)
1985 char *string;
1986 int quoted;
1987 WORD_LIST *(*func)();
1988{
1989 WORD_LIST *list;
1990 int i, saw_quote;
1991 char *ret;
1992
1993 for (i = saw_quote = 0; string[i]; i++)
1994 {
1995 if (EXP_CHAR (string[i]))
1996 break;
1997 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1998 saw_quote = 1;
1999 }
2000
2001 if (string[i])
2002 {
2003 list = (*func) (string, quoted);
2004 if (list)
2005 {
2006 ret = string_list (list);
2007 dispose_words (list);
2008 }
2009 else
2010 ret = (char *)NULL;
2011 }
2012 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
2013 ret = string_quote_removal (string, quoted);
2014 else
2015 ret = savestring (string);
2016 return ret;
2017}
2018
2019static inline char *
2020expand_string_to_string (string, quoted, func)
2021 char *string;
2022 int quoted;
2023 WORD_LIST *(*func)();
2024{
2025 WORD_LIST *list;
2026 char *ret;
2027
2028 if (string == 0 || *string == '\0')
2029 return ((char *)NULL);
2030
2031 list = (*func) (string, quoted);
2032 if (list)
2033 {
2034 ret = string_list (list);
2035 dispose_words (list);
2036 }
2037 else
2038 ret = (char *)NULL;
2039
2040 return (ret);
2041}
2042
2043#if defined (COND_COMMAND)
2044/* Just remove backslashes in STRING. Returns a new string. */
2045char *
2046remove_backslashes (string)
2047 char *string;
2048{
2049 char *r, *ret, *s;
2050
2051 r = ret = xmalloc (strlen (string) + 1);
2052 for (s = string; s && *s; )
2053 {
2054 if (*s == '\\')
28ef6c31 2055 s++;
cce855bc 2056 if (*s == 0)
28ef6c31 2057 break;
cce855bc
JA
2058 *r++ = *s++;
2059 }
2060 *r = '\0';
2061 return ret;
2062}
2063
2064/* This needs better error handling. */
2065/* Expand W for use as an argument to a unary or binary operator in a
2066 [[...]] expression. If SPECIAL is nonzero, this is the rhs argument
2067 to the != or == operator, and should be treated as a pattern. In
2068 this case, we quote the string specially for the globbing code. The
2069 caller is responsible for removing the backslashes if the unquoted
2070 words is needed later. */
2071char *
2072cond_expand_word (w, special)
2073 WORD_DESC *w;
2074 int special;
2075{
2076 char *r, *p;
2077 WORD_LIST *l;
2078
2079 if (w->word == 0 || w->word[0] == '\0')
2080 return ((char *)NULL);
2081
28ef6c31
JA
2082 if (strchr (w->word, '~') && unquoted_member ('~', w->word))
2083 {
2084 p = bash_tilde_expand (w->word);
2085 free (w->word);
2086 w->word = p;
2087 }
2088
b72432fd 2089 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
cce855bc
JA
2090 if (l)
2091 {
2092 if (special == 0)
2093 {
2094 dequote_list (l);
2095 r = string_list (l);
2096 }
2097 else
28ef6c31
JA
2098 {
2099 p = string_list (l);
2100 r = quote_string_for_globbing (p, QGLOB_CVTNULL);
2101 free (p);
2102 }
cce855bc
JA
2103 dispose_words (l);
2104 }
2105 else
2106 r = (char *)NULL;
2107
2108 return r;
2109}
2110#endif
2111
2112/* Call expand_word_internal to expand W and handle error returns.
2113 A convenience function for functions that don't want to handle
2114 any errors or free any memory before aborting. */
2115static WORD_LIST *
b72432fd 2116call_expand_word_internal (w, q, i, c, e)
cce855bc 2117 WORD_DESC *w;
b72432fd 2118 int q, i, *c, *e;
cce855bc
JA
2119{
2120 WORD_LIST *result;
2121
b72432fd 2122 result = expand_word_internal (w, q, i, c, e);
bb70624e 2123 if (result == &expand_word_error || result == &expand_word_fatal)
cce855bc 2124 {
28ef6c31 2125 expand_no_split_dollar_star = 0; /* XXX */
cce855bc 2126 /* By convention, each time this error is returned, w->word has
bb70624e
JA
2127 already been freed (it sometimes may not be in the fatal case,
2128 but that doesn't result in a memory leak because we're going
2129 to exit in most cases). */
cce855bc 2130 w->word = (char *)NULL;
28ef6c31 2131 last_command_exit_value = EXECUTION_FAILURE;
bb70624e 2132 jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
cce855bc
JA
2133 /* NOTREACHED */
2134 }
cce855bc
JA
2135 else
2136 return (result);
2137}
2138
2139/* Perform parameter expansion, command substitution, and arithmetic
2140 expansion on STRING, as if it were a word. Leave the result quoted. */
2141static WORD_LIST *
2142expand_string_internal (string, quoted)
2143 char *string;
2144 int quoted;
2145{
2146 WORD_DESC td;
2147 WORD_LIST *tresult;
2148
2149 if (string == 0 || *string == 0)
2150 return ((WORD_LIST *)NULL);
2151
28ef6c31
JA
2152 td.flags = 0;
2153 td.word = savestring (string);
2154
b72432fd 2155 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
28ef6c31
JA
2156
2157 FREE (td.word);
cce855bc 2158 return (tresult);
726f6388
JA
2159}
2160
2161/* Expand STRING by performing parameter expansion, command substitution,
2162 and arithmetic expansion. Dequote the resulting WORD_LIST before
2163 returning it, but do not perform word splitting. The call to
2164 remove_quoted_nulls () is in here because word splitting normally
2165 takes care of quote removal. */
2166WORD_LIST *
2167expand_string_unsplit (string, quoted)
2168 char *string;
2169 int quoted;
2170{
2171 WORD_LIST *value;
2172
28ef6c31 2173 if (string == 0 || *string == '\0')
726f6388
JA
2174 return ((WORD_LIST *)NULL);
2175
28ef6c31 2176 expand_no_split_dollar_star = 1;
726f6388 2177 value = expand_string_internal (string, quoted);
28ef6c31
JA
2178 expand_no_split_dollar_star = 0;
2179
726f6388
JA
2180 if (value)
2181 {
2182 if (value->word)
2183 remove_quoted_nulls (value->word->word);
2184 dequote_list (value);
2185 }
2186 return (value);
2187}
2188
bb70624e
JA
2189
2190/* Expand one of the PS? prompt strings. This is a sort of combination of
2191 expand_string_unsplit and expand_string_internal, but returns the
2192 passed string when an error occurs. Might want to trap other calls
2193 to jump_to_top_level here so we don't endlessly loop. */
2194WORD_LIST *
2195expand_prompt_string (string, quoted)
2196 char *string;
2197 int quoted;
2198{
2199 WORD_LIST *value;
2200 WORD_DESC td;
2201
2202 if (string == 0 || *string == 0)
2203 return ((WORD_LIST *)NULL);
2204
28ef6c31 2205 td.flags = 0;
bb70624e 2206 td.word = savestring (string);
28ef6c31
JA
2207
2208 no_longjmp_on_fatal_error = 1;
bb70624e 2209 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
28ef6c31
JA
2210 no_longjmp_on_fatal_error = 0;
2211
bb70624e
JA
2212 if (value == &expand_word_error || value == &expand_word_fatal)
2213 {
2214 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
2215 return value;
2216 }
2217 FREE (td.word);
2218 if (value)
2219 {
2220 if (value->word)
2221 remove_quoted_nulls (value->word->word);
2222 dequote_list (value);
2223 }
2224 return (value);
2225}
2226
726f6388
JA
2227/* Expand STRING just as if you were expanding a word, but do not dequote
2228 the resultant WORD_LIST. This is called only from within this file,
2229 and is used to correctly preserve quoted characters when expanding
2230 things like ${1+"$@"}. This does parameter expansion, command
b72432fd 2231 substitution, arithmetic expansion, and word splitting. */
726f6388
JA
2232static WORD_LIST *
2233expand_string_leave_quoted (string, quoted)
2234 char *string;
2235 int quoted;
2236{
2237 WORD_LIST *tlist;
2238 WORD_LIST *tresult;
2239
ccc6cda3 2240 if (string == 0 || *string == '\0')
726f6388
JA
2241 return ((WORD_LIST *)NULL);
2242
2243 tlist = expand_string_internal (string, quoted);
2244
2245 if (tlist)
2246 {
2247 tresult = word_list_split (tlist);
2248 dispose_words (tlist);
2249 return (tresult);
2250 }
2251 return ((WORD_LIST *)NULL);
2252}
2253
ccc6cda3
JA
2254/* This does not perform word splitting or dequote the WORD_LIST
2255 it returns. */
2256static WORD_LIST *
2257expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
2258 char *string;
2259 int quoted, *dollar_at_p, *has_dollar_at;
2260{
2261 WORD_DESC td;
2262 WORD_LIST *tresult;
2263
2264 if (string == 0 || *string == '\0')
2265 return (WORD_LIST *)NULL;
2266
28ef6c31 2267 td.flags = 0;
ccc6cda3 2268 td.word = string;
b72432fd 2269 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
ccc6cda3
JA
2270 return (tresult);
2271}
2272
726f6388
JA
2273/* Expand STRING just as if you were expanding a word. This also returns
2274 a list of words. Note that filename globbing is *NOT* done for word
2275 or string expansion, just when the shell is expanding a command. This
2276 does parameter expansion, command substitution, arithmetic expansion,
2277 and word splitting. Dequote the resultant WORD_LIST before returning. */
2278WORD_LIST *
2279expand_string (string, quoted)
2280 char *string;
2281 int quoted;
2282{
2283 WORD_LIST *result;
2284
28ef6c31 2285 if (string == 0 || *string == '\0')
726f6388
JA
2286 return ((WORD_LIST *)NULL);
2287
2288 result = expand_string_leave_quoted (string, quoted);
ccc6cda3 2289 return (result ? dequote_list (result) : result);
726f6388
JA
2290}
2291
2292/***************************************************
2293 * *
2294 * Functions to handle quoting chars *
2295 * *
2296 ***************************************************/
2297
cce855bc
JA
2298/* Conventions:
2299
2300 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
2301 The parser passes CTLNUL as CTLESC CTLNUL. */
2302
2303/* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2304 This is necessary to make unquoted CTLESC and CTLNUL characters in the
2305 data stream pass through properly.
2306 Here we remove doubled CTLESC characters inside quoted strings before
2307 quoting the entire string, so we do not double the number of CTLESC
2308 characters. */
2309static char *
2310remove_quoted_escapes (string)
2311 char *string;
2312{
2313 register char *s;
2314 int docopy;
2315 char *t, *t1;
2316
2317 if (string == NULL)
2318 return (string);
2319
2320 t1 = t = xmalloc (strlen (string) + 1);
2321 for (docopy = 0, s = string; *s; s++, t1++)
2322 {
2323 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2324 {
2325 s++;
2326 docopy = 1;
2327 }
2328 *t1 = *s;
2329 }
2330 *t1 = '\0';
2331 if (docopy)
2332 strcpy (string, t);
2333 free (t);
2334 return (string);
2335}
2336
2337/* Quote escape characters in string s, but no other characters. This is
2338 used to protect CTLESC and CTLNUL in variable values from the rest of
2339 the word expansion process after the variable is expanded. */
2340static char *
2341quote_escapes (string)
2342 char *string;
2343{
2344 register char *s, *t;
2345 char *result;
2346
2347 result = xmalloc ((strlen (string) * 2) + 1);
2348 for (s = string, t = result; *s; )
2349 {
2350 if (*s == CTLESC || *s == CTLNUL)
2351 *t++ = CTLESC;
2352 *t++ = *s++;
2353 }
2354 *t = '\0';
2355 return (result);
2356}
2357
2358static WORD_LIST *
2359list_quote_escapes (list)
2360 WORD_LIST *list;
2361{
2362 register WORD_LIST *w;
2363 char *t;
2364
2365 for (w = list; w; w = w->next)
2366 {
2367 t = w->word->word;
2368 w->word->word = quote_escapes (t);
2369 free (t);
2370 }
2371 return list;
2372}
2373
bb70624e
JA
2374#if 0
2375/* UNUSED */
cce855bc
JA
2376static char *
2377dequote_escapes (string)
2378 char *string;
2379{
2380 register char *s, *t;
2381 char *result;
2382
2383 result = xmalloc (strlen (string) + 1);
2384 for (s = string, t = result; *s; )
2385 {
2386 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2387 {
2388 s++;
2389 if (*s == '\0')
2390 break;
2391 }
2392 *t++ = *s++;
2393 }
2394 *t = '\0';
2395 return result;
2396}
2397#endif
2398
ccc6cda3 2399static WORD_LIST *
726f6388 2400dequote_list (list)
ccc6cda3 2401 WORD_LIST *list;
726f6388
JA
2402{
2403 register char *s;
ccc6cda3 2404 register WORD_LIST *tlist;
726f6388 2405
ccc6cda3 2406 for (tlist = list; tlist; tlist = tlist->next)
726f6388 2407 {
ccc6cda3
JA
2408 s = dequote_string (tlist->word->word);
2409 free (tlist->word->word);
2410 tlist->word->word = s;
726f6388 2411 }
ccc6cda3 2412 return list;
726f6388
JA
2413}
2414
bb70624e 2415/* Return a new string with the quoted representation of character C. */
726f6388
JA
2416static char *
2417make_quoted_char (c)
2418 int c;
2419{
2420 char *temp;
2421
2422 temp = xmalloc (3);
2423 if (c == 0)
2424 {
2425 temp[0] = CTLNUL;
2426 temp[1] = '\0';
2427 }
2428 else
2429 {
2430 temp[0] = CTLESC;
2431 temp[1] = c;
2432 temp[2] = '\0';
2433 }
2434 return (temp);
2435}
2436
2437/* Quote STRING. Return a new string. */
ccc6cda3 2438char *
726f6388
JA
2439quote_string (string)
2440 char *string;
2441{
ccc6cda3 2442 register char *t;
726f6388
JA
2443 char *result;
2444
ccc6cda3 2445 if (*string == 0)
726f6388
JA
2446 {
2447 result = xmalloc (2);
2448 result[0] = CTLNUL;
2449 result[1] = '\0';
2450 }
2451 else
2452 {
726f6388
JA
2453 result = xmalloc ((strlen (string) * 2) + 1);
2454
ccc6cda3 2455 for (t = result; *string; )
726f6388
JA
2456 {
2457 *t++ = CTLESC;
2458 *t++ = *string++;
2459 }
2460 *t = '\0';
2461 }
2462 return (result);
2463}
2464
2465/* De-quoted quoted characters in STRING. */
2466char *
2467dequote_string (string)
2468 char *string;
2469{
2470 register char *t;
2471 char *result;
2472
2473 result = xmalloc (strlen (string) + 1);
2474
2475 if (QUOTED_NULL (string))
2476 {
2477 result[0] = '\0';
2478 return (result);
2479 }
2480
2481 /* If no character in the string can be quoted, don't bother examining
2482 each character. Just return a copy of the string passed to us. */
2483 if (strchr (string, CTLESC) == NULL) /* XXX */
2484 { /* XXX */
2485 strcpy (result, string); /* XXX */
2486 return (result); /* XXX */
2487 }
2488
ccc6cda3 2489 for (t = result; *string; string++, t++)
726f6388
JA
2490 {
2491 if (*string == CTLESC)
2492 {
2493 string++;
2494
2495 if (!*string)
2496 break;
2497 }
2498
ccc6cda3 2499 *t = *string;
726f6388
JA
2500 }
2501
2502 *t = '\0';
2503 return (result);
2504}
2505
2506/* Quote the entire WORD_LIST list. */
ccc6cda3 2507static WORD_LIST *
726f6388
JA
2508quote_list (list)
2509 WORD_LIST *list;
2510{
2511 register WORD_LIST *w;
ccc6cda3 2512 char *t;
726f6388
JA
2513
2514 for (w = list; w; w = w->next)
2515 {
ccc6cda3 2516 t = w->word->word;
726f6388
JA
2517 w->word->word = quote_string (t);
2518 free (t);
ccc6cda3 2519 w->word->flags |= W_QUOTED;
726f6388 2520 }
ccc6cda3 2521 return list;
726f6388
JA
2522}
2523
cce855bc
JA
2524/* Perform quoted null character removal on STRING. We don't allow any
2525 quoted null characters in the middle or at the ends of strings because
2526 of how expand_word_internal works. remove_quoted_nulls () turns
2527 STRING into an empty string iff it only consists of a quoted null,
2528 and removes all unquoted CTLNUL characters. */
2529/*
2530#define remove_quoted_nulls(string) \
2531 do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
2532*/
2533static void
2534remove_quoted_nulls (string)
2535 char *string;
2536{
2537 char *nstr, *s, *p;
2538
2539 nstr = savestring (string);
2540 nstr[0] = '\0';
2541 for (p = nstr, s = string; *s; s++)
2542 {
2543 if (*s == CTLESC)
2544 {
2545 *p++ = *s++; /* CTLESC */
2546 if (*s == 0)
2547 break;
2548 *p++ = *s; /* quoted char */
2549 continue;
2550 }
2551 if (*s == CTLNUL)
28ef6c31 2552 continue;
cce855bc
JA
2553 *p++ = *s;
2554 }
2555 *p = '\0';
2556 strcpy (string, nstr);
2557 free (nstr);
2558}
2559
2560/* Perform quoted null character removal on each element of LIST.
2561 This modifies LIST. */
2562void
2563word_list_remove_quoted_nulls (list)
2564 WORD_LIST *list;
2565{
2566 register WORD_LIST *t;
2567
2568 for (t = list; t; t = t->next)
2569 remove_quoted_nulls (t->word->word);
2570}
2571
2572/* **************************************************************** */
2573/* */
2574/* Functions for Matching and Removing Patterns */
2575/* */
2576/* **************************************************************** */
2577
2578/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
2579 can have one of 4 values:
2580 RP_LONG_LEFT remove longest matching portion at start of PARAM
726f6388
JA
2581 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
2582 RP_LONG_RIGHT remove longest matching portion at end of PARAM
2583 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
2584*/
2585
2586#define RP_LONG_LEFT 1
2587#define RP_SHORT_LEFT 2
2588#define RP_LONG_RIGHT 3
2589#define RP_SHORT_RIGHT 4
2590
2591static char *
2592remove_pattern (param, pattern, op)
2593 char *param, *pattern;
2594 int op;
2595{
ccc6cda3
JA
2596 register int len;
2597 register char *end;
726f6388
JA
2598 register char *p, *ret, c;
2599
ccc6cda3
JA
2600 if (param == NULL || *param == '\0')
2601 return (param);
726f6388
JA
2602 if (pattern == NULL || *pattern == '\0') /* minor optimization */
2603 return (savestring (param));
2604
ccc6cda3
JA
2605 len = STRLEN (param);
2606 end = param + len;
726f6388
JA
2607
2608 switch (op)
2609 {
2610 case RP_LONG_LEFT: /* remove longest match at start */
2611 for (p = end; p >= param; p--)
2612 {
2613 c = *p; *p = '\0';
cce855bc 2614 if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
726f6388
JA
2615 {
2616 *p = c;
2617 return (savestring (p));
2618 }
2619 *p = c;
2620 }
2621 break;
2622
2623 case RP_SHORT_LEFT: /* remove shortest match at start */
2624 for (p = param; p <= end; p++)
2625 {
2626 c = *p; *p = '\0';
cce855bc 2627 if (fnmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
726f6388
JA
2628 {
2629 *p = c;
2630 return (savestring (p));
2631 }
2632 *p = c;
2633 }
2634 break;
2635
ccc6cda3
JA
2636 case RP_LONG_RIGHT: /* remove longest match at end */
2637 for (p = param; p <= end; p++)
2638 {
cce855bc 2639 if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
ccc6cda3
JA
2640 {
2641 c = *p; *p = '\0';
2642 ret = savestring (param);
2643 *p = c;
2644 return (ret);
2645 }
2646 }
2647 break;
2648
2649 case RP_SHORT_RIGHT: /* remove shortest match at end */
2650 for (p = end; p >= param; p--)
2651 {
cce855bc 2652 if (fnmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
ccc6cda3
JA
2653 {
2654 c = *p; *p = '\0';
2655 ret = savestring (param);
2656 *p = c;
2657 return (ret);
2658 }
2659 }
2660 break;
2661 }
2662 return (savestring (param)); /* no match, return original string */
2663}
2664
2665/* Return 1 of the first character of STRING could match the first
2666 character of pattern PAT. Used to avoid n2 calls to fnmatch(). */
2667static int
2668match_pattern_char (pat, string)
2669 char *pat, *string;
2670{
d166f048 2671 char c;
ccc6cda3
JA
2672
2673 if (*string == 0)
2674 return (0);
2675
2676 switch (c = *pat++)
2677 {
2678 default:
2679 return (*string == c);
2680 case '\\':
2681 return (*string == *pat);
2682 case '?':
28ef6c31 2683 return (*pat == LPAREN ? 1 : (*string != '\0'));
ccc6cda3
JA
2684 case '*':
2685 return (1);
cce855bc
JA
2686 case '+':
2687 case '!':
2688 case '@':
28ef6c31 2689 return (*pat == LPAREN ? 1 : (*string == c));
ccc6cda3 2690 case '[':
d166f048 2691 return (*string != '\0');
ccc6cda3
JA
2692 }
2693}
2694
2695/* Match PAT anywhere in STRING and return the match boundaries.
2696 This returns 1 in case of a successful match, 0 otherwise. SP
2697 and EP are pointers into the string where the match begins and
2698 ends, respectively. MTYPE controls what kind of match is attempted.
2699 MATCH_BEG and MATCH_END anchor the match at the beginning and end
2700 of the string, respectively. The longest match is returned. */
2701static int
2702match_pattern (string, pat, mtype, sp, ep)
2703 char *string, *pat;
2704 int mtype;
2705 char **sp, **ep;
2706{
2707 int c;
2708 register char *p, *p1;
2709 char *end;
2710
2711 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
2712 return (0);
2713
2714 end = string + STRLEN (string);
2715
2716 switch (mtype)
2717 {
2718 case MATCH_ANY:
2719 for (p = string; p <= end; p++)
2720 {
2721 if (match_pattern_char (pat, p))
2722 {
2723 for (p1 = end; p1 >= p; p1--)
2724 {
2725 c = *p1; *p1 = '\0';
cce855bc 2726 if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0)
ccc6cda3
JA
2727 {
2728 *p1 = c;
2729 *sp = p;
2730 *ep = p1;
2731 return 1;
2732 }
2733 *p1 = c;
2734 }
2735 }
2736 }
2737 return (0);
2738
2739 case MATCH_BEG:
2740 if (match_pattern_char (pat, string) == 0)
28ef6c31 2741 return (0);
ccc6cda3
JA
2742 for (p = end; p >= string; p--)
2743 {
2744 c = *p; *p = '\0';
cce855bc 2745 if (fnmatch (pat, string, FNMATCH_EXTFLAG) == 0)
ccc6cda3
JA
2746 {
2747 *p = c;
2748 *sp = string;
2749 *ep = p;
2750 return 1;
2751 }
2752 *p = c;
2753 }
2754 return (0);
726f6388 2755
ccc6cda3
JA
2756 case MATCH_END:
2757 for (p = string; p <= end; p++)
cce855bc 2758 if (fnmatch (pat, p, FNMATCH_EXTFLAG) == 0)
726f6388 2759 {
ccc6cda3
JA
2760 *sp = p;
2761 *ep = end;
2762 return 1;
726f6388 2763 }
ccc6cda3 2764 return (0);
726f6388 2765 }
ccc6cda3
JA
2766
2767 return (0);
726f6388
JA
2768}
2769
cce855bc
JA
2770static int
2771getpatspec (c, value)
2772 int c;
2773 char *value;
2774{
2775 if (c == '#')
2776 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
2777 else /* c == '%' */
2778 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
2779}
2780
2781/* Posix.2 says that the WORD should be run through tilde expansion,
2782 parameter expansion, command substitution and arithmetic expansion.
2783 This leaves the result quoted, so quote_string_for_globbing () has
2784 to be called to fix it up for fnmatch (). If QUOTED is non-zero,
2785 it means that the entire expression was enclosed in double quotes.
2786 This means that quoting characters in the pattern do not make any
2787 special pattern characters quoted. For example, the `*' in the
2788 following retains its special meaning: "${foo#'*'}". */
2789static char *
2790getpattern (value, quoted, expandpat)
2791 char *value;
2792 int quoted, expandpat;
2793{
2794 char *pat, *tword;
2795 WORD_LIST *l;
2796 int i;
2797
2798 tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value);
2799
2800 /* expand_string_internal () leaves WORD quoted and does not perform
2801 word splitting. */
2802 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
2803 {
2804 i = 0;
2805 pat = string_extract_double_quoted (tword, &i, 1);
2806 free (tword);
2807 tword = pat;
2808 }
2809
2810 /* There is a problem here: how to handle single or double quotes in the
2811 pattern string when the whole expression is between double quotes? */
2812#if 0
2813 l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL)
2814#else
2815 l = *tword ? expand_string_for_rhs (tword,
2816 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted,
2817 (int *)NULL, (int *)NULL)
2818#endif
2819 : (WORD_LIST *)0;
2820 free (tword);
2821 pat = string_list (l);
2822 dispose_words (l);
2823 if (pat)
2824 {
2825 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
2826 free (pat);
2827 pat = tword;
2828 }
2829 return (pat);
2830}
2831
2832/* Handle removing a pattern from a string as a result of ${name%[%]value}
2833 or ${name#[#]value}. */
2834static char *
2835parameter_brace_remove_pattern (value, temp, c, quoted)
2836 char *value, *temp;
2837 int c, quoted;
2838{
2839 int patspec;
2840 char *pattern, *tword;
2841
2842 patspec = getpatspec (c, value);
2843 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2844 value++;
2845
2846 pattern = getpattern (value, quoted, 1);
2847
2848 tword = remove_pattern (temp, pattern, patspec);
2849
2850 FREE (pattern);
2851 return (tword);
2852}
2853
2854static char *
2855list_remove_pattern (list, pattern, patspec, type, quoted)
2856 WORD_LIST *list;
2857 char *pattern;
2858 int patspec, type, quoted;
2859{
2860 WORD_LIST *new, *l;
2861 WORD_DESC *w;
2862 char *tword;
2863
2864 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
2865 {
2866 tword = remove_pattern (l->word->word, pattern, patspec);
2867 w = make_bare_word (tword);
2868 free (tword);
2869 new = make_word_list (w, new);
2870 }
2871
2872 l = REVERSE_LIST (new, WORD_LIST *);
2873 if (type == '*')
2874 tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
2875 else
2876 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
2877
2878 dispose_words (l);
2879 return (tword);
2880}
2881
2882static char *
2883parameter_list_remove_pattern (value, type, c, quoted)
2884 char *value;
2885 int type, c, quoted;
2886{
2887 int patspec;
2888 char *pattern, *ret;
2889 WORD_LIST *list;
2890
2891 patspec = getpatspec (c, value);
2892 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2893 value++;
2894
2895 pattern = getpattern (value, quoted, 1);
2896
2897 list = list_rest_of_args ();
2898 ret = list_remove_pattern (list, pattern, patspec, type, quoted);
2899 dispose_words (list);
2900 FREE (pattern);
2901 return (ret);
2902}
2903
2904#if defined (ARRAY_VARS)
2905static char *
2906array_remove_pattern (value, aspec, aval, c, quoted)
2907 char *value, *aspec, *aval; /* AVAL == evaluated ASPEC */
2908 int c, quoted;
2909{
2910 SHELL_VAR *var;
2911 int len, patspec;
2912 char *ret, *t, *pattern;
2913 WORD_LIST *l;
2914
2915 var = array_variable_part (aspec, &t, &len);
2916 if (var == 0)
2917 return ((char *)NULL);
2918
2919 patspec = getpatspec (c, value);
2920 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2921 value++;
2922
2923 pattern = getpattern (value, quoted, 1);
2924
2925 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
2926 {
2927 if (array_p (var) == 0)
28ef6c31
JA
2928 {
2929 report_error ("%s: bad array subscript", aspec);
2930 FREE (pattern);
2931 return ((char *)NULL);
2932 }
cce855bc
JA
2933 l = array_to_word_list (array_cell (var));
2934 if (l == 0)
28ef6c31 2935 return ((char *)NULL);
cce855bc
JA
2936 ret = list_remove_pattern (l, pattern, patspec, t[0], quoted);
2937 dispose_words (l);
2938 }
2939 else
2940 {
2941 ret = remove_pattern (aval, pattern, patspec);
2942 if (ret)
2943 {
2944 t = quote_escapes (ret);
2945 free (ret);
2946 ret = t;
2947 }
2948 }
2949
2950 FREE (pattern);
2951 return ret;
2952}
2953#endif /* ARRAY_VARS */
2954
726f6388
JA
2955/*******************************************
2956 * *
2957 * Functions to expand WORD_DESCs *
2958 * *
2959 *******************************************/
2960
2961/* Expand WORD, performing word splitting on the result. This does
2962 parameter expansion, command substitution, arithmetic expansion,
2963 word splitting, and quote removal. */
2964
2965WORD_LIST *
2966expand_word (word, quoted)
2967 WORD_DESC *word;
2968 int quoted;
2969{
2970 WORD_LIST *result, *tresult;
2971
b72432fd 2972 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
726f6388
JA
2973 result = word_list_split (tresult);
2974 dispose_words (tresult);
ccc6cda3 2975 return (result ? dequote_list (result) : result);
726f6388
JA
2976}
2977
2978/* Expand WORD, but do not perform word splitting on the result. This
2979 does parameter expansion, command substitution, arithmetic expansion,
2980 and quote removal. */
2981WORD_LIST *
28ef6c31 2982expand_word_unsplit (word, quoted)
726f6388
JA
2983 WORD_DESC *word;
2984 int quoted;
2985{
2986 WORD_LIST *result;
2987
28ef6c31 2988 expand_no_split_dollar_star = 1;
b72432fd 2989 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
28ef6c31
JA
2990 expand_no_split_dollar_star = 0;
2991
ccc6cda3 2992 return (result ? dequote_list (result) : result);
726f6388
JA
2993}
2994
2995/* Perform shell expansions on WORD, but do not perform word splitting or
2996 quote removal on the result. */
2997WORD_LIST *
2998expand_word_leave_quoted (word, quoted)
2999 WORD_DESC *word;
3000 int quoted;
3001{
b72432fd 3002 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
726f6388
JA
3003}
3004
726f6388
JA
3005#if defined (PROCESS_SUBSTITUTION)
3006
cce855bc
JA
3007/*****************************************************************/
3008/* */
3009/* Hacking Process Substitution */
3010/* */
3011/*****************************************************************/
726f6388 3012
726f6388
JA
3013#if !defined (HAVE_DEV_FD)
3014/* Named pipes must be removed explicitly with `unlink'. This keeps a list
3015 of FIFOs the shell has open. unlink_fifo_list will walk the list and
3016 unlink all of them. add_fifo_list adds the name of an open FIFO to the
3017 list. NFIFO is a count of the number of FIFOs in the list. */
3018#define FIFO_INCR 20
3019
3020static char **fifo_list = (char **)NULL;
ccc6cda3
JA
3021static int nfifo;
3022static int fifo_list_size;
726f6388
JA
3023
3024static void
3025add_fifo_list (pathname)
3026 char *pathname;
3027{
3028 if (nfifo >= fifo_list_size - 1)
3029 {
3030 fifo_list_size += FIFO_INCR;
3031 fifo_list = (char **)xrealloc (fifo_list,
3032 fifo_list_size * sizeof (char *));
3033 }
3034
3035 fifo_list[nfifo++] = savestring (pathname);
3036}
3037
3038void
3039unlink_fifo_list ()
3040{
ccc6cda3 3041 if (nfifo == 0)
726f6388
JA
3042 return;
3043
3044 while (nfifo--)
3045 {
3046 unlink (fifo_list[nfifo]);
3047 free (fifo_list[nfifo]);
3048 fifo_list[nfifo] = (char *)NULL;
3049 }
3050 nfifo = 0;
3051}
3052
3053static char *
3054make_named_pipe ()
3055{
3056 char *tname;
3057
28ef6c31 3058 tname = sh_mktmpname ("sh-np", MT_USERANDOM);
726f6388
JA
3059 if (mkfifo (tname, 0600) < 0)
3060 {
3061 free (tname);
3062 return ((char *)NULL);
3063 }
3064
3065 add_fifo_list (tname);
3066 return (tname);
3067}
3068
726f6388
JA
3069#else /* HAVE_DEV_FD */
3070
3071/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
3072 has open to children. NFDS is a count of the number of bits currently
3073 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
3074 of open files. */
3075static char *dev_fd_list = (char *)NULL;
ccc6cda3 3076static int nfds;
726f6388
JA
3077static int totfds; /* The highest possible number of open files. */
3078
3079static void
3080add_fifo_list (fd)
3081 int fd;
3082{
3083 if (!dev_fd_list || fd >= totfds)
3084 {
3085 int ofds;
3086
3087 ofds = totfds;
3088 totfds = getdtablesize ();
3089 if (totfds < 0 || totfds > 256)
3090 totfds = 256;
3091 if (fd > totfds)
3092 totfds = fd + 2;
3093
3094 dev_fd_list = xrealloc (dev_fd_list, totfds);
3095 bzero (dev_fd_list + ofds, totfds - ofds);
3096 }
3097
3098 dev_fd_list[fd] = 1;
3099 nfds++;
3100}
3101
3102void
3103unlink_fifo_list ()
3104{
3105 register int i;
3106
ccc6cda3 3107 if (nfds == 0)
726f6388
JA
3108 return;
3109
3110 for (i = 0; nfds && i < totfds; i++)
3111 if (dev_fd_list[i])
3112 {
3113 close (i);
3114 dev_fd_list[i] = 0;
3115 nfds--;
3116 }
3117
3118 nfds = 0;
3119}
3120
3121#if defined (NOTDEF)
3122print_dev_fd_list ()
3123{
3124 register int i;
3125
3126 fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
3127 fflush (stderr);
3128
3129 for (i = 0; i < totfds; i++)
3130 {
3131 if (dev_fd_list[i])
3132 fprintf (stderr, " %d", i);
3133 }
3134 fprintf (stderr, "\n");
3135}
3136#endif /* NOTDEF */
3137
3138static char *
3139make_dev_fd_filename (fd)
3140 int fd;
3141{
bb70624e 3142 char *ret, intbuf[16], *p;
726f6388 3143
d166f048 3144 ret = xmalloc (sizeof (DEV_FD_PREFIX) + 4);
bb70624e
JA
3145
3146 strcpy (ret, DEV_FD_PREFIX);
3147 p = inttostr (fd, intbuf, sizeof (intbuf));
3148 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
3149
726f6388
JA
3150 add_fifo_list (fd);
3151 return (ret);
3152}
3153
3154#endif /* HAVE_DEV_FD */
3155
3156/* Return a filename that will open a connection to the process defined by
3157 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
3158 a filename in /dev/fd corresponding to a descriptor that is one of the
3159 ends of the pipe. If not defined, we use named pipes on systems that have
3160 them. Systems without /dev/fd and named pipes are out of luck.
3161
3162 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
3163 use the read end of the pipe and dup that file descriptor to fd 0 in
3164 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
3165 writing or use the write end of the pipe in the child, and dup that
3166 file descriptor to fd 1 in the child. The parent does the opposite. */
3167
3168static char *
3169process_substitute (string, open_for_read_in_child)
3170 char *string;
3171 int open_for_read_in_child;
3172{
3173 char *pathname;
3174 int fd, result;
3175 pid_t old_pid, pid;
3176#if defined (HAVE_DEV_FD)
3177 int parent_pipe_fd, child_pipe_fd;
3178 int fildes[2];
3179#endif /* HAVE_DEV_FD */
3180#if defined (JOB_CONTROL)
3181 pid_t old_pipeline_pgrp;
ccc6cda3 3182#endif
726f6388 3183
cce855bc 3184 if (!string || !*string || wordexp_only)
726f6388
JA
3185 return ((char *)NULL);
3186
3187#if !defined (HAVE_DEV_FD)
3188 pathname = make_named_pipe ();
3189#else /* HAVE_DEV_FD */
3190 if (pipe (fildes) < 0)
3191 {
ccc6cda3 3192 sys_error ("cannot make pipe for process substitution");
726f6388
JA
3193 return ((char *)NULL);
3194 }
3195 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
3196 the pipe in the parent, otherwise the read end. */
3197 parent_pipe_fd = fildes[open_for_read_in_child];
3198 child_pipe_fd = fildes[1 - open_for_read_in_child];
d166f048
JA
3199 /* Move the parent end of the pipe to some high file descriptor, to
3200 avoid clashes with FDs used by the script. */
3201 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
3202
726f6388
JA
3203 pathname = make_dev_fd_filename (parent_pipe_fd);
3204#endif /* HAVE_DEV_FD */
3205
3206 if (!pathname)
3207 {
ccc6cda3 3208 sys_error ("cannot make pipe for process substitution");
726f6388
JA
3209 return ((char *)NULL);
3210 }
3211
3212 old_pid = last_made_pid;
3213
3214#if defined (JOB_CONTROL)
3215 old_pipeline_pgrp = pipeline_pgrp;
3216 pipeline_pgrp = shell_pgrp;
ccc6cda3 3217#if 0
726f6388 3218 cleanup_the_pipeline ();
ccc6cda3
JA
3219#else
3220 save_pipeline (1);
3221#endif
3222#endif /* JOB_CONTROL */
3223
726f6388
JA
3224 pid = make_child ((char *)NULL, 1);
3225 if (pid == 0)
3226 {
ccc6cda3 3227 reset_terminating_signals (); /* XXX */
726f6388
JA
3228 /* Cancel traps, in trap.c. */
3229 restore_original_signals ();
3230 setup_async_signals ();
28ef6c31 3231 subshell_environment |= SUBSHELL_COMSUB;
726f6388 3232 }
ccc6cda3
JA
3233
3234#if defined (JOB_CONTROL)
726f6388
JA
3235 set_sigchld_handler ();
3236 stop_making_children ();
3237 pipeline_pgrp = old_pipeline_pgrp;
ccc6cda3 3238#endif /* JOB_CONTROL */
726f6388
JA
3239
3240 if (pid < 0)
3241 {
ccc6cda3 3242 sys_error ("cannot make child for process substitution");
726f6388
JA
3243 free (pathname);
3244#if defined (HAVE_DEV_FD)
3245 close (parent_pipe_fd);
3246 close (child_pipe_fd);
3247#endif /* HAVE_DEV_FD */
3248 return ((char *)NULL);
3249 }
3250
3251 if (pid > 0)
3252 {
ccc6cda3
JA
3253#if defined (JOB_CONTROL)
3254 restore_pipeline (1);
3255#endif
3256
726f6388
JA
3257 last_made_pid = old_pid;
3258
3259#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
3260 close_pgrp_pipe ();
3261#endif /* JOB_CONTROL && PGRP_PIPE */
3262
3263#if defined (HAVE_DEV_FD)
3264 close (child_pipe_fd);
3265#endif /* HAVE_DEV_FD */
3266
3267 return (pathname);
3268 }
3269
3270 set_sigint_handler ();
3271
3272#if defined (JOB_CONTROL)
3273 set_job_control (0);
3274#endif /* JOB_CONTROL */
3275
3276#if !defined (HAVE_DEV_FD)
3277 /* Open the named pipe in the child. */
ccc6cda3 3278 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
726f6388
JA
3279 if (fd < 0)
3280 {
ccc6cda3
JA
3281 sys_error ("cannot open named pipe %s for %s", pathname,
3282 open_for_read_in_child ? "reading" : "writing");
726f6388
JA
3283 exit (127);
3284 }
bb70624e
JA
3285 if (open_for_read_in_child)
3286 {
28ef6c31 3287 if (sh_unset_nodelay_mode (fd) < 0)
bb70624e
JA
3288 {
3289 sys_error ("cannout reset nodelay mode for fd %d", fd);
3290 exit (127);
3291 }
3292 }
726f6388
JA
3293#else /* HAVE_DEV_FD */
3294 fd = child_pipe_fd;
3295#endif /* HAVE_DEV_FD */
3296
3297 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
3298 {
ccc6cda3
JA
3299 sys_error ("cannot duplicate named pipe %s as fd %d", pathname,
3300 open_for_read_in_child ? 0 : 1);
726f6388
JA
3301 exit (127);
3302 }
3303
3304 close (fd);
3305
3306 /* Need to close any files that this process has open to pipes inherited
3307 from its parent. */
3308 if (current_fds_to_close)
3309 {
3310 close_fd_bitmap (current_fds_to_close);
3311 current_fds_to_close = (struct fd_bitmap *)NULL;
3312 }
3313
3314#if defined (HAVE_DEV_FD)
3315 /* Make sure we close the parent's end of the pipe and clear the slot
3316 in the fd list so it is not closed later, if reallocated by, for
3317 instance, pipe(2). */
3318 close (parent_pipe_fd);
3319 dev_fd_list[parent_pipe_fd] = 0;
3320#endif /* HAVE_DEV_FD */
3321
d166f048 3322 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
726f6388
JA
3323
3324#if !defined (HAVE_DEV_FD)
3325 /* Make sure we close the named pipe in the child before we exit. */
3326 close (open_for_read_in_child ? 0 : 1);
3327#endif /* !HAVE_DEV_FD */
3328
3329 exit (result);
3330 /*NOTREACHED*/
3331}
3332#endif /* PROCESS_SUBSTITUTION */
3333
cce855bc
JA
3334/***********************************/
3335/* */
3336/* Command Substitution */
3337/* */
3338/***********************************/
3339
d166f048
JA
3340static char *
3341read_comsub (fd, quoted)
3342 int fd, quoted;
3343{
3344 char *istring, buf[128], *bufp;
3345 int bufn, istring_index, istring_size, c;
3346
3347 istring = (char *)NULL;
3348 istring_index = istring_size = bufn = 0;
3349
28ef6c31
JA
3350#ifdef __CYGWIN__
3351 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
3352#endif
3353
d166f048
JA
3354 /* Read the output of the command through the pipe. */
3355 while (1)
3356 {
3357 if (fd < 0)
28ef6c31 3358 break;
d166f048
JA
3359 if (--bufn <= 0)
3360 {
bb70624e 3361 bufn = zread (fd, buf, sizeof (buf));
d166f048
JA
3362 if (bufn <= 0)
3363 break;
3364 bufp = buf;
3365 }
3366 c = *bufp++;
3367
28ef6c31
JA
3368 if (c == 0)
3369 {
3370#if 0
3371 internal_warning ("read_comsub: ignored null byte in input");
3372#endif
3373 continue;
3374 }
3375
d166f048
JA
3376 /* Add the character to ISTRING, possibly after resizing it. */
3377 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
3378
3379 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
3380 istring[istring_index++] = CTLESC;
3381
3382 istring[istring_index++] = c;
28ef6c31
JA
3383
3384#if 0
3385#if defined (__CYGWIN__)
3386 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
3387 {
3388 istring_index--;
3389 istring[istring_index - 1] = '\n';
3390 }
3391#endif
3392#endif
d166f048
JA
3393 }
3394
3395 if (istring)
3396 istring[istring_index] = '\0';
3397
3398 /* If we read no output, just return now and save ourselves some
3399 trouble. */
3400 if (istring_index == 0)
3401 {
3402 FREE (istring);
3403 return (char *)NULL;
3404 }
3405
3406 /* Strip trailing newlines from the output of the command. */
3407 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
3408 {
3409 while (istring_index > 0)
3410 {
3411 if (istring[istring_index - 1] == '\n')
3412 {
3413 --istring_index;
3414
3415 /* If the newline was quoted, remove the quoting char. */
3416 if (istring[istring_index - 1] == CTLESC)
3417 --istring_index;
3418 }
3419 else
3420 break;
3421 }
3422 istring[istring_index] = '\0';
3423 }
3424 else
3425 strip_trailing (istring, istring_index - 1, 1);
3426
3427 return istring;
3428}
3429
726f6388
JA
3430/* Perform command substitution on STRING. This returns a string,
3431 possibly quoted. */
bb70624e 3432char *
726f6388
JA
3433command_substitute (string, quoted)
3434 char *string;
3435 int quoted;
3436{
ccc6cda3
JA
3437 pid_t pid, old_pid, old_pipeline_pgrp;
3438 char *istring;
bb70624e 3439 int result, fildes[2], function_value;
726f6388 3440
ccc6cda3 3441 istring = (char *)NULL;
726f6388
JA
3442
3443 /* Don't fork () if there is no need to. In the case of no command to
3444 run, just return NULL. */
3445 if (!string || !*string || (string[0] == '\n' && !string[1]))
3446 return ((char *)NULL);
3447
cce855bc
JA
3448 if (wordexp_only && read_but_dont_execute)
3449 {
3450 last_command_exit_value = 125;
3451 jump_to_top_level (EXITPROG);
3452 }
3453
bb70624e
JA
3454 /* We're making the assumption here that the command substitution will
3455 eventually run a command from the file system. Since we'll run
3456 maybe_make_export_env in this subshell before executing that command,
3457 the parent shell and any other shells it starts will have to remake
3458 the environment. If we make it before we fork, other shells won't
3459 have to. Don't bother if we have any temporary variable assignments,
3460 though, because the export environment will be remade after this
3461 command completes anyway, but do it if all the words to be expanded
3462 are variable assignments. */
3463 if (subst_assign_varlist == 0 || garglist == 0)
3464 maybe_make_export_env (); /* XXX */
3465
726f6388
JA
3466 /* Pipe the output of executing STRING into the current shell. */
3467 if (pipe (fildes) < 0)
3468 {
ccc6cda3 3469 sys_error ("cannot make pipes for command substitution");
726f6388
JA
3470 goto error_exit;
3471 }
3472
3473 old_pid = last_made_pid;
3474#if defined (JOB_CONTROL)
ccc6cda3 3475 old_pipeline_pgrp = pipeline_pgrp;
28ef6c31
JA
3476 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
3477 if ((subshell_environment & SUBSHELL_PIPE) == 0)
3478 pipeline_pgrp = shell_pgrp;
ccc6cda3
JA
3479 cleanup_the_pipeline ();
3480#endif
726f6388 3481
ccc6cda3 3482 pid = make_child ((char *)NULL, 0);
726f6388
JA
3483 if (pid == 0)
3484 /* Reset the signal handlers in the child, but don't free the
3485 trap strings. */
3486 reset_signal_handlers ();
ccc6cda3
JA
3487
3488#if defined (JOB_CONTROL)
3489 set_sigchld_handler ();
3490 stop_making_children ();
3491 pipeline_pgrp = old_pipeline_pgrp;
3492#endif /* JOB_CONTROL */
726f6388
JA
3493
3494 if (pid < 0)
3495 {
ccc6cda3 3496 sys_error ("cannot make child for command substitution");
726f6388
JA
3497 error_exit:
3498
3499 FREE (istring);
3500 close (fildes[0]);
3501 close (fildes[1]);
3502 return ((char *)NULL);
3503 }
3504
3505 if (pid == 0)
3506 {
3507 set_sigint_handler (); /* XXX */
28ef6c31 3508
726f6388
JA
3509 if (dup2 (fildes[1], 1) < 0)
3510 {
ccc6cda3 3511 sys_error ("command_substitute: cannot duplicate pipe as fd 1");
726f6388
JA
3512 exit (EXECUTION_FAILURE);
3513 }
3514
3515 /* If standard output is closed in the parent shell
3516 (such as after `exec >&-'), file descriptor 1 will be
3517 the lowest available file descriptor, and end up in
3518 fildes[0]. This can happen for stdin and stderr as well,
3519 but stdout is more important -- it will cause no output
3520 to be generated from this command. */
3521 if ((fildes[1] != fileno (stdin)) &&
3522 (fildes[1] != fileno (stdout)) &&
3523 (fildes[1] != fileno (stderr)))
3524 close (fildes[1]);
3525
3526 if ((fildes[0] != fileno (stdin)) &&
3527 (fildes[0] != fileno (stdout)) &&
3528 (fildes[0] != fileno (stderr)))
3529 close (fildes[0]);
3530
3531 /* The currently executing shell is not interactive. */
3532 interactive = 0;
3533
ccc6cda3 3534 /* This is a subshell environment. */
28ef6c31 3535 subshell_environment |= SUBSHELL_COMSUB;
ccc6cda3 3536
28ef6c31
JA
3537 /* When not in POSIX mode, command substitution does not inherit
3538 the -e flag. */
3539 if (posixly_correct == 0)
3540 exit_immediately_on_error = 0;
726f6388
JA
3541
3542 remove_quoted_escapes (string);
3543
ccc6cda3 3544 startup_state = 2; /* see if we can avoid a fork */
726f6388
JA
3545 /* Give command substitution a place to jump back to on failure,
3546 so we don't go back up to main (). */
3547 result = setjmp (top_level);
3548
bb70624e
JA
3549 /* If we're running a command substitution inside a shell function,
3550 trap `return' so we don't return from the function in the subshell
3551 and go off to never-never land. */
3552 if (result == 0 && return_catch_flag)
3553 function_value = setjmp (return_catch);
3554 else
3555 function_value = 0;
3556
726f6388
JA
3557 if (result == EXITPROG)
3558 exit (last_command_exit_value);
3559 else if (result)
3560 exit (EXECUTION_FAILURE);
bb70624e
JA
3561 else if (function_value)
3562 exit (return_catch_value);
726f6388 3563 else
d166f048 3564 exit (parse_and_execute (string, "command substitution", SEVAL_NOHIST));
726f6388
JA
3565 }
3566 else
3567 {
726f6388
JA
3568#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
3569 close_pgrp_pipe ();
3570#endif /* JOB_CONTROL && PGRP_PIPE */
3571
3572 close (fildes[1]);
3573
d166f048 3574 istring = read_comsub (fildes[0], quoted);
ccc6cda3 3575
726f6388
JA
3576 close (fildes[0]);
3577
b72432fd 3578 current_command_subst_pid = pid;
726f6388
JA
3579 last_command_exit_value = wait_for (pid);
3580 last_command_subst_pid = pid;
3581 last_made_pid = old_pid;
3582
3583#if defined (JOB_CONTROL)
3584 /* If last_command_exit_value > 128, then the substituted command
3585 was terminated by a signal. If that signal was SIGINT, then send
3586 SIGINT to ourselves. This will break out of loops, for instance. */
3587 if (last_command_exit_value == (128 + SIGINT))
3588 kill (getpid (), SIGINT);
3589
3590 /* wait_for gives the terminal back to shell_pgrp. If some other
cce855bc
JA
3591 process group should have it, give it away to that group here.
3592 pipeline_pgrp is non-zero only while we are constructing a
3593 pipline, so what we are concerned about is whether or not that
3594 pipeline was started in the background. A pipeline started in
3595 the background should never get the tty back here. */
3596#if 0
3597 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
3598#else
28ef6c31 3599 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
cce855bc 3600#endif
28ef6c31 3601 give_terminal_to (pipeline_pgrp, 0);
726f6388
JA
3602#endif /* JOB_CONTROL */
3603
726f6388
JA
3604 return (istring);
3605 }
3606}
3607
3608/********************************************************
3609 * *
3610 * Utility functions for parameter expansion *
3611 * *
3612 ********************************************************/
3613
cce855bc 3614/* Utility functions to manage arrays and their contents for expansion */
ccc6cda3
JA
3615
3616#if defined (ARRAY_VARS)
ccc6cda3
JA
3617int
3618valid_array_reference (name)
3619 char *name;
3620{
3621 char *t;
3622 int r, len;
3623
28ef6c31 3624 t = strchr (name, '['); /* ] */
ccc6cda3
JA
3625 if (t)
3626 {
3627 *t = '\0';
3628 r = legal_identifier (name);
3629 *t = '[';
3630 if (r == 0)
3631 return 0;
3632 /* Check for a properly-terminated non-blank subscript. */
3633 len = skipsubscript (t, 0);
3634 if (t[len] != ']' || len == 1)
3635 return 0;
3636 for (r = 1; r < len; r++)
3637 if (whitespace (t[r]) == 0)
3638 return 1;
3639 return 0;
3640 }
3641 return 0;
3642}
3643
3644/* Expand the array index beginning at S and extending LEN characters. */
3645int
3646array_expand_index (s, len)
3647 char *s;
3648 int len;
3649{
3650 char *exp, *t;
d166f048 3651 int val, expok;
ccc6cda3
JA
3652
3653 exp = xmalloc (len);
3654 strncpy (exp, s, len - 1);
3655 exp[len - 1] = '\0';
3656 t = maybe_expand_string (exp, 0, expand_string);
3657 this_command_name = (char *)NULL;
d166f048 3658 val = evalexp (t, &expok);
ccc6cda3
JA
3659 free (t);
3660 free (exp);
d166f048 3661 if (expok == 0)
28ef6c31
JA
3662 {
3663 last_command_exit_value = EXECUTION_FAILURE;
3664 jump_to_top_level (DISCARD);
3665 }
ccc6cda3
JA
3666 return val;
3667}
3668
3669/* Return the variable specified by S without any subscript. If non-null,
3670 return the index of the start of the subscript in *SUBP. If non-null,
3671 the length of the subscript is returned in *LENP. */
3672SHELL_VAR *
3673array_variable_part (s, subp, lenp)
3674 char *s, **subp;
3675 int *lenp;
3676{
3677 char *t;
3678 int ind, ni;
3679 SHELL_VAR *var;
3680
3681 t = strchr (s, '[');
3682 ind = t - s;
3683 ni = skipsubscript (s, ind);
3684 if (ni <= ind + 1 || s[ni] != ']')
726f6388 3685 {
ccc6cda3
JA
3686 report_error ("%s: bad array subscript", s);
3687 return ((SHELL_VAR *)NULL);
3688 }
3689
3690 *t = '\0';
3691 var = find_variable (s);
28ef6c31 3692 *t++ = '['; /* ] */
ccc6cda3
JA
3693
3694 if (subp)
3695 *subp = t;
3696 if (lenp)
3697 *lenp = ni - ind;
3698 return var;
3699}
3700
3701static char *
3702array_value_internal (s, quoted, allow_all)
3703 char *s;
3704 int quoted, allow_all;
3705{
3706 int len, ind;
cce855bc
JA
3707 char *retval, *t, *temp;
3708 WORD_LIST *l, *list;
ccc6cda3
JA
3709 SHELL_VAR *var;
3710
3711 var = array_variable_part (s, &t, &len);
3712
3713 if (var == 0)
3714 return (char *)NULL;
3715
28ef6c31 3716 /* [ */
ccc6cda3
JA
3717 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3718 {
28ef6c31
JA
3719 if (allow_all == 0)
3720 {
3721 report_error ("%s: bad array subscript", s);
3722 return ((char *)NULL);
3723 }
3724 else if (array_p (var) == 0)
3725 {
3726 l = (WORD_LIST *)NULL;
3727 l = add_string_to_list (value_cell (var), l);
3728 }
3729 else
3730 {
3731 l = array_to_word_list (array_cell (var));
3732 if (l == (WORD_LIST *)NULL)
3733 return ((char *) NULL);
3734 }
ccc6cda3 3735
cce855bc
JA
3736 if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
3737 {
3738 temp = string_list_dollar_star (l);
3739 retval = quote_string (temp);
3740 free (temp);
3741 }
3742 else /* ${name[@]} or unquoted ${name[*]} */
3743 retval = string_list_dollar_at (l, quoted);
ccc6cda3
JA
3744
3745 dispose_words (l);
3746 }
3747 else
3748 {
3749 ind = array_expand_index (t, len);
3750 if (ind < 0)
726f6388 3751 {
ccc6cda3
JA
3752 report_error ("%s: bad array subscript", var->name);
3753 return ((char *)NULL);
726f6388 3754 }
ccc6cda3 3755 if (array_p (var) == 0)
28ef6c31 3756 return (ind == 0 ? savestring (value_cell (var)) : (char *)NULL);
ccc6cda3
JA
3757 retval = array_reference (array_cell (var), ind);
3758 if (retval)
3759 retval = quote_escapes (retval);
726f6388
JA
3760 }
3761
ccc6cda3
JA
3762 return retval;
3763}
726f6388 3764
ccc6cda3
JA
3765static char *
3766array_value (s, quoted)
3767 char *s;
3768 int quoted;
3769{
3770 return (array_value_internal (s, quoted, 1));
3771}
3772
3773/* Return the value of the array indexing expression S as a single string.
3774 If ALLOW_ALL is 0, do not allow `@' and `*' subscripts. This is used
3775 by other parts of the shell such as the arithmetic expression evaluator
3776 in expr.c. */
3777char *
3778get_array_value (s, allow_all)
3779 char *s;
3780 int allow_all;
3781{
3782 return (array_value_internal (s, 0, allow_all));
3783}
3784
3785static int
3786array_length_reference (s)
3787 char *s;
3788{
3789 int ind, len;
3790 char *t;
3791 ARRAY *array;
3792 SHELL_VAR *var;
3793
3794 var = array_variable_part (s, &t, &len);
726f6388 3795
ccc6cda3
JA
3796 /* If unbound variables should generate an error, report one and return
3797 failure. */
3798 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
726f6388 3799 {
ccc6cda3
JA
3800 ind = *--t;
3801 *t = '\0';
3802 report_error ("%s: unbound variable", s);
3803 *t++ = (char)ind;
3804 return (-1);
726f6388 3805 }
ccc6cda3
JA
3806 else if (var == 0)
3807 return 0;
726f6388 3808
28ef6c31
JA
3809 /* We support a couple of expansions for variables that are not arrays.
3810 We'll return the length of the value for v[0], and 1 for v[@] or
3811 v[*]. Return 0 for everything else. */
3812
3813 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
726f6388 3814
ccc6cda3 3815 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
28ef6c31 3816 return (array_p (var) ? array_num_elements (array) : 1);
ccc6cda3
JA
3817
3818 ind = array_expand_index (t, len);
3819 if (ind < 0)
3820 {
3821 report_error ("%s: bad array subscript", t);
3822 return (-1);
3823 }
ccc6cda3 3824
28ef6c31
JA
3825 if (array_p (var))
3826 t = array_reference (array, ind);
3827 else
3828 t = (ind == 0) ? value_cell (var) : (char *)NULL;
3829
3830 len = STRLEN (t);
ccc6cda3 3831 return (len);
726f6388 3832}
ccc6cda3 3833#endif /* ARRAY_VARS */
726f6388
JA
3834
3835static int
3836valid_brace_expansion_word (name, var_is_special)
3837 char *name;
3838 int var_is_special;
3839{
28ef6c31 3840 if (isdigit (*name) && all_digits (name))
726f6388
JA
3841 return 1;
3842 else if (var_is_special)
3843 return 1;
ccc6cda3
JA
3844#if defined (ARRAY_VARS)
3845 else if (valid_array_reference (name))
3846 return 1;
3847#endif /* ARRAY_VARS */
726f6388
JA
3848 else if (legal_identifier (name))
3849 return 1;
3850 else
3851 return 0;
3852}
ccc6cda3 3853
726f6388
JA
3854/* Parameter expand NAME, and return a new string which is the expansion,
3855 or NULL if there was no expansion.
3856 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
3857 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
3858 NAME was found inside of a double-quoted expression. */
3859static char *
3860parameter_brace_expand_word (name, var_is_special, quoted)
3861 char *name;
3862 int var_is_special, quoted;
3863{
ccc6cda3
JA
3864 char *temp, *tt;
3865 int arg_index;
3866 SHELL_VAR *var;
3867 WORD_LIST *l;
726f6388
JA
3868
3869 /* Handle multiple digit arguments, as in ${11}. */
28ef6c31 3870 if (isdigit (*name))
726f6388 3871 {
ccc6cda3 3872 arg_index = atoi (name);
726f6388
JA
3873 temp = get_dollar_var_value (arg_index);
3874 }
3875 else if (var_is_special) /* ${@} */
3876 {
cce855bc 3877 int sindex;
726f6388 3878 tt = xmalloc (2 + strlen (name));
cce855bc 3879 tt[sindex = 0] = '$';
726f6388 3880 strcpy (tt + 1, name);
cce855bc 3881#if 0
726f6388
JA
3882 l = expand_string_leave_quoted (tt, quoted);
3883 free (tt);
3884 temp = string_list (l);
3885 dispose_words (l);
cce855bc
JA
3886#else
3887 temp = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
3888 (int *)NULL, (int *)NULL, 0);
3889 free (tt);
3890#endif
726f6388 3891 }
ccc6cda3
JA
3892#if defined (ARRAY_VARS)
3893 else if (valid_array_reference (name))
3894 {
3895 temp = array_value (name, quoted);
3896 }
3897#endif
3898 else if (var = find_variable (name))
3899 {
3900 if (var && invisible_p (var) == 0)
28ef6c31 3901 {
ccc6cda3
JA
3902#if defined (ARRAY_VARS)
3903 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
3904#else
3905 temp = value_cell (var);
3906#endif
3907
3908 if (temp)
3909 temp = quote_escapes (temp);
cce855bc
JA
3910
3911 if (tempvar_p (var))
3912 dispose_variable (var);
28ef6c31 3913 }
ccc6cda3
JA
3914 else
3915 temp = (char *)NULL;
3916 }
726f6388 3917 else
ccc6cda3 3918 temp = (char *)NULL;
726f6388 3919
726f6388
JA
3920 return (temp);
3921}
3922
ccc6cda3
JA
3923/* Expand an indirect reference to a variable: ${!NAME} expands to the
3924 value of the variable whose name is the value of NAME. */
3925static char *
3926parameter_brace_expand_indir (name, var_is_special, quoted)
3927 char *name;
3928 int var_is_special, quoted;
3929{
3930 char *temp, *t;
3931
3932 t = parameter_brace_expand_word (name, var_is_special, quoted);
3933 if (t == 0)
3934 return (t);
bb70624e 3935#if 0
ccc6cda3 3936 temp = parameter_brace_expand_word (t, t[0] == '@' && t[1] == '\0', quoted);
bb70624e
JA
3937#else
3938 temp = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
3939#endif
ccc6cda3
JA
3940 free (t);
3941 return temp;
3942}
3943
726f6388
JA
3944/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
3945 depending on the value of C, the separating character. C can be one of
ccc6cda3
JA
3946 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
3947 between double quotes. */
726f6388 3948static char *
ccc6cda3 3949parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
726f6388 3950 char *name, *value;
ccc6cda3 3951 int c, quoted, *qdollaratp, *hasdollarat;
726f6388
JA
3952{
3953 WORD_LIST *l;
3954 char *t, *t1, *temp;
ccc6cda3 3955 int hasdol;
726f6388 3956
ccc6cda3 3957 temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
28ef6c31 3958 ? bash_tilde_expand (value)
ccc6cda3 3959 : savestring (value);
726f6388 3960
ccc6cda3
JA
3961 /* If the entire expression is between double quotes, we want to treat
3962 the value as a double-quoted string, with the exception that we strip
3963 embedded unescaped double quotes. */
3964 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *temp)
726f6388 3965 {
ccc6cda3
JA
3966 hasdol = 0;
3967 t = string_extract_double_quoted (temp, &hasdol, 1);
726f6388
JA
3968 free (temp);
3969 temp = t;
726f6388 3970 }
ccc6cda3 3971
726f6388 3972 hasdol = 0;
ccc6cda3
JA
3973 /* XXX was 0 not quoted */
3974 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
3975 : (WORD_LIST *)0;
3976 if (hasdollarat)
3977 *hasdollarat = hasdol || (l && l->next);
726f6388 3978 free (temp);
726f6388
JA
3979 if (l)
3980 {
ccc6cda3
JA
3981 /* The expansion of TEMP returned something. We need to treat things
3982 slightly differently if HASDOL is non-zero. */
726f6388 3983 temp = string_list (l);
ccc6cda3
JA
3984 /* If l->next is not null, we know that TEMP contained "$@", since that
3985 is the only expansion that creates more than one word. */
3986 if ((hasdol && quoted) || l->next)
3987 *qdollaratp = 1;
726f6388
JA
3988 dispose_words (l);
3989 }
ccc6cda3 3990 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
726f6388 3991 {
ccc6cda3
JA
3992 /* The brace expansion occurred between double quotes and there was
3993 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
3994 it does not expand to anything. In this case, we want to return
3995 a quoted empty string. */
726f6388
JA
3996 temp = xmalloc (2);
3997 temp[0] = CTLNUL;
3998 temp[1] = '\0';
3999 }
4000 else
4001 temp = (char *)NULL;
4002
4003 if (c == '-' || c == '+')
4004 return (temp);
4005
4006 /* c == '=' */
ccc6cda3 4007 t = temp ? savestring (temp) : savestring ("");
726f6388
JA
4008 t1 = dequote_string (t);
4009 free (t);
4010 bind_variable (name, t1);
4011 free (t1);
4012 return (temp);
4013}
4014
4015/* Deal with the right hand side of a ${name:?value} expansion in the case
4016 that NAME is null or not set. If VALUE is non-null it is expanded and
4017 used as the error message to print, otherwise a standard message is
4018 printed. */
4019static void
4020parameter_brace_expand_error (name, value)
4021 char *name, *value;
4022{
ccc6cda3
JA
4023 WORD_LIST *l;
4024 char *temp;
4025
726f6388
JA
4026 if (value && *value)
4027 {
28ef6c31
JA
4028 temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
4029 ? bash_tilde_expand (value)
4030 : savestring (value);
4031
4032 l = expand_string (temp, 0);
4033 FREE (temp);
ccc6cda3
JA
4034 temp = string_list (l);
4035 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
4036 FREE (temp);
726f6388
JA
4037 dispose_words (l);
4038 }
4039 else
4040 report_error ("%s: parameter null or not set", name);
4041
4042 /* Free the data we have allocated during this expansion, since we
4043 are about to longjmp out. */
4044 free (name);
4045 FREE (value);
4046}
4047
4048/* Return 1 if NAME is something for which parameter_brace_expand_length is
4049 OK to do. */
4050static int
4051valid_length_expression (name)
4052 char *name;
4053{
28ef6c31
JA
4054 return (name[1] == '\0' || /* ${#} */
4055 ((sh_syntaxtab[name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
4056 (isdigit (name[1]) && all_digits (name + 1)) || /* ${#11} */
ccc6cda3
JA
4057#if defined (ARRAY_VARS)
4058 valid_array_reference (name + 1) || /* ${#a[7]} */
4059#endif
726f6388
JA
4060 legal_identifier (name + 1)); /* ${#PS1} */
4061}
4062
4063/* Handle the parameter brace expansion that requires us to return the
4064 length of a parameter. */
4065static int
4066parameter_brace_expand_length (name)
4067 char *name;
4068{
ccc6cda3
JA
4069 char *t, *newname;
4070 int number;
4071 WORD_LIST *list;
4072#if defined (ARRAY_VARS)
4073 SHELL_VAR *var;
4074#endif
4075
4076 if (name[1] == '\0') /* ${#} */
4077 number = number_of_args ();
cce855bc
JA
4078 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
4079 number = number_of_args ();
28ef6c31 4080 else if ((sh_syntaxtab[name[1]] & CSPECVAR) && name[2] == '\0')
cce855bc
JA
4081 {
4082 /* Take the lengths of some of the shell's special parameters. */
4083 switch (name[1])
4084 {
4085 case '-':
4086 t = which_set_flags ();
4087 break;
4088 case '?':
4089 t = itos (last_command_exit_value);
4090 break;
4091 case '$':
4092 t = itos (dollar_dollar_pid);
4093 break;
4094 case '!':
4095 if (last_asynchronous_pid == NO_PID)
4096 t = (char *)NULL;
4097 else
4098 t = itos ((int)last_asynchronous_pid);
4099 break;
4100 case '#':
4101 t = itos (number_of_args ());
4102 break;
4103 }
4104 number = STRLEN (t);
4105 FREE (t);
4106 }
ccc6cda3
JA
4107#if defined (ARRAY_VARS)
4108 else if (valid_array_reference (name + 1))
4109 number = array_length_reference (name + 1);
4110#endif /* ARRAY_VARS */
cce855bc 4111 else
ccc6cda3
JA
4112 {
4113 number = 0;
4114
28ef6c31 4115 if (isdigit (name[1])) /* ${#1} */
ccc6cda3
JA
4116 {
4117 t = get_dollar_var_value (atoi (name + 1));
4118 number = STRLEN (t);
4119 FREE (t);
4120 }
4121#if defined (ARRAY_VARS)
4122 else if ((var = find_variable (name + 1)) && array_p (var))
4123 {
4124 t = array_reference (array_cell (var), 0);
4125 number = STRLEN (t);
4126 }
4127#endif
4128 else /* ${#PS1} */
4129 {
4130 newname = savestring (name);
4131 newname[0] = '$';
4132 list = expand_string (newname, Q_DOUBLE_QUOTES);
4133 t = list ? string_list (list) : (char *)NULL;
4134 free (newname);
4135 if (list)
4136 dispose_words (list);
4137
4138 number = STRLEN (t);
4139 FREE (t);
4140 }
4141 }
ccc6cda3
JA
4142
4143 return (number);
4144}
4145
28ef6c31
JA
4146/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
4147 so we do some ad-hoc parsing of an arithmetic expression to find
4148 the first DELIM, instead of using strchr(3). Two rules:
4149 1. If the substring contains a `(', read until closing `)'.
4150 2. If the substring contains a `?', read past one `:' for each `?'.
4151*/
4152
4153static char *
4154skiparith (substr, delim)
4155 char *substr;
4156 int delim;
4157{
4158 int skipcol, pcount;
4159 char *t;
4160
4161 for (skipcol = pcount = 0, t = substr; *t; t++)
4162 {
4163 /* Balance parens */
4164 if (*t == '(')
4165 {
4166 pcount++;
4167 continue;
4168 }
4169 if (*t == ')' && pcount)
4170 {
4171 pcount--;
4172 continue;
4173 }
4174 if (pcount)
4175 continue;
4176
4177 /* Skip one `:' for each `?' */
4178 if (*t == ':' && skipcol)
4179 {
4180 skipcol--;
4181 continue;
4182 }
4183 if (*t == delim)
4184 break;
4185 if (*t == '?')
4186 {
4187 skipcol++;
4188 continue;
4189 }
4190 }
4191 return t;
4192}
4193
ccc6cda3
JA
4194/* Verify and limit the start and end of the desired substring. If
4195 VTYPE == 0, a regular shell variable is being used; if it is 1,
cce855bc 4196 then the positional parameters are being used; if it is 2, then
e8ce775d
JA
4197 VALUE is really a pointer to an array variable that should be used.
4198 Return value is 1 if both values were OK, 0 if there was a problem
4199 with an invalid expression, or -1 if the values were out of range. */
ccc6cda3
JA
4200static int
4201verify_substring_values (value, substr, vtype, e1p, e2p)
4202 char *value, *substr;
4203 int vtype, *e1p, *e2p;
4204{
bb70624e 4205 char *t, *temp1, *temp2;
d166f048 4206 int len, expok;
ccc6cda3
JA
4207#if defined (ARRAY_VARS)
4208 ARRAY *a;
4209#endif
4210
28ef6c31
JA
4211#if 1
4212 /* duplicate behavior of strchr(3) */
4213 t = skiparith (substr, ':');
4214 if (*t && *t == ':')
4215 *t = '\0';
4216 else
4217 t = (char *)0;
4218#else
ccc6cda3
JA
4219 t = strchr (substr, ':');
4220 if (t)
4221 *t = '\0';
28ef6c31 4222#endif
d166f048
JA
4223 temp1 = maybe_expand_string (substr, Q_DOUBLE_QUOTES, expand_string);
4224 *e1p = evalexp (temp1, &expok);
ccc6cda3 4225 free (temp1);
d166f048
JA
4226 if (expok == 0)
4227 return (0);
ccc6cda3
JA
4228
4229 switch (vtype)
4230 {
4231 case VT_VARIABLE:
d166f048 4232 case VT_ARRAYMEMBER:
ccc6cda3
JA
4233 len = strlen (value);
4234 break;
4235 case VT_POSPARMS:
4236 len = number_of_args () + 1;
4237 break;
4238#if defined (ARRAY_VARS)
4239 case VT_ARRAYVAR:
4240 a = (ARRAY *)value;
4241 len = array_num_elements (a) + 1;
4242 break;
4243#endif
4244 }
4245
4246 if (*e1p < 0) /* negative offsets count from end */
4247 *e1p += len;
4248
d166f048 4249 if (*e1p >= len || *e1p < 0)
e8ce775d 4250 return (-1);
d166f048 4251
ccc6cda3
JA
4252 if (t)
4253 {
4254 t++;
bb70624e
JA
4255 temp2 = savestring (t);
4256 temp1 = maybe_expand_string (temp2, Q_DOUBLE_QUOTES, expand_string);
4257 free (temp2);
ccc6cda3 4258 t[-1] = ':';
d166f048 4259 *e2p = evalexp (temp1, &expok);
ccc6cda3 4260 free (temp1);
d166f048 4261 if (expok == 0)
28ef6c31 4262 return (0);
ccc6cda3 4263 if (*e2p < 0)
28ef6c31
JA
4264 {
4265 internal_error ("%s: substring expression < 0", t);
ccc6cda3 4266 return (0);
28ef6c31 4267 }
ccc6cda3
JA
4268 *e2p += *e1p; /* want E2 chars starting at E1 */
4269 if (*e2p > len)
28ef6c31 4270 *e2p = len;
ccc6cda3
JA
4271 }
4272 else
4273 *e2p = len;
4274
4275 return (1);
4276}
4277
ccc6cda3 4278/* Return the type of variable specified by VARNAME (simple variable,
cce855bc 4279 positional param, or array variable). Also return the value specified
ccc6cda3
JA
4280 by VARNAME (value of a variable or a reference to an array element). */
4281static int
4282get_var_and_type (varname, value, varp, valp)
4283 char *varname, *value;
4284 SHELL_VAR **varp;
4285 char **valp;
4286{
4287 int vtype;
4288 char *temp;
4289#if defined (ARRAY_VARS)
4290 SHELL_VAR *v;
4291#endif
4292
4293 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0'; /* VT_POSPARMS */
4294 *varp = (SHELL_VAR *)NULL;
4295
4296#if defined (ARRAY_VARS)
4297 if (valid_array_reference (varname))
4298 {
4299 v = array_variable_part (varname, &temp, (int *)0);
4300 if (v && array_p (v))
4301 {
d166f048 4302 if ((temp[0] == '@' || temp[0] == '*') && temp[1] == ']')
ccc6cda3
JA
4303 {
4304 vtype = VT_ARRAYVAR;
4305 *valp = (char *)array_cell (v);
4306 }
4307 else
4308 {
d166f048 4309 vtype = VT_ARRAYMEMBER;
ccc6cda3
JA
4310 *valp = array_value (varname, 1);
4311 }
4312 *varp = v;
4313 }
4314 else
4315 return -1;
4316 }
4317 else if ((v = find_variable (varname)) && array_p (v))
4318 {
4319 vtype = VT_VARIABLE;
4320 *varp = v;
4321 *valp = array_reference (array_cell (v), 0);
4322 }
4323 else
4324#endif
4325 *valp = value;
4326
4327 return vtype;
4328}
4329
cce855bc
JA
4330/******************************************************/
4331/* */
4332/* Functions to extract substrings of variable values */
4333/* */
4334/******************************************************/
4335
ccc6cda3
JA
4336/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
4337 is `@', use the positional parameters; otherwise, use the value of
4338 VARNAME. If VARNAME is an array variable, use the array elements. */
4339
4340static char *
4341parameter_brace_substring (varname, value, substr, quoted)
4342 char *varname, *value, *substr;
4343 int quoted;
4344{
e8ce775d 4345 int e1, e2, vtype, r;
ccc6cda3
JA
4346 char *temp, *val;
4347 SHELL_VAR *v;
4348
4349 if (value == 0)
4350 return ((char *)NULL);
4351
4352 this_command_name = varname;
4353
4354 vtype = get_var_and_type (varname, value, &v, &val);
4355 if (vtype == -1)
4356 return ((char *)NULL);
4357
e8ce775d
JA
4358 r = verify_substring_values (val, substr, vtype, &e1, &e2);
4359 if (r <= 0)
d166f048
JA
4360 {
4361 if (val && vtype == VT_ARRAYMEMBER)
4362 free (val);
e8ce775d 4363 return ((r == 0) ? &expand_param_error : (char *)NULL);
d166f048 4364 }
ccc6cda3
JA
4365
4366 switch (vtype)
4367 {
4368 case VT_VARIABLE:
d166f048 4369 case VT_ARRAYMEMBER:
ccc6cda3 4370 temp = quoted ? quoted_substring (value, e1, e2) : substring (value, e1, e2);
28ef6c31
JA
4371 if (val && vtype == VT_ARRAYMEMBER)
4372 free (val);
ccc6cda3
JA
4373 break;
4374 case VT_POSPARMS:
4375 temp = pos_params (varname, e1, e2, quoted);
4376 break;
4377#if defined (ARRAY_VARS)
4378 case VT_ARRAYVAR:
4379 temp = array_subrange (array_cell (v), e1, e2, quoted);
4380 break;
4381#endif
4382 }
4383
4384 return temp;
4385}
4386
cce855bc
JA
4387/****************************************************************/
4388/* */
4389/* Functions to perform pattern substitution on variable values */
4390/* */
4391/****************************************************************/
4392
ccc6cda3
JA
4393char *
4394pat_subst (string, pat, rep, mflags)
4395 char *string, *pat, *rep;
4396 int mflags;
4397{
4398 char *ret, *s, *e, *str;
4399 int rsize, rptr, l, replen, mtype;
4400
b72432fd
JA
4401 mtype = mflags & MATCH_TYPEMASK;
4402
4403 /* Special cases:
4404 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
4405 * with REP and return the result.
4406 * 2. A null pattern with mtype == MATCH_END means to append REP to
4407 * STRING and return the result.
4408 */
4409 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
4410 {
4411 replen = STRLEN (rep);
4412 l = strlen (string);
4413 ret = xmalloc (replen + l + 2);
bb70624e
JA
4414 if (replen == 0)
4415 strcpy (ret, string);
4416 else if (mtype == MATCH_BEG)
b72432fd
JA
4417 {
4418 strcpy (ret, rep);
4419 strcpy (ret + replen, string);
4420 }
4421 else
4422 {
4423 strcpy (ret, string);
4424 strcpy (ret + l, rep);
4425 }
4426 return (ret);
4427 }
4428
ccc6cda3
JA
4429 ret = xmalloc (rsize = 64);
4430 ret[0] = '\0';
4431
ccc6cda3
JA
4432 for (replen = STRLEN (rep), rptr = 0, str = string;;)
4433 {
4434 if (match_pattern (str, pat, mtype, &s, &e) == 0)
4435 break;
4436 l = s - str;
4437 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
4438
4439 /* OK, now copy the leading unmatched portion of the string (from
4440 str to s) to ret starting at rptr (the current offset). Then copy
28ef6c31
JA
4441 the replacement string at ret + rptr + (s - str). Increment
4442 rptr (if necessary) and str and go on. */
ccc6cda3
JA
4443 if (l)
4444 {
4445 strncpy (ret + rptr, str, l);
4446 rptr += l;
4447 }
4448 if (replen)
4449 {
4450 strncpy (ret + rptr, rep, replen);
4451 rptr += replen;
4452 }
28ef6c31
JA
4453 if (s == e)
4454 e++; /* avoid infinite recursion on zero-length match */
ccc6cda3
JA
4455 str = e; /* e == end of match */
4456 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
28ef6c31 4457 break;
ccc6cda3
JA
4458 }
4459
4460 /* Now copy the unmatched portion of the input string */
4461 if (*str)
d166f048
JA
4462 {
4463 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
4464 strcpy (ret + rptr, str);
4465 }
ccc6cda3
JA
4466 else
4467 ret[rptr] = '\0';
4468
4469 return ret;
4470}
4471
4472/* Do pattern match and replacement on the positional parameters. */
4473static char *
4474pos_params_pat_subst (string, pat, rep, mflags)
4475 char *string, *pat, *rep;
4476 int mflags;
4477{
4478 WORD_LIST *save, *params;
4479 WORD_DESC *w;
4480 char *ret;
4481
4482 save = params = list_rest_of_args ();
4483 if (save == 0)
4484 return ((char *)NULL);
4485
4486 for ( ; params; params = params->next)
4487 {
4488 ret = pat_subst (params->word->word, pat, rep, mflags);
4489 w = make_bare_word (ret);
4490 dispose_word (params->word);
4491 params->word = w;
4492 FREE (ret);
4493 }
4494
4495 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
4496 dispose_words (save);
4497
4498 return (ret);
4499}
4500
cce855bc
JA
4501/* Perform pattern substitution on VALUE, which is the expansion of
4502 VARNAME. PATSUB is an expression supplying the pattern to match
4503 and the string to substitute. QUOTED is a flags word containing
4504 the type of quoting currently in effect. */
ccc6cda3
JA
4505static char *
4506parameter_brace_patsub (varname, value, patsub, quoted)
4507 char *varname, *value, *patsub;
4508 int quoted;
4509{
4510 int vtype, mflags;
bb70624e 4511 char *val, *temp, *pat, *rep, *p, *lpatsub;
ccc6cda3
JA
4512 SHELL_VAR *v;
4513
4514 if (value == 0)
4515 return ((char *)NULL);
4516
4517 this_command_name = varname;
4518
4519 vtype = get_var_and_type (varname, value, &v, &val);
4520 if (vtype == -1)
4521 return ((char *)NULL);
4522
4523 mflags = 0;
4524 if (*patsub == '/')
4525 {
4526 mflags |= MATCH_GLOBREP;
4527 patsub++;
4528 }
bb70624e
JA
4529 /* Malloc this because maybe_expand_string or one of the expansion functions
4530 in its call chain may free it on a substitution error. */
4531 lpatsub = savestring (patsub);
ccc6cda3
JA
4532
4533 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4534 mflags |= MATCH_QUOTED;
4535
bb70624e 4536 if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
ccc6cda3
JA
4537 *rep++ = '\0';
4538 else
4539 rep = (char *)NULL;
4540
4541 if (rep && *rep == '\0')
4542 rep = (char *)NULL;
4543
4544 /* Expand PAT and REP for command, variable and parameter, arithmetic,
4545 and process substitution. Also perform quote removal. Do not
4546 perform word splitting or filename generation. */
cce855bc 4547#if 0
bb70624e 4548 pat = maybe_expand_string (lpatsub, quoted, expand_string_unsplit);
cce855bc 4549#else
bb70624e 4550 pat = maybe_expand_string (lpatsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit);
cce855bc 4551#endif
bb70624e 4552
ccc6cda3 4553 if (rep)
d166f048
JA
4554 {
4555 if ((mflags & MATCH_QUOTED) == 0)
4556 rep = maybe_expand_string (rep, quoted, expand_string_unsplit);
4557 else
28ef6c31 4558 rep = expand_string_to_string (rep, quoted, expand_string_unsplit);
d166f048 4559 }
ccc6cda3
JA
4560
4561 p = pat;
d166f048 4562 if (pat && pat[0] == '#')
ccc6cda3
JA
4563 {
4564 mflags |= MATCH_BEG;
4565 p++;
4566 }
d166f048 4567 else if (pat && pat[0] == '%')
ccc6cda3
JA
4568 {
4569 mflags |= MATCH_END;
4570 p++;
4571 }
4572 else
4573 mflags |= MATCH_ANY;
4574
cce855bc
JA
4575 /* OK, we now want to substitute REP for PAT in VAL. If
4576 flags & MATCH_GLOBREP is non-zero, the substitution is done
4577 everywhere, otherwise only the first occurrence of PAT is
4578 replaced. */
ccc6cda3
JA
4579 switch (vtype)
4580 {
4581 case VT_VARIABLE:
d166f048 4582 case VT_ARRAYMEMBER:
ccc6cda3
JA
4583 temp = pat_subst (val, p, rep, mflags);
4584 break;
4585 case VT_POSPARMS:
4586 temp = pos_params_pat_subst (val, p, rep, mflags);
4587 break;
4588#if defined (ARRAY_VARS)
4589 case VT_ARRAYVAR:
4590 temp = array_pat_subst (array_cell (v), p, rep, mflags);
4591 break;
4592#endif
4593 }
4594
d166f048
JA
4595 if (val && v && array_p (v) && vtype == VT_ARRAYMEMBER)
4596 free (val);
4597
ccc6cda3
JA
4598 FREE (pat);
4599 FREE (rep);
bb70624e 4600 free (lpatsub);
ccc6cda3
JA
4601
4602 return temp;
4603}
4604
cce855bc
JA
4605/****************************************************************/
4606/* */
4607/* Functions to perform parameter expansion on a string */
4608/* */
4609/****************************************************************/
4610
ccc6cda3
JA
4611/* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
4612static char *
4613parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
4614 char *string;
4615 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
4616{
4617 int check_nullness, var_is_set, var_is_null, var_is_special;
4618 int want_substring, want_indir, want_patsub;
4619 char *name, *value, *temp, *temp1;
4620 int t_index, sindex, c, number;
4621
ccc6cda3
JA
4622 value = (char *)NULL;
4623 var_is_set = var_is_null = var_is_special = check_nullness = 0;
4624 want_substring = want_indir = want_patsub = 0;
4625
cce855bc
JA
4626 sindex = *indexp;
4627 t_index = ++sindex;
4628 name = string_extract (string, &t_index, "#%:-=?+/}", 1);
4629
4630 /* If the name really consists of a special variable, then make sure
4631 that we have the entire name. We don't allow indirect references
4632 to special variables except `#', `?', `@' and `*'. */
4633 if ((sindex == t_index &&
ccc6cda3
JA
4634 (string[t_index] == '-' ||
4635 string[t_index] == '?' ||
cce855bc
JA
4636 string[t_index] == '#')) ||
4637 (sindex == t_index - 1 && string[sindex] == '!' &&
28ef6c31
JA
4638 (string[t_index] == '#' ||
4639 string[t_index] == '?' ||
4640 string[t_index] == '@' ||
4641 string[t_index] == '*')))
ccc6cda3
JA
4642 {
4643 t_index++;
4644 free (name);
4645 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
4646 name = xmalloc (3 + (strlen (temp1)));
4647 *name = string[sindex];
4648 if (string[sindex] == '!')
4649 {
28ef6c31
JA
4650 /* indirect reference of $#, $?, $@, or $* */
4651 name[1] = string[sindex + 1];
4652 strcpy (name + 2, temp1);
ccc6cda3 4653 }
cce855bc 4654 else
ccc6cda3
JA
4655 strcpy (name + 1, temp1);
4656 free (temp1);
4657 }
4658 sindex = t_index;
4659
4660 /* Find out what character ended the variable name. Then
4661 do the appropriate thing. */
4662 if (c = string[sindex])
4663 sindex++;
4664
4665 /* If c is followed by one of the valid parameter expansion
4666 characters, move past it as normal. If not, assume that
4667 a substring specification is being given, and do not move
4668 past it. */
28ef6c31 4669 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
ccc6cda3
JA
4670 {
4671 check_nullness++;
4672 if (c = string[sindex])
4673 sindex++;
4674 }
cce855bc 4675 else if (c == ':' && string[sindex] != RBRACE)
ccc6cda3 4676 want_substring = 1;
cce855bc 4677 else if (c == '/' && string[sindex] != RBRACE)
ccc6cda3
JA
4678 want_patsub = 1;
4679
cce855bc
JA
4680 /* Catch the valid and invalid brace expressions that made it through the
4681 tests above. */
4682 /* ${#-} is a valid expansion and means to take the length of $-.
4683 Similarly for ${#?} and ${##}... */
4684 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
28ef6c31 4685 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
cce855bc
JA
4686 {
4687 name = xrealloc (name, 3);
4688 name[1] = c;
4689 name[2] = '\0';
4690 c = string[sindex++];
4691 }
4692
4693 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
4694 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
4695 member (c, "%:=+/") && string[sindex] == RBRACE)
4696 {
4697 temp = (char *)NULL;
4698 goto bad_substitution;
4699 }
4700
4701 /* Indirect expansion begins with a `!'. A valid indirect expansion is
4702 either a variable name, one of the positional parameters or a special
4703 variable that expands to one of the positional parameters. */
4704 want_indir = *name == '!' &&
28ef6c31
JA
4705 (legal_variable_starter (name[1]) || isdigit (name[1])
4706 || VALID_INDIR_PARAM (name[1]));
ccc6cda3
JA
4707
4708 /* Determine the value of this variable. */
4709
cce855bc 4710 /* Check for special variables, directly referenced. */
bb70624e 4711 if (SPECIAL_VAR (name, want_indir))
ccc6cda3
JA
4712 var_is_special++;
4713
cce855bc
JA
4714 /* Check for special expansion things, like the length of a parameter */
4715 if (*name == '#' && name[1])
ccc6cda3 4716 {
cce855bc 4717 /* If we are not pointing at the character just after the
28ef6c31
JA
4718 closing brace, then we haven't gotten all of the name.
4719 Since it begins with a special character, this is a bad
4720 substitution. Also check NAME for validity before trying
4721 to go on. */
cce855bc 4722 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
ccc6cda3
JA
4723 {
4724 temp = (char *)NULL;
4725 goto bad_substitution;
4726 }
4727
4728 number = parameter_brace_expand_length (name);
4729 free (name);
4730
4731 *indexp = sindex;
4732 return ((number < 0) ? &expand_param_error : itos (number));
4733 }
4734
4735 /* ${@} is identical to $@. */
4736 if (name[0] == '@' && name[1] == '\0')
4737 {
4738 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4739 *quoted_dollar_atp = 1;
4740
4741 if (contains_dollar_at)
4742 *contains_dollar_at = 1;
4743 }
4744
bb70624e
JA
4745 /* Process ${PREFIX*} expansion. */
4746 if (want_indir && string[sindex - 1] == RBRACE &&
4747 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
4748 legal_variable_starter (name[1]))
4749 {
4750 char **x;
4751 WORD_LIST *xlist;
4752
4753 temp1 = savestring (name + 1);
4754 number = strlen (temp1);
4755 temp1[number - 1] = '\0';
4756 x = all_variables_matching_prefix (temp1);
4757 xlist = argv_to_word_list (x, 1, 0);
28ef6c31
JA
4758 if (string[sindex - 2] == '*')
4759 temp = string_list_dollar_star (xlist);
4760 else
4761 {
4762 temp = string_list_dollar_at (xlist, quoted);
4763 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4764 *quoted_dollar_atp = 1;
4765 if (contains_dollar_at)
4766 *contains_dollar_at = 1;
4767 }
bb70624e
JA
4768 free (x);
4769 free (xlist);
4770 free (temp1);
4771 *indexp = sindex;
4772 return (temp);
4773 }
4774
ccc6cda3
JA
4775 /* Make sure that NAME is valid before trying to go on. */
4776 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
4777 var_is_special) == 0)
4778 {
4779 temp = (char *)NULL;
4780 goto bad_substitution;
4781 }
4782
4783 if (want_indir)
4784 temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted);
4785 else
4786 temp = parameter_brace_expand_word (name, var_is_special, quoted);
4787
4788#if defined (ARRAY_VARS)
cce855bc 4789 if (valid_array_reference (name))
ccc6cda3
JA
4790 {
4791 temp1 = strchr (name, '[');
4792 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
28ef6c31 4793 {
ccc6cda3
JA
4794 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4795 *quoted_dollar_atp = 1;
4796 if (contains_dollar_at)
4797 *contains_dollar_at = 1;
cce855bc
JA
4798 } /* [ */
4799 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4800 which should result in separate words even when IFS is unset. */
4801 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4802 {
4803 if (contains_dollar_at)
4804 *contains_dollar_at = 1;
ccc6cda3
JA
4805 }
4806 }
4807#endif
4808
4809 var_is_set = temp != (char *)0;
4810 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
4811
4812 /* Get the rest of the stuff inside the braces. */
cce855bc 4813 if (c && c != RBRACE)
ccc6cda3
JA
4814 {
4815 /* Extract the contents of the ${ ... } expansion
28ef6c31 4816 according to the Posix.2 rules. */
ccc6cda3 4817 value = extract_dollar_brace_string (string, &sindex, quoted);
cce855bc 4818 if (string[sindex] == RBRACE)
28ef6c31 4819 sindex++;
ccc6cda3
JA
4820 else
4821 goto bad_substitution;
4822 }
4823 else
4824 value = (char *)NULL;
726f6388 4825
ccc6cda3
JA
4826 *indexp = sindex;
4827
4828 /* If this is a substring spec, process it and add the result. */
4829 if (want_substring)
726f6388 4830 {
ccc6cda3
JA
4831 temp1 = parameter_brace_substring (name, temp, value, quoted);
4832 FREE (name);
4833 FREE (value);
4834 FREE (temp);
4835 return (temp1);
726f6388 4836 }
ccc6cda3 4837 else if (want_patsub)
726f6388 4838 {
ccc6cda3
JA
4839 temp1 = parameter_brace_patsub (name, temp, value, quoted);
4840 FREE (name);
4841 FREE (value);
4842 FREE (temp);
4843 return (temp1);
4844 }
726f6388 4845
ccc6cda3
JA
4846 /* Do the right thing based on which character ended the variable name. */
4847 switch (c)
4848 {
4849 default:
4850 case '\0':
4851 bad_substitution:
4852 report_error ("%s: bad substitution", string ? string : "??");
4853 FREE (value);
4854 FREE (temp);
4855 free (name);
4856 return &expand_param_error;
4857
cce855bc 4858 case RBRACE:
ccc6cda3 4859 if (var_is_set == 0 && unbound_vars_is_error)
28ef6c31 4860 {
ccc6cda3
JA
4861 report_error ("%s: unbound variable", name);
4862 FREE (value);
4863 FREE (temp);
4864 free (name);
4865 last_command_exit_value = EXECUTION_FAILURE;
d166f048 4866 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
726f6388 4867 }
ccc6cda3 4868 break;
726f6388 4869
ccc6cda3
JA
4870 case '#': /* ${param#[#]pattern} */
4871 case '%': /* ${param%[%]pattern} */
4872 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
28ef6c31
JA
4873 {
4874 FREE (value);
ccc6cda3 4875 break;
28ef6c31 4876 }
ccc6cda3
JA
4877 if ((name[0] == '@' || name[0] == '*') && name[1] == '\0')
4878 temp1 = parameter_list_remove_pattern (value, name[0], c, quoted);
4879#if defined (ARRAY_VARS)
4880 else if (valid_array_reference (name))
4881 temp1 = array_remove_pattern (value, name, temp, c, quoted);
4882#endif
4883 else
4884 temp1 = parameter_brace_remove_pattern (value, temp, c, quoted);
4885 free (temp);
4886 free (value);
4887 temp = temp1;
4888 break;
4889
4890 case '-':
4891 case '=':
4892 case '?':
4893 case '+':
4894 if (var_is_set && var_is_null == 0)
28ef6c31
JA
4895 {
4896 /* If the operator is `+', we don't want the value of the named
4897 variable for anything, just the value of the right hand side. */
bb70624e 4898
ccc6cda3
JA
4899 if (c == '+')
4900 {
28ef6c31
JA
4901 /* XXX -- if we're double-quoted and the named variable is "$@",
4902 we want to turn off any special handling of "$@" --
4903 we're not using it, so whatever is on the rhs applies. */
4904 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4905 *quoted_dollar_atp = 0;
4906 if (contains_dollar_at)
4907 *contains_dollar_at = 0;
4908
ccc6cda3
JA
4909 FREE (temp);
4910 if (value)
28ef6c31 4911 {
ccc6cda3
JA
4912 temp = parameter_brace_expand_rhs (name, value, c,
4913 quoted,
4914 quoted_dollar_atp,
4915 contains_dollar_at);
4916 free (value);
4917 }
4918 else
28ef6c31 4919 temp = (char *)NULL;
ccc6cda3
JA
4920 }
4921 else
4922 {
4923 FREE (value);
4924 }
4925 /* Otherwise do nothing; just use the value in TEMP. */
726f6388 4926 }
ccc6cda3 4927 else /* VAR not set or VAR is NULL. */
28ef6c31 4928 {
ccc6cda3
JA
4929 FREE (temp);
4930 temp = (char *)NULL;
4931 if (c == '=' && var_is_special)
4932 {
4933 report_error ("$%s: cannot assign in this way", name);
4934 free (name);
4935 free (value);
4936 return &expand_param_error;
4937 }
4938 else if (c == '?')
4939 {
4940 parameter_brace_expand_error (name, value);
28ef6c31 4941 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
ccc6cda3
JA
4942 }
4943 else if (c != '+')
28ef6c31
JA
4944 {
4945 /* XXX -- if we're double-quoted and the named variable is "$@",
4946 we want to turn off any special handling of "$@" --
4947 we're not using it, so whatever is on the rhs applies. */
4948 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4949 *quoted_dollar_atp = 0;
4950 if (contains_dollar_at)
4951 *contains_dollar_at = 0;
4952
4953 temp = parameter_brace_expand_rhs (name, value, c, quoted,
4954 quoted_dollar_atp,
4955 contains_dollar_at);
4956 }
ccc6cda3 4957 free (value);
726f6388 4958 }
28ef6c31 4959
ccc6cda3 4960 break;
726f6388 4961 }
ccc6cda3
JA
4962 free (name);
4963 return (temp);
726f6388
JA
4964}
4965
cce855bc
JA
4966/* Expand a single ${xxx} expansion. The braces are optional. When
4967 the braces are used, parameter_brace_expand() does the work,
4968 possibly calling param_expand recursively. */
4969static char *
4970param_expand (string, sindex, quoted, expanded_something,
4971 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
4972 pflags)
4973 char *string;
4974 int *sindex, quoted, *expanded_something, *contains_dollar_at;
4975 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
4976{
4977 char *temp, *temp1;
4978 int zindex, number, c, t_index, expok;
4979 SHELL_VAR *var;
4980 WORD_LIST *list, *tlist;
4981
4982 zindex = *sindex;
4983 c = string[++zindex];
4984
4985 temp = (char *)NULL;
4986
4987 /* Do simple cases first. Switch on what follows '$'. */
4988 switch (c)
4989 {
4990 /* $0 .. $9? */
4991 case '0':
4992 case '1':
4993 case '2':
4994 case '3':
4995 case '4':
4996 case '5':
4997 case '6':
4998 case '7':
4999 case '8':
5000 case '9':
5001 temp1 = dollar_vars[digit_value (c)];
5002 if (unbound_vars_is_error && temp1 == (char *)NULL)
5003 {
5004 report_error ("$%c: unbound variable", c);
5005 last_command_exit_value = EXECUTION_FAILURE;
5006 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5007 }
5008 temp = temp1 ? savestring (temp1) : (char *)NULL;
5009 break;
5010
5011 /* $$ -- pid of the invoking shell. */
5012 case '$':
5013 temp = itos (dollar_dollar_pid);
5014 break;
5015
5016 /* $# -- number of positional parameters. */
5017 case '#':
5018 temp = itos (number_of_args ());
5019 break;
5020
5021 /* $? -- return value of the last synchronous command. */
5022 case '?':
5023 temp = itos (last_command_exit_value);
5024 break;
5025
5026 /* $- -- flags supplied to the shell on invocation or by `set'. */
5027 case '-':
5028 temp = which_set_flags ();
5029 break;
5030
5031 /* $! -- Pid of the last asynchronous command. */
5032 case '!':
5033 /* If no asynchronous pids have been created, expand to nothing.
5034 If `set -u' has been executed, and no async processes have
5035 been created, this is an expansion error. */
5036 if (last_asynchronous_pid == NO_PID)
5037 {
5038 if (expanded_something)
5039 *expanded_something = 0;
5040 temp = (char *)NULL;
5041 if (unbound_vars_is_error)
5042 {
5043 report_error ("$%c: unbound variable", c);
5044 last_command_exit_value = EXECUTION_FAILURE;
5045 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
5046 }
5047 }
5048 else
5049 temp = itos ((int)last_asynchronous_pid);
5050 break;
5051
5052 /* The only difference between this and $@ is when the arg is quoted. */
5053 case '*': /* `$*' */
5054 list = list_rest_of_args ();
5055
5056 /* If there are no command-line arguments, this should just
5057 disappear if there are other characters in the expansion,
5058 even if it's quoted. */
5059 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
5060 temp = (char *)NULL;
5061 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5062 {
5063 /* If we have "$*" we want to make a string of the positional
5064 parameters, separated by the first character of $IFS, and
5065 quote the whole string, including the separators. If IFS
5066 is unset, the parameters are separated by ' '; if $IFS is
5067 null, the parameters are concatenated. */
5068 temp = string_list_dollar_star (list);
5069 temp1 = quote_string (temp);
5070 free (temp);
5071 temp = temp1;
5072 }
5073 else
28ef6c31
JA
5074 {
5075 /* If the $* is not quoted it is identical to $@ */
5076 temp = string_list_dollar_at (list, quoted);
5077 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
5078 *contains_dollar_at = 1;
5079 }
cce855bc
JA
5080
5081 dispose_words (list);
5082 break;
5083
5084 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
5085 means that we have to turn quoting off after we split into
5086 the individually quoted arguments so that the final split
5087 on the first character of $IFS is still done. */
5088 case '@': /* `$@' */
5089 list = list_rest_of_args ();
5090
5091 /* We want to flag the fact that we saw this. We can't turn
5092 off quoting entirely, because other characters in the
5093 string might need it (consider "\"$@\""), but we need some
5094 way to signal that the final split on the first character
5095 of $IFS should be done, even though QUOTED is 1. */
5096 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
5097 *quoted_dollar_at_p = 1;
5098 if (contains_dollar_at)
5099 *contains_dollar_at = 1;
5100
5101 /* We want to separate the positional parameters with the first
5102 character of $IFS in case $IFS is something other than a space.
5103 We also want to make sure that splitting is done no matter what --
5104 according to POSIX.2, this expands to a list of the positional
5105 parameters no matter what IFS is set to. */
5106 temp = string_list_dollar_at (list, quoted);
5107
5108 dispose_words (list);
5109 break;
5110
5111 case LBRACE:
5112 temp = parameter_brace_expand (string, &zindex, quoted,
5113 quoted_dollar_at_p,
5114 contains_dollar_at);
5115 if (temp == &expand_param_error || temp == &expand_param_fatal)
5116 return (temp);
5117
5118 /* XXX */
bb70624e 5119 /* Quoted nulls should be removed if there is anything else
cce855bc
JA
5120 in the string. */
5121 /* Note that we saw the quoted null so we can add one back at
5122 the end of this function if there are no other characters
28ef6c31
JA
5123 in the string, discard TEMP, and go on. The exception to
5124 this is when we have "${@}" and $1 is '', since $@ needs
5125 special handling. */
cce855bc
JA
5126 if (temp && QUOTED_NULL (temp))
5127 {
5128 if (had_quoted_null_p)
5129 *had_quoted_null_p = 1;
28ef6c31
JA
5130 if (*quoted_dollar_at_p == 0)
5131 {
5132 free (temp);
5133 temp = (char *)NULL;
5134 }
5135
cce855bc
JA
5136 }
5137
5138 goto return0;
5139
5140 /* Do command or arithmetic substitution. */
5141 case LPAREN:
5142 /* We have to extract the contents of this paren substitution. */
5143 t_index = zindex + 1;
5144 temp = extract_command_subst (string, &t_index);
5145 zindex = t_index;
5146
5147 /* For Posix.2-style `$(( ))' arithmetic substitution,
28ef6c31 5148 extract the expression and pass it to the evaluator. */
cce855bc
JA
5149 if (temp && *temp == LPAREN)
5150 {
5151 char *temp2;
5152 temp1 = temp + 1;
5153 temp2 = savestring (temp1);
5154 t_index = strlen (temp2) - 1;
5155
5156 if (temp2[t_index] != RPAREN)
5157 {
5158 free (temp2);
5159 goto comsub;
5160 }
5161
5162 /* Cut off ending `)' */
5163 temp2[t_index] = '\0';
5164
5165 /* Expand variables found inside the expression. */
5166 temp1 = maybe_expand_string (temp2, Q_DOUBLE_QUOTES, expand_string);
5167 free (temp2);
5168
5169arithsub:
5170 /* No error messages. */
5171 this_command_name = (char *)NULL;
5172 number = evalexp (temp1, &expok);
5173 free (temp);
5174 free (temp1);
5175 if (expok == 0)
5176 {
5177 if (interactive_shell == 0 && posixly_correct)
5178 {
5179 last_command_exit_value = EXECUTION_FAILURE;
5180 return (&expand_param_fatal);
5181 }
5182 else
5183 return (&expand_param_error);
5184 }
5185 temp = itos (number);
5186 break;
5187 }
5188
5189comsub:
5190 temp1 = command_substitute (temp, quoted);
5191 FREE (temp);
5192 temp = temp1;
5193 break;
5194
5195 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
5196 away in a future bash release. */
5197 case '[':
bb70624e 5198 /* Extract the contents of this arithmetic substitution. */
cce855bc
JA
5199 t_index = zindex + 1;
5200 temp = extract_arithmetic_subst (string, &t_index);
5201 zindex = t_index;
5202
5203 /* Do initial variable expansion. */
5204 temp1 = maybe_expand_string (temp, Q_DOUBLE_QUOTES, expand_string);
5205
5206 goto arithsub;
5207
5208 default:
5209 /* Find the variable in VARIABLE_LIST. */
5210 temp = (char *)NULL;
5211
5212 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
5213 ;
5214 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
5215
5216 /* If this isn't a variable name, then just output the `$'. */
5217 if (temp1 == 0 || *temp1 == '\0')
5218 {
5219 FREE (temp1);
5220 temp = xmalloc (2);
5221 temp[0] = '$';
5222 temp[1] = '\0';
5223 if (expanded_something)
5224 *expanded_something = 0;
5225 goto return0;
5226 }
5227
5228 /* If the variable exists, return its value cell. */
5229 var = find_variable (temp1);
5230
5231 if (var && invisible_p (var) == 0 && value_cell (var))
5232 {
5233#if defined (ARRAY_VARS)
5234 if (array_p (var))
5235 {
5236 temp = array_reference (array_cell (var), 0);
5237 if (temp)
5238 temp = quote_escapes (temp);
5239 }
5240 else
5241#endif
5242 temp = quote_escapes (value_cell (var));
5243 free (temp1);
5244 if (tempvar_p (var)) /* XXX */
5245 {
5246 dispose_variable (var); /* XXX */
5247 var = (SHELL_VAR *)NULL;
5248 }
5249 goto return0;
5250 }
5251
5252 temp = (char *)NULL;
5253
5254 if (unbound_vars_is_error)
5255 report_error ("%s: unbound variable", temp1);
5256 else
5257 {
5258 free (temp1);
5259 goto return0;
5260 }
5261
5262 free (temp1);
5263 last_command_exit_value = EXECUTION_FAILURE;
5264 return ((unbound_vars_is_error && interactive_shell == 0)
5265 ? &expand_param_fatal
5266 : &expand_param_error);
5267 }
5268
5269 if (string[zindex])
5270 zindex++;
5271
5272return0:
5273 *sindex = zindex;
5274 return (temp);
5275}
5276
5277/* Make a word list which is the result of parameter and variable
5278 expansion, command substitution, arithmetic substitution, and
5279 quote removal of WORD. Return a pointer to a WORD_LIST which is
5280 the result of the expansion. If WORD contains a null word, the
5281 word list returned is also null.
726f6388 5282
ccc6cda3
JA
5283 QUOTED contains flag values defined in shell.h.
5284
b72432fd
JA
5285 ISEXP is used to tell expand_word_internal that the word should be
5286 treated as the result of an expansion. This has implications for
5287 how IFS characters in the word are treated.
5288
726f6388
JA
5289 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
5290 they point to an integer value which receives information about expansion.
5291 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
5292 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
5293 else zero.
5294
5295 This only does word splitting in the case of $@ expansion. In that
5296 case, we split on ' '. */
5297
5298/* Values for the local variable quoted_state. */
5299#define UNQUOTED 0
5300#define PARTIALLY_QUOTED 1
5301#define WHOLLY_QUOTED 2
5302
5303static WORD_LIST *
b72432fd 5304expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
726f6388 5305 WORD_DESC *word;
b72432fd 5306 int quoted, isexp;
726f6388
JA
5307 int *contains_dollar_at;
5308 int *expanded_something;
5309{
ccc6cda3
JA
5310 WORD_LIST *list;
5311 WORD_DESC *tword;
5312 SHELL_VAR *var;
726f6388
JA
5313
5314 /* The intermediate string that we build while expanding. */
ccc6cda3 5315 char *istring;
726f6388
JA
5316
5317 /* The current size of the above object. */
ccc6cda3 5318 int istring_size;
726f6388
JA
5319
5320 /* Index into ISTRING. */
ccc6cda3 5321 int istring_index;
726f6388
JA
5322
5323 /* Temporary string storage. */
ccc6cda3 5324 char *temp, *temp1;
726f6388
JA
5325
5326 /* The text of WORD. */
ccc6cda3 5327 register char *string;
726f6388
JA
5328
5329 /* The index into STRING. */
ccc6cda3 5330 int sindex;
726f6388
JA
5331
5332 /* This gets 1 if we see a $@ while quoted. */
ccc6cda3 5333 int quoted_dollar_at;
726f6388
JA
5334
5335 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
5336 whether WORD contains no quoting characters, a partially quoted
5337 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
ccc6cda3
JA
5338 int quoted_state;
5339
5340 int had_quoted_null;
cce855bc 5341 int has_dollar_at;
28ef6c31 5342 int tflag;
726f6388
JA
5343
5344 register int c; /* Current character. */
5345 int number; /* Temporary number value. */
5346 int t_index; /* For calls to string_extract_xxx. */
726f6388 5347
b72432fd 5348 char ifscmap[256];
bb70624e 5349 char twochars[2];
b72432fd 5350
d166f048 5351 istring = xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
ccc6cda3 5352 istring[istring_index = 0] = '\0';
cce855bc 5353 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
ccc6cda3
JA
5354 quoted_state = UNQUOTED;
5355
5356 string = word->word;
5357 if (string == 0)
5358 goto finished_with_string;
726f6388
JA
5359
5360 if (contains_dollar_at)
5361 *contains_dollar_at = 0;
5362
b72432fd
JA
5363 /* Cache a bitmap of characters in IFS for quoting IFS characters that are
5364 not part of an expansion. POSIX.2 says this is a must. */
5365 temp = getifs ();
5366 bzero (ifscmap, sizeof (ifscmap));
5367 for (temp1 = temp; temp1 && *temp1; temp1++)
5368#if 0
5369 /* This check compensates for what I think is a parsing problem -- the
5370 end brace matching algorithms for ${...} expressions differ between
5371 parse.y and subst.c. For instance, the parser passes
5372 ${abc:-G { I } K } as one word when it should be three. */
5373 if (*temp1 != ' ' && *temp1 != '\t' && *temp1 != '\n')
5374#endif
bb70624e 5375 ifscmap[(unsigned char)*temp1] = 1;
b72432fd 5376
726f6388
JA
5377 /* Begin the expansion. */
5378
ccc6cda3 5379 for (sindex = 0; ;)
726f6388
JA
5380 {
5381 c = string[sindex];
5382
5383 /* Case on toplevel character. */
5384 switch (c)
5385 {
5386 case '\0':
5387 goto finished_with_string;
5388
5389 case CTLESC:
5390 temp = xmalloc (3);
5391 temp[0] = CTLESC;
5392 temp[1] = c = string[++sindex];
5393 temp[2] = '\0';
5394
cce855bc 5395dollar_add_string:
726f6388
JA
5396 if (string[sindex])
5397 sindex++;
5398
cce855bc
JA
5399add_string:
5400 if (temp)
5401 {
5402 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
5403 temp = (char *)0;
5404 }
5405
5406 break;
726f6388
JA
5407
5408#if defined (PROCESS_SUBSTITUTION)
5409 /* Process substitution. */
5410 case '<':
5411 case '>':
5412 {
cce855bc 5413 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
726f6388 5414 {
bb70624e 5415 sindex--; /* add_character: label increments sindex */
726f6388
JA
5416 goto add_character;
5417 }
5418 else
cce855bc 5419 t_index = sindex + 1; /* skip past both '<' and LPAREN */
726f6388 5420
cce855bc 5421 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
ccc6cda3 5422 sindex = t_index;
726f6388
JA
5423
5424 /* If the process substitution specification is `<()', we want to
5425 open the pipe for writing in the child and produce output; if
5426 it is `>()', we want to open the pipe for reading in the child
5427 and consume input. */
ccc6cda3 5428 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
726f6388
JA
5429
5430 FREE (temp1);
5431
5432 goto dollar_add_string;
5433 }
5434#endif /* PROCESS_SUBSTITUTION */
5435
726f6388 5436 case '$':
726f6388
JA
5437 if (expanded_something)
5438 *expanded_something = 1;
5439
cce855bc
JA
5440 has_dollar_at = 0;
5441 temp = param_expand (string, &sindex, quoted, expanded_something,
5442 &has_dollar_at, &quoted_dollar_at,
5443 &had_quoted_null, 0);
726f6388 5444
cce855bc 5445 if (temp == &expand_param_error || temp == &expand_param_fatal)
726f6388 5446 {
cce855bc
JA
5447 free (string);
5448 free (istring);
5449 return ((temp == &expand_param_error) ? &expand_word_error
5450 : &expand_word_fatal);
5451 }
5452 if (contains_dollar_at && has_dollar_at)
5453 *contains_dollar_at = 1;
5454 goto add_string;
5455 break;
726f6388 5456
cce855bc
JA
5457 case '`': /* Backquoted command substitution. */
5458 {
5459 sindex++;
726f6388 5460
cce855bc
JA
5461 if (expanded_something)
5462 *expanded_something = 1;
726f6388 5463
cce855bc
JA
5464 temp = string_extract (string, &sindex, "`", 0);
5465 de_backslash (temp);
5466 temp1 = command_substitute (temp, quoted);
5467 FREE (temp);
5468 temp = temp1;
5469 goto dollar_add_string;
5470 }
ccc6cda3 5471
cce855bc
JA
5472 case '\\':
5473 if (string[sindex + 1] == '\n')
5474 {
5475 sindex += 2;
5476 continue;
5477 }
726f6388 5478
cce855bc 5479 c = string[++sindex];
726f6388 5480
cce855bc 5481 if (quoted & Q_HERE_DOCUMENT)
28ef6c31 5482 tflag = CBSHDOC;
cce855bc 5483 else if (quoted & Q_DOUBLE_QUOTES)
28ef6c31 5484 tflag = CBSDQUOTE;
cce855bc 5485 else
28ef6c31
JA
5486 tflag = 0;
5487
726f6388 5488
28ef6c31 5489 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
cce855bc 5490 {
bb70624e
JA
5491 twochars[0] = '\\';
5492 twochars[1] = c;
5493 }
5494 else if (c == 0)
5495 {
5496 c = CTLNUL;
5497 sindex--; /* add_character: label increments sindex */
5498 goto add_character;
cce855bc
JA
5499 }
5500 else
bb70624e
JA
5501 {
5502 twochars[0] = CTLESC;
5503 twochars[1] = c;
5504 }
726f6388 5505
bb70624e
JA
5506 sindex++;
5507add_twochars:
5508 /* BEFORE jumping here, we need to increment sindex if appropriate */
5509 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
5510 DEFAULT_ARRAY_SIZE);
5511 istring[istring_index++] = twochars[0];
5512 istring[istring_index++] = twochars[1];
5513 istring[istring_index] = '\0';
5514
5515 break;
726f6388 5516
cce855bc
JA
5517 case '"':
5518 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
5519 goto add_character;
ccc6cda3
JA
5520
5521 t_index = ++sindex;
5522 temp = string_extract_double_quoted (string, &sindex, 0);
5523
5524 /* If the quotes surrounded the entire string, then the
5525 whole word was quoted. */
5526 quoted_state = (t_index == 1 && string[sindex] == '\0')
5527 ? WHOLLY_QUOTED
5528 : PARTIALLY_QUOTED;
5529
5530 if (temp && *temp)
726f6388 5531 {
ccc6cda3
JA
5532 tword = make_word (temp); /* XXX */
5533 free (temp);
5534 temp = (char *)NULL;
5535
cce855bc 5536 has_dollar_at = 0;
b72432fd 5537 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
726f6388 5538
ccc6cda3
JA
5539 if (list == &expand_word_error || list == &expand_word_fatal)
5540 {
5541 free (istring);
5542 free (string);
5543 /* expand_word_internal has already freed temp_word->word
5544 for us because of the way it prints error messages. */
5545 tword->word = (char *)NULL;
5546 dispose_word (tword);
5547 return list;
5548 }
726f6388 5549
ccc6cda3 5550 dispose_word (tword);
726f6388 5551
ccc6cda3
JA
5552 /* "$@" (a double-quoted dollar-at) expands into nothing,
5553 not even a NULL word, when there are no positional
5554 parameters. */
cce855bc 5555 if (list == 0 && has_dollar_at)
726f6388 5556 {
ccc6cda3
JA
5557 quoted_dollar_at++;
5558 break;
5559 }
5560
5561 /* If we get "$@", we know we have expanded something, so we
5562 need to remember it for the final split on $IFS. This is
5563 a special case; it's the only case where a quoted string
5564 can expand into more than one word. It's going to come back
5565 from the above call to expand_word_internal as a list with
5566 a single word, in which all characters are quoted and
5567 separated by blanks. What we want to do is to turn it back
5568 into a list for the next piece of code. */
5569 if (list)
5570 dequote_list (list);
5571
cce855bc 5572 if (has_dollar_at)
ccc6cda3
JA
5573 {
5574 quoted_dollar_at++;
5575 if (contains_dollar_at)
5576 *contains_dollar_at = 1;
5577 if (expanded_something)
5578 *expanded_something = 1;
5579 }
5580 }
5581 else
5582 {
5583 /* What we have is "". This is a minor optimization. */
5584 free (temp);
5585 list = (WORD_LIST *)NULL;
5586 }
5587
5588 /* The code above *might* return a list (consider the case of "$@",
5589 where it returns "$1", "$2", etc.). We can't throw away the
5590 rest of the list, and we have to make sure each word gets added
5591 as quoted. We test on tresult->next: if it is non-NULL, we
5592 quote the whole list, save it to a string with string_list, and
5593 add that string. We don't need to quote the results of this
5594 (and it would be wrong, since that would quote the separators
5595 as well), so we go directly to add_string. */
5596 if (list)
5597 {
5598 if (list->next)
5599 {
bc4cd23c
JA
5600 /* Testing quoted_dollar_at makes sure that "$@" is
5601 split correctly when $IFS does not contain a space. */
5602 temp = quoted_dollar_at
5603 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
5604 : string_list (quote_list (list));
ccc6cda3 5605 dispose_words (list);
726f6388
JA
5606 goto add_string;
5607 }
5608 else
5609 {
ccc6cda3
JA
5610 temp = savestring (list->word->word);
5611 dispose_words (list);
cce855bc
JA
5612#if 1
5613 /* If the string is not a quoted null string, we want
5614 to remove any embedded unquoted CTLNUL characters.
5615 We do not want to turn quoted null strings back into
5616 the empty string, though. We do this because we
5617 want to remove any quoted nulls from expansions that
5618 contain other characters. For example, if we have
5619 x"$*"y or "x$*y" and there are no positional parameters,
5620 the $* should expand into nothing. */
5621 if (QUOTED_NULL (temp) == 0)
5622 remove_quoted_nulls (temp); /* XXX */
5623#endif
726f6388
JA
5624 }
5625 }
ccc6cda3
JA
5626 else
5627 temp = (char *)NULL;
726f6388 5628
ccc6cda3
JA
5629 /* We do not want to add quoted nulls to strings that are only
5630 partially quoted; we can throw them away. */
5631 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
cce855bc 5632 continue;
726f6388 5633
ccc6cda3 5634 add_quoted_string:
726f6388 5635
ccc6cda3
JA
5636 if (temp)
5637 {
5638 temp1 = temp;
5639 temp = quote_string (temp);
5640 free (temp1);
bb70624e 5641 goto add_string;
ccc6cda3
JA
5642 }
5643 else
5644 {
5645 /* Add NULL arg. */
bb70624e
JA
5646 c = CTLNUL;
5647 sindex--; /* add_character: label increments sindex */
5648 goto add_character;
ccc6cda3 5649 }
bb70624e 5650
ccc6cda3 5651 /* break; */
726f6388 5652
ccc6cda3
JA
5653 case '\'':
5654 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
5655 goto add_character;
726f6388 5656
ccc6cda3
JA
5657 t_index = ++sindex;
5658 temp = string_extract_single_quoted (string, &sindex);
726f6388 5659
ccc6cda3
JA
5660 /* If the entire STRING was surrounded by single quotes,
5661 then the string is wholly quoted. */
5662 quoted_state = (t_index == 1 && string[sindex] == '\0')
5663 ? WHOLLY_QUOTED
5664 : PARTIALLY_QUOTED;
726f6388 5665
ccc6cda3
JA
5666 /* If all we had was '', it is a null expansion. */
5667 if (*temp == '\0')
5668 {
5669 free (temp);
5670 temp = (char *)NULL;
5671 }
5672 else
5673 remove_quoted_escapes (temp);
726f6388 5674
ccc6cda3
JA
5675 /* We do not want to add quoted nulls to strings that are only
5676 partially quoted; such nulls are discarded. */
5677 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
5678 continue;
726f6388 5679
bb70624e
JA
5680 /* If we have a quoted null expansion, add a quoted NULL to istring. */
5681 if (temp == 0)
5682 {
5683 c = CTLNUL;
5684 sindex--; /* add_character: label increments sindex */
5685 goto add_character;
5686 }
5687 else
5688 goto add_quoted_string;
5689
ccc6cda3 5690 /* break; */
726f6388
JA
5691
5692 default:
726f6388 5693 /* This is the fix for " $@ " */
b72432fd 5694 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && ifscmap[c]))
726f6388 5695 {
bb70624e
JA
5696 if (string[sindex]) /* from old goto dollar_add_string */
5697 sindex++;
5698 if (c == 0)
5699 {
5700 c = CTLNUL;
5701 goto add_character;
5702 }
5703 else
5704 {
5705 twochars[0] = CTLESC;
5706 twochars[1] = c;
5707 goto add_twochars;
5708 }
726f6388
JA
5709 }
5710
5711 add_character:
ccc6cda3
JA
5712 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
5713 DEFAULT_ARRAY_SIZE);
726f6388
JA
5714 istring[istring_index++] = c;
5715 istring[istring_index] = '\0';
5716
5717 /* Next character. */
5718 sindex++;
5719 }
5720 }
5721
5722finished_with_string:
726f6388
JA
5723 /* OK, we're ready to return. If we have a quoted string, and
5724 quoted_dollar_at is not set, we do no splitting at all; otherwise
5725 we split on ' '. The routines that call this will handle what to
5726 do if nothing has been expanded. */
ccc6cda3
JA
5727
5728 /* Partially and wholly quoted strings which expand to the empty
5729 string are retained as an empty arguments. Unquoted strings
5730 which expand to the empty string are discarded. The single
5731 exception is the case of expanding "$@" when there are no
5732 positional parameters. In that case, we discard the expansion. */
5733
5734 /* Because of how the code that handles "" and '' in partially
5735 quoted strings works, we need to make ISTRING into a QUOTED_NULL
5736 if we saw quoting characters, but the expansion was empty.
5737 "" and '' are tossed away before we get to this point when
5738 processing partially quoted strings. This makes "" and $xxx""
5739 equivalent when xxx is unset. We also look to see whether we
5740 saw a quoted null from a ${} expansion and add one back if we
5741 need to. */
5742
5743 /* If we expand to nothing and there were no single or double quotes
5744 in the word, we throw it away. Otherwise, we return a NULL word.
5745 The single exception is for $@ surrounded by double quotes when
5746 there are no positional parameters. In that case, we also throw
5747 the word away. */
5748
5749 if (*istring == '\0')
5750 {
5751 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
726f6388 5752 {
726f6388
JA
5753 istring[0] = CTLNUL;
5754 istring[1] = '\0';
ccc6cda3
JA
5755 tword = make_bare_word (istring);
5756 list = make_word_list (tword, (WORD_LIST *)NULL);
5757 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5758 tword->flags |= W_QUOTED;
726f6388 5759 }
ccc6cda3
JA
5760 /* According to sh, ksh, and Posix.2, if a word expands into nothing
5761 and a double-quoted "$@" appears anywhere in it, then the entire
5762 word is removed. */
5763 else if (quoted_state == UNQUOTED || quoted_dollar_at)
5764 list = (WORD_LIST *)NULL;
5765#if 0
5766 else
726f6388 5767 {
ccc6cda3
JA
5768 tword = make_bare_word (istring);
5769 list = make_word_list (tword, (WORD_LIST *)NULL);
5770 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5771 tword->flags |= W_QUOTED;
726f6388 5772 }
ccc6cda3
JA
5773#endif
5774 }
5775 else if (word->flags & W_NOSPLIT)
5776 {
5777 tword = make_bare_word (istring);
5778 list = make_word_list (tword, (WORD_LIST *)NULL);
5779 if (word->flags & W_ASSIGNMENT)
5780 tword->flags |= W_ASSIGNMENT; /* XXX */
b72432fd
JA
5781 if (word->flags & W_NOGLOB)
5782 tword->flags |= W_NOGLOB; /* XXX */
ccc6cda3 5783 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
28ef6c31 5784 tword->flags |= W_QUOTED;
ccc6cda3
JA
5785 }
5786 else
5787 {
5788 char *ifs_chars;
5789
b72432fd 5790 ifs_chars = (quoted_dollar_at || has_dollar_at) ? getifs () : (char *)NULL;
726f6388 5791
cce855bc
JA
5792 /* If we have $@, we need to split the results no matter what. If
5793 IFS is unset or NULL, string_list_dollar_at has separated the
5794 positional parameters with a space, so we split on space (we have
5795 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
5796 string_list_dollar_at has separated the positional parameters
5797 with the first character of $IFS, so we split on $IFS. */
5798 if (has_dollar_at && ifs_chars)
5799 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
ccc6cda3
JA
5800 else
5801 {
5802 tword = make_bare_word (istring);
5803 list = make_word_list (tword, (WORD_LIST *)NULL);
5804 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
5805 tword->flags |= W_QUOTED;
5806 if (word->flags & W_ASSIGNMENT)
5807 tword->flags |= W_ASSIGNMENT;
b72432fd
JA
5808 if (word->flags & W_NOGLOB)
5809 tword->flags |= W_NOGLOB;
726f6388 5810 }
726f6388 5811 }
726f6388 5812
ccc6cda3
JA
5813 free (istring);
5814 return (list);
726f6388
JA
5815}
5816
5817/* **************************************************************** */
5818/* */
5819/* Functions for Quote Removal */
5820/* */
5821/* **************************************************************** */
5822
5823/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
5824 backslash quoting rules for within double quotes. */
5825char *
5826string_quote_removal (string, quoted)
5827 char *string;
5828 int quoted;
5829{
ccc6cda3 5830 char *r, *result_string, *temp;
726f6388
JA
5831 int sindex, tindex, c, dquote;
5832
5833 /* The result can be no longer than the original string. */
5834 r = result_string = xmalloc (strlen (string) + 1);
5835
ccc6cda3 5836 for (dquote = sindex = 0; c = string[sindex];)
726f6388
JA
5837 {
5838 switch (c)
5839 {
5840 case '\\':
5841 c = string[++sindex];
28ef6c31 5842 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
726f6388 5843 *r++ = '\\';
ccc6cda3 5844 /* FALLTHROUGH */
726f6388
JA
5845
5846 default:
5847 *r++ = c;
5848 sindex++;
5849 break;
5850
5851 case '\'':
ccc6cda3 5852 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
726f6388
JA
5853 {
5854 *r++ = c;
5855 sindex++;
ccc6cda3 5856 break;
726f6388 5857 }
ccc6cda3
JA
5858 tindex = sindex + 1;
5859 temp = string_extract_single_quoted (string, &tindex);
5860 if (temp)
726f6388 5861 {
ccc6cda3
JA
5862 strcpy (r, temp);
5863 r += strlen (r);
5864 free (temp);
726f6388 5865 }
ccc6cda3 5866 sindex = tindex;
726f6388
JA
5867 break;
5868
5869 case '"':
5870 dquote = 1 - dquote;
5871 sindex++;
5872 break;
5873 }
5874 }
5875 *r = '\0';
5876 return (result_string);
5877}
5878
ccc6cda3
JA
5879#if 0
5880/* UNUSED */
726f6388
JA
5881/* Perform quote removal on word WORD. This allocates and returns a new
5882 WORD_DESC *. */
5883WORD_DESC *
5884word_quote_removal (word, quoted)
5885 WORD_DESC *word;
5886 int quoted;
5887{
5888 WORD_DESC *w;
5889 char *t;
5890
5891 t = string_quote_removal (word->word, quoted);
ccc6cda3 5892 w = make_bare_word (t);
d166f048 5893 free (t);
726f6388
JA
5894 return (w);
5895}
5896
5897/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
5898 the members of the list are treated as if they are surrounded by
5899 double quotes. Return a new list, or NULL if LIST is NULL. */
5900WORD_LIST *
5901word_list_quote_removal (list, quoted)
5902 WORD_LIST *list;
5903 int quoted;
5904{
ccc6cda3 5905 WORD_LIST *result, *t, *tresult;
726f6388 5906
ccc6cda3 5907 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
726f6388
JA
5908 {
5909 tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
5910 tresult->word = word_quote_removal (t->word, quoted);
5911 tresult->next = (WORD_LIST *)NULL;
5912 result = (WORD_LIST *) list_append (result, tresult);
726f6388
JA
5913 }
5914 return (result);
5915}
ccc6cda3 5916#endif
726f6388 5917
726f6388
JA
5918/*******************************************
5919 * *
5920 * Functions to perform word splitting *
5921 * *
5922 *******************************************/
5923
b72432fd
JA
5924static char *
5925getifs ()
5926{
5927 SHELL_VAR *ifs;
5928
5929 ifs = find_variable ("IFS");
5930 /* If IFS is unset, it defaults to " \t\n". */
5931 return (ifs ? value_cell (ifs) : " \t\n");
5932}
5933
726f6388
JA
5934/* This splits a single word into a WORD LIST on $IFS, but only if the word
5935 is not quoted. list_string () performs quote removal for us, even if we
5936 don't do any splitting. */
5937WORD_LIST *
5938word_split (w)
5939 WORD_DESC *w;
5940{
5941 WORD_LIST *result;
ccc6cda3
JA
5942 SHELL_VAR *ifs;
5943 char *ifs_chars;
726f6388
JA
5944
5945 if (w)
5946 {
ccc6cda3 5947 ifs = find_variable ("IFS");
726f6388 5948 /* If IFS is unset, it defaults to " \t\n". */
ccc6cda3 5949 ifs_chars = ifs ? value_cell (ifs) : " \t\n";
726f6388 5950
ccc6cda3 5951 if ((w->flags & W_QUOTED) || !ifs_chars)
726f6388
JA
5952 ifs_chars = "";
5953
ccc6cda3 5954 result = list_string (w->word, ifs_chars, w->flags & W_QUOTED);
cce855bc
JA
5955
5956 if (ifs && tempvar_p (ifs)) /* XXX */
5957 dispose_variable (ifs); /* XXX */
726f6388
JA
5958 }
5959 else
5960 result = (WORD_LIST *)NULL;
ccc6cda3 5961
726f6388
JA
5962 return (result);
5963}
5964
5965/* Perform word splitting on LIST and return the RESULT. It is possible
5966 to return (WORD_LIST *)NULL. */
5967static WORD_LIST *
5968word_list_split (list)
5969 WORD_LIST *list;
5970{
ccc6cda3 5971 WORD_LIST *result, *t, *tresult;
726f6388 5972
ccc6cda3 5973 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
726f6388
JA
5974 {
5975 tresult = word_split (t->word);
5976 result = (WORD_LIST *) list_append (result, tresult);
726f6388
JA
5977 }
5978 return (result);
5979}
5980
5981/**************************************************
5982 * *
cce855bc 5983 * Functions to expand an entire WORD_LIST *
726f6388
JA
5984 * *
5985 **************************************************/
5986
cce855bc
JA
5987/* Put NLIST (which is a WORD_LIST * of only one element) at the front of
5988 ELIST, and set ELIST to the new list. */
5989#define PREPEND_LIST(nlist, elist) \
5990 do { nlist->next = elist; elist = nlist; } while (0)
5991
726f6388
JA
5992/* Separate out any initial variable assignments from TLIST. If set -k has
5993 been executed, remove all assignment statements from TLIST. Initial
5994 variable assignments and other environment assignments are placed
bb70624e 5995 on SUBST_ASSIGN_VARLIST. */
726f6388
JA
5996static WORD_LIST *
5997separate_out_assignments (tlist)
5998 WORD_LIST *tlist;
5999{
6000 register WORD_LIST *vp, *lp;
6001
6002 if (!tlist)
6003 return ((WORD_LIST *)NULL);
6004
bb70624e
JA
6005 if (subst_assign_varlist)
6006 dispose_words (subst_assign_varlist); /* Clean up after previous error */
b72432fd 6007
bb70624e 6008 subst_assign_varlist = (WORD_LIST *)NULL;
726f6388
JA
6009 vp = lp = tlist;
6010
6011 /* Separate out variable assignments at the start of the command.
6012 Loop invariant: vp->next == lp
6013 Loop postcondition:
6014 lp = list of words left after assignment statements skipped
6015 tlist = original list of words
6016 */
ccc6cda3 6017 while (lp && (lp->word->flags & W_ASSIGNMENT))
726f6388
JA
6018 {
6019 vp = lp;
6020 lp = lp->next;
6021 }
6022
bb70624e
JA
6023 /* If lp != tlist, we have some initial assignment statements.
6024 We make SUBST_ASSIGN_VARLIST point to the list of assignment
6025 words and TLIST point to the remaining words. */
726f6388
JA
6026 if (lp != tlist)
6027 {
bb70624e 6028 subst_assign_varlist = tlist;
726f6388
JA
6029 /* ASSERT(vp->next == lp); */
6030 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
6031 tlist = lp; /* remainder of word list */
6032 }
6033
6034 /* vp == end of variable list */
6035 /* tlist == remainder of original word list without variable assignments */
6036 if (!tlist)
6037 /* All the words in tlist were assignment statements */
6038 return ((WORD_LIST *)NULL);
6039
6040 /* ASSERT(tlist != NULL); */
ccc6cda3 6041 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
726f6388
JA
6042
6043 /* If the -k option is in effect, we need to go through the remaining
bb70624e
JA
6044 words, separate out the assignment words, and place them on
6045 SUBST_ASSIGN_VARLIST. */
726f6388
JA
6046 if (place_keywords_in_env)
6047 {
6048 WORD_LIST *tp; /* tp == running pointer into tlist */
6049
6050 tp = tlist;
6051 lp = tlist->next;
6052
6053 /* Loop Invariant: tp->next == lp */
6054 /* Loop postcondition: tlist == word list without assignment statements */
6055 while (lp)
6056 {
ccc6cda3 6057 if (lp->word->flags & W_ASSIGNMENT)
726f6388
JA
6058 {
6059 /* Found an assignment statement, add this word to end of
bb70624e
JA
6060 subst_assign_varlist (vp). */
6061 if (!subst_assign_varlist)
6062 subst_assign_varlist = vp = lp;
726f6388
JA
6063 else
6064 {
6065 vp->next = lp;
6066 vp = lp;
6067 }
6068
6069 /* Remove the word pointed to by LP from TLIST. */
6070 tp->next = lp->next;
6071 /* ASSERT(vp == lp); */
6072 lp->next = (WORD_LIST *)NULL;
6073 lp = tp->next;
6074 }
6075 else
6076 {
6077 tp = lp;
6078 lp = lp->next;
6079 }
6080 }
6081 }
6082 return (tlist);
6083}
6084
cce855bc
JA
6085#define WEXP_VARASSIGN 0x001
6086#define WEXP_BRACEEXP 0x002
6087#define WEXP_TILDEEXP 0x004
6088#define WEXP_PARAMEXP 0x008
6089#define WEXP_PATHEXP 0x010
6090
6091/* All of the expansions, including variable assignments at the start of
6092 the list. */
6093#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
6094
6095/* All of the expansions except variable assignments at the start of
6096 the list. */
6097#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
6098
6099/* All of the `shell expansions': brace expansion, tilde expansion, parameter
6100 expansion, command substitution, arithmetic expansion, word splitting, and
6101 quote removal. */
6102#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
6103
726f6388
JA
6104/* Take the list of words in LIST and do the various substitutions. Return
6105 a new list of words which is the expanded list, and without things like
6106 variable assignments. */
6107
6108WORD_LIST *
6109expand_words (list)
6110 WORD_LIST *list;
6111{
cce855bc 6112 return (expand_word_list_internal (list, WEXP_ALL));
726f6388
JA
6113}
6114
6115/* Same as expand_words (), but doesn't hack variable or environment
6116 variables. */
6117WORD_LIST *
6118expand_words_no_vars (list)
6119 WORD_LIST *list;
6120{
cce855bc 6121 return (expand_word_list_internal (list, WEXP_NOVARS));
726f6388
JA
6122}
6123
cce855bc
JA
6124WORD_LIST *
6125expand_words_shellexp (list)
726f6388 6126 WORD_LIST *list;
726f6388 6127{
cce855bc
JA
6128 return (expand_word_list_internal (list, WEXP_SHELLEXP));
6129}
726f6388 6130
cce855bc
JA
6131static WORD_LIST *
6132glob_expand_word_list (tlist, eflags)
6133 WORD_LIST *tlist;
6134 int eflags;
6135{
6136 char **glob_array, *temp_string;
6137 register int glob_index;
6138 WORD_LIST *glob_list, *output_list, *disposables, *next;
6139 WORD_DESC *tword;
726f6388 6140
cce855bc
JA
6141 output_list = disposables = (WORD_LIST *)NULL;
6142 glob_array = (char **)NULL;
6143 while (tlist)
6144 {
6145 /* For each word, either globbing is attempted or the word is
6146 added to orig_list. If globbing succeeds, the results are
6147 added to orig_list and the word (tlist) is added to the list
6148 of disposable words. If globbing fails and failed glob
6149 expansions are left unchanged (the shell default), the
6150 original word is added to orig_list. If globbing fails and
6151 failed glob expansions are removed, the original word is
6152 added to the list of disposable words. orig_list ends up
6153 in reverse order and requires a call to reverse_list to
6154 be set right. After all words are examined, the disposable
6155 words are freed. */
6156 next = tlist->next;
726f6388 6157
cce855bc 6158 /* If the word isn't an assignment and contains an unquoted
28ef6c31 6159 pattern matching character, then glob it. */
b72432fd 6160 if ((tlist->word->flags & W_NOGLOB) == 0 &&
cce855bc 6161 unquoted_glob_pattern_p (tlist->word->word))
726f6388 6162 {
cce855bc
JA
6163 glob_array = shell_glob_filename (tlist->word->word);
6164
6165 /* Handle error cases.
6166 I don't think we should report errors like "No such file
6167 or directory". However, I would like to report errors
6168 like "Read failed". */
6169
6170 if (GLOB_FAILED (glob_array))
726f6388 6171 {
bb70624e 6172 glob_array = (char **)xmalloc (sizeof (char *));
cce855bc
JA
6173 glob_array[0] = (char *)NULL;
6174 }
6175
6176 /* Dequote the current word in case we have to use it. */
6177 if (glob_array[0] == NULL)
6178 {
6179 temp_string = dequote_string (tlist->word->word);
6180 free (tlist->word->word);
6181 tlist->word->word = temp_string;
6182 }
6183
6184 /* Make the array into a word list. */
6185 glob_list = (WORD_LIST *)NULL;
6186 for (glob_index = 0; glob_array[glob_index]; glob_index++)
6187 {
6188 tword = make_bare_word (glob_array[glob_index]);
6189 tword->flags |= W_GLOBEXP; /* XXX */
6190 glob_list = make_word_list (tword, glob_list);
6191 }
6192
6193 if (glob_list)
6194 {
6195 output_list = (WORD_LIST *)list_append (glob_list, output_list);
6196 PREPEND_LIST (tlist, disposables);
6197 }
6198 else if (allow_null_glob_expansion == 0)
6199 {
6200 /* Failed glob expressions are left unchanged. */
6201 PREPEND_LIST (tlist, output_list);
6202 }
6203 else
6204 {
6205 /* Failed glob expressions are removed. */
6206 PREPEND_LIST (tlist, disposables);
726f6388 6207 }
726f6388 6208 }
cce855bc
JA
6209 else
6210 {
6211 /* Dequote the string. */
6212 temp_string = dequote_string (tlist->word->word);
6213 free (tlist->word->word);
6214 tlist->word->word = temp_string;
6215 PREPEND_LIST (tlist, output_list);
6216 }
6217
6218 free_array (glob_array);
6219 glob_array = (char **)NULL;
6220
6221 tlist = next;
726f6388
JA
6222 }
6223
cce855bc
JA
6224 if (disposables)
6225 dispose_words (disposables);
6226
6227 if (output_list)
6228 output_list = REVERSE_LIST (output_list, WORD_LIST *);
6229
6230 return (output_list);
6231}
726f6388
JA
6232
6233#if defined (BRACE_EXPANSION)
cce855bc
JA
6234static WORD_LIST *
6235brace_expand_word_list (tlist, eflags)
6236 WORD_LIST *tlist;
6237 int eflags;
6238{
6239 register char **expansions;
6240 char *temp_string;
6241 WORD_LIST *disposables, *output_list, *next;
6242 WORD_DESC *w;
6243 int eindex;
6244
6245 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
726f6388 6246 {
cce855bc 6247 next = tlist->next;
726f6388 6248
cce855bc
JA
6249 /* Only do brace expansion if the word has a brace character. If
6250 not, just add the word list element to BRACES and continue. In
6251 the common case, at least when running shell scripts, this will
6252 degenerate to a bunch of calls to `strchr', and then what is
6253 basically a reversal of TLIST into BRACES, which is corrected
6254 by a call to reverse_list () on BRACES when the end of TLIST
6255 is reached. */
6256 if (strchr (tlist->word->word, LBRACE))
726f6388 6257 {
cce855bc 6258 expansions = brace_expand (tlist->word->word);
726f6388 6259
cce855bc 6260 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
726f6388 6261 {
cce855bc
JA
6262 w = make_word (temp_string);
6263 /* If brace expansion didn't change the word, preserve
6264 the flags. We may want to preserve the flags
6265 unconditionally someday -- XXX */
6266 if (STREQ (temp_string, tlist->word->word))
6267 w->flags = tlist->word->flags;
6268 output_list = make_word_list (w, output_list);
6269 free (expansions[eindex]);
726f6388 6270 }
cce855bc 6271 free (expansions);
726f6388 6272
cce855bc
JA
6273 /* Add TLIST to the list of words to be freed after brace
6274 expansion has been performed. */
6275 PREPEND_LIST (tlist, disposables);
6276 }
6277 else
6278 PREPEND_LIST (tlist, output_list);
726f6388 6279 }
cce855bc
JA
6280
6281 if (disposables)
6282 dispose_words (disposables);
6283
6284 if (output_list)
6285 output_list = REVERSE_LIST (output_list, WORD_LIST *);
6286
6287 return (output_list);
6288}
6289#endif
6290
6291static WORD_LIST *
6292shell_expand_word_list (tlist, eflags)
6293 WORD_LIST *tlist;
6294 int eflags;
6295{
6296 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
6297 int expanded_something, has_dollar_at;
6298 char *temp_string;
726f6388 6299
726f6388 6300 /* We do tilde expansion all the time. This is what 1003.2 says. */
cce855bc
JA
6301 new_list = (WORD_LIST *)NULL;
6302 for (orig_list = tlist; tlist; tlist = next)
726f6388 6303 {
ccc6cda3 6304 temp_string = tlist->word->word;
726f6388
JA
6305
6306 next = tlist->next;
6307
6308 /* Posix.2 section 3.6.1 says that tildes following `=' in words
6309 which are not assignment statements are not expanded. We do
ccc6cda3
JA
6310 this only if POSIXLY_CORRECT is enabled. Essentially, we do
6311 tilde expansion on unquoted assignment statements (flags include
6312 W_ASSIGNMENT but not W_QUOTED). */
6313 if (temp_string[0] == '~' ||
6314 (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
6315 posixly_correct == 0 &&
6316 strchr (temp_string, '~') &&
6317 (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string))))
726f6388 6318 {
ccc6cda3
JA
6319 tlist->word->word = bash_tilde_expand (temp_string);
6320 free (temp_string);
726f6388
JA
6321 }
6322
ccc6cda3 6323 expanded_something = 0;
726f6388 6324 expanded = expand_word_internal
b72432fd 6325 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
726f6388
JA
6326
6327 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
6328 {
6329 /* By convention, each time this error is returned,
6330 tlist->word->word has already been freed. */
6331 tlist->word->word = (char *)NULL;
ccc6cda3 6332
726f6388
JA
6333 /* Dispose our copy of the original list. */
6334 dispose_words (orig_list);
d166f048 6335 /* Dispose the new list we're building. */
726f6388
JA
6336 dispose_words (new_list);
6337
28ef6c31 6338 last_command_exit_value = EXECUTION_FAILURE;
726f6388 6339 if (expanded == &expand_word_error)
ccc6cda3 6340 jump_to_top_level (DISCARD);
726f6388 6341 else
ccc6cda3 6342 jump_to_top_level (FORCE_EOF);
726f6388
JA
6343 }
6344
ccc6cda3
JA
6345 /* Don't split words marked W_NOSPLIT. */
6346 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
726f6388 6347 {
ccc6cda3 6348 temp_list = word_list_split (expanded);
726f6388
JA
6349 dispose_words (expanded);
6350 }
6351 else
6352 {
6353 /* If no parameter expansion, command substitution, process
6354 substitution, or arithmetic substitution took place, then
6355 do not do word splitting. We still have to remove quoted
6356 null characters from the result. */
6357 word_list_remove_quoted_nulls (expanded);
ccc6cda3 6358 temp_list = expanded;
726f6388
JA
6359 }
6360
ccc6cda3
JA
6361 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
6362 new_list = (WORD_LIST *)list_append (expanded, new_list);
726f6388
JA
6363 }
6364
cce855bc
JA
6365 if (orig_list)
6366 dispose_words (orig_list);
726f6388 6367
726f6388 6368 if (new_list)
cce855bc 6369 new_list = REVERSE_LIST (new_list, WORD_LIST *);
726f6388 6370
cce855bc
JA
6371 return (new_list);
6372}
726f6388 6373
cce855bc
JA
6374/* The workhorse for expand_words () and expand_words_no_vars ().
6375 First arg is LIST, a WORD_LIST of words.
b72432fd
JA
6376 Second arg EFLAGS is a flags word controlling which expansions are
6377 performed.
726f6388 6378
cce855bc
JA
6379 This does all of the substitutions: brace expansion, tilde expansion,
6380 parameter expansion, command substitution, arithmetic expansion,
6381 process substitution, word splitting, and pathname expansion, according
6382 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
6383 set, or for which no expansion is done, do not undergo word splitting.
b72432fd 6384 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
cce855bc
JA
6385static WORD_LIST *
6386expand_word_list_internal (list, eflags)
6387 WORD_LIST *list;
6388 int eflags;
6389{
6390 WORD_LIST *new_list, *temp_list;
6391 int tint;
726f6388 6392
cce855bc
JA
6393 if (list == 0)
6394 return ((WORD_LIST *)NULL);
726f6388 6395
bb70624e 6396 garglist = new_list = copy_word_list (list);
cce855bc
JA
6397 if (eflags & WEXP_VARASSIGN)
6398 {
bb70624e 6399 garglist = new_list = separate_out_assignments (new_list);
cce855bc
JA
6400 if (new_list == 0)
6401 {
bb70624e 6402 if (subst_assign_varlist)
cce855bc
JA
6403 {
6404 /* All the words were variable assignments, so they are placed
6405 into the shell's environment. */
bb70624e 6406 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
cce855bc
JA
6407 {
6408 this_command_name = (char *)NULL; /* no arithmetic errors */
6409 tint = do_assignment (temp_list->word->word);
6410 /* Variable assignment errors in non-interactive shells
6411 running in Posix.2 mode cause the shell to exit. */
28ef6c31 6412 if (tint == 0)
ccc6cda3 6413 {
cce855bc 6414 last_command_exit_value = EXECUTION_FAILURE;
28ef6c31
JA
6415 if (interactive_shell == 0 && posixly_correct)
6416 jump_to_top_level (FORCE_EOF);
6417 else
6418 jump_to_top_level (DISCARD);
ccc6cda3 6419 }
726f6388 6420 }
bb70624e
JA
6421 dispose_words (subst_assign_varlist);
6422 subst_assign_varlist = (WORD_LIST *)NULL;
cce855bc
JA
6423 }
6424 return ((WORD_LIST *)NULL);
6425 }
6426 }
726f6388 6427
cce855bc
JA
6428 /* Begin expanding the words that remain. The expansions take place on
6429 things that aren't really variable assignments. */
726f6388 6430
cce855bc
JA
6431#if defined (BRACE_EXPANSION)
6432 /* Do brace expansion on this word if there are any brace characters
6433 in the string. */
6434 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
6435 new_list = brace_expand_word_list (new_list, eflags);
6436#endif /* BRACE_EXPANSION */
726f6388 6437
cce855bc
JA
6438 /* Perform the `normal' shell expansions: tilde expansion, parameter and
6439 variable substitution, command substitution, arithmetic expansion,
6440 and word splitting. */
6441 new_list = shell_expand_word_list (new_list, eflags);
726f6388 6442
cce855bc
JA
6443 /* Okay, we're almost done. Now let's just do some filename
6444 globbing. */
6445 if (new_list)
6446 {
6447 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
6448 /* Glob expand the word list unless globbing has been disabled. */
6449 new_list = glob_expand_word_list (new_list, eflags);
726f6388 6450 else
cce855bc
JA
6451 /* Dequote the words, because we're not performing globbing. */
6452 new_list = dequote_list (new_list);
726f6388
JA
6453 }
6454
bb70624e 6455 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
726f6388 6456 {
726f6388
JA
6457 Function *assign_func;
6458
6459 /* If the remainder of the words expand to nothing, Posix.2 requires
6460 that the variable and environment assignments affect the shell's
6461 environment. */
6462 assign_func = new_list ? assign_in_env : do_assignment;
6463
bb70624e 6464 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
726f6388 6465 {
ccc6cda3
JA
6466 this_command_name = (char *)NULL;
6467 tint = (*assign_func) (temp_list->word->word);
6468 /* Variable assignment errors in non-interactive shells running
6469 in Posix.2 mode cause the shell to exit. */
28ef6c31 6470 if (tint == 0 && assign_func == do_assignment)
ccc6cda3
JA
6471 {
6472 last_command_exit_value = EXECUTION_FAILURE;
28ef6c31
JA
6473 if (interactive_shell == 0 && posixly_correct)
6474 jump_to_top_level (FORCE_EOF);
6475 else
6476 jump_to_top_level (DISCARD);
ccc6cda3 6477 }
726f6388 6478 }
726f6388 6479
bb70624e
JA
6480 dispose_words (subst_assign_varlist);
6481 subst_assign_varlist = (WORD_LIST *)NULL;
726f6388
JA
6482 }
6483
cce855bc 6484#if 0
ccc6cda3
JA
6485 tint = list_length (new_list) + 1;
6486 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
cce855bc
JA
6487 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
6488 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
ccc6cda3 6489 glob_argv_flags[tint] = '\0';
ccc6cda3 6490#endif
726f6388 6491
cce855bc 6492 return (new_list);
ccc6cda3 6493}