]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/mapfile.def
Bash-4.4 distribution sources and documentation
[thirdparty/bash.git] / builtins / mapfile.def
1 This file is mapfile.def, from which is created mapfile.c.
2 It implements the builtin "mapfile" in Bash.
3
4 Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
5 Copyright (C) 2008-2016 Free Software Foundation, Inc.
6
7 This file is part of GNU Bash, the Bourne Again SHell.
8
9 Bash is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Bash is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Bash. If not, see <http://www.gnu.org/licenses/>.
21
22 $PRODUCES mapfile.c
23
24 $BUILTIN mapfile
25 $FUNCTION mapfile_builtin
26 $SHORT_DOC mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
27 Read lines from the standard input into an indexed array variable.
28
29 Read lines from the standard input into the indexed array variable ARRAY, or
30 from file descriptor FD if the -u option is supplied. The variable MAPFILE
31 is the default ARRAY.
32
33 Options:
34 -d delim Use DELIM to terminate lines, instead of newline
35 -n count Copy at most COUNT lines. If COUNT is 0, all lines are copied
36 -O origin Begin assigning to ARRAY at index ORIGIN. The default index is 0
37 -s count Discard the first COUNT lines read
38 -t Remove a trailing DELIM from each line read (default newline)
39 -u fd Read lines from file descriptor FD instead of the standard input
40 -C callback Evaluate CALLBACK each time QUANTUM lines are read
41 -c quantum Specify the number of lines read between each call to
42 CALLBACK
43
44 Arguments:
45 ARRAY Array variable name to use for file data
46
47 If -C is supplied without -c, the default quantum is 5000. When
48 CALLBACK is evaluated, it is supplied the index of the next array
49 element to be assigned and the line to be assigned to that element
50 as additional arguments.
51
52 If not supplied with an explicit origin, mapfile will clear ARRAY before
53 assigning to it.
54
55 Exit Status:
56 Returns success unless an invalid option is given or ARRAY is readonly or
57 not an indexed array.
58 $END
59
60 $BUILTIN readarray
61 $FUNCTION mapfile_builtin
62 $SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
63 Read lines from a file into an array variable.
64
65 A synonym for `mapfile'.
66 $END
67
68 #include <config.h>
69
70 #include "builtins.h"
71 #include "posixstat.h"
72
73 #if defined (HAVE_UNISTD_H)
74 # include <unistd.h>
75 #endif
76
77 #include "bashansi.h"
78 #include "bashintl.h"
79
80 #include <stdio.h>
81 #include <errno.h>
82
83 #include "../bashintl.h"
84 #include "../shell.h"
85 #include "common.h"
86 #include "bashgetopt.h"
87
88 #if !defined (errno)
89 extern int errno;
90 #endif
91
92 #if defined (ARRAY_VARS)
93
94 static int run_callback __P((const char *, unsigned int, const char *));
95
96 #define DEFAULT_ARRAY_NAME "MAPFILE"
97 #define DEFAULT_VARIABLE_NAME "MAPLINE" /* not used right now */
98
99 /* The value specifying how frequently `mapfile' calls the callback. */
100 #define DEFAULT_QUANTUM 5000
101
102 /* Values for FLAGS */
103 #define MAPF_CLEARARRAY 0x01
104 #define MAPF_CHOP 0x02
105
106 static int delim;
107
108 static int
109 run_callback (callback, curindex, curline)
110 const char *callback;
111 unsigned int curindex;
112 const char *curline;
113 {
114 unsigned int execlen;
115 char *execstr, *qline;
116 int flags;
117
118 qline = sh_single_quote (curline);
119 execlen = strlen (callback) + strlen (qline) + 10;
120 /* 1 for each space between %s and %d,
121 another 1 for the last nul char for C string. */
122 execlen += 3;
123 execstr = xmalloc (execlen);
124
125 flags = SEVAL_NOHIST;
126 #if 0
127 if (interactive)
128 flags |= SEVAL_INTERACT;
129 #endif
130 snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
131 free (qline);
132 return evalstring (execstr, NULL, flags);
133 }
134
135 static void
136 do_chop(line, delim)
137 char *line;
138 unsigned char delim;
139 {
140 int length;
141
142 length = strlen (line);
143 if (length && line[length-1] == delim)
144 line[length-1] = '\0';
145 }
146
147 static int
148 mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, delim, flags)
149 int fd;
150 long line_count_goal, origin, nskip, callback_quantum;
151 char *callback, *array_name;
152 int delim;
153 int flags;
154 {
155 char *line;
156 size_t line_length;
157 unsigned int array_index, line_count;
158 SHELL_VAR *entry;
159 int unbuffered_read;
160
161 line = NULL;
162 line_length = 0;
163 unbuffered_read = 0;
164
165 /* The following check should be done before reading any lines. Doing it
166 here allows us to call bind_array_element instead of bind_array_variable
167 and skip the variable lookup on every call. */
168 entry = find_or_make_array_variable (array_name, 1);
169 if (entry == 0 || readonly_p (entry) || noassign_p (entry))
170 {
171 if (entry && readonly_p (entry))
172 err_readonly (array_name);
173
174 return (EXECUTION_FAILURE);
175 }
176 else if (array_p (entry) == 0)
177 {
178 builtin_error (_("%s: not an indexed array"), array_name);
179 return (EXECUTION_FAILURE);
180 }
181 else if (invisible_p (entry))
182 VUNSETATTR (entry, att_invisible); /* no longer invisible */
183
184 if (flags & MAPF_CLEARARRAY)
185 array_flush (array_cell (entry));
186
187 #ifndef __CYGWIN__
188 unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
189 #else
190 unbuffered_read = 1;
191 #endif
192
193 if (delim != '\n')
194 unbuffered_read = 1;
195
196 zreset ();
197
198 /* Skip any lines at beginning of file? */
199 for (line_count = 0; line_count < nskip; line_count++)
200 if (zgetline (fd, &line, &line_length, delim, unbuffered_read) < 0)
201 break;
202
203 line = 0;
204 line_length = 0;
205
206 /* Reset the buffer for bash own stream */
207 for (array_index = origin, line_count = 1;
208 zgetline (fd, &line, &line_length, delim, unbuffered_read) != -1;
209 array_index++)
210 {
211 /* Remove trailing newlines? */
212 if (flags & MAPF_CHOP)
213 do_chop (line, delim);
214
215 /* Has a callback been registered and if so is it time to call it? */
216 if (callback && line_count && (line_count % callback_quantum) == 0)
217 {
218 run_callback (callback, array_index, line);
219
220 /* Reset the buffer for bash own stream. */
221 if (unbuffered_read == 0)
222 zsyncfd (fd);
223 }
224
225 /* XXX - bad things can happen if the callback modifies ENTRY, e.g.,
226 unsetting it or changing it to a non-indexed-array type. */
227 bind_array_element (entry, array_index, line, 0);
228
229 /* Have we exceeded # of lines to store? */
230 line_count++;
231 if (line_count_goal != 0 && line_count > line_count_goal)
232 break;
233 }
234
235 xfree (line);
236
237 if (unbuffered_read == 0)
238 zsyncfd (fd);
239
240 return EXECUTION_SUCCESS;
241 }
242
243 int
244 mapfile_builtin (list)
245 WORD_LIST *list;
246 {
247 int opt, code, fd, clear_array, flags;
248 intmax_t intval;
249 long lines, origin, nskip, callback_quantum;
250 char *array_name, *callback;
251
252 clear_array = 1;
253 fd = 0;
254 lines = origin = nskip = 0;
255 flags = MAPF_CLEARARRAY;
256 callback_quantum = DEFAULT_QUANTUM;
257 callback = 0;
258 delim = '\n';
259
260 reset_internal_getopt ();
261 while ((opt = internal_getopt (list, "d:u:n:O:tC:c:s:")) != -1)
262 {
263 switch (opt)
264 {
265 case 'd':
266 delim = *list_optarg;
267 break;
268 case 'u':
269 code = legal_number (list_optarg, &intval);
270 if (code == 0 || intval < 0 || intval != (int)intval)
271 {
272 builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
273 return (EXECUTION_FAILURE);
274 }
275 else
276 fd = intval;
277
278 if (sh_validfd (fd) == 0)
279 {
280 builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
281 return (EXECUTION_FAILURE);
282 }
283 break;
284
285 case 'n':
286 code = legal_number (list_optarg, &intval);
287 if (code == 0 || intval < 0 || intval != (unsigned)intval)
288 {
289 builtin_error (_("%s: invalid line count"), list_optarg);
290 return (EXECUTION_FAILURE);
291 }
292 else
293 lines = intval;
294 break;
295
296 case 'O':
297 code = legal_number (list_optarg, &intval);
298 if (code == 0 || intval < 0 || intval != (unsigned)intval)
299 {
300 builtin_error (_("%s: invalid array origin"), list_optarg);
301 return (EXECUTION_FAILURE);
302 }
303 else
304 origin = intval;
305 flags &= ~MAPF_CLEARARRAY;
306 break;
307 case 't':
308 flags |= MAPF_CHOP;
309 break;
310 case 'C':
311 callback = list_optarg;
312 break;
313 case 'c':
314 code = legal_number (list_optarg, &intval);
315 if (code == 0 || intval <= 0 || intval != (unsigned)intval)
316 {
317 builtin_error (_("%s: invalid callback quantum"), list_optarg);
318 return (EXECUTION_FAILURE);
319 }
320 else
321 callback_quantum = intval;
322 break;
323 case 's':
324 code = legal_number (list_optarg, &intval);
325 if (code == 0 || intval < 0 || intval != (unsigned)intval)
326 {
327 builtin_error (_("%s: invalid line count"), list_optarg);
328 return (EXECUTION_FAILURE);
329 }
330 else
331 nskip = intval;
332 break;
333 CASE_HELPOPT;
334 default:
335 builtin_usage ();
336 return (EX_USAGE);
337 }
338 }
339 list = loptend;
340
341 if (list == 0)
342 array_name = DEFAULT_ARRAY_NAME;
343 else if (list->word == 0 || list->word->word == 0)
344 {
345 builtin_error ("internal error: getting variable name");
346 return (EXECUTION_FAILURE);
347 }
348 else if (list->word->word[0] == '\0')
349 {
350 builtin_error (_("empty array variable name"));
351 return (EX_USAGE);
352 }
353 else
354 array_name = list->word->word;
355
356 if (legal_identifier (array_name) == 0)
357 {
358 sh_invalidid (array_name);
359 return (EXECUTION_FAILURE);
360 }
361
362 return mapfile (fd, lines, origin, nskip, callback_quantum, callback, array_name, delim, flags);
363 }
364
365 #else
366
367 int
368 mapfile_builtin (list)
369 WORD_LIST *list;
370 {
371 builtin_error (_("array variable support required"));
372 return (EXECUTION_FAILURE);
373 }
374
375 #endif /* ARRAY_VARS */