summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2010-02-04 18:43:05 +0000
committerdelphij <delphij@FreeBSD.org>2010-02-04 18:43:05 +0000
commit314d37171eeeaf59a5b31a334f60c81fe2e6745c (patch)
tree922142fb6348e5d6c63fc34056e3e1e85129a988
parent4650055e248bb24fa28802c303a9d9af06e02256 (diff)
downloadFreeBSD-src-314d37171eeeaf59a5b31a334f60c81fe2e6745c.zip
FreeBSD-src-314d37171eeeaf59a5b31a334f60c81fe2e6745c.tar.gz
Use libedit when interacting with tty, which provided history
functionality, etc. as did by GNU bc. This also fixes an issue where BSDL bc can not handle very long line. Reported by: imp Reviewed by: imp
-rw-r--r--usr.bin/bc/Makefile3
-rw-r--r--usr.bin/bc/bc.y18
-rw-r--r--usr.bin/bc/extern.h6
-rw-r--r--usr.bin/bc/scan.l39
4 files changed, 65 insertions, 1 deletions
diff --git a/usr.bin/bc/Makefile b/usr.bin/bc/Makefile
index 17514ca..55f465d 100644
--- a/usr.bin/bc/Makefile
+++ b/usr.bin/bc/Makefile
@@ -5,6 +5,9 @@ PROG= bc
SRCS= bc.y scan.l
CFLAGS+= -I. -I${.CURDIR}
+DPADD= ${LIBEDIT} ${LIBTERMCAP}
+LDADD= -ledit -ltermcap
+
FILES+= bc.library
FILESDIR=${SHAREDIR}/misc
diff --git a/usr.bin/bc/bc.y b/usr.bin/bc/bc.y
index b00d140..b00d5ac 100644
--- a/usr.bin/bc/bc.y
+++ b/usr.bin/bc/bc.y
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <getopt.h>
+#include <histedit.h>
#include <limits.h>
#include <search.h>
#include <signal.h>
@@ -1106,6 +1107,13 @@ sigchld(int signo)
}
}
+static const char *
+dummy_prompt(void)
+{
+
+ return ("");
+}
+
int
main(int argc, char *argv[])
{
@@ -1173,6 +1181,16 @@ main(int argc, char *argv[])
dup(p[1]);
close(p[0]);
close(p[1]);
+ 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);
+ }
} else {
close(STDIN_FILENO);
dup(p[0]);
diff --git a/usr.bin/bc/extern.h b/usr.bin/bc/extern.h
index a99c46c..d1e9fe8 100644
--- a/usr.bin/bc/extern.h
+++ b/usr.bin/bc/extern.h
@@ -35,4 +35,8 @@ extern int sargc;
extern const char **sargv;
extern const char *filename;
extern char *cmdexpr;
-bool interactive;
+extern bool interactive;
+extern EditLine *el;
+extern History *hist;
+extern HistEvent he;
+
diff --git a/usr.bin/bc/scan.l b/usr.bin/bc/scan.l
index 81dd862..40f8ae6 100644
--- a/usr.bin/bc/scan.l
+++ b/usr.bin/bc/scan.l
@@ -22,6 +22,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
+#include <histedit.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
@@ -33,13 +34,22 @@ __FBSDID("$FreeBSD$");
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))
%}
%option always-interactive
@@ -286,3 +296,32 @@ yywrap(void)
}
return (1);
}
+
+static int
+bc_yyinput(char *buf, int maxlen)
+{
+ int num;
+ if (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);
+}
+
OpenPOWER on IntegriCloud