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