aboutsummaryrefslogtreecommitdiff
path: root/src/glob.c
blob: c816964734682df806aaaf8ff02e8cf1e2a2e443 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "unalf.h"

/* this is an Atari DOS or MS-DOS style match: "*.*" matches everything,
   even files with no extension (no dot). "*" by itself matches only
   files with no extension, as does "*."
   matching is case-insensitive. */

static void split_filename(const char *fname, char *name, const char **ext) {
	int i;

	for(i = 0; i < 8; i++) {
		if(fname[i] == '.' || fname[i] == '\0')
			break;
		name[i] = fname[i];
	}
	name[i] = '\0';

	*ext = strchr(fname, '.');
	if(*ext) {
		(*ext)++;
		if(!**ext) *ext = 0;
	}

	// fprintf(stderr, "split %s into: '%s' and '%s'\n",
			// fname, name, (*ext ? *ext : "<none>"));
}

static int match_part(const char *pat, const char *arg) {
	char p;

	if(arg && arg[0] == '\0') arg = 0;

	if(!pat) {
		if(arg)
			return 0;
		else
			return 1;
	}

	while((p = toupper(*pat++))) {
		// fprintf(stderr, "p == %c\n", p);
		switch(p) {
			case '*': return 1;
			case '?':
				if(!arg || *arg == '\0')
					return 0;
				arg++;
				break;
			default:
				if(!arg || toupper(*arg) != p)
					return 0;
				arg++;
				break;
		}
	}

	return *arg ? 0 : 1;
}

int globmatch(const char *pat, const char *arg) {
	char npat[9], name[9];
	const char *epat = 0, *ext = 0;

	split_filename(pat, npat, &epat);
	split_filename(arg, name, &ext);

	return match_part(npat, name) && match_part(epat, ext);
}

int file_wanted(const char *filename) {
	int i;
	char **ig;

	/* if excluded, always return false */
	for(i = 0; i < exclude_count; i++) {
		if(globmatch(exclude_globs[i], filename))
			return 0;
	}

	/* if no include globs, always match (as though *.* were given) */
	if(!*include_globs)
		return 1;

	ig = (char **)include_globs;
	while(*ig) {
		if(globmatch(*ig, filename))
			return 1;
		ig++;
	}

	return 0;
}

/* for testing: */
#if 0
int main(int argc, char **argv) {
	int matched;
	const char *pattern;

	if(argc < 3) {
		fprintf(stderr, "usage: %s <glob-pattern> <filename> ...\n", argv[0]);
		return 1;
	}

	pattern = argv[1];
	argv++;

	while(*++argv) {
		matched = globmatch(pattern, *argv);
		printf("%s %s %s\n", *argv, matched ? "matches" : "DOES NOT match", pattern);
	}

	return 0;
}
#endif