1 /* arrayfunc.c -- High-level array functions used by other parts of the shell. */
3 /* Copyright (C) 2001-2021 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 /* We don't allow assignment to `*' or `@' associative array keys if the
342 caller hasn't told us the subscript has already been expanded
343 (ASS_NOEXPAND). If the caller has explicitly told us it's ok
344 (ASS_ALLOWALLSUB) we allow it. */
345 if (((isassoc
== 0 || (flags
& (ASS_NOEXPAND
|ASS_ALLOWALLSUB
)) == 0) &&
346 (ALL_ELEMENT_SUB (sub
[0]) && sub
[1] == ']')) ||
350 err_badarraysub (name
);
351 return ((SHELL_VAR
*)NULL
);
354 entry
= assign_array_element_internal (entry
, name
, vname
, sub
, sublen
, value
, flags
);
361 assign_array_element_internal (entry
, name
, vname
, sub
, sublen
, value
, flags
)
363 char *name
; /* only used for error messages */
373 if (entry
&& assoc_p (entry
))
375 sub
[sublen
-1] = '\0';
376 if ((flags
& ASS_NOEXPAND
) == 0)
377 akey
= expand_assignment_string_to_string (sub
, 0); /* [ */
379 akey
= savestring (sub
);
381 if (akey
== 0 || *akey
== 0)
383 err_badarraysub (name
);
385 return ((SHELL_VAR
*)NULL
);
387 entry
= bind_assoc_variable (entry
, vname
, akey
, value
, flags
);
391 ind
= array_expand_index (entry
, sub
, sublen
, 0);
392 /* negative subscripts to indexed arrays count back from end */
393 if (entry
&& ind
< 0)
394 ind
= (array_p (entry
) ? array_max_index (array_cell (entry
)) : 0) + 1 + ind
;
397 err_badarraysub (name
);
398 return ((SHELL_VAR
*)NULL
);
400 entry
= bind_array_variable (vname
, ind
, value
, flags
);
406 /* Find the array variable corresponding to NAME. If there is no variable,
407 create a new array variable. If the variable exists but is not an array,
408 convert it to an indexed array. If FLAGS&1 is non-zero, an existing
409 variable is checked for the readonly or noassign attribute in preparation
410 for assignment (e.g., by the `read' builtin). If FLAGS&2 is non-zero, we
411 create an associative array. */
413 find_or_make_array_variable (name
, flags
)
419 var
= find_variable (name
);
422 /* See if we have a nameref pointing to a variable that hasn't been
424 var
= find_variable_last_nameref (name
, 1);
425 if (var
&& nameref_p (var
) && invisible_p (var
))
427 internal_warning (_("%s: removing nameref attribute"), name
);
428 VUNSETATTR (var
, att_nameref
);
430 if (var
&& nameref_p (var
))
432 if (valid_nameref_value (nameref_cell (var
), 2) == 0)
434 sh_invalidid (nameref_cell (var
));
435 return ((SHELL_VAR
*)NULL
);
437 var
= (flags
& 2) ? make_new_assoc_variable (nameref_cell (var
)) : make_new_array_variable (nameref_cell (var
));
442 var
= (flags
& 2) ? make_new_assoc_variable (name
) : make_new_array_variable (name
);
443 else if ((flags
& 1) && (readonly_p (var
) || noassign_p (var
)))
445 if (readonly_p (var
))
447 return ((SHELL_VAR
*)NULL
);
449 else if ((flags
& 2) && array_p (var
))
451 set_exit_status (EXECUTION_FAILURE
);
452 report_error (_("%s: cannot convert indexed to associative array"), name
);
453 return ((SHELL_VAR
*)NULL
);
455 else if (array_p (var
) == 0 && assoc_p (var
) == 0)
456 var
= convert_var_to_array (var
);
461 /* Perform a compound assignment statement for array NAME, where VALUE is
462 the text between the parens: NAME=( VALUE ) */
464 assign_array_from_string (name
, value
, flags
)
472 if (flags
& ASS_MKASSOC
)
475 var
= find_or_make_array_variable (name
, vflags
);
477 return ((SHELL_VAR
*)NULL
);
479 return (assign_array_var_from_string (var
, value
, flags
));
482 /* Sequentially assign the indices of indexed array variable VAR from the
485 assign_array_var_from_word_list (var
, list
, flags
)
490 register arrayind_t i
;
491 register WORD_LIST
*l
;
494 a
= array_cell (var
);
495 i
= (flags
& ASS_APPEND
) ? array_max_index (a
) + 1 : 0;
497 for (l
= list
; l
; l
= l
->next
, i
++)
498 bind_array_var_internal (var
, i
, 0, l
->word
->word
, flags
& ~ASS_APPEND
);
500 VUNSETATTR (var
, att_invisible
); /* no longer invisible */
506 expand_compound_array_assignment (var
, value
, flags
)
511 WORD_LIST
*list
, *nlist
;
515 /* This condition is true when invoked from the declare builtin with a
517 declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' */
518 if (*value
== '(') /*)*/
521 val
= extract_array_assignment_list (value
, &ni
);
523 return (WORD_LIST
*)NULL
;
528 /* Expand the value string into a list of words, performing all the
529 shell expansions including pathname generation and word splitting. */
530 /* First we split the string on whitespace, using the shell parser
531 (ksh93 seems to do this). */
532 list
= parse_string_to_word_list (val
, 1, "array assign");
534 /* Note that we defer expansion of the assignment statements for associative
535 arrays here, so we don't have to scan the subscript and find the ending
536 bracket twice. See the caller below. */
537 if (var
&& assoc_p (var
))
544 /* If we're using [subscript]=value, we need to quote each [ and ] to
545 prevent unwanted filename expansion. This doesn't need to be done
546 for associative array expansion, since that uses a different expansion
547 function (see assign_compound_array_list below). */
549 quote_array_assignment_chars (list
);
551 /* Now that we've split it, perform the shell expansions on each
553 nlist
= list
? expand_words_no_vars (list
) : (WORD_LIST
*)NULL
;
555 dispose_words (list
);
563 #if ASSOC_KVPAIR_ASSIGNMENT
565 assign_assoc_from_kvlist (var
, nlist
, h
, flags
)
572 char *akey
, *aval
, *k
, *v
;
574 for (list
= nlist
; list
; list
= list
->next
)
576 k
= list
->word
->word
;
577 v
= list
->next
? list
->next
->word
->word
: 0;
582 akey
= expand_assignment_string_to_string (k
, 0);
583 if (akey
== 0 || *akey
== 0)
590 aval
= expand_assignment_string_to_string (v
, 0);
593 aval
= (char *)xmalloc (1);
594 aval
[0] = '\0'; /* like do_assignment_internal */
597 bind_assoc_var_internal (var
, h
, akey
, aval
, flags
);
602 /* Return non-zero if L appears to be a key-value pair associative array
603 compound assignment. */
605 kvpair_assignment_p (l
)
608 return (l
&& (l
->word
->flags
& W_ASSIGNMENT
) == 0 && l
->word
->word
[0] != '['); /*]*/
612 expand_and_quote_kvpair_word (w
)
617 t
= w
? expand_assignment_string_to_string (w
, 0) : 0;
618 r
= sh_single_quote (t
? t
: "");
624 /* Callers ensure that VAR is not NULL. Associative array assignments have not
625 been expanded when this is called, or have been expanded once and single-
626 quoted, so we don't have to scan through an unquoted expanded subscript to
627 find the ending bracket; indexed array assignments have been expanded and
628 possibly single-quoted to prevent further expansion.
630 If this is an associative array, we perform the assignments into NHASH and
631 set NHASH to be the value of VAR after processing the assignments in NLIST */
633 assign_compound_array_list (var
, nlist
, flags
)
639 HASH_TABLE
*h
, *nhash
;
641 char *w
, *val
, *nval
, *savecmd
;
642 int len
, iflags
, free_val
;
643 arrayind_t ind
, last_ind
;
646 a
= (var
&& array_p (var
)) ? array_cell (var
) : (ARRAY
*)0;
647 nhash
= h
= (var
&& assoc_p (var
)) ? assoc_cell (var
) : (HASH_TABLE
*)0;
652 /* Now that we are ready to assign values to the array, kill the existing
654 if ((flags
& ASS_APPEND
) == 0)
656 if (a
&& array_p (var
))
658 else if (h
&& assoc_p (var
))
659 nhash
= assoc_create (h
->nbuckets
);
662 last_ind
= (a
&& (flags
& ASS_APPEND
)) ? array_max_index (a
) + 1 : 0;
664 #if ASSOC_KVPAIR_ASSIGNMENT
665 if (assoc_p (var
) && kvpair_assignment_p (nlist
))
667 iflags
= flags
& ~ASS_APPEND
;
668 assign_assoc_from_kvlist (var
, nlist
, nhash
, iflags
);
669 if (nhash
&& nhash
!= h
)
671 h
= assoc_cell (var
);
672 var_setassoc (var
, nhash
);
679 for (list
= nlist
; list
; list
= list
->next
)
681 /* Don't allow var+=(values) to make assignments in VALUES append to
682 existing values by default. */
683 iflags
= flags
& ~ASS_APPEND
;
684 w
= list
->word
->word
;
686 /* We have a word of the form [ind]=value */
687 if ((list
->word
->flags
& W_ASSIGNMENT
) && w
[0] == '[')
689 /* Don't have to handle embedded quotes specially any more, since
690 associative array subscripts have not been expanded yet (see
692 len
= skipsubscript (w
, 0, 0);
694 /* XXX - changes for `+=' */
695 if (w
[len
] != ']' || (w
[len
+1] != '=' && (w
[len
+1] != '+' || w
[len
+2] != '=')))
702 nval
= make_variable_value (var
, w
, flags
);
703 if (var
->assign_func
)
704 (*var
->assign_func
) (var
, nval
, last_ind
, 0);
706 array_insert (a
, last_ind
, nval
);
718 if (ALL_ELEMENT_SUB (w
[1]) && len
== 2 && array_p (var
))
720 set_exit_status (EXECUTION_FAILURE
);
721 report_error (_("%s: cannot assign to non-numeric index"), w
);
727 ind
= array_expand_index (var
, w
+ 1, len
, 0);
728 /* negative subscripts to indexed arrays count back from end */
730 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
739 else if (assoc_p (var
))
741 /* This is not performed above, see expand_compound_array_assignment */
743 akey
= expand_assignment_string_to_string (w
+1, 0);
745 /* And we need to expand the value also, see below */
746 if (akey
== 0 || *akey
== 0)
754 /* XXX - changes for `+=' -- just accept the syntax. ksh93 doesn't do this */
755 if (w
[len
+ 1] == '+' && w
[len
+ 2] == '=')
757 iflags
|= ASS_APPEND
;
763 else if (assoc_p (var
))
765 set_exit_status (EXECUTION_FAILURE
);
766 report_error (_("%s: %s: must use subscript when assigning associative array"), var
->name
, w
);
769 else /* No [ind]=value, just a stray `=' */
776 /* See above; we need to expand the value here */
779 val
= expand_assignment_string_to_string (val
, 0);
782 val
= (char *)xmalloc (1);
783 val
[0] = '\0'; /* like do_assignment_internal */
788 savecmd
= this_command_name
;
790 this_command_name
= (char *)NULL
; /* no command name for errors */
792 bind_assoc_var_internal (var
, nhash
, akey
, val
, iflags
);
794 bind_array_var_internal (var
, ind
, akey
, val
, iflags
);
796 this_command_name
= savecmd
;
802 if (assoc_p (var
) && nhash
&& nhash
!= h
)
804 h
= assoc_cell (var
);
805 var_setassoc (var
, nhash
);
810 /* Perform a compound array assignment: VAR->name=( VALUE ). The
811 VALUE has already had the parentheses stripped. */
813 assign_array_var_from_string (var
, value
, flags
)
823 nlist
= expand_compound_array_assignment (var
, value
, flags
);
824 assign_compound_array_list (var
, nlist
, flags
);
827 dispose_words (nlist
);
830 VUNSETATTR (var
, att_invisible
); /* no longer invisible */
835 /* Quote globbing chars and characters in $IFS before the `=' in an assignment
836 statement (usually a compound array assignment) to protect them from
837 unwanted filename expansion or word splitting. */
839 quote_assign (string
)
844 char *temp
, *t
, *subs
;
845 const char *s
, *send
;
849 slen
= strlen (string
);
850 send
= string
+ slen
;
852 t
= temp
= (char *)xmalloc (slen
* 2 + 1);
854 for (s
= string
; *s
; )
858 if (saw_eq
== 0 && *s
== '[') /* looks like a subscript */
861 se
= skipsubscript (string
, ss
, 0);
862 subs
= substring (s
, ss
, se
);
872 if (saw_eq
== 0 && (glob_char_p (s
) || isifs (*s
)))
875 COPY_CHAR_P (t
, s
, send
);
881 /* Take a word W of the form [IND]=VALUE and transform it to ['IND']='VALUE'
882 to prevent further expansion. This is called for compound assignments to
883 indexed arrays. W has already undergone word expansions. If W has no [IND]=,
884 just single-quote and return it. */
886 quote_compound_array_word (w
, type
)
890 char *nword
, *sub
, *value
, *t
;
894 return (sh_single_quote (w
));
895 ind
= skipsubscript (w
, 0, 0);
896 if (w
[ind
] != RBRACK
)
897 return (sh_single_quote (w
));
901 sub
= sh_single_quote (w
+1);
904 nword
= xmalloc (wlen
* 4 + 5); /* wlen*4 is max single quoted length */
907 memcpy (nword
+1, sub
, i
);
908 i
++; /* accommodate the opening LBRACK */
909 nword
[i
++] = w
[ind
++]; /* RBRACK */
911 nword
[i
++] = w
[ind
++];
912 nword
[i
++] = w
[ind
++];
913 value
= sh_single_quote (w
+ ind
);
914 strcpy (nword
+ i
, value
);
919 /* Expand the key and value in W, which is of the form [KEY]=VALUE, and
920 reconstruct W with the expanded and single-quoted version:
921 ['expanded-key']='expanded-value'. If there is no [KEY]=, single-quote the
922 word and return it. Very similar to previous function, but does not assume
923 W has already been expanded, and expands the KEY and VALUE separately.
924 Used for compound assignments to associative arrays that are arguments to
925 declaration builtins (declare -A a=( list )). */
927 expand_and_quote_assoc_word (w
, type
)
931 char *nword
, *key
, *value
, *t
;
935 return (sh_single_quote (w
));
936 ind
= skipsubscript (w
, 0, 0);
937 if (w
[ind
] != RBRACK
)
938 return (sh_single_quote (w
));
941 t
= expand_assignment_string_to_string (w
+1, 0);
943 key
= sh_single_quote (t
? t
: "");
947 nword
= xmalloc (wlen
+ 5);
949 memcpy (nword
+1, key
, wlen
);
950 i
= wlen
+ 1; /* accommodate the opening LBRACK */
952 nword
[i
++] = w
[ind
++]; /* RBRACK */
954 nword
[i
++] = w
[ind
++];
955 nword
[i
++] = w
[ind
++];
957 t
= expand_assignment_string_to_string (w
+ind
, 0);
958 value
= sh_single_quote (t
? t
: "");
960 nword
= xrealloc (nword
, wlen
+ 5 + STRLEN (value
));
961 strcpy (nword
+ i
, value
);
969 /* For each word in a compound array assignment, if the word looks like
970 [ind]=value, single-quote ind and value, but leave the brackets and
971 the = sign (and any `+') alone. If it's not an assignment, just single-
972 quote the word. This is used for indexed arrays. */
974 quote_compound_array_list (list
, type
)
981 for (l
= list
; l
; l
= l
->next
)
983 if (l
->word
== 0 || l
->word
->word
== 0)
984 continue; /* should not happen, but just in case... */
985 if ((l
->word
->flags
& W_ASSIGNMENT
) == 0)
986 t
= sh_single_quote (l
->word
->word
);
988 t
= quote_compound_array_word (l
->word
->word
, type
);
989 free (l
->word
->word
);
994 /* For each word in a compound array assignment, if the word looks like
995 [ind]=value, quote globbing chars and characters in $IFS before the `='. */
997 quote_array_assignment_chars (list
)
1003 for (l
= list
; l
; l
= l
->next
)
1005 if (l
->word
== 0 || l
->word
->word
== 0 || l
->word
->word
[0] == '\0')
1006 continue; /* should not happen, but just in case... */
1007 /* Don't bother if it hasn't been recognized as an assignment or
1008 doesn't look like [ind]=value */
1009 if ((l
->word
->flags
& W_ASSIGNMENT
) == 0)
1011 if (l
->word
->word
[0] != '[' || mbschr (l
->word
->word
, '=') == 0) /* ] */
1014 nword
= quote_assign (l
->word
->word
);
1015 free (l
->word
->word
);
1016 l
->word
->word
= nword
;
1017 l
->word
->flags
|= W_NOGLOB
; /* XXX - W_NOSPLIT also? */
1021 /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
1023 /* This function is called with SUB pointing to just after the beginning
1024 `[' of an array subscript and removes the array element to which SUB
1025 expands from array VAR. A subscript of `*' or `@' unsets the array. */
1026 /* If FLAGS&1 (VA_NOEXPAND) we don't expand the subscript; we just use it
1027 as-is. If FLAGS&VA_ONEWORD, we don't try to use skipsubscript to parse
1028 the subscript, we just assume the subscript ends with a close bracket
1029 and use the rest. */
1031 unbind_array_element (var
, sub
, flags
)
1041 /* If the caller tells us to treat the entire `sub' as one word, we don't
1042 bother to call skipsubscript. */
1043 if (var
&& assoc_p (var
) && (flags
&VA_ONEWORD
))
1044 len
= strlen (sub
) - 1;
1046 len
= skipsubscript (sub
, 0, (flags
&VA_NOEXPAND
) || (var
&& assoc_p(var
))); /* XXX */
1047 if (sub
[len
] != ']' || len
== 0)
1049 builtin_error ("%s[%s: %s", var
->name
, sub
, _(bash_badsub_errmsg
));
1054 if (ALL_ELEMENT_SUB (sub
[0]) && sub
[1] == 0)
1056 if (array_p (var
) || assoc_p (var
))
1058 #if 0 /* TAG: bash-5.2 */
1059 if (flags
& VA_ALLOWALL
)
1062 unbind_variable (var
->name
); /* XXX -- {array,assoc}_flush ? */
1065 /* otherwise we fall through and try to unset element `@' or `*' */
1068 return -2; /* don't allow this to unset scalar variables */
1073 akey
= (flags
& VA_NOEXPAND
) ? sub
: expand_assignment_string_to_string (sub
, 0);
1074 if (akey
== 0 || *akey
== 0)
1076 builtin_error ("[%s]: %s", sub
, _(bash_badsub_errmsg
));
1080 assoc_remove (assoc_cell (var
), akey
);
1084 else if (array_p (var
))
1086 ind
= array_expand_index (var
, sub
, len
+1, 0);
1087 /* negative subscripts to indexed arrays count back from end */
1089 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
1092 builtin_error ("[%s]: %s", sub
, _(bash_badsub_errmsg
));
1095 ae
= array_remove (array_cell (var
), ind
);
1097 array_dispose_element (ae
);
1099 else /* array_p (var) == 0 && assoc_p (var) == 0 */
1101 akey
= this_command_name
;
1102 ind
= array_expand_index (var
, sub
, len
+1, 0);
1103 this_command_name
= akey
;
1106 unbind_variable (var
->name
);
1110 return -2; /* any subscript other than 0 is invalid with scalar variables */
1116 /* Format and output an array assignment in compound form VAR=(VALUES),
1117 suitable for re-use as input. */
1119 print_array_assignment (var
, quoted
)
1125 vstr
= array_to_assign (array_cell (var
), quoted
);
1128 printf ("%s=%s\n", var
->name
, quoted
? "'()'" : "()");
1131 printf ("%s=%s\n", var
->name
, vstr
);
1136 /* Format and output an associative array assignment in compound form
1137 VAR=(VALUES), suitable for re-use as input. */
1139 print_assoc_assignment (var
, quoted
)
1145 vstr
= assoc_to_assign (assoc_cell (var
), quoted
);
1148 printf ("%s=%s\n", var
->name
, quoted
? "'()'" : "()");
1151 printf ("%s=%s\n", var
->name
, vstr
);
1156 /***********************************************************************/
1158 /* Utility functions to manage arrays and their contents for expansion */
1160 /***********************************************************************/
1162 /* Return 1 if NAME is a properly-formed array reference v[sub]. */
1164 /* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
1166 valid_array_reference (name
, flags
)
1171 int r
, len
, isassoc
;
1174 t
= mbschr (name
, '['); /* ] */
1179 r
= legal_identifier (name
);
1180 if (flags
& VA_NOEXPAND
) /* Don't waste a lookup if we don't need one */
1181 isassoc
= (entry
= find_variable (name
)) && assoc_p (entry
);
1186 if (isassoc
&& ((flags
& (VA_NOEXPAND
|VA_ONEWORD
)) == (VA_NOEXPAND
|VA_ONEWORD
)))
1187 len
= strlen (t
) - 1;
1189 len
= skipsubscript (t
, 0, flags
&VA_NOEXPAND
); /* VA_NOEXPAND must be 1 */
1191 /* Check for a properly-terminated non-null subscript. */
1192 len
= skipsubscript (t
, 0, 0); /* arithmetic expression */
1194 if (t
[len
] != ']' || len
== 1 || t
[len
+1] != '\0')
1198 /* Could check and allow subscripts consisting only of whitespace for
1199 existing associative arrays, using isassoc */
1200 for (r
= 1; r
< len
; r
++)
1201 if (whitespace (t
[r
]) == 0)
1205 /* This allows blank subscripts */
1212 /* Expand the array index beginning at S and extending LEN characters. */
1214 array_expand_index (var
, s
, len
, flags
)
1220 char *exp
, *t
, *savecmd
;
1224 exp
= (char *)xmalloc (len
);
1225 strncpy (exp
, s
, len
- 1);
1226 exp
[len
- 1] = '\0';
1227 #if 0 /* TAG: maybe bash-5.2 */
1228 if ((flags
& AV_NOEXPAND
) == 0)
1229 t
= expand_arith_string (exp
, Q_DOUBLE_QUOTES
|Q_ARITH
|Q_ARRAYSUB
); /* XXX - Q_ARRAYSUB for future use */
1233 t
= expand_arith_string (exp
, Q_DOUBLE_QUOTES
|Q_ARITH
|Q_ARRAYSUB
); /* XXX - Q_ARRAYSUB for future use */
1235 savecmd
= this_command_name
;
1236 this_command_name
= (char *)NULL
;
1237 val
= evalexp (t
, EXP_EXPANDED
, &expok
); /* XXX - was 0 but we expanded exp already */
1238 this_command_name
= savecmd
;
1244 set_exit_status (EXECUTION_FAILURE
);
1246 if (no_longjmp_on_fatal_error
)
1248 top_level_cleanup ();
1249 jump_to_top_level (DISCARD
);
1254 /* Return the name of the variable specified by S without any subscript.
1255 If SUBP is non-null, return a pointer to the start of the subscript
1256 in *SUBP. If LENP is non-null, the length of the subscript is returned
1257 in *LENP. This returns newly-allocated memory. */
1259 array_variable_name (s
, flags
, subp
, lenp
)
1268 t
= mbschr (s
, '[');
1275 return ((char *)NULL
);
1278 ni
= skipsubscript (s
, ind
, flags
); /* XXX - was 0 not flags */
1279 if (ni
<= ind
+ 1 || s
[ni
] != ']')
1281 err_badarraysub (s
);
1286 return ((char *)NULL
);
1290 ret
= savestring (s
);
1301 /* Return the variable specified by S without any subscript. If SUBP is
1302 non-null, return a pointer to the start of the subscript in *SUBP.
1303 If LENP is non-null, the length of the subscript is returned in *LENP. */
1305 array_variable_part (s
, flags
, subp
, lenp
)
1314 t
= array_variable_name (s
, flags
, subp
, lenp
);
1316 return ((SHELL_VAR
*)NULL
);
1317 var
= find_variable (t
); /* XXX - handle namerefs here? */
1320 return var
; /* now return invisible variables; caller must handle */
1323 #define INDEX_ERROR() \
1327 err_badarraysub (var->name); \
1331 err_badarraysub (s); \
1332 t[-1] = '['; /* ] */\
1334 return ((char *)NULL); \
1338 /* Return a string containing the elements in the array and subscript
1339 described by S. If the subscript is * or @, obeys quoting rules akin
1340 to the expansion of $* and $@ including double quoting. If RTYPE
1341 is non-null it gets 1 if the array reference is name[*], 2 if the
1342 reference is name[@], and 0 otherwise. */
1344 array_value_internal (s
, quoted
, flags
, rtype
, indp
)
1346 int quoted
, flags
, *rtype
;
1352 char *retval
, *t
, *temp
;
1356 var
= array_variable_part (s
, (flags
&AV_NOEXPAND
) ? 1 : 0, &t
, &len
); /* XXX */
1358 /* Expand the index, even if the variable doesn't exist, in case side
1359 effects are needed, like ${w[i++]} where w is unset. */
1362 return (char *)NULL
;
1366 return ((char *)NULL
); /* error message already printed */
1370 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == ']')
1373 *rtype
= (t
[0] == '*') ? 1 : 2;
1374 if ((flags
& AV_ALLOWALL
) == 0)
1376 err_badarraysub (s
);
1377 return ((char *)NULL
);
1379 else if (var
== 0 || value_cell (var
) == 0) /* XXX - check for invisible_p(var) ? */
1380 return ((char *)NULL
);
1381 else if (invisible_p (var
))
1382 return ((char *)NULL
);
1383 else if (array_p (var
) == 0 && assoc_p (var
) == 0)
1384 l
= add_string_to_list (value_cell (var
), (WORD_LIST
*)NULL
);
1385 else if (assoc_p (var
))
1387 l
= assoc_to_word_list (assoc_cell (var
));
1388 if (l
== (WORD_LIST
*)NULL
)
1389 return ((char *)NULL
);
1393 l
= array_to_word_list (array_cell (var
));
1394 if (l
== (WORD_LIST
*)NULL
)
1395 return ((char *) NULL
);
1398 /* Caller of array_value takes care of inspecting rtype and duplicating
1399 retval if rtype == 0, so this is not a memory leak */
1400 if (t
[0] == '*' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1402 temp
= string_list_dollar_star (l
, quoted
, (flags
& AV_ASSIGNRHS
) ? PF_ASSIGNRHS
: 0);
1403 retval
= quote_string (temp
);
1406 else /* ${name[@]} or unquoted ${name[*]} */
1407 retval
= string_list_dollar_at (l
, quoted
, (flags
& AV_ASSIGNRHS
) ? PF_ASSIGNRHS
: 0);
1415 if (var
== 0 || array_p (var
) || assoc_p (var
) == 0)
1417 if ((flags
& AV_USEIND
) == 0 || indp
== 0)
1419 ind
= array_expand_index (var
, t
, len
, flags
);
1422 /* negative subscripts to indexed arrays count back from end */
1423 if (var
&& array_p (var
))
1424 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
1434 else if (assoc_p (var
))
1437 if ((flags
& AV_NOEXPAND
) == 0)
1438 akey
= expand_assignment_string_to_string (t
, 0); /* [ */
1440 akey
= savestring (t
);
1442 if (akey
== 0 || *akey
== 0)
1449 if (var
== 0 || value_cell (var
) == 0) /* XXX - check invisible_p(var) ? */
1452 return ((char *)NULL
);
1454 else if (invisible_p (var
))
1457 return ((char *)NULL
);
1459 if (array_p (var
) == 0 && assoc_p (var
) == 0)
1460 return (ind
== 0 ? value_cell (var
) : (char *)NULL
);
1461 else if (assoc_p (var
))
1463 retval
= assoc_reference (assoc_cell (var
), akey
);
1467 retval
= array_reference (array_cell (var
), ind
);
1473 /* Return a string containing the elements described by the array and
1474 subscript contained in S, obeying quoting for subscripts * and @. */
1476 array_value (s
, quoted
, flags
, rtype
, indp
)
1478 int quoted
, flags
, *rtype
;
1481 return (array_value_internal (s
, quoted
, flags
|AV_ALLOWALL
, rtype
, indp
));
1484 /* Return the value of the array indexing expression S as a single string.
1485 If (FLAGS & AV_ALLOWALL) is 0, do not allow `@' and `*' subscripts. This
1486 is used by other parts of the shell such as the arithmetic expression
1487 evaluator in expr.c. */
1489 get_array_value (s
, flags
, rtype
, indp
)
1494 return (array_value_internal (s
, 0, flags
, rtype
, indp
));
1498 array_keys (s
, quoted
, pflags
)
1503 char *retval
, *t
, *temp
;
1507 var
= array_variable_part (s
, 0, &t
, &len
);
1510 if (var
== 0 || ALL_ELEMENT_SUB (t
[0]) == 0 || t
[1] != ']')
1511 return (char *)NULL
;
1513 if (var_isset (var
) == 0 || invisible_p (var
))
1514 return (char *)NULL
;
1516 if (array_p (var
) == 0 && assoc_p (var
) == 0)
1517 l
= add_string_to_list ("0", (WORD_LIST
*)NULL
);
1518 else if (assoc_p (var
))
1519 l
= assoc_keys_to_word_list (assoc_cell (var
));
1521 l
= array_keys_to_word_list (array_cell (var
));
1522 if (l
== (WORD_LIST
*)NULL
)
1523 return ((char *) NULL
);
1525 retval
= string_list_pos_params (t
[0], l
, quoted
, pflags
);
1530 #endif /* ARRAY_VARS */