📄 variables.c
字号:
var_setarray (entry, array); VSETATTR (entry, att_array); return entry;}SHELL_VAR *make_local_array_variable (name) char *name;{ SHELL_VAR *var; ARRAY *array; var = make_local_variable (name); if (var == 0 || array_p (var)) return var; array = array_create (); dispose_variable_value (var); var_setarray (var, array); VSETATTR (var, att_array); return var;}SHELL_VAR *make_new_assoc_variable (name) char *name;{ SHELL_VAR *entry; HASH_TABLE *hash; entry = make_new_variable (name, global_variables->table); hash = assoc_create (0); var_setassoc (entry, hash); VSETATTR (entry, att_assoc); return entry;}SHELL_VAR *make_local_assoc_variable (name) char *name;{ SHELL_VAR *var; HASH_TABLE *hash; var = make_local_variable (name); if (var == 0 || assoc_p (var)) return var; dispose_variable_value (var); hash = assoc_create (0); var_setassoc (var, hash); VSETATTR (var, att_assoc); return var;}#endifchar *make_variable_value (var, value, flags) SHELL_VAR *var; char *value; int flags;{ char *retval, *oval; intmax_t lval, rval; int expok, olen, op; /* If this variable has had its type set to integer (via `declare -i'), then do expression evaluation on it and store the result. The functions in expr.c (evalexp()) and bind_int_variable() are responsible for turning off the integer flag if they don't want further evaluation done. */ if (integer_p (var)) { if (flags & ASS_APPEND) { oval = value_cell (var); lval = evalexp (oval, &expok); /* ksh93 seems to do this */ if (expok == 0) { top_level_cleanup (); jump_to_top_level (DISCARD); } } rval = evalexp (value, &expok); if (expok == 0) { top_level_cleanup (); jump_to_top_level (DISCARD); } if (flags & ASS_APPEND) rval += lval; retval = itos (rval); }#if defined (CASEMOD_ATTRS) else if (capcase_p (var) || uppercase_p (var) || lowercase_p (var)) { if (flags & ASS_APPEND) { oval = get_variable_value (var); if (oval == 0) /* paranoia */ oval = ""; olen = STRLEN (oval); retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1); strcpy (retval, oval); if (value) strcpy (retval+olen, value); } else if (*value) retval = savestring (value); else { retval = (char *)xmalloc (1); retval[0] = '\0'; } op = capcase_p (var) ? CASE_CAPITALIZE : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER); oval = sh_modcase (retval, (char *)0, op); free (retval); retval = oval; }#endif /* CASEMOD_ATTRS */ else if (value) { if (flags & ASS_APPEND) { oval = get_variable_value (var); if (oval == 0) /* paranoia */ oval = ""; olen = STRLEN (oval); retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1); strcpy (retval, oval); if (value) strcpy (retval+olen, value); } else if (*value) retval = savestring (value); else { retval = (char *)xmalloc (1); retval[0] = '\0'; } } else retval = (char *)NULL; return retval;}/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the temporary environment (but usually is not). */static SHELL_VAR *bind_variable_internal (name, value, table, hflags, aflags) const char *name; char *value; HASH_TABLE *table; int hflags, aflags;{ char *newval; SHELL_VAR *entry; entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table); if (entry == 0) { entry = make_new_variable (name, table); var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */ } else if (entry->assign_func) /* array vars have assign functions now */ { INVALIDATE_EXPORTSTR (entry); newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value; if (assoc_p (entry)) entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0")); else if (array_p (entry)) entry = (*(entry->assign_func)) (entry, newval, 0, 0); else entry = (*(entry->assign_func)) (entry, newval, -1, 0); if (newval != value) free (newval); return (entry); } else { if (readonly_p (entry) || noassign_p (entry)) { if (readonly_p (entry)) err_readonly (name); return (entry); } /* Variables which are bound are visible. */ VUNSETATTR (entry, att_invisible); newval = make_variable_value (entry, value, aflags); /* XXX */ /* Invalidate any cached export string */ INVALIDATE_EXPORTSTR (entry);#if defined (ARRAY_VARS) /* XXX -- this bears looking at again -- XXX */ /* If an existing array variable x is being assigned to with x=b or `read x' or something of that nature, silently convert it to x[0]=b or `read x[0]'. */ if (array_p (entry)) { array_insert (array_cell (entry), 0, newval); free (newval); } else if (assoc_p (entry)) { assoc_insert (assoc_cell (entry), savestring ("0"), newval); free (newval); } else#endif { FREE (value_cell (entry)); var_setvalue (entry, newval); } } if (mark_modified_vars) VSETATTR (entry, att_exported); if (exported_p (entry)) array_needs_making = 1; return (entry);} /* Bind a variable NAME to VALUE. This conses up the name and value strings. If we have a temporary environment, we bind there first, then we bind into shell_variables. */SHELL_VAR *bind_variable (name, value, flags) const char *name; char *value; int flags;{ SHELL_VAR *v; VAR_CONTEXT *vc; if (shell_variables == 0) create_variable_tables (); /* If we have a temporary environment, look there first for the variable, and, if found, modify the value there before modifying it in the shell_variables table. This allows sourced scripts to modify values given to them in a temporary environment while modifying the variable value that the caller sees. */ if (temporary_env) bind_tempenv_variable (name, value); /* XXX -- handle local variables here. */ for (vc = shell_variables; vc; vc = vc->down) { if (vc_isfuncenv (vc) || vc_isbltnenv (vc)) { v = hash_lookup (name, vc->table); if (v) return (bind_variable_internal (name, value, vc->table, 0, flags)); } } return (bind_variable_internal (name, value, global_variables->table, 0, flags));}/* Make VAR, a simple shell variable, have value VALUE. Once assigned a value, variables are no longer invisible. This is a duplicate of part of the internals of bind_variable. If the variable is exported, or all modified variables should be exported, mark the variable for export and note that the export environment needs to be recreated. */SHELL_VAR *bind_variable_value (var, value, aflags) SHELL_VAR *var; char *value; int aflags;{ char *t; VUNSETATTR (var, att_invisible); if (var->assign_func) { /* If we're appending, we need the old value, so use make_variable_value */ t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value; (*(var->assign_func)) (var, t, -1, 0); if (t != value && t) free (t); } else { t = make_variable_value (var, value, aflags); FREE (value_cell (var)); var_setvalue (var, t); } INVALIDATE_EXPORTSTR (var); if (mark_modified_vars) VSETATTR (var, att_exported); if (exported_p (var)) array_needs_making = 1; return (var);}/* Bind/create a shell variable with the name LHS to the RHS. This creates or modifies a variable such that it is an integer. This used to be in expr.c, but it is here so that all of the variable binding stuff is localized. Since we don't want any recursive evaluation from bind_variable() (possible without this code, since bind_variable() calls the evaluator for variables with the integer attribute set), we temporarily turn off the integer attribute for each variable we set here, then turn it back on after binding as necessary. */SHELL_VAR *bind_int_variable (lhs, rhs) char *lhs, *rhs;{ register SHELL_VAR *v; int isint, isarr; isint = isarr = 0;#if defined (ARRAY_VARS) if (valid_array_reference (lhs)) { isarr = 1; v = array_variable_part (lhs, (char **)0, (int *)0); } else#endif v = find_variable (lhs); if (v) { isint = integer_p (v); VUNSETATTR (v, att_integer); }#if defined (ARRAY_VARS) if (isarr) v = assign_array_element (lhs, rhs, 0); else#endif v = bind_variable (lhs, rhs, 0); if (v && isint) VSETATTR (v, att_integer); return (v);}SHELL_VAR *bind_var_to_int (var, val) char *var; intmax_t val;{ char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p; p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0); return (bind_int_variable (var, p));}/* Do a function binding to a variable. You pass the name and the command to bind to. This conses the name and command. */SHELL_VAR *bind_function (name, value) const char *name; COMMAND *value;{ SHELL_VAR *entry; entry = find_function (name); if (entry == 0) { BUCKET_CONTENTS *elt; elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH); entry = new_shell_variable (name); elt->data = (PTR_T)entry; } else INVALIDATE_EXPORTSTR (entry); if (var_isset (entry)) dispose_command (function_cell (entry)); if (value) var_setfunc (entry, copy_command (value)); else var_setfunc (entry, 0); VSETATTR (entry, att_function); if (mark_modified_vars) VSETATTR (entry, att_exported); VUNSETATTR (entry, att_invisible); /* Just to be sure */ if (exported_p (entry)) array_needs_making = 1;#if defined (PROGRAMMABLE_COMPLETION) set_itemlist_dirty (&it_functions);#endif return (entry);}#if defined (DEBUGGER)/* Bind a function definition, which includes source file and line number information in addition to the command, into the FUNCTION_DEF hash table.*/voidbind_function_def (name, value) const char *name; FUNCTION_DEF *value;{ FUNCTION_DEF *entry; BUCKET_CONTENTS *elt; COMMAND *cmd; entry = find_function_def (name); if (entry) { dispose_function_def_contents (entry); entry = copy_function_def_contents (value, entry); } else { cmd = value->command; value->command = 0; entry = copy_function_def (value); value->command = cmd; elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH); elt->data = (PTR_T *)entry; }}#endif /* DEBUGGER *//* Add STRING, which is of the form foo=bar, to the temporary environment HASH_TABLE (temporary_env). The functions in execute_cmd.c are responsible for moving the main temporary env to one of the other temporary environments. The expansion code in subst.c calls this. */intassign_in_env (word, flags) WORD_DESC *word; int flags;{ int offset; char *name, *temp, *value; SHELL_VAR *var; const char *string; string = word->word; offset = assignment (string, 0); name = savestring (string); value = (char *)NULL; if (name[offset] == '=') { name[offset] = 0; /* ignore the `+' when assigning temporary environment */ if (name[offset - 1] == '+') name[offset - 1] = '\0'; var = find_variable (name); if (var && (readonly_p (var) || noassign_p (var))) { if (readonly_p (var)) err_readonly (name); free (name); return (0); } temp = name + offset + 1; value = expand_assignment_string_to_string (temp, 0); } if (temporary_env == 0) temporary_env = hash_create (TEMPENV_HASH_BUCKETS); var = hash_lookup (name, temporary_env); if (var == 0) var = make_new_variable (name, temporary_env); else FREE (value_cell (var)); if (value == 0) { value = (char *)xmalloc (1); /* like do_assignment_internal */ value[0] = '\0'; } var_setvalue (var, value); var->attributes |= (att_exported|att_tempvar); var->co
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -