-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmatch.c
126 lines (119 loc) · 2.84 KB
/
match.c
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
116
117
118
119
120
121
122
123
124
125
126
/*--------------------------------------------------------------*
* Match a string, wildcards # and * *
*--------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "match.h"
typedef struct {
int code; /* >0 = len(text), <0 = len(##), 0=* */
const char *text;
} Segment;
Segment segment[32];
int numseg=0;
int match_min=0;
int match_max=0;
int numstar=0;
#if 0
static void dump_match(void)
{
int i,j,code;
for (i=0; i<numseg; i++) {
code = segment[i].code;
printf("%d\t", code);
if (code < 0) {
for (j=0; j<(-code); j++) {
printf("#");
}
}else if (code > 0) {
printf("%*s", code, segment[i].text);
}else{
printf("*");
}
printf("\n");
}
}
#endif
/*--------------------------------------------------------------*
* Compile a match pattern *
*--------------------------------------------------------------*/
void init_match(const char *pat)
{
const char *lit = NULL;
char c;
numseg = 0;
match_min = 0;
numstar = 0;
for (; (c=*pat) != '\0'; pat++) {
switch (c) {
case '*':
if (lit != NULL) {
segment[numseg++].code = pat-lit;
lit = NULL;
}
segment[numseg++].code = 0;
numstar++;
break;
case '#':
case '.':
match_min++;
if (lit != NULL) {
segment[numseg++].code = pat-lit;
lit = NULL;
}
segment[numseg].code = -1;
for (; pat[1] == '#'; pat++) {
match_min++;
segment[numseg].code--;
}
numseg++;
break;
default:
match_min++;
if (lit == NULL) {
lit = pat;
segment[numseg].text = lit;
}
}
}
if (lit != NULL) {
segment[numseg++].code = pat-lit;
}
match_max = numstar? 20: match_min;
}
static int match_tail(const char *word,
Segment seg[],
int nseg,
int nstar,
int spare)
{
int code;
for (; nseg; seg++,nseg--) {
code = seg[0].code;
if (code < 0) { /* (-code) single wildcards "#" */
word += (-code);
}else if (seg[0].code > 0) { /* literal text */
if (strncmp(word, seg[0].text, code) != 0) {
return 0;
}
word += code;
}else{ /* multiple wildcard "*" */
if (nstar) {
for (; spare >= 0; word++,spare--) {
if (match_tail(word, seg+1, nseg-1, nstar-1, spare)) {
return 1; /* tail matched */
}
}
return 0;
}else{
return match_tail(word+spare, seg+1, nseg-1, 0, 0);
}
}
}
return (word[0]=='\0');
}
int match_word(const char *word)
{
int spare = strlen(word) - match_min;
if (spare < 0) return 0;
return match_tail(word, segment, numseg, numstar, spare);
}