1 /* braces.c -- code for doing word expansion in curly braces. */
3 /* Copyright (C) 1987-2003 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 Bash is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21 /* Stuff in curly braces gets expanded before all other shell expansions. */
25 #if defined (BRACE_EXPANSION)
27 #if defined (HAVE_UNISTD_H)
29 # include <sys/types.h>
42 #include "chartypes.h"
44 #define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
46 #define BRACE_SEQ_SPECIFIER ".."
50 Segregate the text into 3 sections: preamble (stuff before an open brace),
51 postamble (stuff after the matching close brace) and amble (stuff after
52 preamble, and before postamble). Expand amble, and then tack on the
53 expansions to preamble. Expand postamble, and tack on the expansions to
57 /* The character which is used to separate arguments. */
58 int brace_arg_separator
= ',';
61 static int brace_gobbler
__P((char *, size_t, int *, int));
62 static char **expand_amble
__P((char *, size_t, int));
63 static char **expand_seqterm
__P((char *, size_t));
64 static char **mkseq
__P((int, int, int, int));
65 static char **array_concat
__P((char **, char **));
67 static int brace_gobbler ();
68 static char **expand_amble ();
69 static char **expand_seqterm ();
70 static char **mkseq();
71 static char **array_concat ();
81 for (i
= 0; a
[i
]; i
++)
82 printf ("dump_result: a[%d] = -%s-\n", i
, a
[i
]);
86 /* Return an array of strings; the brace expansion of TEXT. */
93 char *preamble
, *postamble
, *amble
;
95 char **tack
, **result
;
100 /* Find the text of the preamble. */
101 tlen
= strlen (text
);
103 #if defined (CSH_BRACE_COMPAT)
104 c
= brace_gobbler (text
, tlen
, &i
, '{'); /* } */
106 /* Make sure that when we exit this loop, c == 0 or text[i] begins a
107 valid brace expansion sequence. */
110 c
= brace_gobbler (text
, tlen
, &i
, '{'); /* } */
112 /* Verify that c begins a valid brace expansion word. If it doesn't, we
113 go on. Loop stops when there are no more open braces in the word. */
116 start
= j
= i
+ 1; /* { */
117 c
= brace_gobbler (text
, tlen
, &j
, '}');
118 if (c
== 0) /* it's not */
134 #endif /* !CSH_BRACE_COMPAT */
136 preamble
= (char *)xmalloc (i
+ 1);
137 strncpy (preamble
, text
, i
);
140 result
= (char **)xmalloc (2 * sizeof (char *));
141 result
[0] = preamble
;
142 result
[1] = (char *)NULL
;
144 /* Special case. If we never found an exciting character, then
145 the preamble is all of the text, so just return that. */
149 /* Find the amble. This is the stuff inside this set of braces. */
151 c
= brace_gobbler (text
, tlen
, &i
, '}');
153 /* What if there isn't a matching close brace? */
157 /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
158 and I, then this should be an error. Otherwise, it isn't. */
165 ADVANCE_CHAR (text
, tlen
, j
);
169 if (text
[j
] == brace_arg_separator
)
171 strvec_dispose (result
);
172 report_error ("no closing `%c' in %s", '}', text
);
173 throw_to_top_level ();
175 ADVANCE_CHAR (text
, tlen
, j
);
178 free (preamble
); /* Same as result[0]; see initialization. */
179 result
[0] = savestring (text
);
184 amble
= substring (text
, start
, i
);
187 amble
= (char *)xmalloc (1 + (i
- start
));
188 strncpy (amble
, &text
[start
], (i
- start
));
196 /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
197 just return without doing any expansion. */
201 if (amble
[j
] == '\\')
204 ADVANCE_CHAR (amble
, alen
, j
);
208 if (amble
[j
] == brace_arg_separator
)
211 ADVANCE_CHAR (amble
, alen
, j
);
216 tack
= expand_seqterm (amble
, alen
);
223 result
[0] = savestring (text
);
229 tack
= expand_amble (amble
, alen
, 0);
231 result
= array_concat (result
, tack
);
233 strvec_dispose (tack
);
235 postamble
= text
+ i
+ 1;
237 tack
= brace_expand (postamble
);
238 result
= array_concat (result
, tack
);
239 strvec_dispose (tack
);
244 /* Expand the text found inside of braces. We simply try to split the
245 text at BRACE_ARG_SEPARATORs into separate strings. We then brace
246 expand each slot which needs it, until there are no more slots which
249 expand_amble (text
, tlen
, flags
)
254 char **result
, **partial
;
260 result
= (char **)NULL
;
266 c
= brace_gobbler (text
, tlen
, &i
, brace_arg_separator
);
268 tem
= substring (text
, start
, i
);
270 tem
= (char *)xmalloc (1 + (i
- start
));
271 strncpy (tem
, &text
[start
], (i
- start
));
272 tem
[i
- start
] = '\0';
275 partial
= brace_expand (tem
);
281 register int lr
, lp
, j
;
283 lr
= strvec_len (result
);
284 lp
= strvec_len (partial
);
286 result
= strvec_resize (result
, lp
+ lr
+ 1);
288 for (j
= 0; j
< lp
; j
++)
289 result
[lr
+ j
] = partial
[j
];
291 result
[lr
+ j
] = (char *)NULL
;
295 ADVANCE_CHAR (text
, tlen
, i
);
306 mkseq (start
, end
, incr
, type
)
307 int start
, end
, incr
, type
;
312 n
= abs (end
- start
) + 1;
313 result
= strvec_create (n
+ 1);
318 if (start
> end
&& incr
> 0)
320 else if (start
< end
&& incr
< 0)
323 /* Make sure we go through the loop at least once, so {3..3} prints `3' */
329 QUIT
; /* XXX - memory leak here */
332 result
[i
++] = itos (n
);
335 t
= (char *)xmalloc (2);
346 result
[i
] = (char *)0;
351 expand_seqterm (text
, tlen
)
356 int i
, lhs_t
, rhs_t
, lhs_v
, rhs_v
;
360 t
= strstr (text
, BRACE_SEQ_SPECIFIER
);
362 return ((char **)NULL
);
364 i
= t
- text
; /* index of start of BRACE_SEQ_SPECIFIER */
365 lhs
= substring (text
, 0, i
);
366 rhs
= substring (text
, i
+ sizeof(BRACE_SEQ_SPECIFIER
) - 1, tlen
);
368 if (lhs
[0] == 0 || rhs
[0] == 0)
372 return ((char **)NULL
);
375 /* Now figure out whether LHS and RHS are integers or letters. Both
376 sides have to match. */
377 lhs_t
= (legal_number (lhs
, &tl
)) ? ST_INT
:
378 ((ISALPHA (lhs
[0]) && lhs
[1] == 0) ? ST_CHAR
: ST_BAD
);
379 rhs_t
= (legal_number (rhs
, &tr
)) ? ST_INT
:
380 ((ISALPHA (rhs
[0]) && rhs
[1] == 0) ? ST_CHAR
: ST_BAD
);
382 if (lhs_t
!= rhs_t
|| lhs_t
== ST_BAD
|| rhs_t
== ST_BAD
)
386 return ((char **)NULL
);
389 /* OK, we have something. It's either a sequence of integers, ascending
390 or descending, or a sequence or letters, ditto. Generate the sequence,
391 put it into a string vector, and return it. */
393 if (lhs_t
== ST_CHAR
)
395 lhs_v
= (unsigned char)lhs
[0];
396 rhs_v
= (unsigned char)rhs
[0];
400 lhs_v
= tl
; /* integer truncation */
404 result
= mkseq (lhs_v
, rhs_v
, 1, lhs_t
);
412 /* Start at INDEX, and skip characters in TEXT. Set INDEX to the
413 index of the character matching SATISFY. This understands about
414 quoting. Return the character that caused us to stop searching;
415 this is either the same as SATISFY, or 0. */
416 /* If SATISFY is `}', we are looking for a brace expression, so we
417 should enforce the rules that govern valid brace expansions:
418 1) to count as an arg separator, a comma or `..' has to be outside
419 an inner set of braces.
422 brace_gobbler (text
, tlen
, indx
, satisfy
)
428 register int i
, c
, quoted
, level
, commas
, pass_next
;
435 level
= quoted
= pass_next
= 0;
436 #if defined (CSH_BRACE_COMPAT)
439 commas
= (satisfy
== '}') ? 0 : 1;
448 ADVANCE_CHAR (text
, tlen
, i
);
452 /* A backslash escapes the next character. This allows backslash to
453 escape the quote character in a double-quoted string. */
454 if (c
== '\\' && (quoted
== 0 || quoted
== '"' || quoted
== '`'))
462 /* If compiling for the shell, treat ${...} like \{...} */
463 if (c
== '$' && text
[i
+1] == '{' && quoted
!= '\'') /* } */
477 ADVANCE_CHAR (text
, tlen
, i
);
481 if (c
== '"' || c
== '\'' || c
== '`')
489 /* Pass new-style command substitutions through unchanged. */
490 if (c
== '$' && text
[i
+1] == '(') /* ) */
493 t
= extract_command_subst (text
, &si
);
501 if (c
== satisfy
&& level
== 0 && quoted
== 0 && commas
> 0)
503 /* We ignore an open brace surrounded by whitespace, and also
504 an open brace followed immediately by a close brace preceded
507 ((!i
|| brace_whitespace (text
[i
- 1])) &&
508 (brace_whitespace (text
[i
+ 1]) || text
[i
+ 1] == '}')))
519 else if (c
== '}' && level
)
521 #if !defined (CSH_BRACE_COMPAT)
522 else if (satisfy
== '}' && c
== brace_arg_separator
&& level
== 0)
524 else if (satisfy
== '}' && STREQN (text
+i
, BRACE_SEQ_SPECIFIER
, 2) &&
525 text
[i
+2] != satisfy
&& level
== 0)
529 ADVANCE_CHAR (text
, tlen
, i
);
536 /* Return a new array of strings which is the result of appending each
537 string in ARR2 to each string in ARR1. The resultant array is
538 len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
539 are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
542 array_concat (arr1
, arr2
)
545 register int i
, j
, len
, len1
, len2
;
546 register char **result
;
549 return (strvec_copy (arr2
));
552 return (strvec_copy (arr1
));
554 len1
= strvec_len (arr1
);
555 len2
= strvec_len (arr2
);
557 result
= (char **)xmalloc ((1 + (len1
* len2
)) * sizeof (char *));
560 for (i
= 0; i
< len1
; i
++)
562 int strlen_1
= strlen (arr1
[i
]);
564 for (j
= 0; j
< len2
; j
++)
566 result
[len
] = (char *)xmalloc (1 + strlen_1
+ strlen (arr2
[j
]));
567 strcpy (result
[len
], arr1
[i
]);
568 strcpy (result
[len
] + strlen_1
, arr2
[j
]);
575 result
[len
] = (char *)NULL
;
582 fatal_error (format
, arg1
, arg2
)
583 char *format
, *arg1
, *arg2
;
585 report_error (format
, arg1
, arg2
);
589 report_error (format
, arg1
, arg2
)
590 char *format
, *arg1
, *arg2
;
592 fprintf (stderr
, format
, arg1
, arg2
);
593 fprintf (stderr
, "\n");
605 fprintf (stderr
, "brace_expand> ");
607 if ((!fgets (example
, 256, stdin
)) ||
608 (strncmp (example
, "quit", 4) == 0))
611 if (strlen (example
))
612 example
[strlen (example
) - 1] = '\0';
614 result
= brace_expand (example
);
616 for (i
= 0; result
[i
]; i
++)
617 printf ("%s\n", result
[i
]);
625 * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
630 #endif /* BRACE_EXPANSION */