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