⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arrayfunc.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 2 页
字号:
/* arrayfunc.c -- High-level array functions used by other parts of the shell. *//* Copyright (C) 2001-2010 Free Software Foundation, Inc.   This file is part of GNU Bash, the Bourne Again SHell.   Bash is free software: you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation, either version 3 of the License, or   (at your option) any later version.   Bash is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with Bash.  If not, see <http://www.gnu.org/licenses/>.*/#include "config.h"#if defined (ARRAY_VARS)#if defined (HAVE_UNISTD_H)#  include <unistd.h>#endif#include <stdio.h>#include "bashintl.h"#include "shell.h"#include "pathexp.h"#include "shmbutil.h"#include "builtins/common.h"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 *, char *, int));static char *quote_assign __P((const char *));static void quote_array_assignment_chars __P((WORD_LIST *));static char *array_value_internal __P((char *, int, int, int *, arrayind_t *));/* Standard error message to use when encountering an invalid array subscript */const char * const bash_badsub_errmsg = N_("bad array subscript");/* **************************************************************** *//*								    *//*  Functions to manipulate array variables and perform assignments *//*								    *//* **************************************************************** *//* Convert a shell variable to an array variable.  The original value is   saved as array[0]. */SHELL_VAR *convert_var_to_array (var)     SHELL_VAR *var;{  char *oldval;  ARRAY *array;  oldval = value_cell (var);  array = array_create ();  if (oldval)    array_insert (array, 0, oldval);  FREE (value_cell (var));  var_setarray (var, array);  /* these aren't valid anymore */  var->dynamic_value = (sh_var_value_func_t *)NULL;  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;}/* Convert a shell variable to an array variable.  The original value is   saved as array[0]. */SHELL_VAR *convert_var_to_assoc (var)     SHELL_VAR *var;{  char *oldval;  HASH_TABLE *hash;  oldval = value_cell (var);  hash = assoc_create (0);  if (oldval)    assoc_insert (hash, savestring ("0"), oldval);  FREE (value_cell (var));  var_setassoc (var, hash);  /* these aren't valid anymore */  var->dynamic_value = (sh_var_value_func_t *)NULL;  var->assign_func = (sh_var_assign_func_t *)NULL;  INVALIDATE_EXPORTSTR (var);  if (exported_p (var))    array_needs_making++;  VSETATTR (var, att_assoc);  VUNSETATTR (var, att_invisible);  return var;}static SHELL_VAR *bind_array_var_internal (entry, ind, key, value, flags)     SHELL_VAR *entry;     arrayind_t ind;     char *key;     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);      if (assoc_p (entry))	newval = assoc_reference (assoc_cell (entry), key);      else	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_assoc|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, key);  else if (assoc_p (entry))    assoc_insert (assoc_cell (entry), key, newval);  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   existing value as name[0].   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, flags)     char *name;     arrayind_t ind;     char *value;     int flags;{  SHELL_VAR *entry;  entry = var_lookup (name, shell_variables);  if (entry == (SHELL_VAR *) 0)    entry = make_new_array_variable (name);  else if (readonly_p (entry) || noassign_p (entry))    {      if (readonly_p (entry))	err_readonly (name);      return (entry);    }  else if (array_p (entry) == 0)    entry = convert_var_to_array (entry);  /* ENTRY is an array variable, and ARRAY points to the value. */  return (bind_array_var_internal (entry, ind, 0, value, flags));}SHELL_VAR *bind_array_element (entry, ind, value, flags)     SHELL_VAR *entry;     arrayind_t ind;     char *value;     int flags;{  return (bind_array_var_internal (entry, ind, 0, value, flags));}                    SHELL_VAR *bind_assoc_variable (entry, name, key, value, flags)     SHELL_VAR *entry;     char *name;     char *key;     char *value;     int flags;{  SHELL_VAR *dentry;  char *newval;  if (readonly_p (entry) || noassign_p (entry))    {      if (readonly_p (entry))	err_readonly (name);      return (entry);    }  return (bind_array_var_internal (entry, 0, key, 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, flags)     char *name, *value;     int flags;{  char *sub, *vname, *akey;  arrayind_t ind;  int sublen;  SHELL_VAR *entry;  vname = array_variable_name (name, &sub, &sublen);  if (vname == 0)    return ((SHELL_VAR *)NULL);  if ((ALL_ELEMENT_SUB (sub[0]) && sub[1] == ']') || (sublen <= 1))    {      free (vname);      err_badarraysub (name);      return ((SHELL_VAR *)NULL);    }  entry = find_variable (vname);  if (entry && assoc_p (entry))    {      sub[sublen-1] = '\0';      akey = expand_assignment_string_to_string (sub, 0);	/* [ */      sub[sublen-1] = ']';      if (akey == 0 || *akey == 0)	{	  free (vname);	  err_badarraysub (name);	  return ((SHELL_VAR *)NULL);	}      entry = bind_assoc_variable (entry, vname, akey, value, flags);    }  else    {      ind = array_expand_index (sub, sublen);      if (ind < 0)	{	  free (vname);	  err_badarraysub (name);	  return ((SHELL_VAR *)NULL);	}      entry = bind_array_variable (vname, ind, value, flags);    }  free (vname);  return (entry);}/* Find the array variable corresponding to NAME.  If there is no variable,   create a new array variable.  If the variable exists but is not an array,   convert it to an indexed array.  If FLAGS&1 is non-zero, an existing   variable is checked for the readonly or noassign attribute in preparation   for assignment (e.g., by the `read' builtin).  If FLAGS&2 is non-zero, we   create an associative array. */SHELL_VAR *find_or_make_array_variable (name, flags)     char *name;     int flags;{  SHELL_VAR *var;  var = find_variable (name);  if (var == 0)    var = (flags & 2) ? make_new_assoc_variable (name) : make_new_array_variable (name);  else if ((flags & 1) && (readonly_p (var) || noassign_p (var)))    {      if (readonly_p (var))	err_readonly (name);      return ((SHELL_VAR *)NULL);    }  else if ((flags & 2) && array_p (var))    {      report_error (_("%s: cannot convert indexed to associative array"), name);      return ((SHELL_VAR *)NULL);    }  else if (array_p (var) == 0 && assoc_p (var) == 0)    var = convert_var_to_array (var);  return (var);}  /* 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, flags)     char *name, *value;     int flags;{  SHELL_VAR *var;  int vflags;  vflags = 1;  if (flags & ASS_MKASSOC)    vflags |= 2;  var = find_or_make_array_variable (name, vflags);  if (var == 0)    return ((SHELL_VAR *)NULL);  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, flags)     SHELL_VAR *var;     WORD_LIST *list;     int flags;{  register arrayind_t i;  register WORD_LIST *l;  ARRAY *a;  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, 0);    else      array_insert (a, i, l->word->word);  return var;}WORD_LIST *expand_compound_array_assignment (var, value, flags)     SHELL_VAR *var;     char *value;     int flags;{  WORD_LIST *list, *nlist;  char *val;  int ni;  /* I don't believe this condition is ever true any more. */  if (*value == '(')	/*)*/    {      ni = 1;      val = extract_array_assignment_list (value, &ni);      if (val == 0)	return (WORD_LIST *)NULL;    }  else    val = value;  /* Expand the value string into a list of words, performing all the     shell expansions including pathname generation and word splitting. */  /* First we split the string on whitespace, using the shell parser     (ksh93 seems to do this). */  list = parse_string_to_word_list (val, 1, "array assign");  /* If we're using [subscript]=value, we need to quote each [ and ] to     prevent unwanted filename expansion. */  if (list)    quote_array_assignment_chars (list);  /* Now that we've split it, perform the shell expansions on each     word in the list. */  nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;  dispose_words (list);  if (val != value)    free (val);  return nlist;}/* Callers ensure that VAR is not NULL */voidassign_compound_array_list (var, nlist, flags)     SHELL_VAR *var;     WORD_LIST *nlist;     int flags;{  ARRAY *a;  HASH_TABLE *h;  WORD_LIST *list;  char *w, *val, *nval;  int len, iflags;  arrayind_t ind, last_ind;  char *akey;  a = (var && array_p (var)) ? array_cell (var) : (ARRAY *)0;  h = (var && assoc_p (var)) ? assoc_cell (var) : (HASH_TABLE *)0;  akey = (char *)0;  ind = 0;  /* Now that we are ready to assign values to the array, kill the existing     value. */  if ((flags & ASS_APPEND) == 0)    {      if (a && array_p (var))	array_flush (a);      else if (h && assoc_p (var))	assoc_flush (h);    }  last_ind = (a && (flags & ASS_APPEND)) ? array_max_index (a) + 1 : 0;  for (list = nlist; list; list = list->next)    {      iflags = flags;      w = list->word->word;      /* We have a word of the form [ind]=value */      if ((list->word->flags & W_ASSIGNMENT) && w[0] == '[')	{	  len = skipsubscript (w, 0, (var && assoc_p (var) != 0));	  /* XXX - changes for `+=' */ 	  if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))	    {	      if (assoc_p (var))		{		  err_badarraysub (w);		  continue;		}	      nval = make_variable_value (var, w, flags);	      if (var->assign_func)		(*var->assign_func) (var, nval, last_ind, 0);	      else		array_insert (a, last_ind, nval);	      FREE (nval);	      last_ind++;	      continue;	    }	  if (len == 1)	    {	      err_badarraysub (w);	      continue;	    }	  if (ALL_ELEMENT_SUB (w[1]) && len == 2)	    {	      if (assoc_p (var))		report_error (_("%s: invalid associative array key"), w);	      else		report_error (_("%s: cannot assign to non-numeric index"), w);	      continue;	    }	  if (array_p (var))	    {	      ind = array_expand_index (w + 1, len);	      if (ind < 0)		{		  err_badarraysub (w);		  continue;		}	      last_ind = ind;	    }	  else if (assoc_p (var))	    {	      akey = substring (w, 1, len);	      if (akey == 0 || *akey == 0)		{		  err_badarraysub (w);		  continue;		}	    }	  /* XXX - changes for `+=' -- just accept the syntax.  ksh93 doesn't do this */	  if (w[len + 1] == '+' && w[len + 2] == '=')	    {	      iflags |= ASS_APPEND;	      val = w + len + 3;	    }	  else	    val = w + len + 2;	}      else if (assoc_p (var))	{	  report_error (_("%s: %s: must use subscript when assigning associative array"), var->name, w);	  continue;	}      else		/* No [ind]=value, just a stray `=' */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -