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
@@ -46,7 +46,7 @@ advance_line ()
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
@@ -56,8 +56,6 @@ void 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 */
@@ -315,18 +313,16 @@ end_def (void)
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
@@ -453,44 +449,40 @@ lerror (struct locus *loc, const char *fmt, ...)
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[] = {
@@ -502,8 +494,8 @@ struct prompt_exp prompt_exp[] = {
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
@@ -513,58 +505,92 @@ expand_char (int c)
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 { 558 {
559 putchar ('%'); 559 if (!head)
560 break; 560 head = tail;
561 prompt = s + 2;
561 } 562 }
562 expand_char (*s); 563 else
564 prompt = s;
565 s += 2;
563 } 566 }
564 else 567 else
565 putchar (*s); 568 ++s;
569 }
570
571 if (s > prompt)
572 {
573 slist_insert (&tail, slist_new_l (prompt, s - prompt));
574 if (!head)
575 head = tail;
566 } 576 }
567 577
568 fflush (stdout); 578 len = 0;
579 for (p = head; p; p = p->next)
580 len += strlen (p->str);
581
582 ret = emalloc (len + 1);
583 end = ret;
584 for (p = head; p; p = p->next)
585 {
586 s = p->str;
587 while (*s)
588 *end++ = *s++;
589 }
590 *end = 0;