source: vendor/bash/3.1/subst.c@ 3590

Last change on this file since 3590 was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 205.1 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)
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
2578#if defined (COND_COMMAND)
2579/* Just remove backslashes in STRING. Returns a new string. */
2580char *
2581remove_backslashes (string)
2582 char *string;
2583{
2584 char *r, *ret, *s;
2585
2586 r = ret = (char *)xmalloc (strlen (string) + 1);
2587 for (s = string; s && *s; )
2588 {
2589 if (*s == '\\')
2590 s++;
2591 if (*s == 0)
2592 break;
2593 *r++ = *s++;
2594 }
2595 *r = '\0';
2596 return ret;
2597}
2598
2599/* This needs better error handling. */
2600/* Expand W for use as an argument to a unary or binary operator in a
2601 [[...]] expression. If SPECIAL is nonzero, this is the rhs argument
2602 to the != or == operator, and should be treated as a pattern. In
2603 this case, we quote the string specially for the globbing code. The
2604 caller is responsible for removing the backslashes if the unquoted
2605 words is needed later. */
2606char *
2607cond_expand_word (w, special)
2608 WORD_DESC *w;
2609 int special;
2610{
2611 char *r, *p;
2612 WORD_LIST *l;
2613
2614 if (w->word == 0 || w->word[0] == '\0')
2615 return ((char *)NULL);
2616
2617 l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
2618 if (l)
2619 {
2620 if (special == 0)
2621 {
2622 dequote_list (l);
2623 r = string_list (l);
2624 }
2625 else
2626 {
2627 p = string_list (l);
2628 r = quote_string_for_globbing (p, QGLOB_CVTNULL);
2629 free (p);
2630 }
2631 dispose_words (l);
2632 }
2633 else
2634 r = (char *)NULL;
2635
2636 return r;
2637}
2638#endif
2639
2640/* Call expand_word_internal to expand W and handle error returns.
2641 A convenience function for functions that don't want to handle
2642 any errors or free any memory before aborting. */
2643static WORD_LIST *
2644call_expand_word_internal (w, q, i, c, e)
2645 WORD_DESC *w;
2646 int q, i, *c, *e;
2647{
2648 WORD_LIST *result;
2649
2650 result = expand_word_internal (w, q, i, c, e);
2651 if (result == &expand_word_error || result == &expand_word_fatal)
2652 {
2653 /* By convention, each time this error is returned, w->word has
2654 already been freed (it sometimes may not be in the fatal case,
2655 but that doesn't result in a memory leak because we're going
2656 to exit in most cases). */
2657 w->word = (char *)NULL;
2658 last_command_exit_value = EXECUTION_FAILURE;
2659 exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
2660 /* NOTREACHED */
2661 }
2662 else
2663 return (result);
2664}
2665
2666/* Perform parameter expansion, command substitution, and arithmetic
2667 expansion on STRING, as if it were a word. Leave the result quoted. */
2668static WORD_LIST *
2669expand_string_internal (string, quoted)
2670 char *string;
2671 int quoted;
2672{
2673 WORD_DESC td;
2674 WORD_LIST *tresult;
2675
2676 if (string == 0 || *string == 0)
2677 return ((WORD_LIST *)NULL);
2678
2679 td.flags = 0;
2680 td.word = savestring (string);
2681
2682 tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2683
2684 FREE (td.word);
2685 return (tresult);
2686}
2687
2688/* Expand STRING by performing parameter expansion, command substitution,
2689 and arithmetic expansion. Dequote the resulting WORD_LIST before
2690 returning it, but do not perform word splitting. The call to
2691 remove_quoted_nulls () is in here because word splitting normally
2692 takes care of quote removal. */
2693WORD_LIST *
2694expand_string_unsplit (string, quoted)
2695 char *string;
2696 int quoted;
2697{
2698 WORD_LIST *value;
2699
2700 if (string == 0 || *string == '\0')
2701 return ((WORD_LIST *)NULL);
2702
2703 expand_no_split_dollar_star = 1;
2704 value = expand_string_internal (string, quoted);
2705 expand_no_split_dollar_star = 0;
2706
2707 if (value)
2708 {
2709 if (value->word)
2710 {
2711 remove_quoted_nulls (value->word->word);
2712 value->word->flags &= ~W_HASQUOTEDNULL;
2713 }
2714 dequote_list (value);
2715 }
2716 return (value);
2717}
2718
2719/* Expand the rhs of an assignment statement */
2720WORD_LIST *
2721expand_string_assignment (string, quoted)
2722 char *string;
2723 int quoted;
2724{
2725 WORD_DESC td;
2726 WORD_LIST *value;
2727
2728 if (string == 0 || *string == '\0')
2729 return ((WORD_LIST *)NULL);
2730
2731 expand_no_split_dollar_star = 1;
2732
2733 td.flags = W_ASSIGNRHS;
2734 td.word = savestring (string);
2735 value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2736 FREE (td.word);
2737
2738 expand_no_split_dollar_star = 0;
2739
2740 if (value)
2741 {
2742 if (value->word)
2743 {
2744 remove_quoted_nulls (value->word->word);
2745 value->word->flags &= ~W_HASQUOTEDNULL;
2746 }
2747 dequote_list (value);
2748 }
2749 return (value);
2750}
2751
2752
2753/* Expand one of the PS? prompt strings. This is a sort of combination of
2754 expand_string_unsplit and expand_string_internal, but returns the
2755 passed string when an error occurs. Might want to trap other calls
2756 to jump_to_top_level here so we don't endlessly loop. */
2757WORD_LIST *
2758expand_prompt_string (string, quoted)
2759 char *string;
2760 int quoted;
2761{
2762 WORD_LIST *value;
2763 WORD_DESC td;
2764
2765 if (string == 0 || *string == 0)
2766 return ((WORD_LIST *)NULL);
2767
2768 td.flags = 0;
2769 td.word = savestring (string);
2770
2771 no_longjmp_on_fatal_error = 1;
2772 value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
2773 no_longjmp_on_fatal_error = 0;
2774
2775 if (value == &expand_word_error || value == &expand_word_fatal)
2776 {
2777 value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
2778 return value;
2779 }
2780 FREE (td.word);
2781 if (value)
2782 {
2783 if (value->word)
2784 {
2785 remove_quoted_nulls (value->word->word);
2786 value->word->flags &= ~W_HASQUOTEDNULL;
2787 }
2788 dequote_list (value);
2789 }
2790 return (value);
2791}
2792
2793/* Expand STRING just as if you were expanding a word, but do not dequote
2794 the resultant WORD_LIST. This is called only from within this file,
2795 and is used to correctly preserve quoted characters when expanding
2796 things like ${1+"$@"}. This does parameter expansion, command
2797 substitution, arithmetic expansion, and word splitting. */
2798static WORD_LIST *
2799expand_string_leave_quoted (string, quoted)
2800 char *string;
2801 int quoted;
2802{
2803 WORD_LIST *tlist;
2804 WORD_LIST *tresult;
2805
2806 if (string == 0 || *string == '\0')
2807 return ((WORD_LIST *)NULL);
2808
2809 tlist = expand_string_internal (string, quoted);
2810
2811 if (tlist)
2812 {
2813 tresult = word_list_split (tlist);
2814 dispose_words (tlist);
2815 return (tresult);
2816 }
2817 return ((WORD_LIST *)NULL);
2818}
2819
2820/* This does not perform word splitting or dequote the WORD_LIST
2821 it returns. */
2822static WORD_LIST *
2823expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
2824 char *string;
2825 int quoted, *dollar_at_p, *has_dollar_at;
2826{
2827 WORD_DESC td;
2828 WORD_LIST *tresult;
2829
2830 if (string == 0 || *string == '\0')
2831 return (WORD_LIST *)NULL;
2832
2833 td.flags = 0;
2834 td.word = string;
2835 tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
2836 return (tresult);
2837}
2838
2839/* Expand STRING just as if you were expanding a word. This also returns
2840 a list of words. Note that filename globbing is *NOT* done for word
2841 or string expansion, just when the shell is expanding a command. This
2842 does parameter expansion, command substitution, arithmetic expansion,
2843 and word splitting. Dequote the resultant WORD_LIST before returning. */
2844WORD_LIST *
2845expand_string (string, quoted)
2846 char *string;
2847 int quoted;
2848{
2849 WORD_LIST *result;
2850
2851 if (string == 0 || *string == '\0')
2852 return ((WORD_LIST *)NULL);
2853
2854 result = expand_string_leave_quoted (string, quoted);
2855 return (result ? dequote_list (result) : result);
2856}
2857
2858/***************************************************
2859 * *
2860 * Functions to handle quoting chars *
2861 * *
2862 ***************************************************/
2863
2864/* Conventions:
2865
2866 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
2867 The parser passes CTLNUL as CTLESC CTLNUL. */
2868
2869/* Quote escape characters in string s, but no other characters. This is
2870 used to protect CTLESC and CTLNUL in variable values from the rest of
2871 the word expansion process after the variable is expanded. */
2872char *
2873quote_escapes (string)
2874 char *string;
2875{
2876 register char *s, *t;
2877 size_t slen;
2878 char *result, *send;
2879 DECLARE_MBSTATE;
2880
2881 slen = strlen (string);
2882 send = string + slen;
2883
2884 t = result = (char *)xmalloc ((slen * 2) + 1);
2885 s = string;
2886
2887 while (*s)
2888 {
2889 if (*s == CTLESC || *s == CTLNUL)
2890 *t++ = CTLESC;
2891 COPY_CHAR_P (t, s, send);
2892 }
2893 *t = '\0';
2894 return (result);
2895}
2896
2897static WORD_LIST *
2898list_quote_escapes (list)
2899 WORD_LIST *list;
2900{
2901 register WORD_LIST *w;
2902 char *t;
2903
2904 for (w = list; w; w = w->next)
2905 {
2906 t = w->word->word;
2907 w->word->word = quote_escapes (t);
2908 free (t);
2909 }
2910 return list;
2911}
2912
2913/* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
2914
2915 The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
2916 This is necessary to make unquoted CTLESC and CTLNUL characters in the
2917 data stream pass through properly.
2918
2919 We need to remove doubled CTLESC characters inside quoted strings before
2920 quoting the entire string, so we do not double the number of CTLESC
2921 characters.
2922
2923 Also used by parts of the pattern substitution code. */
2924static char *
2925dequote_escapes (string)
2926 char *string;
2927{
2928 register char *s, *t;
2929 size_t slen;
2930 char *result, *send;
2931 DECLARE_MBSTATE;
2932
2933 if (string == 0)
2934 return string;
2935
2936 slen = strlen (string);
2937 send = string + slen;
2938
2939 t = result = (char *)xmalloc (slen + 1);
2940 s = string;
2941
2942 if (strchr (string, CTLESC) == 0)
2943 return (strcpy (result, s));
2944
2945 while (*s)
2946 {
2947 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
2948 {
2949 s++;
2950 if (*s == '\0')
2951 break;
2952 }
2953 COPY_CHAR_P (t, s, send);
2954 }
2955 *t = '\0';
2956 return result;
2957}
2958
2959/* Return a new string with the quoted representation of character C. */
2960static char *
2961make_quoted_char (c)
2962 int c;
2963{
2964 char *temp;
2965
2966 temp = (char *)xmalloc (3);
2967 if (c == 0)
2968 {
2969 temp[0] = CTLNUL;
2970 temp[1] = '\0';
2971 }
2972 else
2973 {
2974 temp[0] = CTLESC;
2975 temp[1] = c;
2976 temp[2] = '\0';
2977 }
2978 return (temp);
2979}
2980
2981/* Quote STRING. Return a new string. */
2982char *
2983quote_string (string)
2984 char *string;
2985{
2986 register char *t;
2987 size_t slen;
2988 char *result, *send;
2989
2990 if (*string == 0)
2991 {
2992 result = (char *)xmalloc (2);
2993 result[0] = CTLNUL;
2994 result[1] = '\0';
2995 }
2996 else
2997 {
2998 DECLARE_MBSTATE;
2999
3000 slen = strlen (string);
3001 send = string + slen;
3002
3003 result = (char *)xmalloc ((slen * 2) + 1);
3004
3005 for (t = result; string < send; )
3006 {
3007 *t++ = CTLESC;
3008 COPY_CHAR_P (t, string, send);
3009 }
3010 *t = '\0';
3011 }
3012 return (result);
3013}
3014
3015/* De-quoted quoted characters in STRING. */
3016char *
3017dequote_string (string)
3018 char *string;
3019{
3020 register char *s, *t;
3021 size_t slen;
3022 char *result, *send;
3023 DECLARE_MBSTATE;
3024
3025 slen = strlen (string);
3026
3027 t = result = (char *)xmalloc (slen + 1);
3028
3029 if (QUOTED_NULL (string))
3030 {
3031 result[0] = '\0';
3032 return (result);
3033 }
3034
3035 /* If no character in the string can be quoted, don't bother examining
3036 each character. Just return a copy of the string passed to us. */
3037 if (strchr (string, CTLESC) == NULL)
3038 return (strcpy (result, string));
3039
3040 send = string + slen;
3041 s = string;
3042 while (*s)
3043 {
3044 if (*s == CTLESC)
3045 {
3046 s++;
3047 if (*s == '\0')
3048 break;
3049 }
3050 COPY_CHAR_P (t, s, send);
3051 }
3052
3053 *t = '\0';
3054 return (result);
3055}
3056
3057/* Quote the entire WORD_LIST list. */
3058static WORD_LIST *
3059quote_list (list)
3060 WORD_LIST *list;
3061{
3062 register WORD_LIST *w;
3063 char *t;
3064
3065 for (w = list; w; w = w->next)
3066 {
3067 t = w->word->word;
3068 w->word->word = quote_string (t);
3069 free (t);
3070 w->word->flags |= W_QUOTED;
3071 }
3072 return list;
3073}
3074
3075static WORD_LIST *
3076dequote_list (list)
3077 WORD_LIST *list;
3078{
3079 register char *s;
3080 register WORD_LIST *tlist;
3081
3082 for (tlist = list; tlist; tlist = tlist->next)
3083 {
3084 s = dequote_string (tlist->word->word);
3085 free (tlist->word->word);
3086 tlist->word->word = s;
3087 }
3088 return list;
3089}
3090
3091/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
3092 string. */
3093static char *
3094remove_quoted_escapes (string)
3095 char *string;
3096{
3097 char *t;
3098
3099 if (string)
3100 {
3101 t = dequote_escapes (string);
3102 strcpy (string, t);
3103 free (t);
3104 }
3105
3106 return (string);
3107}
3108
3109/* Perform quoted null character removal on STRING. We don't allow any
3110 quoted null characters in the middle or at the ends of strings because
3111 of how expand_word_internal works. remove_quoted_nulls () turns
3112 STRING into an empty string iff it only consists of a quoted null,
3113 and removes all unquoted CTLNUL characters. */
3114static char *
3115remove_quoted_nulls (string)
3116 char *string;
3117{
3118 register size_t slen;
3119 register int i, j, prev_i;
3120 DECLARE_MBSTATE;
3121
3122 if (strchr (string, CTLNUL) == 0) /* XXX */
3123 return string; /* XXX */
3124
3125 slen = strlen (string);
3126 i = j = 0;
3127
3128 while (i < slen)
3129 {
3130 if (string[i] == CTLESC)
3131 {
3132 /* Old code had j++, but we cannot assume that i == j at this
3133 point -- what if a CTLNUL has already been removed from the
3134 string? We don't want to drop the CTLESC or recopy characters
3135 that we've already copied down. */
3136 i++; string[j++] = CTLESC;
3137 if (i == slen)
3138 break;
3139 }
3140 else if (string[i] == CTLNUL)
3141 i++;
3142
3143 prev_i = i;
3144 ADVANCE_CHAR (string, slen, i);
3145 if (j < prev_i)
3146 {
3147 do string[j++] = string[prev_i++]; while (prev_i < i);
3148 }
3149 else
3150 j = i;
3151 }
3152 string[j] = '\0';
3153
3154 return (string);
3155}
3156
3157/* Perform quoted null character removal on each element of LIST.
3158 This modifies LIST. */
3159void
3160word_list_remove_quoted_nulls (list)
3161 WORD_LIST *list;
3162{
3163 register WORD_LIST *t;
3164
3165 for (t = list; t; t = t->next)
3166 {
3167 remove_quoted_nulls (t->word->word);
3168 t->word->flags &= ~W_HASQUOTEDNULL;
3169 }
3170}
3171
3172/* **************************************************************** */
3173/* */
3174/* Functions for Matching and Removing Patterns */
3175/* */
3176/* **************************************************************** */
3177
3178#if defined (HANDLE_MULTIBYTE)
3179#if 0 /* Currently unused */
3180static unsigned char *
3181mb_getcharlens (string, len)
3182 char *string;
3183 int len;
3184{
3185 int i, offset, last;
3186 unsigned char *ret;
3187 char *p;
3188 DECLARE_MBSTATE;
3189
3190 i = offset = 0;
3191 last = 0;
3192 ret = (unsigned char *)xmalloc (len);
3193 memset (ret, 0, len);
3194 while (string[last])
3195 {
3196 ADVANCE_CHAR (string, len, offset);
3197 ret[last] = offset - last;
3198 last = offset;
3199 }
3200 return ret;
3201}
3202#endif
3203#endif
3204
3205/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
3206 can have one of 4 values:
3207 RP_LONG_LEFT remove longest matching portion at start of PARAM
3208 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
3209 RP_LONG_RIGHT remove longest matching portion at end of PARAM
3210 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
3211*/
3212
3213#define RP_LONG_LEFT 1
3214#define RP_SHORT_LEFT 2
3215#define RP_LONG_RIGHT 3
3216#define RP_SHORT_RIGHT 4
3217
3218static char *
3219remove_upattern (param, pattern, op)
3220 char *param, *pattern;
3221 int op;
3222{
3223 register int len;
3224 register char *end;
3225 register char *p, *ret, c;
3226
3227 len = STRLEN (param);
3228 end = param + len;
3229
3230 switch (op)
3231 {
3232 case RP_LONG_LEFT: /* remove longest match at start */
3233 for (p = end; p >= param; p--)
3234 {
3235 c = *p; *p = '\0';
3236 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3237 {
3238 *p = c;
3239 return (savestring (p));
3240 }
3241 *p = c;
3242
3243 }
3244 break;
3245
3246 case RP_SHORT_LEFT: /* remove shortest match at start */
3247 for (p = param; p <= end; p++)
3248 {
3249 c = *p; *p = '\0';
3250 if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3251 {
3252 *p = c;
3253 return (savestring (p));
3254 }
3255 *p = c;
3256 }
3257 break;
3258
3259 case RP_LONG_RIGHT: /* remove longest match at end */
3260 for (p = param; p <= end; p++)
3261 {
3262 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3263 {
3264 c = *p; *p = '\0';
3265 ret = savestring (param);
3266 *p = c;
3267 return (ret);
3268 }
3269 }
3270 break;
3271
3272 case RP_SHORT_RIGHT: /* remove shortest match at end */
3273 for (p = end; p >= param; p--)
3274 {
3275 if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3276 {
3277 c = *p; *p = '\0';
3278 ret = savestring (param);
3279 *p = c;
3280 return (ret);
3281 }
3282 }
3283 break;
3284 }
3285
3286 return (savestring (param)); /* no match, return original string */
3287}
3288
3289#if defined (HANDLE_MULTIBYTE)
3290
3291#if !defined (HAVE_WCSDUP)
3292static wchar_t *
3293wcsdup (ws)
3294 wchar_t *ws;
3295{
3296 wchar_t *ret;
3297 size_t len;
3298
3299 len = wcslen (ws);
3300 ret = xmalloc ((len + 1) * sizeof (wchar_t));
3301 if (ret == 0)
3302 return ret;
3303 return (wcscpy (ret, ws));
3304}
3305#endif /* !HAVE_WCSDUP */
3306
3307static wchar_t *
3308remove_wpattern (wparam, wstrlen, wpattern, op)
3309 wchar_t *wparam;
3310 size_t wstrlen;
3311 wchar_t *wpattern;
3312 int op;
3313{
3314 wchar_t wc;
3315 int n, n1;
3316 wchar_t *ret;
3317
3318 switch (op)
3319 {
3320 case RP_LONG_LEFT: /* remove longest match at start */
3321 for (n = wstrlen; n >= 0; n--)
3322 {
3323 wc = wparam[n]; wparam[n] = L'\0';
3324 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3325 {
3326 wparam[n] = wc;
3327 return (wcsdup (wparam + n));
3328 }
3329 wparam[n] = wc;
3330 }
3331 break;
3332
3333 case RP_SHORT_LEFT: /* remove shortest match at start */
3334 for (n = 0; n <= wstrlen; n++)
3335 {
3336 wc = wparam[n]; wparam[n] = L'\0';
3337 if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3338 {
3339 wparam[n] = wc;
3340 return (wcsdup (wparam + n));
3341 }
3342 wparam[n] = wc;
3343 }
3344 break;
3345
3346 case RP_LONG_RIGHT: /* remove longest match at end */
3347 for (n = 0; n <= wstrlen; n++)
3348 {
3349 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3350 {
3351 wc = wparam[n]; wparam[n] = L'\0';
3352 ret = wcsdup (wparam);
3353 wparam[n] = wc;
3354 return (ret);
3355 }
3356 }
3357 break;
3358
3359 case RP_SHORT_RIGHT: /* remove shortest match at end */
3360 for (n = wstrlen; n >= 0; n--)
3361 {
3362 if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
3363 {
3364 wc = wparam[n]; wparam[n] = L'\0';
3365 ret = wcsdup (wparam);
3366 wparam[n] = wc;
3367 return (ret);
3368 }
3369 }
3370 break;
3371 }
3372
3373 return (wcsdup (wparam)); /* no match, return original string */
3374}
3375#endif /* HANDLE_MULTIBYTE */
3376
3377static char *
3378remove_pattern (param, pattern, op)
3379 char *param, *pattern;
3380 int op;
3381{
3382 if (param == NULL)
3383 return (param);
3384 if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
3385 return (savestring (param));
3386
3387#if defined (HANDLE_MULTIBYTE)
3388 if (MB_CUR_MAX > 1)
3389 {
3390 wchar_t *ret, *oret;
3391 size_t n;
3392 wchar_t *wparam, *wpattern;
3393 mbstate_t ps;
3394 char *xret;
3395
3396 n = xdupmbstowcs (&wpattern, NULL, pattern);
3397 if (n == (size_t)-1)
3398 return (remove_upattern (param, pattern, op));
3399 n = xdupmbstowcs (&wparam, NULL, param);
3400 if (n == (size_t)-1)
3401 {
3402 free (wpattern);
3403 return (remove_upattern (param, pattern, op));
3404 }
3405 oret = ret = remove_wpattern (wparam, n, wpattern, op);
3406
3407 free (wparam);
3408 free (wpattern);
3409
3410 n = strlen (param);
3411 xret = xmalloc (n + 1);
3412 memset (&ps, '\0', sizeof (mbstate_t));
3413 n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
3414 xret[n] = '\0'; /* just to make sure */
3415 free (oret);
3416 return xret;
3417 }
3418 else
3419#endif
3420 return (remove_upattern (param, pattern, op));
3421}
3422
3423/* Return 1 of the first character of STRING could match the first
3424 character of pattern PAT. Used to avoid n2 calls to strmatch(). */
3425static int
3426match_pattern_char (pat, string)
3427 char *pat, *string;
3428{
3429 char c;
3430
3431 if (*string == 0)
3432 return (0);
3433
3434 switch (c = *pat++)
3435 {
3436 default:
3437 return (*string == c);
3438 case '\\':
3439 return (*string == *pat);
3440 case '?':
3441 return (*pat == LPAREN ? 1 : (*string != '\0'));
3442 case '*':
3443 return (1);
3444 case '+':
3445 case '!':
3446 case '@':
3447 return (*pat == LPAREN ? 1 : (*string == c));
3448 case '[':
3449 return (*string != '\0');
3450 }
3451}
3452
3453/* Match PAT anywhere in STRING and return the match boundaries.
3454 This returns 1 in case of a successful match, 0 otherwise. SP
3455 and EP are pointers into the string where the match begins and
3456 ends, respectively. MTYPE controls what kind of match is attempted.
3457 MATCH_BEG and MATCH_END anchor the match at the beginning and end
3458 of the string, respectively. The longest match is returned. */
3459static int
3460match_upattern (string, pat, mtype, sp, ep)
3461 char *string, *pat;
3462 int mtype;
3463 char **sp, **ep;
3464{
3465 int c, len;
3466 register char *p, *p1, *npat;
3467 char *end;
3468
3469 /* If the pattern doesn't match anywhere in the string, go ahead and
3470 short-circuit right away. A minor optimization, saves a bunch of
3471 unnecessary calls to strmatch (up to N calls for a string of N
3472 characters) if the match is unsuccessful. To preserve the semantics
3473 of the substring matches below, we make sure that the pattern has
3474 `*' as first and last character, making a new pattern if necessary. */
3475 /* XXX - check this later if I ever implement `**' with special meaning,
3476 since this will potentially result in `**' at the beginning or end */
3477 len = STRLEN (pat);
3478 if (pat[0] != '*' || pat[len - 1] != '*')
3479 {
3480 p = npat = xmalloc (len + 3);
3481 p1 = pat;
3482 if (*p1 != '*')
3483 *p++ = '*';
3484 while (*p1)
3485 *p++ = *p1++;
3486 if (p1[-1] != '*' || p[-2] == '\\')
3487 *p++ = '*';
3488 *p = '\0';
3489 }
3490 else
3491 npat = pat;
3492 c = strmatch (npat, string, FNMATCH_EXTFLAG);
3493 if (npat != pat)
3494 free (npat);
3495 if (c == FNM_NOMATCH)
3496 return (0);
3497
3498 len = STRLEN (string);
3499 end = string + len;
3500
3501 switch (mtype)
3502 {
3503 case MATCH_ANY:
3504 for (p = string; p <= end; p++)
3505 {
3506 if (match_pattern_char (pat, p))
3507 {
3508 for (p1 = end; p1 >= p; p1--)
3509 {
3510 c = *p1; *p1 = '\0';
3511 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3512 {
3513 *p1 = c;
3514 *sp = p;
3515 *ep = p1;
3516 return 1;
3517 }
3518 *p1 = c;
3519 }
3520 }
3521 }
3522
3523 return (0);
3524
3525 case MATCH_BEG:
3526 if (match_pattern_char (pat, string) == 0)
3527 return (0);
3528
3529 for (p = end; p >= string; p--)
3530 {
3531 c = *p; *p = '\0';
3532 if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
3533 {
3534 *p = c;
3535 *sp = string;
3536 *ep = p;
3537 return 1;
3538 }
3539 *p = c;
3540 }
3541
3542 return (0);
3543
3544 case MATCH_END:
3545 for (p = string; p <= end; p++)
3546 {
3547 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
3548 {
3549 *sp = p;
3550 *ep = end;
3551 return 1;
3552 }
3553
3554 }
3555
3556 return (0);
3557 }
3558
3559 return (0);
3560}
3561
3562#if defined (HANDLE_MULTIBYTE)
3563/* Return 1 of the first character of WSTRING could match the first
3564 character of pattern WPAT. Wide character version. */
3565static int
3566match_pattern_wchar (wpat, wstring)
3567 wchar_t *wpat, *wstring;
3568{
3569 wchar_t wc;
3570
3571 if (*wstring == 0)
3572 return (0);
3573
3574 switch (wc = *wpat++)
3575 {
3576 default:
3577 return (*wstring == wc);
3578 case L'\\':
3579 return (*wstring == *wpat);
3580 case L'?':
3581 return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
3582 case L'*':
3583 return (1);
3584 case L'+':
3585 case L'!':
3586 case L'@':
3587 return (*wpat == LPAREN ? 1 : (*wstring == wc));
3588 case L'[':
3589 return (*wstring != L'\0');
3590 }
3591}
3592
3593/* Match WPAT anywhere in WSTRING and return the match boundaries.
3594 This returns 1 in case of a successful match, 0 otherwise. Wide
3595 character version. */
3596static int
3597match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
3598 wchar_t *wstring;
3599 char **indices;
3600 size_t wstrlen;
3601 wchar_t *wpat;
3602 int mtype;
3603 char **sp, **ep;
3604{
3605 wchar_t wc, *wp, *nwpat, *wp1;
3606 int len;
3607#if 0
3608 size_t n, n1; /* Apple's gcc seems to miscompile this badly */
3609#else
3610 int n, n1;
3611#endif
3612
3613 /* If the pattern doesn't match anywhere in the string, go ahead and
3614 short-circuit right away. A minor optimization, saves a bunch of
3615 unnecessary calls to strmatch (up to N calls for a string of N
3616 characters) if the match is unsuccessful. To preserve the semantics
3617 of the substring matches below, we make sure that the pattern has
3618 `*' as first and last character, making a new pattern if necessary. */
3619 /* XXX - check this later if I ever implement `**' with special meaning,
3620 since this will potentially result in `**' at the beginning or end */
3621 len = wcslen (wpat);
3622 if (wpat[0] != L'*' || wpat[len - 1] != L'*')
3623 {
3624 wp = nwpat = xmalloc ((len + 3) * sizeof (wchar_t));
3625 wp1 = wpat;
3626 if (*wp1 != L'*')
3627 *wp++ = L'*';
3628 while (*wp1 != L'\0')
3629 *wp++ = *wp1++;
3630 if (wp1[-1] != L'*' || wp1[-2] == L'\\')
3631 *wp++ = L'*';
3632 *wp = '\0';
3633 }
3634 else
3635 nwpat = wpat;
3636 len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
3637 if (nwpat != wpat)
3638 free (nwpat);
3639 if (len == FNM_NOMATCH)
3640 return (0);
3641
3642 switch (mtype)
3643 {
3644 case MATCH_ANY:
3645 for (n = 0; n <= wstrlen; n++)
3646 {
3647 if (match_pattern_wchar (wpat, wstring + n))
3648 {
3649 for (n1 = wstrlen; n1 >= n; n1--)
3650 {
3651 wc = wstring[n1]; wstring[n1] = L'\0';
3652 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3653 {
3654 wstring[n1] = wc;
3655 *sp = indices[n];
3656 *ep = indices[n1];
3657 return 1;
3658 }
3659 wstring[n1] = wc;
3660 }
3661 }
3662 }
3663
3664 return (0);
3665
3666 case MATCH_BEG:
3667 if (match_pattern_wchar (wpat, wstring) == 0)
3668 return (0);
3669
3670 for (n = wstrlen; n >= 0; n--)
3671 {
3672 wc = wstring[n]; wstring[n] = L'\0';
3673 if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
3674 {
3675 wstring[n] = wc;
3676 *sp = indices[0];
3677 *ep = indices[n];
3678 return 1;
3679 }
3680 wstring[n] = wc;
3681 }
3682
3683 return (0);
3684
3685 case MATCH_END:
3686 for (n = 0; n <= wstrlen; n++)
3687 {
3688 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
3689 {
3690 *sp = indices[n];
3691 *ep = indices[wstrlen];
3692 return 1;
3693 }
3694 }
3695
3696 return (0);
3697 }
3698
3699 return (0);
3700}
3701#endif /* HANDLE_MULTIBYTE */
3702
3703static int
3704match_pattern (string, pat, mtype, sp, ep)
3705 char *string, *pat;
3706 int mtype;
3707 char **sp, **ep;
3708{
3709#if defined (HANDLE_MULTIBYTE)
3710 int ret;
3711 size_t n;
3712 wchar_t *wstring, *wpat;
3713 char **indices;
3714#endif
3715
3716 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
3717 return (0);
3718
3719#if defined (HANDLE_MULTIBYTE)
3720 if (MB_CUR_MAX > 1)
3721 {
3722 n = xdupmbstowcs (&wpat, NULL, pat);
3723 if (n == (size_t)-1)
3724 return (match_upattern (string, pat, mtype, sp, ep));
3725 n = xdupmbstowcs (&wstring, &indices, string);
3726 if (n == (size_t)-1)
3727 {
3728 free (wpat);
3729 return (match_upattern (string, pat, mtype, sp, ep));
3730 }
3731 ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
3732
3733 free (wpat);
3734 free (wstring);
3735 free (indices);
3736
3737 return (ret);
3738 }
3739 else
3740#endif
3741 return (match_upattern (string, pat, mtype, sp, ep));
3742}
3743
3744static int
3745getpatspec (c, value)
3746 int c;
3747 char *value;
3748{
3749 if (c == '#')
3750 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
3751 else /* c == '%' */
3752 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
3753}
3754
3755/* Posix.2 says that the WORD should be run through tilde expansion,
3756 parameter expansion, command substitution and arithmetic expansion.
3757 This leaves the result quoted, so quote_string_for_globbing () has
3758 to be called to fix it up for strmatch (). If QUOTED is non-zero,
3759 it means that the entire expression was enclosed in double quotes.
3760 This means that quoting characters in the pattern do not make any
3761 special pattern characters quoted. For example, the `*' in the
3762 following retains its special meaning: "${foo#'*'}". */
3763static char *
3764getpattern (value, quoted, expandpat)
3765 char *value;
3766 int quoted, expandpat;
3767{
3768 char *pat, *tword;
3769 WORD_LIST *l;
3770 int i;
3771
3772 /* There is a problem here: how to handle single or double quotes in the
3773 pattern string when the whole expression is between double quotes?
3774 POSIX.2 says that enclosing double quotes do not cause the pattern to
3775 be quoted, but does that leave us a problem with @ and array[@] and their
3776 expansions inside a pattern? */
3777#if 0
3778 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
3779 {
3780 i = 0;
3781 pat = string_extract_double_quoted (tword, &i, 1);
3782 free (tword);
3783 tword = pat;
3784 }
3785#endif
3786
3787 /* expand_string_for_rhs () leaves WORD quoted and does not perform
3788 word splitting. */
3789 l = *value ? expand_string_for_rhs (value,
3790 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
3791 (int *)NULL, (int *)NULL)
3792 : (WORD_LIST *)0;
3793 pat = string_list (l);
3794 dispose_words (l);
3795 if (pat)
3796 {
3797 tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
3798 free (pat);
3799 pat = tword;
3800 }
3801 return (pat);
3802}
3803
3804#if 0
3805/* Handle removing a pattern from a string as a result of ${name%[%]value}
3806 or ${name#[#]value}. */
3807static char *
3808variable_remove_pattern (value, pattern, patspec, quoted)
3809 char *value, *pattern;
3810 int patspec, quoted;
3811{
3812 char *tword;
3813
3814 tword = remove_pattern (value, pattern, patspec);
3815
3816 return (tword);
3817}
3818#endif
3819
3820static char *
3821list_remove_pattern (list, pattern, patspec, itype, quoted)
3822 WORD_LIST *list;
3823 char *pattern;
3824 int patspec, itype, quoted;
3825{
3826 WORD_LIST *new, *l;
3827 WORD_DESC *w;
3828 char *tword;
3829
3830 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
3831 {
3832 tword = remove_pattern (l->word->word, pattern, patspec);
3833 w = alloc_word_desc ();
3834 w->word = tword ? tword : savestring ("");
3835 new = make_word_list (w, new);
3836 }
3837
3838 l = REVERSE_LIST (new, WORD_LIST *);
3839 if (itype == '*')
3840 tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
3841 else
3842 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3843
3844 dispose_words (l);
3845 return (tword);
3846}
3847
3848static char *
3849parameter_list_remove_pattern (itype, pattern, patspec, quoted)
3850 int itype;
3851 char *pattern;
3852 int patspec, quoted;
3853{
3854 char *ret;
3855 WORD_LIST *list;
3856
3857 list = list_rest_of_args ();
3858 if (list == 0)
3859 return ((char *)NULL);
3860 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3861 dispose_words (list);
3862 return (ret);
3863}
3864
3865#if defined (ARRAY_VARS)
3866static char *
3867array_remove_pattern (a, pattern, patspec, varname, quoted)
3868 ARRAY *a;
3869 char *pattern;
3870 int patspec;
3871 char *varname; /* so we can figure out how it's indexed */
3872 int quoted;
3873{
3874 int itype;
3875 char *ret;
3876 WORD_LIST *list;
3877 SHELL_VAR *v;
3878
3879 /* compute itype from varname here */
3880 v = array_variable_part (varname, &ret, 0);
3881 itype = ret[0];
3882
3883 list = array_to_word_list (a);
3884 if (list == 0)
3885 return ((char *)NULL);
3886 ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
3887 dispose_words (list);
3888
3889 return ret;
3890}
3891#endif /* ARRAY_VARS */
3892
3893static char *
3894parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
3895 char *varname, *value, *patstr;
3896 int rtype, quoted;
3897{
3898 int vtype, patspec, starsub;
3899 char *temp1, *val, *pattern;
3900 SHELL_VAR *v;
3901
3902 if (value == 0)
3903 return ((char *)NULL);
3904
3905 this_command_name = varname;
3906
3907 vtype = get_var_and_type (varname, value, quoted, &v, &val);
3908 if (vtype == -1)
3909 return ((char *)NULL);
3910
3911 starsub = vtype & VT_STARSUB;
3912 vtype &= ~VT_STARSUB;
3913
3914 patspec = getpatspec (rtype, patstr);
3915 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
3916 patstr++;
3917
3918 pattern = getpattern (patstr, quoted, 1);
3919
3920 temp1 = (char *)NULL; /* shut up gcc */
3921 switch (vtype)
3922 {
3923 case VT_VARIABLE:
3924 case VT_ARRAYMEMBER:
3925 temp1 = remove_pattern (val, pattern, patspec);
3926 if (vtype == VT_VARIABLE)
3927 FREE (val);
3928 if (temp1)
3929 {
3930 val = quote_escapes (temp1);
3931 free (temp1);
3932 temp1 = val;
3933 }
3934 break;
3935#if defined (ARRAY_VARS)
3936 case VT_ARRAYVAR:
3937 temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
3938 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3939 {
3940 val = quote_escapes (temp1);
3941 free (temp1);
3942 temp1 = val;
3943 }
3944 break;
3945#endif
3946 case VT_POSPARMS:
3947 temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
3948 if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
3949 {
3950 val = quote_escapes (temp1);
3951 free (temp1);
3952 temp1 = val;
3953 }
3954 break;
3955 }
3956
3957 FREE (pattern);
3958 return temp1;
3959}
3960
3961/*******************************************
3962 * *
3963 * Functions to expand WORD_DESCs *
3964 * *
3965 *******************************************/
3966
3967/* Expand WORD, performing word splitting on the result. This does
3968 parameter expansion, command substitution, arithmetic expansion,
3969 word splitting, and quote removal. */
3970
3971WORD_LIST *
3972expand_word (word, quoted)
3973 WORD_DESC *word;
3974 int quoted;
3975{
3976 WORD_LIST *result, *tresult;
3977
3978 tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
3979 result = word_list_split (tresult);
3980 dispose_words (tresult);
3981 return (result ? dequote_list (result) : result);
3982}
3983
3984/* Expand WORD, but do not perform word splitting on the result. This
3985 does parameter expansion, command substitution, arithmetic expansion,
3986 and quote removal. */
3987WORD_LIST *
3988expand_word_unsplit (word, quoted)
3989 WORD_DESC *word;
3990 int quoted;
3991{
3992 WORD_LIST *result;
3993
3994 expand_no_split_dollar_star = 1;
3995 result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
3996 expand_no_split_dollar_star = 0;
3997
3998 return (result ? dequote_list (result) : result);
3999}
4000
4001/* Perform shell expansions on WORD, but do not perform word splitting or
4002 quote removal on the result. */
4003WORD_LIST *
4004expand_word_leave_quoted (word, quoted)
4005 WORD_DESC *word;
4006 int quoted;
4007{
4008 return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
4009}
4010
4011#if defined (PROCESS_SUBSTITUTION)
4012
4013/*****************************************************************/
4014/* */
4015/* Hacking Process Substitution */
4016/* */
4017/*****************************************************************/
4018
4019#if !defined (HAVE_DEV_FD)
4020/* Named pipes must be removed explicitly with `unlink'. This keeps a list
4021 of FIFOs the shell has open. unlink_fifo_list will walk the list and
4022 unlink all of them. add_fifo_list adds the name of an open FIFO to the
4023 list. NFIFO is a count of the number of FIFOs in the list. */
4024#define FIFO_INCR 20
4025
4026struct temp_fifo {
4027 char *file;
4028 pid_t proc;
4029};
4030
4031static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
4032static int nfifo;
4033static int fifo_list_size;
4034
4035static void
4036add_fifo_list (pathname)
4037 char *pathname;
4038{
4039 if (nfifo >= fifo_list_size - 1)
4040 {
4041 fifo_list_size += FIFO_INCR;
4042 fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
4043 fifo_list_size * sizeof (struct temp_fifo));
4044 }
4045
4046 fifo_list[nfifo].file = savestring (pathname);
4047 nfifo++;
4048}
4049
4050void
4051unlink_fifo_list ()
4052{
4053 int saved, i, j;
4054
4055 if (nfifo == 0)
4056 return;
4057
4058 for (i = saved = 0; i < nfifo; i++)
4059 {
4060 if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
4061 {
4062 unlink (fifo_list[i].file);
4063 free (fifo_list[i].file);
4064 fifo_list[i].file = (char *)NULL;
4065 fifo_list[i].proc = -1;
4066 }
4067 else
4068 saved++;
4069 }
4070
4071 /* If we didn't remove some of the FIFOs, compact the list. */
4072 if (saved)
4073 {
4074 for (i = j = 0; i < nfifo; i++)
4075 if (fifo_list[i].file)
4076 {
4077 fifo_list[j].file = fifo_list[i].file;
4078 fifo_list[j].proc = fifo_list[i].proc;
4079 j++;
4080 }
4081 nfifo = j;
4082 }
4083 else
4084 nfifo = 0;
4085}
4086
4087static char *
4088make_named_pipe ()
4089{
4090 char *tname;
4091
4092 tname = sh_mktmpname ("sh-np", MT_USERANDOM);
4093 if (mkfifo (tname, 0600) < 0)
4094 {
4095 free (tname);
4096 return ((char *)NULL);
4097 }
4098
4099 add_fifo_list (tname);
4100 return (tname);
4101}
4102
4103#else /* HAVE_DEV_FD */
4104
4105/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
4106 has open to children. NFDS is a count of the number of bits currently
4107 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
4108 of open files. */
4109static char *dev_fd_list = (char *)NULL;
4110static int nfds;
4111static int totfds; /* The highest possible number of open files. */
4112
4113static void
4114add_fifo_list (fd)
4115 int fd;
4116{
4117 if (!dev_fd_list || fd >= totfds)
4118 {
4119 int ofds;
4120
4121 ofds = totfds;
4122 totfds = getdtablesize ();
4123 if (totfds < 0 || totfds > 256)
4124 totfds = 256;
4125 if (fd > totfds)
4126 totfds = fd + 2;
4127
4128 dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
4129 memset (dev_fd_list + ofds, '\0', totfds - ofds);
4130 }
4131
4132 dev_fd_list[fd] = 1;
4133 nfds++;
4134}
4135
4136void
4137unlink_fifo_list ()
4138{
4139 register int i;
4140
4141 if (nfds == 0)
4142 return;
4143
4144 for (i = 0; nfds && i < totfds; i++)
4145 if (dev_fd_list[i])
4146 {
4147 close (i);
4148 dev_fd_list[i] = 0;
4149 nfds--;
4150 }
4151
4152 nfds = 0;
4153}
4154
4155#if defined (NOTDEF)
4156print_dev_fd_list ()
4157{
4158 register int i;
4159
4160 fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
4161 fflush (stderr);
4162
4163 for (i = 0; i < totfds; i++)
4164 {
4165 if (dev_fd_list[i])
4166 fprintf (stderr, " %d", i);
4167 }
4168 fprintf (stderr, "\n");
4169}
4170#endif /* NOTDEF */
4171
4172static char *
4173make_dev_fd_filename (fd)
4174 int fd;
4175{
4176 char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
4177
4178 ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
4179
4180 strcpy (ret, DEV_FD_PREFIX);
4181 p = inttostr (fd, intbuf, sizeof (intbuf));
4182 strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
4183
4184 add_fifo_list (fd);
4185 return (ret);
4186}
4187
4188#endif /* HAVE_DEV_FD */
4189
4190/* Return a filename that will open a connection to the process defined by
4191 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
4192 a filename in /dev/fd corresponding to a descriptor that is one of the
4193 ends of the pipe. If not defined, we use named pipes on systems that have
4194 them. Systems without /dev/fd and named pipes are out of luck.
4195
4196 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
4197 use the read end of the pipe and dup that file descriptor to fd 0 in
4198 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
4199 writing or use the write end of the pipe in the child, and dup that
4200 file descriptor to fd 1 in the child. The parent does the opposite. */
4201
4202static char *
4203process_substitute (string, open_for_read_in_child)
4204 char *string;
4205 int open_for_read_in_child;
4206{
4207 char *pathname;
4208 int fd, result;
4209 pid_t old_pid, pid;
4210#if defined (HAVE_DEV_FD)
4211 int parent_pipe_fd, child_pipe_fd;
4212 int fildes[2];
4213#endif /* HAVE_DEV_FD */
4214#if defined (JOB_CONTROL)
4215 pid_t old_pipeline_pgrp;
4216#endif
4217
4218 if (!string || !*string || wordexp_only)
4219 return ((char *)NULL);
4220
4221#if !defined (HAVE_DEV_FD)
4222 pathname = make_named_pipe ();
4223#else /* HAVE_DEV_FD */
4224 if (pipe (fildes) < 0)
4225 {
4226 sys_error (_("cannot make pipe for process substitution"));
4227 return ((char *)NULL);
4228 }
4229 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
4230 the pipe in the parent, otherwise the read end. */
4231 parent_pipe_fd = fildes[open_for_read_in_child];
4232 child_pipe_fd = fildes[1 - open_for_read_in_child];
4233 /* Move the parent end of the pipe to some high file descriptor, to
4234 avoid clashes with FDs used by the script. */
4235 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
4236
4237 pathname = make_dev_fd_filename (parent_pipe_fd);
4238#endif /* HAVE_DEV_FD */
4239
4240 if (!pathname)
4241 {
4242 sys_error (_("cannot make pipe for process substitution"));
4243 return ((char *)NULL);
4244 }
4245
4246 old_pid = last_made_pid;
4247
4248#if defined (JOB_CONTROL)
4249 old_pipeline_pgrp = pipeline_pgrp;
4250 pipeline_pgrp = shell_pgrp;
4251 save_pipeline (1);
4252#endif /* JOB_CONTROL */
4253
4254 pid = make_child ((char *)NULL, 1);
4255 if (pid == 0)
4256 {
4257 reset_terminating_signals (); /* XXX */
4258 free_pushed_string_input ();
4259 /* Cancel traps, in trap.c. */
4260 restore_original_signals ();
4261 setup_async_signals ();
4262 subshell_environment |= SUBSHELL_COMSUB;
4263 }
4264
4265#if defined (JOB_CONTROL)
4266 set_sigchld_handler ();
4267 stop_making_children ();
4268 pipeline_pgrp = old_pipeline_pgrp;
4269#endif /* JOB_CONTROL */
4270
4271 if (pid < 0)
4272 {
4273 sys_error (_("cannot make child for process substitution"));
4274 free (pathname);
4275#if defined (HAVE_DEV_FD)
4276 close (parent_pipe_fd);
4277 close (child_pipe_fd);
4278#endif /* HAVE_DEV_FD */
4279 return ((char *)NULL);
4280 }
4281
4282 if (pid > 0)
4283 {
4284#if defined (JOB_CONTROL)
4285 restore_pipeline (1);
4286#endif
4287
4288#if !defined (HAVE_DEV_FD)
4289 fifo_list[nfifo-1].proc = pid;
4290#endif
4291
4292 last_made_pid = old_pid;
4293
4294#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4295 close_pgrp_pipe ();
4296#endif /* JOB_CONTROL && PGRP_PIPE */
4297
4298#if defined (HAVE_DEV_FD)
4299 close (child_pipe_fd);
4300#endif /* HAVE_DEV_FD */
4301
4302 return (pathname);
4303 }
4304
4305 set_sigint_handler ();
4306
4307#if defined (JOB_CONTROL)
4308 set_job_control (0);
4309#endif /* JOB_CONTROL */
4310
4311#if !defined (HAVE_DEV_FD)
4312 /* Open the named pipe in the child. */
4313 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
4314 if (fd < 0)
4315 {
4316 /* Two separate strings for ease of translation. */
4317 if (open_for_read_in_child)
4318 sys_error (_("cannot open named pipe %s for reading"), pathname);
4319 else
4320 sys_error (_("cannot open named pipe %s for writing"), pathname);
4321
4322 exit (127);
4323 }
4324 if (open_for_read_in_child)
4325 {
4326 if (sh_unset_nodelay_mode (fd) < 0)
4327 {
4328 sys_error (_("cannout reset nodelay mode for fd %d"), fd);
4329 exit (127);
4330 }
4331 }
4332#else /* HAVE_DEV_FD */
4333 fd = child_pipe_fd;
4334#endif /* HAVE_DEV_FD */
4335
4336 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
4337 {
4338 sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
4339 open_for_read_in_child ? 0 : 1);
4340 exit (127);
4341 }
4342
4343 if (fd != (open_for_read_in_child ? 0 : 1))
4344 close (fd);
4345
4346 /* Need to close any files that this process has open to pipes inherited
4347 from its parent. */
4348 if (current_fds_to_close)
4349 {
4350 close_fd_bitmap (current_fds_to_close);
4351 current_fds_to_close = (struct fd_bitmap *)NULL;
4352 }
4353
4354#if defined (HAVE_DEV_FD)
4355 /* Make sure we close the parent's end of the pipe and clear the slot
4356 in the fd list so it is not closed later, if reallocated by, for
4357 instance, pipe(2). */
4358 close (parent_pipe_fd);
4359 dev_fd_list[parent_pipe_fd] = 0;
4360#endif /* HAVE_DEV_FD */
4361
4362 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
4363
4364#if !defined (HAVE_DEV_FD)
4365 /* Make sure we close the named pipe in the child before we exit. */
4366 close (open_for_read_in_child ? 0 : 1);
4367#endif /* !HAVE_DEV_FD */
4368
4369 exit (result);
4370 /*NOTREACHED*/
4371}
4372#endif /* PROCESS_SUBSTITUTION */
4373
4374/***********************************/
4375/* */
4376/* Command Substitution */
4377/* */
4378/***********************************/
4379
4380static char *
4381read_comsub (fd, quoted)
4382 int fd, quoted;
4383{
4384 char *istring, buf[128], *bufp;
4385 int istring_index, istring_size, c;
4386 ssize_t bufn;
4387
4388 istring = (char *)NULL;
4389 istring_index = istring_size = bufn = 0;
4390
4391#ifdef __CYGWIN__
4392 setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
4393#endif
4394
4395 /* Read the output of the command through the pipe. */
4396 while (1)
4397 {
4398 if (fd < 0)
4399 break;
4400 if (--bufn <= 0)
4401 {
4402 bufn = zread (fd, buf, sizeof (buf));
4403 if (bufn <= 0)
4404 break;
4405 bufp = buf;
4406 }
4407 c = *bufp++;
4408
4409 if (c == 0)
4410 {
4411#if 0
4412 internal_warning ("read_comsub: ignored null byte in input");
4413#endif
4414 continue;
4415 }
4416
4417 /* Add the character to ISTRING, possibly after resizing it. */
4418 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
4419
4420 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
4421 istring[istring_index++] = CTLESC;
4422
4423 istring[istring_index++] = c;
4424
4425#if 0
4426#if defined (__CYGWIN__)
4427 if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
4428 {
4429 istring_index--;
4430 istring[istring_index - 1] = '\n';
4431 }
4432#endif
4433#endif
4434 }
4435
4436 if (istring)
4437 istring[istring_index] = '\0';
4438
4439 /* If we read no output, just return now and save ourselves some
4440 trouble. */
4441 if (istring_index == 0)
4442 {
4443 FREE (istring);
4444 return (char *)NULL;
4445 }
4446
4447 /* Strip trailing newlines from the output of the command. */
4448 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4449 {
4450 while (istring_index > 0)
4451 {
4452 if (istring[istring_index - 1] == '\n')
4453 {
4454 --istring_index;
4455
4456 /* If the newline was quoted, remove the quoting char. */
4457 if (istring[istring_index - 1] == CTLESC)
4458 --istring_index;
4459 }
4460 else
4461 break;
4462 }
4463 istring[istring_index] = '\0';
4464 }
4465 else
4466 strip_trailing (istring, istring_index - 1, 1);
4467
4468 return istring;
4469}
4470
4471/* Perform command substitution on STRING. This returns a string,
4472 possibly quoted. */
4473char *
4474command_substitute (string, quoted)
4475 char *string;
4476 int quoted;
4477{
4478 pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
4479 char *istring;
4480 int result, fildes[2], function_value, pflags, rc;
4481
4482 istring = (char *)NULL;
4483
4484 /* Don't fork () if there is no need to. In the case of no command to
4485 run, just return NULL. */
4486 if (!string || !*string || (string[0] == '\n' && !string[1]))
4487 return ((char *)NULL);
4488
4489 if (wordexp_only && read_but_dont_execute)
4490 {
4491 last_command_exit_value = 125;
4492 jump_to_top_level (EXITPROG);
4493 }
4494
4495 /* We're making the assumption here that the command substitution will
4496 eventually run a command from the file system. Since we'll run
4497 maybe_make_export_env in this subshell before executing that command,
4498 the parent shell and any other shells it starts will have to remake
4499 the environment. If we make it before we fork, other shells won't
4500 have to. Don't bother if we have any temporary variable assignments,
4501 though, because the export environment will be remade after this
4502 command completes anyway, but do it if all the words to be expanded
4503 are variable assignments. */
4504 if (subst_assign_varlist == 0 || garglist == 0)
4505 maybe_make_export_env (); /* XXX */
4506
4507 /* Flags to pass to parse_and_execute() */
4508 pflags = interactive ? SEVAL_RESETLINE : 0;
4509
4510 /* Pipe the output of executing STRING into the current shell. */
4511 if (pipe (fildes) < 0)
4512 {
4513 sys_error (_("cannot make pipe for command substitution"));
4514 goto error_exit;
4515 }
4516
4517 old_pid = last_made_pid;
4518#if defined (JOB_CONTROL)
4519 old_pipeline_pgrp = pipeline_pgrp;
4520 /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
4521 if ((subshell_environment & SUBSHELL_PIPE) == 0)
4522 pipeline_pgrp = shell_pgrp;
4523 cleanup_the_pipeline ();
4524#endif /* JOB_CONTROL */
4525
4526 old_async_pid = last_asynchronous_pid;
4527#if 0
4528 pid = make_child ((char *)NULL, 0);
4529#else
4530 pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
4531#endif
4532 last_asynchronous_pid = old_async_pid;
4533
4534 if (pid == 0)
4535 /* Reset the signal handlers in the child, but don't free the
4536 trap strings. */
4537 reset_signal_handlers ();
4538
4539#if defined (JOB_CONTROL)
4540 set_sigchld_handler ();
4541 stop_making_children ();
4542 pipeline_pgrp = old_pipeline_pgrp;
4543#else
4544 stop_making_children ();
4545#endif /* JOB_CONTROL */
4546
4547 if (pid < 0)
4548 {
4549 sys_error (_("cannot make child for command substitution"));
4550 error_exit:
4551
4552 FREE (istring);
4553 close (fildes[0]);
4554 close (fildes[1]);
4555 return ((char *)NULL);
4556 }
4557
4558 if (pid == 0)
4559 {
4560 set_sigint_handler (); /* XXX */
4561
4562 free_pushed_string_input ();
4563
4564 if (dup2 (fildes[1], 1) < 0)
4565 {
4566 sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
4567 exit (EXECUTION_FAILURE);
4568 }
4569
4570 /* If standard output is closed in the parent shell
4571 (such as after `exec >&-'), file descriptor 1 will be
4572 the lowest available file descriptor, and end up in
4573 fildes[0]. This can happen for stdin and stderr as well,
4574 but stdout is more important -- it will cause no output
4575 to be generated from this command. */
4576 if ((fildes[1] != fileno (stdin)) &&
4577 (fildes[1] != fileno (stdout)) &&
4578 (fildes[1] != fileno (stderr)))
4579 close (fildes[1]);
4580
4581 if ((fildes[0] != fileno (stdin)) &&
4582 (fildes[0] != fileno (stdout)) &&
4583 (fildes[0] != fileno (stderr)))
4584 close (fildes[0]);
4585
4586 /* The currently executing shell is not interactive. */
4587 interactive = 0;
4588
4589 /* This is a subshell environment. */
4590 subshell_environment |= SUBSHELL_COMSUB;
4591
4592 /* When not in POSIX mode, command substitution does not inherit
4593 the -e flag. */
4594 if (posixly_correct == 0)
4595 exit_immediately_on_error = 0;
4596
4597 remove_quoted_escapes (string);
4598
4599 startup_state = 2; /* see if we can avoid a fork */
4600 /* Give command substitution a place to jump back to on failure,
4601 so we don't go back up to main (). */
4602 result = setjmp (top_level);
4603
4604 /* If we're running a command substitution inside a shell function,
4605 trap `return' so we don't return from the function in the subshell
4606 and go off to never-never land. */
4607 if (result == 0 && return_catch_flag)
4608 function_value = setjmp (return_catch);
4609 else
4610 function_value = 0;
4611
4612 if (result == ERREXIT)
4613 rc = last_command_exit_value;
4614 else if (result == EXITPROG)
4615 rc = last_command_exit_value;
4616 else if (result)
4617 rc = EXECUTION_FAILURE;
4618 else if (function_value)
4619 rc = return_catch_value;
4620 else
4621 {
4622 subshell_level++;
4623 rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
4624 subshell_level--;
4625 }
4626
4627 last_command_exit_value = rc;
4628 rc = run_exit_trap ();
4629 exit (rc);
4630 }
4631 else
4632 {
4633#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
4634 close_pgrp_pipe ();
4635#endif /* JOB_CONTROL && PGRP_PIPE */
4636
4637 close (fildes[1]);
4638
4639 istring = read_comsub (fildes[0], quoted);
4640
4641 close (fildes[0]);
4642
4643 current_command_subst_pid = pid;
4644 last_command_exit_value = wait_for (pid);
4645 last_command_subst_pid = pid;
4646 last_made_pid = old_pid;
4647
4648#if defined (JOB_CONTROL)
4649 /* If last_command_exit_value > 128, then the substituted command
4650 was terminated by a signal. If that signal was SIGINT, then send
4651 SIGINT to ourselves. This will break out of loops, for instance. */
4652 if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
4653 kill (getpid (), SIGINT);
4654
4655 /* wait_for gives the terminal back to shell_pgrp. If some other
4656 process group should have it, give it away to that group here.
4657 pipeline_pgrp is non-zero only while we are constructing a
4658 pipline, so what we are concerned about is whether or not that
4659 pipeline was started in the background. A pipeline started in
4660 the background should never get the tty back here. */
4661#if 0
4662 if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
4663#else
4664 if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
4665#endif
4666 give_terminal_to (pipeline_pgrp, 0);
4667#endif /* JOB_CONTROL */
4668
4669 return (istring);
4670 }
4671}
4672
4673/********************************************************
4674 * *
4675 * Utility functions for parameter expansion *
4676 * *
4677 ********************************************************/
4678
4679#if defined (ARRAY_VARS)
4680
4681static arrayind_t
4682array_length_reference (s)
4683 char *s;
4684{
4685 int len;
4686 arrayind_t ind;
4687 char *t, c;
4688 ARRAY *array;
4689 SHELL_VAR *var;
4690
4691 var = array_variable_part (s, &t, &len);
4692
4693 /* If unbound variables should generate an error, report one and return
4694 failure. */
4695 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
4696 {
4697 c = *--t;
4698 *t = '\0';
4699 err_unboundvar (s);
4700 *t = c;
4701 return (-1);
4702 }
4703 else if (var == 0)
4704 return 0;
4705
4706 /* We support a couple of expansions for variables that are not arrays.
4707 We'll return the length of the value for v[0], and 1 for v[@] or
4708 v[*]. Return 0 for everything else. */
4709
4710 array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
4711
4712 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
4713 return (array_p (var) ? array_num_elements (array) : 1);
4714
4715 ind = array_expand_index (t, len);
4716 if (ind < 0)
4717 {
4718 err_badarraysub (t);
4719 return (-1);
4720 }
4721
4722 if (array_p (var))
4723 t = array_reference (array, ind);
4724 else
4725 t = (ind == 0) ? value_cell (var) : (char *)NULL;
4726
4727 len = STRLEN (t);
4728 return (len);
4729}
4730#endif /* ARRAY_VARS */
4731
4732static int
4733valid_brace_expansion_word (name, var_is_special)
4734 char *name;
4735 int var_is_special;
4736{
4737 if (DIGIT (*name) && all_digits (name))
4738 return 1;
4739 else if (var_is_special)
4740 return 1;
4741#if defined (ARRAY_VARS)
4742 else if (valid_array_reference (name))
4743 return 1;
4744#endif /* ARRAY_VARS */
4745 else if (legal_identifier (name))
4746 return 1;
4747 else
4748 return 0;
4749}
4750
4751static int
4752chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
4753 char *name;
4754 int quoted;
4755 int *quoted_dollar_atp, *contains_dollar_at;
4756{
4757 char *temp1;
4758
4759 if (name == 0)
4760 {
4761 if (quoted_dollar_atp)
4762 *quoted_dollar_atp = 0;
4763 if (contains_dollar_at)
4764 *contains_dollar_at = 0;
4765 return 0;
4766 }
4767
4768 /* check for $@ and $* */
4769 if (name[0] == '@' && name[1] == 0)
4770 {
4771 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4772 *quoted_dollar_atp = 1;
4773 if (contains_dollar_at)
4774 *contains_dollar_at = 1;
4775 return 1;
4776 }
4777 else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
4778 {
4779 if (contains_dollar_at)
4780 *contains_dollar_at = 1;
4781 return 1;
4782 }
4783
4784 /* Now check for ${array[@]} and ${array[*]} */
4785#if defined (ARRAY_VARS)
4786 else if (valid_array_reference (name))
4787 {
4788 temp1 = xstrchr (name, '[');
4789 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4790 {
4791 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4792 *quoted_dollar_atp = 1;
4793 if (contains_dollar_at)
4794 *contains_dollar_at = 1;
4795 return 1;
4796 } /* [ */
4797 /* ${array[*]}, when unquoted, should be treated like ${array[@]},
4798 which should result in separate words even when IFS is unset. */
4799 if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
4800 {
4801 if (contains_dollar_at)
4802 *contains_dollar_at = 1;
4803 return 1;
4804 }
4805 }
4806#endif
4807 return 0;
4808}
4809
4810/* Parameter expand NAME, and return a new string which is the expansion,
4811 or NULL if there was no expansion.
4812 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
4813 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
4814 NAME was found inside of a double-quoted expression. */
4815static WORD_DESC *
4816parameter_brace_expand_word (name, var_is_special, quoted)
4817 char *name;
4818 int var_is_special, quoted;
4819{
4820 WORD_DESC *ret;
4821 char *temp, *tt;
4822 intmax_t arg_index;
4823 SHELL_VAR *var;
4824 int atype;
4825
4826 ret = 0;
4827 temp = 0;
4828
4829 /* Handle multiple digit arguments, as in ${11}. */
4830 if (legal_number (name, &arg_index))
4831 {
4832 tt = get_dollar_var_value (arg_index);
4833 if (tt)
4834 temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4835 ? quote_string (tt)
4836 : quote_escapes (tt);
4837 else
4838 temp = (char *)NULL;
4839 FREE (tt);
4840 }
4841 else if (var_is_special) /* ${@} */
4842 {
4843 int sindex;
4844 tt = (char *)xmalloc (2 + strlen (name));
4845 tt[sindex = 0] = '$';
4846 strcpy (tt + 1, name);
4847
4848 ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
4849 (int *)NULL, (int *)NULL, 0);
4850 free (tt);
4851 }
4852#if defined (ARRAY_VARS)
4853 else if (valid_array_reference (name))
4854 {
4855 temp = array_value (name, quoted, &atype);
4856 if (atype == 0 && temp)
4857 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4858 ? quote_string (temp)
4859 : quote_escapes (temp);
4860 }
4861#endif
4862 else if (var = find_variable (name))
4863 {
4864 if (var_isset (var) && invisible_p (var) == 0)
4865 {
4866#if defined (ARRAY_VARS)
4867 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
4868#else
4869 temp = value_cell (var);
4870#endif
4871
4872 if (temp)
4873 temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
4874 ? quote_string (temp)
4875 : quote_escapes (temp);
4876 }
4877 else
4878 temp = (char *)NULL;
4879 }
4880 else
4881 temp = (char *)NULL;
4882
4883 if (ret == 0)
4884 {
4885 ret = alloc_word_desc ();
4886 ret->word = temp;
4887 }
4888 return ret;
4889}
4890
4891/* Expand an indirect reference to a variable: ${!NAME} expands to the
4892 value of the variable whose name is the value of NAME. */
4893static WORD_DESC *
4894parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
4895 char *name;
4896 int var_is_special, quoted;
4897 int *quoted_dollar_atp, *contains_dollar_at;
4898{
4899 char *temp, *t;
4900 WORD_DESC *w;
4901
4902 w = parameter_brace_expand_word (name, var_is_special, quoted);
4903 t = w->word;
4904 /* Have to dequote here if necessary */
4905 if (t)
4906 {
4907 temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
4908 ? dequote_string (t)
4909 : dequote_escapes (t);
4910 free (t);
4911 t = temp;
4912 }
4913 dispose_word_desc (w);
4914
4915 chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
4916 if (t == 0)
4917 return (WORD_DESC *)NULL;
4918
4919 w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
4920 free (t);
4921
4922 return w;
4923}
4924
4925/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
4926 depending on the value of C, the separating character. C can be one of
4927 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
4928 between double quotes. */
4929static WORD_DESC *
4930parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
4931 char *name, *value;
4932 int c, quoted, *qdollaratp, *hasdollarat;
4933{
4934 WORD_DESC *w;
4935 WORD_LIST *l;
4936 char *t, *t1, *temp;
4937 int hasdol;
4938
4939 /* If the entire expression is between double quotes, we want to treat
4940 the value as a double-quoted string, with the exception that we strip
4941 embedded unescaped double quotes. */
4942 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
4943 {
4944 hasdol = 0;
4945 temp = string_extract_double_quoted (value, &hasdol, 1);
4946 }
4947 else
4948 temp = value;
4949
4950 w = alloc_word_desc ();
4951 hasdol = 0;
4952 /* XXX was 0 not quoted */
4953 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
4954 : (WORD_LIST *)0;
4955 if (hasdollarat)
4956 *hasdollarat = hasdol || (l && l->next);
4957 if (temp != value)
4958 free (temp);
4959 if (l)
4960 {
4961 /* The expansion of TEMP returned something. We need to treat things
4962 slightly differently if HASDOL is non-zero. If we have "$@", the
4963 individual words have already been quoted. We need to turn them
4964 into a string with the words separated by the first character of
4965 $IFS without any additional quoting, so string_list_dollar_at won't
4966 do the right thing. We use string_list_dollar_star instead. */
4967 temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
4968
4969 /* If l->next is not null, we know that TEMP contained "$@", since that
4970 is the only expansion that creates more than one word. */
4971 if (qdollaratp && ((hasdol && quoted) || l->next))
4972 *qdollaratp = 1;
4973 dispose_words (l);
4974 }
4975 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
4976 {
4977 /* The brace expansion occurred between double quotes and there was
4978 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
4979 it does not expand to anything. In this case, we want to return
4980 a quoted empty string. */
4981 temp = (char *)xmalloc (2);
4982 temp[0] = CTLNUL;
4983 temp[1] = '\0';
4984 w->flags |= W_HASQUOTEDNULL;
4985 }
4986 else
4987 temp = (char *)NULL;
4988
4989 if (c == '-' || c == '+')
4990 {
4991 w->word = temp;
4992 return w;
4993 }
4994
4995 /* c == '=' */
4996 t = temp ? savestring (temp) : savestring ("");
4997 t1 = dequote_string (t);
4998 free (t);
4999#if defined (ARRAY_VARS)
5000 if (valid_array_reference (name))
5001 assign_array_element (name, t1, 0);
5002 else
5003#endif /* ARRAY_VARS */
5004 bind_variable (name, t1, 0);
5005 free (t1);
5006
5007 w->word = temp;
5008 return w;
5009}
5010
5011/* Deal with the right hand side of a ${name:?value} expansion in the case
5012 that NAME is null or not set. If VALUE is non-null it is expanded and
5013 used as the error message to print, otherwise a standard message is
5014 printed. */
5015static void
5016parameter_brace_expand_error (name, value)
5017 char *name, *value;
5018{
5019 WORD_LIST *l;
5020 char *temp;
5021
5022 if (value && *value)
5023 {
5024 l = expand_string (value, 0);
5025 temp = string_list (l);
5026 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
5027 FREE (temp);
5028 dispose_words (l);
5029 }
5030 else
5031 report_error (_("%s: parameter null or not set"), name);
5032
5033 /* Free the data we have allocated during this expansion, since we
5034 are about to longjmp out. */
5035 free (name);
5036 FREE (value);
5037}
5038
5039/* Return 1 if NAME is something for which parameter_brace_expand_length is
5040 OK to do. */
5041static int
5042valid_length_expression (name)
5043 char *name;
5044{
5045 return (name[1] == '\0' || /* ${#} */
5046 ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
5047 (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
5048#if defined (ARRAY_VARS)
5049 valid_array_reference (name + 1) || /* ${#a[7]} */
5050#endif
5051 legal_identifier (name + 1)); /* ${#PS1} */
5052}
5053
5054#if defined (HANDLE_MULTIBYTE)
5055size_t
5056mbstrlen (s)
5057 const char *s;
5058{
5059 size_t clen, nc;
5060 mbstate_t mbs, mbsbak;
5061
5062 nc = 0;
5063 memset (&mbs, 0, sizeof (mbs));
5064 mbsbak = mbs;
5065 while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
5066 {
5067 if (MB_INVALIDCH(clen))
5068 {
5069 clen = 1; /* assume single byte */
5070 mbs = mbsbak;
5071 }
5072
5073 s += clen;
5074 nc++;
5075 mbsbak = mbs;
5076 }
5077 return nc;
5078}
5079#endif
5080
5081
5082/* Handle the parameter brace expansion that requires us to return the
5083 length of a parameter. */
5084static intmax_t
5085parameter_brace_expand_length (name)
5086 char *name;
5087{
5088 char *t, *newname;
5089 intmax_t number, arg_index;
5090 WORD_LIST *list;
5091#if defined (ARRAY_VARS)
5092 SHELL_VAR *var;
5093#endif
5094
5095 if (name[1] == '\0') /* ${#} */
5096 number = number_of_args ();
5097 else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
5098 number = number_of_args ();
5099 else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
5100 {
5101 /* Take the lengths of some of the shell's special parameters. */
5102 switch (name[1])
5103 {
5104 case '-':
5105 t = which_set_flags ();
5106 break;
5107 case '?':
5108 t = itos (last_command_exit_value);
5109 break;
5110 case '$':
5111 t = itos (dollar_dollar_pid);
5112 break;
5113 case '!':
5114 if (last_asynchronous_pid == NO_PID)
5115 t = (char *)NULL;
5116 else
5117 t = itos (last_asynchronous_pid);
5118 break;
5119 case '#':
5120 t = itos (number_of_args ());
5121 break;
5122 }
5123 number = STRLEN (t);
5124 FREE (t);
5125 }
5126#if defined (ARRAY_VARS)
5127 else if (valid_array_reference (name + 1))
5128 number = array_length_reference (name + 1);
5129#endif /* ARRAY_VARS */
5130 else
5131 {
5132 number = 0;
5133
5134 if (legal_number (name + 1, &arg_index)) /* ${#1} */
5135 {
5136 t = get_dollar_var_value (arg_index);
5137 number = MB_STRLEN (t);
5138 FREE (t);
5139 }
5140#if defined (ARRAY_VARS)
5141 else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && array_p (var))
5142 {
5143 t = array_reference (array_cell (var), 0);
5144 number = MB_STRLEN (t);
5145 }
5146#endif
5147 else /* ${#PS1} */
5148 {
5149 newname = savestring (name);
5150 newname[0] = '$';
5151 list = expand_string (newname, Q_DOUBLE_QUOTES);
5152 t = list ? string_list (list) : (char *)NULL;
5153 free (newname);
5154 if (list)
5155 dispose_words (list);
5156
5157 number = MB_STRLEN (t);
5158 FREE (t);
5159 }
5160 }
5161
5162 return (number);
5163}
5164
5165/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
5166 so we do some ad-hoc parsing of an arithmetic expression to find
5167 the first DELIM, instead of using strchr(3). Two rules:
5168 1. If the substring contains a `(', read until closing `)'.
5169 2. If the substring contains a `?', read past one `:' for each `?'.
5170*/
5171
5172static char *
5173skiparith (substr, delim)
5174 char *substr;
5175 int delim;
5176{
5177 size_t sublen;
5178 int skipcol, pcount, i;
5179 DECLARE_MBSTATE;
5180
5181 sublen = strlen (substr);
5182 i = skipcol = pcount = 0;
5183 while (substr[i])
5184 {
5185 /* Balance parens */
5186 if (substr[i] == LPAREN)
5187 {
5188 pcount++;
5189 i++;
5190 continue;
5191 }
5192 if (substr[i] == RPAREN && pcount)
5193 {
5194 pcount--;
5195 i++;
5196 continue;
5197 }
5198 if (pcount)
5199 {
5200 ADVANCE_CHAR (substr, sublen, i);
5201 continue;
5202 }
5203
5204 /* Skip one `:' for each `?' */
5205 if (substr[i] == ':' && skipcol)
5206 {
5207 skipcol--;
5208 i++;
5209 continue;
5210 }
5211 if (substr[i] == delim)
5212 break;
5213 if (substr[i] == '?')
5214 {
5215 skipcol++;
5216 i++;
5217 continue;
5218 }
5219 ADVANCE_CHAR (substr, sublen, i);
5220 }
5221
5222 return (substr + i);
5223}
5224
5225/* Verify and limit the start and end of the desired substring. If
5226 VTYPE == 0, a regular shell variable is being used; if it is 1,
5227 then the positional parameters are being used; if it is 2, then
5228 VALUE is really a pointer to an array variable that should be used.
5229 Return value is 1 if both values were OK, 0 if there was a problem
5230 with an invalid expression, or -1 if the values were out of range. */
5231static int
5232verify_substring_values (value, substr, vtype, e1p, e2p)
5233 char *value, *substr;
5234 int vtype;
5235 intmax_t *e1p, *e2p;
5236{
5237 char *t, *temp1, *temp2;
5238 arrayind_t len;
5239 int expok;
5240#if defined (ARRAY_VARS)
5241 ARRAY *a;
5242#endif
5243
5244 /* duplicate behavior of strchr(3) */
5245 t = skiparith (substr, ':');
5246 if (*t && *t == ':')
5247 *t = '\0';
5248 else
5249 t = (char *)0;
5250
5251 temp1 = expand_string_if_necessary (substr, Q_DOUBLE_QUOTES, expand_string);
5252 *e1p = evalexp (temp1, &expok);
5253 free (temp1);
5254 if (expok == 0)
5255 return (0);
5256
5257 len = -1; /* paranoia */
5258 switch (vtype)
5259 {
5260 case VT_VARIABLE:
5261 case VT_ARRAYMEMBER:
5262 len = MB_STRLEN (value);
5263 break;
5264 case VT_POSPARMS:
5265 len = number_of_args () + 1;
5266 break;
5267#if defined (ARRAY_VARS)
5268 case VT_ARRAYVAR:
5269 a = (ARRAY *)value;
5270 /* For arrays, the first value deals with array indices. Negative
5271 offsets count from one past the array's maximum index. */
5272 len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
5273 break;
5274#endif
5275 }
5276
5277 if (len == -1) /* paranoia */
5278 return -1;
5279
5280 if (*e1p < 0) /* negative offsets count from end */
5281 *e1p += len;
5282
5283 if (*e1p > len || *e1p < 0)
5284 return (-1);
5285
5286#if defined (ARRAY_VARS)
5287 /* For arrays, the second offset deals with the number of elements. */
5288 if (vtype == VT_ARRAYVAR)
5289 len = array_num_elements (a);
5290#endif
5291
5292 if (t)
5293 {
5294 t++;
5295 temp2 = savestring (t);
5296 temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
5297 free (temp2);
5298 t[-1] = ':';
5299 *e2p = evalexp (temp1, &expok);
5300 free (temp1);
5301 if (expok == 0)
5302 return (0);
5303 if (*e2p < 0)
5304 {
5305 internal_error (_("%s: substring expression < 0"), t);
5306 return (0);
5307 }
5308#if defined (ARRAY_VARS)
5309 /* In order to deal with sparse arrays, push the intelligence about how
5310 to deal with the number of elements desired down to the array-
5311 specific functions. */
5312 if (vtype != VT_ARRAYVAR)
5313#endif
5314 {
5315 *e2p += *e1p; /* want E2 chars starting at E1 */
5316 if (*e2p > len)
5317 *e2p = len;
5318 }
5319 }
5320 else
5321 *e2p = len;
5322
5323 return (1);
5324}
5325
5326/* Return the type of variable specified by VARNAME (simple variable,
5327 positional param, or array variable). Also return the value specified
5328 by VARNAME (value of a variable or a reference to an array element).
5329 If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
5330 characters in the value are quoted with CTLESC and takes appropriate
5331 steps. For convenience, *VALP is set to the dequoted VALUE. */
5332static int
5333get_var_and_type (varname, value, quoted, varp, valp)
5334 char *varname, *value;
5335 int quoted;
5336 SHELL_VAR **varp;
5337 char **valp;
5338{
5339 int vtype;
5340 char *temp;
5341#if defined (ARRAY_VARS)
5342 SHELL_VAR *v;
5343#endif
5344
5345 /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
5346 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
5347 if (vtype == VT_POSPARMS && varname[0] == '*')
5348 vtype |= VT_STARSUB;
5349 *varp = (SHELL_VAR *)NULL;
5350
5351#if defined (ARRAY_VARS)
5352 if (valid_array_reference (varname))
5353 {
5354 v = array_variable_part (varname, &temp, (int *)0);
5355 if (v && array_p (v))
5356 { /* [ */
5357 if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
5358 {
5359 vtype = VT_ARRAYVAR;
5360 if (temp[0] == '*')
5361 vtype |= VT_STARSUB;
5362 *valp = (char *)array_cell (v);
5363 }
5364 else
5365 {
5366 vtype = VT_ARRAYMEMBER;
5367 *valp = array_value (varname, 1, (int *)NULL);
5368 }
5369 *varp = v;
5370 }
5371 else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
5372 {
5373 vtype = VT_VARIABLE;
5374 *varp = v;
5375 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5376 *valp = dequote_string (value);
5377 else
5378 *valp = dequote_escapes (value);
5379 }
5380 else
5381 return -1;
5382 }
5383 else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v))
5384 {
5385 vtype = VT_ARRAYMEMBER;
5386 *varp = v;
5387 *valp = array_reference (array_cell (v), 0);
5388 }
5389 else
5390#endif
5391 {
5392 if (value && vtype == VT_VARIABLE)
5393 {
5394 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5395 *valp = dequote_string (value);
5396 else
5397 *valp = dequote_escapes (value);
5398 }
5399 else
5400 *valp = value;
5401 }
5402
5403 return vtype;
5404}
5405
5406/******************************************************/
5407/* */
5408/* Functions to extract substrings of variable values */
5409/* */
5410/******************************************************/
5411
5412#if defined (HANDLE_MULTIBYTE)
5413/* Character-oriented rather than strictly byte-oriented substrings. S and
5414 E, rather being strict indices into STRING, indicate character (possibly
5415 multibyte character) positions that require calculation.
5416 Used by the ${param:offset[:length]} expansion. */
5417static char *
5418mb_substring (string, s, e)
5419 char *string;
5420 int s, e;
5421{
5422 char *tt;
5423 int start, stop, i, slen;
5424 DECLARE_MBSTATE;
5425
5426 start = 0;
5427 /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
5428 slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
5429
5430 i = s;
5431 while (string[start] && i--)
5432 ADVANCE_CHAR (string, slen, start);
5433 stop = start;
5434 i = e - s;
5435 while (string[stop] && i--)
5436 ADVANCE_CHAR (string, slen, stop);
5437 tt = substring (string, start, stop);
5438 return tt;
5439}
5440#endif
5441
5442/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
5443 is `@', use the positional parameters; otherwise, use the value of
5444 VARNAME. If VARNAME is an array variable, use the array elements. */
5445
5446static char *
5447parameter_brace_substring (varname, value, substr, quoted)
5448 char *varname, *value, *substr;
5449 int quoted;
5450{
5451 intmax_t e1, e2;
5452 int vtype, r, starsub;
5453 char *temp, *val, *tt;
5454 SHELL_VAR *v;
5455
5456 if (value == 0)
5457 return ((char *)NULL);
5458
5459 this_command_name = varname;
5460
5461 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5462 if (vtype == -1)
5463 return ((char *)NULL);
5464
5465 starsub = vtype & VT_STARSUB;
5466 vtype &= ~VT_STARSUB;
5467
5468 r = verify_substring_values (val, substr, vtype, &e1, &e2);
5469 if (r <= 0)
5470 return ((r == 0) ? &expand_param_error : (char *)NULL);
5471
5472 switch (vtype)
5473 {
5474 case VT_VARIABLE:
5475 case VT_ARRAYMEMBER:
5476#if defined (HANDLE_MULTIBYTE)
5477 if (MB_CUR_MAX > 1)
5478 tt = mb_substring (val, e1, e2);
5479 else
5480#endif
5481 tt = substring (val, e1, e2);
5482
5483 if (vtype == VT_VARIABLE)
5484 FREE (val);
5485 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
5486 temp = quote_string (tt);
5487 else
5488 temp = tt ? quote_escapes (tt) : (char *)NULL;
5489 FREE (tt);
5490 break;
5491 case VT_POSPARMS:
5492 tt = pos_params (varname, e1, e2, quoted);
5493 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5494 {
5495 temp = tt ? quote_escapes (tt) : (char *)NULL;
5496 FREE (tt);
5497 }
5498 else
5499 temp = tt;
5500 break;
5501#if defined (ARRAY_VARS)
5502 case VT_ARRAYVAR:
5503 /* We want E2 to be the number of elements desired (arrays can be sparse,
5504 so verify_substring_values just returns the numbers specified and we
5505 rely on array_subrange to understand how to deal with them). */
5506 tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
5507 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
5508 {
5509 temp = tt ? quote_escapes (tt) : (char *)NULL;
5510 FREE (tt);
5511 }
5512 else
5513 temp = tt;
5514 break;
5515#endif
5516 default:
5517 temp = (char *)NULL;
5518 }
5519
5520 return temp;
5521}
5522
5523/****************************************************************/
5524/* */
5525/* Functions to perform pattern substitution on variable values */
5526/* */
5527/****************************************************************/
5528
5529char *
5530pat_subst (string, pat, rep, mflags)
5531 char *string, *pat, *rep;
5532 int mflags;
5533{
5534 char *ret, *s, *e, *str;
5535 int rsize, rptr, l, replen, mtype;
5536
5537 mtype = mflags & MATCH_TYPEMASK;
5538
5539 /* Special cases:
5540 * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
5541 * with REP and return the result.
5542 * 2. A null pattern with mtype == MATCH_END means to append REP to
5543 * STRING and return the result.
5544 */
5545 if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
5546 {
5547 replen = STRLEN (rep);
5548 l = strlen (string);
5549 ret = (char *)xmalloc (replen + l + 2);
5550 if (replen == 0)
5551 strcpy (ret, string);
5552 else if (mtype == MATCH_BEG)
5553 {
5554 strcpy (ret, rep);
5555 strcpy (ret + replen, string);
5556 }
5557 else
5558 {
5559 strcpy (ret, string);
5560 strcpy (ret + l, rep);
5561 }
5562 return (ret);
5563 }
5564
5565 ret = (char *)xmalloc (rsize = 64);
5566 ret[0] = '\0';
5567
5568 for (replen = STRLEN (rep), rptr = 0, str = string;;)
5569 {
5570 if (match_pattern (str, pat, mtype, &s, &e) == 0)
5571 break;
5572 l = s - str;
5573 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
5574
5575 /* OK, now copy the leading unmatched portion of the string (from
5576 str to s) to ret starting at rptr (the current offset). Then copy
5577 the replacement string at ret + rptr + (s - str). Increment
5578 rptr (if necessary) and str and go on. */
5579 if (l)
5580 {
5581 strncpy (ret + rptr, str, l);
5582 rptr += l;
5583 }
5584 if (replen)
5585 {
5586 strncpy (ret + rptr, rep, replen);
5587 rptr += replen;
5588 }
5589 str = e; /* e == end of match */
5590
5591 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
5592 break;
5593
5594 if (s == e)
5595 e++, str++; /* avoid infinite recursion on zero-length match */
5596 }
5597
5598 /* Now copy the unmatched portion of the input string */
5599 if (*str)
5600 {
5601 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
5602 strcpy (ret + rptr, str);
5603 }
5604 else
5605 ret[rptr] = '\0';
5606
5607 return ret;
5608}
5609
5610/* Do pattern match and replacement on the positional parameters. */
5611static char *
5612pos_params_pat_subst (string, pat, rep, mflags)
5613 char *string, *pat, *rep;
5614 int mflags;
5615{
5616 WORD_LIST *save, *params;
5617 WORD_DESC *w;
5618 char *ret, *tt;
5619
5620 save = params = list_rest_of_args ();
5621 if (save == 0)
5622 return ((char *)NULL);
5623
5624 for ( ; params; params = params->next)
5625 {
5626 ret = pat_subst (params->word->word, pat, rep, mflags);
5627 w = alloc_word_desc ();
5628 w->word = ret ? ret : savestring ("");
5629 dispose_word (params->word);
5630 params->word = w;
5631 }
5632
5633 if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
5634 ret = string_list_dollar_star (quote_list (save));
5635 else
5636 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
5637 dispose_words (save);
5638
5639 return (ret);
5640}
5641
5642/* Perform pattern substitution on VALUE, which is the expansion of
5643 VARNAME. PATSUB is an expression supplying the pattern to match
5644 and the string to substitute. QUOTED is a flags word containing
5645 the type of quoting currently in effect. */
5646static char *
5647parameter_brace_patsub (varname, value, patsub, quoted)
5648 char *varname, *value, *patsub;
5649 int quoted;
5650{
5651 int vtype, mflags, starsub;
5652 char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
5653 SHELL_VAR *v;
5654
5655 if (value == 0)
5656 return ((char *)NULL);
5657
5658 this_command_name = varname;
5659
5660 vtype = get_var_and_type (varname, value, quoted, &v, &val);
5661 if (vtype == -1)
5662 return ((char *)NULL);
5663
5664 starsub = vtype & VT_STARSUB;
5665 vtype &= ~VT_STARSUB;
5666
5667 mflags = 0;
5668 if (*patsub == '/')
5669 {
5670 mflags |= MATCH_GLOBREP;
5671 patsub++;
5672 }
5673
5674 /* Malloc this because expand_string_if_necessary or one of the expansion
5675 functions in its call chain may free it on a substitution error. */
5676 lpatsub = savestring (patsub);
5677
5678 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
5679 mflags |= MATCH_QUOTED;
5680
5681 if (starsub)
5682 mflags |= MATCH_STARSUB;
5683
5684 if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
5685 *rep++ = '\0';
5686 else
5687 rep = (char *)NULL;
5688
5689 if (rep && *rep == '\0')
5690 rep = (char *)NULL;
5691
5692 /* Perform the same expansions on the pattern as performed by the
5693 pattern removal expansions. */
5694 pat = getpattern (lpatsub, quoted, 1);
5695
5696 if (rep)
5697 {
5698 if ((mflags & MATCH_QUOTED) == 0)
5699 rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
5700 else
5701 rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
5702 }
5703
5704 p = pat;
5705 if (pat && pat[0] == '#')
5706 {
5707 mflags |= MATCH_BEG;
5708 p++;
5709 }
5710 else if (pat && pat[0] == '%')
5711 {
5712 mflags |= MATCH_END;
5713 p++;
5714 }
5715 else
5716 mflags |= MATCH_ANY;
5717
5718 /* OK, we now want to substitute REP for PAT in VAL. If
5719 flags & MATCH_GLOBREP is non-zero, the substitution is done
5720 everywhere, otherwise only the first occurrence of PAT is
5721 replaced. The pattern matching code doesn't understand
5722 CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
5723 values passed in (VT_VARIABLE) so the pattern substitution
5724 code works right. We need to requote special chars after
5725 we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
5726 other cases if QUOTED == 0, since the posparams and arrays
5727 indexed by * or @ do special things when QUOTED != 0. */
5728
5729 switch (vtype)
5730 {
5731 case VT_VARIABLE:
5732 case VT_ARRAYMEMBER:
5733 temp = pat_subst (val, p, rep, mflags);
5734 if (vtype == VT_VARIABLE)
5735 FREE (val);
5736 if (temp)
5737 {
5738 tt = quote_escapes (temp);
5739 free (temp);
5740 temp = tt;
5741 }
5742 break;
5743 case VT_POSPARMS:
5744 temp = pos_params_pat_subst (val, p, rep, mflags);
5745 if (temp && (mflags & MATCH_QUOTED) == 0)
5746 {
5747 tt = quote_escapes (temp);
5748 free (temp);
5749 temp = tt;
5750 }
5751 break;
5752#if defined (ARRAY_VARS)
5753 case VT_ARRAYVAR:
5754 temp = array_patsub (array_cell (v), p, rep, mflags);
5755 if (temp && (mflags & MATCH_QUOTED) == 0)
5756 {
5757 tt = quote_escapes (temp);
5758 free (temp);
5759 temp = tt;
5760 }
5761 break;
5762#endif
5763 }
5764
5765 FREE (pat);
5766 FREE (rep);
5767 free (lpatsub);
5768
5769 return temp;
5770}
5771
5772/****************************************************************/
5773/* */
5774/* Functions to perform parameter expansion on a string */
5775/* */
5776/****************************************************************/
5777
5778/* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
5779static WORD_DESC *
5780parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
5781 char *string;
5782 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
5783{
5784 int check_nullness, var_is_set, var_is_null, var_is_special;
5785 int want_substring, want_indir, want_patsub;
5786 char *name, *value, *temp, *temp1;
5787 WORD_DESC *tdesc, *ret;
5788 int t_index, sindex, c, tflag;
5789 intmax_t number;
5790
5791 value = (char *)NULL;
5792 var_is_set = var_is_null = var_is_special = check_nullness = 0;
5793 want_substring = want_indir = want_patsub = 0;
5794
5795 sindex = *indexp;
5796 t_index = ++sindex;
5797 name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
5798
5799 ret = 0;
5800 tflag = 0;
5801
5802 /* If the name really consists of a special variable, then make sure
5803 that we have the entire name. We don't allow indirect references
5804 to special variables except `#', `?', `@' and `*'. */
5805 if ((sindex == t_index &&
5806 (string[t_index] == '-' ||
5807 string[t_index] == '?' ||
5808 string[t_index] == '#')) ||
5809 (sindex == t_index - 1 && string[sindex] == '!' &&
5810 (string[t_index] == '#' ||
5811 string[t_index] == '?' ||
5812 string[t_index] == '@' ||
5813 string[t_index] == '*')))
5814 {
5815 t_index++;
5816 free (name);
5817 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
5818 name = (char *)xmalloc (3 + (strlen (temp1)));
5819 *name = string[sindex];
5820 if (string[sindex] == '!')
5821 {
5822 /* indirect reference of $#, $?, $@, or $* */
5823 name[1] = string[sindex + 1];
5824 strcpy (name + 2, temp1);
5825 }
5826 else
5827 strcpy (name + 1, temp1);
5828 free (temp1);
5829 }
5830 sindex = t_index;
5831
5832 /* Find out what character ended the variable name. Then
5833 do the appropriate thing. */
5834 if (c = string[sindex])
5835 sindex++;
5836
5837 /* If c is followed by one of the valid parameter expansion
5838 characters, move past it as normal. If not, assume that
5839 a substring specification is being given, and do not move
5840 past it. */
5841 if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
5842 {
5843 check_nullness++;
5844 if (c = string[sindex])
5845 sindex++;
5846 }
5847 else if (c == ':' && string[sindex] != RBRACE)
5848 want_substring = 1;
5849 else if (c == '/' && string[sindex] != RBRACE)
5850 want_patsub = 1;
5851
5852 /* Catch the valid and invalid brace expressions that made it through the
5853 tests above. */
5854 /* ${#-} is a valid expansion and means to take the length of $-.
5855 Similarly for ${#?} and ${##}... */
5856 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
5857 VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
5858 {
5859 name = (char *)xrealloc (name, 3);
5860 name[1] = c;
5861 name[2] = '\0';
5862 c = string[sindex++];
5863 }
5864
5865 /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
5866 if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
5867 member (c, "%:=+/") && string[sindex] == RBRACE)
5868 {
5869 temp = (char *)NULL;
5870 goto bad_substitution;
5871 }
5872
5873 /* Indirect expansion begins with a `!'. A valid indirect expansion is
5874 either a variable name, one of the positional parameters or a special
5875 variable that expands to one of the positional parameters. */
5876 want_indir = *name == '!' &&
5877 (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
5878 || VALID_INDIR_PARAM (name[1]));
5879
5880 /* Determine the value of this variable. */
5881
5882 /* Check for special variables, directly referenced. */
5883 if (SPECIAL_VAR (name, want_indir))
5884 var_is_special++;
5885
5886 /* Check for special expansion things, like the length of a parameter */
5887 if (*name == '#' && name[1])
5888 {
5889 /* If we are not pointing at the character just after the
5890 closing brace, then we haven't gotten all of the name.
5891 Since it begins with a special character, this is a bad
5892 substitution. Also check NAME for validity before trying
5893 to go on. */
5894 if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
5895 {
5896 temp = (char *)NULL;
5897 goto bad_substitution;
5898 }
5899
5900 number = parameter_brace_expand_length (name);
5901 free (name);
5902
5903 *indexp = sindex;
5904 if (number < 0)
5905 return (&expand_wdesc_error);
5906 else
5907 {
5908 ret = alloc_word_desc ();
5909 ret->word = itos (number);
5910 return ret;
5911 }
5912 }
5913
5914 /* ${@} is identical to $@. */
5915 if (name[0] == '@' && name[1] == '\0')
5916 {
5917 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5918 *quoted_dollar_atp = 1;
5919
5920 if (contains_dollar_at)
5921 *contains_dollar_at = 1;
5922 }
5923
5924 /* Process ${!PREFIX*} expansion. */
5925 if (want_indir && string[sindex - 1] == RBRACE &&
5926 (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
5927 legal_variable_starter ((unsigned char) name[1]))
5928 {
5929 char **x;
5930 WORD_LIST *xlist;
5931
5932 temp1 = savestring (name + 1);
5933 number = strlen (temp1);
5934 temp1[number - 1] = '\0';
5935 x = all_variables_matching_prefix (temp1);
5936 xlist = strvec_to_word_list (x, 0, 0);
5937 if (string[sindex - 2] == '*')
5938 temp = string_list_dollar_star (xlist);
5939 else
5940 {
5941 temp = string_list_dollar_at (xlist, quoted);
5942 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5943 *quoted_dollar_atp = 1;
5944 if (contains_dollar_at)
5945 *contains_dollar_at = 1;
5946 }
5947 free (x);
5948 free (xlist);
5949 free (temp1);
5950 *indexp = sindex;
5951
5952 ret = alloc_word_desc ();
5953 ret->word = temp;
5954 return ret;
5955 }
5956
5957#if defined (ARRAY_VARS)
5958 /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
5959 if (want_indir && string[sindex - 1] == RBRACE &&
5960 string[sindex - 2] == ']' && valid_array_reference (name+1))
5961 {
5962 char *x, *x1;
5963
5964 temp1 = savestring (name + 1);
5965 x = array_variable_name (temp1, &x1, (int *)0); /* [ */
5966 FREE (x);
5967 if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
5968 {
5969 temp = array_keys (temp1, quoted);
5970 if (x1[0] == '@')
5971 {
5972 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
5973 *quoted_dollar_atp = 1;
5974 if (contains_dollar_at)
5975 *contains_dollar_at = 1;
5976 }
5977
5978 free (temp1);
5979 *indexp = sindex;
5980
5981 ret = alloc_word_desc ();
5982 ret->word = temp;
5983 return ret;
5984 }
5985
5986 free (temp1);
5987 }
5988#endif /* ARRAY_VARS */
5989
5990 /* Make sure that NAME is valid before trying to go on. */
5991 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
5992 var_is_special) == 0)
5993 {
5994 temp = (char *)NULL;
5995 goto bad_substitution;
5996 }
5997
5998 if (want_indir)
5999 tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
6000 else
6001 tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
6002
6003 if (tdesc)
6004 {
6005 temp = tdesc->word;
6006 tflag = tdesc->flags;
6007 dispose_word_desc (tdesc);
6008 }
6009 else
6010 temp = (char *)0;
6011
6012#if defined (ARRAY_VARS)
6013 if (valid_array_reference (name))
6014 chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
6015#endif
6016
6017 var_is_set = temp != (char *)0;
6018 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
6019
6020 /* Get the rest of the stuff inside the braces. */
6021 if (c && c != RBRACE)
6022 {
6023 /* Extract the contents of the ${ ... } expansion
6024 according to the Posix.2 rules. */
6025 value = extract_dollar_brace_string (string, &sindex, quoted, 0);
6026 if (string[sindex] == RBRACE)
6027 sindex++;
6028 else
6029 goto bad_substitution;
6030 }
6031 else
6032 value = (char *)NULL;
6033
6034 *indexp = sindex;
6035
6036 /* If this is a substring spec, process it and add the result. */
6037 if (want_substring)
6038 {
6039 temp1 = parameter_brace_substring (name, temp, value, quoted);
6040 FREE (name);
6041 FREE (value);
6042 FREE (temp);
6043
6044 if (temp1 == &expand_param_error)
6045 return (&expand_wdesc_error);
6046 else if (temp1 == &expand_param_fatal)
6047 return (&expand_wdesc_fatal);
6048
6049 ret = alloc_word_desc ();
6050 ret->word = temp1;
6051 return ret;
6052 }
6053 else if (want_patsub)
6054 {
6055 temp1 = parameter_brace_patsub (name, temp, value, quoted);
6056 FREE (name);
6057 FREE (value);
6058 FREE (temp);
6059
6060 if (temp1 == &expand_param_error)
6061 return (&expand_wdesc_error);
6062 else if (temp1 == &expand_param_fatal)
6063 return (&expand_wdesc_fatal);
6064
6065 ret = alloc_word_desc ();
6066 ret->word = temp1;
6067 return ret;
6068 }
6069
6070 /* Do the right thing based on which character ended the variable name. */
6071 switch (c)
6072 {
6073 default:
6074 case '\0':
6075 bad_substitution:
6076 report_error (_("%s: bad substitution"), string ? string : "??");
6077 FREE (value);
6078 FREE (temp);
6079 free (name);
6080 return &expand_wdesc_error;
6081
6082 case RBRACE:
6083 if (var_is_set == 0 && unbound_vars_is_error)
6084 {
6085 err_unboundvar (name);
6086 FREE (value);
6087 FREE (temp);
6088 free (name);
6089 last_command_exit_value = EXECUTION_FAILURE;
6090 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6091 }
6092 break;
6093
6094 case '#': /* ${param#[#]pattern} */
6095 case '%': /* ${param%[%]pattern} */
6096 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
6097 {
6098 FREE (value);
6099 break;
6100 }
6101 temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
6102 free (temp);
6103 free (value);
6104 temp = temp1;
6105 break;
6106
6107 case '-':
6108 case '=':
6109 case '?':
6110 case '+':
6111 if (var_is_set && var_is_null == 0)
6112 {
6113 /* If the operator is `+', we don't want the value of the named
6114 variable for anything, just the value of the right hand side. */
6115
6116 if (c == '+')
6117 {
6118 /* XXX -- if we're double-quoted and the named variable is "$@",
6119 we want to turn off any special handling of "$@" --
6120 we're not using it, so whatever is on the rhs applies. */
6121 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6122 *quoted_dollar_atp = 0;
6123 if (contains_dollar_at)
6124 *contains_dollar_at = 0;
6125
6126 FREE (temp);
6127 if (value)
6128 {
6129 ret = parameter_brace_expand_rhs (name, value, c,
6130 quoted,
6131 quoted_dollar_atp,
6132 contains_dollar_at);
6133 /* XXX - fix up later, esp. noting presence of
6134 W_HASQUOTEDNULL in ret->flags */
6135 free (value);
6136 }
6137 else
6138 temp = (char *)NULL;
6139 }
6140 else
6141 {
6142 FREE (value);
6143 }
6144 /* Otherwise do nothing; just use the value in TEMP. */
6145 }
6146 else /* VAR not set or VAR is NULL. */
6147 {
6148 FREE (temp);
6149 temp = (char *)NULL;
6150 if (c == '=' && var_is_special)
6151 {
6152 report_error (_("$%s: cannot assign in this way"), name);
6153 free (name);
6154 free (value);
6155 return &expand_wdesc_error;
6156 }
6157 else if (c == '?')
6158 {
6159 parameter_brace_expand_error (name, value);
6160 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6161 }
6162 else if (c != '+')
6163 {
6164 /* XXX -- if we're double-quoted and the named variable is "$@",
6165 we want to turn off any special handling of "$@" --
6166 we're not using it, so whatever is on the rhs applies. */
6167 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
6168 *quoted_dollar_atp = 0;
6169 if (contains_dollar_at)
6170 *contains_dollar_at = 0;
6171
6172 ret = parameter_brace_expand_rhs (name, value, c, quoted,
6173 quoted_dollar_atp,
6174 contains_dollar_at);
6175 /* XXX - fix up later, esp. noting presence of
6176 W_HASQUOTEDNULL in tdesc->flags */
6177 }
6178 free (value);
6179 }
6180
6181 break;
6182 }
6183 free (name);
6184
6185 if (ret == 0)
6186 {
6187 ret = alloc_word_desc ();
6188 ret->flags = tflag;
6189 ret->word = temp;
6190 }
6191 return (ret);
6192}
6193
6194/* Expand a single ${xxx} expansion. The braces are optional. When
6195 the braces are used, parameter_brace_expand() does the work,
6196 possibly calling param_expand recursively. */
6197static WORD_DESC *
6198param_expand (string, sindex, quoted, expanded_something,
6199 contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
6200 pflags)
6201 char *string;
6202 int *sindex, quoted, *expanded_something, *contains_dollar_at;
6203 int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
6204{
6205 char *temp, *temp1, uerror[3];
6206 int zindex, t_index, expok;
6207 unsigned char c;
6208 intmax_t number;
6209 SHELL_VAR *var;
6210 WORD_LIST *list;
6211 WORD_DESC *tdesc, *ret;
6212 int tflag;
6213
6214 zindex = *sindex;
6215 c = string[++zindex];
6216
6217 temp = (char *)NULL;
6218 ret = tdesc = (WORD_DESC *)NULL;
6219 tflag = 0;
6220
6221 /* Do simple cases first. Switch on what follows '$'. */
6222 switch (c)
6223 {
6224 /* $0 .. $9? */
6225 case '0':
6226 case '1':
6227 case '2':
6228 case '3':
6229 case '4':
6230 case '5':
6231 case '6':
6232 case '7':
6233 case '8':
6234 case '9':
6235 temp1 = dollar_vars[TODIGIT (c)];
6236 if (unbound_vars_is_error && temp1 == (char *)NULL)
6237 {
6238 uerror[0] = '$';
6239 uerror[1] = c;
6240 uerror[2] = '\0';
6241 err_unboundvar (uerror);
6242 last_command_exit_value = EXECUTION_FAILURE;
6243 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6244 }
6245 if (temp1)
6246 temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6247 ? quote_string (temp1)
6248 : quote_escapes (temp1);
6249 else
6250 temp = (char *)NULL;
6251
6252 break;
6253
6254 /* $$ -- pid of the invoking shell. */
6255 case '$':
6256 temp = itos (dollar_dollar_pid);
6257 break;
6258
6259 /* $# -- number of positional parameters. */
6260 case '#':
6261 temp = itos (number_of_args ());
6262 break;
6263
6264 /* $? -- return value of the last synchronous command. */
6265 case '?':
6266 temp = itos (last_command_exit_value);
6267 break;
6268
6269 /* $- -- flags supplied to the shell on invocation or by `set'. */
6270 case '-':
6271 temp = which_set_flags ();
6272 break;
6273
6274 /* $! -- Pid of the last asynchronous command. */
6275 case '!':
6276 /* If no asynchronous pids have been created, expand to nothing.
6277 If `set -u' has been executed, and no async processes have
6278 been created, this is an expansion error. */
6279 if (last_asynchronous_pid == NO_PID)
6280 {
6281 if (expanded_something)
6282 *expanded_something = 0;
6283 temp = (char *)NULL;
6284 if (unbound_vars_is_error)
6285 {
6286 uerror[0] = '$';
6287 uerror[1] = c;
6288 uerror[2] = '\0';
6289 err_unboundvar (uerror);
6290 last_command_exit_value = EXECUTION_FAILURE;
6291 return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
6292 }
6293 }
6294 else
6295 temp = itos (last_asynchronous_pid);
6296 break;
6297
6298 /* The only difference between this and $@ is when the arg is quoted. */
6299 case '*': /* `$*' */
6300 list = list_rest_of_args ();
6301
6302 /* If there are no command-line arguments, this should just
6303 disappear if there are other characters in the expansion,
6304 even if it's quoted. */
6305 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
6306 temp = (char *)NULL;
6307 else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
6308 {
6309 /* If we have "$*" we want to make a string of the positional
6310 parameters, separated by the first character of $IFS, and
6311 quote the whole string, including the separators. If IFS
6312 is unset, the parameters are separated by ' '; if $IFS is
6313 null, the parameters are concatenated. */
6314 temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
6315 temp1 = quote_string (temp);
6316 if (*temp == 0)
6317 tflag |= W_HASQUOTEDNULL;
6318 free (temp);
6319 temp = temp1;
6320 }
6321 else
6322 {
6323 /* We check whether or not we're eventually going to split $* here,
6324 for example when IFS is empty and we are processing the rhs of
6325 an assignment statement. In that case, we don't separate the
6326 arguments at all. Otherwise, if the $* is not quoted it is
6327 identical to $@ */
6328#if 1
6329# if defined (HANDLE_MULTIBYTE)
6330 if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
6331# else
6332 if (expand_no_split_dollar_star && ifs_firstc == 0)
6333# endif
6334 temp = string_list_dollar_star (list);
6335 else
6336 temp = string_list_dollar_at (list, quoted);
6337#else
6338 temp = string_list_dollar_at (list, quoted);
6339#endif
6340 if (expand_no_split_dollar_star == 0 && contains_dollar_at)
6341 *contains_dollar_at = 1;
6342 }
6343
6344 dispose_words (list);
6345 break;
6346
6347 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
6348 means that we have to turn quoting off after we split into
6349 the individually quoted arguments so that the final split
6350 on the first character of $IFS is still done. */
6351 case '@': /* `$@' */
6352 list = list_rest_of_args ();
6353
6354 /* We want to flag the fact that we saw this. We can't turn
6355 off quoting entirely, because other characters in the
6356 string might need it (consider "\"$@\""), but we need some
6357 way to signal that the final split on the first character
6358 of $IFS should be done, even though QUOTED is 1. */
6359 if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6360 *quoted_dollar_at_p = 1;
6361 if (contains_dollar_at)
6362 *contains_dollar_at = 1;
6363
6364 /* We want to separate the positional parameters with the first
6365 character of $IFS in case $IFS is something other than a space.
6366 We also want to make sure that splitting is done no matter what --
6367 according to POSIX.2, this expands to a list of the positional
6368 parameters no matter what IFS is set to. */
6369 temp = string_list_dollar_at (list, quoted);
6370
6371 dispose_words (list);
6372 break;
6373
6374 case LBRACE:
6375 tdesc = parameter_brace_expand (string, &zindex, quoted,
6376 quoted_dollar_at_p,
6377 contains_dollar_at);
6378
6379 /* Fix this later when parameter_brace_expand returns a WORD_DESC * */
6380 if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
6381 return (tdesc);
6382 temp = tdesc ? tdesc->word : (char *)0;
6383
6384 /* XXX */
6385 /* Quoted nulls should be removed if there is anything else
6386 in the string. */
6387 /* Note that we saw the quoted null so we can add one back at
6388 the end of this function if there are no other characters
6389 in the string, discard TEMP, and go on. The exception to
6390 this is when we have "${@}" and $1 is '', since $@ needs
6391 special handling. */
6392 /* XXX - fix this once parameter_brace_expand returns a WORD_DESC * */
6393#if 0
6394 if (temp && QUOTED_NULL (temp))
6395#else
6396 if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
6397#endif
6398 {
6399 if (had_quoted_null_p)
6400 *had_quoted_null_p = 1;
6401 if (*quoted_dollar_at_p == 0)
6402 {
6403 free (temp);
6404 tdesc->word = temp = (char *)NULL;
6405 }
6406
6407 }
6408
6409 ret = tdesc;
6410 goto return0;
6411
6412 /* Do command or arithmetic substitution. */
6413 case LPAREN:
6414 /* We have to extract the contents of this paren substitution. */
6415 t_index = zindex + 1;
6416 temp = extract_command_subst (string, &t_index);
6417 zindex = t_index;
6418
6419 /* For Posix.2-style `$(( ))' arithmetic substitution,
6420 extract the expression and pass it to the evaluator. */
6421 if (temp && *temp == LPAREN)
6422 {
6423 char *temp2;
6424 temp1 = temp + 1;
6425 temp2 = savestring (temp1);
6426 t_index = strlen (temp2) - 1;
6427
6428 if (temp2[t_index] != RPAREN)
6429 {
6430 free (temp2);
6431 goto comsub;
6432 }
6433
6434 /* Cut off ending `)' */
6435 temp2[t_index] = '\0';
6436
6437 /* Expand variables found inside the expression. */
6438 temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
6439 free (temp2);
6440
6441arithsub:
6442 /* No error messages. */
6443 this_command_name = (char *)NULL;
6444 number = evalexp (temp1, &expok);
6445 free (temp);
6446 free (temp1);
6447 if (expok == 0)
6448 {
6449 if (interactive_shell == 0 && posixly_correct)
6450 {
6451 last_command_exit_value = EXECUTION_FAILURE;
6452 return (&expand_wdesc_fatal);
6453 }
6454 else
6455 return (&expand_wdesc_error);
6456 }
6457 temp = itos (number);
6458 break;
6459 }
6460
6461comsub:
6462 if (pflags & PF_NOCOMSUB)
6463 /* we need zindex+1 because string[zindex] == RPAREN */
6464 temp1 = substring (string, *sindex, zindex+1);
6465 else
6466 temp1 = command_substitute (temp, quoted);
6467 FREE (temp);
6468 temp = temp1;
6469 break;
6470
6471 /* Do POSIX.2d9-style arithmetic substitution. This will probably go
6472 away in a future bash release. */
6473 case '[':
6474 /* Extract the contents of this arithmetic substitution. */
6475 t_index = zindex + 1;
6476 temp = extract_arithmetic_subst (string, &t_index);
6477 zindex = t_index;
6478
6479 /* Do initial variable expansion. */
6480 temp1 = expand_string_if_necessary (temp, Q_DOUBLE_QUOTES, expand_string);
6481
6482 goto arithsub;
6483
6484 default:
6485 /* Find the variable in VARIABLE_LIST. */
6486 temp = (char *)NULL;
6487
6488 for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
6489 ;
6490 temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
6491
6492 /* If this isn't a variable name, then just output the `$'. */
6493 if (temp1 == 0 || *temp1 == '\0')
6494 {
6495 FREE (temp1);
6496 temp = (char *)xmalloc (2);
6497 temp[0] = '$';
6498 temp[1] = '\0';
6499 if (expanded_something)
6500 *expanded_something = 0;
6501 goto return0;
6502 }
6503
6504 /* If the variable exists, return its value cell. */
6505 var = find_variable (temp1);
6506
6507 if (var && invisible_p (var) == 0 && var_isset (var))
6508 {
6509#if defined (ARRAY_VARS)
6510 if (array_p (var))
6511 {
6512 temp = array_reference (array_cell (var), 0);
6513 if (temp)
6514 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6515 ? quote_string (temp)
6516 : quote_escapes (temp);
6517 else if (unbound_vars_is_error)
6518 goto unbound_variable;
6519 }
6520 else
6521#endif
6522 {
6523 temp = value_cell (var);
6524
6525 temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
6526 ? quote_string (temp)
6527 : quote_escapes (temp);
6528 }
6529
6530 free (temp1);
6531
6532 goto return0;
6533 }
6534
6535 temp = (char *)NULL;
6536
6537unbound_variable:
6538 if (unbound_vars_is_error)
6539 err_unboundvar (temp1);
6540 else
6541 {
6542 free (temp1);
6543 goto return0;
6544 }
6545
6546 free (temp1);
6547 last_command_exit_value = EXECUTION_FAILURE;
6548 return ((unbound_vars_is_error && interactive_shell == 0)
6549 ? &expand_wdesc_fatal
6550 : &expand_wdesc_error);
6551 }
6552
6553 if (string[zindex])
6554 zindex++;
6555
6556return0:
6557 *sindex = zindex;
6558
6559 if (ret == 0)
6560 {
6561 ret = alloc_word_desc ();
6562 ret->flags = tflag; /* XXX */
6563 ret->word = temp;
6564 }
6565 return ret;
6566}
6567
6568/* Make a word list which is the result of parameter and variable
6569 expansion, command substitution, arithmetic substitution, and
6570 quote removal of WORD. Return a pointer to a WORD_LIST which is
6571 the result of the expansion. If WORD contains a null word, the
6572 word list returned is also null.
6573
6574 QUOTED contains flag values defined in shell.h.
6575
6576 ISEXP is used to tell expand_word_internal that the word should be
6577 treated as the result of an expansion. This has implications for
6578 how IFS characters in the word are treated.
6579
6580 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
6581 they point to an integer value which receives information about expansion.
6582 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
6583 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
6584 else zero.
6585
6586 This only does word splitting in the case of $@ expansion. In that
6587 case, we split on ' '. */
6588
6589/* Values for the local variable quoted_state. */
6590#define UNQUOTED 0
6591#define PARTIALLY_QUOTED 1
6592#define WHOLLY_QUOTED 2
6593
6594static WORD_LIST *
6595expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
6596 WORD_DESC *word;
6597 int quoted, isexp;
6598 int *contains_dollar_at;
6599 int *expanded_something;
6600{
6601 WORD_LIST *list;
6602 WORD_DESC *tword;
6603
6604 /* The intermediate string that we build while expanding. */
6605 char *istring;
6606
6607 /* The current size of the above object. */
6608 int istring_size;
6609
6610 /* Index into ISTRING. */
6611 int istring_index;
6612
6613 /* Temporary string storage. */
6614 char *temp, *temp1;
6615
6616 /* The text of WORD. */
6617 register char *string;
6618
6619 /* The size of STRING. */
6620 size_t string_size;
6621
6622 /* The index into STRING. */
6623 int sindex;
6624
6625 /* This gets 1 if we see a $@ while quoted. */
6626 int quoted_dollar_at;
6627
6628 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
6629 whether WORD contains no quoting characters, a partially quoted
6630 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
6631 int quoted_state;
6632
6633 /* State flags */
6634 int had_quoted_null;
6635 int has_dollar_at;
6636 int tflag;
6637
6638 int assignoff; /* If assignment, offset of `=' */
6639
6640 register unsigned char c; /* Current character. */
6641 int t_index; /* For calls to string_extract_xxx. */
6642
6643 char twochars[2];
6644
6645 DECLARE_MBSTATE;
6646
6647 istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
6648 istring[istring_index = 0] = '\0';
6649 quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
6650 quoted_state = UNQUOTED;
6651
6652 string = word->word;
6653 if (string == 0)
6654 goto finished_with_string;
6655 /* Don't need the string length for the SADD... and COPY_ macros unless
6656 multibyte characters are possible. */
6657 string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
6658
6659 if (contains_dollar_at)
6660 *contains_dollar_at = 0;
6661
6662 assignoff = -1;
6663
6664 /* Begin the expansion. */
6665
6666 for (sindex = 0; ;)
6667 {
6668 c = string[sindex];
6669
6670 /* Case on toplevel character. */
6671 switch (c)
6672 {
6673 case '\0':
6674 goto finished_with_string;
6675
6676 case CTLESC:
6677 sindex++;
6678#if HANDLE_MULTIBYTE
6679 if (MB_CUR_MAX > 1 && string[sindex])
6680 {
6681 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
6682 }
6683 else
6684#endif
6685 {
6686 temp = (char *)xmalloc (3);
6687 temp[0] = CTLESC;
6688 temp[1] = c = string[sindex];
6689 temp[2] = '\0';
6690 }
6691
6692dollar_add_string:
6693 if (string[sindex])
6694 sindex++;
6695
6696add_string:
6697 if (temp)
6698 {
6699 istring = sub_append_string (temp, istring, &istring_index, &istring_size);
6700 temp = (char *)0;
6701 }
6702
6703 break;
6704
6705#if defined (PROCESS_SUBSTITUTION)
6706 /* Process substitution. */
6707 case '<':
6708 case '>':
6709 {
6710 if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & W_DQUOTE) || posixly_correct)
6711 {
6712 sindex--; /* add_character: label increments sindex */
6713 goto add_character;
6714 }
6715 else
6716 t_index = sindex + 1; /* skip past both '<' and LPAREN */
6717
6718 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
6719 sindex = t_index;
6720
6721 /* If the process substitution specification is `<()', we want to
6722 open the pipe for writing in the child and produce output; if
6723 it is `>()', we want to open the pipe for reading in the child
6724 and consume input. */
6725 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
6726
6727 FREE (temp1);
6728
6729 goto dollar_add_string;
6730 }
6731#endif /* PROCESS_SUBSTITUTION */
6732
6733 case '=':
6734 /* Posix.2 section 3.6.1 says that tildes following `=' in words
6735 which are not assignment statements are not expanded. If the
6736 shell isn't in posix mode, though, we perform tilde expansion
6737 on `likely candidate' unquoted assignment statements (flags
6738 include W_ASSIGNMENT but not W_QUOTED). A likely candidate
6739 contains an unquoted :~ or =~. Something to think about: we
6740 now have a flag that says to perform tilde expansion on arguments
6741 to `assignment builtins' like declare and export that look like
6742 assignment statements. We now do tilde expansion on such words
6743 even in POSIX mode. */
6744 if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
6745 goto add_character;
6746 /* If we're not in posix mode or forcing assignment-statement tilde
6747 expansion, note where the `=' appears in the word and prepare to
6748 do tilde expansion following the first `='. */
6749 if ((word->flags & W_ASSIGNMENT) &&
6750 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
6751 assignoff == -1 && sindex > 0)
6752 assignoff = sindex;
6753 if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
6754 word->flags |= W_ITILDE;
6755#if 0
6756 else if ((word->flags & W_ASSIGNMENT) &&
6757 (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
6758 string[sindex+1] == '~')
6759 word->flags |= W_ITILDE;
6760#endif
6761 goto add_character;
6762
6763 case ':':
6764 if (word->flags & W_NOTILDE)
6765 goto add_character;
6766
6767 if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
6768 string[sindex+1] == '~')
6769 word->flags |= W_ITILDE;
6770 goto add_character;
6771
6772 case '~':
6773 /* If the word isn't supposed to be tilde expanded, or we're not
6774 at the start of a word or after an unquoted : or = in an
6775 assignment statement, we don't do tilde expansion. */
6776 if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
6777 (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
6778 (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6779 {
6780 word->flags &= ~W_ITILDE;
6781 goto add_character;
6782 }
6783
6784 if (word->flags & W_ASSIGNRHS)
6785 tflag = 2;
6786 else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
6787 tflag = 1;
6788 else
6789 tflag = 0;
6790
6791 temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
6792
6793 word->flags &= ~W_ITILDE;
6794
6795 if (temp && *temp && t_index > 0)
6796 {
6797 temp1 = bash_tilde_expand (temp, tflag);
6798 free (temp);
6799 temp = temp1;
6800 sindex += t_index;
6801 goto add_string;
6802 }
6803 else
6804 {
6805 FREE (temp);
6806 goto add_character;
6807 }
6808
6809 case '$':
6810 if (expanded_something)
6811 *expanded_something = 1;
6812
6813 has_dollar_at = 0;
6814 tword = param_expand (string, &sindex, quoted, expanded_something,
6815 &has_dollar_at, &quoted_dollar_at,
6816 &had_quoted_null,
6817 (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
6818
6819 if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
6820 {
6821 free (string);
6822 free (istring);
6823 return ((tword == &expand_wdesc_error) ? &expand_word_error
6824 : &expand_word_fatal);
6825 }
6826 if (contains_dollar_at && has_dollar_at)
6827 *contains_dollar_at = 1;
6828
6829 if (tword && (tword->flags & W_HASQUOTEDNULL))
6830 had_quoted_null = 1;
6831
6832 temp = tword->word;
6833 dispose_word_desc (tword);
6834
6835 goto add_string;
6836 break;
6837
6838 case '`': /* Backquoted command substitution. */
6839 {
6840 t_index = sindex++;
6841
6842 temp = string_extract (string, &sindex, "`", EX_REQMATCH);
6843 /* The test of sindex against t_index is to allow bare instances of
6844 ` to pass through, for backwards compatibility. */
6845 if (temp == &extract_string_error || temp == &extract_string_fatal)
6846 {
6847 if (sindex - 1 == t_index)
6848 {
6849 sindex = t_index;
6850 goto add_character;
6851 }
6852 report_error ("bad substitution: no closing \"`\" in %s", string+t_index);
6853 free (string);
6854 free (istring);
6855 return ((temp == &extract_string_error) ? &expand_word_error
6856 : &expand_word_fatal);
6857 }
6858
6859 if (expanded_something)
6860 *expanded_something = 1;
6861
6862 if (word->flags & W_NOCOMSUB)
6863 /* sindex + 1 because string[sindex] == '`' */
6864 temp1 = substring (string, t_index, sindex + 1);
6865 else
6866 {
6867 de_backslash (temp);
6868 temp1 = command_substitute (temp, quoted);
6869 }
6870 FREE (temp);
6871 temp = temp1;
6872 goto dollar_add_string;
6873 }
6874
6875 case '\\':
6876 if (string[sindex + 1] == '\n')
6877 {
6878 sindex += 2;
6879 continue;
6880 }
6881
6882 c = string[++sindex];
6883
6884 if (quoted & Q_HERE_DOCUMENT)
6885 tflag = CBSHDOC;
6886 else if (quoted & Q_DOUBLE_QUOTES)
6887 tflag = CBSDQUOTE;
6888 else
6889 tflag = 0;
6890
6891 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
6892 {
6893 SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
6894 }
6895 else if (c == 0)
6896 {
6897 c = CTLNUL;
6898 sindex--; /* add_character: label increments sindex */
6899 goto add_character;
6900 }
6901 else
6902 {
6903 SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
6904 }
6905
6906 sindex++;
6907add_twochars:
6908 /* BEFORE jumping here, we need to increment sindex if appropriate */
6909 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
6910 DEFAULT_ARRAY_SIZE);
6911 istring[istring_index++] = twochars[0];
6912 istring[istring_index++] = twochars[1];
6913 istring[istring_index] = '\0';
6914
6915 break;
6916
6917 case '"':
6918#if 0
6919 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
6920#else
6921 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
6922#endif
6923 goto add_character;
6924
6925 t_index = ++sindex;
6926 temp = string_extract_double_quoted (string, &sindex, 0);
6927
6928 /* If the quotes surrounded the entire string, then the
6929 whole word was quoted. */
6930 quoted_state = (t_index == 1 && string[sindex] == '\0')
6931 ? WHOLLY_QUOTED
6932 : PARTIALLY_QUOTED;
6933
6934 if (temp && *temp)
6935 {
6936 tword = alloc_word_desc ();
6937 tword->word = temp;
6938
6939 temp = (char *)NULL;
6940
6941 has_dollar_at = 0;
6942 /* Need to get W_HASQUOTEDNULL flag through this function. */
6943 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
6944
6945 if (list == &expand_word_error || list == &expand_word_fatal)
6946 {
6947 free (istring);
6948 free (string);
6949 /* expand_word_internal has already freed temp_word->word
6950 for us because of the way it prints error messages. */
6951 tword->word = (char *)NULL;
6952 dispose_word (tword);
6953 return list;
6954 }
6955
6956 dispose_word (tword);
6957
6958 /* "$@" (a double-quoted dollar-at) expands into nothing,
6959 not even a NULL word, when there are no positional
6960 parameters. */
6961 if (list == 0 && has_dollar_at)
6962 {
6963 quoted_dollar_at++;
6964 break;
6965 }
6966
6967 /* If we get "$@", we know we have expanded something, so we
6968 need to remember it for the final split on $IFS. This is
6969 a special case; it's the only case where a quoted string
6970 can expand into more than one word. It's going to come back
6971 from the above call to expand_word_internal as a list with
6972 a single word, in which all characters are quoted and
6973 separated by blanks. What we want to do is to turn it back
6974 into a list for the next piece of code. */
6975 if (list)
6976 dequote_list (list);
6977
6978 if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
6979 had_quoted_null = 1;
6980
6981 if (has_dollar_at)
6982 {
6983 quoted_dollar_at++;
6984 if (contains_dollar_at)
6985 *contains_dollar_at = 1;
6986 if (expanded_something)
6987 *expanded_something = 1;
6988 }
6989 }
6990 else
6991 {
6992 /* What we have is "". This is a minor optimization. */
6993 FREE (temp);
6994 list = (WORD_LIST *)NULL;
6995 }
6996
6997 /* The code above *might* return a list (consider the case of "$@",
6998 where it returns "$1", "$2", etc.). We can't throw away the
6999 rest of the list, and we have to make sure each word gets added
7000 as quoted. We test on tresult->next: if it is non-NULL, we
7001 quote the whole list, save it to a string with string_list, and
7002 add that string. We don't need to quote the results of this
7003 (and it would be wrong, since that would quote the separators
7004 as well), so we go directly to add_string. */
7005 if (list)
7006 {
7007 if (list->next)
7008 {
7009 /* Testing quoted_dollar_at makes sure that "$@" is
7010 split correctly when $IFS does not contain a space. */
7011 temp = quoted_dollar_at
7012 ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
7013 : string_list (quote_list (list));
7014 dispose_words (list);
7015 goto add_string;
7016 }
7017 else
7018 {
7019 temp = savestring (list->word->word);
7020 tflag = list->word->flags;
7021 dispose_words (list);
7022
7023 /* If the string is not a quoted null string, we want
7024 to remove any embedded unquoted CTLNUL characters.
7025 We do not want to turn quoted null strings back into
7026 the empty string, though. We do this because we
7027 want to remove any quoted nulls from expansions that
7028 contain other characters. For example, if we have
7029 x"$*"y or "x$*y" and there are no positional parameters,
7030 the $* should expand into nothing. */
7031 /* We use the W_HASQUOTEDNULL flag to differentiate the
7032 cases: a quoted null character as above and when
7033 CTLNUL is contained in the (non-null) expansion
7034 of some variable. We use the had_quoted_null flag to
7035 pass the value through this function to its caller. */
7036 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
7037 remove_quoted_nulls (temp); /* XXX */
7038 }
7039 }
7040 else
7041 temp = (char *)NULL;
7042
7043 /* We do not want to add quoted nulls to strings that are only
7044 partially quoted; we can throw them away. */
7045 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
7046 continue;
7047
7048 add_quoted_string:
7049
7050 if (temp)
7051 {
7052 temp1 = temp;
7053 temp = quote_string (temp);
7054 free (temp1);
7055 goto add_string;
7056 }
7057 else
7058 {
7059 /* Add NULL arg. */
7060 c = CTLNUL;
7061 sindex--; /* add_character: label increments sindex */
7062 goto add_character;
7063 }
7064
7065 /* break; */
7066
7067 case '\'':
7068#if 0
7069 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
7070#else
7071 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
7072#endif
7073 goto add_character;
7074
7075 t_index = ++sindex;
7076 temp = string_extract_single_quoted (string, &sindex);
7077
7078 /* If the entire STRING was surrounded by single quotes,
7079 then the string is wholly quoted. */
7080 quoted_state = (t_index == 1 && string[sindex] == '\0')
7081 ? WHOLLY_QUOTED
7082 : PARTIALLY_QUOTED;
7083
7084 /* If all we had was '', it is a null expansion. */
7085 if (*temp == '\0')
7086 {
7087 free (temp);
7088 temp = (char *)NULL;
7089 }
7090 else
7091 remove_quoted_escapes (temp); /* ??? */
7092
7093 /* We do not want to add quoted nulls to strings that are only
7094 partially quoted; such nulls are discarded. */
7095 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
7096 continue;
7097
7098 /* If we have a quoted null expansion, add a quoted NULL to istring. */
7099 if (temp == 0)
7100 {
7101 c = CTLNUL;
7102 sindex--; /* add_character: label increments sindex */
7103 goto add_character;
7104 }
7105 else
7106 goto add_quoted_string;
7107
7108 /* break; */
7109
7110 default:
7111 /* This is the fix for " $@ " */
7112 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
7113 {
7114 if (string[sindex]) /* from old goto dollar_add_string */
7115 sindex++;
7116 if (c == 0)
7117 {
7118 c = CTLNUL;
7119 goto add_character;
7120 }
7121 else
7122 {
7123#if HANDLE_MULTIBYTE
7124 if (MB_CUR_MAX > 1)
7125 sindex--;
7126
7127 if (MB_CUR_MAX > 1)
7128 {
7129 SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
7130 }
7131 else
7132#endif
7133 {
7134 twochars[0] = CTLESC;
7135 twochars[1] = c;
7136 goto add_twochars;
7137 }
7138 }
7139 }
7140
7141 SADD_MBCHAR (temp, string, sindex, string_size);
7142
7143 add_character:
7144 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
7145 DEFAULT_ARRAY_SIZE);
7146 istring[istring_index++] = c;
7147 istring[istring_index] = '\0';
7148
7149 /* Next character. */
7150 sindex++;
7151 }
7152 }
7153
7154finished_with_string:
7155 /* OK, we're ready to return. If we have a quoted string, and
7156 quoted_dollar_at is not set, we do no splitting at all; otherwise
7157 we split on ' '. The routines that call this will handle what to
7158 do if nothing has been expanded. */
7159
7160 /* Partially and wholly quoted strings which expand to the empty
7161 string are retained as an empty arguments. Unquoted strings
7162 which expand to the empty string are discarded. The single
7163 exception is the case of expanding "$@" when there are no
7164 positional parameters. In that case, we discard the expansion. */
7165
7166 /* Because of how the code that handles "" and '' in partially
7167 quoted strings works, we need to make ISTRING into a QUOTED_NULL
7168 if we saw quoting characters, but the expansion was empty.
7169 "" and '' are tossed away before we get to this point when
7170 processing partially quoted strings. This makes "" and $xxx""
7171 equivalent when xxx is unset. We also look to see whether we
7172 saw a quoted null from a ${} expansion and add one back if we
7173 need to. */
7174
7175 /* If we expand to nothing and there were no single or double quotes
7176 in the word, we throw it away. Otherwise, we return a NULL word.
7177 The single exception is for $@ surrounded by double quotes when
7178 there are no positional parameters. In that case, we also throw
7179 the word away. */
7180
7181 if (*istring == '\0')
7182 {
7183 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
7184 {
7185 istring[0] = CTLNUL;
7186 istring[1] = '\0';
7187 tword = make_bare_word (istring);
7188 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7189 list = make_word_list (tword, (WORD_LIST *)NULL);
7190 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7191 tword->flags |= W_QUOTED;
7192 }
7193 /* According to sh, ksh, and Posix.2, if a word expands into nothing
7194 and a double-quoted "$@" appears anywhere in it, then the entire
7195 word is removed. */
7196 else if (quoted_state == UNQUOTED || quoted_dollar_at)
7197 list = (WORD_LIST *)NULL;
7198#if 0
7199 else
7200 {
7201 tword = make_bare_word (istring);
7202 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7203 tword->flags |= W_QUOTED;
7204 list = make_word_list (tword, (WORD_LIST *)NULL);
7205 }
7206#else
7207 else
7208 list = (WORD_LIST *)NULL;
7209#endif
7210 }
7211 else if (word->flags & W_NOSPLIT)
7212 {
7213 tword = make_bare_word (istring);
7214 if (word->flags & W_ASSIGNMENT)
7215 tword->flags |= W_ASSIGNMENT; /* XXX */
7216 if (word->flags & W_COMPASSIGN)
7217 tword->flags |= W_COMPASSIGN; /* XXX */
7218 if (word->flags & W_NOGLOB)
7219 tword->flags |= W_NOGLOB; /* XXX */
7220 if (word->flags & W_NOEXPAND)
7221 tword->flags |= W_NOEXPAND; /* XXX */
7222 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
7223 tword->flags |= W_QUOTED;
7224 if (had_quoted_null)
7225 tword->flags |= W_HASQUOTEDNULL;
7226 list = make_word_list (tword, (WORD_LIST *)NULL);
7227 }
7228 else
7229 {
7230 char *ifs_chars;
7231
7232 ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
7233
7234 /* If we have $@, we need to split the results no matter what. If
7235 IFS is unset or NULL, string_list_dollar_at has separated the
7236 positional parameters with a space, so we split on space (we have
7237 set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
7238 string_list_dollar_at has separated the positional parameters
7239 with the first character of $IFS, so we split on $IFS. */
7240 if (has_dollar_at && ifs_chars)
7241 list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
7242 else
7243 {
7244 tword = make_bare_word (istring);
7245 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
7246 tword->flags |= W_QUOTED;
7247 if (word->flags & W_ASSIGNMENT)
7248 tword->flags |= W_ASSIGNMENT;
7249 if (word->flags & W_COMPASSIGN)
7250 tword->flags |= W_COMPASSIGN;
7251 if (word->flags & W_NOGLOB)
7252 tword->flags |= W_NOGLOB;
7253 if (word->flags & W_NOEXPAND)
7254 tword->flags |= W_NOEXPAND;
7255 if (had_quoted_null)
7256 tword->flags |= W_HASQUOTEDNULL; /* XXX */
7257 list = make_word_list (tword, (WORD_LIST *)NULL);
7258 }
7259 }
7260
7261 free (istring);
7262 return (list);
7263}
7264
7265/* **************************************************************** */
7266/* */
7267/* Functions for Quote Removal */
7268/* */
7269/* **************************************************************** */
7270
7271/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
7272 backslash quoting rules for within double quotes or a here document. */
7273char *
7274string_quote_removal (string, quoted)
7275 char *string;
7276 int quoted;
7277{
7278 size_t slen;
7279 char *r, *result_string, *temp, *send;
7280 int sindex, tindex, dquote;
7281 unsigned char c;
7282 DECLARE_MBSTATE;
7283
7284 /* The result can be no longer than the original string. */
7285 slen = strlen (string);
7286 send = string + slen;
7287
7288 r = result_string = (char *)xmalloc (slen + 1);
7289
7290 for (dquote = sindex = 0; c = string[sindex];)
7291 {
7292 switch (c)
7293 {
7294 case '\\':
7295 c = string[++sindex];
7296 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
7297 *r++ = '\\';
7298 /* FALLTHROUGH */
7299
7300 default:
7301 SCOPY_CHAR_M (r, string, send, sindex);
7302 break;
7303
7304 case '\'':
7305 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
7306 {
7307 *r++ = c;
7308 sindex++;
7309 break;
7310 }
7311 tindex = sindex + 1;
7312 temp = string_extract_single_quoted (string, &tindex);
7313 if (temp)
7314 {
7315 strcpy (r, temp);
7316 r += strlen (r);
7317 free (temp);
7318 }
7319 sindex = tindex;
7320 break;
7321
7322 case '"':
7323 dquote = 1 - dquote;
7324 sindex++;
7325 break;
7326 }
7327 }
7328 *r = '\0';
7329 return (result_string);
7330}
7331
7332#if 0
7333/* UNUSED */
7334/* Perform quote removal on word WORD. This allocates and returns a new
7335 WORD_DESC *. */
7336WORD_DESC *
7337word_quote_removal (word, quoted)
7338 WORD_DESC *word;
7339 int quoted;
7340{
7341 WORD_DESC *w;
7342 char *t;
7343
7344 t = string_quote_removal (word->word, quoted);
7345 w = alloc_word_desc ();
7346 w->word = t ? t : savestring ("");
7347 return (w);
7348}
7349
7350/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
7351 the members of the list are treated as if they are surrounded by
7352 double quotes. Return a new list, or NULL if LIST is NULL. */
7353WORD_LIST *
7354word_list_quote_removal (list, quoted)
7355 WORD_LIST *list;
7356 int quoted;
7357{
7358 WORD_LIST *result, *t, *tresult, *e;
7359
7360 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7361 {
7362 tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
7363#if 0
7364 result = (WORD_LIST *) list_append (result, tresult);
7365#else
7366 if (result == 0)
7367 result = e = tresult;
7368 else
7369 {
7370 e->next = tresult;
7371 while (e->next)
7372 e = e->next;
7373 }
7374#endif
7375 }
7376 return (result);
7377}
7378#endif
7379
7380/*******************************************
7381 * *
7382 * Functions to perform word splitting *
7383 * *
7384 *******************************************/
7385
7386void
7387setifs (v)
7388 SHELL_VAR *v;
7389{
7390 char *t;
7391 unsigned char uc;
7392
7393 ifs_var = v;
7394#if 0
7395 ifs_value = v ? value_cell (v) : " \t\n";
7396#else
7397 ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
7398#endif
7399
7400 /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
7401 handle multibyte chars in IFS */
7402 memset (ifs_cmap, '\0', sizeof (ifs_cmap));
7403 for (t = ifs_value ; t && *t; t++)
7404 {
7405 uc = *t;
7406 ifs_cmap[uc] = 1;
7407 }
7408
7409#if defined (HANDLE_MULTIBYTE)
7410 if (ifs_value == 0)
7411 {
7412 ifs_firstc[0] = '\0';
7413 ifs_firstc_len = 1;
7414 }
7415 else
7416 {
7417 size_t ifs_len;
7418 ifs_len = strnlen (ifs_value, MB_CUR_MAX);
7419 ifs_firstc_len = MBLEN (ifs_value, ifs_len);
7420 if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
7421 {
7422 ifs_firstc[0] = ifs_value[0];
7423 ifs_firstc[1] = '\0';
7424 ifs_firstc_len = 1;
7425 }
7426 else
7427 memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
7428 }
7429#else
7430 ifs_firstc = ifs_value ? *ifs_value : 0;
7431#endif
7432}
7433
7434char *
7435getifs ()
7436{
7437 return ifs_value;
7438}
7439
7440/* This splits a single word into a WORD LIST on $IFS, but only if the word
7441 is not quoted. list_string () performs quote removal for us, even if we
7442 don't do any splitting. */
7443WORD_LIST *
7444word_split (w, ifs_chars)
7445 WORD_DESC *w;
7446 char *ifs_chars;
7447{
7448 WORD_LIST *result;
7449
7450 if (w)
7451 {
7452 char *xifs;
7453
7454 xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
7455 result = list_string (w->word, xifs, w->flags & W_QUOTED);
7456 }
7457 else
7458 result = (WORD_LIST *)NULL;
7459
7460 return (result);
7461}
7462
7463/* Perform word splitting on LIST and return the RESULT. It is possible
7464 to return (WORD_LIST *)NULL. */
7465static WORD_LIST *
7466word_list_split (list)
7467 WORD_LIST *list;
7468{
7469 WORD_LIST *result, *t, *tresult, *e;
7470
7471 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
7472 {
7473 tresult = word_split (t->word, ifs_value);
7474#if 0
7475 result = (WORD_LIST *) list_append (result, tresult);
7476#else
7477 if (result == 0)
7478 result = e = tresult;
7479 else
7480 {
7481 e->next = tresult;
7482 while (e->next)
7483 e = e->next;
7484 }
7485#endif
7486 }
7487 return (result);
7488}
7489
7490/**************************************************
7491 * *
7492 * Functions to expand an entire WORD_LIST *
7493 * *
7494 **************************************************/
7495
7496/* Do any word-expansion-specific cleanup and jump to top_level */
7497static void
7498exp_jump_to_top_level (v)
7499 int v;
7500{
7501 /* Cleanup code goes here. */
7502 expand_no_split_dollar_star = 0; /* XXX */
7503 expanding_redir = 0;
7504
7505 jump_to_top_level (v);
7506}
7507
7508/* Put NLIST (which is a WORD_LIST * of only one element) at the front of
7509 ELIST, and set ELIST to the new list. */
7510#define PREPEND_LIST(nlist, elist) \
7511 do { nlist->next = elist; elist = nlist; } while (0)
7512
7513/* Separate out any initial variable assignments from TLIST. If set -k has
7514 been executed, remove all assignment statements from TLIST. Initial
7515 variable assignments and other environment assignments are placed
7516 on SUBST_ASSIGN_VARLIST. */
7517static WORD_LIST *
7518separate_out_assignments (tlist)
7519 WORD_LIST *tlist;
7520{
7521 register WORD_LIST *vp, *lp;
7522
7523 if (!tlist)
7524 return ((WORD_LIST *)NULL);
7525
7526 if (subst_assign_varlist)
7527 dispose_words (subst_assign_varlist); /* Clean up after previous error */
7528
7529 subst_assign_varlist = (WORD_LIST *)NULL;
7530 vp = lp = tlist;
7531
7532 /* Separate out variable assignments at the start of the command.
7533 Loop invariant: vp->next == lp
7534 Loop postcondition:
7535 lp = list of words left after assignment statements skipped
7536 tlist = original list of words
7537 */
7538 while (lp && (lp->word->flags & W_ASSIGNMENT))
7539 {
7540 vp = lp;
7541 lp = lp->next;
7542 }
7543
7544 /* If lp != tlist, we have some initial assignment statements.
7545 We make SUBST_ASSIGN_VARLIST point to the list of assignment
7546 words and TLIST point to the remaining words. */
7547 if (lp != tlist)
7548 {
7549 subst_assign_varlist = tlist;
7550 /* ASSERT(vp->next == lp); */
7551 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
7552 tlist = lp; /* remainder of word list */
7553 }
7554
7555 /* vp == end of variable list */
7556 /* tlist == remainder of original word list without variable assignments */
7557 if (!tlist)
7558 /* All the words in tlist were assignment statements */
7559 return ((WORD_LIST *)NULL);
7560
7561 /* ASSERT(tlist != NULL); */
7562 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
7563
7564 /* If the -k option is in effect, we need to go through the remaining
7565 words, separate out the assignment words, and place them on
7566 SUBST_ASSIGN_VARLIST. */
7567 if (place_keywords_in_env)
7568 {
7569 WORD_LIST *tp; /* tp == running pointer into tlist */
7570
7571 tp = tlist;
7572 lp = tlist->next;
7573
7574 /* Loop Invariant: tp->next == lp */
7575 /* Loop postcondition: tlist == word list without assignment statements */
7576 while (lp)
7577 {
7578 if (lp->word->flags & W_ASSIGNMENT)
7579 {
7580 /* Found an assignment statement, add this word to end of
7581 subst_assign_varlist (vp). */
7582 if (!subst_assign_varlist)
7583 subst_assign_varlist = vp = lp;
7584 else
7585 {
7586 vp->next = lp;
7587 vp = lp;
7588 }
7589
7590 /* Remove the word pointed to by LP from TLIST. */
7591 tp->next = lp->next;
7592 /* ASSERT(vp == lp); */
7593 lp->next = (WORD_LIST *)NULL;
7594 lp = tp->next;
7595 }
7596 else
7597 {
7598 tp = lp;
7599 lp = lp->next;
7600 }
7601 }
7602 }
7603 return (tlist);
7604}
7605
7606#define WEXP_VARASSIGN 0x001
7607#define WEXP_BRACEEXP 0x002
7608#define WEXP_TILDEEXP 0x004
7609#define WEXP_PARAMEXP 0x008
7610#define WEXP_PATHEXP 0x010
7611
7612/* All of the expansions, including variable assignments at the start of
7613 the list. */
7614#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
7615
7616/* All of the expansions except variable assignments at the start of
7617 the list. */
7618#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
7619
7620/* All of the `shell expansions': brace expansion, tilde expansion, parameter
7621 expansion, command substitution, arithmetic expansion, word splitting, and
7622 quote removal. */
7623#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
7624
7625/* Take the list of words in LIST and do the various substitutions. Return
7626 a new list of words which is the expanded list, and without things like
7627 variable assignments. */
7628
7629WORD_LIST *
7630expand_words (list)
7631 WORD_LIST *list;
7632{
7633 return (expand_word_list_internal (list, WEXP_ALL));
7634}
7635
7636/* Same as expand_words (), but doesn't hack variable or environment
7637 variables. */
7638WORD_LIST *
7639expand_words_no_vars (list)
7640 WORD_LIST *list;
7641{
7642 return (expand_word_list_internal (list, WEXP_NOVARS));
7643}
7644
7645WORD_LIST *
7646expand_words_shellexp (list)
7647 WORD_LIST *list;
7648{
7649 return (expand_word_list_internal (list, WEXP_SHELLEXP));
7650}
7651
7652static WORD_LIST *
7653glob_expand_word_list (tlist, eflags)
7654 WORD_LIST *tlist;
7655 int eflags;
7656{
7657 char **glob_array, *temp_string;
7658 register int glob_index;
7659 WORD_LIST *glob_list, *output_list, *disposables, *next;
7660 WORD_DESC *tword;
7661
7662 output_list = disposables = (WORD_LIST *)NULL;
7663 glob_array = (char **)NULL;
7664 while (tlist)
7665 {
7666 /* For each word, either globbing is attempted or the word is
7667 added to orig_list. If globbing succeeds, the results are
7668 added to orig_list and the word (tlist) is added to the list
7669 of disposable words. If globbing fails and failed glob
7670 expansions are left unchanged (the shell default), the
7671 original word is added to orig_list. If globbing fails and
7672 failed glob expansions are removed, the original word is
7673 added to the list of disposable words. orig_list ends up
7674 in reverse order and requires a call to REVERSE_LIST to
7675 be set right. After all words are examined, the disposable
7676 words are freed. */
7677 next = tlist->next;
7678
7679 /* If the word isn't an assignment and contains an unquoted
7680 pattern matching character, then glob it. */
7681 if ((tlist->word->flags & W_NOGLOB) == 0 &&
7682 unquoted_glob_pattern_p (tlist->word->word))
7683 {
7684 glob_array = shell_glob_filename (tlist->word->word);
7685
7686 /* Handle error cases.
7687 I don't think we should report errors like "No such file
7688 or directory". However, I would like to report errors
7689 like "Read failed". */
7690
7691 if (glob_array == 0 || GLOB_FAILED (glob_array))
7692 {
7693 glob_array = (char **)xmalloc (sizeof (char *));
7694 glob_array[0] = (char *)NULL;
7695 }
7696
7697 /* Dequote the current word in case we have to use it. */
7698 if (glob_array[0] == NULL)
7699 {
7700 temp_string = dequote_string (tlist->word->word);
7701 free (tlist->word->word);
7702 tlist->word->word = temp_string;
7703 }
7704
7705 /* Make the array into a word list. */
7706 glob_list = (WORD_LIST *)NULL;
7707 for (glob_index = 0; glob_array[glob_index]; glob_index++)
7708 {
7709 tword = make_bare_word (glob_array[glob_index]);
7710 tword->flags |= W_GLOBEXP; /* XXX */
7711 glob_list = make_word_list (tword, glob_list);
7712 }
7713
7714 if (glob_list)
7715 {
7716 output_list = (WORD_LIST *)list_append (glob_list, output_list);
7717 PREPEND_LIST (tlist, disposables);
7718 }
7719 else if (fail_glob_expansion != 0)
7720 {
7721 report_error (_("no match: %s"), tlist->word->word);
7722 jump_to_top_level (DISCARD);
7723 }
7724 else if (allow_null_glob_expansion == 0)
7725 {
7726 /* Failed glob expressions are left unchanged. */
7727 PREPEND_LIST (tlist, output_list);
7728 }
7729 else
7730 {
7731 /* Failed glob expressions are removed. */
7732 PREPEND_LIST (tlist, disposables);
7733 }
7734 }
7735 else
7736 {
7737 /* Dequote the string. */
7738 temp_string = dequote_string (tlist->word->word);
7739 free (tlist->word->word);
7740 tlist->word->word = temp_string;
7741 PREPEND_LIST (tlist, output_list);
7742 }
7743
7744 strvec_dispose (glob_array);
7745 glob_array = (char **)NULL;
7746
7747 tlist = next;
7748 }
7749
7750 if (disposables)
7751 dispose_words (disposables);
7752
7753 if (output_list)
7754 output_list = REVERSE_LIST (output_list, WORD_LIST *);
7755
7756 return (output_list);
7757}
7758
7759#if defined (BRACE_EXPANSION)
7760static WORD_LIST *
7761brace_expand_word_list (tlist, eflags)
7762 WORD_LIST *tlist;
7763 int eflags;
7764{
7765 register char **expansions;
7766 char *temp_string;
7767 WORD_LIST *disposables, *output_list, *next;
7768 WORD_DESC *w;
7769 int eindex;
7770
7771 for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
7772 {
7773 next = tlist->next;
7774
7775 /* Only do brace expansion if the word has a brace character. If
7776 not, just add the word list element to BRACES and continue. In
7777 the common case, at least when running shell scripts, this will
7778 degenerate to a bunch of calls to `xstrchr', and then what is
7779 basically a reversal of TLIST into BRACES, which is corrected
7780 by a call to REVERSE_LIST () on BRACES when the end of TLIST
7781 is reached. */
7782 if (xstrchr (tlist->word->word, LBRACE))
7783 {
7784 expansions = brace_expand (tlist->word->word);
7785
7786 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
7787 {
7788 w = make_word (temp_string);
7789 /* If brace expansion didn't change the word, preserve
7790 the flags. We may want to preserve the flags
7791 unconditionally someday -- XXX */
7792 if (STREQ (temp_string, tlist->word->word))
7793 w->flags = tlist->word->flags;
7794 output_list = make_word_list (w, output_list);
7795 free (expansions[eindex]);
7796 }
7797 free (expansions);
7798
7799 /* Add TLIST to the list of words to be freed after brace
7800 expansion has been performed. */
7801 PREPEND_LIST (tlist, disposables);
7802 }
7803 else
7804 PREPEND_LIST (tlist, output_list);
7805 }
7806
7807 if (disposables)
7808 dispose_words (disposables);
7809
7810 if (output_list)
7811 output_list = REVERSE_LIST (output_list, WORD_LIST *);
7812
7813 return (output_list);
7814}
7815#endif
7816
7817static WORD_LIST *
7818shell_expand_word_list (tlist, eflags)
7819 WORD_LIST *tlist;
7820 int eflags;
7821{
7822 WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
7823 int expanded_something, has_dollar_at;
7824 char *temp_string;
7825
7826 /* We do tilde expansion all the time. This is what 1003.2 says. */
7827 new_list = (WORD_LIST *)NULL;
7828 for (orig_list = tlist; tlist; tlist = next)
7829 {
7830 temp_string = tlist->word->word;
7831
7832 next = tlist->next;
7833
7834#if defined (ARRAY_VARS)
7835 /* If this is a compound array assignment to a builtin that accepts
7836 such assignments (e.g., `declare'), take the assignment and perform
7837 it separately, handling the semantics of declarations inside shell
7838 functions. This avoids the double-evaluation of such arguments,
7839 because `declare' does some evaluation of compound assignments on
7840 its own. */
7841 if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
7842 {
7843 int t;
7844
7845 t = do_word_assignment (tlist->word);
7846 if (t == 0)
7847 {
7848 last_command_exit_value = EXECUTION_FAILURE;
7849 exp_jump_to_top_level (DISCARD);
7850 }
7851
7852 /* Now transform the word as ksh93 appears to do and go on */
7853 t = assignment (tlist->word->word, 0);
7854 tlist->word->word[t] = '\0';
7855 tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG);
7856 }
7857#endif
7858
7859 expanded_something = 0;
7860 expanded = expand_word_internal
7861 (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
7862
7863 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
7864 {
7865 /* By convention, each time this error is returned,
7866 tlist->word->word has already been freed. */
7867 tlist->word->word = (char *)NULL;
7868
7869 /* Dispose our copy of the original list. */
7870 dispose_words (orig_list);
7871 /* Dispose the new list we're building. */
7872 dispose_words (new_list);
7873
7874 last_command_exit_value = EXECUTION_FAILURE;
7875 if (expanded == &expand_word_error)
7876 exp_jump_to_top_level (DISCARD);
7877 else
7878 exp_jump_to_top_level (FORCE_EOF);
7879 }
7880
7881 /* Don't split words marked W_NOSPLIT. */
7882 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
7883 {
7884 temp_list = word_list_split (expanded);
7885 dispose_words (expanded);
7886 }
7887 else
7888 {
7889 /* If no parameter expansion, command substitution, process
7890 substitution, or arithmetic substitution took place, then
7891 do not do word splitting. We still have to remove quoted
7892 null characters from the result. */
7893 word_list_remove_quoted_nulls (expanded);
7894 temp_list = expanded;
7895 }
7896
7897 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
7898 new_list = (WORD_LIST *)list_append (expanded, new_list);
7899 }
7900
7901 if (orig_list)
7902 dispose_words (orig_list);
7903
7904 if (new_list)
7905 new_list = REVERSE_LIST (new_list, WORD_LIST *);
7906
7907 return (new_list);
7908}
7909
7910/* The workhorse for expand_words () and expand_words_no_vars ().
7911 First arg is LIST, a WORD_LIST of words.
7912 Second arg EFLAGS is a flags word controlling which expansions are
7913 performed.
7914
7915 This does all of the substitutions: brace expansion, tilde expansion,
7916 parameter expansion, command substitution, arithmetic expansion,
7917 process substitution, word splitting, and pathname expansion, according
7918 to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
7919 set, or for which no expansion is done, do not undergo word splitting.
7920 Words with the W_NOGLOB bit set do not undergo pathname expansion. */
7921static WORD_LIST *
7922expand_word_list_internal (list, eflags)
7923 WORD_LIST *list;
7924 int eflags;
7925{
7926 WORD_LIST *new_list, *temp_list;
7927 int tint;
7928
7929 if (list == 0)
7930 return ((WORD_LIST *)NULL);
7931
7932 garglist = new_list = copy_word_list (list);
7933 if (eflags & WEXP_VARASSIGN)
7934 {
7935 garglist = new_list = separate_out_assignments (new_list);
7936 if (new_list == 0)
7937 {
7938 if (subst_assign_varlist)
7939 {
7940 /* All the words were variable assignments, so they are placed
7941 into the shell's environment. */
7942 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
7943 {
7944 this_command_name = (char *)NULL; /* no arithmetic errors */
7945 tint = do_word_assignment (temp_list->word);
7946 /* Variable assignment errors in non-interactive shells
7947 running in Posix.2 mode cause the shell to exit. */
7948 if (tint == 0)
7949 {
7950 last_command_exit_value = EXECUTION_FAILURE;
7951 if (interactive_shell == 0 && posixly_correct)
7952 exp_jump_to_top_level (FORCE_EOF);
7953 else
7954 exp_jump_to_top_level (DISCARD);
7955 }
7956 }
7957 dispose_words (subst_assign_varlist);
7958 subst_assign_varlist = (WORD_LIST *)NULL;
7959 }
7960 return ((WORD_LIST *)NULL);
7961 }
7962 }
7963
7964 /* Begin expanding the words that remain. The expansions take place on
7965 things that aren't really variable assignments. */
7966
7967#if defined (BRACE_EXPANSION)
7968 /* Do brace expansion on this word if there are any brace characters
7969 in the string. */
7970 if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
7971 new_list = brace_expand_word_list (new_list, eflags);
7972#endif /* BRACE_EXPANSION */
7973
7974 /* Perform the `normal' shell expansions: tilde expansion, parameter and
7975 variable substitution, command substitution, arithmetic expansion,
7976 and word splitting. */
7977 new_list = shell_expand_word_list (new_list, eflags);
7978
7979 /* Okay, we're almost done. Now let's just do some filename
7980 globbing. */
7981 if (new_list)
7982 {
7983 if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
7984 /* Glob expand the word list unless globbing has been disabled. */
7985 new_list = glob_expand_word_list (new_list, eflags);
7986 else
7987 /* Dequote the words, because we're not performing globbing. */
7988 new_list = dequote_list (new_list);
7989 }
7990
7991 if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
7992 {
7993 sh_wassign_func_t *assign_func;
7994
7995 /* If the remainder of the words expand to nothing, Posix.2 requires
7996 that the variable and environment assignments affect the shell's
7997 environment. */
7998 assign_func = new_list ? assign_in_env : do_word_assignment;
7999 tempenv_assign_error = 0;
8000
8001 for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
8002 {
8003 this_command_name = (char *)NULL;
8004 tint = (*assign_func) (temp_list->word);
8005 /* Variable assignment errors in non-interactive shells running
8006 in Posix.2 mode cause the shell to exit. */
8007 if (tint == 0)
8008 {
8009 if (assign_func == do_word_assignment)
8010 {
8011 last_command_exit_value = EXECUTION_FAILURE;
8012 if (interactive_shell == 0 && posixly_correct)
8013 exp_jump_to_top_level (FORCE_EOF);
8014 else
8015 exp_jump_to_top_level (DISCARD);
8016 }
8017 else
8018 tempenv_assign_error++;
8019 }
8020 }
8021
8022 dispose_words (subst_assign_varlist);
8023 subst_assign_varlist = (WORD_LIST *)NULL;
8024 }
8025
8026#if 0
8027 tint = list_length (new_list) + 1;
8028 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
8029 for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
8030 glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
8031 glob_argv_flags[tint] = '\0';
8032#endif
8033
8034 return (new_list);
8035}
Note: See TracBrowser for help on using the repository browser.