]> git.ipfire.org Git - thirdparty/bash.git/blame - braces.c
Imported from ../bash-4.0-rc1.tar.gz.
[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));
3185942a 66static char **mkseq __P((int, int, 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
JA
309mkseq (start, end, incr, type, width)
310 int start, end, incr, type, width;
b80f6443 311{
0628567a 312 int n, i;
b80f6443
JA
313 char **result, *t;
314
315 n = abs (end - start) + 1;
316 result = strvec_create (n + 1);
317
0628567a
JA
318 if (incr == 0)
319 incr = 1;
320
321 if (start > end && incr > 0)
322 incr = -incr;
323 else if (start < end && incr < 0)
324 incr = -incr;
b80f6443
JA
325
326 /* Make sure we go through the loop at least once, so {3..3} prints `3' */
327 i = 0;
328 n = start;
329 do
330 {
0628567a
JA
331#if defined (SHELL)
332 QUIT; /* XXX - memory leak here */
333#endif
b80f6443
JA
334 if (type == ST_INT)
335 result[i++] = itos (n);
3185942a
JA
336 else if (type == ST_ZINT)
337 {
338 int len;
339 len = asprintf (&t, "%0*d", width, n);
340 result[i++] = t;
341 }
b80f6443
JA
342 else
343 {
344 t = (char *)xmalloc (2);
345 t[0] = n;
346 t[1] = '\0';
347 result[i++] = t;
348 }
b80f6443 349 n += incr;
3185942a
JA
350 if ((incr < 0 && n < end) || (incr > 0 && n > end))
351 break;
b80f6443
JA
352 }
353 while (1);
354
355 result[i] = (char *)0;
356 return (result);
357}
358
359static char **
360expand_seqterm (text, tlen)
361 char *text;
362 size_t tlen;
363{
364 char *t, *lhs, *rhs;
3185942a 365 int i, lhs_t, rhs_t, lhs_v, rhs_v, incr, lhs_l, rhs_l, width;
b80f6443 366 intmax_t tl, tr;
3185942a 367 char **result, *ep;
b80f6443
JA
368
369 t = strstr (text, BRACE_SEQ_SPECIFIER);
370 if (t == 0)
371 return ((char **)NULL);
372
3185942a
JA
373 lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
374 lhs = substring (text, 0, lhs_l);
375 rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
b80f6443
JA
376
377 if (lhs[0] == 0 || rhs[0] == 0)
378 {
379 free (lhs);
380 free (rhs);
381 return ((char **)NULL);
382 }
383
384 /* Now figure out whether LHS and RHS are integers or letters. Both
385 sides have to match. */
386 lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
387 ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
3185942a
JA
388
389 /* Decide on rhs and whether or not it looks like the user specified
390 an increment */
391 ep = 0;
392 if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
393 {
394 rhs_t = ST_INT;
395 tr = strtoimax (rhs, &ep, 10);
396 if (ep && *ep != 0 && *ep != '.')
397 rhs_t = ST_BAD; /* invalid */
398 }
399 else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
400 {
401 rhs_t = ST_CHAR;
402 ep = rhs + 1;
403 }
404 else
405 {
406 rhs_t = ST_BAD;
407 ep = 0;
408 }
409
410 incr = 1;
411 if (rhs_t != ST_BAD)
412 {
413 if (ep && *ep == '.' && ep[1] == '.' && ep[2])
414 incr = strtoimax (ep + 2, &ep, 10);
415 if (*ep != 0)
416 rhs_t = ST_BAD; /* invalid incr */
417 }
b80f6443
JA
418
419 if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
420 {
421 free (lhs);
422 free (rhs);
423 return ((char **)NULL);
424 }
425
426 /* OK, we have something. It's either a sequence of integers, ascending
427 or descending, or a sequence or letters, ditto. Generate the sequence,
428 put it into a string vector, and return it. */
429
430 if (lhs_t == ST_CHAR)
431 {
eb873671
JA
432 lhs_v = (unsigned char)lhs[0];
433 rhs_v = (unsigned char)rhs[0];
3185942a 434 width = 1;
b80f6443
JA
435 }
436 else
437 {
438 lhs_v = tl; /* integer truncation */
439 rhs_v = tr;
3185942a
JA
440
441 /* Decide whether or not the terms need zero-padding */
442 rhs_l = tlen - lhs_l - sizeof (BRACE_SEQ_SPECIFIER) + 1;
443 width = 0;
444 if (lhs_l > 1 && lhs[0] == '0')
445 width = lhs_l, lhs_t = ST_ZINT;
446 if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
447 width = lhs_l, lhs_t = ST_ZINT;
448 if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
449 width = rhs_l, lhs_t = ST_ZINT;
450 if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
451 width = rhs_l, lhs_t = ST_ZINT;
b80f6443
JA
452 }
453
3185942a 454 result = mkseq (lhs_v, rhs_v, incr, lhs_t, width);
b80f6443
JA
455
456 free (lhs);
457 free (rhs);
458
459 return (result);
460}
461
726f6388
JA
462/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
463 index of the character matching SATISFY. This understands about
464 quoting. Return the character that caused us to stop searching;
465 this is either the same as SATISFY, or 0. */
0628567a
JA
466/* If SATISFY is `}', we are looking for a brace expression, so we
467 should enforce the rules that govern valid brace expansions:
468 1) to count as an arg separator, a comma or `..' has to be outside
469 an inner set of braces.
470*/
726f6388 471static int
7117c2d2 472brace_gobbler (text, tlen, indx, satisfy)
726f6388 473 char *text;
7117c2d2 474 size_t tlen;
726f6388
JA
475 int *indx;
476 int satisfy;
477{
0628567a 478 register int i, c, quoted, level, commas, pass_next;
d166f048
JA
479#if defined (SHELL)
480 int si;
481 char *t;
482#endif
7117c2d2 483 DECLARE_MBSTATE;
726f6388
JA
484
485 level = quoted = pass_next = 0;
0628567a
JA
486#if defined (CSH_BRACE_COMPAT)
487 commas = 1;
488#else
489 commas = (satisfy == '}') ? 0 : 1;
490#endif
726f6388 491
7117c2d2
JA
492 i = *indx;
493 while (c = text[i])
726f6388
JA
494 {
495 if (pass_next)
496 {
497 pass_next = 0;
7117c2d2 498 ADVANCE_CHAR (text, tlen, i);
726f6388
JA
499 continue;
500 }
501
502 /* A backslash escapes the next character. This allows backslash to
503 escape the quote character in a double-quoted string. */
504 if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
28ef6c31
JA
505 {
506 pass_next = 1;
7117c2d2 507 i++;
28ef6c31
JA
508 continue;
509 }
726f6388 510
b80f6443
JA
511#if defined (SHELL)
512 /* If compiling for the shell, treat ${...} like \{...} */
513 if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
514 {
515 pass_next = 1;
516 i++;
eb873671
JA
517 if (quoted == 0)
518 level++;
b80f6443
JA
519 continue;
520 }
521#endif
522
726f6388
JA
523 if (quoted)
524 {
525 if (c == quoted)
526 quoted = 0;
7117c2d2 527 ADVANCE_CHAR (text, tlen, i);
726f6388
JA
528 continue;
529 }
530
531 if (c == '"' || c == '\'' || c == '`')
532 {
533 quoted = c;
7117c2d2 534 i++;
726f6388
JA
535 continue;
536 }
ccc6cda3 537
d166f048 538#if defined (SHELL)
3185942a
JA
539 /* Pass new-style command and process substitutions through unchanged. */
540 if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
d166f048
JA
541 {
542 si = i + 2;
3185942a 543 t = extract_command_subst (text, &si, 0);
d166f048
JA
544 i = si;
545 free (t);
7117c2d2 546 i++;
d166f048
JA
547 continue;
548 }
549#endif
550
0628567a 551 if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
726f6388
JA
552 {
553 /* We ignore an open brace surrounded by whitespace, and also
ccc6cda3
JA
554 an open brace followed immediately by a close brace preceded
555 by whitespace. */
726f6388
JA
556 if (c == '{' &&
557 ((!i || brace_whitespace (text[i - 1])) &&
558 (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
7117c2d2
JA
559 {
560 i++;
561 continue;
562 }
b80f6443 563
726f6388
JA
564 break;
565 }
566
567 if (c == '{')
568 level++;
569 else if (c == '}' && level)
570 level--;
0628567a
JA
571#if !defined (CSH_BRACE_COMPAT)
572 else if (satisfy == '}' && c == brace_arg_separator && level == 0)
573 commas++;
574 else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) &&
575 text[i+2] != satisfy && level == 0)
576 commas++;
577#endif
7117c2d2
JA
578
579 ADVANCE_CHAR (text, tlen, i);
726f6388
JA
580 }
581
582 *indx = i;
583 return (c);
584}
585
586/* Return a new array of strings which is the result of appending each
587 string in ARR2 to each string in ARR1. The resultant array is
588 len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
589 are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
590 is returned. */
591static char **
592array_concat (arr1, arr2)
593 char **arr1, **arr2;
594{
595 register int i, j, len, len1, len2;
596 register char **result;
597
ccc6cda3 598 if (arr1 == 0)
7117c2d2 599 return (strvec_copy (arr2));
726f6388 600
ccc6cda3 601 if (arr2 == 0)
7117c2d2 602 return (strvec_copy (arr1));
726f6388 603
7117c2d2
JA
604 len1 = strvec_len (arr1);
605 len2 = strvec_len (arr2);
726f6388
JA
606
607 result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
608
609 len = 0;
610 for (i = 0; i < len1; i++)
611 {
612 int strlen_1 = strlen (arr1[i]);
613
614 for (j = 0; j < len2; j++)
615 {
b80f6443 616 result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
726f6388
JA
617 strcpy (result[len], arr1[i]);
618 strcpy (result[len] + strlen_1, arr2[j]);
619 len++;
620 }
621 free (arr1[i]);
622 }
623 free (arr1);
624
625 result[len] = (char *)NULL;
626 return (result);
627}
628
629#if defined (TEST)
630#include <stdio.h>
631
632fatal_error (format, arg1, arg2)
633 char *format, *arg1, *arg2;
634{
635 report_error (format, arg1, arg2);
636 exit (1);
637}
638
639report_error (format, arg1, arg2)
640 char *format, *arg1, *arg2;
641{
642 fprintf (stderr, format, arg1, arg2);
643 fprintf (stderr, "\n");
644}
645
646main ()
647{
648 char example[256];
649
650 for (;;)
651 {
652 char **result;
653 int i;
654
655 fprintf (stderr, "brace_expand> ");
656
657 if ((!fgets (example, 256, stdin)) ||
658 (strncmp (example, "quit", 4) == 0))
659 break;
660
661 if (strlen (example))
662 example[strlen (example) - 1] = '\0';
663
664 result = brace_expand (example);
665
666 for (i = 0; result[i]; i++)
667 printf ("%s\n", result[i]);
668
669 free_array (result);
670 }
671}
672\f
673/*
674 * Local variables:
675 * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
676 * end:
677 */
678
679#endif /* TEST */
ccc6cda3 680#endif /* BRACE_EXPANSION */