summaryrefslogtreecommitdiffabout
path: root/src/gdbmtool.c
Side-by-side diff
Diffstat (limited to 'src/gdbmtool.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/gdbmtool.c102
1 files changed, 82 insertions, 20 deletions
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 65b6740..2d57cbc 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -320,26 +320,12 @@ get_screen_lines ()
const char *lines = getenv ("LINES");
if (lines)
return strtol (lines, NULL, 10);
#endif
return -1;
}
-
-
-#define ARG_UNUSED __attribute__ ((__unused__))
-
-#define NARGS 5
-
-struct handler_param
-{
- int argc;
- struct gdbmarg **argv;
- FILE *fp;
- void *data;
-};
-
/* Open database */
void
open_handler (struct handler_param *param)
{
if (opendb (param->argv[0]->v.string) == 0)
@@ -748,13 +734,13 @@ list_handler (struct handler_param *param)
/* quit - quit the program */
void
quit_handler (struct handler_param *param ARG_UNUSED)
{
if (gdbm_file != NULL)
gdbm_close (gdbm_file);
-
+ input_done ();
exit (EXIT_OK);
}
/* export FILE [truncate] - export to a flat file format */
void
export_handler (struct handler_param *param)
@@ -888,24 +874,25 @@ struct argdef
{
char *name;
int type;
int ds;
};
+#define NARGS 5
+
struct command
{
char *name; /* Command name */
size_t len; /* Name length */
int tok;
int (*begin) (struct handler_param *param, size_t *);
void (*handler) (struct handler_param *param);
void (*end) (void *data);
struct argdef args[NARGS];
char *doc;
};
-
struct command command_tab[] = {
#define S(s) #s, sizeof (#s) - 1
{ S(count), T_CMD,
checkdb, count_handler, NULL,
{ { NULL } }, N_("count (number of entries)") },
@@ -1004,12 +991,19 @@ struct command command_tab[] = {
NULL, close_handler, NULL,
{ { NULL } }, N_("close the database") },
{ S(open), T_CMD,
NULL, open_handler, NULL,
{ { "FILE", GDBM_ARG_STRING }, { NULL } },
N_("open new database") },
+#ifdef WITH_READLINE
+ { S(history), T_CMD,
+ input_history_begin, input_history_handler, NULL,
+ { { N_("[FROM]"), GDBM_ARG_STRING },
+ { N_("[COUNT]"), GDBM_ARG_STRING },
+ { NULL } }, N_("show input history") },
+#endif
#undef S
{ 0 }
};
static int
cmdcmp (const void *a, const void *b)
@@ -1023,12 +1017,45 @@ void
sort_commands ()
{
qsort (command_tab, sizeof (command_tab) / sizeof (command_tab[0]) - 1,
sizeof (command_tab[0]), cmdcmp);
}
+/* Generator function for command completion. STATE lets us know whether
+ to start from scratch; without any state (i.e. STATE == 0), then we
+ start at the top of the list. */
+char *
+command_generator (const char *text, int state)
+{
+ const char *name;
+ static int len;
+ static struct command *cmd;
+
+ /* If this is a new word to complete, initialize now. This includes
+ saving the length of TEXT for efficiency, and initializing the index
+ variable to 0. */
+ if (!state)
+ {
+ cmd = command_tab;
+ len = strlen (text);
+ }
+
+ if (!cmd->name)
+ return NULL;
+
+ /* Return the next name which partially matches from the command list. */
+ while ((name = cmd->name))
+ {
+ cmd++;
+ if (strncmp (name, text, len) == 0)
+ return strdup (name);
+ }
+
+ /* If no names matched, then return NULL. */
+ return NULL;
+}
/* ? - help handler */
#define CMDCOLS 30
int
help_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
@@ -1171,31 +1198,61 @@ gdbmarg_kvpair (struct kvpair *kvp, struct locus *loc)
arg->loc = *loc;
arg->v.kvpair = kvp;
return arg;
}
struct slist *
-slist_new (char *s)
+slist_new_s (char *s)
{
struct slist *lp = emalloc (sizeof (*lp));
lp->next = NULL;
lp->str = s;
return lp;
}
+struct slist *
+slist_new (char const *s)
+{
+ return slist_new_s (estrdup (s));
+}
+
+struct slist *
+slist_new_l (char const *s, size_t l)
+{
+ char *copy = emalloc (l + 1);
+ memcpy (copy, s, l);
+ copy[l] = 0;
+ return slist_new_s (copy);
+}
+
void
slist_free (struct slist *lp)
{
while (lp)
{
struct slist *next = lp->next;
free (lp->str);
free (lp);
lp = next;
}
}
+
+void
+slist_insert (struct slist **where, struct slist *what)
+{
+ if (*where)
+ {
+ while (what->next)
+ what = what->next;
+ what->next = (*where)->next;
+ (*where)->next = what;
+ }
+ else
+ what->next = NULL;
+ *where = what;
+}
struct kvpair *
kvpair_string (struct locus *loc, char *val)
{
struct kvpair *p = ecalloc (1, sizeof (*p));
p->type = KV_STRING;
@@ -1213,13 +1270,12 @@ kvpair_list (struct locus *loc, struct slist *s)
if (loc)
p->loc = *loc;
p->val.l = s;
return p;
}
-
static void
kvlist_free (struct kvpair *kvp)
{
while (kvp)
{
struct kvpair *next = kvp->next;
@@ -1531,32 +1587,36 @@ int
main (int argc, char *argv[])
{
int intr;
int opt;
int bv;
int norc = 0;
+ int res;
char *source = "-";
set_progname (argv[0]);
#ifdef HAVE_SETLOCALE
setlocale (LC_ALL, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
sort_commands ();
-
+
/* Initialize variables. */
intr = isatty (0);
+ interactive = intr; /* Used early by input_init */
dsdef[DS_KEY] = dsegm_new_field (datadef_lookup ("string"), NULL, 1);
dsdef[DS_CONTENT] = dsegm_new_field (datadef_lookup ("string"), NULL, 1);
variable_set ("open", VART_STRING, "wrcreat");
variable_set ("pager", VART_STRING, getenv ("PAGER"));
+ input_init ();
+
for (opt = parseopt_first (argc, argv, optab);
opt != EOF;
opt = parseopt_next ())
switch (opt)
{
case 'f':
@@ -1637,8 +1697,10 @@ main (int argc, char *argv[])
/* Welcome message. */
if (intr && !variable_is_true ("quiet"))
printf (_("\nWelcome to the gdbm tool. Type ? for help.\n\n"));
if (setsource (source, intr))
exit (EXIT_FATAL);
- return yyparse ();
+ res = yyparse ();
+ input_done ();
+ return res;
}

Return to:

Send suggestions and report system problems to the System administrator.