Control: tags -1 + patch

This is caused by a non-printable character (meant to be interpreted by
the terminal) stuffed in the prompt string given to GNU readline.

It should have been enclosed in RL_PROMPT_START_IGNORE/RL_PROMPT_END_IGNORE
pairs.  "fix-readline-related-bug.patch" does that.  It is a Scheme-only
fix, but it's not ideal because it hardcodes libreadline constants.
Ideally, "Iedline.scm" would get eval-ed in an environment where C code
has made the constants (from <readline/readline.h>) available.  This way
the constants are not hardcoded in the source code and the Scheme
namespace is not polluted with implementation details.  Alas, I could
not figure out how to try-load some Scheme code from C with a prepared
environment.

While reading some of the code I found what *might* be 2 other
(unrelated) bugs.  See "add-missing-edit-line-feature.patch" and
"fix-argument-imm-being-ignored-in-m_letstar1.patch".

Cheers.
Description: Fix readline-related bug
 Non-printable character (meant to be interpreted by the terminal) in the
 prompt string was not enclosed in RL_PROMPT_START_IGNORE/RL_PROMPT_END_IGNORE
 pairs, resulting in improper behaviour by GNU readline.
 .
 This is a Scheme-only fix, but it's not ideal because it hardcodes
 libreadline constants.  Ideally, "Iedline.scm" would get eval-ed in an
 environment where C code has made the constants (from <readline/readline.h>)
 available.  This way the constants are not hardcoded in the source code and
 the Scheme namespace is not polluted with implementation details.
Author: astian <ast...@elude.in>
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=831017
Forwarded: no
Last-Update: 2018-03-03

--- scm-5f2.orig/Iedline.scm
+++ scm-5f2/Iedline.scm
@@ -23,7 +23,17 @@
 ;; lines, i.e. lines unterminated by a newline.
 
 (define (make-edited-line-port)
-  (let ((prompt "")
+  (let  ; The prompt string we receive.
+       ((prompt "")
+	; Hack to make readline overwrite the prompt we manually write.
+	; Notice that #\cr is being wrapped in #\soh and #\stx, respectively
+	; RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE (defined in
+	; <readline/readline.h>), to signal to readline that #\cr is
+	; invisible.
+	(prompt-hack (string #\soh #\cr #\stx))
+	; Concatenation of "prompt-hack" and "prompt", this is the actual
+	; prompt we send to readline.
+	(prompt-real "")
 	(outp (default-output-port))
 	(inp (default-input-port))
 	(strp (call-with-input-string "" identity)))
@@ -31,18 +41,40 @@
      (vector (lambda (c)
 	       (write-char c outp))
 	     (lambda (s)
+	       ; Reverse-engineered assumption: string-write to this port will
+	       ; only be done in the following cases:
+	       ;
+	       ;   - Empty string.
+	       ;
+	       ;   - Printing repl results, in which case the string will
+	       ;     always come linefeed-terminated.
+	       ;
+	       ;   - Prompt printing, which will never be linefeed-terminated.
+	       ;     The prompt string is immediately printed (manually),
+	       ;     later, when GNU readline is called, a carriage return
+	       ;     prepended to the same prompt string will cause it to
+	       ;     write its prompt on top of the one we printed ourselves
+	       ;     (therefore only one instance of the prompt string is
+	       ;     actually visible to the interactive user).  Presumably
+	       ;     this is the result of kluging optional readline support
+	       ;     on top of an existing prompting mechanism.
+	       ;
+	       ; -- astian
 	       (display s outp)
 	       (or (zero? (string-length s))
 		   (eq? #\newline (string-ref s (- (string-length s) 1)))
 		   (begin
-		     (set! prompt (string-append "\r" s))
-		     (force-output outp))))
+		     (or (string=? s prompt)
+			 (begin
+			   (set! prompt s)
+			   (set! prompt-real (string-append prompt-hack prompt)))))
+		     (force-output outp)))
 	     (lambda ()
 	       (force-output outp))
 	     (lambda ()
 	       (let tail ((c (read-char strp)))
 		 (if (char? c) c
-		     (let ((str (read-edited-line prompt)))
+		     (let ((str (read-edited-line prompt-real)))
 		       (if (string? str)
 			   (let ((n (string-length str)))
 			     (add-history str)
Description: Add missing "edit-line" feature
 Don't know why it was missing.
Author: astian <ast...@elude.in>
Forwarded: no
Last-Update: 2018-03-03

--- scm-5f2.orig/edline.c
+++ scm-5f2/edline.c
@@ -65,6 +65,9 @@ void init_edline()
   make_subr(s_def_outport, tc7_subr_0, def_outport);
   make_subr(s_readline, tc7_subr_1, lreadline);
   make_subr(s_add_history, tc7_subr_1, ladd_history);
+
+  add_feature("edit-line");
+
   if (scm_ldprog(s_Iedline))
     wta(*loc_errobj, "couldn't init", s_Iedline);
 }
Description: Fix argument "imm" being ignored in "m_letstar1"
 Like "m_letrec1", "m_letstar1" is used in the implementation of various
 syntactic elements.  Like in "m_letrec1", argument "imm" in "m_letstar1"
 is supposed to indicate (methinks) what syntactic element is being
 implemented.
Author: astian <ast...@elude.in>
Forwarded: no
Last-Update: 2018-03-03

--- scm-5f2.orig/eval.c
+++ scm-5f2/eval.c
@@ -1274,6 +1274,7 @@ int scm_nullenv_p(env)
 static SCM m_letstar1(imm, vars, inits, body, env, ctxt)
      SCM imm, vars, inits, body, env, ctxt;
 {
+  SCM op = MAKSPCSYM2(IM_LETSTAR, imm);
   SCM init, bdgs = cons(env, EOL); /* initial env is for debug printing. */
   SCM *loc = &CDR(bdgs);
   while (NIMP(vars)) {
@@ -1284,7 +1285,7 @@ static SCM m_letstar1(imm, vars, inits,
     vars = CDR(vars);
     inits = CDR(inits);
   }
-  return cons2(IM_LETSTAR, bdgs, m_body(body, env, ctxt));
+  return cons2(op, bdgs, m_body(body, env, ctxt));
 }
 
 SCM m_letstar(xorig, env, ctxt)

Reply via email to