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
This commit is contained in:
Xin LI 2010-02-04 18:43:05 +00:00
parent a505d4352f
commit 4218135bf7
4 changed files with 65 additions and 1 deletions

View File

@ -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

View File

@ -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]);

View File

@ -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;

View File

@ -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);
}