aboutsummaryrefslogtreecommitdiff
path: root/src/lex.l
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/lex.l
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/lex.l')
-rw-r--r--src/lex.l134
1 files changed, 80 insertions, 54 deletions
diff --git a/src/lex.l b/src/lex.l
index 9c2c5f8..236474d 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -43,24 +43,22 @@ advance_line ()
43 while (0); 43 while (0);
44 44
45#undef YY_INPUT 45#undef YY_INPUT
46#define YY_INPUT(buf,result,max_size) \ 46#define YY_INPUT(buf,result,max_size) \
47 do \ 47 do \
48 { \ 48 { \
49 result = read_input (buf, max_size); \ 49 result = input_read (yyin, buf, max_size); \
50 } \ 50 } \
51 while (0); 51 while (0);
52 52
53void string_begin (void); 53void string_begin (void);
54void string_add (const char *s, int l); 54void string_add (const char *s, int l);
55void string_addc (int c); 55void string_addc (int c);
56char *string_end (void); 56char *string_end (void);
57int unescape (int c); 57int unescape (int c);
58 58
59static ssize_t read_input (char *buf, size_t size);
60
61struct context /* Input context */ 59struct context /* Input context */
62{ 60{
63 struct context *parent; /* Pointer to the parent context */ 61 struct context *parent; /* Pointer to the parent context */
64 struct locus locus; /* Locus */ 62 struct locus locus; /* Locus */
65 struct point point; 63 struct point point;
66 int interactive; 64 int interactive;
@@ -312,24 +310,22 @@ begin_def (void)
312void 310void
313end_def (void) 311end_def (void)
314{ 312{
315 BEGIN (INITIAL); 313 BEGIN (INITIAL);
316} 314}
317 315
318static ssize_t 316void
319read_input (char *buf, size_t size) 317print_prompt_at_bol (void)
320{ 318{
321 if (interactive) 319 if (YY_AT_BOL ())
322 { 320 {
323 if (YY_AT_BOL ()) 321 char *s = make_prompt ();
324 print_prompt (); 322 fputs (s, stdout);
325 if (fgets (buf, size, yyin) == NULL) 323 fflush (stdout);
326 return 0; 324 free (s);
327 return strlen (buf);
328 } 325 }
329 return fread (buf, 1, size, yyin);
330} 326}
331 327
332 328
333struct strseg 329struct strseg
334{ 330{
335 struct strseg *next; 331 struct strseg *next;
@@ -450,121 +446,151 @@ lerror (struct locus *loc, const char *fmt, ...)
450 va_start (ap, fmt); 446 va_start (ap, fmt);
451 vlerror (loc, fmt, ap); 447 vlerror (loc, fmt, ap);
452 va_end (ap); 448 va_end (ap);
453} 449}
454 450
455 451
456struct prompt_exp; 452static struct slist *
457 453pe_file_name (void)
458void
459pe_file_name (struct prompt_exp *p)
460{ 454{
461 if (file_name) 455 return file_name ? slist_new (file_name) : NULL;
462 fwrite (file_name, strlen (file_name), 1, stdout);
463} 456}
464 457
465void 458static struct slist *
466pe_program_name (struct prompt_exp *p) 459pe_program_name (void)
467{ 460{
468 fwrite (progname, strlen (progname), 1, stdout); 461 return slist_new (progname);
469} 462}
470 463
471void 464static struct slist *
472pe_package_name (struct prompt_exp *p) 465pe_package_name (void)
473{ 466{
474 fwrite (PACKAGE_NAME, sizeof (PACKAGE_NAME) - 1, 1, stdout); 467 return slist_new (PACKAGE_NAME);
475} 468}
476 469
477void 470static struct slist *
478pe_program_version (struct prompt_exp *p) 471pe_program_version (void)
479{ 472{
480 fwrite (PACKAGE_VERSION, sizeof (PACKAGE_VERSION) - 1, 1, stdout); 473 return slist_new (PACKAGE_VERSION);
481} 474}
482 475
483void 476static struct slist *
484pe_space (struct prompt_exp *p) 477pe_space (void)
485{ 478{
486 fwrite (" ", 1, 1, stdout); 479 return slist_new (" ");
487} 480}
488 481
489struct prompt_exp 482struct prompt_exp
490{ 483{
491 int ch; 484 int ch;
492 void (*fun) (struct prompt_exp *); 485 struct slist *(*fun) (void);
493 char *cache;
494}; 486};
495 487
496struct prompt_exp prompt_exp[] = { 488struct prompt_exp prompt_exp[] = {
497 { 'f', pe_file_name }, 489 { 'f', pe_file_name },
498 { 'p', pe_program_name }, 490 { 'p', pe_program_name },
499 { 'P', pe_package_name }, 491 { 'P', pe_package_name },
500 { 'v', pe_program_version }, 492 { 'v', pe_program_version },
501 { '_', pe_space }, 493 { '_', pe_space },
502 { 0 } 494 { 0 }
503}; 495};
504 496
505static void 497static int
506expand_char (int c) 498expand_char (int c, struct slist **tailp)
507{ 499{
508 struct prompt_exp *p; 500 struct prompt_exp *p;
509 501
510 if (c && c != '%') 502 if (c && c != '%')
511 { 503 {
512 for (p = prompt_exp; p->ch; p++) 504 for (p = prompt_exp; p->ch; p++)
513 { 505 {
514 if (c == p->ch) 506 if (c == p->ch)
515 { 507 {
516 if (p->cache) 508 struct slist *s = p->fun ();
517 free (p->cache); 509 if (s)
518 p->fun (p); 510 slist_insert (tailp, s);
519 return; 511 return 0;
520 } 512 }
521 } 513 }
522 } 514 }
523 putchar ('%'); 515 return 1;
524 putchar (c);
525} 516}
526 517
527char const * 518char const *
528psname () 519psname (void)
529{ 520{
530 if (YYSTATE == DEF || YYSTATE == MLSTR) 521 if (YYSTATE == DEF || YYSTATE == MLSTR)
531 return "ps2"; 522 return "ps2";
532 return "ps1"; 523 return "ps1";
533} 524}
534 525
535void 526char *
536print_prompt () 527make_prompt (void)
537{ 528{
538 const char *s; 529 const char *s;
539 const char *prompt; 530 const char *prompt;
540 531 struct slist *head = NULL, *tail = NULL, *p;
532 char *ret, *end;
533 size_t len;
534
541 switch (variable_get (psname (), VART_STRING, (void *) &prompt)) 535 switch (variable_get (psname (), VART_STRING, (void *) &prompt))
542 { 536 {
543 case VAR_OK: 537 case VAR_OK:
544 break; 538 break;
545 539
546 case VAR_ERR_NOTSET: 540 case VAR_ERR_NOTSET:
547 return; 541 return NULL;
548 542
549 default: 543 default:
550 abort (); 544 abort ();
551 } 545 }
552 546
553 for (s = prompt; *s; s++) 547 for (s = prompt; *s; )
554 { 548 {
555 if (*s == '%') 549 if (*s == '%' && s[1])
556 { 550 {
557 if (!*++s) 551 if (s > prompt)
552 {
553 slist_insert (&tail, slist_new_l (prompt, s - prompt));
554 if (!head)
555 head = tail;
556 }
557 if (expand_char (s[1], &tail) == 0)
558