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/lex.l | |
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/lex.l')
-rw-r--r-- | src/lex.l | 130 |
1 files changed, 78 insertions, 52 deletions
@@ -46,7 +46,7 @@ advance_line () #define YY_INPUT(buf,result,max_size) \ do \ { \ - result = read_input (buf, max_size); \ + result = input_read (yyin, buf, max_size); \ } \ while (0); @@ -56,8 +56,6 @@ void string_addc (int c); char *string_end (void); int unescape (int c); -static ssize_t read_input (char *buf, size_t size); - struct context /* Input context */ { struct context *parent; /* Pointer to the parent context */ @@ -315,18 +313,16 @@ end_def (void) BEGIN (INITIAL); } -static ssize_t -read_input (char *buf, size_t size) -{ - if (interactive) +void +print_prompt_at_bol (void) { if (YY_AT_BOL ()) - print_prompt (); - if (fgets (buf, size, yyin) == NULL) - return 0; - return strlen (buf); + { + char *s = make_prompt (); + fputs (s, stdout); + fflush (stdout); + free (s); } - return fread (buf, 1, size, yyin); } @@ -453,44 +449,40 @@ lerror (struct locus *loc, const char *fmt, ...) } -struct prompt_exp; - -void -pe_file_name (struct prompt_exp *p) +static struct slist * +pe_file_name (void) { - if (file_name) - fwrite (file_name, strlen (file_name), 1, stdout); + return file_name ? slist_new (file_name) : NULL; } -void -pe_program_name (struct prompt_exp *p) +static struct slist * +pe_program_name (void) { - fwrite (progname, strlen (progname), 1, stdout); + return slist_new (progname); } -void -pe_package_name (struct prompt_exp *p) +static struct slist * +pe_package_name (void) { - fwrite (PACKAGE_NAME, sizeof (PACKAGE_NAME) - 1, 1, stdout); + return slist_new (PACKAGE_NAME); } -void -pe_program_version (struct prompt_exp *p) +static struct slist * +pe_program_version (void) { - fwrite (PACKAGE_VERSION, sizeof (PACKAGE_VERSION) - 1, 1, stdout); + return slist_new (PACKAGE_VERSION); } -void -pe_space (struct prompt_exp *p) +static struct slist * +pe_space (void) { - fwrite (" ", 1, 1, stdout); + return slist_new (" "); } struct prompt_exp { int ch; - void (*fun) (struct prompt_exp *); - char *cache; + struct slist *(*fun) (void); }; struct prompt_exp prompt_exp[] = { @@ -502,8 +494,8 @@ struct prompt_exp prompt_exp[] = { { 0 } }; -static void -expand_char (int c) +static int +expand_char (int c, struct slist **tailp) { struct prompt_exp *p; @@ -513,30 +505,32 @@ expand_char (int c) { if (c == p->ch) { - if (p->cache) - free (p->cache); - p->fun (p); - return; + struct slist *s = p->fun (); + if (s) + slist_insert (tailp, s); + return 0; } } } - putchar ('%'); - putchar (c); + return 1; } char const * -psname () +psname (void) { if (YYSTATE == DEF || YYSTATE == MLSTR) return "ps2"; return "ps1"; } -void -print_prompt () +char * +make_prompt (void) { const char *s; const char *prompt; + struct slist *head = NULL, *tail = NULL, *p; + char *ret, *end; + size_t len; switch (variable_get (psname (), VART_STRING, (void *) &prompt)) { @@ -544,27 +538,59 @@ print_prompt () break; case VAR_ERR_NOTSET: - return; + return NULL; default: abort (); } - for (s = prompt; *s; s++) + for (s = prompt; *s; ) { - if (*s == '%') + if (*s == '%' && s[1]) { - if (!*++s) + if (s > prompt) { - putchar ('%'); - break; + slist_insert (&tail, slist_new_l (prompt, s - prompt)); + if (!head) + head = tail; + } + if (expand_char (s[1], &tail) == 0) + { + if (!head) + head = tail; + prompt = s + 2; } - expand_char (*s); + else + prompt = s; + s += 2; } else - putchar (*s); + ++s; } - fflush (stdout); + if (s > prompt) + { + slist_insert (&tail, slist_new_l (prompt, s - prompt)); + if (!head) + head = tail; + } + + len = 0; + for (p = head; p; p = p->next) + len += strlen (p->str); + + ret = emalloc (len + 1); + end = ret; + for (p = head; p; p = p->next) + { + s = p->str; + while (*s) + *end++ = *s++; + } + *end = 0; + + slist_free (head); + + return ret; } |