|
Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com |
From: Gabriel Linder (linder
jeuxvideo.com)
Date: Tue Aug 17 2010 - 11:11:32 CDT
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Fri, 13 Aug 2010 15:09:20 +0200
Gabriel Linder <linder
jeuxvideo.com> wrote:
> On Fri, 13 Aug 2010 14:30:50 +0200
> Otto Moerbeek <otto
drijf.net> wrote:
>
> > Take a look at freebsd. They have added editline support to bc. If
> > (big if) we're going to add command line editing and history, I'd
> > rather take that.
>
> I will take a look at their implementation then, thank you.
>
Here is a new diff with evolutions from FreeBSD added. I did keep a
single fread for real files, though.
Bonus : fixed a bug in their version when el_push'ing lines.
? test
Index: Makefile
===================================================================
RCS file: /cvs/src/usr.bin/bc/Makefile,v
retrieving revision 1.4
diff -u -r1.4 Makefile
--- Makefile 30 Jun 2006 19:02:28 -0000 1.4
+++ Makefile 17 Aug 2010 16:00:05 -0000

-5,6 +5,8 
CPPFLAGS+= -I. -I${.CURDIR}
CFLAGS+= -Wall -Wno-unused
YFLAGS+=
+LDADD= -lcurses -ledit
+DPADD= ${LIBCURSES} ${LIBEDIT}
beforeinstall:
install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/bc.library \
Index: bc.y
===================================================================
RCS file: /cvs/src/usr.bin/bc/bc.y,v
retrieving revision 1.33
diff -u -r1.33 bc.y
--- bc.y 27 Oct 2009 23:59:36 -0000 1.33
+++ bc.y 17 Aug 2010 16:00:05 -0000

-43,6 +43,7 
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+#include <histedit.h>
#include "extern.h"
#include "pathnames.h"

-1073,6 +1074,34 
}
}
+/* ARGSUSED */
+static const char *
+prompt(EditLine *el)
+{
+ return "";
+}
+
+static void
+init_editline(void)
+{
+ if (interactive) {
+ /*
+ * Our stdout will be stdin for dc, so we pass stderr as stdout.
+ */
+ if ((el = el_init(__progname, stdin, stderr, stderr)) == NULL)
+ err(1, "cannot initialise editline");
+ if ((hl = history_init()) == NULL)
+ err(1, "cannot initialise editline history");
+ history(hl, &hev, H_SETSIZE, 100);
+ el_set(el, EL_HIST, history, hl);
+ el_set(el, EL_PROMPT, prompt);
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_TERMINAL, NULL);
+ el_set(el, EL_SIGNAL, 1);
+ el_source(el, NULL);
+ }
+}
+
int
main(int argc, char *argv[])
{

-1129,6 +1158,7 
dup(p[1]);
close(p[0]);
close(p[1]);
+ init_editline();
} else {
close(STDIN_FILENO);
dup(p[0]);
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.bin/bc/extern.h,v
retrieving revision 1.6
diff -u -r1.6 extern.h
--- extern.h 18 Mar 2006 20:44:43 -0000 1.6
+++ extern.h 17 Aug 2010 16:00:05 -0000

-23,17 +23,19 
ssize_t store;
};
-int yylex(void);
-void yyerror(char *);
-void fatal(const char *);
-void abort_line(int);
+int yylex(void);
+void yyerror(char *);
+void fatal(const char *);
-extern int lineno;
-extern char *yytext;
-extern FILE *yyin;
-extern int fileindex;
-extern int sargc;
-extern char **sargv;
-extern char *filename;
-extern char *cmdexpr;
-bool interactive;
+extern int lineno;
+extern char *yytext;
+extern FILE *yyin;
+extern int fileindex;
+extern int sargc;
+extern char **sargv;
+extern char *filename;
+extern char *cmdexpr;
+extern bool interactive;
+extern EditLine *el;
+extern History *hl;
+extern HistEvent hev;
Index: scan.l
===================================================================
RCS file: /cvs/src/usr.bin/bc/scan.l,v
retrieving revision 1.23
diff -u -r1.23 scan.l
--- scan.l 27 Oct 2009 23:59:36 -0000 1.23
+++ scan.l 17 Aug 2010 16:00:05 -0000

-18,10 +18,10 
*/
#include <err.h>
-#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+#include <histedit.h>
#include "extern.h"
#include "pathnames.h"

-29,6 +29,9 
int lineno;
bool interactive;
+EditLine *el;
+History *hl;
+HistEvent hev;
static char *strbuf = NULL;
static size_t strbuf_sz = 1;

-36,6 +39,10 
static void init_strbuf(void);
static void add_str(const char *);
+static int bc_yyinput(char *, const int);
+
+#define YY_INPUT(buf, result, max_size) \
+ (result = bc_yyinput(buf, max_size))
%}

-221,19 +228,6 
strlcat(strbuf, str, strbuf_sz);
}
-/* ARGSUSED */
-void
-abort_line(int sig)
-{
- static const char str[] = "[\n]P\n";
- int save_errno;
-
- save_errno = errno;
- YY_FLUSH_BUFFER; /* XXX signal race? */
- write(STDOUT_FILENO, str, sizeof(str) - 1);
- errno = save_errno;
-}
-
int
yywrap(void)
{

-271,8 +265,6 
} else if (fileindex == sargc) {
fileindex++;
yyin = stdin;
- if (interactive)
- signal(SIGINT, abort_line);
lineno = 1;
filename = "stdin";
return (0);

-280,3 +272,45 
return (1);
}
+static int
+bc_yyinput(char *buf, const int max_size)
+{
+ /*
+ * This function is used to read both math library and user input,
+ * so we have to check for stdin before using editline even in
+ * interactive mode.
+ */
+ if (interactive && yyin == stdin) {
+ /*
+ * el_push'ed lines do not need to be added to history.
+ */
+ static bool was_pushed = false;
+ const char *line;
+ int count;
+ if ((line = el_gets(el, &count)) == NULL || count <= 0) {
+ if (count == 0) {
+ return YY_NULL;
+ }
+ err(1, "cannot read input line");
+ }
+ if (!was_pushed)
+ history(hl, &hev, H_ENTER, line);
+ else
+ was_pushed = false;
+ if (count > max_size) {
+ el_push(el, (char *)((uintptr_t)line + max_size));
+ count = max_size;
+ was_pushed = true;
+ }
+ memcpy(buf, line, count);
+ return count;
+ } else {
+ if (feof(yyin)) {
+ if (ferror(yyin)) {
+ YY_FATAL_ERROR("input in flex scanner failed");
+ }
+ return YY_NULL;
+ }
+ return fread(buf, sizeof(char), max_size, yyin);
+ }
+}
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]