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