summaryrefslogtreecommitdiff
path: root/Src/glob.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/glob.c')
-rw-r--r--Src/glob.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/Src/glob.c b/Src/glob.c
index c552e6cf1..5f6813589 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -1924,14 +1924,29 @@ hasbraces(char *str)
case Inbrace:
if (!lbr) {
lbr = str - 1;
+ if (*str == '-')
+ str++;
while (idigit(*str))
str++;
if (*str == '.' && str[1] == '.') {
- str++;
- while (idigit(*++str));
+ str++; str++;
+ if (*str == '-')
+ str++;
+ while (idigit(*str))
+ str++;
if (*str == Outbrace &&
(idigit(lbr[1]) || idigit(str[-1])))
return 1;
+ else if (*str == '.' && str[1] == '.') {
+ str++; str++;
+ if (*str == '-')
+ str++;
+ while (idigit(*str))
+ str++;
+ if (*str == Outbrace &&
+ (idigit(lbr[1]) || idigit(str[-1])))
+ return 1;
+ }
}
} else {
char *s = --str;
@@ -2061,18 +2076,20 @@ xpandbraces(LinkList list, LinkNode *np)
} else if (bc == 1) {
if (*str2 == Comma)
++comma; /* we have {foo,bar} */
- else if (*str2 == '.' && str2[1] == '.')
+ else if (*str2 == '.' && str2[1] == '.') {
dotdot++; /* we have {num1..num2} */
+ ++str2;
+ }
}
DPUTS(bc, "BUG: unmatched brace in xpandbraces()");
if (!comma && dotdot) {
/* Expand range like 0..10 numerically: comma or recursive
brace expansion take precedence. */
- char *dots, *p;
+ char *dots, *p, *dots2 = NULL;
LinkNode olast = last;
/* Get the first number of the range */
- int rstart = zstrtol(str+1,&dots,10), rend = 0, err = 0, rev = 0;
- int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2;
+ int rstart = zstrtol(str+1,&dots,10), rend = 0, err = 0, rev = 0, rincr = 1;
+ int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2, wid3 = 0;
int strp = str - str3;
if (dots == str + 1 || *dots != '.' || dots[1] != '.')
@@ -2080,23 +2097,53 @@ xpandbraces(LinkList list, LinkNode *np)
else {
/* Get the last number of the range */
rend = zstrtol(dots+2,&p,10);
- if (p == dots+2 || p != str2)
+ if (p == dots+2)
err++;
+ /* check for {num1..num2..incr} */
+ if (p != str2) {
+ wid2 = (p - dots) - 2;
+ dots2 = p;
+ if (dotdot == 2 && *p == '.' && p[1] == '.') {
+ rincr = zstrtol(p+2, &p, 10);
+ wid3 = p - dots2 - 2;
+ if (p != str2 || !rincr)
+ err++;
+ } else
+ err++;
+ }
}
if (!err) {
/* If either no. begins with a zero, pad the output with *
- * zeroes. Otherwise, choose a min width to suppress them. */
- int minw = (str[1] == '0') ? wid1 : (dots[2] == '0' ) ? wid2 :
- (wid2 > wid1) ? wid1 : wid2;
+ * zeroes. Otherwise, set min width to 0 to suppress them.
+ * str+1 is the first number in the range, dots+2 the last,
+ * and dots2+2 is the increment if that's given. */
+ /* TODO: sorry about this */
+ int minw = (str[1] == '0' || (str[1] == '-' && str[2] == '0'))
+ ? wid1
+ : (dots[2] == '0' || (dots[2] == '-' && dots[3] == '0'))
+ ? wid2
+ : (dots2 && (dots2[2] == '0' ||
+ (dots2[2] == '-' && dots2[3] == '0')))
+ ? wid3
+ : 0;
+ if (rincr < 0) {
+ /* Handle negative increment */
+ rincr = -rincr;
+ rev = !rev;
+ }
if (rstart > rend) {
/* Handle decreasing ranges correctly. */
int rt = rend;
rend = rstart;
rstart = rt;
- rev = 1;
+ rev = !rev;
+ } else if (rincr > 1) {
+ /* when incr > 1, range is aligned to the highest number of str1,
+ * compensate for this so that it is aligned to the first number */
+ rend -= (rend - rstart) % rincr;
}
uremnode(list, node);
- for (; rend >= rstart; rend--) {
+ for (; rend >= rstart; rend -= rincr) {
/* Node added in at end, so do highest first */
p = dupstring(str3);
sprintf(p + strp, "%0*d", minw, rend);