From b8271d89db991558e10c26d45d960bbc0257fa31 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 18 Jun 2022 17:18:05 +0300 Subject: [PATCH] Fix location tracking in gdbmtool. Fix the recover command. In particular, this addresses https://puszcza.gnu.org.ua/bugs/?566 * src/gdbmshell.c: Fix parameter parsing failure (recover_handler): Accept varargs (command_tab): Use argdoc to provide help for varargs (help_handler): Handle argdoc * src/gram.y: Accept a single unadorned key=value pair as argument. Conflict: Fix only the part that caused the problem Origin Patch: https://git.gnu.org.ua/gdbm.git/commit/?id=b8271d89db991558e10c26d45d960bbc0257fa31 --- src/gdbmshell.c | 156 +++++++++++++++++++++++++++++++++++--------------------- src/gram.y | 8 +++ 2 files changed, 106 insertions(+), 58 deletions(-) diff --git a/src/gdbmshell.c b/src/gdbmshell.c index 9f0d06c..4b84c23 100644 --- a/src/gdbmshell.c +++ b/src/gdbmshell.c @@ -625,64 +625,95 @@ recover_handler (struct command_param *param, struct command_environ *cenv) gdbm_recovery rcvr; int flags = 0; int rc; - int i; char *p; int summary = 0; - for (i = 0; i < param->argc; i++) + if (param->vararg) { - char *arg = PARAM_STRING (param, i); - if (strcmp (arg, "verbose") == 0) - { - rcvr.errfun = err_printer; - flags |= GDBM_RCVR_ERRFUN; - } - else if (strcmp (arg, "force") == 0) - { - flags |= GDBM_RCVR_FORCE; - } - else if (strcmp (arg, "summary") == 0) - { - summary = 1; - } - else if (strcmp (arg, "backup") == 0) - { - flags |= GDBM_RCVR_BACKUP; - } - else if (strncmp (arg, "max-failures=", 13) == 0) + struct gdbmarg *arg; + int i; + + for (arg = param->vararg, i = 0; arg; arg = arg->next, i++) { - rcvr.max_failures = strtoul (arg + 13, &p, 10); - if (*p) + if (arg->type == GDBM_ARG_STRING) { - terror (_("not a number (stopped near %s)"), p); - return 1; + if (strcmp (arg->v.string, "verbose") == 0) + { + rcvr.errfun = err_printer; + flags |= GDBM_RCVR_ERRFUN; + } + else if (strcmp (arg->v.string, "force") == 0) + { + flags |= GDBM_RCVR_FORCE; + } + else if (strcmp (arg->v.string, "summary") == 0) + { + summary = 1; + } + else if (strcmp (arg->v.string, "backup") == 0) + { + flags |= GDBM_RCVR_BACKUP; + } + else + { + lerror (&arg->loc, _("unrecognized argument: %s"), arg->v.string); + return GDBMSHELL_SYNTAX; + } } - flags |= GDBM_RCVR_MAX_FAILURES; - } - else if (strncmp (arg, "max-failed-keys=", 16) == 0) - { - rcvr.max_failed_keys = strtoul (arg + 16, &p, 10); - if (*p) + else if (arg->type == GDBM_ARG_KVPAIR) { - terror (_("not a number (stopped near %s)"), p); - return 1; + if (arg->v.kvpair->type != KV_STRING) + { + lerror (&arg->loc, _("%s: bad argument type"), arg->v.kvpair->key); + return GDBMSHELL_SYNTAX; + } + else if (arg->v.kvpair->next) + { + lerror (&arg->loc, _("unexpected compound statement")); + return GDBMSHELL_SYNTAX; + } + + if (strcmp (arg->v.kvpair->key, "max-failures") == 0) + { + rcvr.max_failures = strtoul (arg->v.kvpair->val.s, &p, 10); + if (*p) + { + lerror (&arg->loc, _("not a number (stopped near %s)"), p); + return GDBMSHELL_SYNTAX; + } + flags |= GDBM_RCVR_MAX_FAILURES; + } + else if (strcmp (arg->v.kvpair->key, "max-failed-keys") == 0) + { + rcvr.max_failed_keys = strtoul (arg->v.kvpair->val.s, &p, 10); + if (*p) + { + lerror (&arg->loc, _("not a number (stopped near %s)"), p); + return GDBMSHELL_SYNTAX; + } + flags |= GDBM_RCVR_MAX_FAILED_KEYS; + } + else if (strcmp (arg->v.kvpair->key, "max-failed-buckets") == 0) + { + rcvr.max_failures = strtoul (arg->v.kvpair->val.s, &p, 10); + if (*p) + { + lerror (&arg->loc, _("not a number (stopped near %s)"), p); + return GDBMSHELL_SYNTAX; + } + flags |= GDBM_RCVR_MAX_FAILED_BUCKETS; + } + else + { + lerror (&arg->loc, _("unrecognized argument: %s"), arg->v.kvpair->key); + return GDBMSHELL_SYNTAX; + } } - flags |= GDBM_RCVR_MAX_FAILED_KEYS; - } - else if (strncmp (arg, "max-failed-buckets=", 19) == 0) - { - rcvr.max_failures = strtoul (arg + 19, &p, 10); - if (*p) + else { - terror (_("not a number (stopped near %s)"), p); - return 1; + lerror (&arg->loc, _("unexpected datum")); + return GDBMSHELL_SYNTAX; } - flags |= GDBM_RCVR_MAX_FAILED_BUCKETS; - } - else - { - terror (_("unrecognized argument: %s"), arg); - return GDBMSHELL_SYNTAX; } } @@ -1765,6 +1796,7 @@ struct command int (*handler) (struct command_param *param, struct command_environ *cenv); void (*end) (void *data); struct argdef args[NARGS]; + char *argdoc[NARGS]; int variadic; enum command_repeat_type repeat; char *doc; @@ -1891,21 +1923,21 @@ static struct command command_tab[] = { }, { .name = "recover", - .args = { - { "[verbose]", GDBM_ARG_STRING }, - { "[summary]", GDBM_ARG_STRING }, - { "[backup]", GDBM_ARG_STRING }, - { "[force]", GDBM_ARG_STRING }, - { "[max-failed-keys=N]", GDBM_ARG_STRING }, - { "[max-failed-buckets=N]", GDBM_ARG_STRING }, - { "[max-failures=N]", GDBM_ARG_STRING }, - { NULL } + .argdoc = { + "[verbose]", + "[summary]", + "[backup]", + "[force]", + "[max-failed-keys=N]", + "[max-failed-buckets=N]", + "[max-failures=N]", + NULL }, .doc = N_("recover the database"), .tok = T_CMD, .begin = checkdb_begin, .handler = recover_handler, - .variadic = FALSE, + .variadic = TRUE, .repeat = REPEAT_NEVER, }, { @@ -2244,7 +2276,15 @@ help_handler (struct command_param *param GDBM_ARG_UNUSED, } n += fprintf (fp, " %s", gettext (cmd->args[i].name)); } - + for (i = 0; i < NARGS && cmd->argdoc[i]; i++) + { + if (n >= CMDCOLS) + { + fputc ('\n', fp); + n = fprintf (fp, "%*.*s", optoff, optoff, ""); + } + n += fprintf (fp, " %s", gettext (cmd->argdoc[i])); + } if (n < CMDCOLS) fprintf (fp, "%*.s", CMDCOLS-n, ""); else diff --git a/src/gram.y b/src/gram.y index 561de89..156bb2c 100644 --- a/src/gram.y +++ b/src/gram.y @@ -140,6 +140,13 @@ arg : string { $$ = gdbmarg_string ($1, &@1); } + | T_IDENT '=' string + { + struct locus loc = { .beg = @1.beg, .end = @3.end }; + struct kvpair *kvp = kvpair_string (&loc, $3); + kvp->key = $1; + $$ = gdbmarg_kvpair (kvp, &loc); + } | compound { $$ = gdbmarg_kvpair ($1, &@1); @@ -175,6 +182,7 @@ kvpair : value | T_IDENT '=' value { $3->key = $1; + $3->loc.beg = @1.beg; $$ = $3; } ; -- 1.8.3.1