1 /* arrayfunc.c -- High-level array functions used by other parts of the shell. */
3 /* Copyright (C) 2001-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
23 #if defined (ARRAY_VARS)
25 #if defined (HAVE_UNISTD_H)
33 #include "execute_cmd.h"
37 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
38 # include <mbstr.h> /* mbschr */
41 #include "builtins/common.h"
48 /* This variable means to not expand associative array subscripts more than
49 once, when performing variable expansion. */
50 int assoc_expand_once
= 0;
52 /* Ditto for indexed array subscripts -- currently unused */
53 int array_expand_once
= 0;
55 static SHELL_VAR
*bind_array_var_internal
PARAMS((SHELL_VAR
*, arrayind_t
, char *, char *, int));
56 static SHELL_VAR
*assign_array_element_internal
PARAMS((SHELL_VAR
*, char *, char *, char *, int, char *, int));
58 static void assign_assoc_from_kvlist
PARAMS((SHELL_VAR
*, WORD_LIST
*, HASH_TABLE
*, int));
60 static char *quote_assign
PARAMS((const char *));
61 static void quote_array_assignment_chars
PARAMS((WORD_LIST
*));
62 static char *quote_compound_array_word
PARAMS((char *, int));
63 static char *array_value_internal
PARAMS((const char *, int, int, int *, arrayind_t
*));
65 /* Standard error message to use when encountering an invalid array subscript */
66 const char * const bash_badsub_errmsg
= N_("bad array subscript");
68 /* **************************************************************** */
70 /* Functions to manipulate array variables and perform assignments */
72 /* **************************************************************** */
74 /* Convert a shell variable to an array variable. The original value is
77 convert_var_to_array (var
)
83 oldval
= value_cell (var
);
84 array
= array_create ();
86 array_insert (array
, 0, oldval
);
88 FREE (value_cell (var
));
89 var_setarray (var
, array
);
91 /* these aren't valid anymore */
92 var
->dynamic_value
= (sh_var_value_func_t
*)NULL
;
93 var
->assign_func
= (sh_var_assign_func_t
*)NULL
;
95 INVALIDATE_EXPORTSTR (var
);
99 VSETATTR (var
, att_array
);
101 VUNSETATTR (var
, att_invisible
);
103 /* Make sure it's not marked as an associative array any more */
104 VUNSETATTR (var
, att_assoc
);
106 /* Since namerefs can't be array variables, turn off nameref attribute */
107 VUNSETATTR (var
, att_nameref
);
112 /* Convert a shell variable to an array variable. The original value is
113 saved as array[0]. */
115 convert_var_to_assoc (var
)
121 oldval
= value_cell (var
);
122 hash
= assoc_create (0);
124 assoc_insert (hash
, savestring ("0"), oldval
);
126 FREE (value_cell (var
));
127 var_setassoc (var
, hash
);
129 /* these aren't valid anymore */
130 var
->dynamic_value
= (sh_var_value_func_t
*)NULL
;
131 var
->assign_func
= (sh_var_assign_func_t
*)NULL
;
133 INVALIDATE_EXPORTSTR (var
);
134 if (exported_p (var
))
135 array_needs_making
++;
137 VSETATTR (var
, att_assoc
);
139 VUNSETATTR (var
, att_invisible
);
141 /* Make sure it's not marked as an indexed array any more */
142 VUNSETATTR (var
, att_array
);
144 /* Since namerefs can't be array variables, turn off nameref attribute */
145 VUNSETATTR (var
, att_nameref
);
151 make_array_variable_value (entry
, ind
, key
, value
, flags
)
161 /* If we're appending, we need the old value of the array reference, so
162 fake out make_variable_value with a dummy SHELL_VAR */
163 if (flags
& ASS_APPEND
)
165 dentry
= (SHELL_VAR
*)xmalloc (sizeof (SHELL_VAR
));
166 dentry
->name
= savestring (entry
->name
);
168 newval
= assoc_reference (assoc_cell (entry
), key
);
170 newval
= array_reference (array_cell (entry
), ind
);
172 dentry
->value
= savestring (newval
);
175 dentry
->value
= (char *)xmalloc (1);
176 dentry
->value
[0] = '\0';
178 dentry
->exportstr
= 0;
179 dentry
->attributes
= entry
->attributes
& ~(att_array
|att_assoc
|att_exported
);
180 /* Leave the rest of the members uninitialized; the code doesn't look
182 newval
= make_variable_value (dentry
, value
, flags
);
183 dispose_variable (dentry
);
186 newval
= make_variable_value (entry
, value
, flags
);
191 /* Assign HASH[KEY]=VALUE according to FLAGS. ENTRY is an associative array
192 variable; HASH is the hash table to assign into. HASH may or may not be
193 the hash table associated with ENTRY; if it's not, the caller takes care
195 XXX - make sure that any dynamic associative array variables recreate the
196 hash table on each assignment. BASH_CMDS and BASH_ALIASES already do this */
198 bind_assoc_var_internal (entry
, hash
, key
, value
, flags
)
207 /* Use the existing array contents to expand the value */
208 newval
= make_array_variable_value (entry
, 0, key
, value
, flags
);
210 if (entry
->assign_func
)
211 (*entry
->assign_func
) (entry
, newval
, 0, key
);
213 assoc_insert (hash
, key
, newval
);
217 VUNSETATTR (entry
, att_invisible
); /* no longer invisible */
219 /* check mark_modified_variables if we ever want to export array vars */
223 /* Perform ENTRY[IND]=VALUE or ENTRY[KEY]=VALUE. This is not called for every
224 assignment to an associative array; see assign_compound_array_list below. */
226 bind_array_var_internal (entry
, ind
, key
, value
, flags
)
235 newval
= make_array_variable_value (entry
, ind
, key
, value
, flags
);
237 if (entry
->assign_func
)
238 (*entry
->assign_func
) (entry
, newval
, ind
, key
);
239 else if (assoc_p (entry
))
240 assoc_insert (assoc_cell (entry
), key
, newval
);
242 array_insert (array_cell (entry
), ind
, newval
);
245 VUNSETATTR (entry
, att_invisible
); /* no longer invisible */
247 /* check mark_modified_variables if we ever want to export array vars */
251 /* Perform an array assignment name[ind]=value. If NAME already exists and
252 is not an array, and IND is 0, perform name=value instead. If NAME exists
253 and is not an array, and IND is not 0, convert it into an array with the
254 existing value as name[0].
256 If NAME does not exist, just create an array variable, no matter what
257 IND's value may be. */
259 bind_array_variable (name
, ind
, value
, flags
)
267 entry
= find_shell_variable (name
);
269 if (entry
== (SHELL_VAR
*) 0)
271 /* Is NAME a nameref variable that points to an unset variable? */
272 entry
= find_variable_nameref_for_create (name
, 0);
273 if (entry
== INVALID_NAMEREF_VALUE
)
274 return ((SHELL_VAR
*)0);
275 if (entry
&& nameref_p (entry
))
276 entry
= make_new_array_variable (nameref_cell (entry
));
278 if (entry
== (SHELL_VAR
*) 0)
279 entry
= make_new_array_variable (name
);
280 else if ((readonly_p (entry
) && (flags
&ASS_FORCE
) == 0) || noassign_p (entry
))
282 if (readonly_p (entry
))
286 else if (array_p (entry
) == 0)
287 entry
= convert_var_to_array (entry
);
289 /* ENTRY is an array variable, and ARRAY points to the value. */
290 return (bind_array_var_internal (entry
, ind
, 0, value
, flags
));
294 bind_array_element (entry
, ind
, value
, flags
)
300 return (bind_array_var_internal (entry
, ind
, 0, value
, flags
));
304 bind_assoc_variable (entry
, name
, key
, value
, flags
)
311 if ((readonly_p (entry
) && (flags
&ASS_FORCE
) == 0) || noassign_p (entry
))
313 if (readonly_p (entry
))
318 return (bind_assoc_var_internal (entry
, assoc_cell (entry
), key
, value
, flags
));
321 /* Parse NAME, a lhs of an assignment statement of the form v[s], and
322 assign VALUE to that array element by calling bind_array_variable().
323 Flags are ASS_ assignment flags */
325 assign_array_element (name
, value
, flags
)
333 vname
= array_variable_name (name
, (flags
& ASS_NOEXPAND
) != 0, &sub
, &sublen
);
336 return ((SHELL_VAR
*)NULL
);
338 entry
= find_variable (vname
);
339 isassoc
= entry
&& assoc_p (entry
);
341 if (((isassoc
== 0 || (flags
& ASS_NOEXPAND
) == 0) && (ALL_ELEMENT_SUB (sub
[0]) && sub
[1] == ']')) || (sublen
<= 1))
344 err_badarraysub (name
);
345 return ((SHELL_VAR
*)NULL
);
348 entry
= assign_array_element_internal (entry
, name
, vname
, sub
, sublen
, value
, flags
);
355 assign_array_element_internal (entry
, name
, vname
, sub
, sublen
, value
, flags
)
357 char *name
; /* only used for error messages */
367 if (entry
&& assoc_p (entry
))
369 sub
[sublen
-1] = '\0';
370 if ((flags
& ASS_NOEXPAND
) == 0)
371 akey
= expand_assignment_string_to_string (sub
, 0); /* [ */
373 akey
= savestring (sub
);
375 if (akey
== 0 || *akey
== 0)
377 err_badarraysub (name
);
379 return ((SHELL_VAR
*)NULL
);
381 entry
= bind_assoc_variable (entry
, vname
, akey
, value
, flags
);
385 ind
= array_expand_index (entry
, sub
, sublen
, 0);
386 /* negative subscripts to indexed arrays count back from end */
387 if (entry
&& ind
< 0)
388 ind
= (array_p (entry
) ? array_max_index (array_cell (entry
)) : 0) + 1 + ind
;
391 err_badarraysub (name
);
392 return ((SHELL_VAR
*)NULL
);
394 entry
= bind_array_variable (vname
, ind
, value
, flags
);
400 /* Find the array variable corresponding to NAME. If there is no variable,
401 create a new array variable. If the variable exists but is not an array,
402 convert it to an indexed array. If FLAGS&1 is non-zero, an existing
403 variable is checked for the readonly or noassign attribute in preparation
404 for assignment (e.g., by the `read' builtin). If FLAGS&2 is non-zero, we
405 create an associative array. */
407 find_or_make_array_variable (name
, flags
)
413 var
= find_variable (name
);
416 /* See if we have a nameref pointing to a variable that hasn't been
418 var
= find_variable_last_nameref (name
, 1);
419 if (var
&& nameref_p (var
) && invisible_p (var
))
421 internal_warning (_("%s: removing nameref attribute"), name
);
422 VUNSETATTR (var
, att_nameref
);
424 if (var
&& nameref_p (var
))
426 if (valid_nameref_value (nameref_cell (var
), 2) == 0)
428 sh_invalidid (nameref_cell (var
));
429 return ((SHELL_VAR
*)NULL
);
431 var
= (flags
& 2) ? make_new_assoc_variable (nameref_cell (var
)) : make_new_array_variable (nameref_cell (var
));
436 var
= (flags
& 2) ? make_new_assoc_variable (name
) : make_new_array_variable (name
);
437 else if ((flags
& 1) && (readonly_p (var
) || noassign_p (var
)))
439 if (readonly_p (var
))
441 return ((SHELL_VAR
*)NULL
);
443 else if ((flags
& 2) && array_p (var
))
445 set_exit_status (EXECUTION_FAILURE
);
446 report_error (_("%s: cannot convert indexed to associative array"), name
);
447 return ((SHELL_VAR
*)NULL
);
449 else if (array_p (var
) == 0 && assoc_p (var
) == 0)
450 var
= convert_var_to_array (var
);
455 /* Perform a compound assignment statement for array NAME, where VALUE is
456 the text between the parens: NAME=( VALUE ) */
458 assign_array_from_string (name
, value
, flags
)
466 if (flags
& ASS_MKASSOC
)
469 var
= find_or_make_array_variable (name
, vflags
);
471 return ((SHELL_VAR
*)NULL
);
473 return (assign_array_var_from_string (var
, value
, flags
));
476 /* Sequentially assign the indices of indexed array variable VAR from the
479 assign_array_var_from_word_list (var
, list
, flags
)
484 register arrayind_t i
;
485 register WORD_LIST
*l
;
488 a
= array_cell (var
);
489 i
= (flags
& ASS_APPEND
) ? array_max_index (a
) + 1 : 0;
491 for (l
= list
; l
; l
= l
->next
, i
++)
492 bind_array_var_internal (var
, i
, 0, l
->word
->word
, flags
& ~ASS_APPEND
);
494 VUNSETATTR (var
, att_invisible
); /* no longer invisible */
500 expand_compound_array_assignment (var
, value
, flags
)
505 WORD_LIST
*list
, *nlist
;
509 /* This condition is true when invoked from the declare builtin with a
511 declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' */
512 if (*value
== '(') /*)*/
515 val
= extract_array_assignment_list (value
, &ni
);
517 return (WORD_LIST
*)NULL
;
522 /* Expand the value string into a list of words, performing all the
523 shell expansions including pathname generation and word splitting. */
524 /* First we split the string on whitespace, using the shell parser
525 (ksh93 seems to do this). */
526 list
= parse_string_to_word_list (val
, 1, "array assign");
528 /* Note that we defer expansion of the assignment statements for associative
529 arrays here, so we don't have to scan the subscript and find the ending
530 bracket twice. See the caller below. */
531 if (var
&& assoc_p (var
))
538 /* If we're using [subscript]=value, we need to quote each [ and ] to
539 prevent unwanted filename expansion. This doesn't need to be done
540 for associative array expansion, since that uses a different expansion
541 function (see assign_compound_array_list below). */
543 quote_array_assignment_chars (list
);
545 /* Now that we've split it, perform the shell expansions on each
547 nlist
= list
? expand_words_no_vars (list
) : (WORD_LIST
*)NULL
;
549 dispose_words (list
);
557 #if ASSOC_KVPAIR_ASSIGNMENT
559 assign_assoc_from_kvlist (var
, nlist
, h
, flags
)
566 char *akey
, *aval
, *k
, *v
;
568 for (list
= nlist
; list
; list
= list
->next
)
570 k
= list
->word
->word
;
571 v
= list
->next
? list
->next
->word
->word
: 0;
576 akey
= expand_assignment_string_to_string (k
, 0);
577 if (akey
== 0 || *akey
== 0)
584 aval
= expand_assignment_string_to_string (v
, 0);
587 aval
= (char *)xmalloc (1);
588 aval
[0] = '\0'; /* like do_assignment_internal */
591 bind_assoc_var_internal (var
, h
, akey
, aval
, flags
);
596 /* Return non-zero if L appears to be a key-value pair associative array
597 compound assignment. */
599 kvpair_assignment_p (l
)
602 return (l
&& (l
->word
->flags
& W_ASSIGNMENT
) == 0 && l
->word
->word
[0] != '['); /*]*/
606 expand_and_quote_kvpair_word (w
)
611 t
= w
? expand_assignment_string_to_string (w
, 0) : 0;
612 r
= sh_single_quote (t
? t
: "");
618 /* Callers ensure that VAR is not NULL. Associative array assignments have not
619 been expanded when this is called, or have been expanded once and single-
620 quoted, so we don't have to scan through an unquoted expanded subscript to
621 find the ending bracket; indexed array assignments have been expanded and
622 possibly single-quoted to prevent further expansion.
624 If this is an associative array, we perform the assignments into NHASH and
625 set NHASH to be the value of VAR after processing the assignments in NLIST */
627 assign_compound_array_list (var
, nlist
, flags
)
633 HASH_TABLE
*h
, *nhash
;
635 char *w
, *val
, *nval
, *savecmd
;
636 int len
, iflags
, free_val
;
637 arrayind_t ind
, last_ind
;
640 a
= (var
&& array_p (var
)) ? array_cell (var
) : (ARRAY
*)0;
641 nhash
= h
= (var
&& assoc_p (var
)) ? assoc_cell (var
) : (HASH_TABLE
*)0;
646 /* Now that we are ready to assign values to the array, kill the existing
648 if ((flags
& ASS_APPEND
) == 0)
650 if (a
&& array_p (var
))
652 else if (h
&& assoc_p (var
))
653 nhash
= assoc_create (h
->nbuckets
);
656 last_ind
= (a
&& (flags
& ASS_APPEND
)) ? array_max_index (a
) + 1 : 0;
658 #if ASSOC_KVPAIR_ASSIGNMENT
659 if (assoc_p (var
) && kvpair_assignment_p (nlist
))
661 iflags
= flags
& ~ASS_APPEND
;
662 assign_assoc_from_kvlist (var
, nlist
, nhash
, iflags
);
663 if (nhash
&& nhash
!= h
)
665 h
= assoc_cell (var
);
666 var_setassoc (var
, nhash
);
673 for (list
= nlist
; list
; list
= list
->next
)
675 /* Don't allow var+=(values) to make assignments in VALUES append to
676 existing values by default. */
677 iflags
= flags
& ~ASS_APPEND
;
678 w
= list
->word
->word
;
680 /* We have a word of the form [ind]=value */
681 if ((list
->word
->flags
& W_ASSIGNMENT
) && w
[0] == '[')
683 /* Don't have to handle embedded quotes specially any more, since
684 associative array subscripts have not been expanded yet (see
686 len
= skipsubscript (w
, 0, 0);
688 /* XXX - changes for `+=' */
689 if (w
[len
] != ']' || (w
[len
+1] != '=' && (w
[len
+1] != '+' || w
[len
+2] != '=')))
696 nval
= make_variable_value (var
, w
, flags
);
697 if (var
->assign_func
)
698 (*var
->assign_func
) (var
, nval
, last_ind
, 0);
700 array_insert (a
, last_ind
, nval
);
712 if (ALL_ELEMENT_SUB (w
[1]) && len
== 2)
714 set_exit_status (EXECUTION_FAILURE
);
716 report_error (_("%s: invalid associative array key"), w
);
718 report_error (_("%s: cannot assign to non-numeric index"), w
);
724 ind
= array_expand_index (var
, w
+ 1, len
, 0);
725 /* negative subscripts to indexed arrays count back from end */
727 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
736 else if (assoc_p (var
))
738 /* This is not performed above, see expand_compound_array_assignment */
740 akey
= expand_assignment_string_to_string (w
+1, 0);
742 /* And we need to expand the value also, see below */
743 if (akey
== 0 || *akey
== 0)
751 /* XXX - changes for `+=' -- just accept the syntax. ksh93 doesn't do this */
752 if (w
[len
+ 1] == '+' && w
[len
+ 2] == '=')
754 iflags
|= ASS_APPEND
;
760 else if (assoc_p (var
))
762 set_exit_status (EXECUTION_FAILURE
);
763 report_error (_("%s: %s: must use subscript when assigning associative array"), var
->name
, w
);
766 else /* No [ind]=value, just a stray `=' */
773 /* See above; we need to expand the value here */
776 val
= expand_assignment_string_to_string (val
, 0);
779 val
= (char *)xmalloc (1);
780 val
[0] = '\0'; /* like do_assignment_internal */
785 savecmd
= this_command_name
;
787 this_command_name
= (char *)NULL
; /* no command name for errors */
789 bind_assoc_var_internal (var
, nhash
, akey
, val
, iflags
);
791 bind_array_var_internal (var
, ind
, akey
, val
, iflags
);
793 this_command_name
= savecmd
;
799 if (assoc_p (var
) && nhash
&& nhash
!= h
)
801 h
= assoc_cell (var
);
802 var_setassoc (var
, nhash
);
807 /* Perform a compound array assignment: VAR->name=( VALUE ). The
808 VALUE has already had the parentheses stripped. */
810 assign_array_var_from_string (var
, value
, flags
)
820 nlist
= expand_compound_array_assignment (var
, value
, flags
);
821 assign_compound_array_list (var
, nlist
, flags
);
824 dispose_words (nlist
);
827 VUNSETATTR (var
, att_invisible
); /* no longer invisible */
832 /* Quote globbing chars and characters in $IFS before the `=' in an assignment
833 statement (usually a compound array assignment) to protect them from
834 unwanted filename expansion or word splitting. */
836 quote_assign (string
)
841 char *temp
, *t
, *subs
;
842 const char *s
, *send
;
846 slen
= strlen (string
);
847 send
= string
+ slen
;
849 t
= temp
= (char *)xmalloc (slen
* 2 + 1);
851 for (s
= string
; *s
; )
855 if (saw_eq
== 0 && *s
== '[') /* looks like a subscript */
858 se
= skipsubscript (string
, ss
, 0);
859 subs
= substring (s
, ss
, se
);
869 if (saw_eq
== 0 && (glob_char_p (s
) || isifs (*s
)))
872 COPY_CHAR_P (t
, s
, send
);
878 /* Take a word W of the form [IND]=VALUE and transform it to ['IND']='VALUE'
879 to prevent further expansion. This is called for compound assignments to
880 indexed arrays. W has already undergone word expansions. If W has no [IND]=,
881 just single-quote and return it. */
883 quote_compound_array_word (w
, type
)
887 char *nword
, *sub
, *value
, *t
;
891 return (sh_single_quote (w
));
892 ind
= skipsubscript (w
, 0, 0);
893 if (w
[ind
] != RBRACK
)
894 return (sh_single_quote (w
));
898 sub
= sh_single_quote (w
+1);
901 nword
= xmalloc (wlen
* 4 + 5); /* wlen*4 is max single quoted length */
904 memcpy (nword
+1, sub
, i
);
905 i
++; /* accommodate the opening LBRACK */
906 nword
[i
++] = w
[ind
++]; /* RBRACK */
908 nword
[i
++] = w
[ind
++];
909 nword
[i
++] = w
[ind
++];
910 value
= sh_single_quote (w
+ ind
);
911 strcpy (nword
+ i
, value
);
916 /* Expand the key and value in W, which is of the form [KEY]=VALUE, and
917 reconstruct W with the expanded and single-quoted version:
918 ['expanded-key']='expanded-value'. If there is no [KEY]=, single-quote the
919 word and return it. Very similar to previous function, but does not assume
920 W has already been expanded, and expands the KEY and VALUE separately.
921 Used for compound assignments to associative arrays that are arguments to
922 declaration builtins (declare -A a=( list )). */
924 expand_and_quote_assoc_word (w
, type
)
928 char *nword
, *key
, *value
, *t
;
932 return (sh_single_quote (w
));
933 ind
= skipsubscript (w
, 0, 0);
934 if (w
[ind
] != RBRACK
)
935 return (sh_single_quote (w
));
938 t
= expand_assignment_string_to_string (w
+1, 0);
940 key
= sh_single_quote (t
? t
: "");
944 nword
= xmalloc (wlen
+ 5);
946 memcpy (nword
+1, key
, wlen
);
947 i
= wlen
+ 1; /* accommodate the opening LBRACK */
949 nword
[i
++] = w
[ind
++]; /* RBRACK */
951 nword
[i
++] = w
[ind
++];
952 nword
[i
++] = w
[ind
++];
954 t
= expand_assignment_string_to_string (w
+ind
, 0);
955 value
= sh_single_quote (t
? t
: "");
957 nword
= xrealloc (nword
, wlen
+ 5 + STRLEN (value
));
958 strcpy (nword
+ i
, value
);
966 /* For each word in a compound array assignment, if the word looks like
967 [ind]=value, single-quote ind and value, but leave the brackets and
968 the = sign (and any `+') alone. If it's not an assignment, just single-
969 quote the word. This is used for indexed arrays. */
971 quote_compound_array_list (list
, type
)
978 for (l
= list
; l
; l
= l
->next
)
980 if (l
->word
== 0 || l
->word
->word
== 0)
981 continue; /* should not happen, but just in case... */
982 if ((l
->word
->flags
& W_ASSIGNMENT
) == 0)
983 t
= sh_single_quote (l
->word
->word
);
985 t
= quote_compound_array_word (l
->word
->word
, type
);
986 free (l
->word
->word
);
991 /* For each word in a compound array assignment, if the word looks like
992 [ind]=value, quote globbing chars and characters in $IFS before the `='. */
994 quote_array_assignment_chars (list
)
1000 for (l
= list
; l
; l
= l
->next
)
1002 if (l
->word
== 0 || l
->word
->word
== 0 || l
->word
->word
[0] == '\0')
1003 continue; /* should not happen, but just in case... */
1004 /* Don't bother if it hasn't been recognized as an assignment or
1005 doesn't look like [ind]=value */
1006 if ((l
->word
->flags
& W_ASSIGNMENT
) == 0)
1008 if (l
->word
->word
[0] != '[' || mbschr (l
->word
->word
, '=') == 0) /* ] */
1011 nword
= quote_assign (l
->word
->word
);
1012 free (l
->word
->word
);
1013 l
->word
->word
= nword
;
1014 l
->word
->flags
|= W_NOGLOB
; /* XXX - W_NOSPLIT also? */
1018 /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
1020 /* This function is called with SUB pointing to just after the beginning
1021 `[' of an array subscript and removes the array element to which SUB
1022 expands from array VAR. A subscript of `*' or `@' unsets the array. */
1023 /* If FLAGS&1 we don't expand the subscript; we just use it as-is. */
1025 unbind_array_element (var
, sub
, flags
)
1035 len
= skipsubscript (sub
, 0, (flags
&1) || (var
&& assoc_p(var
))); /* XXX */
1036 if (sub
[len
] != ']' || len
== 0)
1038 builtin_error ("%s[%s: %s", var
->name
, sub
, _(bash_badsub_errmsg
));
1043 if (ALL_ELEMENT_SUB (sub
[0]) && sub
[1] == 0)
1045 if (array_p (var
) || assoc_p (var
))
1047 unbind_variable (var
->name
); /* XXX -- {array,assoc}_flush ? */
1051 return -2; /* don't allow this to unset scalar variables */
1056 akey
= (flags
& 1) ? sub
: expand_assignment_string_to_string (sub
, 0);
1057 if (akey
== 0 || *akey
== 0)
1059 builtin_error ("[%s]: %s", sub
, _(bash_badsub_errmsg
));
1063 assoc_remove (assoc_cell (var
), akey
);
1067 else if (array_p (var
))
1069 ind
= array_expand_index (var
, sub
, len
+1, 0);
1070 /* negative subscripts to indexed arrays count back from end */
1072 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
1075 builtin_error ("[%s]: %s", sub
, _(bash_badsub_errmsg
));
1078 ae
= array_remove (array_cell (var
), ind
);
1080 array_dispose_element (ae
);
1082 else /* array_p (var) == 0 && assoc_p (var) == 0 */
1084 akey
= this_command_name
;
1085 ind
= array_expand_index (var
, sub
, len
+1, 0);
1086 this_command_name
= akey
;
1089 unbind_variable (var
->name
);
1093 return -2; /* any subscript other than 0 is invalid with scalar variables */
1099 /* Format and output an array assignment in compound form VAR=(VALUES),
1100 suitable for re-use as input. */
1102 print_array_assignment (var
, quoted
)
1108 vstr
= array_to_assign (array_cell (var
), quoted
);
1111 printf ("%s=%s\n", var
->name
, quoted
? "'()'" : "()");
1114 printf ("%s=%s\n", var
->name
, vstr
);
1119 /* Format and output an associative array assignment in compound form
1120 VAR=(VALUES), suitable for re-use as input. */
1122 print_assoc_assignment (var
, quoted
)
1128 vstr
= assoc_to_assign (assoc_cell (var
), quoted
);
1131 printf ("%s=%s\n", var
->name
, quoted
? "'()'" : "()");
1134 printf ("%s=%s\n", var
->name
, vstr
);
1139 /***********************************************************************/
1141 /* Utility functions to manage arrays and their contents for expansion */
1143 /***********************************************************************/
1145 /* Return 1 if NAME is a properly-formed array reference v[sub]. */
1147 /* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
1149 valid_array_reference (name
, flags
)
1154 int r
, len
, isassoc
;
1157 t
= mbschr (name
, '['); /* ] */
1162 r
= legal_identifier (name
);
1163 if (flags
& VA_NOEXPAND
) /* Don't waste a lookup if we don't need one */
1164 isassoc
= (entry
= find_variable (name
)) && assoc_p (entry
);
1169 if (isassoc
&& ((flags
& (VA_NOEXPAND
|VA_ONEWORD
)) == (VA_NOEXPAND
|VA_ONEWORD
)))
1170 len
= strlen (t
) - 1;
1172 len
= skipsubscript (t
, 0, flags
&VA_NOEXPAND
); /* VA_NOEXPAND must be 1 */
1174 /* Check for a properly-terminated non-null subscript. */
1175 len
= skipsubscript (t
, 0, 0); /* arithmetic expression */
1177 if (t
[len
] != ']' || len
== 1 || t
[len
+1] != '\0')
1181 /* Could check and allow subscripts consisting only of whitespace for
1182 existing associative arrays, using isassoc */
1183 for (r
= 1; r
< len
; r
++)
1184 if (whitespace (t
[r
]) == 0)
1188 /* This allows blank subscripts */
1195 /* Expand the array index beginning at S and extending LEN characters. */
1197 array_expand_index (var
, s
, len
, flags
)
1203 char *exp
, *t
, *savecmd
;
1207 exp
= (char *)xmalloc (len
);
1208 strncpy (exp
, s
, len
- 1);
1209 exp
[len
- 1] = '\0';
1210 #if 0 /* TAG: maybe bash-5.2 */
1211 if ((flags
& AV_NOEXPAND
) == 0)
1212 t
= expand_arith_string (exp
, Q_DOUBLE_QUOTES
|Q_ARITH
|Q_ARRAYSUB
); /* XXX - Q_ARRAYSUB for future use */
1216 t
= expand_arith_string (exp
, Q_DOUBLE_QUOTES
|Q_ARITH
|Q_ARRAYSUB
); /* XXX - Q_ARRAYSUB for future use */
1217 savecmd
= this_command_name
;
1218 this_command_name
= (char *)NULL
;
1219 val
= evalexp (t
, EXP_EXPANDED
, &expok
); /* XXX - was 0 but we expanded exp already */
1220 this_command_name
= savecmd
;
1226 set_exit_status (EXECUTION_FAILURE
);
1228 if (no_longjmp_on_fatal_error
)
1230 top_level_cleanup ();
1231 jump_to_top_level (DISCARD
);
1236 /* Return the name of the variable specified by S without any subscript.
1237 If SUBP is non-null, return a pointer to the start of the subscript
1238 in *SUBP. If LENP is non-null, the length of the subscript is returned
1239 in *LENP. This returns newly-allocated memory. */
1241 array_variable_name (s
, flags
, subp
, lenp
)
1250 t
= mbschr (s
, '[');
1257 return ((char *)NULL
);
1260 ni
= skipsubscript (s
, ind
, flags
); /* XXX - was 0 not flags */
1261 if (ni
<= ind
+ 1 || s
[ni
] != ']')
1263 err_badarraysub (s
);
1268 return ((char *)NULL
);
1272 ret
= savestring (s
);
1283 /* Return the variable specified by S without any subscript. If SUBP is
1284 non-null, return a pointer to the start of the subscript in *SUBP.
1285 If LENP is non-null, the length of the subscript is returned in *LENP. */
1287 array_variable_part (s
, flags
, subp
, lenp
)
1296 t
= array_variable_name (s
, flags
, subp
, lenp
);
1298 return ((SHELL_VAR
*)NULL
);
1299 var
= find_variable (t
); /* XXX - handle namerefs here? */
1302 return var
; /* now return invisible variables; caller must handle */
1305 #define INDEX_ERROR() \
1309 err_badarraysub (var->name); \
1313 err_badarraysub (s); \
1314 t[-1] = '['; /* ] */\
1316 return ((char *)NULL); \
1320 /* Return a string containing the elements in the array and subscript
1321 described by S. If the subscript is * or @, obeys quoting rules akin
1322 to the expansion of $* and $@ including double quoting. If RTYPE
1323 is non-null it gets 1 if the array reference is name[*], 2 if the
1324 reference is name[@], and 0 otherwise. */
1326 array_value_internal (s
, quoted
, flags
, rtype
, indp
)
1328 int quoted
, flags
, *rtype
;
1334 char *retval
, *t
, *temp
;
1338 var
= array_variable_part (s
, (flags
&AV_NOEXPAND
) ? 1 : 0, &t
, &len
); /* XXX */
1340 /* Expand the index, even if the variable doesn't exist, in case side
1341 effects are needed, like ${w[i++]} where w is unset. */
1344 return (char *)NULL
;
1348 return ((char *)NULL
); /* error message already printed */
1352 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == ']')
1355 *rtype
= (t
[0] == '*') ? 1 : 2;
1356 if ((flags
& AV_ALLOWALL
) == 0)
1358 err_badarraysub (s
);
1359 return ((char *)NULL
);
1361 else if (var
== 0 || value_cell (var
) == 0) /* XXX - check for invisible_p(var) ? */
1362 return ((char *)NULL
);
1363 else if (invisible_p (var
))
1364 return ((char *)NULL
);
1365 else if (array_p (var
) == 0 && assoc_p (var
) == 0)
1366 l
= add_string_to_list (value_cell (var
), (WORD_LIST
*)NULL
);
1367 else if (assoc_p (var
))
1369 l
= assoc_to_word_list (assoc_cell (var
));
1370 if (l
== (WORD_LIST
*)NULL
)
1371 return ((char *)NULL
);
1375 l
= array_to_word_list (array_cell (var
));
1376 if (l
== (WORD_LIST
*)NULL
)
1377 return ((char *) NULL
);
1380 /* Caller of array_value takes care of inspecting rtype and duplicating
1381 retval if rtype == 0, so this is not a memory leak */
1382 if (t
[0] == '*' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1384 temp
= string_list_dollar_star (l
, quoted
, (flags
& AV_ASSIGNRHS
) ? PF_ASSIGNRHS
: 0);
1385 retval
= quote_string (temp
);
1388 else /* ${name[@]} or unquoted ${name[*]} */
1389 retval
= string_list_dollar_at (l
, quoted
, (flags
& AV_ASSIGNRHS
) ? PF_ASSIGNRHS
: 0);
1397 if (var
== 0 || array_p (var
) || assoc_p (var
) == 0)
1399 if ((flags
& AV_USEIND
) == 0 || indp
== 0)
1401 ind
= array_expand_index (var
, t
, len
, flags
);
1404 /* negative subscripts to indexed arrays count back from end */
1405 if (var
&& array_p (var
))
1406 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
1416 else if (assoc_p (var
))
1419 if ((flags
& AV_NOEXPAND
) == 0)
1420 akey
= expand_assignment_string_to_string (t
, 0); /* [ */
1422 akey
= savestring (t
);
1424 if (akey
== 0 || *akey
== 0)
1431 if (var
== 0 || value_cell (var
) == 0) /* XXX - check invisible_p(var) ? */
1434 return ((char *)NULL
);
1436 else if (invisible_p (var
))
1439 return ((char *)NULL
);
1441 if (array_p (var
) == 0 && assoc_p (var
) == 0)
1442 return (ind
== 0 ? value_cell (var
) : (char *)NULL
);
1443 else if (assoc_p (var
))
1445 retval
= assoc_reference (assoc_cell (var
), akey
);
1449 retval
= array_reference (array_cell (var
), ind
);
1455 /* Return a string containing the elements described by the array and
1456 subscript contained in S, obeying quoting for subscripts * and @. */
1458 array_value (s
, quoted
, flags
, rtype
, indp
)
1460 int quoted
, flags
, *rtype
;
1463 return (array_value_internal (s
, quoted
, flags
|AV_ALLOWALL
, rtype
, indp
));
1466 /* Return the value of the array indexing expression S as a single string.
1467 If (FLAGS & AV_ALLOWALL) is 0, do not allow `@' and `*' subscripts. This
1468 is used by other parts of the shell such as the arithmetic expression
1469 evaluator in expr.c. */
1471 get_array_value (s
, flags
, rtype
, indp
)
1476 return (array_value_internal (s
, 0, flags
, rtype
, indp
));
1480 array_keys (s
, quoted
, pflags
)
1485 char *retval
, *t
, *temp
;
1489 var
= array_variable_part (s
, 0, &t
, &len
);
1492 if (var
== 0 || ALL_ELEMENT_SUB (t
[0]) == 0 || t
[1] != ']')
1493 return (char *)NULL
;
1495 if (var_isset (var
) == 0 || invisible_p (var
))
1496 return (char *)NULL
;
1498 if (array_p (var
) == 0 && assoc_p (var
) == 0)
1499 l
= add_string_to_list ("0", (WORD_LIST
*)NULL
);
1500 else if (assoc_p (var
))
1501 l
= assoc_keys_to_word_list (assoc_cell (var
));
1503 l
= array_keys_to_word_list (array_cell (var
));
1504 if (l
== (WORD_LIST
*)NULL
)
1505 return ((char *) NULL
);
1507 retval
= string_list_pos_params (t
[0], l
, quoted
, pflags
);
1512 #endif /* ARRAY_VARS */