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