]> git.ipfire.org Git - thirdparty/bash.git/blob - arrayfunc.c
bash-5.1 distribution sources and documentation
[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 #ifndef LBRACK
44 # define LBRACK '['
45 # define RBRACK ']'
46 #endif
47
48 /* This variable means to not expand associative array subscripts more than
49 once, when performing variable expansion. */
50 int assoc_expand_once = 0;
51
52 /* Ditto for indexed array subscripts -- currently unused */
53 int array_expand_once = 0;
54
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));
57
58 static void assign_assoc_from_kvlist PARAMS((SHELL_VAR *, WORD_LIST *, HASH_TABLE *, int));
59
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 *));
64
65 /* Standard error message to use when encountering an invalid array subscript */
66 const char * const bash_badsub_errmsg = N_("bad array subscript");
67
68 /* **************************************************************** */
69 /* */
70 /* Functions to manipulate array variables and perform assignments */
71 /* */
72 /* **************************************************************** */
73
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;
79 {
80 char *oldval;
81 ARRAY *array;
82
83 oldval = value_cell (var);
84 array = array_create ();
85 if (oldval)
86 array_insert (array, 0, oldval);
87
88 FREE (value_cell (var));
89 var_setarray (var, array);
90
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;
94
95 INVALIDATE_EXPORTSTR (var);
96 if (exported_p (var))
97 array_needs_making++;
98
99 VSETATTR (var, att_array);
100 if (oldval)
101 VUNSETATTR (var, att_invisible);
102
103 /* Make sure it's not marked as an associative array any more */
104 VUNSETATTR (var, att_assoc);
105
106 /* Since namerefs can't be array variables, turn off nameref attribute */
107 VUNSETATTR (var, att_nameref);
108
109 return var;
110 }
111
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;
117 {
118 char *oldval;
119 HASH_TABLE *hash;
120
121 oldval = value_cell (var);
122 hash = assoc_create (0);
123 if (oldval)
124 assoc_insert (hash, savestring ("0"), oldval);
125
126 FREE (value_cell (var));
127 var_setassoc (var, hash);
128
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;
132
133 INVALIDATE_EXPORTSTR (var);
134 if (exported_p (var))
135 array_needs_making++;
136
137 VSETATTR (var, att_assoc);
138 if (oldval)
139 VUNSETATTR (var, att_invisible);
140
141 /* Make sure it's not marked as an indexed array any more */
142 VUNSETATTR (var, att_array);
143
144 /* Since namerefs can't be array variables, turn off nameref attribute */
145 VUNSETATTR (var, att_nameref);
146
147 return var;
148 }
149
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;
157 {
158 SHELL_VAR *dentry;
159 char *newval;
160
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)
164 {
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
174 {
175 dentry->value = (char *)xmalloc (1);
176 dentry->value[0] = '\0';
177 }
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);
184 }
185 else
186 newval = make_variable_value (entry, value, flags);
187
188 return newval;
189 }
190
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. BASH_CMDS and BASH_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;
204 {
205 char *newval;
206
207 /* Use the existing array contents to expand the value */
208 newval = make_array_variable_value (entry, 0, key, value, flags);
209
210 if (entry->assign_func)
211 (*entry->assign_func) (entry, newval, 0, key);
212 else
213 assoc_insert (hash, key, newval);
214
215 FREE (newval);
216
217 VUNSETATTR (entry, att_invisible); /* no longer invisible */
218
219 /* check mark_modified_variables if we ever want to export array vars */
220 return (entry);
221 }
222
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;
232 {
233 char *newval;
234
235 newval = make_array_variable_value (entry, ind, key, value, flags);
236
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);
244
245 VUNSETATTR (entry, att_invisible); /* no longer invisible */
246
247 /* check mark_modified_variables if we ever want to export array vars */
248 return (entry);
249 }
250
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].
255
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;
264 {
265 SHELL_VAR *entry;
266
267 entry = find_shell_variable (name);
268
269 if (entry == (SHELL_VAR *) 0)
270 {
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));
277 }
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))
281 {
282 if (readonly_p (entry))
283 err_readonly (name);
284 return (entry);
285 }
286 else if (array_p (entry) == 0)
287 entry = convert_var_to_array (entry);
288
289 /* ENTRY is an array variable, and ARRAY points to the value. */
290 return (bind_array_var_internal (entry, ind, 0, value, flags));
291 }
292
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;
299 {
300 return (bind_array_var_internal (entry, ind, 0, value, flags));
301 }
302
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;
310 {
311 if ((readonly_p (entry) && (flags&ASS_FORCE) == 0) || noassign_p (entry))
312 {
313 if (readonly_p (entry))
314 err_readonly (name);
315 return (entry);
316 }
317
318 return (bind_assoc_var_internal (entry, assoc_cell (entry), key, value, flags));
319 }
320
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;
328 {
329 char *sub, *vname;
330 int sublen, isassoc;
331 SHELL_VAR *entry;
332
333 vname = array_variable_name (name, (flags & ASS_NOEXPAND) != 0, &sub, &sublen);
334
335 if (vname == 0)
336 return ((SHELL_VAR *)NULL);
337
338 entry = find_variable (vname);
339 isassoc = entry && assoc_p (entry);
340
341 if (((isassoc == 0 || (flags & ASS_NOEXPAND) == 0) && (ALL_ELEMENT_SUB (sub[0]) && sub[1] == ']')) || (sublen <= 1))
342 {
343 free (vname);
344 err_badarraysub (name);
345 return ((SHELL_VAR *)NULL);
346 }
347
348 entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags);
349
350 free (vname);
351 return entry;
352 }
353
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;
363 {
364 char *akey;
365 arrayind_t ind;
366
367 if (entry && assoc_p (entry))
368 {
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)
376 {
377 err_badarraysub (name);
378 FREE (akey);
379 return ((SHELL_VAR *)NULL);
380 }
381 entry = bind_assoc_variable (entry, vname, akey, value, flags);
382 }
383 else
384 {
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)
390 {
391 err_badarraysub (name);
392 return ((SHELL_VAR *)NULL);
393 }
394 entry = bind_array_variable (vname, ind, value, flags);
395 }
396
397 return (entry);
398 }
399
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;
410 {
411 SHELL_VAR *var;
412
413 var = find_variable (name);
414 if (var == 0)
415 {
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))
420 {
421 internal_warning (_("%s: removing nameref attribute"), name);
422 VUNSETATTR (var, att_nameref);
423 }
424 if (var && nameref_p (var))
425 {
426 if (valid_nameref_value (nameref_cell (var), 2) == 0)
427 {
428 sh_invalidid (nameref_cell (var));
429 return ((SHELL_VAR *)NULL);
430 }
431 var = (flags & 2) ? make_new_assoc_variable (nameref_cell (var)) : make_new_array_variable (nameref_cell (var));
432 }
433 }
434
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)))
438 {
439 if (readonly_p (var))
440 err_readonly (name);
441 return ((SHELL_VAR *)NULL);
442 }
443 else if ((flags & 2) && array_p (var))
444 {
445 set_exit_status (EXECUTION_FAILURE);
446 report_error (_("%s: cannot convert indexed to associative array"), name);
447 return ((SHELL_VAR *)NULL);
448 }
449 else if (array_p (var) == 0 && assoc_p (var) == 0)
450 var = convert_var_to_array (var);
451
452 return (var);
453 }
454
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;
461 {
462 SHELL_VAR *var;
463 int vflags;
464
465 vflags = 1;
466 if (flags & ASS_MKASSOC)
467 vflags |= 2;
468
469 var = find_or_make_array_variable (name, vflags);
470 if (var == 0)
471 return ((SHELL_VAR *)NULL);
472
473 return (assign_array_var_from_string (var, value, flags));
474 }
475
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;
483 {
484 register arrayind_t i;
485 register WORD_LIST *l;
486 ARRAY *a;
487
488 a = array_cell (var);
489 i = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
490
491 for (l = list; l; l = l->next, i++)
492 bind_array_var_internal (var, i, 0, l->word->word, flags & ~ASS_APPEND);
493
494 VUNSETATTR (var, att_invisible); /* no longer invisible */
495
496 return var;
497 }
498
499 WORD_LIST *
500 expand_compound_array_assignment (var, value, flags)
501 SHELL_VAR *var;
502 char *value;
503 int flags;
504 {
505 WORD_LIST *list, *nlist;
506 char *val;
507 int ni;
508
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 == '(') /*)*/
513 {
514 ni = 1;
515 val = extract_array_assignment_list (value, &ni);
516 if (val == 0)
517 return (WORD_LIST *)NULL;
518 }
519 else
520 val = value;
521
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");
527
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))
532 {
533 if (val != value)
534 free (val);
535 return list;
536 }
537
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);
544
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;
548
549 dispose_words (list);
550
551 if (val != value)
552 free (val);
553
554 return nlist;
555 }
556
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;
564 {
565 WORD_LIST *list;
566 char *akey, *aval, *k, *v;
567 int free_aval;
568
569 for (list = nlist; list; list = list->next)
570 {
571 free_aval = 0;
572
573 k = list->word->word;
574 v = list->next ? list->next->word->word : 0;
575
576 if (list->next)
577 list = list->next;
578
579 akey = expand_assignment_string_to_string (k, 0);
580 aval = expand_assignment_string_to_string (v, 0);
581
582 if (akey == 0 || *akey == 0)
583 {
584 err_badarraysub (k);
585 FREE (akey);
586 continue;
587 }
588 if (aval == 0)
589 {
590 aval = (char *)xmalloc (1);
591 aval[0] = '\0'; /* like do_assignment_internal */
592 free_aval = 1;
593 }
594
595 bind_assoc_var_internal (var, h, akey, aval, flags);
596 if (free_aval)
597 free (aval);
598 }
599 }
600 #endif
601
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.
607
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;
615 {
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;
623
624 a = (var && array_p (var)) ? array_cell (var) : (ARRAY *)0;
625 nhash = h = (var && assoc_p (var)) ? assoc_cell (var) : (HASH_TABLE *)0;
626
627 akey = (char *)0;
628 ind = 0;
629
630 /* Now that we are ready to assign values to the array, kill the existing
631 value. */
632 if ((flags & ASS_APPEND) == 0)
633 {
634 if (a && array_p (var))
635 array_flush (a);
636 else if (h && assoc_p (var))
637 nhash = assoc_create (h->nbuckets);
638 }
639
640 last_ind = (a && (flags & ASS_APPEND)) ? array_max_index (a) + 1 : 0;
641
642 #if ASSOC_KVPAIR_ASSIGNMENT
643 if (assoc_p (var) && nlist && (nlist->word->flags & W_ASSIGNMENT) == 0 && nlist->word->word[0] != '[') /*]*/
644 {
645 iflags = flags & ~ASS_APPEND;
646 assign_assoc_from_kvlist (var, nlist, nhash, iflags);
647 if (nhash && nhash != h)
648 {
649 h = assoc_cell (var);
650 var_setassoc (var, nhash);
651 assoc_dispose (h);
652 }
653 return;
654 }
655 #endif
656
657 for (list = nlist; list; list = list->next)
658 {
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;
663
664 /* We have a word of the form [ind]=value */
665 if ((list->word->flags & W_ASSIGNMENT) && w[0] == '[')
666 {
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);
671
672 /* XXX - changes for `+=' */
673 if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
674 {
675 if (assoc_p (var))
676 {
677 err_badarraysub (w);
678 continue;
679 }
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;
688 }
689
690 if (len == 1)
691 {
692 err_badarraysub (w);
693 continue;
694 }
695
696 if (ALL_ELEMENT_SUB (w[1]) && len == 2)
697 {
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;
704 }
705
706 if (array_p (var))
707 {
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)
713 {
714 err_badarraysub (w);
715 continue;
716 }
717
718 last_ind = ind;
719 }
720 else if (assoc_p (var))
721 {
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)
728 {
729 err_badarraysub (w);
730 FREE (akey);
731 continue;
732 }
733 }
734
735 /* XXX - changes for `+=' -- just accept the syntax. ksh93 doesn't do this */
736 if (w[len + 1] == '+' && w[len + 2] == '=')
737 {
738 iflags |= ASS_APPEND;
739 val = w + len + 3;
740 }
741 else
742 val = w + len + 2;
743 }
744 else if (assoc_p (var))
745 {
746 set_exit_status (EXECUTION_FAILURE);
747 report_error (_("%s: %s: must use subscript when assigning associative array"), var->name, w);
748 continue;
749 }
750 else /* No [ind]=value, just a stray `=' */
751 {
752 ind = last_ind;
753 val = w;
754 }
755
756 free_val = 0;
757 /* See above; we need to expand the value here */
758 if (assoc_p (var))
759 {
760 val = expand_assignment_string_to_string (val, 0);
761 if (val == 0)
762 {
763 val = (char *)xmalloc (1);
764 val[0] = '\0'; /* like do_assignment_internal */
765 }
766 free_val = 1;
767 }
768
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;
778
779 if (free_val)
780 free (val);
781 }
782
783 if (assoc_p (var) && nhash && nhash != h)
784 {
785 h = assoc_cell (var);
786 var_setassoc (var, nhash);
787 assoc_dispose (h);
788 }
789 }
790
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;
798 {
799 WORD_LIST *nlist;
800
801 if (value == 0)
802 return var;
803
804 nlist = expand_compound_array_assignment (var, value, flags);
805 assign_compound_array_list (var, nlist, flags);
806
807 if (nlist)
808 dispose_words (nlist);
809
810 if (var)
811 VUNSETATTR (var, att_invisible); /* no longer invisible */
812
813 return (var);
814 }
815
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;
822 {
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;
829
830 slen = strlen (string);
831 send = string + slen;
832
833 t = temp = (char *)xmalloc (slen * 2 + 1);
834 saw_eq = 0;
835 for (s = string; *s; )
836 {
837 if (*s == '=')
838 saw_eq = 1;
839 if (saw_eq == 0 && *s == '[') /* looks like a subscript */
840 {
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;
852 }
853 if (saw_eq == 0 && (glob_char_p (s) || isifs (*s)))
854 *t++ = '\\';
855
856 COPY_CHAR_P (t, s, send);
857 }
858 *t = '\0';
859 return temp;
860 }
861
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;
870 {
871 char *nword, *sub, *value, *t;
872 int ind, wlen, i;
873
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));
879
880 wlen = strlen (w);
881 w[ind] = '\0';
882 sub = sh_single_quote (w+1);
883 w[ind] = RBRACK;
884
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);
896
897 return nword;
898 }
899
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;
911 {
912 char *nword, *key, *value, *t;
913 int ind, wlen, i;
914
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));
920
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);
926
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 */
932
933 nword[i++] = w[ind++]; /* RBRACK */
934 if (w[ind] == '+')
935 nword[i++] = w[ind++];
936 nword[i++] = w[ind++];
937
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);
943
944 free (key);
945 free (value);
946
947 return nword;
948 }
949
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;
958 {
959 char *t;
960 WORD_LIST *l;
961
962 for (l = list; l; l = l->next)
963 {
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;
972 }
973 }
974
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;
980 {
981 char *nword;
982 WORD_LIST *l;
983
984 for (l = list; l; l = l->next)
985 {
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;
994
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? */
999 }
1000 }
1001
1002 /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
1003
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. */
1008 int
1009 unbind_array_element (var, sub, flags)
1010 SHELL_VAR *var;
1011 char *sub;
1012 int flags;
1013 {
1014 int len;
1015 arrayind_t ind;
1016 char *akey;
1017 ARRAY_ELEMENT *ae;
1018
1019 len = skipsubscript (sub, 0, (flags&1) || (var && assoc_p(var))); /* XXX */
1020 if (sub[len] != ']' || len == 0)
1021 {
1022 builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg));
1023 return -1;
1024 }
1025 sub[len] = '\0';
1026
1027 if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
1028 {
1029 if (array_p (var) || assoc_p (var))
1030 {
1031 unbind_variable (var->name); /* XXX -- {array,assoc}_flush ? */
1032 return (0);
1033 }
1034 else
1035 return -2; /* don't allow this to unset scalar variables */
1036 }
1037
1038 if (assoc_p (var))
1039 {
1040 akey = (flags & 1) ? sub : expand_assignment_string_to_string (sub, 0);
1041 if (akey == 0 || *akey == 0)
1042 {
1043 builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
1044 FREE (akey);
1045 return -1;
1046 }
1047 assoc_remove (assoc_cell (var), akey);
1048 if (akey != sub)
1049 free (akey);
1050 }
1051 else if (array_p (var))
1052 {
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)
1058 {
1059 builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
1060 return -1;
1061 }
1062 ae = array_remove (array_cell (var), ind);
1063 if (ae)
1064 array_dispose_element (ae);
1065 }
1066 else /* array_p (var) == 0 && assoc_p (var) == 0 */
1067 {
1068 akey = this_command_name;
1069 ind = array_expand_index (var, sub, len+1, 0);
1070 this_command_name = akey;
1071 if (ind == 0)
1072 {
1073 unbind_variable (var->name);
1074 return (0);
1075 }
1076 else
1077 return -2; /* any subscript other than 0 is invalid with scalar variables */
1078 }
1079
1080 return 0;
1081 }
1082
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;
1089 {
1090 char *vstr;
1091
1092 vstr = array_to_assign (array_cell (var), quoted);
1093
1094 if (vstr == 0)
1095 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
1096 else
1097 {
1098 printf ("%s=%s\n", var->name, vstr);
1099 free (vstr);
1100 }
1101 }
1102
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;
1109 {
1110 char *vstr;
1111
1112 vstr = assoc_to_assign (assoc_cell (var), quoted);
1113
1114 if (vstr == 0)
1115 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
1116 else
1117 {
1118 printf ("%s=%s\n", var->name, vstr);
1119 free (vstr);
1120 }
1121 }
1122
1123 /***********************************************************************/
1124 /* */
1125 /* Utility functions to manage arrays and their contents for expansion */
1126 /* */
1127 /***********************************************************************/
1128
1129 /* Return 1 if NAME is a properly-formed array reference v[sub]. */
1130
1131 /* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
1132 int
1133 valid_array_reference (name, flags)
1134 const char *name;
1135 int flags;
1136 {
1137 char *t;
1138 int r, len, isassoc;
1139 SHELL_VAR *entry;
1140
1141 t = mbschr (name, '['); /* ] */
1142 isassoc = 0;
1143 if (t)
1144 {
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;
1152
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 */
1160
1161 if (t[len] != ']' || len == 1 || t[len+1] != '\0')
1162 return 0;
1163
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
1175 }
1176 return 0;
1177 }
1178
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;
1186 {
1187 char *exp, *t, *savecmd;
1188 int expok;
1189 arrayind_t val;
1190
1191 exp = (char *)xmalloc (len);
1192 strncpy (exp, s, len - 1);
1193 exp[len - 1] = '\0';
1194 #if 0 /* TAG: maybe bash-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)
1209 {
1210 set_exit_status (EXECUTION_FAILURE);
1211
1212 if (no_longjmp_on_fatal_error)
1213 return 0;
1214 top_level_cleanup ();
1215 jump_to_top_level (DISCARD);
1216 }
1217 return val;
1218 }
1219
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;
1230 {
1231 char *t, *ret;
1232 int ind, ni;
1233
1234 t = mbschr (s, '[');
1235 if (t == 0)
1236 {
1237 if (subp)
1238 *subp = t;
1239 if (lenp)
1240 *lenp = 0;
1241 return ((char *)NULL);
1242 }
1243 ind = t - s;
1244 ni = skipsubscript (s, ind, flags); /* XXX - was 0 not flags */
1245 if (ni <= ind + 1 || s[ni] != ']')
1246 {
1247 err_badarraysub (s);
1248 if (subp)
1249 *subp = t;
1250 if (lenp)
1251 *lenp = 0;
1252 return ((char *)NULL);
1253 }
1254
1255 *t = '\0';
1256 ret = savestring (s);
1257 *t++ = '['; /* ] */
1258
1259 if (subp)
1260 *subp = t;
1261 if (lenp)
1262 *lenp = ni - ind;
1263
1264 return ret;
1265 }
1266
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;
1276 {
1277 char *t;
1278 SHELL_VAR *var;
1279
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? */
1284
1285 free (t);
1286 return var; /* now return invisible variables; caller must handle */
1287 }
1288
1289 #define INDEX_ERROR() \
1290 do \
1291 { \
1292 if (var) \
1293 err_badarraysub (var->name); \
1294 else \
1295 { \
1296 t[-1] = '\0'; \
1297 err_badarraysub (s); \
1298 t[-1] = '['; /* ] */\
1299 } \
1300 return ((char *)NULL); \
1301 } \
1302 while (0)
1303
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;
1314 {
1315 int len;
1316 arrayind_t ind;
1317 char *akey;
1318 char *retval, *t, *temp;
1319 WORD_LIST *l;
1320 SHELL_VAR *var;
1321
1322 var = array_variable_part (s, (flags&AV_NOEXPAND) ? 1 : 0, &t, &len); /* XXX */
1323
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
1330
1331 if (len == 0)
1332 return ((char *)NULL); /* error message already printed */
1333
1334 /* [ */
1335 akey = 0;
1336 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
1337 {
1338 if (rtype)
1339 *rtype = (t[0] == '*') ? 1 : 2;
1340 if ((flags & AV_ALLOWALL) == 0)
1341 {
1342 err_badarraysub (s);
1343 return ((char *)NULL);
1344 }
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))
1352 {
1353 l = assoc_to_word_list (assoc_cell (var));
1354 if (l == (WORD_LIST *)NULL)
1355 return ((char *)NULL);
1356 }
1357 else
1358 {
1359 l = array_to_word_list (array_cell (var));
1360 if (l == (WORD_LIST *)NULL)
1361 return ((char *) NULL);
1362 }
1363
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)))
1367 {
1368 temp = string_list_dollar_star (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
1369 retval = quote_string (temp);
1370 free (temp);
1371 }
1372 else /* ${name[@]} or unquoted ${name[*]} */
1373 retval = string_list_dollar_at (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
1374
1375 dispose_words (l);
1376 }
1377 else
1378 {
1379 if (rtype)
1380 *rtype = 0;
1381 if (var == 0 || array_p (var) || assoc_p (var) == 0)
1382 {
1383 if ((flags & AV_USEIND) == 0 || indp == 0)
1384 {
1385 ind = array_expand_index (var, t, len, flags);
1386 if (ind < 0)
1387 {
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();
1393 }
1394 if (indp)
1395 *indp = ind;
1396 }
1397 else if (indp)
1398 ind = *indp;
1399 }
1400 else if (assoc_p (var))
1401 {
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)
1409 {
1410 FREE (akey);
1411 INDEX_ERROR();
1412 }
1413 }
1414
1415 if (var == 0 || value_cell (var) == 0) /* XXX - check invisible_p(var) ? */
1416 {
1417 FREE (akey);
1418 return ((char *)NULL);
1419 }
1420 else if (invisible_p (var))
1421 {
1422 FREE (akey);
1423 return ((char *)NULL);
1424 }
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))
1428 {
1429 retval = assoc_reference (assoc_cell (var), akey);
1430 free (akey);
1431 }
1432 else
1433 retval = array_reference (array_cell (var), ind);
1434 }
1435
1436 return retval;
1437 }
1438
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;
1446 {
1447 return (array_value_internal (s, quoted, flags|AV_ALLOWALL, rtype, indp));
1448 }
1449
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;
1459 {
1460 return (array_value_internal (s, 0, flags, rtype, indp));
1461 }
1462
1463 char *
1464 array_keys (s, quoted, pflags)
1465 char *s;
1466 int quoted, pflags;
1467 {
1468 int len;
1469 char *retval, *t, *temp;
1470 WORD_LIST *l;
1471 SHELL_VAR *var;
1472
1473 var = array_variable_part (s, 0, &t, &len);
1474
1475 /* [ */
1476 if (var == 0 || ALL_ELEMENT_SUB (t[0]) == 0 || t[1] != ']')
1477 return (char *)NULL;
1478
1479 if (var_isset (var) == 0 || invisible_p (var))
1480 return (char *)NULL;
1481
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);
1490
1491 retval = string_list_pos_params (t[0], l, quoted, pflags);
1492
1493 dispose_words (l);
1494 return retval;
1495 }
1496 #endif /* ARRAY_VARS */