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