summaryrefslogtreecommitdiffstats
path: root/lib/libedit/history.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2001-10-01 08:41:27 +0000
committerobrien <obrien@FreeBSD.org>2001-10-01 08:41:27 +0000
commit90300f853673b3879ab4d6a60683ff69b564c58b (patch)
treef9436ba88ca8f8420af319b0a12dd175381b507b /lib/libedit/history.c
parentf805e363ed51ace3356b37eb173c3d6435c35022 (diff)
downloadFreeBSD-src-90300f853673b3879ab4d6a60683ff69b564c58b.zip
FreeBSD-src-90300f853673b3879ab4d6a60683ff69b564c58b.tar.gz
+ Sync with NetBSD, bringing in feature enhancements.
+ Convert to ANSI-C function definitions + style(9) Submitted by: kris
Diffstat (limited to 'lib/libedit/history.c')
-rw-r--r--lib/libedit/history.c1062
1 files changed, 621 insertions, 441 deletions
diff --git a/lib/libedit/history.c b/lib/libedit/history.c
index 6579412..f0eff88 100644
--- a/lib/libedit/history.c
+++ b/lib/libedit/history.c
@@ -32,6 +32,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $NetBSD: history.c,v 1.16 2000/09/04 22:06:30 lukem Exp $
*/
#include <sys/cdefs.h>
@@ -39,6 +41,8 @@ __FBSDID("$FreeBSD$");
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/*
* hist.c: History access functions
@@ -47,53 +51,56 @@ static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#include <string.h>
#include <stdlib.h>
-#if __STDC__
#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
+#include <vis.h>
+#include <sys/stat.h>
-static const char hist_cookie[] = "_HiStOrY_V1_\n";
+static const char hist_cookie[] = "_HiStOrY_V2_\n";
#include "histedit.h"
-typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
-typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
-typedef void (*history_vfun_t) __P((ptr_t));
+typedef int (*history_gfun_t)(ptr_t, HistEvent *);
+typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
+typedef void (*history_vfun_t)(ptr_t, HistEvent *);
+typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
struct history {
- ptr_t h_ref; /* Argument for history fcns */
- history_gfun_t h_first; /* Get the first element */
- history_gfun_t h_next; /* Get the next element */
- history_gfun_t h_last; /* Get the last element */
- history_gfun_t h_prev; /* Get the previous element */
- history_gfun_t h_curr; /* Get the current element */
- history_vfun_t h_clear; /* Clear the history list */
- history_efun_t h_enter; /* Add an element */
- history_efun_t h_add; /* Append to an element */
+ ptr_t h_ref; /* Argument for history fcns */
+ int h_ent; /* Last entry point for history */
+ history_gfun_t h_first; /* Get the first element */
+ history_gfun_t h_next; /* Get the next element */
+ history_gfun_t h_last; /* Get the last element */
+ history_gfun_t h_prev; /* Get the previous element */
+ history_gfun_t h_curr; /* Get the current element */
+ history_sfun_t h_set; /* Set the current element */
+ history_vfun_t h_clear; /* Clear the history list */
+ history_efun_t h_enter; /* Add an element */
+ history_efun_t h_add; /* Append to an element */
};
-
-#define HNEXT(h) (*(h)->h_next)((h)->h_ref)
-#define HFIRST(h) (*(h)->h_first)((h)->h_ref)
-#define HPREV(h) (*(h)->h_prev)((h)->h_ref)
-#define HLAST(h) (*(h)->h_last)((h)->h_ref)
-#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
-#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref)
-#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
-#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
-
-#define h_malloc(a) malloc(a)
-#define h_free(a) free(a)
-
-
-private int history_set_num __P((History *, int));
-private int history_set_fun __P((History *, History *));
-private int history_load __P((History *, const char *));
-private int history_save __P((History *, const char *));
-private const HistEvent *history_prev_event __P((History *, int));
-private const HistEvent *history_next_event __P((History *, int));
-private const HistEvent *history_next_string __P((History *, const char *));
-private const HistEvent *history_prev_string __P((History *, const char *));
+#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
+#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
+#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
+#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
+#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
+#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
+#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
+#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
+#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
+
+#define h_malloc(a) malloc(a)
+#define h_realloc(a, b) realloc((a), (b))
+#define h_free(a) free(a)
+
+
+private int history_setsize(History *, HistEvent *, int);
+private int history_getsize(History *, HistEvent *);
+private int history_set_fun(History *, History *);
+private int history_load(History *, const char *);
+private int history_save(History *, const char *);
+private int history_prev_event(History *, HistEvent *, int);
+private int history_next_event(History *, HistEvent *, int);
+private int history_next_string(History *, HistEvent *, const char *);
+private int history_prev_string(History *, HistEvent *, const char *);
/***********************************************************************/
@@ -102,228 +109,332 @@ private const HistEvent *history_prev_string __P((History *, const char *));
* Builtin- history implementation
*/
typedef struct hentry_t {
- HistEvent ev; /* What we return */
- struct hentry_t *next; /* Next entry */
- struct hentry_t *prev; /* Previous entry */
-} hentry_t;
+ HistEvent ev; /* What we return */
+ struct hentry_t *next; /* Next entry */
+ struct hentry_t *prev; /* Previous entry */
+} hentry_t;
typedef struct history_t {
- hentry_t list; /* Fake list header element */
- hentry_t *cursor; /* Current element in the list */
- int max; /* Maximum number of events */
- int cur; /* Current number of events */
- int eventno; /* Current event number */
-} history_t;
-
-private const HistEvent *history_def_first __P((ptr_t));
-private const HistEvent *history_def_last __P((ptr_t));
-private const HistEvent *history_def_next __P((ptr_t));
-private const HistEvent *history_def_prev __P((ptr_t));
-private const HistEvent *history_def_curr __P((ptr_t));
-private const HistEvent *history_def_enter __P((ptr_t, const char *));
-private const HistEvent *history_def_add __P((ptr_t, const char *));
-private void history_def_init __P((ptr_t *, int));
-private void history_def_clear __P((ptr_t));
-private const HistEvent *history_def_insert __P((history_t *, const char *));
-private void history_def_delete __P((history_t *, hentry_t *));
-
-#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))
-
+ hentry_t list; /* Fake list header element */
+ hentry_t *cursor; /* Current element in the list */
+ int max; /* Maximum number of events */
+ int cur; /* Current number of events */
+ int eventid; /* For generation of unique event id */
+} history_t;
+
+private int history_def_first(ptr_t, HistEvent *);
+private int history_def_last(ptr_t, HistEvent *);
+private int history_def_next(ptr_t, HistEvent *);
+private int history_def_prev(ptr_t, HistEvent *);
+private int history_def_curr(ptr_t, HistEvent *);
+private int history_def_set(ptr_t, HistEvent *, const int n);
+private int history_def_enter(ptr_t, HistEvent *, const char *);
+private int history_def_add(ptr_t, HistEvent *, const char *);
+private void history_def_init(ptr_t *, HistEvent *, int);
+private void history_def_clear(ptr_t, HistEvent *);
+private int history_def_insert(history_t *, HistEvent *, const char *);
+private void history_def_delete(history_t *, HistEvent *, hentry_t *);
+
+#define history_def_setsize(p, num)(void) (((history_t *) p)->max = (num))
+#define history_def_getsize(p) (((history_t *) p)->cur)
+
+#define he_strerror(code) he_errlist[code]
+#define he_seterrev(evp, code) {\
+ evp->num = code;\
+ evp->str = he_strerror(code);\
+ }
+
+/* error messages */
+static const char *const he_errlist[] = {
+ "OK",
+ "unknown error",
+ "malloc() failed",
+ "first event not found",
+ "last event not found",
+ "empty list",
+ "no next event",
+ "no previous event",
+ "current event is invalid",
+ "event not found",
+ "can't read history from file",
+ "can't write history",
+ "required parameter(s) not supplied",
+ "history size negative",
+ "function not allowed with other history-functions-set the default",
+ "bad parameters"
+};
+/* error codes */
+#define _HE_OK 0
+#define _HE_UNKNOWN 1
+#define _HE_MALLOC_FAILED 2
+#define _HE_FIRST_NOTFOUND 3
+#define _HE_LAST_NOTFOUND 4
+#define _HE_EMPTY_LIST 5
+#define _HE_END_REACHED 6
+#define _HE_START_REACHED 7
+#define _HE_CURR_INVALID 8
+#define _HE_NOT_FOUND 9
+#define _HE_HIST_READ 10
+#define _HE_HIST_WRITE 11
+#define _HE_PARAM_MISSING 12
+#define _HE_SIZE_NEGATIVE 13
+#define _HE_NOT_ALLOWED 14
+#define _HE_BAD_PARAM 15
/* history_def_first():
* Default function to return the first event in the history.
*/
-private const HistEvent *
-history_def_first(p)
- ptr_t p;
+private int
+history_def_first(ptr_t p, HistEvent *ev)
{
- history_t *h = (history_t *) p;
- h->cursor = h->list.next;
- if (h->cursor != &h->list)
- return &h->cursor->ev;
- else
- return NULL;
+ history_t *h = (history_t *) p;
+
+ h->cursor = h->list.next;
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_FIRST_NOTFOUND);
+ return (-1);
+ }
+
+ return (0);
}
+
/* history_def_last():
* Default function to return the last event in the history.
*/
-private const HistEvent *
-history_def_last(p)
- ptr_t p;
+private int
+history_def_last(ptr_t p, HistEvent *ev)
{
- history_t *h = (history_t *) p;
- h->cursor = h->list.prev;
- if (h->cursor != &h->list)
- return &h->cursor->ev;
- else
- return NULL;
+ history_t *h = (history_t *) p;
+
+ h->cursor = h->list.prev;
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_LAST_NOTFOUND);
+ return (-1);
+ }
+
+ return (0);
}
+
/* history_def_next():
* Default function to return the next event in the history.
*/
-private const HistEvent *
-history_def_next(p)
- ptr_t p;
+private int
+history_def_next(ptr_t p, HistEvent *ev)
{
- history_t *h = (history_t *) p;
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ h->cursor = h->cursor->next;
+ else {
+ he_seterrev(ev, _HE_EMPTY_LIST);
+ return (-1);
+ }
- if (h->cursor != &h->list)
- h->cursor = h->cursor->next;
- else
- return NULL;
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_END_REACHED);
+ return (-1);
+ }
- if (h->cursor != &h->list)
- return &h->cursor->ev;
- else
- return NULL;
+ return (0);
}
/* history_def_prev():
* Default function to return the previous event in the history.
*/
-private const HistEvent *
-history_def_prev(p)
- ptr_t p;
+private int
+history_def_prev(ptr_t p, HistEvent *ev)
{
- history_t *h = (history_t *) p;
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ h->cursor = h->cursor->prev;
+ else {
+ he_seterrev(ev,
+ (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
+ return (-1);
+ }
- if (h->cursor != &h->list)
- h->cursor = h->cursor->prev;
- else
- return NULL;
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev, _HE_START_REACHED);
+ return (-1);
+ }
- if (h->cursor != &h->list)
- return &h->cursor->ev;
- else
- return NULL;
+ return (0);
}
/* history_def_curr():
* Default function to return the current event in the history.
*/
-private const HistEvent *
-history_def_curr(p)
- ptr_t p;
+private int
+history_def_curr(ptr_t p, HistEvent *ev)
+{
+ history_t *h = (history_t *) p;
+
+ if (h->cursor != &h->list)
+ *ev = h->cursor->ev;
+ else {
+ he_seterrev(ev,
+ (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
+ return (-1);
+ }
+
+ return (0);
+}
+
+
+/* history_def_set():
+ * Default function to set the current event in the history to the
+ * given one.
+ */
+private int
+history_def_set(ptr_t p, HistEvent *ev, const int n)
{
- history_t *h = (history_t *) p;
+ history_t *h = (history_t *) p;
- if (h->cursor != &h->list)
- return &h->cursor->ev;
- else
- return NULL;
+ if (h->cur == 0) {
+ he_seterrev(ev, _HE_EMPTY_LIST);
+ return (-1);
+ }
+ if (h->cursor == &h->list || h->cursor->ev.num != n) {
+ for (h->cursor = h->list.next; h->cursor != &h->list;
+ h->cursor = h->cursor->next)
+ if (h->cursor->ev.num == n)
+ break;
+ }
+ if (h->cursor == &h->list) {
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
+ }
+ return (0);
}
/* history_def_add():
* Append string to element
*/
-private const HistEvent *
-history_def_add(p, str)
- ptr_t p;
- const char *str;
+private int
+history_def_add(ptr_t p, HistEvent *ev, const char *str)
{
- history_t *h = (history_t *) p;
- size_t len;
- char *s;
-
- if (h->cursor == &h->list)
- return (history_def_enter(p, str));
- len = strlen(h->cursor->ev.str) + strlen(str) + 1;
- s = (char *) h_malloc(len);
- (void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */
- (void)strcat(s, str); /* XXX strcat is safe */
- h_free((ptr_t) h->cursor->ev.str);
- h->cursor->ev.str = s;
- return &h->cursor->ev;
+ history_t *h = (history_t *) p;
+ size_t len;
+ char *s;
+
+ if (h->cursor == &h->list)
+ return (history_def_enter(p, ev, str));
+ len = strlen(h->cursor->ev.str) + strlen(str) + 1;
+ s = (char *) h_malloc(len);
+ if (!s) {
+ he_seterrev(ev, _HE_MALLOC_FAILED);
+ return (-1);
+ }
+ (void) strlcpy(s, h->cursor->ev.str, len);
+ (void) strlcat(s, str, len);
+ /* LINTED const cast */
+ h_free((ptr_t) h->cursor->ev.str);
+ h->cursor->ev.str = s;
+ *ev = h->cursor->ev;
+ return (0);
}
/* history_def_delete():
* Delete element hp of the h list
*/
+/* ARGSUSED */
private void
-history_def_delete(h, hp)
- history_t *h;
- hentry_t *hp;
+history_def_delete(history_t *h, HistEvent *ev, hentry_t *hp)
{
- if (hp == &h->list)
- abort();
- hp->prev->next = hp->next;
- hp->next->prev = hp->prev;
- h_free((ptr_t) hp->ev.str);
- h_free(hp);
- h->cur--;
+
+ if (hp == &h->list)
+ abort();
+ hp->prev->next = hp->next;
+ hp->next->prev = hp->prev;
+ /* LINTED const cast */
+ h_free((ptr_t) hp->ev.str);
+ h_free(hp);
+ h->cur--;
}
/* history_def_insert():
* Insert element with string str in the h list
*/
-private const HistEvent *
-history_def_insert(h, str)
- history_t *h;
- const char *str;
+private int
+history_def_insert(history_t *h, HistEvent *ev, const char *str)
{
- h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
- h->cursor->ev.str = strdup(str);
- h->cursor->next = h->list.next;
- h->cursor->prev = &h->list;
- h->list.next->prev = h->cursor;
- h->list.next = h->cursor;
- h->cur++;
-
- return &h->cursor->ev;
+
+ h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
+ if (h->cursor)
+ h->cursor->ev.str = strdup(str);
+ if (!h->cursor || !h->cursor->ev.str) {
+ he_seterrev(ev, _HE_MALLOC_FAILED);
+ return (-1);
+ }
+ h->cursor->ev.num = ++h->eventid;
+ h->cursor->next = h->list.next;
+ h->cursor->prev = &h->list;
+ h->list.next->prev = h->cursor;
+ h->list.next = h->cursor;
+ h->cur++;
+
+ *ev = h->cursor->ev;
+ return (0);
}
/* history_def_enter():
* Default function to enter an item in the history
*/
-private const HistEvent *
-history_def_enter(p, str)
- ptr_t p;
- const char *str;
+private int
+history_def_enter(ptr_t p, HistEvent *ev, const char *str)
{
- history_t *h = (history_t *) p;
- const HistEvent *ev;
+ history_t *h = (history_t *) p;
+ if (history_def_insert(h, ev, str) == -1)
+ return (-1); /* error, keep error message */
- ev = history_def_insert(h, str);
- ((HistEvent*) ev)->num = ++h->eventno;
+ /*
+ * Always keep at least one entry.
+ * This way we don't have to check for the empty list.
+ */
+ while (h->cur - 1 > h->max)
+ history_def_delete(h, ev, h->list.prev);
- /*
- * Always keep at least one entry.
- * This way we don't have to check for the empty list.
- */
- while (h->cur > h->max + 1)
- history_def_delete(h, h->list.prev);
- return ev;
+ return (0);
}
/* history_def_init():
* Default history initialization function
*/
+/* ARGSUSED */
private void
-history_def_init(p, n)
- ptr_t *p;
- int n;
+history_def_init(ptr_t *p, HistEvent *ev, int n)
{
- history_t *h = (history_t *) h_malloc(sizeof(history_t));
- if (n <= 0)
- n = 0;
- h->eventno = 0;
- h->cur = 0;
- h->max = n;
- h->list.next = h->list.prev = &h->list;
- h->list.ev.str = NULL;
- h->list.ev.num = 0;
- h->cursor = &h->list;
- *p = (ptr_t) h;
+ history_t *h = (history_t *) h_malloc(sizeof(history_t));
+
+ if (n <= 0)
+ n = 0;
+ h->eventid = 0;
+ h->cur = 0;
+ h->max = n;
+ h->list.next = h->list.prev = &h->list;
+ h->list.ev.str = NULL;
+ h->list.ev.num = 0;
+ h->cursor = &h->list;
+ *p = (ptr_t) h;
}
@@ -331,39 +442,43 @@ history_def_init(p, n)
* Default history cleanup function
*/
private void
-history_def_clear(p)
- ptr_t p;
+history_def_clear(ptr_t p, HistEvent *ev)
{
- history_t *h = (history_t *) p;
+ history_t *h = (history_t *) p;
- while (h->list.prev != &h->list)
- history_def_delete(h, h->list.prev);
- h->eventno = 0;
- h->cur = 0;
+ while (h->list.prev != &h->list)
+ history_def_delete(h, ev, h->list.prev);
+ h->eventid = 0;
+ h->cur = 0;
}
+
+
+
/************************************************************************/
/* history_init():
* Initialization function.
*/
public History *
-history_init()
+history_init(void)
{
- History *h = (History *) h_malloc(sizeof(History));
-
- history_def_init(&h->h_ref, 0);
-
- h->h_next = history_def_next;
- h->h_first = history_def_first;
- h->h_last = history_def_last;
- h->h_prev = history_def_prev;
- h->h_curr = history_def_curr;
- h->h_clear = history_def_clear;
- h->h_enter = history_def_enter;
- h->h_add = history_def_add;
-
- return h;
+ History *h = (History *) h_malloc(sizeof(History));
+ HistEvent ev;
+
+ history_def_init(&h->h_ref, &ev, 0);
+ h->h_ent = -1;
+ h->h_next = history_def_next;
+ h->h_first = history_def_first;
+ h->h_last = history_def_last;
+ h->h_prev = history_def_prev;
+ h->h_curr = history_def_curr;
+ h->h_set = history_def_set;
+ h->h_clear = history_def_clear;
+ h->h_enter = history_def_enter;
+ h->h_add = history_def_add;
+
+ return (h);
}
@@ -371,27 +486,55 @@ history_init()
* clean up history;
*/
public void
-history_end(h)
- History *h;
+history_end(History *h)
{
- if (h->h_next == history_def_next)
- history_def_clear(h->h_ref);
+ HistEvent ev;
+
+ if (h->h_next == history_def_next)
+ history_def_clear(h->h_ref, &ev);
}
-/* history_set_num():
+/* history_setsize():
* Set history number of events
*/
private int
-history_set_num(h, num)
- History *h;
- int num;
+history_setsize(History *h, HistEvent *ev, int num)
+{
+
+ if (h->h_next != history_def_next) {
+ he_seterrev(ev, _HE_NOT_ALLOWED);
+ return (-1);
+ }
+ if (num < 0) {
+ he_seterrev(ev, _HE_BAD_PARAM);
+ return (-1);
+ }
+ history_def_setsize(h->h_ref, num);
+ return (0);
+}
+
+
+/* history_getsize():
+ * Get number of events currently in history
+ */
+private int
+history_getsize(History *h, HistEvent *ev)
{
- if (h->h_next != history_def_next || num < 0)
- return -1;
- history_def_set(h->h_ref, num);
- return 0;
+ int retval = 0;
+
+ if (h->h_next != history_def_next) {
+ he_seterrev(ev, _HE_NOT_ALLOWED);
+ return (-1);
+ }
+ retval = history_def_getsize(h->h_ref);
+ if (retval < -1) {
+ he_seterrev(ev, _HE_SIZE_NEGATIVE);
+ return (-1);
+ }
+ ev->num = retval;
+ return (0);
}
@@ -399,39 +542,43 @@ history_set_num(h, num)
* Set history functions
*/
private int
-history_set_fun(h, nh)
- History *h, *nh;
+history_set_fun(History *h, History *nh)
{
- if (nh->h_first == NULL || nh->h_next == NULL ||
- nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL ||
- nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
- nh->h_ref == NULL) {
- if (h->h_next != history_def_next) {
- history_def_init(&h->h_ref, 0);
- h->h_first = history_def_first;
- h->h_next = history_def_next;
- h->h_last = history_def_last;
- h->h_prev = history_def_prev;
- h->h_curr = history_def_curr;
- h->h_clear = history_def_clear;
- h->h_enter = history_def_enter;
- h->h_add = history_def_add;
+ HistEvent ev;
+
+ if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
+ nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
+ nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
+ nh->h_ref == NULL) {
+ if (h->h_next != history_def_next) {
+ history_def_init(&h->h_ref, &ev, 0);
+ h->h_first = history_def_first;
+ h->h_next = history_def_next;
+ h->h_last = history_def_last;
+ h->h_prev = history_def_prev;
+ h->h_curr = history_def_curr;
+ h->h_set = history_def_set;
+ h->h_clear = history_def_clear;
+ h->h_enter = history_def_enter;
+ h->h_add = history_def_add;
+ }
+ return (-1);
}
- return -1;
- }
-
- if (h->h_next == history_def_next)
- history_def_clear(h->h_ref);
-
- h->h_first = nh->h_first;
- h->h_next = nh->h_next;
- h->h_last = nh->h_last;
- h->h_prev = nh->h_prev;
- h->h_curr = nh->h_curr;
- h->h_clear = nh->h_clear;
- h->h_enter = nh->h_enter;
- h->h_add = nh->h_add;
- return 0;
+ if (h->h_next == history_def_next)
+ history_def_clear(h->h_ref, &ev);
+
+ h->h_ent = -1;
+ h->h_first = nh->h_first;
+ h->h_next = nh->h_next;
+ h->h_last = nh->h_last;
+ h->h_prev = nh->h_prev;
+ h->h_curr = nh->h_curr;
+ h->h_set = nh->h_set;
+ h->h_clear = nh->h_clear;
+ h->h_enter = nh->h_enter;
+ h->h_add = nh->h_add;
+
+ return (0);
}
@@ -439,34 +586,46 @@ history_set_fun(h, nh)
* History load function
*/
private int
-history_load(h, fname)
- History *h;
- const char *fname;
+history_load(History *h, const char *fname)
{
- FILE *fp;
- char *line;
- size_t sz;
- int i = -1;
-
- if ((fp = fopen(fname, "r")) == NULL)
- return i;
-
- if ((line = fgetln(fp, &sz)) == NULL)
- goto done;
-
- if (strncmp(line, hist_cookie, sz) != 0)
- goto done;
-
- for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
- char c = line[sz];
- line[sz] = '\0';
- HENTER(h, line);
- line[sz] = c;
- }
+ FILE *fp;
+ char *line;
+ size_t sz, max_size;
+ char *ptr;
+ int i = -1;
+ HistEvent ev;
+
+ if ((fp = fopen(fname, "r")) == NULL)
+ return (i);
+
+ if ((line = fgetln(fp, &sz)) == NULL)
+ goto done;
+
+ if (strncmp(line, hist_cookie, sz) != 0)
+ goto done;
+
+ ptr = h_malloc(max_size = 1024);
+ for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
+ char c = line[sz];
+
+ if (sz != 0 && line[sz - 1] == '\n')
+ line[--sz] = '\0';
+ else
+ line[sz] = '\0';
+
+ if (max_size < sz) {
+ max_size = (sz + 1023) & ~1023;
+ ptr = h_realloc(ptr, max_size);
+ }
+ (void) strunvis(ptr, line);
+ line[sz] = c;
+ HENTER(h, &ev, ptr);
+ }
+ h_free(ptr);
done:
- (void) fclose(fp);
- return i;
+ (void) fclose(fp);
+ return (i);
}
@@ -474,214 +633,235 @@ done:
* History save function
*/
private int
-history_save(h, fname)
- History *h;
- const char *fname;
+history_save(History *h, const char *fname)
{
- FILE *fp;
- const HistEvent *ev;
- int i = 0;
-
- if ((fp = fopen(fname, "w")) == NULL)
- return -1;
-
- (void) fputs(hist_cookie, fp);
- for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++)
- (void) fprintf(fp, "%s", ev->str);
- (void) fclose(fp);
- return i;
+ FILE *fp;
+ HistEvent ev;
+ int i = 0, retval;
+ size_t len, max_size;
+ char *ptr;
+
+ if ((fp = fopen(fname, "w")) == NULL)
+ return (-1);
+
+ (void) fchmod(fileno(fp), S_IRUSR|S_IWUSR);
+ (void) fputs(hist_cookie, fp);
+ ptr = h_malloc(max_size = 1024);
+ for (retval = HLAST(h, &ev);
+ retval != -1;
+ retval = HPREV(h, &ev), i++) {
+ len = strlen(ev.str) * 4;
+ if (len >= max_size) {
+ max_size = (len + 1023) & 1023;
+ ptr = h_realloc(ptr, max_size);
+ }
+ (void) strvis(ptr, ev.str, VIS_WHITE);
+ (void) fprintf(fp, "%s\n", ev.str);
+ }
+ h_free(ptr);
+ (void) fclose(fp);
+ return (i);
}
/* history_prev_event():
* Find the previous event, with number given
*/
-private const HistEvent *
-history_prev_event(h, num)
- History *h;
- int num;
+private int
+history_prev_event(History *h, HistEvent *ev, int num)
{
- const HistEvent *ev;
- for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
- if (ev->num == num)
- return ev;
- return NULL;
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+ if (ev->num == num)
+ return (0);
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
}
/* history_next_event():
* Find the next event, with number given
*/
-private const HistEvent *
-history_next_event(h, num)
- History *h;
- int num;
+private int
+history_next_event(History *h, HistEvent *ev, int num)
{
- const HistEvent *ev;
- for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
- if (ev->num == num)
- return ev;
- return NULL;
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+ if (ev->num == num)
+ return (0);
+
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
}
/* history_prev_string():
* Find the previous event beginning with string
*/
-private const HistEvent *
-history_prev_string(h, str)
- History *h;
- const char* str;
+private int
+history_prev_string(History *h, HistEvent *ev, const char *str)
{
- const HistEvent *ev;
- size_t len = strlen(str);
+ size_t len = strlen(str);
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+ if (strncmp(str, ev->str, len) == 0)
+ return (0);
- for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
- if (strncmp(str, ev->str, len) == 0)
- return ev;
- return NULL;
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
}
/* history_next_string():
* Find the next event beginning with string
*/
-private const HistEvent *
-history_next_string(h, str)
- History *h;
- const char* str;
+private int
+history_next_string(History *h, HistEvent *ev, const char *str)
{
- const HistEvent *ev;
- size_t len = strlen(str);
+ size_t len = strlen(str);
+ int retval;
+
+ for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+ if (strncmp(str, ev->str, len) == 0)
+ return (0);
- for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
- if (strncmp(str, ev->str, len) == 0)
- return ev;
- return NULL;
+ he_seterrev(ev, _HE_NOT_FOUND);
+ return (-1);
}
/* history():
* User interface to history functions.
*/
-const HistEvent *
-#if __STDC__
-history(History *h, int fun, ...)
-#else
-history(va_alist)
- va_dcl
-#endif
+int
+history(History *h, HistEvent *ev, int fun, ...)
{
- va_list va;
- const HistEvent *ev = NULL;
- const char *str;
- static HistEvent sev = { 0, "" };
-
-#if __STDC__
- va_start(va, fun);
-#else
- History *h;
- int fun;
- va_start(va);
- h = va_arg(va, History *);
- fun = va_arg(va, int);
-#endif
-
- switch (fun) {
- case H_ADD:
- str = va_arg(va, const char *);
- ev = HADD(h, str);
- break;
-
- case H_ENTER:
- str = va_arg(va, const char *);
- ev = HENTER(h, str);
- break;
-
- case H_FIRST:
- ev = HFIRST(h);
- break;
-
- case H_NEXT:
- ev = HNEXT(h);
- break;
-
- case H_LAST:
- ev = HLAST(h);
- break;
-
- case H_PREV:
- ev = HPREV(h);
- break;
-
- case H_CURR:
- ev = HCURR(h);
- break;
-
- case H_CLEAR:
- HCLEAR(h);
- break;
-
- case H_LOAD:
- sev.num = history_load(h, va_arg(va, const char *));
- ev = &sev;
- break;
-
- case H_SAVE:
- sev.num = history_save(h, va_arg(va, const char *));
- ev = &sev;
- break;
-
- case H_PREV_EVENT:
- ev = history_prev_event(h, va_arg(va, int));
- break;
-
- case H_NEXT_EVENT:
- ev = history_next_event(h, va_arg(va, int));
- break;
-
- case H_PREV_STR:
- ev = history_prev_string(h, va_arg(va, const char*));
- break;
-
- case H_NEXT_STR:
- ev = history_next_string(h, va_arg(va, const char*));
- break;
-
- case H_EVENT:
- if (history_set_num(h, va_arg(va, int)) == 0) {
- sev.num = -1;
- ev = &sev;
- }
- break;
-
- case H_FUNC:
+ va_list va;
+ const char *str;
+ int retval;
+
+ va_start(va, fun);
+
+ he_seterrev(ev, _HE_OK);
+
+ switch (fun) {
+ case H_GETSIZE:
+ retval = history_getsize(h, ev);
+ break;
+
+ case H_SETSIZE:
+ retval = history_setsize(h, ev, va_arg(va, int));
+ break;
+
+ case H_ADD:
+ str = va_arg(va, const char *);
+ retval = HADD(h, ev, str);
+ break;
+
+ case H_ENTER:
+ str = va_arg(va, const char *);
+ if ((retval = HENTER(h, ev, str)) != -1)
+ h->h_ent = ev->num;
+ break;
+
+ case H_APPEND:
+ str = va_arg(va, const char *);
+ if ((retval = HSET(h, ev, h->h_ent)) != -1)
+ retval = HADD(h, ev, str);
+ break;
+
+ case H_FIRST:
+ retval = HFIRST(h, ev);
+ break;
+
+ case H_NEXT:
+ retval = HNEXT(h, ev);
+ break;
+
+ case H_LAST:
+ retval = HLAST(h, ev);
+ break;
+
+ case H_PREV:
+ retval = HPREV(h, ev);
+ break;
+
+ case H_CURR:
+ retval = HCURR(h, ev);
+ break;
+
+ case H_SET:
+ retval = HSET(h, ev, va_arg(va, const int));
+ break;
+
+ case H_CLEAR:
+ HCLEAR(h, ev);
+ retval = 0;
+ break;
+
+ case H_LOAD:
+ retval = history_load(h, va_arg(va, const char *));
+ if (retval == -1)
+ he_seterrev(ev, _HE_HIST_READ);
+ break;
+
+ case H_SAVE:
+ retval = history_save(h, va_arg(va, const char *));
+ if (retval == -1)
+ he_seterrev(ev, _HE_HIST_WRITE);
+ break;
+
+ case H_PREV_EVENT:
+ retval = history_prev_event(h, ev, va_arg(va, int));
+ break;
+
+ case H_NEXT_EVENT:
+ retval = history_next_event(h, ev, va_arg(va, int));
+ break;
+
+ case H_PREV_STR:
+ retval = history_prev_string(h, ev, va_arg(va, const char *));
+ break;
+
+ case H_NEXT_STR:
+ retval = history_next_string(h, ev, va_arg(va, const char *));
+ break;
+
+ case H_FUNC:
{
- History hf;
- hf.h_ref = va_arg(va, ptr_t);
- hf.h_first = va_arg(va, history_gfun_t);
- hf.h_next = va_arg(va, history_gfun_t);
- hf.h_last = va_arg(va, history_gfun_t);
- hf.h_prev = va_arg(va, history_gfun_t);
- hf.h_curr = va_arg(va, history_gfun_t);
- hf.h_clear = va_arg(va, history_vfun_t);
- hf.h_enter = va_arg(va, history_efun_t);
- hf.h_add = va_arg(va, history_efun_t);
-
- if (history_set_fun(h, &hf) == 0) {
- sev.num = -1;
- ev = &sev;
- }
+ History hf;
+
+ hf.h_ref = va_arg(va, ptr_t);
+ h->h_ent = -1;
+ hf.h_first = va_arg(va, history_gfun_t);
+ hf.h_next = va_arg(va, history_gfun_t);
+ hf.h_last = va_arg(va, history_gfun_t);
+ hf.h_prev = va_arg(va, history_gfun_t);
+ hf.h_curr = va_arg(va, history_gfun_t);
+ hf.h_set = va_arg(va, history_sfun_t);
+ hf.h_clear = va_arg(va, history_vfun_t);
+ hf.h_enter = va_arg(va, history_efun_t);
+ hf.h_add = va_arg(va, history_efun_t);
+
+ if ((retval = history_set_fun(h, &hf)) == -1)
+ he_seterrev(ev, _HE_PARAM_MISSING);
+ break;
}
- break;
- case H_END:
- history_end(h);
- break;
+ case H_END:
+ history_end(h);
+ retval = 0;
+ break;
- default:
- break;
- }
- va_end(va);
- return ev;
+ default:
+ retval = -1;
+ he_seterrev(ev, _HE_UNKNOWN);
+ break;
+ }
+ va_end(va);
+ return (retval);
}
OpenPOWER on IntegriCloud