⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 history.c

📁 早期freebsd实现
💻 C
字号:
/*- * 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>#if __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#include "histedit.h"typedef const HistEvent *	(*history_gfun_t) __P((ptr_t));typedef const HistEvent *	(*history_efun_t) __P((ptr_t, const char *));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_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	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_gfun_t,						     history_gfun_t,						     history_gfun_t,						     history_gfun_t,						     history_gfun_t,						     history_efun_t,						     history_efun_t, ptr_t));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_end    __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);    (void) strcat(s, str);    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 voidhistory_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 voidhistory_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_end(): *	Default history cleanup function */private voidhistory_def_end(p)    ptr_t p;{    history_t *h = (history_t *) p;    while (h->list.prev != &h->list)	history_def_delete(h, h->list.prev);}/************************************************************************//* 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_enter = history_def_enter;    h->h_add   = history_def_add;    return h;}/* history_end(): *	clean up history; */public voidhistory_end(h)    History *h;{    if (h->h_next == history_def_next)	history_def_end(h->h_ref);}/* history_set_num(): *	Set history number of events */private inthistory_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 inthistory_set_fun(h, first, next, last, prev, curr, enter, add, ptr)    History *h;    history_gfun_t first, next, last, prev, curr;    history_efun_t enter, add;    ptr_t ptr;{    if (first == NULL || next == NULL ||         last == NULL  || prev == NULL || curr == NULL ||	enter == NULL || add == NULL || 	ptr == 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_enter = history_def_enter;	    h->h_add   = history_def_add;	}	return -1;    }    if (h->h_next == history_def_next)	history_def_end(h->h_ref);    h->h_next  = next;    h->h_first = first;    h->h_enter = enter;    h->h_add   = add;    return 0;}/* 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 *#if __STDC__history(History *h, int fun, ...)#elsehistory(va_alist)    va_dcl#endif{    va_list va;    const HistEvent *ev = NULL;    const char *str;    static const HistEvent sev = { 0, "" };#if __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_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)	    ev = &sev;	break;    case H_FUNC:	{	    history_gfun_t	first = va_arg(va, history_gfun_t);	    history_gfun_t	next  = va_arg(va, history_gfun_t);	    history_gfun_t	last  = va_arg(va, history_gfun_t);	    history_gfun_t	prev  = va_arg(va, history_gfun_t);	    history_gfun_t	curr  = va_arg(va, history_gfun_t);	    history_efun_t	enter = va_arg(va, history_efun_t);	    history_efun_t	add   = va_arg(va, history_efun_t);	    ptr_t		ptr   = va_arg(va, ptr_t);	    if (history_set_fun(h, first, next, last, prev, 				   curr, enter, add, ptr) == 0)		ev = &sev;	}	break;    case H_END:	history_end(h);	break;    default:	break;    }    va_end(va);    return ev;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -