bc(1): Add libedit support.
authorSascha Wildner <saw@online.de>
Mon, 23 Jul 2012 17:23:55 +0000 (19:23 +0200)
committerSascha Wildner <saw@online.de>
Mon, 23 Jul 2012 17:30:58 +0000 (19:30 +0200)
Reported-by: Pierre Abbat <phma@phma.optus.nu>
Taken-from:  FreeBSD

usr.bin/bc/Makefile
usr.bin/bc/bc.y
usr.bin/bc/extern.h
usr.bin/bc/scan.l

index 7ea6bb3..5caf951 100644 (file)
@@ -1,11 +1,13 @@
 #      $OpenBSD: Makefile,v 1.2 2003/11/03 19:51:42 otto Exp $
-#      $DragonFly: src/usr.bin/bc/Makefile,v 1.4 2007/08/27 16:50:51 pavalos Exp $
 
 PROG=          bc
 SRCS=          bc.y scan.l y.tab.h
 CFLAGS+=       -I. -I${.CURDIR}
 WARNS?=                2
 
+DPADD=         ${LIBEDIT} ${LIBTERMCAP}
+LDADD=         -ledit -ltermcap
+
 SCRIPTS=       bc.library
 SCRIPTSMODE=   444
 SCRIPTSDIR=    /usr/share/misc
index 1f25152..f129a70 100644 (file)
@@ -1,7 +1,6 @@
 %{
 /*
  * $OpenBSD: bc.y,v 1.32 2006/05/18 05:49:53 otto Exp $
- * $DragonFly: src/usr.bin/bc/bc.y,v 1.3 2007/09/01 18:42:08 pavalos Exp $
  */
 
 /*
@@ -39,6 +38,7 @@
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
+#include <histedit.h>
 #include <limits.h>
 #include <search.h>
 #include <signal.h>
@@ -1076,6 +1076,12 @@ sigchld(int signo)
        }
 }
 
+static const char *
+dummy_prompt(void)
+{
+       return ("");
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -1141,6 +1147,16 @@ main(int argc, char *argv[])
                        err(1, "cannot find dc");
                }
        }
+       if (interactive) {
+               el = el_init("bc", stdin, stderr, stderr);
+               hist = history_init();
+               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_PROMPT, dummy_prompt);
+               el_source(el, NULL);
+       }
        yywrap();
        return yyparse();
 }
index 0ba989b..888d0ff 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * $OpenBSD: extern.h,v 1.6 2006/03/18 20:44:43 otto Exp $
- * $DragonFly: src/usr.bin/bc/extern.h,v 1.3 2007/09/01 18:42:08 pavalos Exp $
  */
 
 /*
@@ -39,4 +38,7 @@ extern int    sargc;
 extern char    **sargv;
 extern char    *filename;
 extern char    *cmdexpr;
-bool           interactive;
+extern bool     interactive;
+extern EditLine        *el;
+extern History *hist;
+extern HistEvent he;
index 5bc1a17..15c84e0 100644 (file)
@@ -1,7 +1,6 @@
 %{
 /*
  * $OpenBSD: scan.l,v 1.21 2006/03/18 20:44:43 otto Exp $
- * $DragonFly: src/usr.bin/bc/scan.l,v 1.3 2007/09/01 18:42:08 pavalos Exp $
  */
 
 /*
@@ -22,6 +21,7 @@
 
 #include <err.h>
 #include <errno.h>
+#include <histedit.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <string.h>
 int            lineno;
 bool           interactive;
 
+HistEvent       he;
+EditLine       *el;
+History                *hist;
+
 static char    *strbuf = NULL;
 static size_t  strbuf_sz = 1;
 static bool    dot_seen;
 
 static void    init_strbuf(void);
 static void    add_str(const char *);
+static int     bc_yyinput(char *, int);
+
+#undef YY_INPUT
+#define YY_INPUT(buf,retval,max) \
+       (retval = bc_yyinput(buf, max))
 
 %}
 
@@ -285,3 +294,31 @@ yywrap(void)
        }
        return (1);
 }
+
+static int
+bc_yyinput(char *buf, int maxlen)
+{
+       int num;
+       if (yyin == stdin && interactive) {
+               const char *bp;
+
+               if ((bp = el_gets(el, &num)) == NULL || num == 0)
+                       return (0);
+               if (num > maxlen) {
+                       el_push(el, (char *)(uintptr_t)(bp) + maxlen);
+                       num = maxlen;
+               }
+               memcpy(buf, bp, num);
+               history(hist, &he, H_ENTER, bp);
+       } else {
+               int c = '*';
+               for (num = 0; num < maxlen &&
+                   (c = getc(yyin)) != EOF && c != '\n'; ++num)
+                       buf[num] = (char) c;
+               if (c == '\n')
+                       buf[num++] = (char) c;
+               if (c == EOF && ferror(yyin))
+                       YY_FATAL_ERROR( "input in flex scanner failed" );
+       }
+       return (num);
+}