improve of cmpl.
[bush.git] / src / var / arrayfunc.c
blob596205454d16622eec9095933322065bffc76d0c
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/>.
21 #include "config.h"
23 #if defined (ARRAY_VARS)
25 #if defined (HAVE_UNISTD_H)
26 # include <unistd.h>
27 #endif
28 #include <stdio.h>
30 #include "bushintl.h"
32 #include "shell.h"
33 #include "runner/execute_cmd.h"
34 #include "impl/pathexp.h"
36 #include "shmbutil.h"
37 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
38 # include <mbstr.h> /* mbschr */
39 #endif
41 #include "builtins/common.h"
43 #ifndef LBRACK
44 # define LBRACK '['
45 # define RBRACK ']'
46 #endif
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 /* **************************************************************** */
69 /* */
70 /* Functions to manipulate array variables and perform assignments */
71 /* */
72 /* **************************************************************** */
74 /* Convert a shell variable to an array variable. The original value is
75 saved as array[0]. */
76 SHELL_VAR *
77 convert_var_to_array (var)
78 SHELL_VAR *var;
80 char *oldval;
81 ARRAY *array;
83 oldval = value_cell (var);
84 array = array_create ();
85 if (oldval)
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);
96 if (exported_p (var))
97 array_needs_making++;
99 VSETATTR (var, att_array);
100 if (oldval)
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);
109 return var;
112 /* Convert a shell variable to an array variable. The original value is
113 saved as array[0]. */
114 SHELL_VAR *
115 convert_var_to_assoc (var)
116 SHELL_VAR *var;
118 char *oldval;
119 HASH_TABLE *hash;
121 oldval = value_cell (var);
122 hash = assoc_create (0);
123 if (oldval)
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);
138 if (oldval)
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);
147 return var;
150 char *
151 make_array_variable_value (entry, ind, key, value, flags)
152 SHELL_VAR *entry;
153 arrayind_t ind;
154 char *key;
155 char *value;
156 int flags;
158 SHELL_VAR *dentry;
159 char *newval;
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);
167 if (assoc_p (entry))
168 newval = assoc_reference (assoc_cell (entry), key);
169 else
170 newval = array_reference (array_cell (entry), ind);
171 if (newval)
172 dentry->value = savestring (newval);
173 else
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
181 at them. */
182 newval = make_variable_value (dentry, value, flags);
183 dispose_variable (dentry);
185 else
186 newval = make_variable_value (entry, value, flags);
188 return newval;
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
194 of it.
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 */
197 static SHELL_VAR *
198 bind_assoc_var_internal (entry, hash, key, value, flags)
199 SHELL_VAR *entry;
200 HASH_TABLE *hash;
201 char *key;
202 char *value;
203 int flags;
205 char *newval;
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);
212 else
213 assoc_insert (hash, key, newval);
215 FREE (newval);
217 VUNSETATTR (entry, att_invisible); /* no longer invisible */
219 /* check mark_modified_variables if we ever want to export array vars */
220 return (entry);
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. */
225 static SHELL_VAR *
226 bind_array_var_internal (entry, ind, key, value, flags)
227 SHELL_VAR *entry;
228 arrayind_t ind;
229 char *key;
230 char *value;
231 int flags;
233 char *newval;
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);
241 else
242 array_insert (array_cell (entry), ind, newval);
243 FREE (newval);
245 VUNSETATTR (entry, att_invisible); /* no longer invisible */
247 /* check mark_modified_variables if we ever want to export array vars */
248 return (entry);
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. */
258 SHELL_VAR *
259 bind_array_variable (name, ind, value, flags)
260 char *name;
261 arrayind_t ind;
262 char *value;
263 int flags;
265 SHELL_VAR *entry;
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))
283 err_readonly (name);
284 return (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));
293 SHELL_VAR *
294 bind_array_element (entry, ind, value, flags)
295 SHELL_VAR *entry;
296 arrayind_t ind;
297 char *value;
298 int flags;
300 return (bind_array_var_internal (entry, ind, 0, value, flags));
303 SHELL_VAR *
304 bind_assoc_variable (entry, name, key, value, flags)
305 SHELL_VAR *entry;
306 char *name;
307 char *key;
308 char *value;
309 int flags;
311 if ((readonly_p (entry) && (flags&ASS_FORCE) == 0) || noassign_p (entry))
313 if (readonly_p (entry))
314 err_readonly (name);
315 return (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 */
324 SHELL_VAR *
325 assign_array_element (name, value, flags)
326 char *name, *value;
327 int flags;
329 char *sub, *vname;
330 int sublen, isassoc;
331 SHELL_VAR *entry;
333 vname = array_variable_name (name, (flags & ASS_NOEXPAND) != 0, &sub, &sublen);
335 if (vname == 0)
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))
343 free (vname);
344 err_badarraysub (name);
345 return ((SHELL_VAR *)NULL);
348 entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags);
350 free (vname);
351 return entry;
354 static SHELL_VAR *
355 assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
356 SHELL_VAR *entry;
357 char *name; /* only used for error messages */
358 char *vname;
359 char *sub;
360 int sublen;
361 char *value;
362 int flags;
364 char *akey;
365 arrayind_t ind;
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); /* [ */
372 else
373 akey = savestring (sub);
374 sub[sublen-1] = ']';
375 if (akey == 0 || *akey == 0)
377 err_badarraysub (name);
378 FREE (akey);
379 return ((SHELL_VAR *)NULL);
381 entry = bind_assoc_variable (entry, vname, akey, value, flags);
383 else
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;
389 if (ind < 0)
391 err_badarraysub (name);
392 return ((SHELL_VAR *)NULL);
394 entry = bind_array_variable (vname, ind, value, flags);
397 return (entry);
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. */
406 SHELL_VAR *
407 find_or_make_array_variable (name, flags)
408 char *name;
409 int flags;
411 SHELL_VAR *var;
413 var = find_variable (name);
414 if (var == 0)
416 /* See if we have a nameref pointing to a variable that hasn't been
417 created yet. */
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));
435 if (var == 0)
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))
440 err_readonly (name);
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);
452 return (var);
455 /* Perform a compound assignment statement for array NAME, where VALUE is
456 the text between the parens: NAME=( VALUE ) */
457 SHELL_VAR *
458 assign_array_from_string (name, value, flags)
459 char *name, *value;
460 int flags;
462 SHELL_VAR *var;
463 int vflags;
465 vflags = 1;
466 if (flags & ASS_MKASSOC)
467 vflags |= 2;
469 var = find_or_make_array_variable (name, vflags);
470 if (var == 0)
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
477 words in LIST. */
478 SHELL_VAR *
479 assign_array_var_from_word_list (var, list, flags)
480 SHELL_VAR *var;
481 WORD_LIST *list;
482 int flags;
484 register arrayind_t i;
485 register WORD_LIST *l;
486 ARRAY *a;
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 */
496 return var;
499 WORD_LIST *
500 expand_compound_array_assignment (var, value, flags)
501 SHELL_VAR *var;
502 char *value;
503 int flags;
505 WORD_LIST *list, *nlist;
506 char *val;
507 int ni;
509 /* This condition is true when invoked from the declare builtin with a
510 command like
511 declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' */
512 if (*value == '(') /*)*/
514 ni = 1;
515 val = extract_array_assignment_list (value, &ni);
516 if (val == 0)
517 return (WORD_LIST *)NULL;
519 else
520 val = value;
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))
533 if (val != value)
534 free (val);
535 return list;
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). */
542 if (list)
543 quote_array_assignment_chars (list);
545 /* Now that we've split it, perform the shell expansions on each
546 word in the list. */
547 nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;
549 dispose_words (list);
551 if (val != value)
552 free (val);
554 return nlist;
557 #if ASSOC_KVPAIR_ASSIGNMENT
558 static void
559 assign_assoc_from_kvlist (var, nlist, h, flags)
560 SHELL_VAR *var;
561 WORD_LIST *nlist;
562 HASH_TABLE *h;
563 int flags;
565 WORD_LIST *list;
566 char *akey, *aval, *k, *v;
567 int free_aval;
569 for (list = nlist; list; list = list->next)
571 free_aval = 0;
573 k = list->word->word;
574 v = list->next ? list->next->word->word : 0;
576 if (list->next)
577 list = list->next;
579 akey = expand_assignment_string_to_string (k, 0);
580 aval = expand_assignment_string_to_string (v, 0);
582 if (akey == 0 || *akey == 0)
584 err_badarraysub (k);
585 FREE (akey);
586 continue;
588 if (aval == 0)
590 aval = (char *)xmalloc (1);
591 aval[0] = '\0'; /* like do_assignment_internal */
592 free_aval = 1;
595 bind_assoc_var_internal (var, h, akey, aval, flags);
596 if (free_aval)
597 free (aval);
600 #endif
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 */
610 void
611 assign_compound_array_list (var, nlist, flags)
612 SHELL_VAR *var;
613 WORD_LIST *nlist;
614 int flags;
616 ARRAY *a;
617 HASH_TABLE *h, *nhash;
618 WORD_LIST *list;
619 char *w, *val, *nval, *savecmd;
620 int len, iflags, free_val;
621 arrayind_t ind, last_ind;
622 char *akey;
624 a = (var && array_p (var)) ? array_cell (var) : (ARRAY *)0;
625 nhash = h = (var && assoc_p (var)) ? assoc_cell (var) : (HASH_TABLE *)0;
627 akey = (char *)0;
628 ind = 0;
630 /* Now that we are ready to assign values to the array, kill the existing
631 value. */
632 if ((flags & ASS_APPEND) == 0)
634 if (a && array_p (var))
635 array_flush (a);
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);
651 assoc_dispose (h);
653 return;
655 #endif
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
669 above). */
670 len = skipsubscript (w, 0, 0);
672 /* XXX - changes for `+=' */
673 if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
675 if (assoc_p (var))
677 err_badarraysub (w);
678 continue;
680 nval = make_variable_value (var, w, flags);
681 if (var->assign_func)
682 (*var->assign_func) (var, nval, last_ind, 0);
683 else
684 array_insert (a, last_ind, nval);
685 FREE (nval);
686 last_ind++;
687 continue;
690 if (len == 1)
692 err_badarraysub (w);
693 continue;
696 if (ALL_ELEMENT_SUB (w[1]) && len == 2)
698 set_exit_status (EXECUTION_FAILURE);
699 if (assoc_p (var))
700 report_error (_("%s: invalid associative array key"), w);
701 else
702 report_error (_("%s: cannot assign to non-numeric index"), w);
703 continue;
706 if (array_p (var))
708 ind = array_expand_index (var, w + 1, len, 0);
709 /* negative subscripts to indexed arrays count back from end */
710 if (ind < 0)
711 ind = array_max_index (array_cell (var)) + 1 + ind;
712 if (ind < 0)
714 err_badarraysub (w);
715 continue;
718 last_ind = ind;
720 else if (assoc_p (var))
722 /* This is not performed above, see expand_compound_array_assignment */
723 w[len] = '\0'; /*[*/
724 akey = expand_assignment_string_to_string (w+1, 0);
725 w[len] = ']';
726 /* And we need to expand the value also, see below */
727 if (akey == 0 || *akey == 0)
729 err_badarraysub (w);
730 FREE (akey);
731 continue;
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;
739 val = w + len + 3;
741 else
742 val = w + len + 2;
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);
748 continue;
750 else /* No [ind]=value, just a stray `=' */
752 ind = last_ind;
753 val = w;
756 free_val = 0;
757 /* See above; we need to expand the value here */
758 if (assoc_p (var))
760 val = expand_assignment_string_to_string (val, 0);
761 if (val == 0)
763 val = (char *)xmalloc (1);
764 val[0] = '\0'; /* like do_assignment_internal */
766 free_val = 1;
769 savecmd = this_command_name;
770 if (integer_p (var))
771 this_command_name = (char *)NULL; /* no command name for errors */
772 if (assoc_p (var))
773 bind_assoc_var_internal (var, nhash, akey, val, iflags);
774 else
775 bind_array_var_internal (var, ind, akey, val, iflags);
776 last_ind++;
777 this_command_name = savecmd;
779 if (free_val)
780 free (val);
783 if (assoc_p (var) && nhash && nhash != h)
785 h = assoc_cell (var);
786 var_setassoc (var, nhash);
787 assoc_dispose (h);
791 /* Perform a compound array assignment: VAR->name=( VALUE ). The
792 VALUE has already had the parentheses stripped. */
793 SHELL_VAR *
794 assign_array_var_from_string (var, value, flags)
795 SHELL_VAR *var;
796 char *value;
797 int flags;
799 WORD_LIST *nlist;
801 if (value == 0)
802 return var;
804 nlist = expand_compound_array_assignment (var, value, flags);
805 assign_compound_array_list (var, nlist, flags);
807 if (nlist)
808 dispose_words (nlist);
810 if (var)
811 VUNSETATTR (var, att_invisible); /* no longer invisible */
813 return (var);
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. */
819 static char *
820 quote_assign (string)
821 const char *string;
823 size_t slen;
824 int saw_eq;
825 char *temp, *t, *subs;
826 const char *s, *send;
827 int ss, se;
828 DECLARE_MBSTATE;
830 slen = strlen (string);
831 send = string + slen;
833 t = temp = (char *)xmalloc (slen * 2 + 1);
834 saw_eq = 0;
835 for (s = string; *s; )
837 if (*s == '=')
838 saw_eq = 1;
839 if (saw_eq == 0 && *s == '[') /* looks like a subscript */
841 ss = s - string;
842 se = skipsubscript (string, ss, 0);
843 subs = substring (s, ss, se);
844 *t++ = '\\';
845 strcpy (t, subs);
846 t += se - ss;
847 *t++ = '\\';
848 *t++ = ']';
849 s += se + 1;
850 free (subs);
851 continue;
853 if (saw_eq == 0 && (glob_char_p (s) || isifs (*s)))
854 *t++ = '\\';
856 COPY_CHAR_P (t, s, send);
858 *t = '\0';
859 return temp;
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. */
866 static char *
867 quote_compound_array_word (w, type)
868 char *w;
869 int type;
871 char *nword, *sub, *value, *t;
872 int ind, wlen, i;
874 if (w[0] != LBRACK)
875 return (sh_single_quote (w));
876 ind = skipsubscript (w, 0, 0);
877 if (w[ind] != RBRACK)
878 return (sh_single_quote (w));
880 wlen = strlen (w);
881 w[ind] = '\0';
882 sub = sh_single_quote (w+1);
883 w[ind] = RBRACK;
885 nword = xmalloc (wlen * 4 + 5); /* wlen*4 is max single quoted length */
886 nword[0] = LBRACK;
887 i = STRLEN (sub);
888 memcpy (nword+1, sub, i);
889 i++; /* accommodate the opening LBRACK */
890 nword[i++] = w[ind++]; /* RBRACK */
891 if (w[ind] == '+')
892 nword[i++] = w[ind++];
893 nword[i++] = w[ind++];
894 value = sh_single_quote (w + ind);
895 strcpy (nword + i, value);
897 return nword;
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 )). */
907 char *
908 expand_and_quote_assoc_word (w, type)
909 char *w;
910 int type;
912 char *nword, *key, *value, *t;
913 int ind, wlen, i;
915 if (w[0] != LBRACK)
916 return (sh_single_quote (w));
917 ind = skipsubscript (w, 0, 0);
918 if (w[ind] != RBRACK)
919 return (sh_single_quote (w));
921 w[ind] = '\0';
922 t = expand_assignment_string_to_string (w+1, 0);
923 w[ind] = RBRACK;
924 key = sh_single_quote (t ? t : "");
925 free (t);
927 wlen = STRLEN (key);
928 nword = xmalloc (wlen + 5);
929 nword[0] = LBRACK;
930 memcpy (nword+1, key, wlen);
931 i = wlen + 1; /* accommodate the opening LBRACK */
933 nword[i++] = w[ind++]; /* RBRACK */
934 if (w[ind] == '+')
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 : "");
940 free (t);
941 nword = xrealloc (nword, wlen + 5 + STRLEN (value));
942 strcpy (nword + i, value);
944 free (key);
945 free (value);
947 return nword;
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. */
954 void
955 quote_compound_array_list (list, type)
956 WORD_LIST *list;
957 int type;
959 char *t;
960 WORD_LIST *l;
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);
968 else
969 t = quote_compound_array_word (l->word->word, type);
970 free (l->word->word);
971 l->word->word = t;
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 `='. */
977 static void
978 quote_array_assignment_chars (list)
979 WORD_LIST *list;
981 char *nword;
982 WORD_LIST *l;
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)
991 continue;
992 if (l->word->word[0] != '[' || mbschr (l->word->word, '=') == 0) /* ] */
993 continue;
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)
1010 SHELL_VAR *var;
1011 char *sub;
1012 int flags;
1014 int len;
1015 arrayind_t ind;
1016 char *akey;
1017 ARRAY_ELEMENT *ae;
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));
1023 return -1;
1025 sub[len] = '\0';
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 ? */
1032 return (0);
1034 else
1035 return -2; /* don't allow this to unset scalar variables */
1038 if (assoc_p (var))
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));
1044 FREE (akey);
1045 return -1;
1047 assoc_remove (assoc_cell (var), akey);
1048 if (akey != sub)
1049 free (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 */
1055 if (ind < 0)
1056 ind = array_max_index (array_cell (var)) + 1 + ind;
1057 if (ind < 0)
1059 builtin_error ("[%s]: %s", sub, _(bush_badsub_errmsg));
1060 return -1;
1062 ae = array_remove (array_cell (var), ind);
1063 if (ae)
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;
1071 if (ind == 0)
1073 unbind_variable (var->name);
1074 return (0);
1076 else
1077 return -2; /* any subscript other than 0 is invalid with scalar variables */
1080 return 0;
1083 /* Format and output an array assignment in compound form VAR=(VALUES),
1084 suitable for re-use as input. */
1085 void
1086 print_array_assignment (var, quoted)
1087 SHELL_VAR *var;
1088 int quoted;
1090 char *vstr;
1092 vstr = array_to_assign (array_cell (var), quoted);
1094 if (vstr == 0)
1095 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
1096 else
1098 printf ("%s=%s\n", var->name, vstr);
1099 free (vstr);
1103 /* Format and output an associative array assignment in compound form
1104 VAR=(VALUES), suitable for re-use as input. */
1105 void
1106 print_assoc_assignment (var, quoted)
1107 SHELL_VAR *var;
1108 int quoted;
1110 char *vstr;
1112 vstr = assoc_to_assign (assoc_cell (var), quoted);
1114 if (vstr == 0)
1115 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
1116 else
1118 printf ("%s=%s\n", var->name, vstr);
1119 free (vstr);
1123 /***********************************************************************/
1124 /* */
1125 /* Utility functions to manage arrays and their contents for expansion */
1126 /* */
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)
1134 const char *name;
1135 int flags;
1137 char *t;
1138 int r, len, isassoc;
1139 SHELL_VAR *entry;
1141 t = mbschr (name, '['); /* ] */
1142 isassoc = 0;
1143 if (t)
1145 *t = '\0';
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);
1149 *t = '[';
1150 if (r == 0)
1151 return 0;
1153 if (isassoc && ((flags & (VA_NOEXPAND|VA_ONEWORD)) == (VA_NOEXPAND|VA_ONEWORD)))
1154 len = strlen (t) - 1;
1155 else if (isassoc)
1156 len = skipsubscript (t, 0, flags&VA_NOEXPAND); /* VA_NOEXPAND must be 1 */
1157 else
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')
1162 return 0;
1164 #if 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)
1169 return 1;
1170 return 0;
1171 #else
1172 /* This allows blank subscripts */
1173 return 1;
1174 #endif
1176 return 0;
1179 /* Expand the array index beginning at S and extending LEN characters. */
1180 arrayind_t
1181 array_expand_index (var, s, len, flags)
1182 SHELL_VAR *var;
1183 char *s;
1184 int len;
1185 int flags;
1187 char *exp, *t, *savecmd;
1188 int expok;
1189 arrayind_t val;
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 */
1197 else
1198 t = exp;
1199 #endif
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;
1205 if (t != exp)
1206 free (t);
1207 free (exp);
1208 if (expok == 0)
1210 set_exit_status (EXECUTION_FAILURE);
1212 if (no_longjmp_on_fatal_error)
1213 return 0;
1214 top_level_cleanup ();
1215 jump_to_top_level (DISCARD);
1217 return val;
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. */
1224 char *
1225 array_variable_name (s, flags, subp, lenp)
1226 const char *s;
1227 int flags;
1228 char **subp;
1229 int *lenp;
1231 char *t, *ret;
1232 int ind, ni;
1234 t = mbschr (s, '[');
1235 if (t == 0)
1237 if (subp)
1238 *subp = t;
1239 if (lenp)
1240 *lenp = 0;
1241 return ((char *)NULL);
1243 ind = t - s;
1244 ni = skipsubscript (s, ind, flags); /* XXX - was 0 not flags */
1245 if (ni <= ind + 1 || s[ni] != ']')
1247 err_badarraysub (s);
1248 if (subp)
1249 *subp = t;
1250 if (lenp)
1251 *lenp = 0;
1252 return ((char *)NULL);
1255 *t = '\0';
1256 ret = savestring (s);
1257 *t++ = '['; /* ] */
1259 if (subp)
1260 *subp = t;
1261 if (lenp)
1262 *lenp = ni - ind;
1264 return ret;
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. */
1270 SHELL_VAR *
1271 array_variable_part (s, flags, subp, lenp)
1272 const char *s;
1273 int flags;
1274 char **subp;
1275 int *lenp;
1277 char *t;
1278 SHELL_VAR *var;
1280 t = array_variable_name (s, flags, subp, lenp);
1281 if (t == 0)
1282 return ((SHELL_VAR *)NULL);
1283 var = find_variable (t); /* XXX - handle namerefs here? */
1285 free (t);
1286 return var; /* now return invisible variables; caller must handle */
1289 #define INDEX_ERROR() \
1290 do \
1292 if (var) \
1293 err_badarraysub (var->name); \
1294 else \
1296 t[-1] = '\0'; \
1297 err_badarraysub (s); \
1298 t[-1] = '['; /* ] */\
1300 return ((char *)NULL); \
1302 while (0)
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. */
1309 static char *
1310 array_value_internal (s, quoted, flags, rtype, indp)
1311 const char *s;
1312 int quoted, flags, *rtype;
1313 arrayind_t *indp;
1315 int len;
1316 arrayind_t ind;
1317 char *akey;
1318 char *retval, *t, *temp;
1319 WORD_LIST *l;
1320 SHELL_VAR *var;
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. */
1326 #if 0
1327 if (var == 0)
1328 return (char *)NULL;
1329 #endif
1331 if (len == 0)
1332 return ((char *)NULL); /* error message already printed */
1334 /* [ */
1335 akey = 0;
1336 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
1338 if (rtype)
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);
1357 else
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);
1370 free (temp);
1372 else /* ${name[@]} or unquoted ${name[*]} */
1373 retval = string_list_dollar_at (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
1375 dispose_words (l);
1377 else
1379 if (rtype)
1380 *rtype = 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);
1386 if (ind < 0)
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;
1391 if (ind < 0)
1392 INDEX_ERROR();
1394 if (indp)
1395 *indp = ind;
1397 else if (indp)
1398 ind = *indp;
1400 else if (assoc_p (var))
1402 t[len - 1] = '\0';
1403 if ((flags & AV_NOEXPAND) == 0)
1404 akey = expand_assignment_string_to_string (t, 0); /* [ */
1405 else
1406 akey = savestring (t);
1407 t[len - 1] = ']';
1408 if (akey == 0 || *akey == 0)
1410 FREE (akey);
1411 INDEX_ERROR();
1415 if (var == 0 || value_cell (var) == 0) /* XXX - check invisible_p(var) ? */
1417 FREE (akey);
1418 return ((char *)NULL);
1420 else if (invisible_p (var))
1422 FREE (akey);
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);
1430 free (akey);
1432 else
1433 retval = array_reference (array_cell (var), ind);
1436 return retval;
1439 /* Return a string containing the elements described by the array and
1440 subscript contained in S, obeying quoting for subscripts * and @. */
1441 char *
1442 array_value (s, quoted, flags, rtype, indp)
1443 const char *s;
1444 int quoted, flags, *rtype;
1445 arrayind_t *indp;
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. */
1454 char *
1455 get_array_value (s, flags, rtype, indp)
1456 const char *s;
1457 int flags, *rtype;
1458 arrayind_t *indp;
1460 return (array_value_internal (s, 0, flags, rtype, indp));
1463 char *
1464 array_keys (s, quoted, pflags)
1465 char *s;
1466 int quoted, pflags;
1468 int len;
1469 char *retval, *t, *temp;
1470 WORD_LIST *l;
1471 SHELL_VAR *var;
1473 var = array_variable_part (s, 0, &t, &len);
1475 /* [ */
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));
1486 else
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);
1493 dispose_words (l);
1494 return retval;
1496 #endif /* ARRAY_VARS */