blob: e91d326ea42d39b3f0cabc9dd0e21d7c597e62a0 [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001/* braces.c -- code for doing word expansion in curly braces. */
2
Chet Ramey8868eda2020-12-06 15:51:17 -05003/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00004
5 This file is part of GNU Bash, the Bourne Again SHell.
6
Jari Aalto31859422009-01-12 13:36:28 +00007 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.
Jari Aalto726f6381996-08-26 18:22:31 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 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.
Jari Aalto726f6381996-08-26 18:22:31 +000016
17 You should have received a copy of the GNU General Public License
Jari Aalto31859422009-01-12 13:36:28 +000018 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
Jari Aalto726f6381996-08-26 18:22:31 +000020
Jari Aaltoccc6cda1996-12-23 17:02:34 +000021/* Stuff in curly braces gets expanded before all other shell expansions. */
Jari Aalto726f6381996-08-26 18:22:31 +000022
Jari Aaltoccc6cda1996-12-23 17:02:34 +000023#include "config.h"
24
25#if defined (BRACE_EXPANSION)
26
27#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000028# ifdef _MINIX
29# include <sys/types.h>
30# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000031# include <unistd.h>
32#endif
Jari Aalto726f6381996-08-26 18:22:31 +000033
Chet Rameyac50fba2014-02-26 09:36:43 -050034#include <errno.h>
35
Jari Aaltod166f041997-06-05 14:59:13 +000036#include "bashansi.h"
Chet Rameyac50fba2014-02-26 09:36:43 -050037#include "bashintl.h"
Jari Aalto726f6381996-08-26 18:22:31 +000038
39#if defined (SHELL)
Jari Aaltoccc6cda1996-12-23 17:02:34 +000040# include "shell.h"
Chet Rameya0c0a002016-09-15 16:59:08 -040041#else
42# if defined (TEST)
43typedef char *WORD_DESC;
44typedef char **WORD_LIST;
45#define _(X) X
46# endif /* TEST */
Jari Aalto726f6381996-08-26 18:22:31 +000047#endif /* SHELL */
48
Chet Rameyac50fba2014-02-26 09:36:43 -050049#include "typemax.h" /* INTMAX_MIN, INTMAX_MAX */
Jari Aalto726f6381996-08-26 18:22:31 +000050#include "general.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000051#include "shmbutil.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000052#include "chartypes.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000053
Chet Rameyac50fba2014-02-26 09:36:43 -050054#ifndef errno
55extern int errno;
56#endif
57
Jari Aalto726f6381996-08-26 18:22:31 +000058#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
59
Jari Aaltob80f6442004-07-27 13:29:18 +000060#define BRACE_SEQ_SPECIFIER ".."
61
Chet Ramey8868eda2020-12-06 15:51:17 -050062extern int asprintf PARAMS((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
Chet Rameyac50fba2014-02-26 09:36:43 -050063
Jari Aalto726f6381996-08-26 18:22:31 +000064/* 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. */
Jari Aalto31859422009-01-12 13:36:28 +000074static const int brace_arg_separator = ',';
Jari Aalto726f6381996-08-26 18:22:31 +000075
Chet Ramey8868eda2020-12-06 15:51:17 -050076#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 **));
Jari Aaltof73dda02001-11-13 17:56:06 +000082#else
Jari Aalto726f6381996-08-26 18:22:31 +000083static int brace_gobbler ();
Jari Aaltof73dda02001-11-13 17:56:06 +000084static char **expand_amble ();
Jari Aaltob80f6442004-07-27 13:29:18 +000085static char **expand_seqterm ();
86static char **mkseq();
Jari Aaltof73dda02001-11-13 17:56:06 +000087static char **array_concat ();
88#endif
Jari Aalto726f6381996-08-26 18:22:31 +000089
Jari Aalto06285672006-10-10 14:15:34 +000090#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
Jari Aalto726f6381996-08-26 18:22:31 +0000102/* Return an array of strings; the brace expansion of TEXT. */
103char **
104brace_expand (text)
105 char *text;
106{
107 register int start;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000108 size_t tlen;
Jari Aalto726f6381996-08-26 18:22:31 +0000109 char *preamble, *postamble, *amble;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000110 size_t alen;
Jari Aalto726f6381996-08-26 18:22:31 +0000111 char **tack, **result;
Jari Aalto06285672006-10-10 14:15:34 +0000112 int i, j, c, c1;
Jari Aalto726f6381996-08-26 18:22:31 +0000113
Jari Aalto7117c2d2002-07-17 14:10:11 +0000114 DECLARE_MBSTATE;
115
Jari Aalto726f6381996-08-26 18:22:31 +0000116 /* Find the text of the preamble. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000117 tlen = strlen (text);
Jari Aalto726f6381996-08-26 18:22:31 +0000118 i = 0;
Jari Aalto06285672006-10-10 14:15:34 +0000119#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 */
Jari Aalto726f6381996-08-26 18:22:31 +0000151
152 preamble = (char *)xmalloc (i + 1);
Chet Rameyac50fba2014-02-26 09:36:43 -0500153 if (i > 0)
154 strncpy (preamble, text, i);
Jari Aalto726f6381996-08-26 18:22:31 +0000155 preamble[i] = '\0';
156
157 result = (char **)xmalloc (2 * sizeof (char *));
158 result[0] = preamble;
159 result[1] = (char *)NULL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000160
Jari Aalto726f6381996-08-26 18:22:31 +0000161 /* 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;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000168 c = brace_gobbler (text, tlen, &i, '}');
Jari Aalto726f6381996-08-26 18:22:31 +0000169
170 /* What if there isn't a matching close brace? */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000171 if (c == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000172 {
173#if defined (NOTDEF)
Jari Aalto726f6381996-08-26 18:22:31 +0000174 /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
175 and I, then this should be an error. Otherwise, it isn't. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000176 j = start;
177 while (j < i)
Jari Aalto726f6381996-08-26 18:22:31 +0000178 {
179 if (text[j] == '\\')
180 {
181 j++;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000182 ADVANCE_CHAR (text, tlen, j);
Jari Aalto726f6381996-08-26 18:22:31 +0000183 continue;
184 }
185
186 if (text[j] == brace_arg_separator)
Jari Aaltob80f6442004-07-27 13:29:18 +0000187 { /* { */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000188 strvec_dispose (result);
Chet Ramey8868eda2020-12-06 15:51:17 -0500189 set_exit_status (EXECUTION_FAILURE);
Jari Aaltob80f6442004-07-27 13:29:18 +0000190 report_error ("no closing `%c' in %s", '}', text);
Jari Aalto726f6381996-08-26 18:22:31 +0000191 throw_to_top_level ();
192 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000193 ADVANCE_CHAR (text, tlen, j);
Jari Aalto726f6381996-08-26 18:22:31 +0000194 }
195#endif
196 free (preamble); /* Same as result[0]; see initialization. */
197 result[0] = savestring (text);
198 return (result);
199 }
200
Jari Aaltobb706242000-03-17 21:46:59 +0000201#if defined (SHELL)
202 amble = substring (text, start, i);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000203 alen = i - start;
Jari Aaltobb706242000-03-17 21:46:59 +0000204#else
Jari Aalto726f6381996-08-26 18:22:31 +0000205 amble = (char *)xmalloc (1 + (i - start));
206 strncpy (amble, &text[start], (i - start));
Jari Aalto7117c2d2002-07-17 14:10:11 +0000207 alen = i - start;
208 amble[alen] = '\0';
Jari Aaltobb706242000-03-17 21:46:59 +0000209#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000210
211#if defined (SHELL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000212 INITIALIZE_MBSTATE;
213
Jari Aalto726f6381996-08-26 18:22:31 +0000214 /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
215 just return without doing any expansion. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000216 j = 0;
217 while (amble[j])
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000218 {
219 if (amble[j] == '\\')
220 {
221 j++;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000222 ADVANCE_CHAR (amble, alen, j);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000223 continue;
224 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000225
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000226 if (amble[j] == brace_arg_separator)
227 break;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000228
229 ADVANCE_CHAR (amble, alen, j);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000230 }
Jari Aalto726f6381996-08-26 18:22:31 +0000231
Jari Aaltob80f6442004-07-27 13:29:18 +0000232 if (amble[j] == 0)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000233 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000234 tack = expand_seqterm (amble, alen);
235 if (tack)
236 goto add_tack;
Chet Rameyac50fba2014-02-26 09:36:43 -0500237 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 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000250 else
251 {
252 free (amble);
253 free (preamble);
254 result[0] = savestring (text);
255 return (result);
256 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000257 }
Jari Aalto726f6381996-08-26 18:22:31 +0000258#endif /* SHELL */
259
Jari Aaltob80f6442004-07-27 13:29:18 +0000260 tack = expand_amble (amble, alen, 0);
261add_tack:
Jari Aalto726f6381996-08-26 18:22:31 +0000262 result = array_concat (result, tack);
263 free (amble);
Chet Rameyac50fba2014-02-26 09:36:43 -0500264 if (tack != result)
265 strvec_dispose (tack);
Jari Aalto726f6381996-08-26 18:22:31 +0000266
Jari Aaltob80f6442004-07-27 13:29:18 +0000267 postamble = text + i + 1;
268
Chet Rameyac50fba2014-02-26 09:36:43 -0500269 if (postamble && *postamble)
270 {
271 tack = brace_expand (postamble);
272 result = array_concat (result, tack);
273 if (tack != result)
274 strvec_dispose (tack);
275 }
Jari Aalto726f6381996-08-26 18:22:31 +0000276
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 **
Jari Aaltob80f6442004-07-27 13:29:18 +0000285expand_amble (text, tlen, flags)
Jari Aalto726f6381996-08-26 18:22:31 +0000286 char *text;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000287 size_t tlen;
Jari Aaltob80f6442004-07-27 13:29:18 +0000288 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +0000289{
Chet Rameyac50fba2014-02-26 09:36:43 -0500290 char **result, **partial, **tresult;
Jari Aalto726f6381996-08-26 18:22:31 +0000291 char *tem;
292 int start, i, c;
293
Chet Rameya0c0a002016-09-15 16:59:08 -0400294#if defined (SHELL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000295 DECLARE_MBSTATE;
Chet Rameya0c0a002016-09-15 16:59:08 -0400296#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000297
Jari Aalto726f6381996-08-26 18:22:31 +0000298 result = (char **)NULL;
299
Jari Aalto7117c2d2002-07-17 14:10:11 +0000300 start = i = 0;
301 c = 1;
302 while (c)
Jari Aalto726f6381996-08-26 18:22:31 +0000303 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000304 c = brace_gobbler (text, tlen, &i, brace_arg_separator);
Jari Aaltobb706242000-03-17 21:46:59 +0000305#if defined (SHELL)
306 tem = substring (text, start, i);
307#else
Jari Aalto726f6381996-08-26 18:22:31 +0000308 tem = (char *)xmalloc (1 + (i - start));
309 strncpy (tem, &text[start], (i - start));
Chet Rameya0c0a002016-09-15 16:59:08 -0400310 tem[i - start] = '\0';
Jari Aaltobb706242000-03-17 21:46:59 +0000311#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000312
313 partial = brace_expand (tem);
314
315 if (!result)
316 result = partial;
317 else
318 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000319 register int lr, lp, j;
320
321 lr = strvec_len (result);
322 lp = strvec_len (partial);
Jari Aalto726f6381996-08-26 18:22:31 +0000323
Chet Rameyac50fba2014-02-26 09:36:43 -0500324 tresult = strvec_mresize (result, lp + lr + 1);
325 if (tresult == 0)
326 {
327 internal_error (_("brace expansion: cannot allocate memory for %s"), tem);
Chet Rameya0c0a002016-09-15 16:59:08 -0400328 free (tem);
329 strvec_dispose (partial);
Chet Rameyac50fba2014-02-26 09:36:43 -0500330 strvec_dispose (result);
331 result = (char **)NULL;
332 return result;
333 }
334 else
335 result = tresult;
Jari Aalto726f6381996-08-26 18:22:31 +0000336
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);
Chet Rameya0c0a002016-09-15 16:59:08 -0400344#if defined (SHELL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000345 ADVANCE_CHAR (text, tlen, i);
Chet Rameya0c0a002016-09-15 16:59:08 -0400346#else
347 i++;
348#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000349 start = i;
Jari Aalto726f6381996-08-26 18:22:31 +0000350 }
351 return (result);
352}
353
Jari Aaltob80f6442004-07-27 13:29:18 +0000354#define ST_BAD 0
355#define ST_INT 1
356#define ST_CHAR 2
Jari Aalto31859422009-01-12 13:36:28 +0000357#define ST_ZINT 3
Jari Aaltob80f6442004-07-27 13:29:18 +0000358
359static char **
Jari Aalto31859422009-01-12 13:36:28 +0000360mkseq (start, end, incr, type, width)
Chet Rameyac50fba2014-02-26 09:36:43 -0500361 intmax_t start, end, incr;
362 int type, width;
Jari Aaltob80f6442004-07-27 13:29:18 +0000363{
Chet Rameyac50fba2014-02-26 09:36:43 -0500364 intmax_t n, prevn;
Chet Rameyd233b482019-01-07 09:27:52 -0500365 int i, nelem;
Jari Aaltob80f6442004-07-27 13:29:18 +0000366 char **result, *t;
367
Jari Aalto06285672006-10-10 14:15:34 +0000368 if (incr == 0)
369 incr = 1;
Chet Rameyac50fba2014-02-26 09:36:43 -0500370
Jari Aalto06285672006-10-10 14:15:34 +0000371 if (start > end && incr > 0)
372 incr = -incr;
373 else if (start < end && incr < 0)
Chet Rameyac50fba2014-02-26 09:36:43 -0500374 {
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 */
Chet Rameyd233b482019-01-07 09:27:52 -0500400 if ((prevn / sh_imaxabs (incr)) > INT_MAX - 3) /* check int overflow */
Chet Rameyac50fba2014-02-26 09:36:43 -0500401 return ((char **)NULL);
Chet Rameyd233b482019-01-07 09:27:52 -0500402 nelem = (prevn / sh_imaxabs(incr)) + 1;
Chet Rameyac50fba2014-02-26 09:36:43 -0500403 result = strvec_mcreate (nelem + 1);
404 if (result == 0)
405 {
Chet Rameyd233b482019-01-07 09:27:52 -0500406 internal_error (_("brace expansion: failed to allocate memory for %u elements"), (unsigned int)nelem);
Chet Rameyac50fba2014-02-26 09:36:43 -0500407 return ((char **)NULL);
408 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000409
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 {
Jari Aalto06285672006-10-10 14:15:34 +0000415#if defined (SHELL)
Chet Rameya0c0a002016-09-15 16:59:08 -0400416 if (ISINTERRUPT)
417 {
Chet Rameyd233b482019-01-07 09:27:52 -0500418 result[i] = (char *)NULL;
Chet Rameya0c0a002016-09-15 16:59:08 -0400419 strvec_dispose (result);
420 result = (char **)NULL;
421 }
422 QUIT;
Jari Aalto06285672006-10-10 14:15:34 +0000423#endif
Jari Aaltob80f6442004-07-27 13:29:18 +0000424 if (type == ST_INT)
Chet Rameyac50fba2014-02-26 09:36:43 -0500425 result[i++] = t = itos (n);
Jari Aalto31859422009-01-12 13:36:28 +0000426 else if (type == ST_ZINT)
427 {
Chet Ramey495aee42011-11-22 19:11:26 -0500428 int len, arg;
429 arg = n;
430 len = asprintf (&t, "%0*d", width, arg);
Jari Aalto31859422009-01-12 13:36:28 +0000431 result[i++] = t;
432 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000433 else
434 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500435 if (t = (char *)malloc (2))
436 {
437 t[0] = n;
438 t[1] = '\0';
439 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000440 result[i++] = t;
441 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500442
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
Jari Aaltob80f6442004-07-27 13:29:18 +0000460 n += incr;
Chet Rameyac50fba2014-02-26 09:36:43 -0500461
Jari Aalto31859422009-01-12 13:36:28 +0000462 if ((incr < 0 && n < end) || (incr > 0 && n > end))
463 break;
Jari Aaltob80f6442004-07-27 13:29:18 +0000464 }
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;
Chet Rameyd233b482019-01-07 09:27:52 -0500477 int lhs_t, rhs_t, lhs_l, rhs_l, width;
Chet Rameyac50fba2014-02-26 09:36:43 -0500478 intmax_t lhs_v, rhs_v, incr;
Jari Aaltob80f6442004-07-27 13:29:18 +0000479 intmax_t tl, tr;
Chet Ramey00018032011-11-21 20:51:19 -0500480 char **result, *ep, *oep;
Jari Aaltob80f6442004-07-27 13:29:18 +0000481
482 t = strstr (text, BRACE_SEQ_SPECIFIER);
483 if (t == 0)
484 return ((char **)NULL);
485
Jari Aalto31859422009-01-12 13:36:28 +0000486 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);
Jari Aaltob80f6442004-07-27 13:29:18 +0000489
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);
Jari Aalto31859422009-01-12 13:36:28 +0000501
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;
Chet Rameyac50fba2014-02-26 09:36:43 -0500508 errno = 0;
Jari Aalto31859422009-01-12 13:36:28 +0000509 tr = strtoimax (rhs, &ep, 10);
Chet Rameyac50fba2014-02-26 09:36:43 -0500510 if (errno == ERANGE || (ep && *ep != 0 && *ep != '.'))
Jari Aalto31859422009-01-12 13:36:28 +0000511 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 {
Chet Ramey00018032011-11-21 20:51:19 -0500527 oep = ep;
Chet Rameyac50fba2014-02-26 09:36:43 -0500528 errno = 0;
Jari Aalto31859422009-01-12 13:36:28 +0000529 if (ep && *ep == '.' && ep[1] == '.' && ep[2])
530 incr = strtoimax (ep + 2, &ep, 10);
Chet Rameyac50fba2014-02-26 09:36:43 -0500531 if (*ep != 0 || errno == ERANGE)
532 rhs_t = ST_BAD; /* invalid incr or overflow */
Chet Ramey00018032011-11-21 20:51:19 -0500533 tlen -= ep - oep;
Jari Aalto31859422009-01-12 13:36:28 +0000534 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000535
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 {
Jari Aaltoeb873672004-11-09 21:37:25 +0000549 lhs_v = (unsigned char)lhs[0];
550 rhs_v = (unsigned char)rhs[0];
Jari Aalto31859422009-01-12 13:36:28 +0000551 width = 1;
Jari Aaltob80f6442004-07-27 13:29:18 +0000552 }
553 else
554 {
555 lhs_v = tl; /* integer truncation */
556 rhs_v = tr;
Jari Aalto31859422009-01-12 13:36:28 +0000557
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;
Chet Ramey00018032011-11-21 20:51:19 -0500569
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;
Jari Aaltob80f6442004-07-27 13:29:18 +0000574 }
575
Jari Aalto31859422009-01-12 13:36:28 +0000576 result = mkseq (lhs_v, rhs_v, incr, lhs_t, width);
Jari Aaltob80f6442004-07-27 13:29:18 +0000577
578 free (lhs);
579 free (rhs);
580
581 return (result);
582}
583
Jari Aalto726f6381996-08-26 18:22:31 +0000584/* 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. */
Jari Aalto06285672006-10-10 14:15:34 +0000588/* 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*/
Jari Aalto726f6381996-08-26 18:22:31 +0000593static int
Jari Aalto7117c2d2002-07-17 14:10:11 +0000594brace_gobbler (text, tlen, indx, satisfy)
Jari Aalto726f6381996-08-26 18:22:31 +0000595 char *text;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000596 size_t tlen;
Jari Aalto726f6381996-08-26 18:22:31 +0000597 int *indx;
598 int satisfy;
599{
Jari Aalto06285672006-10-10 14:15:34 +0000600 register int i, c, quoted, level, commas, pass_next;
Jari Aaltod166f041997-06-05 14:59:13 +0000601#if defined (SHELL)
602 int si;
603 char *t;
604#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000605 DECLARE_MBSTATE;
Jari Aalto726f6381996-08-26 18:22:31 +0000606
607 level = quoted = pass_next = 0;
Jari Aalto06285672006-10-10 14:15:34 +0000608#if defined (CSH_BRACE_COMPAT)
609 commas = 1;
610#else
611 commas = (satisfy == '}') ? 0 : 1;
612#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000613
Jari Aalto7117c2d2002-07-17 14:10:11 +0000614 i = *indx;
615 while (c = text[i])
Jari Aalto726f6381996-08-26 18:22:31 +0000616 {
617 if (pass_next)
618 {
619 pass_next = 0;
Chet Rameya0c0a002016-09-15 16:59:08 -0400620#if defined (SHELL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000621 ADVANCE_CHAR (text, tlen, i);
Chet Rameya0c0a002016-09-15 16:59:08 -0400622#else
623 i++;
624#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000625 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 == '`'))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000631 {
632 pass_next = 1;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000633 i++;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000634 continue;
635 }
Jari Aalto726f6381996-08-26 18:22:31 +0000636
Jari Aaltob80f6442004-07-27 13:29:18 +0000637#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++;
Jari Aaltoeb873672004-11-09 21:37:25 +0000643 if (quoted == 0)
644 level++;
Jari Aaltob80f6442004-07-27 13:29:18 +0000645 continue;
646 }
647#endif
648
Jari Aalto726f6381996-08-26 18:22:31 +0000649 if (quoted)
650 {
651 if (c == quoted)
652 quoted = 0;
Chet Rameyac50fba2014-02-26 09:36:43 -0500653#if defined (SHELL)
654 /* The shell allows quoted command substitutions */
655 if (quoted == '"' && c == '$' && text[i+1] == '(') /*)*/
656 goto comsub;
657#endif
Chet Rameya0c0a002016-09-15 16:59:08 -0400658#if defined (SHELL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000659 ADVANCE_CHAR (text, tlen, i);
Chet Rameya0c0a002016-09-15 16:59:08 -0400660#else
661 i++;
662#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000663 continue;
664 }
665
666 if (c == '"' || c == '\'' || c == '`')
667 {
668 quoted = c;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000669 i++;
Jari Aalto726f6381996-08-26 18:22:31 +0000670 continue;
671 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000672
Jari Aaltod166f041997-06-05 14:59:13 +0000673#if defined (SHELL)
Jari Aalto31859422009-01-12 13:36:28 +0000674 /* Pass new-style command and process substitutions through unchanged. */
675 if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
Jari Aaltod166f041997-06-05 14:59:13 +0000676 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500677comsub:
Jari Aaltod166f041997-06-05 14:59:13 +0000678 si = i + 2;
Jari Aalto31859422009-01-12 13:36:28 +0000679 t = extract_command_subst (text, &si, 0);
Jari Aaltod166f041997-06-05 14:59:13 +0000680 i = si;
681 free (t);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000682 i++;
Jari Aaltod166f041997-06-05 14:59:13 +0000683 continue;
684 }
685#endif
686
Jari Aalto06285672006-10-10 14:15:34 +0000687 if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000688 {
689 /* We ignore an open brace surrounded by whitespace, and also
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000690 an open brace followed immediately by a close brace preceded
691 by whitespace. */
Jari Aalto726f6381996-08-26 18:22:31 +0000692 if (c == '{' &&
693 ((!i || brace_whitespace (text[i - 1])) &&
694 (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000695 {
696 i++;
697 continue;
698 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000699
Jari Aalto726f6381996-08-26 18:22:31 +0000700 break;
701 }
702
703 if (c == '{')
704 level++;
705 else if (c == '}' && level)
706 level--;
Jari Aalto06285672006-10-10 14:15:34 +0000707#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
Jari Aalto7117c2d2002-07-17 14:10:11 +0000714
Chet Rameya0c0a002016-09-15 16:59:08 -0400715#if defined (SHELL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000716 ADVANCE_CHAR (text, tlen, i);
Chet Rameya0c0a002016-09-15 16:59:08 -0400717#else
718 i++;
719#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000720 }
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
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000738 if (arr1 == 0)
Chet Rameyac50fba2014-02-26 09:36:43 -0500739 return (arr2); /* XXX - see if we can get away without copying? */
Jari Aalto726f6381996-08-26 18:22:31 +0000740
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000741 if (arr2 == 0)
Chet Rameyac50fba2014-02-26 09:36:43 -0500742 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 */
Jari Aalto726f6381996-08-26 18:22:31 +0000755
Jari Aalto7117c2d2002-07-17 14:10:11 +0000756 len1 = strvec_len (arr1);
757 len2 = strvec_len (arr2);
Jari Aalto726f6381996-08-26 18:22:31 +0000758
Chet Rameyd233b482019-01-07 09:27:52 -0500759 result = (char **)malloc ((1 + (len1 * len2)) * sizeof (char *));
760 if (result == 0)
761 return (result);
Jari Aalto726f6381996-08-26 18:22:31 +0000762
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 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000770 result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
Jari Aalto726f6381996-08-26 18:22:31 +0000771 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
Chet Rameya0c0a002016-09-15 16:59:08 -0400786void *
787xmalloc(n)
788 size_t n;
Jari Aalto726f6381996-08-26 18:22:31 +0000789{
Chet Rameya0c0a002016-09-15 16:59:08 -0400790 return (malloc (n));
Jari Aalto726f6381996-08-26 18:22:31 +0000791}
792
Chet Rameya0c0a002016-09-15 16:59:08 -0400793void *
794xrealloc(p, n)
795 void *p;
796 size_t n;
797{
798 return (realloc (p, n));
799}
800
801int
802internal_error (format, arg1, arg2)
Jari Aalto726f6381996-08-26 18:22:31 +0000803 char *format, *arg1, *arg2;
804{
805 fprintf (stderr, format, arg1, arg2);
806 fprintf (stderr, "\n");
807}
Chet Rameya0c0a002016-09-15 16:59:08 -0400808
Jari Aalto726f6381996-08-26 18:22:31 +0000809main ()
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
Chet Rameya0c0a002016-09-15 16:59:08 -0400832 strvec_dispose (result);
Jari Aalto726f6381996-08-26 18:22:31 +0000833 }
834}
835
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 */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000843#endif /* BRACE_EXPANSION */