Annotation of embedaddon/lighttpd/src/configparser.y, revision 1.1.1.3
1.1 misho 1: %token_prefix TK_
2: %extra_argument {config_t *ctx}
3: %name configparser
4:
5: %include {
1.1.1.3 ! misho 6: #include "first.h"
1.1 misho 7: #include "configfile.h"
8: #include "buffer.h"
9: #include "array.h"
1.1.1.3 ! misho 10: #include "request.h" /* http_request_host_normalize() */
1.1 misho 11:
12: #include <assert.h>
1.1.1.3 ! misho 13: #include <ctype.h>
! 14: #include <errno.h>
1.1 misho 15: #include <stdio.h>
16: #include <string.h>
17:
18: static void configparser_push(config_t *ctx, data_config *dc, int isnew) {
19: if (isnew) {
20: dc->context_ndx = ctx->all_configs->used;
1.1.1.2 misho 21: force_assert(dc->context_ndx > ctx->current->context_ndx);
1.1 misho 22: array_insert_unique(ctx->all_configs, (data_unset *)dc);
23: dc->parent = ctx->current;
1.1.1.3 ! misho 24: vector_config_weak_push(&dc->parent->children, dc);
1.1 misho 25: }
1.1.1.3 ! misho 26: if (ctx->configs_stack.used > 0 && ctx->current->context_ndx == 0) {
1.1 misho 27: fprintf(stderr, "Cannot use conditionals inside a global { ... } block\n");
28: exit(-1);
29: }
1.1.1.3 ! misho 30: vector_config_weak_push(&ctx->configs_stack, ctx->current);
1.1 misho 31: ctx->current = dc;
32: }
33:
34: static data_config *configparser_pop(config_t *ctx) {
35: data_config *old = ctx->current;
1.1.1.3 ! misho 36: ctx->current = vector_config_weak_pop(&ctx->configs_stack);
1.1 misho 37: return old;
38: }
39:
40: /* return a copied variable */
41: static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
42: data_unset *du;
43: data_config *dc;
44:
45: #if 0
46: fprintf(stderr, "get var %s\n", key->ptr);
47: #endif
48: for (dc = ctx->current; dc; dc = dc->parent) {
49: #if 0
50: fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
51: array_print(dc->value, 0);
52: #endif
53: if (NULL != (du = array_get_element(dc->value, key->ptr))) {
54: return du->copy(du);
55: }
56: }
57: return NULL;
58: }
59:
60: /* op1 is to be eat/return by this function if success, op1->key is not cared
61: op2 is left untouch, unreferenced
62: */
63: data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
64: /* type mismatch */
65: if (op1->type != op2->type) {
66: if (op1->type == TYPE_STRING && op2->type == TYPE_INTEGER) {
67: data_string *ds = (data_string *)op1;
1.1.1.3 ! misho 68: buffer_append_int(ds->value, ((data_integer*)op2)->value);
1.1 misho 69: return op1;
70: } else if (op1->type == TYPE_INTEGER && op2->type == TYPE_STRING) {
71: data_string *ds = data_string_init();
1.1.1.3 ! misho 72: buffer_append_int(ds->value, ((data_integer*)op1)->value);
1.1 misho 73: buffer_append_string_buffer(ds->value, ((data_string*)op2)->value);
74: op1->free(op1);
75: return (data_unset *)ds;
76: } else {
77: fprintf(stderr, "data type mismatch, cannot merge\n");
1.1.1.3 ! misho 78: op1->free(op1);
1.1 misho 79: return NULL;
80: }
81: }
82:
83: switch (op1->type) {
84: case TYPE_STRING:
85: buffer_append_string_buffer(((data_string *)op1)->value, ((data_string *)op2)->value);
86: break;
87: case TYPE_INTEGER:
88: ((data_integer *)op1)->value += ((data_integer *)op2)->value;
89: break;
90: case TYPE_ARRAY: {
91: array *dst = ((data_array *)op1)->value;
92: array *src = ((data_array *)op2)->value;
93: data_unset *du;
94: size_t i;
95:
96: for (i = 0; i < src->used; i ++) {
97: du = (data_unset *)src->data[i];
98: if (du) {
1.1.1.3 ! misho 99: if (du->is_index_key || buffer_is_empty(du->key) || !array_get_element(dst, du->key->ptr)) {
! 100: array_insert_unique(dst, du->copy(du));
! 101: } else {
! 102: fprintf(stderr, "Duplicate array-key '%s'\n", du->key->ptr);
! 103: op1->free(op1);
! 104: return NULL;
! 105: }
1.1 misho 106: }
107: }
108: break;
109: default:
1.1.1.2 misho 110: force_assert(0);
1.1 misho 111: break;
112: }
113: }
114: return op1;
115: }
116:
1.1.1.3 ! misho 117: static int configparser_remoteip_normalize_compat(buffer *rvalue) {
! 118: /* $HTTP["remoteip"] IPv6 accepted with or without '[]' for config compat
! 119: * http_request_host_normalize() expects IPv6 with '[]',
! 120: * and config processing at runtime expects COMP_HTTP_REMOTE_IP
! 121: * compared without '[]', so strip '[]' after normalization */
! 122: buffer *b = buffer_init();
! 123: int rc;
! 124:
! 125: if (rvalue->ptr[0] != '[') {
! 126: buffer_append_string_len(b, CONST_STR_LEN("["));
! 127: buffer_append_string_buffer(b, rvalue);
! 128: buffer_append_string_len(b, CONST_STR_LEN("]"));
! 129: } else {
! 130: buffer_append_string_buffer(b, rvalue);
! 131: }
! 132:
! 133: rc = http_request_host_normalize(b);
! 134:
! 135: if (0 == rc) {
! 136: /* remove surrounding '[]' */
! 137: size_t blen = buffer_string_length(b);
! 138: if (blen > 1) buffer_copy_string_len(rvalue, b->ptr+1, blen-2);
! 139: }
! 140:
! 141: buffer_free(b);
! 142: return rc;
! 143: }
! 144:
1.1 misho 145: }
146:
147: %parse_failure {
148: ctx->ok = 0;
149: }
150:
151: input ::= metalines.
152: metalines ::= metalines metaline.
153: metalines ::= .
154: metaline ::= varline.
155: metaline ::= global.
156: metaline ::= condlines(A) EOL. { A = NULL; }
157: metaline ::= include.
158: metaline ::= include_shell.
159: metaline ::= EOL.
160:
161: %type value {data_unset *}
162: %type expression {data_unset *}
163: %type aelement {data_unset *}
164: %type condline {data_config *}
165: %type condlines {data_config *}
166: %type aelements {array *}
167: %type array {array *}
168: %type key {buffer *}
169: %type stringop {buffer *}
170:
171: %type cond {config_cond_t }
172:
1.1.1.3 ! misho 173: %destructor value { if ($$) $$->free($$); }
! 174: %destructor expression { if ($$) $$->free($$); }
! 175: %destructor aelement { if ($$) $$->free($$); }
1.1 misho 176: %destructor aelements { array_free($$); }
177: %destructor array { array_free($$); }
178: %destructor key { buffer_free($$); }
179: %destructor stringop { buffer_free($$); }
180:
181: %token_type {buffer *}
182: %token_destructor { buffer_free($$); }
183:
184: varline ::= key(A) ASSIGN expression(B). {
185: if (ctx->ok) {
1.1.1.3 ! misho 186: buffer_copy_buffer(B->key, A);
1.1 misho 187: if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
188: fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
189: ctx->current->context_ndx,
190: ctx->current->key->ptr, A->ptr);
191: ctx->ok = 0;
192: } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
193: array_insert_unique(ctx->current->value, B);
194: B = NULL;
195: } else {
196: fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
197: ctx->current->context_ndx,
198: ctx->current->key->ptr, B->key->ptr);
199: ctx->ok = 0;
200: B->free(B);
201: B = NULL;
202: }
203: }
204: buffer_free(A);
205: A = NULL;
206: }
207:
208: varline ::= key(A) APPEND expression(B). {
1.1.1.3 ! misho 209: if (ctx->ok) {
! 210: array *vars = ctx->current->value;
! 211: data_unset *du;
1.1 misho 212:
1.1.1.3 ! misho 213: if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
! 214: fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
! 215: ctx->current->context_ndx,
! 216: ctx->current->key->ptr, A->ptr);
1.1 misho 217: ctx->ok = 0;
1.1.1.3 ! misho 218: } else if (NULL != (du = array_extract_element(vars, A->ptr)) || NULL != (du = configparser_get_variable(ctx, A))) {
! 219: du = configparser_merge_data(du, B);
! 220: if (NULL == du) {
! 221: ctx->ok = 0;
! 222: }
! 223: else {
! 224: buffer_copy_buffer(du->key, A);
! 225: array_insert_unique(ctx->current->value, du);
! 226: }
! 227: B->free(B);
! 228: } else {
! 229: buffer_copy_buffer(B->key, A);
! 230: array_insert_unique(ctx->current->value, B);
1.1 misho 231: }
1.1.1.3 ! misho 232: buffer_free(A);
! 233: A = NULL;
! 234: B = NULL;
1.1 misho 235: }
236: }
237:
238: key(A) ::= LKEY(B). {
239: if (strchr(B->ptr, '.') == NULL) {
240: A = buffer_init_string("var.");
241: buffer_append_string_buffer(A, B);
242: buffer_free(B);
243: B = NULL;
244: } else {
245: A = B;
246: B = NULL;
247: }
248: }
249:
250: expression(A) ::= expression(B) PLUS value(C). {
1.1.1.3 ! misho 251: A = NULL;
! 252: if (ctx->ok) {
! 253: A = configparser_merge_data(B, C);
! 254: if (NULL == A) {
! 255: ctx->ok = 0;
! 256: }
! 257: B = NULL;
! 258: C->free(C);
! 259: C = NULL;
1.1 misho 260: }
261: }
262:
263: expression(A) ::= value(B). {
264: A = B;
265: B = NULL;
266: }
267:
268: value(A) ::= key(B). {
269: A = NULL;
1.1.1.3 ! misho 270: if (ctx->ok) {
! 271: if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
! 272: char *env;
1.1 misho 273:
1.1.1.3 ! misho 274: if (NULL != (env = getenv(B->ptr + 4))) {
! 275: data_string *ds;
! 276: ds = data_string_init();
! 277: buffer_append_string(ds->value, env);
! 278: A = (data_unset *)ds;
! 279: }
! 280: else {
! 281: fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
! 282: ctx->ok = 0;
! 283: }
! 284: } else if (NULL == (A = configparser_get_variable(ctx, B))) {
! 285: fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
1.1 misho 286: ctx->ok = 0;
287: }
1.1.1.3 ! misho 288: buffer_free(B);
! 289: B = NULL;
1.1 misho 290: }
291: }
292:
293: value(A) ::= STRING(B). {
294: A = (data_unset *)data_string_init();
1.1.1.3 ! misho 295: buffer_copy_buffer(((data_string *)(A))->value, B);
1.1 misho 296: buffer_free(B);
297: B = NULL;
298: }
299:
300: value(A) ::= INTEGER(B). {
1.1.1.3 ! misho 301: char *endptr;
1.1 misho 302: A = (data_unset *)data_integer_init();
1.1.1.3 ! misho 303: errno = 0;
! 304: ((data_integer *)(A))->value = strtol(B->ptr, &endptr, 10);
! 305: /* skip trailing whitespace */
! 306: if (endptr != B->ptr) while (isspace(*endptr)) endptr++;
! 307: if (0 != errno || *endptr != '\0') {
! 308: fprintf(stderr, "error parsing number: '%s'\n", B->ptr);
! 309: ctx->ok = 0;
! 310: }
1.1 misho 311: buffer_free(B);
312: B = NULL;
313: }
314: value(A) ::= array(B). {
315: A = (data_unset *)data_array_init();
316: array_free(((data_array *)(A))->value);
317: ((data_array *)(A))->value = B;
318: B = NULL;
319: }
320: array(A) ::= LPARAN RPARAN. {
321: A = array_init();
322: }
323: array(A) ::= LPARAN aelements(B) RPARAN. {
324: A = B;
325: B = NULL;
326: }
327:
328: aelements(A) ::= aelements(C) COMMA aelement(B). {
1.1.1.3 ! misho 329: A = NULL;
! 330: if (ctx->ok) {
! 331: if (buffer_is_empty(B->key) ||
! 332: NULL == array_get_element(C, B->key->ptr)) {
! 333: array_insert_unique(C, B);
! 334: B = NULL;
! 335: } else {
! 336: fprintf(stderr, "Error: duplicate array-key: %s. Please get rid of the duplicate entry.\n",
! 337: B->key->ptr);
! 338: ctx->ok = 0;
! 339: B->free(B);
! 340: B = NULL;
! 341: }
1.1 misho 342:
1.1.1.3 ! misho 343: A = C;
! 344: C = NULL;
! 345: }
1.1 misho 346: }
347:
348: aelements(A) ::= aelements(C) COMMA. {
349: A = C;
350: C = NULL;
351: }
352:
353: aelements(A) ::= aelement(B). {
1.1.1.3 ! misho 354: A = NULL;
! 355: if (ctx->ok) {
! 356: A = array_init();
! 357: array_insert_unique(A, B);
! 358: B = NULL;
! 359: }
1.1 misho 360: }
361:
362: aelement(A) ::= expression(B). {
363: A = B;
364: B = NULL;
365: }
366: aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). {
1.1.1.3 ! misho 367: A = NULL;
! 368: if (ctx->ok) {
! 369: buffer_copy_buffer(C->key, B);
! 370: buffer_free(B);
! 371: B = NULL;
1.1 misho 372:
1.1.1.3 ! misho 373: A = C;
! 374: C = NULL;
! 375: }
1.1 misho 376: }
377:
378: eols ::= EOL.
379: eols ::= .
380:
381: globalstart ::= GLOBAL. {
382: data_config *dc;
383: dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
1.1.1.2 misho 384: force_assert(dc);
1.1 misho 385: configparser_push(ctx, dc, 0);
386: }
387:
1.1.1.3 ! misho 388: global ::= globalstart LCURLY metalines RCURLY. {
! 389: force_assert(ctx->current);
1.1 misho 390: configparser_pop(ctx);
1.1.1.3 ! misho 391: force_assert(ctx->current);
1.1 misho 392: }
393:
394: condlines(A) ::= condlines(B) eols ELSE condline(C). {
1.1.1.3 ! misho 395: A = NULL;
! 396: if (ctx->ok) {
! 397: if (B->context_ndx >= C->context_ndx) {
! 398: fprintf(stderr, "unreachable else condition\n");
! 399: ctx->ok = 0;
! 400: }
! 401: C->prev = B;
! 402: B->next = C;
! 403: A = C;
! 404: B = NULL;
! 405: C = NULL;
1.1 misho 406: }
407: }
408:
409: condlines(A) ::= condline(B). {
410: A = B;
411: B = NULL;
412: }
413:
414: condline(A) ::= context LCURLY metalines RCURLY. {
1.1.1.3 ! misho 415: A = NULL;
! 416: if (ctx->ok) {
! 417: data_config *cur;
1.1 misho 418:
1.1.1.3 ! misho 419: cur = ctx->current;
! 420: configparser_pop(ctx);
1.1 misho 421:
1.1.1.3 ! misho 422: force_assert(cur && ctx->current);
1.1 misho 423:
1.1.1.3 ! misho 424: A = cur;
! 425: }
1.1 misho 426: }
427:
428: context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expression(D). {
429: data_config *dc;
430: buffer *b, *rvalue, *op;
431:
432: if (ctx->ok && D->type != TYPE_STRING) {
433: fprintf(stderr, "rvalue must be string");
434: ctx->ok = 0;
435: }
436:
1.1.1.3 ! misho 437: if (ctx->ok) {
1.1 misho 438: switch(E) {
439: case CONFIG_COND_NE:
1.1.1.3 ! misho 440: op = buffer_init_string("!=");
! 441: break;
1.1 misho 442: case CONFIG_COND_EQ:
1.1.1.3 ! misho 443: op = buffer_init_string("==");
1.1 misho 444: break;
445: case CONFIG_COND_NOMATCH:
1.1.1.3 ! misho 446: op = buffer_init_string("!~");
! 447: break;
! 448: case CONFIG_COND_MATCH:
! 449: op = buffer_init_string("=~");
! 450: break;
! 451: default:
! 452: force_assert(0);
! 453: return; /* unreachable */
! 454: }
! 455:
! 456: b = buffer_init();
! 457: buffer_copy_buffer(b, ctx->current->key);
! 458: buffer_append_string(b, "/");
! 459: buffer_append_string_buffer(b, B);
! 460: buffer_append_string_buffer(b, C);
! 461: buffer_append_string_buffer(b, op);
! 462: rvalue = ((data_string*)D)->value;
! 463: buffer_append_string_buffer(b, rvalue);
1.1 misho 464:
1.1.1.3 ! misho 465: if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) {
! 466: configparser_push(ctx, dc, 0);
! 467: } else {
! 468: static const struct {
! 469: comp_key_t comp;
! 470: char *comp_key;
! 471: size_t len;
! 472: } comps[] = {
! 473: { COMP_SERVER_SOCKET, CONST_STR_LEN("SERVER[\"socket\"]" ) },
! 474: { COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) },
! 475: { COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) },
! 476: { COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) },
! 477: { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
! 478: { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"user-agent\"]" ) },
! 479: { COMP_HTTP_LANGUAGE, CONST_STR_LEN("HTTP[\"language\"]" ) },
! 480: { COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) },
! 481: { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
! 482: { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) },
! 483: { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
! 484: { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") },
! 485: { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") },
! 486: { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) },
! 487: { COMP_UNSET, NULL, 0 },
! 488: };
! 489: size_t i;
1.1 misho 490:
1.1.1.3 ! misho 491: dc = data_config_init();
1.1 misho 492:
1.1.1.3 ! misho 493: buffer_copy_buffer(dc->key, b);
! 494: buffer_copy_buffer(dc->op, op);
! 495: buffer_copy_buffer(dc->comp_key, B);
! 496: buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\""));
! 497: buffer_append_string_buffer(dc->comp_key, C);
! 498: buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]"));
! 499: dc->cond = E;
! 500:
! 501: for (i = 0; comps[i].comp_key; i ++) {
! 502: if (buffer_is_equal_string(
! 503: dc->comp_key, comps[i].comp_key, comps[i].len)) {
! 504: dc->comp = comps[i].comp;
! 505: break;
! 506: }
! 507: }
! 508: if (COMP_UNSET == dc->comp) {
! 509: fprintf(stderr, "error comp_key %s", dc->comp_key->ptr);
1.1 misho 510: ctx->ok = 0;
1.1.1.3 ! misho 511: }
! 512: else if (COMP_HTTP_REMOTE_IP == dc->comp
! 513: && (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE)) {
! 514: char * const slash = strchr(rvalue->ptr, '/'); /* CIDR mask */
! 515: char * const colon = strchr(rvalue->ptr, ':'); /* IPv6 */
! 516: if (NULL != slash && slash == rvalue->ptr){/*(skip AF_UNIX /path/file)*/
! 517: }
! 518: else if (NULL != slash) {
! 519: char *nptr;
! 520: const unsigned long nm_bits = strtoul(slash + 1, &nptr, 10);
! 521: if (*nptr || 0 == nm_bits || nm_bits > (NULL != colon ? 128 : 32)) {
! 522: /*(also rejects (slash+1 == nptr) which results in nm_bits = 0)*/
! 523: fprintf(stderr, "invalid or missing netmask: %s\n", rvalue->ptr);
! 524: ctx->ok = 0;
! 525: }
! 526: else {
! 527: int rc;
! 528: buffer_string_set_length(rvalue, (size_t)(slash - rvalue->ptr)); /*(truncate)*/
! 529: rc = (NULL == colon)
! 530: ? http_request_host_normalize(rvalue)
! 531: : configparser_remoteip_normalize_compat(rvalue);
! 532: buffer_append_string_len(rvalue, CONST_STR_LEN("/"));
! 533: buffer_append_int(rvalue, (int)nm_bits);
! 534: if (0 != rc) {
! 535: fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
! 536: ctx->ok = 0;
! 537: }
! 538: }
! 539: }
! 540: else {
! 541: int rc = (NULL == colon)
! 542: ? http_request_host_normalize(rvalue)
! 543: : configparser_remoteip_normalize_compat(rvalue);
! 544: if (0 != rc) {
! 545: fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
! 546: ctx->ok = 0;
! 547: }
! 548: }
! 549: }
! 550: else if (COMP_SERVER_SOCKET == dc->comp) {
! 551: /*(redundant with parsing in network.c; not actually required here)*/
! 552: if (rvalue->ptr[0] != ':' /*(network.c special-cases ":" and "[]")*/
! 553: && !(rvalue->ptr[0] == '[' && rvalue->ptr[1] == ']')) {
! 554: if (http_request_host_normalize(rvalue)) {
! 555: fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
! 556: ctx->ok = 0;
! 557: }
! 558: }
! 559: }
! 560: else if (COMP_HTTP_HOST == dc->comp) {
! 561: if (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE) {
! 562: if (http_request_host_normalize(rvalue)) {
! 563: fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
! 564: ctx->ok = 0;
! 565: }
! 566: }
! 567: }
! 568:
! 569: if (ctx->ok) switch(E) {
! 570: case CONFIG_COND_NE:
! 571: case CONFIG_COND_EQ:
! 572: dc->string = buffer_init_buffer(rvalue);
! 573: break;
! 574: case CONFIG_COND_NOMATCH:
! 575: case CONFIG_COND_MATCH: {
! 576: #ifdef HAVE_PCRE_H
! 577: const char *errptr;
! 578: int erroff, captures;
! 579:
! 580: if (NULL == (dc->regex =
! 581: pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) {
! 582: dc->string = buffer_init_string(errptr);
! 583: dc->cond = CONFIG_COND_UNSET;
! 584:
! 585: fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n",
! 586: rvalue->ptr, errptr, erroff);
! 587:
! 588: ctx->ok = 0;
! 589: } else if (NULL == (dc->regex_study =
! 590: pcre_study(dc->regex, 0, &errptr)) &&
! 591: errptr != NULL) {
! 592: fprintf(stderr, "studying regex failed: %s -> %s\n",
! 593: rvalue->ptr, errptr);
! 594: ctx->ok = 0;
! 595: } else if (0 != (pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, &captures))) {
! 596: fprintf(stderr, "getting capture count for regex failed: %s\n",
! 597: rvalue->ptr);
! 598: ctx->ok = 0;
! 599: } else if (captures > 9) {
! 600: fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n",
! 601: rvalue->ptr);
! 602: ctx->ok = 0;
! 603: } else {
! 604: dc->string = buffer_init_buffer(rvalue);
! 605: }
! 606: #else
! 607: fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n"
! 608: "(perhaps just a missing pcre-devel package ?) \n",
! 609: B->ptr, C->ptr);
1.1 misho 610: ctx->ok = 0;
1.1.1.3 ! misho 611: #endif
! 612: break;
! 613: }
! 614:
! 615: default:
! 616: fprintf(stderr, "unknown condition for $%s[%s]\n",
! 617: B->ptr, C->ptr);
1.1 misho 618: ctx->ok = 0;
1.1.1.3 ! misho 619: break;
1.1 misho 620: }
621:
1.1.1.3 ! misho 622: if (ctx->ok) {
! 623: configparser_push(ctx, dc, 1);
! 624: } else {
! 625: dc->free((data_unset*) dc);
! 626: }
1.1 misho 627: }
628:
1.1.1.3 ! misho 629: buffer_free(b);
! 630: buffer_free(op);
! 631: buffer_free(B);
! 632: B = NULL;
! 633: buffer_free(C);
! 634: C = NULL;
! 635: D->free(D);
! 636: D = NULL;
1.1 misho 637: }
638: }
639: cond(A) ::= EQ. {
640: A = CONFIG_COND_EQ;
641: }
642: cond(A) ::= MATCH. {
643: A = CONFIG_COND_MATCH;
644: }
645: cond(A) ::= NE. {
646: A = CONFIG_COND_NE;
647: }
648: cond(A) ::= NOMATCH. {
649: A = CONFIG_COND_NOMATCH;
650: }
651:
652: stringop(A) ::= expression(B). {
653: A = NULL;
654: if (ctx->ok) {
655: if (B->type == TYPE_STRING) {
656: A = buffer_init_buffer(((data_string*)B)->value);
657: } else if (B->type == TYPE_INTEGER) {
658: A = buffer_init();
1.1.1.3 ! misho 659: buffer_copy_int(A, ((data_integer *)B)->value);
1.1 misho 660: } else {
661: fprintf(stderr, "operand must be string");
662: ctx->ok = 0;
663: }
664: }
665: B->free(B);
666: B = NULL;
667: }
668:
669: include ::= INCLUDE stringop(A). {
670: if (ctx->ok) {
671: if (0 != config_parse_file(ctx->srv, ctx, A->ptr)) {
672: ctx->ok = 0;
673: }
674: buffer_free(A);
675: A = NULL;
676: }
677: }
678:
679: include_shell ::= INCLUDE_SHELL stringop(A). {
680: if (ctx->ok) {
681: if (0 != config_parse_cmd(ctx->srv, ctx, A->ptr)) {
682: ctx->ok = 0;
683: }
684: buffer_free(A);
685: A = NULL;
686: }
687: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>