Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / builtins / read.def
1 This file is read.def, from which is created read.c.
2 It implements the builtin "read" 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 read.c
23
24 $BUILTIN read
25 $FUNCTION read_builtin
26 $SHORT_DOC read [-r] [-p prompt] [-a array] [-e] [name ...]
27 One line is read from the standard input, and the first word is
28 assigned to the first NAME, the second word to the second NAME, and so
29 on, with leftover words assigned to the last NAME.  Only the characters
30 found in $IFS are recognized as word delimiters.  The return code is
31 zero, unless end-of-file is encountered.  If no NAMEs are supplied, the
32 line read is stored in the REPLY variable.  If the -r option is given,
33 this signifies `raw' input, and backslash escaping is disabled.  If
34 the `-p' option is supplied, the string supplied as an argument is
35 output without a trailing newline before attempting to read.  If -a is
36 supplied, the words read are assigned to sequential indices of ARRAY,
37 starting at zero.  If -e is supplied and the shell is interactive,
38 readline is used to obtain the line.
39 $END
40
41 #include <config.h>
42
43 #include <stdio.h>
44
45 #if defined (HAVE_UNISTD_H)
46 #  include <unistd.h>
47 #endif
48
49 #include "../shell.h"
50 #include "common.h"
51 #include "bashgetopt.h"
52
53 #if defined (READLINE)
54 #include "../bashline.h"
55 #include <readline/readline.h>
56 #endif
57
58 #define issep(c)        (strchr (ifs_chars, (c)))
59
60 extern int interrupt_immediately;
61
62 #if defined (READLINE)
63 static char *edit_line ();
64 #endif
65 static SHELL_VAR *bind_read_variable ();
66
67 /* Read the value of the shell variables whose names follow.
68    The reading is done from the current input stream, whatever
69    that may be.  Successive words of the input line are assigned
70    to the variables mentioned in LIST.  The last variable in LIST
71    gets the remainder of the words on the line.  If no variables
72    are mentioned in LIST, then the default variable is $REPLY. */
73 int
74 read_builtin (list)
75      WORD_LIST *list;
76 {
77   register char *varname;
78   int size, i, raw, pass_next, saw_escape, eof, opt, retval, edit;
79   char c;
80   char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
81   char *e, *t, *t1;
82   SHELL_VAR *var;
83 #if defined (ARRAY_VARS)
84   WORD_LIST *alist;
85 #endif
86 #if defined (READLINE)
87   char *rlbuf;
88   int rlind;
89 #endif
90
91   i = 0;                /* Index into the string that we are reading. */
92   raw = edit = 0;       /* Not reading raw input by default. */
93   arrayname = prompt = (char *)NULL;
94
95 #if defined (READLINE)
96   rlbuf = (char *)0;
97   rlind = 0;
98 #endif
99
100   reset_internal_getopt ();
101   while ((opt = internal_getopt (list, "erp:a:")) != -1)
102     {
103       switch (opt)
104         {
105         case 'r':
106           raw = 1;
107           break;
108         case 'p':
109           prompt = list_optarg;
110           break;
111         case 'e':
112 #if defined (READLINE)
113           edit = 1;
114 #endif
115           break;
116 #if defined (ARRAY_VARS)
117         case 'a':
118           arrayname = list_optarg;
119           break;
120 #endif
121         default:
122           builtin_usage ();
123           return (EX_USAGE);
124         }
125     }
126   list = loptend;
127
128   /* IF IFS is unset, we use the default of " \t\n". */
129   var = find_variable ("IFS");
130   ifs_chars = var ? value_cell (var) : " \t\n";
131   if (ifs_chars == 0)           /* XXX */
132     ifs_chars = "";             /* XXX */
133
134   input_string = xmalloc (size = 128);
135
136   begin_unwind_frame ("read_builtin");
137   add_unwind_protect (xfree, input_string);
138 #if defined (READLINE)
139   add_unwind_protect (xfree, rlbuf);
140 #endif
141   interrupt_immediately++;
142
143   /* If the -p or -e flags were given, but input is not coming from the
144      terminal, turn them off. */
145   if ((prompt || edit) && (isatty (0) == 0))
146     {
147       prompt = (char *)NULL;
148       edit = 0;
149     }
150
151   if (prompt && edit == 0)
152     {
153       fprintf (stderr, "%s", prompt);
154       fflush (stderr);
155     }
156
157   pass_next = 0;        /* Non-zero signifies last char was backslash. */
158   saw_escape = 0;       /* Non-zero signifies that we saw an escape char */
159
160   for (eof = 0;;)
161     {
162 #if defined (READLINE)
163       if (edit)
164         {
165           if (rlbuf && rlbuf[rlind] == '\0')
166             {
167               free (rlbuf);
168               rlbuf = (char *)0;
169             }
170           if (rlbuf == 0)
171             {
172               rlbuf = edit_line (prompt ? prompt : "");
173               rlind = 0;
174             }
175           if (rlbuf == 0)
176             {
177               eof = 1;
178               break;
179             }
180           c = rlbuf[rlind++];
181         }
182       else
183 #endif   
184       if (read (0, &c, 1) != 1)
185         {
186           eof = 1;
187           break;
188         }
189
190       if (i + 2 >= size)
191         input_string = xrealloc (input_string, size += 128);
192
193       /* If the next character is to be accepted verbatim, a backslash
194          newline pair still disappears from the input. */
195       if (pass_next)
196         {
197           if (c == '\n')
198             i--;                /* back up over the CTLESC */
199           else
200             input_string[i++] = c;
201           pass_next = 0;
202           continue;
203         }
204
205       if (c == '\\' && raw == 0)
206         {
207           pass_next++;
208           saw_escape++;
209           input_string[i++] = CTLESC;
210           continue;
211         }
212
213       if (c == '\n')
214         break;
215
216       if (c == CTLESC || c == CTLNUL)
217         {
218           saw_escape++;
219           input_string[i++] = CTLESC;
220         }
221
222       input_string[i++] = c;
223     }
224   input_string[i] = '\0';
225
226   interrupt_immediately--;
227   discard_unwind_frame ("read_builtin");
228
229   retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
230
231 #if defined (ARRAY_VARS)
232   /* If -a was given, take the string read, break it into a list of words,
233      an assign them to `arrayname' in turn. */
234   if (arrayname)
235     {
236       var = find_variable (arrayname);
237       if (var == 0)
238         var = make_new_array_variable (arrayname);
239       else if (array_p (var) == 0)
240         var = convert_var_to_array (var);
241
242       empty_array (array_cell (var));
243
244       alist = list_string (input_string, ifs_chars, 0);
245       if (alist)
246         {
247           assign_array_var_from_word_list (var, alist);
248           dispose_words (alist);
249         }
250       free (input_string);
251       return (retval);
252     }
253 #endif /* ARRAY_VARS */ 
254
255   if (!list)
256     {
257       if (saw_escape)
258         {
259           t = dequote_string (input_string);
260           var = bind_variable ("REPLY", t);
261           free (t);
262         }
263       else
264         var = bind_variable ("REPLY", input_string);
265       var->attributes &= ~att_invisible;
266       free (input_string);
267       return (retval);
268     }
269
270   /* This code implements the Posix.2 spec for splitting the words
271      read and assigning them to variables. */
272   orig_input_string = input_string;
273
274   /* Remove IFS white space at the beginning of the input string.  If
275      $IFS is null, no field splitting is performed. */
276   for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
277     ;
278   input_string = t;
279
280   for (; list->next; list = list->next)
281     {
282       varname = list->word->word;
283 #if defined (ARRAY_VARS)
284       if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
285 #else
286       if (legal_identifier (varname) == 0)
287 #endif
288         {
289           builtin_error ("`%s': not a valid identifier", varname);
290           free (orig_input_string);
291           return (EXECUTION_FAILURE);
292         }
293
294       /* If there are more variables than words read from the input,
295          the remaining variables are set to the empty string. */
296       if (*input_string)
297         {
298           /* This call updates INPUT_STRING. */
299           t = get_word_from_string (&input_string, ifs_chars, &e);
300           if (t)
301             *e = '\0';
302           /* Don't bother to remove the CTLESC unless we added one
303              somewhere while reading the string. */
304           if (t && saw_escape)
305             {
306               t1 = dequote_string (t);
307               var = bind_read_variable (varname, t1);
308               free (t1);
309             }
310           else
311             var = bind_read_variable (varname, t);
312         }
313       else
314         {
315           t = (char *)0;
316           var = bind_read_variable (varname, "");
317         }
318
319       FREE (t);
320       if (var == 0)
321         {
322           free (orig_input_string);
323           return (EXECUTION_FAILURE);
324         }
325
326       stupidly_hack_special_variables (varname);
327       var->attributes &= ~att_invisible;
328     }
329
330   /* Now assign the rest of the line to the last variable argument. */
331 #if defined (ARRAY_VARS)
332   if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
333 #else
334   if (legal_identifier (list->word->word) == 0)
335 #endif
336     {
337       builtin_error ("`%s': not a valid identifier", list->word->word);
338       free (orig_input_string);
339       return (EXECUTION_FAILURE);
340     }
341
342   /* This has to be done this way rather than using string_list
343      and list_string because Posix.2 says that the last variable gets the
344      remaining words and their intervening separators. */
345   input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
346
347   if (saw_escape)
348     {
349       t = dequote_string (input_string);
350       var = bind_read_variable (list->word->word, t);
351       free (t);
352     }
353   else
354     var = bind_read_variable (list->word->word, input_string);
355   stupidly_hack_special_variables (list->word->word);
356   if (var)
357     var->attributes &= ~att_invisible;
358   free (orig_input_string);
359
360   return (retval);
361 }
362
363 static SHELL_VAR *
364 bind_read_variable (name, value)
365      char *name, *value;
366 {
367 #if defined (ARRAY_VARS)
368   if (valid_array_reference (name) == 0)
369     {
370       if (legal_identifier (name) == 0)
371         {
372           builtin_error ("`%s': not a valid identifier", name);
373           return ((SHELL_VAR *)NULL);
374         }
375       return (bind_variable (name, value));
376     }
377   else
378     return (do_array_element_assignment (name, value));
379 #else
380   return bind_variable (name, value);
381 #endif
382 }
383
384 #if defined (READLINE)
385 static char *
386 edit_line (p)
387      char *p;
388 {
389   char *ret;
390   int len;
391
392   if (!bash_readline_initialized)
393     initialize_readline ();
394   ret = readline (p);
395   if (ret == 0)
396     return ret;
397   len = strlen (ret);
398   ret = xrealloc (ret, len + 2);
399   ret[len++] = '\n';
400   ret[len] = '\0';
401   return ret;
402 }
403 #endif