]> git.ipfire.org Git - thirdparty/bash.git/blame - braces.c
Bash-4.2 patch 16
[thirdparty/bash.git] / braces.c
CommitLineData
726f6388
JA
1/* braces.c -- code for doing word expansion in curly braces. */
2
3185942a 3/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
726f6388
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
726f6388 11
3185942a
JA
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
726f6388
JA
16
17 You should have received a copy of the GNU General Public License
3185942a
JA
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
726f6388 20
ccc6cda3 21/* Stuff in curly braces gets expanded before all other shell expansions. */
726f6388 22
ccc6cda3
JA
23#include "config.h"
24
25#if defined (BRACE_EXPANSION)
26
27#if defined (HAVE_UNISTD_H)
cce855bc
JA
28# ifdef _MINIX
29# include <sys/types.h>
30# endif
ccc6cda3
JA
31# include <unistd.h>
32#endif
726f6388 33
d166f048 34#include "bashansi.h"
726f6388
JA
35
36#if defined (SHELL)
ccc6cda3 37# include "shell.h"
726f6388
JA
38#endif /* SHELL */
39
40#include "general.h"
7117c2d2 41#include "shmbutil.h"
b80f6443 42#include "chartypes.h"
7117c2d2 43
726f6388
JA
44#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
45
b80f6443
JA
46#define BRACE_SEQ_SPECIFIER ".."
47
3185942a
JA
48extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
49
726f6388
JA
50/* Basic idea:
51
52 Segregate the text into 3 sections: preamble (stuff before an open brace),
53 postamble (stuff after the matching close brace) and amble (stuff after
54 preamble, and before postamble). Expand amble, and then tack on the
55 expansions to preamble. Expand postamble, and tack on the expansions to
56 the result so far.
57 */
58
59/* The character which is used to separate arguments. */
3185942a 60static const int brace_arg_separator = ',';
726f6388 61
f73dda09 62#if defined (__P)
7117c2d2 63static int brace_gobbler __P((char *, size_t, int *, int));
b80f6443
JA
64static char **expand_amble __P((char *, size_t, int));
65static char **expand_seqterm __P((char *, size_t));
495aee44 66static char **mkseq __P((intmax_t, intmax_t, int, int, int));
f73dda09
JA
67static char **array_concat __P((char **, char **));
68#else
726f6388 69static int brace_gobbler ();
f73dda09 70static char **expand_amble ();
b80f6443
JA
71static char **expand_seqterm ();
72static char **mkseq();
f73dda09
JA
73static char **array_concat ();
74#endif
726f6388 75
0628567a
JA
76#if 0
77static void
78dump_result (a)
79 char **a;
80{
81 int i;
82
83 for (i = 0; a[i]; i++)
84 printf ("dump_result: a[%d] = -%s-\n", i, a[i]);
85}
86#endif
87
726f6388
JA
88/* Return an array of strings; the brace expansion of TEXT. */
89char **
90brace_expand (text)
91 char *text;
92{
93 register int start;
7117c2d2 94 size_t tlen;
726f6388 95 char *preamble, *postamble, *amble;
7117c2d2 96 size_t alen;
726f6388 97 char **tack, **result;
0628567a 98 int i, j, c, c1;
726f6388 99
7117c2d2
JA
100 DECLARE_MBSTATE;
101
726f6388 102 /* Find the text of the preamble. */
7117c2d2 103 tlen = strlen (text);
726f6388 104 i = 0;
0628567a
JA
105#if defined (CSH_BRACE_COMPAT)
106 c = brace_gobbler (text, tlen, &i, '{'); /* } */
107#else
108 /* Make sure that when we exit this loop, c == 0 or text[i] begins a
109 valid brace expansion sequence. */
110 do
111 {
112 c = brace_gobbler (text, tlen, &i, '{'); /* } */
113 c1 = c;
114 /* Verify that c begins a valid brace expansion word. If it doesn't, we
115 go on. Loop stops when there are no more open braces in the word. */
116 if (c)
117 {
118 start = j = i + 1; /* { */
119 c = brace_gobbler (text, tlen, &j, '}');
120 if (c == 0) /* it's not */
121 {
122 i++;
123 c = c1;
124 continue;
125 }
126 else /* it is */
127 {
128 c = c1;
129 break;
130 }
131 }
132 else
133 break;
134 }
135 while (c);
136#endif /* !CSH_BRACE_COMPAT */
726f6388
JA
137
138 preamble = (char *)xmalloc (i + 1);
139 strncpy (preamble, text, i);
140 preamble[i] = '\0';
141
142 result = (char **)xmalloc (2 * sizeof (char *));
143 result[0] = preamble;
144 result[1] = (char *)NULL;
ccc6cda3 145
726f6388
JA
146 /* Special case. If we never found an exciting character, then
147 the preamble is all of the text, so just return that. */
148 if (c != '{')
149 return (result);
150
151 /* Find the amble. This is the stuff inside this set of braces. */
152 start = ++i;
7117c2d2 153 c = brace_gobbler (text, tlen, &i, '}');
726f6388
JA
154
155 /* What if there isn't a matching close brace? */
ccc6cda3 156 if (c == 0)
726f6388
JA
157 {
158#if defined (NOTDEF)
726f6388
JA
159 /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
160 and I, then this should be an error. Otherwise, it isn't. */
7117c2d2
JA
161 j = start;
162 while (j < i)
726f6388
JA
163 {
164 if (text[j] == '\\')
165 {
166 j++;
7117c2d2 167 ADVANCE_CHAR (text, tlen, j);
726f6388
JA
168 continue;
169 }
170
171 if (text[j] == brace_arg_separator)
b80f6443 172 { /* { */
7117c2d2 173 strvec_dispose (result);
b80f6443 174 report_error ("no closing `%c' in %s", '}', text);
726f6388
JA
175 throw_to_top_level ();
176 }
7117c2d2 177 ADVANCE_CHAR (text, tlen, j);
726f6388
JA
178 }
179#endif
180 free (preamble); /* Same as result[0]; see initialization. */
181 result[0] = savestring (text);
182 return (result);
183 }
184
bb70624e
JA
185#if defined (SHELL)
186 amble = substring (text, start, i);
7117c2d2 187 alen = i - start;
bb70624e 188#else
726f6388
JA
189 amble = (char *)xmalloc (1 + (i - start));
190 strncpy (amble, &text[start], (i - start));
7117c2d2
JA
191 alen = i - start;
192 amble[alen] = '\0';
bb70624e 193#endif
726f6388
JA
194
195#if defined (SHELL)
7117c2d2
JA
196 INITIALIZE_MBSTATE;
197
726f6388
JA
198 /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
199 just return without doing any expansion. */
7117c2d2
JA
200 j = 0;
201 while (amble[j])
ccc6cda3
JA
202 {
203 if (amble[j] == '\\')
204 {
205 j++;
7117c2d2 206 ADVANCE_CHAR (amble, alen, j);
ccc6cda3
JA
207 continue;
208 }
7117c2d2 209
ccc6cda3
JA
210 if (amble[j] == brace_arg_separator)
211 break;
7117c2d2
JA
212
213 ADVANCE_CHAR (amble, alen, j);
ccc6cda3
JA
214 }
215
b80f6443 216 if (amble[j] == 0)
ccc6cda3 217 {
b80f6443
JA
218 tack = expand_seqterm (amble, alen);
219 if (tack)
220 goto add_tack;
221 else
222 {
223 free (amble);
224 free (preamble);
225 result[0] = savestring (text);
226 return (result);
227 }
ccc6cda3 228 }
726f6388
JA
229#endif /* SHELL */
230
b80f6443
JA
231 tack = expand_amble (amble, alen, 0);
232add_tack:
726f6388
JA
233 result = array_concat (result, tack);
234 free (amble);
7117c2d2 235 strvec_dispose (tack);
726f6388 236
b80f6443
JA
237 postamble = text + i + 1;
238
726f6388
JA
239 tack = brace_expand (postamble);
240 result = array_concat (result, tack);
7117c2d2 241 strvec_dispose (tack);
726f6388
JA
242
243 return (result);
244}
245
246/* Expand the text found inside of braces. We simply try to split the
247 text at BRACE_ARG_SEPARATORs into separate strings. We then brace
248 expand each slot which needs it, until there are no more slots which
249 need it. */
250static char **
b80f6443 251expand_amble (text, tlen, flags)
726f6388 252 char *text;
7117c2d2 253 size_t tlen;
b80f6443 254 int flags;
726f6388
JA
255{
256 char **result, **partial;
257 char *tem;
258 int start, i, c;
259
7117c2d2
JA
260 DECLARE_MBSTATE;
261
726f6388
JA
262 result = (char **)NULL;
263
7117c2d2
JA
264 start = i = 0;
265 c = 1;
266 while (c)
726f6388 267 {
7117c2d2 268 c = brace_gobbler (text, tlen, &i, brace_arg_separator);
bb70624e
JA
269#if defined (SHELL)
270 tem = substring (text, start, i);
271#else
726f6388
JA
272 tem = (char *)xmalloc (1 + (i - start));
273 strncpy (tem, &text[start], (i - start));
274 tem[i- start] = '\0';
bb70624e 275#endif
726f6388
JA
276
277 partial = brace_expand (tem);
278
279 if (!result)
280 result = partial;
281 else
282 {
b80f6443
JA
283 register int lr, lp, j;
284
285 lr = strvec_len (result);
286 lp = strvec_len (partial);
726f6388 287
7117c2d2 288 result = strvec_resize (result, lp + lr + 1);
726f6388
JA
289
290 for (j = 0; j < lp; j++)
291 result[lr + j] = partial[j];
292
293 result[lr + j] = (char *)NULL;
294 free (partial);
295 }
296 free (tem);
7117c2d2
JA
297 ADVANCE_CHAR (text, tlen, i);
298 start = i;
726f6388
JA
299 }
300 return (result);
301}
302
b80f6443
JA
303#define ST_BAD 0
304#define ST_INT 1
305#define ST_CHAR 2
3185942a 306#define ST_ZINT 3
b80f6443
JA
307
308static char **
3185942a 309mkseq (start, end, incr, type, width)
495aee44
CR
310 intmax_t start, end;
311 int incr, type, width;
b80f6443 312{
495aee44
CR
313 intmax_t n;
314 int i;
b80f6443
JA
315 char **result, *t;
316
495aee44
CR
317 i = abs (end - start) + 1;
318 result = strvec_create (i + 1);
b80f6443 319
0628567a
JA
320 if (incr == 0)
321 incr = 1;
322
323 if (start > end && incr > 0)
324 incr = -incr;
325 else if (start < end && incr < 0)
326 incr = -incr;
b80f6443
JA
327
328 /* Make sure we go through the loop at least once, so {3..3} prints `3' */
329 i = 0;
330 n = start;
331 do
332 {
0628567a
JA
333#if defined (SHELL)
334 QUIT; /* XXX - memory leak here */
335#endif
b80f6443
JA
336 if (type == ST_INT)
337 result[i++] = itos (n);
3185942a
JA
338 else if (type == ST_ZINT)
339 {
495aee44
CR
340 int len, arg;
341 arg = n;
342 len = asprintf (&t, "%0*d", width, arg);
3185942a
JA
343 result[i++] = t;
344 }
b80f6443
JA
345 else
346 {
347 t = (char *)xmalloc (2);
348 t[0] = n;
349 t[1] = '\0';
350 result[i++] = t;
351 }
b80f6443 352 n += incr;
3185942a
JA
353 if ((incr < 0 && n < end) || (incr > 0 && n > end))
354 break;
b80f6443
JA
355 }
356 while (1);
357
358 result[i] = (char *)0;
359 return (result);
360}
361
362static char **
363expand_seqterm (text, tlen)
364 char *text;
365 size_t tlen;
366{
367 char *t, *lhs, *rhs;
495aee44
CR
368 int i, lhs_t, rhs_t, incr, lhs_l, rhs_l, width;
369 intmax_t lhs_v, rhs_v;
b80f6443 370 intmax_t tl, tr;
0001803f 371 char **result, *ep, *oep;
b80f6443
JA
372
373 t = strstr (text, BRACE_SEQ_SPECIFIER);
374 if (t == 0)
375 return ((char **)NULL);
376
3185942a
JA
377 lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
378 lhs = substring (text, 0, lhs_l);
379 rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
b80f6443
JA
380
381 if (lhs[0] == 0 || rhs[0] == 0)
382 {
383 free (lhs);
384 free (rhs);
385 return ((char **)NULL);
386 }
387
388 /* Now figure out whether LHS and RHS are integers or letters. Both
389 sides have to match. */
390 lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
391 ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
3185942a
JA
392
393 /* Decide on rhs and whether or not it looks like the user specified
394 an increment */
395 ep = 0;
396 if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
397 {
398 rhs_t = ST_INT;
399 tr = strtoimax (rhs, &ep, 10);
400 if (ep && *ep != 0 && *ep != '.')
401 rhs_t = ST_BAD; /* invalid */
402 }
403 else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
404 {
405 rhs_t = ST_CHAR;
406 ep = rhs + 1;
407 }
408 else
409 {
410 rhs_t = ST_BAD;
411 ep = 0;
412 }
413
414 incr = 1;
415 if (rhs_t != ST_BAD)
416 {
0001803f 417 oep = ep;
3185942a
JA
418 if (ep && *ep == '.' && ep[1] == '.' && ep[2])
419 incr = strtoimax (ep + 2, &ep, 10);
420 if (*ep != 0)
421 rhs_t = ST_BAD; /* invalid incr */
0001803f 422 tlen -= ep - oep;
3185942a 423 }
b80f6443
JA
424
425 if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
426 {
427 free (lhs);
428 free (rhs);
429 return ((char **)NULL);
430 }
431
432 /* OK, we have something. It's either a sequence of integers, ascending
433 or descending, or a sequence or letters, ditto. Generate the sequence,
434 put it into a string vector, and return it. */
435
436 if (lhs_t == ST_CHAR)
437 {
eb873671
JA
438 lhs_v = (unsigned char)lhs[0];
439 rhs_v = (unsigned char)rhs[0];
3185942a 440 width = 1;
b80f6443
JA
441 }
442 else
443 {
444 lhs_v = tl; /* integer truncation */
445 rhs_v = tr;
3185942a
JA
446
447 /* Decide whether or not the terms need zero-padding */
448 rhs_l = tlen - lhs_l - sizeof (BRACE_SEQ_SPECIFIER) + 1;
449 width = 0;
450 if (lhs_l > 1 && lhs[0] == '0')
451 width = lhs_l, lhs_t = ST_ZINT;
452 if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
453 width = lhs_l, lhs_t = ST_ZINT;
454 if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
455 width = rhs_l, lhs_t = ST_ZINT;
456 if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
457 width = rhs_l, lhs_t = ST_ZINT;
0001803f
CR
458
459 if (width < lhs_l && lhs_t == ST_ZINT)
460 width = lhs_l;
461 if (width < rhs_l && lhs_t == ST_ZINT)
462 width = rhs_l;
b80f6443
JA
463 }
464
3185942a 465 result = mkseq (lhs_v, rhs_v, incr, lhs_t, width);
b80f6443
JA
466
467 free (lhs);
468 free (rhs);
469
470 return (result);
471}
472
726f6388
JA
473/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
474 index of the character matching SATISFY. This understands about
475 quoting. Return the character that caused us to stop searching;
476 this is either the same as SATISFY, or 0. */
0628567a
JA
477/* If SATISFY is `}', we are looking for a brace expression, so we
478 should enforce the rules that govern valid brace expansions:
479 1) to count as an arg separator, a comma or `..' has to be outside
480 an inner set of braces.
481*/
726f6388 482static int
7117c2d2 483brace_gobbler (text, tlen, indx, satisfy)
726f6388 484 char *text;
7117c2d2 485 size_t tlen;
726f6388
JA
486 int *indx;
487 int satisfy;
488{
0628567a 489 register int i, c, quoted, level, commas, pass_next;
d166f048
JA
490#if defined (SHELL)
491 int si;
492 char *t;
493#endif
7117c2d2 494 DECLARE_MBSTATE;
726f6388
JA
495
496 level = quoted = pass_next = 0;
0628567a
JA
497#if defined (CSH_BRACE_COMPAT)
498 commas = 1;
499#else
500 commas = (satisfy == '}') ? 0 : 1;
501#endif
726f6388 502
7117c2d2
JA
503 i = *indx;
504 while (c = text[i])
726f6388
JA
505 {
506 if (pass_next)
507 {
508 pass_next = 0;
7117c2d2 509 ADVANCE_CHAR (text, tlen, i);
726f6388
JA
510 continue;
511 }
512
513 /* A backslash escapes the next character. This allows backslash to
514 escape the quote character in a double-quoted string. */
515 if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
28ef6c31
JA
516 {
517 pass_next = 1;
7117c2d2 518 i++;
28ef6c31
JA
519 continue;
520 }
726f6388 521
b80f6443
JA
522#if defined (SHELL)
523 /* If compiling for the shell, treat ${...} like \{...} */
524 if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
525 {
526 pass_next = 1;
527 i++;
eb873671
JA
528 if (quoted == 0)
529 level++;
b80f6443
JA
530 continue;
531 }
532#endif
533
726f6388
JA
534 if (quoted)
535 {
536 if (c == quoted)
537 quoted = 0;
7117c2d2 538 ADVANCE_CHAR (text, tlen, i);
726f6388
JA
539 continue;
540 }
541
542 if (c == '"' || c == '\'' || c == '`')
543 {
544 quoted = c;
7117c2d2 545 i++;
726f6388
JA
546 continue;
547 }
ccc6cda3 548
d166f048 549#if defined (SHELL)
3185942a
JA
550 /* Pass new-style command and process substitutions through unchanged. */
551 if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
d166f048
JA
552 {
553 si = i + 2;
3185942a 554 t = extract_command_subst (text, &si, 0);
d166f048
JA
555 i = si;
556 free (t);
7117c2d2 557 i++;
d166f048
JA
558 continue;
559 }
560#endif
561
0628567a 562 if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
726f6388
JA
563 {
564 /* We ignore an open brace surrounded by whitespace, and also
ccc6cda3
JA
565 an open brace followed immediately by a close brace preceded
566 by whitespace. */
726f6388
JA
567 if (c == '{' &&
568 ((!i || brace_whitespace (text[i - 1])) &&
569 (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
7117c2d2
JA
570 {
571 i++;
572 continue;
573 }
b80f6443 574
726f6388
JA
575 break;
576 }
577
578 if (c == '{')
579 level++;
580 else if (c == '}' && level)
581 level--;
0628567a
JA
582#if !defined (CSH_BRACE_COMPAT)
583 else if (satisfy == '}' && c == brace_arg_separator && level == 0)
584 commas++;
585 else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) &&
586 text[i+2] != satisfy && level == 0)
587 commas++;
588#endif
7117c2d2
JA
589
590 ADVANCE_CHAR (text, tlen, i);
726f6388
JA
591 }
592
593 *indx = i;
594 return (c);
595}
596
597/* Return a new array of strings which is the result of appending each
598 string in ARR2 to each string in ARR1. The resultant array is
599 len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
600 are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
601 is returned. */
602static char **
603array_concat (arr1, arr2)
604 char **arr1, **arr2;
605{
606 register int i, j, len, len1, len2;
607 register char **result;
608
ccc6cda3 609 if (arr1 == 0)
7117c2d2 610 return (strvec_copy (arr2));
726f6388 611
ccc6cda3 612 if (arr2 == 0)
7117c2d2 613 return (strvec_copy (arr1));
726f6388 614
7117c2d2
JA
615 len1 = strvec_len (arr1);
616 len2 = strvec_len (arr2);
726f6388
JA
617
618 result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
619
620 len = 0;
621 for (i = 0; i < len1; i++)
622 {
623 int strlen_1 = strlen (arr1[i]);
624
625 for (j = 0; j < len2; j++)
626 {
b80f6443 627 result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
726f6388
JA
628 strcpy (result[len], arr1[i]);
629 strcpy (result[len] + strlen_1, arr2[j]);
630 len++;
631 }
632 free (arr1[i]);
633 }
634 free (arr1);
635
636 result[len] = (char *)NULL;
637 return (result);
638}
639
640#if defined (TEST)
641#include <stdio.h>
642
643fatal_error (format, arg1, arg2)
644 char *format, *arg1, *arg2;
645{
646 report_error (format, arg1, arg2);
647 exit (1);
648}
649
650report_error (format, arg1, arg2)
651 char *format, *arg1, *arg2;
652{
653 fprintf (stderr, format, arg1, arg2);
654 fprintf (stderr, "\n");
655}
656
657main ()
658{
659 char example[256];
660
661 for (;;)
662 {
663 char **result;
664 int i;
665
666 fprintf (stderr, "brace_expand> ");
667
668 if ((!fgets (example, 256, stdin)) ||
669 (strncmp (example, "quit", 4) == 0))
670 break;
671
672 if (strlen (example))
673 example[strlen (example) - 1] = '\0';
674
675 result = brace_expand (example);
676
677 for (i = 0; result[i]; i++)
678 printf ("%s\n", result[i]);
679
680 free_array (result);
681 }
682}
683\f
684/*
685 * Local variables:
686 * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
687 * end:
688 */
689
690#endif /* TEST */
ccc6cda3 691#endif /* BRACE_EXPANSION */