forked from facebook/watchman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpcre.c
111 lines (93 loc) · 2.47 KB
/
pcre.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
/* Copyright 2013-present Facebook, Inc.
* Licensed under the Apache License, Version 2.0 */
#include "watchman.h"
#ifdef HAVE_PCRE_H
struct match_pcre {
pcre *re;
pcre_extra *extra;
bool wholename;
};
static bool eval_pcre(struct w_query_ctx *ctx,
struct watchman_file *file,
void *data)
{
struct match_pcre *match = data;
w_string_t *str;
int rc;
if (match->wholename) {
str = w_query_ctx_get_wholename(ctx);
} else {
str = file->name;
}
rc = pcre_exec(match->re, match->extra,
str->buf, str->len, 0, 0, NULL, 0);
if (rc == PCRE_ERROR_NOMATCH) {
return false;
}
if (rc >= 0) {
return true;
}
// An error. It's not actionable here
return false;
}
static void dispose_pcre(void *data)
{
struct match_pcre *match = data;
if (match->re) {
pcre_free(match->re);
}
if (match->extra) {
pcre_free(match->extra);
}
free(match);
}
static w_query_expr *pcre_parser_inner(w_query *query,
json_t *term, bool caseless)
{
const char *ignore, *pattern, *scope = "basename";
const char *which = caseless ? "ipcre" : "pcre";
struct match_pcre *data;
pcre *re;
const char *errptr = NULL;
int erroff = 0;
int errcode = 0;
if (json_unpack(term, "[s,s,s]", &ignore, &pattern, &scope) != 0 &&
json_unpack(term, "[s,s]", &ignore, &pattern) != 0) {
ignore_result(asprintf(&query->errmsg,
"Expected [\"%s\", \"pattern\", \"scope\"?]",
which));
return NULL;
}
if (strcmp(scope, "basename") && strcmp(scope, "wholename")) {
ignore_result(asprintf(&query->errmsg,
"Invalid scope '%s' for %s expression",
scope, which));
return NULL;
}
re = pcre_compile2(pattern, caseless ? PCRE_CASELESS : 0,
&errcode, &errptr, &erroff, NULL);
if (!re) {
ignore_result(asprintf(&query->errmsg,
"invalid %s: code %d %s at offset %d in %s",
which, errcode, errptr, erroff, pattern));
return NULL;
}
data = malloc(sizeof(*data));
data->re = re;
data->extra = pcre_study(re, 0, &errptr);
data->wholename = !strcmp(scope, "wholename");
return w_query_expr_new(eval_pcre, dispose_pcre, data);
}
static w_query_expr *pcre_parser(w_query *query, json_t *term)
{
return pcre_parser_inner(query, term, !query->case_sensitive);
}
W_TERM_PARSER("pcre", pcre_parser)
static w_query_expr *ipcre_parser(w_query *query, json_t *term)
{
return pcre_parser_inner(query, term, true);
}
W_TERM_PARSER("ipcre", ipcre_parser)
#endif
/* vim:ts=2:sw=2:et:
*/