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