summaryrefslogtreecommitdiff
path: root/src/fnmatch/fnmatch.c
blob: 069df2ee77ca9f9518b045e366478e9cc97e4cb6 (plain)
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <fnmatch.h>
#include <string.h>
#include "_assert.h"

int fnmatch(const char * pattern, const char * string, int flags)
{
	ASSERT_NONNULL(pattern);
	ASSERT_NONNULL(string);
	/* __ASSERT_FLAGS(flags, FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD); */
	const int period = flags & FNM_PERIOD;
	const int pathname = flags & FNM_PATHNAME;
	const int noescape = flags & FNM_NOESCAPE;
	char last = '/';

	while (*pattern && *string) {
		if (*pattern == '?') {
			pattern++;
			if (pathname && *string == '/') {
				return FNM_NOMATCH;
			}

			if (period && *string == '.') {
				if (pathname && !(last == '/')) {
					return FNM_NOMATCH;
				}
				/* TODO: period & !pathname */
			}

			last = *string;
			string++;

			continue;
		}

		if (*pattern == '[') {
			char *ket = strchr(pattern, ']');
			if (ket) {
				/* TODO: FNM_PATHNAME */
				/* TODO: FNM_PERIOD */
				/* match all or none */
				pattern = ket + 1;
				if (0) {
					return FNM_NOMATCH;
				}

				last = *string;
				string++;
				continue;
			}
			/* match a literal bracket, handled by main branch */
		}

		if (*pattern == '*') {
			/* multiple * is the same as one * */
			while (*pattern == '*') {
				pattern++;
			}

			/* TODO: period and pathname */
			if (*pattern == '\0') {
				return 0;
			}

			while (*string) {
				/* TODO: period and pathname */
				if (fnmatch(pattern, string, flags) == 0) {
					return 0;
				}
				string++;
			}
			return FNM_NOMATCH;
		}

		if (*pattern == '\\' && !noescape) {
			pattern++;
			if (*string != *pattern) {
				return FNM_NOMATCH;
			}
		}

		if (*pattern != *string) {
			return FNM_NOMATCH;
		}

		last = *string;
		pattern++;
		string++;
	}

	if (*pattern || *string) {
		return FNM_NOMATCH;
	}

	return 0;
}

/*
POSIX(2)
*/