Index: main/pbx.c =================================================================== --- main/pbx.c (revision 228977) +++ main/pbx.c (working copy) @@ -2133,16 +2133,16 @@ * we could encode the special cases as 0xffXX where XX * is 1, 2, 3, 4 as used above. */ -static int ext_cmp1(const char **p) +static int ext_cmp1(const char **p, unsigned char *bitwise) { - uint32_t chars[8]; - int c, cmin = 0xff, count = 0; + int c, count = 0; const char *end; /* load, sign extend and advance pointer until we find * a valid character. */ c = *(*p)++; + memset(bitwise, 0xff, 32); /* always return unless we have a set of chars */ switch (toupper(c)) { @@ -2150,13 +2150,20 @@ return 0x0000 | (c & 0xff); case 'N': /* 2..9 */ - return 0x0800 | '2' ; + bitwise[6] = 0x01; + bitwise[7] = 0xfe; + return 0x0800; case 'X': /* 0..9 */ - return 0x0A00 | '0'; + bitwise[5] = 0x7f; + bitwise[6] = 0x00; + bitwise[7] = 0xfe; + return 0x0A00; case 'Z': /* 1..9 */ - return 0x0900 | '1'; + bitwise[6] = 0x00; + bitwise[7] = 0xfe; + return 0x0900; case '.': /* wildcard */ return 0x10000; @@ -2179,26 +2186,29 @@ return 0x40000; /* XXX make this entry go last... */ } - memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */ for (; *p < end ; (*p)++) { unsigned char c1, c2; /* first-last char in range */ c1 = (unsigned char)((*p)[0]); if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ c2 = (unsigned char)((*p)[2]); - *p += 2; /* skip a total of 3 chars */ - } else /* individual character */ + *p += 2; /* skip a total of 3 chars */ + } else { /* individual character */ c2 = c1; - if (c1 < cmin) - cmin = c1; + } for (; c1 <= c2; c1++) { - uint32_t mask = 1 << (c1 % 32); - if ( (chars[ c1 / 32 ] & mask) == 0) + unsigned char mask = 1 << (c1 % 8); + /* Count the number of characters in the class, discarding duplicates. */ + if ( (bitwise[ c1 / 8 ] & mask) == 1) { count += 0x100; - chars[ c1 / 32 ] |= mask; + } + /*!\note If two patterns score the same, but one includes '0' (as + * the lowest ASCII value in the given class) and the other does + * not, then the one including '0' will compare as coming first. */ + bitwise[ c1 / 8 ] &= ~mask; } } (*p)++; - return count == 0 ? 0x30000 : (count | cmin); + return count == 0 ? 0x30000 : count; } /*! @@ -2208,8 +2218,9 @@ { /* make sure non-patterns come first. * If a is not a pattern, it either comes first or - * we use strcmp to compare the strings. + * we do a more complex pattern comparison. */ + unsigned char bitwise[2][32]; int ret = 0; if (a[0] != '_') @@ -2218,16 +2229,20 @@ /* Now we know a is a pattern; if b is not, a comes first */ if (b[0] != '_') return 1; -#if 0 /* old mode for ext matching */ - return strcmp(a, b); -#endif + /* ok we need full pattern sorting routine */ - while (!ret && a && b) - ret = ext_cmp1(&a) - ext_cmp1(&b); - if (ret == 0) + while (!ret && a && b) { + ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); + if (ret == 0) { + /* Are the classes different, even though they score the same? */ + ret = memcmp(bitwise[0], bitwise[1], 32); + } + } + if (ret == 0) { return 0; - else + } else { return (ret > 0) ? 1 : -1; + } } int ast_extension_cmp(const char *a, const char *b)