Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / core / ngx_regex.c
blob3771aab8ee76285498f01396d29dd17c4d080156
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
12 typedef struct {
13 ngx_flag_t pcre_jit;
14 } ngx_regex_conf_t;
17 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
18 static void ngx_libc_cdecl ngx_regex_free(void *p);
19 #if (NGX_HAVE_PCRE_JIT)
20 static void ngx_pcre_free_studies(void *data);
21 #endif
23 static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
25 static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
26 static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);
28 static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
29 static ngx_conf_post_t ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
32 static ngx_command_t ngx_regex_commands[] = {
34 { ngx_string("pcre_jit"),
35 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
36 ngx_conf_set_flag_slot,
38 offsetof(ngx_regex_conf_t, pcre_jit),
39 &ngx_regex_pcre_jit_post },
41 ngx_null_command
45 static ngx_core_module_t ngx_regex_module_ctx = {
46 ngx_string("regex"),
47 ngx_regex_create_conf,
48 ngx_regex_init_conf
52 ngx_module_t ngx_regex_module = {
53 NGX_MODULE_V1,
54 &ngx_regex_module_ctx, /* module context */
55 ngx_regex_commands, /* module directives */
56 NGX_CORE_MODULE, /* module type */
57 NULL, /* init master */
58 ngx_regex_module_init, /* init module */
59 NULL, /* init process */
60 NULL, /* init thread */
61 NULL, /* exit thread */
62 NULL, /* exit process */
63 NULL, /* exit master */
64 NGX_MODULE_V1_PADDING
68 static ngx_pool_t *ngx_pcre_pool;
69 static ngx_list_t *ngx_pcre_studies;
72 void
73 ngx_regex_init(void)
75 pcre_malloc = ngx_regex_malloc;
76 pcre_free = ngx_regex_free;
80 static ngx_inline void
81 ngx_regex_malloc_init(ngx_pool_t *pool)
83 #if (NGX_THREADS)
84 ngx_core_tls_t *tls;
86 if (ngx_threaded) {
87 tls = ngx_thread_get_tls(ngx_core_tls_key);
88 tls->pool = pool;
89 return;
92 #endif
94 ngx_pcre_pool = pool;
98 static ngx_inline void
99 ngx_regex_malloc_done(void)
101 #if (NGX_THREADS)
102 ngx_core_tls_t *tls;
104 if (ngx_threaded) {
105 tls = ngx_thread_get_tls(ngx_core_tls_key);
106 tls->pool = NULL;
107 return;
110 #endif
112 ngx_pcre_pool = NULL;
116 ngx_int_t
117 ngx_regex_compile(ngx_regex_compile_t *rc)
119 int n, erroff;
120 char *p;
121 pcre *re;
122 const char *errstr;
123 ngx_regex_elt_t *elt;
125 ngx_regex_malloc_init(rc->pool);
127 re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
128 &errstr, &erroff, NULL);
130 /* ensure that there is no current pool */
131 ngx_regex_malloc_done();
133 if (re == NULL) {
134 if ((size_t) erroff == rc->pattern.len) {
135 rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
136 "pcre_compile() failed: %s in \"%V\"",
137 errstr, &rc->pattern)
138 - rc->err.data;
140 } else {
141 rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
142 "pcre_compile() failed: %s in \"%V\" at \"%s\"",
143 errstr, &rc->pattern, rc->pattern.data + erroff)
144 - rc->err.data;
147 return NGX_ERROR;
150 rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
151 if (rc->regex == NULL) {
152 return NGX_ERROR;
155 rc->regex->code = re;
157 /* do not study at runtime */
159 if (ngx_pcre_studies != NULL) {
160 elt = ngx_list_push(ngx_pcre_studies);
161 if (elt == NULL) {
162 return NGX_ERROR;
165 elt->regex = rc->regex;
166 elt->name = rc->pattern.data;
169 n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
170 if (n < 0) {
171 p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
172 goto failed;
175 if (rc->captures == 0) {
176 return NGX_OK;
179 n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
180 if (n < 0) {
181 p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
182 goto failed;
185 if (rc->named_captures == 0) {
186 return NGX_OK;
189 n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
190 if (n < 0) {
191 p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
192 goto failed;
195 n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
196 if (n < 0) {
197 p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
198 goto failed;
201 return NGX_OK;
203 failed:
205 rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
206 - rc->err.data;
207 return NGX_OK;
211 ngx_int_t
212 ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
214 ngx_int_t n;
215 ngx_uint_t i;
216 ngx_regex_elt_t *re;
218 re = a->elts;
220 for (i = 0; i < a->nelts; i++) {
222 n = ngx_regex_exec(re[i].regex, s, NULL, 0);
224 if (n == NGX_REGEX_NO_MATCHED) {
225 continue;
228 if (n < 0) {
229 ngx_log_error(NGX_LOG_ALERT, log, 0,
230 ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
231 n, s, re[i].name);
232 return NGX_ERROR;
235 /* match */
237 return NGX_OK;
240 return NGX_DECLINED;
244 static void * ngx_libc_cdecl
245 ngx_regex_malloc(size_t size)
247 ngx_pool_t *pool;
248 #if (NGX_THREADS)
249 ngx_core_tls_t *tls;
251 if (ngx_threaded) {
252 tls = ngx_thread_get_tls(ngx_core_tls_key);
253 pool = tls->pool;
255 } else {
256 pool = ngx_pcre_pool;
259 #else
261 pool = ngx_pcre_pool;
263 #endif
265 if (pool) {
266 return ngx_palloc(pool, size);
269 return NULL;
273 static void ngx_libc_cdecl
274 ngx_regex_free(void *p)
276 return;
280 #if (NGX_HAVE_PCRE_JIT)
282 static void
283 ngx_pcre_free_studies(void *data)
285 ngx_list_t *studies = data;
287 ngx_uint_t i;
288 ngx_list_part_t *part;
289 ngx_regex_elt_t *elts;
291 part = &studies->part;
292 elts = part->elts;
294 for (i = 0 ; /* void */ ; i++) {
296 if (i >= part->nelts) {
297 if (part->next == NULL) {
298 break;
301 part = part->next;
302 elts = part->elts;
303 i = 0;
306 if (elts[i].regex->extra != NULL) {
307 pcre_free_study(elts[i].regex->extra);
312 #endif
315 static ngx_int_t
316 ngx_regex_module_init(ngx_cycle_t *cycle)
318 int opt;
319 const char *errstr;
320 ngx_uint_t i;
321 ngx_list_part_t *part;
322 ngx_regex_elt_t *elts;
324 opt = 0;
326 #if (NGX_HAVE_PCRE_JIT)
328 ngx_regex_conf_t *rcf;
329 ngx_pool_cleanup_t *cln;
331 rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
333 if (rcf->pcre_jit) {
334 opt = PCRE_STUDY_JIT_COMPILE;
337 * The PCRE JIT compiler uses mmap for its executable codes, so we
338 * have to explicitly call the pcre_free_study() function to free
339 * this memory.
342 cln = ngx_pool_cleanup_add(cycle->pool, 0);
343 if (cln == NULL) {
344 return NGX_ERROR;
347 cln->handler = ngx_pcre_free_studies;
348 cln->data = ngx_pcre_studies;
351 #endif
353 ngx_regex_malloc_init(cycle->pool);
355 part = &ngx_pcre_studies->part;
356 elts = part->elts;
358 for (i = 0 ; /* void */ ; i++) {
360 if (i >= part->nelts) {
361 if (part->next == NULL) {
362 break;
365 part = part->next;
366 elts = part->elts;
367 i = 0;
370 elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);
372 if (errstr != NULL) {
373 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
374 "pcre_study() failed: %s in \"%s\"",
375 errstr, elts[i].name);
378 #if (NGX_HAVE_PCRE_JIT)
379 if (opt & PCRE_STUDY_JIT_COMPILE) {
380 int jit, n;
382 jit = 0;
383 n = pcre_fullinfo(elts[i].regex->code, elts[i].regex->extra,
384 PCRE_INFO_JIT, &jit);
386 if (n != 0 || jit != 1) {
387 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
388 "JIT compiler does not support pattern: \"%s\"",
389 elts[i].name);
392 #endif
395 ngx_regex_malloc_done();
397 ngx_pcre_studies = NULL;
399 return NGX_OK;
403 static void *
404 ngx_regex_create_conf(ngx_cycle_t *cycle)
406 ngx_regex_conf_t *rcf;
408 rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
409 if (rcf == NULL) {
410 return NULL;
413 rcf->pcre_jit = NGX_CONF_UNSET;
415 ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
416 if (ngx_pcre_studies == NULL) {
417 return NULL;
420 return rcf;
424 static char *
425 ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
427 ngx_regex_conf_t *rcf = conf;
429 ngx_conf_init_value(rcf->pcre_jit, 0);
431 return NGX_CONF_OK;
435 static char *
436 ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
438 ngx_flag_t *fp = data;
440 if (*fp == 0) {
441 return NGX_CONF_OK;
444 #if (NGX_HAVE_PCRE_JIT)
446 int jit, r;
448 jit = 0;
449 r = pcre_config(PCRE_CONFIG_JIT, &jit);
451 if (r != 0 || jit != 1) {
452 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
453 "PCRE library does not support JIT");
454 *fp = 0;
457 #else
458 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
459 "nginx was built without PCRE JIT support");
460 *fp = 0;
461 #endif
463 return NGX_CONF_OK;