+static char *
+string_var_assignment (v, s)
+ SHELL_VAR *v;
+ char *s;
+{
+ char flags[MAX_ATTRIBUTES], *ret, *val;
+ int i;
+
+ val = sh_quote_reusable (s, 0);
+ i = var_attribute_string (v, 0, flags);
+ ret = (char *)xmalloc (i + strlen (val) + strlen (v->name) + 16 + MAX_ATTRIBUTES);
+ if (i > 0)
+ sprintf (ret, "declare -%s %s=%s", flags, v->name, val);
+ else
+ sprintf (ret, "%s=%s", v->name, val);
+ free (val);
+ return ret;
+}
+
+#if defined (ARRAY_VARS)
+static char *
+array_var_assignment (v, itype, quoted)
+ SHELL_VAR *v;
+ int itype, quoted;
+{
+ char *ret, *val, flags[MAX_ATTRIBUTES];
+ int i;
+
+ if (v == 0)
+ return (char *)NULL;
+ val = array_p (v) ? array_to_assign (array_cell (v), 0)
+ : assoc_to_assign (assoc_cell (v), 0);
+ if (val == 0)
+ {
+ val = (char *)xmalloc (3);
+ val[0] = '(';
+ val[1] = ')';
+ val[2] = 0;
+ }
+ else
+ {
+ ret = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) ? quote_string (val) : quote_escapes (val);
+ free (val);
+ val = ret;
+ }
+ i = var_attribute_string (v, 0, flags);
+ ret = (char *)xmalloc (i + strlen (val) + strlen (v->name) + 16);
+ sprintf (ret, "declare -%s %s=%s", flags, v->name, val);
+ free (val);
+ return ret;
+}
+#endif
+
+static char *
+pos_params_assignment (list, itype, quoted)
+ WORD_LIST *list;
+ int itype;
+ int quoted;
+{
+ char *temp, *ret;
+
+ /* first, we transform the list to quote each word. */
+ temp = list_transform ('Q', (SHELL_VAR *)0, list, itype, quoted);
+ ret = (char *)xmalloc (strlen (temp) + 8);
+ strcpy (ret, "set -- ");
+ strcpy (ret + 7, temp);
+ free (temp);
+ return ret;
+}
+
+static char *
+string_transform (xc, v, s)
+ int xc;
+ SHELL_VAR *v;
+ char *s;
+{
+ char *ret, flags[MAX_ATTRIBUTES];
+ int i;
+
+ if (((xc == 'A' || xc == 'a') && v == 0) || (xc != 'a' && s == 0))
+ return (char *)NULL;
+
+ switch (xc)
+ {
+ /* Transformations that interrogate the variable */
+ case 'a':
+ i = var_attribute_string (v, 0, flags);
+ ret = (i > 0) ? savestring (flags) : (char *)NULL;
+ break;
+ case 'A':
+ ret = string_var_assignment (v, s);
+ break;
+ /* Transformations that modify the variable's value */
+ case 'E':
+ ret = ansiexpand (s, 0, strlen (s), (int *)0);
+ break;
+ case 'P':
+ ret = decode_prompt_string (s);
+ break;
+ case 'Q':
+ ret = sh_quote_reusable (s, 0);
+ break;
+ default:
+ ret = (char *)NULL;
+ break;
+ }
+ return ret;
+}
+
+static char *
+list_transform (xc, v, list, itype, quoted)
+ int xc;
+ SHELL_VAR *v;
+ WORD_LIST *list;
+ int itype, quoted;
+{
+ WORD_LIST *new, *l;
+ WORD_DESC *w;
+ char *tword;
+
+ for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
+ {
+ tword = string_transform (xc, v, l->word->word);
+ w = alloc_word_desc ();
+ w->word = tword ? tword : savestring (""); /* XXX */
+ new = make_word_list (w, new);
+ }
+
+ l = REVERSE_LIST (new, WORD_LIST *);
+ tword = string_list_pos_params (itype, l, quoted);
+ dispose_words (l);
+
+ return (tword);
+}
+
+static char *
+parameter_list_transform (xc, itype, quoted)
+ int xc;
+ int itype;
+ int quoted;
+{
+ char *ret;
+ WORD_LIST *list;
+
+ list = list_rest_of_args ();
+ if (list == 0)
+ return ((char *)NULL);
+ if (xc == 'A')
+ return (pos_params_assignment (list, itype, quoted));
+ ret = list_transform (xc, (SHELL_VAR *)0, list, itype, quoted);
+ dispose_words (list);
+ return (ret);
+}
+
+#if defined (ARRAY_VARS)
+static char *
+array_transform (xc, var, varname, quoted)
+ int xc;
+ SHELL_VAR *var;
+ char *varname; /* so we can figure out how it's indexed */
+ int quoted;
+{
+ ARRAY *a;
+ HASH_TABLE *h;
+ int itype;
+ char *ret;
+ WORD_LIST *list;
+ SHELL_VAR *v;
+
+ /* compute itype from varname here */
+ v = array_variable_part (varname, &ret, 0);
+
+ /* XXX */
+ if (v && invisible_p (v))
+ return ((char *)NULL);
+
+ itype = ret[0];
+
+ if (xc == 'A')
+ return (array_var_assignment (v, itype, quoted));
+
+ a = (v && array_p (v)) ? array_cell (v) : 0;
+ h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
+
+ list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
+ if (list == 0)
+ return ((char *)NULL);
+ ret = list_transform (xc, v, list, itype, quoted);
+ dispose_words (list);
+
+ return ret;
+}
+#endif /* ARRAY_VARS */
+
+static char *
+parameter_brace_transform (varname, value, ind, xform, rtype, quoted, flags)
+ char *varname, *value;
+ int ind;
+ char *xform;
+ int rtype, quoted, flags;
+{
+ int vtype, xc;
+ char *temp1, *val;
+ SHELL_VAR *v;
+
+ xc = xform[0];
+ if (value == 0 && xc != 'A' && xc != 'a')
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ /* check for valid values of xc */
+ switch (xc)
+ {
+ case 'a': /* expand to a string with just attributes */
+ case 'A': /* expand as an assignment statement with attributes */
+ case 'E': /* expand like $'...' */
+ case 'P': /* expand like prompt string */
+ case 'Q': /* quote reusably */
+ break;
+ default:
+ return &expand_param_error;
+ }
+
+ temp1 = (char *)NULL; /* shut up gcc */
+ switch (vtype & ~VT_STARSUB)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ temp1 = string_transform (xc, v, val);
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (temp1)
+ {
+ val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ ? quote_string (temp1)
+ : quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ temp1 = array_transform (xc, v, varname, quoted);
+ if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+#endif
+ case VT_POSPARMS:
+ temp1 = parameter_list_transform (xc, varname[0], quoted);
+ if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+ }
+
+ return temp1;
+}
+