NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Re: lib/48957 libedit/readline.c prompt bug



The following reply was made to PR lib/48957; it has been noted by GNATS.

From: "Simon J. Gerraty" <sjg%juniper.net@localhost>
To: Christos Zoulas <christos%zoulas.com@localhost>
Cc: <sjg%juniper.net@localhost>, <gnats-bugs%NetBSD.org@localhost>
Subject: Re: Re: lib/48957 libedit/readline.c prompt bug
Date: Thu, 7 Dec 2017 18:03:30 -0800

 Christos Zoulas <christos%zoulas.com@localhost> wrote:
 > The caller is supposed to deal with input inside rl_linefunc according
 > to this:
 > 
 > https://
 
 Sorry stupid IT filter renders the url useless ;-)
  
 > ...since the prompt gets printed before the read_char returns.
 > 
 > Do you have code that reproduces the different behavior between readline
 > and libedit? Because my example does not do it.
 
 Using straight readline isn't a problem, its code using the callback
 dance.
 
 Below is a simple test app, that captures the essence of what Python's
 readline extension does (started from cpp output from that ;-)
 
 When linked with real readline Python behaves ok.
 With libedit/readline it looks like:
 
 Python 2.7.8 (default, Dec  6 2017, 13:52:53)
 [GCC 4.2.1 Compatible Juniper Clang 3.7.1
 (git%psd-tools-git01.juniper.net@localhost:tool on junos
 Type "help", "copyright", "credits" or "license" for more information.
 
 >>> print 'hi'
 >>> hi
 print 'there'
 >>> there
 ^D
 
 which is broken.
 I added the original copyright back to keep our lawyers happy ;-)
 
 /*
  * This test case is derrived from pre-processed output of
  * python's readline extension - expecting to use gnu readline
  * so we keep the original copyright...
  * I have removed all the Py* and anything else that wasn't necessary
  * to reproduce the prompt bug (prompt being issued before
  * call_readline returns)
  * with libedit/readline as currently in NetBSD and FreeBSD we see:
  *
  * >>> print 'hi'
  * >>> hi
  * print 'there'
  * >>> there
  *
  * rather than:
  *
  * >>> print 'hi'
  * hi
  * >>> print 'there'
  * there
  * >>>
  */
 /* This module makes GNU readline available to Python.  It has ideas
  * contributed by Lee Busby, LLNL, and William Magro, Cornell Theory
  * Center.  The completer interface was inspired by Lele Gaifax.  More
  * recently, it was largely rewritten by Guido van Rossum.
  */
 
 #include <sys/select.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <edit/readline/readline.h>
 #include <edit/readline/history.h>
 
 static char *completer_word_break_characters;
 
 static int _history_length = -1;
 
 static void
 setup_readline(void)
 {
     using_history();
 
     rl_readline_name = "python";
 
     rl_bind_key('\t', rl_insert);
 
     rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
     rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
 
     completer_word_break_characters =
         rl_completer_word_break_characters =
         strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?");
 
         rl_initialize();
 }
 
 
 static char *completed_input_string;
 static void
 rlhandler(char *text)
 {
     completed_input_string = text;
     rl_callback_handler_remove();
 }
 
 static char *
 readline_until_enter_or_signal(char *prompt, int *signal)
 {
     char * not_done_reading = "";
     fd_set selectset;
 
     *signal = 0;
 
     rl_callback_handler_install (prompt, rlhandler);
     FD_ZERO(&selectset);
 
     completed_input_string = not_done_reading;
 
     while (completed_input_string == not_done_reading) {
         int has_input = 0;
 
         while (!has_input)
         { struct timeval timeout = {0, 100000};
 
 
 	    FD_SET(0, &selectset);
             has_input = select(2, &selectset, NULL, NULL, &timeout);
         }
 
         if(has_input > 0) {
             rl_callback_read_char();
         }
     }
 
     return completed_input_string;
 }
 
 static char *
 call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
 {
     static int once;
     size_t n;
     char *p, *q;
     int signal;
     HIST_ENTRY *he;
 
 
     if (sys_stdin != rl_instream || sys_stdout != rl_outstream) {
         rl_instream = sys_stdin;
         rl_outstream = sys_stdout;
 
         rl_prep_terminal (1);
 
     }
 
 
     p = readline_until_enter_or_signal(prompt, &signal);
 
 
     if (signal) {
         return ((void *)0);
     }
 
 
     if (p == ((void *)0)) {
         return p;
     }
 
 
     n = strlen(p);
     return p;
 }
 
 
 
 int
 main(int argc, char *argv[])
 {
     char *cp;
     setup_readline();    
     while ((cp = call_readline(stdin, stdout, ">>> "))) {
 	printf("read: '%s'\n", cp);
     }
     return 0;
 }
 


Home | Main Index | Thread Index | Old Index