This file is declare.def, from which is created declare.c. It implements the builtins "declare" and "local" in Bash. Copyright (C) 1987, 1989, 1991 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 1, 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; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. $PRODUCES declare.c $BUILTIN declare $FUNCTION declare_builtin $SHORT_DOC declare [-[frxi]] name[=value] ... Declare variables and/or give them attributes. If no NAMEs are given, then display the values of variables instead. The flags are: -f to select from among function names only, -r to make NAMEs readonly, -x to make NAMEs export, -i to make NAMEs have the `integer' attribute set. Variables with the integer attribute have arithmetic evaluation (see `let') done when the variable is assigned to. Using `+' instead of `-' turns off the given attribute instead. When used in a function, makes NAMEs local, as with the `local' command. $END $BUILTIN typeset $FUNCTION declare_builtin $SHORT_DOC typeset [-[frxi]] name[=value] ... Obsolete. See `declare'. $END #include #include "../shell.h" static int declare_internal (); /* Declare or change variable attributes. */ int declare_builtin (list) register WORD_LIST *list; { return (declare_internal (list, 0)); } $BUILTIN local $FUNCTION local_builtin $SHORT_DOC local name[=value] ... Create a local variable called NAME, and give it VALUE. LOCAL can only be used within a function; it makes the variable NAME have a visible scope restricted to that function and its children. $END int local_builtin (list) register WORD_LIST *list; { extern int variable_context; if (variable_context) return (declare_internal (list, 1)); else { builtin_error ("Can only be used in a function"); return (EXECUTION_FAILURE); } } /* The workhorse function. */ static int declare_internal (list, no_modifiers) register WORD_LIST *list; int no_modifiers; { extern int variable_context, array_needs_making; int flags_on = 0, flags_off = 0; int any_failed = 0; while (list) { register char *t = list->word->word; int *flags; if (strcmp (t, "--") == 0) { list = list->next; break; } if (*t != '+' && *t != '-') break; if (no_modifiers) { builtin_error ("Modifiers not allowed"); return (EXECUTION_FAILURE); } if (*t == '+') flags = &flags_off; else flags = &flags_on; t++; while (*t) { if (*t == 'f') *flags |= att_function, t++; else if (*t == 'x') *flags |= att_exported, t++, array_needs_making = 1; else if (*t == 'r') *flags |= att_readonly, t++; else if (*t == 'i') *flags |= att_integer, t++; else { builtin_error ("unknown option: `-%c'", *t); return (EXECUTION_FAILURE); } } list = list->next; } /* If there are no more arguments left, then we just want to show some variables. */ if (!list) { /* If we didn't allow modifiers, then this is the `local' command. Perhaps the flag should be called `local_command' instead of `no_modifiers'. At any rate, only show local variables defined at this context level. */ if (no_modifiers) { register SHELL_VAR **vlist; register int i; vlist = map_over (variable_in_context, shell_variables); if (vlist) { for (i = 0; vlist[i]; i++) print_assignment (vlist[i]); free (vlist); } } else { if (!flags_on) set_builtin ((WORD_LIST *)NULL); else set_or_show_attributes ((WORD_LIST *)NULL, flags_on); } fflush (stdout); return (EXECUTION_SUCCESS); } /* There are arguments left, so we are making variables. */ while (list) { char *value, *name = savestring (list->word->word); int offset = assignment (name); if (offset) { name[offset] = '\0'; value = name + offset + 1; } else { value = ""; } /* If VARIABLE_CONTEXT has a non-zero value, then we are executing inside of a function. This means we should make local variables, not global ones. */ if (variable_context) make_local_variable (name); /* If we are declaring a function, then complain about it in some way. We don't let people make functions by saying `typeset -f foo=bar'. */ /* There should be a way, however, to let people look at a particular function definition by saying `typeset -f foo'. */ if (flags_on & att_function) { if (offset) { builtin_error ("Can't use `-f' to make functions"); return (EXECUTION_FAILURE); } else { SHELL_VAR *find_function (), *funvar; funvar = find_function (name); if (funvar) { extern char *named_function_string (); char *result = named_function_string (name, (COMMAND *)function_cell (funvar), 1); printf ("%s\n", result); } else any_failed++; goto hack_next_variable; } } else { SHELL_VAR *var; var = find_variable (name); if (!var) var = bind_variable (name, ""); /* We are not allowed to rebind readonly variables that already are readonly unless we are turning off the readonly bit. */ if (flags_off & att_readonly) flags_on &= ~att_readonly; if (value && readonly_p (var) && (!(flags_off & att_readonly))) { builtin_error ("%s: readonly variable", name); any_failed++; goto hack_next_variable; } var->attributes |= flags_on; var->attributes &= ~flags_off; if (offset) { free (var->value); if (integer_p (var)) { long val, evalexp (); char *itos (); val = evalexp (value); var->value = itos ((int)val); } else var->value = savestring (value); } } stupidly_hack_special_variables (name); hack_next_variable: free (name); list = list->next; } return ((!any_failed) ? EXECUTION_SUCCESS : EXECUTION_FAILURE); }