Updated libedit to NetBSD upstream
Note: This unconditionally assumes wchar_t support. May need revision if some platforms prove problematic.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: history.c,v 1.38 2011/01/16 03:05:51 christos Exp $ */
|
||||
/* $NetBSD: history.c,v 1.57 2016/04/11 18:56:31 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@@ -32,39 +32,72 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NARROWCHAR
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if !defined(lint) && !defined(SCCSID)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: history.c,v 1.38 2011/01/16 03:05:51 christos Exp $");
|
||||
__RCSID("$NetBSD: history.c,v 1.57 2016/04/11 18:56:31 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint && not SCCSID */
|
||||
|
||||
/*
|
||||
* hist.c: TYPE(History) access functions
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <vis.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vis.h>
|
||||
|
||||
static const char hist_cookie[] = "_HiStOrY_V2_\n";
|
||||
|
||||
#include "histedit.h"
|
||||
|
||||
|
||||
#ifdef NARROWCHAR
|
||||
|
||||
#define Char char
|
||||
#define FUN(prefix, rest) prefix ## _ ## rest
|
||||
#define FUNW(type) type
|
||||
#define TYPE(type) type
|
||||
#define STR(x) x
|
||||
|
||||
#define Strlen(s) strlen(s)
|
||||
#define Strdup(s) strdup(s)
|
||||
#define Strcmp(d, s) strcmp(d, s)
|
||||
#define Strncmp(d, s, n) strncmp(d, s, n)
|
||||
#define Strncpy(d, s, n) strncpy(d, s, n)
|
||||
#define Strncat(d, s, n) strncat(d, s, n)
|
||||
#define ct_decode_string(s, b) (s)
|
||||
#define ct_encode_string(s, b) (s)
|
||||
|
||||
#else
|
||||
#include "chartype.h"
|
||||
|
||||
typedef int (*history_gfun_t)(ptr_t, TYPE(HistEvent) *);
|
||||
typedef int (*history_efun_t)(ptr_t, TYPE(HistEvent) *, const Char *);
|
||||
typedef void (*history_vfun_t)(ptr_t, TYPE(HistEvent) *);
|
||||
typedef int (*history_sfun_t)(ptr_t, TYPE(HistEvent) *, const int);
|
||||
#define Char wchar_t
|
||||
#define FUN(prefix, rest) prefix ## _w ## rest
|
||||
#define FUNW(type) type ## _w
|
||||
#define TYPE(type) type ## W
|
||||
#define STR(x) L ## x
|
||||
|
||||
#define Strlen(s) wcslen(s)
|
||||
#define Strdup(s) wcsdup(s)
|
||||
#define Strcmp(d, s) wcscmp(d, s)
|
||||
#define Strncmp(d, s, n) wcsncmp(d, s, n)
|
||||
#define Strncpy(d, s, n) wcsncpy(d, s, n)
|
||||
#define Strncat(d, s, n) wcsncat(d, s, n)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
|
||||
typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
|
||||
typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
|
||||
typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
|
||||
|
||||
struct TYPE(history) {
|
||||
ptr_t h_ref; /* Argument for history fcns */
|
||||
void *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 */
|
||||
@@ -100,18 +133,20 @@ typedef struct {
|
||||
} HistEventPrivate;
|
||||
|
||||
|
||||
|
||||
private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
|
||||
private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
|
||||
private int history_set_fun(TYPE(History) *, TYPE(History) *);
|
||||
private int history_load(TYPE(History) *, const char *);
|
||||
private int history_save(TYPE(History) *, const char *);
|
||||
private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
|
||||
private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
|
||||
static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
static int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
|
||||
static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
static int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
|
||||
static int history_set_fun(TYPE(History) *, TYPE(History) *);
|
||||
static int history_load(TYPE(History) *, const char *);
|
||||
static int history_save(TYPE(History) *, const char *);
|
||||
static int history_save_fp(TYPE(History) *, FILE *);
|
||||
static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
|
||||
static int history_next_string(TYPE(History) *, TYPE(HistEvent) *,
|
||||
const Char *);
|
||||
static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *,
|
||||
const Char *);
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -136,23 +171,23 @@ typedef struct history_t {
|
||||
#define H_UNIQUE 1 /* Store only unique elements */
|
||||
} history_t;
|
||||
|
||||
private int history_def_next(ptr_t, TYPE(HistEvent) *);
|
||||
private int history_def_first(ptr_t, TYPE(HistEvent) *);
|
||||
private int history_def_prev(ptr_t, TYPE(HistEvent) *);
|
||||
private int history_def_last(ptr_t, TYPE(HistEvent) *);
|
||||
private int history_def_curr(ptr_t, TYPE(HistEvent) *);
|
||||
private int history_def_set(ptr_t, TYPE(HistEvent) *, const int);
|
||||
private void history_def_clear(ptr_t, TYPE(HistEvent) *);
|
||||
private int history_def_enter(ptr_t, TYPE(HistEvent) *, const Char *);
|
||||
private int history_def_add(ptr_t, TYPE(HistEvent) *, const Char *);
|
||||
private int history_def_del(ptr_t, TYPE(HistEvent) *, const int);
|
||||
static int history_def_next(void *, TYPE(HistEvent) *);
|
||||
static int history_def_first(void *, TYPE(HistEvent) *);
|
||||
static int history_def_prev(void *, TYPE(HistEvent) *);
|
||||
static int history_def_last(void *, TYPE(HistEvent) *);
|
||||
static int history_def_curr(void *, TYPE(HistEvent) *);
|
||||
static int history_def_set(void *, TYPE(HistEvent) *, const int);
|
||||
static void history_def_clear(void *, TYPE(HistEvent) *);
|
||||
static int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
|
||||
static int history_def_add(void *, TYPE(HistEvent) *, const Char *);
|
||||
static int history_def_del(void *, TYPE(HistEvent) *, const int);
|
||||
|
||||
private int history_def_init(ptr_t *, TYPE(HistEvent) *, int);
|
||||
private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
|
||||
private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
|
||||
static int history_def_init(void **, TYPE(HistEvent) *, int);
|
||||
static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
|
||||
static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
|
||||
|
||||
private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
|
||||
private int history_set_nth(ptr_t, TYPE(HistEvent) *, int);
|
||||
static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
|
||||
static int history_set_nth(void *, TYPE(HistEvent) *, int);
|
||||
|
||||
#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
|
||||
#define history_def_getsize(p) (((history_t *)p)->cur)
|
||||
@@ -209,8 +244,8 @@ static const Char *const he_errlist[] = {
|
||||
/* history_def_first():
|
||||
* Default function to return the first event in the history.
|
||||
*/
|
||||
private int
|
||||
history_def_first(ptr_t p, TYPE(HistEvent) *ev)
|
||||
static int
|
||||
history_def_first(void *p, TYPE(HistEvent) *ev)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
@@ -219,18 +254,18 @@ history_def_first(ptr_t p, TYPE(HistEvent) *ev)
|
||||
*ev = h->cursor->ev;
|
||||
else {
|
||||
he_seterrev(ev, _HE_FIRST_NOTFOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_def_last():
|
||||
* Default function to return the last event in the history.
|
||||
*/
|
||||
private int
|
||||
history_def_last(ptr_t p, TYPE(HistEvent) *ev)
|
||||
static int
|
||||
history_def_last(void *p, TYPE(HistEvent) *ev)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
@@ -239,69 +274,69 @@ history_def_last(ptr_t p, TYPE(HistEvent) *ev)
|
||||
*ev = h->cursor->ev;
|
||||
else {
|
||||
he_seterrev(ev, _HE_LAST_NOTFOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_def_next():
|
||||
* Default function to return the next event in the history.
|
||||
*/
|
||||
private int
|
||||
history_def_next(ptr_t p, TYPE(HistEvent) *ev)
|
||||
static int
|
||||
history_def_next(void *p, TYPE(HistEvent) *ev)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
if (h->cursor == &h->list) {
|
||||
he_seterrev(ev, _HE_EMPTY_LIST);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->cursor->next == &h->list) {
|
||||
he_seterrev(ev, _HE_END_REACHED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
h->cursor = h->cursor->next;
|
||||
*ev = h->cursor->ev;
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_def_prev():
|
||||
* Default function to return the previous event in the history.
|
||||
*/
|
||||
private int
|
||||
history_def_prev(ptr_t p, TYPE(HistEvent) *ev)
|
||||
static int
|
||||
history_def_prev(void *p, TYPE(HistEvent) *ev)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
if (h->cursor == &h->list) {
|
||||
he_seterrev(ev,
|
||||
(h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->cursor->prev == &h->list) {
|
||||
he_seterrev(ev, _HE_START_REACHED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
h->cursor = h->cursor->prev;
|
||||
*ev = h->cursor->ev;
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_def_curr():
|
||||
* Default function to return the current event in the history.
|
||||
*/
|
||||
private int
|
||||
history_def_curr(ptr_t p, TYPE(HistEvent) *ev)
|
||||
static int
|
||||
history_def_curr(void *p, TYPE(HistEvent) *ev)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
@@ -310,10 +345,10 @@ history_def_curr(ptr_t p, TYPE(HistEvent) *ev)
|
||||
else {
|
||||
he_seterrev(ev,
|
||||
(h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -321,14 +356,14 @@ history_def_curr(ptr_t p, TYPE(HistEvent) *ev)
|
||||
* Default function to set the current event in the history to the
|
||||
* given one.
|
||||
*/
|
||||
private int
|
||||
history_def_set(ptr_t p, TYPE(HistEvent) *ev, const int n)
|
||||
static int
|
||||
history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
if (h->cur == 0) {
|
||||
he_seterrev(ev, _HE_EMPTY_LIST);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
if (h->cursor == &h->list || h->cursor->ev.num != n) {
|
||||
for (h->cursor = h->list.next; h->cursor != &h->list;
|
||||
@@ -338,9 +373,9 @@ history_def_set(ptr_t p, TYPE(HistEvent) *ev, const int n)
|
||||
}
|
||||
if (h->cursor == &h->list) {
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -348,14 +383,14 @@ history_def_set(ptr_t p, TYPE(HistEvent) *ev, const int n)
|
||||
* Default function to set the current event in the history to the
|
||||
* n-th one.
|
||||
*/
|
||||
private int
|
||||
history_set_nth(ptr_t p, TYPE(HistEvent) *ev, int n)
|
||||
static int
|
||||
history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
if (h->cur == 0) {
|
||||
he_seterrev(ev, _HE_EMPTY_LIST);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
for (h->cursor = h->list.prev; h->cursor != &h->list;
|
||||
h->cursor = h->cursor->prev)
|
||||
@@ -363,17 +398,17 @@ history_set_nth(ptr_t p, TYPE(HistEvent) *ev, int n)
|
||||
break;
|
||||
if (h->cursor == &h->list) {
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_def_add():
|
||||
* Append string to element
|
||||
*/
|
||||
private int
|
||||
history_def_add(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
|
||||
static int
|
||||
history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
size_t len;
|
||||
@@ -381,38 +416,38 @@ history_def_add(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
|
||||
HistEventPrivate *evp = (void *)&h->cursor->ev;
|
||||
|
||||
if (h->cursor == &h->list)
|
||||
return (history_def_enter(p, ev, str));
|
||||
return history_def_enter(p, ev, str);
|
||||
len = Strlen(evp->str) + Strlen(str) + 1;
|
||||
s = h_malloc(len * sizeof(*s));
|
||||
if (s == NULL) {
|
||||
he_seterrev(ev, _HE_MALLOC_FAILED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
(void) Strncpy(s, h->cursor->ev.str, len);
|
||||
s[len - 1] = '\0';
|
||||
(void) Strncat(s, str, len - Strlen(s) - 1);
|
||||
h_free((ptr_t)evp->str);
|
||||
h_free(evp->str);
|
||||
evp->str = s;
|
||||
*ev = h->cursor->ev;
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private int
|
||||
static int
|
||||
history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
|
||||
int num, void **data)
|
||||
{
|
||||
if (history_set_nth(h, ev, num) != 0)
|
||||
return (-1);
|
||||
return -1;
|
||||
/* magic value to skip delete (just set to n-th history) */
|
||||
if (data == (void **)-1)
|
||||
return (0);
|
||||
return 0;
|
||||
ev->str = Strdup(h->cursor->ev.str);
|
||||
ev->num = h->cursor->ev.num;
|
||||
if (data)
|
||||
*data = h->cursor->data;
|
||||
history_def_delete(h, ev, h->cursor);
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,17 +455,17 @@ history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
|
||||
* Delete element hp of the h list
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
private int
|
||||
history_def_del(ptr_t p, TYPE(HistEvent) *ev __attribute__((__unused__)),
|
||||
static int
|
||||
history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
|
||||
const int num)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
if (history_def_set(h, ev, num) != 0)
|
||||
return (-1);
|
||||
return -1;
|
||||
ev->str = Strdup(h->cursor->ev.str);
|
||||
ev->num = h->cursor->ev.num;
|
||||
history_def_delete(h, ev, h->cursor);
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +473,7 @@ history_def_del(ptr_t p, TYPE(HistEvent) *ev __attribute__((__unused__)),
|
||||
* Delete element hp of the h list
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
private void
|
||||
static void
|
||||
history_def_delete(history_t *h,
|
||||
TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
|
||||
{
|
||||
@@ -452,7 +487,7 @@ history_def_delete(history_t *h,
|
||||
}
|
||||
hp->prev->next = hp->next;
|
||||
hp->next->prev = hp->prev;
|
||||
h_free((ptr_t) evp->str);
|
||||
h_free(evp->str);
|
||||
h_free(hp);
|
||||
h->cur--;
|
||||
}
|
||||
@@ -461,47 +496,49 @@ history_def_delete(history_t *h,
|
||||
/* history_def_insert():
|
||||
* Insert element with string str in the h list
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
|
||||
{
|
||||
hentry_t *c;
|
||||
|
||||
h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
|
||||
if (h->cursor == NULL)
|
||||
c = h_malloc(sizeof(*c));
|
||||
if (c == NULL)
|
||||
goto oomem;
|
||||
if ((h->cursor->ev.str = h_strdup(str)) == NULL) {
|
||||
h_free((ptr_t)h->cursor);
|
||||
if ((c->ev.str = h_strdup(str)) == NULL) {
|
||||
h_free(c);
|
||||
goto oomem;
|
||||
}
|
||||
h->cursor->data = NULL;
|
||||
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;
|
||||
c->data = NULL;
|
||||
c->ev.num = ++h->eventid;
|
||||
c->next = h->list.next;
|
||||
c->prev = &h->list;
|
||||
h->list.next->prev = c;
|
||||
h->list.next = c;
|
||||
h->cur++;
|
||||
h->cursor = c;
|
||||
|
||||
*ev = h->cursor->ev;
|
||||
return (0);
|
||||
*ev = c->ev;
|
||||
return 0;
|
||||
oomem:
|
||||
he_seterrev(ev, _HE_MALLOC_FAILED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* history_def_enter():
|
||||
* Default function to enter an item in the history
|
||||
*/
|
||||
private int
|
||||
history_def_enter(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
|
||||
static int
|
||||
history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
|
||||
Strcmp(h->list.next->ev.str, str) == 0)
|
||||
return (0);
|
||||
return 0;
|
||||
|
||||
if (history_def_insert(h, ev, str) == -1)
|
||||
return (-1); /* error, keep error message */
|
||||
return -1; /* error, keep error message */
|
||||
|
||||
/*
|
||||
* Always keep at least one entry.
|
||||
@@ -510,7 +547,7 @@ history_def_enter(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
|
||||
while (h->cur > h->max && h->cur > 0)
|
||||
history_def_delete(h, ev, h->list.prev);
|
||||
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,10 +555,10 @@ history_def_enter(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
|
||||
* Default history initialization function
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
private int
|
||||
history_def_init(ptr_t *p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
|
||||
static int
|
||||
history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
|
||||
{
|
||||
history_t *h = (history_t *) h_malloc(sizeof(history_t));
|
||||
history_t *h = (history_t *) h_malloc(sizeof(*h));
|
||||
if (h == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -535,7 +572,7 @@ history_def_init(ptr_t *p, TYPE(HistEvent) *ev __attribute__((__unused__)), int
|
||||
h->list.ev.num = 0;
|
||||
h->cursor = &h->list;
|
||||
h->flags = 0;
|
||||
*p = (ptr_t) h;
|
||||
*p = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -543,13 +580,14 @@ history_def_init(ptr_t *p, TYPE(HistEvent) *ev __attribute__((__unused__)), int
|
||||
/* history_def_clear():
|
||||
* Default history cleanup function
|
||||
*/
|
||||
private void
|
||||
history_def_clear(ptr_t p, TYPE(HistEvent) *ev)
|
||||
static void
|
||||
history_def_clear(void *p, TYPE(HistEvent) *ev)
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
while (h->list.prev != &h->list)
|
||||
history_def_delete(h, ev, h->list.prev);
|
||||
h->cursor = &h->list;
|
||||
h->eventid = 0;
|
||||
h->cur = 0;
|
||||
}
|
||||
@@ -562,16 +600,16 @@ history_def_clear(ptr_t p, TYPE(HistEvent) *ev)
|
||||
/* history_init():
|
||||
* Initialization function.
|
||||
*/
|
||||
public TYPE(History) *
|
||||
TYPE(History) *
|
||||
FUN(history,init)(void)
|
||||
{
|
||||
TYPE(HistEvent) ev;
|
||||
TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(TYPE(History)));
|
||||
TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
|
||||
if (h == NULL)
|
||||
return NULL;
|
||||
|
||||
if (history_def_init(&h->h_ref, &ev, 0) == -1) {
|
||||
h_free((ptr_t)h);
|
||||
h_free(h);
|
||||
return NULL;
|
||||
}
|
||||
h->h_ent = -1;
|
||||
@@ -586,14 +624,14 @@ FUN(history,init)(void)
|
||||
h->h_add = history_def_add;
|
||||
h->h_del = history_def_del;
|
||||
|
||||
return (h);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
/* history_end():
|
||||
* clean up history;
|
||||
*/
|
||||
public void
|
||||
void
|
||||
FUN(history,end)(TYPE(History) *h)
|
||||
{
|
||||
TYPE(HistEvent) ev;
|
||||
@@ -609,77 +647,77 @@ FUN(history,end)(TYPE(History) *h)
|
||||
/* history_setsize():
|
||||
* Set history number of events
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
|
||||
{
|
||||
|
||||
if (h->h_next != history_def_next) {
|
||||
he_seterrev(ev, _HE_NOT_ALLOWED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
if (num < 0) {
|
||||
he_seterrev(ev, _HE_BAD_PARAM);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
history_def_setsize(h->h_ref, num);
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_getsize():
|
||||
* Get number of events currently in history
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
|
||||
{
|
||||
if (h->h_next != history_def_next) {
|
||||
he_seterrev(ev, _HE_NOT_ALLOWED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
ev->num = history_def_getsize(h->h_ref);
|
||||
if (ev->num < -1) {
|
||||
he_seterrev(ev, _HE_SIZE_NEGATIVE);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_setunique():
|
||||
* Set if adjacent equal events should not be entered in history.
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
|
||||
{
|
||||
|
||||
if (h->h_next != history_def_next) {
|
||||
he_seterrev(ev, _HE_NOT_ALLOWED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
history_def_setunique(h->h_ref, uni);
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_getunique():
|
||||
* Get if adjacent equal events should not be entered in history.
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
|
||||
{
|
||||
if (h->h_next != history_def_next) {
|
||||
he_seterrev(ev, _HE_NOT_ALLOWED);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
ev->num = history_def_getunique(h->h_ref);
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_set_fun():
|
||||
* Set history functions
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_set_fun(TYPE(History) *h, TYPE(History) *nh)
|
||||
{
|
||||
TYPE(HistEvent) ev;
|
||||
@@ -689,7 +727,8 @@ history_set_fun(TYPE(History) *h, TYPE(History) *nh)
|
||||
nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
|
||||
nh->h_del == NULL || nh->h_ref == NULL) {
|
||||
if (h->h_next != history_def_next) {
|
||||
history_def_init(&h->h_ref, &ev, 0);
|
||||
if (history_def_init(&h->h_ref, &ev, 0) == -1)
|
||||
return -1;
|
||||
h->h_first = history_def_first;
|
||||
h->h_next = history_def_next;
|
||||
h->h_last = history_def_last;
|
||||
@@ -701,7 +740,7 @@ history_set_fun(TYPE(History) *h, TYPE(History) *nh)
|
||||
h->h_add = history_def_add;
|
||||
h->h_del = history_def_del;
|
||||
}
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
if (h->h_next == history_def_next)
|
||||
history_def_clear(h->h_ref, &ev);
|
||||
@@ -718,50 +757,49 @@ history_set_fun(TYPE(History) *h, TYPE(History) *nh)
|
||||
h->h_add = nh->h_add;
|
||||
h->h_del = nh->h_del;
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_load():
|
||||
* TYPE(History) load function
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_load(TYPE(History) *h, const char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char *line;
|
||||
size_t sz, max_size;
|
||||
size_t llen;
|
||||
ssize_t sz;
|
||||
size_t max_size;
|
||||
char *ptr;
|
||||
int i = -1;
|
||||
TYPE(HistEvent) ev;
|
||||
#ifdef WIDECHAR
|
||||
#ifndef NARROWCHAR
|
||||
static ct_buffer_t conv;
|
||||
#endif
|
||||
|
||||
if ((fp = fopen(fname, "r")) == NULL)
|
||||
return (i);
|
||||
return i;
|
||||
|
||||
if ((line = fgetln(fp, &sz)) == NULL)
|
||||
line = NULL;
|
||||
llen = 0;
|
||||
if ((sz = getline(&line, &llen, fp)) == -1)
|
||||
goto done;
|
||||
|
||||
if (strncmp(line, hist_cookie, sz) != 0)
|
||||
if (strncmp(line, hist_cookie, (size_t)sz) != 0)
|
||||
goto done;
|
||||
|
||||
ptr = h_malloc(max_size = 1024);
|
||||
ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
|
||||
if (ptr == NULL)
|
||||
goto done;
|
||||
for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
|
||||
char c = line[sz];
|
||||
|
||||
if (sz != 0 && line[sz - 1] == '\n')
|
||||
for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) {
|
||||
if (sz > 0 && line[sz - 1] == '\n')
|
||||
line[--sz] = '\0';
|
||||
else
|
||||
line[sz] = '\0';
|
||||
|
||||
if (max_size < sz) {
|
||||
if (max_size < (size_t)sz) {
|
||||
char *nptr;
|
||||
max_size = (sz + 1024) & ~1023;
|
||||
nptr = h_realloc(ptr, max_size);
|
||||
max_size = ((size_t)sz + 1024) & (size_t)~1023;
|
||||
nptr = h_realloc(ptr, max_size * sizeof(*ptr));
|
||||
if (nptr == NULL) {
|
||||
i = -1;
|
||||
goto oomem;
|
||||
@@ -769,88 +807,104 @@ history_load(TYPE(History) *h, const char *fname)
|
||||
ptr = nptr;
|
||||
}
|
||||
(void) strunvis(ptr, line);
|
||||
line[sz] = c;
|
||||
if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
|
||||
i = -1;
|
||||
goto oomem;
|
||||
}
|
||||
}
|
||||
oomem:
|
||||
h_free((ptr_t)ptr);
|
||||
h_free(ptr);
|
||||
done:
|
||||
free(line);
|
||||
(void) fclose(fp);
|
||||
return (i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* history_save():
|
||||
/* history_save_fp():
|
||||
* TYPE(History) save function
|
||||
*/
|
||||
private int
|
||||
history_save(TYPE(History) *h, const char *fname)
|
||||
static int
|
||||
history_save_fp(TYPE(History) *h, FILE *fp)
|
||||
{
|
||||
FILE *fp;
|
||||
TYPE(HistEvent) ev;
|
||||
int i = -1, retval;
|
||||
size_t len, max_size;
|
||||
char *ptr;
|
||||
#ifdef WIDECHAR
|
||||
const char *str;
|
||||
#ifndef NARROWCHAR
|
||||
static ct_buffer_t conv;
|
||||
#endif
|
||||
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
|
||||
goto done;
|
||||
if (fputs(hist_cookie, fp) == EOF)
|
||||
goto done;
|
||||
ptr = h_malloc(max_size = 1024);
|
||||
ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
|
||||
if (ptr == NULL)
|
||||
goto done;
|
||||
for (i = 0, retval = HLAST(h, &ev);
|
||||
retval != -1;
|
||||
retval = HPREV(h, &ev), i++) {
|
||||
len = Strlen(ev.str) * 4;
|
||||
if (len >= max_size) {
|
||||
str = ct_encode_string(ev.str, &conv);
|
||||
len = strlen(str) * 4 + 1;
|
||||
if (len > max_size) {
|
||||
char *nptr;
|
||||
max_size = (len + 1024) & ~1023;
|
||||
nptr = h_realloc(ptr, max_size);
|
||||
max_size = (len + 1024) & (size_t)~1023;
|
||||
nptr = h_realloc(ptr, max_size * sizeof(*ptr));
|
||||
if (nptr == NULL) {
|
||||
i = -1;
|
||||
goto oomem;
|
||||
}
|
||||
ptr = nptr;
|
||||
}
|
||||
(void) strvis(ptr, ct_encode_string(ev.str, &conv), VIS_WHITE);
|
||||
(void) strvis(ptr, str, VIS_WHITE);
|
||||
(void) fprintf(fp, "%s\n", ptr);
|
||||
}
|
||||
oomem:
|
||||
h_free((ptr_t)ptr);
|
||||
h_free(ptr);
|
||||
done:
|
||||
(void) fclose(fp);
|
||||
return (i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* history_save():
|
||||
* History save function
|
||||
*/
|
||||
static int
|
||||
history_save(TYPE(History) *h, const char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
return -1;
|
||||
|
||||
i = history_save_fp(h, fp);
|
||||
|
||||
(void) fclose(fp);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* history_prev_event():
|
||||
* Find the previous event, with number given
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
|
||||
{
|
||||
int retval;
|
||||
|
||||
for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
|
||||
if (ev->num == num)
|
||||
return (0);
|
||||
return 0;
|
||||
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private int
|
||||
static int
|
||||
history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
|
||||
{
|
||||
int retval;
|
||||
@@ -859,35 +913,35 @@ history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
|
||||
if (ev->num == num) {
|
||||
if (d)
|
||||
*d = ((history_t *)h->h_ref)->cursor->data;
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* history_next_event():
|
||||
* Find the next event, with number given
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
|
||||
{
|
||||
int retval;
|
||||
|
||||
for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
|
||||
if (ev->num == num)
|
||||
return (0);
|
||||
return 0;
|
||||
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* history_prev_string():
|
||||
* Find the previous event beginning with string
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
|
||||
{
|
||||
size_t len = Strlen(str);
|
||||
@@ -895,17 +949,17 @@ history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
|
||||
|
||||
for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
|
||||
if (Strncmp(str, ev->str, len) == 0)
|
||||
return (0);
|
||||
return 0;
|
||||
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* history_next_string():
|
||||
* Find the next event beginning with string
|
||||
*/
|
||||
private int
|
||||
static int
|
||||
history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
|
||||
{
|
||||
size_t len = Strlen(str);
|
||||
@@ -913,10 +967,10 @@ history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
|
||||
|
||||
for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
|
||||
if (Strncmp(str, ev->str, len) == 0)
|
||||
return (0);
|
||||
return 0;
|
||||
|
||||
he_seterrev(ev, _HE_NOT_FOUND);
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1013,6 +1067,12 @@ FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
|
||||
he_seterrev(ev, _HE_HIST_WRITE);
|
||||
break;
|
||||
|
||||
case H_SAVE_FP:
|
||||
retval = history_save_fp(h, va_arg(va, FILE *));
|
||||
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;
|
||||
@@ -1033,7 +1093,7 @@ FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
|
||||
{
|
||||
TYPE(History) hf;
|
||||
|
||||
hf.h_ref = va_arg(va, ptr_t);
|
||||
hf.h_ref = va_arg(va, void *);
|
||||
h->h_ent = -1;
|
||||
hf.h_first = va_arg(va, history_gfun_t);
|
||||
hf.h_next = va_arg(va, history_gfun_t);
|
||||
|
||||
Reference in New Issue
Block a user