summaryrefslogtreecommitdiff
path: root/braces.c
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>2004-07-27 13:29:18 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:56 +0000
commitb80f6443b6b7b620c7272664c66ecb0b120a0998 (patch)
tree9f71c98d8fe8fa0f41d95e1eb4227f32a09d43ca /braces.c
parent7117c2d221b2aed4ede8600f6a36b7c1454b4f55 (diff)
downloadbash-b80f6443b6b7b620c7272664c66ecb0b120a0998.tar.gz
Imported from ../bash-3.0.tar.gz.
Diffstat (limited to 'braces.c')
-rw-r--r--braces.c169
1 files changed, 146 insertions, 23 deletions
diff --git a/braces.c b/braces.c
index 4f5b0f0f..0fb9b9d7 100644
--- a/braces.c
+++ b/braces.c
@@ -1,6 +1,6 @@
/* braces.c -- code for doing word expansion in curly braces. */
-/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2003 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -39,9 +39,12 @@
#include "general.h"
#include "shmbutil.h"
+#include "chartypes.h"
#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
+#define BRACE_SEQ_SPECIFIER ".."
+
/* Basic idea:
Segregate the text into 3 sections: preamble (stuff before an open brace),
@@ -56,11 +59,15 @@ int brace_arg_separator = ',';
#if defined (__P)
static int brace_gobbler __P((char *, size_t, int *, int));
-static char **expand_amble __P((char *, size_t));
+static char **expand_amble __P((char *, size_t, int));
+static char **expand_seqterm __P((char *, size_t));
+static char **mkseq __P((int, int, int));
static char **array_concat __P((char **, char **));
#else
static int brace_gobbler ();
static char **expand_amble ();
+static char **expand_seqterm ();
+static char **mkseq();
static char **array_concat ();
#endif
@@ -117,9 +124,9 @@ brace_expand (text)
}
if (text[j] == brace_arg_separator)
- {
+ { /* { */
strvec_dispose (result);
- report_error ("missing `}'");
+ report_error ("no closing `%c' in %s", '}', text);
throw_to_top_level ();
}
ADVANCE_CHAR (text, tlen, j);
@@ -161,22 +168,29 @@ brace_expand (text)
ADVANCE_CHAR (amble, alen, j);
}
- if (!amble[j])
+ if (amble[j] == 0)
{
- free (amble);
- free (preamble);
- result[0] = savestring (text);
- return (result);
+ tack = expand_seqterm (amble, alen);
+ if (tack)
+ goto add_tack;
+ else
+ {
+ free (amble);
+ free (preamble);
+ result[0] = savestring (text);
+ return (result);
+ }
}
#endif /* SHELL */
- postamble = &text[i + 1];
-
- tack = expand_amble (amble, alen);
+ tack = expand_amble (amble, alen, 0);
+add_tack:
result = array_concat (result, tack);
free (amble);
strvec_dispose (tack);
+ postamble = text + i + 1;
+
tack = brace_expand (postamble);
result = array_concat (result, tack);
strvec_dispose (tack);
@@ -189,9 +203,10 @@ brace_expand (text)
expand each slot which needs it, until there are no more slots which
need it. */
static char **
-expand_amble (text, tlen)
+expand_amble (text, tlen, flags)
char *text;
size_t tlen;
+ int flags;
{
char **result, **partial;
char *tem;
@@ -220,9 +235,10 @@ expand_amble (text, tlen)
result = partial;
else
{
- register int lr = strvec_len (result);
- register int lp = strvec_len (partial);
- register int j;
+ register int lr, lp, j;
+
+ lr = strvec_len (result);
+ lp = strvec_len (partial);
result = strvec_resize (result, lp + lr + 1);
@@ -239,6 +255,108 @@ expand_amble (text, tlen)
return (result);
}
+#define ST_BAD 0
+#define ST_INT 1
+#define ST_CHAR 2
+
+static char **
+mkseq (start, end, type)
+ int start, end, type;
+{
+ int n, incr, i;
+ char **result, *t;
+
+ n = abs (end - start) + 1;
+ result = strvec_create (n + 1);
+
+ incr = (start < end) ? 1 : -1;
+
+ /* Make sure we go through the loop at least once, so {3..3} prints `3' */
+ i = 0;
+ n = start;
+ do
+ {
+ if (type == ST_INT)
+ result[i++] = itos (n);
+ else
+ {
+ t = (char *)xmalloc (2);
+ t[0] = n;
+ t[1] = '\0';
+ result[i++] = t;
+ }
+ if (n == end)
+ break;
+ n += incr;
+ }
+ while (1);
+
+ result[i] = (char *)0;
+ return (result);
+}
+
+static char **
+expand_seqterm (text, tlen)
+ char *text;
+ size_t tlen;
+{
+ char *t, *lhs, *rhs;
+ int i, lhs_t, rhs_t, lhs_v, rhs_v;
+ intmax_t tl, tr;
+ char **result;
+
+ t = strstr (text, BRACE_SEQ_SPECIFIER);
+ if (t == 0)
+ return ((char **)NULL);
+
+ i = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
+ lhs = substring (text, 0, i);
+ rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
+
+ if (lhs[0] == 0 || rhs[0] == 0)
+ {
+ free (lhs);
+ free (rhs);
+ return ((char **)NULL);
+ }
+
+ /* Now figure out whether LHS and RHS are integers or letters. Both
+ sides have to match. */
+ lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
+ ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
+ rhs_t = (legal_number (rhs, &tr)) ? ST_INT :
+ ((ISALPHA (rhs[0]) && rhs[1] == 0) ? ST_CHAR : ST_BAD);
+
+ if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
+ {
+ free (lhs);
+ free (rhs);
+ return ((char **)NULL);
+ }
+
+ /* OK, we have something. It's either a sequence of integers, ascending
+ or descending, or a sequence or letters, ditto. Generate the sequence,
+ put it into a string vector, and return it. */
+
+ if (lhs_t == ST_CHAR)
+ {
+ lhs_v = lhs[0];
+ rhs_v = rhs[0];
+ }
+ else
+ {
+ lhs_v = tl; /* integer truncation */
+ rhs_v = tr;
+ }
+
+ result = mkseq (lhs_v, rhs_v, lhs_t);
+
+ free (lhs);
+ free (rhs);
+
+ return (result);
+}
+
/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
index of the character matching SATISFY. This understands about
quoting. Return the character that caused us to stop searching;
@@ -278,6 +396,16 @@ brace_gobbler (text, tlen, indx, satisfy)
continue;
}
+#if defined (SHELL)
+ /* If compiling for the shell, treat ${...} like \{...} */
+ if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+#endif
+
if (quoted)
{
if (c == quoted)
@@ -318,11 +446,7 @@ brace_gobbler (text, tlen, indx, satisfy)
i++;
continue;
}
-#if defined (SHELL)
- /* If this is being compiled as part of bash, ignore the `{'
- in a `${}' construct */
- if ((c != '{') || i == 0 || (text[i - 1] != '$'))
-#endif /* SHELL */
+
break;
}
@@ -368,8 +492,7 @@ array_concat (arr1, arr2)
for (j = 0; j < len2; j++)
{
- result[len] =
- (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
+ result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
strcpy (result[len], arr1[i]);
strcpy (result[len] + strlen_1, arr2[j]);
len++;