]> git.ipfire.org Git - thirdparty/bash.git/blob - arrayfunc.c
commit bash-20200420 snapshot
[thirdparty/bash.git] / arrayfunc.c
1 /* arrayfunc.c -- High-level array functions used by other parts of the shell. */
2
3 /* Copyright (C) 2001-2020 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
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.
11
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.
16
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/>.
19 */
20
21 #include "config.h"
22
23 #if defined (ARRAY_VARS)
24
25 #if defined (HAVE_UNISTD_H)
26 # include <unistd.h>
27 #endif
28 #include <stdio.h>
29
30 #include "bashintl.h"
31
32 #include "shell.h"
33 #include "execute_cmd.h"
34 #include "pathexp.h"
35
36 #include "shmbutil.h"
37 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
38 # include <mbstr.h> /* mbschr */
39 #endif
40
41 #include "builtins/common.h"
42
43 /* This variable means to not expand associative array subscripts more than
44 once, when performing variable expansion. */
45 int assoc_expand_once = 0;
46
47 /* Ditto for indexed array subscripts -- currently unused */
48 int array_expand_once = 0;
49
50 static SHELL_VAR *bind_array_var_internal PARAMS((SHELL_VAR *, arrayind_t, char *, char *, int));
51 static SHELL_VAR *assign_array_element_internal PARAMS((SHELL_VAR *, char *, char *, char *, int, char *, int));
52
53 static void assign_assoc_from_kvlist PARAMS((SHELL_VAR *, WORD_LIST *, HASH_TABLE *, int));
54
55 static char *quote_assign PARAMS((const char *));
56 static void quote_array_assignment_chars PARAMS((WORD_LIST *));
57 static char *array_value_internal PARAMS((const char *, int, int, int *, arrayind_t *));
58
59 /* Standard error message to use when encountering an invalid array subscript */
60 const char * const bash_badsub_errmsg = N_("bad array subscript");
61
62 /* **************************************************************** */
63 /* */
64 /* Functions to manipulate array variables and perform assignments */
65 /* */
66 /* **************************************************************** */
67
68 /* Convert a shell variable to an array variable. The original value is
69 saved as array[0]. */
70 SHELL_VAR *
71 convert_var_to_array (var)
72 SHELL_VAR *var;
73 {
74 char *oldval;
75 ARRAY *array;
76
77 oldval = value_cell (var);
78 array = array_create ();
79 if (oldval)
80 array_insert (array, 0, oldval);
81
82 FREE (value_cell (var));
83 var_setarray (var, array);
84
85 /* these aren't valid anymore */
86 var->dynamic_value = (sh_var_value_func_t *)NULL;
87 var->assign_func = (sh_var_assign_func_t *)NULL;
88
89 INVALIDATE_EXPORTSTR (var);
90 if (exported_p (var))
91 array_needs_making++;
92
93 VSETATTR (var, att_array);
94 if (oldval)
95 VUNSETATTR (var, att_invisible);
96
97 /* Make sure it's not marked as an associative array any more */
98 VUNSETATTR (var, att_assoc);
99
100 /* Since namerefs can't be array variables, turn off nameref attribute */
101 VUNSETATTR (var, att_nameref);
102
103 return var;
104 }
105
106 /* Convert a shell variable to an array variable. The original value is
107 saved as array[0]. */
108 SHELL_VAR *
109 convert_var_to_assoc (var)
110 SHELL_VAR *var;
111 {
112 char *oldval;
113 HASH_TABLE *hash;
114
115 oldval = value_cell (var);
116 hash = assoc_create (0);
117 if (oldval)
118 assoc_insert (hash, savestring ("0"), oldval);
119
120 FREE (value_cell (var));
121 var_setassoc (var, hash);
122
123 /* these aren't valid anymore */
124 var->dynamic_value = (sh_var_value_func_t *)NULL;
125 var->assign_func = (sh_var_assign_func_t *)NULL;
126
127 INVALIDATE_EXPORTSTR (var);
128 if (exported_p (var))
129 array_needs_making++;
130
131 VSETATTR (var, att_assoc);
132 if (oldval)
133 VUNSETATTR (var, att_invisible);
134
135 /* Make sure it's not marked as an indexed array any more */
136 VUNSETATTR (var, att_array);
137
138 /* Since namerefs can't be array variables, turn off nameref attribute */
139 VUNSETATTR (var, att_nameref);
140
141 return var;
142 }
143
144 char *
145 make_array_variable_value (entry, ind, key, value, flags)
146 SHELL_VAR *entry;
147 arrayind_t ind;
148 char *key;
149 char *value;
150 int flags;
151 {
152 SHELL_VAR *dentry;
153 char *newval;
154
155 /* If we're appending, we need the old value of the array reference, so
156 fake out make_variable_value with a dummy SHELL_VAR */
157 if (flags & ASS_APPEND)
158 {
159 dentry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
160 dentry->name = savestring (entry->name);
161 if (assoc_p (entry))
162 newval = assoc_reference (assoc_cell (entry), key);
163 else
164 newval = array_reference (array_cell (entry), ind);
165 if (newval)
166 dentry->value = savestring (newval);
167 else
168 {
169 dentry->value = (char *)xmalloc (1);
170 dentry->value[0] = '\0';
171 }
172 dentry->exportstr = 0;
173 dentry->attributes = entry->attributes & ~(att_array|att_assoc|att_exported);
174 /* Leave the rest of the members uninitialized; the code doesn't look
175 at them. */
176 newval = make_variable_value (dentry, value, flags);
177 dispose_variable (dentry);
178 }
179 else
180 newval = make_variable_value (entry, value, flags);
181
182 return newval;
183 }
184
185 /* Assign HASH[KEY]=VALUE according to FLAGS. ENTRY is an associative array
186 variable; HASH is the hash table to assign into. HASH may or may not be
187 the hash table associated with ENTRY; if it's not, the caller takes care
188 of it.
189 XXX - make sure that any dynamic associative array variables recreate the
190 hash table on each assignment. BASH_CMDS and BASH_ALIASES already do this */
191 static SHELL_VAR *
192 bind_assoc_var_internal (entry, hash, key, value, flags)
193 SHELL_VAR *entry;
194 HASH_TABLE *hash;
195 char *key;
196 char *value;
197 int flags;
198 {
199 char *newval;
200
201 /* Use the existing array contents to expand the value */
202 newval = make_array_variable_value (entry, 0, key, value, flags);
203
204 if (entry->assign_func)
205 (*entry->assign_func) (entry, newval, 0, key);
206 else
207 assoc_insert (hash, key, newval);
208
209 FREE (newval);
210
211 VUNSETATTR (entry, att_invisible); /* no longer invisible */
212
213 /* check mark_modified_variables if we ever want to export array vars */
214 return (entry);
215 }
216
217 /* Perform ENTRY[IND]=VALUE or ENTRY[KEY]=VALUE. This is not called for every
218 assignment to an associative array; see assign_compound_array_list below. */
219 static SHELL_VAR *
220 bind_array_var_internal (entry, ind, key, value, flags)
221 SHELL_VAR *entry;
222 arrayind_t ind;
223 char *key;
224 char *value;
225 int flags;
226 {
227 char *newval;
228
229 newval = make_array_variable_value (entry, ind, key, value, flags);
230
231 if (entry->assign_func)
232 (*entry->assign_func) (entry, newval, ind, key);
233 else if (assoc_p (entry))
234 assoc_insert (assoc_cell (entry), key, newval);
235 else
236 array_insert (array_cell (entry), ind, newval);
237 FREE (newval);
238
239 VUNSETATTR (entry, att_invisible); /* no longer invisible */
240
241 /* check mark_modified_variables if we ever want to export array vars */
242 return (entry);
243 }
244
245 /* Perform an array assignment name[ind]=value. If NAME already exists and
246 is not an array, and IND is 0, perform name=value instead. If NAME exists
247 and is not an array, and IND is not 0, convert it into an array with the
248 existing value as name[0].
249
250 If NAME does not exist, just create an array variable, no matter what
251 IND's value may be. */
252 SHELL_VAR *
253 bind_array_variable (name, ind, value, flags)
254 char *name;
255 arrayind_t ind;
256 char *value;
257 int flags;
258 {
259 SHELL_VAR *entry;
260
261 entry = find_shell_variable (name);
262
263 if (entry == (SHELL_VAR *) 0)
264 {
265 /* Is NAME a nameref variable that points to an unset variable? */
266 entry = find_variable_nameref_for_create (name, 0);
267 if (entry == INVALID_NAMEREF_VALUE)
268 return ((SHELL_VAR *)0);
269 if (entry && nameref_p (entry))
270 entry = make_new_array_variable (nameref_cell (entry));
271 }
272 if (entry == (SHELL_VAR *) 0)
273 entry = make_new_array_variable (name);
274 else if ((readonly_p (entry) && (flags&ASS_FORCE) == 0) || noassign_p (entry))
275 {
276 if (readonly_p (entry))
277 err_readonly (name);
278 return (entry);
279 }
280 else if (array_p (entry) == 0)
281 entry = convert_var_to_array (entry);
282
283 /* ENTRY is an array variable, and ARRAY points to the value. */
284 return (bind_array_var_internal (entry, ind, 0, value, flags));
285 }
286
287 SHELL_VAR *
288 bind_array_element (entry, ind, value, flags)
289 SHELL_VAR *entry;
290 arrayind_t ind;
291 char *value;
292 int flags;
293 {
294 return (bind_array_var_internal (entry, ind, 0, value, flags));
295 }
296
297 SHELL_VAR *
298 bind_assoc_variable (entry, name, key, value, flags)
299 SHELL_VAR *entry;
300 char *name;
301 char *key;
302 char *value;
303 int flags;
304 {
305 if ((readonly_p (entry) && (flags&ASS_FORCE) == 0) || noassign_p (entry))
306 {
307 if (readonly_p (entry))
308 err_readonly (name);
309 return (entry);
310 }
311
312 return (bind_assoc_var_internal (entry, assoc_cell (entry), key, value, flags));
313 }
314
315 /* Parse NAME, a lhs of an assignment statement of the form v[s], and
316 assign VALUE to that array element by calling bind_array_variable().
317 Flags are ASS_ assignment flags */
318 SHELL_VAR *
319 assign_array_element (name, value, flags)
320 char *name, *value;
321 int flags;
322 {
323 char *sub, *vname;
324 int sublen, isassoc;
325 SHELL_VAR *entry;
326
327 vname = array_variable_name (name, (flags & ASS_NOEXPAND) != 0, &sub, &sublen);
328
329 if (vname == 0)
330 return ((SHELL_VAR *)NULL);
331
332 entry = find_variable (vname);
333 isassoc = entry && assoc_p (entry);
334
335 if (((isassoc == 0 || (flags & ASS_NOEXPAND) == 0) && (ALL_ELEMENT_SUB (sub[0]) && sub[1] == ']')) || (sublen <= 1))
336 {
337 free (vname);
338 err_badarraysub (name);
339 return ((SHELL_VAR *)NULL);
340 }
341
342 entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags);
343
344 free (vname);
345 return entry;
346 }
347
348 static SHELL_VAR *
349 assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
350 SHELL_VAR *entry;
351 char *name; /* only used for error messages */
352 char *vname;
353 char *sub;
354 int sublen;
355 char *value;
356 int flags;
357 {
358 char *akey;
359 arrayind_t ind;
360
361 if (entry && assoc_p (entry))
362 {
363 sub[sublen-1] = '\0';
364 if ((flags & ASS_NOEXPAND) == 0)
365 akey = expand_assignment_string_to_string (sub, 0); /* [ */
366 else
367 akey = savestring (sub);
368 sub[sublen-1] = ']';
369 if (akey == 0 || *akey == 0)
370 {
371 err_badarraysub (name);
372 FREE (akey);
373 return ((SHELL_VAR *)NULL);
374 }
375 entry = bind_assoc_variable (entry, vname, akey, value, flags);
376 }
377 else
378 {
379 ind = array_expand_index (entry, sub, sublen, 0);
380 /* negative subscripts to indexed arrays count back from end */
381 if (entry && ind < 0)
382 ind = (array_p (entry) ? array_max_index (array_cell (entry)) : 0) + 1 + ind;
383 if (ind < 0)
384 {
385 err_badarraysub (name);
386 return ((SHELL_VAR *)NULL);
387 }
388 entry = bind_array_variable (vname, ind, value, flags);
389 }
390
391 return (entry);
392 }
393
394 /* Find the array variable corresponding to NAME. If there is no variable,
395 create a new array variable. If the variable exists but is not an array,
396 convert it to an indexed array. If FLAGS&1 is non-zero, an existing
397 variable is checked for the readonly or noassign attribute in preparation
398 for assignment (e.g., by the `read' builtin). If FLAGS&2 is non-zero, we
399 create an associative array. */
400 SHELL_VAR *
401 find_or_make_array_variable (name, flags)
402 char *name;
403 int flags;
404 {
405 SHELL_VAR *var;
406
407 var = find_variable (name);
408 if (var == 0)
409 {
410 /* See if we have a nameref pointing to a variable that hasn't been
411 created yet. */
412 var = find_variable_last_nameref (name, 1);
413 if (var && nameref_p (var) && invisible_p (var))
414 {
415 internal_warning (_("%s: removing nameref attribute"), name);
416 VUNSETATTR (var, att_nameref);
417 }
418 if (var && nameref_p (var))
419 {
420 if (valid_nameref_value (nameref_cell (var), 2) == 0)
421 {
422 sh_invalidid (nameref_cell (var));
423 return ((SHELL_VAR *)NULL);
424 }
425 var = (flags & 2) ? make_new_assoc_variable (nameref_cell (var)) : make_new_array_variable (nameref_cell (var));
426 }
427 }
428
429 if (var == 0)
430 var = (flags & 2) ? make_new_assoc_variable (name) : make_new_array_variable (name);
431 else if ((flags & 1) && (readonly_p (var) || noassign_p (var)))
432 {
433 if (readonly_p (var))
434 err_readonly (name);
435 return ((SHELL_VAR *)NULL);
436 }
437 else if ((flags & 2) && array_p (var))
438 {
439 set_exit_status (EXECUTION_FAILURE);
440 report_error (_("%s: cannot convert indexed to associative array"), name);
441 return ((SHELL_VAR *)NULL);
442 }
443 else if (array_p (var) == 0 && assoc_p (var) == 0)
444 var = convert_var_to_array (var);
445
446 return (var);
447 }
448
449 /* Perform a compound assignment statement for array NAME, where VALUE is
450 the text between the parens: NAME=( VALUE ) */
451 SHELL_VAR *
452 assign_array_from_string (name, value, flags)
453 char *name, *value;
454 int flags;
455 {
456 SHELL_VAR *var;
457 int vflags;
458
459 vflags = 1;
460 if (flags & ASS_MKASSOC)
461 vflags |= 2;
462
463 var = find_or_make_array_variable (name, vflags);
464 if (var == 0)
465 return ((SHELL_VAR *)NULL);
466
467 return (assign_array_var_from_string (var, value, flags));
468 }
469
470 /* Sequentially assign the indices of indexed array variable VAR from the
471 words in LIST. */
472 SHELL_VAR *
473 assign_array_var_from_word_list (var, list, flags)
474 SHELL_VAR *var;
475 WORD_LIST *list;
476 int flags;
477 {
478 register arrayind_t i;
479 register WORD_LIST *l;
480 ARRAY *a;
481
482 a = array_cell (var);
483 i = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
484
485 for (l = list; l; l = l->next, i++)
486 bind_array_var_internal (var, i, 0, l->word->word, flags & ~ASS_APPEND);
487
488 VUNSETATTR (var, att_invisible); /* no longer invisible */
489
490 return var;
491 }
492
493 WORD_LIST *
494 expand_compound_array_assignment (var, value, flags)
495 SHELL_VAR *var;
496 char *value;
497 int flags;
498 {
499 WORD_LIST *list, *nlist;
500 char *val;
501 int ni;
502
503 /* This condition is true when invoked from the declare builtin with a
504 command like
505 declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' */
506 if (*value == '(') /*)*/
507 {
508 ni = 1;
509 val = extract_array_assignment_list (value, &ni);
510 if (val == 0)
511 return (WORD_LIST *)NULL;
512 }
513 else
514 val = value;
515
516 /* Expand the value string into a list of words, performing all the
517 shell expansions including pathname generation and word splitting. */
518 /* First we split the string on whitespace, using the shell parser
519 (ksh93 seems to do this). */
520 list = parse_string_to_word_list (val, 1, "array assign");
521
522 /* Note that we defer expansion of the assignment statements for associative
523 arrays here, so we don't have to scan the subscript and find the ending
524 bracket twice. See the caller below. */
525 if (var && assoc_p (var))
526 {
527 if (val != value)
528 free (val);
529 return list;
530 }
531
532 /* If we're using [subscript]=value, we need to quote each [ and ] to
533 prevent unwanted filename expansion. This doesn't need to be done
534 for associative array expansion, since that uses a different expansion
535 function (see assign_compound_array_list below). */
536 if (list)
537 quote_array_assignment_chars (list);
538
539 /* Now that we've split it, perform the shell expansions on each
540 word in the list. */
541 nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;
542
543 dispose_words (list);
544
545 if (val != value)
546 free (val);
547
548 return nlist;
549 }
550
551 #if ASSOC_KVPAIR_ASSIGNMENT
552 static void
553 assign_assoc_from_kvlist (var, nlist, h, flags)
554 SHELL_VAR *var;
555 WORD_LIST *nlist;
556 HASH_TABLE *h;
557 int flags;
558 {
559 WORD_LIST *list;
560 char *akey, *aval, *k, *v;
561 int free_aval;
562
563 for (list = nlist; list; list = list->next)
564 {
565 free_aval = 0;
566
567 k = list->word->word;
568 v = list->next ? list->next->word->word : 0;
569
570 if (list->next)
571 list = list->next;
572
573 akey = expand_assignment_string_to_string (k, 0);
574 aval = expand_assignment_string_to_string (v, 0);
575
576 if (akey == 0 || *akey == 0)
577 {
578 err_badarraysub (k);
579 FREE (akey);
580 continue;
581 }
582 if (aval == 0)
583 {
584 aval = (char *)xmalloc (1);
585 aval[0] = '\0'; /* like do_assignment_internal */
586 free_aval = 1;
587 }
588
589 bind_assoc_var_internal (var, h, akey, aval, flags);
590 if (free_aval)
591 free (aval);
592 }
593 }
594 #endif
595
596 /* Callers ensure that VAR is not NULL. Associative array assignments have not
597 been expanded when this is called, so we don't have to scan through the
598 expanded subscript to find the ending bracket; indexed array assignments
599 have been expanded.
600 If this is an associative array, we perform the assignments into NHASH and
601 set NHASH to be the value of VAR after processing the assignments in NLIST */
602 void
603 assign_compound_array_list (var, nlist, flags)
604 SHELL_VAR *var;
605 WORD_LIST *nlist;
606 int flags;
607 {
608 ARRAY *a;
609 HASH_TABLE *h, *nhash;
610 WORD_LIST *list;
611 char *w, *val, *nval, *savecmd;
612 int len, iflags, free_val;
613 arrayind_t ind, last_ind;
614 char *akey;
615
616 a = (var && array_p (var)) ? array_cell (var) : (ARRAY *)0;
617 nhash = h = (var && assoc_p (var)) ? assoc_cell (var) : (HASH_TABLE *)0;
618
619 akey = (char *)0;
620 ind = 0;
621
622 /* Now that we are ready to assign values to the array, kill the existing
623 value. */
624 if ((flags & ASS_APPEND) == 0)
625 {
626 if (a && array_p (var))
627 array_flush (a);
628 else if (h && assoc_p (var))
629 nhash = assoc_create (h->nbuckets);
630 }
631
632 last_ind = (a && (flags & ASS_APPEND)) ? array_max_index (a) + 1 : 0;
633
634 #if ASSOC_KVPAIR_ASSIGNMENT
635 if (assoc_p (var) && nlist && (nlist->word->flags & W_ASSIGNMENT) == 0 && nlist->word->word[0] != '[') /*]*/
636 {
637 iflags = flags & ~ASS_APPEND;
638 assign_assoc_from_kvlist (var, nlist, nhash, iflags);
639 if (nhash && nhash != h)
640 {
641 h = assoc_cell (var);
642 var_setassoc (var, nhash);
643 assoc_dispose (h);
644 }
645 return;
646 }
647 #endif
648
649 for (list = nlist; list; list = list->next)
650 {
651 /* Don't allow var+=(values) to make assignments in VALUES append to
652 existing values by default. */
653 iflags = flags & ~ASS_APPEND;
654 w = list->word->word;
655
656 /* We have a word of the form [ind]=value */
657 if ((list->word->flags & W_ASSIGNMENT) && w[0] == '[')
658 {
659 /* Don't have to handle embedded quotes specially any more, since
660 associative array subscripts have not been expanded yet (see
661 above). */
662 len = skipsubscript (w, 0, 0);
663
664 /* XXX - changes for `+=' */
665 if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
666 {
667 if (assoc_p (var))
668 {
669 err_badarraysub (w);
670 continue;
671 }
672 nval = make_variable_value (var, w, flags);
673 if (var->assign_func)
674 (*var->assign_func) (var, nval, last_ind, 0);
675 else
676 array_insert (a, last_ind, nval);
677 FREE (nval);
678 last_ind++;
679 continue;
680 }
681
682 if (len == 1)
683 {
684 err_badarraysub (w);
685 continue;
686 }
687
688 if (ALL_ELEMENT_SUB (w[1]) && len == 2)
689 {
690 set_exit_status (EXECUTION_FAILURE);
691 if (assoc_p (var))
692 report_error (_("%s: invalid associative array key"), w);
693 else
694 report_error (_("%s: cannot assign to non-numeric index"), w);
695 continue;
696 }
697
698 if (array_p (var))
699 {
700 ind = array_expand_index (var, w + 1, len, 0);
701 /* negative subscripts to indexed arrays count back from end */
702 if (ind < 0)
703 ind = array_max_index (array_cell (var)) + 1 + ind;
704 if (ind < 0)
705 {
706 err_badarraysub (w);
707 continue;
708 }
709
710 last_ind = ind;
711 }
712 else if (assoc_p (var))
713 {
714 /* This is not performed above, see expand_compound_array_assignment */
715 w[len] = '\0'; /*[*/
716 akey = expand_assignment_string_to_string (w+1, 0);
717 w[len] = ']';
718 /* And we need to expand the value also, see below */
719 if (akey == 0 || *akey == 0)
720 {
721 err_badarraysub (w);
722 FREE (akey);
723 continue;
724 }
725 }
726
727 /* XXX - changes for `+=' -- just accept the syntax. ksh93 doesn't do this */
728 if (w[len + 1] == '+' && w[len + 2] == '=')
729 {
730 iflags |= ASS_APPEND;
731 val = w + len + 3;
732 }
733 else
734 val = w + len + 2;
735 }
736 else if (assoc_p (var))
737 {
738 set_exit_status (EXECUTION_FAILURE);
739 report_error (_("%s: %s: must use subscript when assigning associative array"), var->name, w);
740 continue;
741 }
742 else /* No [ind]=value, just a stray `=' */
743 {
744 ind = last_ind;
745 val = w;
746 }
747
748 free_val = 0;
749 /* See above; we need to expand the value here */
750 if (assoc_p (var))
751 {
752 val = expand_assignment_string_to_string (val, 0);
753 if (val == 0)
754 {
755 val = (char *)xmalloc (1);
756 val[0] = '\0'; /* like do_assignment_internal */
757 }
758 free_val = 1;
759 }
760
761 savecmd = this_command_name;
762 if (integer_p (var))
763 this_command_name = (char *)NULL; /* no command name for errors */
764 if (assoc_p (var))
765 bind_assoc_var_internal (var, nhash, akey, val, iflags);
766 else
767 bind_array_var_internal (var, ind, akey, val, iflags);
768 last_ind++;
769 this_command_name = savecmd;
770
771 if (free_val)
772 free (val);
773 }
774
775 if (assoc_p (var) && nhash && nhash != h)
776 {
777 h = assoc_cell (var);
778 var_setassoc (var, nhash);
779 assoc_dispose (h);
780 }
781 }
782
783 /* Perform a compound array assignment: VAR->name=( VALUE ). The
784 VALUE has already had the parentheses stripped. */
785 SHELL_VAR *
786 assign_array_var_from_string (var, value, flags)
787 SHELL_VAR *var;
788 char *value;
789 int flags;
790 {
791 WORD_LIST *nlist;
792
793 if (value == 0)
794 return var;
795
796 nlist = expand_compound_array_assignment (var, value, flags);
797 assign_compound_array_list (var, nlist, flags);
798
799 if (nlist)
800 dispose_words (nlist);
801
802 if (var)
803 VUNSETATTR (var, att_invisible); /* no longer invisible */
804
805 return (var);
806 }
807
808 /* Quote globbing chars and characters in $IFS before the `=' in an assignment
809 statement (usually a compound array assignment) to protect them from
810 unwanted filename expansion or word splitting. */
811 static char *
812 quote_assign (string)
813 const char *string;
814 {
815 size_t slen;
816 int saw_eq;
817 char *temp, *t, *subs;
818 const char *s, *send;
819 int ss, se;
820 DECLARE_MBSTATE;
821
822 slen = strlen (string);
823 send = string + slen;
824
825 t = temp = (char *)xmalloc (slen * 2 + 1);
826 saw_eq = 0;
827 for (s = string; *s; )
828 {
829 if (*s == '=')
830 saw_eq = 1;
831 if (saw_eq == 0 && *s == '[') /* looks like a subscript */
832 {
833 ss = s - string;
834 se = skipsubscript (string, ss, 0);
835 subs = substring (s, ss, se);
836 *t++ = '\\';
837 strcpy (t, subs);
838 t += se - ss;
839 *t++ = '\\';
840 *t++ = ']';
841 s += se + 1;
842 free (subs);
843 continue;
844 }
845 if (saw_eq == 0 && (glob_char_p (s) || isifs (*s)))
846 *t++ = '\\';
847
848 COPY_CHAR_P (t, s, send);
849 }
850 *t = '\0';
851 return temp;
852 }
853
854 /* For each word in a compound array assignment, if the word looks like
855 [ind]=value, quote globbing chars and characters in $IFS before the `='. */
856 static void
857 quote_array_assignment_chars (list)
858 WORD_LIST *list;
859 {
860 char *nword;
861 WORD_LIST *l;
862
863 for (l = list; l; l = l->next)
864 {
865 if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0')
866 continue; /* should not happen, but just in case... */
867 /* Don't bother if it hasn't been recognized as an assignment or
868 doesn't look like [ind]=value */
869 if ((l->word->flags & W_ASSIGNMENT) == 0)
870 continue;
871 if (l->word->word[0] != '[' || mbschr (l->word->word, '=') == 0) /* ] */
872 continue;
873
874 nword = quote_assign (l->word->word);
875 free (l->word->word);
876 l->word->word = nword;
877 l->word->flags |= W_NOGLOB; /* XXX - W_NOSPLIT also? */
878 }
879 }
880
881 /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
882
883 /* This function is called with SUB pointing to just after the beginning
884 `[' of an array subscript and removes the array element to which SUB
885 expands from array VAR. A subscript of `*' or `@' unsets the array. */
886 /* If FLAGS&1 we don't expand the subscript; we just use it as-is. */
887 int
888 unbind_array_element (var, sub, flags)
889 SHELL_VAR *var;
890 char *sub;
891 int flags;
892 {
893 int len;
894 arrayind_t ind;
895 char *akey;
896 ARRAY_ELEMENT *ae;
897
898 len = skipsubscript (sub, 0, (flags&1) || (var && assoc_p(var))); /* XXX */
899 if (sub[len] != ']' || len == 0)
900 {
901 builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg));
902 return -1;
903 }
904 sub[len] = '\0';
905
906 if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
907 {
908 if (array_p (var) || assoc_p (var))
909 {
910 unbind_variable (var->name); /* XXX -- {array,assoc}_flush ? */
911 return (0);
912 }
913 else
914 return -2; /* don't allow this to unset scalar variables */
915 }
916
917 if (assoc_p (var))
918 {
919 akey = (flags & 1) ? sub : expand_assignment_string_to_string (sub, 0);
920 if (akey == 0 || *akey == 0)
921 {
922 builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
923 FREE (akey);
924 return -1;
925 }
926 assoc_remove (assoc_cell (var), akey);
927 if (akey != sub)
928 free (akey);
929 }
930 else if (array_p (var))
931 {
932 ind = array_expand_index (var, sub, len+1, 0);
933 /* negative subscripts to indexed arrays count back from end */
934 if (ind < 0)
935 ind = array_max_index (array_cell (var)) + 1 + ind;
936 if (ind < 0)
937 {
938 builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
939 return -1;
940 }
941 ae = array_remove (array_cell (var), ind);
942 if (ae)
943 array_dispose_element (ae);
944 }
945 else /* array_p (var) == 0 && assoc_p (var) == 0 */
946 {
947 akey = this_command_name;
948 ind = array_expand_index (var, sub, len+1, 0);
949 this_command_name = akey;
950 if (ind == 0)
951 {
952 unbind_variable (var->name);
953 return (0);
954 }
955 else
956 return -2; /* any subscript other than 0 is invalid with scalar variables */
957 }
958
959 return 0;
960 }
961
962 /* Format and output an array assignment in compound form VAR=(VALUES),
963 suitable for re-use as input. */
964 void
965 print_array_assignment (var, quoted)
966 SHELL_VAR *var;
967 int quoted;
968 {
969 char *vstr;
970
971 vstr = array_to_assign (array_cell (var), quoted);
972
973 if (vstr == 0)
974 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
975 else
976 {
977 printf ("%s=%s\n", var->name, vstr);
978 free (vstr);
979 }
980 }
981
982 /* Format and output an associative array assignment in compound form
983 VAR=(VALUES), suitable for re-use as input. */
984 void
985 print_assoc_assignment (var, quoted)
986 SHELL_VAR *var;
987 int quoted;
988 {
989 char *vstr;
990
991 vstr = assoc_to_assign (assoc_cell (var), quoted);
992
993 if (vstr == 0)
994 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
995 else
996 {
997 printf ("%s=%s\n", var->name, vstr);
998 free (vstr);
999 }
1000 }
1001
1002 /***********************************************************************/
1003 /* */
1004 /* Utility functions to manage arrays and their contents for expansion */
1005 /* */
1006 /***********************************************************************/
1007
1008 /* Return 1 if NAME is a properly-formed array reference v[sub]. */
1009
1010 /* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
1011 int
1012 valid_array_reference (name, flags)
1013 const char *name;
1014 int flags;
1015 {
1016 char *t;
1017 int r, len, isassoc;
1018 SHELL_VAR *entry;
1019
1020 t = mbschr (name, '['); /* ] */
1021 isassoc = 0;
1022 if (t)
1023 {
1024 *t = '\0';
1025 r = legal_identifier (name);
1026 if (flags & VA_NOEXPAND) /* Don't waste a lookup if we don't need one */
1027 isassoc = (entry = find_variable (name)) && assoc_p (entry);
1028 *t = '[';
1029 if (r == 0)
1030 return 0;
1031
1032 if (isassoc && ((flags & (VA_NOEXPAND|VA_ONEWORD)) == (VA_NOEXPAND|VA_ONEWORD)))
1033 len = strlen (t) - 1;
1034 else if (isassoc)
1035 len = skipsubscript (t, 0, flags&VA_NOEXPAND); /* VA_NOEXPAND must be 1 */
1036 else
1037 /* Check for a properly-terminated non-null subscript. */
1038 len = skipsubscript (t, 0, 0); /* arithmetic expression */
1039
1040 if (t[len] != ']' || len == 1 || t[len+1] != '\0')
1041 return 0;
1042
1043 #if 0
1044 /* Could check and allow subscripts consisting only of whitespace for
1045 existing associative arrays, using isassoc */
1046 for (r = 1; r < len; r++)
1047 if (whitespace (t[r]) == 0)
1048 return 1;
1049 return 0;
1050 #else
1051 /* This allows blank subscripts */
1052 return 1;
1053 #endif
1054 }
1055 return 0;
1056 }
1057
1058 /* Expand the array index beginning at S and extending LEN characters. */
1059 arrayind_t
1060 array_expand_index (var, s, len, flags)
1061 SHELL_VAR *var;
1062 char *s;
1063 int len;
1064 int flags;
1065 {
1066 char *exp, *t, *savecmd;
1067 int expok;
1068 arrayind_t val;
1069
1070 exp = (char *)xmalloc (len);
1071 strncpy (exp, s, len - 1);
1072 exp[len - 1] = '\0';
1073 #if 0 /* TAG: maybe bash-5.1 */
1074 if ((flags & AV_NOEXPAND) == 0)
1075 t = expand_arith_string (exp, Q_DOUBLE_QUOTES|Q_ARITH|Q_ARRAYSUB); /* XXX - Q_ARRAYSUB for future use */
1076 else
1077 t = exp;
1078 #endif
1079 t = expand_arith_string (exp, Q_DOUBLE_QUOTES|Q_ARITH|Q_ARRAYSUB); /* XXX - Q_ARRAYSUB for future use */
1080 savecmd = this_command_name;
1081 this_command_name = (char *)NULL;
1082 val = evalexp (t, EXP_EXPANDED, &expok); /* XXX - was 0 but we expanded exp already */
1083 this_command_name = savecmd;
1084 if (t != exp)
1085 free (t);
1086 free (exp);
1087 if (expok == 0)
1088 {
1089 set_exit_status (EXECUTION_FAILURE);
1090
1091 if (no_longjmp_on_fatal_error)
1092 return 0;
1093 top_level_cleanup ();
1094 jump_to_top_level (DISCARD);
1095 }
1096 return val;
1097 }
1098
1099 /* Return the name of the variable specified by S without any subscript.
1100 If SUBP is non-null, return a pointer to the start of the subscript
1101 in *SUBP. If LENP is non-null, the length of the subscript is returned
1102 in *LENP. This returns newly-allocated memory. */
1103 char *
1104 array_variable_name (s, flags, subp, lenp)
1105 const char *s;
1106 int flags;
1107 char **subp;
1108 int *lenp;
1109 {
1110 char *t, *ret;
1111 int ind, ni;
1112
1113 t = mbschr (s, '[');
1114 if (t == 0)
1115 {
1116 if (subp)
1117 *subp = t;
1118 if (lenp)
1119 *lenp = 0;
1120 return ((char *)NULL);
1121 }
1122 ind = t - s;
1123 ni = skipsubscript (s, ind, flags); /* XXX - was 0 not flags */
1124 if (ni <= ind + 1 || s[ni] != ']')
1125 {
1126 err_badarraysub (s);
1127 if (subp)
1128 *subp = t;
1129 if (lenp)
1130 *lenp = 0;
1131 return ((char *)NULL);
1132 }
1133
1134 *t = '\0';
1135 ret = savestring (s);
1136 *t++ = '['; /* ] */
1137
1138 if (subp)
1139 *subp = t;
1140 if (lenp)
1141 *lenp = ni - ind;
1142
1143 return ret;
1144 }
1145
1146 /* Return the variable specified by S without any subscript. If SUBP is
1147 non-null, return a pointer to the start of the subscript in *SUBP.
1148 If LENP is non-null, the length of the subscript is returned in *LENP. */
1149 SHELL_VAR *
1150 array_variable_part (s, flags, subp, lenp)
1151 const char *s;
1152 int flags;
1153 char **subp;
1154 int *lenp;
1155 {
1156 char *t;
1157 SHELL_VAR *var;
1158
1159 t = array_variable_name (s, flags, subp, lenp);
1160 if (t == 0)
1161 return ((SHELL_VAR *)NULL);
1162 var = find_variable (t); /* XXX - handle namerefs here? */
1163
1164 free (t);
1165 return var; /* now return invisible variables; caller must handle */
1166 }
1167
1168 #define INDEX_ERROR() \
1169 do \
1170 { \
1171 if (var) \
1172 err_badarraysub (var->name); \
1173 else \
1174 { \
1175 t[-1] = '\0'; \
1176 err_badarraysub (s); \
1177 t[-1] = '['; /* ] */\
1178 } \
1179 return ((char *)NULL); \
1180 } \
1181 while (0)
1182
1183 /* Return a string containing the elements in the array and subscript
1184 described by S. If the subscript is * or @, obeys quoting rules akin
1185 to the expansion of $* and $@ including double quoting. If RTYPE
1186 is non-null it gets 1 if the array reference is name[*], 2 if the
1187 reference is name[@], and 0 otherwise. */
1188 static char *
1189 array_value_internal (s, quoted, flags, rtype, indp)
1190 const char *s;
1191 int quoted, flags, *rtype;
1192 arrayind_t *indp;
1193 {
1194 int len;
1195 arrayind_t ind;
1196 char *akey;
1197 char *retval, *t, *temp;
1198 WORD_LIST *l;
1199 SHELL_VAR *var;
1200
1201 var = array_variable_part (s, (flags&AV_NOEXPAND) ? 1 : 0, &t, &len); /* XXX */
1202
1203 /* Expand the index, even if the variable doesn't exist, in case side
1204 effects are needed, like ${w[i++]} where w is unset. */
1205 #if 0
1206 if (var == 0)
1207 return (char *)NULL;
1208 #endif
1209
1210 if (len == 0)
1211 return ((char *)NULL); /* error message already printed */
1212
1213 /* [ */
1214 akey = 0;
1215 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
1216 {
1217 if (rtype)
1218 *rtype = (t[0] == '*') ? 1 : 2;
1219 if ((flags & AV_ALLOWALL) == 0)
1220 {
1221 err_badarraysub (s);
1222 return ((char *)NULL);
1223 }
1224 else if (var == 0 || value_cell (var) == 0) /* XXX - check for invisible_p(var) ? */
1225 return ((char *)NULL);
1226 else if (invisible_p (var))
1227 return ((char *)NULL);
1228 else if (array_p (var) == 0 && assoc_p (var) == 0)
1229 l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
1230 else if (assoc_p (var))
1231 {
1232 l = assoc_to_word_list (assoc_cell (var));
1233 if (l == (WORD_LIST *)NULL)
1234 return ((char *)NULL);
1235 }
1236 else
1237 {
1238 l = array_to_word_list (array_cell (var));
1239 if (l == (WORD_LIST *)NULL)
1240 return ((char *) NULL);
1241 }
1242
1243 /* Caller of array_value takes care of inspecting rtype and duplicating
1244 retval if rtype == 0, so this is not a memory leak */
1245 if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
1246 {
1247 temp = string_list_dollar_star (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
1248 retval = quote_string (temp);
1249 free (temp);
1250 }
1251 else /* ${name[@]} or unquoted ${name[*]} */
1252 retval = string_list_dollar_at (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
1253
1254 dispose_words (l);
1255 }
1256 else
1257 {
1258 if (rtype)
1259 *rtype = 0;
1260 if (var == 0 || array_p (var) || assoc_p (var) == 0)
1261 {
1262 if ((flags & AV_USEIND) == 0 || indp == 0)
1263 {
1264 ind = array_expand_index (var, t, len, flags);
1265 if (ind < 0)
1266 {
1267 /* negative subscripts to indexed arrays count back from end */
1268 if (var && array_p (var))
1269 ind = array_max_index (array_cell (var)) + 1 + ind;
1270 if (ind < 0)
1271 INDEX_ERROR();
1272 }
1273 if (indp)
1274 *indp = ind;
1275 }
1276 else if (indp)
1277 ind = *indp;
1278 }
1279 else if (assoc_p (var))
1280 {
1281 t[len - 1] = '\0';
1282 if ((flags & AV_NOEXPAND) == 0)
1283 akey = expand_assignment_string_to_string (t, 0); /* [ */
1284 else
1285 akey = savestring (t);
1286 t[len - 1] = ']';
1287 if (akey == 0 || *akey == 0)
1288 {
1289 FREE (akey);
1290 INDEX_ERROR();
1291 }
1292 }
1293
1294 if (var == 0 || value_cell (var) == 0) /* XXX - check invisible_p(var) ? */
1295 {
1296 FREE (akey);
1297 return ((char *)NULL);
1298 }
1299 else if (invisible_p (var))
1300 {
1301 FREE (akey);
1302 return ((char *)NULL);
1303 }
1304 if (array_p (var) == 0 && assoc_p (var) == 0)
1305 return (ind == 0 ? value_cell (var) : (char *)NULL);
1306 else if (assoc_p (var))
1307 {
1308 retval = assoc_reference (assoc_cell (var), akey);
1309 free (akey);
1310 }
1311 else
1312 retval = array_reference (array_cell (var), ind);
1313 }
1314
1315 return retval;
1316 }
1317
1318 /* Return a string containing the elements described by the array and
1319 subscript contained in S, obeying quoting for subscripts * and @. */
1320 char *
1321 array_value (s, quoted, flags, rtype, indp)
1322 const char *s;
1323 int quoted, flags, *rtype;
1324 arrayind_t *indp;
1325 {
1326 return (array_value_internal (s, quoted, flags|AV_ALLOWALL, rtype, indp));
1327 }
1328
1329 /* Return the value of the array indexing expression S as a single string.
1330 If (FLAGS & AV_ALLOWALL) is 0, do not allow `@' and `*' subscripts. This
1331 is used by other parts of the shell such as the arithmetic expression
1332 evaluator in expr.c. */
1333 char *
1334 get_array_value (s, flags, rtype, indp)
1335 const char *s;
1336 int flags, *rtype;
1337 arrayind_t *indp;
1338 {
1339 return (array_value_internal (s, 0, flags, rtype, indp));
1340 }
1341
1342 char *
1343 array_keys (s, quoted, pflags)
1344 char *s;
1345 int quoted, pflags;
1346 {
1347 int len;
1348 char *retval, *t, *temp;
1349 WORD_LIST *l;
1350 SHELL_VAR *var;
1351
1352 var = array_variable_part (s, 0, &t, &len);
1353
1354 /* [ */
1355 if (var == 0 || ALL_ELEMENT_SUB (t[0]) == 0 || t[1] != ']')
1356 return (char *)NULL;
1357
1358 if (var_isset (var) == 0 || invisible_p (var))
1359 return (char *)NULL;
1360
1361 if (array_p (var) == 0 && assoc_p (var) == 0)
1362 l = add_string_to_list ("0", (WORD_LIST *)NULL);
1363 else if (assoc_p (var))
1364 l = assoc_keys_to_word_list (assoc_cell (var));
1365 else
1366 l = array_keys_to_word_list (array_cell (var));
1367 if (l == (WORD_LIST *)NULL)
1368 return ((char *) NULL);
1369
1370 retval = string_list_pos_params (t[0], l, quoted, pflags);
1371
1372 dispose_words (l);
1373 return retval;
1374 }
1375 #endif /* ARRAY_VARS */