2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * @(#)history.c 8.1 (Berkeley) 6/4/93
33 * $NetBSD: history.c,v 1.29 2005/07/06 21:13:02 christos Exp $
34 * $DragonFly: src/lib/libedit/history.c,v 1.6 2005/11/13 11:58:30 corecode Exp $
40 * hist.c: History access functions
52 static const char hist_cookie[] = "_HiStOrY_V2_\n";
56 typedef int (*history_gfun_t)(ptr_t, HistEvent *);
57 typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
58 typedef void (*history_vfun_t)(ptr_t, HistEvent *);
59 typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
62 ptr_t h_ref; /* Argument for history fcns */
63 int h_ent; /* Last entry point for history */
64 history_gfun_t h_first; /* Get the first element */
65 history_gfun_t h_next; /* Get the next element */
66 history_gfun_t h_last; /* Get the last element */
67 history_gfun_t h_prev; /* Get the previous element */
68 history_gfun_t h_curr; /* Get the current element */
69 history_sfun_t h_set; /* Set the current element */
70 history_vfun_t h_clear; /* Clear the history list */
71 history_efun_t h_enter; /* Add an element */
72 history_efun_t h_add; /* Append to an element */
75 #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
76 #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
77 #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
78 #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
79 #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
80 #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
81 #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
82 #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
83 #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
85 #define h_strdup(a) strdup(a)
86 #define h_malloc(a) malloc(a)
87 #define h_realloc(a, b) realloc((a), (b))
88 #define h_free(a) free(a)
97 private int history_setsize(History *, HistEvent *, int);
98 private int history_getsize(History *, HistEvent *);
99 private int history_setunique(History *, HistEvent *, int);
100 private int history_getunique(History *, HistEvent *);
101 private int history_set_fun(History *, History *);
102 private int history_load(History *, const char *);
103 private int history_save(History *, const char *);
104 private int history_prev_event(History *, HistEvent *, int);
105 private int history_next_event(History *, HistEvent *, int);
106 private int history_next_string(History *, HistEvent *, const char *);
107 private int history_prev_string(History *, HistEvent *, const char *);
110 /***********************************************************************/
113 * Builtin- history implementation
115 typedef struct hentry_t {
116 HistEvent ev; /* What we return */
117 struct hentry_t *next; /* Next entry */
118 struct hentry_t *prev; /* Previous entry */
121 typedef struct history_t {
122 hentry_t list; /* Fake list header element */
123 hentry_t *cursor; /* Current element in the list */
124 int max; /* Maximum number of events */
125 int cur; /* Current number of events */
126 int eventid; /* For generation of unique event id */
127 int flags; /* History flags */
128 #define H_UNIQUE 1 /* Store only unique elements */
131 private int history_def_first(ptr_t, HistEvent *);
132 private int history_def_last(ptr_t, HistEvent *);
133 private int history_def_next(ptr_t, HistEvent *);
134 private int history_def_prev(ptr_t, HistEvent *);
135 private int history_def_curr(ptr_t, HistEvent *);
136 private int history_def_set(ptr_t, HistEvent *, const int n);
137 private int history_def_enter(ptr_t, HistEvent *, const char *);
138 private int history_def_add(ptr_t, HistEvent *, const char *);
139 private int history_def_init(ptr_t *, HistEvent *, int);
140 private void history_def_clear(ptr_t, HistEvent *);
141 private int history_def_insert(history_t *, HistEvent *, const char *);
142 private void history_def_delete(history_t *, HistEvent *, hentry_t *);
144 #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
145 #define history_def_getsize(p) (((history_t *)p)->cur)
146 #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
147 #define history_def_setunique(p, uni) \
149 (((history_t *)p)->flags) |= H_UNIQUE; \
151 (((history_t *)p)->flags) &= ~H_UNIQUE
153 #define he_strerror(code) he_errlist[code]
154 #define he_seterrev(evp, code) {\
156 evp->str = he_strerror(code);\
160 static const char *const he_errlist[] = {
164 "first event not found",
165 "last event not found",
169 "current event is invalid",
171 "can't read history from file",
172 "can't write history",
173 "required parameter(s) not supplied",
174 "history size negative",
175 "function not allowed with other history-functions-set the default",
180 #define _HE_UNKNOWN 1
181 #define _HE_MALLOC_FAILED 2
182 #define _HE_FIRST_NOTFOUND 3
183 #define _HE_LAST_NOTFOUND 4
184 #define _HE_EMPTY_LIST 5
185 #define _HE_END_REACHED 6
186 #define _HE_START_REACHED 7
187 #define _HE_CURR_INVALID 8
188 #define _HE_NOT_FOUND 9
189 #define _HE_HIST_READ 10
190 #define _HE_HIST_WRITE 11
191 #define _HE_PARAM_MISSING 12
192 #define _HE_SIZE_NEGATIVE 13
193 #define _HE_NOT_ALLOWED 14
194 #define _HE_BAD_PARAM 15
196 /* history_def_first():
197 * Default function to return the first event in the history.
200 history_def_first(ptr_t p, HistEvent *ev)
202 history_t *h = (history_t *) p;
204 h->cursor = h->list.next;
205 if (h->cursor != &h->list)
208 he_seterrev(ev, _HE_FIRST_NOTFOUND);
216 /* history_def_last():
217 * Default function to return the last event in the history.
220 history_def_last(ptr_t p, HistEvent *ev)
222 history_t *h = (history_t *) p;
224 h->cursor = h->list.prev;
225 if (h->cursor != &h->list)
228 he_seterrev(ev, _HE_LAST_NOTFOUND);
236 /* history_def_next():
237 * Default function to return the next event in the history.
240 history_def_next(ptr_t p, HistEvent *ev)
242 history_t *h = (history_t *) p;
244 if (h->cursor == &h->list) {
245 he_seterrev(ev, _HE_EMPTY_LIST);
249 if (h->cursor->next == &h->list) {
250 he_seterrev(ev, _HE_END_REACHED);
254 h->cursor = h->cursor->next;
261 /* history_def_prev():
262 * Default function to return the previous event in the history.
265 history_def_prev(ptr_t p, HistEvent *ev)
267 history_t *h = (history_t *) p;
269 if (h->cursor == &h->list) {
271 (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
275 if (h->cursor->prev == &h->list) {
276 he_seterrev(ev, _HE_START_REACHED);
280 h->cursor = h->cursor->prev;
287 /* history_def_curr():
288 * Default function to return the current event in the history.
291 history_def_curr(ptr_t p, HistEvent *ev)
293 history_t *h = (history_t *) p;
295 if (h->cursor != &h->list)
299 (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
307 /* history_def_set():
308 * Default function to set the current event in the history to the
312 history_def_set(ptr_t p, HistEvent *ev, const int n)
314 history_t *h = (history_t *) p;
317 he_seterrev(ev, _HE_EMPTY_LIST);
320 if (h->cursor == &h->list || h->cursor->ev.num != n) {
321 for (h->cursor = h->list.next; h->cursor != &h->list;
322 h->cursor = h->cursor->next)
323 if (h->cursor->ev.num == n)
326 if (h->cursor == &h->list) {
327 he_seterrev(ev, _HE_NOT_FOUND);
334 /* history_def_add():
335 * Append string to element
338 history_def_add(ptr_t p, HistEvent *ev, const char *str)
340 history_t *h = (history_t *) p;
343 HistEventPrivate *evp = (void *)&h->cursor->ev;
345 if (h->cursor == &h->list)
346 return (history_def_enter(p, ev, str));
347 len = strlen(evp->str) + strlen(str) + 1;
348 s = (char *) h_malloc(len);
350 he_seterrev(ev, _HE_MALLOC_FAILED);
353 (void) strlcpy(s, h->cursor->ev.str, len);
354 (void) strlcat(s, str, len);
355 h_free((ptr_t)evp->str);
362 /* history_def_delete():
363 * Delete element hp of the h list
367 history_def_delete(history_t *h,
368 HistEvent *ev __attribute__((__unused__)), hentry_t *hp)
370 HistEventPrivate *evp = (void *)&hp->ev;
373 hp->prev->next = hp->next;
374 hp->next->prev = hp->prev;
375 h_free((ptr_t) evp->str);
381 /* history_def_insert():
382 * Insert element with string str in the h list
385 history_def_insert(history_t *h, HistEvent *ev, const char *str)
388 h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
389 if (h->cursor == NULL)
391 if ((h->cursor->ev.str = h_strdup(str)) == NULL) {
392 h_free((ptr_t)h->cursor);
395 h->cursor->ev.num = ++h->eventid;
396 h->cursor->next = h->list.next;
397 h->cursor->prev = &h->list;
398 h->list.next->prev = h->cursor;
399 h->list.next = h->cursor;
405 he_seterrev(ev, _HE_MALLOC_FAILED);
410 /* history_def_enter():
411 * Default function to enter an item in the history
414 history_def_enter(ptr_t p, HistEvent *ev, const char *str)
416 history_t *h = (history_t *) p;
418 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
419 strcmp(h->list.next->ev.str, str) == 0)
422 if (history_def_insert(h, ev, str) == -1)
423 return (-1); /* error, keep error message */
426 * Always keep at least one entry.
427 * This way we don't have to check for the empty list.
429 while (h->cur > h->max && h->cur > 0)
430 history_def_delete(h, ev, h->list.prev);
436 /* history_def_init():
437 * Default history initialization function
441 history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n)
443 history_t *h = (history_t *) h_malloc(sizeof(history_t));
452 h->list.next = h->list.prev = &h->list;
453 h->list.ev.str = NULL;
455 h->cursor = &h->list;
462 /* history_def_clear():
463 * Default history cleanup function
466 history_def_clear(ptr_t p, HistEvent *ev)
468 history_t *h = (history_t *) p;
470 while (h->list.prev != &h->list)
471 history_def_delete(h, ev, h->list.prev);
479 /************************************************************************/
482 * Initialization function.
488 History *h = (History *) h_malloc(sizeof(History));
492 if (history_def_init(&h->h_ref, &ev, 0) == -1) {
497 h->h_next = history_def_next;
498 h->h_first = history_def_first;
499 h->h_last = history_def_last;
500 h->h_prev = history_def_prev;
501 h->h_curr = history_def_curr;
502 h->h_set = history_def_set;
503 h->h_clear = history_def_clear;
504 h->h_enter = history_def_enter;
505 h->h_add = history_def_add;
515 history_end(History *h)
519 if (h->h_next == history_def_next)
520 history_def_clear(h->h_ref, &ev);
526 /* history_setsize():
527 * Set history number of events
530 history_setsize(History *h, HistEvent *ev, int num)
533 if (h->h_next != history_def_next) {
534 he_seterrev(ev, _HE_NOT_ALLOWED);
538 he_seterrev(ev, _HE_BAD_PARAM);
541 history_def_setsize(h->h_ref, num);
546 /* history_getsize():
547 * Get number of events currently in history
550 history_getsize(History *h, HistEvent *ev)
552 if (h->h_next != history_def_next) {
553 he_seterrev(ev, _HE_NOT_ALLOWED);
556 ev->num = history_def_getsize(h->h_ref);
558 he_seterrev(ev, _HE_SIZE_NEGATIVE);
565 /* history_setunique():
566 * Set if adjacent equal events should not be entered in history.
569 history_setunique(History *h, HistEvent *ev, int uni)
572 if (h->h_next != history_def_next) {
573 he_seterrev(ev, _HE_NOT_ALLOWED);
576 history_def_setunique(h->h_ref, uni);
581 /* history_getunique():
582 * Get if adjacent equal events should not be entered in history.
585 history_getunique(History *h, HistEvent *ev)
587 if (h->h_next != history_def_next) {
588 he_seterrev(ev, _HE_NOT_ALLOWED);
591 ev->num = history_def_getunique(h->h_ref);
596 /* history_set_fun():
597 * Set history functions
600 history_set_fun(History *h, History *nh)
604 if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
605 nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
606 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
608 if (h->h_next != history_def_next) {
609 history_def_init(&h->h_ref, &ev, 0);
610 h->h_first = history_def_first;
611 h->h_next = history_def_next;
612 h->h_last = history_def_last;
613 h->h_prev = history_def_prev;
614 h->h_curr = history_def_curr;
615 h->h_set = history_def_set;
616 h->h_clear = history_def_clear;
617 h->h_enter = history_def_enter;
618 h->h_add = history_def_add;
622 if (h->h_next == history_def_next)
623 history_def_clear(h->h_ref, &ev);
626 h->h_first = nh->h_first;
627 h->h_next = nh->h_next;
628 h->h_last = nh->h_last;
629 h->h_prev = nh->h_prev;
630 h->h_curr = nh->h_curr;
631 h->h_set = nh->h_set;
632 h->h_clear = nh->h_clear;
633 h->h_enter = nh->h_enter;
634 h->h_add = nh->h_add;
641 * History load function
644 history_load(History *h, const char *fname)
653 if ((fp = fopen(fname, "r")) == NULL)
656 if ((line = fgetln(fp, &sz)) == NULL)
659 if (strncmp(line, hist_cookie, sz) != 0)
662 ptr = h_malloc(max_size = 1024);
665 for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
668 if (sz != 0 && line[sz - 1] == '\n')
675 max_size = (sz + 1024) & ~1023;
676 nptr = h_realloc(ptr, max_size);
683 (void) strunvis(ptr, line);
685 if (HENTER(h, &ev, ptr) == -1) {
699 * History save function
702 history_save(History *h, const char *fname)
707 size_t len, max_size;
710 if ((fp = fopen(fname, "w")) == NULL)
713 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
715 if (fputs(hist_cookie, fp) == EOF)
717 ptr = h_malloc(max_size = 1024);
720 for (i = 0, retval = HLAST(h, &ev);
722 retval = HPREV(h, &ev), i++) {
723 len = strlen(ev.str) * 4;
724 if (len >= max_size) {
726 max_size = (len + 1024) & ~1023;
727 nptr = h_realloc(ptr, max_size);
734 (void) strvis(ptr, ev.str, VIS_WHITE);
735 (void) fprintf(fp, "%s\n", ptr);
745 /* history_prev_event():
746 * Find the previous event, with number given
749 history_prev_event(History *h, HistEvent *ev, int num)
753 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
757 he_seterrev(ev, _HE_NOT_FOUND);
762 /* history_next_event():
763 * Find the next event, with number given
766 history_next_event(History *h, HistEvent *ev, int num)
770 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
774 he_seterrev(ev, _HE_NOT_FOUND);
779 /* history_prev_string():
780 * Find the previous event beginning with string
783 history_prev_string(History *h, HistEvent *ev, const char *str)
785 size_t len = strlen(str);
788 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
789 if (strncmp(str, ev->str, len) == 0)
792 he_seterrev(ev, _HE_NOT_FOUND);
797 /* history_next_string():
798 * Find the next event beginning with string
801 history_next_string(History *h, HistEvent *ev, const char *str)
803 size_t len = strlen(str);
806 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
807 if (strncmp(str, ev->str, len) == 0)
810 he_seterrev(ev, _HE_NOT_FOUND);
816 * User interface to history functions.
819 history(History *h, HistEvent *ev, int fun, ...)
827 he_seterrev(ev, _HE_OK);
831 retval = history_getsize(h, ev);
835 retval = history_setsize(h, ev, va_arg(va, int));
839 retval = history_getunique(h, ev);
843 retval = history_setunique(h, ev, va_arg(va, int));
847 str = va_arg(va, const char *);
848 retval = HADD(h, ev, str);
852 str = va_arg(va, const char *);
853 if ((retval = HENTER(h, ev, str)) != -1)
858 str = va_arg(va, const char *);
859 if ((retval = HSET(h, ev, h->h_ent)) != -1)
860 retval = HADD(h, ev, str);
864 retval = HFIRST(h, ev);
868 retval = HNEXT(h, ev);
872 retval = HLAST(h, ev);
876 retval = HPREV(h, ev);
880 retval = HCURR(h, ev);
884 retval = HSET(h, ev, va_arg(va, const int));
893 retval = history_load(h, va_arg(va, const char *));
895 he_seterrev(ev, _HE_HIST_READ);
899 retval = history_save(h, va_arg(va, const char *));
901 he_seterrev(ev, _HE_HIST_WRITE);
905 retval = history_prev_event(h, ev, va_arg(va, int));
909 retval = history_next_event(h, ev, va_arg(va, int));
913 retval = history_prev_string(h, ev, va_arg(va, const char *));
917 retval = history_next_string(h, ev, va_arg(va, const char *));
924 hf.h_ref = va_arg(va, ptr_t);
926 hf.h_first = va_arg(va, history_gfun_t);
927 hf.h_next = va_arg(va, history_gfun_t);
928 hf.h_last = va_arg(va, history_gfun_t);
929 hf.h_prev = va_arg(va, history_gfun_t);
930 hf.h_curr = va_arg(va, history_gfun_t);
931 hf.h_set = va_arg(va, history_sfun_t);
932 hf.h_clear = va_arg(va, history_vfun_t);
933 hf.h_enter = va_arg(va, history_efun_t);
934 hf.h_add = va_arg(va, history_efun_t);
936 if ((retval = history_set_fun(h, &hf)) == -1)
937 he_seterrev(ev, _HE_PARAM_MISSING);
948 he_seterrev(ev, _HE_UNKNOWN);