Module Name: src Committed By: christos Date: Sun Jan 3 18:27:10 UTC 2010
Modified Files: src/lib/libedit: chartype.h editline.3 histedit.h history.c readline.c tokenizer.c src/lib/libedit/TEST: Makefile Added Files: src/lib/libedit/TEST: wtc1.c Log Message: rename historyw -> history_w for consistency. add wide tst code and make it the default. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/lib/libedit/chartype.h cvs rdiff -u -r1.71 -r1.72 src/lib/libedit/editline.3 cvs rdiff -u -r1.44 -r1.45 src/lib/libedit/histedit.h cvs rdiff -u -r1.36 -r1.37 src/lib/libedit/history.c cvs rdiff -u -r1.87 -r1.88 src/lib/libedit/readline.c cvs rdiff -u -r1.17 -r1.18 src/lib/libedit/tokenizer.c cvs rdiff -u -r1.3 -r1.4 src/lib/libedit/TEST/Makefile cvs rdiff -u -r0 -r1.1 src/lib/libedit/TEST/wtc1.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libedit/chartype.h diff -u src/lib/libedit/chartype.h:1.3 src/lib/libedit/chartype.h:1.4 --- src/lib/libedit/chartype.h:1.3 Thu Dec 31 13:32:37 2009 +++ src/lib/libedit/chartype.h Sun Jan 3 13:27:10 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: chartype.h,v 1.3 2009/12/31 18:32:37 christos Exp $ */ +/* $NetBSD: chartype.h,v 1.4 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ #define Char wchar_t #define Int wint_t #define FUN(prefix,rest) prefix ## _w ## rest -#define FUNW(type) type ## w +#define FUNW(type) type ## _w #define TYPE(type) type ## W #define FSTR "%ls" #define STR(x) L ## x Index: src/lib/libedit/editline.3 diff -u src/lib/libedit/editline.3:1.71 src/lib/libedit/editline.3:1.72 --- src/lib/libedit/editline.3:1.71 Thu Dec 31 10:58:26 2009 +++ src/lib/libedit/editline.3 Sun Jan 3 13:27:10 2010 @@ -1,4 +1,4 @@ -.\" $NetBSD: editline.3,v 1.71 2009/12/31 15:58:26 christos Exp $ +.\" $NetBSD: editline.3,v 1.72 2010/01/03 18:27:10 christos Exp $ .\" .\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -59,7 +59,7 @@ .Nm history_end , .Nm history_wend , .Nm history , -.Nm historyw , +.Nm history_w , .Nm tok_init , .Nm tok_winit , .Nm tok_end , @@ -130,7 +130,7 @@ .Ft int .Fn history "History *h" "HistEvent *ev" "int op" "..." .Ft int -.Fn historyw "HistoryW *h" "HistEventW *ev" "int op" "..." +.Fn history_w "HistoryW *h" "HistEventW *ev" "int op" "..." .Ft Tokenizer * .Fn tok_init "const char *IFS" .Ft TokenizerW * Index: src/lib/libedit/histedit.h diff -u src/lib/libedit/histedit.h:1.44 src/lib/libedit/histedit.h:1.45 --- src/lib/libedit/histedit.h:1.44 Thu Dec 31 10:58:26 2009 +++ src/lib/libedit/histedit.h Sun Jan 3 13:27:10 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: histedit.h,v 1.44 2009/12/31 15:58:26 christos Exp $ */ +/* $NetBSD: histedit.h,v 1.45 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -114,13 +114,16 @@ int el_get(EditLine *, int, ...); unsigned char _el_fn_complete(EditLine *, int); - /* * el_set/el_get parameters * - * When using el_wset/el_wget: - * wchar_t is wchar_t, otherwise it is char. - * prompt_func is el_wpfunc_t, otherise it is el_pfunc_t . + * When using el_wset/el_wget (as opposed to el_set/el_get): + * Char is wchar_t, otherwise it is char. + * prompt_func is el_wpfunc_t, otherwise it is el_pfunc_t . + + * Prompt function prototypes are: + * typedef char *(*el_pfunct_t) (EditLine *); + * typedef wchar_t *(*el_wpfunct_t) (EditLine *); * * For operations that support set or set/get, the argument types listed are for * the "set" operation. For "get", each listed type must be a pointer. @@ -128,17 +131,17 @@ * * Operations that only support "get" have the correct argument types listed. */ -#define EL_PROMPT 0 /* , promt_func); set/get */ +#define EL_PROMPT 0 /* , prompt_func); set/get */ #define EL_TERMINAL 1 /* , const char *); set/get */ -#define EL_EDITOR 2 /* , const wchar_t *); set/get */ +#define EL_EDITOR 2 /* , const Char *); set/get */ #define EL_SIGNAL 3 /* , int); set/get */ -#define EL_BIND 4 /* , const wchar_t *, ..., NULL); set */ -#define EL_TELLTC 5 /* , const wchar_t *, ..., NULL); set */ -#define EL_SETTC 6 /* , const wchar_t *, ..., NULL); set */ -#define EL_ECHOTC 7 /* , const wchar_t *, ..., NULL); set */ -#define EL_SETTY 8 /* , const wchar_t *, ..., NULL); set */ -#define EL_ADDFN 9 /* , const wchar_t *, const wchar_t * set */ - /* , el_func_t); */ +#define EL_BIND 4 /* , const Char *, ..., NULL); set */ +#define EL_TELLTC 5 /* , const Char *, ..., NULL); set */ +#define EL_SETTC 6 /* , const Char *, ..., NULL); set */ +#define EL_ECHOTC 7 /* , const Char *, ..., NULL); set */ +#define EL_SETTY 8 /* , const Char *, ..., NULL); set */ +#define EL_ADDFN 9 /* , const Char *, const Char, set */ + /* el_func_t); */ #define EL_HIST 10 /* , hist_fun_t, const ptr_t); set */ #define EL_EDITMODE 11 /* , int); set/get */ #define EL_RPROMPT 12 /* , prompt_func); set/get */ @@ -146,12 +149,12 @@ #define EL_CLIENTDATA 14 /* , void *); set/get */ #define EL_UNBUFFERED 15 /* , int); set/get */ #define EL_PREP_TERM 16 /* , int); set */ -#define EL_GETTC 17 /* , const wchar_t *, ..., NULL); get */ +#define EL_GETTC 17 /* , const Char *, ..., NULL); get */ #define EL_GETFP 18 /* , int, FILE **); get */ #define EL_SETFP 19 /* , int, FILE *); set */ #define EL_REFRESH 20 /* , void); set */ -#define EL_PROMPT_ESC 21 /* , prompt_func, wchar_t); set/get */ -#define EL_RPROMPT_ESC 22 /* , prompt_func, wchar_t); set/get */ +#define EL_PROMPT_ESC 21 /* , prompt_func, Char); set/get */ +#define EL_RPROMPT_ESC 22 /* , prompt_func, Char); set/get */ #define EL_BUILTIN_GETCFN (NULL) @@ -280,22 +283,22 @@ /* * ==== History ==== */ -typedef struct histeventw { +typedef struct histeventW { int num; const wchar_t *str; } HistEventW; -typedef struct historyw HistoryW; +typedef struct historyW HistoryW; HistoryW * history_winit(void); void history_wend(HistoryW *); -int historyw(HistoryW *, HistEventW *, int, ...); +int history_w(HistoryW *, HistEventW *, int, ...); /* * ==== Tokenization ==== */ -typedef struct tokenizerw TokenizerW; +typedef struct tokenizerW TokenizerW; /* Wide character tokenizer support */ TokenizerW *tok_winit(const wchar_t *); Index: src/lib/libedit/history.c diff -u src/lib/libedit/history.c:1.36 src/lib/libedit/history.c:1.37 --- src/lib/libedit/history.c:1.36 Wed Dec 30 18:54:52 2009 +++ src/lib/libedit/history.c Sun Jan 3 13:27:10 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: history.c,v 1.36 2009/12/30 23:54:52 christos Exp $ */ +/* $NetBSD: history.c,v 1.37 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: history.c,v 1.36 2009/12/30 23:54:52 christos Exp $"); +__RCSID("$NetBSD: history.c,v 1.37 2010/01/03 18:27:10 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -64,7 +64,7 @@ typedef void (*history_vfun_t)(ptr_t, TYPE(HistEvent) *); typedef int (*history_sfun_t)(ptr_t, TYPE(HistEvent) *, const int); -struct FUNW(history) { +struct TYPE(history) { ptr_t h_ref; /* Argument for history fcns */ int h_ent; /* Last entry point for history */ history_gfun_t h_first; /* Get the first element */ Index: src/lib/libedit/readline.c diff -u src/lib/libedit/readline.c:1.87 src/lib/libedit/readline.c:1.88 --- src/lib/libedit/readline.c:1.87 Wed Dec 30 18:54:52 2009 +++ src/lib/libedit/readline.c Sun Jan 3 13:27:10 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.87 2009/12/30 23:54:52 christos Exp $ */ +/* $NetBSD: readline.c,v 1.88 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.87 2009/12/30 23:54:52 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.88 2010/01/03 18:27:10 christos Exp $"); #endif /* not lint && not SCCSID */ #include <sys/types.h> @@ -1298,7 +1298,8 @@ rl_initialize(); if (filename == NULL && (filename = _default_history_file()) == NULL) return errno; - return (FUNW(history)(h, &ev, H_LOAD, filename) == -1 ? (errno ? errno : EINVAL) : 0); + return (FUNW(history)(h, &ev, H_LOAD, filename) == -1 ? + (errno ? errno : EINVAL) : 0); } @@ -1314,7 +1315,8 @@ rl_initialize(); if (filename == NULL && (filename = _default_history_file()) == NULL) return errno; - return (FUNW(history)(h, &ev, H_SAVE, filename) == -1 ? (errno ? errno : EINVAL) : 0); + return (FUNW(history)(h, &ev, H_SAVE, filename) == -1 ? + (errno ? errno : EINVAL) : 0); } @@ -1456,7 +1458,7 @@ { TYPE(HistEvent) ev; - FUNW(history)(h, &ev, H_CLEAR); + (void)FUNW(history)(h, &ev, H_CLEAR); history_length = 0; } @@ -1474,7 +1476,7 @@ return (0); curr_num = ev.num; - FUNW(history)(h, &ev, H_FIRST); + (void)FUNW(history)(h, &ev, H_FIRST); off = 1; while (ev.num != curr_num && FUNW(history)(h, &ev, H_NEXT) == 0) off++; @@ -1508,7 +1510,7 @@ return (-1); curr_num = ev.num; - FUNW(history)(h, &ev, H_FIRST); + (void)FUNW(history)(h, &ev, H_FIRST); size = 0; do size += Strlen(ev.str) * sizeof(*ev.str); @@ -1533,7 +1535,7 @@ if (pos >= history_length || pos < 0) return (-1); - FUNW(history)(h, &ev, H_CURR); + (void)FUNW(history)(h, &ev, H_CURR); curr_num = ev.num; /* @@ -1541,7 +1543,7 @@ * (void **)-1 */ if (FUNW(history)(h, &ev, H_DELDATA, pos, (void **)-1)) { - FUNW(history)(h, &ev, H_SET, curr_num); + (void)FUNW(history)(h, &ev, H_SET, curr_num); return(-1); } return (0); @@ -1592,7 +1594,7 @@ if (FUNW(history)(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) break; } - FUNW(history)(h, &ev, H_SET, curr_num); + (void)FUNW(history)(h, &ev, H_SET, curr_num); return (-1); } @@ -1605,7 +1607,8 @@ { TYPE(HistEvent) ev; - return (FUNW(history)(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str)); + return (FUNW(history)(h, &ev, direction < 0 ? + H_PREV_STR : H_NEXT_STR, str)); } @@ -1641,7 +1644,8 @@ } /* set "current" pointer back to previous state */ - FUNW(history)(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); + (void)FUNW(history)(h, &ev, + pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); return (-1); } Index: src/lib/libedit/tokenizer.c diff -u src/lib/libedit/tokenizer.c:1.17 src/lib/libedit/tokenizer.c:1.18 --- src/lib/libedit/tokenizer.c:1.17 Wed Dec 30 18:54:52 2009 +++ src/lib/libedit/tokenizer.c Sun Jan 3 13:27:10 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: tokenizer.c,v 1.17 2009/12/30 23:54:52 christos Exp $ */ +/* $NetBSD: tokenizer.c,v 1.18 2010/01/03 18:27:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tokenizer.c,v 1.17 2009/12/30 23:54:52 christos Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.18 2010/01/03 18:27:10 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -68,7 +68,7 @@ #define tok_strdup(a) Strdup(a) -struct FUNW(tokenizer) { +struct TYPE(tokenizer) { Char *ifs; /* In field separator */ int argc, amax; /* Current and maximum number of args */ Char **argv; /* Argument list */ Index: src/lib/libedit/TEST/Makefile diff -u src/lib/libedit/TEST/Makefile:1.3 src/lib/libedit/TEST/Makefile:1.4 --- src/lib/libedit/TEST/Makefile:1.3 Thu Aug 31 16:20:38 2006 +++ src/lib/libedit/TEST/Makefile Sun Jan 3 13:27:10 2010 @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.3 2006/08/31 20:20:38 rpaulo Exp $ +# $NetBSD: Makefile,v 1.4 2010/01/03 18:27:10 christos Exp $ NOMAN=1 -PROG=tc1 +PROG=wtc1 CPPFLAGS=-I${.CURDIR}/.. LDADD+=-ledit -ltermcap DPADD+=${LIBEDIT} ${LIBTERMCAP} Added files: Index: src/lib/libedit/TEST/wtc1.c diff -u /dev/null src/lib/libedit/TEST/wtc1.c:1.1 --- /dev/null Sun Jan 3 13:27:10 2010 +++ src/lib/libedit/TEST/wtc1.c Sun Jan 3 13:27:10 2010 @@ -0,0 +1,269 @@ +#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 <limits.h> +#include <locale.h> + +#include "../histedit.h" + + +static int continuation; +volatile sig_atomic_t gotsig; + +static wchar_t * +prompt(EditLine *el) +{ + static wchar_t a[] = L"\1\e[7m\1Edit$\1\e[0m\1 "; + static wchar_t b[] = L"Edit> "; + + return continuation ? b : a; +} + + +static void +sig(int i) +{ + gotsig = i; +} + +const char * +my_wcstombs(const wchar_t *wstr) +{ + static struct { + char *str; + int len; + } buf; + + int needed = wcstombs(0, wstr, 0) + 1; + if (needed > buf.len) { + buf.str = malloc(needed); + buf.len = needed; + } + wcstombs(buf.str, wstr, needed); + buf.str[needed - 1] = 0; + + return buf.str; +} + + +static unsigned char +complete(EditLine *el, int ch) +{ + DIR *dd = opendir("."); + struct dirent *dp; + const wchar_t *ptr; + char *buf, *bptr; + const LineInfoW *lf = el_wline(el); + int len, mblen, i; + unsigned char res; + + /* Find the last word */ + for (ptr = lf->cursor -1; !iswspace(*ptr) && ptr > lf->buffer; --ptr) + continue; + len = lf->cursor - ++ptr; + + /* Convert last word to multibyte encoding, so we can compare to it */ + wctomb(NULL, 0); /* Reset shift state */ + mblen = MB_LEN_MAX * len + 1; + buf = bptr =(char *)malloc(mblen); + for (i = 0; i < len; ++i) { + /* Note: really should test for -1 return from wctomb */ + bptr += wctomb(bptr, ptr[i]); + } + *bptr = 0; /* Terminate multibyte string */ + mblen = bptr - buf; + + /* Scan directory for matching name */ + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (mblen > strlen(dp->d_name)) + continue; + if (strncmp(dp->d_name, buf, mblen) == 0) { + if (el_insertstr(el, &dp->d_name[mblen]) == -1) + res = CC_ERROR; + else + res = CC_REFRESH; + break; + } + } + + closedir(dd); + free(buf); + return res; +} + + +int +main(int argc, char *argv[]) +{ + EditLine *el = NULL; + int numc, ncontinuation; + const wchar_t *line; + TokenizerW *tok; + HistoryW *hist; + HistEventW ev; +#ifdef DEBUG + int i; +#endif + + setlocale(LC_ALL, ""); + + (void)signal(SIGINT, sig); + (void)signal(SIGQUIT, sig); + (void)signal(SIGHUP, sig); + (void)signal(SIGTERM, sig); + + hist = history_winit(); /* Init built-in history */ + history_w(hist, &ev, H_SETSIZE, 100); /* Remember 100 events */ + + tok = tok_winit(NULL); /* Init the tokenizer */ + + el = el_init(argv[0], stdin, stdout, stderr); + + el_wset(el, EL_EDITOR, L"vi"); /* Default editor is vi */ + el_wset(el, EL_SIGNAL, 1); /* Handle signals gracefully */ + el_wset(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */ + + el_wset(el, EL_HIST, history_w, hist); /* FIXME - history_w? */ + + /* Add a user-defined function */ + el_wset(el, EL_ADDFN, L"ed-complete", L"Complete argument", complete); + + /* Bind <tab> to it */ + el_wset(el, EL_BIND, L"^I", L"ed-complete", NULL); + + /* + * Bind j, k in vi command mode to previous and next line, instead + * of previous and next history. + */ + el_wset(el, EL_BIND, L"-a", L"k", L"ed-prev-line", NULL); + el_wset(el, EL_BIND, L"-a", L"j", L"ed-next-line", NULL); + + /* Source the user's defaults file. */ + el_source(el, NULL); + + while((line = el_wgets(el, &numc)) != NULL && numc != 0) { + int ac, cc, co, rc; + const wchar_t **av; + + const LineInfoW *li; + li = el_wline(el); + +#ifdef DEBUG + (void)fwprintf(stderr, L"==> got %d %ls", numc, line); + (void)fwprintf(stderr, L" > li `%.*ls_%.*ls'\n", + (li->cursor - li->buffer), li->buffer, + (li->lastchar - 1 - li->cursor), + (li->cursor >= li->lastchar) ? L"" : li->cursor); +#endif + + if (gotsig) { + (void)fprintf(stderr, "Got signal %d.\n", gotsig); + gotsig = 0; + el_reset(el); + } + + if(!continuation && numc == 1) + continue; /* Only got a linefeed */ + + ac = cc = co = 0; + ncontinuation = tok_wline(tok, li, &ac, &av, &cc, &co); + if (ncontinuation < 0) { + (void) fprintf(stderr, "Internal error\n"); + continuation = 0; + continue; + } + +#ifdef DEBUG + (void)fprintf(stderr, " > nc %d ac %d cc %d co %d\n", + ncontinuation, ac, cc, co); +#endif + history_w(hist, &ev, continuation ? H_APPEND : H_ENTER, line); + + continuation = ncontinuation; + ncontinuation = 0; + if(continuation) + continue; + +#ifdef DEBUG + for (i = 0; i < ac; ++i) { + (void)fwprintf(stderr, L" > arg# %2d ", i); + if (i != cc) + (void)fwprintf(stderr, L"`%ls'\n", av[i]); + else + (void)fwprintf(stderr, L"`%.*ls_%ls'\n", + co, av[i], av[i] + co); + } +#endif + + if (wcscmp (av[0], L"history") == 0) { + switch(ac) { + case 1: + for(rc = history_w(hist, &ev, H_LAST); + rc != -1; + rc = history_w(hist, &ev, H_PREV)) + (void)fwprintf(stdout, L"%4d %ls", + ev.num, ev.str); + break; + case 2: + if (wcscmp(av[1], L"clear") == 0) + history_w(hist, &ev, H_CLEAR); + else + goto badhist; + break; + case 3: + if (wcscmp(av[1], L"load") == 0) + history_w(hist, &ev, H_LOAD, + my_wcstombs(av[2])); + else if (wcscmp(av[1], L"save") == 0) + history_w(hist, &ev, H_SAVE, + my_wcstombs(av[2])); + else + goto badhist; + break; + badhist: + default: + (void)fprintf(stderr, + "Bad history arguments\n"); + break; + } + } else if (el_wparse(el, ac, av) == -1) { + switch (fork()) { + case 0: { + Tokenizer *ntok = tok_init(NULL); + int nargc; + const char **nav; + tok_str(ntok, my_wcstombs(line), &nargc, &nav); + execvp(nav[0],(char **)nav); + perror(nav[0]); + _exit(1); + /* NOTREACHED */ + break; + } + case -1: + perror("fork"); + break; + default: + if (wait(&rc) == -1) + perror("wait"); + (void)fprintf(stderr, "Exit %x\n", rc); + break; + } + } + + tok_wreset(tok); + } + + el_end(el); + tok_wend(tok); + history_wend(hist); + + fprintf(stdout, "\n"); + return 0; +} + +