optionally use bundled db
authorSven Verdoolaege <skimo@kotnet.org>
Tue, 29 Dec 2009 15:59:08 +0000 (29 16:59 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Fri, 1 Jan 2010 15:33:21 +0000 (1 16:33 +0100)
In fact, use it by default.

Rename db.[ch] to avoid confusion with the similarly named files in db.1.85.

Put db1 specific code in log1.c and vi_db1.c.
Some of this code is very similar to the db[34] code.
We may want to clean that up later.

common/common.h
common/log1.c [new file with mode: 0644]
common/vi_db.c [moved from common/db.c with 100% similarity]
common/vi_db.h [moved from common/db.h with 73% similarity]
common/vi_db1.c [moved from common/db1.c with 69% similarity]
dist/Makefile.am
dist/acconfig.h
dist/configure.in

index 5d59dbd..624a53f 100644 (file)
@@ -26,7 +26,7 @@
  * on most machines to which we're porting vi, and we want to include
  * them in a very specific order, regardless.
  */
-#include "db.h"
+#include "vi_db.h"
 #include <regex.h>
 
 /*
@@ -102,6 +102,8 @@ typedef enum { SEQ_ABBREV, SEQ_COMMAND, SEQ_INPUT } seq_t;
 #include "screen.h"            /* Required by exf.h. */
 #include "exf.h"
 #include "mem.h"
+#ifndef USE_BUNDLED_DB
 #include "vi_auto.h"
+#endif
 
 #include "extern.h"
diff --git a/common/log1.c b/common/log1.c
new file mode 100644 (file)
index 0000000..3419863
--- /dev/null
@@ -0,0 +1,777 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ *     Keith Bostic.  All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "$Id: log.c,v 10.26 2002/03/02 23:12:13 skimo Exp $ (Berkeley) $Date: 2002/03/02 23:12:13 $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <bitstring.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+/*
+ * The log consists of records, each containing a type byte and a variable
+ * length byte string, as follows:
+ *
+ *     LOG_CURSOR_INIT         MARK
+ *     LOG_CURSOR_END          MARK
+ *     LOG_LINE_APPEND_F       db_recno_t              char *
+ *     LOG_LINE_APPEND_B       db_recno_t              char *
+ *     LOG_LINE_DELETE_F       db_recno_t              char *
+ *     LOG_LINE_DELETE_B       db_recno_t              char *
+ *     LOG_LINE_RESET_F        db_recno_t              char *
+ *     LOG_LINE_RESET_B        db_recno_t              char *
+ *     LOG_MARK                LMARK
+ *
+ * We do before image physical logging.  This means that the editor layer
+ * MAY NOT modify records in place, even if simply deleting or overwriting
+ * characters.  Since the smallest unit of logging is a line, we're using
+ * up lots of space.  This may eventually have to be reduced, probably by
+ * doing logical logging, which is a much cooler database phrase.
+ *
+ * The implementation of the historic vi 'u' command, using roll-forward and
+ * roll-back, is simple.  Each set of changes has a LOG_CURSOR_INIT record,
+ * followed by a number of other records, followed by a LOG_CURSOR_END record.
+ * LOG_LINE_RESET records come in pairs.  The first is a LOG_LINE_RESET_B
+ * record, and is the line before the change.  The second is LOG_LINE_RESET_F,
+ * and is the line after the change.  Roll-back is done by backing up to the
+ * first LOG_CURSOR_INIT record before a change.  Roll-forward is done in a
+ * similar fashion.
+ *
+ * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END
+ * record for a line different from the current one.  It should be noted that
+ * this means that a subsequent 'u' command will make a change based on the
+ * new position of the log's cursor.  This is okay, and, in fact, historic vi
+ * behaved that way.
+ */
+
+static int     log_cursor1 __P((SCR *, int));
+static void    log_err __P((SCR *, char *, int));
+#if defined(DEBUG) && 0
+static void    log_trace __P((SCR *, char *, db_recno_t, u_char *));
+#endif
+
+/* Try and restart the log on failure, i.e. if we run out of memory. */
+#define        LOG_ERR {                                                       \
+       log_err(sp, __FILE__, __LINE__);                                \
+       return (1);                                                     \
+}
+
+/* offset of CHAR_T string in log needs to be aligned on some systems
+ * because it is passed to db_set as a string
+ */
+typedef struct {
+    char    data[sizeof(u_char) /* type */ + sizeof(db_recno_t)];
+    CHAR_T  str[1];
+} log_t;
+#define CHAR_T_OFFSET ((char *)(((log_t*)0)->str) - (char *)0)
+
+/*
+ * log_init --
+ *     Initialize the logging subsystem.
+ *
+ * PUBLIC: int log_init __P((SCR *, EXF *));
+ */
+int
+log_init(SCR *sp, EXF *ep)
+{
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        *
+        * Initialize the buffer.  The logging subsystem has its own
+        * buffers because the global ones are almost by definition
+        * going to be in use when the log runs.
+        */
+       sp->wp->l_lp = NULL;
+       sp->wp->l_len = 0;
+       ep->l_cursor.lno = 1;           /* XXX Any valid recno. */
+       ep->l_cursor.cno = 0;
+       ep->l_high = ep->l_cur = 1;
+
+       ep->log = dbopen(NULL, O_CREAT | O_NONBLOCK | O_RDWR,
+           S_IRUSR | S_IWUSR, DB_RECNO, NULL);
+       if (ep->log == NULL) {
+               msgq(sp, M_SYSERR, "009|Log file");
+               F_SET(ep, F_NOLOG);
+               return (1);
+       }
+
+       ep->l_win = NULL;
+       /*LOCK_INIT(sp->wp, ep);*/
+
+       return (0);
+}
+
+/*
+ * log_end --
+ *     Close the logging subsystem.
+ *
+ * PUBLIC: int log_end __P((SCR *, EXF *));
+ */
+int
+log_end(SCR *sp, EXF *ep)
+{
+       /*
+        * !!!
+        * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
+        */
+       /*LOCK_END(sp->wp, ep);*/
+       if (ep->log != NULL) {
+               (void)(ep->log->close)(ep->log);
+               ep->log = NULL;
+       }
+       if (sp->wp->l_lp != NULL) {
+               free(sp->wp->l_lp);
+               sp->wp->l_lp = NULL;
+       }
+       sp->wp->l_len = 0;
+       ep->l_cursor.lno = 1;           /* XXX Any valid recno. */
+       ep->l_cursor.cno = 0;
+       ep->l_high = ep->l_cur = 1;
+       return (0);
+}
+
+/*
+ * log_cursor --
+ *     Log the current cursor position, starting an event.
+ *
+ * PUBLIC: int log_cursor __P((SCR *));
+ */
+int
+log_cursor(SCR *sp)
+{
+       EXF *ep;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /*
+        * If any changes were made since the last cursor init,
+        * put out the ending cursor record.
+        */
+       if (ep->l_cursor.lno == OOBLNO) {
+               if (ep->l_win && ep->l_win != sp->wp)
+                       return 0;
+               ep->l_cursor.lno = sp->lno;
+               ep->l_cursor.cno = sp->cno;
+               ep->l_win = NULL;
+               return (log_cursor1(sp, LOG_CURSOR_END));
+       }
+       ep->l_cursor.lno = sp->lno;
+       ep->l_cursor.cno = sp->cno;
+       return (0);
+}
+
+/*
+ * log_cursor1 --
+ *     Actually push a cursor record out.
+ */
+static int
+log_cursor1(SCR *sp, int type)
+{
+       DBT data, key;
+       EXF *ep;
+
+       ep = sp->ep;
+
+       /*
+       if (type == LOG_CURSOR_INIT &&
+           LOCK_TRY(sp->wp, ep))
+               return 1;
+       */
+
+       BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, sizeof(u_char) + sizeof(MARK));
+       sp->wp->l_lp[0] = type;
+       memmove(sp->wp->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
+
+       memset(&key, 0, sizeof(key));
+       key.data = &ep->l_cur;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.size = sizeof(u_char) + sizeof(MARK);
+       if (ep->log->put(ep->log, &key, &data, 0) == -1)
+               LOG_ERR;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
+           type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
+           sp->lno, sp->cno);
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+
+       /*
+       if (type == LOG_CURSOR_END)
+               LOCK_UNLOCK(sp->wp, ep);
+       */
+       return (0);
+}
+
+/*
+ * log_line --
+ *     Log a line change.
+ *
+ * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
+ */
+int
+log_line(SCR *sp, db_recno_t lno, u_int action)
+{
+       DBT data, key;
+       EXF *ep;
+       size_t len;
+       CHAR_T *lp;
+       db_recno_t lcur;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /*
+        * XXX
+        *
+        * Kluge for vi.  Clear the EXF undo flag so that the
+        * next 'u' command does a roll-back, regardless.
+        */
+       F_CLR(ep, F_UNDO);
+
+       /* Put out one initial cursor record per set of changes. */
+       if (ep->l_cursor.lno != OOBLNO) {
+               if (log_cursor1(sp, LOG_CURSOR_INIT))
+                       return (1);
+               ep->l_cursor.lno = OOBLNO;
+               ep->l_win = sp->wp;
+       } /*else if (ep->l_win != sp->wp) {
+               printf("log_line own: %p, this: %p\n", ep->l_win, sp->wp);
+               return 1;
+       }*/
+
+       switch (action) {
+       /* newly added for DB4 logging */
+       case LOG_LINE_APPEND_B:
+       case LOG_LINE_DELETE_F:
+               return 0;
+       }
+
+       /*
+        * Put out the changes.  If it's a LOG_LINE_RESET_B call, it's a
+        * special case, avoid the caches.  Also, if it fails and it's
+        * line 1, it just means that the user started with an empty file,
+        * so fake an empty length line.
+        */
+       if (action == LOG_LINE_RESET_B) {
+               if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) {
+                       static CHAR_T nul = 0;
+                       if (lno != 1) {
+                               db_err(sp, lno);
+                               return (1);
+                       }
+                       len = 0;
+                       lp = &nul;
+               }
+       } else
+               if (db_get(sp, lno, DBG_FATAL, &lp, &len))
+                       return (1);
+       BINC_RETC(sp,
+           sp->wp->l_lp, sp->wp->l_len, 
+           len * sizeof(CHAR_T) + CHAR_T_OFFSET);
+       sp->wp->l_lp[0] = action;
+       memmove(sp->wp->l_lp + sizeof(u_char), &lno, sizeof(db_recno_t));
+       MEMMOVEW(sp->wp->l_lp + CHAR_T_OFFSET, lp, len);
+
+       lcur = ep->l_cur;
+       memset(&key, 0, sizeof(key));
+       key.data = &lcur;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.size = len * sizeof(CHAR_T) + CHAR_T_OFFSET;
+       if (ep->log->put(ep->log, &key, &data, 0) == -1)
+               LOG_ERR;
+
+#if defined(DEBUG) && 0
+       switch (action) {
+       case LOG_LINE_APPEND_F:
+               vtrace(sp, "%u: log_line: append_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_APPEND_B:
+               vtrace(sp, "%u: log_line: append_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_DELETE_F:
+               vtrace(sp, "%lu: log_line: delete_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_DELETE_B:
+               vtrace(sp, "%lu: log_line: delete_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_RESET_F:
+               vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       case LOG_LINE_RESET_B:
+               vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
+                   ep->l_cur, lno, len);
+               break;
+       }
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+
+       return (0);
+}
+
+/*
+ * log_mark --
+ *     Log a mark position.  For the log to work, we assume that there
+ *     aren't any operations that just put out a log record -- this
+ *     would mean that undo operations would only reset marks, and not
+ *     cause any other change.
+ *
+ * PUBLIC: int log_mark __P((SCR *, LMARK *));
+ */
+int
+log_mark(SCR *sp, LMARK *lmp)
+{
+       DBT data, key;
+       EXF *ep;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG))
+               return (0);
+
+       /* Put out one initial cursor record per set of changes. */
+       if (ep->l_cursor.lno != OOBLNO) {
+               if (log_cursor1(sp, LOG_CURSOR_INIT))
+                       return (1);
+               ep->l_cursor.lno = OOBLNO;
+               ep->l_win = sp->wp;
+       }
+
+       BINC_RETC(sp, sp->wp->l_lp,
+           sp->wp->l_len, sizeof(u_char) + sizeof(LMARK));
+       sp->wp->l_lp[0] = LOG_MARK;
+       memmove(sp->wp->l_lp + sizeof(u_char), lmp, sizeof(LMARK));
+
+       memset(&key, 0, sizeof(key));
+       key.data = &ep->l_cur;
+       key.size = sizeof(db_recno_t);
+       memset(&data, 0, sizeof(data));
+       data.data = sp->wp->l_lp;
+       data.size = sizeof(u_char) + sizeof(LMARK);
+       if (ep->log->put(ep->log, &key, &data, 0) == -1)
+               LOG_ERR;
+
+#if defined(DEBUG) && 0
+       vtrace(sp, "%lu: mark %c: %lu/%u\n",
+           ep->l_cur, lmp->name, lmp->lno, lmp->cno);
+#endif
+       /* Reset high water mark. */
+       ep->l_high = ++ep->l_cur;
+       return (0);
+}
+
+/*
+ * Log_backward --
+ *     Roll the log backward one operation.
+ *
+ * PUBLIC: int log_backward __P((SCR *, MARK *));
+ */
+int
+log_backward(SCR *sp, MARK *rp)
+{
+       DBT key, data;
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       int didop;
+       u_char *p;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+                   "010|Logging not being performed, undo not possible");
+               return (1);
+       }
+
+       if (ep->l_cur == 1) {
+               msgq(sp, M_BERR, "011|No changes to undo");
+               return (1);
+       }
+
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+       ep->l_win = sp->wp;
+               
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       key.data = &ep->l_cur;          /* Initialize db request. */
+       key.size = sizeof(recno_t);
+       for (didop = 0;;) {
+               --ep->l_cur;
+               if (ep->log->get(ep->log, &key, &data, 0))
+                       LOG_ERR;
+#if defined(DEBUG) && 0
+               log_trace(sp, "log_backward", ep->l_cur, data.data);
+#endif
+               switch (*(p = (u_char *)data.data)) {
+               case LOG_CURSOR_INIT:
+                       if (didop) {
+                               memmove(rp, p + sizeof(u_char), sizeof(MARK));
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_CURSOR_END:
+                       break;
+               case LOG_LINE_APPEND_F:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_delete(sp, lno))
+                               goto err;
+                       ++sp->rptlines[L_DELETED];
+                       break;
+               case LOG_LINE_DELETE_B:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_insert(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (data.size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       ++sp->rptlines[L_ADDED];
+                       break;
+               case LOG_LINE_RESET_F:
+                       break;
+               case LOG_LINE_RESET_B:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_set(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (data.size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       if (sp->rptlchange != lno) {
+                               sp->rptlchange = lno;
+                               ++sp->rptlines[L_CHANGED];
+                       }
+                       break;
+               case LOG_MARK:
+                       didop = 1;
+                       memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+                       m.lno = lm.lno;
+                       m.cno = lm.cno;
+                       if (mark_set(sp, lm.name, &m, 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+err:   F_CLR(ep, F_NOLOG);
+       ep->l_win = NULL;
+       return (1);
+}
+
+/*
+ * Log_setline --
+ *     Reset the line to its original appearance.
+ *
+ * XXX
+ * There's a bug in this code due to our not logging cursor movements
+ * unless a change was made.  If you do a change, move off the line,
+ * then move back on and do a 'U', the line will be restored to the way
+ * it was before the original change.
+ *
+ * PUBLIC: int log_setline __P((SCR *));
+ */
+int
+log_setline(SCR *sp)
+{
+       DBT key, data;
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       u_char *p;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+                   "012|Logging not being performed, undo not possible");
+               return (1);
+       }
+
+       if (ep->l_cur == 1)
+               return (1);
+
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+       ep->l_win = sp->wp;
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       key.data = &ep->l_cur;          /* Initialize db request. */
+       key.size = sizeof(recno_t);
+
+       for (;;) {
+               --ep->l_cur;
+               if (ep->log->get(ep->log, &key, &data, 0))
+                       LOG_ERR;
+#if defined(DEBUG) && 0
+               log_trace(sp, "log_setline", ep->l_cur, data.data);
+#endif
+               switch (*(p = (u_char *)data.data)) {
+               case LOG_CURSOR_INIT:
+                       memmove(&m, p + sizeof(u_char), sizeof(MARK));
+                       if (m.lno != sp->lno || ep->l_cur == 1) {
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_CURSOR_END:
+                       memmove(&m, p + sizeof(u_char), sizeof(MARK));
+                       if (m.lno != sp->lno) {
+                               ++ep->l_cur;
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_LINE_APPEND_F:
+               case LOG_LINE_DELETE_B:
+               case LOG_LINE_RESET_F:
+                       break;
+               case LOG_LINE_RESET_B:
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (lno == sp->lno &&
+                           db_set(sp, lno, (CHAR_T *)(p + CHAR_T_OFFSET),
+                               (data.size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       if (sp->rptlchange != lno) {
+                               sp->rptlchange = lno;
+                               ++sp->rptlines[L_CHANGED];
+                       }
+               case LOG_MARK:
+                       memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+                       m.lno = lm.lno;
+                       m.cno = lm.cno;
+                       if (mark_set(sp, lm.name, &m, 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+err:   F_CLR(ep, F_NOLOG);
+       ep->l_win = NULL;
+       return (1);
+}
+
+/*
+ * Log_forward --
+ *     Roll the log forward one operation.
+ *
+ * PUBLIC: int log_forward __P((SCR *, MARK *));
+ */
+int
+log_forward(SCR *sp, MARK *rp)
+{
+       DBT key, data;
+       EXF *ep;
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+       int didop;
+       u_char *p;
+
+       ep = sp->ep;
+       if (F_ISSET(ep, F_NOLOG)) {
+               msgq(sp, M_ERR,
+           "013|Logging not being performed, roll-forward not possible");
+               return (1);
+       }
+
+       if (ep->l_cur == ep->l_high) {
+               msgq(sp, M_BERR, "014|No changes to re-do");
+               return (1);
+       }
+
+       if (ep->l_win && ep->l_win != sp->wp) {
+               ex_emsg(sp, NULL, EXM_LOCKED);
+               return 1;
+       }
+       ep->l_win = sp->wp;
+
+       F_SET(ep, F_NOLOG);             /* Turn off logging. */
+
+       key.data = &ep->l_cur;          /* Initialize db request. */
+       key.size = sizeof(recno_t);
+       for (didop = 0;;) {
+               ++ep->l_cur;
+               if (ep->log->get(ep->log, &key, &data, 0))
+                       LOG_ERR;
+#if defined(DEBUG) && 0
+               log_trace(sp, "log_forward", ep->l_cur, data.data);
+#endif
+               switch (*(p = (u_char *)data.data)) {
+               case LOG_CURSOR_END:
+                       if (didop) {
+                               ++ep->l_cur;
+                               memmove(rp, p + sizeof(u_char), sizeof(MARK));
+                               F_CLR(ep, F_NOLOG);
+                               ep->l_win = NULL;
+                               return (0);
+                       }
+                       break;
+               case LOG_CURSOR_INIT:
+                       break;
+               case LOG_LINE_APPEND_F:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_insert(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (data.size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       ++sp->rptlines[L_ADDED];
+                       break;
+               case LOG_LINE_DELETE_B:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_delete(sp, lno))
+                               goto err;
+                       ++sp->rptlines[L_DELETED];
+                       break;
+               case LOG_LINE_RESET_B:
+                       break;
+               case LOG_LINE_RESET_F:
+                       didop = 1;
+                       memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+                       if (db_set(sp, lno, 
+                           (CHAR_T *)(p + CHAR_T_OFFSET),
+                           (data.size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
+                               goto err;
+                       if (sp->rptlchange != lno) {
+                               sp->rptlchange = lno;
+                               ++sp->rptlines[L_CHANGED];
+                       }
+                       break;
+               case LOG_MARK:
+                       didop = 1;
+                       memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+                       m.lno = lm.lno;
+                       m.cno = lm.cno;
+                       if (mark_set(sp, lm.name, &m, 0))
+                               goto err;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+err:   F_CLR(ep, F_NOLOG);
+       ep->l_win = NULL;
+       return (1);
+}
+
+/*
+ * log_err --
+ *     Try and restart the log on failure, i.e. if we run out of memory.
+ */
+static void
+log_err(SCR *sp, char *file, int line)
+{
+       EXF *ep;
+
+       msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
+       ep = sp->ep;
+       (void)ep->log->close(ep->log);
+       if (!log_init(sp, ep))
+               msgq(sp, M_ERR, "267|Log restarted");
+}
+
+#if defined(DEBUG) && 0
+static void
+log_trace(sp, msg, rno, p)
+       SCR *sp;
+       char *msg;
+       db_recno_t rno;
+       u_char *p;
+{
+       LMARK lm;
+       MARK m;
+       db_recno_t lno;
+
+       switch (*p) {
+       case LOG_CURSOR_INIT:
+               memmove(&m, p + sizeof(u_char), sizeof(MARK));
+               vtrace(sp, "%lu: %s:  C_INIT: %u/%u\n", rno, msg, m.lno, m.cno);
+               break;
+       case LOG_CURSOR_END:
+               memmove(&m, p + sizeof(u_char), sizeof(MARK));
+               vtrace(sp, "%lu: %s:   C_END: %u/%u\n", rno, msg, m.lno, m.cno);
+               break;
+       case LOG_LINE_APPEND_F:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  APPEND_F: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_APPEND_B:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  APPEND_B: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_DELETE_F:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  DELETE_F: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_DELETE_B:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s:  DELETE_B: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_RESET_F:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno);
+               break;
+       case LOG_LINE_RESET_B:
+               memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
+               vtrace(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno);
+               break;
+       case LOG_MARK:
+               memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
+               vtrace(sp,
+                   "%lu: %s:    MARK: %u/%u\n", rno, msg, lm.lno, lm.cno);
+               break;
+       default:
+               abort();
+       }
+}
+#endif
similarity index 100%
rename from common/db.c
rename to common/vi_db.c
similarity index 73%
rename from common/db.h
rename to common/vi_db.h
index 87dcf2d..081dc3e 100644 (file)
@@ -4,6 +4,27 @@
 #define DB_BUFFER_SMALL                ENOMEM
 #endif
 
+#ifdef USE_BUNDLED_DB
+
+typedef void DB_ENV;
+
+typedef recno_t db_recno_t;
+#define DB_MAX_RECORDS MAX_REC_NUMBER
+
+#define db_env_close(env,flags)
+#define db_env_create(env,flags)                                       \
+       1
+#define db_env_remove(env,path,flags)                                  \
+       1
+#define db_open(db,file,type,flags,mode)                               \
+    (db)->open(db, file, NULL, type, flags, mode)
+#define db_get_low(db,key,data,flags)                                  \
+    (db)->get(db, key, data, flags)
+#define db_close(db)                                                   \
+    (db)->close(db)
+
+#else
+
 #if DB_VERSION_MAJOR >= 3 && DB_VERSION_MINOR >= 1
 #define db_env_open(env,path,flags,mode)                               \
     (env)->open(env, path, flags, mode)
@@ -31,6 +52,8 @@
 #define db_close(db)                                                   \
     (db)->close(db, DB_NOSYNC)
 
+#endif
+
 #ifdef USE_DYNAMIC_LOADING
 #define db_create      nvi_db_create
 #define db_env_create   nvi_db_env_create
similarity index 69%
rename from common/db1.c
rename to common/vi_db1.c
index 86430da..6d63c94 100644 (file)
@@ -16,9 +16,11 @@ static const char sccsid[] = "$Id: db1.c,v 10.1 2002/03/09 12:53:57 skimo Exp $
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <sys/time.h>
+#include <sys/stat.h>
 
 #include <bitstring.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
@@ -26,8 +28,6 @@ static const char sccsid[] = "$Id: db1.c,v 10.1 2002/03/09 12:53:57 skimo Exp $
 #include "common.h"
 #include "../vi/vi.h"
 
-static int scr_update __P((SCR *, db_recno_t, lnop_t, int));
-
 /*
  * db_eget --
  *     Front-end to db_get, special case handling for empty files.
@@ -140,35 +140,28 @@ db_get(SCR *sp, db_recno_t lno, u_int32_t flags, CHAR_T **pp, size_t *lenp)
        }
 
        /* Look-aside into the cache, and see if the line we want is there. */
-       /*
-        * Line cache will not work if different screens view the same
-        * file with different encodings.
-        * Multiple threads accessing the same cache can be a problem as
-        * well.
-        * So, line cache is (temporarily) disabled.
-        */
-       if (0 && lno == ep->c_lno) {
+       if (lno == sp->c_lno) {
 #if defined(DEBUG) && 0
                vtrace(sp, "retrieve cached line %lu\n", (u_long)lno);
 #endif
                if (lenp != NULL)
-                       *lenp = ep->c_len;
+                       *lenp = sp->c_len;
                if (pp != NULL)
-                       *pp = ep->c_lp;
+                       *pp = sp->c_lp;
                return (0);
        }
-       ep->c_lno = OOBLNO;
+       sp->c_lno = OOBLNO;
 
 nocache:
        nlen = 1024;
 retry:
        /* data.size contains length in bytes */
-       BINC_GOTO(sp, CHAR_T, ep->c_lp, ep->c_blen, nlen);
+       BINC_GOTO(sp, CHAR_T, sp->c_lp, sp->c_blen, nlen);
 
        /* Get the line from the underlying database. */
        key.data = &lno;
        key.size = sizeof(lno);
-       switch (ep->db->actual_db->get(ep->db->actual_db, &key, &data, 0)) {
+       switch (ep->db->get(ep->db, &key, &data, 0)) {
         case -1:
                goto err2;
        case 1:
@@ -185,7 +178,7 @@ err3:               if (lenp != NULL)
                        nlen = data.size;
                        goto retry;
                } else
-                       memcpy(ep->c_lp, data.data, nlen);
+                       memcpy(sp->c_lp, data.data, nlen);
        }
 
        if (FILE2INT(sp, data.data, data.size, wp, wlen)) {
@@ -198,11 +191,11 @@ err3:             if (lenp != NULL)
 
        /* Reset the cache. */
        if (wp != data.data) {
-           BINC_GOTOW(sp, ep->c_lp, ep->c_blen, wlen);
-           MEMCPYW(ep->c_lp, wp, wlen);
+           BINC_GOTOW(sp, sp->c_lp, sp->c_blen, wlen);
+           MEMCPYW(sp->c_lp, wp, wlen);
        }
-       ep->c_lno = lno;
-       ep->c_len = wlen;
+       sp->c_lno = lno;
+       sp->c_len = wlen;
 
 #if defined(DEBUG) && 0
        vtrace(sp, "retrieve DB line %lu\n", (u_long)lno);
@@ -210,7 +203,7 @@ err3:               if (lenp != NULL)
        if (lenp != NULL)
                *lenp = wlen;
        if (pp != NULL)
-               *pp = ep->c_lp;
+               *pp = sp->c_lp;
        return (0);
 }
 
@@ -246,12 +239,12 @@ db_delete(SCR *sp, db_recno_t lno)
                return (1);
 
        /* Log change. */
-       log_line(sp, lno, LOG_LINE_DELETE);
+       log_line(sp, lno, LOG_LINE_DELETE_B);
 
        /* Update file. */
        key.data = &lno;
        key.size = sizeof(lno);
-       sp->db_error = ep->db->actual_db->del(ep->db->actual_db, &key, 0);
+       sp->db_error = ep->db->del(ep->db, &key, 0);
        if (sp->db_error != 0) {
                if (sp->db_error == -1)
                        sp->db_error = errno;
@@ -262,16 +255,16 @@ db_delete(SCR *sp, db_recno_t lno)
        }
 
        /* Flush the cache, update line count, before screen update. */
-       if (lno <= ep->c_lno)
-               ep->c_lno = OOBLNO;
-       if (ep->c_nlines != OOBLNO)
-               --ep->c_nlines;
+       update_cache(sp, LINE_DELETE, lno);
 
        /* File now modified. */
        if (F_ISSET(ep, F_FIRSTMODIFY))
                (void)rcv_init(sp);
        F_SET(ep, F_MODIFIED);
 
+       /* Log after change. */
+       log_line(sp, lno, LOG_LINE_DELETE_F);
+
        /* Update screen. */
        return (scr_update(sp, lno, LINE_DELETE, 1));
 }
@@ -287,6 +280,8 @@ db_append(SCR *sp, int update, db_recno_t lno, CHAR_T *p, size_t len)
 {
        DBT data, key;
        EXF *ep;
+       char *fp;
+       size_t flen;
        int rval;
 
 #if defined(DEBUG) && 0
@@ -301,31 +296,33 @@ db_append(SCR *sp, int update, db_recno_t lno, CHAR_T *p, size_t len)
                ex_emsg(sp, NULL, EXM_LOCKED);
                return 1;
        }
+
+       /* Log before change. */
+       log_line(sp, lno + 1, LOG_LINE_APPEND_B);
+
+       INT2FILE(sp, p, len, fp, flen);
                
        /* Update file. */
        key.data = &lno;
        key.size = sizeof(lno);
-       data.data = p;
-       data.size = len;
-       if (ep->db->actual_db->put(ep->db->actual_db, &key, &data, R_IAFTER)) {
+       data.data = fp;
+       data.size = flen;
+       if (ep->db->put(ep->db, &key, &data, R_IAFTER)) {
                msgq(sp, M_DBERR, "004|unable to append to line %lu", 
                        (u_long)lno);
                return (1);
        }
 
        /* Flush the cache, update line count, before screen update. */
-       if (lno < ep->c_lno)
-               ep->c_lno = OOBLNO;
-       if (ep->c_nlines != OOBLNO)
-               ++ep->c_nlines;
+       update_cache(sp, LINE_INSERT, lno);
 
        /* File now dirty. */
        if (F_ISSET(ep, F_FIRSTMODIFY))
                (void)rcv_init(sp);
        F_SET(ep, F_MODIFIED);
 
-       /* Log change. */
-       log_line(sp, lno + 1, LOG_LINE_APPEND);
+       /* Log after change. */
+       log_line(sp, lno + 1, LOG_LINE_APPEND_F);
 
        /* Update marks, @ and global commands. */
        rval = 0;
@@ -358,6 +355,8 @@ db_insert(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len)
 {
        DBT data, key;
        EXF *ep;
+       char *fp;
+       size_t flen;
        int rval;
 
 #if defined(DEBUG) && 0
@@ -373,31 +372,33 @@ db_insert(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len)
                ex_emsg(sp, NULL, EXM_LOCKED);
                return 1;
        }
+
+       /* Log before change. */
+       log_line(sp, lno, LOG_LINE_APPEND_B);
+
+       INT2FILE(sp, p, len, fp, flen);
                
        /* Update file. */
        key.data = &lno;
        key.size = sizeof(lno);
-       data.data = p;
-       data.size = len;
-       if (ep->db->actual_db->put(ep->db->actual_db, &key, &data, R_IBEFORE)) {
+       data.data = fp;
+       data.size = flen;
+       if (ep->db->put(ep->db, &key, &data, R_IBEFORE)) {
                msgq(sp, M_SYSERR,
                    "005|unable to insert at line %lu", (u_long)lno);
                return (1);
        }
 
        /* Flush the cache, update line count, before screen update. */
-       if (lno >= ep->c_lno)
-               ep->c_lno = OOBLNO;
-       if (ep->c_nlines != OOBLNO)
-               ++ep->c_nlines;
+       update_cache(sp, LINE_INSERT, lno);
 
        /* File now dirty. */
        if (F_ISSET(ep, F_FIRSTMODIFY))
                (void)rcv_init(sp);
        F_SET(ep, F_MODIFIED);
 
-       /* Log change. */
-       log_line(sp, lno, LOG_LINE_INSERT);
+       /* Log after change. */
+       log_line(sp, lno, LOG_LINE_APPEND_F);
 
        /* Update marks, @ and global commands. */
        rval = 0;
@@ -449,7 +450,7 @@ db_set(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len)
        data.data = fp;
        data.size = flen;
        sp->db_error =
-               ep->db->actual_db->put(ep->db->actual_db, &key, &data, 0);
+               ep->db->put(ep->db, &key, &data, 0);
        if (sp->db_error != 0) {
                if (sp->db_error == -1)
                        sp->db_error = errno;
@@ -459,8 +460,7 @@ db_set(SCR *sp, db_recno_t lno, CHAR_T *p, size_t len)
        }
 
        /* Flush the cache, before logging or screen update. */
-       if (lno == ep->c_lno)
-               ep->c_lno = OOBLNO;
+       update_cache(sp, LINE_RESET, lno);
 
        /* File now dirty. */
        if (F_ISSET(ep, F_FIRSTMODIFY))
@@ -543,8 +543,7 @@ db_last(SCR *sp, db_recno_t *lnop)
        key.data = &lno;
        key.size = sizeof(lno);
 
-       sp->db_error = ep->db->actual_db->seq(ep->db->actual_db, &key, &data,
-                                                                       R_LAST);
+       sp->db_error = ep->db->seq(ep->db, &key, &data, R_LAST);
        switch (sp->db_error) {
        case 1:
                *lnop = 0;
@@ -561,16 +560,14 @@ alloc_err:
 
        memcpy(&lno, key.data, sizeof(lno));
 
-       if (lno != ep->c_lno) {
+       if (lno != sp->c_lno) {
            FILE2INT(sp, data.data, data.size, wp, wlen);
 
            /* Fill the cache. */
-           if (wp != data.data) {
-               BINC_GOTOW(sp, ep->c_lp, ep->c_blen, wlen);
-               MEMCPYW(ep->c_lp, wp, wlen);
-           }
-           ep->c_lno = lno;
-           ep->c_len = wlen;
+           BINC_GOTOW(sp, sp->c_lp, sp->c_blen, wlen);
+           MEMCPYW(sp->c_lp, wp, wlen);
+           sp->c_lno = lno;
+           sp->c_len = wlen;
        }
        ep->c_nlines = lno;
 
@@ -599,7 +596,7 @@ db_err(SCR *sp, db_recno_t lno)
  *     Update all of the screens that are backed by the file that
  *     just changed.
  */
-static int
+int
 scr_update(SCR *sp, db_recno_t lno, lnop_t op, int current)
 {
        EXF *ep;
@@ -623,169 +620,97 @@ scr_update(SCR *sp, db_recno_t lno, lnop_t op, int current)
 }
 
 /*
- * DB1->3 compatibility layer
+ * PUBLIC: void update_cache __P((SCR *sp, lnop_t op, db_recno_t lno));
  */
+void
+update_cache(SCR *sp, lnop_t op, db_recno_t lno)
+{
+       SCR* scrp;
+       EXF *ep;
 
-#include <assert.h>
-#include <stdlib.h>
-
-#undef O_SHLOCK
-#undef O_EXLOCK
-#include <fcntl.h>
-
-static int db1_close(DB *, u_int32_t);
-static int db1_open(DB *, const char *, const char *, DBTYPE, u_int32_t, int);
-static int db1_sync(DB *, u_int32_t);
-static int db1_get(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
-static int db1_put(DB *, DB_TXN *, DBT *, DBT *, u_int32_t);
-static int db1_set_flags(DB *, u_int32_t);
-static int db1_set_pagesize(DB *, u_int32_t);
-static int db1_set_re_delim(DB *, int);
-static int db1_set_re_source(DB *, const char *);
-
-int
-db_create(DB **dbp, DB_ENV *dbenv, u_int32_t flags) {
-       assert(dbenv == NULL && flags == 0);
-
-       *dbp = malloc(sizeof **dbp);
-       if (*dbp == NULL)
-               return -1;
-
-       (*dbp)->type = DB_UNKNOWN;
-       (*dbp)->actual_db = NULL;
-       (*dbp)->_pagesize = 0;
-       (*dbp)->_flags = 0;
-       memset(&(*dbp)->_recno_info, 0, sizeof (RECNOINFO));
-
-       (*dbp)->close = db1_close;
-       (*dbp)->open = db1_open;
-       (*dbp)->sync = db1_sync;
-       (*dbp)->get = db1_get;
-       (*dbp)->put = db1_put;
-       (*dbp)->set_flags = db1_set_flags;
-       (*dbp)->set_pagesize = db1_set_pagesize;
-       (*dbp)->set_re_delim = db1_set_re_delim;
-       (*dbp)->set_re_source = db1_set_re_source;
+       ep = sp->ep;
 
-       return 0;
-}
+       /* Flush the cache, update line count, before screen update. */
+       /* The flushing is probably not needed, since it was incorrect
+        * for db_insert.  It might be better to adjust it, like
+        * marks, @ and global
+        */
+       for (scrp = ep->scrq.cqh_first; scrp != (void *)&ep->scrq; 
+           scrp = scrp->eq.cqe_next)
+               switch (op) {
+               case LINE_INSERT:
+               case LINE_DELETE:
+                       if (lno <= scrp->c_lno)
+                               scrp->c_lno = OOBLNO;
+                       break;
+               case LINE_RESET:
+                       if (lno == scrp->c_lno)
+                               scrp->c_lno = OOBLNO;
+                       break;
+               }
 
-char *
-db_strerror(int error) {
-       return error > 0? strerror(error) : "record not found";
+       if (ep->c_nlines != OOBLNO)
+               switch (op) {
+               case LINE_INSERT:
+                       ++ep->c_nlines;
+                       break;
+               case LINE_DELETE:
+                       --ep->c_nlines;
+                       break;
+               }
 }
 
-static int
-db1_close(DB *db, u_int32_t flags) {
-       if (flags & DB_NOSYNC) {
-               /* XXX warn user? */
-       }
-       db->actual_db->close(db->actual_db);
-
-       db->type = DB_UNKNOWN;
-       db->actual_db = NULL;
-       db->_pagesize = 0;
-       db->_flags = 0;
-       memset(&db->_recno_info, 0, sizeof (RECNOINFO));
+/*
+ * PUBLIC: int db_msg_open __P((SCR *, char *, DB **));
+ */
+int db_msg_open(SCR *sp, char *file, DB **dbp)
+{
+       *dbp = dbopen(file, O_NONBLOCK | O_RDONLY, 0, DB_RECNO, NULL);
 
-       return 0;
+       return *dbp == NULL;
 }
 
-static int
-db1_open(DB *db, const char *file, const char *database, DBTYPE type,
-                                               u_int32_t flags, int mode) {
-       int oldflags = 0;
-
-       assert(database == NULL && !(flags & ~(DB_CREATE | DB_TRUNCATE)));
-
-       db->type = type;
-
-       if (flags & DB_CREATE)
-               oldflags |= O_CREAT;
-       if (flags & DB_TRUNCATE)
-               oldflags |= O_TRUNC;
-
-       if (type == DB_RECNO) {
-               char *tmp = (char *) file;
-
-               /* The interface is reversed in DB3 */
-               file = db->_recno_info.bfname;
-               db->_recno_info.bfname = tmp;
-
-               /* ... and so, we should avoid to truncate the main file! */
-               oldflags &= ~O_TRUNC;
-
-               db->_recno_info.flags =
-                       db->_flags & DB_SNAPSHOT? R_SNAPSHOT : 0;
-               db->_recno_info.psize = db->_pagesize;
+/*
+ * PUBLIC: int db_init __P((SCR *, EXF *, char *, char *, size_t, int *));
+ */
+int
+db_init(SCR *sp, EXF *ep, char *rcv_name, char *oname, size_t psize, int *open_err)
+{
+       RECNOINFO oinfo;
+
+       memset(&oinfo, 0, sizeof(RECNOINFO));
+       oinfo.bval = '\n';                      /* Always set. */
+       oinfo.psize = psize;
+       oinfo.flags = R_SNAPSHOT;
+       if (rcv_name)
+               oinfo.bfname = ep->rcv_path;
+
+#define _DB_OPEN_MODE  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+
+       ep->db = dbopen(rcv_name == NULL ? oname : NULL,
+           O_NONBLOCK | O_RDONLY, _DB_OPEN_MODE, DB_RECNO, &oinfo);
+       
+       if (!ep->db) {
+               msgq_str(sp,
+                   M_DBERR, rcv_name == NULL ? oname : rcv_name, "%s");
+               /*
+                * !!!
+                * Historically, vi permitted users to edit files that couldn't
+                * be read.  This isn't useful for single files from a command
+                * line, but it's quite useful for "vi *.c", since you can skip
+                * past files that you can't read.
+                */ 
+               ep->db = NULL; /* Don't close it; it wasn't opened */
+
+               *open_err = 1;
+               return 1;
        }
 
-       db->actual_db = dbopen(file, oldflags, mode, type,
-                               type == DB_RECNO? &db->_recno_info : NULL);
-
-       return db->actual_db == NULL? errno : 0;
-}
-
-static int
-db1_sync(DB *db, u_int32_t flags) {
-       assert(flags == 0);
-
-       return db->actual_db->sync(db->actual_db, db->type == DB_UNKNOWN?
-                                       R_RECNOSYNC : 0) == 0? 0 : errno;
-}
-
-static int
-db1_get(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) {
-       int err;
-
-       assert(flags == 0 && txnid == NULL);
-
-       err = db->actual_db->get(db->actual_db, key, data, flags);
-
-       return err == -1? errno : err;
-}
-
-static int
-db1_put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) {
-       int err;
-
-       assert(flags == 0 && txnid == NULL);
-
-       err = db->actual_db->put(db->actual_db, key, data, flags);
-
-       return err == -1? errno : err;
-}
-
-static int
-db1_set_flags(DB *db, u_int32_t flags) {
-       assert((flags & ~(DB_RENUMBER | DB_SNAPSHOT)) == 0);
-
-       /* Can't prevent renumbering from happening with DB1 */
-       assert((flags | db->_flags) & DB_RENUMBER);
-
-
-       db->_flags |= flags;
-
        return 0;
 }
 
-static int
-db1_set_pagesize(DB *db, u_int32_t pagesize) {
-       db->_pagesize = pagesize;
-
-       return 0;
-}
-
-static int
-db1_set_re_delim(DB *db, int re_delim) {
-       db->_recno_info.bval = re_delim;
-
-       return 0;
-}
-
-static int
-db1_set_re_source(DB *db, const char *re_source) {
-       db->_recno_info.bfname = (char *) re_source;
-
-       return 0;
+char *
+db_strerror(int error)
+{
+       return error > 0 ? strerror(error) : "record not found";
 }
index c1d6871..db85a26 100644 (file)
@@ -2,8 +2,46 @@ visrcdir= @srcdir@/..
 
 ACLOCAL_AMFLAGS = -I m4
 
+if BUNDLED_DB
+    DB_C = $(visrcdir)/common/vi_db1.c
+    DB_SRCS = \
+       $(visrcdir)/db.1.85/recno/rec_delete.c \
+       $(visrcdir)/db.1.85/recno/rec_get.c \
+       $(visrcdir)/db.1.85/recno/rec_put.c \
+       $(visrcdir)/db.1.85/recno/rec_utils.c \
+       $(visrcdir)/db.1.85/recno/rec_open.c \
+       $(visrcdir)/db.1.85/recno/rec_seq.c \
+       $(visrcdir)/db.1.85/recno/rec_close.c \
+       $(visrcdir)/db.1.85/recno/rec_search.c \
+       $(visrcdir)/db.1.85/db/db.c \
+       $(visrcdir)/db.1.85/btree/bt_debug.c \
+       $(visrcdir)/db.1.85/btree/bt_get.c \
+       $(visrcdir)/db.1.85/btree/bt_open.c \
+       $(visrcdir)/db.1.85/btree/bt_delete.c \
+       $(visrcdir)/db.1.85/btree/bt_put.c \
+       $(visrcdir)/db.1.85/btree/bt_overflow.c \
+       $(visrcdir)/db.1.85/btree/bt_close.c \
+       $(visrcdir)/db.1.85/btree/bt_page.c \
+       $(visrcdir)/db.1.85/btree/bt_split.c \
+       $(visrcdir)/db.1.85/btree/bt_search.c \
+       $(visrcdir)/db.1.85/btree/bt_utils.c \
+       $(visrcdir)/db.1.85/btree/bt_seq.c \
+       $(visrcdir)/db.1.85/btree/bt_conv.c \
+       $(visrcdir)/db.1.85/mpool/mpool.c \
+       $(visrcdir)/db.1.85/hash/hash_bigkey.c \
+       $(visrcdir)/db.1.85/hash/hash_log2.c \
+       $(visrcdir)/db.1.85/hash/hash.c \
+       $(visrcdir)/db.1.85/hash/hash_func.c \
+       $(visrcdir)/db.1.85/hash/hash_page.c \
+       $(visrcdir)/db.1.85/hash/hash_buf.c \
+       $(visrcdir)/db.1.85/hash/hsearch.c
+else
+    DB_C = $(visrcdir)/common/vi_db.c
+endif
+
 lib_LTLIBRARIES = libvi.la
 libvi_la_SOURCES = \
+       $(DB_SRCS) \
        $(visrcdir)/common/api.c \
        $(visrcdir)/common/conv.c \
        $(visrcdir)/common/conv.h \
@@ -12,7 +50,7 @@ libvi_la_SOURCES = \
        $(visrcdir)/common/args.h \
        $(visrcdir)/common/common.h \
        $(visrcdir)/common/cut.h \
-       $(visrcdir)/common/db.h \
+       $(visrcdir)/common/vi_db.h \
        $(visrcdir)/common/exf.h \
        $(visrcdir)/common/gs.h \
        $(visrcdir)/common/key.h \
@@ -85,7 +123,7 @@ libvi_la_SOURCES = \
        $(visrcdir)/vi/vi.h \
        $(visrcdir)/common/gs.c \
        $(visrcdir)/common/key.c \
-       $(visrcdir)/common/db.c \
+       $(DB_C) \
        $(visrcdir)/common/main.c \
        $(visrcdir)/common/mark.c \
        $(visrcdir)/common/msg.c \
@@ -148,8 +186,11 @@ EXTRA_libvi_la_SOURCES = \
        $(visrcdir)/regex/regex.h \
        $(visrcdir)/regex/regex2.h \
        $(visrcdir)/regex/utils.h \
+       $(visrcdir)/common/vi_db.c \
+       $(visrcdir)/common/vi_db1.c \
        $(visrcdir)/common/dldb.c \
        $(visrcdir)/common/log.c \
+       $(visrcdir)/common/log1.c \
        $(visrcdir)/common/log4.c \
        $(visrcdir)/clib/bsearch.c \
        $(visrcdir)/clib/env.c \
@@ -189,7 +230,7 @@ vi_SOURCES = \
        $(visrcdir)/cl/cl_term.c \
        $(visrcdir)/common/nothread.c
 vi_LDADD = libvi.la @perllibs@ @CURSLIBS@
-vi_CPPFLAGS = @CURSCPPFLAGS@ @perlldflags@ $(AM_CPPFLAGS)
+vi_CPPFLAGS = $(AM_CPPFLAGS) @CURSCPPFLAGS@ @perlldflags@
 vi_LDFLAGS = @CURSLDFLAGS@ @perlldflags@
 
 vi_ipc_SOURCES = \
@@ -243,7 +284,12 @@ vi_motif_CFLAGS = @XINCS@
 
 VI=-DVI=\"$(bindir)/`echo vi-ipc | sed '$(transform)'`\"
 CFLAGS=        $(OPTFLAG)
+if BUNDLED_DB
+AM_CPPFLAGS=    -D__DBINTERFACE_PRIVATE -I$(visrcdir)/db.1.85/include \
+                -D__REGEX_PRIVATE -I. -I$(visrcdir)/include $(VI)
+else
 AM_CPPFLAGS=    -D__REGEX_PRIVATE -I. -I$(visrcdir)/include $(VI)
+endif
 PERL=  @vi_cv_path_perl@
 PERLLIB=@vi_cv_perllib@
 SHRPENV=@shrpenv@
index bd720c9..1e62275 100644 (file)
@@ -96,8 +96,8 @@
 /* Define if your sprintf returns a pointer, not a length. */
 #undef SPRINTF_RET_CHARPNT
 
-/* Define when using db1 */
-#undef USE_DB1
+/* Define when using bundled db */
+#undef USE_BUNDLED_DB
 
 /* Define when using db4 logging */
 #undef USE_DB4_LOGGING
index f91c8fc..f0f9e60 100644 (file)
@@ -948,30 +948,45 @@ fi
 
 AC_ARG_WITH(db_type,
        [  --with-db=bundled|system Which db to use. ])
+
+dnl Check for DB 3
+AC_ARG_WITH(db_prefix,
+       [  --with-db-prefix=PFX    Path to db installation. ])
+
+AC_SUBST(DB_LDFLAGS)
+AC_SUBST(DB_CPPFLAGS)
+if test "x$with_db_prefix" != "x"; then
+       DB_LDFLAGS="-L$with_db_prefix/lib $LDFLAGS"
+       DB_CPPFLAGS="-I$with_db_prefix/include $CPPFLAGS"
+       with_db_type="system"
+fi
+
+AC_MSG_CHECKING(which db to use)
 case "$with_db_type" in
-"db1")
-       AC_MSG_WARN([Use of db1 is not officially supported.])
-       AC_DEFINE(USE_DB1)
-       ;;
 "system")
        ;;
 *)
        with_db_type="bundled"
        ;;
 esac
+AC_MSG_RESULT($with_db_type)
+AM_CONDITIONAL(BUNDLED_DB, test $with_db_type = bundled)
 
-dnl Check for DB 3
-AC_ARG_WITH(db_prefix,
-       [  --with-db-prefix=PFX    Path to db installation. ])
-
-SAVELDFLAGS="$LDFLAGS"
-if test "x$with_db_prefix" != "x"; then
-       LDFLAGS="-L$with_db_prefix/lib $LDFLAGS"
-       CPPFLAGS="-I$with_db_prefix/include $CPPFLAGS"
-fi
-if test "$with_db_type" != db1; then
+case "$with_db_type" in
+bundled)
+       AC_DEFINE(USE_BUNDLED_DB)
+       LIBOBJS="log1.o $LIBOBJS"
+       ;;
+system)
+       SAVELDFLAGS="$LDFLAGS"
        SAVELIBS="$LIBS"
 
+       if test "x$with_db_prefix" != "x"; then
+               LDFLAGS="-L$with_db_prefix/lib $LDFLAGS"
+               CPPFLAGS="-I$with_db_prefix/include $CPPFLAGS"
+               with_db_type="system"
+       fi
+
        LIBS="$LIBS -ldb"
        AC_TRY_LINK([#include <db.h>],
                [db_create(NULL,NULL,0)],
@@ -981,78 +996,79 @@ if test "$with_db_type" != db1; then
        fi
 
        LIBS="$SAVELIBS"
-fi
-LDFLAGS="$SAVELDFLAGS"
-
-AC_SUBST(dl_src)
-AC_MSG_CHECKING(if --enable-dynamic-loading option specified)
-AC_ARG_ENABLE(dynamic-loading,
-       [  --enable-dynamic-loading Load DB 3 dynamically.],
-       [vi_cv_dl=$enableval], [vi_cv_dl="no"])
-AC_MSG_RESULT($vi_cv_dl)
-if test "$vi_cv_dl" = yes; then
-       AC_CHECK_LIB(dl, dlopen,
-               [vi_cv_dlfatal="no"], [vi_cv_dlfatal="yes"])
-       if test "$vi_cv_dlfatal" = "yes"; then
-               AC_MSG_ERROR([Need dl to support dynamic loading.])
-       fi
-       OLDPATH="$PATH"
+       LDFLAGS="$SAVELDFLAGS"
 
-       PATH="$with_db_prefix/lib:/usr/lib:/lib"
-       AC_PATH_PROG(vi_cv_path_db3, libdb-3.so, no)
-       if test "$vi_cv_path_db3" = no; then
-               AC_MSG_ERROR([Path of libdb-3.so not found.])
-       fi
-       PATH="$OLDPATH"
+       AC_SUBST(dl_src)
+       AC_MSG_CHECKING(if --enable-dynamic-loading option specified)
+       AC_ARG_ENABLE(dynamic-loading,
+               [  --enable-dynamic-loading Load DB 3 dynamically.],
+               [vi_cv_dl=$enableval], [vi_cv_dl="no"])
+       AC_MSG_RESULT($vi_cv_dl)
+       if test "$vi_cv_dl" = yes; then
+               AC_CHECK_LIB(dl, dlopen,
+                       [vi_cv_dlfatal="no"], [vi_cv_dlfatal="yes"])
+               if test "$vi_cv_dlfatal" = "yes"; then
+                       AC_MSG_ERROR([Need dl to support dynamic loading.])
+               fi
+               OLDPATH="$PATH"
 
-       AC_DEFINE(USE_DYNAMIC_LOADING)
-       LIBOBJS="dldb.o $LIBOBJS"
-       dl_src=../common/dldb.c
-       LIBS="-ldl $LIBS"
-else
-       LIBS="-ldb $LIBS"
-       if test "X$with_db_prefix" != "X"; then
-               LDFLAGS="`echo $with_db_prefix/lib | sed "$LRscript"` $LDFLAGS"
+               PATH="$with_db_prefix/lib:/usr/lib:/lib"
+               AC_PATH_PROG(vi_cv_path_db3, libdb-3.so, no)
+               if test "$vi_cv_path_db3" = no; then
+                       AC_MSG_ERROR([Path of libdb-3.so not found.])
+               fi
+               PATH="$OLDPATH"
+
+               AC_DEFINE(USE_DYNAMIC_LOADING)
+               LIBOBJS="dldb.o $LIBOBJS"
+               dl_src=../common/dldb.c
+               LIBS="-ldl $LIBS"
+       else
+               LIBS="-ldb $LIBS"
+               if test "X$with_db_prefix" != "X"; then
+                       LDFLAGS="`echo $with_db_prefix/lib | sed "$LRscript"` $LDFLAGS"
+               fi
        fi
-fi
 
-AC_ARG_WITH(db_build,
-       [  --with-db-build=prefix  Path to db build. ])
-if test "x$with_db_build" != "x"; then
-       vi_cv_dbsrc=`$AWK '/^srcdir/ {gsub("srcdir[[ \t]]*=","");print $1}' \
-                    $with_db_build/Makefile`
-       case $with_db_build in
-       *[[\\/]]);;
-       *)
-           with_db_build="$with_db_build/";;
-       esac
-       case $vi_cv_dbsrc in
-       [[\\/]]*);;
-       *)
-           vi_cv_dbsrc="$with_db_build$vi_cv_dbsrc";;
-       esac
-fi;
-
-vi_cv_db4="no"
-AC_ARG_ENABLE(log4,
-       [  --enable-db4-logging    Enable experimental/broken db4 logging.],
-       [
-       AC_MSG_CHECKING(for DB 4)
-       AC_EGREP_CPP([^4],
-               [#include <db.h>
-       DB_VERSION_MAJOR],
-               [vi_cv_db4="yes"], [vi_cv_db4="no"])
-       AC_MSG_RESULT($vi_cv_db4)
-       ])
-if test "$vi_cv_db4" = "yes"; then
-       CPPFLAGS="-I$vi_cv_dbsrc/include $CPPFLAGS"
-       CPPFLAGS="-I$vi_cv_dbsrc/include_auto $CPPFLAGS"
-       CPPFLAGS="-I$with_db_build $CPPFLAGS"
-       AC_DEFINE(USE_DB4_LOGGING)
-       LIBOBJS="log4.o vi_auto.o vi_rec.o $LIBOBJS"
-else
-       LIBOBJS="log.o $LIBOBJS"
-fi
+       AC_ARG_WITH(db_build,
+               [  --with-db-build=prefix  Path to db build. ])
+       if test "x$with_db_build" != "x"; then
+               vi_cv_dbsrc=`$AWK '/^srcdir/ {gsub("srcdir[[ \t]]*=","");print $1}' \
+                            $with_db_build/Makefile`
+               case $with_db_build in
+               *[[\\/]]);;
+               *)
+                   with_db_build="$with_db_build/";;
+               esac
+               case $vi_cv_dbsrc in
+               [[\\/]]*);;
+               *)
+                   vi_cv_dbsrc="$with_db_build$vi_cv_dbsrc";;
+               esac
+       fi;
+
+       vi_cv_db4="no"
+       AC_ARG_ENABLE(log4,
+               [  --enable-db4-logging    Enable experimental/broken db4 logging.],
+               [
+               AC_MSG_CHECKING(for DB 4)
+               AC_EGREP_CPP([^4],
+                       [#include <db.h>
+               DB_VERSION_MAJOR],
+                       [vi_cv_db4="yes"], [vi_cv_db4="no"])
+               AC_MSG_RESULT($vi_cv_db4)
+               ])
+       if test "$vi_cv_db4" = "yes"; then
+               DB_CPPFLAGS="-I$vi_cv_dbsrc/include $DB_CPPFLAGS"
+               DB_CPPFLAGS="-I$vi_cv_dbsrc/include_auto $DB_CPPFLAGS"
+               DB_CPPFLAGS="-I$with_db_build $DB_CPPFLAGS"
+               AC_DEFINE(USE_DB4_LOGGING)
+               LIBOBJS="log4.o vi_auto.o vi_rec.o $LIBOBJS"
+       else
+               LIBOBJS="log.o $LIBOBJS"
+       fi
+       ;;
+esac
 
 dnl We compile in nvi's RE routines unless the user specifies otherwise.
 AC_MSG_CHECKING(if --disable-re option specified)