summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-03-22 09:36:51 +0000
committerIgor Sysoev <igor@sysoev.ru>2009-03-22 09:36:51 +0000
commit8508c10bb872694083938afa4b3a832a647601dc (patch)
tree4532f0b7bbf653bae21d5e643ab4870beca92fb9
parentc7ce3a99bc8f21a89370f06b0aff8cdbcab88765 (diff)
downloadnginx-8508c10bb872694083938afa4b3a832a647601dc.tar.gz
ngx_http_script_flush_complex_value()
ngx_http_complex_value() ngx_http_compile_complex_value()
-rw-r--r--src/http/ngx_http_script.c303
-rw-r--r--src/http/ngx_http_script.h124
2 files changed, 372 insertions, 55 deletions
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 7313c342a..05851ec1d 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -12,7 +12,7 @@
static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
- ngx_str_t *value);
+ ngx_str_t *value, ngx_uint_t last);
static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
ngx_str_t *name);
static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
@@ -20,6 +20,10 @@ static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
ngx_uint_t n);
#endif
+static ngx_int_t
+ ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
+static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
+static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
#define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
@@ -27,6 +31,186 @@ static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
+void
+ngx_http_scrip_flush_complex_value(ngx_http_request_t *r,
+ ngx_http_complex_value_t *val)
+{
+ ngx_uint_t *index;
+
+ index = val->flushes;
+
+ if (index) {
+ while (*index != (ngx_uint_t) -1) {
+
+ if (r->variables[*index].no_cacheable) {
+ r->variables[*index].valid = 0;
+ r->variables[*index].not_found = 0;
+ }
+
+ index++;
+ }
+ }
+}
+
+
+ngx_int_t
+ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
+ ngx_str_t *value)
+{
+ size_t len;
+ ngx_http_script_code_pt code;
+ ngx_http_script_len_code_pt lcode;
+ ngx_http_script_engine_t e;
+
+ if (val->lengths == NULL) {
+ *value = val->value;
+ return NGX_OK;
+ }
+
+ ngx_http_scrip_flush_complex_value(r, val);
+
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
+
+ e.ip = val->lengths;
+ e.request = r;
+ e.flushed = 1;
+
+ len = 0;
+
+ while (*(uintptr_t *) e.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) e.ip;
+ len += lcode(&e);
+ }
+
+ value->len = len;
+ value->data = ngx_pnalloc(r->pool, len);
+ if (value->data == NULL) {
+ return NGX_ERROR;
+ }
+
+ e.ip = val->values;
+ e.pos = value->data;
+ e.buf = *value;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+
+ *value = e.buf;
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
+{
+ ngx_str_t *v;
+ ngx_uint_t i, n, nv, nc;
+ ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
+ ngx_http_script_compile_t sc;
+
+ v = ccv->value;
+
+ if (v->len == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, ccv->cf, 0, "empty parameter");
+ return NGX_ERROR;
+ }
+
+ ccv->complex_value->value = *v;
+ ccv->complex_value->flushes = NULL;
+ ccv->complex_value->lengths = NULL;
+ ccv->complex_value->values = NULL;
+
+ nv = 0;
+ nc = 0;
+
+ for (i = 0; i < v->len; i++) {
+ if (v->data[i] == '$') {
+ if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
+ nc++;
+
+ } else {
+ nv++;
+ }
+ }
+ }
+
+ if (v->data[0] != '$' && (ccv->conf_prefix || ccv->root_prefix)) {
+
+ if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ ccv->conf_prefix = 0;
+ ccv->root_prefix = 0;
+ }
+
+ if (nv == 0 && nc == 0) {
+ return NGX_OK;
+ }
+
+ n = nv + 1;
+
+ if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
+ + sizeof(ngx_http_script_var_code_t))
+ + sizeof(uintptr_t);
+
+ if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
+ + sizeof(ngx_http_script_var_code_t))
+ + sizeof(uintptr_t)
+ + v->len
+ + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ pf = &flushes;
+ pl = &lengths;
+ pv = &values;
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = ccv->cf;
+ sc.source = v;
+ sc.flushes = &pf;
+ sc.lengths = &pl;
+ sc.values = &pv;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+ sc.zero = ccv->zero;
+ sc.conf_prefix = ccv->conf_prefix;
+ sc.root_prefix = ccv->root_prefix;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (flushes.nelts) {
+ ccv->complex_value->flushes = flushes.elts;
+ ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
+ }
+
+ ccv->complex_value->lengths = lengths.elts;
+ ccv->complex_value->values = values.elts;
+
+ return NGX_OK;
+}
+
+
ngx_uint_t
ngx_http_script_variables_count(ngx_str_t *value)
{
@@ -180,7 +364,9 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc)
sc->size += name.len;
- if (ngx_http_script_add_copy_code(sc, &name) != NGX_OK) {
+ if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
+ != NGX_OK)
+ {
return NGX_ERROR;
}
}
@@ -309,8 +495,25 @@ ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
static ngx_int_t
ngx_http_script_done(ngx_http_script_compile_t *sc)
{
+ ngx_str_t zero;
uintptr_t *code;
+ if (sc->zero) {
+
+ zero.len = 1;
+ zero.data = (u_char *) "\0";
+
+ if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+
+ if (sc->conf_prefix || sc->root_prefix) {
+ if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+
if (sc->complete_lengths) {
code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
if (code == NULL) {
@@ -373,11 +576,16 @@ ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
static ngx_int_t
-ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value)
+ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
+ ngx_uint_t last)
{
- size_t size;
+ u_char *p;
+ size_t size, len, zero;
ngx_http_script_copy_code_t *code;
+ zero = (sc->zero && last);
+ len = value->len + zero;
+
code = ngx_http_script_add_code(*sc->lengths,
sizeof(ngx_http_script_copy_code_t), NULL);
if (code == NULL) {
@@ -385,10 +593,9 @@ ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value)
}
code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
- code->len = value->len;
+ code->len = len;
- size = (sizeof(ngx_http_script_copy_code_t) + value->len
- + sizeof(uintptr_t) - 1)
+ size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
code = ngx_http_script_add_code(*sc->values, size, &sc->main);
@@ -397,10 +604,15 @@ ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value)
}
code->code = ngx_http_script_copy_code;
- code->len = value->len;
+ code->len = len;
- ngx_memcpy((u_char *) code + sizeof(ngx_http_script_copy_code_t),
- value->data, value->len);
+ p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
+ value->data, value->len);
+
+ if (zero) {
+ *p = '\0';
+ sc->zero = 0;
+ }
return NGX_OK;
}
@@ -988,6 +1200,77 @@ ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
#endif
+static ngx_int_t
+ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
+{
+ ngx_http_script_full_name_code_t *code;
+
+ code = ngx_http_script_add_code(*sc->lengths,
+ sizeof(ngx_http_script_full_name_code_t),
+ NULL);
+ if (code == NULL) {
+ return NGX_ERROR;
+ }
+
+ code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
+ code->prefix = sc->conf_prefix;
+
+ code = ngx_http_script_add_code(*sc->values,
+ sizeof(ngx_http_script_full_name_code_t),
+ &sc->main);
+ if (code == NULL) {
+ return NGX_ERROR;
+ }
+
+ code->code = ngx_http_script_full_name_code;
+ code->prefix = sc->conf_prefix;
+
+ return NGX_OK;
+}
+
+
+static size_t
+ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_full_name_code_t *code;
+
+ code = (ngx_http_script_full_name_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_full_name_code_t);
+
+ return code->prefix ? sizeof(NGX_CONF_PREFIX) : ngx_cycle->root.len;
+}
+
+
+static void
+ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_full_name_code_t *code;
+
+ ngx_str_t value;
+
+ code = (ngx_http_script_full_name_code_t *) e->ip;
+
+ value.data = e->buf.data;
+ value.len = e->pos - e->buf.data;
+
+ if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->prefix)
+ != NGX_OK)
+ {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+
+ e->buf = value;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script fullname: \"%V\"", &value);
+
+ e->ip += sizeof(ngx_http_script_full_name_code_t);
+}
+
+
void
ngx_http_script_return_code(ngx_http_script_engine_t *e)
{
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index c55526cda..7f36ce547 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -53,86 +53,114 @@ typedef struct {
unsigned compile_args:1;
unsigned complete_lengths:1;
unsigned complete_values:1;
- unsigned dup_capture:1;
+ unsigned zero:1;
+ unsigned conf_prefix:1;
+ unsigned root_prefix:1;
+ unsigned dup_capture:1;
unsigned args:1;
} ngx_http_script_compile_t;
+typedef struct {
+ ngx_str_t value;
+ ngx_uint_t *flushes;
+ void *lengths;
+ void *values;
+} ngx_http_complex_value_t;
+
+
+typedef struct {
+ ngx_conf_t *cf;
+ ngx_str_t *value;
+ ngx_http_complex_value_t *complex_value;
+
+ unsigned zero:1;
+ unsigned conf_prefix:1;
+ unsigned root_prefix:1;
+} ngx_http_compile_complex_value_t;
+
+
typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e);
typedef size_t (*ngx_http_script_len_code_pt) (ngx_http_script_engine_t *e);
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t len;
+ ngx_http_script_code_pt code;
+ uintptr_t len;
} ngx_http_script_copy_code_t;
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t index;
+ ngx_http_script_code_pt code;
+ uintptr_t index;
} ngx_http_script_var_code_t;
typedef struct {
- ngx_http_script_code_pt code;
- ngx_http_set_variable_pt handler;
- uintptr_t data;
+ ngx_http_script_code_pt code;
+ ngx_http_set_variable_pt handler;
+ uintptr_t data;
} ngx_http_script_var_handler_code_t;
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t n;
+ ngx_http_script_code_pt code;
+ uintptr_t n;
} ngx_http_script_copy_capture_code_t;
#if (NGX_PCRE)
typedef struct {
- ngx_http_script_code_pt code;
- ngx_regex_t *regex;
- ngx_array_t *lengths;
- uintptr_t size;
- uintptr_t ncaptures;
- uintptr_t status;
- uintptr_t next;
-
- uintptr_t test:1;
- uintptr_t negative_test:1;
- uintptr_t uri:1;
- uintptr_t args:1;
+ ngx_http_script_code_pt code;
+ ngx_regex_t *regex;
+ ngx_array_t *lengths;
+ uintptr_t size;
+ uintptr_t ncaptures;
+ uintptr_t status;
+ uintptr_t next;
+
+ uintptr_t test:1;
+ uintptr_t negative_test:1;
+ uintptr_t uri:1;
+ uintptr_t args:1;
/* add the r->args to the new arguments */
- uintptr_t add_args:1;
+ uintptr_t add_args:1;
- uintptr_t redirect:1;
- uintptr_t break_cycle:1;
+ uintptr_t redirect:1;
+ uintptr_t break_cycle:1;
- ngx_str_t name;
+ ngx_str_t name;
} ngx_http_script_regex_code_t;
typedef struct {
- ngx_http_script_code_pt code;
+ ngx_http_script_code_pt code;
- uintptr_t uri:1;
- uintptr_t args:1;
+ uintptr_t uri:1;
+ uintptr_t args:1;
/* add the r->args to the new arguments */
- uintptr_t add_args:1;
+ uintptr_t add_args:1;
- uintptr_t redirect:1;
+ uintptr_t redirect:1;
} ngx_http_script_regex_end_code_t;
#endif
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t status;
- uintptr_t null;
+ ngx_http_script_code_pt code;
+ uintptr_t prefix;
+} ngx_http_script_full_name_code_t;
+
+
+typedef struct {
+ ngx_http_script_code_pt code;
+ uintptr_t status;
+ uintptr_t null;
} ngx_http_script_return_code_t;
@@ -149,32 +177,38 @@ typedef enum {
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t op;
+ ngx_http_script_code_pt code;
+ uintptr_t op;
} ngx_http_script_file_code_t;
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t next;
- void **loc_conf;
+ ngx_http_script_code_pt code;
+ uintptr_t next;
+ void **loc_conf;
} ngx_http_script_if_code_t;
typedef struct {
- ngx_http_script_code_pt code;
- ngx_array_t *lengths;
+ ngx_http_script_code_pt code;
+ ngx_array_t *lengths;
} ngx_http_script_complex_value_code_t;
typedef struct {
- ngx_http_script_code_pt code;
- uintptr_t value;
- uintptr_t text_len;
- uintptr_t text_data;
+ ngx_http_script_code_pt code;
+ uintptr_t value;
+ uintptr_t text_len;
+ uintptr_t text_data;
} ngx_http_script_value_code_t;
+void ngx_http_scrip_flush_complex_value(ngx_http_request_t *r,
+ ngx_http_complex_value_t *val);
+ngx_int_t ngx_http_complex_value(ngx_http_request_t *r,
+ ngx_http_complex_value_t *val, ngx_str_t *value);
+ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv);
+
ngx_uint_t ngx_http_script_variables_count(ngx_str_t *value);
ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc);
u_char *ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,