diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2022-06-18 17:18:05 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2022-06-18 17:27:06 +0300 |
commit | b8271d89db991558e10c26d45d960bbc0257fa31 (patch) | |
tree | b3da6dacd5dbdfae43348af6b9e8cae88852e98b | |
parent | 94d0a6238e9573473d2cfdc74135305b2f6741f2 (diff) | |
download | gdbm-b8271d89db991558e10c26d45d960bbc0257fa31.tar.gz |
Fix location tracking in gdbmtool. Fix the recover command.
In particular, this addresses https://puszcza.gnu.org.ua/bugs/?566
* configure.ac: Fix diagnostic message
* tools/gdbmshell.c: Use lerror when needed.
(recover_handler): Accept varargs
(command_tab): Use argdoc to provide help for varargs
(help_handler): Handle argdoc
* tools/gdbmtool.h (PARAM_LOCPTR): New macro.
* tools/gram.y: Accept a single unadorned key=value pair as argument.
Fix locus for key=value pair in a list.
* tools/lex.l (YY_USER_ACTION): Use setbeg() to decide whether yyloc.beg
must be updated.
(setbeg): New function.
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | tools/gdbmshell.c | 402 | ||||
-rw-r--r-- | tools/gdbmtool.h | 1 | ||||
-rw-r--r-- | tools/gram.y | 164 | ||||
-rw-r--r-- | tools/lex.l | 21 |
5 files changed, 335 insertions, 256 deletions
diff --git a/configure.ac b/configure.ac index 3547d9c..d884bcc 100644 --- a/configure.ac +++ b/configure.ac @@ -256,10 +256,11 @@ EOF if test "$want_gdbmtool_debug" != default; then cat <<EOF NOTE: You used the --enable-gdbmtool-debug option. In order for your changes -NOTE: to take effect, please run the following command prior to building the +NOTE: to take effect, please run the following commands prior to building the NOTE: package: NOTE: NOTE: make -C src maintainer-clean-generic +NOTE: make -C tools maintainer-clean-generic NOTE: EOF fi diff --git a/tools/gdbmshell.c b/tools/gdbmshell.c index 1d7a29f..40b5ce7 100644 --- a/tools/gdbmshell.c +++ b/tools/gdbmshell.c @@ -91,7 +91,7 @@ opendb (char *dbname, int fd) int filemode; GDBM_FILE db; int n; - + switch (variable_get ("cachesize", VART_INT, (void**) &cache_size)) { case VAR_OK: @@ -108,10 +108,10 @@ opendb (char *dbname, int fd) default: abort (); } - + if (variable_get ("open", VART_INT, (void**) &flags) != VAR_OK) abort (); - + if (flags == GDBM_NEWDB) { if (interactive () && variable_is_true ("confirm") && @@ -126,14 +126,14 @@ opendb (char *dbname, int fd) abort (); flags |= n; - + if (!variable_is_true ("lock")) flags |= GDBM_NOLOCK; if (!variable_is_true ("mmap")) flags |= GDBM_NOMMAP; if (variable_is_true ("sync")) flags |= GDBM_SYNC; - + if (variable_get ("filemode", VART_INT, (void**) &filemode)) abort (); @@ -164,10 +164,10 @@ opendb (char *dbname, int fd) { gdbmshell_setopt ("GDBM_SETCENTFREE", GDBM_SETCENTFREE, 1); } - + if (gdbm_file) gdbm_close (gdbm_file); - + gdbm_file = db; return GDBMSHELL_OK; } @@ -245,7 +245,7 @@ print_bucket (FILE *fp) hash_bucket *bucket = gdbm_file->bucket; int start = bucket_dir_start (); int dircount = bucket_refcount (); - + hash_prefix = start << (GDBM_HASH_BITS - gdbm_file->header->dir_bits); fprintf (fp, "******* "); @@ -265,10 +265,10 @@ print_bucket (FILE *fp) fprintf (fp, " (%d-%d)", start, start + dircount - 1); } fprintf (fp, "\n"); - + fprintf (fp, _("count = %d\n" - "load factor = %3d\n"), + "load factor = %3d\n"), bucket->count, bucket->count * 100 / gdbm_file->header->bucket_elems); @@ -313,8 +313,8 @@ avail_list_count (avail_block *avblk, off_t off, void *data) ctr->lines += avblk->count; return ctr->lines > ctr->min_size; -} - +} + static size_t _gdbm_avail_list_size (GDBM_FILE dbf, size_t min_size) { @@ -329,7 +329,7 @@ static void av_table_display (avail_elem *av_table, int count, FILE *fp) { int i; - + for (i = 0; i < count; i++) { fprintf (fp, " %15d %10lu \n", @@ -341,7 +341,7 @@ static int avail_list_print (avail_block *avblk, off_t n, void *data) { FILE *fp = data; - + fputc ('\n', fp); if (n == 0)//FIXME fprintf (fp, "%s", _("header block")); @@ -369,7 +369,7 @@ _gdbm_print_bucket_cache (FILE *fp, GDBM_FILE dbf) { int i; cache_elem *elem; - + fprintf (fp, _("Bucket Cache (size %zu/%zu):\n Index: Address Changed Data_Hash \n"), dbf->cache_num, dbf->cache_size); @@ -432,7 +432,7 @@ open_handler (struct command_param *param, char *filename; int fd = -1; int rc; - + closedb (); if (param->argc == 1) @@ -442,7 +442,7 @@ open_handler (struct command_param *param, variable_get ("filename", VART_STRING, (void**) &filename); variable_get ("fd", VART_INT, (void**) &fd); } - + if ((rc = opendb (filename, fd)) == GDBMSHELL_OK) { variable_set ("filename", VART_STRING, filename); @@ -484,7 +484,7 @@ count_to_str (gdbm_count_t count, char *buf, size_t bufsize) } return p; } - + /* count - count items in the database */ static int count_handler (struct command_param *param GDBM_ARG_UNUSED, @@ -505,7 +505,7 @@ count_handler (struct command_param *param GDBM_ARG_UNUSED, if (!p) terror ("%s", _("count buffer overflow")); else - fprintf (cenv->fp, + fprintf (cenv->fp, ngettext ("There is %s item in the database.\n", "There are %s items in the database.\n", count), @@ -668,64 +668,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; } } @@ -746,7 +777,7 @@ recover_handler (struct command_param *param, struct command_environ *cenv) (unsigned long) rcvr.recovered_buckets, (unsigned long) rcvr.failed_buckets); } - + if (rcvr.backup_name) { fprintf (cenv->fp, @@ -762,7 +793,7 @@ recover_handler (struct command_param *param, struct command_environ *cenv) rc = GDBMSHELL_GDBM_ERR; } return rc; -} +} /* avail - print available list */ static int @@ -798,8 +829,8 @@ print_current_bucket_begin (struct command_param *param GDBM_ARG_UNUSED, { if (exp_count) *exp_count = gdbm_file->bucket - ? bucket_print_lines (gdbm_file->bucket) + 3 - : 1; + ? bucket_print_lines (gdbm_file->bucket) + 3 + : 1; } return rc; } @@ -837,7 +868,7 @@ getnum (int *pnum, char *arg, char **endp) *pnum = x; return 0; } - + /* bucket NUM - print a bucket and set it as a current one. Uses print_current_bucket_handler */ static int @@ -847,7 +878,7 @@ print_bucket_begin (struct command_param *param, { int rc; int n = -1; - + if ((rc = checkdb ()) != GDBMSHELL_OK) return rc; @@ -858,7 +889,8 @@ print_bucket_begin (struct command_param *param, if (n >= GDBM_DIR_COUNT (gdbm_file)) { - terror (_("bucket number out of range (0..%lu)"), + lerror (PARAM_LOCPTR (param, 0), + _("bucket number out of range (0..%lu)"), GDBM_DIR_COUNT (gdbm_file)); return GDBMSHELL_SYNTAX; } @@ -874,7 +906,7 @@ print_bucket_begin (struct command_param *param, return GDBMSHELL_GDBM_ERR; } } - + if (exp_count) *exp_count = bucket_print_lines (gdbm_file->bucket) + 3; return GDBMSHELL_OK; @@ -886,7 +918,7 @@ print_sibling_bucket_begin (struct command_param *param, size_t *exp_count) { int rc, n0, n, bucket_bits; - + if ((rc = checkdb ()) != GDBMSHELL_OK) return rc; if (!gdbm_file->bucket) @@ -904,7 +936,7 @@ print_sibling_bucket_begin (struct command_param *param, fprintf (stderr, _("no sibling\n")); return GDBMSHELL_ERR; } - + if (_gdbm_get_bucket (gdbm_file, n)) { dberror (_("%s failed"), "_gdbm_get_bucket"); @@ -921,11 +953,11 @@ print_sibling_bucket_begin (struct command_param *param, } return GDBMSHELL_ERR; } - + if (exp_count) *exp_count = bucket_print_lines (gdbm_file->bucket) + 3; return GDBMSHELL_OK; -} +} /* dir - print hash directory */ static int @@ -934,7 +966,7 @@ print_dir_begin (struct command_param *param GDBM_ARG_UNUSED, size_t *exp_count) { int rc; - + if ((rc = checkdb ()) == GDBMSHELL_OK) { if (exp_count) @@ -987,7 +1019,7 @@ print_header_begin (struct command_param *param GDBM_ARG_UNUSED, { int rc; int n; - + if ((rc = checkdb ()) != GDBMSHELL_OK) return rc; @@ -1008,7 +1040,7 @@ print_header_begin (struct command_param *param GDBM_ARG_UNUSED, if (exp_count) *exp_count = n; - + return GDBMSHELL_OK; } @@ -1036,7 +1068,7 @@ print_header_handler (struct command_param *param GDBM_ARG_UNUSED, default: abort (); } - + fprintf (fp, _("\nFile Header: \n\n")); fprintf (fp, _(" type = %s\n"), type); fprintf (fp, _(" directory start = %lu\n"), @@ -1058,7 +1090,7 @@ print_header_handler (struct command_param *param GDBM_ARG_UNUSED, if (gdbm_file->xheader) { fprintf (fp, _("\nExtended Header: \n\n")); - fprintf (fp, _(" version = %d\n"), gdbm_file->xheader->version); + fprintf (fp, _(" version = %d\n"), gdbm_file->xheader->version); fprintf (fp, _(" numsync = %u\n"), gdbm_file->xheader->numsync); } @@ -1165,18 +1197,18 @@ print_snapshot (char const *snapname, FILE *fp) struct error_entry errs[MAXERRS]; int errn = 0; int i; - + switch (st.st_mode & ~S_IFREG) { case S_IRUSR: case S_IWUSR: break; - + default: - error_push (errs, &errn, ARRAY_SIZE (errs), N_("bad file mode"), - 0, 0); + error_push (errs, &errn, ARRAY_SIZE (errs), N_("bad file mode"), + 0, 0); } - + fprintf (fp, "%s: ", snapname); fprintf (fp, "%03o %s ", st.st_mode & 0777, decode_mode (st.st_mode, buf)); @@ -1225,7 +1257,7 @@ print_snapshot (char const *snapname, FILE *fp) if (errs[i].sys_err) fprintf (fp, ": %s", strerror (errs[i].sys_err)); fputc ('\n', fp); - } + } } else { @@ -1250,17 +1282,17 @@ snapshot_err_fn (FILE *fp, char const *sa, char const *sb) print_snapshot (sa, fp); print_snapshot (sb, fp); break; - + case EINVAL: fprintf (fp, "%s.\n", _("Invalid arguments in call to gdbm_latest_snapshot")); break; - + case ENOSYS: fprintf (fp, "%s.\n", _("Function is not implemented: GDBM is built without crash-tolerance support")); break; - } + } } static struct snapshot_status_info snapshot_status_info[] = { @@ -1289,19 +1321,19 @@ static struct snapshot_status_info snapshot_status_info[] = { snapshot_print_fn } }; - + static int snapshot_handler (struct command_param *param, struct command_environ *cenv) { char *sa = tildexpand (PARAM_STRING (param, 0)); char *sb = tildexpand (PARAM_STRING (param, 1)); char const *sel; - int rc = gdbm_latest_snapshot (sa, sb, &sel); + int rc = gdbm_latest_snapshot (sa, sb, &sel); if (rc >= 0 && rc < ARRAY_SIZE (snapshot_status_info)) { fprintf (cenv->fp, - "%s: %s.\n", + "%s: %s.\n", snapshot_status_info[rc].code, gettext (snapshot_status_info[rc].descr)); if (snapshot_status_info[rc].fn) @@ -1347,7 +1379,7 @@ print_cache_begin (struct command_param *param GDBM_ARG_UNUSED, size_t *exp_count) { int rc; - + if ((rc = checkdb ()) == GDBMSHELL_OK) { if (exp_count) @@ -1380,7 +1412,7 @@ list_begin (struct command_param *param GDBM_ARG_UNUSED, size_t *exp_count) { int rc; - + if ((rc = checkdb ()) == GDBMSHELL_OK) { if (param->argc) @@ -1391,7 +1423,7 @@ list_begin (struct command_param *param GDBM_ARG_UNUSED, PARAM_STRING (param, 0)); return GDBMSHELL_ERR; } - + if (!gdbm_file->bucket) { fprintf (stderr, "%s", _("select bucket first\n")); @@ -1415,7 +1447,7 @@ list_begin (struct command_param *param GDBM_ARG_UNUSED, if (exp_count) { gdbm_count_t count; - + if (gdbm_count (gdbm_file, &count)) *exp_count = 0; else if (count > SIZE_T_MAX) @@ -1425,7 +1457,7 @@ list_begin (struct command_param *param GDBM_ARG_UNUSED, } } } - + return rc; } @@ -1435,13 +1467,13 @@ list_bucket_keys (struct command_environ *cenv) int rc = GDBMSHELL_OK; int i; hash_bucket *bucket = gdbm_file->bucket; - + for (i = 0; i < bucket->count; i++) { if (bucket->h_table[i].hash_value != -1) { datum key, content; - + key.dptr = _gdbm_read_entry (gdbm_file, i); if (!key.dptr) { @@ -1477,7 +1509,7 @@ list_all_keys (struct command_environ *cenv) datum key; datum data; int rc = GDBMSHELL_OK; - + key = gdbm_firstkey (gdbm_file); if (!key.dptr && gdbm_errno != GDBM_ITEM_NOT_FOUND) { @@ -1547,7 +1579,7 @@ export_handler (struct command_param *param, int i; int filemode; int rc = GDBMSHELL_OK; - + for (i = 1; i < param->argc; i++) { if (strcmp (PARAM_STRING (param, i), "truncate") == 0) @@ -1558,7 +1590,8 @@ export_handler (struct command_param *param, format = GDBM_DUMP_FMT_ASCII; else { - terror (_("unrecognized argument: %s"), PARAM_STRING (param, i)); + lerror (PARAM_LOCPTR (param, i), + _("unrecognized argument: %s"), PARAM_STRING (param, i)); return GDBMSHELL_SYNTAX; } } @@ -1584,7 +1617,7 @@ import_handler (struct command_param *param, int i; int rc = GDBMSHELL_OK; char *file_name; - + for (i = 1; i < param->argc; i++) { if (strcmp (PARAM_STRING (param, i), "replace") == 0) @@ -1593,7 +1626,8 @@ import_handler (struct command_param *param, meta_mask = GDBM_META_MASK_MODE | GDBM_META_MASK_OWNER; else { - terror (_("unrecognized argument: %s"), + lerror (PARAM_LOCPTR (param, i), + _("unrecognized argument: %s"), PARAM_STRING (param, i)); return GDBMSHELL_SYNTAX; } @@ -1612,7 +1646,7 @@ import_handler (struct command_param *param, rc = checkdb (); variable_set ("open", VART_STRING, save_mode); free (save_mode); - + if (rc) return rc; @@ -1686,7 +1720,7 @@ debug_handler (struct command_param *param, struct command_environ *cenv) { struct gdbmarg *arg; int i; - + for (arg = param->vararg, i = 0; arg; arg = arg->next, i++) { if (arg->type == GDBM_ARG_STRING) @@ -1694,7 +1728,7 @@ debug_handler (struct command_param *param, struct command_environ *cenv) int flag; int negate; char const *tok = arg->v.string; - + if (tok[0] == '-') { ++tok; @@ -1707,8 +1741,8 @@ debug_handler (struct command_param *param, struct command_environ *cenv) } else negate = 0; - - flag = gdbm_debug_token (tok); + + flag = gdbm_debug_token (tok); if (flag) { if (negate) @@ -1717,10 +1751,10 @@ debug_handler (struct command_param *param, struct command_environ *cenv) gdbm_debug_flags |= flag; } else - terror (_("unknown debug flag: %s"), tok); + lerror (&arg->loc, _("unknown debug flag: %s"), tok); } else - terror (_("invalid type of argument %d"), i); + lerror (&arg->loc, _("invalid type of argument %d"), i); } } else @@ -1747,7 +1781,7 @@ shell_handler (struct command_param *param, char *argv[4]; pid_t pid, rc; int status; - + argv[0] = getenv ("$SHELL"); if (!argv[0]) argv[0] = "/bin/sh"; @@ -1846,7 +1880,7 @@ struct history_param int from; int count; }; - + static int input_history_begin (struct command_param *param, struct command_environ *cenv GDBM_ARG_UNUSED, @@ -1863,7 +1897,7 @@ input_history_begin (struct command_param *param, input_stream_name ()); return GDBMSHELL_OK; } - + switch (param->argc) { case 1: @@ -1902,7 +1936,7 @@ input_history_handler (struct command_param *param GDBM_ARG_UNUSED, struct history_param *p = cenv->data; int i; FILE *fp = cenv->fp; - + for (i = 0; i < p->count; i++) { const char *s = input_history_get (p->from + i); @@ -1943,6 +1977,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; @@ -2058,7 +2093,7 @@ static struct command command_tab[] = { .doc = N_("begin iteration: get first key and datum"), .tok = T_CMD, .begin = checkdb_begin, - .handler = firstkey_handler, + .handler = firstkey_handler, .variadic = FALSE, .repeat = REPEAT_NEVER, }, @@ -2073,21 +2108,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, }, { @@ -2098,7 +2133,7 @@ static struct command command_tab[] = { .handler = avail_handler, .variadic = FALSE, .repeat = REPEAT_NEVER, - }, + }, { .name = "bucket", .args = { @@ -2185,7 +2220,7 @@ static struct command command_tab[] = { .handler = sync_handler, .variadic = FALSE, .repeat = REPEAT_NEVER, - }, + }, { .name = "upgrade", .doc = N_("Upgrade the database to extended format"), @@ -2203,7 +2238,7 @@ static struct command command_tab[] = { .handler = downgrade_handler, .variadic = FALSE, .repeat = REPEAT_NEVER, - }, + }, { .name = "snapshot", .args = { @@ -2244,9 +2279,9 @@ static struct command command_tab[] = { }, { .name = "set", - .args = { - { "[VAR=VALUE...]" }, - { NULL } + .argdoc = { + "[VAR=VALUE...]", + NULL }, .doc = N_("set or list variables"), .tok = T_SET, @@ -2255,9 +2290,9 @@ static struct command command_tab[] = { }, { .name = "unset", - .args = { - { "VAR..." }, - { NULL } + .argdoc = { + "VAR...", + NULL }, .doc = N_("unset variables"), .tok = T_UNSET, @@ -2266,10 +2301,10 @@ static struct command command_tab[] = { }, { .name = "define", - .args = { - { "key|content", GDBM_ARG_STRING }, - { "{ FIELD-LIST }", GDBM_ARG_STRING }, - { NULL } + .argdoc = { + "key|content", + "{ FIELD-LIST }", + NULL }, .doc = N_("define datum structure"), .tok = T_DEF, @@ -2325,6 +2360,17 @@ static struct command command_tab[] = { { .name = "debug", .doc = N_("query/set debug level"), + .argdoc = { +#if GDBM_DEBUG_ENABLE + "[[+-]err]", + "[[+-]open]", + "[[+-]store]", + "[[+-]read]", + "[[+-]lookup]", + "[[+-]all]", +#endif + NULL + }, .tok = T_CMD, .handler = debug_handler, .variadic = TRUE, @@ -2390,7 +2436,7 @@ command_generator (const char *text, int state) { cmd++; if (strncmp (name, text, len) == 0) - return strdup (name); + return strdup (name); } /* If no names matched, then return NULL. */ @@ -2419,7 +2465,7 @@ help_handler (struct command_param *param GDBM_ARG_UNUSED, fflush (cenv->fp); wf = wordwrap_fdopen (fileno (cenv->fp)); - + for (cmd = command_tab; cmd->name; cmd++) { int i; @@ -2434,11 +2480,15 @@ help_handler (struct command_param *param GDBM_ARG_UNUSED, for (i = 0; i < NARGS && cmd->args[i].name; i++) { wordwrap_printf (wf, " %s", gettext (cmd->args[i].name)); - } + } + for (i = 0; cmd->argdoc[i]; i++) + { + wordwrap_printf (wf, " %s", gettext (cmd->argdoc[i])); + } wordwrap_set_right_margin (wf, 0); wordwrap_set_left_margin (wf, CMDCOLS); - + wordwrap_printf (wf, " %s", gettext (cmd->doc)); wordwrap_flush (wf); } @@ -2452,7 +2502,7 @@ command_lookup (const char *str, struct locus *loc, struct command **pcmd) enum { fcom_init, fcom_found, fcom_ambig, fcom_abort } state = fcom_init; struct command *cmd, *found = NULL; size_t len = strlen (str); - + for (cmd = command_tab; state != fcom_abort && cmd->name; cmd++) { size_t n = len < cmd->len ? len : cmd->len; @@ -2480,7 +2530,7 @@ command_lookup (const char *str, struct locus *loc, struct command **pcmd) case fcom_ambig: fprintf (stderr, " %s\n", cmd->name); break; - + case fcom_abort: /* should not happen */ abort (); @@ -2490,7 +2540,7 @@ command_lookup (const char *str, struct locus *loc, struct command **pcmd) if (state == fcom_init) lerror (loc, interactive () ? _("Invalid command. Try ? for help.") : - _("Unknown command")); + _("Unknown command")); if (!found) return T_BOGUS; @@ -2608,7 +2658,7 @@ kvpair_list (struct locus *loc, struct slist *s) p->loc = *loc; p->val.l = s; return p; -} +} void kvlist_free (struct kvpair *kvp) @@ -2768,7 +2818,7 @@ struct gdbmarg * coerce_k2d (struct gdbmarg *arg, struct argdef *def) { datum d; - + if (datum_scan (&d, dsdef[def->ds], arg->v.kvpair)) return NULL; return gdbmarg_datum (&d, &arg->loc); @@ -2783,7 +2833,7 @@ coerce_s2d (struct gdbmarg *arg, struct argdef *def) memset (&kvp, 0, sizeof (kvp)); kvp.type = KV_STRING; kvp.val.s = arg->v.string; - + if (datum_scan (&d, dsdef[def->ds], &kvp)) return NULL; return gdbmarg_datum (&d, &arg->loc); @@ -2794,12 +2844,12 @@ coerce_s2d (struct gdbmarg *arg, struct argdef *def) coerce_type_t coerce_tab[GDBM_ARG_MAX][GDBM_ARG_MAX] = { /* s d k */ /* s */ { coerce_ref, coerce_fail, coerce_fail }, - /* d */ { coerce_s2d, coerce_ref, coerce_k2d }, + /* d */ { coerce_s2d, coerce_ref, coerce_k2d }, /* k */ { coerce_fail, coerce_fail, coerce_ref } }; char *argtypestr[] = { "string", "datum", "k/v pair" }; - + static struct gdbmarg * coerce (struct gdbmarg *arg, struct argdef *def) { @@ -2860,7 +2910,7 @@ format_arg (struct gdbmarg *arg, struct argdef *def, FILE *fp) terror ("%s:%d: INTERNAL ERROR: unexpected data type in arglist", __FILE__, __LINE__); break; - + case GDBM_ARG_KVPAIR: { struct kvpair *kvp = arg->v.kvpair; @@ -2870,7 +2920,7 @@ format_arg (struct gdbmarg *arg, struct argdef *def, FILE *fp) case KV_STRING: fprintf (fp, "%s", kvp->val.s); break; - + case KV_LIST: { struct slist *p = kvp->val.l; @@ -2881,7 +2931,7 @@ format_arg (struct gdbmarg *arg, struct argdef *def, FILE *fp) } } } -} +} struct timing { @@ -2918,10 +2968,10 @@ timeval_sub (struct timeval a, struct timeval b) void timing_stop (struct timing *t) -{ +{ struct rusage r; struct timeval now; - + gettimeofday (&now, NULL); getrusage (RUSAGE_SELF, &r); t->real = timeval_sub (now, t->real); @@ -2936,7 +2986,7 @@ getline (char **pbuf, size_t *psize, FILE *fp) char *buf = *pbuf; size_t size = *psize; ssize_t off = 0; - + do { if (!buf || size == 0 || off == size - 1) @@ -2979,7 +3029,7 @@ argsprep (struct command *cmd, struct gdbmarglist *arglist, size_t argsize =0; ssize_t n; struct gdbmarg *t; - + if (*argname == '[') /* Optional argument */ break; @@ -2999,7 +3049,7 @@ argsprep (struct command *cmd, struct gdbmarglist *arglist, } trimnl (argbuf); - + t = gdbmarg_string (argbuf, &yylloc); if (param_push_arg (param, t, &cmd->args[i])) { @@ -3016,9 +3066,9 @@ argsprep (struct command *cmd, struct gdbmarglist *arglist, param_term (param); param->vararg = arg; - + return 0; -} +} int run_command (struct command *cmd, struct gdbmarglist *arglist) @@ -3031,7 +3081,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) struct command_environ cenv = COMMAND_ENVIRON_INITIALIZER; int rc = 0; struct timing tm; - + if (argsprep (cmd, arglist, ¶m)) rc = GDBMSHELL_ERR; else @@ -3040,7 +3090,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) /* Prepare for calling the handler */ pagfp = NULL; - + if (variable_is_true ("trace")) { fprintf (stderr, "+ %s", cmd->name); @@ -3057,7 +3107,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) } fputc ('\n', stderr); } - + expected_lines = 0; expected_lines_ptr = (interactive () && pager) ? &expected_lines : NULL; rc = 0; @@ -3075,11 +3125,11 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) strerror (errno)); pager = NULL; cenv.fp = stdout; - } + } } else cenv.fp = stdout; - + timing_start (&tm); rc = cmd->handler (¶m, &cenv); timing_stop (&tm); @@ -3096,7 +3146,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) tm.user.tv_sec, tm.user.tv_usec, tm.sys.tv_sec, tm.sys.tv_usec); } - + if (pagfp) pclose (pagfp); } @@ -3128,7 +3178,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) gdbmarglist_free (arglist); rc = 0; } - + return rc; } @@ -3148,7 +3198,7 @@ gdbmshell_run (int (*init) (void *, instream_t *), void *data) qsort (command_tab, i, sizeof (command_tab[0]), cmdcmp); commands_sorted = 1; } - + /* Initialize variables. */ dsdef[DS_KEY] = dsegm_new_field (datadef_lookup ("string"), NULL, 1); dsdef[DS_CONTENT] = dsegm_new_field (datadef_lookup ("string"), NULL, 1); @@ -3159,7 +3209,7 @@ gdbmshell_run (int (*init) (void *, instream_t *), void *data) last_cmd = NULL; gdbmarglist_init (&last_args, NULL); - + lex_trace (0); rc = init (data, &instream); @@ -3169,7 +3219,7 @@ gdbmshell_run (int (*init) (void *, instream_t *), void *data) if (rc == 0) { struct sigaction act, old_act; - + act.sa_flags = 0; sigemptyset(&act.sa_mask); act.sa_handler = SIG_IGN; @@ -3196,7 +3246,7 @@ gdbmshell_run (int (*init) (void *, instream_t *), void *data) } variables_free (); - + return rc; } diff --git a/tools/gdbmtool.h b/tools/gdbmtool.h index 748a210..5e65c8e 100644 --- a/tools/gdbmtool.h +++ b/tools/gdbmtool.h @@ -237,6 +237,7 @@ struct command_param #define HANDLER_PARAM_INITIALIZER { 0, 0, NULL, NULL } +#define PARAM_LOCPTR(p,n) (&(p)->argv[n]->loc) #define PARAM_STRING(p,n) ((p)->argv[n]->v.string) #define PARAM_DATUM(p,n) ((p)->argv[n]->v.dat) #define PARAM_KVPAIR(p,n) ((p)->argv[n]->v.kvpair) diff --git a/tools/gram.y b/tools/gram.y index 6b09152..e052815 100644 --- a/tools/gram.y +++ b/tools/gram.y @@ -19,12 +19,12 @@ #include "gdbmtool.h" struct dsegm *dsdef[DS_MAX]; - + %} %define parse.error verbose %locations - + %token <type> T_TYPE %token T_OFF "off" T_PAD "pad" @@ -38,7 +38,7 @@ struct dsegm *dsdef[DS_MAX]; %token <num> T_NUM "number" %token <string> T_IDENT "identifier" T_WORD "word" %type <cmd> command -%type <string> string +%type <string> string %type <arg> arg %type <arglist> arglist arg1list %type <dsegm> def defbody @@ -74,29 +74,29 @@ struct dsegm *dsdef[DS_MAX]; %% input : /* empty */ - | stmtlist + | stmtlist ; stmtlist : stmt - | stmtlist stmt - ; + | stmtlist stmt + ; stmt : /* empty */ eol - { + { if (run_last_command ()) { YYABORT; } } - | command arglist eol - { + | command arglist eol + { if (run_command ($1, &$2)) { YYABORT; } } - | set eol - | defn eol + | set eol + | defn eol | T_BOGUS eol { if (interactive ()) @@ -107,8 +107,8 @@ stmt : /* empty */ eol else YYERROR; } - | error { end_def(); } eol - { + | error { end_def(); } eol + { if (interactive ()) { yyclearin; @@ -117,55 +117,62 @@ stmt : /* empty */ eol else YYERROR; } - ; + ; command : T_CMD - | T_SHELL - ; + | T_SHELL + ; eol : '\n' - | ';' - ; + | ';' + ; arglist : /* empty */ - { + { gdbmarglist_init (&$$, NULL); } - | arg1list + | arg1list ; arg1list : arg - { + { gdbmarglist_init (&$$, $1); } - | arg1list arg + | arg1list arg { gdbmarglist_add (&$1, $2); $$ = $1; } - ; + ; arg : string - { + { $$ = gdbmarg_string ($1, &@1); } - | compound + | 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); } ; compound : '{' kvlist '}' - { + { $$ = $2.head; } - ; + ; kvlist : kvpair - { + { $$.head = $$.tail = $1; } - | kvlist ',' kvpair + | kvlist ',' kvpair { if (kvlist_find ($1.head, $3->key)) { @@ -178,66 +185,67 @@ kvlist : kvpair $1.tail = $3; $$ = $1; } - ; + ; kvpair : value - | T_IDENT '=' value + | T_IDENT '=' value { $3->key = $1; + $3->loc.beg = @1.beg; $$ = $3; } - ; + ; value : string - { + { $$ = kvpair_string (&@1, $1); } - | '{' slist '}' + | '{' slist '}' { $$ = kvpair_list (&@1, $2.head); } - ; + ; slist : string - { + { $$.head = $$.tail = slist_new_s ($1); } - | slist ',' string + | slist ',' string { struct slist *s = slist_new_s ($3); slist_insert (&$1.tail, s); $$ = $1; } - ; + ; string : T_IDENT - | T_WORD - ; + | T_WORD + ; defn : T_DEF defid { begin_def (); } defbody - { + { end_def (); dsegm_list_free (dsdef[$2]); dsdef[$2] = $4; } - ; + ; defbody : '{' deflist optcomma '}' - { + { $$ = $2.head; } - | T_TYPE - { + | T_TYPE + { $$ = dsegm_new_field ($1, NULL, 1); } - ; + ; optcomma : /* empty */ - | ',' - ; + | ',' + ; defid : T_IDENT - { + { if (strcmp ($1, "key") == 0) { $$ = DS_KEY; @@ -256,58 +264,58 @@ defid : T_IDENT YYERROR; } } - ; + ; deflist : def - { + { $$.head = $$.tail = $1; } - | deflist ',' def + | deflist ',' def { $1.tail->next = $3; $1.tail = $3; $$ = $1; } - ; + ; def : T_TYPE T_IDENT - { + { $$ = dsegm_new_field ($1, $2, 1); } - | T_TYPE T_IDENT '[' T_NUM ']' - { + | T_TYPE T_IDENT '[' T_NUM ']' + { $$ = dsegm_new_field ($1, $2, $4); } - | T_OFF T_NUM + | T_OFF T_NUM { $$ = dsegm_new (FDEF_OFF); $$->v.n = $2; } - | T_PAD T_NUM + | T_PAD T_NUM { $$ = dsegm_new (FDEF_PAD); $$->v.n = $2; } - ; + ; set : T_SET - { + { variable_print_all (stdout); - } - | T_SET asgnlist + } + | T_SET asgnlist | T_UNSET varlist - ; + ; asgnlist : asgn - | asgnlist asgn - ; + | asgnlist asgn + ; asgn : T_IDENT - { + { int t = 1; int rc; char *varname = $1; - + rc = variable_set (varname, VART_BOOL, &t); if (rc == VAR_ERR_NOTDEF && strncmp (varname, "no", 2) == 0) { @@ -320,7 +328,7 @@ asgn : T_IDENT { case VAR_OK: break; - + case VAR_ERR_NOTDEF: lerror (&@1, _("no such variable: %s"), varname); break; @@ -336,20 +344,20 @@ asgn : T_IDENT case VAR_ERR_GDBM: dberror ("%s", _("can't set variable")); break; - + default: lerror (&@1, _("unexpected error setting %s: %d"), $1, rc); } free ($1); } - | T_IDENT '=' string + | T_IDENT '=' string { int rc = variable_set ($1, VART_STRING, $3); switch (rc) { case VAR_OK: break; - + case VAR_ERR_NOTDEF: lerror (&@1, _("no such variable: %s"), $1); break; @@ -368,20 +376,20 @@ asgn : T_IDENT free ($1); free ($3); } - ; + ; varlist : var - | varlist var - ; + | varlist var + ; var : T_IDENT - { + { int rc = variable_unset ($1); switch (rc) { case VAR_OK: break; - + case VAR_ERR_NOTDEF: lerror (&@1, _("no such variable: %s"), $1); break; @@ -392,7 +400,7 @@ var : T_IDENT } free ($1); } - ; + ; %% @@ -437,7 +445,7 @@ yyerror (char const *s) void gram_trace (int n) { -#if GDBMTOOL_DEBUG +#if GDBMTOOL_DEBUG yydebug = 1; #endif } diff --git a/tools/lex.l b/tools/lex.l index fb1e49e..ae4525e 100644 --- a/tools/lex.l +++ b/tools/lex.l @@ -37,10 +37,12 @@ advance_line (void) context_tos->point.col = 0; } +static int setbeg (void); + #define YY_USER_ACTION \ do \ { \ - if (YYSTATE == 0) \ + if (setbeg ()) \ { \ yylloc.beg = context_tos->point; \ yylloc.beg.col++; \ @@ -681,6 +683,23 @@ psname (void) } } +static int +setbeg (void) +{ + switch (YYSTATE) + { + case INITIAL: + case CMD: + case SHELL: + case DEF: + return 1; + + default: + /* STR MLSTR SHELLWS SHSTR SHQ */ + return 0; + } +} + char * make_prompt (void) { |