diff src/core/ngx_regex.c @ 546:e19e5f542878 NGINX_0_8_25

nginx 0.8.25 *) Change: now no message is written in an error log if a variable is not found by $r->variable() method. *) Feature: the ngx_http_degradation_module. *) Feature: regular expression named captures. *) Feature: now URI part is not required a "proxy_pass" directive if variables are used. *) Feature: now the "msie_padding" directive works for Chrome too. *) Bugfix: a segmentation fault occurred in a worker process on low memory condition; the bug had appeared in 0.8.18. *) Bugfix: nginx sent gzipped responses to clients those do not support gzip, if "gzip_static on" and "gzip_vary off"; the bug had appeared in 0.8.16.
author Igor Sysoev <http://sysoev.ru>
date Mon, 16 Nov 2009 00:00:00 +0300
parents 984bb0b1399b
children 697030d79811
line wrap: on
line diff
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -23,25 +23,16 @@ ngx_regex_init(void)
 }
 
 
-ngx_regex_t *
-ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, ngx_pool_t *pool,
-    ngx_str_t *err)
+static ngx_inline void
+ngx_regex_malloc_init(ngx_pool_t *pool)
 {
-    int              erroff;
-    const char      *errstr;
-    ngx_regex_t     *re;
 #if (NGX_THREADS)
     ngx_core_tls_t  *tls;
 
-#if (NGX_SUPPRESS_WARN)
-    tls = NULL;
-#endif
-
     if (ngx_threaded) {
         tls = ngx_thread_get_tls(ngx_core_tls_key);
         tls->pool = pool;
-    } else {
-        ngx_pcre_pool = pool;
+        return;
     }
 
 #else
@@ -49,35 +40,103 @@ ngx_regex_compile(ngx_str_t *pattern, ng
     ngx_pcre_pool = pool;
 
 #endif
+}
 
-    re = pcre_compile((const char *) pattern->data, (int) options,
+
+static ngx_inline void
+ngx_regex_malloc_done(void)
+{
+#if (NGX_THREADS)
+    ngx_core_tls_t  *tls;
+
+    if (ngx_threaded) {
+        tls = ngx_thread_get_tls(ngx_core_tls_key);
+        tls->pool = NULL;
+        return;
+    }
+
+#else
+
+    ngx_pcre_pool = NULL;
+
+#endif
+}
+
+
+ngx_int_t
+ngx_regex_compile(ngx_regex_compile_t *rc)
+{
+    int           n, erroff;
+    char         *p;
+    const char   *errstr;
+    ngx_regex_t  *re;
+
+    ngx_regex_malloc_init(rc->pool);
+
+    re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
                       &errstr, &erroff, NULL);
 
+    /* ensure that there is no current pool */
+    ngx_regex_malloc_done();
+
     if (re == NULL) {
-       if ((size_t) erroff == pattern->len) {
-           ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\"%Z",
-                        errstr, pattern->data);
+        if ((size_t) erroff == rc->pattern.len) {
+           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                              "pcre_compile() failed: %s in \"%V\"",
+                               errstr, &rc->pattern)
+                      - rc->err.data;
+
         } else {
-           ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z",
-                        errstr, pattern->data, pattern->data + erroff);
+           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                              "pcre_compile() failed: %s in \"%V\" at \"%s\"",
+                               errstr, &rc->pattern, rc->pattern.data + erroff)
+                      - rc->err.data;
         }
+
+        return NGX_ERROR;
+    }
+
+    rc->regex = re;
+
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
+        goto failed;
+    }
+
+    if (rc->captures == 0) {
+        return NGX_OK;
     }
 
-    /* ensure that there is no current pool */
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
+        goto failed;
+    }
+
+    if (rc->named_captures == 0) {
+        return NGX_OK;
+    }
 
-#if (NGX_THREADS)
-    if (ngx_threaded) {
-        tls->pool = NULL;
-    } else {
-        ngx_pcre_pool = NULL;
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
+        goto failed;
     }
-#else
-    ngx_pcre_pool = NULL;
-#endif
+
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
+        goto failed;
+    }
 
-    return re;
+    return NGX_OK;
+
+failed:
+
+    rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
+                  - rc->err.data;
+    return NGX_OK;
 }
 
 
@@ -99,22 +158,6 @@ ngx_regex_capture_count(ngx_regex_t *re)
 
 
 ngx_int_t
-ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size)
-{
-    int  rc;
-
-    rc = pcre_exec(re, NULL, (const char *) s->data, s->len, 0, 0,
-                   captures, size);
-
-    if (rc == -1) {
-        return NGX_REGEX_NO_MATCHED;
-    }
-
-    return rc;
-}
-
-
-ngx_int_t
 ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
 {
     ngx_int_t         n;
@@ -133,7 +176,7 @@ ngx_regex_exec_array(ngx_array_t *a, ngx
 
         if (n < 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
-                          ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"",
+                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
                           n, s, re[i].name);
             return NGX_ERROR;
         }
@@ -157,11 +200,15 @@ ngx_regex_malloc(size_t size)
     if (ngx_threaded) {
         tls = ngx_thread_get_tls(ngx_core_tls_key);
         pool = tls->pool;
+
     } else {
         pool = ngx_pcre_pool;
     }
+
 #else
+
     pool = ngx_pcre_pool;
+
 #endif
 
     if (pool) {