17b7ea2d558168ce9f2c43441a1ad49d474b605d
[platform/upstream/bash.git] / builtins / declare.def
1 This file is declare.def, from which is created declare.c.
2 It implements the builtins "declare" and "local" in Bash.
3
4 Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING.  If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 $PRODUCES declare.c
23
24 $BUILTIN declare
25 $FUNCTION declare_builtin
26 $SHORT_DOC declare [-[frxi]] name[=value] ...
27 Declare variables and/or give them attributes.  If no NAMEs are
28 given, then display the values of variables instead.
29
30 The flags are:
31
32   -f    to select from among function names only,
33   -r    to make NAMEs readonly,
34   -x    to make NAMEs export,
35   -i    to make NAMEs have the `integer' attribute set.
36
37 Variables with the integer attribute have arithmetic evaluation (see
38 `let') done when the variable is assigned to.
39
40 Using `+' instead of `-' turns off the given attribute instead.  When
41 used in a function, makes NAMEs local, as with the `local' command.
42 $END
43
44 $BUILTIN typeset
45 $FUNCTION declare_builtin
46 $SHORT_DOC typeset [-[frxi]] name[=value] ...
47 Obsolete.  See `declare'.
48 $END
49
50 #include <stdio.h>
51
52 #if defined (HAVE_STRING_H)
53 #  include <string.h>
54 #else /* !HAVE_STRING_H */
55 #  include <strings.h>
56 #endif /* !HAVE_STRING_H */
57
58 #include "../shell.h"
59
60 extern int variable_context, array_needs_making;
61
62 static int declare_internal ();
63
64 /* Declare or change variable attributes. */
65 int
66 declare_builtin (list)
67      register WORD_LIST *list;
68 {
69   return (declare_internal (list, 0));
70 }
71
72 $BUILTIN local
73 $FUNCTION local_builtin
74 $SHORT_DOC local name[=value] ...
75 Create a local variable called NAME, and give it VALUE.  LOCAL
76 can only be used within a function; it makes the variable NAME
77 have a visible scope restricted to that function and its children.
78 $END
79 int
80 local_builtin (list)
81      register WORD_LIST *list;
82 {
83   if (variable_context)
84     return (declare_internal (list, 1));
85   else
86     {
87       builtin_error ("Can only be used in a function");
88       return (EXECUTION_FAILURE);
89     }
90 }
91
92 /* The workhorse function. */
93 static int
94 declare_internal (list, local_var)
95      register WORD_LIST *list;
96      int local_var;
97 {
98   int flags_on = 0, flags_off = 0;
99   int any_failed = 0;
100
101   while (list)
102     {
103       register char *t = list->word->word;
104       int *flags;
105
106       if (t[0] == '-' && t[1] == '-' && t[2] == '\0')
107         {
108           list = list->next;
109           break;
110         }
111
112       if (*t != '+' && *t != '-')
113         break;
114
115       if (*t == '+')
116         flags = &flags_off;
117       else
118         flags = &flags_on;
119
120       t++;
121
122       while (*t)
123         {
124           if (*t == 'f')
125             *flags |= att_function, t++;
126           else if (*t == 'x')
127             *flags |= att_exported, t++, array_needs_making = 1;
128           else if (*t == 'r')
129             *flags |= att_readonly, t++;
130           else if (*t == 'i')
131             *flags |= att_integer, t++;
132           else
133             {
134               builtin_error ("unknown option: `-%c'", *t);
135               return (EX_USAGE);
136             }
137         }
138
139       list = list->next;
140     }
141
142   /* If there are no more arguments left, then we just want to show
143      some variables. */
144   if (!list)
145     {
146       /* Show local variables defined at this context level if this is
147          the `local' builtin. */
148       if (local_var)
149         {
150           register SHELL_VAR **vlist;
151           register int i;
152
153           vlist = map_over (variable_in_context, shell_variables);
154
155           if (vlist)
156             {
157               for (i = 0; vlist[i]; i++)
158                 print_assignment (vlist[i]);
159
160               free (vlist);
161             }
162         }
163       else
164         {
165           if (!flags_on)
166             set_builtin ((WORD_LIST *)NULL);
167           else
168             set_or_show_attributes ((WORD_LIST *)NULL, flags_on);
169         }
170
171       fflush (stdout);
172       return (EXECUTION_SUCCESS);
173     }
174
175 #define NEXT_VARIABLE() free (name); list = list->next; continue
176
177   /* There are arguments left, so we are making variables. */
178   while (list)
179     {
180       char *value, *name = savestring (list->word->word);
181       int offset = assignment (name);
182
183       if (offset)
184         {
185           name[offset] = '\0';
186           value = name + offset + 1;
187         }
188       else
189         value = "";
190
191       if (legal_identifier (name) == 0)
192         {
193           builtin_error ("%s: not a legal variable name", name);
194           any_failed++;
195           NEXT_VARIABLE ();
196         }
197
198       /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
199          inside of a function.  This means we should make local variables,
200          not global ones. */
201
202       if (variable_context)
203         make_local_variable (name);
204
205       /* If we are declaring a function, then complain about it in some way.
206          We don't let people make functions by saying `typeset -f foo=bar'. */
207
208       /* There should be a way, however, to let people look at a particular
209          function definition by saying `typeset -f foo'. */
210
211       if (flags_on & att_function)
212         {
213           if (offset)
214             {
215               builtin_error ("Can't use `-f' to make functions");
216               return (EXECUTION_FAILURE);
217             }
218           else
219             {
220               SHELL_VAR *find_function (), *funvar;
221
222               funvar = find_function (name);
223
224               if (funvar)
225                 {
226                   if (readonly_p (funvar) && (flags_off & att_readonly))
227                     {
228                       builtin_error ("%s: readonly function", name);
229                       any_failed++;
230                       NEXT_VARIABLE ();
231                     }
232
233                   if (flags_on == att_function && flags_off == 0)
234                     {
235                       char *result = named_function_string
236                                 (name, (COMMAND *)function_cell (funvar), 1);
237                       printf ("%s\n", result);
238                     }
239                   else
240                     {
241                       funvar->attributes |= flags_on;
242                       funvar->attributes &= ~flags_off;
243                     }
244                 }
245               else
246                 any_failed++;
247               NEXT_VARIABLE ();
248             }
249         }
250       else
251         {
252           SHELL_VAR *var;
253
254           var = find_variable (name);
255
256           if (!var)
257             var = bind_variable (name, "");
258
259           if (readonly_p (var) && (flags_off & att_readonly))
260             {
261               builtin_error ("%s: readonly variable", name);
262               any_failed++;
263               NEXT_VARIABLE ();
264             }
265
266           var->attributes |= flags_on;
267           var->attributes &= ~flags_off;
268
269           if (offset)
270             {
271               free (var->value);
272               if (integer_p (var))
273                 {
274                   long val, evalexp ();
275                   char *itos ();
276
277                   val = evalexp (value);
278                   var->value = itos ((int)val);
279                 }
280               else
281                 var->value = savestring (value);
282             }
283         }
284
285       stupidly_hack_special_variables (name);
286
287       NEXT_VARIABLE ();
288     }
289   return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
290 }