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