From 25b12c5d1139de9b7527a1fa2b722fe19c46f462 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 5 Dec 2010 21:07:48 +0000 Subject: 28474, 28478: extended {START..END..STEP} syntax --- Src/glob.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 12 deletions(-) (limited to 'Src/glob.c') 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); -- cgit 1.4.1