history.c revision 1.34 1 1.34 christos /* $NetBSD: history.c,v 1.34 2009/09/07 21:24:33 christos Exp $ */
2 1.3 lukem
3 1.1 cgd /*-
4 1.1 cgd * Copyright (c) 1992, 1993
5 1.1 cgd * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * This code is derived from software contributed to Berkeley by
8 1.1 cgd * Christos Zoulas of Cornell University.
9 1.1 cgd *
10 1.1 cgd * Redistribution and use in source and binary forms, with or without
11 1.1 cgd * modification, are permitted provided that the following conditions
12 1.1 cgd * are met:
13 1.1 cgd * 1. Redistributions of source code must retain the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer.
15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 cgd * notice, this list of conditions and the following disclaimer in the
17 1.1 cgd * documentation and/or other materials provided with the distribution.
18 1.24 agc * 3. Neither the name of the University nor the names of its contributors
19 1.1 cgd * may be used to endorse or promote products derived from this software
20 1.1 cgd * without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 cgd * SUCH DAMAGE.
33 1.1 cgd */
34 1.1 cgd
35 1.19 christos #include "config.h"
36 1.1 cgd #if !defined(lint) && !defined(SCCSID)
37 1.6 christos #if 0
38 1.1 cgd static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
39 1.6 christos #else
40 1.34 christos __RCSID("$NetBSD: history.c,v 1.34 2009/09/07 21:24:33 christos Exp $");
41 1.6 christos #endif
42 1.1 cgd #endif /* not lint && not SCCSID */
43 1.1 cgd
44 1.1 cgd /*
45 1.1 cgd * hist.c: History access functions
46 1.1 cgd */
47 1.1 cgd #include <string.h>
48 1.1 cgd #include <stdlib.h>
49 1.1 cgd #include <stdarg.h>
50 1.19 christos #ifdef HAVE_VIS_H
51 1.12 christos #include <vis.h>
52 1.19 christos #else
53 1.19 christos #include "np/vis.h"
54 1.19 christos #endif
55 1.17 christos #include <sys/stat.h>
56 1.1 cgd
57 1.12 christos static const char hist_cookie[] = "_HiStOrY_V2_\n";
58 1.2 christos
59 1.1 cgd #include "histedit.h"
60 1.1 cgd
61 1.16 lukem typedef int (*history_gfun_t)(ptr_t, HistEvent *);
62 1.16 lukem typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
63 1.16 lukem typedef void (*history_vfun_t)(ptr_t, HistEvent *);
64 1.16 lukem typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
65 1.1 cgd
66 1.1 cgd struct history {
67 1.16 lukem ptr_t h_ref; /* Argument for history fcns */
68 1.16 lukem int h_ent; /* Last entry point for history */
69 1.16 lukem history_gfun_t h_first; /* Get the first element */
70 1.16 lukem history_gfun_t h_next; /* Get the next element */
71 1.16 lukem history_gfun_t h_last; /* Get the last element */
72 1.16 lukem history_gfun_t h_prev; /* Get the previous element */
73 1.16 lukem history_gfun_t h_curr; /* Get the current element */
74 1.16 lukem history_sfun_t h_set; /* Set the current element */
75 1.30 christos history_sfun_t h_del; /* Set the given element */
76 1.16 lukem history_vfun_t h_clear; /* Clear the history list */
77 1.16 lukem history_efun_t h_enter; /* Add an element */
78 1.16 lukem history_efun_t h_add; /* Append to an element */
79 1.1 cgd };
80 1.22 christos
81 1.16 lukem #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
82 1.16 lukem #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
83 1.16 lukem #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
84 1.16 lukem #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
85 1.16 lukem #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
86 1.16 lukem #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
87 1.16 lukem #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
88 1.7 christos #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
89 1.7 christos #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
90 1.30 christos #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
91 1.1 cgd
92 1.25 christos #define h_strdup(a) strdup(a)
93 1.16 lukem #define h_malloc(a) malloc(a)
94 1.16 lukem #define h_realloc(a, b) realloc((a), (b))
95 1.16 lukem #define h_free(a) free(a)
96 1.1 cgd
97 1.19 christos typedef struct {
98 1.19 christos int num;
99 1.19 christos char *str;
100 1.19 christos } HistEventPrivate;
101 1.19 christos
102 1.19 christos
103 1.1 cgd
104 1.16 lukem private int history_setsize(History *, HistEvent *, int);
105 1.16 lukem private int history_getsize(History *, HistEvent *);
106 1.22 christos private int history_setunique(History *, HistEvent *, int);
107 1.22 christos private int history_getunique(History *, HistEvent *);
108 1.16 lukem private int history_set_fun(History *, History *);
109 1.16 lukem private int history_load(History *, const char *);
110 1.16 lukem private int history_save(History *, const char *);
111 1.16 lukem private int history_prev_event(History *, HistEvent *, int);
112 1.16 lukem private int history_next_event(History *, HistEvent *, int);
113 1.16 lukem private int history_next_string(History *, HistEvent *, const char *);
114 1.16 lukem private int history_prev_string(History *, HistEvent *, const char *);
115 1.1 cgd
116 1.1 cgd
117 1.1 cgd /***********************************************************************/
118 1.1 cgd
119 1.1 cgd /*
120 1.1 cgd * Builtin- history implementation
121 1.1 cgd */
122 1.1 cgd typedef struct hentry_t {
123 1.16 lukem HistEvent ev; /* What we return */
124 1.34 christos void *data; /* data */
125 1.16 lukem struct hentry_t *next; /* Next entry */
126 1.16 lukem struct hentry_t *prev; /* Previous entry */
127 1.22 christos } hentry_t;
128 1.1 cgd
129 1.1 cgd typedef struct history_t {
130 1.22 christos hentry_t list; /* Fake list header element */
131 1.22 christos hentry_t *cursor; /* Current element in the list */
132 1.22 christos int max; /* Maximum number of events */
133 1.22 christos int cur; /* Current number of events */
134 1.16 lukem int eventid; /* For generation of unique event id */
135 1.22 christos int flags; /* History flags */
136 1.22 christos #define H_UNIQUE 1 /* Store only unique elements */
137 1.22 christos } history_t;
138 1.16 lukem
139 1.30 christos private int history_def_next(ptr_t, HistEvent *);
140 1.16 lukem private int history_def_first(ptr_t, HistEvent *);
141 1.30 christos private int history_def_prev(ptr_t, HistEvent *);
142 1.16 lukem private int history_def_last(ptr_t, HistEvent *);
143 1.16 lukem private int history_def_curr(ptr_t, HistEvent *);
144 1.30 christos private int history_def_set(ptr_t, HistEvent *, const int);
145 1.30 christos private void history_def_clear(ptr_t, HistEvent *);
146 1.16 lukem private int history_def_enter(ptr_t, HistEvent *, const char *);
147 1.16 lukem private int history_def_add(ptr_t, HistEvent *, const char *);
148 1.30 christos private int history_def_del(ptr_t, HistEvent *, const int);
149 1.30 christos
150 1.21 christos private int history_def_init(ptr_t *, HistEvent *, int);
151 1.16 lukem private int history_def_insert(history_t *, HistEvent *, const char *);
152 1.16 lukem private void history_def_delete(history_t *, HistEvent *, hentry_t *);
153 1.1 cgd
154 1.34 christos private int history_deldata_nth(history_t *, HistEvent *, int, void **);
155 1.34 christos private int history_set_nth(ptr_t, HistEvent *, int);
156 1.34 christos
157 1.22 christos #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
158 1.22 christos #define history_def_getsize(p) (((history_t *)p)->cur)
159 1.22 christos #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
160 1.22 christos #define history_def_setunique(p, uni) \
161 1.22 christos if (uni) \
162 1.22 christos (((history_t *)p)->flags) |= H_UNIQUE; \
163 1.22 christos else \
164 1.22 christos (((history_t *)p)->flags) &= ~H_UNIQUE
165 1.1 cgd
166 1.16 lukem #define he_strerror(code) he_errlist[code]
167 1.16 lukem #define he_seterrev(evp, code) {\
168 1.7 christos evp->num = code;\
169 1.7 christos evp->str = he_strerror(code);\
170 1.7 christos }
171 1.14 simonb
172 1.7 christos /* error messages */
173 1.7 christos static const char *const he_errlist[] = {
174 1.16 lukem "OK",
175 1.16 lukem "unknown error",
176 1.16 lukem "malloc() failed",
177 1.16 lukem "first event not found",
178 1.16 lukem "last event not found",
179 1.16 lukem "empty list",
180 1.16 lukem "no next event",
181 1.16 lukem "no previous event",
182 1.16 lukem "current event is invalid",
183 1.16 lukem "event not found",
184 1.16 lukem "can't read history from file",
185 1.16 lukem "can't write history",
186 1.16 lukem "required parameter(s) not supplied",
187 1.16 lukem "history size negative",
188 1.16 lukem "function not allowed with other history-functions-set the default",
189 1.16 lukem "bad parameters"
190 1.7 christos };
191 1.7 christos /* error codes */
192 1.16 lukem #define _HE_OK 0
193 1.16 lukem #define _HE_UNKNOWN 1
194 1.16 lukem #define _HE_MALLOC_FAILED 2
195 1.16 lukem #define _HE_FIRST_NOTFOUND 3
196 1.16 lukem #define _HE_LAST_NOTFOUND 4
197 1.16 lukem #define _HE_EMPTY_LIST 5
198 1.16 lukem #define _HE_END_REACHED 6
199 1.16 lukem #define _HE_START_REACHED 7
200 1.16 lukem #define _HE_CURR_INVALID 8
201 1.16 lukem #define _HE_NOT_FOUND 9
202 1.16 lukem #define _HE_HIST_READ 10
203 1.16 lukem #define _HE_HIST_WRITE 11
204 1.16 lukem #define _HE_PARAM_MISSING 12
205 1.16 lukem #define _HE_SIZE_NEGATIVE 13
206 1.16 lukem #define _HE_NOT_ALLOWED 14
207 1.16 lukem #define _HE_BAD_PARAM 15
208 1.1 cgd
209 1.1 cgd /* history_def_first():
210 1.1 cgd * Default function to return the first event in the history.
211 1.1 cgd */
212 1.7 christos private int
213 1.16 lukem history_def_first(ptr_t p, HistEvent *ev)
214 1.1 cgd {
215 1.16 lukem history_t *h = (history_t *) p;
216 1.7 christos
217 1.16 lukem h->cursor = h->list.next;
218 1.16 lukem if (h->cursor != &h->list)
219 1.16 lukem *ev = h->cursor->ev;
220 1.16 lukem else {
221 1.16 lukem he_seterrev(ev, _HE_FIRST_NOTFOUND);
222 1.16 lukem return (-1);
223 1.16 lukem }
224 1.7 christos
225 1.16 lukem return (0);
226 1.1 cgd }
227 1.1 cgd
228 1.8 christos
229 1.1 cgd /* history_def_last():
230 1.1 cgd * Default function to return the last event in the history.
231 1.1 cgd */
232 1.7 christos private int
233 1.16 lukem history_def_last(ptr_t p, HistEvent *ev)
234 1.16 lukem {
235 1.16 lukem history_t *h = (history_t *) p;
236 1.16 lukem
237 1.16 lukem h->cursor = h->list.prev;
238 1.16 lukem if (h->cursor != &h->list)
239 1.16 lukem *ev = h->cursor->ev;
240 1.16 lukem else {
241 1.16 lukem he_seterrev(ev, _HE_LAST_NOTFOUND);
242 1.16 lukem return (-1);
243 1.16 lukem }
244 1.7 christos
245 1.16 lukem return (0);
246 1.1 cgd }
247 1.1 cgd
248 1.8 christos
249 1.1 cgd /* history_def_next():
250 1.1 cgd * Default function to return the next event in the history.
251 1.1 cgd */
252 1.7 christos private int
253 1.16 lukem history_def_next(ptr_t p, HistEvent *ev)
254 1.16 lukem {
255 1.16 lukem history_t *h = (history_t *) p;
256 1.16 lukem
257 1.28 christos if (h->cursor == &h->list) {
258 1.16 lukem he_seterrev(ev, _HE_EMPTY_LIST);
259 1.16 lukem return (-1);
260 1.16 lukem }
261 1.1 cgd
262 1.28 christos if (h->cursor->next == &h->list) {
263 1.16 lukem he_seterrev(ev, _HE_END_REACHED);
264 1.16 lukem return (-1);
265 1.16 lukem }
266 1.7 christos
267 1.28 christos h->cursor = h->cursor->next;
268 1.28 christos *ev = h->cursor->ev;
269 1.28 christos
270 1.16 lukem return (0);
271 1.1 cgd }
272 1.1 cgd
273 1.1 cgd
274 1.1 cgd /* history_def_prev():
275 1.1 cgd * Default function to return the previous event in the history.
276 1.1 cgd */
277 1.7 christos private int
278 1.16 lukem history_def_prev(ptr_t p, HistEvent *ev)
279 1.16 lukem {
280 1.16 lukem history_t *h = (history_t *) p;
281 1.16 lukem
282 1.28 christos if (h->cursor == &h->list) {
283 1.16 lukem he_seterrev(ev,
284 1.16 lukem (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
285 1.16 lukem return (-1);
286 1.16 lukem }
287 1.1 cgd
288 1.28 christos if (h->cursor->prev == &h->list) {
289 1.16 lukem he_seterrev(ev, _HE_START_REACHED);
290 1.16 lukem return (-1);
291 1.16 lukem }
292 1.7 christos
293 1.28 christos h->cursor = h->cursor->prev;
294 1.28 christos *ev = h->cursor->ev;
295 1.28 christos
296 1.16 lukem return (0);
297 1.1 cgd }
298 1.1 cgd
299 1.1 cgd
300 1.1 cgd /* history_def_curr():
301 1.1 cgd * Default function to return the current event in the history.
302 1.1 cgd */
303 1.7 christos private int
304 1.16 lukem history_def_curr(ptr_t p, HistEvent *ev)
305 1.1 cgd {
306 1.16 lukem history_t *h = (history_t *) p;
307 1.1 cgd
308 1.16 lukem if (h->cursor != &h->list)
309 1.16 lukem *ev = h->cursor->ev;
310 1.16 lukem else {
311 1.16 lukem he_seterrev(ev,
312 1.16 lukem (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
313 1.16 lukem return (-1);
314 1.16 lukem }
315 1.7 christos
316 1.16 lukem return (0);
317 1.1 cgd }
318 1.1 cgd
319 1.8 christos
320 1.8 christos /* history_def_set():
321 1.8 christos * Default function to set the current event in the history to the
322 1.8 christos * given one.
323 1.8 christos */
324 1.8 christos private int
325 1.16 lukem history_def_set(ptr_t p, HistEvent *ev, const int n)
326 1.16 lukem {
327 1.16 lukem history_t *h = (history_t *) p;
328 1.8 christos
329 1.16 lukem if (h->cur == 0) {
330 1.16 lukem he_seterrev(ev, _HE_EMPTY_LIST);
331 1.16 lukem return (-1);
332 1.16 lukem }
333 1.16 lukem if (h->cursor == &h->list || h->cursor->ev.num != n) {
334 1.16 lukem for (h->cursor = h->list.next; h->cursor != &h->list;
335 1.16 lukem h->cursor = h->cursor->next)
336 1.16 lukem if (h->cursor->ev.num == n)
337 1.16 lukem break;
338 1.16 lukem }
339 1.16 lukem if (h->cursor == &h->list) {
340 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
341 1.16 lukem return (-1);
342 1.16 lukem }
343 1.16 lukem return (0);
344 1.8 christos }
345 1.8 christos
346 1.8 christos
347 1.34 christos /* history_set_nth():
348 1.34 christos * Default function to set the current event in the history to the
349 1.34 christos * n-th one.
350 1.34 christos */
351 1.34 christos private int
352 1.34 christos history_set_nth(ptr_t p, HistEvent *ev, int n)
353 1.34 christos {
354 1.34 christos history_t *h = (history_t *) p;
355 1.34 christos
356 1.34 christos if (h->cur == 0) {
357 1.34 christos he_seterrev(ev, _HE_EMPTY_LIST);
358 1.34 christos return (-1);
359 1.34 christos }
360 1.34 christos for (h->cursor = h->list.prev; h->cursor != &h->list;
361 1.34 christos h->cursor = h->cursor->prev)
362 1.34 christos if (n-- <= 0)
363 1.34 christos break;
364 1.34 christos if (h->cursor == &h->list) {
365 1.34 christos he_seterrev(ev, _HE_NOT_FOUND);
366 1.34 christos return (-1);
367 1.34 christos }
368 1.34 christos return (0);
369 1.34 christos }
370 1.34 christos
371 1.34 christos
372 1.1 cgd /* history_def_add():
373 1.1 cgd * Append string to element
374 1.1 cgd */
375 1.7 christos private int
376 1.16 lukem history_def_add(ptr_t p, HistEvent *ev, const char *str)
377 1.16 lukem {
378 1.16 lukem history_t *h = (history_t *) p;
379 1.16 lukem size_t len;
380 1.16 lukem char *s;
381 1.19 christos HistEventPrivate *evp = (void *)&h->cursor->ev;
382 1.16 lukem
383 1.16 lukem if (h->cursor == &h->list)
384 1.16 lukem return (history_def_enter(p, ev, str));
385 1.19 christos len = strlen(evp->str) + strlen(str) + 1;
386 1.16 lukem s = (char *) h_malloc(len);
387 1.21 christos if (s == NULL) {
388 1.16 lukem he_seterrev(ev, _HE_MALLOC_FAILED);
389 1.16 lukem return (-1);
390 1.16 lukem }
391 1.16 lukem (void) strlcpy(s, h->cursor->ev.str, len);
392 1.16 lukem (void) strlcat(s, str, len);
393 1.21 christos h_free((ptr_t)evp->str);
394 1.19 christos evp->str = s;
395 1.16 lukem *ev = h->cursor->ev;
396 1.16 lukem return (0);
397 1.1 cgd }
398 1.1 cgd
399 1.1 cgd
400 1.34 christos private int
401 1.34 christos history_deldata_nth(history_t *h, HistEvent *ev,
402 1.34 christos int num, void **data)
403 1.34 christos {
404 1.34 christos if (history_set_nth(h, ev, num) != 0)
405 1.34 christos return (-1);
406 1.34 christos /* magic value to skip delete (just set to n-th history) */
407 1.34 christos if (data == (void **)-1)
408 1.34 christos return (0);
409 1.34 christos ev->str = strdup(h->cursor->ev.str);
410 1.34 christos ev->num = h->cursor->ev.num;
411 1.34 christos if (data)
412 1.34 christos *data = h->cursor->data;
413 1.34 christos history_def_delete(h, ev, h->cursor);
414 1.34 christos return (0);
415 1.34 christos }
416 1.34 christos
417 1.34 christos
418 1.30 christos /* history_def_del():
419 1.30 christos * Delete element hp of the h list
420 1.30 christos */
421 1.30 christos /* ARGSUSED */
422 1.30 christos private int
423 1.30 christos history_def_del(ptr_t p, HistEvent *ev __attribute__((__unused__)),
424 1.30 christos const int num)
425 1.30 christos {
426 1.30 christos history_t *h = (history_t *) p;
427 1.30 christos if (history_def_set(h, ev, num) != 0)
428 1.30 christos return (-1);
429 1.30 christos ev->str = strdup(h->cursor->ev.str);
430 1.30 christos ev->num = h->cursor->ev.num;
431 1.30 christos history_def_delete(h, ev, h->cursor);
432 1.30 christos return (0);
433 1.30 christos }
434 1.30 christos
435 1.30 christos
436 1.1 cgd /* history_def_delete():
437 1.1 cgd * Delete element hp of the h list
438 1.1 cgd */
439 1.11 christos /* ARGSUSED */
440 1.1 cgd private void
441 1.23 christos history_def_delete(history_t *h,
442 1.23 christos HistEvent *ev __attribute__((__unused__)), hentry_t *hp)
443 1.16 lukem {
444 1.19 christos HistEventPrivate *evp = (void *)&hp->ev;
445 1.16 lukem if (hp == &h->list)
446 1.16 lukem abort();
447 1.34 christos if (h->cursor == hp) {
448 1.30 christos h->cursor = hp->prev;
449 1.34 christos if (h->cursor == &h->list)
450 1.34 christos h->cursor = hp->next;
451 1.34 christos }
452 1.16 lukem hp->prev->next = hp->next;
453 1.16 lukem hp->next->prev = hp->prev;
454 1.19 christos h_free((ptr_t) evp->str);
455 1.16 lukem h_free(hp);
456 1.16 lukem h->cur--;
457 1.1 cgd }
458 1.1 cgd
459 1.1 cgd
460 1.1 cgd /* history_def_insert():
461 1.1 cgd * Insert element with string str in the h list
462 1.1 cgd */
463 1.7 christos private int
464 1.16 lukem history_def_insert(history_t *h, HistEvent *ev, const char *str)
465 1.16 lukem {
466 1.16 lukem
467 1.16 lukem h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
468 1.21 christos if (h->cursor == NULL)
469 1.21 christos goto oomem;
470 1.25 christos if ((h->cursor->ev.str = h_strdup(str)) == NULL) {
471 1.21 christos h_free((ptr_t)h->cursor);
472 1.21 christos goto oomem;
473 1.16 lukem }
474 1.34 christos h->cursor->data = NULL;
475 1.16 lukem h->cursor->ev.num = ++h->eventid;
476 1.16 lukem h->cursor->next = h->list.next;
477 1.16 lukem h->cursor->prev = &h->list;
478 1.16 lukem h->list.next->prev = h->cursor;
479 1.16 lukem h->list.next = h->cursor;
480 1.16 lukem h->cur++;
481 1.1 cgd
482 1.16 lukem *ev = h->cursor->ev;
483 1.16 lukem return (0);
484 1.21 christos oomem:
485 1.21 christos he_seterrev(ev, _HE_MALLOC_FAILED);
486 1.21 christos return (-1);
487 1.1 cgd }
488 1.1 cgd
489 1.1 cgd
490 1.1 cgd /* history_def_enter():
491 1.1 cgd * Default function to enter an item in the history
492 1.1 cgd */
493 1.7 christos private int
494 1.16 lukem history_def_enter(ptr_t p, HistEvent *ev, const char *str)
495 1.16 lukem {
496 1.16 lukem history_t *h = (history_t *) p;
497 1.16 lukem
498 1.22 christos if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
499 1.22 christos strcmp(h->list.next->ev.str, str) == 0)
500 1.22 christos return (0);
501 1.22 christos
502 1.16 lukem if (history_def_insert(h, ev, str) == -1)
503 1.16 lukem return (-1); /* error, keep error message */
504 1.16 lukem
505 1.16 lukem /*
506 1.16 lukem * Always keep at least one entry.
507 1.16 lukem * This way we don't have to check for the empty list.
508 1.16 lukem */
509 1.18 jdolecek while (h->cur > h->max && h->cur > 0)
510 1.16 lukem history_def_delete(h, ev, h->list.prev);
511 1.7 christos
512 1.22 christos return (1);
513 1.1 cgd }
514 1.1 cgd
515 1.1 cgd
516 1.1 cgd /* history_def_init():
517 1.1 cgd * Default history initialization function
518 1.1 cgd */
519 1.11 christos /* ARGSUSED */
520 1.21 christos private int
521 1.23 christos history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n)
522 1.16 lukem {
523 1.16 lukem history_t *h = (history_t *) h_malloc(sizeof(history_t));
524 1.21 christos if (h == NULL)
525 1.21 christos return -1;
526 1.16 lukem
527 1.16 lukem if (n <= 0)
528 1.16 lukem n = 0;
529 1.16 lukem h->eventid = 0;
530 1.16 lukem h->cur = 0;
531 1.16 lukem h->max = n;
532 1.16 lukem h->list.next = h->list.prev = &h->list;
533 1.16 lukem h->list.ev.str = NULL;
534 1.16 lukem h->list.ev.num = 0;
535 1.16 lukem h->cursor = &h->list;
536 1.22 christos h->flags = 0;
537 1.16 lukem *p = (ptr_t) h;
538 1.21 christos return 0;
539 1.1 cgd }
540 1.1 cgd
541 1.1 cgd
542 1.2 christos /* history_def_clear():
543 1.1 cgd * Default history cleanup function
544 1.1 cgd */
545 1.1 cgd private void
546 1.16 lukem history_def_clear(ptr_t p, HistEvent *ev)
547 1.16 lukem {
548 1.16 lukem history_t *h = (history_t *) p;
549 1.16 lukem
550 1.16 lukem while (h->list.prev != &h->list)
551 1.16 lukem history_def_delete(h, ev, h->list.prev);
552 1.16 lukem h->eventid = 0;
553 1.16 lukem h->cur = 0;
554 1.1 cgd }
555 1.1 cgd
556 1.2 christos
557 1.2 christos
558 1.2 christos
559 1.1 cgd /************************************************************************/
560 1.1 cgd
561 1.1 cgd /* history_init():
562 1.1 cgd * Initialization function.
563 1.1 cgd */
564 1.1 cgd public History *
565 1.16 lukem history_init(void)
566 1.1 cgd {
567 1.21 christos HistEvent ev;
568 1.16 lukem History *h = (History *) h_malloc(sizeof(History));
569 1.21 christos if (h == NULL)
570 1.21 christos return NULL;
571 1.1 cgd
572 1.21 christos if (history_def_init(&h->h_ref, &ev, 0) == -1) {
573 1.21 christos h_free((ptr_t)h);
574 1.21 christos return NULL;
575 1.21 christos }
576 1.16 lukem h->h_ent = -1;
577 1.16 lukem h->h_next = history_def_next;
578 1.16 lukem h->h_first = history_def_first;
579 1.16 lukem h->h_last = history_def_last;
580 1.16 lukem h->h_prev = history_def_prev;
581 1.16 lukem h->h_curr = history_def_curr;
582 1.16 lukem h->h_set = history_def_set;
583 1.16 lukem h->h_clear = history_def_clear;
584 1.16 lukem h->h_enter = history_def_enter;
585 1.16 lukem h->h_add = history_def_add;
586 1.31 christos h->h_del = history_def_del;
587 1.1 cgd
588 1.16 lukem return (h);
589 1.1 cgd }
590 1.1 cgd
591 1.1 cgd
592 1.1 cgd /* history_end():
593 1.1 cgd * clean up history;
594 1.1 cgd */
595 1.1 cgd public void
596 1.16 lukem history_end(History *h)
597 1.1 cgd {
598 1.16 lukem HistEvent ev;
599 1.16 lukem
600 1.16 lukem if (h->h_next == history_def_next)
601 1.16 lukem history_def_clear(h->h_ref, &ev);
602 1.32 christos h_free(h->h_ref);
603 1.29 christos h_free(h);
604 1.1 cgd }
605 1.1 cgd
606 1.1 cgd
607 1.1 cgd
608 1.12 christos /* history_setsize():
609 1.1 cgd * Set history number of events
610 1.1 cgd */
611 1.1 cgd private int
612 1.16 lukem history_setsize(History *h, HistEvent *ev, int num)
613 1.16 lukem {
614 1.7 christos
615 1.16 lukem if (h->h_next != history_def_next) {
616 1.16 lukem he_seterrev(ev, _HE_NOT_ALLOWED);
617 1.16 lukem return (-1);
618 1.16 lukem }
619 1.16 lukem if (num < 0) {
620 1.16 lukem he_seterrev(ev, _HE_BAD_PARAM);
621 1.16 lukem return (-1);
622 1.16 lukem }
623 1.16 lukem history_def_setsize(h->h_ref, num);
624 1.16 lukem return (0);
625 1.1 cgd }
626 1.1 cgd
627 1.16 lukem
628 1.12 christos /* history_getsize():
629 1.7 christos * Get number of events currently in history
630 1.7 christos */
631 1.7 christos private int
632 1.16 lukem history_getsize(History *h, HistEvent *ev)
633 1.16 lukem {
634 1.22 christos if (h->h_next != history_def_next) {
635 1.22 christos he_seterrev(ev, _HE_NOT_ALLOWED);
636 1.22 christos return (-1);
637 1.22 christos }
638 1.22 christos ev->num = history_def_getsize(h->h_ref);
639 1.22 christos if (ev->num < -1) {
640 1.22 christos he_seterrev(ev, _HE_SIZE_NEGATIVE);
641 1.22 christos return (-1);
642 1.22 christos }
643 1.22 christos return (0);
644 1.22 christos }
645 1.22 christos
646 1.22 christos
647 1.22 christos /* history_setunique():
648 1.22 christos * Set if adjacent equal events should not be entered in history.
649 1.22 christos */
650 1.22 christos private int
651 1.22 christos history_setunique(History *h, HistEvent *ev, int uni)
652 1.22 christos {
653 1.7 christos
654 1.16 lukem if (h->h_next != history_def_next) {
655 1.16 lukem he_seterrev(ev, _HE_NOT_ALLOWED);
656 1.16 lukem return (-1);
657 1.16 lukem }
658 1.22 christos history_def_setunique(h->h_ref, uni);
659 1.22 christos return (0);
660 1.22 christos }
661 1.22 christos
662 1.22 christos
663 1.22 christos /* history_getunique():
664 1.22 christos * Get if adjacent equal events should not be entered in history.
665 1.22 christos */
666 1.22 christos private int
667 1.22 christos history_getunique(History *h, HistEvent *ev)
668 1.22 christos {
669 1.22 christos if (h->h_next != history_def_next) {
670 1.22 christos he_seterrev(ev, _HE_NOT_ALLOWED);
671 1.16 lukem return (-1);
672 1.16 lukem }
673 1.22 christos ev->num = history_def_getunique(h->h_ref);
674 1.16 lukem return (0);
675 1.7 christos }
676 1.1 cgd
677 1.16 lukem
678 1.1 cgd /* history_set_fun():
679 1.1 cgd * Set history functions
680 1.1 cgd */
681 1.1 cgd private int
682 1.16 lukem history_set_fun(History *h, History *nh)
683 1.16 lukem {
684 1.16 lukem HistEvent ev;
685 1.16 lukem
686 1.16 lukem if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
687 1.16 lukem nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
688 1.16 lukem nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
689 1.30 christos nh->h_del == NULL || nh->h_ref == NULL) {
690 1.16 lukem if (h->h_next != history_def_next) {
691 1.16 lukem history_def_init(&h->h_ref, &ev, 0);
692 1.16 lukem h->h_first = history_def_first;
693 1.16 lukem h->h_next = history_def_next;
694 1.16 lukem h->h_last = history_def_last;
695 1.16 lukem h->h_prev = history_def_prev;
696 1.16 lukem h->h_curr = history_def_curr;
697 1.16 lukem h->h_set = history_def_set;
698 1.16 lukem h->h_clear = history_def_clear;
699 1.16 lukem h->h_enter = history_def_enter;
700 1.16 lukem h->h_add = history_def_add;
701 1.30 christos h->h_del = history_def_del;
702 1.16 lukem }
703 1.16 lukem return (-1);
704 1.16 lukem }
705 1.16 lukem if (h->h_next == history_def_next)
706 1.16 lukem history_def_clear(h->h_ref, &ev);
707 1.16 lukem
708 1.16 lukem h->h_ent = -1;
709 1.16 lukem h->h_first = nh->h_first;
710 1.16 lukem h->h_next = nh->h_next;
711 1.16 lukem h->h_last = nh->h_last;
712 1.16 lukem h->h_prev = nh->h_prev;
713 1.16 lukem h->h_curr = nh->h_curr;
714 1.16 lukem h->h_set = nh->h_set;
715 1.16 lukem h->h_clear = nh->h_clear;
716 1.16 lukem h->h_enter = nh->h_enter;
717 1.16 lukem h->h_add = nh->h_add;
718 1.30 christos h->h_del = nh->h_del;
719 1.1 cgd
720 1.16 lukem return (0);
721 1.1 cgd }
722 1.1 cgd
723 1.1 cgd
724 1.2 christos /* history_load():
725 1.2 christos * History load function
726 1.2 christos */
727 1.2 christos private int
728 1.16 lukem history_load(History *h, const char *fname)
729 1.16 lukem {
730 1.16 lukem FILE *fp;
731 1.16 lukem char *line;
732 1.16 lukem size_t sz, max_size;
733 1.16 lukem char *ptr;
734 1.16 lukem int i = -1;
735 1.16 lukem HistEvent ev;
736 1.16 lukem
737 1.16 lukem if ((fp = fopen(fname, "r")) == NULL)
738 1.16 lukem return (i);
739 1.16 lukem
740 1.16 lukem if ((line = fgetln(fp, &sz)) == NULL)
741 1.16 lukem goto done;
742 1.16 lukem
743 1.16 lukem if (strncmp(line, hist_cookie, sz) != 0)
744 1.16 lukem goto done;
745 1.16 lukem
746 1.16 lukem ptr = h_malloc(max_size = 1024);
747 1.21 christos if (ptr == NULL)
748 1.21 christos goto done;
749 1.16 lukem for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
750 1.16 lukem char c = line[sz];
751 1.16 lukem
752 1.16 lukem if (sz != 0 && line[sz - 1] == '\n')
753 1.16 lukem line[--sz] = '\0';
754 1.16 lukem else
755 1.16 lukem line[sz] = '\0';
756 1.16 lukem
757 1.16 lukem if (max_size < sz) {
758 1.21 christos char *nptr;
759 1.27 christos max_size = (sz + 1024) & ~1023;
760 1.21 christos nptr = h_realloc(ptr, max_size);
761 1.21 christos if (nptr == NULL) {
762 1.21 christos i = -1;
763 1.21 christos goto oomem;
764 1.21 christos }
765 1.21 christos ptr = nptr;
766 1.16 lukem }
767 1.16 lukem (void) strunvis(ptr, line);
768 1.16 lukem line[sz] = c;
769 1.21 christos if (HENTER(h, &ev, ptr) == -1) {
770 1.33 sketch i = -1;
771 1.33 sketch goto oomem;
772 1.21 christos }
773 1.16 lukem }
774 1.21 christos oomem:
775 1.21 christos h_free((ptr_t)ptr);
776 1.2 christos done:
777 1.16 lukem (void) fclose(fp);
778 1.16 lukem return (i);
779 1.2 christos }
780 1.2 christos
781 1.2 christos
782 1.2 christos /* history_save():
783 1.2 christos * History save function
784 1.2 christos */
785 1.2 christos private int
786 1.16 lukem history_save(History *h, const char *fname)
787 1.16 lukem {
788 1.16 lukem FILE *fp;
789 1.16 lukem HistEvent ev;
790 1.21 christos int i = -1, retval;
791 1.16 lukem size_t len, max_size;
792 1.16 lukem char *ptr;
793 1.16 lukem
794 1.16 lukem if ((fp = fopen(fname, "w")) == NULL)
795 1.16 lukem return (-1);
796 1.16 lukem
797 1.21 christos if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
798 1.21 christos goto done;
799 1.21 christos if (fputs(hist_cookie, fp) == EOF)
800 1.21 christos goto done;
801 1.16 lukem ptr = h_malloc(max_size = 1024);
802 1.21 christos if (ptr == NULL)
803 1.21 christos goto done;
804 1.21 christos for (i = 0, retval = HLAST(h, &ev);
805 1.16 lukem retval != -1;
806 1.16 lukem retval = HPREV(h, &ev), i++) {
807 1.16 lukem len = strlen(ev.str) * 4;
808 1.16 lukem if (len >= max_size) {
809 1.21 christos char *nptr;
810 1.27 christos max_size = (len + 1024) & ~1023;
811 1.21 christos nptr = h_realloc(ptr, max_size);
812 1.21 christos if (nptr == NULL) {
813 1.21 christos i = -1;
814 1.21 christos goto oomem;
815 1.21 christos }
816 1.21 christos ptr = nptr;
817 1.16 lukem }
818 1.16 lukem (void) strvis(ptr, ev.str, VIS_WHITE);
819 1.20 christos (void) fprintf(fp, "%s\n", ptr);
820 1.16 lukem }
821 1.21 christos oomem:
822 1.21 christos h_free((ptr_t)ptr);
823 1.21 christos done:
824 1.16 lukem (void) fclose(fp);
825 1.16 lukem return (i);
826 1.2 christos }
827 1.2 christos
828 1.2 christos
829 1.1 cgd /* history_prev_event():
830 1.1 cgd * Find the previous event, with number given
831 1.1 cgd */
832 1.7 christos private int
833 1.16 lukem history_prev_event(History *h, HistEvent *ev, int num)
834 1.16 lukem {
835 1.16 lukem int retval;
836 1.7 christos
837 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
838 1.16 lukem if (ev->num == num)
839 1.16 lukem return (0);
840 1.16 lukem
841 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
842 1.16 lukem return (-1);
843 1.1 cgd }
844 1.1 cgd
845 1.1 cgd
846 1.34 christos private int
847 1.34 christos history_next_evdata(History *h, HistEvent *ev, int num, void **d)
848 1.34 christos {
849 1.34 christos int retval;
850 1.34 christos
851 1.34 christos for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
852 1.34 christos if (num-- <= 0) {
853 1.34 christos if (d)
854 1.34 christos *d = ((history_t *)h->h_ref)->cursor->data;
855 1.34 christos return (0);
856 1.34 christos }
857 1.34 christos
858 1.34 christos he_seterrev(ev, _HE_NOT_FOUND);
859 1.34 christos return (-1);
860 1.34 christos }
861 1.34 christos
862 1.34 christos
863 1.1 cgd /* history_next_event():
864 1.1 cgd * Find the next event, with number given
865 1.1 cgd */
866 1.7 christos private int
867 1.16 lukem history_next_event(History *h, HistEvent *ev, int num)
868 1.16 lukem {
869 1.16 lukem int retval;
870 1.16 lukem
871 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
872 1.16 lukem if (ev->num == num)
873 1.16 lukem return (0);
874 1.7 christos
875 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
876 1.16 lukem return (-1);
877 1.1 cgd }
878 1.1 cgd
879 1.1 cgd
880 1.1 cgd /* history_prev_string():
881 1.1 cgd * Find the previous event beginning with string
882 1.1 cgd */
883 1.7 christos private int
884 1.16 lukem history_prev_string(History *h, HistEvent *ev, const char *str)
885 1.16 lukem {
886 1.16 lukem size_t len = strlen(str);
887 1.16 lukem int retval;
888 1.7 christos
889 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
890 1.16 lukem if (strncmp(str, ev->str, len) == 0)
891 1.16 lukem return (0);
892 1.16 lukem
893 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
894 1.16 lukem return (-1);
895 1.1 cgd }
896 1.1 cgd
897 1.1 cgd
898 1.1 cgd /* history_next_string():
899 1.1 cgd * Find the next event beginning with string
900 1.1 cgd */
901 1.7 christos private int
902 1.16 lukem history_next_string(History *h, HistEvent *ev, const char *str)
903 1.16 lukem {
904 1.16 lukem size_t len = strlen(str);
905 1.16 lukem int retval;
906 1.16 lukem
907 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
908 1.16 lukem if (strncmp(str, ev->str, len) == 0)
909 1.16 lukem return (0);
910 1.7 christos
911 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
912 1.16 lukem return (-1);
913 1.1 cgd }
914 1.1 cgd
915 1.1 cgd
916 1.1 cgd /* history():
917 1.1 cgd * User interface to history functions.
918 1.1 cgd */
919 1.7 christos int
920 1.7 christos history(History *h, HistEvent *ev, int fun, ...)
921 1.1 cgd {
922 1.16 lukem va_list va;
923 1.16 lukem const char *str;
924 1.16 lukem int retval;
925 1.16 lukem
926 1.16 lukem va_start(va, fun);
927 1.16 lukem
928 1.16 lukem he_seterrev(ev, _HE_OK);
929 1.16 lukem
930 1.16 lukem switch (fun) {
931 1.16 lukem case H_GETSIZE:
932 1.16 lukem retval = history_getsize(h, ev);
933 1.16 lukem break;
934 1.16 lukem
935 1.16 lukem case H_SETSIZE:
936 1.16 lukem retval = history_setsize(h, ev, va_arg(va, int));
937 1.22 christos break;
938 1.22 christos
939 1.22 christos case H_GETUNIQUE:
940 1.22 christos retval = history_getunique(h, ev);
941 1.22 christos break;
942 1.22 christos
943 1.22 christos case H_SETUNIQUE:
944 1.22 christos retval = history_setunique(h, ev, va_arg(va, int));
945 1.16 lukem break;
946 1.16 lukem
947 1.16 lukem case H_ADD:
948 1.16 lukem str = va_arg(va, const char *);
949 1.16 lukem retval = HADD(h, ev, str);
950 1.16 lukem break;
951 1.16 lukem
952 1.30 christos case H_DEL:
953 1.30 christos retval = HDEL(h, ev, va_arg(va, const int));
954 1.30 christos break;
955 1.30 christos
956 1.16 lukem case H_ENTER:
957 1.16 lukem str = va_arg(va, const char *);
958 1.16 lukem if ((retval = HENTER(h, ev, str)) != -1)
959 1.16 lukem h->h_ent = ev->num;
960 1.16 lukem break;
961 1.16 lukem
962 1.16 lukem case H_APPEND:
963 1.16 lukem str = va_arg(va, const char *);
964 1.16 lukem if ((retval = HSET(h, ev, h->h_ent)) != -1)
965 1.16 lukem retval = HADD(h, ev, str);
966 1.16 lukem break;
967 1.16 lukem
968 1.16 lukem case H_FIRST:
969 1.16 lukem retval = HFIRST(h, ev);
970 1.16 lukem break;
971 1.1 cgd
972 1.16 lukem case H_NEXT:
973 1.16 lukem retval = HNEXT(h, ev);
974 1.16 lukem break;
975 1.16 lukem
976 1.16 lukem case H_LAST:
977 1.16 lukem retval = HLAST(h, ev);
978 1.16 lukem break;
979 1.16 lukem
980 1.16 lukem case H_PREV:
981 1.16 lukem retval = HPREV(h, ev);
982 1.16 lukem break;
983 1.16 lukem
984 1.16 lukem case H_CURR:
985 1.16 lukem retval = HCURR(h, ev);
986 1.16 lukem break;
987 1.16 lukem
988 1.16 lukem case H_SET:
989 1.16 lukem retval = HSET(h, ev, va_arg(va, const int));
990 1.16 lukem break;
991 1.16 lukem
992 1.16 lukem case H_CLEAR:
993 1.16 lukem HCLEAR(h, ev);
994 1.16 lukem retval = 0;
995 1.16 lukem break;
996 1.16 lukem
997 1.16 lukem case H_LOAD:
998 1.16 lukem retval = history_load(h, va_arg(va, const char *));
999 1.16 lukem if (retval == -1)
1000 1.16 lukem he_seterrev(ev, _HE_HIST_READ);
1001 1.16 lukem break;
1002 1.16 lukem
1003 1.16 lukem case H_SAVE:
1004 1.16 lukem retval = history_save(h, va_arg(va, const char *));
1005 1.16 lukem if (retval == -1)
1006 1.16 lukem he_seterrev(ev, _HE_HIST_WRITE);
1007 1.16 lukem break;
1008 1.16 lukem
1009 1.16 lukem case H_PREV_EVENT:
1010 1.16 lukem retval = history_prev_event(h, ev, va_arg(va, int));
1011 1.16 lukem break;
1012 1.16 lukem
1013 1.16 lukem case H_NEXT_EVENT:
1014 1.16 lukem retval = history_next_event(h, ev, va_arg(va, int));
1015 1.16 lukem break;
1016 1.1 cgd
1017 1.16 lukem case H_PREV_STR:
1018 1.16 lukem retval = history_prev_string(h, ev, va_arg(va, const char *));
1019 1.16 lukem break;
1020 1.7 christos
1021 1.16 lukem case H_NEXT_STR:
1022 1.16 lukem retval = history_next_string(h, ev, va_arg(va, const char *));
1023 1.16 lukem break;
1024 1.1 cgd
1025 1.16 lukem case H_FUNC:
1026 1.1 cgd {
1027 1.16 lukem History hf;
1028 1.16 lukem
1029 1.16 lukem hf.h_ref = va_arg(va, ptr_t);
1030 1.16 lukem h->h_ent = -1;
1031 1.16 lukem hf.h_first = va_arg(va, history_gfun_t);
1032 1.16 lukem hf.h_next = va_arg(va, history_gfun_t);
1033 1.16 lukem hf.h_last = va_arg(va, history_gfun_t);
1034 1.16 lukem hf.h_prev = va_arg(va, history_gfun_t);
1035 1.16 lukem hf.h_curr = va_arg(va, history_gfun_t);
1036 1.16 lukem hf.h_set = va_arg(va, history_sfun_t);
1037 1.16 lukem hf.h_clear = va_arg(va, history_vfun_t);
1038 1.16 lukem hf.h_enter = va_arg(va, history_efun_t);
1039 1.16 lukem hf.h_add = va_arg(va, history_efun_t);
1040 1.30 christos hf.h_del = va_arg(va, history_sfun_t);
1041 1.8 christos
1042 1.16 lukem if ((retval = history_set_fun(h, &hf)) == -1)
1043 1.16 lukem he_seterrev(ev, _HE_PARAM_MISSING);
1044 1.16 lukem break;
1045 1.16 lukem }
1046 1.16 lukem
1047 1.16 lukem case H_END:
1048 1.16 lukem history_end(h);
1049 1.16 lukem retval = 0;
1050 1.16 lukem break;
1051 1.16 lukem
1052 1.34 christos case H_NEXT_EVDATA:
1053 1.34 christos {
1054 1.34 christos int num = va_arg(va, int);
1055 1.34 christos void **d = va_arg(va, void **);
1056 1.34 christos retval = history_next_evdata(h, ev, num, d);
1057 1.34 christos break;
1058 1.34 christos }
1059 1.34 christos
1060 1.34 christos case H_DELDATA:
1061 1.34 christos {
1062 1.34 christos int num = va_arg(va, int);
1063 1.34 christos void **d = va_arg(va, void **);
1064 1.34 christos retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
1065 1.34 christos break;
1066 1.34 christos }
1067 1.34 christos
1068 1.34 christos case H_REPLACE: /* only use after H_NEXT_EVDATA */
1069 1.34 christos {
1070 1.34 christos const char *line = va_arg(va, const char *);
1071 1.34 christos void *d = va_arg(va, void *);
1072 1.34 christos const char *s;
1073 1.34 christos if(!line || !(s = strdup(line))) {
1074 1.34 christos retval = -1;
1075 1.34 christos break;
1076 1.34 christos }
1077 1.34 christos ((history_t *)h->h_ref)->cursor->ev.str = s;
1078 1.34 christos ((history_t *)h->h_ref)->cursor->data = d;
1079 1.34 christos retval = 0;
1080 1.34 christos break;
1081 1.34 christos }
1082 1.34 christos
1083 1.16 lukem default:
1084 1.16 lukem retval = -1;
1085 1.16 lukem he_seterrev(ev, _HE_UNKNOWN);
1086 1.16 lukem break;
1087 1.16 lukem }
1088 1.16 lukem va_end(va);
1089 1.34 christos return retval;
1090 1.1 cgd }
1091