xref: /csrg-svn/lib/libedit/history.c (revision 61275)
154219Sbostic /*-
2*61275Sbostic  * Copyright (c) 1992, 1993
3*61275Sbostic  *	The Regents of the University of California.  All rights reserved.
454219Sbostic  *
554219Sbostic  * This code is derived from software contributed to Berkeley by
654219Sbostic  * Christos Zoulas of Cornell University.
754219Sbostic  *
854219Sbostic  * %sccs.include.redist.c%
954219Sbostic  */
1054219Sbostic 
1154624Schristos #if !defined(lint) && !defined(SCCSID)
12*61275Sbostic static char sccsid[] = "@(#)history.c	8.1 (Berkeley) 06/04/93";
1354624Schristos #endif /* not lint && not SCCSID */
1454219Sbostic 
1554219Sbostic /*
1654219Sbostic  * hist.c: History access functions
1754219Sbostic  */
1854219Sbostic #include "sys.h"
1954219Sbostic 
2054219Sbostic #include <string.h>
2154219Sbostic #include <stdlib.h>
2254219Sbostic #if __STDC__
2354219Sbostic #include <stdarg.h>
2454219Sbostic #else
2554219Sbostic #include <varargs.h>
2654219Sbostic #endif
2754219Sbostic 
2854249Smarc #include "histedit.h"
2954219Sbostic 
3054219Sbostic typedef const HistEvent *	(*history_gfun_t) __P((ptr_t));
3154219Sbostic typedef const HistEvent *	(*history_efun_t) __P((ptr_t, const char *));
3254219Sbostic 
3354219Sbostic struct history {
3454219Sbostic     ptr_t	   h_ref;		/* Argument for history fcns	*/
3554219Sbostic     history_gfun_t h_first;		/* Get the first element	*/
3654219Sbostic     history_gfun_t h_next;		/* Get the next element		*/
3754219Sbostic     history_gfun_t h_last;		/* Get the last element		*/
3854219Sbostic     history_gfun_t h_prev;		/* Get the previous element	*/
3954219Sbostic     history_gfun_t h_curr;		/* Get the current element	*/
4054219Sbostic     history_efun_t h_enter;		/* Add an element		*/
4154219Sbostic     history_efun_t h_add;		/* Append to an element		*/
4254219Sbostic };
4354219Sbostic 
4454219Sbostic #define	HNEXT(h)  	(*(h)->h_next)((h)->h_ref)
4554219Sbostic #define	HFIRST(h) 	(*(h)->h_first)((h)->h_ref)
4654219Sbostic #define	HPREV(h)  	(*(h)->h_prev)((h)->h_ref)
4754219Sbostic #define	HLAST(h) 	(*(h)->h_last)((h)->h_ref)
4854219Sbostic #define	HCURR(h) 	(*(h)->h_curr)((h)->h_ref)
4954219Sbostic #define	HENTER(h, str)	(*(h)->h_enter)((h)->h_ref, str)
5054219Sbostic #define	HADD(h, str)	(*(h)->h_add)((h)->h_ref, str)
5154219Sbostic 
5254219Sbostic #define h_malloc(a)	malloc(a)
5354219Sbostic #define h_free(a)	free(a)
5454219Sbostic 
5554219Sbostic 
5654219Sbostic private int		 history_set_num	__P((History *, int));
5754219Sbostic private int		 history_set_fun	__P((History *, history_gfun_t,
5854219Sbostic 						     history_gfun_t,
5954219Sbostic 						     history_gfun_t,
6054219Sbostic 						     history_gfun_t,
6154219Sbostic 						     history_gfun_t,
6254219Sbostic 						     history_efun_t,
6354219Sbostic 						     history_efun_t, ptr_t));
6454219Sbostic private const HistEvent *history_prev_event	__P((History *, int));
6554219Sbostic private const HistEvent *history_next_event	__P((History *, int));
6654219Sbostic private const HistEvent *history_next_string	__P((History *, const char *));
6754219Sbostic private const HistEvent *history_prev_string	__P((History *, const char *));
6854219Sbostic 
6954219Sbostic 
7054219Sbostic /***********************************************************************/
7154219Sbostic 
7254219Sbostic /*
7354219Sbostic  * Builtin- history implementation
7454219Sbostic  */
7554219Sbostic typedef struct hentry_t {
7654219Sbostic     HistEvent ev;		/* What we return		*/
7754219Sbostic     struct hentry_t *next;	/* Next entry			*/
7854219Sbostic     struct hentry_t *prev;	/* Previous entry		*/
7954219Sbostic } hentry_t;
8054219Sbostic 
8154219Sbostic typedef struct history_t {
8254219Sbostic     hentry_t  list;		/* Fake list header element	*/
8354219Sbostic     hentry_t *cursor;		/* Current element in the list	*/
8454219Sbostic     int	max;			/* Maximum number of events	*/
8554219Sbostic     int cur;			/* Current number of events	*/
8654219Sbostic     int	eventno;		/* Current event number		*/
8754219Sbostic } history_t;
8854219Sbostic 
8954219Sbostic private const HistEvent *history_def_first  __P((ptr_t));
9054219Sbostic private const HistEvent *history_def_last   __P((ptr_t));
9154219Sbostic private const HistEvent *history_def_next   __P((ptr_t));
9254219Sbostic private const HistEvent *history_def_prev   __P((ptr_t));
9354219Sbostic private const HistEvent *history_def_curr   __P((ptr_t));
9454219Sbostic private const HistEvent *history_def_enter  __P((ptr_t, const char *));
9554219Sbostic private const HistEvent *history_def_add    __P((ptr_t, const char *));
9654219Sbostic private void             history_def_init   __P((ptr_t *, int));
9754219Sbostic private void             history_def_end    __P((ptr_t));
9854219Sbostic private const HistEvent *history_def_insert __P((history_t *, const char *));
9954219Sbostic private void             history_def_delete __P((history_t *, hentry_t *));
10054219Sbostic 
10154219Sbostic #define history_def_set(p, num)	(void) (((history_t *) p)->max = (num))
10254219Sbostic 
10354219Sbostic 
10454219Sbostic /* history_def_first():
10554219Sbostic  *	Default function to return the first event in the history.
10654219Sbostic  */
10754219Sbostic private const HistEvent *
history_def_first(p)10854219Sbostic history_def_first(p)
10954219Sbostic     ptr_t p;
11054219Sbostic {
11154219Sbostic     history_t *h = (history_t *) p;
11254219Sbostic     h->cursor = h->list.next;
11354219Sbostic     if (h->cursor != &h->list)
11454219Sbostic 	return &h->cursor->ev;
11554219Sbostic     else
11654219Sbostic 	return NULL;
11754219Sbostic }
11854219Sbostic 
11954219Sbostic /* history_def_last():
12054219Sbostic  *	Default function to return the last event in the history.
12154219Sbostic  */
12254219Sbostic private const HistEvent *
history_def_last(p)12354219Sbostic history_def_last(p)
12454219Sbostic     ptr_t p;
12554219Sbostic {
12654219Sbostic     history_t *h = (history_t *) p;
12754219Sbostic     h->cursor = h->list.prev;
12854219Sbostic     if (h->cursor != &h->list)
12954219Sbostic 	return &h->cursor->ev;
13054219Sbostic     else
13154219Sbostic 	return NULL;
13254219Sbostic }
13354219Sbostic 
13454219Sbostic /* history_def_next():
13554219Sbostic  *	Default function to return the next event in the history.
13654219Sbostic  */
13754219Sbostic private const HistEvent *
history_def_next(p)13854219Sbostic history_def_next(p)
13954219Sbostic     ptr_t p;
14054219Sbostic {
14154219Sbostic     history_t *h = (history_t *) p;
14254219Sbostic 
14354219Sbostic     if (h->cursor != &h->list)
14454219Sbostic 	h->cursor = h->cursor->next;
14554219Sbostic     else
14654219Sbostic 	return NULL;
14754219Sbostic 
14854219Sbostic     if (h->cursor != &h->list)
14954219Sbostic 	return &h->cursor->ev;
15054219Sbostic     else
15154219Sbostic 	return NULL;
15254219Sbostic }
15354219Sbostic 
15454219Sbostic 
15554219Sbostic /* history_def_prev():
15654219Sbostic  *	Default function to return the previous event in the history.
15754219Sbostic  */
15854219Sbostic private const HistEvent *
history_def_prev(p)15954219Sbostic history_def_prev(p)
16054219Sbostic     ptr_t p;
16154219Sbostic {
16254219Sbostic     history_t *h = (history_t *) p;
16354219Sbostic 
16454219Sbostic     if (h->cursor != &h->list)
16554219Sbostic 	h->cursor = h->cursor->prev;
16654219Sbostic     else
16754219Sbostic 	return NULL;
16854219Sbostic 
16954219Sbostic     if (h->cursor != &h->list)
17054219Sbostic 	return &h->cursor->ev;
17154219Sbostic     else
17254219Sbostic 	return NULL;
17354219Sbostic }
17454219Sbostic 
17554219Sbostic 
17654219Sbostic /* history_def_curr():
17754219Sbostic  *	Default function to return the current event in the history.
17854219Sbostic  */
17954219Sbostic private const HistEvent *
history_def_curr(p)18054219Sbostic history_def_curr(p)
18154219Sbostic     ptr_t p;
18254219Sbostic {
18354219Sbostic     history_t *h = (history_t *) p;
18454219Sbostic 
18554219Sbostic     if (h->cursor != &h->list)
18654219Sbostic 	return &h->cursor->ev;
18754219Sbostic     else
18854219Sbostic 	return NULL;
18954219Sbostic }
19054219Sbostic 
19154219Sbostic 
19254219Sbostic /* history_def_add():
19354219Sbostic  *	Append string to element
19454219Sbostic  */
19554219Sbostic private const HistEvent *
history_def_add(p,str)19654219Sbostic history_def_add(p, str)
19754219Sbostic     ptr_t p;
19854219Sbostic     const char *str;
19954219Sbostic {
20054219Sbostic     history_t *h = (history_t *) p;
20154219Sbostic     size_t len;
20254219Sbostic     char *s;
20354219Sbostic 
20454219Sbostic     if (h->cursor == &h->list)
20554219Sbostic 	return (history_def_enter(p, str));
20654219Sbostic     len = strlen(h->cursor->ev.str) + strlen(str) + 1;
20754219Sbostic     s = (char *) h_malloc(len);
20854219Sbostic     (void) strcpy(s, h->cursor->ev.str);
20954219Sbostic     (void) strcat(s, str);
21054219Sbostic     h_free((ptr_t) h->cursor->ev.str);
21154219Sbostic     h->cursor->ev.str = s;
21254219Sbostic     return &h->cursor->ev;
21354219Sbostic }
21454219Sbostic 
21554219Sbostic 
21654219Sbostic /* history_def_delete():
21754219Sbostic  *	Delete element hp of the h list
21854219Sbostic  */
21954219Sbostic private void
history_def_delete(h,hp)22054219Sbostic history_def_delete(h, hp)
22154219Sbostic     history_t *h;
22254219Sbostic     hentry_t *hp;
22354219Sbostic {
22454219Sbostic     if (hp == &h->list)
22554219Sbostic 	abort();
22654219Sbostic     hp->prev->next = hp->next;
22754219Sbostic     hp->next->prev = hp->prev;
22854219Sbostic     h_free((ptr_t) hp->ev.str);
22954219Sbostic     h_free(hp);
23054219Sbostic     h->cur--;
23154219Sbostic }
23254219Sbostic 
23354219Sbostic 
23454219Sbostic /* history_def_insert():
23554219Sbostic  *	Insert element with string str in the h list
23654219Sbostic  */
23754219Sbostic private const HistEvent *
history_def_insert(h,str)23854219Sbostic history_def_insert(h, str)
23954219Sbostic     history_t *h;
24054219Sbostic     const char *str;
24154219Sbostic {
24254219Sbostic     h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
24354219Sbostic     h->cursor->ev.str = strdup(str);
24454219Sbostic     h->cursor->next = h->list.next;
24554219Sbostic     h->cursor->prev = &h->list;
24654219Sbostic     h->list.next->prev = h->cursor;
24754219Sbostic     h->list.next = h->cursor;
24854219Sbostic     h->cur++;
24954219Sbostic 
25054219Sbostic     return &h->cursor->ev;
25154219Sbostic }
25254219Sbostic 
25354219Sbostic 
25454219Sbostic /* history_def_enter():
25554219Sbostic  *	Default function to enter an item in the history
25654219Sbostic  */
25754219Sbostic private const HistEvent *
history_def_enter(p,str)25854219Sbostic history_def_enter(p, str)
25954219Sbostic     ptr_t p;
26054219Sbostic     const char *str;
26154219Sbostic {
26254219Sbostic     history_t *h = (history_t *) p;
26354219Sbostic     const HistEvent *ev;
26454219Sbostic 
26554219Sbostic 
26654219Sbostic     ev = history_def_insert(h, str);
26754219Sbostic     ((HistEvent*) ev)->num = ++h->eventno;
26854219Sbostic 
26954219Sbostic     /*
27054219Sbostic      * Always keep at least one entry.
27154219Sbostic      * This way we don't have to check for the empty list.
27254219Sbostic      */
27354219Sbostic     while (h->cur > h->max + 1)
27454219Sbostic 	history_def_delete(h, h->list.prev);
27554219Sbostic     return ev;
27654219Sbostic }
27754219Sbostic 
27854219Sbostic 
27954219Sbostic /* history_def_init():
28054219Sbostic  *	Default history initialization function
28154219Sbostic  */
28254219Sbostic private void
history_def_init(p,n)28354219Sbostic history_def_init(p, n)
28454219Sbostic     ptr_t *p;
28554219Sbostic     int n;
28654219Sbostic {
28754219Sbostic     history_t *h = (history_t *) h_malloc(sizeof(history_t));
28854219Sbostic     if (n <= 0)
28954219Sbostic 	n = 0;
29054219Sbostic     h->eventno = 0;
29154219Sbostic     h->cur = 0;
29254219Sbostic     h->max = n;
29354219Sbostic     h->list.next = h->list.prev = &h->list;
29454219Sbostic     h->list.ev.str = NULL;
29554219Sbostic     h->list.ev.num = 0;
29654219Sbostic     h->cursor = &h->list;
29754219Sbostic     *p = (ptr_t) h;
29854219Sbostic }
29954219Sbostic 
30054219Sbostic 
30154219Sbostic /* history_def_end():
30254219Sbostic  *	Default history cleanup function
30354219Sbostic  */
30454219Sbostic private void
history_def_end(p)30554219Sbostic history_def_end(p)
30654219Sbostic     ptr_t p;
30754219Sbostic {
30854219Sbostic     history_t *h = (history_t *) p;
30954219Sbostic 
31054219Sbostic     while (h->list.prev != &h->list)
31154219Sbostic 	history_def_delete(h, h->list.prev);
31254219Sbostic }
31354219Sbostic 
31454219Sbostic /************************************************************************/
31554219Sbostic 
31654219Sbostic /* history_init():
31754219Sbostic  *	Initialization function.
31854219Sbostic  */
31954219Sbostic public History *
history_init()32054219Sbostic history_init()
32154219Sbostic {
32254219Sbostic     History *h = (History *) h_malloc(sizeof(History));
32354219Sbostic 
32454219Sbostic     history_def_init(&h->h_ref, 0);
32554219Sbostic 
32654219Sbostic     h->h_next  = history_def_next;
32754219Sbostic     h->h_first = history_def_first;
32854219Sbostic     h->h_last  = history_def_last;
32954219Sbostic     h->h_prev  = history_def_prev;
33054219Sbostic     h->h_curr  = history_def_curr;
33154219Sbostic     h->h_enter = history_def_enter;
33254219Sbostic     h->h_add   = history_def_add;
33354219Sbostic 
33454219Sbostic     return h;
33554219Sbostic }
33654219Sbostic 
33754219Sbostic 
33854219Sbostic /* history_end():
33954219Sbostic  *	clean up history;
34054219Sbostic  */
34154219Sbostic public void
history_end(h)34254219Sbostic history_end(h)
34354219Sbostic     History *h;
34454219Sbostic {
34554219Sbostic     if (h->h_next == history_def_next)
34654219Sbostic 	history_def_end(h->h_ref);
34754219Sbostic }
34854219Sbostic 
34954219Sbostic 
35054219Sbostic 
35154219Sbostic /* history_set_num():
35254219Sbostic  *	Set history number of events
35354219Sbostic  */
35454219Sbostic private int
history_set_num(h,num)35554219Sbostic history_set_num(h, num)
35654219Sbostic     History *h;
35754219Sbostic     int num;
35854219Sbostic {
35954219Sbostic     if (h->h_next != history_def_next || num < 0)
36054219Sbostic 	return -1;
36154219Sbostic     history_def_set(h->h_ref, num);
36254219Sbostic     return 0;
36354219Sbostic }
36454219Sbostic 
36554219Sbostic 
36654219Sbostic /* history_set_fun():
36754219Sbostic  *	Set history functions
36854219Sbostic  */
36954219Sbostic private int
history_set_fun(h,first,next,last,prev,curr,enter,add,ptr)37054219Sbostic history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
37154219Sbostic     History *h;
37254219Sbostic     history_gfun_t first, next, last, prev, curr;
37354219Sbostic     history_efun_t enter, add;
37454219Sbostic     ptr_t ptr;
37554219Sbostic {
37654219Sbostic     if (first == NULL || next == NULL ||
37754219Sbostic         last == NULL  || prev == NULL || curr == NULL ||
37854219Sbostic 	enter == NULL || add == NULL ||
37954219Sbostic 	ptr == NULL ) {
38054219Sbostic 	if (h->h_next != history_def_next) {
38154219Sbostic 	    history_def_init(&h->h_ref, 0);
38254219Sbostic 	    h->h_first = history_def_first;
38354219Sbostic 	    h->h_next  = history_def_next;
38454219Sbostic 	    h->h_last  = history_def_last;
38554219Sbostic 	    h->h_prev  = history_def_prev;
38654219Sbostic 	    h->h_curr  = history_def_curr;
38754219Sbostic 	    h->h_enter = history_def_enter;
38854219Sbostic 	    h->h_add   = history_def_add;
38954219Sbostic 	}
39054219Sbostic 	return -1;
39154219Sbostic     }
39254219Sbostic 
39354219Sbostic     if (h->h_next == history_def_next)
39454219Sbostic 	history_def_end(h->h_ref);
39554219Sbostic 
39654219Sbostic     h->h_next  = next;
39754219Sbostic     h->h_first = first;
39854219Sbostic     h->h_enter = enter;
39954219Sbostic     h->h_add   = add;
40054219Sbostic     return 0;
40154219Sbostic }
40254219Sbostic 
40354219Sbostic 
40454219Sbostic /* history_prev_event():
40554219Sbostic  *	Find the previous event, with number given
40654219Sbostic  */
40754219Sbostic private const HistEvent *
history_prev_event(h,num)40854219Sbostic history_prev_event(h, num)
40954219Sbostic     History *h;
41054219Sbostic     int num;
41154219Sbostic {
41254219Sbostic     const HistEvent *ev;
41354219Sbostic     for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
41454219Sbostic 	if (ev->num == num)
41554219Sbostic 	    return ev;
41654219Sbostic     return NULL;
41754219Sbostic }
41854219Sbostic 
41954219Sbostic 
42054219Sbostic /* history_next_event():
42154219Sbostic  *	Find the next event, with number given
42254219Sbostic  */
42354219Sbostic private const HistEvent *
history_next_event(h,num)42454219Sbostic history_next_event(h, num)
42554219Sbostic     History *h;
42654219Sbostic     int num;
42754219Sbostic {
42854219Sbostic     const HistEvent *ev;
42954219Sbostic     for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
43054219Sbostic 	if (ev->num == num)
43154219Sbostic 	    return ev;
43254219Sbostic     return NULL;
43354219Sbostic }
43454219Sbostic 
43554219Sbostic 
43654219Sbostic /* history_prev_string():
43754219Sbostic  *	Find the previous event beginning with string
43854219Sbostic  */
43954219Sbostic private const HistEvent *
history_prev_string(h,str)44054219Sbostic history_prev_string(h, str)
44154219Sbostic     History *h;
44254219Sbostic     const char* str;
44354219Sbostic {
44454219Sbostic     const HistEvent *ev;
44554219Sbostic     size_t len = strlen(str);
44654219Sbostic 
44754219Sbostic     for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
44854219Sbostic 	if (strncmp(str, ev->str, len) == 0)
44954219Sbostic 	    return ev;
45054219Sbostic     return NULL;
45154219Sbostic }
45254219Sbostic 
45354219Sbostic 
45454219Sbostic /* history_next_string():
45554219Sbostic  *	Find the next event beginning with string
45654219Sbostic  */
45754219Sbostic private const HistEvent *
history_next_string(h,str)45854219Sbostic history_next_string(h, str)
45954219Sbostic     History *h;
46054219Sbostic     const char* str;
46154219Sbostic {
46254219Sbostic     const HistEvent *ev;
46354219Sbostic     size_t len = strlen(str);
46454219Sbostic 
46554219Sbostic     for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
46654219Sbostic 	if (strncmp(str, ev->str, len) == 0)
46754219Sbostic 	    return ev;
46854219Sbostic     return NULL;
46954219Sbostic }
47054219Sbostic 
47154219Sbostic 
47254219Sbostic /* history():
47354219Sbostic  *	User interface to history functions.
47454219Sbostic  */
47554219Sbostic const HistEvent *
47654219Sbostic #if __STDC__
history(History * h,int fun,...)47754219Sbostic history(History *h, int fun, ...)
47854219Sbostic #else
47954219Sbostic history(va_alist)
48054219Sbostic     va_dcl
48154219Sbostic #endif
48254219Sbostic {
48354219Sbostic     va_list va;
48455353Schristos     const HistEvent *ev = NULL;
48554219Sbostic     const char *str;
48654219Sbostic     static const HistEvent sev = { 0, "" };
48754219Sbostic 
48854219Sbostic #if __STDC__
48954219Sbostic     va_start(va, fun);
49054219Sbostic #else
49154219Sbostic     History *h;
49254219Sbostic     int fun;
49354219Sbostic     va_start(va);
49454219Sbostic     h = va_arg(va, History *);
49554219Sbostic     fun = va_arg(va, int);
49654219Sbostic #endif
49754219Sbostic 
49854219Sbostic     switch (fun) {
49954219Sbostic     case H_ADD:
50054219Sbostic 	str = va_arg(va, const char *);
50154219Sbostic 	ev = HADD(h, str);
50254219Sbostic 	break;
50354219Sbostic 
50454219Sbostic     case H_ENTER:
50554219Sbostic 	str = va_arg(va, const char *);
50654219Sbostic 	ev = HENTER(h, str);
50754219Sbostic 	break;
50854219Sbostic 
50954219Sbostic     case H_FIRST:
51054219Sbostic 	ev = HFIRST(h);
51154219Sbostic 	break;
51254219Sbostic 
51354219Sbostic     case H_NEXT:
51454219Sbostic 	ev = HNEXT(h);
51554219Sbostic 	break;
51654219Sbostic 
51754219Sbostic     case H_LAST:
51854219Sbostic 	ev = HLAST(h);
51954219Sbostic 	break;
52054219Sbostic 
52154219Sbostic     case H_PREV:
52254219Sbostic 	ev = HPREV(h);
52354219Sbostic 	break;
52454219Sbostic 
52554219Sbostic     case H_CURR:
52654219Sbostic 	ev = HCURR(h);
52754219Sbostic 	break;
52854219Sbostic 
52954219Sbostic     case H_PREV_EVENT:
53054219Sbostic 	ev = history_prev_event(h, va_arg(va, int));
53154219Sbostic 	break;
53254219Sbostic 
53354219Sbostic     case H_NEXT_EVENT:
53454219Sbostic 	ev = history_next_event(h, va_arg(va, int));
53554219Sbostic 	break;
53654219Sbostic 
53754219Sbostic     case H_PREV_STR:
53854219Sbostic 	ev = history_prev_string(h, va_arg(va, const char*));
53954219Sbostic 	break;
54054219Sbostic 
54154219Sbostic     case H_NEXT_STR:
54254219Sbostic 	ev = history_next_string(h, va_arg(va, const char*));
54354219Sbostic 	break;
54454219Sbostic 
54554219Sbostic     case H_EVENT:
54654219Sbostic 	if (history_set_num(h, va_arg(va, int)) == 0)
54754219Sbostic 	    ev = &sev;
54854219Sbostic 	break;
54954219Sbostic 
55054219Sbostic     case H_FUNC:
55154219Sbostic 	{
55254219Sbostic 	    history_gfun_t	first = va_arg(va, history_gfun_t);
55354219Sbostic 	    history_gfun_t	next  = va_arg(va, history_gfun_t);
55454219Sbostic 	    history_gfun_t	last  = va_arg(va, history_gfun_t);
55554219Sbostic 	    history_gfun_t	prev  = va_arg(va, history_gfun_t);
55654219Sbostic 	    history_gfun_t	curr  = va_arg(va, history_gfun_t);
55754219Sbostic 	    history_efun_t	enter = va_arg(va, history_efun_t);
55854219Sbostic 	    history_efun_t	add   = va_arg(va, history_efun_t);
55954219Sbostic 	    ptr_t		ptr   = va_arg(va, ptr_t);
56054219Sbostic 
56154219Sbostic 	    if (history_set_fun(h, first, next, last, prev,
56254219Sbostic 				   curr, enter, add, ptr) == 0)
56354219Sbostic 		ev = &sev;
56454219Sbostic 	}
56554219Sbostic 	break;
56654219Sbostic 
56754219Sbostic     case H_END:
56854219Sbostic 	history_end(h);
56954219Sbostic 	break;
57054219Sbostic 
57154219Sbostic     default:
57254219Sbostic 	break;
57354219Sbostic     }
57454219Sbostic     va_end(va);
57554219Sbostic     return ev;
57654219Sbostic }
577