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.32 2006/09/28 13:52:51 christos Exp $
34 * $DragonFly: src/lib/libedit/history.c,v 1.7 2007/05/05 00:27:39 pavalos 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_sfun_t h_del
; /* Set the given element */
71 history_vfun_t h_clear
; /* Clear the history list */
72 history_efun_t h_enter
; /* Add an element */
73 history_efun_t h_add
; /* Append to an element */
76 #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
77 #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
78 #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
79 #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
80 #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
81 #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
82 #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
83 #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
84 #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
85 #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
87 #define h_strdup(a) strdup(a)
88 #define h_malloc(a) malloc(a)
89 #define h_realloc(a, b) realloc((a), (b))
90 #define h_free(a) free(a)
99 private int history_setsize(History
*, HistEvent
*, int);
100 private int history_getsize(History
*, HistEvent
*);
101 private int history_setunique(History
*, HistEvent
*, int);
102 private int history_getunique(History
*, HistEvent
*);
103 private int history_set_fun(History
*, History
*);
104 private int history_load(History
*, const char *);
105 private int history_save(History
*, const char *);
106 private int history_prev_event(History
*, HistEvent
*, int);
107 private int history_next_event(History
*, HistEvent
*, int);
108 private int history_next_string(History
*, HistEvent
*, const char *);
109 private int history_prev_string(History
*, HistEvent
*, const char *);
112 /***********************************************************************/
115 * Builtin- history implementation
117 typedef struct hentry_t
{
118 HistEvent ev
; /* What we return */
119 struct hentry_t
*next
; /* Next entry */
120 struct hentry_t
*prev
; /* Previous entry */
123 typedef struct history_t
{
124 hentry_t list
; /* Fake list header element */
125 hentry_t
*cursor
; /* Current element in the list */
126 int max
; /* Maximum number of events */
127 int cur
; /* Current number of events */
128 int eventid
; /* For generation of unique event id */
129 int flags
; /* History flags */
130 #define H_UNIQUE 1 /* Store only unique elements */
133 private int history_def_next(ptr_t
, HistEvent
*);
134 private int history_def_first(ptr_t
, HistEvent
*);
135 private int history_def_prev(ptr_t
, HistEvent
*);
136 private int history_def_last(ptr_t
, HistEvent
*);
137 private int history_def_curr(ptr_t
, HistEvent
*);
138 private int history_def_set(ptr_t
, HistEvent
*, const int);
139 private void history_def_clear(ptr_t
, HistEvent
*);
140 private int history_def_enter(ptr_t
, HistEvent
*, const char *);
141 private int history_def_add(ptr_t
, HistEvent
*, const char *);
142 private int history_def_del(ptr_t
, HistEvent
*, const int);
144 private int history_def_init(ptr_t
*, HistEvent
*, int);
145 private int history_def_insert(history_t
*, HistEvent
*, const char *);
146 private void history_def_delete(history_t
*, HistEvent
*, hentry_t
*);
148 #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
149 #define history_def_getsize(p) (((history_t *)p)->cur)
150 #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
151 #define history_def_setunique(p, uni) \
153 (((history_t *)p)->flags) |= H_UNIQUE; \
155 (((history_t *)p)->flags) &= ~H_UNIQUE
157 #define he_strerror(code) he_errlist[code]
158 #define he_seterrev(evp, code) {\
160 evp->str = he_strerror(code);\
164 static const char *const he_errlist
[] = {
168 "first event not found",
169 "last event not found",
173 "current event is invalid",
175 "can't read history from file",
176 "can't write history",
177 "required parameter(s) not supplied",
178 "history size negative",
179 "function not allowed with other history-functions-set the default",
184 #define _HE_UNKNOWN 1
185 #define _HE_MALLOC_FAILED 2
186 #define _HE_FIRST_NOTFOUND 3
187 #define _HE_LAST_NOTFOUND 4
188 #define _HE_EMPTY_LIST 5
189 #define _HE_END_REACHED 6
190 #define _HE_START_REACHED 7
191 #define _HE_CURR_INVALID 8
192 #define _HE_NOT_FOUND 9
193 #define _HE_HIST_READ 10
194 #define _HE_HIST_WRITE 11
195 #define _HE_PARAM_MISSING 12
196 #define _HE_SIZE_NEGATIVE 13
197 #define _HE_NOT_ALLOWED 14
198 #define _HE_BAD_PARAM 15
200 /* history_def_first():
201 * Default function to return the first event in the history.
204 history_def_first(ptr_t p
, HistEvent
*ev
)
206 history_t
*h
= (history_t
*) p
;
208 h
->cursor
= h
->list
.next
;
209 if (h
->cursor
!= &h
->list
)
212 he_seterrev(ev
, _HE_FIRST_NOTFOUND
);
220 /* history_def_last():
221 * Default function to return the last event in the history.
224 history_def_last(ptr_t p
, HistEvent
*ev
)
226 history_t
*h
= (history_t
*) p
;
228 h
->cursor
= h
->list
.prev
;
229 if (h
->cursor
!= &h
->list
)
232 he_seterrev(ev
, _HE_LAST_NOTFOUND
);
240 /* history_def_next():
241 * Default function to return the next event in the history.
244 history_def_next(ptr_t p
, HistEvent
*ev
)
246 history_t
*h
= (history_t
*) p
;
248 if (h
->cursor
== &h
->list
) {
249 he_seterrev(ev
, _HE_EMPTY_LIST
);
253 if (h
->cursor
->next
== &h
->list
) {
254 he_seterrev(ev
, _HE_END_REACHED
);
258 h
->cursor
= h
->cursor
->next
;
265 /* history_def_prev():
266 * Default function to return the previous event in the history.
269 history_def_prev(ptr_t p
, HistEvent
*ev
)
271 history_t
*h
= (history_t
*) p
;
273 if (h
->cursor
== &h
->list
) {
275 (h
->cur
> 0) ? _HE_END_REACHED
: _HE_EMPTY_LIST
);
279 if (h
->cursor
->prev
== &h
->list
) {
280 he_seterrev(ev
, _HE_START_REACHED
);
284 h
->cursor
= h
->cursor
->prev
;
291 /* history_def_curr():
292 * Default function to return the current event in the history.
295 history_def_curr(ptr_t p
, HistEvent
*ev
)
297 history_t
*h
= (history_t
*) p
;
299 if (h
->cursor
!= &h
->list
)
303 (h
->cur
> 0) ? _HE_CURR_INVALID
: _HE_EMPTY_LIST
);
311 /* history_def_set():
312 * Default function to set the current event in the history to the
316 history_def_set(ptr_t p
, HistEvent
*ev
, const int n
)
318 history_t
*h
= (history_t
*) p
;
321 he_seterrev(ev
, _HE_EMPTY_LIST
);
324 if (h
->cursor
== &h
->list
|| h
->cursor
->ev
.num
!= n
) {
325 for (h
->cursor
= h
->list
.next
; h
->cursor
!= &h
->list
;
326 h
->cursor
= h
->cursor
->next
)
327 if (h
->cursor
->ev
.num
== n
)
330 if (h
->cursor
== &h
->list
) {
331 he_seterrev(ev
, _HE_NOT_FOUND
);
338 /* history_def_add():
339 * Append string to element
342 history_def_add(ptr_t p
, HistEvent
*ev
, const char *str
)
344 history_t
*h
= (history_t
*) p
;
347 HistEventPrivate
*evp
= (void *)&h
->cursor
->ev
;
349 if (h
->cursor
== &h
->list
)
350 return (history_def_enter(p
, ev
, str
));
351 len
= strlen(evp
->str
) + strlen(str
) + 1;
352 s
= (char *) h_malloc(len
);
354 he_seterrev(ev
, _HE_MALLOC_FAILED
);
357 (void) strlcpy(s
, h
->cursor
->ev
.str
, len
);
358 (void) strlcat(s
, str
, len
);
359 h_free((ptr_t
)evp
->str
);
366 /* history_def_del():
367 * Delete element hp of the h list
371 history_def_del(ptr_t p
, HistEvent
*ev
__attribute__((__unused__
)),
374 history_t
*h
= (history_t
*) p
;
375 if (history_def_set(h
, ev
, num
) != 0)
377 ev
->str
= strdup(h
->cursor
->ev
.str
);
378 ev
->num
= h
->cursor
->ev
.num
;
379 history_def_delete(h
, ev
, h
->cursor
);
384 /* history_def_delete():
385 * Delete element hp of the h list
389 history_def_delete(history_t
*h
,
390 HistEvent
*ev
__attribute__((__unused__
)), hentry_t
*hp
)
392 HistEventPrivate
*evp
= (void *)&hp
->ev
;
396 h
->cursor
= hp
->prev
;
397 hp
->prev
->next
= hp
->next
;
398 hp
->next
->prev
= hp
->prev
;
399 h_free((ptr_t
) evp
->str
);
405 /* history_def_insert():
406 * Insert element with string str in the h list
409 history_def_insert(history_t
*h
, HistEvent
*ev
, const char *str
)
412 h
->cursor
= (hentry_t
*) h_malloc(sizeof(hentry_t
));
413 if (h
->cursor
== NULL
)
415 if ((h
->cursor
->ev
.str
= h_strdup(str
)) == NULL
) {
416 h_free((ptr_t
)h
->cursor
);
419 h
->cursor
->ev
.num
= ++h
->eventid
;
420 h
->cursor
->next
= h
->list
.next
;
421 h
->cursor
->prev
= &h
->list
;
422 h
->list
.next
->prev
= h
->cursor
;
423 h
->list
.next
= h
->cursor
;
429 he_seterrev(ev
, _HE_MALLOC_FAILED
);
434 /* history_def_enter():
435 * Default function to enter an item in the history
438 history_def_enter(ptr_t p
, HistEvent
*ev
, const char *str
)
440 history_t
*h
= (history_t
*) p
;
442 if ((h
->flags
& H_UNIQUE
) != 0 && h
->list
.next
!= &h
->list
&&
443 strcmp(h
->list
.next
->ev
.str
, str
) == 0)
446 if (history_def_insert(h
, ev
, str
) == -1)
447 return (-1); /* error, keep error message */
450 * Always keep at least one entry.
451 * This way we don't have to check for the empty list.
453 while (h
->cur
> h
->max
&& h
->cur
> 0)
454 history_def_delete(h
, ev
, h
->list
.prev
);
460 /* history_def_init():
461 * Default history initialization function
465 history_def_init(ptr_t
*p
, HistEvent
*ev
__attribute__((__unused__
)), int n
)
467 history_t
*h
= (history_t
*) h_malloc(sizeof(history_t
));
476 h
->list
.next
= h
->list
.prev
= &h
->list
;
477 h
->list
.ev
.str
= NULL
;
479 h
->cursor
= &h
->list
;
486 /* history_def_clear():
487 * Default history cleanup function
490 history_def_clear(ptr_t p
, HistEvent
*ev
)
492 history_t
*h
= (history_t
*) p
;
494 while (h
->list
.prev
!= &h
->list
)
495 history_def_delete(h
, ev
, h
->list
.prev
);
503 /************************************************************************/
506 * Initialization function.
512 History
*h
= (History
*) h_malloc(sizeof(History
));
516 if (history_def_init(&h
->h_ref
, &ev
, 0) == -1) {
521 h
->h_next
= history_def_next
;
522 h
->h_first
= history_def_first
;
523 h
->h_last
= history_def_last
;
524 h
->h_prev
= history_def_prev
;
525 h
->h_curr
= history_def_curr
;
526 h
->h_set
= history_def_set
;
527 h
->h_clear
= history_def_clear
;
528 h
->h_enter
= history_def_enter
;
529 h
->h_add
= history_def_add
;
530 h
->h_del
= history_def_del
;
540 history_end(History
*h
)
544 if (h
->h_next
== history_def_next
)
545 history_def_clear(h
->h_ref
, &ev
);
552 /* history_setsize():
553 * Set history number of events
556 history_setsize(History
*h
, HistEvent
*ev
, int num
)
559 if (h
->h_next
!= history_def_next
) {
560 he_seterrev(ev
, _HE_NOT_ALLOWED
);
564 he_seterrev(ev
, _HE_BAD_PARAM
);
567 history_def_setsize(h
->h_ref
, num
);
572 /* history_getsize():
573 * Get number of events currently in history
576 history_getsize(History
*h
, HistEvent
*ev
)
578 if (h
->h_next
!= history_def_next
) {
579 he_seterrev(ev
, _HE_NOT_ALLOWED
);
582 ev
->num
= history_def_getsize(h
->h_ref
);
584 he_seterrev(ev
, _HE_SIZE_NEGATIVE
);
591 /* history_setunique():
592 * Set if adjacent equal events should not be entered in history.
595 history_setunique(History
*h
, HistEvent
*ev
, int uni
)
598 if (h
->h_next
!= history_def_next
) {
599 he_seterrev(ev
, _HE_NOT_ALLOWED
);
602 history_def_setunique(h
->h_ref
, uni
);
607 /* history_getunique():
608 * Get if adjacent equal events should not be entered in history.
611 history_getunique(History
*h
, HistEvent
*ev
)
613 if (h
->h_next
!= history_def_next
) {
614 he_seterrev(ev
, _HE_NOT_ALLOWED
);
617 ev
->num
= history_def_getunique(h
->h_ref
);
622 /* history_set_fun():
623 * Set history functions
626 history_set_fun(History
*h
, History
*nh
)
630 if (nh
->h_first
== NULL
|| nh
->h_next
== NULL
|| nh
->h_last
== NULL
||
631 nh
->h_prev
== NULL
|| nh
->h_curr
== NULL
|| nh
->h_set
== NULL
||
632 nh
->h_enter
== NULL
|| nh
->h_add
== NULL
|| nh
->h_clear
== NULL
||
633 nh
->h_del
== NULL
|| nh
->h_ref
== NULL
) {
634 if (h
->h_next
!= history_def_next
) {
635 history_def_init(&h
->h_ref
, &ev
, 0);
636 h
->h_first
= history_def_first
;
637 h
->h_next
= history_def_next
;
638 h
->h_last
= history_def_last
;
639 h
->h_prev
= history_def_prev
;
640 h
->h_curr
= history_def_curr
;
641 h
->h_set
= history_def_set
;
642 h
->h_clear
= history_def_clear
;
643 h
->h_enter
= history_def_enter
;
644 h
->h_add
= history_def_add
;
645 h
->h_del
= history_def_del
;
649 if (h
->h_next
== history_def_next
)
650 history_def_clear(h
->h_ref
, &ev
);
653 h
->h_first
= nh
->h_first
;
654 h
->h_next
= nh
->h_next
;
655 h
->h_last
= nh
->h_last
;
656 h
->h_prev
= nh
->h_prev
;
657 h
->h_curr
= nh
->h_curr
;
658 h
->h_set
= nh
->h_set
;
659 h
->h_clear
= nh
->h_clear
;
660 h
->h_enter
= nh
->h_enter
;
661 h
->h_add
= nh
->h_add
;
662 h
->h_del
= nh
->h_del
;
669 * History load function
672 history_load(History
*h
, const char *fname
)
681 if ((fp
= fopen(fname
, "r")) == NULL
)
684 if ((line
= fgetln(fp
, &sz
)) == NULL
)
687 if (strncmp(line
, hist_cookie
, sz
) != 0)
690 ptr
= h_malloc(max_size
= 1024);
693 for (i
= 0; (line
= fgetln(fp
, &sz
)) != NULL
; i
++) {
696 if (sz
!= 0 && line
[sz
- 1] == '\n')
703 max_size
= (sz
+ 1024) & ~1023;
704 nptr
= h_realloc(ptr
, max_size
);
711 (void) strunvis(ptr
, line
);
713 if (HENTER(h
, &ev
, ptr
) == -1) {
727 * History save function
730 history_save(History
*h
, const char *fname
)
735 size_t len
, max_size
;
738 if ((fp
= fopen(fname
, "w")) == NULL
)
741 if (fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
) == -1)
743 if (fputs(hist_cookie
, fp
) == EOF
)
745 ptr
= h_malloc(max_size
= 1024);
748 for (i
= 0, retval
= HLAST(h
, &ev
);
750 retval
= HPREV(h
, &ev
), i
++) {
751 len
= strlen(ev
.str
) * 4;
752 if (len
>= max_size
) {
754 max_size
= (len
+ 1024) & ~1023;
755 nptr
= h_realloc(ptr
, max_size
);
762 (void) strvis(ptr
, ev
.str
, VIS_WHITE
);
763 (void) fprintf(fp
, "%s\n", ptr
);
773 /* history_prev_event():
774 * Find the previous event, with number given
777 history_prev_event(History
*h
, HistEvent
*ev
, int num
)
781 for (retval
= HCURR(h
, ev
); retval
!= -1; retval
= HPREV(h
, ev
))
785 he_seterrev(ev
, _HE_NOT_FOUND
);
790 /* history_next_event():
791 * Find the next event, with number given
794 history_next_event(History
*h
, HistEvent
*ev
, int num
)
798 for (retval
= HCURR(h
, ev
); retval
!= -1; retval
= HNEXT(h
, ev
))
802 he_seterrev(ev
, _HE_NOT_FOUND
);
807 /* history_prev_string():
808 * Find the previous event beginning with string
811 history_prev_string(History
*h
, HistEvent
*ev
, const char *str
)
813 size_t len
= strlen(str
);
816 for (retval
= HCURR(h
, ev
); retval
!= -1; retval
= HNEXT(h
, ev
))
817 if (strncmp(str
, ev
->str
, len
) == 0)
820 he_seterrev(ev
, _HE_NOT_FOUND
);
825 /* history_next_string():
826 * Find the next event beginning with string
829 history_next_string(History
*h
, HistEvent
*ev
, const char *str
)
831 size_t len
= strlen(str
);
834 for (retval
= HCURR(h
, ev
); retval
!= -1; retval
= HPREV(h
, ev
))
835 if (strncmp(str
, ev
->str
, len
) == 0)
838 he_seterrev(ev
, _HE_NOT_FOUND
);
844 * User interface to history functions.
847 history(History
*h
, HistEvent
*ev
, int fun
, ...)
855 he_seterrev(ev
, _HE_OK
);
859 retval
= history_getsize(h
, ev
);
863 retval
= history_setsize(h
, ev
, va_arg(va
, int));
867 retval
= history_getunique(h
, ev
);
871 retval
= history_setunique(h
, ev
, va_arg(va
, int));
875 str
= va_arg(va
, const char *);
876 retval
= HADD(h
, ev
, str
);
880 retval
= HDEL(h
, ev
, va_arg(va
, const int));
884 str
= va_arg(va
, const char *);
885 if ((retval
= HENTER(h
, ev
, str
)) != -1)
890 str
= va_arg(va
, const char *);
891 if ((retval
= HSET(h
, ev
, h
->h_ent
)) != -1)
892 retval
= HADD(h
, ev
, str
);
896 retval
= HFIRST(h
, ev
);
900 retval
= HNEXT(h
, ev
);
904 retval
= HLAST(h
, ev
);
908 retval
= HPREV(h
, ev
);
912 retval
= HCURR(h
, ev
);
916 retval
= HSET(h
, ev
, va_arg(va
, const int));
925 retval
= history_load(h
, va_arg(va
, const char *));
927 he_seterrev(ev
, _HE_HIST_READ
);
931 retval
= history_save(h
, va_arg(va
, const char *));
933 he_seterrev(ev
, _HE_HIST_WRITE
);
937 retval
= history_prev_event(h
, ev
, va_arg(va
, int));
941 retval
= history_next_event(h
, ev
, va_arg(va
, int));
945 retval
= history_prev_string(h
, ev
, va_arg(va
, const char *));
949 retval
= history_next_string(h
, ev
, va_arg(va
, const char *));
956 hf
.h_ref
= va_arg(va
, ptr_t
);
958 hf
.h_first
= va_arg(va
, history_gfun_t
);
959 hf
.h_next
= va_arg(va
, history_gfun_t
);
960 hf
.h_last
= va_arg(va
, history_gfun_t
);
961 hf
.h_prev
= va_arg(va
, history_gfun_t
);
962 hf
.h_curr
= va_arg(va
, history_gfun_t
);
963 hf
.h_set
= va_arg(va
, history_sfun_t
);
964 hf
.h_clear
= va_arg(va
, history_vfun_t
);
965 hf
.h_enter
= va_arg(va
, history_efun_t
);
966 hf
.h_add
= va_arg(va
, history_efun_t
);
967 hf
.h_del
= va_arg(va
, history_sfun_t
);
969 if ((retval
= history_set_fun(h
, &hf
)) == -1)
970 he_seterrev(ev
, _HE_PARAM_MISSING
);
981 he_seterrev(ev
, _HE_UNKNOWN
);