diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-07-12 12:41:15 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-07-12 14:34:16 +0300 |
commit | 89f200b55b309aa67c1fbfc11d4de211725348f4 (patch) | |
tree | 39e2e43f29766cbebbdf61f160b5d062ea63c996 /src | |
parent | e8cad816f36b1cad11bb67c96f0ce878cf30844e (diff) | |
download | gdbm-89f200b55b309aa67c1fbfc11d4de211725348f4.tar.gz gdbm-89f200b55b309aa67c1fbfc11d4de211725348f4.tar.bz2 |
Line-editing support in gdbmtool
* configure.ac: Check if GNU Readline is available.
* src/Makefile.am: Add new files.
* src/input-rl.c: New file.
* src/input-std.c: New file.
* src/gdbmtool.c (handler_param): Move declaration to
the header file.
(quit_handler): Call input_done.
(command_tab): Add the "history" command.
(command_generator): New function.
(slist_new_s, slist_new_l)
(slist_insert): New functions.
(main): Call input_init and input_done.
* src/gdbmtool.h: New protos.
* src/gram.y: Use slist_insert to construct string lists.
* src/lex.l (read_input): Remove. Use input_read instead.
(print_prompt_at_bol): New function.
(print_prompt): Remove.
(make_prompt): New function.
* NEWS: Document changes.
* README: Document readline support.
* doc/gdbm.texi: Document line editing in gdbmtool.
* doc/gdbmtool.1: Likewise.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/gdbmtool.c | 102 | ||||
-rw-r--r-- | src/gdbmtool.h | 31 | ||||
-rw-r--r-- | src/gram.y | 7 | ||||
-rw-r--r-- | src/input-rl.c | 235 | ||||
-rw-r--r-- | src/input-std.c | 43 | ||||
-rw-r--r-- | src/lex.l | 134 |
7 files changed, 483 insertions, 81 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6a05634..b55deb6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -79,7 +79,11 @@ libgdbmapp_a_SOURCES =\ | |||
79 | # Programs | 79 | # Programs |
80 | bin_PROGRAMS = gdbmtool gdbm_load gdbm_dump | 80 | bin_PROGRAMS = gdbmtool gdbm_load gdbm_dump |
81 | 81 | ||
82 | gdbmtool_LDADD = ./libgdbmapp.a ./libgdbm.la | 82 | gdbmtool_LDADD = \ |
83 | ./libgdbmapp.a\ | ||
84 | ./libgdbm.la\ | ||
85 | @READLINE_LIBS@ | ||
86 | |||
83 | gdbmtool_SOURCES = \ | 87 | gdbmtool_SOURCES = \ |
84 | datconv.c\ | 88 | datconv.c\ |
85 | gram.y\ | 89 | gram.y\ |
@@ -89,6 +93,12 @@ gdbmtool_SOURCES = \ | |||
89 | var.c\ | 93 | var.c\ |
90 | util.c | 94 | util.c |
91 | 95 | ||
96 | if GDBM_COND_READLINE | ||
97 | gdbmtool_SOURCES += input-rl.c | ||
98 | else | ||
99 | gdbmtool_SOURCES += input-std.c | ||
100 | endif | ||
101 | |||
92 | AM_YFLAGS = -dtv | 102 | AM_YFLAGS = -dtv |
93 | #AM_LFLAGS = -d | 103 | #AM_LFLAGS = -d |
94 | 104 | ||
diff --git a/src/gdbmtool.c b/src/gdbmtool.c index 65b6740..2d57cbc 100644 --- a/src/gdbmtool.c +++ b/src/gdbmtool.c | |||
@@ -323,20 +323,6 @@ get_screen_lines () | |||
323 | #endif | 323 | #endif |
324 | return -1; | 324 | return -1; |
325 | } | 325 | } |
326 | |||
327 | |||
328 | #define ARG_UNUSED __attribute__ ((__unused__)) | ||
329 | |||
330 | #define NARGS 5 | ||
331 | |||
332 | struct handler_param | ||
333 | { | ||
334 | int argc; | ||
335 | struct gdbmarg **argv; | ||
336 | FILE *fp; | ||
337 | void *data; | ||
338 | }; | ||
339 | |||
340 | 326 | ||
341 | /* Open database */ | 327 | /* Open database */ |
342 | void | 328 | void |
@@ -751,7 +737,7 @@ quit_handler (struct handler_param *param ARG_UNUSED) | |||
751 | { | 737 | { |
752 | if (gdbm_file != NULL) | 738 | if (gdbm_file != NULL) |
753 | gdbm_close (gdbm_file); | 739 | gdbm_close (gdbm_file); |
754 | 740 | input_done (); | |
755 | exit (EXIT_OK); | 741 | exit (EXIT_OK); |
756 | } | 742 | } |
757 | 743 | ||
@@ -891,6 +877,8 @@ struct argdef | |||
891 | int ds; | 877 | int ds; |
892 | }; | 878 | }; |
893 | 879 | ||
880 | #define NARGS 5 | ||
881 | |||
894 | struct command | 882 | struct command |
895 | { | 883 | { |
896 | char *name; /* Command name */ | 884 | char *name; /* Command name */ |
@@ -902,7 +890,6 @@ struct command | |||
902 | struct argdef args[NARGS]; | 890 | struct argdef args[NARGS]; |
903 | char *doc; | 891 | char *doc; |
904 | }; | 892 | }; |
905 | |||
906 | 893 | ||
907 | struct command command_tab[] = { | 894 | struct command command_tab[] = { |
908 | #define S(s) #s, sizeof (#s) - 1 | 895 | #define S(s) #s, sizeof (#s) - 1 |
@@ -1007,6 +994,13 @@ struct command command_tab[] = { | |||
1007 | NULL, open_handler, NULL, | 994 | NULL, open_handler, NULL, |
1008 | { { "FILE", GDBM_ARG_STRING }, { NULL } }, | 995 | { { "FILE", GDBM_ARG_STRING }, { NULL } }, |
1009 | N_("open new database") }, | 996 | N_("open new database") }, |
997 | #ifdef WITH_READLINE | ||
998 | { S(history), T_CMD, | ||
999 | input_history_begin, input_history_handler, NULL, | ||
1000 | { { N_("[FROM]"), GDBM_ARG_STRING }, | ||
1001 | { N_("[COUNT]"), GDBM_ARG_STRING }, | ||
1002 | { NULL } }, N_("show input history") }, | ||
1003 | #endif | ||
1010 | #undef S | 1004 | #undef S |
1011 | { 0 } | 1005 | { 0 } |
1012 | }; | 1006 | }; |
@@ -1026,6 +1020,39 @@ sort_commands () | |||
1026 | sizeof (command_tab[0]), cmdcmp); | 1020 | sizeof (command_tab[0]), cmdcmp); |
1027 | } | 1021 | } |
1028 | 1022 | ||
1023 | /* Generator function for command completion. STATE lets us know whether | ||
1024 | to start from scratch; without any state (i.e. STATE == 0), then we | ||
1025 | start at the top of the list. */ | ||
1026 | char * | ||
1027 | command_generator (const char *text, int state) | ||
1028 | { | ||
1029 | const char *name; | ||
1030 | static int len; | ||
1031 | static struct command *cmd; | ||
1032 | |||
1033 | /* If this is a new word to complete, initialize now. This includes | ||
1034 | saving the length of TEXT for efficiency, and initializing the index | ||
1035 | variable to 0. */ | ||
1036 | if (!state) | ||
1037 | { | ||
1038 | cmd = command_tab; | ||
1039 | len = strlen (text); | ||
1040 | } | ||
1041 | |||
1042 | if (!cmd->name) | ||
1043 | return NULL; | ||
1044 | |||
1045 | /* Return the next name which partially matches from the command list. */ | ||
1046 | while ((name = cmd->name)) | ||
1047 | { | ||
1048 | cmd++; | ||
1049 | if (strncmp (name, text, len) == 0) | ||
1050 | return strdup (name); | ||
1051 | } | ||
1052 | |||
1053 | /* If no names matched, then return NULL. */ | ||
1054 | return NULL; | ||
1055 | } | ||
1029 | 1056 | ||
1030 | /* ? - help handler */ | 1057 | /* ? - help handler */ |
1031 | #define CMDCOLS 30 | 1058 | #define CMDCOLS 30 |
@@ -1174,7 +1201,7 @@ gdbmarg_kvpair (struct kvpair *kvp, struct locus *loc) | |||
1174 | } | 1201 | } |
1175 | 1202 | ||
1176 | struct slist * | 1203 | struct slist * |
1177 | slist_new (char *s) | 1204 | slist_new_s (char *s) |
1178 | { | 1205 | { |
1179 | struct slist *lp = emalloc (sizeof (*lp)); | 1206 | struct slist *lp = emalloc (sizeof (*lp)); |
1180 | lp->next = NULL; | 1207 | lp->next = NULL; |
@@ -1182,6 +1209,21 @@ slist_new (char *s) | |||
1182 | return lp; | 1209 | return lp; |
1183 | } | 1210 | } |
1184 | 1211 | ||
1212 | struct slist * | ||
1213 | slist_new (char const *s) | ||
1214 | { | ||
1215 | return slist_new_s (estrdup (s)); | ||
1216 | } | ||
1217 | |||
1218 | struct slist * | ||
1219 | slist_new_l (char const *s, size_t l) | ||
1220 | { | ||
1221 | char *copy = emalloc (l + 1); | ||
1222 | memcpy (copy, s, l); | ||
1223 | copy[l] = 0; | ||
1224 | return slist_new_s (copy); | ||
1225 | } | ||
1226 | |||
1185 | void | 1227 | void |
1186 | slist_free (struct slist *lp) | 1228 | slist_free (struct slist *lp) |
1187 | { | 1229 | { |
@@ -1193,6 +1235,21 @@ slist_free (struct slist *lp) | |||
1193 | lp = next; | 1235 | lp = next; |
1194 | } | 1236 | } |
1195 | } | 1237 | } |
1238 | |||
1239 | void | ||
1240 | slist_insert (struct slist **where, struct slist *what) | ||
1241 | { | ||
1242 | if (*where) | ||
1243 | { | ||
1244 | while (what->next) | ||
1245 | what = what->next; | ||
1246 | what->next = (*where)->next; | ||
1247 | (*where)->next = what; | ||
1248 | } | ||
1249 | else | ||
1250 | what->next = NULL; | ||
1251 | *where = what; | ||
1252 | } | ||
1196 | 1253 | ||
1197 | struct kvpair * | 1254 | struct kvpair * |
1198 | kvpair_string (struct locus *loc, char *val) | 1255 | kvpair_string (struct locus *loc, char *val) |
@@ -1216,7 +1273,6 @@ kvpair_list (struct locus *loc, struct slist *s) | |||
1216 | return p; | 1273 | return p; |
1217 | } | 1274 | } |
1218 | 1275 | ||
1219 | |||
1220 | static void | 1276 | static void |
1221 | kvlist_free (struct kvpair *kvp) | 1277 | kvlist_free (struct kvpair *kvp) |
1222 | { | 1278 | { |
@@ -1534,6 +1590,7 @@ main (int argc, char *argv[]) | |||
1534 | int opt; | 1590 | int opt; |
1535 | int bv; | 1591 | int bv; |
1536 | int norc = 0; | 1592 | int norc = 0; |
1593 | int res; | ||
1537 | char *source = "-"; | 1594 | char *source = "-"; |
1538 | 1595 | ||
1539 | set_progname (argv[0]); | 1596 | set_progname (argv[0]); |
@@ -1545,15 +1602,18 @@ main (int argc, char *argv[]) | |||
1545 | textdomain (PACKAGE); | 1602 | textdomain (PACKAGE); |
1546 | 1603 | ||
1547 | sort_commands (); | 1604 | sort_commands (); |
1548 | 1605 | ||
1549 | /* Initialize variables. */ | 1606 | /* Initialize variables. */ |
1550 | intr = isatty (0); | 1607 | intr = isatty (0); |
1608 | interactive = intr; /* Used early by input_init */ | ||
1551 | dsdef[DS_KEY] = dsegm_new_field (datadef_lookup ("string"), NULL, 1); | 1609 | dsdef[DS_KEY] = dsegm_new_field (datadef_lookup ("st |