aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-07-12 12:41:15 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2016-07-12 14:34:16 +0300
commit89f200b55b309aa67c1fbfc11d4de211725348f4 (patch)
tree39e2e43f29766cbebbdf61f160b5d062ea63c996 /src
parente8cad816f36b1cad11bb67c96f0ce878cf30844e (diff)
downloadgdbm-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.am12
-rw-r--r--src/gdbmtool.c102
-rw-r--r--src/gdbmtool.h31
-rw-r--r--src/gram.y7
-rw-r--r--src/input-rl.c235
-rw-r--r--src/input-std.c43
-rw-r--r--src/lex.l134
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
80bin_PROGRAMS = gdbmtool gdbm_load gdbm_dump 80bin_PROGRAMS = gdbmtool gdbm_load gdbm_dump
81 81
82gdbmtool_LDADD = ./libgdbmapp.a ./libgdbm.la 82gdbmtool_LDADD = \
83 ./libgdbmapp.a\
84 ./libgdbm.la\
85 @READLINE_LIBS@
86
83gdbmtool_SOURCES = \ 87gdbmtool_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
96if GDBM_COND_READLINE
97 gdbmtool_SOURCES += input-rl.c
98else
99 gdbmtool_SOURCES += input-std.c
100endif
101
92AM_YFLAGS = -dtv 102AM_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
332struct 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 */
342void 328void
@@ -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
894struct command 882struct 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
907struct command command_tab[] = { 894struct 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. */
1026char *
1027command_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
1176struct slist * 1203struct slist *
1177slist_new (char *s) 1204slist_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
1212struct slist *
1213slist_new (char const *s)
1214{
1215 return slist_new_s (estrdup (s));
1216}
1217
1218struct slist *
1219slist_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
1185void 1227void
1186slist_free (struct slist *lp) 1228slist_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
1239void
1240slist_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
1197struct kvpair * 1254struct kvpair *
1198kvpair_string (struct locus *loc, char *val) 1255kvpair_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
1220static void 1276static void
1221kvlist_free (struct kvpair *kvp) 1277kvlist_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