Implement starstar in glob conversion.
This commit is contained in:
parent
485b269f9c
commit
095924ee65
|
@ -359,282 +359,6 @@ return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
|
||||||
* Convert a glob pattern *
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
/* For a basic glob, only * ? and [...] are recognized.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
pattype the pattern type
|
|
||||||
pattern the pattern
|
|
||||||
plength length in code units
|
|
||||||
utf TRUE if UTF
|
|
||||||
use_buffer where to put the output
|
|
||||||
use_length length of use_buffer
|
|
||||||
bufflenptr where to put the used length
|
|
||||||
dummyrun TRUE if a dummy run
|
|
||||||
ccontext the convert context
|
|
||||||
|
|
||||||
Returns: 0 => success
|
|
||||||
!0 => error code
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
convert_glob(uint32_t pattype, PCRE2_SPTR pattern, PCRE2_SIZE plength,
|
|
||||||
BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length,
|
|
||||||
PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext)
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
char not_sep_class[8];
|
|
||||||
char lookbehind_not_sep[12];
|
|
||||||
PCRE2_SPTR glob = pattern;
|
|
||||||
PCRE2_UCHAR *p = use_buffer;
|
|
||||||
PCRE2_UCHAR *pp = p;
|
|
||||||
PCRE2_UCHAR *endp = p + use_length - 1; /* Allow for trailing zero */
|
|
||||||
PCRE2_SIZE convlength = 0;
|
|
||||||
uint32_t range_start = 0;
|
|
||||||
uint32_t range_state = RANGE_NOT_STARTED;
|
|
||||||
uint32_t posix_class_state = POSIX_CLASS_NOT_STARTED;
|
|
||||||
BOOL inclass = FALSE;
|
|
||||||
BOOL nextisliteral = FALSE;
|
|
||||||
BOOL endswith = FALSE;
|
|
||||||
BOOL sep_in_range = FALSE;
|
|
||||||
|
|
||||||
(void)utf; /* Not used when Unicode not supported */
|
|
||||||
(void)pattype; /* Pro tem */
|
|
||||||
|
|
||||||
/* Set up a string containing [^<sep>] where <sep> is the possibly escaped part
|
|
||||||
separator. */
|
|
||||||
|
|
||||||
s = not_sep_class;
|
|
||||||
*s++ = CHAR_LEFT_SQUARE_BRACKET;
|
|
||||||
*s++ = CHAR_CIRCUMFLEX_ACCENT;
|
|
||||||
if (ccontext->glob_separator == CHAR_BACKSLASH) *s++ = CHAR_BACKSLASH;
|
|
||||||
*s++ = ccontext->glob_separator;
|
|
||||||
*s++ = CHAR_RIGHT_SQUARE_BRACKET;
|
|
||||||
*s++ = 0;
|
|
||||||
|
|
||||||
/* Set up a string containing (?<!<sep>) where <sep> is the possibly escaped
|
|
||||||
part separator. */
|
|
||||||
|
|
||||||
s = lookbehind_not_sep;
|
|
||||||
*s++ = CHAR_LEFT_PARENTHESIS;
|
|
||||||
*s++ = CHAR_QUESTION_MARK;
|
|
||||||
*s++ = CHAR_LESS_THAN_SIGN;
|
|
||||||
*s++ = CHAR_EXCLAMATION_MARK;
|
|
||||||
if (ccontext->glob_separator == CHAR_BACKSLASH) *s++ = CHAR_BACKSLASH;
|
|
||||||
*s++ = ccontext->glob_separator;
|
|
||||||
*s++ = CHAR_RIGHT_PARENTHESIS;
|
|
||||||
*s++ = 0;
|
|
||||||
|
|
||||||
/* Initialize default for error offset as end of input. */
|
|
||||||
|
|
||||||
*bufflenptr = plength;
|
|
||||||
|
|
||||||
/* If the pattern starts with * and contains at least one more character but no
|
|
||||||
other asterisks or part separators, it means "ends with what follows". This can
|
|
||||||
be optimized. */
|
|
||||||
|
|
||||||
if (plength > 1 && *glob == CHAR_ASTERISK)
|
|
||||||
{
|
|
||||||
PCRE2_SPTR pt;
|
|
||||||
for (pt = glob + plength - 1; pt > glob; pt--)
|
|
||||||
if (*pt == ccontext->glob_separator || *pt == CHAR_ASTERISK) break;
|
|
||||||
endswith = pt == glob;
|
|
||||||
if (endswith) PUTCHARS(STR_QUERY_s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output starts with \A and ends with \z and a binary zero. */
|
|
||||||
|
|
||||||
PUTCHARS(STR_BACKSLASH_A);
|
|
||||||
|
|
||||||
/* If the pattern starts with a wildcard, it must not match a subject that
|
|
||||||
starts with a dot. */
|
|
||||||
|
|
||||||
if (plength > 1 &&
|
|
||||||
(*glob == CHAR_ASTERISK || *glob == CHAR_QUESTION_MARK ||
|
|
||||||
*glob == CHAR_LEFT_SQUARE_BRACKET))
|
|
||||||
PUTCHARS(STR_LOOKAHEAD_NOT_DOT);
|
|
||||||
|
|
||||||
/* Now scan the input */
|
|
||||||
|
|
||||||
while (plength > 0)
|
|
||||||
{
|
|
||||||
uint32_t c, sc;
|
|
||||||
int clength = 1;
|
|
||||||
|
|
||||||
/* Add in the length of the last item, then, if in the dummy run, pull the
|
|
||||||
pointer back to the start of the (temporary) buffer and then remember the
|
|
||||||
start of the next item. */
|
|
||||||
|
|
||||||
convlength += p - pp;
|
|
||||||
if (dummyrun) p = use_buffer;
|
|
||||||
pp = p;
|
|
||||||
|
|
||||||
/* Pick up the next character */
|
|
||||||
|
|
||||||
#ifndef SUPPORT_UNICODE
|
|
||||||
c = *glob;
|
|
||||||
#else
|
|
||||||
GETCHARLENTEST(c, glob, clength);
|
|
||||||
#endif
|
|
||||||
glob += clength;
|
|
||||||
plength -= clength;
|
|
||||||
|
|
||||||
sc = nextisliteral? 0 : c;
|
|
||||||
nextisliteral = FALSE;
|
|
||||||
|
|
||||||
/* Handle a character within a class. */
|
|
||||||
|
|
||||||
if (inclass)
|
|
||||||
{
|
|
||||||
/* A literal part separator is a syntax error */
|
|
||||||
|
|
||||||
if (c == ccontext->glob_separator)
|
|
||||||
{
|
|
||||||
*bufflenptr = glob - pattern - 1;
|
|
||||||
return PCRE2_ERROR_CONVERT_SYNTAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At the end of the class, add a lookbehind for not the separator if any
|
|
||||||
range in the class includes the separator. */
|
|
||||||
|
|
||||||
if (c == CHAR_RIGHT_SQUARE_BRACKET)
|
|
||||||
{
|
|
||||||
PUTCHARS(STR_RIGHT_SQUARE_BRACKET);
|
|
||||||
if (sep_in_range) PUTCHARS(lookbehind_not_sep);
|
|
||||||
inclass = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not the end of the class */
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (posix_class_state)
|
|
||||||
{
|
|
||||||
case POSIX_CLASS_STARTED:
|
|
||||||
if (c <= 127 && islower(c)) break; /* Remain in started state */
|
|
||||||
posix_class_state = POSIX_CLASS_NOT_STARTED;
|
|
||||||
if (c == CHAR_COLON && plength > 0 &&
|
|
||||||
*glob == CHAR_RIGHT_SQUARE_BRACKET)
|
|
||||||
{
|
|
||||||
PUTCHARS(STR_COLON_RIGHT_SQUARE_BRACKET);
|
|
||||||
plength--;
|
|
||||||
glob++;
|
|
||||||
continue; /* With next character after :] */
|
|
||||||
}
|
|
||||||
/* Fall through */
|
|
||||||
|
|
||||||
case POSIX_CLASS_NOT_STARTED:
|
|
||||||
if (c == CHAR_LEFT_SQUARE_BRACKET)
|
|
||||||
posix_class_state = POSIX_CLASS_STARTING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case POSIX_CLASS_STARTING:
|
|
||||||
if (c == CHAR_COLON) posix_class_state = POSIX_CLASS_STARTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range_state == RANGE_STARTING && c == CHAR_MINUS)
|
|
||||||
range_state = RANGE_STARTED;
|
|
||||||
else if (range_state == RANGE_STARTED)
|
|
||||||
{
|
|
||||||
if (range_start <= ccontext->glob_separator &&
|
|
||||||
c >= ccontext->glob_separator)
|
|
||||||
sep_in_range = TRUE;
|
|
||||||
range_state = RANGE_NOT_STARTED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
range_state = RANGE_STARTING;
|
|
||||||
range_start = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == CHAR_BACKSLASH) PUTCHARS(STR_BACKSLASH);
|
|
||||||
if (p + clength > endp) return PCRE2_ERROR_NOMEMORY;
|
|
||||||
memcpy(p, glob - clength, CU2BYTES(clength));
|
|
||||||
p += clength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle a character not within a class. */
|
|
||||||
|
|
||||||
else switch(sc)
|
|
||||||
{
|
|
||||||
case CHAR_ASTERISK:
|
|
||||||
if (endswith)
|
|
||||||
{
|
|
||||||
PUTCHARS(STR_DOT_STAR_LOOKBEHIND);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PUTCHARS(not_sep_class);
|
|
||||||
PUTCHARS(STR_ASTERISK);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CHAR_QUESTION_MARK:
|
|
||||||
PUTCHARS(not_sep_class);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CHAR_LEFT_SQUARE_BRACKET:
|
|
||||||
posix_class_state = POSIX_CLASS_NOT_STARTED;
|
|
||||||
range_state = RANGE_NOT_STARTED;
|
|
||||||
sep_in_range = FALSE;
|
|
||||||
inclass = TRUE;
|
|
||||||
PUTCHARS(STR_LEFT_SQUARE_BRACKET);
|
|
||||||
|
|
||||||
/* Handle ! and ] as first characters */
|
|
||||||
|
|
||||||
if (plength > 0)
|
|
||||||
{
|
|
||||||
if (*glob == CHAR_EXCLAMATION_MARK)
|
|
||||||
{
|
|
||||||
glob++;
|
|
||||||
plength--;
|
|
||||||
PUTCHARS(STR_CIRCUMFLEX_ACCENT);
|
|
||||||
}
|
|
||||||
if (plength > 0 && *glob == CHAR_RIGHT_SQUARE_BRACKET)
|
|
||||||
{
|
|
||||||
glob++;
|
|
||||||
plength--;
|
|
||||||
PUTCHARS(STR_RIGHT_SQUARE_BRACKET);
|
|
||||||
range_start = CHAR_RIGHT_SQUARE_BRACKET;
|
|
||||||
range_state = RANGE_STARTING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CHAR_BACKSLASH:
|
|
||||||
if (plength <= 0) return ERROR_END_BACKSLASH;
|
|
||||||
nextisliteral = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)
|
|
||||||
{
|
|
||||||
PUTCHARS(STR_BACKSLASH);
|
|
||||||
}
|
|
||||||
if (p + clength > endp) return PCRE2_ERROR_NOMEMORY;
|
|
||||||
memcpy(p, glob - clength, CU2BYTES(clength));
|
|
||||||
p += clength;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inclass) return ERROR_MISSING_SQUARE_BRACKET;
|
|
||||||
|
|
||||||
if (endswith) PUTCHARS(STR_RIGHT_PARENTHESIS);
|
|
||||||
PUTCHARS(STR_BACKSLASH_z);
|
|
||||||
convlength += p - pp; /* Final segment */
|
|
||||||
*bufflenptr = convlength;
|
|
||||||
*p++ = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Convert a glob pattern *
|
* Convert a glob pattern *
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
@ -657,7 +381,7 @@ Arguments:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_glob_bash_write(pcre2_output_context *out, PCRE2_UCHAR chr)
|
convert_glob_write(pcre2_output_context *out, PCRE2_UCHAR chr)
|
||||||
{
|
{
|
||||||
out->output_size++;
|
out->output_size++;
|
||||||
|
|
||||||
|
@ -674,7 +398,7 @@ Arguments:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_glob_bash_write_str(pcre2_output_context *out, PCRE2_SIZE length)
|
convert_glob_write_str(pcre2_output_context *out, PCRE2_SIZE length)
|
||||||
{
|
{
|
||||||
uint8_t *out_str = out->out_str;
|
uint8_t *out_str = out->out_str;
|
||||||
PCRE2_UCHAR *output = out->output;
|
PCRE2_UCHAR *output = out->output;
|
||||||
|
@ -707,7 +431,7 @@ Returns: TRUE => success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
convert_glob_bash_parse_class(PCRE2_SPTR *from, PCRE2_SPTR pattern_end,
|
convert_glob_parse_class(PCRE2_SPTR *from, PCRE2_SPTR pattern_end,
|
||||||
pcre2_output_context *out)
|
pcre2_output_context *out)
|
||||||
{
|
{
|
||||||
static const char *posix_classes = "alnum:alpha:ascii:blank:cntrl:digit:"
|
static const char *posix_classes = "alnum:alpha:ascii:blank:cntrl:digit:"
|
||||||
|
@ -719,7 +443,7 @@ PCRE2_UCHAR c;
|
||||||
|
|
||||||
out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET;
|
out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET;
|
||||||
out->out_str[1] = CHAR_COLON;
|
out->out_str[1] = CHAR_COLON;
|
||||||
convert_glob_bash_write_str(out, 2);
|
convert_glob_write_str(out, 2);
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
@ -744,7 +468,7 @@ while (TRUE)
|
||||||
return ERROR_MISSING_SQUARE_BRACKET;
|
return ERROR_MISSING_SQUARE_BRACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_glob_bash_write(out, c);
|
convert_glob_write(out, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = *from;
|
start = *from;
|
||||||
|
@ -763,7 +487,7 @@ while (TRUE)
|
||||||
{
|
{
|
||||||
out->out_str[0] = CHAR_COLON;
|
out->out_str[0] = CHAR_COLON;
|
||||||
out->out_str[1] = CHAR_RIGHT_SQUARE_BRACKET;
|
out->out_str[1] = CHAR_RIGHT_SQUARE_BRACKET;
|
||||||
convert_glob_bash_write_str(out, 2);
|
convert_glob_write_str(out, 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pattern++;
|
pattern++;
|
||||||
|
@ -783,14 +507,15 @@ Arguments:
|
||||||
pattern_end end of pattern
|
pattern_end end of pattern
|
||||||
out output context
|
out output context
|
||||||
separator glob separator
|
separator glob separator
|
||||||
|
with_escape backslash is needed before separator
|
||||||
|
|
||||||
Returns: 0 => success
|
Returns: 0 => success
|
||||||
!0 => error code
|
!0 => error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
convert_glob_bash_parse_range(PCRE2_SPTR *from, PCRE2_SPTR pattern_end,
|
convert_glob_parse_range(PCRE2_SPTR *from, PCRE2_SPTR pattern_end,
|
||||||
pcre2_output_context *out, PCRE2_UCHAR separator)
|
pcre2_output_context *out, PCRE2_UCHAR separator, BOOL with_escape)
|
||||||
{
|
{
|
||||||
PCRE2_SPTR pattern = *from;
|
PCRE2_SPTR pattern = *from;
|
||||||
PCRE2_UCHAR c;
|
PCRE2_UCHAR c;
|
||||||
|
@ -819,14 +544,15 @@ else
|
||||||
len = 3;
|
len = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (separator < 128 && strchr(pcre2_escaped_literals, separator) != NULL)
|
if (with_escape)
|
||||||
{
|
{
|
||||||
out->out_str[len] = CHAR_BACKSLASH;
|
out->out_str[len] = CHAR_BACKSLASH;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_glob_bash_write_str(out, len);
|
out->out_str[len] = (uint8_t) separator;
|
||||||
convert_glob_bash_write(out, separator);
|
|
||||||
|
convert_glob_write_str(out, len + 1);
|
||||||
|
|
||||||
if (c == CHAR_EXCLAMATION_MARK
|
if (c == CHAR_EXCLAMATION_MARK
|
||||||
|| c == CHAR_CIRCUMFLEX_ACCENT)
|
|| c == CHAR_CIRCUMFLEX_ACCENT)
|
||||||
|
@ -843,13 +569,13 @@ else
|
||||||
{
|
{
|
||||||
out->out_str[0] = CHAR_RIGHT_PARENTHESIS;
|
out->out_str[0] = CHAR_RIGHT_PARENTHESIS;
|
||||||
out->out_str[1] = CHAR_LEFT_SQUARE_BRACKET;
|
out->out_str[1] = CHAR_LEFT_SQUARE_BRACKET;
|
||||||
convert_glob_bash_write_str(out, 2);
|
convert_glob_write_str(out, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == CHAR_MINUS || c == CHAR_RIGHT_SQUARE_BRACKET)
|
if (c == CHAR_MINUS || c == CHAR_RIGHT_SQUARE_BRACKET)
|
||||||
{
|
{
|
||||||
convert_glob_bash_write(out, CHAR_BACKSLASH);
|
convert_glob_write(out, CHAR_BACKSLASH);
|
||||||
convert_glob_bash_write(out, c);
|
convert_glob_write(out, c);
|
||||||
pattern++;
|
pattern++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,38 +585,48 @@ while (pattern < pattern_end)
|
||||||
|
|
||||||
if (c == CHAR_RIGHT_SQUARE_BRACKET)
|
if (c == CHAR_RIGHT_SQUARE_BRACKET)
|
||||||
{
|
{
|
||||||
convert_glob_bash_write(out, c);
|
convert_glob_write(out, c);
|
||||||
*from = pattern;
|
*from = pattern;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == CHAR_LEFT_SQUARE_BRACKET && pattern < pattern_end &&
|
if (pattern >= pattern_end) break;
|
||||||
*pattern == CHAR_COLON)
|
|
||||||
|
if (c == CHAR_LEFT_SQUARE_BRACKET && *pattern == CHAR_COLON)
|
||||||
{
|
{
|
||||||
*from = pattern + 1;
|
*from = pattern + 1;
|
||||||
|
|
||||||
result = convert_glob_bash_parse_class(from, pattern_end, out);
|
result = convert_glob_parse_class(from, pattern_end, out);
|
||||||
if (result != 0) return result;
|
if (result != 0) return result;
|
||||||
|
|
||||||
pattern = *from;
|
pattern = *from;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == CHAR_BACKSLASH)
|
/* A dash after a character class is a normal character. */
|
||||||
{
|
if (pattern >= pattern_end || *pattern != CHAR_MINUS)
|
||||||
if (pattern >= pattern_end)
|
continue;
|
||||||
{
|
|
||||||
*from = pattern;
|
c = CHAR_MINUS;
|
||||||
return ERROR_END_BACKSLASH;
|
pattern++;
|
||||||
}
|
|
||||||
c = *pattern++;
|
|
||||||
}
|
}
|
||||||
|
else if (c == CHAR_MINUS)
|
||||||
|
{
|
||||||
|
convert_glob_write(out, CHAR_MINUS);
|
||||||
|
c = *pattern++;
|
||||||
|
|
||||||
|
if (c == CHAR_BACKSLASH)
|
||||||
|
{
|
||||||
|
if (pattern >= pattern_end) break;
|
||||||
|
c = *pattern++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == CHAR_BACKSLASH)
|
||||||
|
c = *pattern++;
|
||||||
|
|
||||||
if (c == CHAR_LEFT_SQUARE_BRACKET || c == CHAR_RIGHT_SQUARE_BRACKET ||
|
if (c == CHAR_LEFT_SQUARE_BRACKET || c == CHAR_RIGHT_SQUARE_BRACKET ||
|
||||||
c == CHAR_BACKSLASH || c == CHAR_MINUS)
|
c == CHAR_BACKSLASH || c == CHAR_MINUS)
|
||||||
convert_glob_bash_write(out, CHAR_BACKSLASH);
|
convert_glob_write(out, CHAR_BACKSLASH);
|
||||||
|
|
||||||
convert_glob_bash_write(out, c);
|
convert_glob_write(out, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
*from = pattern;
|
*from = pattern;
|
||||||
|
@ -898,32 +634,66 @@ return ERROR_MISSING_SQUARE_BRACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Prints the separator into the output.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
out output context
|
||||||
|
separator glob separator
|
||||||
|
with_escape backslash is needed before separator
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
convert_glob_print_separator(pcre2_output_context *out,
|
||||||
|
PCRE2_UCHAR separator, BOOL with_escape)
|
||||||
|
{
|
||||||
|
if (with_escape)
|
||||||
|
convert_glob_write(out, CHAR_BACKSLASH);
|
||||||
|
|
||||||
|
convert_glob_write(out, separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Prints a wildcard into the output.
|
/* Prints a wildcard into the output.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
out output context
|
out output context
|
||||||
separator glob separator
|
separator glob separator
|
||||||
|
with_escape backslash is needed before separator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_glob_bash_wildcard(pcre2_output_context *out,
|
convert_glob_print_wildcard(pcre2_output_context *out,
|
||||||
PCRE2_UCHAR separator)
|
PCRE2_UCHAR separator, BOOL with_escape)
|
||||||
{
|
{
|
||||||
int len = 2;
|
|
||||||
|
|
||||||
out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET;
|
out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET;
|
||||||
out->out_str[1] = CHAR_CIRCUMFLEX_ACCENT;
|
out->out_str[1] = CHAR_CIRCUMFLEX_ACCENT;
|
||||||
|
convert_glob_write_str(out, 2);
|
||||||
|
|
||||||
if (separator < 128 && strchr(pcre2_escaped_literals, separator) != NULL)
|
convert_glob_print_separator(out, separator, with_escape);
|
||||||
{
|
|
||||||
out->out_str[2] = CHAR_BACKSLASH;
|
|
||||||
len = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_glob_bash_write_str(out, len);
|
convert_glob_write(out, CHAR_RIGHT_SQUARE_BRACKET);
|
||||||
|
}
|
||||||
|
|
||||||
convert_glob_bash_write(out, separator);
|
|
||||||
convert_glob_bash_write(out, CHAR_RIGHT_SQUARE_BRACKET);
|
/* Prints a (*COMMIT) into the output.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
out output context
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
convert_glob_print_commit(pcre2_output_context *out)
|
||||||
|
{
|
||||||
|
out->out_str[0] = CHAR_LEFT_PARENTHESIS;
|
||||||
|
out->out_str[1] = CHAR_ASTERISK;
|
||||||
|
out->out_str[2] = CHAR_C;
|
||||||
|
out->out_str[3] = CHAR_O;
|
||||||
|
out->out_str[4] = CHAR_M;
|
||||||
|
out->out_str[5] = CHAR_M;
|
||||||
|
out->out_str[6] = CHAR_I;
|
||||||
|
out->out_str[7] = CHAR_T;
|
||||||
|
convert_glob_write_str(out, 8);
|
||||||
|
convert_glob_write(out, CHAR_RIGHT_PARENTHESIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -945,15 +715,26 @@ Returns: 0 => success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
convert_glob_bash(uint32_t options, PCRE2_SPTR pattern, PCRE2_SIZE plength,
|
convert_glob(uint32_t options, PCRE2_SPTR pattern, PCRE2_SIZE plength,
|
||||||
BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length,
|
BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length,
|
||||||
PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext)
|
PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext)
|
||||||
{
|
{
|
||||||
pcre2_output_context out;
|
pcre2_output_context out;
|
||||||
PCRE2_SPTR pattern_start = pattern;
|
PCRE2_SPTR pattern_start = pattern;
|
||||||
PCRE2_SPTR pattern_end = pattern + plength;
|
PCRE2_SPTR pattern_end = pattern + plength;
|
||||||
|
PCRE2_UCHAR separator = ccontext->glob_separator;
|
||||||
PCRE2_UCHAR c;
|
PCRE2_UCHAR c;
|
||||||
int result;
|
BOOL with_escape, is_start;
|
||||||
|
int result, len;
|
||||||
|
|
||||||
|
if (separator >= 128)
|
||||||
|
{
|
||||||
|
/* Currently only ASCII separators are supported. */
|
||||||
|
*bufflenptr = 0;
|
||||||
|
return PCRE2_ERROR_CONVERT_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
with_escape = strchr(pcre2_escaped_literals, separator) != NULL;
|
||||||
|
|
||||||
/* Initialize default for error offset as end of input. */
|
/* Initialize default for error offset as end of input. */
|
||||||
out.output = use_buffer;
|
out.output = use_buffer;
|
||||||
|
@ -964,9 +745,15 @@ out.out_str[0] = CHAR_LEFT_PARENTHESIS;
|
||||||
out.out_str[1] = CHAR_QUESTION_MARK;
|
out.out_str[1] = CHAR_QUESTION_MARK;
|
||||||
out.out_str[2] = CHAR_s;
|
out.out_str[2] = CHAR_s;
|
||||||
out.out_str[3] = CHAR_RIGHT_PARENTHESIS;
|
out.out_str[3] = CHAR_RIGHT_PARENTHESIS;
|
||||||
out.out_str[4] = CHAR_BACKSLASH;
|
convert_glob_write_str(&out, 4);
|
||||||
out.out_str[5] = CHAR_A;
|
|
||||||
convert_glob_bash_write_str(&out, 6);
|
if (pattern + 1 >= pattern_end ||
|
||||||
|
pattern[0] != CHAR_ASTERISK || pattern[1] != CHAR_ASTERISK)
|
||||||
|
{
|
||||||
|
out.out_str[0] = CHAR_BACKSLASH;
|
||||||
|
out.out_str[1] = CHAR_A;
|
||||||
|
convert_glob_write_str(&out, 2);
|
||||||
|
}
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
|
@ -976,37 +763,112 @@ while (pattern < pattern_end)
|
||||||
|
|
||||||
if (c == CHAR_ASTERISK)
|
if (c == CHAR_ASTERISK)
|
||||||
{
|
{
|
||||||
if (pattern != pattern_start + 1)
|
if (pattern < pattern_end && *pattern == CHAR_ASTERISK)
|
||||||
{
|
{
|
||||||
|
is_start = pattern == pattern_start + 1;
|
||||||
|
|
||||||
|
if (!is_start && pattern[-2] != separator)
|
||||||
|
{
|
||||||
|
result = PCRE2_ERROR_CONVERT_SYNTAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
do pattern++; while (pattern < pattern_end &&
|
||||||
|
*pattern == CHAR_ASTERISK);
|
||||||
|
|
||||||
|
if (pattern >= pattern_end)
|
||||||
|
{
|
||||||
|
convert_glob_write(&out, CHAR_NULL);
|
||||||
|
|
||||||
|
if (!dummyrun &&
|
||||||
|
out.output_size != (PCRE2_SIZE) (out.output - use_buffer))
|
||||||
|
{
|
||||||
|
result = PCRE2_ERROR_NOMEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*bufflenptr = out.output_size - 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pattern == CHAR_BACKSLASH)
|
||||||
|
{
|
||||||
|
pattern++;
|
||||||
|
if (pattern >= pattern_end)
|
||||||
|
{
|
||||||
|
result = PCRE2_ERROR_CONVERT_SYNTAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pattern != separator)
|
||||||
|
{
|
||||||
|
result = PCRE2_ERROR_CONVERT_SYNTAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern++;
|
||||||
|
|
||||||
|
if (is_start)
|
||||||
|
{
|
||||||
|
out.out_str[0] = CHAR_LEFT_PARENTHESIS;
|
||||||
|
out.out_str[1] = CHAR_QUESTION_MARK;
|
||||||
|
out.out_str[2] = CHAR_COLON;
|
||||||
|
out.out_str[3] = CHAR_BACKSLASH;
|
||||||
|
out.out_str[4] = CHAR_A;
|
||||||
|
out.out_str[5] = CHAR_VERTICAL_LINE;
|
||||||
|
convert_glob_write_str(&out, 6);
|
||||||
|
|
||||||
|
convert_glob_print_wildcard(&out, separator, with_escape);
|
||||||
|
convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_glob_print_commit(&out);
|
||||||
|
|
||||||
out.out_str[0] = CHAR_LEFT_PARENTHESIS;
|
out.out_str[0] = CHAR_LEFT_PARENTHESIS;
|
||||||
out.out_str[1] = CHAR_ASTERISK;
|
out.out_str[1] = CHAR_QUESTION_MARK;
|
||||||
out.out_str[2] = CHAR_C;
|
out.out_str[2] = CHAR_COLON;
|
||||||
out.out_str[3] = CHAR_O;
|
out.out_str[3] = CHAR_DOT;
|
||||||
out.out_str[4] = CHAR_M;
|
out.out_str[4] = CHAR_ASTERISK;
|
||||||
out.out_str[5] = CHAR_M;
|
out.out_str[5] = CHAR_QUESTION_MARK;
|
||||||
out.out_str[6] = CHAR_I;
|
len = 6;
|
||||||
out.out_str[7] = CHAR_T;
|
|
||||||
convert_glob_bash_write_str(&out, 8);
|
if (with_escape)
|
||||||
convert_glob_bash_write(&out, CHAR_RIGHT_PARENTHESIS);
|
{
|
||||||
|
out.out_str[6] = CHAR_BACKSLASH;
|
||||||
|
len = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_glob_write_str(&out, len);
|
||||||
|
|
||||||
|
out.out_str[0] = (uint8_t) separator;
|
||||||
|
out.out_str[1] = CHAR_RIGHT_PARENTHESIS;
|
||||||
|
out.out_str[2] = CHAR_QUESTION_MARK;
|
||||||
|
out.out_str[3] = CHAR_QUESTION_MARK;
|
||||||
|
convert_glob_write_str(&out, 4);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_glob_bash_wildcard(&out, ccontext->glob_separator);
|
if (pattern != pattern_start + 1)
|
||||||
|
convert_glob_print_commit(&out);
|
||||||
|
|
||||||
|
convert_glob_print_wildcard(&out, separator, with_escape);
|
||||||
out.out_str[0] = CHAR_ASTERISK;
|
out.out_str[0] = CHAR_ASTERISK;
|
||||||
out.out_str[1] = CHAR_QUESTION_MARK;
|
out.out_str[1] = CHAR_QUESTION_MARK;
|
||||||
convert_glob_bash_write_str(&out, 2);
|
convert_glob_write_str(&out, 2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == CHAR_QUESTION_MARK)
|
if (c == CHAR_QUESTION_MARK)
|
||||||
{
|
{
|
||||||
convert_glob_bash_wildcard(&out, ccontext->glob_separator);
|
convert_glob_print_wildcard(&out, separator, with_escape);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == CHAR_LEFT_SQUARE_BRACKET)
|
if (c == CHAR_LEFT_SQUARE_BRACKET)
|
||||||
{
|
{
|
||||||
result = convert_glob_bash_parse_range(&pattern, pattern_end,
|
result = convert_glob_parse_range(&pattern, pattern_end,
|
||||||
&out, ccontext->glob_separator);
|
&out, separator, with_escape);
|
||||||
if (result != 0) break;
|
if (result != 0) break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1022,9 +884,9 @@ while (pattern < pattern_end)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)
|
if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL)
|
||||||
convert_glob_bash_write(&out, CHAR_BACKSLASH);
|
convert_glob_write(&out, CHAR_BACKSLASH);
|
||||||
|
|
||||||
convert_glob_bash_write(&out, c);
|
convert_glob_write(&out, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
|
@ -1032,9 +894,9 @@ if (result == 0)
|
||||||
out.out_str[0] = CHAR_BACKSLASH;
|
out.out_str[0] = CHAR_BACKSLASH;
|
||||||
out.out_str[1] = CHAR_z;
|
out.out_str[1] = CHAR_z;
|
||||||
out.out_str[2] = CHAR_NULL;
|
out.out_str[2] = CHAR_NULL;
|
||||||
convert_glob_bash_write_str(&out, 3);
|
convert_glob_write_str(&out, 3);
|
||||||
|
|
||||||
if (!dummyrun && out.output_size != (out.output - use_buffer))
|
if (!dummyrun && out.output_size != (PCRE2_SIZE) (out.output - use_buffer))
|
||||||
result = PCRE2_ERROR_NOMEMORY;
|
result = PCRE2_ERROR_NOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1130,17 +992,10 @@ for (i = 0; i < 2; i++)
|
||||||
switch(pattype)
|
switch(pattype)
|
||||||
{
|
{
|
||||||
case PCRE2_CONVERT_GLOB:
|
case PCRE2_CONVERT_GLOB:
|
||||||
rc = convert_glob(pattype, pattern, plength, utf, use_buffer, use_length,
|
rc = convert_glob(options, pattern, plength, utf, use_buffer, use_length,
|
||||||
bufflenptr, dummyrun, ccontext);
|
bufflenptr, dummyrun, ccontext);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
|
||||||
case PCRE2_CONVERT_GLOB_BASH:
|
|
||||||
rc = convert_glob_bash(options, pattern, plength, utf, use_buffer, use_length,
|
|
||||||
bufflenptr, dummyrun, ccontext);
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
|
|
||||||
case PCRE2_CONVERT_POSIX_BASIC:
|
case PCRE2_CONVERT_POSIX_BASIC:
|
||||||
case PCRE2_CONVERT_POSIX_EXTENDED:
|
case PCRE2_CONVERT_POSIX_EXTENDED:
|
||||||
rc = convert_posix(pattype, pattern, plength, utf, use_buffer, use_length,
|
rc = convert_posix(pattype, pattern, plength, utf, use_buffer, use_length,
|
||||||
|
|
|
@ -13,10 +13,6 @@
|
||||||
|
|
||||||
/abc/posix
|
/abc/posix
|
||||||
|
|
||||||
# More than one glob type is an error.
|
|
||||||
|
|
||||||
/abc/convert=glob_bash
|
|
||||||
|
|
||||||
# Separator must be / \ or .
|
# Separator must be / \ or .
|
||||||
|
|
||||||
/a*b/convert_glob_separator=%
|
/a*b/convert_glob_separator=%
|
||||||
|
@ -213,13 +209,8 @@
|
||||||
|
|
||||||
/a*b/convert_glob_separator=/
|
/a*b/convert_glob_separator=/
|
||||||
|
|
||||||
#pattern convert=unset
|
|
||||||
#pattern convert=glob_bash,convert_glob_separator=/
|
|
||||||
|
|
||||||
# Non control character checking
|
# Non control character checking
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
/A\B\\C\D/
|
/A\B\\C\D/
|
||||||
|
|
||||||
/\\{}\?\*+\[\]()|.^$/
|
/\\{}\?\*+\[\]()|.^$/
|
||||||
|
@ -244,6 +235,13 @@
|
||||||
|
|
||||||
/[[:xdigit::]]/
|
/[[:xdigit::]]/
|
||||||
|
|
||||||
|
/****/
|
||||||
|
|
||||||
|
/**\/abc/
|
||||||
|
|
||||||
|
/abc\/**/
|
||||||
|
|
||||||
|
/abc\/**\/abc/
|
||||||
|
|
||||||
#pattern convert=unset
|
#pattern convert=unset
|
||||||
#pattern convert=posix_extended
|
#pattern convert=posix_extended
|
||||||
|
|
|
@ -14,11 +14,6 @@
|
||||||
/abc/posix
|
/abc/posix
|
||||||
** The convert and posix modifiers are mutually exclusive
|
** The convert and posix modifiers are mutually exclusive
|
||||||
|
|
||||||
# More than one glob type is an error.
|
|
||||||
|
|
||||||
/abc/convert=glob_bash
|
|
||||||
** Pattern conversion error at offset 0: bad option value
|
|
||||||
|
|
||||||
# Separator must be / \ or .
|
# Separator must be / \ or .
|
||||||
|
|
||||||
/a*b/convert_glob_separator=%
|
/a*b/convert_glob_separator=%
|
||||||
|
@ -53,7 +48,7 @@
|
||||||
# Tests from the gitwildmatch list, with some additions
|
# Tests from the gitwildmatch list, with some additions
|
||||||
|
|
||||||
/foo/
|
/foo/
|
||||||
\Afoo\z
|
(?s)\Afoo\z
|
||||||
foo
|
foo
|
||||||
0: foo
|
0: foo
|
||||||
/= Expect no match
|
/= Expect no match
|
||||||
|
@ -62,7 +57,7 @@ No match
|
||||||
No match
|
No match
|
||||||
|
|
||||||
//
|
//
|
||||||
\A\z
|
(?s)\A\z
|
||||||
\
|
\
|
||||||
0:
|
0:
|
||||||
|
|
||||||
|
@ -75,14 +70,14 @@ No match
|
||||||
No match
|
No match
|
||||||
|
|
||||||
/*/
|
/*/
|
||||||
\A[^/]*\z
|
(?s)\A[^\/]*?\z
|
||||||
foo
|
foo
|
||||||
0: foo
|
0: foo
|
||||||
\
|
\
|
||||||
0:
|
0:
|
||||||
|
|
||||||
/f*/
|
/f*/
|
||||||
\Af[^/]*\z
|
(?s)\Af(*COMMIT)[^\/]*?\z
|
||||||
foo
|
foo
|
||||||
0: foo
|
0: foo
|
||||||
f
|
f
|
||||||
|
@ -116,18 +111,18 @@ No match
|
||||||
0: aaaaaaabababab
|
0: aaaaaaabababab
|
||||||
|
|
||||||
/foo\*/
|
/foo\*/
|
||||||
\Afoo\*\z
|
(?s)\Afoo\*\z
|
||||||
foo*
|
foo*
|
||||||
0: foo*
|
0: foo*
|
||||||
|
|
||||||
/foo\*bar/
|
/foo\*bar/
|
||||||
\Afoo\*bar\z
|
(?s)\Afoo\*bar\z
|
||||||
\= Expect no match
|
\= Expect no match
|
||||||
foobar
|
foobar
|
||||||
No match
|
No match
|
||||||
|
|
||||||
/f\\oo/
|
/f\\oo/
|
||||||
\Af\\oo\z
|
(?s)\Af\\oo\z
|
||||||
f\\oo
|
f\\oo
|
||||||
0: f\oo
|
0: f\oo
|
||||||
|
|
||||||
|
@ -339,14 +334,8 @@ No match
|
||||||
/a*b/convert_glob_separator=/
|
/a*b/convert_glob_separator=/
|
||||||
\Aa[^/]*b\z
|
\Aa[^/]*b\z
|
||||||
|
|
||||||
#pattern convert=unset
|
|
||||||
#pattern convert=glob_bash,convert_glob_separator=/
|
|
||||||
|
|
||||||
# Non control character checking
|
# Non control character checking
|
||||||
|
|
||||||
//
|
|
||||||
(?s)\A\z
|
|
||||||
|
|
||||||
/A\B\\C\D/
|
/A\B\\C\D/
|
||||||
(?s)\AAB\\CD\z
|
(?s)\AAB\\CD\z
|
||||||
|
|
||||||
|
@ -383,6 +372,17 @@ No match
|
||||||
/[[:xdigit::]]/
|
/[[:xdigit::]]/
|
||||||
** Pattern conversion error at offset 10: missing terminating ] for character class
|
** Pattern conversion error at offset 10: missing terminating ] for character class
|
||||||
|
|
||||||
|
/****/
|
||||||
|
(?s)
|
||||||
|
|
||||||
|
/**\/abc/
|
||||||
|
(?s)(?:\A|[^/])abc\z
|
||||||
|
|
||||||
|
/abc\/**/
|
||||||
|
(?s)\Aabc/
|
||||||
|
|
||||||
|
/abc\/**\/abc/
|
||||||
|
(?s)\Aabc/(*COMMIT)(?:.*?/)??abc\z
|
||||||
|
|
||||||
#pattern convert=unset
|
#pattern convert=unset
|
||||||
#pattern convert=posix_extended
|
#pattern convert=posix_extended
|
||||||
|
|
Loading…
Reference in New Issue