Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Feb 2010 18:43:05 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r203498 - head/usr.bin/bc
Message-ID:  <201002041843.o14Ih5HF098673@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Thu Feb  4 18:43:05 2010
New Revision: 203498
URL: http://svn.freebsd.org/changeset/base/203498

Log:
  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

Modified:
  head/usr.bin/bc/Makefile
  head/usr.bin/bc/bc.y
  head/usr.bin/bc/extern.h
  head/usr.bin/bc/scan.l

Modified: head/usr.bin/bc/Makefile
==============================================================================
--- head/usr.bin/bc/Makefile	Thu Feb  4 17:35:11 2010	(r203497)
+++ head/usr.bin/bc/Makefile	Thu Feb  4 18:43:05 2010	(r203498)
@@ -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
 

Modified: head/usr.bin/bc/bc.y
==============================================================================
--- head/usr.bin/bc/bc.y	Thu Feb  4 17:35:11 2010	(r203497)
+++ head/usr.bin/bc/bc.y	Thu Feb  4 18:43:05 2010	(r203498)
@@ -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]);

Modified: head/usr.bin/bc/extern.h
==============================================================================
--- head/usr.bin/bc/extern.h	Thu Feb  4 17:35:11 2010	(r203497)
+++ head/usr.bin/bc/extern.h	Thu Feb  4 18:43:05 2010	(r203498)
@@ -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;
+

Modified: head/usr.bin/bc/scan.l
==============================================================================
--- head/usr.bin/bc/scan.l	Thu Feb  4 17:35:11 2010	(r203497)
+++ head/usr.bin/bc/scan.l	Thu Feb  4 18:43:05 2010	(r203498)
@@ -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);
+}
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002041843.o14Ih5HF098673>