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 Bush, the Bourne Again SHell.
7 Bush 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 Bush 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 Bush. If not, see <http://www.gnu.org/licenses/>.
23 #if defined (ARRAY_VARS)
25 #if defined (HAVE_UNISTD_H)
33 #include "runner/execute_cmd.h"
34 #include "impl/pathexp.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 bush_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. BUSH_CMDS and BUSH_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
;
569 for (list
= nlist
; list
; list
= list
->next
)
573 k
= list
->word
->word
;
574 v
= list
->next
? list
->next
->word
->word
: 0;
579 akey
= expand_assignment_string_to_string (k
, 0);
580 aval
= expand_assignment_string_to_string (v
, 0);
582 if (akey
== 0 || *akey
== 0)
590 aval
= (char *)xmalloc (1);
591 aval
[0] = '\0'; /* like do_assignment_internal */
595 bind_assoc_var_internal (var
, h
, akey
, aval
, flags
);
602 /* Callers ensure that VAR is not NULL. Associative array assignments have not
603 been expanded when this is called, or have been expanded once and single-
604 quoted, so we don't have to scan through an unquoted expanded subscript to
605 find the ending bracket; indexed array assignments have been expanded and
606 possibly single-quoted to prevent further expansion.
608 If this is an associative array, we perform the assignments into NHASH and
609 set NHASH to be the value of VAR after processing the assignments in NLIST */
611 assign_compound_array_list (var
, nlist
, flags
)
617 HASH_TABLE
*h
, *nhash
;
619 char *w
, *val
, *nval
, *savecmd
;
620 int len
, iflags
, free_val
;
621 arrayind_t ind
, last_ind
;
624 a
= (var
&& array_p (var
)) ? array_cell (var
) : (ARRAY
*)0;
625 nhash
= h
= (var
&& assoc_p (var
)) ? assoc_cell (var
) : (HASH_TABLE
*)0;
630 /* Now that we are ready to assign values to the array, kill the existing
632 if ((flags
& ASS_APPEND
) == 0)
634 if (a
&& array_p (var
))
636 else if (h
&& assoc_p (var
))
637 nhash
= assoc_create (h
->nbuckets
);
640 last_ind
= (a
&& (flags
& ASS_APPEND
)) ? array_max_index (a
) + 1 : 0;
642 #if ASSOC_KVPAIR_ASSIGNMENT
643 if (assoc_p (var
) && nlist
&& (nlist
->word
->flags
& W_ASSIGNMENT
) == 0 && nlist
->word
->word
[0] != '[') /*]*/
645 iflags
= flags
& ~ASS_APPEND
;
646 assign_assoc_from_kvlist (var
, nlist
, nhash
, iflags
);
647 if (nhash
&& nhash
!= h
)
649 h
= assoc_cell (var
);
650 var_setassoc (var
, nhash
);
657 for (list
= nlist
; list
; list
= list
->next
)
659 /* Don't allow var+=(values) to make assignments in VALUES append to
660 existing values by default. */
661 iflags
= flags
& ~ASS_APPEND
;
662 w
= list
->word
->word
;
664 /* We have a word of the form [ind]=value */
665 if ((list
->word
->flags
& W_ASSIGNMENT
) && w
[0] == '[')
667 /* Don't have to handle embedded quotes specially any more, since
668 associative array subscripts have not been expanded yet (see
670 len
= skipsubscript (w
, 0, 0);
672 /* XXX - changes for `+=' */
673 if (w
[len
] != ']' || (w
[len
+1] != '=' && (w
[len
+1] != '+' || w
[len
+2] != '=')))
680 nval
= make_variable_value (var
, w
, flags
);
681 if (var
->assign_func
)
682 (*var
->assign_func
) (var
, nval
, last_ind
, 0);
684 array_insert (a
, last_ind
, nval
);
696 if (ALL_ELEMENT_SUB (w
[1]) && len
== 2)
698 set_exit_status (EXECUTION_FAILURE
);
700 report_error (_("%s: invalid associative array key"), w
);
702 report_error (_("%s: cannot assign to non-numeric index"), w
);
708 ind
= array_expand_index (var
, w
+ 1, len
, 0);
709 /* negative subscripts to indexed arrays count back from end */
711 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
720 else if (assoc_p (var
))
722 /* This is not performed above, see expand_compound_array_assignment */
724 akey
= expand_assignment_string_to_string (w
+1, 0);
726 /* And we need to expand the value also, see below */
727 if (akey
== 0 || *akey
== 0)
735 /* XXX - changes for `+=' -- just accept the syntax. ksh93 doesn't do this */
736 if (w
[len
+ 1] == '+' && w
[len
+ 2] == '=')
738 iflags
|= ASS_APPEND
;
744 else if (assoc_p (var
))
746 set_exit_status (EXECUTION_FAILURE
);
747 report_error (_("%s: %s: must use subscript when assigning associative array"), var
->name
, w
);
750 else /* No [ind]=value, just a stray `=' */
757 /* See above; we need to expand the value here */
760 val
= expand_assignment_string_to_string (val
, 0);
763 val
= (char *)xmalloc (1);
764 val
[0] = '\0'; /* like do_assignment_internal */
769 savecmd
= this_command_name
;
771 this_command_name
= (char *)NULL
; /* no command name for errors */
773 bind_assoc_var_internal (var
, nhash
, akey
, val
, iflags
);
775 bind_array_var_internal (var
, ind
, akey
, val
, iflags
);
777 this_command_name
= savecmd
;
783 if (assoc_p (var
) && nhash
&& nhash
!= h
)
785 h
= assoc_cell (var
);
786 var_setassoc (var
, nhash
);
791 /* Perform a compound array assignment: VAR->name=( VALUE ). The
792 VALUE has already had the parentheses stripped. */
794 assign_array_var_from_string (var
, value
, flags
)
804 nlist
= expand_compound_array_assignment (var
, value
, flags
);
805 assign_compound_array_list (var
, nlist
, flags
);
808 dispose_words (nlist
);
811 VUNSETATTR (var
, att_invisible
); /* no longer invisible */
816 /* Quote globbing chars and characters in $IFS before the `=' in an assignment
817 statement (usually a compound array assignment) to protect them from
818 unwanted filename expansion or word splitting. */
820 quote_assign (string
)
825 char *temp
, *t
, *subs
;
826 const char *s
, *send
;
830 slen
= strlen (string
);
831 send
= string
+ slen
;
833 t
= temp
= (char *)xmalloc (slen
* 2 + 1);
835 for (s
= string
; *s
; )
839 if (saw_eq
== 0 && *s
== '[') /* looks like a subscript */
842 se
= skipsubscript (string
, ss
, 0);
843 subs
= substring (s
, ss
, se
);
853 if (saw_eq
== 0 && (glob_char_p (s
) || isifs (*s
)))
856 COPY_CHAR_P (t
, s
, send
);
862 /* Take a word W of the form [IND]=VALUE and transform it to ['IND']='VALUE'
863 to prevent further expansion. This is called for compound assignments to
864 indexed arrays. W has already undergone word expansions. If W has no [IND]=,
865 just single-quote and return it. */
867 quote_compound_array_word (w
, type
)
871 char *nword
, *sub
, *value
, *t
;
875 return (sh_single_quote (w
));
876 ind
= skipsubscript (w
, 0, 0);
877 if (w
[ind
] != RBRACK
)
878 return (sh_single_quote (w
));
882 sub
= sh_single_quote (w
+1);
885 nword
= xmalloc (wlen
* 4 + 5); /* wlen*4 is max single quoted length */
888 memcpy (nword
+1, sub
, i
);
889 i
++; /* accommodate the opening LBRACK */
890 nword
[i
++] = w
[ind
++]; /* RBRACK */
892 nword
[i
++] = w
[ind
++];
893 nword
[i
++] = w
[ind
++];
894 value
= sh_single_quote (w
+ ind
);
895 strcpy (nword
+ i
, value
);
900 /* Expand the key and value in W, which is of the form [KEY]=VALUE, and
901 reconstruct W with the expanded and single-quoted version:
902 ['expanded-key']='expanded-value'. If there is no [KEY]=, single-quote the
903 word and return it. Very similar to previous function, but does not assume
904 W has already been expanded, and expands the KEY and VALUE separately.
905 Used for compound assignments to associative arrays that are arguments to
906 declaration builtins (declare -A a=( list )). */
908 expand_and_quote_assoc_word (w
, type
)
912 char *nword
, *key
, *value
, *t
;
916 return (sh_single_quote (w
));
917 ind
= skipsubscript (w
, 0, 0);
918 if (w
[ind
] != RBRACK
)
919 return (sh_single_quote (w
));
922 t
= expand_assignment_string_to_string (w
+1, 0);
924 key
= sh_single_quote (t
? t
: "");
928 nword
= xmalloc (wlen
+ 5);
930 memcpy (nword
+1, key
, wlen
);
931 i
= wlen
+ 1; /* accommodate the opening LBRACK */
933 nword
[i
++] = w
[ind
++]; /* RBRACK */
935 nword
[i
++] = w
[ind
++];
936 nword
[i
++] = w
[ind
++];
938 t
= expand_assignment_string_to_string (w
+ind
, 0);
939 value
= sh_single_quote (t
? t
: "");
941 nword
= xrealloc (nword
, wlen
+ 5 + STRLEN (value
));
942 strcpy (nword
+ i
, value
);
950 /* For each word in a compound array assignment, if the word looks like
951 [ind]=value, single-quote ind and value, but leave the brackets and
952 the = sign (and any `+') alone. If it's not an assignment, just single-
953 quote the word. This is used for indexed arrays. */
955 quote_compound_array_list (list
, type
)
962 for (l
= list
; l
; l
= l
->next
)
964 if (l
->word
== 0 || l
->word
->word
== 0)
965 continue; /* should not happen, but just in case... */
966 if ((l
->word
->flags
& W_ASSIGNMENT
) == 0)
967 t
= sh_single_quote (l
->word
->word
);
969 t
= quote_compound_array_word (l
->word
->word
, type
);
970 free (l
->word
->word
);
975 /* For each word in a compound array assignment, if the word looks like
976 [ind]=value, quote globbing chars and characters in $IFS before the `='. */
978 quote_array_assignment_chars (list
)
984 for (l
= list
; l
; l
= l
->next
)
986 if (l
->word
== 0 || l
->word
->word
== 0 || l
->word
->word
[0] == '\0')
987 continue; /* should not happen, but just in case... */
988 /* Don't bother if it hasn't been recognized as an assignment or
989 doesn't look like [ind]=value */
990 if ((l
->word
->flags
& W_ASSIGNMENT
) == 0)
992 if (l
->word
->word
[0] != '[' || mbschr (l
->word
->word
, '=') == 0) /* ] */
995 nword
= quote_assign (l
->word
->word
);
996 free (l
->word
->word
);
997 l
->word
->word
= nword
;
998 l
->word
->flags
|= W_NOGLOB
; /* XXX - W_NOSPLIT also? */
1002 /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
1004 /* This function is called with SUB pointing to just after the beginning
1005 `[' of an array subscript and removes the array element to which SUB
1006 expands from array VAR. A subscript of `*' or `@' unsets the array. */
1007 /* If FLAGS&1 we don't expand the subscript; we just use it as-is. */
1009 unbind_array_element (var
, sub
, flags
)
1019 len
= skipsubscript (sub
, 0, (flags
&1) || (var
&& assoc_p(var
))); /* XXX */
1020 if (sub
[len
] != ']' || len
== 0)
1022 builtin_error ("%s[%s: %s", var
->name
, sub
, _(bush_badsub_errmsg
));
1027 if (ALL_ELEMENT_SUB (sub
[0]) && sub
[1] == 0)
1029 if (array_p (var
) || assoc_p (var
))
1031 unbind_variable (var
->name
); /* XXX -- {array,assoc}_flush ? */
1035 return -2; /* don't allow this to unset scalar variables */
1040 akey
= (flags
& 1) ? sub
: expand_assignment_string_to_string (sub
, 0);
1041 if (akey
== 0 || *akey
== 0)
1043 builtin_error ("[%s]: %s", sub
, _(bush_badsub_errmsg
));
1047 assoc_remove (assoc_cell (var
), akey
);
1051 else if (array_p (var
))
1053 ind
= array_expand_index (var
, sub
, len
+1, 0);
1054 /* negative subscripts to indexed arrays count back from end */
1056 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
1059 builtin_error ("[%s]: %s", sub
, _(bush_badsub_errmsg
));
1062 ae
= array_remove (array_cell (var
), ind
);
1064 array_dispose_element (ae
);
1066 else /* array_p (var) == 0 && assoc_p (var) == 0 */
1068 akey
= this_command_name
;
1069 ind
= array_expand_index (var
, sub
, len
+1, 0);
1070 this_command_name
= akey
;
1073 unbind_variable (var
->name
);
1077 return -2; /* any subscript other than 0 is invalid with scalar variables */
1083 /* Format and output an array assignment in compound form VAR=(VALUES),
1084 suitable for re-use as input. */
1086 print_array_assignment (var
, quoted
)
1092 vstr
= array_to_assign (array_cell (var
), quoted
);
1095 printf ("%s=%s\n", var
->name
, quoted
? "'()'" : "()");
1098 printf ("%s=%s\n", var
->name
, vstr
);
1103 /* Format and output an associative array assignment in compound form
1104 VAR=(VALUES), suitable for re-use as input. */
1106 print_assoc_assignment (var
, quoted
)
1112 vstr
= assoc_to_assign (assoc_cell (var
), quoted
);
1115 printf ("%s=%s\n", var
->name
, quoted
? "'()'" : "()");
1118 printf ("%s=%s\n", var
->name
, vstr
);
1123 /***********************************************************************/
1125 /* Utility functions to manage arrays and their contents for expansion */
1127 /***********************************************************************/
1129 /* Return 1 if NAME is a properly-formed array reference v[sub]. */
1131 /* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
1133 valid_array_reference (name
, flags
)
1138 int r
, len
, isassoc
;
1141 t
= mbschr (name
, '['); /* ] */
1146 r
= legal_identifier (name
);
1147 if (flags
& VA_NOEXPAND
) /* Don't waste a lookup if we don't need one */
1148 isassoc
= (entry
= find_variable (name
)) && assoc_p (entry
);
1153 if (isassoc
&& ((flags
& (VA_NOEXPAND
|VA_ONEWORD
)) == (VA_NOEXPAND
|VA_ONEWORD
)))
1154 len
= strlen (t
) - 1;
1156 len
= skipsubscript (t
, 0, flags
&VA_NOEXPAND
); /* VA_NOEXPAND must be 1 */
1158 /* Check for a properly-terminated non-null subscript. */
1159 len
= skipsubscript (t
, 0, 0); /* arithmetic expression */
1161 if (t
[len
] != ']' || len
== 1 || t
[len
+1] != '\0')
1165 /* Could check and allow subscripts consisting only of whitespace for
1166 existing associative arrays, using isassoc */
1167 for (r
= 1; r
< len
; r
++)
1168 if (whitespace (t
[r
]) == 0)
1172 /* This allows blank subscripts */
1179 /* Expand the array index beginning at S and extending LEN characters. */
1181 array_expand_index (var
, s
, len
, flags
)
1187 char *exp
, *t
, *savecmd
;
1191 exp
= (char *)xmalloc (len
);
1192 strncpy (exp
, s
, len
- 1);
1193 exp
[len
- 1] = '\0';
1194 #if 0 /* TAG: maybe bush-5.2 */
1195 if ((flags
& AV_NOEXPAND
) == 0)
1196 t
= expand_arith_string (exp
, Q_DOUBLE_QUOTES
|Q_ARITH
|Q_ARRAYSUB
); /* XXX - Q_ARRAYSUB for future use */
1200 t
= expand_arith_string (exp
, Q_DOUBLE_QUOTES
|Q_ARITH
|Q_ARRAYSUB
); /* XXX - Q_ARRAYSUB for future use */
1201 savecmd
= this_command_name
;
1202 this_command_name
= (char *)NULL
;
1203 val
= evalexp (t
, EXP_EXPANDED
, &expok
); /* XXX - was 0 but we expanded exp already */
1204 this_command_name
= savecmd
;
1210 set_exit_status (EXECUTION_FAILURE
);
1212 if (no_longjmp_on_fatal_error
)
1214 top_level_cleanup ();
1215 jump_to_top_level (DISCARD
);
1220 /* Return the name of the variable specified by S without any subscript.
1221 If SUBP is non-null, return a pointer to the start of the subscript
1222 in *SUBP. If LENP is non-null, the length of the subscript is returned
1223 in *LENP. This returns newly-allocated memory. */
1225 array_variable_name (s
, flags
, subp
, lenp
)
1234 t
= mbschr (s
, '[');
1241 return ((char *)NULL
);
1244 ni
= skipsubscript (s
, ind
, flags
); /* XXX - was 0 not flags */
1245 if (ni
<= ind
+ 1 || s
[ni
] != ']')
1247 err_badarraysub (s
);
1252 return ((char *)NULL
);
1256 ret
= savestring (s
);
1267 /* Return the variable specified by S without any subscript. If SUBP is
1268 non-null, return a pointer to the start of the subscript in *SUBP.
1269 If LENP is non-null, the length of the subscript is returned in *LENP. */
1271 array_variable_part (s
, flags
, subp
, lenp
)
1280 t
= array_variable_name (s
, flags
, subp
, lenp
);
1282 return ((SHELL_VAR
*)NULL
);
1283 var
= find_variable (t
); /* XXX - handle namerefs here? */
1286 return var
; /* now return invisible variables; caller must handle */
1289 #define INDEX_ERROR() \
1293 err_badarraysub (var->name); \
1297 err_badarraysub (s); \
1298 t[-1] = '['; /* ] */\
1300 return ((char *)NULL); \
1304 /* Return a string containing the elements in the array and subscript
1305 described by S. If the subscript is * or @, obeys quoting rules akin
1306 to the expansion of $* and $@ including double quoting. If RTYPE
1307 is non-null it gets 1 if the array reference is name[*], 2 if the
1308 reference is name[@], and 0 otherwise. */
1310 array_value_internal (s
, quoted
, flags
, rtype
, indp
)
1312 int quoted
, flags
, *rtype
;
1318 char *retval
, *t
, *temp
;
1322 var
= array_variable_part (s
, (flags
&AV_NOEXPAND
) ? 1 : 0, &t
, &len
); /* XXX */
1324 /* Expand the index, even if the variable doesn't exist, in case side
1325 effects are needed, like ${w[i++]} where w is unset. */
1328 return (char *)NULL
;
1332 return ((char *)NULL
); /* error message already printed */
1336 if (ALL_ELEMENT_SUB (t
[0]) && t
[1] == ']')
1339 *rtype
= (t
[0] == '*') ? 1 : 2;
1340 if ((flags
& AV_ALLOWALL
) == 0)
1342 err_badarraysub (s
);
1343 return ((char *)NULL
);
1345 else if (var
== 0 || value_cell (var
) == 0) /* XXX - check for invisible_p(var) ? */
1346 return ((char *)NULL
);
1347 else if (invisible_p (var
))
1348 return ((char *)NULL
);
1349 else if (array_p (var
) == 0 && assoc_p (var
) == 0)
1350 l
= add_string_to_list (value_cell (var
), (WORD_LIST
*)NULL
);
1351 else if (assoc_p (var
))
1353 l
= assoc_to_word_list (assoc_cell (var
));
1354 if (l
== (WORD_LIST
*)NULL
)
1355 return ((char *)NULL
);
1359 l
= array_to_word_list (array_cell (var
));
1360 if (l
== (WORD_LIST
*)NULL
)
1361 return ((char *) NULL
);
1364 /* Caller of array_value takes care of inspecting rtype and duplicating
1365 retval if rtype == 0, so this is not a memory leak */
1366 if (t
[0] == '*' && (quoted
& (Q_HERE_DOCUMENT
|Q_DOUBLE_QUOTES
)))
1368 temp
= string_list_dollar_star (l
, quoted
, (flags
& AV_ASSIGNRHS
) ? PF_ASSIGNRHS
: 0);
1369 retval
= quote_string (temp
);
1372 else /* ${name[@]} or unquoted ${name[*]} */
1373 retval
= string_list_dollar_at (l
, quoted
, (flags
& AV_ASSIGNRHS
) ? PF_ASSIGNRHS
: 0);
1381 if (var
== 0 || array_p (var
) || assoc_p (var
) == 0)
1383 if ((flags
& AV_USEIND
) == 0 || indp
== 0)
1385 ind
= array_expand_index (var
, t
, len
, flags
);
1388 /* negative subscripts to indexed arrays count back from end */
1389 if (var
&& array_p (var
))
1390 ind
= array_max_index (array_cell (var
)) + 1 + ind
;
1400 else if (assoc_p (var
))
1403 if ((flags
& AV_NOEXPAND
) == 0)
1404 akey
= expand_assignment_string_to_string (t
, 0); /* [ */
1406 akey
= savestring (t
);
1408 if (akey
== 0 || *akey
== 0)
1415 if (var
== 0 || value_cell (var
) == 0) /* XXX - check invisible_p(var) ? */
1418 return ((char *)NULL
);
1420 else if (invisible_p (var
))
1423 return ((char *)NULL
);
1425 if (array_p (var
) == 0 && assoc_p (var
) == 0)
1426 return (ind
== 0 ? value_cell (var
) : (char *)NULL
);
1427 else if (assoc_p (var
))
1429 retval
= assoc_reference (assoc_cell (var
), akey
);
1433 retval
= array_reference (array_cell (var
), ind
);
1439 /* Return a string containing the elements described by the array and
1440 subscript contained in S, obeying quoting for subscripts * and @. */
1442 array_value (s
, quoted
, flags
, rtype
, indp
)
1444 int quoted
, flags
, *rtype
;
1447 return (array_value_internal (s
, quoted
, flags
|AV_ALLOWALL
, rtype
, indp
));
1450 /* Return the value of the array indexing expression S as a single string.
1451 If (FLAGS & AV_ALLOWALL) is 0, do not allow `@' and `*' subscripts. This
1452 is used by other parts of the shell such as the arithmetic expression
1453 evaluator in expr.c. */
1455 get_array_value (s
, flags
, rtype
, indp
)
1460 return (array_value_internal (s
, 0, flags
, rtype
, indp
));
1464 array_keys (s
, quoted
, pflags
)
1469 char *retval
, *t
, *temp
;
1473 var
= array_variable_part (s
, 0, &t
, &len
);
1476 if (var
== 0 || ALL_ELEMENT_SUB (t
[0]) == 0 || t
[1] != ']')
1477 return (char *)NULL
;
1479 if (var_isset (var
) == 0 || invisible_p (var
))
1480 return (char *)NULL
;
1482 if (array_p (var
) == 0 && assoc_p (var
) == 0)
1483 l
= add_string_to_list ("0", (WORD_LIST
*)NULL
);
1484 else if (assoc_p (var
))
1485 l
= assoc_keys_to_word_list (assoc_cell (var
));
1487 l
= array_keys_to_word_list (array_cell (var
));
1488 if (l
== (WORD_LIST
*)NULL
)
1489 return ((char *) NULL
);
1491 retval
= string_list_pos_params (t
[0], l
, quoted
, pflags
);
1496 #endif /* ARRAY_VARS */