diff --git a/src/array.h b/src/array.h index c780ed9c..e2603f3c 100644 --- a/src/array.h +++ b/src/array.h @@ -64,7 +64,8 @@ typedef enum { CONFIG_COND_EQ, /** == */ CONFIG_COND_MATCH, /** =~ */ CONFIG_COND_NE, /** != */ - CONFIG_COND_NOMATCH /** !~ */ + CONFIG_COND_NOMATCH, /** !~ */ + CONFIG_COND_ELSE /** (always true if reached) */ } config_cond_t; /** diff --git a/src/configfile-glue.c b/src/configfile-glue.c index 1e62b626..ded98387 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -408,6 +408,8 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat break; } + if (CONFIG_COND_ELSE == dc->cond) return COND_RESULT_TRUE; + /* pass the rules */ switch (dc->comp) { diff --git a/src/configparser.y b/src/configparser.y index f5ba0321..9d2ab190 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -398,6 +398,10 @@ condlines(A) ::= condlines(B) eols ELSE condline(C). { fprintf(stderr, "unreachable else condition\n"); ctx->ok = 0; } + if (B->cond == CONFIG_COND_ELSE) { + fprintf(stderr, "unreachable condition following else catch-all\n"); + ctx->ok = 0; + } C->prev = B; B->next = C; A = C; @@ -636,6 +640,24 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio D = NULL; } } + +context ::= . { + if (ctx->ok) { + data_config *dc = data_config_init(); + buffer_copy_buffer(dc->key, ctx->current->key); + buffer_append_string_len(dc->key, CONST_STR_LEN("/")); + buffer_append_string_len(dc->key, CONST_STR_LEN("else")); + dc->cond = CONFIG_COND_ELSE; + if (NULL == array_get_element(ctx->all_configs, dc->key->ptr)) { + configparser_push(ctx, dc, 1); + } else { + fprintf(stderr, "repeated else condition\n"); + ctx->ok = 0; + dc->free((data_unset *)dc); + } + } +} + cond(A) ::= EQ. { A = CONFIG_COND_EQ; } diff --git a/src/data_config.c b/src/data_config.c index ae7aa1dc..30c32bd2 100644 --- a/src/data_config.c +++ b/src/data_config.c @@ -63,8 +63,12 @@ static void data_config_print(const data_unset *d, int depth) { fprintf(stdout, "config {\n"); } else { - fprintf(stdout, "$%s %s \"%s\" {\n", - ds->comp_key->ptr, ds->op->ptr, ds->string->ptr); + if (ds->cond != CONFIG_COND_ELSE) { + fprintf(stdout, "$%s %s \"%s\" {\n", + ds->comp_key->ptr, ds->op->ptr, ds->string->ptr); + } else { + fprintf(stdout, "{\n"); + } array_print_indent(depth + 1); fprintf(stdout, "# block %d\n", ds->context_ndx); } @@ -103,8 +107,12 @@ static void data_config_print(const data_unset *d, int depth) { array_print_indent(depth); fprintf(stdout, "}"); if (0 != ds->context_ndx) { - fprintf(stdout, " # end of $%s %s \"%s\"", - ds->comp_key->ptr, ds->op->ptr, ds->string->ptr); + if (ds->cond != CONFIG_COND_ELSE) { + fprintf(stdout, " # end of $%s %s \"%s\"", + ds->comp_key->ptr, ds->op->ptr, ds->string->ptr); + } else { + fprintf(stdout, " # end of else"); + } } if (ds->next) {