root/src/noitedit/history.c

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

Make OpenBSD not crap on sprintf and strcpy (replace them)

  • 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 "noitedit/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 "noitedit/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 "noitedit/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) strlcpy(ptr, line, max_size);
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                 /* next line is better. strvis(ptr, ev.str, VIS_WHITE); */
664                 (void) strlcpy(ptr, ev.str, max_size);
665                 (void) fprintf(fp, "%s\n", ev.str);
666         }
667         h_free(ptr);
668         (void) fclose(fp);
669         return (i);
670 }
671
672
673 /* history_prev_event():
674  *      Find the previous event, with number given
675  */
676 private int
677 history_prev_event(History *h, HistEvent *ev, int num)
678 {
679         int retval;
680
681         for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
682                 if (ev->num == num)
683                         return (0);
684
685         he_seterrev(ev, _HE_NOT_FOUND);
686         return (-1);
687 }
688
689
690 /* history_next_event():
691  *      Find the next event, with number given
692  */
693 private int
694 history_next_event(History *h, HistEvent *ev, int num)
695 {
696         int retval;
697
698         for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
699                 if (ev->num == num)
700                         return (0);
701
702         he_seterrev(ev, _HE_NOT_FOUND);
703         return (-1);
704 }
705
706
707 /* history_prev_string():
708  *      Find the previous event beginning with string
709  */
710 private int
711 history_prev_string(History *h, HistEvent *ev, const char *str)
712 {
713         size_t len = strlen(str);
714         int retval;
715
716         for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
717                 if (strncmp(str, ev->str, len) == 0)
718                         return (0);
719
720         he_seterrev(ev, _HE_NOT_FOUND);
721         return (-1);
722 }
723
724
725 /* history_next_string():
726  *      Find the next event beginning with string
727  */
728 private int
729 history_next_string(History *h, HistEvent *ev, const char *str)
730 {
731         size_t len = strlen(str);
732         int retval;
733
734         for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
735                 if (strncmp(str, ev->str, len) == 0)
736                         return (0);
737
738         he_seterrev(ev, _HE_NOT_FOUND);
739         return (-1);
740 }
741
742
743 /* history():
744  *      User interface to history functions.
745  */
746 int
747 history(History *h, HistEvent *ev, int fun, ...)
748 {
749         va_list va;
750         const char *str;
751         int retval;
752
753         va_start(va, fun);
754
755         he_seterrev(ev, _HE_OK);
756
757         switch (fun) {
758         case H_GETSIZE:
759                 retval = history_getsize(h, ev);
760                 break;
761
762         case H_SETSIZE:
763                 retval = history_setsize(h, ev, va_arg(va, int));
764                 break;
765
766         case H_ADD:
767                 str = va_arg(va, const char *);
768                 retval = HADD(h, ev, str);
769                 break;
770
771         case H_ENTER:
772                 str = va_arg(va, const char *);
773                 if ((retval = HENTER(h, ev, str)) != -1)
774                         h->h_ent = ev->num;
775                 break;
776
777         case H_APPEND:
778                 str = va_arg(va, const char *);
779                 if ((retval = HSET(h, ev, h->h_ent)) != -1)
780                         retval = HADD(h, ev, str);
781                 break;
782
783         case H_FIRST:
784                 retval = HFIRST(h, ev);
785                 break;
786
787         case H_NEXT:
788                 retval = HNEXT(h, ev);
789                 break;
790
791         case H_LAST:
792                 retval = HLAST(h, ev);
793                 break;
794
795         case H_PREV:
796                 retval = HPREV(h, ev);
797                 break;
798
799         case H_CURR:
800                 retval = HCURR(h, ev);
801                 break;
802
803         case H_SET:
804                 retval = HSET(h, ev, va_arg(va, const int));
805                 break;
806
807         case H_CLEAR:
808                 HCLEAR(h, ev);
809                 retval = 0;
810                 break;
811
812         case H_LOAD:
813                 retval = history_load(h, va_arg(va, const char *));
814                 if (retval == -1)
815                         he_seterrev(ev, _HE_HIST_READ);
816                 break;
817
818         case H_SAVE:
819                 retval = history_save(h, va_arg(va, const char *));
820                 if (retval == -1)
821                         he_seterrev(ev, _HE_HIST_WRITE);
822                 break;
823
824         case H_PREV_EVENT:
825                 retval = history_prev_event(h, ev, va_arg(va, int));
826                 break;
827
828         case H_NEXT_EVENT:
829                 retval = history_next_event(h, ev, va_arg(va, int));
830                 break;
831
832         case H_PREV_STR:
833                 retval = history_prev_string(h, ev, va_arg(va, const char *));
834                 break;
835
836         case H_NEXT_STR:
837                 retval = history_next_string(h, ev, va_arg(va, const char *));
838                 break;
839
840         case H_FUNC:
841         {
842                 History hf;
843
844                 hf.h_ref = va_arg(va, ptr_t);
845                 h->h_ent = -1;
846                 hf.h_first = va_arg(va, history_gfun_t);
847                 hf.h_next = va_arg(va, history_gfun_t);
848                 hf.h_last = va_arg(va, history_gfun_t);
849                 hf.h_prev = va_arg(va, history_gfun_t);
850                 hf.h_curr = va_arg(va, history_gfun_t);
851                 hf.h_set = va_arg(va, history_sfun_t);
852                 hf.h_clear = va_arg(va, history_vfun_t);
853                 hf.h_enter = va_arg(va, history_efun_t);
854                 hf.h_add = va_arg(va, history_efun_t);
855
856                 if ((retval = history_set_fun(h, &hf)) == -1)
857                         he_seterrev(ev, _HE_PARAM_MISSING);
858                 break;
859         }
860
861         case H_END:
862                 history_end(h);
863                 retval = 0;
864                 break;
865
866         default:
867                 retval = -1;
868                 he_seterrev(ev, _HE_UNKNOWN);
869                 break;
870         }
871         va_end(va);
872         return (retval);
873 }
Note: See TracBrowser for help on using the browser.