diff options
Diffstat (limited to 'src/gdbmtool.c')
-rw-r--r-- | src/gdbmtool.c | 102 |
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 @@ -314,38 +314,24 @@ get_screen_lines () if (lines) ws.ws_row = strtol (lines, NULL, 10); } return ws.ws_row; } #else 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) { free (file_name); file_name = estrdup (param->argv[0]->v.string); } } @@ -742,25 +728,25 @@ list_handler (struct handler_param *param) } free (key.dptr); key = nextkey; } } /* 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) { int format = GDBM_DUMP_FMT_ASCII; int flags = GDBM_WRCREAT; int i; int filemode; @@ -882,36 +868,37 @@ source_handler (struct handler_param *param) void help_handler (struct handler_param *param); int help_begin (struct handler_param *param, size_t *exp_count); 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)") }, { S(delete), T_CMD, checkdb, delete_handler, NULL, { { N_("KEY"), GDBM_ARG_DATUM, DS_KEY }, { NULL } }, N_("delete a record") }, { S(export), T_CMD, checkdb, export_handler, NULL, { { N_("FILE"), GDBM_ARG_STRING }, @@ -998,43 +985,83 @@ struct command command_tab[] = { { NULL } }, N_("define datum structure") }, { S(source), T_CMD, NULL, source_handler, NULL, { { "FILE", GDBM_ARG_STRING }, { NULL } }, N_("source command script") }, { S(close), T_CMD, 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) { struct command const *ac = a; struct command const *bc = b; return strcmp (ac->name, bc->name); } 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) { if (exp_count) *exp_count = sizeof (command_tab) / sizeof (command_tab[0]) + 1; return 0; } @@ -1165,67 +1192,96 @@ gdbmarg_kvpair (struct kvpair *kvp, struct locus *loc) { struct gdbmarg *arg = ecalloc (1, sizeof (*arg)); arg->next = NULL; arg->type = GDBM_ARG_KVPAIR; arg->ref = 1; if (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; if (loc) p->loc = *loc; p->val.s = val; return p; } struct kvpair * kvpair_list (struct locus *loc, struct slist *s) { struct kvpair *p = ecalloc (1, sizeof (*p)); p->type = KV_LIST; 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; free (kvp->key); switch (kvp->type) { case KV_STRING: free (kvp->val.s); break; @@ -1525,44 +1581,48 @@ source_rcfile () } free (fname); } } 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': source = optarg; intr = 0; break; case 'l': bv = 0; @@ -1631,14 +1691,16 @@ main (int argc, char *argv[]) memset (¶m, 0, sizeof (param)); argmax = 0; if (!norc) source_rcfile (); /* 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; } |