Skip to content

Commit d9fde06

Browse files
committed
Merge branch 'rs/ctype'
* rs/ctype: Add is_regex_special() Change NUL char handling of isspecial() Reformat ctype.c Add ctype test Conflicts: Makefile
2 parents 1afcde6 + f9b7cce commit d9fde06

File tree

7 files changed

+118
-29
lines changed

7 files changed

+118
-29
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,7 @@ endif
13571357
### Testing rules
13581358

13591359
TEST_PROGRAMS += test-chmtime$X
1360+
TEST_PROGRAMS += test-ctype$X
13601361
TEST_PROGRAMS += test-date$X
13611362
TEST_PROGRAMS += test-delta$X
13621363
TEST_PROGRAMS += test-genrandom$X
@@ -1376,6 +1377,8 @@ export NO_SVN_TESTS
13761377
test: all
13771378
$(MAKE) -C t/ all
13781379

1380+
test-ctype$X: ctype.o
1381+
13791382
test-date$X: date.o ctype.o
13801383

13811384
test-delta$X: diff-delta.o patch-delta.o

ctype.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,22 @@
55
*/
66
#include "cache.h"
77

8-
/* Just so that no insane platform contaminate namespace with these symbols */
9-
#undef SS
10-
#undef AA
11-
#undef DD
12-
#undef GS
13-
14-
#define SS GIT_SPACE
15-
#define AA GIT_ALPHA
16-
#define DD GIT_DIGIT
17-
#define GS GIT_SPECIAL /* \0, *, ?, [, \\ */
8+
enum {
9+
S = GIT_SPACE,
10+
A = GIT_ALPHA,
11+
D = GIT_DIGIT,
12+
G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
13+
R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */
14+
};
1815

1916
unsigned char sane_ctype[256] = {
20-
GS, 0, 0, 0, 0, 0, 0, 0, 0, SS, SS, 0, 0, SS, 0, 0, /* 0-15 */
21-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-15 */
22-
SS, 0, 0, 0, 0, 0, 0, 0, 0, 0, GS, 0, 0, 0, 0, 0, /* 32-15 */
23-
DD, DD, DD, DD, DD, DD, DD, DD, DD, DD, 0, 0, 0, 0, 0, GS, /* 48-15 */
24-
0, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, /* 64-15 */
25-
AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, GS, GS, 0, 0, 0, /* 80-15 */
26-
0, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, /* 96-15 */
27-
AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, 0, 0, 0, 0, 0, /* 112-15 */
17+
0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */
18+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */
19+
S, 0, 0, 0, R, 0, 0, 0, R, R, G, R, 0, 0, R, 0, /* 32.. 47 */
20+
D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, G, /* 48.. 63 */
21+
0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */
22+
A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, 0, /* 80.. 95 */
23+
0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */
24+
A, A, A, A, A, A, A, A, A, A, A, R, R, 0, 0, 0, /* 112..127 */
2825
/* Nothing in the 128.. range */
2926
};

dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static int match_one(const char *match, const char *name, int namelen)
7575
for (;;) {
7676
unsigned char c1 = *match;
7777
unsigned char c2 = *name;
78-
if (isspecial(c1))
78+
if (c1 == '\0' || is_glob_special(c1))
7979
break;
8080
if (c1 != c2)
8181
return 0;
@@ -678,7 +678,7 @@ static int simple_length(const char *match)
678678
for (;;) {
679679
unsigned char c = *match++;
680680
len++;
681-
if (isspecial(c))
681+
if (c == '\0' || is_glob_special(c))
682682
return len;
683683
}
684684
}

git-compat-util.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,15 @@ extern unsigned char sane_ctype[256];
327327
#define GIT_SPACE 0x01
328328
#define GIT_DIGIT 0x02
329329
#define GIT_ALPHA 0x04
330-
#define GIT_SPECIAL 0x08
330+
#define GIT_GLOB_SPECIAL 0x08
331+
#define GIT_REGEX_SPECIAL 0x10
331332
#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
332333
#define isspace(x) sane_istest(x,GIT_SPACE)
333334
#define isdigit(x) sane_istest(x,GIT_DIGIT)
334335
#define isalpha(x) sane_istest(x,GIT_ALPHA)
335336
#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
336-
#define isspecial(x) sane_istest(x,GIT_SPECIAL)
337+
#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
338+
#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
337339
#define tolower(x) sane_case((unsigned char)(x), 0x20)
338340
#define toupper(x) sane_case((unsigned char)(x), 0)
339341

grep.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,9 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
2828
p->next = NULL;
2929
}
3030

31-
static int isregexspecial(int c)
32-
{
33-
return isspecial(c) || c == '$' || c == '(' || c == ')' || c == '+' ||
34-
c == '.' || c == '^' || c == '{' || c == '|';
35-
}
36-
3731
static int is_fixed(const char *s)
3832
{
39-
while (!isregexspecial(*s))
33+
while (*s && !is_regex_special(*s))
4034
s++;
4135
return !*s;
4236
}

t/t0070-fundamental.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/sh
2+
3+
test_description='check that the most basic functions work
4+
5+
6+
Verify wrappers and compatibility functions.
7+
'
8+
9+
. ./test-lib.sh
10+
11+
test_expect_success 'character classes (isspace, isalpha etc.)' '
12+
test-ctype
13+
'
14+
15+
test_done

test-ctype.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "cache.h"
2+
3+
4+
static int test_isdigit(int c)
5+
{
6+
return isdigit(c);
7+
}
8+
9+
static int test_isspace(int c)
10+
{
11+
return isspace(c);
12+
}
13+
14+
static int test_isalpha(int c)
15+
{
16+
return isalpha(c);
17+
}
18+
19+
static int test_isalnum(int c)
20+
{
21+
return isalnum(c);
22+
}
23+
24+
static int test_is_glob_special(int c)
25+
{
26+
return is_glob_special(c);
27+
}
28+
29+
static int test_is_regex_special(int c)
30+
{
31+
return is_regex_special(c);
32+
}
33+
34+
#define DIGIT "0123456789"
35+
#define LOWER "abcdefghijklmnopqrstuvwxyz"
36+
#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
37+
38+
static const struct ctype_class {
39+
const char *name;
40+
int (*test_fn)(int);
41+
const char *members;
42+
} classes[] = {
43+
{ "isdigit", test_isdigit, DIGIT },
44+
{ "isspace", test_isspace, " \n\r\t" },
45+
{ "isalpha", test_isalpha, LOWER UPPER },
46+
{ "isalnum", test_isalnum, LOWER UPPER DIGIT },
47+
{ "is_glob_special", test_is_glob_special, "*?[\\" },
48+
{ "is_regex_special", test_is_regex_special, "$()*+.?[\\^{|" },
49+
{ NULL }
50+
};
51+
52+
static int test_class(const struct ctype_class *test)
53+
{
54+
int i, rc = 0;
55+
56+
for (i = 0; i < 256; i++) {
57+
int expected = i ? !!strchr(test->members, i) : 0;
58+
int actual = test->test_fn(i);
59+
60+
if (actual != expected) {
61+
rc = 1;
62+
printf("%s classifies char %d (0x%02x) wrongly\n",
63+
test->name, i, i);
64+
}
65+
}
66+
return rc;
67+
}
68+
69+
int main(int argc, char **argv)
70+
{
71+
const struct ctype_class *test;
72+
int rc = 0;
73+
74+
for (test = classes; test->name; test++)
75+
rc |= test_class(test);
76+
77+
return rc;
78+
}

0 commit comments

Comments
 (0)