comparison src/http/ngx_http_script.c @ 2587:8afc4df77ee8

ngx_http_script_flush_complex_value() ngx_http_complex_value() ngx_http_compile_complex_value()
author Igor Sysoev <igor@sysoev.ru>
date Sun, 22 Mar 2009 09:36:51 +0000
parents 2dcbcfc1a8d1
children 2f4a3a4dfd34
comparison
equal deleted inserted replaced
2586:41a965fba141 2587:8afc4df77ee8
10 10
11 11
12 static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc); 12 static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
13 static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc); 13 static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
14 static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, 14 static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
15 ngx_str_t *value); 15 ngx_str_t *value, ngx_uint_t last);
16 static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, 16 static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
17 ngx_str_t *name); 17 ngx_str_t *name);
18 static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc); 18 static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
19 #if (NGX_PCRE) 19 #if (NGX_PCRE)
20 static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, 20 static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
21 ngx_uint_t n); 21 ngx_uint_t n);
22 #endif 22 #endif
23 static ngx_int_t
24 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
25 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
26 static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
23 27
24 28
25 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code 29 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
26 30
27 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL; 31 static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
32
33
34 void
35 ngx_http_scrip_flush_complex_value(ngx_http_request_t *r,
36 ngx_http_complex_value_t *val)
37 {
38 ngx_uint_t *index;
39
40 index = val->flushes;
41
42 if (index) {
43 while (*index != (ngx_uint_t) -1) {
44
45 if (r->variables[*index].no_cacheable) {
46 r->variables[*index].valid = 0;
47 r->variables[*index].not_found = 0;
48 }
49
50 index++;
51 }
52 }
53 }
54
55
56 ngx_int_t
57 ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
58 ngx_str_t *value)
59 {
60 size_t len;
61 ngx_http_script_code_pt code;
62 ngx_http_script_len_code_pt lcode;
63 ngx_http_script_engine_t e;
64
65 if (val->lengths == NULL) {
66 *value = val->value;
67 return NGX_OK;
68 }
69
70 ngx_http_scrip_flush_complex_value(r, val);
71
72 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
73
74 e.ip = val->lengths;
75 e.request = r;
76 e.flushed = 1;
77
78 len = 0;
79
80 while (*(uintptr_t *) e.ip) {
81 lcode = *(ngx_http_script_len_code_pt *) e.ip;
82 len += lcode(&e);
83 }
84
85 value->len = len;
86 value->data = ngx_pnalloc(r->pool, len);
87 if (value->data == NULL) {
88 return NGX_ERROR;
89 }
90
91 e.ip = val->values;
92 e.pos = value->data;
93 e.buf = *value;
94
95 while (*(uintptr_t *) e.ip) {
96 code = *(ngx_http_script_code_pt *) e.ip;
97 code((ngx_http_script_engine_t *) &e);
98 }
99
100 *value = e.buf;
101
102 return NGX_OK;
103 }
104
105
106 ngx_int_t
107 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
108 {
109 ngx_str_t *v;
110 ngx_uint_t i, n, nv, nc;
111 ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
112 ngx_http_script_compile_t sc;
113
114 v = ccv->value;
115
116 if (v->len == 0) {
117 ngx_conf_log_error(NGX_LOG_EMERG, ccv->cf, 0, "empty parameter");
118 return NGX_ERROR;
119 }
120
121 ccv->complex_value->value = *v;
122 ccv->complex_value->flushes = NULL;
123 ccv->complex_value->lengths = NULL;
124 ccv->complex_value->values = NULL;
125
126 nv = 0;
127 nc = 0;
128
129 for (i = 0; i < v->len; i++) {
130 if (v->data[i] == '$') {
131 if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
132 nc++;
133
134 } else {
135 nv++;
136 }
137 }
138 }
139
140 if (v->data[0] != '$' && (ccv->conf_prefix || ccv->root_prefix)) {
141
142 if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
143 return NGX_ERROR;
144 }
145
146 ccv->conf_prefix = 0;
147 ccv->root_prefix = 0;
148 }
149
150 if (nv == 0 && nc == 0) {
151 return NGX_OK;
152 }
153
154 n = nv + 1;
155
156 if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
157 != NGX_OK)
158 {
159 return NGX_ERROR;
160 }
161
162 n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
163 + sizeof(ngx_http_script_var_code_t))
164 + sizeof(uintptr_t);
165
166 if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
167 return NGX_ERROR;
168 }
169
170 n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
171 + sizeof(ngx_http_script_var_code_t))
172 + sizeof(uintptr_t)
173 + v->len
174 + sizeof(uintptr_t) - 1)
175 & ~(sizeof(uintptr_t) - 1);
176
177 if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
178 return NGX_ERROR;
179 }
180
181 pf = &flushes;
182 pl = &lengths;
183 pv = &values;
184
185 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
186
187 sc.cf = ccv->cf;
188 sc.source = v;
189 sc.flushes = &pf;
190 sc.lengths = &pl;
191 sc.values = &pv;
192 sc.complete_lengths = 1;
193 sc.complete_values = 1;
194 sc.zero = ccv->zero;
195 sc.conf_prefix = ccv->conf_prefix;
196 sc.root_prefix = ccv->root_prefix;
197
198 if (ngx_http_script_compile(&sc) != NGX_OK) {
199 return NGX_ERROR;
200 }
201
202 if (flushes.nelts) {
203 ccv->complex_value->flushes = flushes.elts;
204 ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
205 }
206
207 ccv->complex_value->lengths = lengths.elts;
208 ccv->complex_value->values = values.elts;
209
210 return NGX_OK;
211 }
28 212
29 213
30 ngx_uint_t 214 ngx_uint_t
31 ngx_http_script_variables_count(ngx_str_t *value) 215 ngx_http_script_variables_count(ngx_str_t *value)
32 { 216 {
178 name.len++; 362 name.len++;
179 } 363 }
180 364
181 sc->size += name.len; 365 sc->size += name.len;
182 366
183 if (ngx_http_script_add_copy_code(sc, &name) != NGX_OK) { 367 if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
368 != NGX_OK)
369 {
184 return NGX_ERROR; 370 return NGX_ERROR;
185 } 371 }
186 } 372 }
187 373
188 return ngx_http_script_done(sc); 374 return ngx_http_script_done(sc);
307 493
308 494
309 static ngx_int_t 495 static ngx_int_t
310 ngx_http_script_done(ngx_http_script_compile_t *sc) 496 ngx_http_script_done(ngx_http_script_compile_t *sc)
311 { 497 {
498 ngx_str_t zero;
312 uintptr_t *code; 499 uintptr_t *code;
500
501 if (sc->zero) {
502
503 zero.len = 1;
504 zero.data = (u_char *) "\0";
505
506 if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
507 return NGX_ERROR;
508 }
509 }
510
511 if (sc->conf_prefix || sc->root_prefix) {
512 if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
513 return NGX_ERROR;
514 }
515 }
313 516
314 if (sc->complete_lengths) { 517 if (sc->complete_lengths) {
315 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL); 518 code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
316 if (code == NULL) { 519 if (code == NULL) {
317 return NGX_ERROR; 520 return NGX_ERROR;
371 return new; 574 return new;
372 } 575 }
373 576
374 577
375 static ngx_int_t 578 static ngx_int_t
376 ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value) 579 ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
377 { 580 ngx_uint_t last)
378 size_t size; 581 {
582 u_char *p;
583 size_t size, len, zero;
379 ngx_http_script_copy_code_t *code; 584 ngx_http_script_copy_code_t *code;
585
586 zero = (sc->zero && last);
587 len = value->len + zero;
380 588
381 code = ngx_http_script_add_code(*sc->lengths, 589 code = ngx_http_script_add_code(*sc->lengths,
382 sizeof(ngx_http_script_copy_code_t), NULL); 590 sizeof(ngx_http_script_copy_code_t), NULL);
383 if (code == NULL) { 591 if (code == NULL) {
384 return NGX_ERROR; 592 return NGX_ERROR;
385 } 593 }
386 594
387 code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 595 code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
388 code->len = value->len; 596 code->len = len;
389 597
390 size = (sizeof(ngx_http_script_copy_code_t) + value->len 598 size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
391 + sizeof(uintptr_t) - 1)
392 & ~(sizeof(uintptr_t) - 1); 599 & ~(sizeof(uintptr_t) - 1);
393 600
394 code = ngx_http_script_add_code(*sc->values, size, &sc->main); 601 code = ngx_http_script_add_code(*sc->values, size, &sc->main);
395 if (code == NULL) { 602 if (code == NULL) {
396 return NGX_ERROR; 603 return NGX_ERROR;
397 } 604 }
398 605
399 code->code = ngx_http_script_copy_code; 606 code->code = ngx_http_script_copy_code;
400 code->len = value->len; 607 code->len = len;
401 608
402 ngx_memcpy((u_char *) code + sizeof(ngx_http_script_copy_code_t), 609 p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
403 value->data, value->len); 610 value->data, value->len);
611
612 if (zero) {
613 *p = '\0';
614 sc->zero = 0;
615 }
404 616
405 return NGX_OK; 617 return NGX_OK;
406 } 618 }
407 619
408 620
986 } 1198 }
987 1199
988 #endif 1200 #endif
989 1201
990 1202
1203 static ngx_int_t
1204 ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
1205 {
1206 ngx_http_script_full_name_code_t *code;
1207
1208 code = ngx_http_script_add_code(*sc->lengths,
1209 sizeof(ngx_http_script_full_name_code_t),
1210 NULL);
1211 if (code == NULL) {
1212 return NGX_ERROR;
1213 }
1214
1215 code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
1216 code->prefix = sc->conf_prefix;
1217
1218 code = ngx_http_script_add_code(*sc->values,
1219 sizeof(ngx_http_script_full_name_code_t),
1220 &sc->main);
1221 if (code == NULL) {
1222 return NGX_ERROR;
1223 }
1224
1225 code->code = ngx_http_script_full_name_code;
1226 code->prefix = sc->conf_prefix;
1227
1228 return NGX_OK;
1229 }
1230
1231
1232 static size_t
1233 ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
1234 {
1235 ngx_http_script_full_name_code_t *code;
1236
1237 code = (ngx_http_script_full_name_code_t *) e->ip;
1238
1239 e->ip += sizeof(ngx_http_script_full_name_code_t);
1240
1241 return code->prefix ? sizeof(NGX_CONF_PREFIX) : ngx_cycle->root.len;
1242 }
1243
1244
1245 static void
1246 ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
1247 {
1248 ngx_http_script_full_name_code_t *code;
1249
1250 ngx_str_t value;
1251
1252 code = (ngx_http_script_full_name_code_t *) e->ip;
1253
1254 value.data = e->buf.data;
1255 value.len = e->pos - e->buf.data;
1256
1257 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->prefix)
1258 != NGX_OK)
1259 {
1260 e->ip = ngx_http_script_exit;
1261 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1262 return;
1263 }
1264
1265 e->buf = value;
1266
1267 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
1268 "http script fullname: \"%V\"", &value);
1269
1270 e->ip += sizeof(ngx_http_script_full_name_code_t);
1271 }
1272
1273
991 void 1274 void
992 ngx_http_script_return_code(ngx_http_script_engine_t *e) 1275 ngx_http_script_return_code(ngx_http_script_engine_t *e)
993 { 1276 {
994 ngx_http_script_return_code_t *code; 1277 ngx_http_script_return_code_t *code;
995 1278