static char *
parameter_brace_substring (varname, value, ind, substr, quoted, flags)
     char *varname, *value;
     int ind;
     char *substr;
     int quoted, flags;
{
  intmax_t e1, e2;
  int vtype, r, starsub;
  char *temp, *val, *tt, *oname;
  SHELL_VAR *v;

  if (value == 0 && ((varname[0] != '@' && varname[0] != '*') || varname[1]))
    return ((char *)NULL);

  oname = this_command_name;
  this_command_name = varname;

  vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
  if (vtype == -1)
    {
      this_command_name = oname;
      return ((char *)NULL);
    }

  starsub = vtype & VT_STARSUB;
  vtype &= ~VT_STARSUB;

  r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
  this_command_name = oname;
  if (r <= 0)
    {
      if (vtype == VT_VARIABLE)
	FREE (val);
      return ((r == 0) ? &expand_param_error : (char *)NULL);
    }

  switch (vtype)
    {
    case VT_VARIABLE:
    case VT_ARRAYMEMBER:
#if defined (HANDLE_MULTIBYTE)
      if (MB_CUR_MAX > 1)
	tt = mb_substring (val, e1, e2);
      else
#endif
      tt = substring (val, e1, e2);

      if (vtype == VT_VARIABLE)
	FREE (val);
      if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
	temp = quote_string (tt);
      else
	temp = tt ? quote_escapes (tt) : (char *)NULL;
      FREE (tt);
      break;
    case VT_POSPARMS:
      tt = pos_params (varname, e1, e2, quoted);
      if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
	{
	  temp = tt ? quote_escapes (tt) : (char *)NULL;
	  FREE (tt);
	}
      else
	temp = tt;
      break;
#if defined (ARRAY_VARS)
    case VT_ARRAYVAR:
      if (assoc_p (v))
	/* we convert to list and take first e2 elements starting at e1th
	   element -- officially undefined for now */	
	temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
      else
      /* We want E2 to be the number of elements desired (arrays can be sparse,
	 so verify_substring_values just returns the numbers specified and we
	 rely on array_subrange to understand how to deal with them). */
	temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
      /* array_subrange now calls array_quote_escapes as appropriate, so the
	 caller no longer needs to. */
      break;
#endif
    default:
      temp = (char *)NULL;
    }

  return temp;
static char *
parameter_brace_substring (varname, value, ind, substr, quoted, flags)
     char *varname, *value;
     int ind;
     char *substr;
     int quoted, flags;
{
  intmax_t e1, e2;
  int vtype, r, starsub;
  char *temp, *val, *tt, *oname;
  SHELL_VAR *v;

  if (value == 0 && ((varname[0] != '@' && varname[0] != '*') || varname[1]))
    return ((char *)NULL);

  oname = this_command_name;
  this_command_name = varname;

  vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
  if (vtype == -1)
    {
      this_command_name = oname;
      return ((char *)NULL);
    }

  starsub = vtype & VT_STARSUB;
  vtype &= ~VT_STARSUB;

  r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
  this_command_name = oname;
  if (r <= 0)
    {
      if (vtype == VT_VARIABLE)
	FREE (val);
      return ((r == 0) ? &expand_param_error : (char *)NULL);
    }

  switch (vtype)
    {
    case VT_VARIABLE:
    case VT_ARRAYMEMBER:
#if defined (HANDLE_MULTIBYTE)
      if (MB_CUR_MAX > 1)
	tt = mb_substring (val, e1, e2);
      else
#endif
      tt = substring (val, e1, e2);

      if (vtype == VT_VARIABLE)
	FREE (val);
      if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
	temp = quote_string (tt);
      else
	temp = tt ? quote_escapes (tt) : (char *)NULL;
      FREE (tt);
      break;
    case VT_POSPARMS:
      tt = pos_params (varname, e1, e2, quoted);
      if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
	{
	  temp = tt ? quote_escapes (tt) : (char *)NULL;
	  FREE (tt);
	}
      else
	temp = tt;
      break;
#if defined (ARRAY_VARS)
    case VT_ARRAYVAR:
      if (assoc_p (v))
	 	
	temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
      else
       
	temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
       
      break;
#endif
    default:
      temp = (char *)NULL;
    }

  return temp;