source: vendor/bash/3.1-p17/subst.c@ 3274

Last change on this file since 3274 was 3252, checked in by bird, 18 years ago

Applied bash31-017

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