Added a tiny implementation of readline library, based on linenoise sources.
See https://github.com/antirez/linenoise for details. Implemented a routine atexit() in libc. Pdc modified to use readline library.
This commit is contained in:
3
src/cmd/pdc/.gitignore
vendored
Normal file
3
src/cmd/pdc/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
pdc
|
||||
y.tab.c
|
||||
y.tab.h
|
||||
@@ -8,7 +8,8 @@ OBJS = pdc.o
|
||||
LDFLAGS += -g
|
||||
|
||||
CFLAGS += -Werror -Wall -Os
|
||||
CFLAGS += -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC
|
||||
CFLAGS += -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC -DHAVE_READLINE
|
||||
LIBS = -lreadline -lc
|
||||
|
||||
all: pdc
|
||||
|
||||
|
||||
@@ -1,14 +1,48 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct atexit { /* entry allocated per atexit() call */
|
||||
struct atexit *next; /* next enty in a list */
|
||||
void (*func)(void); /* callback function */
|
||||
};
|
||||
|
||||
int errno;
|
||||
struct atexit *__atexit; /* points to head of LIFO stack */
|
||||
|
||||
extern void _cleanup();
|
||||
|
||||
void
|
||||
exit (code)
|
||||
int code;
|
||||
int code;
|
||||
{
|
||||
_cleanup();
|
||||
_exit (code);
|
||||
register struct atexit *p;
|
||||
|
||||
for (p = __atexit; p; p = p->next)
|
||||
(*p->func)();
|
||||
_cleanup();
|
||||
_exit (code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a function to be performed at exit.
|
||||
*/
|
||||
int
|
||||
atexit(fn)
|
||||
void (*fn)();
|
||||
{
|
||||
static struct atexit __atexit0; /* one guaranteed table */
|
||||
register struct atexit *p;
|
||||
|
||||
p = __atexit;
|
||||
if (! p) {
|
||||
p = &__atexit0;
|
||||
} else {
|
||||
p = malloc(sizeof(struct atexit));
|
||||
if (! p)
|
||||
return -1;
|
||||
p->next = __atexit;
|
||||
}
|
||||
p->func = fn;
|
||||
__atexit = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
25
src/libreadline/LICENSE
Normal file
25
src/libreadline/LICENSE
Normal file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
19
src/libreadline/Makefile
Normal file
19
src/libreadline/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
TOPSRC = $(shell cd ../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
|
||||
CFLAGS += -O -Wall -Werror
|
||||
|
||||
OBJS = readline.o
|
||||
|
||||
all: ../libreadline.a
|
||||
|
||||
../libreadline.a: ${OBJS}
|
||||
@$(AR) cru $@ ${OBJS}
|
||||
$(RANLIB) $@
|
||||
|
||||
install: all readline.h history.h
|
||||
install -d $(DESTDIR)/include/readline/
|
||||
cp -p readline.h history.h $(DESTDIR)/include/readline/
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o a.out ../libreadline*.a
|
||||
11
src/libreadline/Makefile-unix
Normal file
11
src/libreadline/Makefile-unix
Normal file
@@ -0,0 +1,11 @@
|
||||
CFLAGS += -Wall -Werror -Os -g
|
||||
|
||||
example: readline.o example.o
|
||||
$(CC) $(LDFLAGS) -o $@ readline.o example.o
|
||||
|
||||
clean:
|
||||
rm -rf *.o example example.dSYM history.txt
|
||||
|
||||
###
|
||||
example.o: example.c readline.h history.h
|
||||
readline.o: readline.c readline.h history.h
|
||||
87
src/libreadline/README
Normal file
87
src/libreadline/README
Normal file
@@ -0,0 +1,87 @@
|
||||
Linenoise
|
||||
~~~~~~~~~
|
||||
A minimal, zero-config, BSD licensed, readline replacement used
|
||||
in Redis, MongoDB, and Android.
|
||||
|
||||
* Single and multi line editing mode with the usual key bindings implemented.
|
||||
* History handling.
|
||||
* Completion.
|
||||
* About 1,100 lines of BSD license source code.
|
||||
* Only uses a subset of VT100 escapes (ANSI.SYS compatible).
|
||||
|
||||
|
||||
Can a line editing library be 20k lines of code?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Line editing with some support for history is a really
|
||||
important feature for command line utilities. Instead of
|
||||
retyping almost the same stuff again and again it's just much
|
||||
better to hit the up arrow and edit on syntax errors, or in
|
||||
order to try a slightly different command. But apparently code
|
||||
dealing with terminals is some sort of Black Magic: readline is
|
||||
30k lines of code, libedit 20k. Is it reasonable to link small
|
||||
utilities to huge libraries just to get a minimal support for
|
||||
line editing?
|
||||
|
||||
So what usually happens is either:
|
||||
|
||||
* Large programs with configure scripts disabling line editing
|
||||
if readline is not present in the system, or not supporting it
|
||||
at all since readline is GPL licensed and libedit (the BSD
|
||||
clone) is not as known and available as readline is (Real world
|
||||
example of this problem: Tclsh).
|
||||
|
||||
* Smaller programs not using a configure script not
|
||||
supporting line editing at all (A problem we had with Redis-cli
|
||||
for instance).
|
||||
|
||||
The result is a pollution of binaries without line editing support.
|
||||
|
||||
So I spent more or less two hours doing a reality check
|
||||
resulting in this little library: is it *really* needed for a
|
||||
line editing library to be 20k lines of code? Apparently not,
|
||||
it is possibe to get a very small, zero configuration, trivial
|
||||
to embed library, that solves the problem. Smaller programs
|
||||
will just include this, supporing line editing out of the box.
|
||||
Larger programs may use this little library or just checking
|
||||
with configure if readline/libedit is available and resorting
|
||||
to linenoise if not.
|
||||
|
||||
|
||||
Terminals, in 2010
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Apparently almost every terminal you can happen to use today
|
||||
has some kind of support for basic VT100 escape sequences. So I
|
||||
tried to write a lib using just very basic VT100 features. The
|
||||
resulting library appears to work everywhere I tried to use it,
|
||||
and now can work even on ANSI.SYS compatible terminals, since
|
||||
no VT220 specific sequences are used anymore.
|
||||
|
||||
The library is currently about 1100 lines of code. In order to
|
||||
use it in your project just look at the *example.c* file in the
|
||||
source distribution, it is trivial. Linenoise is BSD code, so
|
||||
you can use both in free software and commercial software.
|
||||
|
||||
|
||||
Tested with...
|
||||
~~~~~~~~~~~~~~
|
||||
* Linux text only console ($TERM = linux)
|
||||
* Linux KDE terminal application ($TERM = xterm)
|
||||
* Linux xterm ($TERM = xterm)
|
||||
* Linux Buildroot ($TERM = vt100)
|
||||
* Mac OS X iTerm ($TERM = xterm)
|
||||
* Mac OS X default Terminal.app ($TERM = xterm)
|
||||
* OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen)
|
||||
* IBM AIX 6.1
|
||||
* FreeBSD xterm ($TERM = xterm)
|
||||
* ANSI.SYS
|
||||
* Emacs comint mode ($TERM = dumb)
|
||||
|
||||
Please test it everywhere you can and report back!
|
||||
|
||||
|
||||
Let's push this forward!
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Patches should be provided in the respect of linenoise
|
||||
sensibility for small easy to understand code.
|
||||
|
||||
Send feedbacks to antirez at gmail
|
||||
53
src/libreadline/example.c
Normal file
53
src/libreadline/example.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "readline.h"
|
||||
#include "history.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *line;
|
||||
char *prgname = argv[0];
|
||||
|
||||
/* Parse options, with --multiline we enable multi line editing. */
|
||||
while(argc > 1) {
|
||||
argc--;
|
||||
argv++;
|
||||
if (!strcmp(*argv,"--multiline")) {
|
||||
readline_set_multiline(1);
|
||||
printf("Multi-line mode enabled.\n");
|
||||
} else if (!strcmp(*argv,"--keycodes")) {
|
||||
readline_print_keycodes();
|
||||
exit(0);
|
||||
} else {
|
||||
fprintf(stderr, "Usage: %s [--multiline] [--keycodes]\n", prgname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load history from file. The history file is just a plain text file
|
||||
* where entries are separated by newlines. */
|
||||
add_history("history.txt"); /* Load the history at startup */
|
||||
|
||||
/* Now this is the main loop of the typical readline-based application.
|
||||
* The call to readline() will block as long as the user types something
|
||||
* and presses enter.
|
||||
*
|
||||
* The typed string is returned as a malloc() allocated string by
|
||||
* readline, so the user needs to free() it. */
|
||||
while((line = readline("hello> ")) != NULL) {
|
||||
/* Do something with the string. */
|
||||
if (line[0] != '\0' && line[0] != '/') {
|
||||
printf("echo: '%s'\n", line);
|
||||
add_history(line); /* Add to the history. */
|
||||
write_history("history.txt"); /* Save the history on disk. */
|
||||
} else if (!strncmp(line,"/historylen",11)) {
|
||||
/* The "/historylen" command will change the history len. */
|
||||
int len = atoi(line+11);
|
||||
history_set_length(len);
|
||||
} else if (line[0] == '/') {
|
||||
printf("Unrecognized command: %s\n", line);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
75
src/libreadline/history.h
Normal file
75
src/libreadline/history.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Guerrilla line editing library against the idea that a line editing lib
|
||||
* needs to be 20,000 lines of C code.
|
||||
*
|
||||
* Based on linenoise.c with API modified for compatibility with
|
||||
* traditional readline library.
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2015, Serge Vakulenko <serge at vak dot ru>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __HISTORY_H
|
||||
#define __HISTORY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Place STRING at the end of the history list.
|
||||
* The associated data field (if any) is set to NULL.
|
||||
*/
|
||||
void add_history(const char *line);
|
||||
|
||||
/*
|
||||
* Set the maximum length of the current history array.
|
||||
*/
|
||||
int history_set_length(int len);
|
||||
|
||||
/*
|
||||
* Add the contents of FILENAME to the history list, a line at a time.
|
||||
* If FILENAME is NULL, then read from ~/.history. Returns 0 if
|
||||
* successful, or errno if not.
|
||||
*/
|
||||
int read_history(const char *filename);
|
||||
|
||||
/*
|
||||
* Write the current history to FILENAME. If FILENAME is NULL,
|
||||
* then write the history list to ~/.history. Values returned
|
||||
* are as in read_history ().
|
||||
*/
|
||||
int write_history(const char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HISTORY_H */
|
||||
1098
src/libreadline/readline.c
Normal file
1098
src/libreadline/readline.c
Normal file
File diff suppressed because it is too large
Load Diff
74
src/libreadline/readline.h
Normal file
74
src/libreadline/readline.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Guerrilla line editing library against the idea that a line editing lib
|
||||
* needs to be 20,000 lines of C code.
|
||||
*
|
||||
* Based on linenoise.c with API modified for compatibility with
|
||||
* traditional readline library.
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2015, Serge Vakulenko <serge at vak dot ru>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __READLINE_H
|
||||
#define __READLINE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read a line of input.
|
||||
* Prompt with PROMPT.
|
||||
* A NULL PROMPT means none.
|
||||
*/
|
||||
char *readline(const char *prompt);
|
||||
|
||||
/*
|
||||
* Clear the screen.
|
||||
* Used to handle Ctrl+L.
|
||||
*/
|
||||
void readline_clear_screen(void);
|
||||
|
||||
/*
|
||||
* Set if to use or not the multi line mode.
|
||||
*/
|
||||
void readline_set_multiline(int ml);
|
||||
|
||||
/*
|
||||
* This routine is used in order to print scan codes on screen
|
||||
* for debugging / development purposes.
|
||||
*/
|
||||
void readline_print_keycodes(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __READLINE_H */
|
||||
Reference in New Issue
Block a user