1 /* braces.c -- code for doing word expansion in curly braces. */
3 /* Copyright (C) 1987-2002 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>
43 #define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
47 Segregate the text into 3 sections: preamble (stuff before an open brace),
48 postamble (stuff after the matching close brace) and amble (stuff after
49 preamble, and before postamble). Expand amble, and then tack on the
50 expansions to preamble. Expand postamble, and tack on the expansions to
54 /* The character which is used to separate arguments. */
55 int brace_arg_separator = ',';
58 static int brace_gobbler __P((char *, size_t, int *, int));
59 static char **expand_amble __P((char *, size_t));
60 static char **array_concat __P((char **, char **));
62 static int brace_gobbler ();
63 static char **expand_amble ();
64 static char **array_concat ();
67 /* Return an array of strings; the brace expansion of TEXT. */
74 char *preamble, *postamble, *amble;
76 char **tack, **result;
81 /* Find the text of the preamble. */
84 c = brace_gobbler (text, tlen, &i, '{');
86 preamble = (char *)xmalloc (i + 1);
87 strncpy (preamble, text, i);
90 result = (char **)xmalloc (2 * sizeof (char *));
92 result[1] = (char *)NULL;
94 /* Special case. If we never found an exciting character, then
95 the preamble is all of the text, so just return that. */
99 /* Find the amble. This is the stuff inside this set of braces. */
101 c = brace_gobbler (text, tlen, &i, '}');
103 /* What if there isn't a matching close brace? */
107 /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
108 and I, then this should be an error. Otherwise, it isn't. */
115 ADVANCE_CHAR (text, tlen, j);
119 if (text[j] == brace_arg_separator)
121 strvec_dispose (result);
122 report_error ("missing `}'");
123 throw_to_top_level ();
125 ADVANCE_CHAR (text, tlen, j);
128 free (preamble); /* Same as result[0]; see initialization. */
129 result[0] = savestring (text);
134 amble = substring (text, start, i);
137 amble = (char *)xmalloc (1 + (i - start));
138 strncpy (amble, &text[start], (i - start));
146 /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
147 just return without doing any expansion. */
151 if (amble[j] == '\\')
154 ADVANCE_CHAR (amble, alen, j);
158 if (amble[j] == brace_arg_separator)
161 ADVANCE_CHAR (amble, alen, j);
168 result[0] = savestring (text);
173 postamble = &text[i + 1];
175 tack = expand_amble (amble, alen);
176 result = array_concat (result, tack);
178 strvec_dispose (tack);
180 tack = brace_expand (postamble);
181 result = array_concat (result, tack);
182 strvec_dispose (tack);
187 /* Expand the text found inside of braces. We simply try to split the
188 text at BRACE_ARG_SEPARATORs into separate strings. We then brace
189 expand each slot which needs it, until there are no more slots which
192 expand_amble (text, tlen)
196 char **result, **partial;
202 result = (char **)NULL;
208 c = brace_gobbler (text, tlen, &i, brace_arg_separator);
210 tem = substring (text, start, i);
212 tem = (char *)xmalloc (1 + (i - start));
213 strncpy (tem, &text[start], (i - start));
214 tem[i- start] = '\0';
217 partial = brace_expand (tem);
223 register int lr = strvec_len (result);
224 register int lp = strvec_len (partial);
227 result = strvec_resize (result, lp + lr + 1);
229 for (j = 0; j < lp; j++)
230 result[lr + j] = partial[j];
232 result[lr + j] = (char *)NULL;
236 ADVANCE_CHAR (text, tlen, i);
242 /* Start at INDEX, and skip characters in TEXT. Set INDEX to the
243 index of the character matching SATISFY. This understands about
244 quoting. Return the character that caused us to stop searching;
245 this is either the same as SATISFY, or 0. */
247 brace_gobbler (text, tlen, indx, satisfy)
253 register int i, c, quoted, level, pass_next;
260 level = quoted = pass_next = 0;
268 ADVANCE_CHAR (text, tlen, i);
272 /* A backslash escapes the next character. This allows backslash to
273 escape the quote character in a double-quoted string. */
274 if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
285 ADVANCE_CHAR (text, tlen, i);
289 if (c == '"' || c == '\'' || c == '`')
297 /* Pass new-style command substitutions through unchanged. */
298 if (c == '$' && text[i+1] == '(') /* ) */
301 t = extract_command_subst (text, &si);
309 if (c == satisfy && level == 0 && quoted == 0)
311 /* We ignore an open brace surrounded by whitespace, and also
312 an open brace followed immediately by a close brace preceded
315 ((!i || brace_whitespace (text[i - 1])) &&
316 (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
322 /* If this is being compiled as part of bash, ignore the `{'
323 in a `${}' construct */
324 if ((c != '{') || i == 0 || (text[i - 1] != '$'))
331 else if (c == '}' && level)
334 ADVANCE_CHAR (text, tlen, i);
341 /* Return a new array of strings which is the result of appending each
342 string in ARR2 to each string in ARR1. The resultant array is
343 len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
344 are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
347 array_concat (arr1, arr2)
350 register int i, j, len, len1, len2;
351 register char **result;
354 return (strvec_copy (arr2));
357 return (strvec_copy (arr1));
359 len1 = strvec_len (arr1);
360 len2 = strvec_len (arr2);
362 result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
365 for (i = 0; i < len1; i++)
367 int strlen_1 = strlen (arr1[i]);
369 for (j = 0; j < len2; j++)
372 (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
373 strcpy (result[len], arr1[i]);
374 strcpy (result[len] + strlen_1, arr2[j]);
381 result[len] = (char *)NULL;
388 fatal_error (format, arg1, arg2)
389 char *format, *arg1, *arg2;
391 report_error (format, arg1, arg2);
395 report_error (format, arg1, arg2)
396 char *format, *arg1, *arg2;
398 fprintf (stderr, format, arg1, arg2);
399 fprintf (stderr, "\n");
411 fprintf (stderr, "brace_expand> ");
413 if ((!fgets (example, 256, stdin)) ||
414 (strncmp (example, "quit", 4) == 0))
417 if (strlen (example))
418 example[strlen (example) - 1] = '\0';
420 result = brace_expand (example);
422 for (i = 0; result[i]; i++)
423 printf ("%s\n", result[i]);
431 * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
436 #endif /* BRACE_EXPANSION */