/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
-/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2005 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
extern char *this_command_name;
extern int last_command_exit_value;
+extern int array_needs_making;
+
+static SHELL_VAR *bind_array_var_internal __P((SHELL_VAR *, arrayind_t, char *, int));
static void quote_array_assignment_chars __P((WORD_LIST *));
static char *array_value_internal __P((char *, int, int, int *));
var->assign_func = (sh_var_assign_func_t *)NULL;
INVALIDATE_EXPORTSTR (var);
+ if (exported_p (var))
+ array_needs_making++;
VSETATTR (var, att_array);
VUNSETATTR (var, att_invisible);
return var;
}
+static SHELL_VAR *
+bind_array_var_internal (entry, ind, value, flags)
+ SHELL_VAR *entry;
+ arrayind_t ind;
+ char *value;
+ int flags;
+{
+ SHELL_VAR *dentry;
+ char *newval;
+
+ /* If we're appending, we need the old value of the array reference, so
+ fake out make_variable_value with a dummy SHELL_VAR */
+ if (flags & ASS_APPEND)
+ {
+ dentry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+ dentry->name = savestring (entry->name);
+ newval = array_reference (array_cell (entry), ind);
+ if (newval)
+ dentry->value = savestring (newval);
+ else
+ {
+ dentry->value = (char *)xmalloc (1);
+ dentry->value[0] = '\0';
+ }
+ dentry->exportstr = 0;
+ dentry->attributes = entry->attributes & ~(att_array|att_exported);
+ /* Leave the rest of the members uninitialized; the code doesn't look
+ at them. */
+ newval = make_variable_value (dentry, value, flags);
+ dispose_variable (dentry);
+ }
+ else
+ newval = make_variable_value (entry, value, flags);
+
+ if (entry->assign_func)
+ (*entry->assign_func) (entry, newval, ind);
+ else
+ array_insert (array_cell (entry), ind, newval);
+ FREE (newval);
+
+ return (entry);
+}
+
/* Perform an array assignment name[ind]=value. If NAME already exists and
is not an array, and IND is 0, perform name=value instead. If NAME exists
and is not an array, and IND is not 0, convert it into an array with the
If NAME does not exist, just create an array variable, no matter what
IND's value may be. */
SHELL_VAR *
-bind_array_variable (name, ind, value)
+bind_array_variable (name, ind, value, flags)
char *name;
arrayind_t ind;
char *value;
+ int flags;
{
SHELL_VAR *entry;
- char *newval;
entry = var_lookup (name, shell_variables);
entry = convert_var_to_array (entry);
/* ENTRY is an array variable, and ARRAY points to the value. */
- newval = make_variable_value (entry, value);
- if (entry->assign_func)
- (*entry->assign_func) (entry, newval, ind);
- else
- array_insert (array_cell (entry), ind, newval);
- FREE (newval);
-
- return (entry);
+ return (bind_array_var_internal (entry, ind, value, flags));
}
/* Parse NAME, a lhs of an assignment statement of the form v[s], and
assign VALUE to that array element by calling bind_array_variable(). */
SHELL_VAR *
-assign_array_element (name, value)
+assign_array_element (name, value, flags)
char *name, *value;
+ int flags;
{
char *sub, *vname;
arrayind_t ind;
return ((SHELL_VAR *)NULL);
}
- entry = bind_array_variable (vname, ind, value);
+ entry = bind_array_variable (vname, ind, value, flags);
free (vname);
return (entry);
/* Perform a compound assignment statement for array NAME, where VALUE is
the text between the parens: NAME=( VALUE ) */
SHELL_VAR *
-assign_array_from_string (name, value)
+assign_array_from_string (name, value, flags)
char *name, *value;
+ int flags;
{
SHELL_VAR *var;
if (var == 0)
return ((SHELL_VAR *)NULL);
- return (assign_array_var_from_string (var, value));
+ return (assign_array_var_from_string (var, value, flags));
}
/* Sequentially assign the indices of indexed array variable VAR from the
words in LIST. */
SHELL_VAR *
-assign_array_var_from_word_list (var, list)
+assign_array_var_from_word_list (var, list, flags)
SHELL_VAR *var;
WORD_LIST *list;
+ int flags;
{
register arrayind_t i;
register WORD_LIST *l;
ARRAY *a;
- for (a = array_cell (var), l = list, i = 0; l; l = l->next, i++)
+ a = array_cell (var);
+ i = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
+
+ for (l = list; l; l = l->next, i++)
if (var->assign_func)
(*var->assign_func) (var, l->word->word, i);
else
/* Perform a compound array assignment: VAR->name=( VALUE ). The
VALUE has already had the parentheses stripped. */
SHELL_VAR *
-assign_array_var_from_string (var, value)
+assign_array_var_from_string (var, value, flags)
SHELL_VAR *var;
char *value;
+ int flags;
{
ARRAY *a;
WORD_LIST *list, *nlist;
/* Now that we are ready to assign values to the array, kill the existing
value. */
- if (a)
+ if (a && (flags & ASS_APPEND) == 0)
array_flush (a);
+ last_ind = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
- for (last_ind = 0, list = nlist; list; list = list->next)
+ for (list = nlist; list; list = list->next)
{
w = list->word->word;
{
len = skipsubscript (w, 0);
+#if 1
+ /* XXX - changes for `+=' */
+ if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
+#else
if (w[len] != ']' || w[len+1] != '=')
+#endif
{
- nval = make_variable_value (var, w);
+ nval = make_variable_value (var, w, flags);
if (var->assign_func)
(*var->assign_func) (var, nval, last_ind);
else
continue;
}
last_ind = ind;
- val = w + len + 2;
+ /* XXX - changes for `+=' */
+ if (w[len + 1] == '+' && w[len + 2] == '=')
+ {
+ flags |= ASS_APPEND;
+ val = w + len + 3;
+ }
+ else
+ val = w + len + 2;
}
else /* No [ind]=value, just a stray `=' */
{
if (integer_p (var))
this_command_name = (char *)NULL; /* no command name for errors */
- nval = make_variable_value (var, val);
- if (var->assign_func)
- (*var->assign_func) (var, nval, ind);
- else
- array_insert (a, ind, nval);
- FREE (nval);
+ bind_array_var_internal (var, ind, val, flags);
last_ind++;
}
exp = (char *)xmalloc (len);
strncpy (exp, s, len - 1);
exp[len - 1] = '\0';
+#if 0
t = expand_string_to_string (exp, 0);
+#else
+ t = expand_string_to_string (exp, Q_DOUBLE_QUOTES);
+#endif
this_command_name = (char *)NULL;
val = evalexp (t, &expok);
free (t);
err_badarraysub (s);
return ((char *)NULL);
}
- else if (var == 0)
+ else if (var == 0 || value_cell (var) == 0)
return ((char *)NULL);
else if (array_p (var) == 0)
l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);