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