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 | 134 |
1 files changed, 80 insertions, 54 deletions
@@ -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 | ||
53 | void string_begin (void); | 53 | void string_begin (void); |
54 | void string_add (const char *s, int l); | 54 | void string_add (const char *s, int l); |
55 | void string_addc (int c); | 55 | void string_addc (int c); |
56 | char *string_end (void); | 56 | char *string_end (void); |
57 | int unescape (int c); | 57 | int unescape (int c); |
58 | 58 | ||
59 | static ssize_t read_input (char *buf, size_t size); | ||
60 | |||
61 | struct context /* Input context */ | 59 | struct 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) | |||
312 | void | 310 | void |
313 | end_def (void) | 311 | end_def (void) |
314 | { | 312 | { |
315 | BEGIN (INITIAL); | 313 | BEGIN (INITIAL); |
316 | } | 314 | } |
317 | 315 | ||
318 | static ssize_t | 316 | void |
319 | read_input (char *buf, size_t size) | 317 | print_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 | ||
333 | struct strseg | 329 | struct 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 | ||
456 | struct prompt_exp; | 452 | static struct slist * |
457 | 453 | pe_file_name (void) | |
458 | void | ||
459 | pe_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 | ||
465 | void | 458 | static struct slist * |
466 | pe_program_name (struct prompt_exp *p) | 459 | pe_program_name (void) |
467 | { | 460 | { |
468 | fwrite (progname, strlen (progname), 1, stdout); | 461 | return slist_new (progname); |
469 | } | 462 | } |
470 | 463 | ||
471 | void | 464 | static struct slist * |
472 | pe_package_name (struct prompt_exp *p) | 465 | pe_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 | ||
477 | void | 470 | static struct slist * |
478 | pe_program_version (struct prompt_exp *p) | 471 | pe_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 | ||
483 | void | 476 | static struct slist * |
484 | pe_space (struct prompt_exp *p) | 477 | pe_space (void) |
485 | { | 478 | { |
486 | fwrite (" ", 1, 1, stdout); | 479 | return slist_new (" "); |
487 | } | 480 | } |
488 | 481 | ||
489 | struct prompt_exp | 482 | struct 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 | ||
496 | struct prompt_exp prompt_exp[] = { | 488 | struct 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 | ||
505 | static void | 497 | static int |
506 | expand_char (int c) | 498 | expand_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 | ||
527 | char const * | 518 | char const * |
528 | psname () | 519 | psname (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 | ||
535 | void | 526 | char * |
536 | print_prompt () | 527 | make_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 |