📄 arrayfunc.c
字号:
{ ind = last_ind; val = w; } if (integer_p (var)) this_command_name = (char *)NULL; /* no command name for errors */ bind_array_var_internal (var, ind, akey, val, iflags); last_ind++; }}/* 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, flags) SHELL_VAR *var; char *value; int flags;{ WORD_LIST *nlist; if (value == 0) return var; nlist = expand_compound_array_assignment (var, value, flags); assign_compound_array_list (var, nlist, flags); if (nlist) dispose_words (nlist); return (var);}/* Quote globbing chars and characters in $IFS before the `=' in an assignment statement (usually a compound array assignment) to protect them from unwanted filename expansion or word splitting. */static char *quote_assign (string) const char *string;{ size_t slen; int saw_eq; char *temp, *t, *subs; const char *s, *send; int ss, se; DECLARE_MBSTATE; slen = strlen (string); send = string + slen; t = temp = (char *)xmalloc (slen * 2 + 1); saw_eq = 0; for (s = string; *s; ) { if (*s == '=') saw_eq = 1; if (saw_eq == 0 && *s == '[') /* looks like a subscript */ { ss = s - string; se = skipsubscript (string, ss, 0); subs = substring (s, ss, se); *t++ = '\\'; strcpy (t, subs); t += se - ss; *t++ = '\\'; *t++ = ']'; s += se + 1; free (subs); continue; } if (saw_eq == 0 && (glob_char_p (s) || isifs (*s))) *t++ = '\\'; COPY_CHAR_P (t, s, send); } *t = '\0'; return temp;}/* For each word in a compound array assignment, if the word looks like [ind]=value, quote globbing chars and characters in $IFS before the `='. */static voidquote_array_assignment_chars (list) WORD_LIST *list;{ char *nword; WORD_LIST *l; for (l = list; l; l = l->next) { if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0') continue; /* should not happen, but just in case... */ /* Don't bother if it doesn't look like [ind]=value */ if (l->word->word[0] != '[' || mbschr (l->word->word, '=') == 0) /* ] */ continue; nword = quote_assign (l->word->word); free (l->word->word); l->word->word = nword; }}/* skipsubscript moved to subst.c to use private functions. 2009/02/24. *//* This function is called with SUB pointing to just after the beginning `[' of an array subscript and removes the array element to which SUB expands from array VAR. A subscript of `*' or `@' unsets the array. */intunbind_array_element (var, sub) SHELL_VAR *var; char *sub;{ int len; arrayind_t ind; char *akey; ARRAY_ELEMENT *ae; len = skipsubscript (sub, 0, 0); if (sub[len] != ']' || len == 0) { builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg)); return -1; } sub[len] = '\0'; if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0) { unbind_variable (var->name); return (0); } if (assoc_p (var)) { akey = expand_assignment_string_to_string (sub, 0); /* [ */ if (akey == 0 || *akey == 0) { builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg)); return -1; } assoc_remove (assoc_cell (var), akey); free (akey); } else { ind = array_expand_index (sub, len+1); if (ind < 0) { builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg)); return -1; } ae = array_remove (array_cell (var), ind); if (ae) array_dispose_element (ae); } return 0;}/* Format and output an array assignment in compound form VAR=(VALUES), suitable for re-use as input. */voidprint_array_assignment (var, quoted) SHELL_VAR *var; int quoted;{ char *vstr; vstr = array_to_assign (array_cell (var), quoted); if (vstr == 0) printf ("%s=%s\n", var->name, quoted ? "'()'" : "()"); else { printf ("%s=%s\n", var->name, vstr); free (vstr); }}/* Format and output an associative array assignment in compound form VAR=(VALUES), suitable for re-use as input. */voidprint_assoc_assignment (var, quoted) SHELL_VAR *var; int quoted;{ char *vstr; vstr = assoc_to_assign (assoc_cell (var), quoted); if (vstr == 0) printf ("%s=%s\n", var->name, quoted ? "'()'" : "()"); else { printf ("%s=%s\n", var->name, vstr); free (vstr); }}/***********************************************************************//* *//* Utility functions to manage arrays and their contents for expansion *//* *//***********************************************************************//* Return 1 if NAME is a properly-formed array reference v[sub]. */intvalid_array_reference (name) char *name;{ char *t; int r, len; t = mbschr (name, '['); /* ] */ if (t) { *t = '\0'; r = legal_identifier (name); *t = '['; if (r == 0) return 0; /* Check for a properly-terminated non-blank subscript. */ len = skipsubscript (t, 0, 0); if (t[len] != ']' || len == 1) return 0; for (r = 1; r < len; r++) if (whitespace (t[r]) == 0) return 1; return 0; } return 0;}/* Expand the array index beginning at S and extending LEN characters. */arrayind_tarray_expand_index (s, len) char *s; int len;{ char *exp, *t; int expok; arrayind_t val; exp = (char *)xmalloc (len); strncpy (exp, s, len - 1); exp[len - 1] = '\0'; t = expand_arith_string (exp, 0); this_command_name = (char *)NULL; val = evalexp (t, &expok); free (t); free (exp); if (expok == 0) { last_command_exit_value = EXECUTION_FAILURE; top_level_cleanup (); jump_to_top_level (DISCARD); } return val;}/* Return the name of the variable specified by S without any subscript. If SUBP is non-null, return a pointer to the start of the subscript in *SUBP. If LENP is non-null, the length of the subscript is returned in *LENP. This returns newly-allocated memory. */char *array_variable_name (s, subp, lenp) char *s, **subp; int *lenp;{ char *t, *ret; int ind, ni; t = mbschr (s, '['); if (t == 0) { if (subp) *subp = t; if (lenp) *lenp = 0; return ((char *)NULL); } ind = t - s; ni = skipsubscript (s, ind, 0); if (ni <= ind + 1 || s[ni] != ']') { err_badarraysub (s); if (subp) *subp = t; if (lenp) *lenp = 0; return ((char *)NULL); } *t = '\0'; ret = savestring (s); *t++ = '['; /* ] */ if (subp) *subp = t; if (lenp) *lenp = ni - ind; return ret;}/* Return the variable specified by S without any subscript. If SUBP is non-null, return a pointer to the start of the subscript in *SUBP. If LENP is non-null, the length of the subscript is returned in *LENP. */SHELL_VAR *array_variable_part (s, subp, lenp) char *s, **subp; int *lenp;{ char *t; SHELL_VAR *var; t = array_variable_name (s, subp, lenp); if (t == 0) return ((SHELL_VAR *)NULL); var = find_variable (t); free (t); return (var == 0 || invisible_p (var)) ? (SHELL_VAR *)0 : var;}#define INDEX_ERROR() \ do \ { \ if (var) \ err_badarraysub (var->name); \ else \ { \ t[-1] = '\0'; \ err_badarraysub (s); \ t[-1] = '['; /* ] */\ } \ return ((char *)NULL); \ } \ while (0)/* Return a string containing the elements in the array and subscript described by S. If the subscript is * or @, obeys quoting rules akin to the expansion of $* and $@ including double quoting. If RTYPE is non-null it gets 1 if the array reference is name[*], 2 if the reference is name[@], and 0 otherwise. */static char *array_value_internal (s, quoted, flags, rtype, indp) char *s; int quoted, flags, *rtype; arrayind_t *indp;{ int len; arrayind_t ind; char *akey; char *retval, *t, *temp; WORD_LIST *l; SHELL_VAR *var; var = array_variable_part (s, &t, &len); /* Expand the index, even if the variable doesn't exist, in case side effects are needed, like ${w[i++]} where w is unset. */#if 0 if (var == 0) return (char *)NULL;#endif if (len == 0) return ((char *)NULL); /* error message already printed */ /* [ */ if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']') { if (rtype) *rtype = (t[0] == '*') ? 1 : 2; if ((flags & AV_ALLOWALL) == 0) { err_badarraysub (s); return ((char *)NULL); } else if (var == 0 || value_cell (var) == 0) /* XXX - check for invisible_p(var) ? */ return ((char *)NULL); else if (array_p (var) == 0 && assoc_p (var) == 0) l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL); else if (assoc_p (var)) { l = assoc_to_word_list (assoc_cell (var)); if (l == (WORD_LIST *)NULL) return ((char *)NULL); } else { l = array_to_word_list (array_cell (var)); if (l == (WORD_LIST *)NULL) return ((char *) NULL); } if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) { temp = string_list_dollar_star (l); retval = quote_string (temp); free (temp); } else /* ${name[@]} or unquoted ${name[*]} */ retval = string_list_dollar_at (l, quoted); dispose_words (l); } else { if (rtype) *rtype = 0; if (var == 0 || array_p (var) || assoc_p (var) == 0) { if ((flags & AV_USEIND) == 0 || indp == 0) { ind = array_expand_index (t, len); if (ind < 0) { /* negative subscripts to indexed arrays count back from end */ if (var && array_p (var)) ind = array_max_index (array_cell (var)) + 1 + ind; if (ind < 0) INDEX_ERROR(); } if (indp) *indp = ind; } else if (indp) ind = *indp; } else if (assoc_p (var)) { t[len - 1] = '\0'; akey = expand_assignment_string_to_string (t, 0); /* [ */ t[len - 1] = ']'; if (akey == 0 || *akey == 0) INDEX_ERROR(); } if (var == 0 || value_cell (var) == 0) /* XXX - check invisible_p(var) ? */ return ((char *)NULL); if (array_p (var) == 0 && assoc_p (var) == 0) return (ind == 0 ? value_cell (var) : (char *)NULL); else if (assoc_p (var)) { retval = assoc_reference (assoc_cell (var), akey); free (akey); } else retval = array_reference (array_cell (var), ind); } return retval;}/* Return a string containing the elements described by the array and subscript contained in S, obeying quoting for subscripts * and @. */char *array_value (s, quoted, flags, rtype, indp) char *s; int quoted, flags, *rtype; arrayind_t *indp;{ return (array_value_internal (s, quoted, flags|AV_ALLOWALL, rtype, indp));}/* Return the value of the array indexing expression S as a single string. If (FLAGS & AV_ALLOWALL) is 0, do not allow `@' and `*' subscripts. This is used by other parts of the shell such as the arithmetic expression evaluator in expr.c. */char *get_array_value (s, flags, rtype, indp) char *s; int flags, *rtype; arrayind_t *indp;{ return (array_value_internal (s, 0, flags, rtype, indp));}char *array_keys (s, quoted) char *s; int quoted;{ int len; char *retval, *t, *temp; WORD_LIST *l; SHELL_VAR *var; var = array_variable_part (s, &t, &len); /* [ */ if (var == 0 || ALL_ELEMENT_SUB (t[0]) == 0 || t[1] != ']') return (char *)NULL; if (var_isset (var) == 0 || invisible_p (var)) return (char *)NULL; if (array_p (var) == 0 && assoc_p (var) == 0) l = add_string_to_list ("0", (WORD_LIST *)NULL); else if (assoc_p (var)) l = assoc_keys_to_word_list (assoc_cell (var)); else l = array_keys_to_word_list (array_cell (var)); if (l == (WORD_LIST *)NULL) return ((char *) NULL); if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))) { temp = string_list_dollar_star (l); retval = quote_string (temp); free (temp); } else /* ${!name[@]} or unquoted ${!name[*]} */ retval = string_list_dollar_at (l, quoted); dispose_words (l); return retval;}#endif /* ARRAY_VARS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -