Vendor import NetBSD's libedit of "1997-06-25 01:14:45 -0700".

Obtained from:	NetBSD
This commit is contained in:
David E. O'Brien 2011-03-31 00:46:27 +00:00
commit 4d860275f5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/NetBSD/libedit/dist/; revision=220174
svn path=/vendor/NetBSD/libedit/1997-06-25/; revision=220175; tag=vendor/NetBSD/libedit/1997-06-25
40 changed files with 15371 additions and 0 deletions

63
Makefile Normal file
View File

@ -0,0 +1,63 @@
# $NetBSD: Makefile,v 1.8 1997/05/09 07:50:14 mycroft Exp $
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= edit
OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \
parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c
MAN= editline.3 editrc.5
MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \
editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \
editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_source.3 \
editline.3 el_resize.3 editline.3 el_line.3 \
editline.3 el_insertstr.3 editline.3 el_deletestr.3 \
editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3
# For speed and debugging
#SRCS= ${OSRCS} tokenizer.c history.c
# For protection
SRCS= editline.c tokenizer.c history.c
SRCS+= common.h emacs.h fcns.h help.h vi.h
INCS= histedit.h
INCSDIR=/usr/include
CLEANFILES+=common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h
CFLAGS+=-I. -I${.CURDIR}
CFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
CFLAGS+=#-DDEBUG_PASTE
AHDR=vi.h emacs.h common.h
ASRC=${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
vi.h: vi.c makelist
sh ${.CURDIR}/makelist -h ${.CURDIR}/vi.c > ${.TARGET}
emacs.h: emacs.c makelist
sh ${.CURDIR}/makelist -h ${.CURDIR}/emacs.c > ${.TARGET}
common.h: common.c makelist
sh ${.CURDIR}/makelist -h ${.CURDIR}/common.c > ${.TARGET}
fcns.h: ${AHDR} makelist
sh ${.CURDIR}/makelist -fh ${AHDR} > ${.TARGET}
fcns.c: ${AHDR} fcns.h makelist
sh ${.CURDIR}/makelist -fc ${AHDR} > ${.TARGET}
help.c: ${ASRC} makelist
sh ${.CURDIR}/makelist -bc ${ASRC} > ${.TARGET}
help.h: ${ASRC} makelist
sh ${.CURDIR}/makelist -bh ${ASRC} > ${.TARGET}
editline.c: ${OSRCS}
sh ${.CURDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET}
test: libedit.a test.o
${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap
.include <bsd.lib.mk>

250
TEST/test.c Normal file
View File

@ -0,0 +1,250 @@
/* $NetBSD */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 lint
static char copyright[] =
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD";
#endif
#endif /* not lint && not SCCSID */
/*
* test.c: A little test program
*/
#include "sys.h"
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include "histedit.h"
#include "tokenizer.h"
static int continuation = 0;
static EditLine *el = NULL;
static char *
/*ARGSUSED*/
prompt(el)
EditLine *el;
{
static char a[] = "Edit$";
static char b[] = "Edit>";
return continuation ? b : a;
}
static void
sig(i)
int i;
{
(void) fprintf(stderr, "Got signal %d.\n", i);
el_reset(el);
}
static unsigned char
/*ARGSUSED*/
complete(el, ch)
EditLine *el;
int ch;
{
DIR *dd = opendir(".");
struct dirent *dp;
const char* ptr;
const LineInfo *lf = el_line(el);
int len;
/*
* Find the last word
*/
for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--)
continue;
len = lf->cursor - ++ptr;
for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
if (len > strlen(dp->d_name))
continue;
if (strncmp(dp->d_name, ptr, len) == 0) {
closedir(dd);
if (el_insertstr(el, &dp->d_name[len]) == -1)
return CC_ERROR;
else
return CC_REFRESH;
}
}
closedir(dd);
return CC_ERROR;
}
int
/*ARGSUSED*/
main(argc, argv)
int argc;
char *argv[];
{
int num;
const char *buf;
Tokenizer *tok;
History *hist;
(void) signal(SIGINT, sig);
(void) signal(SIGQUIT, sig);
(void) signal(SIGHUP, sig);
(void) signal(SIGTERM, sig);
hist = history_init(); /* Init the builtin history */
history(hist, H_EVENT, 100); /* Remember 100 events */
tok = tok_init(NULL); /* Initialize the tokenizer */
el = el_init(*argv, stdin, stdout); /* Initialize editline */
el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */
el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */
el_set(el, EL_PROMPT, prompt); /* Set the prompt function */
/* Tell editline to use this history interface */
el_set(el, EL_HIST, history, hist);
/* Add a user-defined function */
el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
el_set(el, EL_BIND, "^I", "ed-complete", NULL);/* Bind tab to it */
/*
* Bind j, k in vi command mode to previous and next line, instead
* of previous and next history.
*/
el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
/*
* Source the user's defaults file.
*/
el_source(el, NULL);
while ((buf = el_gets(el, &num)) != NULL && num != 0) {
int ac;
char **av;
#ifdef DEBUG
(void) fprintf(stderr, "got %d %s", num, buf);
#endif
if (!continuation && num == 1)
continue;
if (tok_line(tok, buf, &ac, &av) > 0) {
history(hist, continuation ? H_ADD : H_ENTER, buf);
continuation = 1;
continue;
}
history(hist, continuation ? H_ADD : H_ENTER, buf);
continuation = 0;
if (strcmp(av[0], "history") == 0) {
const struct HistEvent *he;
switch (ac) {
case 1:
for (he = history(hist, H_LAST); he;
he = history(hist, H_PREV))
(void) fprintf(stdout, "%4d %s", he->num, he->str);
break;
case 2:
if (strcmp(av[1], "clear") == 0)
history(hist, H_CLEAR);
else
goto badhist;
break;
case 3:
if (strcmp(av[1], "load") == 0)
history(hist, H_LOAD, av[2]);
else if (strcmp(av[1], "save") == 0)
history(hist, H_SAVE, av[2]);
break;
badhist:
default:
(void) fprintf(stderr, "Bad history arguments\n");
break;
}
}
else if (el_parse(el, ac, av) == -1) {
switch (fork()) {
case 0:
execvp(av[0], av);
perror(av[0]);
_exit(1);
/*NOTREACHED*/
break;
case -1:
perror("fork");
break;
default:
if (wait(&num) == -1)
perror("wait");
(void) fprintf(stderr, "Exit %x\n", num);
break;
}
}
tok_reset(tok);
}
el_end(el);
tok_end(tok);
history_end(hist);
return 0;
}

645
chared.c Normal file
View File

@ -0,0 +1,645 @@
/* $NetBSD: chared.c,v 1.2 1997/01/11 06:47:48 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: chared.c,v 1.2 1997/01/11 06:47:48 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* chared.c: Character editor utilities
*/
#include "sys.h"
#include <stdlib.h>
#include "el.h"
/* cv_undo():
* Handle state for the vi undo command
*/
protected void
cv_undo(el, action, size, ptr)
EditLine *el;
int action, size;
char *ptr;
{
c_undo_t *vu = &el->el_chared.c_undo;
vu->action = action;
vu->ptr = ptr;
vu->isize = size;
(void) memcpy(vu->buf, vu->ptr, size);
#ifdef DEBUG_UNDO
(void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
vu->ptr, vu->isize, vu->dsize);
#endif
}
/* c_insert():
* Insert num characters
*/
protected void
c_insert(el, num)
EditLine *el;
int num;
{
char *cp;
if (el->el_line.lastchar + num >= el->el_line.limit)
return; /* can't go past end of buffer */
if (el->el_line.cursor < el->el_line.lastchar) {
/* if I must move chars */
for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
cp[num] = *cp;
}
el->el_line.lastchar += num;
} /* end c_insert */
/* c_delafter():
* Delete num characters after the cursor
*/
protected void
c_delafter(el, num)
EditLine *el;
int num;
{
if (el->el_line.cursor + num > el->el_line.lastchar)
num = el->el_line.lastchar - el->el_line.cursor;
if (num > 0) {
char *cp;
if (el->el_map.current != el->el_map.emacs)
cv_undo(el, INSERT, num, el->el_line.cursor);
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
*cp = cp[num];
el->el_line.lastchar -= num;
}
}
/* c_delbefore():
* Delete num characters before the cursor
*/
protected void
c_delbefore(el, num)
EditLine *el;
int num;
{
if (el->el_line.cursor - num < el->el_line.buffer)
num = el->el_line.cursor - el->el_line.buffer;
if (num > 0) {
char *cp;
if (el->el_map.current != el->el_map.emacs)
cv_undo(el, INSERT, num, el->el_line.cursor - num);
for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++)
*cp = cp[num];
el->el_line.lastchar -= num;
}
}
/* ce__isword():
* Return if p is part of a word according to emacs
*/
protected int
ce__isword(p)
int p;
{
return isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL;
}
/* cv__isword():
* Return if p is part of a word according to vi
*/
protected int
cv__isword(p)
int p;
{
return !isspace(p);
}
/* c__prev_word():
* Find the previous word
*/
protected char *
c__prev_word(p, low, n, wtest)
register char *p, *low;
register int n;
int (*wtest) __P((int));
{
p--;
while (n--) {
while ((p >= low) && !(*wtest)((unsigned char) *p))
p--;
while ((p >= low) && (*wtest)((unsigned char) *p))
p--;
}
/* cp now points to one character before the word */
p++;
if (p < low)
p = low;
/* cp now points where we want it */
return p;
}
/* c__next_word():
* Find the next word
*/
protected char *
c__next_word(p, high, n, wtest)
register char *p, *high;
register int n;
int (*wtest) __P((int));
{
while (n--) {
while ((p < high) && !(*wtest)((unsigned char) *p))
p++;
while ((p < high) && (*wtest)((unsigned char) *p))
p++;
}
if (p > high)
p = high;
/* p now points where we want it */
return p;
}
/* cv_next_word():
* Find the next word vi style
*/
protected char *
cv_next_word(el, p, high, n, wtest)
EditLine *el;
register char *p, *high;
register int n;
int (*wtest) __P((int));
{
int test;
while (n--) {
test = (*wtest)((unsigned char) *p);
while ((p < high) && (*wtest)((unsigned char) *p) == test)
p++;
/*
* vi historically deletes with cw only the word preserving the
* trailing whitespace! This is not what 'w' does..
*/
if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
while ((p < high) && isspace((unsigned char) *p))
p++;
}
/* p now points where we want it */
if (p > high)
return high;
else
return p;
}
/* cv_prev_word():
* Find the previous word vi style
*/
protected char *
cv_prev_word(el, p, low, n, wtest)
EditLine *el;
register char *p, *low;
register int n;
int (*wtest) __P((int));
{
int test;
while (n--) {
p--;
/*
* vi historically deletes with cb only the word preserving the
* leading whitespace! This is not what 'b' does..
*/
if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
while ((p > low) && isspace((unsigned char) *p))
p--;
test = (*wtest)((unsigned char) *p);
while ((p >= low) && (*wtest)((unsigned char) *p) == test)
p--;
p++;
while (isspace((unsigned char) *p))
p++;
}
/* p now points where we want it */
if (p < low)
return low;
else
return p;
}
#ifdef notdef
/* c__number():
* Ignore character p points to, return number appearing after that.
* A '$' by itself means a big number; "$-" is for negative; '^' means 1.
* Return p pointing to last char used.
*/
protected char *
c__number(p, num, dval)
char *p; /* character position */
int *num; /* Return value */
int dval; /* dval is the number to subtract from like $-3 */
{
register int i;
register int sign = 1;
if (*++p == '^') {
*num = 1;
return p;
}
if (*p == '$') {
if (*++p != '-') {
*num = 0x7fffffff; /* Handle $ */
return --p;
}
sign = -1; /* Handle $- */
++p;
}
for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
continue;
*num = (sign < 0 ? dval - i : i);
return --p;
}
#endif
/* cv_delfini():
* Finish vi delete action
*/
protected void
cv_delfini(el)
EditLine *el;
{
register int size;
int oaction;
if (el->el_chared.c_vcmd.action & INSERT)
el->el_map.current = el->el_map.key;
oaction = el->el_chared.c_vcmd.action;
el->el_chared.c_vcmd.action = NOP;
if (el->el_chared.c_vcmd.pos == 0)
return;
if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
c_delbefore(el, size);
el->el_line.cursor = el->el_chared.c_vcmd.pos;
re_refresh_cursor(el);
}
else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
c_delafter(el, size);
}
else {
size = 1;
c_delafter(el, size);
}
switch (oaction) {
case DELETE|INSERT:
el->el_chared.c_undo.action = DELETE|INSERT;
break;
case DELETE:
el->el_chared.c_undo.action = INSERT;
break;
case NOP:
case INSERT:
default:
abort();
break;
}
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.dsize = size;
}
#ifdef notdef
/* ce__endword():
* Go to the end of this word according to emacs
*/
protected char *
ce__endword(p, high, n)
char *p, *high;
int n;
{
p++;
while (n--) {
while ((p < high) && isspace((unsigned char) *p))
p++;
while ((p < high) && !isspace((unsigned char) *p))
p++;
}
p--;
return p;
}
#endif
/* cv__endword():
* Go to the end of this word according to vi
*/
protected char *
cv__endword(p, high, n)
char *p, *high;
int n;
{
p++;
while (n--) {
while ((p < high) && isspace((unsigned char) *p))
p++;
if (isalnum((unsigned char) *p))
while ((p < high) && isalnum((unsigned char) *p))
p++;
else
while ((p < high) && !(isspace((unsigned char) *p) ||
isalnum((unsigned char) *p)))
p++;
}
p--;
return p;
}
/* ch_init():
* Initialize the character editor
*/
protected int
ch_init(el)
EditLine *el;
{
el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ);
(void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - 2];
el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
(void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
el->el_chared.c_undo.action = NOP;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
el->el_chared.c_undo.ptr = el->el_line.buffer;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = el->el_line.buffer;
el->el_chared.c_vcmd.ins = el->el_line.buffer;
el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
(void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
el->el_chared.c_kill.mark = el->el_line.buffer;
el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
el->el_state.doingarg = 0;
el->el_state.metanext = 0;
el->el_state.argument = 1;
el->el_state.lastcmd = ED_UNASSIGNED;
el->el_chared.c_macro.nline = NULL;
el->el_chared.c_macro.level = -1;
el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
sizeof(char *));
return 0;
}
/* ch_reset():
* Reset the character editor
*/
protected void
ch_reset(el)
EditLine *el;
{
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_chared.c_undo.action = NOP;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
el->el_chared.c_undo.ptr = el->el_line.buffer;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = el->el_line.buffer;
el->el_chared.c_vcmd.ins = el->el_line.buffer;
el->el_chared.c_kill.mark = el->el_line.buffer;
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
el->el_state.doingarg = 0;
el->el_state.metanext = 0;
el->el_state.argument = 1;
el->el_state.lastcmd = ED_UNASSIGNED;
el->el_chared.c_macro.level = -1;
el->el_history.eventno = 0;
}
/* ch_end():
* Free the data structures used by the editor
*/
protected void
ch_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_line.buffer);
el->el_line.buffer = NULL;
el->el_line.limit = NULL;
el_free((ptr_t) el->el_chared.c_undo.buf);
el->el_chared.c_undo.buf = NULL;
el_free((ptr_t) el->el_chared.c_kill.buf);
el->el_chared.c_kill.buf = NULL;
el_free((ptr_t) el->el_chared.c_macro.macro);
el->el_chared.c_macro.macro = NULL;
ch_reset(el);
}
/* el_insertstr():
* Insert string at cursorI
*/
public int
el_insertstr(el, s)
EditLine *el;
char *s;
{
int len;
if ((len = strlen(s)) == 0)
return -1;
if (el->el_line.lastchar + len >= el->el_line.limit)
return -1;
c_insert(el, len);
while (*s)
*el->el_line.cursor++ = *s++;
return 0;
}
/* el_deletestr():
* Delete num characters before the cursor
*/
public void
el_deletestr(el, n)
EditLine *el;
int n;
{
if (n <= 0)
return;
if (el->el_line.cursor < &el->el_line.buffer[n])
return;
c_delbefore(el, n); /* delete before dot */
el->el_line.cursor -= n;
if (el->el_line.cursor < el->el_line.buffer)
el->el_line.cursor = el->el_line.buffer;
}
/* c_gets():
* Get a string
*/
protected int
c_gets(el, buf)
EditLine *el;
char *buf;
{
char ch;
int len = 0;
for (ch = 0; ch == 0;) {
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
switch (ch) {
case 0010: /* Delete and backspace */
case 0177:
if (len > 1) {
*el->el_line.cursor-- = '\0';
el->el_line.lastchar = el->el_line.cursor;
buf[len--] = '\0';
}
else {
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
return CC_REFRESH;
}
re_refresh(el);
ch = 0;
break;
case 0033: /* ESC */
case '\r': /* Newline */
case '\n':
break;
default:
if (len >= EL_BUFSIZ)
term_beep(el);
else {
buf[len++] = ch;
*el->el_line.cursor++ = ch;
el->el_line.lastchar = el->el_line.cursor;
}
re_refresh(el);
ch = 0;
break;
}
}
buf[len] = ch;
return len;
}
/* c_hpos():
* Return the current horizontal position of the cursor
*/
protected int
c_hpos(el)
EditLine *el;
{
char *ptr;
/*
* Find how many characters till the beginning of this line.
*/
if (el->el_line.cursor == el->el_line.buffer)
return 0;
else {
for (ptr = el->el_line.cursor - 1;
ptr >= el->el_line.buffer && *ptr != '\n';
ptr--)
continue;
return el->el_line.cursor - ptr - 1;
}
}

160
chared.h Normal file
View File

@ -0,0 +1,160 @@
/* $NetBSD: chared.h,v 1.2 1997/01/11 06:47:49 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)chared.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.chared.h: Character editor interface
*/
#ifndef _h_el_chared
#define _h_el_chared
#include <ctype.h>
#include <string.h>
#include "histedit.h"
#define EL_MAXMACRO 10
/*
* This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works
* like real vi: i.e. the transition from command<->insert modes moves
* the cursor.
*
* On the other hand we really don't want to move the cursor, because
* all the editing commands don't include the character under the cursor.
* Probably the best fix is to make all the editing commands aware of
* this fact.
*/
#define VI_MOVE
typedef struct c_macro_t {
int level;
char **macro;
char *nline;
} c_macro_t;
/*
* Undo information for both vi and emacs
*/
typedef struct c_undo_t {
int action;
int isize;
int dsize;
char *ptr;
char *buf;
} c_undo_t;
/*
* Current action information for vi
*/
typedef struct c_vcmd_t {
int action;
char *pos;
char *ins;
} c_vcmd_t;
/*
* Kill buffer for emacs
*/
typedef struct c_kill_t {
char *buf;
char *last;
char *mark;
} c_kill_t;
/*
* Note that we use both data structures because the user can bind
* commands from both editors!
*/
typedef struct el_chared_t {
c_undo_t c_undo;
c_kill_t c_kill;
c_vcmd_t c_vcmd;
c_macro_t c_macro;
} el_chared_t;
#define STReof "^D\b\b"
#define STRQQ "\"\""
#define isglob(a) (strchr("*[]?", (a)) != NULL)
#define isword(a) (isprint(a))
#define NOP 0x00
#define DELETE 0x01
#define INSERT 0x02
#define CHANGE 0x04
#define CHAR_FWD 0
#define CHAR_BACK 1
#define MODE_INSERT 0
#define MODE_REPLACE 1
#define MODE_REPLACE_1 2
#include "common.h"
#include "vi.h"
#include "emacs.h"
#include "search.h"
#include "fcns.h"
protected int cv__isword __P((int));
protected void cv_delfini __P((EditLine *));
protected char *cv__endword __P((char *, char *, int));
protected int ce__isword __P((int));
protected void cv_undo __P((EditLine *, int, int, char *));
protected char *cv_next_word __P((EditLine*, char *, char *, int,
int (*)(int)));
protected char *cv_prev_word __P((EditLine*, char *, char *, int,
int (*)(int)));
protected char *c__next_word __P((char *, char *, int, int (*)(int)));
protected char *c__prev_word __P((char *, char *, int, int (*)(int)));
protected void c_insert __P((EditLine *, int));
protected void c_delbefore __P((EditLine *, int));
protected void c_delafter __P((EditLine *, int));
protected int c_gets __P((EditLine *, char *));
protected int c_hpos __P((EditLine *));
protected int ch_init __P((EditLine *));
protected void ch_reset __P((EditLine *));
protected void ch_end __P((EditLine *));
#endif /* _h_el_chared */

998
common.c Normal file
View File

@ -0,0 +1,998 @@
/* $NetBSD: common.c,v 1.3 1997/01/14 04:17:22 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: common.c,v 1.3 1997/01/14 04:17:22 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* common.c: Common Editor functions
*/
#include "sys.h"
#include "el.h"
/* ed_end_of_file():
* Indicate end of file
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
ed_end_of_file(el, c)
EditLine *el;
int c;
{
re_goto_bottom(el);
*el->el_line.lastchar = '\0';
return CC_EOF;
}
/* ed_insert():
* Add character to the line
* Insert a character [bound to all insert keys]
*/
protected el_action_t
ed_insert(el, c)
EditLine *el;
int c;
{
int i;
if (c == '\0')
return CC_ERROR;
if (el->el_line.lastchar + el->el_state.argument >=
el->el_line.limit)
return CC_ERROR; /* end of buffer space */
if (el->el_state.argument == 1) {
if (el->el_state.inputmode != MODE_INSERT) {
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
*el->el_line.cursor;
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
c_delafter(el, 1);
}
c_insert(el, 1);
*el->el_line.cursor++ = c;
el->el_state.doingarg = 0; /* just in case */
re_fastaddc(el); /* fast refresh for one char. */
}
else {
if (el->el_state.inputmode != MODE_INSERT) {
for(i = 0;i < el->el_state.argument; i++)
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
el->el_line.cursor[i];
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
c_delafter(el, el->el_state.argument);
}
c_insert(el, el->el_state.argument);
while (el->el_state.argument--)
*el->el_line.cursor++ = c;
re_refresh(el);
}
if (el->el_state.inputmode == MODE_REPLACE_1)
(void) vi_command_mode(el, 0);
return CC_NORM;
}
/* ed_delete_prev_word():
* Delete from beginning of current word to cursor
* [M-^?] [^W]
*/
protected el_action_t
/*ARGSUSED*/
ed_delete_prev_word(el, c)
EditLine *el;
int c;
{
char *cp, *p, *kp;
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
el->el_state.argument, ce__isword);
for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
*kp++ = *p;
el->el_chared.c_kill.last = kp;
c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
el->el_line.cursor = cp;
if (el->el_line.cursor < el->el_line.buffer)
el->el_line.cursor = el->el_line.buffer; /* bounds check */
return CC_REFRESH;
}
/* ed_delete_next_char():
* Delete character under cursor
* [^D] [x]
*/
protected el_action_t
/*ARGSUSED*/
ed_delete_next_char(el, c)
EditLine *el;
int c;
{
#ifdef notdef /* XXX */
#define EL el->el_line
fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
#endif
if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */
if (el->el_map.type == MAP_VI) {
if (el->el_line.cursor == el->el_line.buffer) {
/* if I'm also at the beginning */
#ifdef KSHVI
return CC_ERROR;
#else
term_overwrite(el, STReof, 4);/* then do a EOF */
term__flush();
return CC_EOF;
#endif
}
else {
#ifdef KSHVI
el->el_line.cursor--;
#else
return CC_ERROR;
#endif
}
}
else {
if (el->el_line.cursor != el->el_line.buffer)
el->el_line.cursor--;
else
return CC_ERROR;
}
}
c_delafter(el, el->el_state.argument); /* delete after dot */
if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer)
el->el_line.cursor = el->el_line.lastchar - 1; /* bounds check */
return CC_REFRESH;
}
/* ed_kill_line():
* Cut to the end of line
* [^K] [^K]
*/
protected el_action_t
/*ARGSUSED*/
ed_kill_line(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
cp = el->el_line.cursor;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_line.lastchar)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */
return CC_REFRESH;
}
/* ed_move_to_end():
* Move cursor to the end of line
* [^E] [^E]
*/
protected el_action_t
/*ARGSUSED*/
ed_move_to_end(el, c)
EditLine *el;
int c;
{
el->el_line.cursor = el->el_line.lastchar;
if (el->el_map.type == MAP_VI) {
#ifdef VI_MOVE
el->el_line.cursor--;
#endif
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
}
return CC_CURSOR;
}
/* ed_move_to_beg():
* Move cursor to the beginning of line
* [^A] [^A]
*/
protected el_action_t
/*ARGSUSED*/
ed_move_to_beg(el, c)
EditLine *el;
int c;
{
el->el_line.cursor = el->el_line.buffer;
if (el->el_map.type == MAP_VI) {
/* We want FIRST non space character */
while (isspace(*el->el_line.cursor))
el->el_line.cursor++;
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
}
return CC_CURSOR;
}
/* ed_transpose_chars():
* Exchange the character to the left of the cursor with the one under it
* [^T] [^T]
*/
protected el_action_t
ed_transpose_chars(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor < el->el_line.lastchar) {
if (el->el_line.lastchar <= &el->el_line.buffer[1])
return CC_ERROR;
else
el->el_line.cursor++;
}
if (el->el_line.cursor > &el->el_line.buffer[1]) {
/* must have at least two chars entered */
c = el->el_line.cursor[-2];
el->el_line.cursor[-2] = el->el_line.cursor[-1];
el->el_line.cursor[-1] = c;
return CC_REFRESH;
}
else
return CC_ERROR;
}
/* ed_next_char():
* Move to the right one character
* [^F] [^F]
*/
protected el_action_t
/*ARGSUSED*/
ed_next_char(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor >= el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor += el->el_state.argument;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* ed_prev_word():
* Move to the beginning of the current word
* [M-b] [b]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
el->el_state.argument,
ce__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* ed_prev_char():
* Move to the left one character
* [^B] [^B]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_char(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor > el->el_line.buffer) {
el->el_line.cursor -= el->el_state.argument;
if (el->el_line.cursor < el->el_line.buffer)
el->el_line.cursor = el->el_line.buffer;
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
else
return CC_ERROR;
}
/* ed_quoted_insert():
* Add the next character typed verbatim
* [^V] [^V]
*/
protected el_action_t
ed_quoted_insert(el, c)
EditLine *el;
int c;
{
int num;
char tc;
tty_quotemode(el);
num = el_getc(el, &tc);
c = (unsigned char) tc;
tty_noquotemode(el);
if (num == 1)
return ed_insert(el, c);
else
return ed_end_of_file(el, 0);
}
/* ed_digit():
* Adds to argument or enters a digit
*/
protected el_action_t
ed_digit(el, c)
EditLine *el;
int c;
{
if (!isdigit(c))
return CC_ERROR;
if (el->el_state.doingarg) {
/* if doing an arg, add this in... */
if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
el->el_state.argument = c - '0';
else {
if (el->el_state.argument > 1000000)
return CC_ERROR;
el->el_state.argument =
(el->el_state.argument * 10) + (c - '0');
}
return CC_ARGHACK;
}
else {
if (el->el_line.lastchar + 1 >= el->el_line.limit)
return CC_ERROR;
if (el->el_state.inputmode != MODE_INSERT) {
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
*el->el_line.cursor;
el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
c_delafter(el, 1);
}
c_insert(el, 1);
*el->el_line.cursor++ = c;
el->el_state.doingarg = 0;
re_fastaddc(el);
}
return CC_NORM;
}
/* ed_argument_digit():
* Digit that starts argument
* For ESC-n
*/
protected el_action_t
ed_argument_digit(el, c)
EditLine *el;
register int c;
{
if (!isdigit(c))
return CC_ERROR;
if (el->el_state.doingarg) {
if (el->el_state.argument > 1000000)
return CC_ERROR;
el->el_state.argument = (el->el_state.argument * 10) + (c - '0');
}
else { /* else starting an argument */
el->el_state.argument = c - '0';
el->el_state.doingarg = 1;
}
return CC_ARGHACK;
}
/* ed_unassigned():
* Indicates unbound character
* Bound to keys that are not assigned
*/
protected el_action_t
/*ARGSUSED*/
ed_unassigned(el, c)
EditLine *el;
int c;
{
term_beep(el);
term__flush();
return CC_NORM;
}
/**
** TTY key handling.
**/
/* ed_tty_sigint():
* Tty interrupt character
* [^C]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigint(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_dsusp():
* Tty delayed suspend character
* [^Y]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_dsusp(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_flush_output():
* Tty flush output characters
* [^O]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_flush_output(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_sigquit():
* Tty quit character
* [^\]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigquit(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_sigtstp():
* Tty suspend character
* [^Z]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigtstp(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_stop_output():
* Tty disallow output characters
* [^S]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_stop_output(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_start_output():
* Tty allow output characters
* [^Q]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_start_output(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_newline():
* Execute command
* [^J]
*/
protected el_action_t
/*ARGSUSED*/
ed_newline(el, c)
EditLine *el;
int c;
{
re_goto_bottom(el);
*el->el_line.lastchar++ = '\n';
*el->el_line.lastchar = '\0';
if (el->el_map.type == MAP_VI)
el->el_chared.c_vcmd.ins = el->el_line.buffer;
return CC_NEWLINE;
}
/* ed_delete_prev_char():
* Delete the character to the left of the cursor
* [^?]
*/
protected el_action_t
/*ARGSUSED*/
ed_delete_prev_char(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor <= el->el_line.buffer)
return CC_ERROR;
c_delbefore(el, el->el_state.argument);
el->el_line.cursor -= el->el_state.argument;
if (el->el_line.cursor < el->el_line.buffer)
el->el_line.cursor = el->el_line.buffer;
return CC_REFRESH;
}
/* ed_clear_screen():
* Clear screen leaving current line at the top
* [^L]
*/
protected el_action_t
/*ARGSUSED*/
ed_clear_screen(el, c)
EditLine *el;
int c;
{
term_clear_screen(el); /* clear the whole real screen */
re_clear_display(el); /* reset everything */
return CC_REFRESH;
}
/* ed_redisplay():
* Redisplay everything
* ^R
*/
protected el_action_t
/*ARGSUSED*/
ed_redisplay(el, c)
EditLine *el;
int c;
{
return CC_REDISPLAY;
}
/* ed_start_over():
* Erase current line and start from scratch
* [^G]
*/
protected el_action_t
/*ARGSUSED*/
ed_start_over(el, c)
EditLine *el;
int c;
{
ch_reset(el);
return CC_REFRESH;
}
/* ed_sequence_lead_in():
* First character in a bound sequence
* Placeholder for external keys
*/
protected el_action_t
/*ARGSUSED*/
ed_sequence_lead_in(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_prev_history():
* Move to the previous history line
* [^P] [k]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_history(el, c)
EditLine *el;
int c;
{
char beep = 0;
el->el_chared.c_undo.action = NOP;
*el->el_line.lastchar = '\0'; /* just in case */
if (el->el_history.eventno == 0) { /* save the current buffer away */
(void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
}
el->el_history.eventno += el->el_state.argument;
if (hist_get(el) == CC_ERROR) {
beep = 1;
/* el->el_history.eventno was fixed by first call */
(void) hist_get(el);
}
re_refresh(el);
if (beep)
return CC_ERROR;
else
return CC_NORM; /* was CC_UP_HIST */
}
/* ed_next_history():
* Move to the next history line
* [^N] [j]
*/
protected el_action_t
/*ARGSUSED*/
ed_next_history(el, c)
EditLine *el;
int c;
{
el->el_chared.c_undo.action = NOP;
*el->el_line.lastchar = '\0'; /* just in case */
el->el_history.eventno -= el->el_state.argument;
if (el->el_history.eventno < 0) {
el->el_history.eventno = 0;
return CC_ERROR; /* make it beep */
}
return hist_get(el);
}
/* ed_search_prev_history():
* Search previous in history for a line matching the current
* next search history [M-P] [K]
*/
protected el_action_t
/*ARGSUSED*/
ed_search_prev_history(el, c)
EditLine *el;
int c;
{
const char *hp;
int h;
bool_t found = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_undo.action = NOP;
*el->el_line.lastchar = '\0'; /* just in case */
if (el->el_history.eventno < 0) {
#ifdef DEBUG_EDIT
(void) fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n");
#endif
el->el_history.eventno = 0;
return CC_ERROR;
}
if (el->el_history.eventno == 0) {
(void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
}
if (el->el_history.ref == NULL)
return CC_ERROR;
hp = HIST_FIRST(el);
if (hp == NULL)
return CC_ERROR;
c_setpat(el); /* Set search pattern !! */
for (h = 1; h <= el->el_history.eventno; h++)
hp = HIST_NEXT(el);
while (hp != NULL) {
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
if ((strncmp(hp, el->el_line.buffer,
el->el_line.lastchar - el->el_line.buffer) ||
hp[el->el_line.lastchar-el->el_line.buffer]) &&
c_hmatch(el, hp)) {
found++;
break;
}
h++;
hp = HIST_NEXT(el);
}
if (!found) {
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "not found\n");
#endif
return CC_ERROR;
}
el->el_history.eventno = h;
return hist_get(el);
}
/* ed_search_next_history():
* Search next in history for a line matching the current
* [M-N] [J]
*/
protected el_action_t
/*ARGSUSED*/
ed_search_next_history(el, c)
EditLine *el;
int c;
{
const char *hp;
int h;
bool_t found = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_undo.action = NOP;
*el->el_line.lastchar = '\0'; /* just in case */
if (el->el_history.eventno == 0)
return CC_ERROR;
if (el->el_history.ref == NULL)
return CC_ERROR;
hp = HIST_FIRST(el);
if (hp == NULL)
return CC_ERROR;
c_setpat(el); /* Set search pattern !! */
for (h = 1; h < el->el_history.eventno && hp; h++) {
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
if ((strncmp(hp, el->el_line.buffer,
el->el_line.lastchar - el->el_line.buffer) ||
hp[el->el_line.lastchar-el->el_line.buffer]) &&
c_hmatch(el, hp))
found = h;
hp = HIST_NEXT(el);
}
if (!found) { /* is it the current history number? */
if (!c_hmatch(el, el->el_history.buf)) {
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "not found\n");
#endif
return CC_ERROR;
}
}
el->el_history.eventno = found;
return hist_get(el);
}
/* ed_prev_line():
* Move up one line
* Could be [k] [^p]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_line(el, c)
EditLine *el;
int c;
{
char *ptr;
int nchars = c_hpos(el);
/*
* Move to the line requested
*/
if (*(ptr = el->el_line.cursor) == '\n')
ptr--;
for (; ptr >= el->el_line.buffer; ptr--)
if (*ptr == '\n' && --el->el_state.argument <= 0)
break;
if (el->el_state.argument > 0)
return CC_ERROR;
/*
* Move to the beginning of the line
*/
for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
continue;
/*
* Move to the character requested
*/
for (ptr++;
nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
ptr++)
continue;
el->el_line.cursor = ptr;
return CC_CURSOR;
}
/* ed_next_line():
* Move down one line
* Could be [j] [^n]
*/
protected el_action_t
/*ARGSUSED*/
ed_next_line(el, c)
EditLine *el;
int c;
{
char *ptr;
int nchars = c_hpos(el);
/*
* Move to the line requested
*/
for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
if (*ptr == '\n' && --el->el_state.argument <= 0)
break;
if (el->el_state.argument > 0)
return CC_ERROR;
/*
* Move to the character requested
*/
for (ptr++;
nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
ptr++)
continue;
el->el_line.cursor = ptr;
return CC_CURSOR;
}
/* ed_command():
* Editline extended command
* [M-X] [:]
*/
protected el_action_t
/*ARGSUSED*/
ed_command(el, c)
EditLine *el;
int c;
{
char tmpbuf[EL_BUFSIZ];
int tmplen;
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
c_insert(el, 3); /* prompt + ": " */
*el->el_line.cursor++ = '\n';
*el->el_line.cursor++ = ':';
*el->el_line.cursor++ = ' ';
re_refresh(el);
tmplen = c_gets(el, tmpbuf);
tmpbuf[tmplen] = '\0';
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (parse_line(el, tmpbuf) == -1)
return CC_ERROR;
else
return CC_REFRESH;
}

532
editline.3 Normal file
View File

@ -0,0 +1,532 @@
.\" $NetBSD: editline.3,v 1.4 1997/01/14 04:17:23 lukem Exp $
.\"
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 REGENTS 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.
.\"
.Dd January 11, 1997
.Os BSD 4.4
.Dt EDITLINE 3
.Sh NAME
.Nm editline ,
.Nm el_init ,
.Nm el_end ,
.Nm el_reset ,
.Nm el_gets ,
.Nm el_getc ,
.Nm el_push ,
.Nm el_parse ,
.Nm el_set ,
.Nm el_source ,
.Nm el_resize ,
.Nm el_line ,
.Nm el_insertstr ,
.Nm el_deletestr ,
.Nm history_init ,
.Nm history_end ,
.Nm history
.Nd line editor and history functions
.Sh SYNOPSIS
.Fd #include <histedit.h>
.Ft EditLine *
.Fn el_init "const char *prog" "FILE *fin" "FILE *fout"
.Ft void
.Fn el_end "EditLine *e"
.Ft void
.Fn el_reset "EditLine *e"
.Ft const char *
.Fn el_gets "EditLine *e" "int *count"
.Ft int
.Fn el_getc "EditLine *e" "char *ch"
.Ft void
.Fn el_push "EditLine *e" "const char *str"
.Ft int
.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
.Ft int
.Fn el_set "EditLine *e" "int op" "..."
.Ft int
.Fn el_source "EditLine *e" "const char *file"
.Ft void
.Fn el_resize "EditLine *e"
.Ft const LineInfo *
.Fn el_line "EditLine *e"
.Ft int
.Fn el_insertstr "EditLine *e" "char *str"
.Ft void
.Fn el_deletestr "EditLine *e" "int count"
.Ft History *
.Fn history_init
.Ft void
.Fn history_end "History *h"
.Ft HistEvent *
.Fn history "History h" "int op" "..."
.Sh DESCRIPTION
The
.Nm
library provides generic line editing and history functions,
similar to those found in
.Xr sh 1 .
.Pp
These functions are available in the
.Nm libedit
library (which needs the
.Nm libtermcap
library).
Programs should be linked with
.Fl ledit ltermcap .
.Sh LINE EDITING FUNCTIONS
The line editing functions use a common data structure,
.Fa EditLine ,
which is created by
.Fn el_init
and freed by
.Fn el_end .
.Pp
The following functions are available:
.Bl -tag -width 4n
.It Fn el_init
Initialise the line editor, and return a data structure
to be used by all other line editing functions.
.Fa prog
is the name of the invoking program, used when reading the
.Xr editrc 5
file to determine which settings to use.
.Fa fin
and
.Fa fout
are the input and output streams (respectively) to use.
In this documentation, references to
.Dq the tty
are actually to this input/output stream combination.
.It Fn el_end
Clean up and finish with
.Fa e ,
assumed to have been created with
.Fn el_init .
.It Fn el_reset
Reset the tty and the parser.
This should be called after an error which may have upset the tty's
state.
.It Fn el_gets
Read a line from the tty.
.Fa count
is modified to contain the number of characters read.
Returns the line read if successful, or
.Dv NULL
if no characters were read or if an error occurred.
.It Fn el_getc
Read a character from the tty.
.Fa ch
is modified to contain the character read.
Returns the number of characters read if successful, -1 otherwise.
.It Fn el_push
Pushes
.Fa str
back onto the input stream.
This is used by the macro expansion mechanism.
Refer to the description of
.Ic bind
.Fl s
in
.Xr editrc 5
for more information.
.It Fn el_parse
Parses the
.Fa argv
array (which is
.Fa argc
elements in size)
to execute builtin
.Nm
commands.
If the command is prefixed with
.Dq prog:
then
.Fn el_parse
will only execute the command if
.Dq prog
matches the
.Fa prog
argument supplied to
.Fn el_init .
The return value is
-1 if the command is unknown,
0 if there was no error or
.Dq prog
didn't match, or
1 if the command returned an error.
Refer to
.Xr editrc 5
for more information.
.Pp
.Em NOTE:
.Va argv[0]
may be modified by
.Fn el_parse .
The colon between
.Dq prog
and the command,
.Ar command ,
will be replaced with a NUL
.Po
.Dq \e0
.Pc .
.It Fn el_set
Set
.Nm
parameters.
.Fa op
determines which parameter to set, and each operation has its
own parameter list.
.Pp
The following values for
.Fa op
are supported, along with the required argument list:
.Bl -tag -width 4n
.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
Define prompt printing function as
.Fa f ,
which is to return a string that contains the prompt.
.It Dv EL_TERMINAL , Fa "const char *type"
Define terminal type of the tty to be
.Fa type ,
or to
.Ev TERM
if
.Fa type
is
.Dv NULL .
.It Dv EL_EDITOR , Fa "const char *mode"
Set editing mode to
.Fa mode ,
which must be one of
.Dq emacs
or
.Dq vi .
.It Dv EL_SIGNAL , Fa "int flag"
If
.Fa flag
is non-zero,
.Nm
will install its own signal handler for the following signals when
reading command input:
.Dv SIGCONT ,
.Dv SIGHUP ,
.Dv SIGINT ,
.Dv SIGQUIT ,
.Dv SIGSTOP ,
.Dv SIGTERM ,
.Dv SIGTSTP ,
and
.Dv SIGWINCH .
Otherwise, the current signal handlers will be used.
.It Dv EL_BIND , Xo
.Fa "const char *" ,
.Fa "..." ,
.Dv NULL
.Xc
Perform the
.Ic bind
builtin command.
Refer to
.Xr editrc 5
for more information.
.It Dv EL_ECHOTC , Xo
.Fa "const char *" ,
.Fa "..." ,
.Dv NULL
.Xc
Perform the
.Ic echotc
builtin command.
Refer to
.Xr editrc 5
for more information.
.It Dv EL_SETTC , Xo
.Fa "const char *" ,
.Fa "..." ,
.Dv NULL
.Xc
Perform the
.Ic settc
builtin command.
Refer to
.Xr editrc 5
for more information.
.It Dv EL_SETTY , Xo
.Fa "const char *" ,
.Fa "..." ,
.Dv NULL
.Xc
Perform the
.Ic setty
builtin command.
Refer to
.Xr editrc 5
for more information.
.It Dv EL_TELLTC , Xo
.Fa "const char *" ,
.Fa "..." ,
.Dv NULL
.Xc
Perform the
.Ic telltc
builtin command.
Refer to
.Xr editrc 5
for more information.
.It Dv EL_ADDFN , Xo
.Fa "const char *name" ,
.Fa "const char *help" ,
.Fa "unsigned char (*func)(EditLine *e, int ch)
.Xc
Add a user defined function,
.Fn func ,
referred to as
.Fa name
which is invoked when a key which is bound to
.Fa name
is entered.
.Fa help
is a description of
.Fa name .
At invocation time,
.Fa ch
is the key which caused the invocation.
The return value of
.Fn func
should be one of:
.Bl -tag -width "CC_REDISPLAY"
.It Dv CC_NORM
Add a normal character.
.It Dv CC_NEWLINE
End of line was entered.
.It Dv CC_EOF
EOF was entered.
.It Dv CC_ARGHACK
Expecting further command input as arguments, do nothing visually.
.It Dv CC_REFRESH
Refresh display.
.It Dv CC_CURSOR
Cursor moved, so update and perform
.Dv CC_REFRESH.
.It Dv CC_REDISPLAY
Redisplay entire input line.
This is useful if a key binding outputs extra information.
.It Dv CC_ERROR
An error occurred.
Beep, and flush tty.
.It Dv CC_FATAL
Fatal error, reset tty to known state.
.El
.It Dv EL_HIST , Xo
.Fa "History *(*func)(History *, int op, ...)" ,
.Fa "const char *ptr"
.Xc
Defines which history function to use, which is usually
.Fn history .
.Fa ptr
should be the value returned by
.Fn history_init .
.El
.It Fn el_source
Initialise
.Nm
by reading the contents of
.Fa file .
.Fn el_parse
is called for each line in
.Fa file .
If
.Fa file
is
.Dv NULL ,
try
.Pa $PWD/.editrc
then
.Pa $HOME/.editrc .
Refer to
.Xr editrc 5
for details on the format of
.Fa file .
.It Fn el_resize
Must be called if the terminal size changes.
If
.Dv EL_SIGNAL
has been set with
.Fn el_set ,
then this is done automatically.
Otherwise, it's the responsibility of the application to call
.Fn el_resize
on the appropriate occasions.
.It Fn el_line
Return the editing information for the current line in a
.Fa LineInfo
structure, which is defined as follows:
.Bd -literal
typedef struct lineinfo {
const char *buffer; /* address of buffer */
const char *cursor; /* address of cursor */
const char *lastchar; /* address of last character */
} LineInfo;
.Ed
.It Fn el_insertstr
Insert
.Fa str
into the line at the cursor.
Returns -1 if
.Fa str
is empty or won't fit, and 0 otherwise.
.It Fn el_deletestr
Delete
.Fa num
characters before the cursor.
.El
.Sh HISTORY LIST FUNCTIONS
The history functions use a common data structure,
.Fa History ,
which is created by
.Fn history_init
and freed by
.Fn history_end .
.Pp
The following functions are available:
.Bl -tag -width 4n
.It Fn history_init
Initialise the history list, and return a data structure
to be used by all other history list functions.
.It Fn history_end
Clean up and finish with
.Fa h ,
assumed to have been created with
.Fn history_init .
.It Fn history
Perform operation
.Fa op
on the history list, with optional arguments as needed by the
operation.
The following values for
.Fa op
are supported, along with the required argument list:
.Bl -tag -width 4n
.It Dv H_EVENT , Fa "int size"
Set size of history to
.Fa size
elements.
.It Dv H_END
Cleans up and finishes with
.Fa h ,
assumed to be created with
.Fn history_init .
.It Dv H_CLEAR
Clear the history.
.It Dv H_FUNC , Xo
.Fa "void *ptr" ,
.Fa "history_gfun_t first" ,
.Fa "history_gfun_t next" ,
.Fa "history_gfun_t last" ,
.Fa "history_gfun_t prev" ,
.Fa "history_gfun_t curr" ,
.Fa "history_vfun_t clear" ,
.Fa "history_efun_t enter" ,
.Fa "history_efun_t add"
.Xc
Define functions to perform various history operations.
.Fa ptr
is the argument given to a function when it's invoked.
.It Dv H_FIRST
Return the first element in the history.
.It Dv H_LAST
Return the last element in the history.
.It Dv H_PREV
Return the previous element in the history.
.It Dv H_NEXT
Return the next element in the history.
.It Dv H_CURR
Return the current element in the history.
.It Dv H_ADD , Fa "const char *str"
Append
.Fa str
to the current element of the history, or create an element with
.Dv H_ENTER
if there isn't one.
.It Dv H_ENTER , Fa "const char *str"
Add
.Fa str
as a new element to the history, and, if necessary,
removing the oldest entry to keep the list to the created size.
.It Dv H_PREV_STR , Fa "const char *str"
Return the closest previous event that starts with
.Fa str .
.It Dv H_NEXT_STR , Fa "const char *str"
Return the closest next event that starts with
.Fa str .
.It Dv H_PREV_EVENT , Fa "int e"
Return the previous event numbered
.Fa e .
.It Dv H_NEXT_EVENT , Fa "int e"
Return the next event numbered
.Fa e .
.It Dv H_LOAD , Fa "const char *file"
Load the history list stored in
.Fa file .
.It Dv H_SAVE , Fa "const char *file"
Save the history list to
.Fa file .
.El
.El
.\"XXX.Sh EXAMPLES
.\"XXX: provide some examples
.Sh SEE ALSO
.Xr editrc 5 ,
.Xr sh 1 ,
.Xr signal 3 ,
.Xr termcap 3
.Sh HISTORY
The
.Nm
library first appeared in
.Bx 4.4 .
.Sh AUTHORS
The
.Nm
library was written by Christos Zoulas,
and this manual was written by Luke Mewburn.
.Sh BUGS
This documentation is probably incomplete.
.Pp
.Fn el_parse
should not modify the supplied
.Va argv[0] .
.Pp
The tokenization functions are not publically defined in
.Fd <histedit.h>

292
editrc.5 Normal file
View File

@ -0,0 +1,292 @@
.\" $NetBSD: editrc.5,v 1.4 1997/04/24 20:20:31 christos Exp $
.\"
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. 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.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 REGENTS 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.
.\"
.Dd January 11, 1997
.Os BSD 4.4
.Dt EDITRC 5
.Sh NAME
.Nm editrc
.Nd configuration file for editline library
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
The
.Nm
file defines various settings to be used by the
.Xr editline 3
library.
.Pp
The format of each line is either:
.Dl prog:command [arg [...]]
or
.Dl command [arg [...]]
.Pp
.Ar command
is one of the
.Xr editline 3
builtin commands.
Refer to
.Sx BUILTIN COMMANDS
for more information.
.Pp
.Ar prog
is the program name string that a program defines when it calls
.Xr el_init 3
to setup
.Xr editline 3 ,
which is usually
.Va argv[0] .
.Ar command
will be executed for any program which matches
.Ar prog .
.Pp
.Ar prog
may also be a
.Xr regex 3
style
regular expression, in which case
.Ar command
will be executed for any program that matches the regular expression.
.Sh BUILTIN COMMANDS
The
.Nm editline
library has some builtin commands, which affect the way
that the line editing and history functions operate.
These are based on similar named builtins present in the
.Xr tcsh 1
shell.
.Pp
The following builtin commands are available:
.Bl -tag -width 4n
.It Ic bind Xo
.Op Fl a
.Op Fl e
.Op Fl k
.Op Fl l
.Op Fl r
.Op Fl s
.Op Fl v
.Op Ar key Op Ar command
.Xc
Without options, list all bound keys, and the editor command to which
each is bound.
If
.Ar key
is supplied, show the bindings for
.Ar key .
If
.Ar key command
is supplied, bind
.Ar command
to
.Ar key .
Options include:
.Bl -tag -width 4n
.It Fl e
Bind all keys to the standard GNU Emacs-like bindings.
.It Fl v
Bind all keys to the standard
.Xr vi 1 -like
bindings.
.It Fl a
List or change key bindings in the
.Xr vi 1
mode alternate (command mode) key map.
.It Fl k
.Ar key
is interpreted as a symbolic arrow key name, which may be one of
.Sq up ,
.Sq down ,
.Sq left
or
.Sq right .
.It Fl l
List all editor commands and a short description of each.
.It Fl r
Remove a key's binding.
.It Fl s
.Ar command
is taken as a literal string and treated as terminal input when
.Ar key
is typed.
Bound keys in
.Ar command
are themselves reinterpreted, and this continues for ten levels of
interpretation.
.El
.Pp
.Ar key
and
.Ar command
can contain control characters of the form
.Sm off
.Sq No ^ Ar character
.Sm on
.Po
e.g.
.Sq ^A
.Pc ,
and the following backslashed escape sequences:
.Pp
.Bl -tag -compact -offset indent -width 4n
.It Ic \ea
Bell
.It Ic \eb
Backspace
.It Ic \ee
Escape
.It Ic \ef
Formfeed
.It Ic \en
Newline
.It Ic \er
Carriage return
.It Ic \et
Horizontal tab
.It Ic \ev
Vertical tab
.Sm off
.It Sy \e Ar nnn
.Sm on
The ASCII character corresponding to the octal number
.Ar nnn .
.El
.Pp
.Sq \e
nullifies the special meaning of the following character,
if it has any, notably
.Sq \e
and
.Sq ^ .
.It Ic echotc Xo
.Op Fl sv
.Ar arg
.Ar ...
.Xc
Exercise terminal capabilities given in
.Ar arg Ar ... .
If
.Ar arg
is
.Sq baud ,
.Sq cols ,
.Sq lines ,
.Sq rows ,
.Sq meta or
.Sq tabs ,
the value of that capability is printed, with
.Dq yes
or
.Dq no
indicating that the terminal does or does not have that capability.
.Pp
.Fl s
returns an emptry string for non-existant capabilities, rather than
causing an error.
.Fl v
causes messages to be verbose.
.It Ic history
List the history.
.It Ic telltc
List the values of all the terminal capabilities (see
.Xr termcap 5 ).
.It Ic settc Ar cap Ar val
Set the terminal capability
.Ar cap
to
.Ar val ,
as defined in
.Xr termcap 5 .
No sanity checking is done.
.It Ic setty Xo
.Op Fl a
.Op Fl d
.Op Fl q
.Op Fl x
.Op Ar +mode
.Op Ar -mode
.Op Ar mode
.Xc
Control which tty modes that
.Nm
won't allow the user to change.
.Fl d ,
.Fl q
or
.Fl x
tells
.Ic setty
to act on the
.Sq edit ,
.Sq quote
or
.Sq execute
set of tty modes respectively; defaulting to
.Fl x .
.Pp
Without other arguments,
.Ic setty
lists the modes in the chosen set which are fixed on
.Po
.Sq +mode
.Pc
or off
.Po
.Sq -mode
.Pc .
.Fl a
lists all tty modes in the chosen set regardless of the setting.
With
.Ar +mode ,
.Ar -mode
or
.Ar mode ,
fixes
.Ar mode
on or off or removes control of
.Ar mode
in the chosen set.
.El
.Sh SEE ALSO
.Xr editline 3 ,
.Xr regex 3 ,
.Xr termcap 5
.Sh AUTHORS
The
.Nm editline
library was written by Christos Zoulas,
and this manual was written by Luke Mewburn,
with some sections inspired by
.Xr tcsh 1 .

343
el.c Normal file
View File

@ -0,0 +1,343 @@
/* $NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
#else
static char rcsid[] = "$NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* el.c: EditLine interface functions
*/
#include "sys.h"
#include <sys/types.h>
#include <sys/param.h>
#include <string.h>
#include <stdlib.h>
#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include "el.h"
/* el_init():
* Initialize editline and set default parameters.
*/
public EditLine *
el_init(prog, fin, fout)
const char *prog;
FILE *fin, *fout;
{
EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
#ifdef DEBUG
char *tty;
#endif
if (el == NULL)
return NULL;
memset(el, 0, sizeof(EditLine));
el->el_infd = fileno(fin);
el->el_outfile = fout;
el->el_prog = strdup(prog);
#ifdef DEBUG
if ((tty = getenv("DEBUGTTY")) != NULL) {
el->el_errfile = fopen(tty, "w");
if (el->el_errfile == NULL) {
extern errno;
(void) fprintf(stderr, "Cannot open %s (%s).\n",
tty, strerror(errno));
return NULL;
}
}
else
#endif
el->el_errfile = stderr;
/*
* Initialize all the modules. Order is important!!!
*/
(void) term_init(el);
(void) tty_init(el);
(void) key_init(el);
(void) map_init(el);
(void) ch_init(el);
(void) search_init(el);
(void) hist_init(el);
(void) prompt_init(el);
(void) sig_init(el);
el->el_flags = 0;
return el;
} /* end el_init */
/* el_end():
* Clean up.
*/
public void
el_end(el)
EditLine *el;
{
if (el == NULL)
return;
el_reset(el);
term_end(el);
tty_end(el);
key_end(el);
map_end(el);
ch_end(el);
search_end(el);
hist_end(el);
prompt_end(el);
sig_end(el);
el_free((ptr_t) el->el_prog);
el_free((ptr_t) el);
} /* end el_end */
/* el_reset():
* Reset the tty and the parser
*/
public void
el_reset(el)
EditLine *el;
{
tty_cookedmode(el);
ch_reset(el); /* XXX: Do we want that? */
}
/* el_set():
* set the editline parameters
*/
public int
#ifdef __STDC__
el_set(EditLine *el, int op, ...)
#else
el_set(va_alist)
va_dcl
#endif
{
va_list va;
int rv;
#ifdef __STDC__
va_start(va, op);
#else
EditLine *el;
int op;
va_start(va);
el = va_arg(va, EditLine *);
op = va_arg(va, int);
#endif
switch (op) {
case EL_PROMPT:
rv = prompt_set(el, va_arg(va, el_pfunc_t));
break;
case EL_TERMINAL:
rv = term_set(el, va_arg(va, char *));
break;
case EL_EDITOR:
rv = map_set_editor(el, va_arg(va, char *));
break;
case EL_SIGNAL:
if (va_arg(va, int))
el->el_flags |= HANDLE_SIGNALS;
else
el->el_flags &= ~HANDLE_SIGNALS;
rv = 0;
break;
case EL_BIND:
case EL_TELLTC:
case EL_SETTC:
case EL_ECHOTC:
case EL_SETTY:
{
char *argv[20];
int i;
for (i = 1; i < 20; i++)
if ((argv[i] = va_arg(va, char *)) == NULL)
break;
switch (op) {
case EL_BIND:
argv[0] = "bind";
rv = map_bind(el, i, argv);
break;
case EL_TELLTC:
argv[0] = "telltc";
rv = term_telltc(el, i, argv);
break;
case EL_SETTC:
argv[0] = "settc";
rv = term_settc(el, i, argv);
break;
case EL_ECHOTC:
argv[0] = "echotc";
rv = term_echotc(el, i, argv);
break;
case EL_SETTY:
argv[0] = "setty";
rv = tty_stty(el, i, argv);
break;
default:
rv = -1;
abort();
break;
}
}
break;
case EL_ADDFN:
{
char *name = va_arg(va, char *);
char *help = va_arg(va, char *);
el_func_t func = va_arg(va, el_func_t);
rv = map_addfunc(el, name, help, func);
}
break;
case EL_HIST:
{
hist_fun_t func = va_arg(va, hist_fun_t);
ptr_t ptr = va_arg(va, char *);
rv = hist_set(el, func, ptr);
}
break;
default:
rv = -1;
}
va_end(va);
return rv;
} /* end el_set */
/* el_line():
* Return editing info
*/
public const LineInfo *
el_line(el)
EditLine *el;
{
return (const LineInfo *) &el->el_line;
}
static const char elpath[] = "/.editrc";
/* el_source():
* Source a file
*/
public int
el_source(el, fname)
EditLine *el;
const char *fname;
{
FILE *fp;
size_t len;
char *ptr, path[MAXPATHLEN];
if (fname == NULL) {
fname = &elpath[1];
if ((fp = fopen(fname, "r")) == NULL) {
if ((ptr = getenv("HOME")) == NULL)
return -1;
(void)snprintf(path, sizeof(path), "%s%s", ptr, elpath);
fname = path;
}
}
if ((fp = fopen(fname, "r")) == NULL)
return -1;
while ((ptr = fgetln(fp, &len)) != NULL) {
if (ptr[len - 1] == '\n')
--len;
ptr[len] = '\0';
if (parse_line(el, ptr) == -1) {
(void) fclose(fp);
return -1;
}
}
(void) fclose(fp);
return 0;
}
/* el_resize():
* Called from program when terminal is resized
*/
public void
el_resize(el)
EditLine *el;
{
int lins, cols;
sigset_t oset, nset;
(void) sigemptyset(&nset);
(void) sigaddset(&nset, SIGWINCH);
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
/* get the correct window size */
if (term_get_size(el, &lins, &cols))
term_change_size(el, lins, cols);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
}

131
el.h Normal file
View File

@ -0,0 +1,131 @@
/* $NetBSD: el.h,v 1.2 1997/01/11 06:47:53 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)el.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.h: Internal structures.
*/
#ifndef _h_el
#define _h_el
/*
* Local defaults
*/
#define KSHVI
#define VIDEFAULT
#define ANCHOR
#include <stdio.h>
#include <sys/types.h>
#define EL_BUFSIZ 1024 /* Maximum line size */
#define HANDLE_SIGNALS 1
typedef int bool_t; /* True or not */
typedef unsigned char el_action_t; /* Index to command array */
typedef struct coord_t { /* Position on the screen */
int h, v;
} coord_t;
typedef struct el_line_t {
char *buffer, /* Input line */
*cursor, /* Cursor position */
*lastchar, /* Last character */
*limit; /* Max position */
} el_line_t;
/*
* Editor state
*/
typedef struct el_state_t {
int inputmode; /* What mode are we in? */
int doingarg; /* Are we getting an argument? */
int argument; /* Numeric argument */
int metanext; /* Is the next char a meta char */
el_action_t lastcmd; /* Previous command */
} el_state_t;
/*
* Until we come up with something better...
*/
#define el_malloc(a) malloc(a)
#define el_realloc(a,b) realloc(a, b)
#define el_free(a) free(a)
#include "tty.h"
#include "prompt.h"
#include "key.h"
#include "term.h"
#include "refresh.h"
#include "chared.h"
#include "common.h"
#include "search.h"
#include "hist.h"
#include "map.h"
#include "parse.h"
#include "sig.h"
#include "help.h"
struct editline {
char *el_prog; /* the program name */
FILE *el_outfile; /* Stdio stuff */
FILE *el_errfile; /* Stdio stuff */
int el_infd; /* Input file descriptor */
int el_flags; /* Various flags. */
coord_t el_cursor; /* Cursor location */
char **el_display, /* Real screen image = what is there */
**el_vdisplay; /* Virtual screen image = what we see */
el_line_t el_line; /* The current line information */
el_state_t el_state; /* Current editor state */
el_term_t el_term; /* Terminal dependent stuff */
el_tty_t el_tty; /* Tty dependent stuff */
el_refresh_t el_refresh; /* Refresh stuff */
el_prompt_t el_prompt; /* Prompt stuff */
el_chared_t el_chared; /* Characted editor stuff */
el_map_t el_map; /* Key mapping stuff */
el_key_t el_key; /* Key binding stuff */
el_history_t el_history; /* History stuff */
el_search_t el_search; /* Search stuff */
el_signal_t el_signal; /* Signal handling stuff */
};
#endif /* _h_el */

510
emacs.c Normal file
View File

@ -0,0 +1,510 @@
/* $NetBSD: emacs.c,v 1.3 1997/01/11 06:47:54 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: emacs.c,v 1.3 1997/01/11 06:47:54 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* emacs.c: Emacs functions
*/
#include "sys.h"
#include "el.h"
/* em_delete_or_list():
* Delete character under cursor or list completions if at end of line
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
em_delete_or_list(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */
if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */
term_overwrite(el, STReof, 4);/* then do a EOF */
term__flush();
return CC_EOF;
}
else {
/* Here we could list completions, but it is an error right now */
term_beep(el);
return CC_ERROR;
}
}
else {
c_delafter(el, el->el_state.argument); /* delete after dot */
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar; /* bounds check */
return CC_REFRESH;
}
}
/* em_delete_next_word():
* Cut from cursor to end of current word
* [M-d]
*/
protected el_action_t
/*ARGSUSED*/
em_delete_next_word(el, c)
EditLine *el;
int c;
{
char *cp, *p, *kp;
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
/* save the text */
*kp++ = *p;
el->el_chared.c_kill.last = kp;
c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar; /* bounds check */
return CC_REFRESH;
}
/* em_yank():
* Paste cut buffer at cursor position
* [^Y]
*/
protected el_action_t
/*ARGSUSED*/
em_yank(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
return CC_ERROR;
if (el->el_line.lastchar +
(el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
el->el_line.limit)
return CC_ERROR;
el->el_chared.c_kill.mark = el->el_line.cursor;
cp = el->el_line.cursor;
/* open the space, */
c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
/* copy the chars */
for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
*cp++ = *kp;
/* if an arg, cursor at beginning else cursor at end */
if (el->el_state.argument == 1)
el->el_line.cursor = cp;
return CC_REFRESH;
}
/* em_kill_line():
* Cut the entire line and save in cut buffer
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
em_kill_line(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
cp = el->el_line.buffer;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_line.lastchar)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
el->el_line.lastchar = el->el_line.buffer; /* zap! -- delete all of it */
el->el_line.cursor = el->el_line.buffer;
return CC_REFRESH;
}
/* em_kill_region():
* Cut area between mark and cursor and save in cut buffer
* [^W]
*/
protected el_action_t
/*ARGSUSED*/
em_kill_region(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
if (!el->el_chared.c_kill.mark)
return CC_ERROR;
if (el->el_chared.c_kill.mark > el->el_line.cursor) {
cp = el->el_line.cursor;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_chared.c_kill.mark)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
c_delafter(el, cp - el->el_line.cursor);
}
else { /* mark is before cursor */
cp = el->el_chared.c_kill.mark;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_line.cursor)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
c_delbefore(el, cp - el->el_chared.c_kill.mark);
el->el_line.cursor = el->el_chared.c_kill.mark;
}
return CC_REFRESH;
}
/* em_copy_region():
* Copy area between mark and cursor to cut buffer
* [M-W]
*/
protected el_action_t
/*ARGSUSED*/
em_copy_region(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
if (el->el_chared.c_kill.mark)
return CC_ERROR;
if (el->el_chared.c_kill.mark > el->el_line.cursor) {
cp = el->el_line.cursor;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_chared.c_kill.mark)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
}
else {
cp = el->el_chared.c_kill.mark;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_line.cursor)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
}
return CC_NORM;
}
/* em_gosmacs_traspose():
* Exchange the two characters before the cursor
* Gosling emacs transpose chars [^T]
*/
protected el_action_t
em_gosmacs_traspose(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor > &el->el_line.buffer[1]) {
/* must have at least two chars entered */
c = el->el_line.cursor[-2];
el->el_line.cursor[-2] = el->el_line.cursor[-1];
el->el_line.cursor[-1] = c;
return CC_REFRESH;
}
else
return CC_ERROR;
}
/* em_next_word():
* Move next to end of current word
* [M-f]
*/
protected el_action_t
/*ARGSUSED*/
em_next_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument,
ce__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* em_upper_case():
* Uppercase the characters from cursor to end of current word
* [M-u]
*/
protected el_action_t
/*ARGSUSED*/
em_upper_case(el, c)
EditLine *el;
int c;
{
char *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
if (islower(*cp))
*cp = toupper(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
return CC_REFRESH;
}
/* em_capitol_case():
* Capitalize the characters from cursor to end of current word
* [M-c]
*/
protected el_action_t
/*ARGSUSED*/
em_capitol_case(el, c)
EditLine *el;
int c;
{
char *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++) {
if (isalpha(*cp)) {
if (islower(*cp))
*cp = toupper(*cp);
cp++;
break;
}
}
for (; cp < ep; cp++)
if (isupper(*cp))
*cp = tolower(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
return CC_REFRESH;
}
/* em_lower_case():
* Lowercase the characters from cursor to end of current word
* [M-l]
*/
protected el_action_t
/*ARGSUSED*/
em_lower_case(el, c)
EditLine *el;
int c;
{
char *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
if (isupper(*cp))
*cp = tolower(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
return CC_REFRESH;
}
/* em_set_mark():
* Set the mark at cursor
* [^@]
*/
protected el_action_t
/*ARGSUSED*/
em_set_mark(el, c)
EditLine *el;
int c;
{
el->el_chared.c_kill.mark = el->el_line.cursor;
return CC_NORM;
}
/* em_exchange_mark():
* Exchange the cursor and mark
* [^X^X]
*/
protected el_action_t
/*ARGSUSED*/
em_exchange_mark(el, c)
EditLine *el;
int c;
{
register char *cp;
cp = el->el_line.cursor;
el->el_line.cursor = el->el_chared.c_kill.mark;
el->el_chared.c_kill.mark = cp;
return CC_CURSOR;
}
/* em_universal_argument():
* Universal argument (argument times 4)
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
em_universal_argument(el, c)
EditLine *el;
int c;
{ /* multiply current argument by 4 */
if (el->el_state.argument > 1000000)
return CC_ERROR;
el->el_state.doingarg = 1;
el->el_state.argument *= 4;
return CC_ARGHACK;
}
/* em_meta_next():
* Add 8th bit to next character typed
* [<ESC>]
*/
protected el_action_t
/*ARGSUSED*/
em_meta_next(el, c)
EditLine *el;
int c;
{
el->el_state.metanext = 1;
return CC_ARGHACK;
}
/* em_toggle_overwrite():
* Switch from insert to overwrite mode or vice versa
*/
protected el_action_t
/*ARGSUSED*/
em_toggle_overwrite(el, c)
EditLine *el;
int c;
{
el->el_state.inputmode =
(el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
return CC_NORM;
}
/* em_copy_prev_word():
* Copy current word to cursor
*/
protected el_action_t
/*ARGSUSED*/
em_copy_prev_word(el, c)
EditLine *el;
int c;
{
char *cp, *oldc, *dp;
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
oldc = el->el_line.cursor;
/* does a bounds check */
cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
el->el_state.argument, ce__isword);
c_insert(el, oldc - cp);
for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
*dp++ = *cp;
el->el_line.cursor = dp; /* put cursor at end */
return CC_REFRESH;
}
/* em_inc_search_next():
* Emacs incremental next search
*/
protected el_action_t
/*ARGSUSED*/
em_inc_search_next(el, c)
EditLine *el;
int c;
{
el->el_search.patlen = 0;
return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
}
/* em_inc_search_prev():
* Emacs incremental reverse search
*/
protected el_action_t
/*ARGSUSED*/
em_inc_search_prev(el, c)
EditLine *el;
int c;
{
el->el_search.patlen = 0;
return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
}

176
hist.c Normal file
View File

@ -0,0 +1,176 @@
/* $NetBSD: hist.c,v 1.2 1997/01/11 06:47:55 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: hist.c,v 1.2 1997/01/11 06:47:55 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* hist.c: History access functions
*/
#include "sys.h"
#include <stdlib.h>
#include "el.h"
/* hist_init():
* Initialization function.
*/
protected int
hist_init(el)
EditLine *el;
{
el->el_history.fun = NULL;
el->el_history.ref = NULL;
el->el_history.buf = (char *) el_malloc(EL_BUFSIZ);
el->el_history.last = el->el_history.buf;
return 0;
}
/* hist_end():
* clean up history;
*/
protected void
hist_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_history.buf);
el->el_history.buf = NULL;
}
/* hist_set():
* Set new history interface
*/
protected int
hist_set(el, fun, ptr)
EditLine *el;
hist_fun_t fun;
ptr_t ptr;
{
el->el_history.ref = ptr;
el->el_history.fun = fun;
return 0;
}
/* hist_get():
* Get a history line and update it in the buffer.
* eventno tells us the event to get.
*/
protected el_action_t
hist_get(el)
EditLine *el;
{
const char *hp;
int h;
if (el->el_history.eventno == 0) { /* if really the current line */
(void) strncpy(el->el_line.buffer, el->el_history.buf, EL_BUFSIZ);
el->el_line.lastchar = el->el_line.buffer +
(el->el_history.last - el->el_history.buf);
#ifdef KSHVI
if (el->el_map.type == MAP_VI)
el->el_line.cursor = el->el_line.buffer;
else
#endif /* KSHVI */
el->el_line.cursor = el->el_line.lastchar;
return CC_REFRESH;
}
if (el->el_history.ref == NULL)
return CC_ERROR;
hp = HIST_FIRST(el);
if (hp == NULL)
return CC_ERROR;
for (h = 1; h < el->el_history.eventno; h++)
if ((hp = HIST_NEXT(el)) == NULL) {
el->el_history.eventno = h;
return CC_ERROR;
}
(void) strncpy(el->el_line.buffer, hp, EL_BUFSIZ);
el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
if (el->el_line.lastchar > el->el_line.buffer) {
if (el->el_line.lastchar[-1] == '\n')
el->el_line.lastchar--;
if (el->el_line.lastchar[-1] == ' ')
el->el_line.lastchar--;
if (el->el_line.lastchar < el->el_line.buffer)
el->el_line.lastchar = el->el_line.buffer;
}
#ifdef KSHVI
if (el->el_map.type == MAP_VI)
el->el_line.cursor = el->el_line.buffer;
else
#endif /* KSHVI */
el->el_line.cursor = el->el_line.lastchar;
return CC_REFRESH;
}
/* hist_list()
* List history entries
*/
protected int
/*ARGSUSED*/
hist_list(el, argc, argv)
EditLine *el;
int argc;
char **argv;
{
const char *str;
if (el->el_history.ref == NULL)
return -1;
for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
(void) fprintf(el->el_outfile, "%d %s", el->el_history.ev->num, str);
return 0;
}

79
hist.h Normal file
View File

@ -0,0 +1,79 @@
/* $NetBSD: hist.h,v 1.3 1997/01/11 06:47:56 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)hist.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.hist.c: History functions
*/
#ifndef _h_el_hist
#define _h_el_hist
#include "histedit.h"
typedef const HistEvent * (*hist_fun_t) __P((ptr_t, int, ...));
typedef struct el_history_t {
char *buf; /* The history buffer */
char *last; /* The last character */
int eventno; /* Event we are looking for */
ptr_t ref; /* Argument for history fcns */
hist_fun_t fun; /* Event access */
const HistEvent *ev; /* Event cookie */
} el_history_t;
#define HIST_FUN(el, fn, arg) \
((((el)->el_history.ev = \
(*(el)->el_history.fun)((el)->el_history.ref, fn, arg)) == NULL) ? \
NULL : (el)->el_history.ev->str)
#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL)
#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL)
#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL)
#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL)
#define HIST_EVENT(el, num) HIST_FUN(el, H_EVENT, num)
#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
protected int hist_init __P((EditLine *));
protected void hist_end __P((EditLine *));
protected el_action_t hist_get __P((EditLine *));
protected int hist_set __P((EditLine *, hist_fun_t, ptr_t));
protected int hist_list __P((EditLine *, int, char **));
#endif /* _h_el_hist */

178
histedit.h Normal file
View File

@ -0,0 +1,178 @@
/* $NetBSD: histedit.h,v 1.5 1997/04/11 17:52:45 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)histedit.h 8.2 (Berkeley) 1/3/94
*/
/*
* histedit.h: Line editor and history interface.
*/
#ifndef _h_editline
#define _h_editline
#include <sys/types.h>
#include <stdio.h>
/*
* ==== Editing ====
*/
typedef struct editline EditLine;
/*
* For user-defined function interface
*/
typedef struct lineinfo {
const char *buffer;
const char *cursor;
const char *lastchar;
} LineInfo;
/*
* EditLine editor function return codes.
* For user-defined function interface
*/
#define CC_NORM 0
#define CC_NEWLINE 1
#define CC_EOF 2
#define CC_ARGHACK 3
#define CC_REFRESH 4
#define CC_CURSOR 5
#define CC_ERROR 6
#define CC_FATAL 7
#define CC_REDISPLAY 8
/*
* Initialization, cleanup, and resetting
*/
EditLine *el_init __P((const char *, FILE *, FILE *));
void el_reset __P((EditLine *));
void el_end __P((EditLine *));
/*
* Get a line, a character or push a string back in the input queue
*/
const char *el_gets __P((EditLine *, int *));
int el_getc __P((EditLine *, char *));
void el_push __P((EditLine *, const char *));
/*
* High level function internals control
* Parses argc, argv array and executes builtin editline commands
*/
int el_parse __P((EditLine *, int, char **));
/*
* Low level editline access function
*/
int el_set __P((EditLine *, int, ...));
/*
* el_set/el_get parameters
*/
#define EL_PROMPT 0 /* , el_pfunc_t); */
#define EL_TERMINAL 1 /* , const char *); */
#define EL_EDITOR 2 /* , const char *); */
#define EL_SIGNAL 3 /* , int); */
#define EL_BIND 4 /* , const char *, ..., NULL); */
#define EL_TELLTC 5 /* , const char *, ..., NULL); */
#define EL_SETTC 6 /* , const char *, ..., NULL); */
#define EL_ECHOTC 7 /* , const char *, ..., NULL); */
#define EL_SETTY 8 /* , const char *, ..., NULL); */
#define EL_ADDFN 9 /* , const char *, const char * */
/* , el_func_t); */
#define EL_HIST 10 /* , hist_fun_t, const char *); */
/*
* Source named file or $PWD/.editrc or $HOME/.editrc
*/
int el_source __P((EditLine *, const char *));
/*
* Must be called when the terminal changes size; If EL_SIGNAL
* is set this is done automatically otherwise it is the responsibility
* of the application
*/
void el_resize __P((EditLine *));
/*
* User-defined function interface.
*/
const LineInfo *el_line __P((EditLine *));
int el_insertstr __P((EditLine *, char *));
void el_deletestr __P((EditLine *, int));
/*
* ==== History ====
*/
typedef struct history History;
typedef struct HistEvent {
int num;
const char *str;
} HistEvent;
/*
* History access functions.
*/
History * history_init __P((void));
void history_end __P((History *));
const HistEvent * history __P((History *, int, ...));
#define H_FUNC 0 /* , UTSL */
#define H_EVENT 1 /* , const int); */
#define H_FIRST 2 /* , void); */
#define H_LAST 3 /* , void); */
#define H_PREV 4 /* , void); */
#define H_NEXT 5 /* , void); */
#define H_CURR 6 /* , void); */
#define H_ADD 7 /* , const char*); */
#define H_ENTER 8 /* , const char*); */
#define H_END 9 /* , void); */
#define H_NEXT_STR 10 /* , const char*); */
#define H_PREV_STR 11 /* , const char*); */
#define H_NEXT_EVENT 12 /* , const int); */
#define H_PREV_EVENT 13 /* , const int); */
#define H_LOAD 14 /* , const char *); */
#define H_SAVE 15 /* , const char *); */
#define H_CLEAR 16 /* , void); */
#endif /* _h_editline */

692
history.c Normal file
View File

@ -0,0 +1,692 @@
/* $NetBSD: history.c,v 1.5 1997/04/11 17:52:46 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* hist.c: History access functions
*/
#include "sys.h"
#include <string.h>
#include <stdlib.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
static const char hist_cookie[] = "_HiStOrY_V1_\n";
#include "histedit.h"
typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
typedef void (*history_vfun_t) __P((ptr_t));
struct history {
ptr_t h_ref; /* Argument for history fcns */
history_gfun_t h_first; /* Get the first element */
history_gfun_t h_next; /* Get the next element */
history_gfun_t h_last; /* Get the last element */
history_gfun_t h_prev; /* Get the previous element */
history_gfun_t h_curr; /* Get the current element */
history_vfun_t h_clear; /* Clear the history list */
history_efun_t h_enter; /* Add an element */
history_efun_t h_add; /* Append to an element */
};
#define HNEXT(h) (*(h)->h_next)((h)->h_ref)
#define HFIRST(h) (*(h)->h_first)((h)->h_ref)
#define HPREV(h) (*(h)->h_prev)((h)->h_ref)
#define HLAST(h) (*(h)->h_last)((h)->h_ref)
#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref)
#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
#define h_malloc(a) malloc(a)
#define h_free(a) free(a)
private int history_set_num __P((History *, int));
private int history_set_fun __P((History *, History *));
private int history_load __P((History *, const char *));
private int history_save __P((History *, const char *));
private const HistEvent *history_prev_event __P((History *, int));
private const HistEvent *history_next_event __P((History *, int));
private const HistEvent *history_next_string __P((History *, const char *));
private const HistEvent *history_prev_string __P((History *, const char *));
/***********************************************************************/
/*
* Builtin- history implementation
*/
typedef struct hentry_t {
HistEvent ev; /* What we return */
struct hentry_t *next; /* Next entry */
struct hentry_t *prev; /* Previous entry */
} hentry_t;
typedef struct history_t {
hentry_t list; /* Fake list header element */
hentry_t *cursor; /* Current element in the list */
int max; /* Maximum number of events */
int cur; /* Current number of events */
int eventno; /* Current event number */
} history_t;
private const HistEvent *history_def_first __P((ptr_t));
private const HistEvent *history_def_last __P((ptr_t));
private const HistEvent *history_def_next __P((ptr_t));
private const HistEvent *history_def_prev __P((ptr_t));
private const HistEvent *history_def_curr __P((ptr_t));
private const HistEvent *history_def_enter __P((ptr_t, const char *));
private const HistEvent *history_def_add __P((ptr_t, const char *));
private void history_def_init __P((ptr_t *, int));
private void history_def_clear __P((ptr_t));
private const HistEvent *history_def_insert __P((history_t *, const char *));
private void history_def_delete __P((history_t *, hentry_t *));
#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))
/* history_def_first():
* Default function to return the first event in the history.
*/
private const HistEvent *
history_def_first(p)
ptr_t p;
{
history_t *h = (history_t *) p;
h->cursor = h->list.next;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_last():
* Default function to return the last event in the history.
*/
private const HistEvent *
history_def_last(p)
ptr_t p;
{
history_t *h = (history_t *) p;
h->cursor = h->list.prev;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_next():
* Default function to return the next event in the history.
*/
private const HistEvent *
history_def_next(p)
ptr_t p;
{
history_t *h = (history_t *) p;
if (h->cursor != &h->list)
h->cursor = h->cursor->next;
else
return NULL;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_prev():
* Default function to return the previous event in the history.
*/
private const HistEvent *
history_def_prev(p)
ptr_t p;
{
history_t *h = (history_t *) p;
if (h->cursor != &h->list)
h->cursor = h->cursor->prev;
else
return NULL;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_curr():
* Default function to return the current event in the history.
*/
private const HistEvent *
history_def_curr(p)
ptr_t p;
{
history_t *h = (history_t *) p;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_add():
* Append string to element
*/
private const HistEvent *
history_def_add(p, str)
ptr_t p;
const char *str;
{
history_t *h = (history_t *) p;
size_t len;
char *s;
if (h->cursor == &h->list)
return (history_def_enter(p, str));
len = strlen(h->cursor->ev.str) + strlen(str) + 1;
s = (char *) h_malloc(len);
(void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */
(void)strcat(s, str); /* XXX strcat is safe */
h_free((ptr_t) h->cursor->ev.str);
h->cursor->ev.str = s;
return &h->cursor->ev;
}
/* history_def_delete():
* Delete element hp of the h list
*/
private void
history_def_delete(h, hp)
history_t *h;
hentry_t *hp;
{
if (hp == &h->list)
abort();
hp->prev->next = hp->next;
hp->next->prev = hp->prev;
h_free((ptr_t) hp->ev.str);
h_free(hp);
h->cur--;
}
/* history_def_insert():
* Insert element with string str in the h list
*/
private const HistEvent *
history_def_insert(h, str)
history_t *h;
const char *str;
{
h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
h->cursor->ev.str = strdup(str);
h->cursor->next = h->list.next;
h->cursor->prev = &h->list;
h->list.next->prev = h->cursor;
h->list.next = h->cursor;
h->cur++;
return &h->cursor->ev;
}
/* history_def_enter():
* Default function to enter an item in the history
*/
private const HistEvent *
history_def_enter(p, str)
ptr_t p;
const char *str;
{
history_t *h = (history_t *) p;
const HistEvent *ev;
ev = history_def_insert(h, str);
((HistEvent*) ev)->num = ++h->eventno;
/*
* Always keep at least one entry.
* This way we don't have to check for the empty list.
*/
while (h->cur > h->max + 1)
history_def_delete(h, h->list.prev);
return ev;
}
/* history_def_init():
* Default history initialization function
*/
private void
history_def_init(p, n)
ptr_t *p;
int n;
{
history_t *h = (history_t *) h_malloc(sizeof(history_t));
if (n <= 0)
n = 0;
h->eventno = 0;
h->cur = 0;
h->max = n;
h->list.next = h->list.prev = &h->list;
h->list.ev.str = NULL;
h->list.ev.num = 0;
h->cursor = &h->list;
*p = (ptr_t) h;
}
/* history_def_clear():
* Default history cleanup function
*/
private void
history_def_clear(p)
ptr_t p;
{
history_t *h = (history_t *) p;
while (h->list.prev != &h->list)
history_def_delete(h, h->list.prev);
h->eventno = 0;
h->cur = 0;
}
/************************************************************************/
/* history_init():
* Initialization function.
*/
public History *
history_init()
{
History *h = (History *) h_malloc(sizeof(History));
history_def_init(&h->h_ref, 0);
h->h_next = history_def_next;
h->h_first = history_def_first;
h->h_last = history_def_last;
h->h_prev = history_def_prev;
h->h_curr = history_def_curr;
h->h_clear = history_def_clear;
h->h_enter = history_def_enter;
h->h_add = history_def_add;
return h;
}
/* history_end():
* clean up history;
*/
public void
history_end(h)
History *h;
{
if (h->h_next == history_def_next)
history_def_clear(h->h_ref);
}
/* history_set_num():
* Set history number of events
*/
private int
history_set_num(h, num)
History *h;
int num;
{
if (h->h_next != history_def_next || num < 0)
return -1;
history_def_set(h->h_ref, num);
return 0;
}
/* history_set_fun():
* Set history functions
*/
private int
history_set_fun(h, nh)
History *h, *nh;
{
if (nh->h_first == NULL || nh->h_next == NULL ||
nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL ||
nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
nh->h_ref == NULL) {
if (h->h_next != history_def_next) {
history_def_init(&h->h_ref, 0);
h->h_first = history_def_first;
h->h_next = history_def_next;
h->h_last = history_def_last;
h->h_prev = history_def_prev;
h->h_curr = history_def_curr;
h->h_clear = history_def_clear;
h->h_enter = history_def_enter;
h->h_add = history_def_add;
}
return -1;
}
if (h->h_next == history_def_next)
history_def_clear(h->h_ref);
h->h_first = nh->h_first;
h->h_next = nh->h_next;
h->h_last = nh->h_last;
h->h_prev = nh->h_prev;
h->h_curr = nh->h_curr;
h->h_clear = nh->h_clear;
h->h_enter = nh->h_enter;
h->h_add = nh->h_add;
return 0;
}
/* history_load():
* History load function
*/
private int
history_load(h, fname)
History *h;
const char *fname;
{
FILE *fp;
char *line;
size_t sz;
int i = -1;
if ((fp = fopen(fname, "r")) == NULL)
return i;
if ((line = fgetln(fp, &sz)) == NULL)
goto done;
if (strncmp(line, hist_cookie, sz) != 0)
goto done;
for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
char c = line[sz];
line[sz] = '\0';
HENTER(h, line);
line[sz] = c;
}
done:
(void) fclose(fp);
return i;
}
/* history_save():
* History save function
*/
private int
history_save(h, fname)
History *h;
const char *fname;
{
FILE *fp;
const HistEvent *ev;
int i = 0;
if ((fp = fopen(fname, "w")) == NULL)
return -1;
(void) fputs(hist_cookie, fp);
for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++)
(void) fprintf(fp, "%s", ev->str);
(void) fclose(fp);
return i;
}
/* history_prev_event():
* Find the previous event, with number given
*/
private const HistEvent *
history_prev_event(h, num)
History *h;
int num;
{
const HistEvent *ev;
for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
if (ev->num == num)
return ev;
return NULL;
}
/* history_next_event():
* Find the next event, with number given
*/
private const HistEvent *
history_next_event(h, num)
History *h;
int num;
{
const HistEvent *ev;
for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
if (ev->num == num)
return ev;
return NULL;
}
/* history_prev_string():
* Find the previous event beginning with string
*/
private const HistEvent *
history_prev_string(h, str)
History *h;
const char* str;
{
const HistEvent *ev;
size_t len = strlen(str);
for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
if (strncmp(str, ev->str, len) == 0)
return ev;
return NULL;
}
/* history_next_string():
* Find the next event beginning with string
*/
private const HistEvent *
history_next_string(h, str)
History *h;
const char* str;
{
const HistEvent *ev;
size_t len = strlen(str);
for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
if (strncmp(str, ev->str, len) == 0)
return ev;
return NULL;
}
/* history():
* User interface to history functions.
*/
const HistEvent *
#ifdef __STDC__
history(History *h, int fun, ...)
#else
history(va_alist)
va_dcl
#endif
{
va_list va;
const HistEvent *ev = NULL;
const char *str;
static HistEvent sev = { 0, "" };
#ifdef __STDC__
va_start(va, fun);
#else
History *h;
int fun;
va_start(va);
h = va_arg(va, History *);
fun = va_arg(va, int);
#endif
switch (fun) {
case H_ADD:
str = va_arg(va, const char *);
ev = HADD(h, str);
break;
case H_ENTER:
str = va_arg(va, const char *);
ev = HENTER(h, str);
break;
case H_FIRST:
ev = HFIRST(h);
break;
case H_NEXT:
ev = HNEXT(h);
break;
case H_LAST:
ev = HLAST(h);
break;
case H_PREV:
ev = HPREV(h);
break;
case H_CURR:
ev = HCURR(h);
break;
case H_CLEAR:
HCLEAR(h);
break;
case H_LOAD:
sev.num = history_load(h, va_arg(va, const char *));
ev = &sev;
break;
case H_SAVE:
sev.num = history_save(h, va_arg(va, const char *));
ev = &sev;
break;
case H_PREV_EVENT:
ev = history_prev_event(h, va_arg(va, int));
break;
case H_NEXT_EVENT:
ev = history_next_event(h, va_arg(va, int));
break;
case H_PREV_STR:
ev = history_prev_string(h, va_arg(va, const char*));
break;
case H_NEXT_STR:
ev = history_next_string(h, va_arg(va, const char*));
break;
case H_EVENT:
if (history_set_num(h, va_arg(va, int)) == 0) {
sev.num = -1;
ev = &sev;
}
break;
case H_FUNC:
{
History hf;
hf.h_ref = va_arg(va, ptr_t);
hf.h_first = va_arg(va, history_gfun_t);
hf.h_next = va_arg(va, history_gfun_t);
hf.h_last = va_arg(va, history_gfun_t);
hf.h_prev = va_arg(va, history_gfun_t);
hf.h_curr = va_arg(va, history_gfun_t);
hf.h_clear = va_arg(va, history_vfun_t);
hf.h_enter = va_arg(va, history_efun_t);
hf.h_add = va_arg(va, history_efun_t);
if (history_set_fun(h, &hf) == 0) {
sev.num = -1;
ev = &sev;
}
}
break;
case H_END:
history_end(h);
break;
default:
break;
}
va_end(va);
return ev;
}

732
key.c Normal file
View File

@ -0,0 +1,732 @@
/* $NetBSD: key.c,v 1.2 1997/01/11 06:47:58 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: key.c,v 1.2 1997/01/11 06:47:58 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* key.c: This module contains the procedures for maintaining
* the extended-key map.
*
* An extended-key (key) is a sequence of keystrokes introduced
* with an sequence introducer and consisting of an arbitrary
* number of characters. This module maintains a map (the el->el_key.map)
* to convert these extended-key sequences into input strs
* (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
*
* Warning:
* If key is a substr of some other keys, then the longer
* keys are lost!! That is, if the keys "abcd" and "abcef"
* are in el->el_key.map, adding the key "abc" will cause the first two
* definitions to be lost.
*
* Restrictions:
* -------------
* 1) It is not possible to have one key that is a
* substr of another.
*/
#include "sys.h"
#include <string.h>
#include <stdlib.h>
#include "el.h"
/*
* The Nodes of the el->el_key.map. The el->el_key.map is a linked list
* of these node elements
*/
struct key_node_t {
char ch; /* single character of key */
int type; /* node type */
key_value_t val; /* command code or pointer to str, */
/* if this is a leaf */
struct key_node_t *next; /* ptr to next char of this key */
struct key_node_t *sibling; /* ptr to another key with same prefix */
};
private int node_trav __P((EditLine *, key_node_t *, char *,
key_value_t *));
private int node__try __P((key_node_t *, char *,
key_value_t *, int));
private key_node_t *node__get __P((int));
private void node__put __P((key_node_t *));
private int node__delete __P((key_node_t **, char *));
private int node_lookup __P((EditLine *, char *, key_node_t *,
int));
private int node_enum __P((EditLine *, key_node_t *, int));
private int key__decode_char __P((char *, int, int));
#define KEY_BUFSIZ EL_BUFSIZ
/* key_init():
* Initialize the key maps
*/
protected int
key_init(el)
EditLine *el;
{
el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
el->el_key.map = NULL;
key_reset(el);
return 0;
}
/* key_end():
* Free the key maps
*/
protected void
key_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_key.buf);
el->el_key.buf = NULL;
/* XXX: provide a function to clear the keys */
el->el_key.map = NULL;
}
/* key_map_cmd():
* Associate cmd with a key value
*/
protected key_value_t *
key_map_cmd(el, cmd)
EditLine *el;
int cmd;
{
el->el_key.val.cmd = (el_action_t) cmd;
return &el->el_key.val;
}
/* key_map_str():
* Associate str with a key value
*/
protected key_value_t *
key_map_str(el, str)
EditLine *el;
char *str;
{
el->el_key.val.str = str;
return &el->el_key.val;
}
/* key_reset():
* Takes all nodes on el->el_key.map and puts them on free list. Then
* initializes el->el_key.map with arrow keys
* [Always bind the ansi arrow keys?]
*/
protected void
key_reset(el)
EditLine *el;
{
node__put(el->el_key.map);
el->el_key.map = NULL;
return;
}
/* key_get():
* Calls the recursive function with entry point el->el_key.map
* Looks up *ch in map and then reads characters until a
* complete match is found or a mismatch occurs. Returns the
* type of the match found (XK_STR, XK_CMD, or XK_EXE).
* Returns NULL in val.str and XK_STR for no match.
* The last character read is returned in *ch.
*/
protected int
key_get(el, ch, val)
EditLine *el;
char *ch;
key_value_t *val;
{
return node_trav(el, el->el_key.map, ch, val);
}
/* key_add():
* Adds key to the el->el_key.map and associates the value in val with it.
* If key is already is in el->el_key.map, the new code is applied to the
* existing key. Ntype specifies if code is a command, an
* out str or a unix command.
*/
protected void
key_add(el, key, val, ntype)
EditLine *el;
char *key;
key_value_t *val;
int ntype;
{
if (key[0] == '\0') {
(void) fprintf(el->el_errfile,
"key_add: Null extended-key not allowed.\n");
return;
}
if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) {
(void) fprintf(el->el_errfile,
"key_add: sequence-lead-in command not allowed\n");
return;
}
if (el->el_key.map == NULL)
/* tree is initially empty. Set up new node to match key[0] */
el->el_key.map = node__get(key[0]); /* it is properly initialized */
/* Now recurse through el->el_key.map */
(void) node__try(el->el_key.map, key, val, ntype);
return;
}
/* key_clear():
*
*/
protected void
key_clear(el, map, in)
EditLine *el;
el_action_t *map;
char *in;
{
if ((map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) &&
((map == el->el_map.key &&
el->el_map.alt[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN) ||
(map == el->el_map.alt &&
el->el_map.key[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN)))
(void) key_delete(el, in);
}
/* key_delete():
* Delete the key and all longer keys staring with key, if
* they exists.
*/
protected int
key_delete(el, key)
EditLine *el;
char *key;
{
if (key[0] == '\0') {
(void) fprintf(el->el_errfile,
"key_delete: Null extended-key not allowed.\n");
return -1;
}
if (el->el_key.map == NULL)
return 0;
(void) node__delete(&el->el_key.map, key);
return 0;
}
/* key_print():
* Print the binding associated with key key.
* Print entire el->el_key.map if null
*/
protected void
key_print(el, key)
EditLine *el;
char *key;
{
/* do nothing if el->el_key.map is empty and null key specified */
if (el->el_key.map == NULL && *key == 0)
return;
el->el_key.buf[0] = '"';
if (node_lookup(el, key, el->el_key.map, 1) <= -1)
/* key is not bound */
(void) fprintf(el->el_errfile, "Unbound extended key \"%s\"\n", key);
return;
}
/* node_trav():
* recursively traverses node in tree until match or mismatch is
* found. May read in more characters.
*/
private int
node_trav(el, ptr, ch, val)
EditLine *el;
key_node_t *ptr;
char *ch;
key_value_t *val;
{
if (ptr->ch == *ch) {
/* match found */
if (ptr->next) {
/* key not complete so get next char */
if (el_getc(el, ch) != 1) { /* if EOF or error */
val->cmd = ED_END_OF_FILE;
return XK_CMD;/* PWP: Pretend we just read an end-of-file */
}
return node_trav(el, ptr->next, ch, val);
}
else {
*val = ptr->val;
if (ptr->type != XK_CMD)
*ch = '\0';
return ptr->type;
}
}
else {
/* no match found here */
if (ptr->sibling) {
/* try next sibling */
return node_trav(el, ptr->sibling, ch, val);
}
else {
/* no next sibling -- mismatch */
val->str = NULL;
return XK_STR;
}
}
}
/* node__try():
* Find a node that matches *str or allocate a new one
*/
private int
node__try(ptr, str, val, ntype)
key_node_t *ptr;
char *str;
key_value_t *val;
int ntype;
{
if (ptr->ch != *str) {
key_node_t *xm;
for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
if (xm->sibling->ch == *str)
break;
if (xm->sibling == NULL)
xm->sibling = node__get(*str); /* setup new node */
ptr = xm->sibling;
}
if (*++str == '\0') {
/* we're there */
if (ptr->next != NULL) {
node__put(ptr->next); /* lose longer keys with this prefix */
ptr->next = NULL;
}
switch (ptr->type) {
case XK_CMD:
case XK_NOD:
break;
case XK_STR:
case XK_EXE:
if (ptr->val.str)
el_free((ptr_t) ptr->val.str);
break;
default:
abort();
break;
}
switch (ptr->type = ntype) {
case XK_CMD:
ptr->val = *val;
break;
case XK_STR:
case XK_EXE:
ptr->val.str = strdup(val->str);
break;
default:
abort();
break;
}
}
else {
/* still more chars to go */
if (ptr->next == NULL)
ptr->next = node__get(*str); /* setup new node */
(void) node__try(ptr->next, str, val, ntype);
}
return 0;
}
/* node__delete():
* Delete node that matches str
*/
private int
node__delete(inptr, str)
key_node_t **inptr;
char *str;
{
key_node_t *ptr;
key_node_t *prev_ptr = NULL;
ptr = *inptr;
if (ptr->ch != *str) {
key_node_t *xm;
for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
if (xm->sibling->ch == *str)
break;
if (xm->sibling == NULL)
return 0;
prev_ptr = xm;
ptr = xm->sibling;
}
if (*++str == '\0') {
/* we're there */
if (prev_ptr == NULL)
*inptr = ptr->sibling;
else
prev_ptr->sibling = ptr->sibling;
ptr->sibling = NULL;
node__put(ptr);
return 1;
}
else if (ptr->next != NULL && node__delete(&ptr->next, str) == 1) {
if (ptr->next != NULL)
return 0;
if (prev_ptr == NULL)
*inptr = ptr->sibling;
else
prev_ptr->sibling = ptr->sibling;
ptr->sibling = NULL;
node__put(ptr);
return 1;
}
else {
return 0;
}
}
/* node__put():
* Puts a tree of nodes onto free list using free(3).
*/
private void
node__put(ptr)
key_node_t *ptr;
{
if (ptr == NULL)
return;
if (ptr->next != NULL) {
node__put(ptr->next);
ptr->next = NULL;
}
node__put(ptr->sibling);
switch (ptr->type) {
case XK_CMD:
case XK_NOD:
break;
case XK_EXE:
case XK_STR:
if (ptr->val.str != NULL)
el_free((ptr_t) ptr->val.str);
break;
default:
abort();
break;
}
el_free((ptr_t) ptr);
}
/* node__get():
* Returns pointer to an key_node_t for ch.
*/
private key_node_t *
node__get(ch)
int ch;
{
key_node_t *ptr;
ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t));
ptr->ch = ch;
ptr->type = XK_NOD;
ptr->val.str = NULL;
ptr->next = NULL;
ptr->sibling = NULL;
return ptr;
}
/* node_lookup():
* look for the str starting at node ptr.
* Print if last node
*/
private int
node_lookup(el, str, ptr, cnt)
EditLine *el;
char *str;
key_node_t *ptr;
int cnt;
{
int ncnt;
if (ptr == NULL)
return -1; /* cannot have null ptr */
if (*str == 0) {
/* no more chars in str. node_enum from here. */
(void) node_enum(el, ptr, cnt);
return 0;
}
else {
/* If match put this char into el->el_key.buf. Recurse */
if (ptr->ch == *str) {
/* match found */
ncnt = key__decode_char(el->el_key.buf, cnt,
(unsigned char) ptr->ch);
if (ptr->next != NULL)
/* not yet at leaf */
return node_lookup(el, str + 1, ptr->next, ncnt + 1);
else {
/* next node is null so key should be complete */
if (str[1] == 0) {
el->el_key.buf[ncnt + 1] = '"';
el->el_key.buf[ncnt + 2] = '\0';
key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
return 0;
}
else
return -1;/* mismatch -- str still has chars */
}
}
else {
/* no match found try sibling */
if (ptr->sibling)
return node_lookup(el, str, ptr->sibling, cnt);
else
return -1;
}
}
}
/* node_enum():
* Traverse the node printing the characters it is bound in buffer
*/
private int
node_enum(el, ptr, cnt)
EditLine *el;
key_node_t *ptr;
int cnt;
{
int ncnt;
if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */
el->el_key.buf[++cnt] = '"';
el->el_key.buf[++cnt] = '\0';
(void) fprintf(el->el_errfile,
"Some extended keys too long for internal print buffer");
(void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf);
return 0;
}
if (ptr == NULL) {
#ifdef DEBUG_EDIT
(void) fprintf(el->el_errfile, "node_enum: BUG!! Null ptr passed\n!");
#endif
return -1;
}
/* put this char at end of str */
ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch);
if (ptr->next == NULL) {
/* print this key and function */
el->el_key.buf[ncnt + 1] = '"';
el->el_key.buf[ncnt + 2] = '\0';
key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
}
else
(void) node_enum(el, ptr->next, ncnt + 1);
/* go to sibling if there is one */
if (ptr->sibling)
(void) node_enum(el, ptr->sibling, cnt);
return 0;
}
/* key_kprint():
* Print the specified key and its associated
* function specified by val
*/
protected void
key_kprint(el, key, val, ntype)
EditLine *el;
char *key;
key_value_t *val;
int ntype;
{
el_bindings_t *fp;
char unparsbuf[EL_BUFSIZ];
static char *fmt = "%-15s-> %s\n";
if (val != NULL)
switch (ntype) {
case XK_STR:
case XK_EXE:
(void) fprintf(el->el_errfile, fmt, key,
key__decode_str(val->str, unparsbuf,
ntype == XK_STR ? "\"\"" : "[]"));
break;
case XK_CMD:
for (fp = el->el_map.help; fp->name; fp++)
if (val->cmd == fp->func) {
(void) fprintf(el->el_errfile, fmt, key, fp->name);
break;
}
#ifdef DEBUG_KEY
if (fp->name == NULL)
(void) fprintf(el->el_errfile, "BUG! Command not found.\n");
#endif
break;
default:
abort();
break;
}
else
(void) fprintf(el->el_errfile, fmt, key, "no input");
}
/* key__decode_char():
* Put a printable form of char in buf.
*/
private int
key__decode_char(buf, cnt, ch)
char *buf;
int cnt, ch;
{
if (ch == 0) {
buf[cnt++] = '^';
buf[cnt] = '@';
return cnt;
}
if (iscntrl(ch)) {
buf[cnt++] = '^';
if (ch == '\177')
buf[cnt] = '?';
else
buf[cnt] = ch | 0100;
}
else if (ch == '^') {
buf[cnt++] = '\\';
buf[cnt] = '^';
}
else if (ch == '\\') {
buf[cnt++] = '\\';
buf[cnt] = '\\';
}
else if (ch == ' ' || (isprint(ch) && !isspace(ch))) {
buf[cnt] = ch;
}
else {
buf[cnt++] = '\\';
buf[cnt++] = ((ch >> 6) & 7) + '0';
buf[cnt++] = ((ch >> 3) & 7) + '0';
buf[cnt] = (ch & 7) + '0';
}
return cnt;
}
/* key__decode_str():
* Make a printable version of the ey
*/
protected char *
key__decode_str(str, buf, sep)
char *str;
char *buf;
char *sep;
{
char *b, *p;
b = buf;
if (sep[0] != '\0')
*b++ = sep[0];
if (*str == 0) {
*b++ = '^';
*b++ = '@';
if (sep[0] != '\0' && sep[1] != '\0')
*b++ = sep[1];
*b++ = 0;
return buf;
}
for (p = str; *p != 0; p++) {
if (iscntrl((unsigned char) *p)) {
*b++ = '^';
if (*p == '\177')
*b++ = '?';
else
*b++ = *p | 0100;
}
else if (*p == '^' || *p == '\\') {
*b++ = '\\';
*b++ = *p;
}
else if (*p == ' ' || (isprint((unsigned char) *p) &&
!isspace((unsigned char) *p))) {
*b++ = *p;
}
else {
*b++ = '\\';
*b++ = ((*p >> 6) & 7) + '0';
*b++ = ((*p >> 3) & 7) + '0';
*b++ = (*p & 7) + '0';
}
}
if (sep[0] != '\0' && sep[1] != '\0')
*b++ = sep[1];
*b++ = 0;
return buf; /* should check for overflow */
}

82
key.h Normal file
View File

@ -0,0 +1,82 @@
/* $NetBSD: key.h,v 1.2 1997/01/11 06:47:59 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)key.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.key.h: Key macro header
*/
#ifndef _h_el_key
#define _h_el_key
typedef union key_value_t {
el_action_t cmd; /* If it is a command the # */
char *str; /* If it is a string... */
} key_value_t;
typedef struct key_node_t key_node_t;
typedef struct el_key_t {
char *buf; /* Key print buffer */
key_node_t *map; /* Key map */
key_value_t val; /* Local conversion buffer */
} el_key_t;
#define XK_CMD 0
#define XK_STR 1
#define XK_NOD 2
#define XK_EXE 3
protected int key_init __P((EditLine *));
protected void key_end __P((EditLine *));
protected key_value_t * key_map_cmd __P((EditLine *, int));
protected key_value_t * key_map_str __P((EditLine *, char *));
protected void key_reset __P((EditLine *));
protected int key_get __P((EditLine *, char *,
key_value_t *));
protected void key_add __P((EditLine *, char *, key_value_t *,
int));
protected void key_clear __P((EditLine *, el_action_t *,
char *));
protected int key_delete __P((EditLine *, char *));
protected void key_print __P((EditLine *, char *));
protected void key_kprint __P((EditLine *, char *,
key_value_t *, int));
protected char *key__decode_str __P((char *, char *, char *));
#endif /* _h_el_key */

185
makelist Normal file
View File

@ -0,0 +1,185 @@
#!/bin/sh -
# $NetBSD: makelist,v 1.3 1997/01/11 06:48:00 lukem Exp $
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Christos Zoulas of Cornell University.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. 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.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
#
# @(#)makelist 5.3 (Berkeley) 6/4/93
# makelist.sh: Automatically generate header files...
AWK=/usr/bin/awk
USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh <filenames>"
if [ "x$1" = "x" ]
then
echo $USAGE 1>&2
exit 1
fi
FLAG="$1"
shift
FILES="$@"
case $FLAG in
-h)
set - `echo $FILES | sed -e 's/\\./_/g'`
hdr="_h_`basename $1`"
cat $FILES | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
name = substr($2, 1, length($2) - 3);
printf("protected el_action_t\t%-25.25s __P((EditLine *, int));\n", name);
}
}
END {
printf("#endif /* %s */\n", "'$hdr'");
}';;
-bc)
cat $FILES | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"sys.h\"\n#include \"el.h\"\n");
printf("private struct el_bindings_t el_func_help[] = {\n");
low = "abcdefghijklmnopqrstuvwxyz_";
high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
for (i = 1; i <= length(low); i++)
tr[substr(low, i, 1)] = substr(high, i, 1);
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
name = substr($2, 1, length($2) - 3);
uname = "";
fname = "";
for (i = 1; i <= length(name); i++) {
s = substr(name, i, 1);
uname = uname tr[s];
if (s == "_")
s = "-";
fname = fname s;
}
printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ",");
ok = 1;
}
}
/^ \*/ {
if (ok) {
printf(" \"");
for (i = 2; i < NF; i++)
printf("%s ", $i);
printf("%s\" },\n", $i);
ok = 0;
}
}
END {
printf(" { NULL, 0, NULL }\n");
printf("};\n");
printf("\nprotected el_bindings_t* help__get()");
printf("{ return el_func_help; }\n");
}';;
-bh)
$AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_help_c\n#define _h_help_c\n");
printf("protected el_bindings_t *help__get\t__P((void));\n");
printf("#endif /* _h_help_c */\n");
}' /dev/null;;
-fh)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
sort | tr '[a-z]' '[A-Z]' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
count = 0;
}
{
printf("#define\t%-30.30s\t%3d\n", $1, count++);
}
END {
printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
printf("typedef el_action_t (*el_func_t) __P((EditLine *, int));");
printf("\nprotected el_func_t* func__get __P((void));\n");
printf("#endif /* _h_fcns_c */\n");
}';;
-fc)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"sys.h\"\n#include \"el.h\"\n");
printf("private el_func_t el_func[] = {");
maxlen = 80;
needn = 1;
len = 0;
}
{
clen = 25 + 2;
len += clen;
if (len >= maxlen)
needn = 1;
if (needn) {
printf("\n ");
needn = 0;
len = 4 + clen;
}
s = $1 ",";
printf("%-26.26s ", s);
}
END {
printf("\n};\n");
printf("\nprotected el_func_t* func__get() { return el_func; }\n");
}';;
-e)
echo "$FILES" | tr ' ' '\012' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#define protected static\n");
printf("#define SCCSID\n");
}
{
printf("#include \"%s\"\n", $1);
}';;
*)
echo $USAGE 1>&2
exit 1;;
esac

1403
map.c Normal file

File diff suppressed because it is too large Load Diff

79
map.h Normal file
View File

@ -0,0 +1,79 @@
/* $NetBSD: map.h,v 1.2 1997/01/11 06:48:01 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)map.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.map.h: Editor maps
*/
#ifndef _h_el_map
#define _h_el_map
typedef struct el_bindings_t { /* for the "bind" shell command */
const char *name; /* function name for bind command */
int func; /* function numeric value */
const char *description; /* description of function */
} el_bindings_t;
typedef struct el_map_t {
el_action_t *alt; /* The current alternate key map */
el_action_t *key; /* The current normal key map */
el_action_t *current; /* The keymap we are using */
el_action_t *emacs; /* The default emacs key map */
el_action_t *vic; /* The vi command mode key map */
el_action_t *vii; /* The vi insert mode key map */
int type; /* Emacs or vi */
el_bindings_t *help; /* The help for the editor functions */
el_func_t *func; /* List of available functions */
int nfunc; /* The number of functions/help items */
} el_map_t;
#define MAP_EMACS 0
#define MAP_VI 1
protected int map_bind __P((EditLine *, int, char **));
protected int map_init __P((EditLine *));
protected void map_end __P((EditLine *));
protected void map_init_vi __P((EditLine *));
protected void map_init_emacs __P((EditLine *));
protected int map_set_editor __P((EditLine *, char *));
protected int map_addfunc __P((EditLine *, const char *,
const char *, el_func_t));
#endif /* _h_el_map */

255
parse.c Normal file
View File

@ -0,0 +1,255 @@
/* $NetBSD: parse.c,v 1.5 1997/01/11 09:57:08 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: parse.c,v 1.5 1997/01/11 09:57:08 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* parse.c: parse an editline extended command
*
* commands are:
*
* bind
* echotc
* gettc
* history
* settc
* setty
*/
#include "sys.h"
#include "el.h"
#include "tokenizer.h"
private struct {
char *name;
int (*func) __P((EditLine *, int, char **));
} cmds[] = {
{ "bind", map_bind },
{ "echotc", term_echotc },
{ "history", hist_list },
{ "telltc", term_telltc },
{ "settc", term_settc },
{ "setty", tty_stty },
{ NULL, NULL }
};
/* parse_line():
* Parse a line and dispatch it
*/
protected int
parse_line(el, line)
EditLine *el;
const char *line;
{
char **argv;
int argc;
Tokenizer *tok;
tok = tok_init(NULL);
tok_line(tok, line, &argc, &argv);
argc = el_parse(el, argc, argv);
tok_end(tok);
return argc;
}
/* el_parse():
* Command dispatcher
*/
public int
el_parse(el, argc, argv)
EditLine *el;
int argc;
char *argv[];
{
char *ptr;
int i;
if (argc < 1)
return -1;
ptr = strchr(argv[0], ':');
if (ptr != NULL) {
*ptr++ = '\0';
if (! el_match(el->el_prog, argv[0]))
return 0;
}
else
ptr = argv[0];
for (i = 0; cmds[i].name != NULL; i++)
if (strcmp(cmds[i].name, ptr) == 0) {
i = (*cmds[i].func)(el, argc, argv);
return -i;
}
return -1;
}
/* parse__escape():
* Parse a string of the form ^<char> \<odigit> \<char> and return
* the appropriate character or -1 if the escape is not valid
*/
protected int
parse__escape(ptr)
const char ** const ptr;
{
const char *p;
int c;
p = *ptr;
if (p[1] == 0)
return -1;
if (*p == '\\') {
p++;
switch (*p) {
case 'a':
c = '\007'; /* Bell */
break;
case 'b':
c = '\010'; /* Backspace */
break;
case 't':
c = '\011'; /* Horizontal Tab */
break;
case 'n':
c = '\012'; /* New Line */
break;
case 'v':
c = '\013'; /* Vertical Tab */
break;
case 'f':
c = '\014'; /* Form Feed */
break;
case 'r':
c = '\015'; /* Carriage Return */
break;
case 'e':
c = '\033'; /* Escape */
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
int cnt, ch;
for (cnt = 0, c = 0; cnt < 3; cnt++) {
ch = *p++;
if (ch < '0' || ch > '7') {
p--;
break;
}
c = (c << 3) | (ch - '0');
}
if ((c & 0xffffff00) != 0)
return -1;
--p;
}
break;
default:
c = *p;
break;
}
}
else if (*p == '^' && isalpha((unsigned char) p[1])) {
p++;
c = (*p == '?') ? '\177' : (*p & 0237);
}
else
c = *p;
*ptr = ++p;
return c;
}
/* parse__string():
* Parse the escapes from in and put the raw string out
*/
protected char *
parse__string(out, in)
char *out;
const char *in;
{
char *rv = out;
int n;
for (;;)
switch (*in) {
case '\0':
*out = '\0';
return rv;
case '\\':
case '^':
if ((n = parse__escape(&in)) == -1)
return NULL;
*out++ = n;
break;
default:
*out++ = *in++;
break;
}
}
/* parse_cmd():
* Return the command number for the command string given
* or -1 if one is not found
*/
protected int
parse_cmd(el, cmd)
EditLine *el;
const char *cmd;
{
el_bindings_t *b;
for (b = el->el_map.help; b->name != NULL; b++)
if (strcmp(b->name, cmd) == 0)
return b->func;
return -1;
}

52
parse.h Normal file
View File

@ -0,0 +1,52 @@
/* $NetBSD: parse.h,v 1.2 1997/01/11 06:48:03 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)parse.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.parse.h: Parser functions
*/
#ifndef _h_el_parse
#define _h_el_parse
protected int parse_line __P((EditLine *, const char *));
protected int parse__escape __P((const char ** const));
protected char * parse__string __P((char *, const char *));
protected int parse_cmd __P((EditLine *, const char *));
#endif /* _h_el_parse */

129
prompt.c Normal file
View File

@ -0,0 +1,129 @@
/* $NetBSD: prompt.c,v 1.2 1997/01/11 06:48:04 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: prompt.c,v 1.2 1997/01/11 06:48:04 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* prompt.c: Prompt printing functions
*/
#include "sys.h"
#include <stdio.h>
#include "el.h"
private char *prompt_default __P((EditLine *));
/* prompt_default():
* Just a default prompt, in case the user did not provide one
*/
private char *
/*ARGSUSED*/
prompt_default(el)
EditLine *el;
{
static char a[3] = { '?', ' ', '\0' };
return a;
}
/* prompt_print():
* Print the prompt and update the prompt position.
* We use an array of integers in case we want to pass
* literal escape sequences in the prompt and we want a
* bit to flag them
*/
protected void
prompt_print(el)
EditLine *el;
{
char *p = (*el->el_prompt.p_func)(el);
while (*p)
re_putc(el, *p++);
el->el_prompt.p_pos.v = el->el_refresh.r_cursor.v;
el->el_prompt.p_pos.h = el->el_refresh.r_cursor.h;
} /* end prompt_print */
/* prompt_init():
* Initialize the prompt stuff
*/
protected int
prompt_init(el)
EditLine *el;
{
el->el_prompt.p_func = prompt_default;
el->el_prompt.p_pos.v = 0;
el->el_prompt.p_pos.h = 0;
return 0;
} /* end prompt_init */
/* prompt_end():
* Clean up the prompt stuff
*/
protected void
/*ARGSUSED*/
prompt_end(el)
EditLine *el;
{
} /* end prompt_end */
/* prompt_set():
* Install a prompt printing function
*/
protected int
prompt_set(el, prf)
EditLine *el;
el_pfunc_t prf;
{
if (prf == NULL)
el->el_prompt.p_func = prompt_default;
else
el->el_prompt.p_func = prf;
el->el_prompt.p_pos.v = 0;
el->el_prompt.p_pos.h = 0;
return 0;
} /* end prompt_set */

61
prompt.h Normal file
View File

@ -0,0 +1,61 @@
/* $NetBSD: prompt.h,v 1.2 1997/01/11 06:48:05 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)prompt.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.prompt.h: Prompt printing stuff
*/
#ifndef _h_el_prompt
#define _h_el_prompt
#include "histedit.h"
typedef char * (*el_pfunc_t) __P((EditLine*));
typedef struct el_prompt_t {
el_pfunc_t p_func; /* Function to return the prompt */
coord_t p_pos; /* position in the line after prompt */
} el_prompt_t;
protected void prompt_print __P((EditLine *));
protected int prompt_set __P((EditLine *, el_pfunc_t));
protected int prompt_init __P((EditLine *));
protected void prompt_end __P((EditLine *));
#endif /* _h_el_prompt */

452
read.c Normal file
View File

@ -0,0 +1,452 @@
/* $NetBSD: read.c,v 1.4 1997/04/11 17:52:47 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: read.c,v 1.4 1997/04/11 17:52:47 christos Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* read.c: Clean this junk up! This is horrible code.
* Terminal read functions
*/
#include "sys.h"
#include <sys/errno.h>
#include <unistd.h>
#include <stdlib.h>
extern int errno;
#include "el.h"
#define OKCMD -1
private int read__fixio __P((int, int));
private int read_preread __P((EditLine *));
private int read_getcmd __P((EditLine *, el_action_t *, char *));
#ifdef DEBUG_EDIT
private void
read_debug(el)
EditLine *el;
{
if (el->el_line.cursor > el->el_line.lastchar)
(void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
if (el->el_line.cursor < el->el_line.buffer)
(void) fprintf(el->el_errfile, "cursor < buffer\r\n");
if (el->el_line.cursor > el->el_line.limit)
(void) fprintf(el->el_errfile, "cursor > limit\r\n");
if (el->el_line.lastchar > el->el_line.limit)
(void) fprintf(el->el_errfile, "lastchar > limit\r\n");
if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
(void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
}
#endif /* DEBUG_EDIT */
/* read__fixio():
* Try to recover from a read error
*/
private int
read__fixio(fd, e)
int fd, e;
{
switch (e) {
case -1: /* Make sure that the code is reachable */
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
# ifndef TRY_AGAIN
# define TRY_AGAIN
# endif
#endif /* EWOULDBLOCK */
#if defined(POSIX) && defined(EAGAIN)
# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EAGAIN:
# ifndef TRY_AGAIN
# define TRY_AGAIN
# endif
# endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
#endif /* POSIX && EAGAIN */
e = 0;
#ifdef TRY_AGAIN
# if defined(F_SETFL) && defined(O_NDELAY)
if ((e = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
return -1;
else
e = 1;
# endif /* F_SETFL && O_NDELAY */
# ifdef FIONBIO
if (ioctl(fd, FIONBIO, (ioctl_t) &e) == -1)
return -1;
else
e = 1;
# endif /* FIONBIO */
#endif /* TRY_AGAIN */
return e ? 0 : -1;
case EINTR:
return 0;
default:
return -1;
}
}
/* read_preread():
* Try to read the stuff in the input queue;
*/
private int
read_preread(el)
EditLine *el;
{
int chrs = 0;
if (el->el_chared.c_macro.nline) {
el_free((ptr_t) el->el_chared.c_macro.nline);
el->el_chared.c_macro.nline = NULL;
}
if (el->el_tty.t_mode == ED_IO)
return 0;
#ifdef FIONREAD
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) &chrs);
if (chrs > 0) {
char buf[EL_BUFSIZ];
chrs = read(el->el_infd, buf, (size_t) MIN(chrs, EL_BUFSIZ - 1));
if (chrs > 0) {
buf[chrs] = '\0';
el->el_chared.c_macro.nline = strdup(buf);
el_push(el->el_chared.c_macro.nline);
}
}
#endif /* FIONREAD */
return chrs > 0;
}
/* el_push():
* Push a macro
*/
public void
el_push(el, str)
EditLine *el;
const char *str;
{
c_macro_t *ma = &el->el_chared.c_macro;
if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
ma->level++;
ma->macro[ma->level] = (char *) str;
}
else {
term_beep(el);
term__flush();
}
}
/* read_getcmd():
* Return next command from the input stream.
*/
private int
read_getcmd(el, cmdnum, ch)
EditLine *el;
el_action_t *cmdnum;
char *ch;
{
el_action_t cmd = 0;
int num;
while (cmd == 0 || cmd == ED_SEQUENCE_LEAD_IN) {
if ((num = el_getc(el, ch)) != 1) /* if EOF or error */
return num;
#ifdef KANJI
if ((*ch & 0200)) {
el->el_state.metanext = 0;
cmd = CcViMap[' '];
break;
}
else
#endif /* KANJI */
if (el->el_state.metanext) {
el->el_state.metanext = 0;
*ch |= 0200;
}
cmd = el->el_map.current[(unsigned char) *ch];
if (cmd == ED_SEQUENCE_LEAD_IN) {
key_value_t val;
switch (key_get(el, ch, &val)) {
case XK_CMD:
cmd = val.cmd;
break;
case XK_STR:
el_push(el, val.str);
break;
#ifdef notyet
case XK_EXE:
/* XXX: In the future to run a user function */
RunCommand(val.str);
break;
#endif
default:
abort();
break;
}
}
if (el->el_map.alt == NULL)
el->el_map.current = el->el_map.key;
}
*cmdnum = cmd;
return OKCMD;
}
/* el_getc():
* Read a character
*/
public int
el_getc(el, cp)
EditLine *el;
char *cp;
{
int num_read;
unsigned char tcp;
int tried = 0;
c_macro_t *ma = &el->el_chared.c_macro;
term__flush();
for (;;) {
if (ma->level < 0) {
if (!read_preread(el))
break;
}
if (ma->level < 0)
break;
if (*ma->macro[ma->level] == 0) {
ma->level--;
continue;
}
*cp = *ma->macro[ma->level]++ & 0377;
if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode On */
ma->level--;
}
return 1;
}
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Turning raw mode on\n");
#endif /* DEBUG_READ */
if (tty_rawmode(el) < 0) /* make sure the tty is set up correctly */
return 0;
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Reading a character\n");
#endif /* DEBUG_READ */
while ((num_read = read(el->el_infd, (char *) &tcp, 1)) == -1)
if (!tried && read__fixio(el->el_infd, errno) == 0)
tried = 1;
else {
*cp = '\0';
return -1;
}
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Got it %c\n", tcp);
#endif /* DEBUG_READ */
*cp = tcp;
return num_read;
}
public const char *
el_gets(el, nread)
EditLine *el;
int *nread;
{
int retval;
el_action_t cmdnum = 0;
int num; /* how many chars we have read at NL */
char ch;
if (el->el_flags & HANDLE_SIGNALS)
sig_set(el);
re_clear_display(el); /* reset the display stuff */
ch_reset(el);
#ifdef FIONREAD
if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
long chrs = 0;
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) &chrs);
if (chrs == 0) {
if (tty_rawmode(el) < 0) {
if (nread)
*nread = 0;
return NULL;
}
}
}
#endif /* FIONREAD */
re_refresh(el); /* print the prompt */
for (num = OKCMD; num == OKCMD;) { /* while still editing this line */
#ifdef DEBUG_EDIT
read_debug(el);
#endif /* DEBUG_EDIT */
/* if EOF or error */
if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Returning from el_gets %d\n", num);
#endif /* DEBUG_READ */
break;
}
if (cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
#ifdef DEBUG_EDIT
(void) fprintf(el->el_errfile,
"ERROR: illegal command from key 0%o\r\n", ch);
#endif /* DEBUG_EDIT */
continue; /* try again */
}
/* now do the real command */
#ifdef DEBUG_READ
{
el_bindings_t *b;
for (b = el->el_map.help; b->name; b++)
if (b->func == cmdnum)
break;
if (b->name)
(void) fprintf(el->el_errfile, "Executing %s\n", b->name);
else
(void) fprintf(el->el_errfile, "Error command = %d\n", cmdnum);
}
#endif /* DEBUG_READ */
retval = (*el->el_map.func[cmdnum])(el, ch);
/* save the last command here */
el->el_state.lastcmd = cmdnum;
/* use any return value */
switch (retval) {
case CC_CURSOR:
el->el_state.argument = 1;
el->el_state.doingarg = 0;
re_refresh_cursor(el);
break;
case CC_REDISPLAY:
re_clear_lines(el);
re_clear_display(el);
/* FALLTHROUGH */
case CC_REFRESH:
el->el_state.argument = 1;
el->el_state.doingarg = 0;
re_refresh(el);
break;
case CC_NORM: /* normal char */
el->el_state.argument = 1;
el->el_state.doingarg = 0;
break;
case CC_ARGHACK: /* Suggested by Rich Salz */
/* <rsalz@pineapple.bbn.com> */
break; /* keep going... */
case CC_EOF: /* end of file typed */
num = 0;
break;
case CC_NEWLINE: /* normal end of line */
num = el->el_line.lastchar - el->el_line.buffer;
break;
case CC_FATAL: /* fatal error, reset to known state */
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "*** editor fatal ERROR ***\r\n\n");
#endif /* DEBUG_READ */
/* put (real) cursor in a known place */
re_clear_display(el); /* reset the display stuff */
ch_reset(el); /* reset the input pointers */
re_refresh(el); /* print the prompt again */
el->el_state.argument = 1;
el->el_state.doingarg = 0;
break;
case CC_ERROR:
default: /* functions we don't know about */
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "*** editor ERROR ***\r\n\n");
#endif /* DEBUG_READ */
el->el_state.argument = 1;
el->el_state.doingarg = 0;
term_beep(el);
term__flush();
break;
}
}
(void) tty_cookedmode(el); /* make sure the tty is set up correctly */
term__flush(); /* flush any buffered output */
if (el->el_flags & HANDLE_SIGNALS)
sig_clr(el);
if (nread)
*nread = num;
return num ? el->el_line.buffer : NULL;
}

1019
refresh.c Normal file

File diff suppressed because it is too large Load Diff

62
refresh.h Normal file
View File

@ -0,0 +1,62 @@
/* $NetBSD: refresh.h,v 1.2 1997/01/11 06:48:08 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)refresh.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.refresh.h: Screen refresh functions
*/
#ifndef _h_el_refresh
#define _h_el_refresh
#include "histedit.h"
typedef struct {
coord_t r_cursor; /* Refresh cursor position */
int r_oldcv, r_newcv; /* Vertical locations */
} el_refresh_t;
protected void re_putc __P((EditLine *, int));
protected void re_clear_lines __P((EditLine *));
protected void re_clear_display __P((EditLine *));
protected void re_refresh __P((EditLine *));
protected void re_refresh_cursor __P((EditLine *));
protected void re_fastaddc __P((EditLine *));
protected void re_goto_bottom __P((EditLine *));
#endif /* _h_el_refresh */

640
search.c Normal file
View File

@ -0,0 +1,640 @@
/* $NetBSD: search.c,v 1.4 1997/01/23 14:02:47 mrg Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: search.c,v 1.4 1997/01/23 14:02:47 mrg Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* search.c: History and character search functions
*/
#include "sys.h"
#include <stdlib.h>
#if defined(REGEX)
#include <regex.h>
#elif defined(REGEXP)
#include <regexp.h>
#endif
#include "el.h"
/*
* Adjust cursor in vi mode to include the character under it
*/
#define EL_CURSOR(el) \
((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
((el)->el_map.current == (el)->el_map.alt)))
/* search_init():
* Initialize the search stuff
*/
protected int
search_init(el)
EditLine *el;
{
el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ);
el->el_search.patlen = 0;
el->el_search.patdir = -1;
el->el_search.chacha = '\0';
el->el_search.chadir = -1;
return 0;
}
/* search_end():
* Initialize the search stuff
*/
protected void
search_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_search.patbuf);
el->el_search.patbuf = NULL;
}
#ifdef REGEXP
/* regerror():
* Handle regular expression errors
*/
public void
/*ARGSUSED*/
regerror(msg)
const char *msg;
{
}
#endif
/* el_match():
* Return if string matches pattern
*/
protected int
el_match(str, pat)
const char *str;
const char *pat;
{
#if defined (REGEX)
regex_t re;
int rv;
#elif defined (REGEXP)
regexp *rp;
int rv;
#else
extern char *re_comp __P((const char *));
extern int re_exec __P((const char *));
#endif
if (strstr(str, pat) != NULL)
return 1;
#if defined(REGEX)
if (regcomp(&re, pat, 0) == 0) {
rv = regexec(&re, str, 0, NULL, 0) == 0;
regfree(&re);
} else {
rv = 0;
}
return rv;
#elif defined(REGEXP)
if ((re = regcomp(pat)) != NULL) {
rv = regexec(re, str);
free((ptr_t) re);
} else {
rv = 0;
}
return rv;
#else
if (re_comp(pat) != NULL)
return 0;
else
return re_exec(str) == 1;
#endif
}
/* c_hmatch():
* return True if the pattern matches the prefix
*/
protected int
c_hmatch(el, str)
EditLine *el;
const char *str;
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
el->el_search.patbuf, str);
#endif /* SDEBUG */
return el_match(str, el->el_search.patbuf);
}
/* c_setpat():
* Set the history seatch pattern
*/
protected void
c_setpat(el)
EditLine *el;
{
if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer;
if (el->el_search.patlen >= EL_BUFSIZ)
el->el_search.patlen = EL_BUFSIZ -1;
if (el->el_search.patlen >= 0) {
(void) strncpy(el->el_search.patbuf, el->el_line.buffer,
el->el_search.patlen);
el->el_search.patbuf[el->el_search.patlen] = '\0';
}
else
el->el_search.patlen = strlen(el->el_search.patbuf);
}
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno);
(void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
(void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf);
(void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
EL_CURSOR(el) - el->el_line.buffer,
el->el_line.lastchar - el->el_line.buffer);
#endif
}
/* ce_inc_search():
* Emacs incremental search
*/
protected el_action_t
ce_inc_search(el, dir)
EditLine *el;
int dir;
{
static char STRfwd[] = { 'f', 'w', 'd', '\0' },
STRbck[] = { 'b', 'c', 'k', '\0' };
static char pchar = ':'; /* ':' = normal, '?' = failed */
static char endcmd[2] = { '\0', '\0' };
char ch, *cp, *ocursor = el->el_line.cursor, oldpchar = pchar;
el_action_t ret = CC_NORM;
int ohisteventno = el->el_history.eventno,
oldpatlen = el->el_search.patlen,
newdir = dir,
done, redo;
if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
el->el_search.patlen >= el->el_line.limit)
return CC_ERROR;
for (;;) {
if (el->el_search.patlen == 0) { /* first round */
pchar = ':';
#ifdef ANCHOR
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
#endif
}
done = redo = 0;
*el->el_line.lastchar++ = '\n';
for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd;
*cp; *el->el_line.lastchar++ = *cp++)
continue;
*el->el_line.lastchar++ = pchar;
for (cp = &el->el_search.patbuf[1];
cp < &el->el_search.patbuf[el->el_search.patlen];
*el->el_line.lastchar++ = *cp++)
continue;
*el->el_line.lastchar = '\0';
re_refresh(el);
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
switch (el->el_map.current[(unsigned char) ch]) {
case ED_INSERT:
case ED_DIGIT:
if (el->el_search.patlen > EL_BUFSIZ - 3)
term_beep(el);
else {
el->el_search.patbuf[el->el_search.patlen++] = ch;
*el->el_line.lastchar++ = ch;
*el->el_line.lastchar = '\0';
re_refresh(el);
}
break;
case EM_INC_SEARCH_NEXT:
newdir = ED_SEARCH_NEXT_HISTORY;
redo++;
break;
case EM_INC_SEARCH_PREV:
newdir = ED_SEARCH_PREV_HISTORY;
redo++;
break;
case ED_DELETE_PREV_CHAR:
if (el->el_search.patlen > 1)
done++;
else
term_beep(el);
break;
default:
switch (ch) {
case 0007: /* ^G: Abort */
ret = CC_ERROR;
done++;
break;
case 0027: /* ^W: Append word */
/* No can do if globbing characters in pattern */
for (cp = &el->el_search.patbuf[1]; ; cp++)
if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
el->el_line.cursor += el->el_search.patlen - 1;
cp = c__next_word(el->el_line.cursor,
el->el_line.lastchar, 1, ce__isword);
while (el->el_line.cursor < cp &&
*el->el_line.cursor != '\n') {
if (el->el_search.patlen > EL_BUFSIZ - 3) {
term_beep(el);
break;
}
el->el_search.patbuf[el->el_search.patlen++] =
*el->el_line.cursor;
*el->el_line.lastchar++ = *el->el_line.cursor++;
}
el->el_line.cursor = ocursor;
*el->el_line.lastchar = '\0';
re_refresh(el);
break;
} else if (isglob(*cp)) {
term_beep(el);
break;
}
break;
default: /* Terminate and execute cmd */
endcmd[0] = ch;
el_push(el, endcmd);
/*FALLTHROUGH*/
case 0033: /* ESC: Terminate */
ret = CC_REFRESH;
done++;
break;
}
break;
}
while (el->el_line.lastchar > el->el_line.buffer &&
*el->el_line.lastchar != '\n')
*el->el_line.lastchar-- = '\0';
*el->el_line.lastchar = '\0';
if (!done) {
/* Can't search if unmatched '[' */
for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']';
cp > el->el_search.patbuf; cp--)
if (*cp == '[' || *cp == ']') {
ch = *cp;
break;
}
if (el->el_search.patlen > 1 && ch != '[') {
if (redo && newdir == dir) {
if (pchar == '?') { /* wrap around */
el->el_history.eventno =
newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
if (hist_get(el) == CC_ERROR)
/* el->el_history.eventno was fixed by first call */
(void) hist_get(el);
el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
el->el_line.lastchar : el->el_line.buffer;
} else
el->el_line.cursor +=
newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1;
}
#ifdef ANCHOR
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
#endif
el->el_search.patbuf[el->el_search.patlen] = '\0';
if (el->el_line.cursor < el->el_line.buffer ||
el->el_line.cursor > el->el_line.lastchar ||
(ret = ce_search_line(el, &el->el_search.patbuf[1],
newdir)) == CC_ERROR) {
/* avoid c_setpat */
el->el_state.lastcmd = (el_action_t) newdir;
ret = newdir == ED_SEARCH_PREV_HISTORY ?
ed_search_prev_history(el, 0) :
ed_search_next_history(el, 0);
if (ret != CC_ERROR) {
el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
el->el_line.lastchar : el->el_line.buffer;
(void) ce_search_line(el, &el->el_search.patbuf[1],
newdir);
}
}
el->el_search.patbuf[--el->el_search.patlen] = '\0';
if (ret == CC_ERROR) {
term_beep(el);
if (el->el_history.eventno != ohisteventno) {
el->el_history.eventno = ohisteventno;
if (hist_get(el) == CC_ERROR)
return CC_ERROR;
}
el->el_line.cursor = ocursor;
pchar = '?';
} else {
pchar = ':';
}
}
ret = ce_inc_search(el, newdir);
if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
/* break abort of failed search at last non-failed */
ret = CC_NORM;
}
if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
/* restore on normal return or error exit */
pchar = oldpchar;
el->el_search.patlen = oldpatlen;
if (el->el_history.eventno != ohisteventno) {
el->el_history.eventno = ohisteventno;
if (hist_get(el) == CC_ERROR)
return CC_ERROR;
}
el->el_line.cursor = ocursor;
if (ret == CC_ERROR)
re_refresh(el);
}
if (done || ret != CC_NORM)
return ret;
}
}
/* cv_search():
* Vi search.
*/
protected el_action_t
cv_search(el, dir)
EditLine *el;
int dir;
{
char ch;
char tmpbuf[EL_BUFSIZ];
int tmplen;
tmplen = 0;
#ifdef ANCHOR
tmpbuf[tmplen++] = '.';
tmpbuf[tmplen++] = '*';
#endif
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
el->el_search.patdir = dir;
c_insert(el, 2); /* prompt + '\n' */
*el->el_line.cursor++ = '\n';
*el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
re_refresh(el);
#ifdef ANCHOR
# define LEN 2
#else
# define LEN 0
#endif
tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
ch = tmpbuf[tmplen];
tmpbuf[tmplen] = '\0';
if (tmplen == LEN) {
/*
* Use the old pattern, but wild-card it.
*/
if (el->el_search.patlen == 0) {
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
re_refresh(el);
return CC_ERROR;
}
#ifdef ANCHOR
if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') {
(void)strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) - 1);
el->el_search.patbuf[0] = '.';
el->el_search.patbuf[1] = '*';
(void)strncpy(&el->el_search.patbuf[2], tmpbuf,
sizeof(el->el_search.patbuf) - 3);
el->el_search.patlen++;
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
el->el_search.patbuf[el->el_search.patlen] = '\0';
}
#endif
}
else {
#ifdef ANCHOR
tmpbuf[tmplen++] = '.';
tmpbuf[tmplen++] = '*';
#endif
tmpbuf[tmplen] = '\0';
(void)strncpy(el->el_search.patbuf, tmpbuf,
sizeof(el->el_search.patbuf) - 1);
el->el_search.patlen = tmplen;
}
el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
ed_search_next_history(el, 0)) == CC_ERROR) {
re_refresh(el);
return CC_ERROR;
}
else {
if (ch == 0033) {
re_refresh(el);
*el->el_line.lastchar++ = '\n';
*el->el_line.lastchar = '\0';
re_goto_bottom(el);
return CC_NEWLINE;
}
else
return CC_REFRESH;
}
}
/* ce_search_line():
* Look for a pattern inside a line
*/
protected el_action_t
ce_search_line(el, pattern, dir)
EditLine *el;
char *pattern;
int dir;
{
char *cp;
if (dir == ED_SEARCH_PREV_HISTORY) {
for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--)
if (el_match(cp, pattern)) {
el->el_line.cursor = cp;
return CC_NORM;
}
return CC_ERROR;
} else {
for (cp = el->el_line.cursor; *cp != '\0' &&
cp < el->el_line.limit; cp++)
if (el_match(cp, pattern)) {
el->el_line.cursor = cp;
return CC_NORM;
}
return CC_ERROR;
}
}
/* cv_repeat_srch():
* Vi repeat search
*/
protected el_action_t
cv_repeat_srch(el, c)
EditLine *el;
int c;
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
c, el->el_search.patlen, el->el_search.patbuf);
#endif
el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
el->el_line.lastchar = el->el_line.buffer;
switch (c) {
case ED_SEARCH_NEXT_HISTORY:
return ed_search_next_history(el, 0);
case ED_SEARCH_PREV_HISTORY:
return ed_search_prev_history(el, 0);
default:
return CC_ERROR;
}
}
/* cv_csearch_back():
* Vi character search reverse
*/
protected el_action_t
cv_csearch_back(el, ch, count, tflag)
EditLine *el;
int ch, count, tflag;
{
char *cp;
cp = el->el_line.cursor;
while (count--) {
if (*cp == ch)
cp--;
while (cp > el->el_line.buffer && *cp != ch)
cp--;
}
if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
return CC_ERROR;
if (*cp == ch && tflag)
cp++;
el->el_line.cursor = cp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
re_refresh_cursor(el);
return CC_NORM;
}
/* cv_csearch_fwd():
* Vi character search forward
*/
protected el_action_t
cv_csearch_fwd(el, ch, count, tflag)
EditLine *el;
int ch, count, tflag;
{
char *cp;
cp = el->el_line.cursor;
while (count--) {
if(*cp == ch)
cp++;
while (cp < el->el_line.lastchar && *cp != ch)
cp++;
}
if (cp >= el->el_line.lastchar)
return CC_ERROR;
if (*cp == ch && tflag)
cp--;
el->el_line.cursor = cp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
re_refresh_cursor(el);
return CC_NORM;
}

70
search.h Normal file
View File

@ -0,0 +1,70 @@
/* $NetBSD: search.h,v 1.2 1997/01/11 06:48:09 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)search.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.search.h: Line and history searching utilities
*/
#ifndef _h_el_search
#define _h_el_search
#include "histedit.h"
typedef struct el_search_t {
char *patbuf; /* The pattern buffer */
int patlen; /* Length of the pattern buffer */
int patdir; /* Direction of the last search */
int chadir; /* Character search direction */
char chacha; /* Character we are looking for */
} el_search_t;
protected int el_match __P((const char *, const char *));
protected int search_init __P((EditLine *));
protected void search_end __P((EditLine *));
protected int c_hmatch __P((EditLine *, const char *));
protected void c_setpat __P((EditLine *));
protected el_action_t ce_inc_search __P((EditLine *, int));
protected el_action_t cv_search __P((EditLine *, int));
protected el_action_t ce_search_line __P((EditLine *, char *, int));
protected el_action_t cv_repeat_srch __P((EditLine *, int));
protected el_action_t cv_csearch_back __P((EditLine *, int, int, int));
protected el_action_t cv_csearch_fwd __P((EditLine *, int, int, int));
#endif /* _h_el_search */

2
shlib_version Normal file
View File

@ -0,0 +1,2 @@
major=0
minor=0

199
sig.c Normal file
View File

@ -0,0 +1,199 @@
/* $NetBSD: sig.c,v 1.3 1997/04/11 17:52:48 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: sig.c,v 1.3 1997/04/11 17:52:48 christos Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* sig.c: Signal handling stuff.
* our policy is to trap all signals, set a good state
* and pass the ball to our caller.
*/
#include "sys.h"
#include "el.h"
#include <stdlib.h>
private EditLine *sel = NULL;
private int sighdl[] = {
#define _DO(a) (a),
ALLSIGS
#undef _DO
-1
};
private void sig_handler __P((int));
/* sig_handler():
* This is the handler called for all signals
* XXX: we cannot pass any data so we just store the old editline
* state in a private variable
*/
private void
sig_handler(signo)
int signo;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
(void) sigaddset(&nset, signo);
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
switch (signo) {
case SIGCONT:
tty_rawmode(sel);
if (ed_redisplay(sel, 0) == CC_REFRESH)
re_refresh(sel);
term__flush();
break;
case SIGWINCH:
el_resize(sel);
break;
default:
tty_cookedmode(sel);
break;
}
for (i = 0; sighdl[i] != -1; i++)
if (signo == sighdl[i])
break;
(void) signal(signo, sel->el_signal[i]);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
(void) kill(0, signo);
}
/* sig_init():
* Initialize all signal stuff
*/
protected int
sig_init(el)
EditLine *el;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
ALLSIGS
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
el->el_signal = (sig_t *) el_malloc(SIGSIZE);
for (i = 0; sighdl[i] != -1; i++)
el->el_signal[i] = SIG_ERR;
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
return 0;
}
/* sig_end():
* Clear all signal stuff
*/
protected void
sig_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_signal);
el->el_signal = NULL;
}
/* sig_set():
* set all the signal handlers
*/
protected void
sig_set(el)
EditLine *el;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
ALLSIGS
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
for (i = 0; sighdl[i] != -1; i++) {
sig_t s;
/* This could happen if we get interrupted */
if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
el->el_signal[i] = s;
}
sel = el;
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
}
/* sig_clr():
* clear all the signal handlers
*/
protected void
sig_clr(el)
EditLine *el;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
ALLSIGS
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
for (i = 0; sighdl[i] != -1; i++)
if (el->el_signal[i] != SIG_ERR)
(void) signal(sighdl[i], el->el_signal[i]);
sel = NULL; /* we are going to die if the handler is called */
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
}

72
sig.h Normal file
View File

@ -0,0 +1,72 @@
/* $NetBSD: sig.h,v 1.2 1997/01/11 06:48:11 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)sig.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.sig.h: Signal handling functions
*/
#ifndef _h_el_sig
#define _h_el_sig
#include <signal.h>
#include "histedit.h"
/*
* Define here all the signals we are going to handle
* The _DO macro is used to iterate in the source code
*/
#define ALLSIGS \
_DO(SIGINT) \
_DO(SIGTSTP) \
_DO(SIGSTOP) \
_DO(SIGQUIT) \
_DO(SIGHUP) \
_DO(SIGTERM) \
_DO(SIGCONT) \
_DO(SIGWINCH)
typedef sig_t *el_signal_t;
protected void sig_end __P((EditLine*));
protected int sig_init __P((EditLine*));
protected void sig_set __P((EditLine*));
protected void sig_clr __P((EditLine*));
#endif /* _h_el_sig */

118
sys.h Normal file
View File

@ -0,0 +1,118 @@
/* $NetBSD: sys.h,v 1.3 1997/01/11 06:48:12 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)sys.h 8.1 (Berkeley) 6/4/93
*/
/*
* sys.h: Put all the stupid compiler and system dependencies here...
*/
#ifndef _h_sys
#define _h_sys
#ifndef public
# define public /* Externally visible functions/variables */
#endif
#ifndef private
# define private static /* Always hidden internals */
#endif
#ifndef protected
# define protected /* Redefined from elsewhere to "static" */
/* When we want to hide everything */
#endif
#include <sys/cdefs.h>
#ifndef _PTR_T
# define _PTR_T
# if __STDC__
typedef void* ptr_t;
# else
typedef char* ptr_t;
# endif
#endif
#ifndef _IOCTL_T
# define _IOCTL_T
# if __STDC__
typedef void* ioctl_t;
# else
typedef char* ioctl_t;
# endif
#endif
#include <stdio.h>
#define REGEX /* Use POSIX.2 regular expression functions */
#undef REGEXP /* Use UNIX V8 regular expression functions */
#ifdef SUNOS
# undef REGEX
# undef REGEXP
# include <malloc.h>
typedef void (*sig_t)__P((int));
# ifdef __GNUC__
/*
* Broken hdrs.
*/
extern char *getenv __P((const char *));
extern int fprintf __P((FILE *, const char *, ...));
extern int sigsetmask __P((int));
extern int sigblock __P((int));
extern int ioctl __P((int, int, void *));
extern int fputc __P((int, FILE *));
extern int fgetc __P((FILE *));
extern int fflush __P((FILE *));
extern int tolower __P((int));
extern int toupper __P((int));
extern int errno, sys_nerr;
extern char *sys_errlist[];
extern void perror __P((const char *));
extern int read __P((int, const char*, int));
# include <string.h>
# define strerror(e) sys_errlist[e]
# endif
# ifdef SABER
extern ptr_t memcpy __P((ptr_t, const ptr_t, size_t));
extern ptr_t memset __P((ptr_t, int, size_t));
# endif
extern char *fgetline __P((FILE *, int *));
#endif
#endif /* _h_sys */

1465
term.c Normal file

File diff suppressed because it is too large Load Diff

120
term.h Normal file
View File

@ -0,0 +1,120 @@
/* $NetBSD: term.h,v 1.4 1997/01/11 06:48:14 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)term.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.term.h: Termcap header
*/
#ifndef _h_el_term
#define _h_el_term
#include "histedit.h"
typedef struct { /* Symbolic function key bindings */
char *name; /* name of the key */
int key; /* Index in termcap table */
key_value_t fun; /* Function bound to it */
int type; /* Type of function */
} fkey_t;
typedef struct {
coord_t t_size; /* # lines and cols */
bool_t t_flags;
#define TERM_CAN_INSERT 0x01 /* Has insert cap */
#define TERM_CAN_DELETE 0x02 /* Has delete cap */
#define TERM_CAN_CEOL 0x04 /* Has CEOL cap */
#define TERM_CAN_TAB 0x08 /* Can use tabs */
#define TERM_CAN_ME 0x10 /* Can turn all attrs. */
#define TERM_CAN_UP 0x20 /* Can move up */
#define TERM_HAS_META 0x40 /* Has a meta key */
char *t_buf; /* Termcap buffer */
int t_loc; /* location used */
char **t_str; /* termcap strings */
int *t_val; /* termcap values */
char *t_cap; /* Termcap buffer */
fkey_t *t_fkey; /* Array of keys */
} el_term_t;
/*
* fKey indexes
*/
#define A_K_DN 0
#define A_K_UP 1
#define A_K_LT 2
#define A_K_RT 3
#define A_K_NKEYS 4
protected void term_move_to_line __P((EditLine *, int));
protected void term_move_to_char __P((EditLine *, int));
protected void term_clear_EOL __P((EditLine *, int));
protected void term_overwrite __P((EditLine *, char *, int));
protected void term_insertwrite __P((EditLine *, char *, int));
protected void term_deletechars __P((EditLine *, int));
protected void term_clear_screen __P((EditLine *));
protected void term_beep __P((EditLine *));
protected void term_change_size __P((EditLine *, int, int));
protected int term_get_size __P((EditLine *, int *, int *));
protected int term_init __P((EditLine *));
protected void term_bind_arrow __P((EditLine *));
protected void term_print_arrow __P((EditLine *, char *));
protected int term_clear_arrow __P((EditLine *, char *));
protected int term_set_arrow __P((EditLine *, char *,
key_value_t *, int));
protected void term_end __P((EditLine *));
protected int term_set __P((EditLine *, char *));
protected int term_settc __P((EditLine *, int, char **));
protected int term_telltc __P((EditLine *, int, char **));
protected int term_echotc __P((EditLine *, int, char **));
protected void term__putc __P((int));
protected void term__flush __P((void));
/*
* Easy access macros
*/
#define EL_FLAGS (el)->el_term.t_flags
#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT)
#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE)
#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL)
#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB)
#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME)
#define EL_HAS_META (EL_FLAGS & TERM_HAS_META)
#endif /* _h_el_term */

54
termcap.h Normal file
View File

@ -0,0 +1,54 @@
/* $NetBSD: termcap.h,v 1.2 1997/01/11 06:48:14 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)termcap.h 8.1 (Berkeley) 6/4/93
*/
/*
* termcap.h: I cannot find those in any include files...
*/
#ifndef _h_termcap
#define _h_termcap
int tgetent __P((char *, char *));
char *tgetstr __P((char *, char **));
int tgetflag __P((char *));
int tgetnum __P((char *));
char *tgoto __P((char *, int, int));
char *tputs __P((char *, int, void (*)(int)));
#endif /* _h_termcap */

391
tokenizer.c Normal file
View File

@ -0,0 +1,391 @@
/* $NetBSD: tokenizer.c,v 1.2 1997/01/11 06:48:15 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: tokenizer.c,v 1.2 1997/01/11 06:48:15 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* tokenize.c: Bourne shell like tokenizer
*/
#include "sys.h"
#include <string.h>
#include <stdlib.h>
#include "tokenizer.h"
typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone } quote_t;
#define IFS "\t \n"
#define TOK_KEEP 1
#define TOK_EAT 2
#define WINCR 20
#define AINCR 10
#define tok_malloc(a) malloc(a)
#define tok_free(a) free(a)
#define tok_realloc(a, b) realloc(a, b)
struct tokenizer {
char *ifs; /* In field separator */
int argc, amax; /* Current and maximum number of args */
char **argv; /* Argument list */
char *wptr, *wmax; /* Space and limit on the word buffer */
char *wstart; /* Beginning of next word */
char *wspace; /* Space of word buffer */
quote_t quote; /* Quoting state */
int flags; /* flags; */
};
private void tok_finish __P((Tokenizer *));
/* tok_finish():
* Finish a word in the tokenizer.
*/
private void
tok_finish(tok)
Tokenizer *tok;
{
*tok->wptr = '\0';
if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) {
tok->argv[tok->argc++] = tok->wstart;
tok->argv[tok->argc] = NULL;
tok->wstart = ++tok->wptr;
}
tok->flags &= ~TOK_KEEP;
}
/* tok_init():
* Initialize the tokenizer
*/
public Tokenizer *
tok_init(ifs)
const char *ifs;
{
Tokenizer* tok = (Tokenizer*) tok_malloc(sizeof(Tokenizer));
tok->ifs = strdup(ifs ? ifs : IFS);
tok->argc = 0;
tok->amax = AINCR;
tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
tok->argv[0] = NULL;
tok->wspace = (char *) tok_malloc(WINCR);
tok->wmax = tok->wspace + WINCR;
tok->wstart = tok->wspace;
tok->wptr = tok->wspace;
tok->flags = 0;
tok->quote = Q_none;
return tok;
}
/* tok_reset():
* Reset the tokenizer
*/
public void
tok_reset(tok)
Tokenizer *tok;
{
tok->argc = 0;
tok->wstart = tok->wspace;
tok->wptr = tok->wspace;
tok->flags = 0;
tok->quote = Q_none;
}
/* tok_end():
* Clean up
*/
public void
tok_end(tok)
Tokenizer *tok;
{
tok_free((ptr_t) tok->ifs);
tok_free((ptr_t) tok->wspace);
tok_free((ptr_t) tok->argv);
tok_free((ptr_t) tok);
}
/* tok_line():
* Bourne shell like tokenizing
* Return:
* -1: Internal error
* 3: Quoted return
* 2: Unmatched double quote
* 1: Unmatched single quote
* 0: Ok
*/
public int
tok_line(tok, line, argc, argv)
Tokenizer *tok;
const char* line;
int *argc;
char ***argv;
{
const char *ptr;
while (1) {
switch (*(ptr = line++)) {
case '\'':
tok->flags |= TOK_KEEP;
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
tok->quote = Q_single; /* Enter single quote mode */
break;
case Q_single: /* Exit single quote mode */
tok->quote = Q_none;
break;
case Q_one: /* Quote this ' */
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
case Q_double: /* Stay in double quote mode */
*tok->wptr++ = *ptr;
break;
case Q_doubleone: /* Quote this ' */
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
case '"':
tok->flags &= ~TOK_EAT;
tok->flags |= TOK_KEEP;
switch (tok->quote) {
case Q_none: /* Enter double quote mode */
tok->quote = Q_double;
break;
case Q_double:
tok->quote = Q_none; /* Exit double quote mode */
break;
case Q_one: /* Quote this " */
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
case Q_single: /* Stay in single quote mode */
*tok->wptr++ = *ptr;
break;
case Q_doubleone: /* Quote this " */
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
case '\\':
tok->flags |= TOK_KEEP;
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none: /* Quote next character */
tok->quote = Q_one;
break;
case Q_double:
tok->quote = Q_doubleone;/* Quote next character */
break;
case Q_one:
*tok->wptr++ = *ptr;
tok->quote = Q_none; /* Quote this, restore state */
break;
case Q_single: /* Stay in single quote mode */
*tok->wptr++ = *ptr;
break;
case Q_doubleone: /* Quote this \ */
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
case '\n':
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
tok_finish(tok);
*argv = tok->argv;
*argc = tok->argc;
return(0);
case Q_single:
case Q_double:
*tok->wptr++ = *ptr; /* Add the return */
break;
case Q_doubleone:
tok->flags |= TOK_EAT;
tok->quote = Q_double; /* Back to double, eat the '\n' */
break;
case Q_one:
tok->flags |= TOK_EAT;
tok->quote = Q_none; /* No quote, more eat the '\n' */
break;
default:
return(0);
}
break;
case '\0':
switch (tok->quote) {
case Q_none:
/* Finish word and return */
if (tok->flags & TOK_EAT) {
tok->flags &= ~TOK_EAT;
return 3;
}
tok_finish(tok);
*argv = tok->argv;
*argc = tok->argc;
return(0);
case Q_single:
return(1);
case Q_double:
return(2);
case Q_doubleone:
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
case Q_one:
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
default:
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
if (strchr(tok->ifs, *ptr) != NULL)
tok_finish(tok);
else
*tok->wptr++ = *ptr;
break;
case Q_single:
case Q_double:
*tok->wptr++ = *ptr;
break;
case Q_doubleone:
*tok->wptr++ = '\\';
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
case Q_one:
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
}
if (tok->wptr >= tok->wmax - 4) {
size_t size = tok->wmax - tok->wspace + WINCR;
char *s = (char *) tok_realloc(tok->wspace, size);
/*SUPPRESS 22*/
int offs = s - tok->wspace;
if (offs != 0) {
int i;
for (i = 0; i < tok->argc; i++)
tok->argv[i] = tok->argv[i] + offs;
tok->wptr = tok->wptr + offs;
tok->wstart = tok->wstart + offs;
tok->wmax = s + size;
tok->wspace = s;
}
}
if (tok->argc >= tok->amax - 4) {
tok->amax += AINCR;
tok->argv = (char **) tok_realloc(tok->argv,
tok->amax * sizeof(char*));
}
}
}

55
tokenizer.h Normal file
View File

@ -0,0 +1,55 @@
/* $NetBSD: tokenizer.h,v 1.2 1997/01/11 06:48:16 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)tokenizer.h 8.1 (Berkeley) 6/4/93
*/
/*
* tokenizer.h: Header file for tokenizer routines
*/
#ifndef _h_tokenizer
#define _h_tokenizer
typedef struct tokenizer Tokenizer;
Tokenizer *tok_init __P((const char *));
void tok_reset __P((Tokenizer *));
void tok_end __P((Tokenizer *));
int tok_line __P((Tokenizer *, const char *,
int *, char ***));
#endif /* _h_tokenizer */

1150
tty.c Normal file

File diff suppressed because it is too large Load Diff

483
tty.h Normal file
View File

@ -0,0 +1,483 @@
/* $NetBSD: tty.h,v 1.4 1997/04/11 21:38:02 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)tty.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.tty.h: Local terminal header
*/
#ifndef _h_el_tty
#define _h_el_tty
#include "histedit.h"
#include <termios.h>
/* Define our own since everyone gets it wrong! */
#define CONTROL(A) ((A) & 037)
/*
* Aix compatible names
*/
# if defined(VWERSE) && !defined(VWERASE)
# define VWERASE VWERSE
# endif /* VWERSE && !VWERASE */
# if defined(VDISCRD) && !defined(VDISCARD)
# define VDISCARD VDISCRD
# endif /* VDISCRD && !VDISCARD */
# if defined(VFLUSHO) && !defined(VDISCARD)
# define VDISCARD VFLUSHO
# endif /* VFLUSHO && VDISCARD */
# if defined(VSTRT) && !defined(VSTART)
# define VSTART VSTRT
# endif /* VSTRT && ! VSTART */
# if defined(VSTAT) && !defined(VSTATUS)
# define VSTATUS VSTAT
# endif /* VSTAT && ! VSTATUS */
# ifndef ONLRET
# define ONLRET 0
# endif /* ONLRET */
# ifndef TAB3
# ifdef OXTABS
# define TAB3 OXTABS
# else
# define TAB3 0
# endif /* OXTABS */
# endif /* !TAB3 */
# if defined(OXTABS) && !defined(XTABS)
# define XTABS OXTABS
# endif /* OXTABS && !XTABS */
# ifndef ONLCR
# define ONLCR 0
# endif /* ONLCR */
# ifndef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN */
# ifndef ECHOCTL
# define ECHOCTL 0
# endif /* ECHOCTL */
# ifndef PARENB
# define PARENB 0
# endif /* PARENB */
# ifndef EXTPROC
# define EXTPROC 0
# endif /* EXTPROC */
# ifndef FLUSHO
# define FLUSHO 0
# endif /* FLUSHO */
# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
# define _POSIX_VDISABLE VDISABLE
# endif /* VDISABLE && ! _POSIX_VDISABLE */
/*
* Work around ISC's definition of IEXTEN which is
* XCASE!
*/
# ifdef ISC
# if defined(IEXTEN) && defined(XCASE)
# if IEXTEN == XCASE
# undef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN == XCASE */
# endif /* IEXTEN && XCASE */
# if defined(IEXTEN) && !defined(XCASE)
# define XCASE IEXTEN
# undef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN && !XCASE */
# endif /* ISC */
/*
* Work around convex weirdness where turning off IEXTEN makes us
* lose all postprocessing!
*/
#if defined(convex) || defined(__convex__)
# if defined(IEXTEN) && IEXTEN != 0
# undef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN != 0 */
#endif /* convex || __convex__ */
/*
* So that we don't lose job control.
*/
#ifdef __SVR4
# undef CSWTCH
#endif
#ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE ((unsigned char) -1)
#endif /* _POSIX_VDISABLE */
#if !defined(CREPRINT) && defined(CRPRNT)
# define CREPRINT CRPRNT
#endif /* !CREPRINT && CRPRNT */
#if !defined(CDISCARD) && defined(CFLUSH)
# define CDISCARD CFLUSH
#endif /* !CDISCARD && CFLUSH */
#ifndef CINTR
# define CINTR CONTROL('c')
#endif /* CINTR */
#ifndef CQUIT
# define CQUIT 034 /* ^\ */
#endif /* CQUIT */
#ifndef CERASE
# define CERASE 0177 /* ^? */
#endif /* CERASE */
#ifndef CKILL
# define CKILL CONTROL('u')
#endif /* CKILL */
#ifndef CEOF
# define CEOF CONTROL('d')
#endif /* CEOF */
#ifndef CEOL
# define CEOL _POSIX_VDISABLE
#endif /* CEOL */
#ifndef CEOL2
# define CEOL2 _POSIX_VDISABLE
#endif /* CEOL2 */
#ifndef CSWTCH
# define CSWTCH _POSIX_VDISABLE
#endif /* CSWTCH */
#ifndef CDSWTCH
# define CDSWTCH _POSIX_VDISABLE
#endif /* CDSWTCH */
#ifndef CERASE2
# define CERASE2 _POSIX_VDISABLE
#endif /* CERASE2 */
#ifndef CSTART
# define CSTART CONTROL('q')
#endif /* CSTART */
#ifndef CSTOP
# define CSTOP CONTROL('s')
#endif /* CSTOP */
#ifndef CSUSP
# define CSUSP CONTROL('z')
#endif /* CSUSP */
#ifndef CDSUSP
# define CDSUSP CONTROL('y')
#endif /* CDSUSP */
#ifdef hpux
# ifndef CREPRINT
# define CREPRINT _POSIX_VDISABLE
# endif /* CREPRINT */
# ifndef CDISCARD
# define CDISCARD _POSIX_VDISABLE
# endif /* CDISCARD */
# ifndef CLNEXT
# define CLNEXT _POSIX_VDISABLE
# endif /* CLNEXT */
# ifndef CWERASE
# define CWERASE _POSIX_VDISABLE
# endif /* CWERASE */
#else /* !hpux */
# ifndef CREPRINT
# define CREPRINT CONTROL('r')
# endif /* CREPRINT */
# ifndef CDISCARD
# define CDISCARD CONTROL('o')
# endif /* CDISCARD */
# ifndef CLNEXT
# define CLNEXT CONTROL('v')
# endif /* CLNEXT */
# ifndef CWERASE
# define CWERASE CONTROL('w')
# endif /* CWERASE */
#endif /* hpux */
#ifndef CSTATUS
# define CSTATUS CONTROL('t')
#endif /* CSTATUS */
#ifndef CPAGE
# define CPAGE ' '
#endif /* CPAGE */
#ifndef CPGOFF
# define CPGOFF CONTROL('m')
#endif /* CPGOFF */
#ifndef CKILL2
# define CKILL2 _POSIX_VDISABLE
#endif /* CKILL2 */
#ifndef CBRK
# ifndef masscomp
# define CBRK 0377
# else
# define CBRK '\0'
# endif /* masscomp */
#endif /* CBRK */
#ifndef CMIN
# define CMIN CEOF
#endif /* CMIN */
#ifndef CTIME
# define CTIME CEOL
#endif /* CTIME */
/*
* Fix for sun inconsistency. On termio VSUSP and the rest of the
* ttychars > NCC are defined. So we undefine them.
*/
#if defined(TERMIO) || defined(POSIX)
# if defined(POSIX) && defined(NCCS)
# define NUMCC NCCS
# else
# ifdef NCC
# define NUMCC NCC
# endif /* NCC */
# endif /* POSIX && NCCS */
# ifdef NUMCC
# ifdef VINTR
# if NUMCC <= VINTR
# undef VINTR
# endif /* NUMCC <= VINTR */
# endif /* VINTR */
# ifdef VQUIT
# if NUMCC <= VQUIT
# undef VQUIT
# endif /* NUMCC <= VQUIT */
# endif /* VQUIT */
# ifdef VERASE
# if NUMCC <= VERASE
# undef VERASE
# endif /* NUMCC <= VERASE */
# endif /* VERASE */
# ifdef VKILL
# if NUMCC <= VKILL
# undef VKILL
# endif /* NUMCC <= VKILL */
# endif /* VKILL */
# ifdef VEOF
# if NUMCC <= VEOF
# undef VEOF
# endif /* NUMCC <= VEOF */
# endif /* VEOF */
# ifdef VEOL
# if NUMCC <= VEOL
# undef VEOL
# endif /* NUMCC <= VEOL */
# endif /* VEOL */
# ifdef VEOL2
# if NUMCC <= VEOL2
# undef VEOL2
# endif /* NUMCC <= VEOL2 */
# endif /* VEOL2 */
# ifdef VSWTCH
# if NUMCC <= VSWTCH
# undef VSWTCH
# endif /* NUMCC <= VSWTCH */
# endif /* VSWTCH */
# ifdef VDSWTCH
# if NUMCC <= VDSWTCH
# undef VDSWTCH
# endif /* NUMCC <= VDSWTCH */
# endif /* VDSWTCH */
# ifdef VERASE2
# if NUMCC <= VERASE2
# undef VERASE2
# endif /* NUMCC <= VERASE2 */
# endif /* VERASE2 */
# ifdef VSTART
# if NUMCC <= VSTART
# undef VSTART
# endif /* NUMCC <= VSTART */
# endif /* VSTART */
# ifdef VSTOP
# if NUMCC <= VSTOP
# undef VSTOP
# endif /* NUMCC <= VSTOP */
# endif /* VSTOP */
# ifdef VWERASE
# if NUMCC <= VWERASE
# undef VWERASE
# endif /* NUMCC <= VWERASE */
# endif /* VWERASE */
# ifdef VSUSP
# if NUMCC <= VSUSP
# undef VSUSP
# endif /* NUMCC <= VSUSP */
# endif /* VSUSP */
# ifdef VDSUSP
# if NUMCC <= VDSUSP
# undef VDSUSP
# endif /* NUMCC <= VDSUSP */
# endif /* VDSUSP */
# ifdef VREPRINT
# if NUMCC <= VREPRINT
# undef VREPRINT
# endif /* NUMCC <= VREPRINT */
# endif /* VREPRINT */
# ifdef VDISCARD
# if NUMCC <= VDISCARD
# undef VDISCARD
# endif /* NUMCC <= VDISCARD */
# endif /* VDISCARD */
# ifdef VLNEXT
# if NUMCC <= VLNEXT
# undef VLNEXT
# endif /* NUMCC <= VLNEXT */
# endif /* VLNEXT */
# ifdef VSTATUS
# if NUMCC <= VSTATUS
# undef VSTATUS
# endif /* NUMCC <= VSTATUS */
# endif /* VSTATUS */
# ifdef VPAGE
# if NUMCC <= VPAGE
# undef VPAGE
# endif /* NUMCC <= VPAGE */
# endif /* VPAGE */
# ifdef VPGOFF
# if NUMCC <= VPGOFF
# undef VPGOFF
# endif /* NUMCC <= VPGOFF */
# endif /* VPGOFF */
# ifdef VKILL2
# if NUMCC <= VKILL2
# undef VKILL2
# endif /* NUMCC <= VKILL2 */
# endif /* VKILL2 */
# ifdef VBRK
# if NUMCC <= VBRK
# undef VBRK
# endif /* NUMCC <= VBRK */
# endif /* VBRK */
# ifdef VMIN
# if NUMCC <= VMIN
# undef VMIN
# endif /* NUMCC <= VMIN */
# endif /* VMIN */
# ifdef VTIME
# if NUMCC <= VTIME
# undef VTIME
# endif /* NUMCC <= VTIME */
# endif /* VTIME */
# endif /* NUMCC */
#endif /* !POSIX */
#define C_INTR 0
#define C_QUIT 1
#define C_ERASE 2
#define C_KILL 3
#define C_EOF 4
#define C_EOL 5
#define C_EOL2 6
#define C_SWTCH 7
#define C_DSWTCH 8
#define C_ERASE2 9
#define C_START 10
#define C_STOP 11
#define C_WERASE 12
#define C_SUSP 13
#define C_DSUSP 14
#define C_REPRINT 15
#define C_DISCARD 16
#define C_LNEXT 17
#define C_STATUS 18
#define C_PAGE 19
#define C_PGOFF 20
#define C_KILL2 21
#define C_BRK 22
#define C_MIN 23
#define C_TIME 24
#define C_NCC 25
#define C_SH(A) (1 << (A))
/*
* Terminal dependend data structures
*/
#define EX_IO 0 /* while we are executing */
#define ED_IO 1 /* while we are editing */
#define TS_IO 2 /* new mode from terminal */
#define QU_IO 2 /* used only for quoted chars */
#define NN_IO 3 /* The number of entries */
#define M_INP 0
#define M_OUT 1
#define M_CTL 2
#define M_LIN 3
#define M_CHAR 4
#define M_NN 5
typedef struct {
char *t_name;
u_int t_setmask;
u_int t_clrmask;
} ttyperm_t[NN_IO][M_NN];
typedef unsigned char ttychar_t[NN_IO][C_NCC];
protected int tty_init __P((EditLine *));
protected void tty_end __P((EditLine *));
protected int tty_stty __P((EditLine *, int, char**));
protected int tty_rawmode __P((EditLine *));
protected int tty_cookedmode __P((EditLine *));
protected int tty_quotemode __P((EditLine *));
protected int tty_noquotemode __P((EditLine *));
protected void tty_bind_char __P((EditLine *, int));
typedef struct {
ttyperm_t t_t;
ttychar_t t_c;
struct termios t_ex, t_ed, t_ts;
int t_tabs;
int t_eight;
speed_t t_speed;
int t_mode;
unsigned char t_vdisable;
} el_tty_t;
#endif /* _h_el_tty */

992
vi.c Normal file
View File

@ -0,0 +1,992 @@
/* $NetBSD: vi.c,v 1.2 1997/01/11 06:48:19 lukem Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
#else
static char rcsid[] = "$NetBSD: vi.c,v 1.2 1997/01/11 06:48:19 lukem Exp $";
#endif
#endif /* not lint && not SCCSID */
/*
* vi.c: Vi mode commands.
*/
#include "sys.h"
#include "el.h"
private el_action_t cv_action __P((EditLine *, int));
/* cv_action():
* Handle vi actions.
*/
private el_action_t
cv_action(el, c)
EditLine *el;
int c;
{
register char *cp, *kp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
kp = el->el_chared.c_undo.buf;
for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
*kp++ = *cp;
el->el_chared.c_undo.dsize++;
}
el->el_chared.c_undo.action = INSERT;
el->el_chared.c_undo.ptr = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (c & INSERT)
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
el->el_chared.c_vcmd.pos = el->el_line.cursor;
el->el_chared.c_vcmd.action = c;
return CC_ARGHACK;
#ifdef notdef
/*
* I don't think that this is needed. But we keep it for now
*/
else if (el_chared.c_vcmd.action == NOP) {
el->el_chared.c_vcmd.pos = el->el_line.cursor;
el->el_chared.c_vcmd.action = c;
return CC_ARGHACK;
}
else {
el->el_chared.c_vcmd.action = 0;
el->el_chared.c_vcmd.pos = 0;
return CC_ERROR;
}
#endif
}
/* cv_paste():
* Paste previous deletion before or after the cursor
*/
protected el_action_t
cv_paste(el, c)
EditLine *el;
int c;
{
char *ptr;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_PASTE
(void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
if (un->isize == 0)
return CC_ERROR;
if (!c && el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
ptr = el->el_line.cursor;
c_insert(el, un->isize);
if (el->el_line.cursor + un->isize > el->el_line.lastchar)
return CC_ERROR;
(void) memcpy(ptr, un->buf, un->isize);
return CC_REFRESH;
}
/* vi_paste_next():
* Vi paste previous deletion to the right of the cursor
* [p]
*/
protected el_action_t
/*ARGSUSED*/
vi_paste_next(el, c)
EditLine *el;
int c;
{
return cv_paste(el, 0);
}
/* vi_paste_prev():
* Vi paste previous deletion to the left of the cursor
* [P]
*/
protected el_action_t
/*ARGSUSED*/
vi_paste_prev(el, c)
EditLine *el;
int c;
{
return cv_paste(el, 1);
}
/* vi_prev_space_word():
* Vi move to the previous space delimited word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_space_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
cv__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_prev_word():
* Vi move to the previous word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
ce__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_next_space_word():
* Vi move to the next space delimited word
* [W]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_space_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
cv__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_next_word():
* Vi move to the next word
* [w]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
ce__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_change_case():
* Vi change case of character under the cursor and advance one character
* [~]
*/
protected el_action_t
vi_change_case(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor < el->el_line.lastchar) {
c = *el->el_line.cursor;
if (isupper(c))
*el->el_line.cursor++ = tolower(c);
else if (islower(c))
*el->el_line.cursor++ = toupper(c);
else
el->el_line.cursor++;
re_fastaddc(el);
return CC_NORM;
}
return CC_ERROR;
}
/* vi_change_meta():
* Vi change prefix command
* [c]
*/
protected el_action_t
/*ARGSUSED*/
vi_change_meta(el, c)
EditLine *el;
int c;
{
/*
* Delete with insert == change: first we delete and then we leave in
* insert mode.
*/
return cv_action(el, DELETE|INSERT);
}
/* vi_insert_at_bol():
* Vi enter insert mode at the beginning of line
* [I]
*/
protected el_action_t
/*ARGSUSED*/
vi_insert_at_bol(el, c)
EditLine *el;
int c;
{
el->el_line.cursor = el->el_line.buffer;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
el->el_map.current = el->el_map.key;
return CC_CURSOR;
}
/* vi_replace_char():
* Vi replace character under the cursor with the next character typed
* [r]
*/
protected el_action_t
/*ARGSUSED*/
vi_replace_char(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE_1;
el->el_chared.c_undo.action = CHANGE;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
return CC_NORM;
}
/* vi_replace_mode():
* Vi enter replace mode
* [R]
*/
protected el_action_t
/*ARGSUSED*/
vi_replace_mode(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE;
el->el_chared.c_undo.action = CHANGE;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
return CC_NORM;
}
/* vi_substitute_char():
* Vi replace character under the cursor and enter insert mode
* [r]
*/
protected el_action_t
/*ARGSUSED*/
vi_substitute_char(el, c)
EditLine *el;
int c;
{
c_delafter(el, el->el_state.argument);
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
/* vi_substitute_line():
* Vi substitute entire line
* [S]
*/
protected el_action_t
/*ARGSUSED*/
vi_substitute_line(el, c)
EditLine *el;
int c;
{
(void) em_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
/* vi_change_to_eol():
* Vi change to end of line
* [C]
*/
protected el_action_t
/*ARGSUSED*/
vi_change_to_eol(el, c)
EditLine *el;
int c;
{
(void) ed_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
/* vi_insert():
* Vi enter insert mode
* [i]
*/
protected el_action_t
/*ARGSUSED*/
vi_insert(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
return CC_NORM;
}
/* vi_add():
* Vi enter insert mode after the cursor
* [a]
*/
protected el_action_t
/*ARGSUSED*/
vi_add(el, c)
EditLine *el;
int c;
{
int ret;
el->el_map.current = el->el_map.key;
if (el->el_line.cursor < el->el_line.lastchar) {
el->el_line.cursor++;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
ret = CC_CURSOR;
}
else
ret = CC_NORM;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
return ret;
}
/* vi_add_at_eol():
* Vi enter insert mode at end of line
* [A]
*/
protected el_action_t
/*ARGSUSED*/
vi_add_at_eol(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_line.cursor = el->el_line.lastchar;
/* Mark where insertion begins */
el->el_chared.c_vcmd.ins = el->el_line.lastchar;
el->el_chared.c_undo.ptr = el->el_line.lastchar;
el->el_chared.c_undo.action = DELETE;
return CC_CURSOR;
}
/* vi_delete_meta():
* Vi delete prefix command
* [d]
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_meta(el, c)
EditLine *el;
int c;
{
return cv_action(el, DELETE);
}
/* vi_end_word():
* Vi move to the end of the current space delimited word
* [E]
*/
protected el_action_t
/*ARGSUSED*/
vi_end_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_to_end_word():
* Vi move to the end of the current word
* [e]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_end_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_undo():
* Vi undo last change
* [u]
*/
protected el_action_t
/*ARGSUSED*/
vi_undo(el, c)
EditLine *el;
int c;
{
char *cp, *kp;
char temp;
int i, size;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_UNDO
(void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
switch (un->action) {
case DELETE:
if (un->dsize == 0)
return CC_NORM;
(void) memcpy(un->buf, un->ptr, un->dsize);
for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
*cp = cp[un->dsize];
el->el_line.lastchar -= un->dsize;
el->el_line.cursor = un->ptr;
un->action = INSERT;
un->isize = un->dsize;
un->dsize = 0;
break;
case DELETE|INSERT:
size = un->isize - un->dsize;
if (size > 0)
i = un->dsize;
else
i = un->isize;
cp = un->ptr;
kp = un->buf;
while (i-- > 0) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
if (size > 0) {
el->el_line.cursor = cp;
c_insert(el, size);
while (size-- > 0 && cp < el->el_line.lastchar) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
}
else if (size < 0) {
size = -size;
for (; cp <= el->el_line.lastchar; cp++) {
*kp++ = *cp;
*cp = cp[size];
}
el->el_line.lastchar -= size;
}
el->el_line.cursor = un->ptr;
i = un->dsize;
un->dsize = un->isize;
un->isize = i;
break;
case INSERT:
if (un->isize == 0)
return CC_NORM;
el->el_line.cursor = un->ptr;
c_insert(el, un->isize);
memcpy(un->ptr, un->buf, un->isize);
un->action = DELETE;
un->dsize = un->isize;
un->isize = 0;
break;
case CHANGE:
if (un->isize == 0)
return CC_NORM;
el->el_line.cursor = un->ptr;
size = (int) (el->el_line.cursor - el->el_line.lastchar);
if (size < un->isize)
size = un->isize;
cp = un->ptr;
kp = un->buf;
for(i = 0; i < size; i++) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
un->dsize = 0;
break;
default:
return CC_ERROR;
}
return CC_REFRESH;
}
/* vi_command_mode():
* Vi enter command mode (use alternative key bindings)
* [<ESC>]
*/
protected el_action_t
/*ARGSUSED*/
vi_command_mode(el, c)
EditLine *el;
int c;
{
int size;
/* [Esc] cancels pending action */
el->el_chared.c_vcmd.ins = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_state.doingarg = 0;
size = el->el_chared.c_undo.ptr - el->el_line.cursor;
if (size < 0)
size = -size;
if (el->el_chared.c_undo.action == (INSERT|DELETE) ||
el->el_chared.c_undo.action == DELETE)
el->el_chared.c_undo.dsize = size;
else
el->el_chared.c_undo.isize = size;
el->el_state.inputmode = MODE_INSERT;
el->el_map.current = el->el_map.alt;
#ifdef VI_MOVE
if (el->el_line.cursor > el->el_line.buffer)
el->el_line.cursor--;
#endif
return CC_CURSOR;
}
/* vi_zero():
* Vi move to the beginning of line
* [0]
*/
protected el_action_t
vi_zero(el, c)
EditLine *el;
int c;
{
if (el->el_state.doingarg) {
if (el->el_state.argument > 1000000)
return CC_ERROR;
el->el_state.argument =
(el->el_state.argument * 10) + (c - '0');
return CC_ARGHACK;
}
else {
el->el_line.cursor = el->el_line.buffer;
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
}
/* vi_delete_prev_char():
* Vi move to previous character (backspace)
* [^H]
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_prev_char(el, c)
EditLine *el;
int c;
{
if (el->el_chared.c_vcmd.ins == 0)
return CC_ERROR;
if (el->el_chared.c_vcmd.ins >
el->el_line.cursor - el->el_state.argument)
return CC_ERROR;
c_delbefore(el, el->el_state.argument);
el->el_line.cursor -= el->el_state.argument;
return CC_REFRESH;
} /* end v_del_char_prev */
/* vi_list_or_eof():
* Vi list choices for completion or indicate end of file if empty line
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
vi_list_or_eof(el, c)
EditLine *el;
int c;
{
#ifdef notyet
if (el->el_line.cursor == el->el_line.lastchar &&
el->el_line.cursor == el->el_line.buffer) {
#endif
term_overwrite(el, STReof, 4); /* then do a EOF */
term__flush();
return CC_EOF;
#ifdef notyet
}
else {
re_goto_bottom(el);
*el->el_line.lastchar = '\0'; /* just in case */
return CC_LIST_CHOICES;
}
#endif
}
/* vi_kill_line_prev():
* Vi cut from beginning of line to cursor
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
vi_kill_line_prev(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
cp = el->el_line.buffer;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_line.cursor)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
el->el_line.cursor = el->el_line.buffer; /* zap! */
return CC_REFRESH;
}
/* vi_search_prev():
* Vi search history previous
* [?]
*/
protected el_action_t
/*ARGSUSED*/
vi_search_prev(el, c)
EditLine *el;
int c;
{
return cv_search(el, ED_SEARCH_PREV_HISTORY);
}
/* vi_search_next():
* Vi search history next
* [/]
*/
protected el_action_t
/*ARGSUSED*/
vi_search_next(el, c)
EditLine *el;
int c;
{
return cv_search(el, ED_SEARCH_NEXT_HISTORY);
}
/* vi_repeat_search_next():
* Vi repeat current search in the same search direction
* [n]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_search_next(el, c)
EditLine *el;
int c;
{
if (el->el_search.patlen == 0)
return CC_ERROR;
else
return cv_repeat_srch(el, el->el_search.patdir);
}
/* vi_repeat_search_prev():
* Vi repeat current search in the opposite search direction
* [N]
*/
/*ARGSUSED*/
protected el_action_t
vi_repeat_search_prev(el, c)
EditLine *el;
int c;
{
if (el->el_search.patlen == 0)
return CC_ERROR;
else
return cv_repeat_srch(el,
el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY);
}
/* vi_next_char():
* Vi move to the character specified next
* [f]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
el->el_search.chadir = CHAR_FWD;
el->el_search.chacha = ch;
return cv_csearch_fwd(el, ch, el->el_state.argument, 0);
}
/* vi_prev_char():
* Vi move to the character specified previous
* [F]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
el->el_search.chadir = CHAR_BACK;
el->el_search.chacha = ch;
return cv_csearch_back(el, ch, el->el_state.argument, 0);
}
/* vi_to_next_char():
* Vi move up to the character specified next
* [t]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_next_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
return cv_csearch_fwd(el, ch, el->el_state.argument, 1);
}
/* vi_to_prev_char():
* Vi move up to the character specified previous
* [T]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_prev_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
return cv_csearch_back(el, ch, el->el_state.argument, 1);
}
/* vi_repeat_next_char():
* Vi repeat current character search in the same search direction
* [;]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_next_char(el, c)
EditLine *el;
int c;
{
if (el->el_search.chacha == 0)
return CC_ERROR;
return el->el_search.chadir == CHAR_FWD ?
cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}
/* vi_repeat_prev_char():
* Vi repeat current character search in the opposite search direction
* [,]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_prev_char(el, c)
EditLine *el;
int c;
{
if (el->el_search.chacha == 0)
return CC_ERROR;
return el->el_search.chadir == CHAR_BACK ?
cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}