about summary refs log tree commit diff
path: root/t/helper/test-regex.c
blob: 10284cc56fa9f69703aa69f242edef113d6a40de (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "test-tool.h"
#include "git-compat-util.h"
#include "gettext.h"

struct reg_flag {
	const char *name;
	int flag;
};

static struct reg_flag reg_flags[] = {
	{ "EXTENDED",	 REG_EXTENDED	},
	{ "NEWLINE",	 REG_NEWLINE	},
	{ "ICASE",	 REG_ICASE	},
	{ "NOTBOL",	 REG_NOTBOL	},
#ifdef REG_STARTEND
	{ "STARTEND",	 REG_STARTEND	},
#endif
	{ NULL, 0 }
};

static int test_regex_bug(void)
{
	char *pat = "[^={} \t]+";
	char *str = "={}\nfred";
	regex_t r;
	regmatch_t m[1];

	if (regcomp(&r, pat, REG_EXTENDED | REG_NEWLINE))
		die("failed regcomp() for pattern '%s'", pat);
	if (regexec(&r, str, 1, m, 0))
		die("no match of pattern '%s' to string '%s'", pat, str);

	/* http://sourceware.org/bugzilla/show_bug.cgi?id=3957  */
	if (m[0].rm_so == 3) /* matches '\n' when it should not */
		die("regex bug confirmed: re-build git with NO_REGEX=1");

	return 0;
}

int cmd__regex(int argc, const char **argv)
{
	const char *pat;
	const char *str;
	int flags = 0;
	regex_t r;
	regmatch_t m[1];

	if (argc == 2 && !strcmp(argv[1], "--bug"))
		return test_regex_bug();
	else if (argc < 3)
		usage("test-tool regex --bug\n"
		      "test-tool regex <pattern> <string> [<options>]");

	argv++;
	pat = *argv++;
	str = *argv++;
	while (*argv) {
		struct reg_flag *rf;
		for (rf = reg_flags; rf->name; rf++)
			if (!strcmp(*argv, rf->name)) {
				flags |= rf->flag;
				break;
			}
		if (!rf->name)
			die("do not recognize %s", *argv);
		argv++;
	}
	git_setup_gettext();

	if (regcomp(&r, pat, flags))
		die("failed regcomp() for pattern '%s'", pat);
	if (regexec(&r, str, 1, m, 0))
		return 1;

	return 0;
}