11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1992, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This code is derived from software contributed to Berkeley by 61573Srgrimes * Christos Zoulas of Cornell University. 71573Srgrimes * 81573Srgrimes * Redistribution and use in source and binary forms, with or without 91573Srgrimes * modification, are permitted provided that the following conditions 101573Srgrimes * are met: 111573Srgrimes * 1. Redistributions of source code must retain the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer. 131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer in the 151573Srgrimes * documentation and/or other materials provided with the distribution. 16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 3184260Sobrien * 32237448Spfg * $NetBSD: history.c,v 1.34 2009/09/07 21:24:33 christos Exp $ 331573Srgrimes */ 341573Srgrimes 351573Srgrimes#if !defined(lint) && !defined(SCCSID) 361573Srgrimesstatic char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; 371573Srgrimes#endif /* not lint && not SCCSID */ 3884260Sobrien#include <sys/cdefs.h> 3984260Sobrien__FBSDID("$FreeBSD$"); 401573Srgrimes 411573Srgrimes/* 421573Srgrimes * hist.c: History access functions 431573Srgrimes */ 441573Srgrimes#include "sys.h" 451573Srgrimes 461573Srgrimes#include <string.h> 471573Srgrimes#include <stdlib.h> 481573Srgrimes#include <stdarg.h> 4984260Sobrien#include <vis.h> 5084260Sobrien#include <sys/stat.h> 511573Srgrimes 5284260Sobrienstatic const char hist_cookie[] = "_HiStOrY_V2_\n"; 5326926Smsmith 541573Srgrimes#include "histedit.h" 551573Srgrimes 5684260Sobrientypedef int (*history_gfun_t)(ptr_t, HistEvent *); 5784260Sobrientypedef int (*history_efun_t)(ptr_t, HistEvent *, const char *); 5884260Sobrientypedef void (*history_vfun_t)(ptr_t, HistEvent *); 5984260Sobrientypedef int (*history_sfun_t)(ptr_t, HistEvent *, const int); 601573Srgrimes 611573Srgrimesstruct history { 6284260Sobrien ptr_t h_ref; /* Argument for history fcns */ 6384260Sobrien int h_ent; /* Last entry point for history */ 6484260Sobrien history_gfun_t h_first; /* Get the first element */ 6584260Sobrien history_gfun_t h_next; /* Get the next element */ 6684260Sobrien history_gfun_t h_last; /* Get the last element */ 6784260Sobrien history_gfun_t h_prev; /* Get the previous element */ 6884260Sobrien history_gfun_t h_curr; /* Get the current element */ 6984260Sobrien history_sfun_t h_set; /* Set the current element */ 70148834Sstefanf history_sfun_t h_del; /* Set the given element */ 7184260Sobrien history_vfun_t h_clear; /* Clear the history list */ 7284260Sobrien history_efun_t h_enter; /* Add an element */ 7384260Sobrien history_efun_t h_add; /* Append to an element */ 741573Srgrimes}; 75148834Sstefanf 7684260Sobrien#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev) 7784260Sobrien#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev) 7884260Sobrien#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev) 7984260Sobrien#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev) 8084260Sobrien#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev) 8184260Sobrien#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n) 8284260Sobrien#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev) 8384260Sobrien#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str) 8484260Sobrien#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str) 85148834Sstefanf#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n) 861573Srgrimes 87148834Sstefanf#define h_strdup(a) strdup(a) 8884260Sobrien#define h_malloc(a) malloc(a) 8984260Sobrien#define h_realloc(a, b) realloc((a), (b)) 9084260Sobrien#define h_free(a) free(a) 911573Srgrimes 92148834Sstefanftypedef struct { 93148834Sstefanf int num; 94148834Sstefanf char *str; 95148834Sstefanf} HistEventPrivate; 961573Srgrimes 97148834Sstefanf 98148834Sstefanf 9984260Sobrienprivate int history_setsize(History *, HistEvent *, int); 10084260Sobrienprivate int history_getsize(History *, HistEvent *); 101148834Sstefanfprivate int history_setunique(History *, HistEvent *, int); 102148834Sstefanfprivate int history_getunique(History *, HistEvent *); 10384260Sobrienprivate int history_set_fun(History *, History *); 10484260Sobrienprivate int history_load(History *, const char *); 10584260Sobrienprivate int history_save(History *, const char *); 10684260Sobrienprivate int history_prev_event(History *, HistEvent *, int); 10784260Sobrienprivate int history_next_event(History *, HistEvent *, int); 10884260Sobrienprivate int history_next_string(History *, HistEvent *, const char *); 10984260Sobrienprivate int history_prev_string(History *, HistEvent *, const char *); 1101573Srgrimes 1111573Srgrimes 1121573Srgrimes/***********************************************************************/ 1131573Srgrimes 1141573Srgrimes/* 1151573Srgrimes * Builtin- history implementation 1161573Srgrimes */ 1171573Srgrimestypedef struct hentry_t { 11884260Sobrien HistEvent ev; /* What we return */ 119237448Spfg void *data; /* data */ 12084260Sobrien struct hentry_t *next; /* Next entry */ 12184260Sobrien struct hentry_t *prev; /* Previous entry */ 122148834Sstefanf} hentry_t; 1231573Srgrimes 1241573Srgrimestypedef struct history_t { 125148834Sstefanf hentry_t list; /* Fake list header element */ 126148834Sstefanf hentry_t *cursor; /* Current element in the list */ 127148834Sstefanf int max; /* Maximum number of events */ 128148834Sstefanf int cur; /* Current number of events */ 12984260Sobrien int eventid; /* For generation of unique event id */ 130148834Sstefanf int flags; /* History flags */ 131148834Sstefanf#define H_UNIQUE 1 /* Store only unique elements */ 132148834Sstefanf} history_t; 1331573Srgrimes 134148834Sstefanfprivate int history_def_next(ptr_t, HistEvent *); 13584260Sobrienprivate int history_def_first(ptr_t, HistEvent *); 136148834Sstefanfprivate int history_def_prev(ptr_t, HistEvent *); 13784260Sobrienprivate int history_def_last(ptr_t, HistEvent *); 13884260Sobrienprivate int history_def_curr(ptr_t, HistEvent *); 139148834Sstefanfprivate int history_def_set(ptr_t, HistEvent *, const int); 140148834Sstefanfprivate void history_def_clear(ptr_t, HistEvent *); 14184260Sobrienprivate int history_def_enter(ptr_t, HistEvent *, const char *); 14284260Sobrienprivate int history_def_add(ptr_t, HistEvent *, const char *); 143148834Sstefanfprivate int history_def_del(ptr_t, HistEvent *, const int); 144148834Sstefanf 145148834Sstefanfprivate int history_def_init(ptr_t *, HistEvent *, int); 14684260Sobrienprivate int history_def_insert(history_t *, HistEvent *, const char *); 14784260Sobrienprivate void history_def_delete(history_t *, HistEvent *, hentry_t *); 1481573Srgrimes 149237448Spfgprivate int history_deldata_nth(history_t *, HistEvent *, int, void **); 150237448Spfgprivate int history_set_nth(ptr_t, HistEvent *, int); 151237448Spfg 152148834Sstefanf#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num)) 153148834Sstefanf#define history_def_getsize(p) (((history_t *)p)->cur) 154148834Sstefanf#define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0) 155148834Sstefanf#define history_def_setunique(p, uni) \ 156148834Sstefanf if (uni) \ 157148834Sstefanf (((history_t *)p)->flags) |= H_UNIQUE; \ 158148834Sstefanf else \ 159148834Sstefanf (((history_t *)p)->flags) &= ~H_UNIQUE 1601573Srgrimes 16184260Sobrien#define he_strerror(code) he_errlist[code] 16284260Sobrien#define he_seterrev(evp, code) {\ 16384260Sobrien evp->num = code;\ 16484260Sobrien evp->str = he_strerror(code);\ 16584260Sobrien } 1661573Srgrimes 16784260Sobrien/* error messages */ 16884260Sobrienstatic const char *const he_errlist[] = { 16984260Sobrien "OK", 17084260Sobrien "unknown error", 17184260Sobrien "malloc() failed", 17284260Sobrien "first event not found", 17384260Sobrien "last event not found", 17484260Sobrien "empty list", 17584260Sobrien "no next event", 17684260Sobrien "no previous event", 17784260Sobrien "current event is invalid", 17884260Sobrien "event not found", 17984260Sobrien "can't read history from file", 18084260Sobrien "can't write history", 18184260Sobrien "required parameter(s) not supplied", 18284260Sobrien "history size negative", 18384260Sobrien "function not allowed with other history-functions-set the default", 18484260Sobrien "bad parameters" 18584260Sobrien}; 18684260Sobrien/* error codes */ 18784260Sobrien#define _HE_OK 0 18884260Sobrien#define _HE_UNKNOWN 1 18984260Sobrien#define _HE_MALLOC_FAILED 2 19084260Sobrien#define _HE_FIRST_NOTFOUND 3 19184260Sobrien#define _HE_LAST_NOTFOUND 4 19284260Sobrien#define _HE_EMPTY_LIST 5 19384260Sobrien#define _HE_END_REACHED 6 19484260Sobrien#define _HE_START_REACHED 7 19584260Sobrien#define _HE_CURR_INVALID 8 19684260Sobrien#define _HE_NOT_FOUND 9 19784260Sobrien#define _HE_HIST_READ 10 19884260Sobrien#define _HE_HIST_WRITE 11 19984260Sobrien#define _HE_PARAM_MISSING 12 20084260Sobrien#define _HE_SIZE_NEGATIVE 13 20184260Sobrien#define _HE_NOT_ALLOWED 14 20284260Sobrien#define _HE_BAD_PARAM 15 20384260Sobrien 2041573Srgrimes/* history_def_first(): 2051573Srgrimes * Default function to return the first event in the history. 2061573Srgrimes */ 20784260Sobrienprivate int 20884260Sobrienhistory_def_first(ptr_t p, HistEvent *ev) 2091573Srgrimes{ 21084260Sobrien history_t *h = (history_t *) p; 21184260Sobrien 21284260Sobrien h->cursor = h->list.next; 21384260Sobrien if (h->cursor != &h->list) 21484260Sobrien *ev = h->cursor->ev; 21584260Sobrien else { 21684260Sobrien he_seterrev(ev, _HE_FIRST_NOTFOUND); 21784260Sobrien return (-1); 21884260Sobrien } 21984260Sobrien 22084260Sobrien return (0); 2211573Srgrimes} 2221573Srgrimes 22384260Sobrien 2241573Srgrimes/* history_def_last(): 2251573Srgrimes * Default function to return the last event in the history. 2261573Srgrimes */ 22784260Sobrienprivate int 22884260Sobrienhistory_def_last(ptr_t p, HistEvent *ev) 2291573Srgrimes{ 23084260Sobrien history_t *h = (history_t *) p; 23184260Sobrien 23284260Sobrien h->cursor = h->list.prev; 23384260Sobrien if (h->cursor != &h->list) 23484260Sobrien *ev = h->cursor->ev; 23584260Sobrien else { 23684260Sobrien he_seterrev(ev, _HE_LAST_NOTFOUND); 23784260Sobrien return (-1); 23884260Sobrien } 23984260Sobrien 24084260Sobrien return (0); 2411573Srgrimes} 2421573Srgrimes 24384260Sobrien 2441573Srgrimes/* history_def_next(): 2451573Srgrimes * Default function to return the next event in the history. 2461573Srgrimes */ 24784260Sobrienprivate int 24884260Sobrienhistory_def_next(ptr_t p, HistEvent *ev) 2491573Srgrimes{ 25084260Sobrien history_t *h = (history_t *) p; 2511573Srgrimes 252148834Sstefanf if (h->cursor == &h->list) { 25384260Sobrien he_seterrev(ev, _HE_EMPTY_LIST); 25484260Sobrien return (-1); 25584260Sobrien } 2561573Srgrimes 257148834Sstefanf if (h->cursor->next == &h->list) { 25884260Sobrien he_seterrev(ev, _HE_END_REACHED); 25984260Sobrien return (-1); 26084260Sobrien } 26184260Sobrien 262148834Sstefanf h->cursor = h->cursor->next; 263148834Sstefanf *ev = h->cursor->ev; 264148834Sstefanf 26584260Sobrien return (0); 2661573Srgrimes} 2671573Srgrimes 2681573Srgrimes 2691573Srgrimes/* history_def_prev(): 2701573Srgrimes * Default function to return the previous event in the history. 2711573Srgrimes */ 27284260Sobrienprivate int 27384260Sobrienhistory_def_prev(ptr_t p, HistEvent *ev) 2741573Srgrimes{ 27584260Sobrien history_t *h = (history_t *) p; 2761573Srgrimes 277148834Sstefanf if (h->cursor == &h->list) { 27884260Sobrien he_seterrev(ev, 27984260Sobrien (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST); 28084260Sobrien return (-1); 28184260Sobrien } 2821573Srgrimes 283148834Sstefanf if (h->cursor->prev == &h->list) { 28484260Sobrien he_seterrev(ev, _HE_START_REACHED); 28584260Sobrien return (-1); 28684260Sobrien } 28784260Sobrien 288148834Sstefanf h->cursor = h->cursor->prev; 289148834Sstefanf *ev = h->cursor->ev; 290148834Sstefanf 29184260Sobrien return (0); 2921573Srgrimes} 2931573Srgrimes 2941573Srgrimes 2951573Srgrimes/* history_def_curr(): 2961573Srgrimes * Default function to return the current event in the history. 2971573Srgrimes */ 29884260Sobrienprivate int 29984260Sobrienhistory_def_curr(ptr_t p, HistEvent *ev) 3001573Srgrimes{ 30184260Sobrien history_t *h = (history_t *) p; 3021573Srgrimes 30384260Sobrien if (h->cursor != &h->list) 30484260Sobrien *ev = h->cursor->ev; 30584260Sobrien else { 30684260Sobrien he_seterrev(ev, 30784260Sobrien (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST); 30884260Sobrien return (-1); 30984260Sobrien } 31084260Sobrien 31184260Sobrien return (0); 3121573Srgrimes} 3131573Srgrimes 3141573Srgrimes 31584260Sobrien/* history_def_set(): 31684260Sobrien * Default function to set the current event in the history to the 31784260Sobrien * given one. 31884260Sobrien */ 31984260Sobrienprivate int 32084260Sobrienhistory_def_set(ptr_t p, HistEvent *ev, const int n) 32184260Sobrien{ 32284260Sobrien history_t *h = (history_t *) p; 32384260Sobrien 32484260Sobrien if (h->cur == 0) { 32584260Sobrien he_seterrev(ev, _HE_EMPTY_LIST); 32684260Sobrien return (-1); 32784260Sobrien } 32884260Sobrien if (h->cursor == &h->list || h->cursor->ev.num != n) { 32984260Sobrien for (h->cursor = h->list.next; h->cursor != &h->list; 33084260Sobrien h->cursor = h->cursor->next) 33184260Sobrien if (h->cursor->ev.num == n) 33284260Sobrien break; 33384260Sobrien } 33484260Sobrien if (h->cursor == &h->list) { 33584260Sobrien he_seterrev(ev, _HE_NOT_FOUND); 33684260Sobrien return (-1); 33784260Sobrien } 33884260Sobrien return (0); 33984260Sobrien} 34084260Sobrien 34184260Sobrien 342237448Spfg/* history_set_nth(): 343237448Spfg * Default function to set the current event in the history to the 344237448Spfg * n-th one. 345237448Spfg */ 346237448Spfgprivate int 347237448Spfghistory_set_nth(ptr_t p, HistEvent *ev, int n) 348237448Spfg{ 349237448Spfg history_t *h = (history_t *) p; 350237448Spfg 351237448Spfg if (h->cur == 0) { 352237448Spfg he_seterrev(ev, _HE_EMPTY_LIST); 353237448Spfg return (-1); 354237448Spfg } 355237448Spfg for (h->cursor = h->list.prev; h->cursor != &h->list; 356237448Spfg h->cursor = h->cursor->prev) 357237448Spfg if (n-- <= 0) 358237448Spfg break; 359237448Spfg if (h->cursor == &h->list) { 360237448Spfg he_seterrev(ev, _HE_NOT_FOUND); 361237448Spfg return (-1); 362237448Spfg } 363237448Spfg return (0); 364237448Spfg} 365237448Spfg 366237448Spfg 3671573Srgrimes/* history_def_add(): 3681573Srgrimes * Append string to element 3691573Srgrimes */ 37084260Sobrienprivate int 37184260Sobrienhistory_def_add(ptr_t p, HistEvent *ev, const char *str) 3721573Srgrimes{ 37384260Sobrien history_t *h = (history_t *) p; 37484260Sobrien size_t len; 37584260Sobrien char *s; 376148834Sstefanf HistEventPrivate *evp = (void *)&h->cursor->ev; 3771573Srgrimes 37884260Sobrien if (h->cursor == &h->list) 37984260Sobrien return (history_def_enter(p, ev, str)); 380148834Sstefanf len = strlen(evp->str) + strlen(str) + 1; 38184260Sobrien s = (char *) h_malloc(len); 382148834Sstefanf if (s == NULL) { 38384260Sobrien he_seterrev(ev, _HE_MALLOC_FAILED); 38484260Sobrien return (-1); 38584260Sobrien } 38684260Sobrien (void) strlcpy(s, h->cursor->ev.str, len); 38784260Sobrien (void) strlcat(s, str, len); 388148834Sstefanf h_free((ptr_t)evp->str); 389148834Sstefanf evp->str = s; 39084260Sobrien *ev = h->cursor->ev; 39184260Sobrien return (0); 3921573Srgrimes} 3931573Srgrimes 3941573Srgrimes 395237448Spfgprivate int 396237448Spfghistory_deldata_nth(history_t *h, HistEvent *ev, 397237448Spfg int num, void **data) 398237448Spfg{ 399237448Spfg if (history_set_nth(h, ev, num) != 0) 400237448Spfg return (-1); 401237448Spfg /* magic value to skip delete (just set to n-th history) */ 402237448Spfg if (data == (void **)-1) 403237448Spfg return (0); 404237448Spfg ev->str = strdup(h->cursor->ev.str); 405237448Spfg ev->num = h->cursor->ev.num; 406237448Spfg if (data) 407237448Spfg *data = h->cursor->data; 408237448Spfg history_def_delete(h, ev, h->cursor); 409237448Spfg return (0); 410237448Spfg} 411237448Spfg 412237448Spfg 413148834Sstefanf/* history_def_del(): 414148834Sstefanf * Delete element hp of the h list 415148834Sstefanf */ 416148834Sstefanf/* ARGSUSED */ 417148834Sstefanfprivate int 418148834Sstefanfhistory_def_del(ptr_t p, HistEvent *ev __unused, 419148834Sstefanf const int num) 420148834Sstefanf{ 421148834Sstefanf history_t *h = (history_t *) p; 422148834Sstefanf if (history_def_set(h, ev, num) != 0) 423148834Sstefanf return (-1); 424148834Sstefanf ev->str = strdup(h->cursor->ev.str); 425148834Sstefanf ev->num = h->cursor->ev.num; 426148834Sstefanf history_def_delete(h, ev, h->cursor); 427148834Sstefanf return (0); 428148834Sstefanf} 429148834Sstefanf 430148834Sstefanf 4311573Srgrimes/* history_def_delete(): 4321573Srgrimes * Delete element hp of the h list 4331573Srgrimes */ 43484260Sobrien/* ARGSUSED */ 4351573Srgrimesprivate void 436148834Sstefanfhistory_def_delete(history_t *h, 437148834Sstefanf HistEvent *ev __unused, hentry_t *hp) 4381573Srgrimes{ 439148834Sstefanf HistEventPrivate *evp = (void *)&hp->ev; 44084260Sobrien if (hp == &h->list) 44184260Sobrien abort(); 442237448Spfg if (h->cursor == hp) { 443148834Sstefanf h->cursor = hp->prev; 444237448Spfg if (h->cursor == &h->list) 445237448Spfg h->cursor = hp->next; 446237448Spfg } 44784260Sobrien hp->prev->next = hp->next; 44884260Sobrien hp->next->prev = hp->prev; 449148834Sstefanf h_free((ptr_t) evp->str); 45084260Sobrien h_free(hp); 45184260Sobrien h->cur--; 4521573Srgrimes} 4531573Srgrimes 4541573Srgrimes 4551573Srgrimes/* history_def_insert(): 4561573Srgrimes * Insert element with string str in the h list 4571573Srgrimes */ 45884260Sobrienprivate int 45984260Sobrienhistory_def_insert(history_t *h, HistEvent *ev, const char *str) 4601573Srgrimes{ 4611573Srgrimes 46284260Sobrien h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); 463148834Sstefanf if (h->cursor == NULL) 464148834Sstefanf goto oomem; 465148834Sstefanf if ((h->cursor->ev.str = h_strdup(str)) == NULL) { 466148834Sstefanf h_free((ptr_t)h->cursor); 467148834Sstefanf goto oomem; 46884260Sobrien } 469237448Spfg h->cursor->data = NULL; 47084260Sobrien h->cursor->ev.num = ++h->eventid; 47184260Sobrien h->cursor->next = h->list.next; 47284260Sobrien h->cursor->prev = &h->list; 47384260Sobrien h->list.next->prev = h->cursor; 47484260Sobrien h->list.next = h->cursor; 47584260Sobrien h->cur++; 47684260Sobrien 47784260Sobrien *ev = h->cursor->ev; 47884260Sobrien return (0); 479148834Sstefanfoomem: 480148834Sstefanf he_seterrev(ev, _HE_MALLOC_FAILED); 481148834Sstefanf return (-1); 4821573Srgrimes} 4831573Srgrimes 4841573Srgrimes 4851573Srgrimes/* history_def_enter(): 4861573Srgrimes * Default function to enter an item in the history 4871573Srgrimes */ 48884260Sobrienprivate int 48984260Sobrienhistory_def_enter(ptr_t p, HistEvent *ev, const char *str) 4901573Srgrimes{ 49184260Sobrien history_t *h = (history_t *) p; 4921573Srgrimes 493148834Sstefanf if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && 494148834Sstefanf strcmp(h->list.next->ev.str, str) == 0) 495148834Sstefanf return (0); 496148834Sstefanf 49784260Sobrien if (history_def_insert(h, ev, str) == -1) 49884260Sobrien return (-1); /* error, keep error message */ 4991573Srgrimes 50084260Sobrien /* 50184260Sobrien * Always keep at least one entry. 50284260Sobrien * This way we don't have to check for the empty list. 50384260Sobrien */ 504148834Sstefanf while (h->cur > h->max && h->cur > 0) 50584260Sobrien history_def_delete(h, ev, h->list.prev); 5061573Srgrimes 507148834Sstefanf return (1); 5081573Srgrimes} 5091573Srgrimes 5101573Srgrimes 5111573Srgrimes/* history_def_init(): 5121573Srgrimes * Default history initialization function 5131573Srgrimes */ 51484260Sobrien/* ARGSUSED */ 515148834Sstefanfprivate int 516148834Sstefanfhistory_def_init(ptr_t *p, HistEvent *ev __unused, int n) 5171573Srgrimes{ 51884260Sobrien history_t *h = (history_t *) h_malloc(sizeof(history_t)); 519148834Sstefanf if (h == NULL) 520148834Sstefanf return -1; 52184260Sobrien 52284260Sobrien if (n <= 0) 52384260Sobrien n = 0; 52484260Sobrien h->eventid = 0; 52584260Sobrien h->cur = 0; 52684260Sobrien h->max = n; 52784260Sobrien h->list.next = h->list.prev = &h->list; 52884260Sobrien h->list.ev.str = NULL; 52984260Sobrien h->list.ev.num = 0; 53084260Sobrien h->cursor = &h->list; 531148834Sstefanf h->flags = 0; 53284260Sobrien *p = (ptr_t) h; 533148834Sstefanf return 0; 5341573Srgrimes} 5351573Srgrimes 5361573Srgrimes 53726926Smsmith/* history_def_clear(): 5381573Srgrimes * Default history cleanup function 5391573Srgrimes */ 5401573Srgrimesprivate void 54184260Sobrienhistory_def_clear(ptr_t p, HistEvent *ev) 5421573Srgrimes{ 54384260Sobrien history_t *h = (history_t *) p; 5441573Srgrimes 54584260Sobrien while (h->list.prev != &h->list) 54684260Sobrien history_def_delete(h, ev, h->list.prev); 54784260Sobrien h->eventid = 0; 54884260Sobrien h->cur = 0; 5491573Srgrimes} 5501573Srgrimes 55184260Sobrien 55284260Sobrien 55384260Sobrien 5541573Srgrimes/************************************************************************/ 5551573Srgrimes 5561573Srgrimes/* history_init(): 5571573Srgrimes * Initialization function. 5581573Srgrimes */ 5591573Srgrimespublic History * 56084260Sobrienhistory_init(void) 5611573Srgrimes{ 562148834Sstefanf HistEvent ev; 56384260Sobrien History *h = (History *) h_malloc(sizeof(History)); 564148834Sstefanf if (h == NULL) 565148834Sstefanf return NULL; 5661573Srgrimes 567148834Sstefanf if (history_def_init(&h->h_ref, &ev, 0) == -1) { 568148834Sstefanf h_free((ptr_t)h); 569148834Sstefanf return NULL; 570148834Sstefanf } 57184260Sobrien h->h_ent = -1; 57284260Sobrien h->h_next = history_def_next; 57384260Sobrien h->h_first = history_def_first; 57484260Sobrien h->h_last = history_def_last; 57584260Sobrien h->h_prev = history_def_prev; 57684260Sobrien h->h_curr = history_def_curr; 57784260Sobrien h->h_set = history_def_set; 57884260Sobrien h->h_clear = history_def_clear; 57984260Sobrien h->h_enter = history_def_enter; 58084260Sobrien h->h_add = history_def_add; 581148834Sstefanf h->h_del = history_def_del; 5821573Srgrimes 58384260Sobrien return (h); 5841573Srgrimes} 5851573Srgrimes 5861573Srgrimes 5871573Srgrimes/* history_end(): 5881573Srgrimes * clean up history; 5891573Srgrimes */ 5901573Srgrimespublic void 59184260Sobrienhistory_end(History *h) 5921573Srgrimes{ 59384260Sobrien HistEvent ev; 59484260Sobrien 59584260Sobrien if (h->h_next == history_def_next) 59684260Sobrien history_def_clear(h->h_ref, &ev); 597167464Sstefanf h_free(h->h_ref); 598148834Sstefanf h_free(h); 5991573Srgrimes} 6001573Srgrimes 6011573Srgrimes 6021573Srgrimes 60384260Sobrien/* history_setsize(): 6041573Srgrimes * Set history number of events 6051573Srgrimes */ 6061573Srgrimesprivate int 60784260Sobrienhistory_setsize(History *h, HistEvent *ev, int num) 6081573Srgrimes{ 60984260Sobrien 61084260Sobrien if (h->h_next != history_def_next) { 61184260Sobrien he_seterrev(ev, _HE_NOT_ALLOWED); 61284260Sobrien return (-1); 61384260Sobrien } 61484260Sobrien if (num < 0) { 61584260Sobrien he_seterrev(ev, _HE_BAD_PARAM); 61684260Sobrien return (-1); 61784260Sobrien } 61884260Sobrien history_def_setsize(h->h_ref, num); 61984260Sobrien return (0); 6201573Srgrimes} 6211573Srgrimes 6221573Srgrimes 62384260Sobrien/* history_getsize(): 62484260Sobrien * Get number of events currently in history 62584260Sobrien */ 62684260Sobrienprivate int 62784260Sobrienhistory_getsize(History *h, HistEvent *ev) 62884260Sobrien{ 62984260Sobrien if (h->h_next != history_def_next) { 63084260Sobrien he_seterrev(ev, _HE_NOT_ALLOWED); 63184260Sobrien return (-1); 63284260Sobrien } 633148834Sstefanf ev->num = history_def_getsize(h->h_ref); 634148834Sstefanf if (ev->num < -1) { 63584260Sobrien he_seterrev(ev, _HE_SIZE_NEGATIVE); 63684260Sobrien return (-1); 63784260Sobrien } 63884260Sobrien return (0); 63984260Sobrien} 64084260Sobrien 64184260Sobrien 642148834Sstefanf/* history_setunique(): 643148834Sstefanf * Set if adjacent equal events should not be entered in history. 644148834Sstefanf */ 645148834Sstefanfprivate int 646148834Sstefanfhistory_setunique(History *h, HistEvent *ev, int uni) 647148834Sstefanf{ 648148834Sstefanf 649148834Sstefanf if (h->h_next != history_def_next) { 650148834Sstefanf he_seterrev(ev, _HE_NOT_ALLOWED); 651148834Sstefanf return (-1); 652148834Sstefanf } 653148834Sstefanf history_def_setunique(h->h_ref, uni); 654148834Sstefanf return (0); 655148834Sstefanf} 656148834Sstefanf 657148834Sstefanf 658148834Sstefanf/* history_getunique(): 659148834Sstefanf * Get if adjacent equal events should not be entered in history. 660148834Sstefanf */ 661148834Sstefanfprivate int 662148834Sstefanfhistory_getunique(History *h, HistEvent *ev) 663148834Sstefanf{ 664148834Sstefanf if (h->h_next != history_def_next) { 665148834Sstefanf he_seterrev(ev, _HE_NOT_ALLOWED); 666148834Sstefanf return (-1); 667148834Sstefanf } 668148834Sstefanf ev->num = history_def_getunique(h->h_ref); 669148834Sstefanf return (0); 670148834Sstefanf} 671148834Sstefanf 672148834Sstefanf 6731573Srgrimes/* history_set_fun(): 6741573Srgrimes * Set history functions 6751573Srgrimes */ 6761573Srgrimesprivate int 67784260Sobrienhistory_set_fun(History *h, History *nh) 6781573Srgrimes{ 67984260Sobrien HistEvent ev; 68084260Sobrien 68184260Sobrien if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL || 68284260Sobrien nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL || 68384260Sobrien nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || 684148834Sstefanf nh->h_del == NULL || nh->h_ref == NULL) { 68584260Sobrien if (h->h_next != history_def_next) { 68684260Sobrien history_def_init(&h->h_ref, &ev, 0); 68784260Sobrien h->h_first = history_def_first; 68884260Sobrien h->h_next = history_def_next; 68984260Sobrien h->h_last = history_def_last; 69084260Sobrien h->h_prev = history_def_prev; 69184260Sobrien h->h_curr = history_def_curr; 69284260Sobrien h->h_set = history_def_set; 69384260Sobrien h->h_clear = history_def_clear; 69484260Sobrien h->h_enter = history_def_enter; 69584260Sobrien h->h_add = history_def_add; 696148834Sstefanf h->h_del = history_def_del; 69784260Sobrien } 69884260Sobrien return (-1); 6991573Srgrimes } 70084260Sobrien if (h->h_next == history_def_next) 70184260Sobrien history_def_clear(h->h_ref, &ev); 7021573Srgrimes 70384260Sobrien h->h_ent = -1; 70484260Sobrien h->h_first = nh->h_first; 70584260Sobrien h->h_next = nh->h_next; 70684260Sobrien h->h_last = nh->h_last; 70784260Sobrien h->h_prev = nh->h_prev; 70884260Sobrien h->h_curr = nh->h_curr; 70984260Sobrien h->h_set = nh->h_set; 71084260Sobrien h->h_clear = nh->h_clear; 71184260Sobrien h->h_enter = nh->h_enter; 71284260Sobrien h->h_add = nh->h_add; 713148834Sstefanf h->h_del = nh->h_del; 7141573Srgrimes 71584260Sobrien return (0); 7161573Srgrimes} 7171573Srgrimes 7181573Srgrimes 71926926Smsmith/* history_load(): 72026926Smsmith * History load function 72126926Smsmith */ 72226926Smsmithprivate int 72384260Sobrienhistory_load(History *h, const char *fname) 72426926Smsmith{ 72584260Sobrien FILE *fp; 72684260Sobrien char *line; 72784260Sobrien size_t sz, max_size; 72884260Sobrien char *ptr; 72984260Sobrien int i = -1; 73084260Sobrien HistEvent ev; 73126926Smsmith 73284260Sobrien if ((fp = fopen(fname, "r")) == NULL) 73384260Sobrien return (i); 73426926Smsmith 73584260Sobrien if ((line = fgetln(fp, &sz)) == NULL) 73684260Sobrien goto done; 73726926Smsmith 73884260Sobrien if (strncmp(line, hist_cookie, sz) != 0) 73984260Sobrien goto done; 74026926Smsmith 74184260Sobrien ptr = h_malloc(max_size = 1024); 742148834Sstefanf if (ptr == NULL) 743148834Sstefanf goto done; 74484260Sobrien for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { 74584260Sobrien char c = line[sz]; 74684260Sobrien 74784260Sobrien if (sz != 0 && line[sz - 1] == '\n') 74884260Sobrien line[--sz] = '\0'; 74984260Sobrien else 75084260Sobrien line[sz] = '\0'; 75184260Sobrien 75284260Sobrien if (max_size < sz) { 753148834Sstefanf char *nptr; 754148834Sstefanf max_size = (sz + 1024) & ~1023; 755148834Sstefanf nptr = h_realloc(ptr, max_size); 756148834Sstefanf if (nptr == NULL) { 757148834Sstefanf i = -1; 758148834Sstefanf goto oomem; 759148834Sstefanf } 760148834Sstefanf ptr = nptr; 76184260Sobrien } 76284260Sobrien (void) strunvis(ptr, line); 76384260Sobrien line[sz] = c; 764148834Sstefanf if (HENTER(h, &ev, ptr) == -1) { 765237448Spfg i = -1; 766237448Spfg goto oomem; 767148834Sstefanf } 76884260Sobrien } 769148834Sstefanfoomem: 770148834Sstefanf h_free((ptr_t)ptr); 77126926Smsmithdone: 77284260Sobrien (void) fclose(fp); 77384260Sobrien return (i); 77426926Smsmith} 77526926Smsmith 77626926Smsmith 77726926Smsmith/* history_save(): 77826926Smsmith * History save function 77926926Smsmith */ 78026926Smsmithprivate int 78184260Sobrienhistory_save(History *h, const char *fname) 78226926Smsmith{ 78384260Sobrien FILE *fp; 78484260Sobrien HistEvent ev; 785148834Sstefanf int i = -1, retval; 78684260Sobrien size_t len, max_size; 78784260Sobrien char *ptr; 78826926Smsmith 78984260Sobrien if ((fp = fopen(fname, "w")) == NULL) 79084260Sobrien return (-1); 79126926Smsmith 792148834Sstefanf if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) 793148834Sstefanf goto done; 794148834Sstefanf if (fputs(hist_cookie, fp) == EOF) 795148834Sstefanf goto done; 79684260Sobrien ptr = h_malloc(max_size = 1024); 797148834Sstefanf if (ptr == NULL) 798148834Sstefanf goto done; 799148834Sstefanf for (i = 0, retval = HLAST(h, &ev); 80084260Sobrien retval != -1; 80184260Sobrien retval = HPREV(h, &ev), i++) { 80284260Sobrien len = strlen(ev.str) * 4; 80384260Sobrien if (len >= max_size) { 804148834Sstefanf char *nptr; 805148834Sstefanf max_size = (len + 1024) & ~1023; 806148834Sstefanf nptr = h_realloc(ptr, max_size); 807148834Sstefanf if (nptr == NULL) { 808148834Sstefanf i = -1; 809148834Sstefanf goto oomem; 810148834Sstefanf } 811148834Sstefanf ptr = nptr; 81284260Sobrien } 81384260Sobrien (void) strvis(ptr, ev.str, VIS_WHITE); 814105095Stjr (void) fprintf(fp, "%s\n", ptr); 81584260Sobrien } 816148834Sstefanfoomem: 817148834Sstefanf h_free((ptr_t)ptr); 818148834Sstefanfdone: 81984260Sobrien (void) fclose(fp); 82084260Sobrien return (i); 82126926Smsmith} 82226926Smsmith 82326926Smsmith 8241573Srgrimes/* history_prev_event(): 8251573Srgrimes * Find the previous event, with number given 8261573Srgrimes */ 82784260Sobrienprivate int 82884260Sobrienhistory_prev_event(History *h, HistEvent *ev, int num) 8291573Srgrimes{ 83084260Sobrien int retval; 83184260Sobrien 83284260Sobrien for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) 83384260Sobrien if (ev->num == num) 83484260Sobrien return (0); 83584260Sobrien 83684260Sobrien he_seterrev(ev, _HE_NOT_FOUND); 83784260Sobrien return (-1); 8381573Srgrimes} 8391573Srgrimes 8401573Srgrimes 841237448Spfgprivate int 842237448Spfghistory_next_evdata(History *h, HistEvent *ev, int num, void **d) 843237448Spfg{ 844237448Spfg int retval; 845237448Spfg 846237448Spfg for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) 847237448Spfg if (num-- <= 0) { 848237448Spfg if (d) 849237448Spfg *d = ((history_t *)h->h_ref)->cursor->data; 850237448Spfg return (0); 851237448Spfg } 852237448Spfg 853237448Spfg he_seterrev(ev, _HE_NOT_FOUND); 854237448Spfg return (-1); 855237448Spfg} 856237448Spfg 857237448Spfg 8581573Srgrimes/* history_next_event(): 8591573Srgrimes * Find the next event, with number given 8601573Srgrimes */ 86184260Sobrienprivate int 86284260Sobrienhistory_next_event(History *h, HistEvent *ev, int num) 8631573Srgrimes{ 86484260Sobrien int retval; 86584260Sobrien 86684260Sobrien for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) 86784260Sobrien if (ev->num == num) 86884260Sobrien return (0); 86984260Sobrien 87084260Sobrien he_seterrev(ev, _HE_NOT_FOUND); 87184260Sobrien return (-1); 8721573Srgrimes} 8731573Srgrimes 8741573Srgrimes 8751573Srgrimes/* history_prev_string(): 8761573Srgrimes * Find the previous event beginning with string 8771573Srgrimes */ 87884260Sobrienprivate int 87984260Sobrienhistory_prev_string(History *h, HistEvent *ev, const char *str) 8801573Srgrimes{ 88184260Sobrien size_t len = strlen(str); 88284260Sobrien int retval; 8831573Srgrimes 88484260Sobrien for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) 88584260Sobrien if (strncmp(str, ev->str, len) == 0) 88684260Sobrien return (0); 88784260Sobrien 88884260Sobrien he_seterrev(ev, _HE_NOT_FOUND); 88984260Sobrien return (-1); 8901573Srgrimes} 8911573Srgrimes 8921573Srgrimes 8931573Srgrimes/* history_next_string(): 8941573Srgrimes * Find the next event beginning with string 8951573Srgrimes */ 89684260Sobrienprivate int 89784260Sobrienhistory_next_string(History *h, HistEvent *ev, const char *str) 8981573Srgrimes{ 89984260Sobrien size_t len = strlen(str); 90084260Sobrien int retval; 9011573Srgrimes 90284260Sobrien for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) 90384260Sobrien if (strncmp(str, ev->str, len) == 0) 90484260Sobrien return (0); 90584260Sobrien 90684260Sobrien he_seterrev(ev, _HE_NOT_FOUND); 90784260Sobrien return (-1); 9081573Srgrimes} 9091573Srgrimes 9101573Srgrimes 9111573Srgrimes/* history(): 9121573Srgrimes * User interface to history functions. 9131573Srgrimes */ 91484260Sobrienint 91584260Sobrienhistory(History *h, HistEvent *ev, int fun, ...) 9161573Srgrimes{ 91784260Sobrien va_list va; 91884260Sobrien const char *str; 91984260Sobrien int retval; 9201573Srgrimes 92184260Sobrien va_start(va, fun); 9221573Srgrimes 92384260Sobrien he_seterrev(ev, _HE_OK); 9241573Srgrimes 92584260Sobrien switch (fun) { 92684260Sobrien case H_GETSIZE: 92784260Sobrien retval = history_getsize(h, ev); 92884260Sobrien break; 9291573Srgrimes 93084260Sobrien case H_SETSIZE: 93184260Sobrien retval = history_setsize(h, ev, va_arg(va, int)); 93284260Sobrien break; 9331573Srgrimes 934148834Sstefanf case H_GETUNIQUE: 935148834Sstefanf retval = history_getunique(h, ev); 936148834Sstefanf break; 937148834Sstefanf 938148834Sstefanf case H_SETUNIQUE: 939148834Sstefanf retval = history_setunique(h, ev, va_arg(va, int)); 940148834Sstefanf break; 941148834Sstefanf 94284260Sobrien case H_ADD: 94384260Sobrien str = va_arg(va, const char *); 94484260Sobrien retval = HADD(h, ev, str); 94584260Sobrien break; 9461573Srgrimes 947148834Sstefanf case H_DEL: 948148834Sstefanf retval = HDEL(h, ev, va_arg(va, const int)); 949148834Sstefanf break; 950148834Sstefanf 95184260Sobrien case H_ENTER: 95284260Sobrien str = va_arg(va, const char *); 95384260Sobrien if ((retval = HENTER(h, ev, str)) != -1) 95484260Sobrien h->h_ent = ev->num; 95584260Sobrien break; 9561573Srgrimes 95784260Sobrien case H_APPEND: 95884260Sobrien str = va_arg(va, const char *); 95984260Sobrien if ((retval = HSET(h, ev, h->h_ent)) != -1) 96084260Sobrien retval = HADD(h, ev, str); 96184260Sobrien break; 9621573Srgrimes 96384260Sobrien case H_FIRST: 96484260Sobrien retval = HFIRST(h, ev); 96584260Sobrien break; 9661573Srgrimes 96784260Sobrien case H_NEXT: 96884260Sobrien retval = HNEXT(h, ev); 96984260Sobrien break; 97026926Smsmith 97184260Sobrien case H_LAST: 97284260Sobrien retval = HLAST(h, ev); 97384260Sobrien break; 9741573Srgrimes 97584260Sobrien case H_PREV: 97684260Sobrien retval = HPREV(h, ev); 97784260Sobrien break; 9781573Srgrimes 97984260Sobrien case H_CURR: 98084260Sobrien retval = HCURR(h, ev); 98184260Sobrien break; 9821573Srgrimes 98384260Sobrien case H_SET: 98484260Sobrien retval = HSET(h, ev, va_arg(va, const int)); 98584260Sobrien break; 9861573Srgrimes 98784260Sobrien case H_CLEAR: 98884260Sobrien HCLEAR(h, ev); 98984260Sobrien retval = 0; 99084260Sobrien break; 9911573Srgrimes 99284260Sobrien case H_LOAD: 99384260Sobrien retval = history_load(h, va_arg(va, const char *)); 99484260Sobrien if (retval == -1) 99584260Sobrien he_seterrev(ev, _HE_HIST_READ); 99684260Sobrien break; 99784260Sobrien 99884260Sobrien case H_SAVE: 99984260Sobrien retval = history_save(h, va_arg(va, const char *)); 100084260Sobrien if (retval == -1) 100184260Sobrien he_seterrev(ev, _HE_HIST_WRITE); 100284260Sobrien break; 100384260Sobrien 100484260Sobrien case H_PREV_EVENT: 100584260Sobrien retval = history_prev_event(h, ev, va_arg(va, int)); 100684260Sobrien break; 100784260Sobrien 100884260Sobrien case H_NEXT_EVENT: 100984260Sobrien retval = history_next_event(h, ev, va_arg(va, int)); 101084260Sobrien break; 101184260Sobrien 101284260Sobrien case H_PREV_STR: 101384260Sobrien retval = history_prev_string(h, ev, va_arg(va, const char *)); 101484260Sobrien break; 101584260Sobrien 101684260Sobrien case H_NEXT_STR: 101784260Sobrien retval = history_next_string(h, ev, va_arg(va, const char *)); 101884260Sobrien break; 101984260Sobrien 102084260Sobrien case H_FUNC: 10211573Srgrimes { 102284260Sobrien History hf; 10231573Srgrimes 102484260Sobrien hf.h_ref = va_arg(va, ptr_t); 102584260Sobrien h->h_ent = -1; 102684260Sobrien hf.h_first = va_arg(va, history_gfun_t); 102784260Sobrien hf.h_next = va_arg(va, history_gfun_t); 102884260Sobrien hf.h_last = va_arg(va, history_gfun_t); 102984260Sobrien hf.h_prev = va_arg(va, history_gfun_t); 103084260Sobrien hf.h_curr = va_arg(va, history_gfun_t); 103184260Sobrien hf.h_set = va_arg(va, history_sfun_t); 103284260Sobrien hf.h_clear = va_arg(va, history_vfun_t); 103384260Sobrien hf.h_enter = va_arg(va, history_efun_t); 103484260Sobrien hf.h_add = va_arg(va, history_efun_t); 1035148834Sstefanf hf.h_del = va_arg(va, history_sfun_t); 103684260Sobrien 103784260Sobrien if ((retval = history_set_fun(h, &hf)) == -1) 103884260Sobrien he_seterrev(ev, _HE_PARAM_MISSING); 103984260Sobrien break; 10401573Srgrimes } 10411573Srgrimes 104284260Sobrien case H_END: 104384260Sobrien history_end(h); 104484260Sobrien retval = 0; 104584260Sobrien break; 10461573Srgrimes 1047237448Spfg case H_NEXT_EVDATA: 1048237448Spfg { 1049237448Spfg int num = va_arg(va, int); 1050237448Spfg void **d = va_arg(va, void **); 1051237448Spfg retval = history_next_evdata(h, ev, num, d); 1052237448Spfg break; 1053237448Spfg } 1054237448Spfg 1055237448Spfg case H_DELDATA: 1056237448Spfg { 1057237448Spfg int num = va_arg(va, int); 1058237448Spfg void **d = va_arg(va, void **); 1059237448Spfg retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d); 1060237448Spfg break; 1061237448Spfg } 1062237448Spfg 1063237448Spfg case H_REPLACE: /* only use after H_NEXT_EVDATA */ 1064237448Spfg { 1065237448Spfg const char *line = va_arg(va, const char *); 1066237448Spfg void *d = va_arg(va, void *); 1067237448Spfg const char *s; 1068237448Spfg if(!line || !(s = strdup(line))) { 1069237448Spfg retval = -1; 1070237448Spfg break; 1071237448Spfg } 1072237448Spfg ((history_t *)h->h_ref)->cursor->ev.str = s; 1073237448Spfg ((history_t *)h->h_ref)->cursor->data = d; 1074237448Spfg retval = 0; 1075237448Spfg break; 1076237448Spfg } 1077237448Spfg 107884260Sobrien default: 107984260Sobrien retval = -1; 108084260Sobrien he_seterrev(ev, _HE_UNKNOWN); 108184260Sobrien break; 108284260Sobrien } 108384260Sobrien va_end(va); 1084237448Spfg return retval; 10851573Srgrimes} 1086