]> git.ipfire.org Git - thirdparty/bash.git/blob - braces.c
Bash-4.3 patch 32
[thirdparty/bash.git] / braces.c
1 /* braces.c -- code for doing word expansion in curly braces. */
2
3 /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
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.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /* Stuff in curly braces gets expanded before all other shell expansions. */
22
23 #include "config.h"
24
25 #if defined (BRACE_EXPANSION)
26
27 #if defined (HAVE_UNISTD_H)
28 # ifdef _MINIX
29 # include <sys/types.h>
30 # endif
31 # include <unistd.h>
32 #endif
33
34 #include <errno.h>
35
36 #include "bashansi.h"
37 #include "bashintl.h"
38
39 #if defined (SHELL)
40 # include "shell.h"
41 #endif /* SHELL */
42
43 #include "typemax.h" /* INTMAX_MIN, INTMAX_MAX */
44 #include "general.h"
45 #include "shmbutil.h"
46 #include "chartypes.h"
47
48 #ifndef errno
49 extern int errno;
50 #endif
51
52 #define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
53
54 #define BRACE_SEQ_SPECIFIER ".."
55
56 extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
57
58 extern int last_command_exit_value;
59
60 /* Basic idea:
61
62 Segregate the text into 3 sections: preamble (stuff before an open brace),
63 postamble (stuff after the matching close brace) and amble (stuff after
64 preamble, and before postamble). Expand amble, and then tack on the
65 expansions to preamble. Expand postamble, and tack on the expansions to
66 the result so far.
67 */
68
69 /* The character which is used to separate arguments. */
70 static const int brace_arg_separator = ',';
71
72 #if defined (__P)
73 static int brace_gobbler __P((char *, size_t, int *, int));
74 static char **expand_amble __P((char *, size_t, int));
75 static char **expand_seqterm __P((char *, size_t));
76 static char **mkseq __P((intmax_t, intmax_t, intmax_t, int, int));
77 static char **array_concat __P((char **, char **));
78 #else
79 static int brace_gobbler ();
80 static char **expand_amble ();
81 static char **expand_seqterm ();
82 static char **mkseq();
83 static char **array_concat ();
84 #endif
85
86 #if 0
87 static void
88 dump_result (a)
89 char **a;
90 {
91 int i;
92
93 for (i = 0; a[i]; i++)
94 printf ("dump_result: a[%d] = -%s-\n", i, a[i]);
95 }
96 #endif
97
98 /* Return an array of strings; the brace expansion of TEXT. */
99 char **
100 brace_expand (text)
101 char *text;
102 {
103 register int start;
104 size_t tlen;
105 char *preamble, *postamble, *amble;
106 size_t alen;
107 char **tack, **result;
108 int i, j, c, c1;
109
110 DECLARE_MBSTATE;
111
112 /* Find the text of the preamble. */
113 tlen = strlen (text);
114 i = 0;
115 #if defined (CSH_BRACE_COMPAT)
116 c = brace_gobbler (text, tlen, &i, '{'); /* } */
117 #else
118 /* Make sure that when we exit this loop, c == 0 or text[i] begins a
119 valid brace expansion sequence. */
120 do
121 {
122 c = brace_gobbler (text, tlen, &i, '{'); /* } */
123 c1 = c;
124 /* Verify that c begins a valid brace expansion word. If it doesn't, we
125 go on. Loop stops when there are no more open braces in the word. */
126 if (c)
127 {
128 start = j = i + 1; /* { */
129 c = brace_gobbler (text, tlen, &j, '}');
130 if (c == 0) /* it's not */
131 {
132 i++;
133 c = c1;
134 continue;
135 }
136 else /* it is */
137 {
138 c = c1;
139 break;
140 }
141 }
142 else
143 break;
144 }
145 while (c);
146 #endif /* !CSH_BRACE_COMPAT */
147
148 preamble = (char *)xmalloc (i + 1);
149 if (i > 0)
150 strncpy (preamble, text, i);
151 preamble[i] = '\0';
152
153 result = (char **)xmalloc (2 * sizeof (char *));
154 result[0] = preamble;
155 result[1] = (char *)NULL;
156
157 /* Special case. If we never found an exciting character, then
158 the preamble is all of the text, so just return that. */
159 if (c != '{')
160 return (result);
161
162 /* Find the amble. This is the stuff inside this set of braces. */
163 start = ++i;
164 c = brace_gobbler (text, tlen, &i, '}');
165
166 /* What if there isn't a matching close brace? */
167 if (c == 0)
168 {
169 #if defined (NOTDEF)
170 /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
171 and I, then this should be an error. Otherwise, it isn't. */
172 j = start;
173 while (j < i)
174 {
175 if (text[j] == '\\')
176 {
177 j++;
178 ADVANCE_CHAR (text, tlen, j);
179 continue;
180 }
181
182 if (text[j] == brace_arg_separator)
183 { /* { */
184 strvec_dispose (result);
185 last_command_exit_value = 1;
186 report_error ("no closing `%c' in %s", '}', text);
187 throw_to_top_level ();
188 }
189 ADVANCE_CHAR (text, tlen, j);
190 }
191 #endif
192 free (preamble); /* Same as result[0]; see initialization. */
193 result[0] = savestring (text);
194 return (result);
195 }
196
197 #if defined (SHELL)
198 amble = substring (text, start, i);
199 alen = i - start;
200 #else
201 amble = (char *)xmalloc (1 + (i - start));
202 strncpy (amble, &text[start], (i - start));
203 alen = i - start;
204 amble[alen] = '\0';
205 #endif
206
207 #if defined (SHELL)
208 INITIALIZE_MBSTATE;
209
210 /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
211 just return without doing any expansion. */
212 j = 0;
213 while (amble[j])
214 {
215 if (amble[j] == '\\')
216 {
217 j++;
218 ADVANCE_CHAR (amble, alen, j);
219 continue;
220 }
221
222 if (amble[j] == brace_arg_separator)
223 break;
224
225 ADVANCE_CHAR (amble, alen, j);
226 }
227
228 if (amble[j] == 0)
229 {
230 tack = expand_seqterm (amble, alen);
231 if (tack)
232 goto add_tack;
233 else if (text[i + 1])
234 {
235 /* If the sequence expansion fails (e.g., because the integers
236 overflow), but there is more in the string, try and process
237 the rest of the string, which may contain additional brace
238 expansions. Treat the unexpanded sequence term as a simple
239 string (including the braces). */
240 tack = strvec_create (2);
241 tack[0] = savestring (text+start-1);
242 tack[0][i-start+2] = '\0';
243 tack[1] = (char *)0;
244 goto add_tack;
245 }
246 else
247 {
248 free (amble);
249 free (preamble);
250 result[0] = savestring (text);
251 return (result);
252 }
253 }
254 #endif /* SHELL */
255
256 tack = expand_amble (amble, alen, 0);
257 add_tack:
258 result = array_concat (result, tack);
259 free (amble);
260 if (tack != result)
261 strvec_dispose (tack);
262
263 postamble = text + i + 1;
264
265 if (postamble && *postamble)
266 {
267 tack = brace_expand (postamble);
268 result = array_concat (result, tack);
269 if (tack != result)
270 strvec_dispose (tack);
271 }
272
273 return (result);
274 }
275
276 /* Expand the text found inside of braces. We simply try to split the
277 text at BRACE_ARG_SEPARATORs into separate strings. We then brace
278 expand each slot which needs it, until there are no more slots which
279 need it. */
280 static char **
281 expand_amble (text, tlen, flags)
282 char *text;
283 size_t tlen;
284 int flags;
285 {
286 char **result, **partial, **tresult;
287 char *tem;
288 int start, i, c;
289
290 DECLARE_MBSTATE;
291
292 result = (char **)NULL;
293
294 start = i = 0;
295 c = 1;
296 while (c)
297 {
298 c = brace_gobbler (text, tlen, &i, brace_arg_separator);
299 #if defined (SHELL)
300 tem = substring (text, start, i);
301 #else
302 tem = (char *)xmalloc (1 + (i - start));
303 strncpy (tem, &text[start], (i - start));
304 tem[i- start] = '\0';
305 #endif
306
307 partial = brace_expand (tem);
308
309 if (!result)
310 result = partial;
311 else
312 {
313 register int lr, lp, j;
314
315 lr = strvec_len (result);
316 lp = strvec_len (partial);
317
318 tresult = strvec_mresize (result, lp + lr + 1);
319 if (tresult == 0)
320 {
321 internal_error (_("brace expansion: cannot allocate memory for %s"), tem);
322 strvec_dispose (result);
323 result = (char **)NULL;
324 return result;
325 }
326 else
327 result = tresult;
328
329 for (j = 0; j < lp; j++)
330 result[lr + j] = partial[j];
331
332 result[lr + j] = (char *)NULL;
333 free (partial);
334 }
335 free (tem);
336 ADVANCE_CHAR (text, tlen, i);
337 start = i;
338 }
339 return (result);
340 }
341
342 #define ST_BAD 0
343 #define ST_INT 1
344 #define ST_CHAR 2
345 #define ST_ZINT 3
346
347 #ifndef sh_imaxabs
348 # define sh_imaxabs(x) (((x) >= 0) ? (x) : -(x))
349 #endif
350
351 /* Handle signed arithmetic overflow and underflow. Have to do it this way
352 to avoid compilers optimizing out simpler overflow checks. */
353
354 /* Make sure that a+b does not exceed MAXV or is smaller than MINV (if b < 0).
355 Assumes that b > 0 if a > 0 and b < 0 if a < 0 */
356 #define ADDOVERFLOW(a,b,minv,maxv) \
357 ((((a) > 0) && ((b) > ((maxv) - (a)))) || \
358 (((a) < 0) && ((b) < ((minv) - (a)))))
359
360 /* Make sure that a-b is not smaller than MINV or exceeds MAXV (if b < 0).
361 Assumes that b > 0 if a > 0 and b < 0 if a < 0 */
362 #define SUBOVERFLOW(a,b,minv,maxv) \
363 ((((b) > 0) && ((a) < ((minv) + (b)))) || \
364 (((b) < 0) && ((a) > ((maxv) + (b)))))
365
366 static char **
367 mkseq (start, end, incr, type, width)
368 intmax_t start, end, incr;
369 int type, width;
370 {
371 intmax_t n, prevn;
372 int i, j, nelem;
373 char **result, *t;
374
375 if (incr == 0)
376 incr = 1;
377
378 if (start > end && incr > 0)
379 incr = -incr;
380 else if (start < end && incr < 0)
381 {
382 if (incr == INTMAX_MIN) /* Don't use -INTMAX_MIN */
383 return ((char **)NULL);
384 incr = -incr;
385 }
386
387 /* Check that end-start will not overflow INTMAX_MIN, INTMAX_MAX. The +3
388 and -2, not strictly necessary, are there because of the way the number
389 of elements and value passed to strvec_create() are calculated below. */
390 if (SUBOVERFLOW (end, start, INTMAX_MIN+3, INTMAX_MAX-2))
391 return ((char **)NULL);
392
393 prevn = sh_imaxabs (end - start);
394 /* Need to check this way in case INT_MAX == INTMAX_MAX */
395 if (INT_MAX == INTMAX_MAX && (ADDOVERFLOW (prevn, 2, INT_MIN, INT_MAX)))
396 return ((char **)NULL);
397 /* Make sure the assignment to nelem below doesn't end up <= 0 due to
398 intmax_t overflow */
399 else if (ADDOVERFLOW ((prevn/sh_imaxabs(incr)), 1, INTMAX_MIN, INTMAX_MAX))
400 return ((char **)NULL);
401
402 /* XXX - TOFIX: potentially allocating a lot of extra memory if
403 imaxabs(incr) != 1 */
404 /* Instead of a simple nelem = prevn + 1, something like:
405 nelem = (prevn / imaxabs(incr)) + 1;
406 would work */
407 nelem = (prevn / sh_imaxabs(incr)) + 1;
408 if (nelem > INT_MAX - 2) /* Don't overflow int */
409 return ((char **)NULL);
410 result = strvec_mcreate (nelem + 1);
411 if (result == 0)
412 {
413 internal_error (_("brace expansion: failed to allocate memory for %d elements"), nelem);
414 return ((char **)NULL);
415 }
416
417 /* Make sure we go through the loop at least once, so {3..3} prints `3' */
418 i = 0;
419 n = start;
420 do
421 {
422 #if defined (SHELL)
423 QUIT; /* XXX - memory leak here */
424 #endif
425 if (type == ST_INT)
426 result[i++] = t = itos (n);
427 else if (type == ST_ZINT)
428 {
429 int len, arg;
430 arg = n;
431 len = asprintf (&t, "%0*d", width, arg);
432 result[i++] = t;
433 }
434 else
435 {
436 if (t = (char *)malloc (2))
437 {
438 t[0] = n;
439 t[1] = '\0';
440 }
441 result[i++] = t;
442 }
443
444 /* We failed to allocate memory for this number, so we bail. */
445 if (t == 0)
446 {
447 char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
448
449 /* Easier to do this than mess around with various intmax_t printf
450 formats (%ld? %lld? %jd?) and PRIdMAX. */
451 p = inttostr (n, lbuf, sizeof (lbuf));
452 internal_error (_("brace expansion: failed to allocate memory for `%s'"), p);
453 strvec_dispose (result);
454 return ((char **)NULL);
455 }
456
457 /* Handle overflow and underflow of n+incr */
458 if (ADDOVERFLOW (n, incr, INTMAX_MIN, INTMAX_MAX))
459 break;
460
461 n += incr;
462
463 if ((incr < 0 && n < end) || (incr > 0 && n > end))
464 break;
465 }
466 while (1);
467
468 result[i] = (char *)0;
469 return (result);
470 }
471
472 static char **
473 expand_seqterm (text, tlen)
474 char *text;
475 size_t tlen;
476 {
477 char *t, *lhs, *rhs;
478 int i, lhs_t, rhs_t, lhs_l, rhs_l, width;
479 intmax_t lhs_v, rhs_v, incr;
480 intmax_t tl, tr;
481 char **result, *ep, *oep;
482
483 t = strstr (text, BRACE_SEQ_SPECIFIER);
484 if (t == 0)
485 return ((char **)NULL);
486
487 lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
488 lhs = substring (text, 0, lhs_l);
489 rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
490
491 if (lhs[0] == 0 || rhs[0] == 0)
492 {
493 free (lhs);
494 free (rhs);
495 return ((char **)NULL);
496 }
497
498 /* Now figure out whether LHS and RHS are integers or letters. Both
499 sides have to match. */
500 lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
501 ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
502
503 /* Decide on rhs and whether or not it looks like the user specified
504 an increment */
505 ep = 0;
506 if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
507 {
508 rhs_t = ST_INT;
509 errno = 0;
510 tr = strtoimax (rhs, &ep, 10);
511 if (errno == ERANGE || (ep && *ep != 0 && *ep != '.'))
512 rhs_t = ST_BAD; /* invalid */
513 }
514 else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
515 {
516 rhs_t = ST_CHAR;
517 ep = rhs + 1;
518 }
519 else
520 {
521 rhs_t = ST_BAD;
522 ep = 0;
523 }
524
525 incr = 1;
526 if (rhs_t != ST_BAD)
527 {
528 oep = ep;
529 errno = 0;
530 if (ep && *ep == '.' && ep[1] == '.' && ep[2])
531 incr = strtoimax (ep + 2, &ep, 10);
532 if (*ep != 0 || errno == ERANGE)
533 rhs_t = ST_BAD; /* invalid incr or overflow */
534 tlen -= ep - oep;
535 }
536
537 if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
538 {
539 free (lhs);
540 free (rhs);
541 return ((char **)NULL);
542 }
543
544 /* OK, we have something. It's either a sequence of integers, ascending
545 or descending, or a sequence or letters, ditto. Generate the sequence,
546 put it into a string vector, and return it. */
547
548 if (lhs_t == ST_CHAR)
549 {
550 lhs_v = (unsigned char)lhs[0];
551 rhs_v = (unsigned char)rhs[0];
552 width = 1;
553 }
554 else
555 {
556 lhs_v = tl; /* integer truncation */
557 rhs_v = tr;
558
559 /* Decide whether or not the terms need zero-padding */
560 rhs_l = tlen - lhs_l - sizeof (BRACE_SEQ_SPECIFIER) + 1;
561 width = 0;
562 if (lhs_l > 1 && lhs[0] == '0')
563 width = lhs_l, lhs_t = ST_ZINT;
564 if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
565 width = lhs_l, lhs_t = ST_ZINT;
566 if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
567 width = rhs_l, lhs_t = ST_ZINT;
568 if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
569 width = rhs_l, lhs_t = ST_ZINT;
570
571 if (width < lhs_l && lhs_t == ST_ZINT)
572 width = lhs_l;
573 if (width < rhs_l && lhs_t == ST_ZINT)
574 width = rhs_l;
575 }
576
577 result = mkseq (lhs_v, rhs_v, incr, lhs_t, width);
578
579 free (lhs);
580 free (rhs);
581
582 return (result);
583 }
584
585 /* Start at INDEX, and skip characters in TEXT. Set INDEX to the
586 index of the character matching SATISFY. This understands about
587 quoting. Return the character that caused us to stop searching;
588 this is either the same as SATISFY, or 0. */
589 /* If SATISFY is `}', we are looking for a brace expression, so we
590 should enforce the rules that govern valid brace expansions:
591 1) to count as an arg separator, a comma or `..' has to be outside
592 an inner set of braces.
593 */
594 static int
595 brace_gobbler (text, tlen, indx, satisfy)
596 char *text;
597 size_t tlen;
598 int *indx;
599 int satisfy;
600 {
601 register int i, c, quoted, level, commas, pass_next;
602 #if defined (SHELL)
603 int si;
604 char *t;
605 #endif
606 DECLARE_MBSTATE;
607
608 level = quoted = pass_next = 0;
609 #if defined (CSH_BRACE_COMPAT)
610 commas = 1;
611 #else
612 commas = (satisfy == '}') ? 0 : 1;
613 #endif
614
615 i = *indx;
616 while (c = text[i])
617 {
618 if (pass_next)
619 {
620 pass_next = 0;
621 ADVANCE_CHAR (text, tlen, i);
622 continue;
623 }
624
625 /* A backslash escapes the next character. This allows backslash to
626 escape the quote character in a double-quoted string. */
627 if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
628 {
629 pass_next = 1;
630 i++;
631 continue;
632 }
633
634 #if defined (SHELL)
635 /* If compiling for the shell, treat ${...} like \{...} */
636 if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
637 {
638 pass_next = 1;
639 i++;
640 if (quoted == 0)
641 level++;
642 continue;
643 }
644 #endif
645
646 if (quoted)
647 {
648 if (c == quoted)
649 quoted = 0;
650 #if defined (SHELL)
651 /* The shell allows quoted command substitutions */
652 if (quoted == '"' && c == '$' && text[i+1] == '(') /*)*/
653 goto comsub;
654 #endif
655 ADVANCE_CHAR (text, tlen, i);
656 continue;
657 }
658
659 if (c == '"' || c == '\'' || c == '`')
660 {
661 quoted = c;
662 i++;
663 continue;
664 }
665
666 #if defined (SHELL)
667 /* Pass new-style command and process substitutions through unchanged. */
668 if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
669 {
670 comsub:
671 si = i + 2;
672 t = extract_command_subst (text, &si, 0);
673 i = si;
674 free (t);
675 i++;
676 continue;
677 }
678 #endif
679
680 if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
681 {
682 /* We ignore an open brace surrounded by whitespace, and also
683 an open brace followed immediately by a close brace preceded
684 by whitespace. */
685 if (c == '{' &&
686 ((!i || brace_whitespace (text[i - 1])) &&
687 (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
688 {
689 i++;
690 continue;
691 }
692
693 break;
694 }
695
696 if (c == '{')
697 level++;
698 else if (c == '}' && level)
699 level--;
700 #if !defined (CSH_BRACE_COMPAT)
701 else if (satisfy == '}' && c == brace_arg_separator && level == 0)
702 commas++;
703 else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) &&
704 text[i+2] != satisfy && level == 0)
705 commas++;
706 #endif
707
708 ADVANCE_CHAR (text, tlen, i);
709 }
710
711 *indx = i;
712 return (c);
713 }
714
715 /* Return 1 if ARR has any non-empty-string members. Used to short-circuit
716 in array_concat() below. */
717 static int
718 degenerate_array (arr)
719 char **arr;
720 {
721 register int i;
722
723 for (i = 0; arr[i]; i++)
724 if (arr[i][0] != '\0')
725 return 0;
726 return 1;
727 }
728
729 /* Return a new array of strings which is the result of appending each
730 string in ARR2 to each string in ARR1. The resultant array is
731 len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
732 are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
733 is returned. */
734 static char **
735 array_concat (arr1, arr2)
736 char **arr1, **arr2;
737 {
738 register int i, j, len, len1, len2;
739 register char **result;
740
741 if (arr1 == 0)
742 return (arr2); /* XXX - see if we can get away without copying? */
743
744 if (arr2 == 0)
745 return (arr1); /* XXX - caller expects us to free arr1 */
746
747 /* We can only short-circuit if the array consists of a single null element;
748 otherwise we need to replicate the contents of the other array and
749 prefix (or append, below) an empty element to each one. */
750 if (arr1[0] && arr1[0][0] == 0 && arr1[1] == 0)
751 {
752 strvec_dispose (arr1);
753 return (arr2); /* XXX - use flags to see if we can avoid copying here */
754 }
755
756 if (arr2[0] && arr2[0][0] == 0 && arr2[1] == 0)
757 return (arr1); /* XXX - rather than copying and freeing it */
758
759 len1 = strvec_len (arr1);
760 len2 = strvec_len (arr2);
761
762 result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
763
764 len = 0;
765 for (i = 0; i < len1; i++)
766 {
767 int strlen_1 = strlen (arr1[i]);
768
769 for (j = 0; j < len2; j++)
770 {
771 result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
772 strcpy (result[len], arr1[i]);
773 strcpy (result[len] + strlen_1, arr2[j]);
774 len++;
775 }
776 free (arr1[i]);
777 }
778 free (arr1);
779
780 result[len] = (char *)NULL;
781 return (result);
782 }
783
784 #if defined (TEST)
785 #include <stdio.h>
786
787 fatal_error (format, arg1, arg2)
788 char *format, *arg1, *arg2;
789 {
790 report_error (format, arg1, arg2);
791 exit (1);
792 }
793
794 report_error (format, arg1, arg2)
795 char *format, *arg1, *arg2;
796 {
797 fprintf (stderr, format, arg1, arg2);
798 fprintf (stderr, "\n");
799 }
800
801 main ()
802 {
803 char example[256];
804
805 for (;;)
806 {
807 char **result;
808 int i;
809
810 fprintf (stderr, "brace_expand> ");
811
812 if ((!fgets (example, 256, stdin)) ||
813 (strncmp (example, "quit", 4) == 0))
814 break;
815
816 if (strlen (example))
817 example[strlen (example) - 1] = '\0';
818
819 result = brace_expand (example);
820
821 for (i = 0; result[i]; i++)
822 printf ("%s\n", result[i]);
823
824 free_array (result);
825 }
826 }
827 \f
828 /*
829 * Local variables:
830 * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
831 * end:
832 */
833
834 #endif /* TEST */
835 #endif /* BRACE_EXPANSION */