root/src/noitedit/history.c

Revision bafab25395cb398ddf5eae42145f0d0bfc00ec22, 19.6 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

import of libedit... prepare to hack

  • Property mode set to 100644
Line 
1 /*      $NetBSD: history.c,v 1.17 2001/03/20 00:08:31 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 "compat.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.17 2001/03/20 00:08:31 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 #include <stdarg.h>
56 #ifdef HAVE_VIS_H
57 #include <vis.h>
58 #endif
59 #include <sys/stat.h>
60
61 static const char hist_cookie[] = "_HiStOrY_V2_\n";
62
63 #include "histedit.h"
64
65 typedef int (*history_gfun_t)(ptr_t, HistEvent *);
66 typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
67 typedef void (*history_vfun_t)(ptr_t, HistEvent *);
68 typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
69
70 struct history {
71         ptr_t h_ref;            /* Argument for history fcns     */
72         int h_ent;              /* Last entry point for history  */
73         history_gfun_t h_first; /* Get the first element         */
74         history_gfun_t h_next;  /* Get the next element          */
75         history_gfun_t h_last;  /* Get the last element          */
76         history_gfun_t h_prev;  /* Get the previous element      */
77         history_gfun_t h_curr;  /* Get the current element       */
78         history_sfun_t h_set;   /* Set the current element       */
79         history_vfun_t h_clear; /* Clear the history list        */
80         history_efun_t h_enter; /* Add an element                */
81         history_efun_t h_add;   /* Append to an element          */
82 };
83 #define HNEXT(h, ev)            (*(h)->h_next)((h)->h_ref, ev)
84 #define HFIRST(h, ev)           (*(h)->h_first)((h)->h_ref, ev)
85 #define HPREV(h, ev)            (*(h)->h_prev)((h)->h_ref, ev)
86 #define HLAST(h, ev)            (*(h)->h_last)((h)->h_ref, ev)
87 #define HCURR(h, ev)            (*(h)->h_curr)((h)->h_ref, ev)
88 #define HSET(h, ev, n)          (*(h)->h_set)((h)->h_ref, ev, n)
89 #define HCLEAR(h, ev)           (*(h)->h_clear)((h)->h_ref, ev)
90 #define HENTER(h, ev, str)      (*(h)->h_enter)((h)->h_ref, ev, str)
91 #define HADD(h, ev, str)        (*(h)->h_add)((h)->h_ref, ev, str)
92
93 #define h_malloc(a)     malloc(a)
94 #define h_realloc(a, b) realloc((a), (b))
95 #define h_free(a)       free(a)
96
97
98 private int history_setsize(History *, HistEvent *, int);
99 private int history_getsize(History *, HistEvent *);
100 private int history_set_fun(History *, History *);
101 private int history_load(History *, const char *);
102 private int history_save(History *, const char *);
103 private int history_prev_event(History *, HistEvent *, int);
104 private int history_next_event(History *, HistEvent *, int);
105 private int history_next_string(History *, HistEvent *, const char *);
106 private int history_prev_string(History *, HistEvent *, const char *);
107
108
109 /***********************************************************************/
110
111 /*
112  * Builtin- history implementation
113  */
114 typedef struct hentry_t {
115         HistEvent ev;           /* What we return                */
116         struct hentry_t *next;  /* Next entry                    */
117         struct hentry_t *prev;  /* Previous entry                */
118 }        hentry_t;
119
120 typedef struct history_t {
121         hentry_t list;          /* Fake list header element      */
122         hentry_t *cursor;       /* Current element in the list   */
123         int max;                /* Maximum number of events      */
124         int cur;                /* Current number of events      */
125         int eventid;            /* For generation of unique event id     */
126 }         history_t;
127
128 private int history_def_first(ptr_t, HistEvent *);
129 private int history_def_last(ptr_t, HistEvent *);
130 private int history_def_next(ptr_t, HistEvent *);
131 private int history_def_prev(ptr_t, HistEvent *);
132 private int history_def_curr(ptr_t, HistEvent *);
133 private int history_def_set(ptr_t, HistEvent *, const int n);
134 private int history_def_enter(ptr_t, HistEvent *, const char *);
135 private int history_def_add(ptr_t, HistEvent *, const char *);
136 private void history_def_init(ptr_t *, HistEvent *, int);
137 private void history_def_clear(ptr_t, HistEvent *);
138 private int history_def_insert(history_t *, HistEvent *, const char *);
139 private void history_def_delete(history_t *, HistEvent *, hentry_t *);
140
141 #define history_def_setsize(p, num)(void) (((history_t *) p)->max = (num))
142 #define history_def_getsize(p)  (((history_t *) p)->cur)
143
144 #define he_strerror(code)       he_errlist[code]
145 #define he_seterrev(evp, code)  {\
146                                     evp->num = code;\
147                                     evp->str = he_strerror(code);\
148                                 }
149
150 /* error messages */
151 static const char *const he_errlist[] = {
152         "OK",
153         "unknown error",
154         "malloc() failed",
155         "first event not found",
156         "last event not found",
157         "empty list",
158         "no next event",
159         "no previous event",
160         "current event is invalid",
161         "event not found",
162         "can't read history from file",
163         "can't write history",
164         "required parameter(s) not supplied",
165         "history size negative",
166         "function not allowed with other history-functions-set the default",
167         "bad parameters"
168 };
169 /* error codes */
170 #define _HE_OK                   0
171 #define _HE_UNKNOWN              1
172 #define _HE_MALLOC_FAILED        2
173 #define _HE_FIRST_NOTFOUND       3
174 #define _HE_LAST_NOTFOUND        4
175 #define _HE_EMPTY_LIST           5
176 #define _HE_END_REACHED          6
177 #define _HE_START_REACHED        7
178 #define _HE_CURR_INVALID         8
179 #define _HE_NOT_FOUND            9
180 #define _HE_HIST_READ           10
181 #define _HE_HIST_WRITE          11
182 #define _HE_PARAM_MISSING       12
183 #define _HE_SIZE_NEGATIVE       13
184 #define _HE_NOT_ALLOWED         14
185 #define _HE_BAD_PARAM           15
186
187 /* history_def_first():
188  *      Default function to return the first event in the history.
189  */
190 private int
191 history_def_first(ptr_t p, HistEvent *ev)
192 {
193         history_t *h = (history_t *) p;
194
195         h->cursor = h->list.next;
196         if (h->cursor != &h->list)
197                 *ev = h->cursor->ev;
198         else {
199                 he_seterrev(ev, _HE_FIRST_NOTFOUND);
200                 return (-1);
201         }
202
203         return (0);
204 }
205
206
207 /* history_def_last():
208  *      Default function to return the last event in the history.
209  */
210 private int
211 history_def_last(ptr_t p, HistEvent *ev)
212 {
213         history_t *h = (history_t *) p;
214
215         h->cursor = h->list.prev;
216         if (h->cursor != &h->list)
217                 *ev = h->cursor->ev;
218         else {
219                 he_seterrev(ev, _HE_LAST_NOTFOUND);
220                 return (-1);
221         }
222
223         return (0);
224 }
225
226
227 /* history_def_next():
228  *      Default function to return the next event in the history.
229  */
230 private int
231 history_def_next(ptr_t p, HistEvent *ev)
232 {
233         history_t *h = (history_t *) p;
234
235         if (h->cursor != &h->list)
236                 h->cursor = h->cursor->next;
237         else {
238                 he_seterrev(ev, _HE_EMPTY_LIST);
239                 return (-1);
240         }
241
242         if (h->cursor != &h->list)
243                 *ev = h->cursor->ev;
244         else {
245                 he_seterrev(ev, _HE_END_REACHED);
246                 return (-1);
247         }
248
249         return (0);
250 }
251
252
253 /* history_def_prev():
254  *      Default function to return the previous event in the history.
255  */
256 private int
257 history_def_prev(ptr_t p, HistEvent *ev)
258 {
259         history_t *h = (history_t *) p;
260
261         if (h->cursor != &h->list)
262                 h->cursor = h->cursor->prev;
263         else {
264                 he_seterrev(ev,
265                     (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
266                 return (-1);
267         }
268
269         if (h->cursor != &h->list)
270                 *ev = h->cursor->ev;
271         else {
272                 he_seterrev(ev, _HE_START_REACHED);
273                 return (-1);
274         }
275
276         return (0);
277 }
278
279
280 /* history_def_curr():
281  *      Default function to return the current event in the history.
282  */
283 private int
284 history_def_curr(ptr_t p, HistEvent *ev)
285 {
286         history_t *h = (history_t *) p;
287
288         if (h->cursor != &h->list)
289                 *ev = h->cursor->ev;
290         else {
291                 he_seterrev(ev,
292                     (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
293                 return (-1);
294         }
295
296         return (0);
297 }
298
299
300 /* history_def_set():
301  *      Default function to set the current event in the history to the
302  *      given one.
303  */
304 private int
305 history_def_set(ptr_t p, HistEvent *ev, const int n)
306 {
307         history_t *h = (history_t *) p;
308
309         if (h->cur == 0) {
310                 he_seterrev(ev, _HE_EMPTY_LIST);
311                 return (-1);
312         }
313         if (h->cursor == &h->list || h->cursor->ev.num != n) {
314                 for (h->cursor = h->list.next; h->cursor != &h->list;
315                     h->cursor = h->cursor->next)
316                         if (h->cursor->ev.num == n)
317                                 break;
318         }
319         if (h->cursor == &h->list) {
320                 he_seterrev(ev, _HE_NOT_FOUND);
321                 return (-1);
322         }
323         return (0);
324 }
325
326
327 /* history_def_add():
328  *      Append string to element
329  */
330 private int
331 history_def_add(ptr_t p, HistEvent *ev, const char *str)
332 {
333         history_t *h = (history_t *) p;
334         size_t len;
335         char *s;
336
337         if (h->cursor == &h->list)
338                 return (history_def_enter(p, ev, str));
339         len = strlen(h->cursor->ev.str) + strlen(str) + 1;
340         s = (char *) h_malloc(len);
341         if (!s) {
342                 he_seterrev(ev, _HE_MALLOC_FAILED);
343                 return (-1);
344         }
345         (void) strlcpy(s, h->cursor->ev.str, len);
346         (void) strlcat(s, str, len);
347         /* LINTED const cast */
348         h_free((ptr_t) h->cursor->ev.str);
349         h->cursor->ev.str = s;
350         *ev = h->cursor->ev;
351         return (0);
352 }
353
354
355 /* history_def_delete():
356  *      Delete element hp of the h list
357  */
358 /* ARGSUSED */
359 private void
360 history_def_delete(history_t *h, HistEvent *ev, hentry_t *hp)
361 {
362         if (hp == &h->list) {
363     abort();
364   }
365         hp->prev->next = hp->next;
366         hp->next->prev = hp->prev;
367         /* LINTED const cast */
368         h_free((ptr_t) hp->ev.str);
369         h_free(hp);
370         h->cur--;
371 }
372
373
374 /* history_def_insert():
375  *      Insert element with string str in the h list
376  */
377 private int
378 history_def_insert(history_t *h, HistEvent *ev, const char *str)
379 {
380
381         h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
382         if (h->cursor)
383                 h->cursor->ev.str = strdup(str);
384         if (!h->cursor || !h->cursor->ev.str) {
385                 he_seterrev(ev, _HE_MALLOC_FAILED);
386                 return (-1);
387         }
388         h->cursor->ev.num = ++h->eventid;
389         h->cursor->next = h->list.next;
390         h->cursor->prev = &h->list;
391         h->list.next->prev = h->cursor;
392         h->list.next = h->cursor;
393         h->cur++;
394
395         *ev = h->cursor->ev;
396         return (0);
397 }
398
399
400 /* history_def_enter():
401  *      Default function to enter an item in the history
402  */
403 private int
404 history_def_enter(ptr_t p, HistEvent *ev, const char *str)
405 {
406         history_t *h = (history_t *) p;
407
408         if (history_def_insert(h, ev, str) == -1)
409                 return (-1);    /* error, keep error message */
410
411         /*
412          * Always keep at least one entry.
413          * This way we don't have to check for the empty list.
414          */
415         while (h->cur - 1 > h->max)
416                 history_def_delete(h, ev, h->list.prev);
417
418         return (0);
419 }
420
421
422 /* history_def_init():
423  *      Default history initialization function
424  */
425 /* ARGSUSED */
426 private void
427 history_def_init(ptr_t *p, HistEvent *ev, int n)
428 {
429         history_t *h = (history_t *) h_malloc(sizeof(history_t));
430
431         if (n <= 0)
432                 n = 0;
433         h->eventid = 0;
434         h->cur = 0;
435         h->max = n;
436         h->list.next = h->list.prev = &h->list;
437         h->list.ev.str = NULL;
438         h->list.ev.num = 0;
439         h->cursor = &h->list;
440         *p = (ptr_t) h;
441 }
442
443
444 /* history_def_clear():
445  *      Default history cleanup function
446  */
447 private void
448 history_def_clear(ptr_t p, HistEvent *ev)
449 {
450         history_t *h = (history_t *) p;
451
452         while (h->list.prev != &h->list)
453                 history_def_delete(h, ev, h->list.prev);
454         h->eventid = 0;
455         h->cur = 0;
456 }
457
458
459
460
461 /************************************************************************/
462
463 /* history_init():
464  *      Initialization function.
465  */
466 public History *
467 history_init(void)
468 {
469         History *h = (History *) h_malloc(sizeof(History));
470         HistEvent ev;
471
472         history_def_init(&h->h_ref, &ev, 0);
473         h->h_ent = -1;
474         h->h_next = history_def_next;
475         h->h_first = history_def_first;
476         h->h_last = history_def_last;
477         h->h_prev = history_def_prev;
478         h->h_curr = history_def_curr;
479         h->h_set = history_def_set;
480         h->h_clear = history_def_clear;
481         h->h_enter = history_def_enter;
482         h->h_add = history_def_add;
483
484         return (h);
485 }
486
487
488 /* history_end():
489  *      clean up history;
490  */
491 public void
492 history_end(History *h)
493 {
494         HistEvent ev;
495
496         if (h->h_next == history_def_next)
497                 history_def_clear(h->h_ref, &ev);
498 }
499
500
501
502 /* history_setsize():
503  *      Set history number of events
504  */
505 private int
506 history_setsize(History *h, HistEvent *ev, int num)
507 {
508
509         if (h->h_next != history_def_next) {
510                 he_seterrev(ev, _HE_NOT_ALLOWED);
511                 return (-1);
512         }
513         if (num < 0) {
514                 he_seterrev(ev, _HE_BAD_PARAM);
515                 return (-1);
516         }
517         history_def_setsize(h->h_ref, num);
518         return (0);
519 }
520
521
522 /* history_getsize():
523  *      Get number of events currently in history
524  */
525 private int
526 history_getsize(History *h, HistEvent *ev)
527 {
528         int retval = 0;
529
530         if (h->h_next != history_def_next) {
531                 he_seterrev(ev, _HE_NOT_ALLOWED);
532                 return (-1);
533         }
534         retval = history_def_getsize(h->h_ref);
535         if (retval < -1) {
536                 he_seterrev(ev, _HE_SIZE_NEGATIVE);
537                 return (-1);
538         }
539         ev->num = retval;
540         return (0);
541 }
542
543
544 /* history_set_fun():
545  *      Set history functions
546  */
547 private int
548 history_set_fun(History *h, History *nh)
549 {
550         HistEvent ev;
551
552         if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
553             nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
554             nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
555             nh->h_ref == NULL) {
556                 if (h->h_next != history_def_next) {
557                         history_def_init(&h->h_ref, &ev, 0);
558                         h->h_first = history_def_first;
559                         h->h_next = history_def_next;
560                         h->h_last = history_def_last;
561                         h->h_prev = history_def_prev;
562                         h->h_curr = history_def_curr;
563                         h->h_set = history_def_set;
564                         h->h_clear = history_def_clear;
565                         h->h_enter = history_def_enter;
566                         h->h_add = history_def_add;
567                 }
568                 return (-1);
569         }
570         if (h->h_next == history_def_next)
571                 history_def_clear(h->h_ref, &ev);
572
573         h->h_ent = -1;
574         h->h_first = nh->h_first;
575         h->h_next = nh->h_next;
576         h->h_last = nh->h_last;
577         h->h_prev = nh->h_prev;
578         h->h_curr = nh->h_curr;
579         h->h_set = nh->h_set;
580         h->h_clear = nh->h_clear;
581         h->h_enter = nh->h_enter;
582         h->h_add = nh->h_add;
583
584         return (0);
585 }
586
587
588 /* history_load():
589  *      History load function
590  */
591 private int
592 history_load(History *h, const char *fname)
593 {
594         FILE *fp;
595         char *line;
596         size_t sz, max_size;
597         char *ptr;
598         int i = -1;
599         HistEvent ev;
600
601         if ((fp = fopen(fname, "r")) == NULL)
602                 return (i);
603
604         if ((line = fgetln(fp, &sz)) == NULL)
605                 goto done;
606
607         if (strncmp(line, hist_cookie, sz) != 0)
608                 goto done;
609
610         ptr = h_malloc(max_size = 1024);
611         for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
612                 char c = line[sz];
613
614                 if (sz != 0 && line[sz - 1] == '\n')
615                         line[--sz] = '\0';
616                 else
617                         line[sz] = '\0';
618
619                 if (max_size <= sz) {
620                         max_size = (sz + 1024) & ~1023;
621                         ptr = h_realloc(ptr, max_size);
622                 }
623                 (void) strunvis(ptr, line);
624                 line[sz] = c;
625                 HENTER(h, &ev, ptr);
626         }
627         h_free(ptr);
628
629 done:
630         (void) fclose(fp);
631         return (i);
632 }
633
634
635 /* history_save():
636  *      History save function
637  */
638 private int
639 history_save(History *h, const char *fname)
640 {
641         FILE *fp;
642         HistEvent ev;
643         int i = 0, retval;
644         size_t len, max_size;
645         char *ptr;
646
647         if ((fp = fopen(fname, "w")) == NULL)
648                 return (-1);
649
650 #if !_MSC_VER
651         (void) fchmod(fileno(fp), S_IRUSR|S_IWUSR);
652 #endif
653         (void) fputs(hist_cookie, fp);
654         ptr = h_malloc(max_size = 1024);
655         for (retval = HLAST(h, &ev);
656             retval != -1;
657             retval = HPREV(h, &ev), i++) {
658                 len = strlen(ev.str) * 4;
659                 if (len >= max_size) {
660                         max_size = (len + 1024) & ~1023;
661                         ptr = h_realloc(ptr, max_size);
662                 }
663                 (void) strvis(ptr, ev.str, VIS_WHITE);
664                 (void) fprintf(fp, "%s\n", ev.str);
665         }
666         h_free(ptr);
667         (void) fclose(fp);
668         return (i);
669 }
670
671
672 /* history_prev_event():
673  *      Find the previous event, with number given
674  */
675 private int
676 history_prev_event(History *h, HistEvent *ev, int num)
677 {
678         int retval;
679
680         for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
681                 if (ev->num == num)
682                         return (0);
683
684         he_seterrev(ev, _HE_NOT_FOUND);
685         return (-1);
686 }
687
688
689 /* history_next_event():
690  *      Find the next event, with number given
691  */
692 private int
693 history_next_event(History *h, HistEvent *ev, int num)
694 {
695         int retval;
696
697         for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
698                 if (ev->num == num)
699                         return (0);
700
701         he_seterrev(ev, _HE_NOT_FOUND);
702         return (-1);
703 }
704
705
706 /* history_prev_string():
707  *      Find the previous event beginning with string
708  */
709 private int
710 history_prev_string(History *h, HistEvent *ev, const char *str)
711 {
712         size_t len = strlen(str);
713         int retval;
714
715         for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
716                 if (strncmp(str, ev->str, len) == 0)
717                         return (0);
718
719         he_seterrev(ev, _HE_NOT_FOUND);
720         return (-1);
721 }
722
723
724 /* history_next_string():
725  *      Find the next event beginning with string
726  */
727 private int
728 history_next_string(History *h, HistEvent *ev, const char *str)
729 {
730         size_t len = strlen(str);
731         int retval;
732
733         for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
734                 if (strncmp(str, ev->str, len) == 0)
735                         return (0);
736
737         he_seterrev(ev, _HE_NOT_FOUND);
738         return (-1);
739 }
740
741
742 /* history():
743  *      User interface to history functions.
744  */
745 int
746 history(History *h, HistEvent *ev, int fun, ...)
747 {
748         va_list va;
749         const char *str;
750         int retval;
751
752         va_start(va, fun);
753
754         he_seterrev(ev, _HE_OK);
755
756         switch (fun) {
757         case H_GETSIZE:
758                 retval = history_getsize(h, ev);
759                 break;
760
761         case H_SETSIZE:
762                 retval = history_setsize(h, ev, va_arg(va, int));
763                 break;
764
765         case H_ADD:
766                 str = va_arg(va, const char *);
767                 retval = HADD(h, ev, str);
768                 break;
769
770         case H_ENTER:
771                 str = va_arg(va, const char *);
772                 if ((retval = HENTER(h, ev, str)) != -1)
773                         h->h_ent = ev->num;
774                 break;
775
776         case H_APPEND:
777                 str = va_arg(va, const char *);
778                 if ((retval = HSET(h, ev, h->h_ent)) != -1)
779                         retval = HADD(h, ev, str);
780                 break;
781
782         case H_FIRST:
783                 retval = HFIRST(h, ev);
784                 break;
785
786         case H_NEXT:
787                 retval = HNEXT(h, ev);
788                 break;
789
790         case H_LAST:
791                 retval = HLAST(h, ev);
792                 break;
793
794         case H_PREV:
795                 retval = HPREV(h, ev);
796                 break;
797
798         case H_CURR:
799                 retval = HCURR(h, ev);
800                 break;
801
802         case H_SET:
803                 retval = HSET(h, ev, va_arg(va, const int));
804                 break;
805
806         case H_CLEAR:
807                 HCLEAR(h, ev);
808                 retval = 0;
809                 break;
810
811         case H_LOAD:
812                 retval = history_load(h, va_arg(va, const char *));
813                 if (retval == -1)
814                         he_seterrev(ev, _HE_HIST_READ);
815                 break;
816
817         case H_SAVE:
818                 retval = history_save(h, va_arg(va, const char *));
819                 if (retval == -1)
820                         he_seterrev(ev, _HE_HIST_WRITE);
821                 break;
822
823         case H_PREV_EVENT:
824                 retval = history_prev_event(h, ev, va_arg(va, int));
825                 break;
826
827         case H_NEXT_EVENT:
828                 retval = history_next_event(h, ev, va_arg(va, int));
829                 break;
830
831         case H_PREV_STR:
832                 retval = history_prev_string(h, ev, va_arg(va, const char *));
833                 break;
834
835         case H_NEXT_STR:
836                 retval = history_next_string(h, ev, va_arg(va, const char *));
837                 break;
838
839         case H_FUNC:
840         {
841                 History hf;
842
843                 hf.h_ref = va_arg(va, ptr_t);
844                 h->h_ent = -1;
845                 hf.h_first = va_arg(va, history_gfun_t);
846                 hf.h_next = va_arg(va, history_gfun_t);
847                 hf.h_last = va_arg(va, history_gfun_t);
848                 hf.h_prev = va_arg(va, history_gfun_t);
849                 hf.h_curr = va_arg(va, history_gfun_t);
850                 hf.h_set = va_arg(va, history_sfun_t);
851                 hf.h_clear = va_arg(va, history_vfun_t);
852                 hf.h_enter = va_arg(va, history_efun_t);
853                 hf.h_add = va_arg(va, history_efun_t);
854
855                 if ((retval = history_set_fun(h, &hf)) == -1)
856                         he_seterrev(ev, _HE_PARAM_MISSING);
857                 break;
858         }
859
860         case H_END:
861                 history_end(h);
862                 retval = 0;
863                 break;
864
865         default:
866                 retval = -1;
867                 he_seterrev(ev, _HE_UNKNOWN);
868                 break;
869         }
870         va_end(va);
871         return (retval);
872 }
Note: See TracBrowser for help on using the browser.