diff options
Diffstat (limited to 'src/config.c')
-rw-r--r-- | src/config.c | 156 |
1 files changed, 112 insertions, 44 deletions
diff --git a/src/config.c b/src/config.c index 93683f0..76ca179 100644 --- a/src/config.c +++ b/src/config.c @@ -417,8 +417,8 @@ find_asrtop(char *s) return NULL; } -static int -parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus) +static struct slb_assertion * +parse_assert_argv(char **argv, struct grecs_symtab *at, grecs_locus_t *locus) { struct slb_assertion *ap; int install; @@ -439,7 +439,7 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus) op = find_asrtop(s); if (!op) { grecs_error(locus, 0, _("invalid operation: %s"), s); - return 1; + return NULL; } opcode = op->opcode; flags ^= op->flags; @@ -447,7 +447,7 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus) oidlen = MAX_OID_LEN; if (!read_objid(argv[0], oid, &oidlen)) { grecs_error(locus, 0, _("cannot parse oid")); - return 1; + return NULL; } install = 1; @@ -457,8 +457,16 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus) ap->opcode = opcode; ap->flags = flags; - ap->value = grecs_strdup(argv[2]); - ap->vallen = strlen(ap->value); + if (strcmp(argv[2], "-prev") == 0) { + ap->value = NULL; + ap->flags |= SLB_ASSERT_PREV; + } else if (argv[2][0] == '-') { + ap->value = grecs_strdup(argv[2] + 1); + ap->vallen = strlen(ap->value); + } else { + ap->value = grecs_strdup(argv[2]); + ap->vallen = strlen(ap->value); + } clone_locus(&ap->locus, locus); len = strlen(argv[0]) + 1 + @@ -470,56 +478,115 @@ parse_assertion(char **argv, struct grecs_symtab *at, grecs_locus_t *locus) strcat(ap->text, argv[1]); strcat(ap->text, " "); strcat(ap->text, argv[2]); - return 0; + return ap; } -int +static struct slb_assertion * +parse_assert_string(char *str, struct grecs_symtab *at, grecs_locus_t *locus) +{ + struct slb_assertion *ap; + struct wordsplit ws; + + if (wordsplit(str, &ws, WRDSF_DEFFLAGS)) { + grecs_error(locus, 0, "can't split argument: %s", + wordsplit_strerror(&ws)); + return NULL; + } + if (ws.ws_wordc > 3) { + grecs_error(locus, 0, "too many arguments to assertion"); + wordsplit_free(&ws); + return NULL; + } else if (ws.ws_wordc < 3) { + grecs_error(locus, 0, "too few arguments to assertion"); + wordsplit_free(&ws); + return NULL; + } + ap = parse_assert_argv(ws.ws_wordv, at, locus); + wordsplit_free(&ws); + return ap; +} + +static int cb_server_assert(enum grecs_callback_command cmd, grecs_locus_t *locus, void *varptr, grecs_value_t *value, void *cb_data) { - struct grecs_symtab *at = *(struct grecs_symtab **)varptr; - int rc; + struct slb_server *srv = varptr; + void **pdata = cb_data; + struct slb_assertion *ap; - if (assert_n_strings(locus, cmd, value, 1, 3)) - return 1; + switch (cmd) { + case grecs_callback_section_begin: + ap = parse_assert_string(value->v.string, srv->assertions, + locus); + if (!ap) + return 1; + *pdata = ap; + break; - if (value->type == GRECS_TYPE_STRING) { - struct wordsplit ws; + case grecs_callback_section_end: + /*ap = *pdata;*/ + break; - if (wordsplit(value->v.string, &ws, WRDSF_DEFFLAGS)) { - grecs_error(locus, 0, - _("can't split argument: %s"), - wordsplit_strerror(&ws)); - return 1; - } - if (ws.ws_wordc > 3) { - grecs_error(locus, 0, - _("too many arguments to assertion")); - wordsplit_free(&ws); - return 1; - } else if (ws.ws_wordc < 3) { - grecs_error(locus, 0, - _("too few arguments to assertion")); - wordsplit_free(&ws); - return 1; + case grecs_callback_set_value: + if (value->type == GRECS_TYPE_STRING) { + if (!parse_assert_string(value->v.string, + srv->assertions, locus)) + return 1; + } else { + char *argv[4]; + + if (assert_n_strings(locus, cmd, value, 3, 3)) + return 1; + + argv[0] = value->v.arg.v[0]->v.string; + argv[1] = value->v.arg.v[1]->v.string; + argv[2] = value->v.arg.v[2]->v.string; + argv[3] = NULL; + if (!parse_assert_argv(argv, srv->assertions, locus)) + return 1; } - rc = parse_assertion(ws.ws_wordv, at, locus); - wordsplit_free(&ws); - } else { - char *argv[4]; - argv[0] = value->v.arg.v[0]->v.string; - argv[1] = value->v.arg.v[1]->v.string; - argv[2] = value->v.arg.v[2]->v.string; - argv[3] = NULL; - rc = parse_assertion(argv, at, locus); } + return 0; +} - return rc; +static int +cb_assertion_action(enum grecs_callback_command cmd, + grecs_locus_t *locus, + void *varptr, + grecs_value_t *value, + void *cb_data) +{ + struct slb_assertion *asrt = varptr; + if (assert_string_value(locus, cmd, value)) + return 1; + if (strcmp(value->v.string, "abort") == 0) + asrt->action = SLB_ASSERT_ABORT; + else if (strcmp(value->v.string, "warn") == 0) + asrt->action = SLB_ASSERT_WARN; + else if (strcmp(value->v.string, "reinit") == 0) + asrt->action = SLB_ASSERT_REINIT; + else { + grecs_error(locus, 0, "unknown action"); + return 1; + } + return 0; } +static struct grecs_keyword server_assert_kw[] = { + { "action", N_("{abort|warn|reinit}"), + N_("Action to take when the assertion fails"), + grecs_type_string, GRECS_DFLT, + NULL, 0, + cb_assertion_action }, + { "message", NULL, N_("Message to issue when the assertion fails"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct slb_assertion, text) }, + { NULL } +}; + int cb_server_macro(enum grecs_callback_command cmd, grecs_locus_t *locus, @@ -866,10 +933,11 @@ static struct grecs_keyword server_kw[] = { "Each of these can be suffixed with \"/i\" to request case-insensitive\n" "comparison.\n" "\n" - "A \"!\" in front of opcode reverts its meaning."), - grecs_type_string, GRECS_MULT, - NULL, offsetof(struct slb_server, assertions), - cb_server_assert }, + "A \"!\" in front of opcode reverts its meaning.\n\n" + "The block part is optional. If omitted, the default action is \"abort\""), + grecs_type_section, GRECS_MULT, + NULL, 0, + cb_server_assert, NULL, server_assert_kw }, { NULL } }; |