summaryrefslogtreecommitdiff
path: root/src/configparser.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/configparser.y')
-rw-r--r--src/configparser.y164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/configparser.y b/src/configparser.y
new file mode 100644
index 00000000..3d424ce3
--- /dev/null
+++ b/src/configparser.y
@@ -0,0 +1,164 @@
+%token_prefix TK_
+%token_type {buffer *}
+%extra_argument {config_t *ctx}
+%name configparser
+
+%include {
+#include <assert.h>
+#include "config.h"
+#include "configfile.h"
+#include "buffer.h"
+#include "array.h"
+}
+
+%parse_failure {
+ ctx->ok = 0;
+}
+
+input ::= metalines.
+metalines ::= metalines metaline.
+metalines ::= .
+metaline ::= varline.
+metaline ::= condline.
+metaline ::= EOL.
+
+%type value {data_unset *}
+%type aelement {data_unset *}
+%type aelements {array *}
+%type array {array *}
+%type cond {config_cond_t }
+%token_destructor { buffer_free($$); }
+
+varline ::= key(A) ASSIGN value(B). {
+ buffer_copy_string_buffer(B->key, A);
+ array_insert_unique(ctx->ctx_config, B);
+ buffer_free(A);
+}
+
+key(A) ::= LKEY(B). {
+ A = B;
+ B = NULL;
+}
+
+value(A) ::= STRING(B). {
+ A = (data_unset *)data_string_init();
+ buffer_copy_string_buffer(((data_string *)(A))->value, B);
+ buffer_free(B);
+}
+
+value(A) ::= INTEGER(B). {
+ A = (data_unset *)data_integer_init();
+ ((data_integer *)(A))->value = strtol(B->ptr, NULL, 10);
+ buffer_free(B);
+}
+value(A) ::= array(B). {
+ A = (data_unset *)data_array_init();
+ array_free(((data_array *)(A))->value);
+ ((data_array *)(A))->value = B;
+}
+array(A) ::= LPARAN aelements(B) RPARAN. {
+ A = B;
+ B = NULL;
+}
+
+aelements(A) ::= aelements(C) COMMA aelement(B). {
+ array_insert_unique(C, B);
+
+ A = C;
+}
+
+aelements(A) ::= aelements(C) COMMA. {
+ A = C;
+}
+
+aelements(A) ::= aelement(B). {
+ A = array_init();
+ array_insert_unique(A, B);
+}
+
+aelement(A) ::= value(B). {
+ A = B;
+ B = NULL;
+}
+aelement(A) ::= STRING(B) ARRAY_ASSIGN value(C). {
+ buffer_copy_string_buffer(C->key, B);
+ buffer_free(B);
+
+ A = C;
+ C = NULL;
+}
+condline ::= context LCURLY metalines RCURLY EOL. {
+ data_config *dc;
+
+ dc = (data_config *)array_get_element(ctx->config, "global");
+ assert(dc);
+ ctx->ctx_name = dc->key;
+ ctx->ctx_config = dc->value;
+}
+
+context ::= DOLLAR SRVVARNAME(B) LBRACKET STRING(C) RBRACKET cond(E) STRING(D). {
+ data_config *dc;
+ buffer *b;
+
+ b = buffer_init();
+ buffer_copy_string_buffer(b, B);
+ buffer_append_string_buffer(b, C);
+ buffer_append_string_buffer(b, D);
+ buffer_append_long(b, E);
+
+ if (NULL != (dc = (data_config *)array_get_element(ctx->config, b->ptr))) {
+ ctx->ctx_name = dc->key;
+ ctx->ctx_config = dc->value;
+ } else {
+ dc = data_config_init();
+
+ buffer_copy_string_buffer(dc->key, b);
+ buffer_copy_string_buffer(dc->comp_key, B);
+ buffer_append_string_buffer(dc->comp_key, C);
+ dc->cond = E;
+
+ switch(E) {
+ case CONFIG_COND_NE:
+ case CONFIG_COND_EQ:
+ dc->match.string = buffer_init_string(D->ptr);
+ break;
+#ifdef HAVE_PCRE_H
+ case CONFIG_COND_NOMATCH:
+ case CONFIG_COND_MATCH: {
+ const char *errptr;
+ int erroff;
+
+ if (NULL == (dc->match.regex =
+ pcre_compile(D->ptr, 0, &errptr, &erroff, NULL))) {
+ dc->match.string = buffer_init_string(errptr);
+ dc->cond = CONFIG_COND_UNSET;
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ array_insert_unique(ctx->config, (data_unset *)dc);
+
+ ctx->ctx_name = dc->key;
+ ctx->ctx_config = dc->value;
+ }
+ buffer_free(b);
+ buffer_free(B);
+ buffer_free(C);
+ buffer_free(D);
+}
+cond(A) ::= EQ. {
+ A = CONFIG_COND_EQ;
+}
+cond(A) ::= MATCH. {
+ A = CONFIG_COND_MATCH;
+}
+cond(A) ::= NE. {
+ A = CONFIG_COND_NE;
+}
+cond(A) ::= NOMATCH. {
+ A = CONFIG_COND_NOMATCH;
+}