-
Notifications
You must be signed in to change notification settings - Fork 27
/
rstr.c
118 lines (111 loc) · 2.36 KB
/
rstr.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
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "vi.h"
struct rstr {
struct rset *rs; /* only for regex patterns */
char *str; /* for simple, non-regex patterns */
int icase; /* ignore case */
int lbeg, lend; /* match line beg/end */
int wbeg, wend; /* match word beg/end */
};
/* return zero if a simple pattern is given */
static int rstr_simple(struct rstr *rs, char *re)
{
char *beg;
char *end;
rs->lbeg = re[0] == '^';
if (rs->lbeg)
re++;
rs->wbeg = re[0] == '\\' && re[1] == '<';
if (rs->wbeg)
re += 2;
beg = re;
while (re[0] && !strchr("\\.*+?[]{}()$", (unsigned char) re[0]))
re++;
end = re;
rs->wend = re[0] == '\\' && re[1] == '>';
if (rs->wend)
re += 2;
rs->lend = re[0] == '$';
if (rs->lend)
re++;
if (!re[0]) {
int len = end - beg;
rs->str = malloc(len + 1);
memcpy(rs->str, beg, len);
rs->str[len] = '\0';
return 0;
}
return 1;
}
struct rstr *rstr_make(char *re, int flg)
{
struct rstr *rs = malloc(sizeof(*rs));
memset(rs, 0, sizeof(*rs));
rs->icase = flg & RE_ICASE;
if (rstr_simple(rs, re))
rs->rs = rset_make(1, &re, flg);
if (!rs->rs && !rs->str) {
free(rs);
return NULL;
}
return rs;
}
static int isword(char *s)
{
int c = (unsigned char) s[0];
return isalnum(c) || c == '_' || c > 127;
}
static int match_case(char *s, char *r, int icase)
{
for (; *r && *s; s++, r++) {
if (!icase && *s != *r)
return 1;
if (icase && tolower((unsigned char) *s) != tolower((unsigned char) *r))
return 1;
}
return *r;
}
/* return zero if an occurrence is found */
int rstr_find(struct rstr *rs, char *s, int n, int *grps, int flg)
{
int len;
char *beg, *end;
char *r;
if (rs->rs)
return rset_find(rs->rs, s, n, grps, flg);
if ((rs->lbeg && (flg & RE_NOTBOL)) || (rs->lend && (flg & RE_NOTEOL)))
return -1;
len = strlen(rs->str);
beg = s;
end = s + strlen(s) - len - 1;
if (end < beg)
return -1;
if (rs->lend)
beg = end;
if (rs->lbeg)
end = s;
for (r = beg; r <= end; r++) {
if (rs->wbeg && r > s && (isword(r - 1) || !isword(r)))
continue;
if (rs->wend && r[len] && (!isword(r + len - 1) || isword(r + len)))
continue;
if (!match_case(r, rs->str, rs->icase)) {
if (n >= 1) {
grps[0] = r - s;
grps[1] = r - s + len;
}
return 0;
}
}
return -1;
}
void rstr_free(struct rstr *rs)
{
if (rs->rs)
rset_free(rs->rs);
free(rs->str);
free(rs);
}