On Thu, May 26, 2011 at 07:02:55AM +0200, Otto Moerbeek wrote:

> Hi,
> 
> adding editline caused a regrssion in the handling of ^C.
> 
> Originally (and I mean the days of AT&T) bc used ^C as an abort line.
> With editline, while appearing to work, the characters typed so far
> remain in the input buffer. Try this: 1+^C2<enter>
> 
> Editline has no signal safe facility to accomodate that. So switch it
> off (you can use ^U anyway). 
> 
> Also, honour the "edit off" command from .editrc or interactively. In
> that case ^C works as before. 

Actually, after some more study I concluded that the non-wide chars
code is safe. We don;t support wide chars editline now, and certainly
will not in bc(1). So this should fare better, and have correct ^C
handling both in editline mode and non-editline mode.

        -Otto

Index: bc.y
===================================================================
RCS file: /cvs/src/usr.bin/bc/bc.y,v
retrieving revision 1.34
diff -u -p -r1.34 bc.y
--- bc.y        7 Mar 2011 08:11:15 -0000       1.34
+++ bc.y        26 May 2011 15:54:39 -0000
@@ -1143,7 +1143,7 @@ main(int argc, char *argv[])
                                history(hist, &he, H_SETSIZE, 100);
                                el_set(el, EL_HIST, history, hist);
                                el_set(el, EL_EDITOR, "emacs");
-                               el_set(el, EL_SIGNAL, 1);
+                               el_set(el, EL_SIGNAL, 0);
                                el_set(el, EL_PROMPT, dummy_prompt);
                                el_source(el, NULL);
                        }
Index: scan.l
===================================================================
RCS file: /cvs/src/usr.bin/bc/scan.l,v
retrieving revision 1.24
diff -u -p -r1.24 scan.l
--- scan.l      7 Mar 2011 08:11:15 -0000       1.24
+++ scan.l      26 May 2011 15:54:39 -0000
@@ -38,6 +38,8 @@ History               *hist;
 static char    *strbuf = NULL;
 static size_t  strbuf_sz = 1;
 static bool    dot_seen;
+static int     use_el;
+static volatile sig_atomic_t skipchars;
 
 static void    init_strbuf(void);
 static void    add_str(const char *);
@@ -236,12 +238,18 @@ add_str(const char *str)
 void
 abort_line(int sig)
 {
-       static const char str[] = "[\n]P\n";
+       static const char str1[] = "[\n]P\n";
+       static const char str2[] = "[^C\n]P\n";
        int save_errno;
+       const LineInfo *info;
 
        save_errno = errno;
-       YY_FLUSH_BUFFER;        /* XXX signal race? */
-       write(STDOUT_FILENO, str, sizeof(str) - 1);
+       if (use_el) {
+               write(STDOUT_FILENO, str2, sizeof(str2) - 1);
+               info = el_line(el);
+               skipchars = info->lastchar - info->buffer;
+       } else
+               write(STDOUT_FILENO, str1, sizeof(str1) - 1);
        errno = save_errno;
 }
 
@@ -295,17 +303,32 @@ static int
 bc_yyinput(char *buf, int maxlen)
 {
        int num;
-       if (yyin == stdin && interactive) {
+
+       if (el != NULL)
+               el_get(el, EL_EDITMODE, &use_el);
+               
+       if (yyin == stdin && interactive && use_el) {
                const char *bp;
+               sigset_t oset, nset;
 
                if ((bp = el_gets(el, &num)) == NULL || num == 0)
                        return (0);
+               sigemptyset(&nset);
+               sigaddset(&nset, SIGINT);
+               sigprocmask(SIG_BLOCK, &nset, &oset);
+               if (skipchars < num) {
+                       bp += skipchars;
+                       num -= skipchars;
+               }
+               skipchars = 0;
+               sigprocmask(SIG_SETMASK, &oset, NULL);
                if (num > maxlen) {
                        el_push(el, (char *)(void *)bp + maxlen);
                        num = maxlen;
                }
                memcpy(buf, bp, num);
                history(hist, &he, H_ENTER, bp);
+               el_get(el, EL_EDITMODE, &use_el);
        } else {
                int c = '*';
                for (num = 0; num < maxlen &&

Reply via email to