|
|
|
@ -166,78 +166,101 @@ static GlobCode glob_range(URLGlob *glob, char *pattern,
|
|
|
|
|
URLPattern *pat;
|
|
|
|
|
char *c;
|
|
|
|
|
int wordamount=1;
|
|
|
|
|
char sep;
|
|
|
|
|
char sep2;
|
|
|
|
|
int step;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
pat = (URLPattern*)&glob->pattern[glob->size / 2];
|
|
|
|
|
/* patterns 0,1,2,... correspond to size=1,3,5,... */
|
|
|
|
|
++glob->size;
|
|
|
|
|
|
|
|
|
|
if (isalpha((int)*pattern)) { /* character range detected */
|
|
|
|
|
char min_c;
|
|
|
|
|
char max_c;
|
|
|
|
|
|
|
|
|
|
pat->type = UPTCharRange;
|
|
|
|
|
if (sscanf(pattern, "%c-%c]", &pat->content.CharRange.min_c,
|
|
|
|
|
&pat->content.CharRange.max_c) != 2 ||
|
|
|
|
|
pat->content.CharRange.min_c >= pat->content.CharRange.max_c ||
|
|
|
|
|
pat->content.CharRange.max_c - pat->content.CharRange.min_c > 'z' - 'a') {
|
|
|
|
|
rc = sscanf(pattern, "%c-%c%c%d%c", &min_c, &max_c, &sep, &step, &sep2);
|
|
|
|
|
if ((rc < 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a'))) {
|
|
|
|
|
/* the pattern is not well-formed */
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
|
|
|
|
"illegal pattern or range specification after pos %d\n", pos);
|
|
|
|
|
"errpr: bad range specification after pos %d\n", pos);
|
|
|
|
|
return GLOB_ERROR;
|
|
|
|
|
}
|
|
|
|
|
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
|
|
|
|
|
/* always check for a literal (may be "") between patterns */
|
|
|
|
|
|
|
|
|
|
if(GLOB_ERROR == glob_word(glob, pattern + 4, pos + 4, &wordamount))
|
|
|
|
|
wordamount=1;
|
|
|
|
|
/* check the (first) separating character */
|
|
|
|
|
if((sep != ']') && (sep != ':')) {
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
|
|
|
|
"error: unsupported character (%c) after range at pos %d\n",
|
|
|
|
|
sep, pos);
|
|
|
|
|
return GLOB_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*amount = (pat->content.CharRange.max_c -
|
|
|
|
|
pat->content.CharRange.min_c + 1) *
|
|
|
|
|
wordamount;
|
|
|
|
|
/* if there was a ":[num]" thing, use that as step or else use 1 */
|
|
|
|
|
pat->content.CharRange.step =
|
|
|
|
|
((sep == ':') && (rc == 5) && (sep2 == ']'))?step:1;
|
|
|
|
|
|
|
|
|
|
return GLOB_OK;
|
|
|
|
|
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
|
|
|
|
|
pat->content.CharRange.max_c = max_c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isdigit((int)*pattern)) { /* numeric range detected */
|
|
|
|
|
else if (isdigit((int)*pattern)) { /* numeric range detected */
|
|
|
|
|
int min_n;
|
|
|
|
|
int max_n;
|
|
|
|
|
|
|
|
|
|
pat->type = UPTNumRange;
|
|
|
|
|
pat->content.NumRange.padlength = 0;
|
|
|
|
|
if (sscanf(pattern, "%d-%d]",
|
|
|
|
|
&pat->content.NumRange.min_n,
|
|
|
|
|
&pat->content.NumRange.max_n) != 2 ||
|
|
|
|
|
pat->content.NumRange.min_n >= pat->content.NumRange.max_n) {
|
|
|
|
|
|
|
|
|
|
rc = sscanf(pattern, "%d-%d%c%d%c", &min_n, &max_n, &sep, &step, &sep2);
|
|
|
|
|
|
|
|
|
|
if ((rc < 2) || (min_n >= max_n)) {
|
|
|
|
|
/* the pattern is not well-formed */
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
|
|
|
|
"error: illegal pattern or range specification after pos %d\n",
|
|
|
|
|
pos);
|
|
|
|
|
"error: bad range specification after pos %d\n", pos);
|
|
|
|
|
return GLOB_ERROR;
|
|
|
|
|
}
|
|
|
|
|
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
|
|
|
|
|
pat->content.NumRange.max_n = max_n;
|
|
|
|
|
|
|
|
|
|
/* if there was a ":[num]" thing, use that as step or else use 1 */
|
|
|
|
|
pat->content.NumRange.step =
|
|
|
|
|
((sep == ':') && (rc == 5) && (sep2 == ']'))?step:1;
|
|
|
|
|
|
|
|
|
|
if (*pattern == '0') { /* leading zero specified */
|
|
|
|
|
c = pattern;
|
|
|
|
|
while (isdigit((int)*c++))
|
|
|
|
|
++pat->content.NumRange.padlength; /* padding length is set for all
|
|
|
|
|
instances of this pattern */
|
|
|
|
|
}
|
|
|
|
|
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
|
|
|
|
|
c = (char*)strchr(pattern, ']'); /* continue after next ']' */
|
|
|
|
|
if(c)
|
|
|
|
|
c++;
|
|
|
|
|
else {
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg), "missing ']'");
|
|
|
|
|
return GLOB_ERROR; /* missing ']' */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* always check for a literal (may be "") between patterns */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
|
|
|
|
"illegal character in range specification at pos %d\n", pos);
|
|
|
|
|
return GLOB_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(GLOB_ERROR == glob_word(glob, c, pos + (c - pattern), &wordamount))
|
|
|
|
|
wordamount = 1;
|
|
|
|
|
c = (char*)strchr(pattern, ']'); /* continue after next ']' */
|
|
|
|
|
if(c)
|
|
|
|
|
c++;
|
|
|
|
|
else {
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg), "missing ']'");
|
|
|
|
|
return GLOB_ERROR; /* missing ']' */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*amount = (pat->content.NumRange.max_n -
|
|
|
|
|
pat->content.NumRange.min_n + 1) *
|
|
|
|
|
/* always check for a literal (may be "") between patterns */
|
|
|
|
|
|
|
|
|
|
if(GLOB_ERROR == glob_word(glob, c, pos + (c - pattern), &wordamount))
|
|
|
|
|
wordamount = 1;
|
|
|
|
|
|
|
|
|
|
if(pat->type == UPTCharRange)
|
|
|
|
|
*amount = (pat->content.CharRange.max_c -
|
|
|
|
|
pat->content.CharRange.min_c + 1) *
|
|
|
|
|
wordamount;
|
|
|
|
|
else
|
|
|
|
|
*amount = (pat->content.NumRange.max_n -
|
|
|
|
|
pat->content.NumRange.min_n + 1) * wordamount;
|
|
|
|
|
|
|
|
|
|
return GLOB_OK;
|
|
|
|
|
}
|
|
|
|
|
snprintf(glob->errormsg, sizeof(glob->errormsg),
|
|
|
|
|
"illegal character in range specification at pos %d\n", pos);
|
|
|
|
|
return GLOB_ERROR;
|
|
|
|
|
return GLOB_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GlobCode glob_word(URLGlob *glob, char *pattern,
|
|
|
|
@ -374,35 +397,36 @@ char *glob_next_url(URLGlob *glob)
|
|
|
|
|
char *lit;
|
|
|
|
|
size_t i;
|
|
|
|
|
size_t j;
|
|
|
|
|
int carry;
|
|
|
|
|
|
|
|
|
|
if (!glob->beenhere)
|
|
|
|
|
glob->beenhere = 1;
|
|
|
|
|
else {
|
|
|
|
|
carry = 1;
|
|
|
|
|
bool carry = TRUE;
|
|
|
|
|
|
|
|
|
|
/* implement a counter over the index ranges of all patterns,
|
|
|
|
|
starting with the rightmost pattern */
|
|
|
|
|
for (i = glob->size / 2 - 1; carry && i < glob->size; --i) {
|
|
|
|
|
carry = 0;
|
|
|
|
|
carry = FALSE;
|
|
|
|
|
pat = &glob->pattern[i];
|
|
|
|
|
switch (pat->type) {
|
|
|
|
|
case UPTSet:
|
|
|
|
|
if (++pat->content.Set.ptr_s == pat->content.Set.size) {
|
|
|
|
|
pat->content.Set.ptr_s = 0;
|
|
|
|
|
carry = 1;
|
|
|
|
|
carry = TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case UPTCharRange:
|
|
|
|
|
if (++pat->content.CharRange.ptr_c > pat->content.CharRange.max_c) {
|
|
|
|
|
pat->content.CharRange.ptr_c += pat->content.CharRange.step;
|
|
|
|
|
if (pat->content.CharRange.ptr_c > pat->content.CharRange.max_c) {
|
|
|
|
|
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
|
|
|
|
|
carry = 1;
|
|
|
|
|
carry = TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case UPTNumRange:
|
|
|
|
|
if (++pat->content.NumRange.ptr_n > pat->content.NumRange.max_n) {
|
|
|
|
|
pat->content.NumRange.ptr_n += pat->content.NumRange.step;
|
|
|
|
|
if (pat->content.NumRange.ptr_n > pat->content.NumRange.max_n) {
|
|
|
|
|
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
|
|
|
|
|
carry = 1;
|
|
|
|
|
carry = TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|