Index: /branches/EMX/src/emx/bsd/curses/Makefile
===================================================================
--- /branches/EMX/src/emx/bsd/curses/Makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/Makefile	(revision 273)
@@ -0,0 +1,22 @@
+#	@(#)Makefile	5.10 (Berkeley) 6/24/90
+
+CC=	gcc -O
+CFLAGS= -I. -DOS2
+
+.c.o:
+	$(CC) -c $(CFLAGS) $<
+
+SRCS=	addbytes.c addch.c addstr.c box.c clear.c clrtobot.c clrtoeol.c \
+	cr_put.c cr_tty.c curses.c delch.c deleteln.c delwin.c endwin.c \
+	erase.c fullname.c getch.c getstr.c idlok.c id_subwi.c initscr.c \
+	insch.c insertln.c longname.c move.c mvprintw.c mvscanw.c mvwin.c \
+	newwin.c overlay.c overwrit.c printw.c putchar.c refresh.c scanw.c \
+	scroll.c touchola.c standout.c touchwin.c tstp.c unctrl.c os2.c
+MAN3=	curses.0
+
+OBJS=   $(SRCS:.c=.o)
+
+curses.a: $(OBJS)
+	-del $@
+	ar r $@ $(OBJS)
+	ar s $@
Index: /branches/EMX/src/emx/bsd/curses/addbytes.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/addbytes.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/addbytes.c	(revision 273)
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)addbytes.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine adds the character to the current position
+ *
+ */
+waddbytes(win, bytes, count)
+reg WINDOW	*win;
+reg char	*bytes;
+reg int		count;
+{
+#define	SYNCH_OUT()	{win->_cury = y; win->_curx = x;}
+#define	SYNCH_IN()	{y = win->_cury; x = win->_curx;}
+	reg int		x, y;
+	reg int		newx;
+
+	SYNCH_IN();
+	while (count--) {
+	    register int c;
+	    static char blanks[] = "        ";
+
+	    c = *bytes++;
+# ifdef FULLDEBUG
+	fprintf(outf, "ADDBYTES('%c') at (%d, %d)\n", c, y, x);
+# endif
+	    switch (c) {
+	      case '\t':
+		    SYNCH_OUT() /* not SYNCH_IN() */;
+		    if (waddbytes(win, blanks, 8-(x%8)) == ERR) {
+			return ERR;
+		    }
+		    SYNCH_IN() /* not SYNCH_OUT() */;
+		    break;
+
+	      default:
+# ifdef FULLDEBUG
+		    fprintf(outf, "ADDBYTES: 1: y = %d, x = %d, firstch = %d, lastch = %d\n", y, x, win->_firstch[y], win->_lastch[y]);
+# endif
+		    if (win->_flags & _STANDOUT)
+			    c |= _STANDOUT;
+		    {
+# ifdef	FULLDEBUG
+			    fprintf(outf, "ADDBYTES(%0.2o, %d, %d)\n", win, y, x);
+# endif
+			    if (win->_y[y][x] != c) {
+				    newx = x + win->_ch_off;
+				    if (win->_firstch[y] == _NOCHANGE) {
+					    win->_firstch[y] =
+							    win->_lastch[y] = newx;
+				    } else if (newx < win->_firstch[y])
+					    win->_firstch[y] = newx;
+				    else if (newx > win->_lastch[y])
+					    win->_lastch[y] = newx;
+# ifdef FULLDEBUG
+				    fprintf(outf, "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n",
+					    win->_firstch[y], win->_lastch[y],
+					    win->_firstch[y] - win->_ch_off,
+					    win->_lastch[y] - win->_ch_off);
+# endif
+			    }
+		    }
+		    win->_y[y][x++] = c;
+		    if (x >= win->_maxx) {
+			    x = 0;
+    newline:
+			    if (++y >= win->_maxy)
+				    if (win->_scroll) {
+					    --y;
+					    SYNCH_OUT();
+					    scroll(win);
+					    SYNCH_IN();
+				    }
+				    else
+					    return ERR;
+		    }
+# ifdef FULLDEBUG
+		    fprintf(outf, "ADDBYTES: 2: y = %d, x = %d, firstch = %d, lastch = %d\n", y, x, win->_firstch[y], win->_lastch[y]);
+# endif
+		    break;
+	      case '\n':
+		    SYNCH_OUT();
+		    wclrtoeol(win);
+		    SYNCH_IN();
+		    if (!NONL)
+			    x = 0;
+		    goto newline;
+	      case '\r':
+		    x = 0;
+		    break;
+	      case '\b':
+		    if (--x < 0)
+			    x = 0;
+		    break;
+	    }
+    }
+    SYNCH_OUT();
+    return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/addch.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/addch.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/addch.c	(revision 273)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)addch.c	5.5 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine adds the character to the current position
+ *
+ */
+waddch(win, c)
+WINDOW	*win;
+char		c;
+{
+    return waddbytes(win, &c, 1);
+}
Index: /branches/EMX/src/emx/bsd/curses/addstr.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/addstr.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/addstr.c	(revision 273)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)addstr.c	5.5 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine adds a string starting at (_cury,_curx)
+ *
+ */
+waddstr(win,str)
+reg WINDOW	*win;
+reg char	*str;
+{
+# ifdef DEBUG
+	fprintf(outf, "WADDSTR(\"%s\")\n", str);
+# endif
+	return waddbytes(win, str, strlen(str));
+}
Index: /branches/EMX/src/emx/bsd/curses/box.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/box.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/box.c	(revision 273)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)box.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine draws a box around the given window with "vert"
+ * as the vertical delimiting char, and "hor", as the horizontal one.
+ *
+ */
+box(win, vert, hor)
+reg WINDOW	*win;
+char		vert, hor; {
+
+	reg int		i;
+	reg int		endy, endx;
+	reg char	*fp, *lp;
+
+	endx = win->_maxx;
+	endy = win->_maxy - 1;
+	fp = win->_y[0];
+	lp = win->_y[endy];
+	for (i = 0; i < endx; i++)
+		fp[i] = lp[i] = hor;
+	endx--;
+	for (i = 0; i <= endy; i++)
+		win->_y[i][0] = (win->_y[i][endx] = vert);
+	if (!win->_scroll && (win->_flags&_SCROLLWIN))
+		fp[0] = fp[endx] = lp[0] = lp[endx] = ' ';
+	touchwin(win);
+}
Index: /branches/EMX/src/emx/bsd/curses/clear.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/clear.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/clear.c	(revision 273)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)clear.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine clears the window.
+ *
+ */
+wclear(win)
+reg WINDOW	*win; {
+
+	werase(win);
+	win->_clear = TRUE;
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/clrtobot.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/clrtobot.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/clrtobot.c	(revision 273)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)clrtobot.c	5.5 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine erases everything on the window.
+ *
+ */
+wclrtobot(win)
+reg WINDOW	*win; {
+
+	reg int		y;
+	reg char	*sp, *end, *maxx;
+	reg int		startx, minx;
+
+	startx = win->_curx;
+	for (y = win->_cury; y < win->_maxy; y++) {
+		minx = _NOCHANGE;
+		end = &win->_y[y][win->_maxx];
+		for (sp = &win->_y[y][startx]; sp < end; sp++)
+			if (*sp != ' ') {
+				maxx = sp;
+				if (minx == _NOCHANGE)
+					minx = sp - win->_y[y];
+				*sp = ' ';
+			}
+		if (minx != _NOCHANGE)
+			touchline(win, y, minx, maxx - &win->_y[y][0]);
+		startx = 0;
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/clrtoeol.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/clrtoeol.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/clrtoeol.c	(revision 273)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)clrtoeol.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine clears up to the end of line
+ *
+ */
+wclrtoeol(win)
+reg WINDOW	*win; {
+
+	reg char	*sp, *end;
+	reg int		y, x;
+	reg char	*maxx;
+	reg int		minx;
+
+	y = win->_cury;
+	x = win->_curx;
+	end = &win->_y[y][win->_maxx];
+	minx = _NOCHANGE;
+	maxx = &win->_y[y][x];
+	for (sp = maxx; sp < end; sp++)
+		if (*sp != ' ') {
+			maxx = sp;
+			if (minx == _NOCHANGE)
+				minx = sp - win->_y[y];
+			*sp = ' ';
+		}
+	/*
+	 * update firstch and lastch for the line
+	 */
+	touchline(win, y, win->_curx, win->_maxx - 1);
+# ifdef DEBUG
+	fprintf(outf, "CLRTOEOL: minx = %d, maxx = %d, firstch = %d, lastch = %d\n", minx, maxx - win->_y[y], win->_firstch[y], win->_lastch[y]);
+# endif
+}
Index: /branches/EMX/src/emx/bsd/curses/cr_put.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/cr_put.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/cr_put.c	(revision 273)
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cr_put.c	5.5 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+# define	HARDTABS	8
+
+extern char	*tgoto();
+int		plodput();
+
+/*
+ * Terminal driving and line formatting routines.
+ * Basic motion optimizations are done here as well
+ * as formatting of lines (printing of control characters,
+ * line numbering and the like).
+ */
+
+/*
+ * Sync the position of the output cursor.
+ * Most work here is rounding for terminal boundaries getting the
+ * column position implied by wraparound or the lack thereof and
+ * rolling up the screen to get destline on the screen.
+ */
+
+static int	outcol, outline, destcol, destline;
+
+WINDOW		*_win;
+
+mvcur(ly, lx, y, x)
+int	ly, lx, y, x; {
+
+#ifdef DEBUG
+	fprintf(outf, "MVCUR: moving cursor from (%d,%d) to (%d,%d)\n", ly, lx, y, x);
+#endif
+	destcol = x;
+	destline = y;
+	outcol = lx;
+	outline = ly;
+	fgoto();
+}
+
+fgoto()
+{
+	reg char	*cgp;
+	reg int		l, c;
+
+	if (destcol >= COLS) {
+		destline += destcol / COLS;
+		destcol %= COLS;
+	}
+	if (outcol >= COLS) {
+		l = (outcol + 1) / COLS;
+		outline += l;
+		outcol %= COLS;
+		if (AM == 0) {
+			while (l > 0) {
+				if (_pfast)
+					if (CR)
+						_puts(CR);
+					else
+						_putchar('\r');
+				if (NL)
+					_puts(NL);
+				else
+					_putchar('\n');
+				l--;
+			}
+			outcol = 0;
+		}
+		if (outline > LINES - 1) {
+			destline -= outline - (LINES - 1);
+			outline = LINES - 1;
+		}
+	}
+	if (destline >= LINES) {
+		l = destline;
+		destline = LINES - 1;
+		if (outline < LINES - 1) {
+			c = destcol;
+			if (_pfast == 0 && !CA)
+				destcol = 0;
+			fgoto();
+			destcol = c;
+		}
+		while (l >= LINES) {
+			/*
+			 * The following linefeed (or simulation thereof)
+			 * is supposed to scroll up the screen, since we
+			 * are on the bottom line.  We make the assumption
+			 * that linefeed will scroll.  If ns is in the
+			 * capability list this won't work.  We should
+			 * probably have an sc capability but sf will
+			 * generally take the place if it works.
+			 *
+			 * Superbee glitch:  in the middle of the screen we
+			 * have to use esc B (down) because linefeed screws up
+			 * in "Efficient Paging" (what a joke) mode (which is
+			 * essential in some SB's because CRLF mode puts garbage
+			 * in at end of memory), but you must use linefeed to
+			 * scroll since down arrow won't go past memory end.
+			 * I turned this off after recieving Paul Eggert's
+			 * Superbee description which wins better.
+			 */
+			if (NL /* && !XB */ && _pfast)
+				_puts(NL);
+			else
+				_putchar('\n');
+			l--;
+			if (_pfast == 0)
+				outcol = 0;
+		}
+	}
+	if (destline < outline && !(CA || UP))
+		destline = outline;
+	if (CA) {
+		cgp = tgoto(CM, destcol, destline);
+		if (plod(strlen(cgp)) > 0)
+			plod(0);
+		else
+			tputs(cgp, 0, _putchar);
+	}
+	else
+		plod(0);
+	outline = destline;
+	outcol = destcol;
+}
+
+/*
+ * Move (slowly) to destination.
+ * Hard thing here is using home cursor on really deficient terminals.
+ * Otherwise just use cursor motions, hacking use of tabs and overtabbing
+ * and backspace.
+ */
+
+static int plodcnt, plodflg;
+
+plodput(c)
+{
+	if (plodflg)
+		plodcnt--;
+	else
+		_putchar(c);
+}
+
+plod(cnt)
+{
+	register int i, j, k;
+	register int soutcol, soutline;
+
+	plodcnt = plodflg = cnt;
+	soutcol = outcol;
+	soutline = outline;
+	/*
+	 * Consider homing and moving down/right from there, vs moving
+	 * directly with local motions to the right spot.
+	 */
+	if (HO) {
+		/*
+		 * i is the cost to home and tab/space to the right to
+		 * get to the proper column.  This assumes ND space costs
+		 * 1 char.  So i+destcol is cost of motion with home.
+		 */
+		if (GT)
+			i = (destcol / HARDTABS) + (destcol % HARDTABS);
+		else
+			i = destcol;
+		/*
+		 * j is cost to move locally without homing
+		 */
+		if (destcol >= outcol) {	/* if motion is to the right */
+			j = destcol / HARDTABS - outcol / HARDTABS;
+			if (GT && j)
+				j += destcol % HARDTABS;
+			else
+				j = destcol - outcol;
+		}
+		else
+			/* leftward motion only works if we can backspace. */
+			if (outcol - destcol <= i && (BS || BC))
+				i = j = outcol - destcol; /* cheaper to backspace */
+			else
+				j = i + 1; /* impossibly expensive */
+
+		/* k is the absolute value of vertical distance */
+		k = outline - destline;
+		if (k < 0)
+			k = -k;
+		j += k;
+
+		/*
+		 * Decision.  We may not have a choice if no UP.
+		 */
+		if (i + destline < j || (!UP && destline < outline)) {
+			/*
+			 * Cheaper to home.  Do it now and pretend it's a
+			 * regular local motion.
+			 */
+			tputs(HO, 0, plodput);
+			outcol = outline = 0;
+		}
+		else if (LL) {
+			/*
+			 * Quickly consider homing down and moving from there.
+			 * Assume cost of LL is 2.
+			 */
+			k = (LINES - 1) - destline;
+			if (i + k + 2 < j && (k<=0 || UP)) {
+				tputs(LL, 0, plodput);
+				outcol = 0;
+				outline = LINES - 1;
+			}
+		}
+	}
+	else
+	/*
+	 * No home and no up means it's impossible.
+	 */
+		if (!UP && destline < outline)
+			return -1;
+	if (GT)
+		i = destcol % HARDTABS + destcol / HARDTABS;
+	else
+		i = destcol;
+/*
+	if (BT && outcol > destcol && (j = (((outcol+7) & ~7) - destcol - 1) >> 3)) {
+		j *= (k = strlen(BT));
+		if ((k += (destcol&7)) > 4)
+			j += 8 - (destcol&7);
+		else
+			j += k;
+	}
+	else
+*/
+		j = outcol - destcol;
+	/*
+	 * If we will later need a \n which will turn into a \r\n by
+	 * the system or the terminal, then don't bother to try to \r.
+	 */
+	if ((NONL || !_pfast) && outline < destline)
+		goto dontcr;
+	/*
+	 * If the terminal will do a \r\n and there isn't room for it,
+	 * then we can't afford a \r.
+	 */
+	if (NC && outline >= destline)
+		goto dontcr;
+	/*
+	 * If it will be cheaper, or if we can't back up, then send
+	 * a return preliminarily.
+	 */
+	if (j > i + 1 || outcol > destcol && !BS && !BC) {
+		/*
+		 * BUG: this doesn't take the (possibly long) length
+		 * of CR into account.
+		 */
+		if (CR)
+			tputs(CR, 0, plodput);
+		else
+			plodput('\r');
+		if (NC) {
+			if (NL)
+				tputs(NL, 0, plodput);
+			else
+				plodput('\n');
+			outline++;
+		}
+		outcol = 0;
+	}
+dontcr:
+	while (outline < destline) {
+		outline++;
+		if (NL)
+			tputs(NL, 0, plodput);
+		else
+			plodput('\n');
+		if (plodcnt < 0)
+			goto out;
+		if (NONL || _pfast == 0)
+			outcol = 0;
+	}
+	if (BT)
+		k = strlen(BT);
+	while (outcol > destcol) {
+		if (plodcnt < 0)
+			goto out;
+/*
+		if (BT && outcol - destcol > k + 4) {
+			tputs(BT, 0, plodput);
+			outcol--;
+			outcol &= ~7;
+			continue;
+		}
+*/
+		outcol--;
+		if (BC)
+			tputs(BC, 0, plodput);
+		else
+			plodput('\b');
+	}
+	while (outline > destline) {
+		outline--;
+		tputs(UP, 0, plodput);
+		if (plodcnt < 0)
+			goto out;
+	}
+	if (GT && destcol - outcol > 1) {
+		for (;;) {
+			i = tabcol(outcol, HARDTABS);
+			if (i > destcol)
+				break;
+			if (TA)
+				tputs(TA, 0, plodput);
+			else
+				plodput('\t');
+			outcol = i;
+		}
+		if (destcol - outcol > 4 && i < COLS && (BC || BS)) {
+			if (TA)
+				tputs(TA, 0, plodput);
+			else
+				plodput('\t');
+			outcol = i;
+			while (outcol > destcol) {
+				outcol--;
+				if (BC)
+					tputs(BC, 0, plodput);
+				else
+					plodput('\b');
+			}
+		}
+	}
+	while (outcol < destcol) {
+		/*
+		 * move one char to the right.  We don't use ND space
+		 * because it's better to just print the char we are
+		 * moving over.
+		 */
+		if (_win != NULL)
+			if (plodflg)	/* avoid a complex calculation */
+				plodcnt--;
+			else {
+				i = curscr->_y[outline][outcol];
+				if ((i&_STANDOUT) == (curscr->_flags&_STANDOUT))
+					_putchar(i);
+				else
+					goto nondes;
+			}
+		else
+nondes:
+		     if (ND)
+			tputs(ND, 0, plodput);
+		else
+			plodput(' ');
+		outcol++;
+		if (plodcnt < 0)
+			goto out;
+	}
+out:
+	if (plodflg) {
+		outcol = soutcol;
+		outline = soutline;
+	}
+	return(plodcnt);
+}
+
+/*
+ * Return the column number that results from being in column col and
+ * hitting a tab, where tabs are set every ts columns.  Work right for
+ * the case where col > COLS, even if ts does not divide COLS.
+ */
+tabcol(col, ts)
+int col, ts;
+{
+	int offset, result;
+
+	if (col >= COLS) {
+		offset = COLS * (col / COLS);
+		col -= offset;
+	}
+	else
+		offset = 0;
+	return col + ts - (col % ts) + offset;
+}
Index: /branches/EMX/src/emx/bsd/curses/cr_tty.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/cr_tty.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/cr_tty.c	(revision 273)
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)cr_tty.c	5.8 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * Terminal initialization routines.
+ *
+ */
+
+# include	"curses.ext"
+
+static bool	*sflags[] = {
+			&AM, &BS, &DA, &DB, &EO, &HC, &HZ, &IN, &MI,
+			&MS, &NC, &NS, &OS, &UL, &XB, &XN, &XT, &XS,
+			&XX
+		};
+
+static char	*_PC,
+		**sstrs[] = {
+			&AL, &BC, &BT, &CD, &CE, &CL, &CM, &CR, &CS,
+			&DC, &DL, &DM, &DO, &ED, &EI, &K0, &K1, &K2,
+			&K3, &K4, &K5, &K6, &K7, &K8, &K9, &HO, &IC,
+			&IM, &IP, &KD, &KE, &KH, &KL, &KR, &KS, &KU,
+			&LL, &MA, &ND, &NL, &_PC, &RC, &SC, &SE, &SF,
+			&SO, &SR, &TA, &TE, &TI, &UC, &UE, &UP, &US,
+			&VB, &VS, &VE, &AL_PARM, &DL_PARM, &UP_PARM,
+			&DOWN_PARM, &LEFT_PARM, &RIGHT_PARM,
+		};
+
+extern char	*tgoto();
+
+char		_tspace[2048];		/* Space for capability strings */
+
+static char	*aoftspace;		/* Address of _tspace for relocation */
+
+static int	destcol, destline;
+
+/*
+ *	This routine does terminal type initialization routines, and
+ * calculation of flags at entry.  It is almost entirely stolen from
+ * Bill Joy's ex version 2.6.
+ */
+short	ospeed = -1;
+
+gettmode() {
+
+# ifdef OS2
+        ioctl (_tty_ch, TCGETA, &_tty);
+	savetty();
+	ospeed = B38400;
+	UPPERCASE = 0;
+	GT = ((_tty.c_iflag & IUCLC) == 0);
+	NONL = ((_tty.c_iflag & ICRNL) == 0);
+# else
+	if (ioctl(_tty_ch, TIOCGETP, &_tty) < 0)
+		return;
+	savetty();
+	if (ioctl(_tty_ch, TIOCSETP, &_tty) < 0)
+		_tty.sg_flags = _res_flg;
+	ospeed = _tty.sg_ospeed;
+	_res_flg = _tty.sg_flags;
+	UPPERCASE = (_tty.sg_flags & LCASE) != 0;
+	GT = ((_tty.sg_flags & XTABS) == 0);
+	NONL = ((_tty.sg_flags & CRMOD) == 0);
+	_tty.sg_flags &= ~XTABS;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+# endif
+# ifdef DEBUG
+	fprintf(outf, "GETTMODE: UPPERCASE = %s\n", UPPERCASE ? "TRUE":"FALSE");
+	fprintf(outf, "GETTMODE: GT = %s\n", GT ? "TRUE" : "FALSE");
+	fprintf(outf, "GETTMODE: NONL = %s\n", NONL ? "TRUE" : "FALSE");
+	fprintf(outf, "GETTMODE: ospeed = %d\n", ospeed);
+# endif
+}
+
+setterm(type)
+reg char	*type; {
+
+	reg int		unknown;
+	static char	genbuf[1024];
+# ifdef TIOCGWINSZ
+	struct winsize win;
+# endif
+
+# ifdef DEBUG
+	fprintf(outf, "SETTERM(\"%s\")\n", type);
+	fprintf(outf, "SETTERM: LINES = %d, COLS = %d\n", LINES, COLS);
+# endif
+	if (type[0] == '\0')
+		type = "xx";
+	unknown = FALSE;
+	if (tgetent(genbuf, type) != 1) {
+		unknown++;
+		strcpy(genbuf, "xx|dumb:");
+	}
+# ifdef DEBUG
+	fprintf(outf, "SETTERM: tty = %s\n", type);
+# endif
+# ifdef TIOCGWINSZ
+	if (ioctl(_tty_ch, TIOCGWINSZ, &win) >= 0) {
+		if (LINES == 0)
+			LINES = win.ws_row;
+		if (COLS == 0)
+			COLS = win.ws_col;
+	}
+# endif
+# ifdef OS2
+      {
+	int result[2];
+	_scrsize(result);
+	LINES = result[1];
+	COLS = result[0];
+      }
+# endif
+
+	if (LINES == 0)
+		LINES = tgetnum("li");
+	if (LINES <= 5)
+		LINES = 24;
+
+	if (COLS == 0)
+		COLS = tgetnum("co");
+	if (COLS <= 4)
+		COLS = 80;
+
+# ifdef DEBUG
+	fprintf(outf, "SETTERM: LINES = %d, COLS = %d\n", LINES, COLS);
+# endif
+	aoftspace = _tspace;
+	zap();			/* get terminal description		*/
+
+	/*
+	 * Handle funny termcap capabilities
+	 */
+	if (CS && SC && RC) AL=DL="";
+	if (AL_PARM && AL==NULL) AL="";
+	if (DL_PARM && DL==NULL) DL="";
+	if (IC && IM==NULL) IM="";
+	if (IC && EI==NULL) EI="";
+	if (!GT) BT=NULL;	/* If we can't tab, we can't backtab either */
+
+	if (tgoto(CM, destcol, destline)[0] == 'O')
+		CA = FALSE, CM = 0;
+	else
+		CA = TRUE;
+
+	PC = _PC ? _PC[0] : FALSE;
+	aoftspace = _tspace;
+	{
+		/* xtype should be the same size as genbuf for longname(). */
+		static char xtype[1024];
+
+		(void)strcpy(xtype,type);
+		strncpy(ttytype, longname(genbuf, xtype), sizeof(ttytype) - 1);
+	}
+	ttytype[sizeof(ttytype) - 1] = '\0';
+	if (unknown)
+		return ERR;
+	return OK;
+}
+
+/*
+ *	This routine gets all the terminal flags from the termcap database
+ */
+
+zap()
+{
+	register char	*namp;
+	register bool	**fp;
+	register char	***sp;
+#ifdef	DEBUG
+	register char	*cp;
+#endif
+	extern char	*tgetstr();
+	char flag[3];
+
+	namp = "ambsdadbeohchzinmimsncnsosulxbxnxtxsxx";
+	fp = sflags;
+	do {
+	        strncpy(flag, namp, 2);
+		flag[2] = 0;
+		*(*fp++) = tgetflag(flag);
+#ifdef DEBUG
+		fprintf(outf, "%2.2s = %s\n", namp, *fp[-1] ? "TRUE" : "FALSE");
+#endif
+		namp += 2;
+	} while (*namp);
+	namp = "albcbtcdceclcmcrcsdcdldmdoedeik0k1k2k3k4k5k6k7k8k9hoicimipkdkekhklkrkskullmandnlpcrcscsesfsosrtatetiucueupusvbvsveALDLUPDOLERI";
+	sp = sstrs;
+	do {
+		*(*sp++) = tgetstr(namp, &aoftspace);
+#ifdef DEBUG
+		fprintf(outf, "%2.2s = %s", namp, *sp[-1] == NULL ? "NULL\n" : "\"");
+		if (*sp[-1] != NULL) {
+			for (cp = *sp[-1]; *cp; cp++)
+				fprintf(outf, "%s", unctrl(*cp));
+			fprintf(outf, "\"\n");
+		}
+#endif
+		namp += 2;
+	} while (*namp);
+	if (XS)
+		SO = SE = NULL;
+	else {
+		if (tgetnum("sg") > 0)
+			SO = NULL;
+		if (tgetnum("ug") > 0)
+			US = NULL;
+		if (!SO && US) {
+			SO = US;
+			SE = UE;
+		}
+	}
+}
+
+/*
+ * return a capability from termcap
+ */
+char *
+getcap(name)
+char *name;
+{
+	char *tgetstr();
+
+	return tgetstr(name, &aoftspace);
+}
Index: /branches/EMX/src/emx/bsd/curses/curses.3
===================================================================
--- /branches/EMX/src/emx/bsd/curses/curses.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/curses.3	(revision 273)
@@ -0,0 +1,197 @@
+.\" Copyright (c) 1985, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"     @(#)curses.3	6.6 (Berkeley) 4/19/91
+.\"
+.Dd April 19, 1991
+.Dt CURSES 3
+.Os BSD 4
+.Sh NAME
+.Nm curses
+.Nd screen functions with ``optimal'' cursor motion
+.Sh SYNOPSIS
+.Nm cc
+.Op Ar flags
+.Ar files
+.Fl lcurses ltermcap
+.Op Ar libraries
+.Sh DESCRIPTION
+These routines give the user a method of updating screens with reasonable
+optimization.  They keep an image of the current screen,
+and the user sets up an image of a new one.  Then the
+.Fn refresh
+tells the routines to make the current screen look like the new one.
+In order to initialize the routines, the routine
+.Fn initscr
+must be called before any of the other routines that deal with windows and
+screens are used.  The routine
+.Fn endwin
+should be called before exiting.
+.Sh SEE ALSO
+.Xr ioctl 2 ,
+.Xr getenv 3 ,
+.Xr tty 4 ,
+.Xr termcap 5
+.Rs
+.%T Screen Updating and Cursor Movement Optimization: A Library Package
+.%A Ken Arnold
+.Re
+.Sh AUTHOR
+.An Ken Arnold
+.Sh FUNCTIONS
+.Bl -column "subwin(win,lines,cols,begin_y,begin_x)   "
+.It addch(ch)	add a character to
+.Em stdscr
+.It addstr(str)	add a string to
+.Em stdscr
+.It box(win,vert,hor)	draw a box around a window
+.It cbreak()	set cbreak mode
+.It clear()	clear
+.Em stdscr
+.It clearok(scr,boolf)	set clear flag for
+.Em scr
+.It clrtobot()	clear to bottom on
+.Em stdscr
+.It clrtoeol()	clear to end of line on
+.Em stdscr
+.It delch()	delete a character
+.It deleteln()	delete a line
+.It delwin(win)	delete
+.Em stdscr
+.It echo()	set echo mode
+.It endwin()	end window modes
+.It erase()	erase
+.Em stdscr
+.It flusok(win,boolf)	set flush-on-refresh flag for
+.Em win
+.It getch()	get a char through
+.Em stdscr
+.It getcap(name)	get terminal capability
+.Em name
+.It getstr(str)	get a string through
+.Em stdscr
+.It gettmode()	get tty modes
+.It getyx(win,y,x)	get (y,x) co-ordinates
+.It inch()	get char at current (y,x) co-ordinates
+.It initscr()	initialize screens
+.It insch(c)	insert a char
+.It insertln()	insert a line
+.It leaveok(win,boolf)	set leave flag for
+.Em stdscr
+.It longname(termbuf,name)	get long name from
+.Em termbuf
+.It move(y,x)	move to (y,x) on
+.Em stdscr
+.It mvcur(lasty,lastx,newy,newx)	actually move cursor
+.It newwin(lines,cols,begin_y,begin_x)\ 	create a new window
+.It nl()	set newline mapping
+.It nocbreak()	unset cbreak mode
+.It noecho()	unset echo mode
+.It nonl()	unset newline mapping
+.It noraw()	unset raw mode
+.It overlay(win1,win2)	overlay win1 on win2
+.It overwrite(win1,win2)	overwrite win1 on top of win2
+.It printw(fmt,arg1,arg2,...)	printf on
+.Em stdscr
+.It raw()	set raw mode
+.It refresh()	make current screen look like
+.Em stdscr
+.It resetty()	reset tty flags to stored value
+.It savetty()	stored current tty flags
+.It scanw(fmt,arg1,arg2,...)	scanf through
+.Em stdscr
+.It scroll(win)	scroll
+.Em win
+one line
+.It scrollok(win,boolf)	set scroll flag
+.It setterm(name)	set term variables for name
+.It standend()	end standout mode
+.It standout()	start standout mode
+.It subwin(win,lines,cols,begin_y,begin_x)\ 	create a subwindow
+.It touchline(win,y,sx,ex)	mark line
+.Em y
+.Em sx
+through
+.Em sy
+as changed
+.It touchoverlap(win1,win2)	mark overlap of
+.Em win1
+on
+.Em win2
+as changed
+.It touchwin(win)	\*(lqchange\*(rq all of
+.Em win
+.It unctrl(ch)	printable version of
+.Em ch
+.It waddch(win,ch)	add char to
+.Em win
+.It waddstr(win,str)	add string to
+.Em win
+.It wclear(win)	clear
+.Em win
+.It wclrtobot(win)	clear to bottom of
+.Em win
+.It wclrtoeol(win)	clear to end of line on
+.Em win
+.It wdelch(win,c)	delete char from
+.Em win
+.It wdeleteln(win)	delete line from
+.Em win
+.It werase(win)	erase
+.Em win
+.It wgetch(win)	get a char through
+.Em win
+.It wgetstr(win,str)	get a string through
+.Em win
+.It winch(win)	get char at current (y,x) in
+.Em win
+.It winsch(win,c)	insert char into
+.Em win
+.It winsertln(win)	insert line into
+.Em win
+.It wmove(win,y,x)	set current (y,x) co-ordinates on
+.Em win
+.It wprintw(win,fmt,arg1,arg2,...)\ 	printf on
+.Em win
+.It wrefresh(win)	make screen look like
+.Em win
+.It wscanw(win,fmt,arg1,arg2,...)\ 	scanf through
+.Em win
+.It wstandend(win)	end standout mode on
+.Em win
+.It wstandout(win)	start standout mode on
+.Em win
+.El
+.Sh HISTORY
+The
+.Nm
+package appeared in
+.Bx 4.0 .
Index: /branches/EMX/src/emx/bsd/curses/curses.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/curses.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/curses.c	(revision 273)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)curses.c	5.7 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * Define global variables
+ *
+ */
+# include	"curses.h"
+
+bool	_echoit		= TRUE,	/* set if stty indicates ECHO		*/
+	_rawmode	= FALSE,/* set if stty indicates RAW mode	*/
+	My_term		= FALSE,/* set if user specifies terminal type	*/
+	_endwin		= FALSE;/* set if endwin has been called	*/
+
+char	ttytype[50],		/* long name of tty			*/
+	*Def_term	= "unknown";	/* default terminal type	*/
+
+int	_tty_ch		= 0,	/* file channel which is a tty		*/
+	LINES,			/* number of lines allowed on screen	*/
+	COLS,			/* number of columns allowed on screen	*/
+	_res_flg;		/* sgtty flags for reseting later	*/
+
+WINDOW	*stdscr		= NULL,
+	*curscr		= NULL;
+
+# ifdef DEBUG
+FILE	*outf;			/* debug output file			*/
+# endif
+
+SGTTY	_tty;			/* tty modes				*/
+
+bool	AM, BS, CA, DA, DB, EO, HC, HZ, IN, MI, MS, NC, NS, OS, UL, XB, XN,
+	XT, XS, XX;
+char	*AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL, *DM,
+	*DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6, *K7, *K8,
+	*K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL, *KR, *KS, *KU,
+	*LL, *MA, *ND, *NL, *RC, *SC, *SE, *SF, *SO, *SR, *TA, *TE,
+	*TI, *UC, *UE, *UP, *US, *VB, *VS, *VE, *AL_PARM, *DL_PARM,
+	*UP_PARM, *DOWN_PARM, *LEFT_PARM, *RIGHT_PARM;
+char	PC;
+
+/*
+ * From the tty modes...
+ */
+
+bool	GT, NONL, UPPERCASE, normtty, _pfast;
Index: /branches/EMX/src/emx/bsd/curses/curses.ext
===================================================================
--- /branches/EMX/src/emx/bsd/curses/curses.ext	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/curses.ext	(revision 273)
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1981 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)curses.ext	5.6 (Berkeley) 4/19/91
+ */
+
+/*
+ * External variables for the curses library
+ */
+
+/* LINTLIBRARY */
+
+#include	"curses.h"
+
+extern bool	_echoit, _rawmode, My_term, _endwin;
+extern char	ttytype[50], *_unctrl[];
+extern int	_tty_ch, LINES, COLS;
+extern SGTTY	_tty;
+char		_putchar();
+
+#ifdef DEBUG
+# define	outf	_outf
+FILE		*outf;
+#endif
Index: /branches/EMX/src/emx/bsd/curses/curses.h
===================================================================
--- /branches/EMX/src/emx/bsd/curses/curses.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/curses.h	(revision 273)
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)curses.h	5.9 (Berkeley) 7/1/90
+ */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifndef WINDOW
+
+#include	<stdio.h>
+#include	<sys/ioctl.h>
+#include	<sys/termio.h>
+typedef	struct termio	SGTTY;
+
+#define	bool	char
+#define	reg	register
+
+#define	TRUE	(1)
+#define	FALSE	(0)
+#define	ERR	(0)
+#define	OK	(1)
+
+#define	_ENDLINE	001
+#define	_FULLWIN	002
+#define	_SCROLLWIN	004
+#define	_FLUSH		010
+#define	_FULLLINE	020
+#define	_IDLINE		040
+#define	_STANDOUT	0200
+#define	_NOCHANGE	-1
+
+#define	_puts(s)	tputs(s, 0, _putchar)
+
+/*
+ * Capabilities from termcap
+ */
+
+extern bool     AM, BS, CA, DA, DB, EO, HC, HZ, IN, MI, MS, NC, NS, OS, UL,
+		XB, XN, XT, XS, XX;
+extern char	*AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL,
+		*DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6,
+		*K7, *K8, *K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL,
+		*KR, *KS, *KU, *LL, *MA, *ND, *NL, *RC, *SC, *SE, *SF,
+		*SO, *SR, *TA, *TE, *TI, *UC, *UE, *UP, *US, *VB, *VS,
+		*VE, *AL_PARM, *DL_PARM, *UP_PARM, *DOWN_PARM,
+		*LEFT_PARM, *RIGHT_PARM;
+extern char	PC;
+
+/*
+ * From the tty modes...
+ */
+
+extern bool	GT, NONL, UPPERCASE, normtty, _pfast;
+
+struct _win_st {
+	short		_cury, _curx;
+	short		_maxy, _maxx;
+	short		_begy, _begx;
+	short		_flags;
+	short		_ch_off;
+	bool		_clear;
+	bool		_leave;
+	bool		_scroll;
+	char		**_y;
+	short		*_firstch;
+	short		*_lastch;
+	struct _win_st	*_nextp, *_orig;
+};
+
+#define	WINDOW	struct _win_st
+
+extern bool	My_term, _echoit, _rawmode, _endwin;
+extern char	*Def_term, ttytype[];
+extern int	LINES, COLS, _tty_ch, _res_flg;
+extern SGTTY	_tty;
+extern WINDOW	*stdscr, *curscr;
+
+#define	VOID(x)	(x)
+
+/*
+ * pseudo functions for standard screen
+ */
+#define	addch(ch)	VOID(waddch(stdscr, ch))
+#define	getch()		VOID(wgetch(stdscr))
+#define	addbytes(da,co)	VOID(waddbytes(stdscr, da,co))
+#define	addstr(str)	VOID(waddbytes(stdscr, str, strlen(str)))
+#define	getstr(str)	VOID(wgetstr(stdscr, str))
+#define	move(y, x)	VOID(wmove(stdscr, y, x))
+#define	clear()		VOID(wclear(stdscr))
+#define	erase()		VOID(werase(stdscr))
+#define	clrtobot()	VOID(wclrtobot(stdscr))
+#define	clrtoeol()	VOID(wclrtoeol(stdscr))
+#define	insertln()	VOID(winsertln(stdscr))
+#define	deleteln()	VOID(wdeleteln(stdscr))
+#define	refresh()	VOID(wrefresh(stdscr))
+#define	inch()		VOID(winch(stdscr))
+#define	insch(c)	VOID(winsch(stdscr,c))
+#define	delch()		VOID(wdelch(stdscr))
+#define	standout()	VOID(wstandout(stdscr))
+#define	standend()	VOID(wstandend(stdscr))
+
+/*
+ * mv functions
+ */
+#define	mvwaddch(win,y,x,ch)	VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch))
+#define	mvwgetch(win,y,x)	VOID(wmove(win,y,x)==ERR?ERR:wgetch(win))
+#define	mvwaddbytes(win,y,x,da,co) \
+		VOID(wmove(win,y,x)==ERR?ERR:waddbytes(win,da,co))
+#define	mvwaddstr(win,y,x,str) \
+		VOID(wmove(win,y,x)==ERR?ERR:waddbytes(win,str,strlen(str)))
+#define mvwgetstr(win,y,x,str)  VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
+#define	mvwinch(win,y,x)	VOID(wmove(win,y,x) == ERR ? ERR : winch(win))
+#define	mvwdelch(win,y,x)	VOID(wmove(win,y,x) == ERR ? ERR : wdelch(win))
+#define	mvwinsch(win,y,x,c)	VOID(wmove(win,y,x) == ERR ? ERR:winsch(win,c))
+#define	mvaddch(y,x,ch)		mvwaddch(stdscr,y,x,ch)
+#define	mvgetch(y,x)		mvwgetch(stdscr,y,x)
+#define	mvaddbytes(y,x,da,co)	mvwaddbytes(stdscr,y,x,da,co)
+#define	mvaddstr(y,x,str)	mvwaddstr(stdscr,y,x,str)
+#define mvgetstr(y,x,str)       mvwgetstr(stdscr,y,x,str)
+#define	mvinch(y,x)		mvwinch(stdscr,y,x)
+#define	mvdelch(y,x)		mvwdelch(stdscr,y,x)
+#define	mvinsch(y,x,c)		mvwinsch(stdscr,y,x,c)
+
+/*
+ * pseudo functions
+ */
+
+#define	clearok(win,bf)	 (win->_clear = bf)
+#define	leaveok(win,bf)	 (win->_leave = bf)
+#define	scrollok(win,bf) (win->_scroll = bf)
+#define flushok(win,bf)	 (bf ? (win->_flags |= _FLUSH):(win->_flags &= ~_FLUSH))
+#define	getyx(win,y,x)	 y = win->_cury, x = win->_curx
+#define	winch(win)	 (win->_y[win->_cury][win->_curx])
+
+#define crmode() cbreak()	/* backwards compatability */
+#define nocrmode() nocbreak()	/* backwards compatability */
+
+#define noraw()         _setraw(0)
+#define raw()           _setraw(1)
+#define nocbreak()      _setraw(2)
+#define cbreak()        _setraw(3)
+#define echo()          _setecho(1)
+#define noecho()        _setecho(0)
+#define nl()            _setnl(1)
+#define nonl()          _setnl(0)
+
+/*
+ * Used to be in unctrl.h.
+ */
+#define	unctrl(c)	_unctrl[(c) & 0377]
+extern char *_unctrl[];
+
+int baudrate (void);
+int box (WINDOW *win, int vert, int hor);
+int delwin (WINDOW *win);
+int endwin (void);
+int erasechar (void);
+char *getcap (char *name);
+int gettmode (void);
+WINDOW *initscr (void);
+int killchar (void);
+char *longname (char *bp, char *def);
+int mvcur (int ly, int lx, int y, int x);
+int mvprintw (int y, int x, const char *fmt, ...);
+int mvscanw (int y, int x, const char *fmt, ...);
+int mvwin (WINDOW *win, int by, int bx);
+int mvwprintw (WINDOW *win, int y, int x, const char *fmt, ...);
+int mvwscanw (WINDOW *win, int y, int x, const char *fmt, ...);
+WINDOW *newwin (int num_lines, int num_cols, int begy, int begx);
+int overlay (WINDOW *win1, WINDOW *win2);
+int overwrite (WINDOW *win1, WINDOW *win2);
+int printw (const char *fmt, ...);
+int resetty (void);
+int savetty (void);
+int scanw (const char *fmt, ...);
+int scroll (WINDOW *win);
+int setterm (char *type);
+WINDOW *subwin (WINDOW *orig, int num_lines, int num_cols, int begy, int begx);
+int touchline (WINDOW *win, int y, int sx, int ex);
+int touchwin (WINDOW *win);
+int waddbytes (reg WINDOW *win, reg char *bytes, reg int count);
+int waddch (WINDOW *win, int c);
+int waddstr (reg WINDOW *win, reg char *str);
+int wclear (WINDOW *win);
+int wclrtobot (WINDOW *win);
+int wclrtoeol (WINDOW *win);
+int wdelch (WINDOW *win);
+int wdeleteln (WINDOW *win);
+int werase (WINDOW *win);
+int wgetch (WINDOW *win);
+int wgetstr (WINDOW *win, char *str);
+int winsch (WINDOW *win, int c);
+int winsertln (WINDOW *win);
+int wmove (WINDOW *win, int y, int x);
+int wprintw (WINDOW *win, const char *fmt, ...);
+int wrefresh (WINDOW *win);
+int wscanw (WINDOW *win, const char *fmt, ...);
+char *wstandend (WINDOW *win);
+char *wstandout (WINDOW *win);
+char _putchar (int c);
+int _setecho (int on);
+int _setnl (int on);
+int _setraw (int on);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
Index: /branches/EMX/src/emx/bsd/curses/delch.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/delch.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/delch.c	(revision 273)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)delch.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine performs an insert-char on the line, leaving
+ * (_cury,_curx) unchanged.
+ *
+ */
+wdelch(win)
+reg WINDOW	*win; {
+
+	reg char	*temp1, *temp2;
+	reg char	*end;
+	reg int		lch;
+
+	end = &win->_y[win->_cury][win->_maxx - 1];
+	temp1 = &win->_y[win->_cury][win->_curx];
+	temp2 = temp1 + 1;
+	while (temp1 < end)
+		*temp1++ = *temp2++;
+	*temp1 = ' ';
+	touchline(win, win->_cury, win->_curx, win->_maxx - 1);
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/deleteln.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/deleteln.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/deleteln.c	(revision 273)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)deleteln.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine deletes a line from the screen.  It leaves
+ * (_cury,_curx) unchanged.
+ *
+ */
+wdeleteln(win)
+reg WINDOW	*win;
+{
+	reg char	*temp;
+	reg int		y;
+	reg char	*end;
+	reg int		x;
+
+# ifdef DEBUG
+	fprintf(outf, "DELETELN(%0.2o)\n", win);
+# endif
+	temp = win->_y[win->_cury];
+	for (y = win->_cury; y < win->_maxy - 1; y++) {
+		if (win->_orig == NULL)
+			win->_y[y] = win->_y[y + 1];
+		else
+			bcopy(win->_y[y + 1], win->_y[y], win->_maxx);
+		touchline(win, y, 0, win->_maxx - 1);
+	}
+	if (win->_orig == NULL)
+		win->_y[y] = temp;
+	else
+		temp = win->_y[y];
+	for (end = &temp[win->_maxx]; temp < end; )
+		*temp++ = ' ';
+	touchline(win, win->_cury, 0, win->_maxx - 1);
+	if (win->_orig == NULL)
+		_id_subwins(win);
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/delwin.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/delwin.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/delwin.c	(revision 273)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)delwin.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine deletes a window and releases it back to the system.
+ *
+ */
+delwin(win)
+reg WINDOW	*win; {
+
+	reg int		i;
+	reg WINDOW	*wp, *np;
+
+	if (win->_orig == NULL) {
+		/*
+		 * If we are the original window, delete the space for
+		 * all the subwindows, and the array of space as well.
+		 */
+		for (i = 0; i < win->_maxy && win->_y[i]; i++)
+			free(win->_y[i]);
+		free(win->_firstch);
+		free(win->_lastch);
+		wp = win->_nextp;
+		while (wp != win) {
+			np = wp->_nextp;
+			delwin(wp);
+			wp = np;
+		}
+	}
+	else {
+		/*
+		 * If we are a subwindow, take ourselves out of the
+		 * list.  NOTE: if we are a subwindow, the minimum list
+		 * is orig followed by this subwindow, so there are
+		 * always at least two windows in the list.
+		 */
+		for (wp = win->_nextp; wp->_nextp != win; wp = wp->_nextp)
+			continue;
+		wp->_nextp = win->_nextp;
+	}
+	free(win->_y);
+	free(win);
+}
Index: /branches/EMX/src/emx/bsd/curses/endwin.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/endwin.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/endwin.c	(revision 273)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)endwin.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * Clean things up before exiting
+ *
+ */
+
+# include	"curses.ext"
+
+endwin()
+{
+	resetty();
+	_puts(VE);
+	_puts(TE);
+	if (curscr) {
+		if (curscr->_flags & _STANDOUT) {
+			_puts(SE);
+			curscr->_flags &= ~_STANDOUT;
+		}
+		_endwin = TRUE;
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/erase.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/erase.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/erase.c	(revision 273)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)erase.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine erases everything on the window.
+ *
+ */
+werase(win)
+reg WINDOW	*win; {
+
+	reg int		y;
+	reg char	*sp, *end, *start, *maxx;
+	reg int		minx;
+
+# ifdef DEBUG
+	fprintf(outf, "WERASE(%0.2o)\n", win);
+# endif
+	for (y = 0; y < win->_maxy; y++) {
+		minx = _NOCHANGE;
+		start = win->_y[y];
+		end = &start[win->_maxx];
+		for (sp = start; sp < end; sp++)
+			if (*sp != ' ') {
+				maxx = sp;
+				if (minx == _NOCHANGE)
+					minx = sp - start;
+				*sp = ' ';
+			}
+		if (minx != _NOCHANGE)
+			touchline(win, y, minx, maxx - win->_y[y]);
+	}
+	win->_curx = win->_cury = 0;
+}
Index: /branches/EMX/src/emx/bsd/curses/fullname.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/fullname.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/fullname.c	(revision 273)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)fullname.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# define	reg	register
+
+/*
+ *	This routine fills in "def" with the full name of the terminal.
+ * This is assumed to be the last name in the list of aliases.
+ *
+ */
+char *
+fullname(bp, def)
+reg char	*bp, *def;
+{
+
+	reg char	*cp;
+
+	*def = 0;			/* in case no name */
+
+	while (*bp && *bp != ':') {
+		cp = def;		/* start of answer */
+		while (*bp && *bp != ':' && *bp != '|') {
+			*cp++ = *bp++;	/* copy name over */
+		}
+		*cp = 0;		/* zero end of name */
+		if (*bp == '|') {
+			bp++;		/* skip over '|' if that is case */
+		}
+	}
+	return(def);
+}
Index: /branches/EMX/src/emx/bsd/curses/getch.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/getch.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/getch.c	(revision 273)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)getch.c	5.6 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine reads in a character from the window.
+ *
+ */
+wgetch(win)
+reg WINDOW	*win; {
+
+	reg bool	weset = FALSE;
+	reg char	inp;
+
+	if (!win->_scroll && (win->_flags&_FULLWIN)
+	    && win->_curx == win->_maxx - 1 && win->_cury == win->_maxy - 1)
+		return ERR;
+# ifdef DEBUG
+	fprintf(outf, "WGETCH: _echoit = %c, _rawmode = %c\n", _echoit ? 'T' : 'F', _rawmode ? 'T' : 'F');
+# endif
+        fflush(stdout);
+	if (_echoit && !_rawmode) {
+		cbreak();
+		weset++;
+	}
+	inp = getchar();
+# ifdef DEBUG
+	fprintf(outf,"WGETCH got '%s'\n",unctrl(inp));
+# endif
+	if (_echoit) {
+		mvwaddch(curscr, win->_cury + win->_begy,
+			win->_curx + win->_begx, inp);
+		waddch(win, inp);
+	}
+	if (weset)
+		nocbreak();
+	return inp;
+}
Index: /branches/EMX/src/emx/bsd/curses/getstr.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/getstr.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/getstr.c	(revision 273)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)getstr.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine gets a string starting at (_cury,_curx)
+ *
+ */
+wgetstr(win,str)
+reg WINDOW	*win;
+reg char	*str; {
+
+	while ((*str = wgetch(win)) != ERR && *str != '\n')
+		str++;
+	if (*str == ERR) {
+		*str = '\0';
+		return ERR;
+	}
+	*str = '\0';
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/id_subwi.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/id_subwi.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/id_subwi.c	(revision 273)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)id_subwins.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ * _id_subwins:
+ *	Re-sync the pointers to _y for all the subwindows.
+ *
+ */
+_id_subwins(orig)
+register WINDOW	*orig;
+{
+	register WINDOW	*win;
+	register int	realy;
+	register int	y, oy, x;
+
+	realy = orig->_begy + orig->_cury;
+	for (win = orig->_nextp; win != orig; win = win->_nextp) {
+		/*
+		 * If the window ends before our current position,
+		 * don't need to do anything.
+		 */
+		if (win->_begy + win->_maxy <= realy)
+			continue;
+
+		oy = orig->_cury;
+		for (y = realy - win->_begy; y < win->_maxy; y++, oy++)
+			win->_y[y] = &orig->_y[oy][win->_ch_off];
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/idlok.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/idlok.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/idlok.c	(revision 273)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)idlok.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ * idlok:
+ *	Turn on and off using insert/deleteln sequences for the given
+ *	window.
+ *
+ */
+idlok(win, bf)
+register WINDOW	*win;
+bool		bf;
+{
+	if (bf)
+		win->_flags |= _IDLINE;
+	else
+		win->_flags &= ~_IDLINE;
+}
Index: /branches/EMX/src/emx/bsd/curses/initscr.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/initscr.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/initscr.c	(revision 273)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)initscr.c	5.6 (Berkeley) 3/3/91";
+#endif /* not lint */
+
+# include	"curses.ext"
+# include	<signal.h>
+
+extern char	*getenv();
+
+/*
+ *	This routine initializes the current and standard screen.
+ *
+ */
+WINDOW *
+initscr() {
+
+	reg char	*sp;
+	void		tstp();
+
+# ifdef DEBUG
+	fprintf(outf, "INITSCR()\n");
+# endif
+	if (My_term)
+		setterm(Def_term);
+	else {
+		gettmode();
+		if ((sp = getenv("TERM")) == NULL)
+			sp = Def_term;
+		setterm(sp);
+# ifdef DEBUG
+		fprintf(outf, "INITSCR: term = %s\n", sp);
+# endif
+	}
+	_puts(TI);
+	_puts(VS);
+# ifdef SIGTSTP
+	signal(SIGTSTP, tstp);
+# endif
+	if (curscr != NULL) {
+# ifdef DEBUG
+		fprintf(outf, "INITSCR: curscr = 0%o\n", curscr);
+# endif
+		delwin(curscr);
+	}
+# ifdef DEBUG
+	fprintf(outf, "LINES = %d, COLS = %d\n", LINES, COLS);
+# endif
+	if ((curscr = newwin(LINES, COLS, 0, 0)) == ERR)
+		return ERR;
+	clearok(curscr, TRUE);
+	curscr->_flags &= ~_FULLLINE;
+	if (stdscr != NULL) {
+# ifdef DEBUG
+		fprintf(outf, "INITSCR: stdscr = 0%o\n", stdscr);
+# endif
+		delwin(stdscr);
+	}
+	stdscr = newwin(LINES, COLS, 0, 0);
+	return stdscr;
+}
Index: /branches/EMX/src/emx/bsd/curses/insch.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/insch.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/insch.c	(revision 273)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)insch.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine performs an insert-char on the line, leaving
+ * (_cury,_curx) unchanged.
+ *
+ */
+winsch(win, c)
+reg WINDOW	*win;
+char		c; {
+
+	reg char	*temp1, *temp2;
+	reg char	*end;
+
+	end = &win->_y[win->_cury][win->_curx];
+	temp1 = &win->_y[win->_cury][win->_maxx - 1];
+	temp2 = temp1 - 1;
+	while (temp1 > end)
+		*temp1-- = *temp2--;
+	*temp1 = c;
+	touchline(win, win->_cury, win->_curx, win->_maxx - 1);
+	if (win->_cury == LINES - 1 && win->_y[LINES-1][COLS-1] != ' ')
+		if (win->_scroll) {
+			wrefresh(win);
+			scroll(win);
+			win->_cury--;
+		}
+		else
+			return ERR;
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/insertln.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/insertln.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/insertln.c	(revision 273)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)insertln.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine performs an insert-line on the window, leaving
+ * (_cury,_curx) unchanged.
+ *
+ */
+winsertln(win)
+reg WINDOW	*win; {
+
+	reg char	*temp;
+	reg int		y;
+	reg char	*end;
+	reg int		x;
+
+#ifdef	DEBUG
+	fprintf(outf, "INSERTLN(%0.2o)\n", win);
+#endif
+	if (win->_orig == NULL)
+		temp = win->_y[win->_maxy - 1];
+	for (y = win->_maxy - 1; y > win->_cury; --y) {
+		if (win->_orig == NULL)
+			win->_y[y] = win->_y[y - 1];
+		else
+			bcopy(win->_y[y - 1], win->_y[y], win->_maxx);
+		touchline(win, y, 0, win->_maxx - 1);
+	}
+	if (win->_orig == NULL)
+		win->_y[y] = temp;
+	else
+		temp = win->_y[y];
+	for (end = &temp[win->_maxx]; temp < end; )
+		*temp++ = ' ';
+	touchline(win, y, 0, win->_maxx - 1);
+	if (win->_orig == NULL)
+		_id_subwins(win);
+}
Index: /branches/EMX/src/emx/bsd/curses/longname.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/longname.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/longname.c	(revision 273)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)longname.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# define	reg	register
+
+/*
+ *	This routine fills in "def" with the long name of the terminal.
+ *
+ */
+char *
+longname(bp, def)
+reg char	*bp, *def; {
+
+	reg char	*cp;
+
+	while (*bp && *bp != ':' && *bp != '|')
+		bp++;
+	if (*bp == '|') {
+		bp++;
+		cp = def;
+		while (*bp && *bp != ':' && *bp != '|')
+			*cp++ = *bp++;
+		*cp = 0;
+	}
+	return def;
+}
Index: /branches/EMX/src/emx/bsd/curses/move.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/move.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/move.c	(revision 273)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)move.c	5.5 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine moves the cursor to the given point
+ *
+ */
+wmove(win, y, x)
+reg WINDOW	*win;
+reg int		y, x; {
+
+# ifdef DEBUG
+	fprintf(outf, "MOVE to (%d, %d)\n", y, x);
+# endif
+	if (x < 0 || y < 0)
+		return ERR;
+	if (x >= win->_maxx || y >= win->_maxy)
+		return ERR;
+	win->_curx = x;
+	win->_cury = y;
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/mvprintw.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/mvprintw.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/mvprintw.c	(revision 273)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mvprintw.c	5.8 (Berkeley) 6/19/91";
+#endif /* not lint */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "curses.ext"
+
+/*
+ * implement the mvprintw commands.  Due to the variable number of
+ * arguments, they cannot be macros.  Sigh....
+ */
+
+#if __STDC__
+mvprintw(reg int y, reg int x, const char *fmt, ...)
+#else
+mvprintw(y, x, fmt, va_alist)
+	reg int y, x;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	int ret;
+
+	if (move(y, x) != OK)
+		return ERR;
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sprintw(stdscr, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
+#if __STDC__
+mvwprintw(reg WINDOW *win, reg int y, reg int x, const char *fmt, ...)
+#else
+mvwprintw(win, y, x, fmt, va_alist)
+	reg WINDOW *win;
+	reg int y, x;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	int ret;
+
+	if (wmove(win, y, x) != OK)
+		return ERR;
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sprintw(win, fmt, ap);
+	va_end(ap);
+	return ret;
+}
Index: /branches/EMX/src/emx/bsd/curses/mvscanw.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/mvscanw.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/mvscanw.c	(revision 273)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mvscanw.c	5.5 (Berkeley) 4/15/91";
+#endif /* not lint */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "curses.ext"
+
+/*
+ * implement the mvscanw commands.  Due to the variable number of
+ * arguments, they cannot be macros.  Another sigh....
+ */
+
+#if __STDC__
+mvscanw(reg int y, reg int x, const char *fmt, ...)
+#else
+mvscanw(y, x, fmt, va_alist)
+	reg int y, x;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	int ret;
+
+	if (move(y, x) != OK)
+		return ERR;
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sscans(stdscr, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
+#if __STDC__
+mvwscanw(reg WINDOW *win, reg int y, reg int x, const char *fmt, ...)
+#else
+mvwscanw(win, y, x, fmt, va_alist)
+	reg WINDOW *win;
+	reg int y, x;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	int ret;
+
+	if (move(y, x) != OK)
+		return ERR;
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sscans(win, fmt, ap);
+	va_end(ap);
+	return ret;
+}
Index: /branches/EMX/src/emx/bsd/curses/mvwin.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/mvwin.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/mvwin.c	(revision 273)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mvwin.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ * relocate the starting position of a window
+ *
+ */
+
+mvwin(win, by, bx)
+reg WINDOW	*win;
+reg int		by, bx; {
+
+	register WINDOW	*orig;
+	register int	dy, dx;
+
+	if (by + win->_maxy > LINES || bx + win->_maxx > COLS)
+		return ERR;
+	dy = by - win->_begy;
+	dx = bx - win->_begx;
+	orig = win->_orig;
+	if (orig == NULL) {
+		orig = win;
+		do {
+			win->_begy += dy;
+			win->_begx += dx;
+			_swflags_(win);
+			win = win->_nextp;
+		} while (win != orig);
+	}
+	else {
+		if (by < orig->_begy || win->_maxy + dy > orig->_maxy)
+			return ERR;
+		if (bx < orig->_begx || win->_maxx + dx > orig->_maxx)
+			return ERR;
+		win->_begy = by;
+		win->_begx = bx;
+		_swflags_(win);
+		_set_subwin_(orig, win);
+	}
+	touchwin(win);
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/newwin.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/newwin.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/newwin.c	(revision 273)
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)newwin.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * allocate space for and set up defaults for a new window
+ *
+ */
+
+# include	"curses.ext"
+
+char	*malloc();
+
+# define	SMALLOC	(short *) malloc
+
+static WINDOW	*makenew();
+
+# undef		nl	/* don't need it here, and it interferes	*/
+
+WINDOW *
+newwin(num_lines, num_cols, begy, begx)
+int	num_lines, num_cols, begy, begx;
+{
+	reg WINDOW	*win;
+	reg char	*sp;
+	reg int		i, by, bx, nl, nc;
+	reg int		j;
+
+	by = begy;
+	bx = begx;
+	nl = num_lines;
+	nc = num_cols;
+
+	if (nl == 0)
+		nl = LINES - by;
+	if (nc == 0)
+		nc = COLS - bx;
+	if ((win = makenew(nl, nc, by, bx)) == NULL)
+		return ERR;
+	if ((win->_firstch = SMALLOC(nl * sizeof win->_firstch[0])) == NULL) {
+		free(win->_y);
+		free(win);
+		return NULL;
+	}
+	if ((win->_lastch = SMALLOC(nl * sizeof win->_lastch[0])) == NULL) {
+		free(win->_y);
+		free(win->_firstch);
+		free(win);
+		return NULL;
+	}
+	win->_nextp = win;
+	for (i = 0; i < nl; i++) {
+		win->_firstch[i] = _NOCHANGE;
+		win->_lastch[i] = _NOCHANGE;
+	}
+	for (i = 0; i < nl; i++)
+		if ((win->_y[i] = malloc(nc * sizeof win->_y[0])) == NULL) {
+			for (j = 0; j < i; j++)
+				free(win->_y[j]);
+			free(win->_firstch);
+			free(win->_lastch);
+			free(win->_y);
+			free(win);
+			return ERR;
+		}
+		else
+			for (sp = win->_y[i]; sp < win->_y[i] + nc; )
+				*sp++ = ' ';
+	win->_ch_off = 0;
+# ifdef DEBUG
+	fprintf(outf, "NEWWIN: win->_ch_off = %d\n", win->_ch_off);
+# endif
+	return win;
+}
+
+WINDOW *
+subwin(orig, num_lines, num_cols, begy, begx)
+reg WINDOW	*orig;
+int		num_lines, num_cols, begy, begx;
+{
+	reg int		i;
+	reg WINDOW	*win;
+	reg int		by, bx, nl, nc;
+
+	by = begy;
+	bx = begx;
+	nl = num_lines;
+	nc = num_cols;
+
+	/*
+	 * make sure window fits inside the original one
+	 */
+# ifdef	DEBUG
+	fprintf(outf, "SUBWIN(%0.2o, %d, %d, %d, %d)\n", orig, nl, nc, by, bx);
+# endif
+	if (by < orig->_begy || bx < orig->_begx
+	    || by + nl > orig->_maxy + orig->_begy
+	    || bx + nc > orig->_maxx + orig->_begx)
+		return ERR;
+	if (nl == 0)
+		nl = orig->_maxy + orig->_begy - by;
+	if (nc == 0)
+		nc = orig->_maxx + orig->_begx - bx;
+	if ((win = makenew(nl, nc, by, bx)) == NULL)
+		return ERR;
+	win->_nextp = orig->_nextp;
+	orig->_nextp = win;
+	win->_orig = orig;
+	_set_subwin_(orig, win);
+	return win;
+}
+
+/*
+ * this code is shared with mvwin()
+ */
+_set_subwin_(orig, win)
+register WINDOW	*orig, *win;
+{
+	register int	i, j, k;
+
+	j = win->_begy - orig->_begy;
+	k = win->_begx - orig->_begx;
+	win->_ch_off = k;
+# ifdef DEBUG
+	fprintf(outf, "_SET_SUBWIN_: win->_ch_off = %d\n", win->_ch_off);
+# endif
+	win->_firstch = &orig->_firstch[j];
+	win->_lastch = &orig->_lastch[j];
+	for (i = 0; i < win->_maxy; i++, j++)
+		win->_y[i] = &orig->_y[j][k];
+
+}
+
+/*
+ *	This routine sets up a window buffer and returns a pointer to it.
+ */
+static WINDOW *
+makenew(num_lines, num_cols, begy, begx)
+int	num_lines, num_cols, begy, begx; {
+
+	reg int		i;
+	reg WINDOW	*win;
+	reg int		by, bx, nl, nc;
+
+	by = begy;
+	bx = begx;
+	nl = num_lines;
+	nc = num_cols;
+
+# ifdef	DEBUG
+	fprintf(outf, "MAKENEW(%d, %d, %d, %d)\n", nl, nc, by, bx);
+# endif
+	if ((win = (WINDOW *) malloc(sizeof *win)) == NULL)
+		return NULL;
+# ifdef DEBUG
+	fprintf(outf, "MAKENEW: nl = %d\n", nl);
+# endif
+	if ((win->_y = (char **) malloc(nl * sizeof win->_y[0])) == NULL) {
+		free(win);
+		return NULL;
+	}
+# ifdef DEBUG
+	fprintf(outf, "MAKENEW: nc = %d\n", nc);
+# endif
+	win->_cury = win->_curx = 0;
+	win->_clear = FALSE;
+	win->_maxy = nl;
+	win->_maxx = nc;
+	win->_begy = by;
+	win->_begx = bx;
+	win->_flags = 0;
+	win->_scroll = win->_leave = FALSE;
+	_swflags_(win);
+# ifdef DEBUG
+	fprintf(outf, "MAKENEW: win->_clear = %d\n", win->_clear);
+	fprintf(outf, "MAKENEW: win->_leave = %d\n", win->_leave);
+	fprintf(outf, "MAKENEW: win->_scroll = %d\n", win->_scroll);
+	fprintf(outf, "MAKENEW: win->_flags = %0.2o\n", win->_flags);
+	fprintf(outf, "MAKENEW: win->_maxy = %d\n", win->_maxy);
+	fprintf(outf, "MAKENEW: win->_maxx = %d\n", win->_maxx);
+	fprintf(outf, "MAKENEW: win->_begy = %d\n", win->_begy);
+	fprintf(outf, "MAKENEW: win->_begx = %d\n", win->_begx);
+# endif
+	return win;
+}
+
+_swflags_(win)
+register WINDOW	*win;
+{
+	win->_flags &= ~(_ENDLINE|_FULLLINE|_FULLWIN|_SCROLLWIN);
+	if (win->_begx + win->_maxx == COLS) {
+		win->_flags |= _ENDLINE;
+		if (win->_begx == 0) {
+			if (AL && DL)
+				win->_flags |= _FULLLINE;
+			if (win->_maxy == LINES && win->_begy == 0)
+				win->_flags |= _FULLWIN;
+		}
+		if (win->_begy + win->_maxy == LINES)
+			win->_flags |= _SCROLLWIN;
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/os2.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/os2.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/os2.c	(revision 273)
@@ -0,0 +1,77 @@
+#include <io.h>
+#include <fcntl.h>
+#include <sys/termio.h>
+
+#include "curses.h"
+
+
+static struct termio tio;
+
+int _setraw(int on)
+{
+  if ( !(on & 2) )
+  {
+    setmode(0, (on & 1) ? O_BINARY : O_TEXT);
+    _pfast = (on & 1) || !(_tty.c_iflag & ICRNL);
+  }
+  _rawmode = (on & 1);
+  _tty.c_lflag &= ~IDEFAULT;
+  if ( (on & 1) )
+    _tty.c_lflag &= ~ICANON;
+  else
+    _tty.c_lflag |= ICANON;
+  ioctl(_tty_ch, TCSETA, &_tty);
+  return 0;
+}
+
+int _setecho(int on)
+{
+  _echoit = on;
+  if ( on )
+    _tty.c_lflag |= ECHO;
+  else
+    _tty.c_lflag &= ~ECHO;
+  ioctl (0, TCSETA, &_tty);
+  return 0;
+}
+
+int _setnl(int on)
+{
+  _pfast = on ? _rawmode : TRUE;
+  if ( on )
+    _tty.c_iflag |= ICRNL;
+  else
+    _tty.c_iflag &= ~ICRNL;
+  ioctl (0, TCSETA, &_tty);
+  return 0;
+}
+
+savetty()
+{
+  ioctl (0, TCGETA, &tio);
+  return 0;
+}
+
+resetty()
+{
+  ioctl (0, TCSETA, &tio);
+  _echoit = (tio.c_lflag & ECHO) == ECHO;
+  _rawmode = (tio.c_iflag & ICANON) == 0;
+  _pfast = (tio.c_iflag & ICRNL) ? _rawmode : TRUE;
+  return 0;
+}
+
+erasechar()
+{
+ return '\b';
+}
+
+killchar()
+{
+  return 127;
+}
+
+baudrate()
+{
+  return B38400;
+}
Index: /branches/EMX/src/emx/bsd/curses/overlay.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/overlay.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/overlay.c	(revision 273)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)overlay.c	5.6 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+# include	<ctype.h>
+
+# define	min(a,b)	(a < b ? a : b)
+# define	max(a,b)	(a > b ? a : b)
+
+/*
+ *	This routine writes win1 on win2 non-destructively.
+ *
+ */
+overlay(win1, win2)
+reg WINDOW	*win1, *win2; {
+
+	reg char	*sp, *end;
+	reg int		x, y, endy, endx, starty, startx;
+	reg int 	y1,y2;
+
+# ifdef DEBUG
+	fprintf(outf, "OVERLAY(%0.2o, %0.2o);\n", win1, win2);
+# endif
+	starty = max(win1->_begy, win2->_begy);
+	startx = max(win1->_begx, win2->_begx);
+	endy = min(win1->_maxy + win1->_begy, win2->_maxy + win2->_begx);
+	endx = min(win1->_maxx + win1->_begx, win2->_maxx + win2->_begx);
+# ifdef DEBUG
+	fprintf(outf, "OVERLAY:from (%d,%d) to (%d,%d)\n", starty, startx, endy, endx);
+# endif
+	if (starty >= endy || startx >= endx)
+		return;
+	y1 = starty - win1->_begy;
+	y2 = starty - win2->_begy;
+	for (y = starty; y < endy; y++, y1++, y2++) {
+		end = &win1->_y[y1][endx - win1->_begx];
+		x = startx - win2->_begx;
+		for (sp = &win1->_y[y1][startx - win1->_begx]; sp < end; sp++) {
+			if (!isspace(*sp))
+				mvwaddch(win2, y2, x, *sp);
+			x++;
+		}
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/overwrit.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/overwrit.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/overwrit.c	(revision 273)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)overwrite.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+# include	<ctype.h>
+
+# define	min(a,b)	(a < b ? a : b)
+# define	max(a,b)	(a > b ? a : b)
+
+/*
+ *	This routine writes win1 on win2 destructively.
+ *
+ */
+overwrite(win1, win2)
+reg WINDOW	*win1, *win2; {
+
+	reg char	*sp, *end;
+	reg int		x, y, endy, endx, starty, startx;
+
+# ifdef DEBUG
+	fprintf(outf, "OVERWRITE(%0.2o, %0.2o);\n", win1, win2);
+# endif
+	starty = max(win1->_begy, win2->_begy);
+	startx = max(win1->_begx, win2->_begx);
+	endy = min(win1->_maxy + win1->_begy, win2->_maxy + win2->_begx);
+	endx = min(win1->_maxx + win1->_begx, win2->_maxx + win2->_begx);
+	if (starty >= endy || startx >= endx)
+		return;
+# ifdef DEBUG
+	fprintf(outf, "OVERWRITE:from (%d,%d) to (%d,%d)\n", starty, startx, endy, endx);
+# endif
+	x = endx - startx;
+	for (y = starty; y < endy; y++) {
+		bcopy(&win1->_y[y - win1->_begy][startx - win1->_begx],
+		      &win2->_y[y - win2->_begy][startx - win2->_begx], x);
+		touchline(win2, y, startx - win2->_begx, endx - win2->_begx);
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/printw.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/printw.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/printw.c	(revision 273)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)printw.c	5.8 (Berkeley) 4/15/91";
+#endif /* not lint */
+
+/*
+ * printw and friends.
+ *
+ * These routines make nonportable assumptions about varargs if __STDC__
+ * is not in effect.
+ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "curses.ext"
+
+/*
+ *	This routine implements a printf on the standard screen.
+ */
+#if __STDC__
+printw(const char *fmt, ...)
+#else
+printw(fmt, va_alist)
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list	ap;
+	int	ret;
+
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sprintw(stdscr, fmt, ap);
+	va_end(ap);
+	return (ret);
+}
+
+/*
+ *	This routine implements a printf on the given window.
+ */
+#if __STDC__
+wprintw(WINDOW *win, const char *fmt, ...)
+#else
+wprintw(win, fmt, va_alist)
+	WINDOW *win;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list	ap;
+	int	ret;
+
+#ifdef __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sprintw(win, fmt, ap);
+	va_end(ap);
+	return (ret);
+}
+
+/*
+ *	This routine actually executes the printf and adds it to the window.
+ *	It must not be declared static as it is used in mvprintw.c.
+ *	THIS SHOULD BE RENAMED vwprintw AND EXPORTED
+ */
+_sprintw(win, fmt, ap)
+	WINDOW *win;
+#if __STDC__
+	const char *fmt;
+#else
+	char *fmt;
+#endif
+	va_list	ap;
+{
+	char buffer[BUFSIZ];
+	register int l, c;
+	
+	(void) vsprintf(buffer, fmt, ap);
+	l = strlen(buffer);
+	
+	for ( c = 0; c < l; c++ ) {
+		if (waddch(win, buffer[c]) == ERR)
+			return (-1);
+	}
+	
+	return OK;
+}
Index: /branches/EMX/src/emx/bsd/curses/putchar.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/putchar.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/putchar.c	(revision 273)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)putchar.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+char
+_putchar(c)
+reg char	c; {
+
+	putchar(c);
+#ifdef DEBUG
+	fprintf(outf, "_PUTCHAR(%s)\n", unctrl(c));
+#endif
+}
Index: /branches/EMX/src/emx/bsd/curses/refresh.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/refresh.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/refresh.c	(revision 273)
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)refresh.c	5.5 (Berkeley) 3/3/91";
+#endif /* not lint */
+
+/*
+ * make the current screen look like "win" over the area coverd by
+ * win.
+ */
+
+# include	"curses.ext"
+
+# ifdef DEBUG
+# define	STATIC
+# else
+# define	STATIC	static
+# endif
+
+STATIC short	ly, lx;
+
+STATIC bool	curwin;
+
+WINDOW	*_win = NULL;
+
+STATIC int	domvcur(), makech();
+
+wrefresh(win)
+reg WINDOW	*win;
+{
+	reg short	wy;
+	reg int		retval;
+	reg WINDOW	*orig;
+
+	/*
+	 * make sure were in visual state
+	 */
+	if (_endwin) {
+		_puts(VS);
+		_puts(TI);
+		_endwin = FALSE;
+	}
+
+	/*
+	 * initialize loop parameters
+	 */
+
+	ly = curscr->_cury;
+	lx = curscr->_curx;
+	wy = 0;
+	_win = win;
+	curwin = (win == curscr);
+
+	if (win->_clear || curscr->_clear || curwin) {
+		if ((win->_flags & _FULLWIN) || curscr->_clear) {
+			_puts(CL);
+			ly = 0;
+			lx = 0;
+			if (!curwin) {
+				curscr->_clear = FALSE;
+				curscr->_cury = 0;
+				curscr->_curx = 0;
+				werase(curscr);
+			}
+			touchwin(win);
+		}
+		win->_clear = FALSE;
+	}
+	if (!CA) {
+		if (win->_curx != 0)
+			_putchar('\n');
+		if (!curwin)
+			werase(curscr);
+	}
+# ifdef DEBUG
+	fprintf(outf, "REFRESH(%0.2o): curwin = %d\n", win, curwin);
+	fprintf(outf, "REFRESH:\n\tfirstch\tlastch\n");
+# endif
+	for (wy = 0; wy < win->_maxy; wy++) {
+# ifdef DEBUG
+		fprintf(outf, "%d\t%d\t%d\n", wy, win->_firstch[wy],
+			win->_lastch[wy]);
+# endif
+		if (win->_firstch[wy] != _NOCHANGE)
+			if (makech(win, wy) == ERR)
+				return ERR;
+			else {
+				if (win->_firstch[wy] >= win->_ch_off)
+					win->_firstch[wy] = win->_maxx +
+							    win->_ch_off;
+				if (win->_lastch[wy] < win->_maxx +
+						       win->_ch_off)
+					win->_lastch[wy] = win->_ch_off;
+				if (win->_lastch[wy] < win->_firstch[wy])
+					win->_firstch[wy] = _NOCHANGE;
+			}
+# ifdef DEBUG
+		fprintf(outf, "\t%d\t%d\n", win->_firstch[wy],
+			win->_lastch[wy]);
+# endif
+	}
+
+	if (win == curscr)
+		domvcur(ly, lx, win->_cury, win->_curx);
+	else {
+		if (win->_leave) {
+			curscr->_cury = ly;
+			curscr->_curx = lx;
+			ly -= win->_begy;
+			lx -= win->_begx;
+			if (ly >= 0 && ly < win->_maxy && lx >= 0 &&
+			    lx < win->_maxx) {
+				win->_cury = ly;
+				win->_curx = lx;
+			}
+			else
+				win->_cury = win->_curx = 0;
+		}
+		else {
+			domvcur(ly, lx, win->_cury + win->_begy,
+				win->_curx + win->_begx);
+			curscr->_cury = win->_cury + win->_begy;
+			curscr->_curx = win->_curx + win->_begx;
+		}
+	}
+	retval = OK;
+ret:
+	_win = NULL;
+	fflush(stdout);
+	return retval;
+}
+
+/*
+ * make a change on the screen
+ */
+STATIC
+makech(win, wy)
+reg WINDOW	*win;
+short		wy;
+{
+	reg char	*nsp, *csp, *ce;
+	reg short	wx, lch, y;
+	reg int		nlsp, clsp;	/* last space in lines		*/
+
+	wx = win->_firstch[wy] - win->_ch_off;
+	if (wx >= win->_maxx)
+		return OK;
+	else if (wx < 0)
+		wx = 0;
+	lch = win->_lastch[wy] - win->_ch_off;
+	if (lch < 0)
+		return OK;
+	else if (lch >= win->_maxx)
+		lch = win->_maxx - 1;;
+	y = wy + win->_begy;
+
+	if (curwin)
+		csp = " ";
+	else
+		csp = &curscr->_y[wy + win->_begy][wx + win->_begx];
+
+	nsp = &win->_y[wy][wx];
+	if (CE && !curwin) {
+		for (ce = &win->_y[wy][win->_maxx - 1]; *ce == ' '; ce--)
+			if (ce <= win->_y[wy])
+				break;
+		nlsp = ce - win->_y[wy];
+	}
+
+	if (!curwin)
+		ce = CE;
+	else
+		ce = NULL;
+
+	while (wx <= lch) {
+		if (*nsp != *csp) {
+			domvcur(ly, lx, y, wx + win->_begx);
+# ifdef DEBUG
+			fprintf(outf, "MAKECH: 1: wx = %d, lx = %d\n", wx, lx);
+# endif
+			ly = y;
+			lx = wx + win->_begx;
+			while (*nsp != *csp && wx <= lch) {
+				if (ce != NULL && wx >= nlsp && *nsp == ' ') {
+					/*
+					 * check for clear to end-of-line
+					 */
+					ce = &curscr->_y[ly][COLS - 1];
+					while (*ce == ' ')
+						if (ce-- <= csp)
+							break;
+					clsp = ce - curscr->_y[ly] - win->_begx;
+# ifdef DEBUG
+					fprintf(outf, "MAKECH: clsp = %d, nlsp = %d\n", clsp, nlsp);
+# endif
+					if (clsp - nlsp >= strlen(CE)
+					    && clsp < win->_maxx) {
+# ifdef DEBUG
+						fprintf(outf, "MAKECH: using CE\n");
+# endif
+						_puts(CE);
+						lx = wx + win->_begx;
+						while (wx++ <= clsp)
+							*csp++ = ' ';
+						return OK;
+					}
+					ce = NULL;
+				}
+				/*
+				 * enter/exit standout mode as appropriate
+				 */
+				if (SO && (*nsp&_STANDOUT) != (curscr->_flags&_STANDOUT)) {
+					if (*nsp & _STANDOUT) {
+						_puts(SO);
+						curscr->_flags |= _STANDOUT;
+					}
+					else {
+						_puts(SE);
+						curscr->_flags &= ~_STANDOUT;
+					}
+				}
+				wx++;
+				if (wx >= win->_maxx && wy == win->_maxy - 1)
+					if (win->_scroll) {
+					    if ((curscr->_flags&_STANDOUT) &&
+					        (win->_flags & _ENDLINE))
+						    if (!MS) {
+							_puts(SE);
+							curscr->_flags &= ~_STANDOUT;
+						    }
+					    if (!curwin)
+						_putchar((*csp = *nsp));
+					    else
+						_putchar(*nsp);
+					    if (win->_flags&_FULLWIN && !curwin)
+						scroll(curscr);
+					    ly = win->_begy+win->_cury;
+					    lx = win->_begx+win->_curx;
+					    return OK;
+					}
+					else if (win->_flags&_SCROLLWIN) {
+					    lx = --wx;
+					    return ERR;
+					}
+				if (!curwin)
+					_putchar((*csp++ = *nsp));
+				else
+					_putchar(*nsp);
+# ifdef FULLDEBUG
+				fprintf(outf,
+					"MAKECH:putchar(%c)\n", *nsp);
+# endif
+				if (UC && (*nsp & _STANDOUT)) {
+					_putchar('\b');
+					_puts(UC);
+				}
+				nsp++;
+			}
+# ifdef DEBUG
+			fprintf(outf, "MAKECH: 2: wx = %d, lx = %d\n", wx, lx);
+# endif
+			if (lx == wx + win->_begx)	/* if no change */
+				break;
+			lx = wx + win->_begx;
+			if (lx >= COLS && AM) {
+				lx = 0;
+				ly++;
+				/*
+				 * xn glitch: chomps a newline after auto-wrap.
+				 * we just feed it now and forget about it.
+				 */
+				if (XN) {
+					_putchar('\n');
+					_putchar('\r');
+				}
+			}
+		}
+		else if (wx <= lch)
+			while (*nsp == *csp && wx <= lch) {
+				nsp++;
+				if (!curwin)
+					csp++;
+				++wx;
+			}
+		else
+			break;
+# ifdef DEBUG
+		fprintf(outf, "MAKECH: 3: wx = %d, lx = %d\n", wx, lx);
+# endif
+	}
+	return OK;
+}
+
+/*
+ * perform a mvcur, leaving standout mode if necessary
+ */
+STATIC
+domvcur(oy, ox, ny, nx)
+int	oy, ox, ny, nx; {
+
+	if (curscr->_flags & _STANDOUT && !MS) {
+		_puts(SE);
+		curscr->_flags &= ~_STANDOUT;
+	}
+	mvcur(oy, ox, ny, nx);
+}
Index: /branches/EMX/src/emx/bsd/curses/scanw.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/scanw.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/scanw.c	(revision 273)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)scanw.c	5.7 (Berkeley) 4/15/91";
+#endif /* not lint */
+
+/*
+ * scanw and friends
+ *
+ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "curses.ext"
+
+/*
+ *	This routine implements a scanf on the standard screen.
+ */
+#if __STDC__
+scanw(const char *fmt, ...)
+#else
+scanw(fmt, va_alist)
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	int ret;
+
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sscans(stdscr, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
+/*
+ *	This routine implements a scanf on the given window.
+ */
+#if __STDC__
+wscanw(WINDOW *win, const char *fmt, ...)
+#else
+wscanw(win, fmt, va_alist)
+	WINDOW *win;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+	int ret;
+
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	ret = _sscans(win, fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
+/*
+ *	This routine actually executes the scanf from the window.
+ *	THIS SHOULD BE RENAMED vwscanw AND EXPORTED
+ */
+_sscans(win, fmt, ap)
+	WINDOW *win;
+#if __STDC__
+	const char *fmt;
+#else
+	char *fmt;
+#endif
+	va_list ap;
+{
+	char buf[100];
+
+	return wgetstr(win, buf) == OK ? vsscanf(buf, fmt, ap) : ERR;
+}
Index: /branches/EMX/src/emx/bsd/curses/scroll.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/scroll.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/scroll.c	(revision 273)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)scroll.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ *	This routine scrolls the window up a line.
+ *
+ */
+scroll(win)
+register  WINDOW	*win;
+{
+	register int	oy, ox;
+
+# ifdef DEBUG
+	fprintf(outf, "SCROLL(%0.2o)\n", win);
+# endif
+
+	if (!win->_scroll)
+		return ERR;
+
+	getyx(win, oy, ox);
+	wmove(win, 0, 0);
+	wdeleteln(win);
+	wmove(win, oy, ox);
+
+	if (win == curscr) {
+		_putchar('\n');
+		if (!NONL)
+			win->_curx = 0;
+# ifdef DEBUG
+		fprintf(outf, "SCROLL: win == curscr\n");
+# endif
+	}
+}
Index: /branches/EMX/src/emx/bsd/curses/standout.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/standout.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/standout.c	(revision 273)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)standout.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * routines dealing with entering and exiting standout mode
+ *
+ */
+
+# include	"curses.ext"
+
+/*
+ * enter standout mode
+ */
+char *
+wstandout(win)
+reg WINDOW	*win;
+{
+	if (!SO && !UC)
+		return FALSE;
+
+	win->_flags |= _STANDOUT;
+	return (SO ? SO : UC);
+}
+
+/*
+ * exit standout mode
+ */
+char *
+wstandend(win)
+reg WINDOW	*win;
+{
+	if (!SO && !UC)
+		return FALSE;
+
+	win->_flags &= ~_STANDOUT;
+	return (SE ? SE : UC);
+}
Index: /branches/EMX/src/emx/bsd/curses/touchola.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/touchola.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/touchola.c	(revision 273)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)toucholap.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+# define	min(a,b)	(a < b ? a : b)
+# define	max(a,b)	(a > b ? a : b)
+
+/*
+ *	Touch, on win2, the part that overlaps with win1.
+ *
+ */
+touchoverlap(win1, win2)
+reg WINDOW	*win1, *win2; {
+
+	reg int		x, y, endy, endx, starty, startx;
+
+# ifdef DEBUG
+	fprintf(outf, "TOUCHOVERLAP(%0.2o, %0.2o);\n", win1, win2);
+# endif
+	starty = max(win1->_begy, win2->_begy);
+	startx = max(win1->_begx, win2->_begx);
+	endy = min(win1->_maxy + win1->_begy, win2->_maxy + win2->_begx);
+	endx = min(win1->_maxx + win1->_begx, win2->_maxx + win2->_begx);
+# ifdef DEBUG
+	fprintf(outf, "TOUCHOVERLAP:from (%d,%d) to (%d,%d)\n", starty, startx, endy, endx);
+	fprintf(outf, "TOUCHOVERLAP:win1 (%d,%d) to (%d,%d)\n", win1->_begy, win1->_begx, win1->_begy + win1->_maxy, win1->_begx + win1->_maxx);
+	fprintf(outf, "TOUCHOVERLAP:win2 (%d,%d) to (%d,%d)\n", win2->_begy, win2->_begx, win2->_begy + win2->_maxy, win2->_begx + win2->_maxx);
+# endif
+	if (starty >= endy || startx >= endx)
+		return;
+	starty -= win2->_begy;
+	startx -= win2->_begx;
+	endy -= win2->_begy;
+	endx -= win2->_begx;
+	endx--;
+	for (y = starty; y < endy; y++)
+		touchline(win2, y, startx, endx);
+}
Index: /branches/EMX/src/emx/bsd/curses/touchwin.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/touchwin.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/touchwin.c	(revision 273)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)touchwin.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+# include	"curses.ext"
+
+/*
+ * make it look like the whole window has been changed.
+ *
+ */
+touchwin(win)
+register WINDOW	*win;
+{
+	register int	y, maxy;
+
+# ifdef	DEBUG
+	fprintf(outf, "TOUCHWIN(%0.2o)\n", win);
+# endif
+	maxy = win->_maxy;
+	for (y = 0; y < maxy; y++)
+		touchline(win, y, 0, win->_maxx - 1);
+}
+
+/*
+ * touch a given line
+ */
+touchline(win, y, sx, ex)
+register WINDOW	*win;
+register int	y, sx, ex;
+{
+# ifdef DEBUG
+	fprintf(outf, "TOUCHLINE(%0.2o, %d, %d, %d)\n", win, y, sx, ex);
+	fprintf(outf, "TOUCHLINE:first = %d, last = %d\n", win->_firstch[y], win->_lastch[y]);
+# endif
+	sx += win->_ch_off;
+	ex += win->_ch_off;
+	if (win->_firstch[y] == _NOCHANGE) {
+		win->_firstch[y] = sx;
+		win->_lastch[y] = ex;
+	}
+	else {
+		if (win->_firstch[y] > sx)
+			win->_firstch[y] = sx;
+		if (win->_lastch[y] < ex)
+			win->_lastch[y] = ex;
+	}
+# ifdef	DEBUG
+	fprintf(outf, "TOUCHLINE:first = %d, last = %d\n", win->_firstch[y], win->_lastch[y]);
+# endif
+}
Index: /branches/EMX/src/emx/bsd/curses/tstp.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/tstp.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/tstp.c	(revision 273)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)tstp.c	5.6 (Berkeley) 3/3/91";
+#endif /* not lint */
+
+# include	<signal.h>
+
+# include	"curses.ext"
+
+/*
+ * handle stop and start signals
+ *
+ * @(#)tstp.c	5.6 (Berkeley) 3/3/91
+ */
+void
+tstp() {
+
+# ifdef SIGTSTP
+
+	SGTTY	tty;
+	int	omask;
+# ifdef DEBUG
+	if (outf)
+		fflush(outf);
+# endif
+	tty = _tty;
+	mvcur(0, COLS - 1, LINES - 1, 0);
+	endwin();
+	fflush(stdout);
+	/* reset signal handler so kill below stops us */
+	signal(SIGTSTP, SIG_DFL);
+#define	mask(s)	(1 << ((s)-1))
+	omask = sigsetmask(sigblock(0) &~ mask(SIGTSTP));
+	kill(0, SIGTSTP);
+	sigblock(mask(SIGTSTP));
+	signal(SIGTSTP, tstp);
+	_tty = tty;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+	wrefresh(curscr);
+# endif	SIGTSTP
+}
Index: /branches/EMX/src/emx/bsd/curses/unctrl.c
===================================================================
--- /branches/EMX/src/emx/bsd/curses/unctrl.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/curses/unctrl.c	(revision 273)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)unctrl.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * define unctrl codes for each character
+ *
+ */
+
+/* LINTLIBRARY */
+char	*_unctrl[]	= {	/* unctrl codes for ttys		*/
+	"^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
+	"^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
+	"^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
+	" ", "!", "\"", "#", "$",  "%", "&", "'", "(", ")", "*", "+", ",", "-",
+	".", "/", "0",  "1", "2",  "3", "4", "5", "6", "7", "8", "9", ":", ";",
+	"<", "=", ">",  "?", "@",  "A", "B", "C", "D", "E", "F", "G", "H", "I",
+	"J", "K", "L",  "M", "N",  "O", "P", "Q", "R", "S", "T", "U", "V", "W",
+	"X", "Y", "Z",  "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
+	"f", "g", "h",  "i", "j",  "k", "l", "m", "n", "o", "p", "q", "r", "s",
+	"t", "u", "v",  "w", "x",  "y", "z", "{", "|", "}", "~", "^?"
+#ifdef OS2
+,
+"", "", "", "", "", "
+", "", "", "", "", "", "", "", "", "", "",
+"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+" ", "¡", "¢", "£", "€", "¥", "Š", "§", "š", "©", "ª", "«", "¬", "­", "®", "¯", 
+"°", "±", "²", "³", "Ž", "µ", "¶", "·", "ž", "¹", "º", "»", "Œ", "œ", "Ÿ", "¿", 
+"À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", 
+"Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", 
+"à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", 
+"ð", "ñ", "ò", "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ"
+#endif
+};
Index: /branches/EMX/src/emx/bsd/db/README
===================================================================
--- /branches/EMX/src/emx/bsd/db/README	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/README	(revision 273)
@@ -0,0 +1,40 @@
+#	@(#)README	8.27 (Berkeley) 9/1/94
+
+This is version 1.85 of the Berkeley DB code.
+
+For information on compiling and installing this software, see the file
+PORT/README.
+
+Newer versions of this software will periodically be made available by
+anonymous ftp from ftp.cs.berkeley.edu.  An archive in compressed format
+is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz.  If
+you'd like to receive announcements of future releases of this software,
+send email to the contact address below.
+
+Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu.
+
+============================================
+Distribution contents:
+
+Makefile.inc	Ignore this, it's the 4.4BSD subsystem Makefile.
+PORT		The per OS/architecture directories to use to build
+		libdb.a, if you're not running 4.4BSD.  See the file
+		PORT/README for more information.
+README		This file.
+btree		The B+tree routines.
+changelog	List of changes, per version.
+db		The dbopen(3) interface routine.
+docs		Various USENIX papers, and the formatted manual pages.
+hash		The extended linear hashing routines.
+man		The unformatted manual pages.
+mpool		The memory pool routines.
+recno		The fixed/variable length record routines.
+test		Test package.
+
+============================================
+Debugging:
+
+If you're running a memory checker (e.g. Purify) on DB, make sure that
+you recompile it with "-DPURIFY" in the CFLAGS, first.  By default,
+allocated pages are not initialized by the DB code, and they will show
+up as reads of uninitialized memory in the buffer write routines.
Index: /branches/EMX/src/emx/bsd/db/btree/bt_close.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_close.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_close.c	(revision 273)
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_close.c	8.7 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int bt_meta __P((BTREE *));
+
+/*
+ * BT_CLOSE -- Close a btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_close(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	int fd;
+#ifdef __EMX__
+	char *tempname;
+	int r;
+#endif /* __EMX__ */
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Sync the tree. */
+	if (__bt_sync(dbp, 0) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Close the memory pool. */
+	if (mpool_close(t->bt_mp) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Free random memory. */
+	if (t->bt_cursor.key.data != NULL) {
+		free(t->bt_cursor.key.data);
+		t->bt_cursor.key.size = 0;
+		t->bt_cursor.key.data = NULL;
+	}
+	if (t->bt_rkey.data) {
+		free(t->bt_rkey.data);
+		t->bt_rkey.size = 0;
+		t->bt_rkey.data = NULL;
+	}
+	if (t->bt_rdata.data) {
+		free(t->bt_rdata.data);
+		t->bt_rdata.size = 0;
+		t->bt_rdata.data = NULL;
+	}
+
+	fd = t->bt_fd;
+#ifdef __EMX__
+	tempname = t->tempname;
+	free(t);
+	free(dbp);
+	r = close(fd) ? RET_ERROR : RET_SUCCESS;
+	if (tempname != NULL) {
+		int e = errno;
+		(void)unlink (tempname);
+		free (tempname);
+		errno = e;
+	}
+	return r;
+#else /* not __EMX__ */
+	free(t);
+	free(dbp);
+	return (close(fd) ? RET_ERROR : RET_SUCCESS);
+#endif /* not __EMX__ */
+}
+
+/*
+ * BT_SYNC -- sync the btree to disk.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_sync(dbp, flags)
+	const DB *dbp;
+	u_int flags;
+{
+	BTREE *t;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Sync doesn't currently take any flags. */
+	if (flags != 0) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
+		return (RET_SUCCESS);
+
+	if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
+		return (RET_ERROR);
+
+	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
+		F_CLR(t, B_MODIFIED);
+
+	return (status);
+}
+
+/*
+ * BT_META -- write the tree meta data to disk.
+ *
+ * Parameters:
+ *	t:	tree
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_meta(t)
+	BTREE *t;
+{
+	BTMETA m;
+	void *p;
+
+	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
+		return (RET_ERROR);
+
+	/* Fill in metadata. */
+	m.magic = BTREEMAGIC;
+	m.version = BTREEVERSION;
+	m.psize = t->bt_psize;
+	m.free = t->bt_free;
+	m.nrecs = t->bt_nrecs;
+	m.flags = F_ISSET(t, SAVEMETA);
+
+	memmove(p, &m, sizeof(BTMETA));
+	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_conv.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_conv.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_conv.c	(revision 273)
@@ -0,0 +1,221 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_conv.c	8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static void mswap __P((PAGE *));
+
+/*
+ * __BT_BPGIN, __BT_BPGOUT --
+ *	Convert host-specific number layout to/from the host-independent
+ *	format stored on disk.
+ *
+ * Parameters:
+ *	t:	tree
+ *	pg:	page number
+ *	h:	page to convert
+ */
+void
+__bt_pgin(t, pg, pp)
+	void *t;
+	pgno_t pg;
+	void *pp;
+{
+	PAGE *h;
+	indx_t i, top;
+	u_char flags;
+	char *p;
+
+	if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+		return;
+	if (pg == P_META) {
+		mswap(pp);
+		return;
+	}
+
+	h = pp;
+	M_32_SWAP(h->pgno);
+	M_32_SWAP(h->prevpg);
+	M_32_SWAP(h->nextpg);
+	M_32_SWAP(h->flags);
+	M_16_SWAP(h->lower);
+	M_16_SWAP(h->upper);
+
+	top = NEXTINDEX(h);
+	if ((h->flags & P_TYPE) == P_BINTERNAL)
+		for (i = 0; i < top; i++) {
+			M_16_SWAP(h->linp[i]);
+			p = (char *)GETBINTERNAL(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(pgno_t);
+			if (*(u_char *)p & P_BIGKEY) {
+				p += sizeof(u_char);
+				P_32_SWAP(p);
+				p += sizeof(pgno_t);
+				P_32_SWAP(p);
+			}
+		}
+	else if ((h->flags & P_TYPE) == P_BLEAF)
+		for (i = 0; i < top; i++) {
+			M_16_SWAP(h->linp[i]);
+			p = (char *)GETBLEAF(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			flags = *(u_char *)p;
+			if (flags & (P_BIGKEY | P_BIGDATA)) {
+				p += sizeof(u_char);
+				if (flags & P_BIGKEY) {
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+				if (flags & P_BIGDATA) {
+					p += sizeof(u_int32_t);
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+			}
+		}
+}
+
+void
+__bt_pgout(t, pg, pp)
+	void *t;
+	pgno_t pg;
+	void *pp;
+{
+	PAGE *h;
+	indx_t i, top;
+	u_char flags;
+	char *p;
+
+	if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+		return;
+	if (pg == P_META) {
+		mswap(pp);
+		return;
+	}
+
+	h = pp;
+	top = NEXTINDEX(h);
+	if ((h->flags & P_TYPE) == P_BINTERNAL)
+		for (i = 0; i < top; i++) {
+			p = (char *)GETBINTERNAL(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(pgno_t);
+			if (*(u_char *)p & P_BIGKEY) {
+				p += sizeof(u_char);
+				P_32_SWAP(p);
+				p += sizeof(pgno_t);
+				P_32_SWAP(p);
+			}
+			M_16_SWAP(h->linp[i]);
+		}
+	else if ((h->flags & P_TYPE) == P_BLEAF)
+		for (i = 0; i < top; i++) {
+			p = (char *)GETBLEAF(h, i);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			P_32_SWAP(p);
+			p += sizeof(u_int32_t);
+			flags = *(u_char *)p;
+			if (flags & (P_BIGKEY | P_BIGDATA)) {
+				p += sizeof(u_char);
+				if (flags & P_BIGKEY) {
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+				if (flags & P_BIGDATA) {
+					p += sizeof(u_int32_t);
+					P_32_SWAP(p);
+					p += sizeof(pgno_t);
+					P_32_SWAP(p);
+				}
+			}
+			M_16_SWAP(h->linp[i]);
+		}
+
+	M_32_SWAP(h->pgno);
+	M_32_SWAP(h->prevpg);
+	M_32_SWAP(h->nextpg);
+	M_32_SWAP(h->flags);
+	M_16_SWAP(h->lower);
+	M_16_SWAP(h->upper);
+}
+
+/*
+ * MSWAP -- Actually swap the bytes on the meta page.
+ *
+ * Parameters:
+ *	p:	page to convert
+ */
+static void
+mswap(pg)
+	PAGE *pg;
+{
+	char *p;
+
+	p = (char *)pg;
+	P_32_SWAP(p);		/* magic */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* version */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* psize */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* free */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* nrecs */
+	p += sizeof(u_int32_t);
+	P_32_SWAP(p);		/* flags */
+	p += sizeof(u_int32_t);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_debug.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_debug.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_debug.c	(revision 273)
@@ -0,0 +1,329 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_debug.c	8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+/*
+ * BT_DUMP -- Dump the tree
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB
+ */
+void
+__bt_dump(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	PAGE *h;
+	pgno_t i;
+	char *sep;
+
+	t = dbp->internal;
+	(void)fprintf(stderr, "%s: pgsz %d",
+	    F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
+	if (F_ISSET(t, R_RECNO))
+		(void)fprintf(stderr, " keys %lu", t->bt_nrecs);
+#undef X
+#define	X(flag, name) \
+	if (F_ISSET(t, flag)) { \
+		(void)fprintf(stderr, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	if (t->flags != 0) {
+		sep = " flags (";
+		X(R_FIXLEN,	"FIXLEN");
+		X(B_INMEM,	"INMEM");
+		X(B_NODUPS,	"NODUPS");
+		X(B_RDONLY,	"RDONLY");
+		X(R_RECNO,	"RECNO");
+		X(B_METADIRTY,"METADIRTY");
+		(void)fprintf(stderr, ")\n");
+	}
+#undef X
+
+	for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+		__bt_dpage(h);
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * BT_DMPAGE -- Dump the meta page
+ *
+ * Parameters:
+ *	h:	pointer to the PAGE
+ */
+void
+__bt_dmpage(h)
+	PAGE *h;
+{
+	BTMETA *m;
+	char *sep;
+
+	m = (BTMETA *)h;
+	(void)fprintf(stderr, "magic %lx\n", m->magic);
+	(void)fprintf(stderr, "version %lu\n", m->version);
+	(void)fprintf(stderr, "psize %lu\n", m->psize);
+	(void)fprintf(stderr, "free %lu\n", m->free);
+	(void)fprintf(stderr, "nrecs %lu\n", m->nrecs);
+	(void)fprintf(stderr, "flags %lu", m->flags);
+#undef X
+#define	X(flag, name) \
+	if (m->flags & flag) { \
+		(void)fprintf(stderr, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	if (m->flags) {
+		sep = " (";
+		X(B_NODUPS,	"NODUPS");
+		X(R_RECNO,	"RECNO");
+		(void)fprintf(stderr, ")");
+	}
+}
+
+/*
+ * BT_DNPAGE -- Dump the page
+ *
+ * Parameters:
+ *	n:	page number to dump.
+ */
+void
+__bt_dnpage(dbp, pgno)
+	DB *dbp;
+	pgno_t pgno;
+{
+	BTREE *t;
+	PAGE *h;
+
+	t = dbp->internal;
+	if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) {
+		__bt_dpage(h);
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * BT_DPAGE -- Dump the page
+ *
+ * Parameters:
+ *	h:	pointer to the PAGE
+ */
+void
+__bt_dpage(h)
+	PAGE *h;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	RINTERNAL *ri;
+	RLEAF *rl;
+	indx_t cur, top;
+	char *sep;
+
+	(void)fprintf(stderr, "    page %d: (", h->pgno);
+#undef X
+#define	X(flag, name) \
+	if (h->flags & flag) { \
+		(void)fprintf(stderr, "%s%s", sep, name); \
+		sep = ", "; \
+	}
+	sep = "";
+	X(P_BINTERNAL,	"BINTERNAL")		/* types */
+	X(P_BLEAF,	"BLEAF")
+	X(P_RINTERNAL,	"RINTERNAL")		/* types */
+	X(P_RLEAF,	"RLEAF")
+	X(P_OVERFLOW,	"OVERFLOW")
+	X(P_PRESERVE,	"PRESERVE");
+	(void)fprintf(stderr, ")\n");
+#undef X
+
+	(void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg);
+	if (h->flags & P_OVERFLOW)
+		return;
+
+	top = NEXTINDEX(h);
+	(void)fprintf(stderr, " lower %3d upper %3d nextind %d\n",
+	    h->lower, h->upper, top);
+	for (cur = 0; cur < top; cur++) {
+		(void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]);
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+			bi = GETBINTERNAL(h, cur);
+			(void)fprintf(stderr,
+			    "size %03d pgno %03d", bi->ksize, bi->pgno);
+			if (bi->flags & P_BIGKEY)
+				(void)fprintf(stderr, " (indirect)");
+			else if (bi->ksize)
+				(void)fprintf(stderr,
+				    " {%.*s}", (int)bi->ksize, bi->bytes);
+			break;
+		case P_RINTERNAL:
+			ri = GETRINTERNAL(h, cur);
+			(void)fprintf(stderr, "entries %03d pgno %03d",
+				ri->nrecs, ri->pgno);
+			break;
+		case P_BLEAF:
+			bl = GETBLEAF(h, cur);
+			if (bl->flags & P_BIGKEY)
+				(void)fprintf(stderr,
+				    "big key page %lu size %u/",
+				    *(pgno_t *)bl->bytes,
+				    *(u_int32_t *)(bl->bytes + sizeof(pgno_t)));
+			else if (bl->ksize)
+				(void)fprintf(stderr, "%s/", bl->bytes);
+			if (bl->flags & P_BIGDATA)
+				(void)fprintf(stderr,
+				    "big data page %lu size %u",
+				    *(pgno_t *)(bl->bytes + bl->ksize),
+				    *(u_int32_t *)(bl->bytes + bl->ksize +
+				    sizeof(pgno_t)));
+			else if (bl->dsize)
+				(void)fprintf(stderr, "%.*s",
+				    (int)bl->dsize, bl->bytes + bl->ksize);
+			break;
+		case P_RLEAF:
+			rl = GETRLEAF(h, cur);
+			if (rl->flags & P_BIGDATA)
+				(void)fprintf(stderr,
+				    "big data page %lu size %u",
+				    *(pgno_t *)rl->bytes,
+				    *(u_int32_t *)(rl->bytes + sizeof(pgno_t)));
+			else if (rl->dsize)
+				(void)fprintf(stderr,
+				    "%.*s", (int)rl->dsize, rl->bytes);
+			break;
+		}
+		(void)fprintf(stderr, "\n");
+	}
+}
+#endif
+
+#ifdef STATISTICS
+/*
+ * BT_STAT -- Gather/print the tree statistics
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB
+ */
+void
+__bt_stat(dbp)
+	DB *dbp;
+{
+	extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
+	extern u_long bt_sortsplit, bt_split;
+	BTREE *t;
+	PAGE *h;
+	pgno_t i, pcont, pinternal, pleaf;
+	u_long ifree, lfree, nkeys;
+	int levels;
+
+	t = dbp->internal;
+	pcont = pinternal = pleaf = 0;
+	nkeys = ifree = lfree = 0;
+	for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+		case P_RINTERNAL:
+			++pinternal;
+			ifree += h->upper - h->lower;
+			break;
+		case P_BLEAF:
+		case P_RLEAF:
+			++pleaf;
+			lfree += h->upper - h->lower;
+			nkeys += NEXTINDEX(h);
+			break;
+		case P_OVERFLOW:
+			++pcont;
+			break;
+		}
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+
+	/* Count the levels of the tree. */
+	for (i = P_ROOT, levels = 0 ;; ++levels) {
+		h = mpool_get(t->bt_mp, i, 0);
+		if (h->flags & (P_BLEAF|P_RLEAF)) {
+			if (levels == 0)
+				levels = 1;
+			(void)mpool_put(t->bt_mp, h, 0);
+			break;
+		}
+		i = F_ISSET(t, R_RECNO) ?
+		    GETRINTERNAL(h, 0)->pgno :
+		    GETBINTERNAL(h, 0)->pgno;
+		(void)mpool_put(t->bt_mp, h, 0);
+	}
+
+	(void)fprintf(stderr, "%d level%s with %ld keys",
+	    levels, levels == 1 ? "" : "s", nkeys);
+	if (F_ISSET(t, R_RECNO))
+		(void)fprintf(stderr, " (%ld header count)", t->bt_nrecs);
+	(void)fprintf(stderr,
+	    "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n",
+	    pinternal + pleaf + pcont, pleaf, pinternal, pcont);
+	(void)fprintf(stderr, "%ld cache hits, %ld cache misses\n",
+	    bt_cache_hit, bt_cache_miss);
+	(void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n",
+	    bt_split, bt_rootsplit, bt_sortsplit);
+	pleaf *= t->bt_psize - BTDATAOFF;
+	if (pleaf)
+		(void)fprintf(stderr,
+		    "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
+		    ((double)(pleaf - lfree) / pleaf) * 100,
+		    pleaf - lfree, lfree);
+	pinternal *= t->bt_psize - BTDATAOFF;
+	if (pinternal)
+		(void)fprintf(stderr,
+		    "%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
+		    ((double)(pinternal - ifree) / pinternal) * 100,
+		    pinternal - ifree, ifree);
+	if (bt_pfxsaved)
+		(void)fprintf(stderr, "prefix checking removed %lu bytes.\n",
+		    bt_pfxsaved);
+}
+#endif
Index: /branches/EMX/src/emx/bsd/db/btree/bt_delete.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_delete.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_delete.c	(revision 273)
@@ -0,0 +1,657 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_delete.c	8.13 (Berkeley) 7/28/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_bdelete __P((BTREE *, const DBT *));
+static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int));
+static int __bt_pdelete __P((BTREE *, PAGE *));
+static int __bt_relink __P((BTREE *, PAGE *));
+static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *));
+
+/*
+ * __bt_delete
+ *	Delete the item(s) referenced by a key.
+ *
+ * Return RET_SPECIAL if the key is not found.
+ */
+int
+__bt_delete(dbp, key, flags)
+	const DB *dbp;
+	const DBT *key;
+	u_int flags;
+{
+	BTREE *t;
+	CURSOR *c;
+	PAGE *h;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Check for change to a read-only tree. */
+	if (F_ISSET(t, B_RDONLY)) {
+		errno = EPERM;
+		return (RET_ERROR);
+	}
+
+	switch (flags) {
+	case 0:
+		status = __bt_bdelete(t, key);
+		break;
+	case R_CURSOR:
+		/*
+		 * If flags is R_CURSOR, delete the cursor.  Must already
+		 * have started a scan and not have already deleted it.
+		 */
+		c = &t->bt_cursor;
+		if (F_ISSET(c, CURS_INIT)) {
+			if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+				return (RET_ERROR);
+
+			/*
+			 * If the page is about to be emptied, we'll need to
+			 * delete it, which means we have to acquire a stack.
+			 */
+			if (NEXTINDEX(h) == 1)
+				if (__bt_stkacq(t, &h, &t->bt_cursor))
+					return (RET_ERROR);
+
+			status = __bt_dleaf(t, NULL, h, c->pg.index);
+
+			if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
+				if (__bt_pdelete(t, h))
+					return (RET_ERROR);
+			} else
+				mpool_put(t->bt_mp,
+				    h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
+			break;
+		}
+		/* FALLTHROUGH */
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+	if (status == RET_SUCCESS)
+		F_SET(t, B_MODIFIED);
+	return (status);
+}
+
+/*
+ * __bt_stkacq --
+ *	Acquire a stack so we can delete a cursor entry.
+ *
+ * Parameters:
+ *	  t:	tree
+ *	 hp:	pointer to current, pinned PAGE pointer
+ *	  c:	pointer to the cursor
+ *
+ * Returns:
+ *	0 on success, 1 on failure
+ */
+static int
+__bt_stkacq(t, hp, c)
+	BTREE *t;
+	PAGE **hp;
+	CURSOR *c;
+{
+	BINTERNAL *bi;
+	EPG *e;
+	EPGNO *parent;
+	PAGE *h;
+	indx_t index;
+	pgno_t pgno;
+	recno_t nextpg, prevpg;
+	int exact, level;
+	
+	/*
+	 * Find the first occurrence of the key in the tree.  Toss the
+	 * currently locked page so we don't hit an already-locked page.
+	 */
+	h = *hp;
+	mpool_put(t->bt_mp, h, 0);
+	if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+		return (1);
+	h = e->page;
+
+	/* See if we got it in one shot. */
+	if (h->pgno == c->pg.pgno)
+		goto ret;
+
+	/*
+	 * Move right, looking for the page.  At each move we have to move
+	 * up the stack until we don't have to move to the next page.  If
+	 * we have to change pages at an internal level, we have to fix the
+	 * stack back up.
+	 */
+	while (h->pgno != c->pg.pgno) {
+		if ((nextpg = h->nextpg) == P_INVALID)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Move up the stack. */
+		for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+			/* Get the parent page. */
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				return (1);
+
+			/* Move to the next index. */
+			if (parent->index != NEXTINDEX(h) - 1) {
+				index = parent->index + 1;
+				BT_PUSH(t, h->pgno, index);
+				break;
+			}
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		/* Restore the stack. */
+		while (level--) {
+			/* Push the next level down onto the stack. */
+			bi = GETBINTERNAL(h, index);
+			pgno = bi->pgno;
+			BT_PUSH(t, pgno, 0);
+
+			/* Lose the currently pinned page. */
+			mpool_put(t->bt_mp, h, 0);
+
+			/* Get the next level down. */
+			if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+				return (1);
+			index = 0;
+		}
+		mpool_put(t->bt_mp, h, 0);
+		if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
+			return (1);
+	}
+
+	if (h->pgno == c->pg.pgno)
+		goto ret;
+
+	/* Reacquire the original stack. */
+	mpool_put(t->bt_mp, h, 0);
+	if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+		return (1);
+	h = e->page;
+
+	/*
+	 * Move left, looking for the page.  At each move we have to move
+	 * up the stack until we don't have to change pages to move to the
+	 * next page.  If we have to change pages at an internal level, we
+	 * have to fix the stack back up.
+	 */
+	while (h->pgno != c->pg.pgno) {
+		if ((prevpg = h->prevpg) == P_INVALID)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+
+		/* Move up the stack. */
+		for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+			/* Get the parent page. */
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				return (1);
+
+			/* Move to the next index. */
+			if (parent->index != 0) {
+				index = parent->index - 1;
+				BT_PUSH(t, h->pgno, index);
+				break;
+			}
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		/* Restore the stack. */
+		while (level--) {
+			/* Push the next level down onto the stack. */
+			bi = GETBINTERNAL(h, index);
+			pgno = bi->pgno;
+
+			/* Lose the currently pinned page. */
+			mpool_put(t->bt_mp, h, 0);
+
+			/* Get the next level down. */
+			if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+				return (1);
+
+			index = NEXTINDEX(h) - 1;
+			BT_PUSH(t, pgno, index);
+		}
+		mpool_put(t->bt_mp, h, 0);
+		if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
+			return (1);
+	}
+	
+
+ret:	mpool_put(t->bt_mp, h, 0);
+	return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
+}
+
+/*
+ * __bt_bdelete --
+ *	Delete all key/data pairs matching the specified key.
+ *
+ * Parameters:
+ *	  t:	tree
+ *	key:	key to delete
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+__bt_bdelete(t, key)
+	BTREE *t;
+	const DBT *key;
+{
+	EPG *e;
+	PAGE *h;
+	int deleted, exact, redo;
+
+	deleted = 0;
+
+	/* Find any matching record; __bt_search pins the page. */
+loop:	if ((e = __bt_search(t, key, &exact)) == NULL)
+		return (deleted ? RET_SUCCESS : RET_ERROR);
+	if (!exact) {
+		mpool_put(t->bt_mp, e->page, 0);
+		return (deleted ? RET_SUCCESS : RET_SPECIAL);
+	}
+
+	/*
+	 * Delete forward, then delete backward, from the found key.  If
+	 * there are duplicates and we reach either side of the page, do
+	 * the key search again, so that we get them all.
+	 */
+	redo = 0;
+	h = e->page;
+	do {
+		if (__bt_dleaf(t, key, h, e->index)) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		if (F_ISSET(t, B_NODUPS)) {
+			if (NEXTINDEX(h) == 0) {
+				if (__bt_pdelete(t, h))
+					return (RET_ERROR);
+			} else
+				mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			return (RET_SUCCESS);
+		}
+		deleted = 1;
+	} while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
+
+	/* Check for right-hand edge of the page. */
+	if (e->index == NEXTINDEX(h))
+		redo = 1;
+
+	/* Delete from the key to the beginning of the page. */
+	while (e->index-- > 0) {
+		if (__bt_cmp(t, key, e) != 0)
+			break;
+		if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		if (e->index == 0)
+			redo = 1;
+	}
+
+	/* Check for an empty page. */
+	if (NEXTINDEX(h) == 0) {
+		if (__bt_pdelete(t, h))
+			return (RET_ERROR);
+		goto loop;
+	}
+
+	/* Put the page. */
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	if (redo)
+		goto loop;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_pdelete --
+ *	Delete a single page from the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	leaf page
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ *
+ * Side-effects:
+ *	mpool_put's the page
+ */
+static int
+__bt_pdelete(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	BINTERNAL *bi;
+	PAGE *pg;
+	EPGNO *parent;
+	indx_t cnt, index, *ip, offset;
+	u_int32_t nksize;
+	char *from;
+
+	/*
+	 * Walk the parent page stack -- a LIFO stack of the pages that were
+	 * traversed when we searched for the page where the delete occurred.
+	 * Each stack entry is a page number and a page index offset.  The
+	 * offset is for the page traversed on the search.  We've just deleted
+	 * a page, so we have to delete the key from the parent page.
+	 *
+	 * If the delete from the parent page makes it empty, this process may
+	 * continue all the way up the tree.  We stop if we reach the root page
+	 * (which is never deleted, it's just not worth the effort) or if the
+	 * delete does not empty the page.
+	 */
+	while ((parent = BT_POP(t)) != NULL) {
+		/* Get the parent page. */
+		if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			return (RET_ERROR);
+		
+		index = parent->index;
+		bi = GETBINTERNAL(pg, index);
+
+		/* Free any overflow pages. */
+		if (bi->flags & P_BIGKEY &&
+		    __ovfl_delete(t, bi->bytes) == RET_ERROR) {
+			mpool_put(t->bt_mp, pg, 0);
+			return (RET_ERROR);
+		}
+
+		/*
+		 * Free the parent if it has only the one key and it's not the
+		 * root page. If it's the rootpage, turn it back into an empty
+		 * leaf page.
+		 */
+		if (NEXTINDEX(pg) == 1)
+			if (pg->pgno == P_ROOT) {
+				pg->lower = BTDATAOFF;
+				pg->upper = t->bt_psize;
+				pg->flags = P_BLEAF;
+			} else {
+				if (__bt_relink(t, pg) || __bt_free(t, pg))
+					return (RET_ERROR);
+				continue;
+			}
+		else {
+			/* Pack remaining key items at the end of the page. */
+			nksize = NBINTERNAL(bi->ksize);
+			from = (char *)pg + pg->upper;
+			memmove(from + nksize, from, (char *)bi - from);
+			pg->upper += nksize;
+
+			/* Adjust indices' offsets, shift the indices down. */
+			offset = pg->linp[index];
+			for (cnt = index, ip = &pg->linp[0]; cnt--; ++ip)
+				if (ip[0] < offset)
+					ip[0] += nksize;
+			for (cnt = NEXTINDEX(pg) - index; --cnt; ++ip)
+				ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
+			pg->lower -= sizeof(indx_t);
+		}
+
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+		break;
+	}
+
+	/* Free the leaf page, as long as it wasn't the root. */
+	if (h->pgno == P_ROOT) {
+		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+		return (RET_SUCCESS);
+	}
+	return (__bt_relink(t, h) || __bt_free(t, h));
+}
+
+/*
+ * __bt_dleaf --
+ *	Delete a single record from a leaf page.
+ *
+ * Parameters:
+ *	t:	tree
+ *    key:	referenced key
+ *	h:	page
+ *	index:	index on page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_dleaf(t, key, h, index)
+	BTREE *t;
+	const DBT *key;
+	PAGE *h;
+	u_int index;
+{
+	BLEAF *bl;
+	indx_t cnt, *ip, offset;
+	u_int32_t nbytes;
+	void *to;
+	char *from;
+
+	/* If this record is referenced by the cursor, delete the cursor. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == index &&
+	    __bt_curdel(t, key, h, index))
+		return (RET_ERROR);
+
+	/* If the entry uses overflow pages, make them available for reuse. */
+	to = bl = GETBLEAF(h, index);
+	if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
+		return (RET_ERROR);
+	if (bl->flags & P_BIGDATA &&
+	    __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Pack the remaining key/data items at the end of the page. */
+	nbytes = NBLEAF(bl);
+	from = (char *)h + h->upper;
+	memmove(from + nbytes, from, (char *)to - from);
+	h->upper += nbytes;
+
+	/* Adjust the indices' offsets, shift the indices down. */
+	offset = h->linp[index];
+	for (cnt = index, ip = &h->linp[0]; cnt--; ++ip)
+		if (ip[0] < offset)
+			ip[0] += nbytes;
+	for (cnt = NEXTINDEX(h) - index; --cnt; ++ip)
+		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+	h->lower -= sizeof(indx_t);
+
+	/* If the cursor is on this page, adjust it as necessary. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > index)
+		--t->bt_cursor.pg.index;
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_curdel --
+ *	Delete the cursor.
+ *
+ * Parameters:
+ *	t:	tree
+ *    key:	referenced key (or NULL)
+ *	h:	page
+ *  index:	index on page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+static int
+__bt_curdel(t, key, h, index)
+	BTREE *t;
+	const DBT *key;
+	PAGE *h;
+	u_int index;
+{
+	CURSOR *c;
+	EPG e;
+	PAGE *pg;
+	int curcopy, status;
+
+	/*
+	 * If there are duplicates, move forward or backward to one.
+	 * Otherwise, copy the key into the cursor area.
+	 */
+	c = &t->bt_cursor;
+	F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
+
+	curcopy = 0;
+	if (!F_ISSET(t, B_NODUPS)) {
+		/*
+		 * We're going to have to do comparisons.  If we weren't
+		 * provided a copy of the key, i.e. the user is deleting
+		 * the current cursor position, get one.
+		 */
+		if (key == NULL) {
+			e.page = h;
+			e.index = index;
+			if ((status = __bt_ret(t, &e,
+			    &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
+				return (status);
+			curcopy = 1;
+			key = &c->key;
+		}
+		/* Check previous key, if not at the beginning of the page. */
+		if (index > 0) { 
+			e.page = h;
+			e.index = index - 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_BEFORE);
+				goto dup2;
+			}
+		}
+		/* Check next key, if not at the end of the page. */
+		if (index < NEXTINDEX(h) - 1) {
+			e.page = h;
+			e.index = index + 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_AFTER);
+				goto dup2;
+			}
+		}
+		/* Check previous key if at the beginning of the page. */
+		if (index == 0 && h->prevpg != P_INVALID) {
+			if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+				return (RET_ERROR);
+			e.page = pg;
+			e.index = NEXTINDEX(pg) - 1;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_BEFORE);
+				goto dup1;
+			}
+			mpool_put(t->bt_mp, pg, 0);
+		}
+		/* Check next key if at the end of the page. */
+		if (index == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
+			if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+				return (RET_ERROR);
+			e.page = pg;
+			e.index = 0;
+			if (__bt_cmp(t, key, &e) == 0) {
+				F_SET(c, CURS_AFTER);
+dup1:				mpool_put(t->bt_mp, pg, 0);
+dup2:				c->pg.pgno = e.page->pgno;
+				c->pg.index = e.index;
+				return (RET_SUCCESS);
+			}
+			mpool_put(t->bt_mp, pg, 0);
+		}
+	}
+	e.page = h;
+	e.index = index;
+	if (curcopy || (status =
+	    __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
+		F_SET(c, CURS_ACQUIRE);
+		return (RET_SUCCESS);
+	}
+	return (status);
+}
+
+/*
+ * __bt_relink --
+ *	Link around a deleted page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to be deleted
+ */
+static int
+__bt_relink(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	PAGE *pg;
+
+	if (h->nextpg != P_INVALID) {
+		if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+			return (RET_ERROR);
+		pg->prevpg = h->prevpg;
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+	}
+	if (h->prevpg != P_INVALID) {
+		if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+			return (RET_ERROR);
+		pg->nextpg = h->nextpg;
+		mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+	}
+	return (0);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_get.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_get.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_get.c	(revision 273)
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_get.c	8.6 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __BT_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to find
+ *	data:	data to return
+ *	flag:	currently unused
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__bt_get(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	int exact, status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Get currently doesn't take any flags. */
+	if (flags) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if ((e = __bt_search(t, key, &exact)) == NULL)
+		return (RET_ERROR);
+	if (!exact) {
+		mpool_put(t->bt_mp, e->page, 0);
+		return (RET_SPECIAL);
+	}
+
+	status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
+
+	/*
+	 * If the user is doing concurrent access, we copied the
+	 * key/data, toss the page.
+	 */
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_open.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_open.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_open.c	(revision 273)
@@ -0,0 +1,469 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_open.c	8.10 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Implementation of btree access method for 4.4BSD.
+ *
+ * The design here was originally based on that of the btree access method
+ * used in the Postgres database system at UC Berkeley.  This implementation
+ * is wholly independent of the Postgres code.
+ */
+
+#include <sys/param.h>
+#ifdef __EMX__
+#include <sys/types.h>
+#endif /* __EMX__ */
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+#undef	MINPSIZE
+#define	MINPSIZE	128
+#endif
+
+static int byteorder __P((void));
+static int nroot __P((BTREE *));
+static int tmp __P((void));
+
+/*
+ * __BT_OPEN -- Open a btree.
+ *
+ * Creates and fills a DB struct, and calls the routine that actually
+ * opens the btree.
+ *
+ * Parameters:
+ *	fname:	filename (NULL for in-memory trees)
+ *	flags:	open flag bits
+ *	mode:	open permission bits
+ *	b:	BTREEINFO pointer
+ *
+ * Returns:
+ *	NULL on failure, pointer to DB on success.
+ *
+ */
+DB *
+__bt_open(fname, flags, mode, openinfo, dflags)
+	const char *fname;
+	int flags, mode, dflags;
+	const BTREEINFO *openinfo;
+{
+	struct stat sb;
+	BTMETA m;
+	BTREE *t;
+	BTREEINFO b;
+	DB *dbp;
+	pgno_t ncache;
+	ssize_t nr;
+	int machine_lorder;
+
+	t = NULL;
+
+	/*
+	 * Intention is to make sure all of the user's selections are okay
+	 * here and then use them without checking.  Can't be complete, since
+	 * we don't know the right page size, lorder or flags until the backing
+	 * file is opened.  Also, the file's page size can cause the cachesize
+	 * to change.
+	 */
+	machine_lorder = byteorder();
+	if (openinfo) {
+		b = *openinfo;
+
+		/* Flags: R_DUP. */
+		if (b.flags & ~(R_DUP))
+			goto einval;
+
+		/*
+		 * Page size must be indx_t aligned and >= MINPSIZE.  Default
+		 * page size is set farther on, based on the underlying file
+		 * transfer size.
+		 */
+		if (b.psize &&
+		    (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
+		    b.psize & sizeof(indx_t) - 1))
+			goto einval;
+
+		/* Minimum number of keys per page; absolute minimum is 2. */
+		if (b.minkeypage) {
+			if (b.minkeypage < 2)
+				goto einval;
+		} else
+			b.minkeypage = DEFMINKEYPAGE;
+
+		/* If no comparison, use default comparison and prefix. */
+		if (b.compare == NULL) {
+			b.compare = __bt_defcmp;
+			if (b.prefix == NULL)
+				b.prefix = __bt_defpfx;
+		}
+
+		if (b.lorder == 0)
+			b.lorder = machine_lorder;
+	} else {
+		b.compare = __bt_defcmp;
+		b.cachesize = 0;
+		b.flags = 0;
+		b.lorder = machine_lorder;
+		b.minkeypage = DEFMINKEYPAGE;
+		b.prefix = __bt_defpfx;
+		b.psize = 0;
+	}
+
+	/* Check for the ubiquitous PDP-11. */
+	if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
+		goto einval;
+
+	/* Allocate and initialize DB and BTREE structures. */
+	if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
+		goto err;
+	memset(t, 0, sizeof(BTREE));
+	t->bt_fd = -1;			/* Don't close unopened fd on error. */
+	t->bt_lorder = b.lorder;
+	t->bt_order = NOT;
+	t->bt_cmp = b.compare;
+	t->bt_pfx = b.prefix;
+	t->bt_rfd = -1;
+
+	if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
+		goto err;
+	memset(t->bt_dbp, 0, sizeof(DB));
+	if (t->bt_lorder != machine_lorder)
+		F_SET(t, B_NEEDSWAP);
+
+	dbp->type = DB_BTREE;
+	dbp->internal = t;
+	dbp->close = __bt_close;
+	dbp->del = __bt_delete;
+	dbp->fd = __bt_fd;
+	dbp->get = __bt_get;
+	dbp->put = __bt_put;
+	dbp->seq = __bt_seq;
+	dbp->sync = __bt_sync;
+
+	/*
+	 * If no file name was supplied, this is an in-memory btree and we
+	 * open a backing temporary file.  Otherwise, it's a disk-based tree.
+	 */
+	if (fname) {
+		switch (flags & O_ACCMODE) {
+		case O_RDONLY:
+			F_SET(t, B_RDONLY);
+			break;
+		case O_RDWR:
+			break;
+		case O_WRONLY:
+		default:
+			goto einval;
+		}
+		
+		if ((t->bt_fd = open(fname, flags, mode)) < 0)
+			goto err;
+
+	} else {
+		if ((flags & O_ACCMODE) != O_RDWR)
+			goto einval;
+#ifdef __EMX__
+		{
+		char namestr[] = "btXXXXXX";
+		char absname[MAXPATHLEN];
+		if ((t->bt_fd = mkstemp (namestr)) == -1)
+			goto err;
+		setmode (t->bt_fd, O_BINARY);
+		if (_abspath (absname, namestr, sizeof (absname)) == 0)
+			t->tempname = strdup (absname);
+		}
+#else /* not __EMX__ */
+		if ((t->bt_fd = tmp()) == -1)
+			goto err;
+#endif /* not __EMX__ */
+		F_SET(t, B_INMEM);
+	}
+
+	if (fcntl(t->bt_fd, F_SETFD, 1) == -1)
+		goto err;
+
+	if (fstat(t->bt_fd, &sb))
+		goto err;
+	if (sb.st_size) {
+		if ((nr = read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
+			goto err;
+		if (nr != sizeof(BTMETA))
+			goto eftype;
+
+		/*
+		 * Read in the meta-data.  This can change the notion of what
+		 * the lorder, page size and flags are, and, when the page size
+		 * changes, the cachesize value can change too.  If the user
+		 * specified the wrong byte order for an existing database, we
+		 * don't bother to return an error, we just clear the NEEDSWAP
+		 * bit.
+		 */
+		if (m.magic == BTREEMAGIC)
+			F_CLR(t, B_NEEDSWAP);
+		else {
+			F_SET(t, B_NEEDSWAP);
+			M_32_SWAP(m.magic);
+			M_32_SWAP(m.version);
+			M_32_SWAP(m.psize);
+			M_32_SWAP(m.free);
+			M_32_SWAP(m.nrecs);
+			M_32_SWAP(m.flags);
+		}
+		if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
+			goto eftype;
+		if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
+		    m.psize & sizeof(indx_t) - 1)
+			goto eftype;
+		if (m.flags & ~SAVEMETA)
+			goto eftype;
+		b.psize = m.psize;
+		F_SET(t, m.flags);
+		t->bt_free = m.free;
+		t->bt_nrecs = m.nrecs;
+	} else {
+		/*
+		 * Set the page size to the best value for I/O to this file.
+		 * Don't overflow the page offset type.
+		 */
+		if (b.psize == 0) {
+#ifdef __EMX__
+			b.psize = 512;
+#else /* not __EMX__ */
+			b.psize = sb.st_blksize;
+#endif /* not __EMX__ */
+			if (b.psize < MINPSIZE)
+				b.psize = MINPSIZE;
+			if (b.psize > MAX_PAGE_OFFSET + 1)
+				b.psize = MAX_PAGE_OFFSET + 1;
+		}
+
+		/* Set flag if duplicates permitted. */
+		if (!(b.flags & R_DUP))
+			F_SET(t, B_NODUPS);
+
+		t->bt_free = P_INVALID;
+		t->bt_nrecs = 0;
+		F_SET(t, B_METADIRTY);
+	}
+
+	t->bt_psize = b.psize;
+
+	/* Set the cache size; must be a multiple of the page size. */
+	if (b.cachesize && b.cachesize & b.psize - 1)
+		b.cachesize += (~b.cachesize & b.psize - 1) + 1;
+	if (b.cachesize < b.psize * MINCACHE)
+		b.cachesize = b.psize * MINCACHE;
+
+	/* Calculate number of pages to cache. */
+	ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
+
+	/*
+	 * The btree data structure requires that at least two keys can fit on
+	 * a page, but other than that there's no fixed requirement.  The user
+	 * specified a minimum number per page, and we translated that into the
+	 * number of bytes a key/data pair can use before being placed on an
+	 * overflow page.  This calculation includes the page header, the size
+	 * of the index referencing the leaf item and the size of the leaf item
+	 * structure.  Also, don't let the user specify a minkeypage such that
+	 * a key/data pair won't fit even if both key and data are on overflow
+	 * pages.
+	 */
+	t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
+	    (sizeof(indx_t) + NBLEAFDBT(0, 0));
+	if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
+		t->bt_ovflsize =
+		    NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
+
+	/* Initialize the buffer pool. */
+	if ((t->bt_mp =
+	    mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
+		goto err;
+	if (!F_ISSET(t, B_INMEM))
+		mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
+
+	/* Create a root page if new tree. */
+	if (nroot(t) == RET_ERROR)
+		goto err;
+
+	/* Global flags. */
+	if (dflags & DB_LOCK)
+		F_SET(t, B_DB_LOCK);
+	if (dflags & DB_SHMEM)
+		F_SET(t, B_DB_SHMEM);
+	if (dflags & DB_TXN)
+		F_SET(t, B_DB_TXN);
+
+	return (dbp);
+
+einval:	errno = EINVAL;
+	goto err;
+
+eftype:	errno = EFTYPE;
+	goto err;
+
+err:	if (t) {
+		if (t->bt_dbp)
+			free(t->bt_dbp);
+		if (t->bt_fd != -1)
+			(void)close(t->bt_fd);
+#ifdef __EMX__
+		if (t->tempname != NULL) {
+			(void)unlink(t->tempname);
+			free(t->tempname);
+		}
+#endif /* __EMX__ */
+		free(t);
+	}
+	return (NULL);
+}
+
+/*
+ * NROOT -- Create the root of a new tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+nroot(t)
+	BTREE *t;
+{
+	PAGE *meta, *root;
+	pgno_t npg;
+
+	if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) {
+		mpool_put(t->bt_mp, meta, 0);
+		return (RET_SUCCESS);
+	}
+	if (errno != EINVAL)		/* It's OK to not exist. */
+		return (RET_ERROR);
+	errno = 0;
+
+	if ((meta = mpool_new(t->bt_mp, &npg)) == NULL)
+		return (RET_ERROR);
+
+	if ((root = mpool_new(t->bt_mp, &npg)) == NULL)
+		return (RET_ERROR);
+
+	if (npg != P_ROOT)
+		return (RET_ERROR);
+	root->pgno = npg;
+	root->prevpg = root->nextpg = P_INVALID;
+	root->lower = BTDATAOFF;
+	root->upper = t->bt_psize;
+	root->flags = P_BLEAF;
+	memset(meta, 0, t->bt_psize);
+	mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, root, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+static int
+tmp()
+{
+	sigset_t set, oset;
+	int fd;
+	char *envtmp;
+	char path[MAXPATHLEN];
+
+	envtmp = getenv("TMPDIR");
+	(void)snprintf(path,
+	    sizeof(path), "%s/bt.XXXXXX", envtmp ? envtmp : "/tmp");
+
+	(void)sigfillset(&set);
+	(void)sigprocmask(SIG_BLOCK, &set, &oset);
+	if ((fd = mkstemp(path)) != -1)
+		(void)unlink(path);
+	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
+	return(fd);
+}
+
+static int
+byteorder()
+{
+	u_int32_t x;
+	u_char *p;
+
+	x = 0x01020304;
+	p = (u_char *)&x;
+	switch (*p) {
+	case 1:
+		return (BIG_ENDIAN);
+	case 4:
+		return (LITTLE_ENDIAN);
+	default:
+		return (0);
+	}
+}
+
+int
+__bt_fd(dbp)
+        const DB *dbp;
+{
+	BTREE *t;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* In-memory database can't have a file descriptor. */
+	if (F_ISSET(t, B_INMEM)) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (t->bt_fd);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_overflow.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_overflow.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_overflow.c	(revision 273)
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_overflow.c	8.5 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * Big key/data code.
+ *
+ * Big key and data entries are stored on linked lists of pages.  The initial
+ * reference is byte string stored with the key or data and is the page number
+ * and size.  The actual record is stored in a chain of pages linked by the
+ * nextpg field of the PAGE header.
+ *
+ * The first page of the chain has a special property.  If the record is used
+ * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
+ * in the header.
+ *
+ * XXX
+ * A single DBT is written to each chain, so a lot of space on the last page
+ * is wasted.  This is a fairly major bug for some data sets.
+ */
+
+/*
+ * __OVFL_GET -- Get an overflow key/data item.
+ *
+ * Parameters:
+ *	t:	tree
+ *	p:	pointer to { pgno_t, u_int32_t }
+ *	buf:	storage address
+ *	bufsz:	storage size
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_get(t, p, ssz, buf, bufsz)
+	BTREE *t;
+	void *p;
+	size_t *ssz;
+	void **buf;
+	size_t *bufsz;
+{
+	PAGE *h;
+	pgno_t pg;
+	size_t nb, plen;
+	u_int32_t sz;
+
+	memmove(&pg, p, sizeof(pgno_t));
+	memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+	*ssz = sz;
+
+#ifdef DEBUG
+	if (pg == P_INVALID || sz == 0)
+		abort();
+#endif
+	/* Make the buffer bigger as necessary. */
+	if (*bufsz < sz) {
+		*buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz));
+		if (*buf == NULL)
+			return (RET_ERROR);
+		*bufsz = sz;
+	}
+
+	/*
+	 * Step through the linked list of pages, copying the data on each one
+	 * into the buffer.  Never copy more than the data's length.
+	 */
+	plen = t->bt_psize - BTDATAOFF;
+	for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+
+		nb = MIN(sz, plen);
+		memmove(p, (char *)h + BTDATAOFF, nb);
+		mpool_put(t->bt_mp, h, 0);
+
+		if ((sz -= nb) == 0)
+			break;
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_PUT -- Store an overflow key/data item.
+ *
+ * Parameters:
+ *	t:	tree
+ *	data:	DBT to store
+ *	pgno:	storage page number
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_put(t, dbt, pg)
+	BTREE *t;
+	const DBT *dbt;
+	pgno_t *pg;
+{
+	PAGE *h, *last;
+	void *p;
+	pgno_t npg;
+	size_t nb, plen;
+	u_int32_t sz;
+
+	/*
+	 * Allocate pages and copy the key/data record into them.  Store the
+	 * number of the first page in the chain.
+	 */
+	plen = t->bt_psize - BTDATAOFF;
+	for (last = NULL, p = dbt->data, sz = dbt->size;;
+	    p = (char *)p + plen, last = h) {
+		if ((h = __bt_new(t, &npg)) == NULL)
+			return (RET_ERROR);
+
+		h->pgno = npg;
+		h->nextpg = h->prevpg = P_INVALID;
+		h->flags = P_OVERFLOW;
+		h->lower = h->upper = 0;
+
+		nb = MIN(sz, plen);
+		memmove((char *)h + BTDATAOFF, p, nb);
+
+		if (last) {
+			last->nextpg = h->pgno;
+			mpool_put(t->bt_mp, last, MPOOL_DIRTY);
+		} else
+			*pg = h->pgno;
+
+		if ((sz -= nb) == 0) {
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		}
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_DELETE -- Delete an overflow chain.
+ *
+ * Parameters:
+ *	t:	tree
+ *	p:	pointer to { pgno_t, u_int32_t }
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_delete(t, p)
+	BTREE *t;
+	void *p;
+{
+	PAGE *h;
+	pgno_t pg;
+	size_t plen;
+	u_int32_t sz;
+
+	memmove(&pg, p, sizeof(pgno_t));
+	memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+
+#ifdef DEBUG
+	if (pg == P_INVALID || sz == 0)
+		abort();
+#endif
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+		return (RET_ERROR);
+
+	/* Don't delete chains used by internal pages. */
+	if (h->flags & P_PRESERVE) {
+		mpool_put(t->bt_mp, h, 0);
+		return (RET_SUCCESS);
+	}
+
+	/* Step through the chain, calling the free routine for each page. */
+	for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
+		pg = h->nextpg;
+		__bt_free(t, h);
+		if (sz <= plen)
+			break;
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+	}
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_page.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_page.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_page.c	(revision 273)
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_page.c	8.3 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_free --
+ *	Put a page on the freelist.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to free
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ *
+ * Side-effect:
+ *	mpool_put's the page.
+ */
+int
+__bt_free(t, h)
+	BTREE *t;
+	PAGE *h;
+{
+	/* Insert the page at the head of the free list. */
+	h->prevpg = P_INVALID;
+	h->nextpg = t->bt_free;
+	t->bt_free = h->pgno;
+	F_SET(t, B_METADIRTY);
+
+	/* Make sure the page gets written back. */
+	return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
+}
+
+/*
+ * __bt_new --
+ *	Get a new page, preferably from the freelist.
+ *
+ * Parameters:
+ *	t:	tree
+ *	npg:	storage for page number.
+ *
+ * Returns:
+ *	Pointer to a page, NULL on error.
+ */
+PAGE *
+__bt_new(t, npg)
+	BTREE *t;
+	pgno_t *npg;
+{
+	PAGE *h;
+
+	if (t->bt_free != P_INVALID &&
+	    (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
+		*npg = t->bt_free;
+		t->bt_free = h->nextpg;
+		F_SET(t, B_METADIRTY);
+		return (h);
+	}
+	return (mpool_new(t->bt_mp, npg));
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_put.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_put.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_put.c	(revision 273)
@@ -0,0 +1,322 @@
+/* bt_put.c -- changed for emx by Eberhard Mattes -- Jun 2000 */
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_put.c	8.8 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *));
+
+/*
+ * __BT_PUT -- Add a btree item to the tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key
+ *	data:	data
+ *	flag:	R_NOOVERWRITE
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
+ *	tree and R_NOOVERWRITE specified.
+ */
+int
+__bt_put(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	DBT tkey, tdata, ckey;  /* ckey added by em */
+	EPG *e;
+	PAGE *h;
+	indx_t index, nxtindex;
+	pgno_t pg;
+	u_int32_t nbytes;
+	int dflags, exact, status;
+	char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Check for change to a read-only tree. */
+	if (F_ISSET(t, B_RDONLY)) {
+		errno = EPERM;
+		return (RET_ERROR);
+	}
+
+	switch (flags) {
+	case 0:
+	case R_NOOVERWRITE:
+		break;
+	case R_CURSOR:
+		/*
+		 * If flags is R_CURSOR, put the cursor.  Must already
+		 * have started a scan and not have already deleted it.
+		 */
+		if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+		    !F_ISSET(&t->bt_cursor,
+		        CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+			break;
+		/* FALLTHROUGH */
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * If the key/data pair won't fit on a page, store it on overflow
+	 * pages.  Only put the key on the overflow page if the pair are
+	 * still too big after moving the data to an overflow page.
+	 *
+	 * XXX
+	 * If the insert fails later on, the overflow pages aren't recovered.
+	 */
+	ckey = *key;
+	dflags = 0;
+	if (key->size + data->size > t->bt_ovflsize) {
+		if (key->size > t->bt_ovflsize) {
+storekey:		if (__ovfl_put(t, key, &pg) == RET_ERROR)
+				return (RET_ERROR);
+			tkey.data = kb;
+			tkey.size = NOVFLSIZE;
+			memmove(kb, &pg, sizeof(pgno_t));
+			memmove(kb + sizeof(pgno_t),
+			    &key->size, sizeof(u_int32_t));
+			dflags |= P_BIGKEY;
+			key = &tkey;
+		}
+		if (key->size + data->size > t->bt_ovflsize) {
+			if (__ovfl_put(t, data, &pg) == RET_ERROR)
+				return (RET_ERROR);
+			tdata.data = db;
+			tdata.size = NOVFLSIZE;
+			memmove(db, &pg, sizeof(pgno_t));
+			memmove(db + sizeof(pgno_t),
+			    &data->size, sizeof(u_int32_t));
+			dflags |= P_BIGDATA;
+			data = &tdata;
+		}
+		if (key->size + data->size > t->bt_ovflsize)
+			goto storekey;
+	}
+
+	/* Replace the cursor. */
+	if (flags == R_CURSOR) {
+		if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
+			return (RET_ERROR);
+		index = t->bt_cursor.pg.index;
+		goto delete;
+	}
+
+	/*
+	 * Find the key to delete, or, the location at which to insert.
+	 * Bt_fast and __bt_search both pin the returned page.
+	 */
+	if (t->bt_order == NOT || (e = bt_fast(t, &ckey, data, &exact)) == NULL)
+		if ((e = __bt_search(t, &ckey, &exact)) == NULL)
+			return (RET_ERROR);
+	h = e->page;
+	index = e->index;
+
+	/*
+	 * Add the key/data pair to the tree.  If an identical key is already
+	 * in the tree, and R_NOOVERWRITE is set, an error is returned.  If
+	 * R_NOOVERWRITE is not set, the key is either added (if duplicates are
+	 * permitted) or an error is returned.
+	 */
+	switch (flags) {
+	case R_NOOVERWRITE:
+		if (!exact)
+			break;
+		mpool_put(t->bt_mp, h, 0);
+		return (RET_SPECIAL);
+	default:
+		if (!exact || !F_ISSET(t, B_NODUPS))
+			break;
+		/*
+		 * !!!
+		 * Note, the delete may empty the page, so we need to put a
+		 * new entry into the page immediately.
+		 */
+delete:		if (__bt_dleaf(t, &ckey, h, index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		break;
+	}
+
+	/*
+	 * If not enough room, or the user has put a ceiling on the number of
+	 * keys permitted in the page, split the page.  The split code will
+	 * insert the key and data and unpin the current page.  If inserting
+	 * into the offset array, shift the pointers up.
+	 */
+	nbytes = NBLEAFDBT(key->size, data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+		if ((status = __bt_split(t, h, key,
+		    data, dflags, nbytes, index)) != RET_SUCCESS)
+			return (status);
+		goto success;
+	}
+
+	if (index < (nxtindex = NEXTINDEX(h)))
+		memmove(h->linp + index + 1, h->linp + index,
+		    (nxtindex - index) * sizeof(indx_t));
+	h->lower += sizeof(indx_t);
+
+	h->linp[index] = h->upper -= nbytes;
+	dest = (char *)h + h->upper;
+	WR_BLEAF(dest, key, data, dflags);
+
+	/* If the cursor is on this page, adjust it as necessary. */
+	if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+	    !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+	    t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= index)
+		++t->bt_cursor.pg.index;
+
+	if (t->bt_order == NOT)
+		if (h->nextpg == P_INVALID) {
+			if (index == NEXTINDEX(h) - 1) {
+				t->bt_order = FORWARD;
+				t->bt_last.index = index;
+				t->bt_last.pgno = h->pgno;
+			}
+		} else if (h->prevpg == P_INVALID) {
+			if (index == 0) {
+				t->bt_order = BACK;
+				t->bt_last.index = 0;
+				t->bt_last.pgno = h->pgno;
+			}
+		}
+
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+success:
+	if (flags == R_SETCURSOR)
+		__bt_setcur(t, e->page->pgno, e->index);
+
+	F_SET(t, B_MODIFIED);
+	return (RET_SUCCESS);
+}
+
+#ifdef STATISTICS
+u_long bt_cache_hit, bt_cache_miss;
+#endif
+
+/*
+ * BT_FAST -- Do a quick check for sorted data.
+ *
+ * Parameters:
+ *	t:	tree
+ *	key:	key to insert
+ *
+ * Returns:
+ * 	EPG for new record or NULL if not found.
+ */
+static EPG *
+bt_fast(t, key, data, exactp)
+	BTREE *t;
+	const DBT *key, *data;
+	int *exactp;
+{
+	PAGE *h;
+	u_int32_t nbytes;
+	int cmp;
+
+	if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
+		t->bt_order = NOT;
+		return (NULL);
+	}
+	t->bt_cur.page = h;
+	t->bt_cur.index = t->bt_last.index;
+
+	/*
+	 * If won't fit in this page or have too many keys in this page,
+	 * have to search to get split stack.
+	 */
+	nbytes = NBLEAFDBT(key->size, data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t))
+		goto miss;
+
+	if (t->bt_order == FORWARD) {
+		if (t->bt_cur.page->nextpg != P_INVALID)
+			goto miss;
+		if (t->bt_cur.index != NEXTINDEX(h) - 1)
+			goto miss;
+		if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0)
+			goto miss;
+		t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index;
+	} else {
+		if (t->bt_cur.page->prevpg != P_INVALID)
+			goto miss;
+		if (t->bt_cur.index != 0)
+			goto miss;
+		if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0)
+			goto miss;
+		t->bt_last.index = 0;
+	}
+	*exactp = cmp == 0;
+#ifdef STATISTICS
+	++bt_cache_hit;
+#endif
+	return (&t->bt_cur);
+
+miss:
+#ifdef STATISTICS
+	++bt_cache_miss;
+#endif
+	t->bt_order = NOT;
+	mpool_put(t->bt_mp, h, 0);
+	return (NULL);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_search.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_search.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_search.c	(revision 273)
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_search.c	8.8 (Berkeley) 7/31/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_snext __P((BTREE *, PAGE *, const DBT *, int *));
+static int __bt_sprev __P((BTREE *, PAGE *, const DBT *, int *));
+
+/*
+ * __bt_search --
+ *	Search a btree for a key.
+ *
+ * Parameters:
+ *	t:	tree to search
+ *	key:	key to find
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	The EPG for matching record, if any, or the EPG for the location
+ *	of the key, if it were inserted into the tree, is entered into
+ *	the bt_cur field of the tree.  A pointer to the field is returned.
+ */
+EPG *
+__bt_search(t, key, exactp)
+	BTREE *t;
+	const DBT *key;
+	int *exactp;
+{
+	PAGE *h;
+	indx_t base, index, lim;
+	pgno_t pg;
+	int cmp;
+
+	BT_CLR(t);
+	for (pg = P_ROOT;;) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (NULL);
+
+		/* Do a binary search on the current page. */
+		t->bt_cur.page = h;
+		for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
+			t->bt_cur.index = index = base + (lim >> 1);
+			if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
+				if (h->flags & P_BLEAF) {
+					*exactp = 1;
+					return (&t->bt_cur);
+				}
+				goto next;
+			}
+			if (cmp > 0) {
+				base = index + 1;
+				--lim;
+			}
+		}
+
+		/*
+		 * If it's a leaf page, we're almost done.  If no duplicates
+		 * are allowed, or we have an exact match, we're done.  Else,
+		 * it's possible that there were matching keys on this page,
+		 * which later deleted, and we're on a page with no matches
+		 * while there are matches on other pages.  If at the start or
+		 * end of a page, check the adjacent page.
+		 */
+		if (h->flags & P_BLEAF) {
+			if (!F_ISSET(t, B_NODUPS)) {
+				if (base == 0 &&
+				    h->prevpg != P_INVALID &&
+				    __bt_sprev(t, h, key, exactp))
+					return (&t->bt_cur);
+				if (base == NEXTINDEX(h) &&
+				    h->nextpg != P_INVALID &&
+				    __bt_snext(t, h, key, exactp))
+					return (&t->bt_cur);
+			}
+			*exactp = 0;
+			t->bt_cur.index = base;
+			return (&t->bt_cur);
+		}
+
+		/*
+		 * No match found.  Base is the smallest index greater than
+		 * key and may be zero or a last + 1 index.  If it's non-zero,
+		 * decrement by one, and record the internal page which should
+		 * be a parent page for the key.  If a split later occurs, the
+		 * inserted page will be to the right of the saved page.
+		 */
+		index = base ? base - 1 : base;
+
+next:		BT_PUSH(t, h->pgno, index);
+		pg = GETBINTERNAL(h, index)->pgno;
+		mpool_put(t->bt_mp, h, 0);
+	}
+}
+
+/*
+ * __bt_snext --
+ *	Check for an exact match after the key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	current page
+ *	key:	key
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	If an exact match found.
+ */
+static int
+__bt_snext(t, h, key, exactp)
+	BTREE *t;
+	PAGE *h;
+	const DBT *key;
+	int *exactp;
+{
+	EPG e;
+
+	/*
+	 * Get the next page.  The key is either an exact
+	 * match, or not as good as the one we already have.
+	 */
+	if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+		return (0);
+	e.index = 0;
+	if (__bt_cmp(t, key, &e) == 0) {
+		mpool_put(t->bt_mp, h, 0);
+		t->bt_cur = e;
+		*exactp = 1;
+		return (1);
+	}
+	mpool_put(t->bt_mp, e.page, 0);
+	return (0);
+}
+
+/*
+ * __bt_sprev --
+ *	Check for an exact match before the key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	current page
+ *	key:	key
+ *	exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	If an exact match found.
+ */
+static int
+__bt_sprev(t, h, key, exactp)
+	BTREE *t;
+	PAGE *h;
+	const DBT *key;
+	int *exactp;
+{
+	EPG e;
+
+	/*
+	 * Get the previous page.  The key is either an exact
+	 * match, or not as good as the one we already have.
+	 */
+	if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+		return (0);
+	e.index = NEXTINDEX(e.page) - 1;
+	if (__bt_cmp(t, key, &e) == 0) {
+		mpool_put(t->bt_mp, h, 0);
+		t->bt_cur = e;
+		*exactp = 1;
+		return (1);
+	}
+	mpool_put(t->bt_mp, e.page, 0);
+	return (0);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_seq.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_seq.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_seq.c	(revision 273)
@@ -0,0 +1,460 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_seq.c	8.7 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_first __P((BTREE *, const DBT *, EPG *, int *));
+static int __bt_seqadv __P((BTREE *, EPG *, int));
+static int __bt_seqset __P((BTREE *, EPG *, DBT *, int));
+
+/*
+ * Sequential scan support.
+ *
+ * The tree can be scanned sequentially, starting from either end of the
+ * tree or from any specific key.  A scan request before any scanning is
+ * done is initialized as starting from the least node.
+ */
+
+/*
+ * __bt_seq --
+ *	Btree sequential scan interface.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key for positioning and return value
+ *	data:	data return value
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__bt_seq(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG e;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/*
+	 * If scan unitialized as yet, or starting at a specific record, set
+	 * the scan to a specific key.  Both __bt_seqset and __bt_seqadv pin
+	 * the page the cursor references if they're successful.
+	 */
+	switch (flags) {
+	case R_NEXT:
+	case R_PREV:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			status = __bt_seqadv(t, &e, flags);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+	case R_LAST:
+	case R_CURSOR:
+		status = __bt_seqset(t, &e, key, flags);
+		break;
+	default:
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS) {
+		__bt_setcur(t, e.page->pgno, e.index);
+
+		status =
+		    __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+		/*
+		 * If the user is doing concurrent access, we copied the
+		 * key/data, toss the page.
+		 */
+		if (F_ISSET(t, B_DB_LOCK))
+			mpool_put(t->bt_mp, e.page, 0);
+		else
+			t->bt_pinned = e.page;
+	}
+	return (status);
+}
+
+/*
+ * __bt_seqset --
+ *	Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ *	t:	tree
+ *	ep:	storage for returned key
+ *	key:	key for initial scan position
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the cursor references.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqset(t, ep, key, flags)
+	BTREE *t;
+	EPG *ep;
+	DBT *key;
+	int flags;
+{
+	PAGE *h;
+	pgno_t pg;
+	int exact;
+
+	/*
+	 * Find the first, last or specific key in the tree and point the
+	 * cursor at it.  The cursor may not be moved until a new key has
+	 * been found.
+	 */
+	switch (flags) {
+	case R_CURSOR:				/* Keyed scan. */
+		/*
+		 * Find the first instance of the key or the smallest key
+		 * which is greater than or equal to the specified key.
+		 */
+		if (key->data == NULL || key->size == 0) {
+			errno = EINVAL;
+			return (RET_ERROR);
+		}
+		return (__bt_first(t, key, ep, &exact));
+	case R_FIRST:				/* First record. */
+	case R_NEXT:
+		/* Walk down the left-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, 0)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+		}
+		ep->page = h;
+		ep->index = 0;
+		break;
+	case R_LAST:				/* Last record. */
+	case R_PREV:
+		/* Walk down the right-hand side of the tree. */
+		for (pg = P_ROOT;;) {
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+
+			/* Check for an empty tree. */
+			if (NEXTINDEX(h) == 0) {
+				mpool_put(t->bt_mp, h, 0);
+				return (RET_SPECIAL);
+			}
+
+			if (h->flags & (P_BLEAF | P_RLEAF))
+				break;
+			pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+			mpool_put(t->bt_mp, h, 0);
+		}
+
+		ep->page = h;
+		ep->index = NEXTINDEX(h) - 1;
+		break;
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_seqadvance --
+ *	Advance the sequential scan.
+ *
+ * Parameters:
+ *	t:	tree
+ *	flags:	R_NEXT, R_PREV
+ *
+ * Side effects:
+ *	Pins the page the new key/data record is on.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqadv(t, ep, flags)
+	BTREE *t;
+	EPG *ep;
+	int flags;
+{
+	CURSOR *c;
+	PAGE *h;
+	indx_t index;
+	pgno_t pg;
+	int exact;
+
+	/*
+	 * There are a couple of states that we can be in.  The cursor has
+	 * been initialized by the time we get here, but that's all we know.
+	 */
+	c = &t->bt_cursor;
+
+	/*
+	 * The cursor was deleted where there weren't any duplicate records,
+	 * so the key was saved.  Find out where that key would go in the
+	 * current tree.  It doesn't matter if the returned key is an exact
+	 * match or not -- if it's an exact match, the record was added after
+	 * the delete so we can just return it.  If not, as long as there's
+	 * a record there, return it.
+	 */
+	if (F_ISSET(c, CURS_ACQUIRE))
+		return (__bt_first(t, &c->key, ep, &exact));
+
+	/* Get the page referenced by the cursor. */
+	if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+		return (RET_ERROR);
+
+	/*
+ 	 * Find the next/previous record in the tree and point the cursor at
+	 * it.  The cursor may not be moved until a new key has been found.
+	 */
+	switch (flags) {
+	case R_NEXT:			/* Next record. */
+		/*
+		 * The cursor was deleted in duplicate records, and moved
+		 * forward to a record that has yet to be returned.  Clear
+		 * that flag, and return the record.
+		 */
+		if (F_ISSET(c, CURS_AFTER))
+			goto usecurrent;
+		index = c->pg.index;
+		if (++index == NEXTINDEX(h)) {
+			pg = h->nextpg;
+			mpool_put(t->bt_mp, h, 0);
+			if (pg == P_INVALID)
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			index = 0;
+		}
+		break;
+	case R_PREV:			/* Previous record. */
+		/*
+		 * The cursor was deleted in duplicate records, and moved
+		 * backward to a record that has yet to be returned.  Clear
+		 * that flag, and return the record.
+		 */
+		if (F_ISSET(c, CURS_BEFORE)) {
+usecurrent:		F_CLR(c, CURS_AFTER | CURS_BEFORE);
+			ep->page = h;
+			ep->index = c->pg.index;
+			return (RET_SUCCESS);
+		}
+		index = c->pg.index;
+		if (index == 0) {
+			pg = h->prevpg;
+			mpool_put(t->bt_mp, h, 0);
+			if (pg == P_INVALID)
+				return (RET_SPECIAL);
+			if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+				return (RET_ERROR);
+			index = NEXTINDEX(h) - 1;
+		} else
+			--index;
+		break;
+	}
+
+	ep->page = h;
+	ep->index = index;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_first --
+ *	Find the first entry.
+ *
+ * Parameters:
+ *	t:	the tree
+ *    key:	the key
+ *  erval:	return EPG
+ * exactp:	pointer to exact match flag
+ *
+ * Returns:
+ *	The first entry in the tree greater than or equal to key,
+ *	or RET_SPECIAL if no such key exists.
+ */
+static int
+__bt_first(t, key, erval, exactp)
+	BTREE *t;
+	const DBT *key;
+	EPG *erval;
+	int *exactp;
+{
+	PAGE *h;
+	EPG *ep, save;
+	pgno_t pg;
+
+	/*
+	 * Find any matching record; __bt_search pins the page.
+	 *
+	 * If it's an exact match and duplicates are possible, walk backwards
+	 * in the tree until we find the first one.  Otherwise, make sure it's
+	 * a valid key (__bt_search may return an index just past the end of a
+	 * page) and return it.
+	 */
+	if ((ep = __bt_search(t, key, exactp)) == NULL)
+		return (NULL);
+	if (*exactp) {
+		if (F_ISSET(t, B_NODUPS)) {
+			*erval = *ep;
+			return (RET_SUCCESS);
+		}
+			
+		/*
+		 * Walk backwards, as long as the entry matches and there are
+		 * keys left in the tree.  Save a copy of each match in case
+		 * we go too far.
+		 */
+		save = *ep;
+		h = ep->page;
+		do {
+			if (save.page->pgno != ep->page->pgno) {
+				mpool_put(t->bt_mp, save.page, 0);
+				save = *ep;
+			} else
+				save.index = ep->index;
+
+			/*
+			 * Don't unpin the page the last (or original) match
+			 * was on, but make sure it's unpinned if an error
+			 * occurs.
+			 */
+			if (ep->index == 0) {
+				if (h->prevpg == P_INVALID)
+					break;
+				if (h->pgno != save.page->pgno)
+					mpool_put(t->bt_mp, h, 0);
+				if ((h = mpool_get(t->bt_mp,
+				    h->prevpg, 0)) == NULL) {
+					if (h->pgno == save.page->pgno)
+						mpool_put(t->bt_mp,
+						    save.page, 0);
+					return (RET_ERROR);
+				}
+				ep->page = h;
+				ep->index = NEXTINDEX(h);
+			}
+			--ep->index;
+		} while (__bt_cmp(t, key, ep) == 0);
+
+		/*
+		 * Reach here with the last page that was looked at pinned,
+		 * which may or may not be the same as the last (or original)
+		 * match page.  If it's not useful, release it.
+		 */
+		if (h->pgno != save.page->pgno)
+			mpool_put(t->bt_mp, h, 0);
+
+		*erval = save;
+		return (RET_SUCCESS);
+	}
+
+	/* If at the end of a page, find the next entry. */
+	if (ep->index == NEXTINDEX(ep->page)) {
+		h = ep->page;
+		pg = h->nextpg;
+		mpool_put(t->bt_mp, h, 0);
+		if (pg == P_INVALID)
+			return (RET_SPECIAL);
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			return (RET_ERROR);
+		ep->index = 0;
+		ep->page = h;
+	}
+	*erval = *ep;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __bt_setcur --
+ *	Set the cursor to an entry in the tree.
+ *
+ * Parameters:
+ *	t:	the tree
+ *   pgno:	page number
+ *  index:	page index
+ */
+void
+__bt_setcur(t, pgno, index)
+	BTREE *t;
+	pgno_t pgno;
+	u_int index;
+{
+	/* Lose any already deleted key. */
+	if (t->bt_cursor.key.data != NULL) {
+		free(t->bt_cursor.key.data);
+		t->bt_cursor.key.size = 0;
+		t->bt_cursor.key.data = NULL;
+	}
+	F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+
+	/* Update the cursor. */
+	t->bt_cursor.pg.pgno = pgno;
+	t->bt_cursor.pg.index = index;
+	F_SET(&t->bt_cursor, CURS_INIT);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_split.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_split.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_split.c	(revision 273)
@@ -0,0 +1,829 @@
+/* bt_split.c -- changed for emx by Eberhard Mattes -- Dec 2000 */
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_split.c	8.9 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int	 bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *));
+static PAGE	*bt_page
+		    __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t));
+static int	 bt_preserve __P((BTREE *, pgno_t));
+static PAGE	*bt_psplit
+		    __P((BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t));
+static PAGE	*bt_root
+		    __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t));
+static int	 bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *));
+static recno_t	 rec_total __P((PAGE *));
+
+#ifdef STATISTICS
+u_long	bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
+#endif
+
+/*
+ * __BT_SPLIT -- Split the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	sp:	page to split
+ *	key:	key to insert
+ *	data:	data to insert
+ *	flags:	BIGKEY/BIGDATA flags
+ *	ilen:	insert length
+ *	skip:	index to leave open
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_split(t, sp, key, data, flags, ilen, argskip)
+	BTREE *t;
+	PAGE *sp;
+	const DBT *key, *data;
+	int flags;
+	size_t ilen;
+	u_int32_t argskip;
+{
+	BINTERNAL *bi;
+	BLEAF *bl, *tbl;
+	DBT a, b;
+	EPGNO *parent;
+	PAGE *h, *l, *r, *lchild, *rchild;
+	indx_t nxtindex;
+	u_int16_t skip;
+	u_int32_t n, nbytes, nksize;
+	int parentsplit;
+	char *dest;
+
+	/*
+	 * Split the page into two pages, l and r.  The split routines return
+	 * a pointer to the page into which the key should be inserted and with
+	 * skip set to the offset which should be used.  Additionally, l and r
+	 * are pinned.
+	 */
+	skip = argskip;
+	h = sp->pgno == P_ROOT ?
+	    bt_root(t, sp, &l, &r, &skip, ilen) :
+	    bt_page(t, sp, &l, &r, &skip, ilen);
+	if (h == NULL)
+		return (RET_ERROR);
+
+	/*
+	 * Insert the new key/data pair into the leaf page.  (Key inserts
+	 * always cause a leaf page to split first.)
+	 */
+	h->linp[skip] = h->upper -= ilen;
+	dest = (char *)h + h->upper;
+	if (F_ISSET(t, R_RECNO))
+		WR_RLEAF(dest, data, flags)
+	else
+		WR_BLEAF(dest, key, data, flags)
+
+	/* If the root page was split, make it look right. */
+	if (sp->pgno == P_ROOT &&
+	    (F_ISSET(t, R_RECNO) ?
+	    bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+		goto err2;
+
+	/*
+	 * Now we walk the parent page stack -- a LIFO stack of the pages that
+	 * were traversed when we searched for the page that split.  Each stack
+	 * entry is a page number and a page index offset.  The offset is for
+	 * the page traversed on the search.  We've just split a page, so we
+	 * have to insert a new key into the parent page.
+	 *
+	 * If the insert into the parent page causes it to split, may have to
+	 * continue splitting all the way up the tree.  We stop if the root
+	 * splits or the page inserted into didn't have to split to hold the
+	 * new key.  Some algorithms replace the key for the old page as well
+	 * as the new page.  We don't, as there's no reason to believe that the
+	 * first key on the old page is any better than the key we have, and,
+	 * in the case of a key being placed at index 0 causing the split, the
+	 * key is unavailable.
+	 *
+	 * There are a maximum of 5 pages pinned at any time.  We keep the left
+	 * and right pages pinned while working on the parent.   The 5 are the
+	 * two children, left parent and right parent (when the parent splits)
+	 * and the root page or the overflow key page when calling bt_preserve.
+	 * This code must make sure that all pins are released other than the
+	 * root page or overflow page which is unlocked elsewhere.
+	 */
+	while ((parent = BT_POP(t)) != NULL) {
+		lchild = l;
+		rchild = r;
+
+		/* Get the parent page. */
+		if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+			goto err2;
+
+	 	/*
+		 * The new key goes ONE AFTER the index, because the split
+		 * was to the right.
+		 */
+		skip = parent->index + 1;
+
+		/*
+		 * Calculate the space needed on the parent page.
+		 *
+		 * Prefix trees: space hack when inserting into BINTERNAL
+		 * pages.  Retain only what's needed to distinguish between
+		 * the new entry and the LAST entry on the page to its left.
+		 * If the keys compare equal, retain the entire key.  Note,
+		 * we don't touch overflow keys, and the entire key must be
+		 * retained for the next-to-left most key on the leftmost
+		 * page of each level, or the search will fail.  Applicable
+		 * ONLY to internal pages that have leaf pages as children.
+		 * Further reduction of the key between pairs of internal
+		 * pages loses too much information.
+		 */
+		switch (rchild->flags & P_TYPE) {
+		case P_BINTERNAL:
+			bi = GETBINTERNAL(rchild, 0);
+			nbytes = NBINTERNAL(bi->ksize);
+			break;
+		case P_BLEAF:
+			bl = GETBLEAF(rchild, 0);
+			nbytes = NBINTERNAL(bl->ksize);
+			if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
+			    (h->prevpg != P_INVALID || skip > 1)) {
+				tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
+				a.size = tbl->ksize;
+				a.data = tbl->bytes;
+				b.size = bl->ksize;
+				b.data = bl->bytes;
+				nksize = t->bt_pfx(&a, &b);
+				n = NBINTERNAL(nksize);
+				if (n < nbytes) {
+#ifdef STATISTICS
+					bt_pfxsaved += nbytes - n;
+#endif
+					nbytes = n;
+				} else
+					nksize = 0;
+			} else
+				nksize = 0;
+			break;
+		case P_RINTERNAL:
+		case P_RLEAF:
+			nbytes = NRINTERNAL;
+			break;
+		default:
+			abort();
+		}
+
+		/* Split the parent page if necessary or shift the indices. */
+		if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+			sp = h;
+			h = h->pgno == P_ROOT ?
+			    bt_root(t, h, &l, &r, &skip, nbytes) :
+			    bt_page(t, h, &l, &r, &skip, nbytes);
+			if (h == NULL)
+				goto err1;
+			parentsplit = 1;
+		} else {
+			if (skip < (nxtindex = NEXTINDEX(h)))
+				memmove(h->linp + skip + 1, h->linp + skip,
+				    (nxtindex - skip) * sizeof(indx_t));
+			h->lower += sizeof(indx_t);
+			parentsplit = 0;
+		}
+
+		/* Insert the key into the parent page. */
+		switch (rchild->flags & P_TYPE) {
+		case P_BINTERNAL:
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			memmove(dest, bi, nbytes);
+			((BINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		case P_BLEAF:
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
+			    rchild->pgno, bl->flags & P_BIGKEY);
+			memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
+			if (bl->flags & P_BIGKEY &&
+			    bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+				goto err1;
+			break;
+		case P_RINTERNAL:
+			/*
+			 * Update the left page count.  If split
+			 * added at index 0, fix the correct page.
+			 */
+			if (skip > 0)
+				dest = (char *)h + h->linp[skip - 1];
+			else
+				dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+			((RINTERNAL *)dest)->nrecs = rec_total(lchild);
+			((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+			/* Update the right page count. */
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			((RINTERNAL *)dest)->nrecs = rec_total(rchild);
+			((RINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		case P_RLEAF:
+			/*
+			 * Update the left page count.  If split
+			 * added at index 0, fix the correct page.
+			 */
+			if (skip > 0)
+				dest = (char *)h + h->linp[skip - 1];
+			else
+				dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+			((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
+			((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+			/* Update the right page count. */
+			h->linp[skip] = h->upper -= nbytes;
+			dest = (char *)h + h->linp[skip];
+			((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
+			((RINTERNAL *)dest)->pgno = rchild->pgno;
+			break;
+		default:
+			abort();
+		}
+
+		/* Unpin the held pages. */
+		if (!parentsplit) {
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		}
+
+		/* If the root page was split, make it look right. */
+		if (sp->pgno == P_ROOT &&
+		    (F_ISSET(t, R_RECNO) ?
+		    bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+			goto err1;
+
+		mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+		mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+	}
+
+	/* Unpin the held pages. */
+	mpool_put(t->bt_mp, l, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, r, MPOOL_DIRTY);
+
+	/* Clear any pages left on the stack. */
+	return (RET_SUCCESS);
+
+	/*
+	 * If something fails in the above loop we were already walking back
+	 * up the tree and the tree is now inconsistent.  Nothing much we can
+	 * do about it but release any memory we're holding.
+	 */
+err1:	mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+	mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+
+err2:	mpool_put(t->bt_mp, l, 0);
+	mpool_put(t->bt_mp, r, 0);
+	__dbpanic(t->bt_dbp);
+	return (RET_ERROR);
+}
+
+/*
+ * BT_PAGE -- Split a non-root page of a btree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	lp:	pointer to left page pointer
+ *	rp:	pointer to right page pointer
+ *	skip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_page(t, h, lp, rp, skip, ilen)
+	BTREE *t;
+	PAGE *h, **lp, **rp;
+	indx_t *skip;
+	size_t ilen;
+{
+	PAGE *l, *r, *tp;
+	pgno_t npg;
+
+#ifdef STATISTICS
+	++bt_split;
+#endif
+	/* Put the new right page for the split into place. */
+	if ((r = __bt_new(t, &npg)) == NULL)
+		return (NULL);
+	r->pgno = npg;
+	r->lower = BTDATAOFF;
+	r->upper = t->bt_psize;
+	r->nextpg = h->nextpg;
+	r->prevpg = h->pgno;
+	r->flags = h->flags & P_TYPE;
+
+	/*
+	 * If we're splitting the last page on a level because we're appending
+	 * a key to it (skip is NEXTINDEX()), it's likely that the data is
+	 * sorted.  Adding an empty page on the side of the level is less work
+	 * and can push the fill factor much higher than normal.  If we're
+	 * wrong it's no big deal, we'll just do the split the right way next
+	 * time.  It may look like it's equally easy to do a similar hack for
+	 * reverse sorted data, that is, split the tree left, but it's not.
+	 * Don't even try.
+	 */
+	if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
+#ifdef STATISTICS
+		++bt_sortsplit;
+#endif
+		h->nextpg = r->pgno;
+		r->lower = BTDATAOFF + sizeof(indx_t);
+		*skip = 0;
+		*lp = h;
+		*rp = r;
+		return (r);
+	}
+
+	/* Put the new left page for the split into place. */
+	if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
+		mpool_put(t->bt_mp, r, 0);
+		return (NULL);
+	}
+#ifdef PURIFY
+	memset(l, 0xff, t->bt_psize);
+#endif
+	l->pgno = h->pgno;
+	l->nextpg = r->pgno;
+	l->prevpg = h->prevpg;
+	l->lower = BTDATAOFF;
+	l->upper = t->bt_psize;
+	l->flags = h->flags & P_TYPE;
+
+	/* Fix up the previous pointer of the page after the split page. */
+	if (h->nextpg != P_INVALID) {
+		if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
+			free(l);
+			/* XXX mpool_free(t->bt_mp, r->pgno); */
+			return (NULL);
+		}
+		tp->prevpg = r->pgno;
+		mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
+	}
+
+	/*
+	 * Split right.  The key/data pairs aren't sorted in the btree page so
+	 * it's simpler to copy the data from the split page onto two new pages
+	 * instead of copying half the data to the right page and compacting
+	 * the left page in place.  Since the left page can't change, we have
+	 * to swap the original and the allocated left page after the split.
+	 */
+	tp = bt_psplit(t, h, l, r, skip, ilen);
+
+	/* Move the new left page onto the old left page. */
+	memmove(h, l, t->bt_psize);
+	if (tp == l)
+		tp = h;
+	free(l);
+
+	*lp = h;
+	*rp = r;
+	return (tp);
+}
+
+/*
+ * BT_ROOT -- Split the root page of a btree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	lp:	pointer to left page pointer
+ *	rp:	pointer to right page pointer
+ *	skip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_root(t, h, lp, rp, skip, ilen)
+	BTREE *t;
+	PAGE *h, **lp, **rp;
+	indx_t *skip;
+	size_t ilen;
+{
+	PAGE *l, *r, *tp;
+	pgno_t lnpg, rnpg;
+
+#ifdef STATISTICS
+	++bt_split;
+	++bt_rootsplit;
+#endif
+	/* Put the new left and right pages for the split into place. */
+	if ((l = __bt_new(t, &lnpg)) == NULL ||
+	    (r = __bt_new(t, &rnpg)) == NULL)
+		return (NULL);
+	l->pgno = lnpg;
+	r->pgno = rnpg;
+	l->nextpg = r->pgno;
+	r->prevpg = l->pgno;
+	l->prevpg = r->nextpg = P_INVALID;
+	l->lower = r->lower = BTDATAOFF;
+	l->upper = r->upper = t->bt_psize;
+	l->flags = r->flags = h->flags & P_TYPE;
+
+	/* Split the root page. */
+	tp = bt_psplit(t, h, l, r, skip, ilen);
+
+	*lp = l;
+	*rp = r;
+	return (tp);
+}
+
+/*
+ * BT_RROOT -- Fix up the recno root page after it has been split.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	l:	left page
+ *	r:	right page
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_rroot(t, h, l, r)
+	BTREE *t;
+	PAGE *h, *l, *r;
+{
+	char *dest;
+
+	/* Insert the left and right keys, set the header information. */
+	h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
+	dest = (char *)h + h->upper;
+	WR_RINTERNAL(dest,
+	    l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
+
+	h->linp[1] = h->upper -= NRINTERNAL;
+	dest = (char *)h + h->upper;
+	WR_RINTERNAL(dest,
+	    r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
+
+	h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+	/* Unpin the root page, set to recno internal page. */
+	h->flags &= ~P_TYPE;
+	h->flags |= P_RINTERNAL;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * BT_BROOT -- Fix up the btree root page after it has been split.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	root page
+ *	l:	left page
+ *	r:	right page
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_broot(t, h, l, r)
+	BTREE *t;
+	PAGE *h, *l, *r;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	u_int32_t nbytes;
+	char *dest;
+
+	/*
+	 * If the root page was a leaf page, change it into an internal page.
+	 * We copy the key we split on (but not the key's data, in the case of
+	 * a leaf page) to the new root page.
+	 *
+	 * The btree comparison code guarantees that the left-most key on any
+	 * level of the tree is never used, so it doesn't need to be filled in.
+	 */
+	nbytes = NBINTERNAL(0);
+	h->linp[0] = h->upper = t->bt_psize - nbytes;
+	dest = (char *)h + h->upper;
+	WR_BINTERNAL(dest, 0, l->pgno, 0);
+
+	switch (h->flags & P_TYPE) {
+	case P_BLEAF:
+		bl = GETBLEAF(r, 0);
+		nbytes = NBINTERNAL(bl->ksize);
+		h->linp[1] = h->upper -= nbytes;
+		dest = (char *)h + h->upper;
+		WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
+		memmove(dest, bl->bytes, bl->ksize);
+
+		/*
+		 * If the key is on an overflow page, mark the overflow chain
+		 * so it isn't deleted when the leaf copy of the key is deleted.
+		 */
+		if (bl->flags & P_BIGKEY &&
+		    bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+			return (RET_ERROR);
+		break;
+	case P_BINTERNAL:
+		bi = GETBINTERNAL(r, 0);
+		nbytes = NBINTERNAL(bi->ksize);
+		h->linp[1] = h->upper -= nbytes;
+		dest = (char *)h + h->upper;
+		memmove(dest, bi, nbytes);
+		((BINTERNAL *)dest)->pgno = r->pgno;
+		break;
+	default:
+		abort();
+	}
+
+	/* There are two keys on the page. */
+	h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+	/* Unpin the root page, set to btree internal page. */
+	h->flags &= ~P_TYPE;
+	h->flags |= P_BINTERNAL;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * BT_PSPLIT -- Do the real work of splitting the page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	h:	page to be split
+ *	l:	page to put lower half of data
+ *	r:	page to put upper half of data
+ *	pskip:	pointer to index to leave open
+ *	ilen:	insert length
+ *
+ * Returns:
+ *	Pointer to page in which to insert.
+ */
+static PAGE *
+bt_psplit(t, h, l, r, pskip, ilen)
+	BTREE *t;
+	PAGE *h, *l, *r;
+	indx_t *pskip;
+	size_t ilen;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	CURSOR *c;
+	RLEAF *rl;
+	PAGE *rval;
+	void *src;
+	indx_t full, half, nxt, off, skip, top, used;
+	u_int32_t nbytes;
+	int bigkeycnt, isbigkey;
+
+	/*
+	 * Split the data to the left and right pages.  Leave the skip index
+	 * open.  Additionally, make some effort not to split on an overflow
+	 * key.  This makes internal page processing faster and can save
+	 * space as overflow keys used by internal pages are never deleted.
+	 */
+	bigkeycnt = 0;
+	skip = *pskip;
+	full = t->bt_psize - BTDATAOFF;
+	half = full / 2;
+	used = 0;
+	for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
+		if (skip == off) {
+			nbytes = ilen;
+			isbigkey = 0;		/* XXX: not really known. */
+		} else
+			switch (h->flags & P_TYPE) {
+			case P_BINTERNAL:
+				src = bi = GETBINTERNAL(h, nxt);
+				nbytes = NBINTERNAL(bi->ksize);
+				isbigkey = bi->flags & P_BIGKEY;
+				break;
+			case P_BLEAF:
+				src = bl = GETBLEAF(h, nxt);
+				nbytes = NBLEAF(bl);
+				isbigkey = bl->flags & P_BIGKEY;
+				break;
+			case P_RINTERNAL:
+				src = GETRINTERNAL(h, nxt);
+				nbytes = NRINTERNAL;
+				isbigkey = 0;
+				break;
+			case P_RLEAF:
+				src = rl = GETRLEAF(h, nxt);
+				nbytes = NRLEAF(rl);
+				isbigkey = 0;
+				break;
+			default:
+				abort();
+			}
+
+		/*
+		 * If the key/data pairs are substantial fractions of the max
+		 * possible size for the page, it's possible to get situations
+		 * where we decide to try and copy too much onto the left page.
+		 * Make sure that doesn't happen.
+		 */
+		if (skip <= off &&
+		    used + nbytes + sizeof(indx_t) >= full || nxt == top - 1) {
+			--off;
+			break;
+		}
+
+		/* Copy the key/data pair, if not the skipped index. */
+		if (skip != off) {
+			++nxt;
+
+			l->linp[off] = l->upper -= nbytes;
+			memmove((char *)l + l->upper, src, nbytes);
+		}
+
+		used += nbytes + sizeof(indx_t);
+		if (used >= half) {
+			if (!isbigkey || bigkeycnt == 3)
+				break;
+			else
+				++bigkeycnt;
+		}
+	}
+
+	/*
+	 * Off is the last offset that's valid for the left page.
+	 * Nxt is the first offset to be placed on the right page.
+	 */
+	l->lower += (off + 1) * sizeof(indx_t);
+
+	/*
+	 * If splitting the page that the cursor was on, the cursor has to be
+	 * adjusted to point to the same record as before the split.  If the
+	 * cursor is at or past the skipped slot, the cursor is incremented by
+	 * one.  If the cursor is on the right page, it is decremented by the
+	 * number of records split to the left page.
+	 */
+	c = &t->bt_cursor;
+	if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
+		if (c->pg.index >= skip)
+			++c->pg.index;
+		if (c->pg.index < nxt)			/* Left page. */
+			c->pg.pgno = l->pgno;
+		else {					/* Right page. */
+			c->pg.pgno = r->pgno;
+			c->pg.index -= nxt;
+		}
+	}
+
+	/*
+	 * If the skipped index was on the left page, just return that page.
+	 * Otherwise, adjust the skip index to reflect the new position on
+	 * the right page.
+	 */
+	if (skip <= off) {
+		skip = -1;
+		rval = l;
+	} else {
+		rval = r;
+		*pskip -= nxt;
+	}
+
+	for (off = 0; nxt < top; ++off) {
+		if (skip == nxt) {
+			++off;
+			skip = 0;
+		}
+		switch (h->flags & P_TYPE) {
+		case P_BINTERNAL:
+			src = bi = GETBINTERNAL(h, nxt);
+			nbytes = NBINTERNAL(bi->ksize);
+			break;
+		case P_BLEAF:
+			src = bl = GETBLEAF(h, nxt);
+			nbytes = NBLEAF(bl);
+			break;
+		case P_RINTERNAL:
+			src = GETRINTERNAL(h, nxt);
+			nbytes = NRINTERNAL;
+			break;
+		case P_RLEAF:
+			src = rl = GETRLEAF(h, nxt);
+			nbytes = NRLEAF(rl);
+			break;
+		default:
+			abort();
+		}
+		++nxt;
+		r->linp[off] = r->upper -= nbytes;
+		memmove((char *)r + r->upper, src, nbytes);
+	}
+	r->lower += off * sizeof(indx_t);
+
+	/* If the key is being appended to the page, adjust the index. */
+	if (skip == top)
+		r->lower += sizeof(indx_t);
+
+	return (rval);
+}
+
+/*
+ * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
+ *
+ * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
+ * record that references them gets deleted.  Chains pointed to by internal
+ * pages never get deleted.  This routine marks a chain as pointed to by an
+ * internal page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	pg:	page number of first page in the chain.
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+static int
+bt_preserve(t, pg)
+	BTREE *t;
+	pgno_t pg;
+{
+	PAGE *h;
+
+	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+		return (RET_ERROR);
+	h->flags |= P_PRESERVE;
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+/*
+ * REC_TOTAL -- Return the number of recno entries below a page.
+ *
+ * Parameters:
+ *	h:	page
+ *
+ * Returns:
+ *	The number of recno entries below a page.
+ *
+ * XXX
+ * These values could be set by the bt_psplit routine.  The problem is that the
+ * entry has to be popped off of the stack etc. or the values have to be passed
+ * all the way back to bt_split/bt_rroot and it's not very clean.
+ */
+static recno_t
+rec_total(h)
+	PAGE *h;
+{
+	recno_t recs;
+	indx_t nxt, top;
+
+	for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
+		recs += GETRINTERNAL(h, nxt)->nrecs;
+	return (recs);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/bt_utils.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/bt_utils.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/bt_utils.c	(revision 273)
@@ -0,0 +1,260 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_utils.c	8.8 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_ret --
+ *	Build return key/data pair.
+ *
+ * Parameters:
+ *	t:	tree
+ *	e:	key/data pair to be returned
+ *	key:	user's key structure (NULL if not to be filled in)
+ *	rkey:	memory area to hold key
+ *	data:	user's data structure (NULL if not to be filled in)
+ *	rdata:	memory area to hold data
+ *       copy:	always copy the key/data item
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_ret(t, e, key, rkey, data, rdata, copy)
+	BTREE *t;
+	EPG *e;
+	DBT *key, *rkey, *data, *rdata;
+	int copy;
+{
+	BLEAF *bl;
+	void *p;
+
+	bl = GETBLEAF(e->page, e->index);
+
+	/*
+	 * We must copy big keys/data to make them contigous.  Otherwise,
+	 * leave the page pinned and don't copy unless the user specified
+	 * concurrent access.
+	 */
+	if (key == NULL)
+		goto dataonly;
+
+	if (bl->flags & P_BIGKEY) {
+		if (__ovfl_get(t, bl->bytes,
+		    &key->size, &rkey->data, &rkey->size))
+			return (RET_ERROR);
+		key->data = rkey->data;
+	} else if (copy || F_ISSET(t, B_DB_LOCK)) {
+		if (bl->ksize > rkey->size) {
+			p = (void *)(rkey->data == NULL ?
+			    malloc(bl->ksize) : realloc(rkey->data, bl->ksize));
+			if (p == NULL)
+				return (RET_ERROR);
+			rkey->data = p;
+			rkey->size = bl->ksize;
+		}
+		memmove(rkey->data, bl->bytes, bl->ksize);
+		key->size = bl->ksize;
+		key->data = rkey->data;
+	} else {
+		key->size = bl->ksize;
+		key->data = bl->bytes;
+	}
+
+dataonly:
+	if (data == NULL)
+		return (RET_SUCCESS);
+
+	if (bl->flags & P_BIGDATA) {
+		if (__ovfl_get(t, bl->bytes + bl->ksize,
+		    &data->size, &rdata->data, &rdata->size))
+			return (RET_ERROR);
+		data->data = rdata->data;
+	} else if (copy || F_ISSET(t, B_DB_LOCK)) {
+		/* Use +1 in case the first record retrieved is 0 length. */
+		if (bl->dsize + 1 > rdata->size) {
+			p = (void *)(rdata->data == NULL ?
+			    malloc(bl->dsize + 1) :
+			    realloc(rdata->data, bl->dsize + 1));
+			if (p == NULL)
+				return (RET_ERROR);
+			rdata->data = p;
+			rdata->size = bl->dsize + 1;
+		}
+		memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
+		data->size = bl->dsize;
+		data->data = rdata->data;
+	} else {
+		data->size = bl->dsize;
+		data->data = bl->bytes + bl->ksize;
+	}
+
+	return (RET_SUCCESS);
+}
+
+/*
+ * __BT_CMP -- Compare a key to a given record.
+ *
+ * Parameters:
+ *	t:	tree
+ *	k1:	DBT pointer of first arg to comparison
+ *	e:	pointer to EPG for comparison
+ *
+ * Returns:
+ *	< 0 if k1 is < record
+ *	= 0 if k1 is = record
+ *	> 0 if k1 is > record
+ */
+int
+__bt_cmp(t, k1, e)
+	BTREE *t;
+	const DBT *k1;
+	EPG *e;
+{
+	BINTERNAL *bi;
+	BLEAF *bl;
+	DBT k2;
+	PAGE *h;
+	void *bigkey;
+
+	/*
+	 * The left-most key on internal pages, at any level of the tree, is
+	 * guaranteed by the following code to be less than any user key.
+	 * This saves us from having to update the leftmost key on an internal
+	 * page when the user inserts a new key in the tree smaller than
+	 * anything we've yet seen.
+	 */
+	h = e->page;
+	if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
+		return (1);
+
+	bigkey = NULL;
+	if (h->flags & P_BLEAF) {
+		bl = GETBLEAF(h, e->index);
+		if (bl->flags & P_BIGKEY)
+			bigkey = bl->bytes;
+		else {
+			k2.data = bl->bytes;
+			k2.size = bl->ksize;
+		}
+	} else {
+		bi = GETBINTERNAL(h, e->index);
+		if (bi->flags & P_BIGKEY)
+			bigkey = bi->bytes;
+		else {
+			k2.data = bi->bytes;
+			k2.size = bi->ksize;
+		}
+	}
+
+	if (bigkey) {
+		if (__ovfl_get(t, bigkey,
+		    &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
+			return (RET_ERROR);
+		k2.data = t->bt_rdata.data;
+	}
+	return ((*t->bt_cmp)(k1, &k2));
+}
+
+/*
+ * __BT_DEFCMP -- Default comparison routine.
+ *
+ * Parameters:
+ *	a:	DBT #1
+ *	b: 	DBT #2
+ *
+ * Returns:
+ *	< 0 if a is < b
+ *	= 0 if a is = b
+ *	> 0 if a is > b
+ */
+int
+__bt_defcmp(a, b)
+	const DBT *a, *b;
+{
+	register size_t len;
+	register u_char *p1, *p2;
+
+	/*
+	 * XXX
+	 * If a size_t doesn't fit in an int, this routine can lose.
+	 * What we need is a integral type which is guaranteed to be
+	 * larger than a size_t, and there is no such thing.
+	 */
+	len = MIN(a->size, b->size);
+	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
+		if (*p1 != *p2)
+			return ((int)*p1 - (int)*p2);
+	return ((int)a->size - (int)b->size);
+}
+
+/*
+ * __BT_DEFPFX -- Default prefix routine.
+ *
+ * Parameters:
+ *	a:	DBT #1
+ *	b: 	DBT #2
+ *
+ * Returns:
+ *	Number of bytes needed to distinguish b from a.
+ */
+size_t
+__bt_defpfx(a, b)
+	const DBT *a, *b;
+{
+	register u_char *p1, *p2;
+	register size_t cnt, len;
+
+	cnt = 1;
+	len = MIN(a->size, b->size);
+	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
+		if (*p1 != *p2)
+			return (cnt);
+
+	/* a->size must be <= b->size, or they wouldn't be in this order. */
+	return (a->size < b->size ? a->size + 1 : a->size);
+}
Index: /branches/EMX/src/emx/bsd/db/btree/btree.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/btree.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/btree.h	(revision 273)
@@ -0,0 +1,386 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)btree.h	8.11 (Berkeley) 8/17/94
+ */
+
+/* Macros to set/clear/test flags. */
+#define	F_SET(p, f)	(p)->flags |= (f)
+#define	F_CLR(p, f)	(p)->flags &= ~(f)
+#define	F_ISSET(p, f)	((p)->flags & (f))
+
+#include <mpool.h>
+
+#define	DEFMINKEYPAGE	(2)		/* Minimum keys per page */
+#define	MINCACHE	(5)		/* Minimum cached pages */
+#define	MINPSIZE	(512)		/* Minimum page size */
+
+/*
+ * Page 0 of a btree file contains a copy of the meta-data.  This page is also
+ * used as an out-of-band page, i.e. page pointers that point to nowhere point
+ * to page 0.  Page 1 is the root of the btree.
+ */
+#define	P_INVALID	 0		/* Invalid tree page number. */
+#define	P_META		 0		/* Tree metadata page number. */
+#define	P_ROOT		 1		/* Tree root page number. */
+
+/*
+ * There are five page layouts in the btree: btree internal pages (BINTERNAL),
+ * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
+ * (RLEAF) and overflow pages.  All five page types have a page header (PAGE).
+ * This implementation requires that values within structures NOT be padded.
+ * (ANSI C permits random padding.)  If your compiler pads randomly you'll have
+ * to do some work to get this package to run.
+ */
+typedef struct _page {
+	pgno_t	pgno;			/* this page's page number */
+	pgno_t	prevpg;			/* left sibling */
+	pgno_t	nextpg;			/* right sibling */
+
+#define	P_BINTERNAL	0x01		/* btree internal page */
+#define	P_BLEAF		0x02		/* leaf page */
+#define	P_OVERFLOW	0x04		/* overflow page */
+#define	P_RINTERNAL	0x08		/* recno internal page */
+#define	P_RLEAF		0x10		/* leaf page */
+#define P_TYPE		0x1f		/* type mask */
+#define	P_PRESERVE	0x20		/* never delete this chain of pages */
+	u_int32_t flags;
+
+	indx_t	lower;			/* lower bound of free space on page */
+	indx_t	upper;			/* upper bound of free space on page */
+	indx_t	linp[1];		/* indx_t-aligned VAR. LENGTH DATA */
+} PAGE;
+
+/* First and next index. */
+#define	BTDATAOFF							\
+	(sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) +		\
+	    sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t))
+#define	NEXTINDEX(p)	(((p)->lower - BTDATAOFF) / sizeof(indx_t))
+
+/*
+ * For pages other than overflow pages, there is an array of offsets into the
+ * rest of the page immediately following the page header.  Each offset is to
+ * an item which is unique to the type of page.  The h_lower offset is just
+ * past the last filled-in index.  The h_upper offset is the first item on the
+ * page.  Offsets are from the beginning of the page.
+ *
+ * If an item is too big to store on a single page, a flag is set and the item
+ * is a { page, size } pair such that the page is the first page of an overflow
+ * chain with size bytes of item.  Overflow pages are simply bytes without any
+ * external structure.
+ *
+ * The page number and size fields in the items are pgno_t-aligned so they can
+ * be manipulated without copying.  (This presumes that 32 bit items can be
+ * manipulated on this system.)
+ */
+#define	LALIGN(n)	(((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1))
+#define	NOVFLSIZE	(sizeof(pgno_t) + sizeof(u_int32_t))
+
+/*
+ * For the btree internal pages, the item is a key.  BINTERNALs are {key, pgno}
+ * pairs, such that the key compares less than or equal to all of the records
+ * on that page.  For a tree without duplicate keys, an internal page with two
+ * consecutive keys, a and b, will have all records greater than or equal to a
+ * and less than b stored on the page associated with a.  Duplicate keys are
+ * somewhat special and can cause duplicate internal and leaf page records and
+ * some minor modifications of the above rule.
+ */
+typedef struct _binternal {
+	u_int32_t ksize;		/* key size */
+	pgno_t	pgno;			/* page number stored on */
+#define	P_BIGDATA	0x01		/* overflow data */
+#define	P_BIGKEY	0x02		/* overflow key */
+	u_char	flags;
+	char	bytes[1];		/* data */
+} BINTERNAL;
+
+/* Get the page's BINTERNAL structure at index indx. */
+#define	GETBINTERNAL(pg, indx)						\
+	((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBINTERNAL(len)							\
+	LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
+
+/* Copy a BINTERNAL entry to the page. */
+#define	WR_BINTERNAL(p, size, pgno, flags) {				\
+	*(u_int32_t *)p = size;						\
+	p += sizeof(u_int32_t);						\
+	*(pgno_t *)p = pgno;						\
+	p += sizeof(pgno_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+}
+
+/*
+ * For the recno internal pages, the item is a page number with the number of
+ * keys found on that page and below.
+ */
+typedef struct _rinternal {
+	recno_t	nrecs;			/* number of records */
+	pgno_t	pgno;			/* page number stored below */
+} RINTERNAL;
+
+/* Get the page's RINTERNAL structure at index indx. */
+#define	GETRINTERNAL(pg, indx)						\
+	((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRINTERNAL							\
+	LALIGN(sizeof(recno_t) + sizeof(pgno_t))
+
+/* Copy a RINTERAL entry to the page. */
+#define	WR_RINTERNAL(p, nrecs, pgno) {					\
+	*(recno_t *)p = nrecs;						\
+	p += sizeof(recno_t);						\
+	*(pgno_t *)p = pgno;						\
+}
+
+/* For the btree leaf pages, the item is a key and data pair. */
+typedef struct _bleaf {
+	u_int32_t	ksize;		/* size of key */
+	u_int32_t	dsize;		/* size of data */
+	u_char	flags;			/* P_BIGDATA, P_BIGKEY */
+	char	bytes[1];		/* data */
+} BLEAF;
+
+/* Get the page's BLEAF structure at index indx. */
+#define	GETBLEAF(pg, indx)						\
+	((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBLEAF(p)	NBLEAFDBT((p)->ksize, (p)->dsize)
+
+/* Get the number of bytes in the user's key/data pair. */
+#define NBLEAFDBT(ksize, dsize)						\
+	LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) +	\
+	    (ksize) + (dsize))
+
+/* Copy a BLEAF entry to the page. */
+#define	WR_BLEAF(p, key, data, flags) {					\
+	*(u_int32_t *)p = key->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_int32_t *)p = data->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+	memmove(p, key->data, key->size);				\
+	p += key->size;							\
+	memmove(p, data->data, data->size);				\
+}
+
+/* For the recno leaf pages, the item is a data entry. */
+typedef struct _rleaf {
+	u_int32_t	dsize;		/* size of data */
+	u_char	flags;			/* P_BIGDATA */
+	char	bytes[1];
+} RLEAF;
+
+/* Get the page's RLEAF structure at index indx. */
+#define	GETRLEAF(pg, indx)						\
+	((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRLEAF(p)	NRLEAFDBT((p)->dsize)
+
+/* Get the number of bytes from the user's data. */
+#define	NRLEAFDBT(dsize)						\
+	LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
+
+/* Copy a RLEAF entry to the page. */
+#define	WR_RLEAF(p, data, flags) {					\
+	*(u_int32_t *)p = data->size;					\
+	p += sizeof(u_int32_t);						\
+	*(u_char *)p = flags;						\
+	p += sizeof(u_char);						\
+	memmove(p, data->data, data->size);				\
+}
+
+/*
+ * A record in the tree is either a pointer to a page and an index in the page
+ * or a page number and an index.  These structures are used as a cursor, stack
+ * entry and search returns as well as to pass records to other routines.
+ *
+ * One comment about searches.  Internal page searches must find the largest
+ * record less than key in the tree so that descents work.  Leaf page searches
+ * must find the smallest record greater than key so that the returned index
+ * is the record's correct position for insertion.
+ */
+typedef struct _epgno {
+	pgno_t	pgno;			/* the page number */
+	indx_t	index;			/* the index on the page */
+} EPGNO;
+
+typedef struct _epg {
+	PAGE	*page;			/* the (pinned) page */
+	indx_t	 index;			/* the index on the page */
+} EPG;
+
+/*
+ * About cursors.  The cursor (and the page that contained the key/data pair
+ * that it referenced) can be deleted, which makes things a bit tricky.  If
+ * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set
+ * or there simply aren't any duplicates of the key) we copy the key that it
+ * referenced when it's deleted, and reacquire a new cursor key if the cursor
+ * is used again.  If there are duplicates keys, we move to the next/previous
+ * key, and set a flag so that we know what happened.  NOTE: if duplicate (to
+ * the cursor) keys are added to the tree during this process, it is undefined
+ * if they will be returned or not in a cursor scan.
+ *
+ * The flags determine the possible states of the cursor:
+ *
+ * CURS_INIT	The cursor references *something*.
+ * CURS_ACQUIRE	The cursor was deleted, and a key has been saved so that
+ *		we can reacquire the right position in the tree.
+ * CURS_AFTER, CURS_BEFORE
+ *		The cursor was deleted, and now references a key/data pair
+ *		that has not yet been returned, either before or after the
+ *		deleted key/data pair.
+ * XXX
+ * This structure is broken out so that we can eventually offer multiple
+ * cursors as part of the DB interface.
+ */
+typedef struct _cursor {
+	EPGNO	 pg;			/* B: Saved tree reference. */
+	DBT	 key;			/* B: Saved key, or key.data == NULL. */
+	recno_t	 rcursor;		/* R: recno cursor (1-based) */
+
+#define	CURS_ACQUIRE	0x01		/*  B: Cursor needs to be reacquired. */
+#define	CURS_AFTER	0x02		/*  B: Unreturned cursor after key. */
+#define	CURS_BEFORE	0x04		/*  B: Unreturned cursor before key. */
+#define	CURS_INIT	0x08		/* RB: Cursor initialized. */
+	u_int8_t flags;
+} CURSOR;
+
+/*
+ * The metadata of the tree.  The nrecs field is used only by the RECNO code.
+ * This is because the btree doesn't really need it and it requires that every
+ * put or delete call modify the metadata.
+ */
+typedef struct _btmeta {
+	u_int32_t	magic;		/* magic number */
+	u_int32_t	version;	/* version */
+	u_int32_t	psize;		/* page size */
+	u_int32_t	free;		/* page number of first free page */
+	u_int32_t	nrecs;		/* R: number of records */
+
+#define	SAVEMETA	(B_NODUPS | R_RECNO)
+	u_int32_t	flags;		/* bt_flags & SAVEMETA */
+} BTMETA;
+
+/* The in-memory btree/recno data structure. */
+typedef struct _btree {
+	MPOOL	 *bt_mp;		/* memory pool cookie */
+
+	DB	 *bt_dbp;		/* pointer to enclosing DB */
+
+	EPG	  bt_cur;		/* current (pinned) page */
+	PAGE	 *bt_pinned;		/* page pinned across calls */
+
+	CURSOR	  bt_cursor;		/* cursor */
+
+#define	BT_PUSH(t, p, i) {						\
+	t->bt_sp->pgno = p; 						\
+	t->bt_sp->index = i; 						\
+	++t->bt_sp;							\
+}
+#define	BT_POP(t)	(t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
+#define	BT_CLR(t)	(t->bt_sp = t->bt_stack)
+	EPGNO	  bt_stack[50];		/* stack of parent pages */
+	EPGNO	 *bt_sp;		/* current stack pointer */
+
+	DBT	  bt_rkey;		/* returned key */
+	DBT	  bt_rdata;		/* returned data */
+
+	int	  bt_fd;		/* tree file descriptor */
+
+	pgno_t	  bt_free;		/* next free page */
+	u_int32_t bt_psize;		/* page size */
+	indx_t	  bt_ovflsize;		/* cut-off for key/data overflow */
+	int	  bt_lorder;		/* byte order */
+					/* sorted order */
+	enum { NOT, BACK, FORWARD } bt_order;
+	EPGNO	  bt_last;		/* last insert */
+
+					/* B: key comparison function */
+	int	(*bt_cmp) __P((const DBT *, const DBT *));
+					/* B: prefix comparison function */
+	size_t	(*bt_pfx) __P((const DBT *, const DBT *));
+					/* R: recno input function */
+	int	(*bt_irec) __P((struct _btree *, recno_t));
+
+	FILE	 *bt_rfp;		/* R: record FILE pointer */
+	int	  bt_rfd;		/* R: record file descriptor */
+
+	caddr_t	  bt_cmap;		/* R: current point in mapped space */
+	caddr_t	  bt_smap;		/* R: start of mapped space */
+	caddr_t   bt_emap;		/* R: end of mapped space */
+	size_t	  bt_msize;		/* R: size of mapped region. */
+
+	recno_t	  bt_nrecs;		/* R: number of records */
+	size_t	  bt_reclen;		/* R: fixed record length */
+	u_char	  bt_bval;		/* R: delimiting byte/pad character */
+
+/*
+ * NB:
+ * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
+ */
+#define	B_INMEM		0x00001		/* in-memory tree */
+#define	B_METADIRTY	0x00002		/* need to write metadata */
+#define	B_MODIFIED	0x00004		/* tree modified */
+#define	B_NEEDSWAP	0x00008		/* if byte order requires swapping */
+#define	B_RDONLY	0x00010		/* read-only tree */
+
+#define	B_NODUPS	0x00020		/* no duplicate keys permitted */
+#define	R_RECNO		0x00080		/* record oriented tree */
+
+#define	R_CLOSEFP	0x00040		/* opened a file pointer */
+#define	R_EOF		0x00100		/* end of input file reached. */
+#define	R_FIXLEN	0x00200		/* fixed length records */
+#define	R_MEMMAPPED	0x00400		/* memory mapped file. */
+#define	R_INMEM		0x00800		/* in-memory file */
+#define	R_MODIFIED	0x01000		/* modified file */
+#define	R_RDONLY	0x02000		/* read-only file */
+
+#define	B_DB_LOCK	0x04000		/* DB_LOCK specified. */
+#define	B_DB_SHMEM	0x08000		/* DB_SHMEM specified. */
+#define	B_DB_TXN	0x10000		/* DB_TXN specified. */
+	u_int32_t flags;
+#ifdef __EMX__
+	char *tempname;			/* Name of temporary file */
+#endif /* __EMX__ */
+} BTREE;
+
+#include "extern.h"
Index: /branches/EMX/src/emx/bsd/db/btree/extern.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/extern.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/extern.h	(revision 273)
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)extern.h	8.10 (Berkeley) 7/20/94
+ */
+
+int	 __bt_close __P((DB *));
+int	 __bt_cmp __P((BTREE *, const DBT *, EPG *));
+int	 __bt_crsrdel __P((BTREE *, EPGNO *));
+int	 __bt_defcmp __P((const DBT *, const DBT *));
+size_t	 __bt_defpfx __P((const DBT *, const DBT *));
+int	 __bt_delete __P((const DB *, const DBT *, u_int));
+int	 __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int));
+int	 __bt_fd __P((const DB *));
+int	 __bt_free __P((BTREE *, PAGE *));
+int	 __bt_get __P((const DB *, const DBT *, DBT *, u_int));
+PAGE	*__bt_new __P((BTREE *, pgno_t *));
+void	 __bt_pgin __P((void *, pgno_t, void *));
+void	 __bt_pgout __P((void *, pgno_t, void *));
+int	 __bt_push __P((BTREE *, pgno_t, int));
+int	 __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int));
+int	 __bt_ret __P((BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int));
+EPG	*__bt_search __P((BTREE *, const DBT *, int *));
+int	 __bt_seq __P((const DB *, DBT *, DBT *, u_int));
+void	 __bt_setcur __P((BTREE *, pgno_t, u_int));
+int	 __bt_split __P((BTREE *, PAGE *,
+	    const DBT *, const DBT *, int, size_t, u_int32_t));
+int	 __bt_sync __P((const DB *, u_int));
+
+int	 __ovfl_delete __P((BTREE *, void *));
+int	 __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *));
+int	 __ovfl_put __P((BTREE *, const DBT *, pgno_t *));
+
+#ifdef DEBUG
+void	 __bt_dnpage __P((DB *, pgno_t));
+void	 __bt_dpage __P((PAGE *));
+void	 __bt_dump __P((DB *));
+#endif
+#ifdef STATISTICS
+void	 __bt_stat __P((DB *));
+#endif
Index: /branches/EMX/src/emx/bsd/db/btree/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/btree/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/btree/makefile	(revision 273)
@@ -0,0 +1,4 @@
+OBJS =	bt_close.o bt_conv.o bt_debug.o bt_delete.o bt_get.o bt_open.o \
+	bt_overflow.o bt_page.o bt_put.o bt_search.o bt_seq.o bt_split.o \
+	bt_utils.o
+.INCLUDE:../emx/makefile.sub
Index: /branches/EMX/src/emx/bsd/db/db/db.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/db/db.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/db/db.c	(revision 273)
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)db.c	8.4 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+
+DB *
+dbopen(fname, flags, mode, type, openinfo)
+	const char *fname;
+	int flags, mode;
+	DBTYPE type;
+	const void *openinfo;
+{
+
+#define	DB_FLAGS	(DB_LOCK | DB_SHMEM | DB_TXN)
+#ifdef __EMX__
+#define	USE_OPEN_FLAGS							\
+	(O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY |		\
+	 O_RDWR | O_SHLOCK | O_TRUNC | O_BINARY)
+	flags |= O_BINARY;
+#else /* not __EMX__ */
+#define	USE_OPEN_FLAGS							\
+	(O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY |		\
+	 O_RDWR | O_SHLOCK | O_TRUNC)
+#endif /* not __EMX__ */
+
+	if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
+		switch (type) {
+		case DB_BTREE:
+			return (__bt_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		case DB_HASH:
+			return (__hash_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		case DB_RECNO:
+			return (__rec_open(fname, flags & USE_OPEN_FLAGS,
+			    mode, openinfo, flags & DB_FLAGS));
+		}
+	errno = EINVAL;
+	return (NULL);
+}
+
+static int
+__dberr()
+{
+	return (RET_ERROR);
+}
+
+/*
+ * __DBPANIC -- Stop.
+ *
+ * Parameters:
+ *	dbp:	pointer to the DB structure.
+ */
+void
+__dbpanic(dbp)
+	DB *dbp;
+{
+	/* The only thing that can succeed is a close. */
+	dbp->del = (int (*)())__dberr;
+	dbp->fd = (int (*)())__dberr;
+	dbp->get = (int (*)())__dberr;
+	dbp->put = (int (*)())__dberr;
+	dbp->seq = (int (*)())__dberr;
+	dbp->sync = (int (*)())__dberr;
+}
Index: /branches/EMX/src/emx/bsd/db/db/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/db/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/db/makefile	(revision 273)
@@ -0,0 +1,2 @@
+OBJS =	db.o
+.INCLUDE:../emx/makefile.sub
Index: /branches/EMX/src/emx/bsd/db/emx/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/emx/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/emx/makefile	(revision 273)
@@ -0,0 +1,2 @@
+OBJS =	munmap.o
+.INCLUDE:../emx/makefile.sub
Index: /branches/EMX/src/emx/bsd/db/emx/makefile.sub
===================================================================
--- /branches/EMX/src/emx/bsd/db/emx/makefile.sub	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/emx/makefile.sub	(revision 273)
@@ -0,0 +1,10 @@
+DBLIB=../db.a
+CC=gcc -O -I../include -D__DBINTERFACE_PRIVATE
+
+.c.o:
+	$(CC) -c $<
+
+default: $(OBJS)
+	-ar d $(DBLIB) __.SYMDEF	
+	ar r $(DBLIB) $(OBJS)
+	ar s $(DBLIB)
Index: /branches/EMX/src/emx/bsd/db/emx/munmap.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/emx/munmap.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/emx/munmap.c	(revision 273)
@@ -0,0 +1,10 @@
+/* munmap.c */
+
+#include <errno.h>
+#include <sys/types.h>
+
+int munmap (caddr_t addr, int len)
+{
+  errno = ENOSYS;
+  return (-1);
+}
Index: /branches/EMX/src/emx/bsd/db/emx/test/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/emx/test/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/emx/test/makefile	(revision 273)
@@ -0,0 +1,13 @@
+CC=gcc -g -I../../include
+DBLIB=../../db.a
+
+.c.o:
+	$(CC) -c $<
+
+default: test1.exe test2.exe
+
+test1.exe: test1.o $(DBLIB)
+	$(CC) test1.o $(DBLIB)
+
+test2.exe: test2.o $(DBLIB)
+	$(CC) test2.o $(DBLIB)
Index: /branches/EMX/src/emx/bsd/db/emx/test/test1.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/emx/test/test1.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/emx/test/test1.c	(revision 273)
@@ -0,0 +1,94 @@
+/* test1.c */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <db.h>
+
+struct rec
+{
+  int n;
+};
+
+
+static void add (DB *db, int n)
+{
+  recno_t key;
+  struct rec data;
+  DBT dbt_key, dbt_data;
+
+  key = n; data.n = n;
+  dbt_key.data = &key; dbt_key.size = sizeof (key);
+  dbt_data.data = &data; dbt_data.size = sizeof (data);
+  if (db->put (db, &dbt_key, &dbt_data, 0) != 0)
+    {
+      perror ("db->put()");
+      exit (2);
+    }
+}
+
+
+static int seq (DB *db, int flags)
+{
+  DBT dbt_key, dbt_data;
+  int rc;
+
+  memset (&dbt_key, 0, sizeof (dbt_key));
+  memset (&dbt_data, 0, sizeof (dbt_data));
+
+  rc = db->seq (db, &dbt_key, &dbt_data, flags);
+  if (rc < 0)
+    {
+      perror ("db->seq()");
+      exit (2);
+    }
+
+  if (rc > 0)
+    return (0);
+
+  printf ("%d -> %d\n", *(recno_t *)dbt_key.data,
+          ((struct rec *)dbt_data.data)->n);
+  return (1);
+}
+
+
+int main (int argc, char *argv[])
+{
+  RECNOINFO info;
+  DB *db;
+  int i;
+
+  info.bval = 0;
+  info.cachesize = 0;
+  info.psize = 0;
+  info.flags = R_FIXEDLEN;
+  info.lorder = 0;
+  info.reclen = sizeof (struct rec);
+  info.bfname = NULL;
+
+  db = dbopen (NULL, O_CREAT | O_RDWR, S_IREAD | S_IWRITE, DB_RECNO, &info);
+  if (db == NULL)
+    {
+      perror ("dbopen()");
+      exit (2);
+    }
+
+  add (db, 5);
+  add (db, 2);
+  add (db, 3);
+  add (db, 1);
+  add (db, 4);
+  add (db, 7);
+
+  if (seq (db, R_FIRST))
+    while (seq (db, R_NEXT))
+      ;
+
+  if (db->close (db) != 0)
+    {
+      perror ("db->close()");
+      exit (2);
+    }
+  return (0);
+}
Index: /branches/EMX/src/emx/bsd/db/emx/test/test2.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/emx/test/test2.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/emx/test/test2.c	(revision 273)
@@ -0,0 +1,110 @@
+/* test2.c */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <db.h>
+
+struct key
+{
+  char name[16];
+};
+
+struct rec
+{
+  int n;
+};
+
+
+static void add (DB *db, char *k, int d)
+{
+  struct rec data;
+  struct key key;
+  DBT dbt_key, dbt_data;
+
+  memset (&key, 0, sizeof (key));
+  strcpy (key.name, k);
+  data.n = d;
+  dbt_key.data = &key; dbt_key.size = sizeof (key);
+  dbt_data.data = &data; dbt_data.size = sizeof (data);
+  if (db->put (db, &dbt_key, &dbt_data, 0) != 0)
+    {
+      perror ("db->put()");
+      exit (2);
+    }
+}
+
+
+static int seq (DB *db, int flags)
+{
+  DBT dbt_key, dbt_data;
+  int rc;
+
+  memset (&dbt_key, 0, sizeof (dbt_key));
+  memset (&dbt_data, 0, sizeof (dbt_data));
+
+  rc = db->seq (db, &dbt_key, &dbt_data, flags);
+  if (rc < 0)
+    {
+      perror ("db->seq()");
+      exit (2);
+    }
+
+  if (rc > 0)
+    return (0);
+
+  printf ("%s -> %d\n",
+          ((struct key *)dbt_key.data)->name,
+          ((struct rec *)dbt_data.data)->n);
+  return (1);
+}
+
+
+int my_compare (const DBT *key1, const DBT *key2)
+{
+  return (strcmp (((struct key *)key1->data)->name,
+                  ((struct key *)key2->data)->name));
+}
+
+
+int main (int argc, char *argv[])
+{
+  BTREEINFO info;
+  DB *db;
+  int i;
+
+  info.flags = 0;
+  info.cachesize = 0;
+  info.psize = 0;
+  info.lorder = 0;
+  info.minkeypage = 0;
+  info.compare = my_compare;
+  info.prefix = NULL;
+
+  db = dbopen ("test2.dat", O_CREAT | O_RDWR, S_IREAD | S_IWRITE, DB_BTREE,
+               &info);
+  if (db == NULL)
+    {
+      perror ("dbopen()");
+      exit (2);
+    }
+
+  add (db, "five", 5);
+  add (db, "two", 2);
+  add (db, "three", 3);
+  add (db, "one", 1);
+  add (db, "four", 4);
+  add (db, "seven", 7);
+
+  if (seq (db, R_FIRST))
+    while (seq (db, R_NEXT))
+      ;
+
+  if (db->close (db) != 0)
+    {
+      perror ("db->close()");
+      exit (2);
+    }
+  return (0);
+}
Index: /branches/EMX/src/emx/bsd/db/hash/README
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/README	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/README	(revision 273)
@@ -0,0 +1,72 @@
+#	@(#)README	8.1 (Berkeley) 6/4/93
+
+This package implements a superset of the hsearch and dbm/ndbm libraries.
+
+Test Programs:
+	All test programs which need key/data pairs expect them entered
+	with key and data on separate lines
+
+	tcreat3.c	
+		Takes 
+			bucketsize (bsize), 
+			fill factor (ffactor), and
+			initial number of elements (nelem).  
+		Creates a hash table named hashtest containing the 
+		keys/data pairs entered from standard in.
+	thash4.c
+		Takes
+			bucketsize (bsize), 
+			fill factor (ffactor), 
+			initial number of elements (nelem)
+			bytes of cache (ncached), and
+			file from which to read data  (fname)
+		Creates a table from the key/data pairs on standard in and
+		then does a read of each key/data in fname
+	tdel.c
+		Takes
+			bucketsize (bsize), and
+			fill factor (ffactor).
+			file from which to read data (fname)
+		Reads each key/data pair from fname and deletes the
+		key from the hash table hashtest
+	tseq.c
+		Reads the key/data pairs in the file hashtest and writes them
+		to standard out.
+	tread2.c
+		Takes
+			butes of cache (ncached).
+		Reads key/data pairs from standard in and looks them up
+		in the file hashtest.
+	tverify.c
+		Reads key/data pairs from standard in, looks them up
+		in the file hashtest, and verifies that the data is
+		correct.
+
+NOTES:
+
+The file search.h is provided for using the hsearch compatible interface
+on BSD systems.  On System V derived systems, search.h should appear in 
+/usr/include.
+
+The man page ../man/db.3 explains the interface to the hashing system.
+The file hash.ps is a postscript copy of a paper explaining
+the history, implementation, and performance of the hash package.
+
+"bugs" or idiosyncracies
+
+If you have a lot of overflows, it is possible to run out of overflow
+pages.  Currently, this will cause a message to be printed on stderr.
+Eventually, this will be indicated by a return error code.
+
+If you are using the ndbm interface and exit without flushing or closing the
+file, you may lose updates since the package buffers all writes.  Also,
+the db interface only creates a single database file.  To avoid overwriting
+the user's original file, the suffix ".db" is appended to the file name
+passed to dbm_open.  Additionally, if your code "knows" about the historic
+.dir and .pag files, it will break.  
+
+There is a fundamental difference between this package and the old hsearch.
+Hsearch requires the user to maintain the keys and data in the application's
+allocated memory while hash takes care of all storage management.  The down
+side is that the byte strings passed in the ENTRY structure must be null
+terminated (both the keys and the data).
Index: /branches/EMX/src/emx/bsd/db/hash/extern.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/extern.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/extern.h	(revision 273)
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)extern.h	8.4 (Berkeley) 6/16/94
+ */
+
+BUFHEAD	*__add_ovflpage __P((HTAB *, BUFHEAD *));
+int	 __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *));
+int	 __big_delete __P((HTAB *, BUFHEAD *));
+int	 __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *));
+int	 __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int));
+int	 __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int));
+int	 __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
+		int, u_int32_t, SPLIT_RETURN *));
+int	 __buf_free __P((HTAB *, int, int));
+void	 __buf_init __P((HTAB *, int));
+u_int32_t	 __call_hash __P((HTAB *, char *, int));
+int	 __delpair __P((HTAB *, BUFHEAD *, int));
+int	 __expand_table __P((HTAB *));
+int	 __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int));
+u_int16_t	 __find_last_page __P((HTAB *, BUFHEAD **));
+void	 __free_ovflpage __P((HTAB *, BUFHEAD *));
+BUFHEAD	*__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int));
+int	 __get_page __P((HTAB *, char *, u_int32_t, int, int, int));
+int	 __ibitmap __P((HTAB *, int, int, int));
+u_int32_t	 __log2 __P((u_int32_t));
+int	 __put_page __P((HTAB *, char *, u_int32_t, int, int));
+void	 __reclaim_buf __P((HTAB *, BUFHEAD *));
+int	 __split_page __P((HTAB *, u_int32_t, u_int32_t));
+
+/* Default hash routine. */
+extern u_int32_t (*__default_hash) __P((const void *, size_t));
+
+#ifdef HASH_STATISTICS
+extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
Index: /branches/EMX/src/emx/bsd/db/hash/hash.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash.c	(revision 273)
@@ -0,0 +1,1007 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash.c	8.9 (Berkeley) 6/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#ifdef __EMX__
+#include <sys/types.h>
+#endif /* not __EMX__ */
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int   alloc_segs __P((HTAB *, int));
+static int   flush_meta __P((HTAB *));
+static int   hash_access __P((HTAB *, ACTION, DBT *, DBT *));
+static int   hash_close __P((DB *));
+static int   hash_delete __P((const DB *, const DBT *, u_int32_t));
+static int   hash_fd __P((const DB *));
+static int   hash_get __P((const DB *, const DBT *, DBT *, u_int32_t));
+static int   hash_put __P((const DB *, DBT *, const DBT *, u_int32_t));
+static void *hash_realloc __P((SEGMENT **, int, int));
+static int   hash_seq __P((const DB *, DBT *, DBT *, u_int32_t));
+static int   hash_sync __P((const DB *, u_int32_t));
+static int   hdestroy __P((HTAB *));
+static HTAB *init_hash __P((HTAB *, const char *, HASHINFO *));
+static int   init_htab __P((HTAB *, int));
+#if BYTE_ORDER == LITTLE_ENDIAN
+static void  swap_header __P((HTAB *));
+static void  swap_header_copy __P((HASHHDR *, HASHHDR *));
+#endif
+
+/* Fast arithmetic, relying on powers of 2, */
+#define MOD(x, y)		((x) & ((y) - 1))
+
+#define RETURN_ERROR(ERR, LOC)	{ save_errno = ERR; goto LOC; }
+
+/* Return values */
+#define	SUCCESS	 (0)
+#define	ERROR	(-1)
+#define	ABNORMAL (1)
+
+#ifdef HASH_STATISTICS
+int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
+
+/************************** INTERFACE ROUTINES ***************************/
+/* OPEN/CLOSE */
+
+extern DB *
+__hash_open(file, flags, mode, info, dflags)
+	const char *file;
+	int flags, mode, dflags;
+	const HASHINFO *info;	/* Special directives for create */
+{
+	HTAB *hashp;
+	struct stat statbuf;
+	DB *dbp;
+	int bpages, hdrsize, new_table, nsegs, save_errno;
+
+	if ((flags & O_ACCMODE) == O_WRONLY) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
+		return (NULL);
+	hashp->fp = -1;
+
+	/*
+	 * Even if user wants write only, we need to be able to read
+	 * the actual file, so we need to open it read/write. But, the
+	 * field in the hashp structure needs to be accurate so that
+	 * we can check accesses.
+	 */
+	hashp->flags = flags;
+
+	new_table = 0;
+	if (!file || (flags & O_TRUNC) ||
+	    (stat(file, &statbuf) && (errno == ENOENT))) {
+		if (errno == ENOENT)
+			errno = 0; /* Just in case someone looks at errno */
+		new_table = 1;
+	}
+	if (file) {
+		if ((hashp->fp = open(file, flags, mode)) == -1)
+			RETURN_ERROR(errno, error0);
+		(void)fcntl(hashp->fp, F_SETFD, 1);
+	}
+	if (new_table) {
+		if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
+			RETURN_ERROR(errno, error1);
+	} else {
+		/* Table already exists */
+		if (info && info->hash)
+			hashp->hash = info->hash;
+		else
+			hashp->hash = __default_hash;
+
+		hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
+#if BYTE_ORDER == LITTLE_ENDIAN
+		swap_header(hashp);
+#endif
+		if (hdrsize == -1)
+			RETURN_ERROR(errno, error1);
+		if (hdrsize != sizeof(HASHHDR))
+			RETURN_ERROR(EFTYPE, error1);
+		/* Verify file type, versions and hash function */
+		if (hashp->MAGIC != HASHMAGIC)
+			RETURN_ERROR(EFTYPE, error1);
+#define	OLDHASHVERSION	1
+		if (hashp->VERSION != HASHVERSION &&
+		    hashp->VERSION != OLDHASHVERSION)
+			RETURN_ERROR(EFTYPE, error1);
+		if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+			RETURN_ERROR(EFTYPE, error1);
+		/*
+		 * Figure out how many segments we need.  Max_Bucket is the
+		 * maximum bucket number, so the number of buckets is
+		 * max_bucket + 1.
+		 */
+		nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
+			 hashp->SGSIZE;
+		hashp->nsegs = 0;
+		if (alloc_segs(hashp, nsegs))
+			/*
+			 * If alloc_segs fails, table will have been destroyed
+			 * and errno will have been set.
+			 */
+			return (NULL);
+		/* Read in bitmaps */
+		bpages = (hashp->SPARES[hashp->OVFL_POINT] +
+		    (hashp->BSIZE << BYTE_SHIFT) - 1) >>
+		    (hashp->BSHIFT + BYTE_SHIFT);
+
+		hashp->nmaps = bpages;
+		(void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
+	}
+
+	/* Initialize Buffer Manager */
+	if (info && info->cachesize)
+		__buf_init(hashp, info->cachesize);
+	else
+		__buf_init(hashp, DEF_BUFSIZE);
+
+	hashp->new_file = new_table;
+	hashp->save_file = file && (hashp->flags & O_RDWR);
+	hashp->cbucket = -1;
+	if (!(dbp = (DB *)malloc(sizeof(DB)))) {
+		save_errno = errno;
+		hdestroy(hashp);
+		errno = save_errno;
+		return (NULL);
+	}
+	dbp->internal = hashp;
+	dbp->close = hash_close;
+	dbp->del = hash_delete;
+	dbp->fd = hash_fd;
+	dbp->get = hash_get;
+	dbp->put = hash_put;
+	dbp->seq = hash_seq;
+	dbp->sync = hash_sync;
+	dbp->type = DB_HASH;
+
+#ifdef DEBUG
+	(void)fprintf(stderr,
+"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
+	    "init_htab:",
+	    "TABLE POINTER   ", hashp,
+	    "BUCKET SIZE     ", hashp->BSIZE,
+	    "BUCKET SHIFT    ", hashp->BSHIFT,
+	    "DIRECTORY SIZE  ", hashp->DSIZE,
+	    "SEGMENT SIZE    ", hashp->SGSIZE,
+	    "SEGMENT SHIFT   ", hashp->SSHIFT,
+	    "FILL FACTOR     ", hashp->FFACTOR,
+	    "MAX BUCKET      ", hashp->MAX_BUCKET,
+	    "OVFL POINT	     ", hashp->OVFL_POINT,
+	    "LAST FREED      ", hashp->LAST_FREED,
+	    "HIGH MASK       ", hashp->HIGH_MASK,
+	    "LOW  MASK       ", hashp->LOW_MASK,
+	    "NSEGS           ", hashp->nsegs,
+	    "NKEYS           ", hashp->NKEYS);
+#endif
+#ifdef HASH_STATISTICS
+	hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
+#endif
+	return (dbp);
+
+error1:
+	if (hashp != NULL)
+		(void)close(hashp->fp);
+
+error0:
+	free(hashp);
+	errno = save_errno;
+	return (NULL);
+}
+
+static int
+hash_close(dbp)
+	DB *dbp;
+{
+	HTAB *hashp;
+	int retval;
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	retval = hdestroy(hashp);
+	free(dbp);
+	return (retval);
+}
+
+static int
+hash_fd(dbp)
+	const DB *dbp;
+{
+	HTAB *hashp;
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	if (hashp->fp == -1) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (hashp->fp);
+}
+
+/************************** LOCAL CREATION ROUTINES **********************/
+static HTAB *
+init_hash(hashp, file, info)
+	HTAB *hashp;
+	const char *file;
+	HASHINFO *info;
+{
+	struct stat statbuf;
+	int nelem;
+
+	nelem = 1;
+	hashp->NKEYS = 0;
+	hashp->LORDER = BYTE_ORDER;
+	hashp->BSIZE = DEF_BUCKET_SIZE;
+	hashp->BSHIFT = DEF_BUCKET_SHIFT;
+	hashp->SGSIZE = DEF_SEGSIZE;
+	hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
+	hashp->DSIZE = DEF_DIRSIZE;
+	hashp->FFACTOR = DEF_FFACTOR;
+	hashp->hash = __default_hash;
+	memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
+	memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
+
+	/* Fix bucket size to be optimal for file system */
+	if (file != NULL) {
+		if (stat(file, &statbuf))
+			return (NULL);
+#ifdef __EMX__
+		hashp->BSIZE = 512;
+#else /* not __EMX__ */
+		hashp->BSIZE = statbuf.st_blksize;
+#endif /* not __EMX__ */
+		hashp->BSHIFT = __log2(hashp->BSIZE);
+	}
+
+	if (info) {
+		if (info->bsize) {
+			/* Round pagesize up to power of 2 */
+			hashp->BSHIFT = __log2(info->bsize);
+			hashp->BSIZE = 1 << hashp->BSHIFT;
+			if (hashp->BSIZE > MAX_BSIZE) {
+				errno = EINVAL;
+				return (NULL);
+			}
+		}
+		if (info->ffactor)
+			hashp->FFACTOR = info->ffactor;
+		if (info->hash)
+			hashp->hash = info->hash;
+		if (info->nelem)
+			nelem = info->nelem;
+		if (info->lorder) {
+			if (info->lorder != BIG_ENDIAN &&
+			    info->lorder != LITTLE_ENDIAN) {
+				errno = EINVAL;
+				return (NULL);
+			}
+			hashp->LORDER = info->lorder;
+		}
+	}
+	/* init_htab should destroy the table and set errno if it fails */
+	if (init_htab(hashp, nelem))
+		return (NULL);
+	else
+		return (hashp);
+}
+/*
+ * This calls alloc_segs which may run out of memory.  Alloc_segs will destroy
+ * the table and set errno, so we just pass the error information along.
+ *
+ * Returns 0 on No Error
+ */
+static int
+init_htab(hashp, nelem)
+	HTAB *hashp;
+	int nelem;
+{
+	register int nbuckets, nsegs;
+	int l2;
+
+	/*
+	 * Divide number of elements by the fill factor and determine a
+	 * desired number of buckets.  Allocate space for the next greater
+	 * power of two number of buckets.
+	 */
+	nelem = (nelem - 1) / hashp->FFACTOR + 1;
+
+	l2 = __log2(MAX(nelem, 2));
+	nbuckets = 1 << l2;
+
+	hashp->SPARES[l2] = l2 + 1;
+	hashp->SPARES[l2 + 1] = l2 + 1;
+	hashp->OVFL_POINT = l2;
+	hashp->LAST_FREED = 2;
+
+	/* First bitmap page is at: splitpoint l2 page offset 1 */
+	if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
+		return (-1);
+
+	hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
+	hashp->HIGH_MASK = (nbuckets << 1) - 1;
+	hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
+	    hashp->BSHIFT) + 1;
+
+	nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
+	nsegs = 1 << __log2(nsegs);
+
+	if (nsegs > hashp->DSIZE)
+		hashp->DSIZE = nsegs;
+	return (alloc_segs(hashp, nsegs));
+}
+
+/********************** DESTROY/CLOSE ROUTINES ************************/
+
+/*
+ * Flushes any changes to the file if necessary and destroys the hashp
+ * structure, freeing all allocated space.
+ */
+static int
+hdestroy(hashp)
+	HTAB *hashp;
+{
+	int i, save_errno;
+
+	save_errno = 0;
+
+#ifdef HASH_STATISTICS
+	(void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
+	    hash_accesses, hash_collisions);
+	(void)fprintf(stderr, "hdestroy: expansions %ld\n",
+	    hash_expansions);
+	(void)fprintf(stderr, "hdestroy: overflows %ld\n",
+	    hash_overflows);
+	(void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
+	    hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
+
+	for (i = 0; i < NCACHED; i++)
+		(void)fprintf(stderr,
+		    "spares[%d] = %d\n", i, hashp->SPARES[i]);
+#endif
+	/*
+	 * Call on buffer manager to free buffers, and if required,
+	 * write them to disk.
+	 */
+	if (__buf_free(hashp, 1, hashp->save_file))
+		save_errno = errno;
+	if (hashp->dir) {
+		free(*hashp->dir);	/* Free initial segments */
+		/* Free extra segments */
+		while (hashp->exsegs--)
+			free(hashp->dir[--hashp->nsegs]);
+		free(hashp->dir);
+	}
+	if (flush_meta(hashp) && !save_errno)
+		save_errno = errno;
+	/* Free Bigmaps */
+	for (i = 0; i < hashp->nmaps; i++)
+		if (hashp->mapp[i])
+			free(hashp->mapp[i]);
+
+	if (hashp->fp != -1)
+		(void)close(hashp->fp);
+#ifdef __EMX__
+	if (hashp->tempname != NULL) {
+		(void)unlink (hashp->tempname);
+		free (hashp->tempname);
+		}
+#endif /* __EMX__ */
+
+	free(hashp);
+
+	if (save_errno) {
+		errno = save_errno;
+		return (ERROR);
+	}
+	return (SUCCESS);
+}
+/*
+ * Write modified pages to disk
+ *
+ * Returns:
+ *	 0 == OK
+ *	-1 ERROR
+ */
+static int
+hash_sync(dbp, flags)
+	const DB *dbp;
+	u_int32_t flags;
+{
+	HTAB *hashp;
+
+	if (flags != 0) {
+		errno = EINVAL;
+		return (ERROR);
+	}
+
+	if (!dbp)
+		return (ERROR);
+
+	hashp = (HTAB *)dbp->internal;
+	if (!hashp->save_file)
+		return (0);
+	if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
+		return (ERROR);
+	hashp->new_file = 0;
+	return (0);
+}
+
+/*
+ * Returns:
+ *	 0 == OK
+ *	-1 indicates that errno should be set
+ */
+static int
+flush_meta(hashp)
+	HTAB *hashp;
+{
+	HASHHDR *whdrp;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	HASHHDR whdr;
+#endif
+	int fp, i, wsize;
+
+	if (!hashp->save_file)
+		return (0);
+	hashp->MAGIC = HASHMAGIC;
+	hashp->VERSION = HASHVERSION;
+	hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
+
+	fp = hashp->fp;
+	whdrp = &hashp->hdr;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	whdrp = &whdr;
+	swap_header_copy(&hashp->hdr, whdrp);
+#endif
+	if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
+	    ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1))
+		return (-1);
+	else
+		if (wsize != sizeof(HASHHDR)) {
+			errno = EFTYPE;
+			hashp->errno = errno;
+			return (-1);
+		}
+	for (i = 0; i < NCACHED; i++)
+		if (hashp->mapp[i])
+			if (__put_page(hashp, (char *)hashp->mapp[i],
+				hashp->BITMAPS[i], 0, 1))
+				return (-1);
+	return (0);
+}
+
+/*******************************SEARCH ROUTINES *****************************/
+/*
+ * All the access routines return
+ *
+ * Returns:
+ *	 0 on SUCCESS
+ *	 1 to indicate an external ERROR (i.e. key not found, etc)
+ *	-1 to indicate an internal ERROR (i.e. out of memory, etc)
+ */
+static int
+hash_get(dbp, key, data, flag)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag) {
+		hashp->errno = errno = EINVAL;
+		return (ERROR);
+	}
+	return (hash_access(hashp, HASH_GET, (DBT *)key, data));
+}
+
+static int
+hash_put(dbp, key, data, flag)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int32_t flag;
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_NOOVERWRITE) {
+		hashp->errno = errno = EINVAL;
+		return (ERROR);
+	}
+	if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+		hashp->errno = errno = EPERM;
+		return (ERROR);
+	}
+	return (hash_access(hashp, flag == R_NOOVERWRITE ?
+	    HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
+}
+
+static int
+hash_delete(dbp, key, flag)
+	const DB *dbp;
+	const DBT *key;
+	u_int32_t flag;		/* Ignored */
+{
+	HTAB *hashp;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_CURSOR) {
+		hashp->errno = errno = EINVAL;
+		return (ERROR);
+	}
+	if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+		hashp->errno = errno = EPERM;
+		return (ERROR);
+	}
+	return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
+}
+
+/*
+ * Assume that hashp has been set in wrapper routine.
+ */
+static int
+hash_access(hashp, action, key, val)
+	HTAB *hashp;
+	ACTION action;
+	DBT *key, *val;
+{
+	register BUFHEAD *rbufp;
+	BUFHEAD *bufp, *save_bufp;
+	register u_int16_t *bp;
+	register int n, ndx, off, size;
+	register char *kp;
+	u_int16_t pageno;
+
+#ifdef HASH_STATISTICS
+	hash_accesses++;
+#endif
+
+	off = hashp->BSIZE;
+	size = key->size;
+	kp = (char *)key->data;
+	rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
+	if (!rbufp)
+		return (ERROR);
+	save_bufp = rbufp;
+
+	/* Pin the bucket chain */
+	rbufp->flags |= BUF_PIN;
+	for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
+		if (bp[1] >= REAL_KEY) {
+			/* Real key/data pair */
+			if (size == off - *bp &&
+			    memcmp(kp, rbufp->page + *bp, size) == 0)
+				goto found;
+			off = bp[1];
+#ifdef HASH_STATISTICS
+			hash_collisions++;
+#endif
+			bp += 2;
+			ndx += 2;
+		} else if (bp[1] == OVFLPAGE) {
+			rbufp = __get_buf(hashp, *bp, rbufp, 0);
+			if (!rbufp) {
+				save_bufp->flags &= ~BUF_PIN;
+				return (ERROR);
+			}
+			/* FOR LOOP INIT */
+			bp = (u_int16_t *)rbufp->page;
+			n = *bp++;
+			ndx = 1;
+			off = hashp->BSIZE;
+		} else if (bp[1] < REAL_KEY) {
+			if ((ndx =
+			    __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
+				goto found;
+			if (ndx == -2) {
+				bufp = rbufp;
+				if (!(pageno =
+				    __find_last_page(hashp, &bufp))) {
+					ndx = 0;
+					rbufp = bufp;
+					break;	/* FOR */
+				}
+				rbufp = __get_buf(hashp, pageno, bufp, 0);
+				if (!rbufp) {
+					save_bufp->flags &= ~BUF_PIN;
+					return (ERROR);
+				}
+				/* FOR LOOP INIT */
+				bp = (u_int16_t *)rbufp->page;
+				n = *bp++;
+				ndx = 1;
+				off = hashp->BSIZE;
+			} else {
+				save_bufp->flags &= ~BUF_PIN;
+				return (ERROR);
+			}
+		}
+
+	/* Not found */
+	switch (action) {
+	case HASH_PUT:
+	case HASH_PUTNEW:
+		if (__addel(hashp, rbufp, key, val)) {
+			save_bufp->flags &= ~BUF_PIN;
+			return (ERROR);
+		} else {
+			save_bufp->flags &= ~BUF_PIN;
+			return (SUCCESS);
+		}
+	case HASH_GET:
+	case HASH_DELETE:
+	default:
+		save_bufp->flags &= ~BUF_PIN;
+		return (ABNORMAL);
+	}
+
+found:
+	switch (action) {
+	case HASH_PUTNEW:
+		save_bufp->flags &= ~BUF_PIN;
+		return (ABNORMAL);
+	case HASH_GET:
+		bp = (u_int16_t *)rbufp->page;
+		if (bp[ndx + 1] < REAL_KEY) {
+			if (__big_return(hashp, rbufp, ndx, val, 0))
+				return (ERROR);
+		} else {
+			val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
+			val->size = bp[ndx] - bp[ndx + 1];
+		}
+		break;
+	case HASH_PUT:
+		if ((__delpair(hashp, rbufp, ndx)) ||
+		    (__addel(hashp, rbufp, key, val))) {
+			save_bufp->flags &= ~BUF_PIN;
+			return (ERROR);
+		}
+		break;
+	case HASH_DELETE:
+		if (__delpair(hashp, rbufp, ndx))
+			return (ERROR);
+		break;
+	default:
+		abort();
+	}
+	save_bufp->flags &= ~BUF_PIN;
+	return (SUCCESS);
+}
+
+static int
+hash_seq(dbp, key, data, flag)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int32_t flag;
+{
+	register u_int32_t bucket;
+	register BUFHEAD *bufp;
+	HTAB *hashp;
+	u_int16_t *bp, ndx;
+
+	hashp = (HTAB *)dbp->internal;
+	if (flag && flag != R_FIRST && flag != R_NEXT) {
+		hashp->errno = errno = EINVAL;
+		return (ERROR);
+	}
+#ifdef HASH_STATISTICS
+	hash_accesses++;
+#endif
+	if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
+		hashp->cbucket = 0;
+		hashp->cndx = 1;
+		hashp->cpage = NULL;
+	}
+
+	for (bp = NULL; !bp || !bp[0]; ) {
+		if (!(bufp = hashp->cpage)) {
+			for (bucket = hashp->cbucket;
+			    bucket <= hashp->MAX_BUCKET;
+			    bucket++, hashp->cndx = 1) {
+				bufp = __get_buf(hashp, bucket, NULL, 0);
+				if (!bufp)
+					return (ERROR);
+				hashp->cpage = bufp;
+				bp = (u_int16_t *)bufp->page;
+				if (bp[0])
+					break;
+			}
+			hashp->cbucket = bucket;
+			if (hashp->cbucket > hashp->MAX_BUCKET) {
+				hashp->cbucket = -1;
+				return (ABNORMAL);
+			}
+		} else
+			bp = (u_int16_t *)hashp->cpage->page;
+
+#ifdef DEBUG
+		assert(bp);
+		assert(bufp);
+#endif
+		while (bp[hashp->cndx + 1] == OVFLPAGE) {
+			bufp = hashp->cpage =
+			    __get_buf(hashp, bp[hashp->cndx], bufp, 0);
+			if (!bufp)
+				return (ERROR);
+			bp = (u_int16_t *)(bufp->page);
+			hashp->cndx = 1;
+		}
+		if (!bp[0]) {
+			hashp->cpage = NULL;
+			++hashp->cbucket;
+		}
+	}
+	ndx = hashp->cndx;
+	if (bp[ndx + 1] < REAL_KEY) {
+		if (__big_keydata(hashp, bufp, key, data, 1))
+			return (ERROR);
+	} else {
+		key->data = (u_char *)hashp->cpage->page + bp[ndx];
+		key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
+		data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
+		data->size = bp[ndx] - bp[ndx + 1];
+		ndx += 2;
+		if (ndx > bp[0]) {
+			hashp->cpage = NULL;
+			hashp->cbucket++;
+			hashp->cndx = 1;
+		} else
+			hashp->cndx = ndx;
+	}
+	return (SUCCESS);
+}
+
+/********************************* UTILITIES ************************/
+
+/*
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==> Error
+ */
+extern int
+__expand_table(hashp)
+	HTAB *hashp;
+{
+	u_int32_t old_bucket, new_bucket;
+	int dirsize, new_segnum, spare_ndx;
+
+#ifdef HASH_STATISTICS
+	hash_expansions++;
+#endif
+	new_bucket = ++hashp->MAX_BUCKET;
+	old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
+
+	new_segnum = new_bucket >> hashp->SSHIFT;
+
+	/* Check if we need a new segment */
+	if (new_segnum >= hashp->nsegs) {
+		/* Check if we need to expand directory */
+		if (new_segnum >= hashp->DSIZE) {
+			/* Reallocate directory */
+			dirsize = hashp->DSIZE * sizeof(SEGMENT *);
+			if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
+				return (-1);
+			hashp->DSIZE = dirsize << 1;
+		}
+		if ((hashp->dir[new_segnum] =
+		    (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL)
+			return (-1);
+		hashp->exsegs++;
+		hashp->nsegs++;
+	}
+	/*
+	 * If the split point is increasing (MAX_BUCKET's log base 2
+	 * * increases), we need to copy the current contents of the spare
+	 * split bucket to the next bucket.
+	 */
+	spare_ndx = __log2(hashp->MAX_BUCKET + 1);
+	if (spare_ndx > hashp->OVFL_POINT) {
+		hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
+		hashp->OVFL_POINT = spare_ndx;
+	}
+
+	if (new_bucket > hashp->HIGH_MASK) {
+		/* Starting a new doubling */
+		hashp->LOW_MASK = hashp->HIGH_MASK;
+		hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
+	}
+	/* Relocate records to the new bucket */
+	return (__split_page(hashp, old_bucket, new_bucket));
+}
+
+/*
+ * If realloc guarantees that the pointer is not destroyed if the realloc
+ * fails, then this routine can go away.
+ */
+static void *
+hash_realloc(p_ptr, oldsize, newsize)
+	SEGMENT **p_ptr;
+	int oldsize, newsize;
+{
+	register void *p;
+
+	if (p = malloc(newsize)) {
+		memmove(p, *p_ptr, oldsize);
+		memset((char *)p + oldsize, 0, newsize - oldsize);
+		free(*p_ptr);
+		*p_ptr = p;
+	}
+	return (p);
+}
+
+extern u_int32_t
+__call_hash(hashp, k, len)
+	HTAB *hashp;
+	char *k;
+	int len;
+{
+	int n, bucket;
+
+	n = hashp->hash(k, len);
+	bucket = n & hashp->HIGH_MASK;
+	if (bucket > hashp->MAX_BUCKET)
+		bucket = bucket & hashp->LOW_MASK;
+	return (bucket);
+}
+
+/*
+ * Allocate segment table.  On error, destroy the table and set errno.
+ *
+ * Returns 0 on success
+ */
+static int
+alloc_segs(hashp, nsegs)
+	HTAB *hashp;
+	int nsegs;
+{
+	register int i;
+	register SEGMENT store;
+
+	int save_errno;
+
+	if ((hashp->dir =
+	    (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) {
+		save_errno = errno;
+		(void)hdestroy(hashp);
+		errno = save_errno;
+		return (-1);
+	}
+	/* Allocate segments */
+	if ((store =
+	    (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
+		save_errno = errno;
+		(void)hdestroy(hashp);
+		errno = save_errno;
+		return (-1);
+	}
+	for (i = 0; i < nsegs; i++, hashp->nsegs++)
+		hashp->dir[i] = &store[i << hashp->SSHIFT];
+	return (0);
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Hashp->hdr needs to be byteswapped.
+ */
+static void
+swap_header_copy(srcp, destp)
+	HASHHDR *srcp, *destp;
+{
+	int i;
+
+	P_32_COPY(srcp->magic, destp->magic);
+	P_32_COPY(srcp->version, destp->version);
+	P_32_COPY(srcp->lorder, destp->lorder);
+	P_32_COPY(srcp->bsize, destp->bsize);
+	P_32_COPY(srcp->bshift, destp->bshift);
+	P_32_COPY(srcp->dsize, destp->dsize);
+	P_32_COPY(srcp->ssize, destp->ssize);
+	P_32_COPY(srcp->sshift, destp->sshift);
+	P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
+	P_32_COPY(srcp->last_freed, destp->last_freed);
+	P_32_COPY(srcp->max_bucket, destp->max_bucket);
+	P_32_COPY(srcp->high_mask, destp->high_mask);
+	P_32_COPY(srcp->low_mask, destp->low_mask);
+	P_32_COPY(srcp->ffactor, destp->ffactor);
+	P_32_COPY(srcp->nkeys, destp->nkeys);
+	P_32_COPY(srcp->hdrpages, destp->hdrpages);
+	P_32_COPY(srcp->h_charkey, destp->h_charkey);
+	for (i = 0; i < NCACHED; i++) {
+		P_32_COPY(srcp->spares[i], destp->spares[i]);
+		P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
+	}
+}
+
+static void
+swap_header(hashp)
+	HTAB *hashp;
+{
+	HASHHDR *hdrp;
+	int i;
+
+	hdrp = &hashp->hdr;
+
+	M_32_SWAP(hdrp->magic);
+	M_32_SWAP(hdrp->version);
+	M_32_SWAP(hdrp->lorder);
+	M_32_SWAP(hdrp->bsize);
+	M_32_SWAP(hdrp->bshift);
+	M_32_SWAP(hdrp->dsize);
+	M_32_SWAP(hdrp->ssize);
+	M_32_SWAP(hdrp->sshift);
+	M_32_SWAP(hdrp->ovfl_point);
+	M_32_SWAP(hdrp->last_freed);
+	M_32_SWAP(hdrp->max_bucket);
+	M_32_SWAP(hdrp->high_mask);
+	M_32_SWAP(hdrp->low_mask);
+	M_32_SWAP(hdrp->ffactor);
+	M_32_SWAP(hdrp->nkeys);
+	M_32_SWAP(hdrp->hdrpages);
+	M_32_SWAP(hdrp->h_charkey);
+	for (i = 0; i < NCACHED; i++) {
+		M_32_SWAP(hdrp->spares[i]);
+		M_16_SWAP(hdrp->bitmaps[i]);
+	}
+}
+#endif
Index: /branches/EMX/src/emx/bsd/db/hash/hash.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash.h	(revision 273)
@@ -0,0 +1,296 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)hash.h	8.3 (Berkeley) 5/31/94
+ */
+
+/* Operations */
+typedef enum {
+	HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
+} ACTION;
+
+/* Buffer Management structures */
+typedef struct _bufhead BUFHEAD;
+
+struct _bufhead {
+	BUFHEAD		*prev;		/* LRU links */
+	BUFHEAD		*next;		/* LRU links */
+	BUFHEAD		*ovfl;		/* Overflow page buffer header */
+	u_int32_t	 addr;		/* Address of this page */
+	char		*page;		/* Actual page data */
+	char	 	flags;
+#define	BUF_MOD		0x0001
+#define BUF_DISK	0x0002
+#define	BUF_BUCKET	0x0004
+#define	BUF_PIN		0x0008
+};
+
+#define IS_BUCKET(X)	((X) & BUF_BUCKET)
+
+typedef BUFHEAD **SEGMENT;
+
+/* Hash Table Information */
+typedef struct hashhdr {		/* Disk resident portion */
+	int		magic;		/* Magic NO for hash tables */
+	int		version;	/* Version ID */
+	u_int32_t	lorder;		/* Byte Order */
+	int		bsize;		/* Bucket/Page Size */
+	int		bshift;		/* Bucket shift */
+	int		dsize;		/* Directory Size */
+	int		ssize;		/* Segment Size */
+	int		sshift;		/* Segment shift */
+	int		ovfl_point;	/* Where overflow pages are being 
+					 * allocated */
+	int		last_freed;	/* Last overflow page freed */
+	int		max_bucket;	/* ID of Maximum bucket in use */
+	int		high_mask;	/* Mask to modulo into entire table */
+	int		low_mask;	/* Mask to modulo into lower half of 
+					 * table */
+	int		ffactor;	/* Fill factor */
+	int		nkeys;		/* Number of keys in hash table */
+	int		hdrpages;	/* Size of table header */
+	int		h_charkey;	/* value of hash(CHARKEY) */
+#define NCACHED	32			/* number of bit maps and spare 
+					 * points */
+	int		spares[NCACHED];/* spare pages for overflow */
+	u_int16_t	bitmaps[NCACHED];	/* address of overflow page 
+						 * bitmaps */
+} HASHHDR;
+
+typedef struct htab	 {		/* Memory resident data structure */
+	HASHHDR 	hdr;		/* Header */
+	int		nsegs;		/* Number of allocated segments */
+	int		exsegs;		/* Number of extra allocated 
+					 * segments */
+	u_int32_t			/* Hash function */
+	    (*hash)__P((const void *, size_t));
+	int		flags;		/* Flag values */
+	int		fp;		/* File pointer */
+	char		*tmp_buf;	/* Temporary Buffer for BIG data */
+	char		*tmp_key;	/* Temporary Buffer for BIG keys */
+	BUFHEAD 	*cpage;		/* Current page */
+	int		cbucket;	/* Current bucket */
+	int		cndx;		/* Index of next item on cpage */
+	int		errno;		/* Error Number -- for DBM 
+					 * compatability */
+	int		new_file;	/* Indicates if fd is backing store 
+					 * or no */
+	int		save_file;	/* Indicates whether we need to flush 
+					 * file at
+					 * exit */
+	u_int32_t	*mapp[NCACHED];	/* Pointers to page maps */
+	int		nmaps;		/* Initial number of bitmaps */
+	int		nbufs;		/* Number of buffers left to 
+					 * allocate */
+	BUFHEAD 	bufhead;	/* Header of buffer lru list */
+	SEGMENT 	*dir;		/* Hash Bucket directory */
+#ifdef __EMX__
+	char		*tempname;	/* Name of temporary file */
+#endif /* __EMX__ */
+} HTAB;
+
+/*
+ * Constants
+ */
+#define	MAX_BSIZE		65536		/* 2^16 */
+#define MIN_BUFFERS		6
+#define MINHDRSIZE		512
+#define DEF_BUFSIZE		65536		/* 64 K */
+#define DEF_BUCKET_SIZE		4096
+#define DEF_BUCKET_SHIFT	12		/* log2(BUCKET) */
+#define DEF_SEGSIZE		256
+#define DEF_SEGSIZE_SHIFT	8		/* log2(SEGSIZE)	 */
+#define DEF_DIRSIZE		256
+#define DEF_FFACTOR		65536
+#define MIN_FFACTOR		4
+#define SPLTMAX			8
+#define CHARKEY			"%$sniglet^&"
+#define NUMKEY			1038583
+#define BYTE_SHIFT		3
+#define INT_TO_BYTE		2
+#define INT_BYTE_SHIFT		5
+#define ALL_SET			((u_int32_t)0xFFFFFFFF)
+#define ALL_CLEAR		0
+
+#define PTROF(X)	((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
+#define ISMOD(X)	((u_int32_t)(ptrdiff_t)(X)&0x1)
+#define DOMOD(X)	((X) = (char *)((ptrdiff_t)(X)|0x1))
+#define ISDISK(X)	((u_int32_t)(ptrdiff_t)(X)&0x2)
+#define DODISK(X)	((X) = (char *)((ptrdiff_t)(X)|0x2))
+
+#define BITS_PER_MAP	32
+
+/* Given the address of the beginning of a big map, clear/set the nth bit */
+#define CLRBIT(A, N)	((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
+#define SETBIT(A, N)	((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
+#define ISSET(A, N)	((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
+
+/* Overflow management */
+/*
+ * Overflow page numbers are allocated per split point.  At each doubling of
+ * the table, we can allocate extra pages.  So, an overflow page number has
+ * the top 5 bits indicate which split point and the lower 11 bits indicate
+ * which page at that split point is indicated (pages within split points are
+ * numberered starting with 1).
+ */
+
+#define SPLITSHIFT	11
+#define SPLITMASK	0x7FF
+#define SPLITNUM(N)	(((u_int32_t)(N)) >> SPLITSHIFT)
+#define OPAGENUM(N)	((N) & SPLITMASK)
+#define	OADDR_OF(S,O)	((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
+
+#define BUCKET_TO_PAGE(B) \
+	(B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0)
+#define OADDR_TO_PAGE(B) 	\
+	BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
+
+/*
+ * page.h contains a detailed description of the page format.
+ *
+ * Normally, keys and data are accessed from offset tables in the top of
+ * each page which point to the beginning of the key and data.  There are
+ * four flag values which may be stored in these offset tables which indicate
+ * the following:
+ *
+ *
+ * OVFLPAGE	Rather than a key data pair, this pair contains
+ *		the address of an overflow page.  The format of
+ *		the pair is:
+ *		    OVERFLOW_PAGE_NUMBER OVFLPAGE
+ *
+ * PARTIAL_KEY	This must be the first key/data pair on a page
+ *		and implies that page contains only a partial key.
+ *		That is, the key is too big to fit on a single page
+ *		so it starts on this page and continues on the next.
+ *		The format of the page is:
+ *		    KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
+ *		
+ *		    KEY_OFF -- offset of the beginning of the key
+ *		    PARTIAL_KEY -- 1
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ * FULL_KEY	This must be the first key/data pair on the page.  It
+ *		is used in two cases.
+ *
+ *		Case 1:
+ *		    There is a complete key on the page but no data
+ *		    (because it wouldn't fit).  The next page contains
+ *		    the data.
+ *
+ *		    Page format it:
+ *		    KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ *		    KEY_OFF -- offset of the beginning of the key
+ *		    FULL_KEY -- 2
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ *		Case 2:
+ *		    This page contains no key, but part of a large
+ *		    data field, which is continued on the next page.
+ *
+ *		    Page format it:
+ *		    DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ *		    KEY_OFF -- offset of the beginning of the data on
+ *				this page
+ *		    FULL_KEY -- 2
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ * FULL_KEY_DATA 
+ *		This must be the first key/data pair on the page.
+ *		There are two cases:
+ *
+ *		Case 1:
+ *		    This page contains a key and the beginning of the
+ *		    data field, but the data field is continued on the
+ *		    next page.
+ *
+ *		    Page format is:
+ *		    KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
+ *
+ *		    KEY_OFF -- offset of the beginning of the key
+ *		    FULL_KEY_DATA -- 3
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    DATA_OFF -- offset of the beginning of the data
+ *
+ *		Case 2:
+ *		    This page contains the last page of a big data pair.
+ *		    There is no key, only the  tail end of the data
+ *		    on this page.
+ *
+ *		    Page format is:
+ *		    DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
+ *
+ *		    DATA_OFF -- offset of the beginning of the data on
+ *				this page
+ *		    FULL_KEY_DATA -- 3
+ *		    OVFL_PAGENO - page number of the next overflow page
+ *		    OVFLPAGE -- 0
+ *
+ *		    OVFL_PAGENO and OVFLPAGE are optional (they are
+ *		    not present if there is no next page).
+ */
+
+#define OVFLPAGE	0
+#define PARTIAL_KEY	1
+#define FULL_KEY	2
+#define FULL_KEY_DATA	3
+#define	REAL_KEY	4
+
+/* Short hands for accessing structure */
+#define BSIZE		hdr.bsize
+#define BSHIFT		hdr.bshift
+#define DSIZE		hdr.dsize
+#define SGSIZE		hdr.ssize
+#define SSHIFT		hdr.sshift
+#define LORDER		hdr.lorder
+#define OVFL_POINT	hdr.ovfl_point
+#define	LAST_FREED	hdr.last_freed
+#define MAX_BUCKET	hdr.max_bucket
+#define FFACTOR		hdr.ffactor
+#define HIGH_MASK	hdr.high_mask
+#define LOW_MASK	hdr.low_mask
+#define NKEYS		hdr.nkeys
+#define HDRPAGES	hdr.hdrpages
+#define SPARES		hdr.spares
+#define BITMAPS		hdr.bitmaps
+#define VERSION		hdr.version
+#define MAGIC		hdr.magic
+#define NEXT_FREE	hdr.next_free
+#define H_CHARKEY	hdr.h_charkey
Index: /branches/EMX/src/emx/bsd/db/hash/hash_bigkey.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash_bigkey.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash_bigkey.c	(revision 273)
@@ -0,0 +1,667 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_bigkey.c	8.3 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE: hash
+ * DESCRIPTION:
+ *	Big key/data handling for the hashing package.
+ *
+ * ROUTINES:
+ * External
+ *	__big_keydata
+ *	__big_split
+ *	__big_insert
+ *	__big_return
+ *	__big_delete
+ *	__find_last_page
+ * Internal
+ *	collect_key
+ *	collect_data
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));
+static int collect_data __P((HTAB *, BUFHEAD *, int, int));
+
+/*
+ * Big_insert
+ *
+ * You need to do an insert and the key/data pair is too big
+ *
+ * Returns:
+ * 0 ==> OK
+ *-1 ==> ERROR
+ */
+extern int
+__big_insert(hashp, bufp, key, val)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	const DBT *key, *val;
+{
+	register u_int16_t *p;
+	int key_size, n, val_size;
+	u_int16_t space, move_bytes, off;
+	char *cp, *key_data, *val_data;
+
+	cp = bufp->page;		/* Character pointer of p. */
+	p = (u_int16_t *)cp;
+
+	key_data = (char *)key->data;
+	key_size = key->size;
+	val_data = (char *)val->data;
+	val_size = val->size;
+
+	/* First move the Key */
+	for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
+	    space = FREESPACE(p) - BIGOVERHEAD) {
+		move_bytes = MIN(space, key_size);
+		off = OFFSET(p) - move_bytes;
+		memmove(cp + off, key_data, move_bytes);
+		key_size -= move_bytes;
+		key_data += move_bytes;
+		n = p[0];
+		p[++n] = off;
+		p[0] = ++n;
+		FREESPACE(p) = off - PAGE_META(n);
+		OFFSET(p) = off;
+		p[n] = PARTIAL_KEY;
+		bufp = __add_ovflpage(hashp, bufp);
+		if (!bufp)
+			return (-1);
+		n = p[0];
+		if (!key_size)
+			if (FREESPACE(p)) {
+				move_bytes = MIN(FREESPACE(p), val_size);
+				off = OFFSET(p) - move_bytes;
+				p[n] = off;
+				memmove(cp + off, val_data, move_bytes);
+				val_data += move_bytes;
+				val_size -= move_bytes;
+				p[n - 2] = FULL_KEY_DATA;
+				FREESPACE(p) = FREESPACE(p) - move_bytes;
+				OFFSET(p) = off;
+			} else
+				p[n - 2] = FULL_KEY;
+		p = (u_int16_t *)bufp->page;
+		cp = bufp->page;
+		bufp->flags |= BUF_MOD;
+	}
+
+	/* Now move the data */
+	for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
+	    space = FREESPACE(p) - BIGOVERHEAD) {
+		move_bytes = MIN(space, val_size);
+		/*
+		 * Here's the hack to make sure that if the data ends on the
+		 * same page as the key ends, FREESPACE is at least one.
+		 */
+		if (space == val_size && val_size == val->size)
+			move_bytes--;
+		off = OFFSET(p) - move_bytes;
+		memmove(cp + off, val_data, move_bytes);
+		val_size -= move_bytes;
+		val_data += move_bytes;
+		n = p[0];
+		p[++n] = off;
+		p[0] = ++n;
+		FREESPACE(p) = off - PAGE_META(n);
+		OFFSET(p) = off;
+		if (val_size) {
+			p[n] = FULL_KEY;
+			bufp = __add_ovflpage(hashp, bufp);
+			if (!bufp)
+				return (-1);
+			cp = bufp->page;
+			p = (u_int16_t *)cp;
+		} else
+			p[n] = FULL_KEY_DATA;
+		bufp->flags |= BUF_MOD;
+	}
+	return (0);
+}
+
+/*
+ * Called when bufp's page  contains a partial key (index should be 1)
+ *
+ * All pages in the big key/data pair except bufp are freed.  We cannot
+ * free bufp because the page pointing to it is lost and we can't get rid
+ * of its pointer.
+ *
+ * Returns:
+ * 0 => OK
+ *-1 => ERROR
+ */
+extern int
+__big_delete(hashp, bufp)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+{
+	register BUFHEAD *last_bfp, *rbufp;
+	u_int16_t *bp, pageno;
+	int key_done, n;
+
+	rbufp = bufp;
+	last_bfp = NULL;
+	bp = (u_int16_t *)bufp->page;
+	pageno = 0;
+	key_done = 0;
+
+	while (!key_done || (bp[2] != FULL_KEY_DATA)) {
+		if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
+			key_done = 1;
+
+		/*
+		 * If there is freespace left on a FULL_KEY_DATA page, then
+		 * the data is short and fits entirely on this page, and this
+		 * is the last page.
+		 */
+		if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
+			break;
+		pageno = bp[bp[0] - 1];
+		rbufp->flags |= BUF_MOD;
+		rbufp = __get_buf(hashp, pageno, rbufp, 0);
+		if (last_bfp)
+			__free_ovflpage(hashp, last_bfp);
+		last_bfp = rbufp;
+		if (!rbufp)
+			return (-1);		/* Error. */
+		bp = (u_int16_t *)rbufp->page;
+	}
+
+	/*
+	 * If we get here then rbufp points to the last page of the big
+	 * key/data pair.  Bufp points to the first one -- it should now be
+	 * empty pointing to the next page after this pair.  Can't free it
+	 * because we don't have the page pointing to it.
+	 */
+
+	/* This is information from the last page of the pair. */
+	n = bp[0];
+	pageno = bp[n - 1];
+
+	/* Now, bp is the first page of the pair. */
+	bp = (u_int16_t *)bufp->page;
+	if (n > 2) {
+		/* There is an overflow page. */
+		bp[1] = pageno;
+		bp[2] = OVFLPAGE;
+		bufp->ovfl = rbufp->ovfl;
+	} else
+		/* This is the last page. */
+		bufp->ovfl = NULL;
+	n -= 2;
+	bp[0] = n;
+	FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
+	OFFSET(bp) = hashp->BSIZE - 1;
+
+	bufp->flags |= BUF_MOD;
+	if (rbufp)
+		__free_ovflpage(hashp, rbufp);
+	if (last_bfp != rbufp)
+		__free_ovflpage(hashp, last_bfp);
+
+	hashp->NKEYS--;
+	return (0);
+}
+/*
+ * Returns:
+ *  0 = key not found
+ * -1 = get next overflow page
+ * -2 means key not found and this is big key/data
+ * -3 error
+ */
+extern int
+__find_bigpair(hashp, bufp, ndx, key, size)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int ndx;
+	char *key;
+	int size;
+{
+	register u_int16_t *bp;
+	register char *p;
+	int ksize;
+	u_int16_t bytes;
+	char *kkey;
+
+	bp = (u_int16_t *)bufp->page;
+	p = bufp->page;
+	ksize = size;
+	kkey = key;
+
+	for (bytes = hashp->BSIZE - bp[ndx];
+	    bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
+	    bytes = hashp->BSIZE - bp[ndx]) {
+		if (memcmp(p + bp[ndx], kkey, bytes))
+			return (-2);
+		kkey += bytes;
+		ksize -= bytes;
+		bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
+		if (!bufp)
+			return (-3);
+		p = bufp->page;
+		bp = (u_int16_t *)p;
+		ndx = 1;
+	}
+
+	if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
+#ifdef HASH_STATISTICS
+		++hash_collisions;
+#endif
+		return (-2);
+	} else
+		return (ndx);
+}
+
+/*
+ * Given the buffer pointer of the first overflow page of a big pair,
+ * find the end of the big pair
+ *
+ * This will set bpp to the buffer header of the last page of the big pair.
+ * It will return the pageno of the overflow page following the last page
+ * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
+ * bucket)
+ */
+extern u_int16_t
+__find_last_page(hashp, bpp)
+	HTAB *hashp;
+	BUFHEAD **bpp;
+{
+	BUFHEAD *bufp;
+	u_int16_t *bp, pageno;
+	int n;
+
+	bufp = *bpp;
+	bp = (u_int16_t *)bufp->page;
+	for (;;) {
+		n = bp[0];
+
+		/*
+		 * This is the last page if: the tag is FULL_KEY_DATA and
+		 * either only 2 entries OVFLPAGE marker is explicit there
+		 * is freespace on the page.
+		 */
+		if (bp[2] == FULL_KEY_DATA &&
+		    ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
+			break;
+
+		pageno = bp[n - 1];
+		bufp = __get_buf(hashp, pageno, bufp, 0);
+		if (!bufp)
+			return (0);	/* Need to indicate an error! */
+		bp = (u_int16_t *)bufp->page;
+	}
+
+	*bpp = bufp;
+	if (bp[0] > 2)
+		return (bp[3]);
+	else
+		return (0);
+}
+
+/*
+ * Return the data for the key/data pair that begins on this page at this
+ * index (index should always be 1).
+ */
+extern int
+__big_return(hashp, bufp, ndx, val, set_current)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int ndx;
+	DBT *val;
+	int set_current;
+{
+	BUFHEAD *save_p;
+	u_int16_t *bp, len, off, save_addr;
+	char *tp;
+
+	bp = (u_int16_t *)bufp->page;
+	while (bp[ndx + 1] == PARTIAL_KEY) {
+		bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!bufp)
+			return (-1);
+		bp = (u_int16_t *)bufp->page;
+		ndx = 1;
+	}
+
+	if (bp[ndx + 1] == FULL_KEY) {
+		bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!bufp)
+			return (-1);
+		bp = (u_int16_t *)bufp->page;
+		save_p = bufp;
+		save_addr = save_p->addr;
+		off = bp[1];
+		len = 0;
+	} else
+		if (!FREESPACE(bp)) {
+			/*
+			 * This is a hack.  We can't distinguish between
+			 * FULL_KEY_DATA that contains complete data or
+			 * incomplete data, so we require that if the data
+			 * is complete, there is at least 1 byte of free
+			 * space left.
+			 */
+			off = bp[bp[0]];
+			len = bp[1] - off;
+			save_p = bufp;
+			save_addr = bufp->addr;
+			bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+			if (!bufp)
+				return (-1);
+			bp = (u_int16_t *)bufp->page;
+		} else {
+			/* The data is all on one page. */
+			tp = (char *)bp;
+			off = bp[bp[0]];
+			val->data = (u_char *)tp + off;
+			val->size = bp[1] - off;
+			if (set_current) {
+				if (bp[0] == 2) {	/* No more buckets in
+							 * chain */
+					hashp->cpage = NULL;
+					hashp->cbucket++;
+					hashp->cndx = 1;
+				} else {
+					hashp->cpage = __get_buf(hashp,
+					    bp[bp[0] - 1], bufp, 0);
+					if (!hashp->cpage)
+						return (-1);
+					hashp->cndx = 1;
+					if (!((u_int16_t *)
+					    hashp->cpage->page)[0]) {
+						hashp->cbucket++;
+						hashp->cpage = NULL;
+					}
+				}
+			}
+			return (0);
+		}
+
+	val->size = collect_data(hashp, bufp, (int)len, set_current);
+	if (val->size == -1)
+		return (-1);
+	if (save_p->addr != save_addr) {
+		/* We are pretty short on buffers. */
+		errno = EINVAL;			/* OUT OF BUFFERS */
+		return (-1);
+	}
+	memmove(hashp->tmp_buf, (save_p->page) + off, len);
+	val->data = (u_char *)hashp->tmp_buf;
+	return (0);
+}
+/*
+ * Count how big the total datasize is by recursing through the pages.  Then
+ * allocate a buffer and copy the data as you recurse up.
+ */
+static int
+collect_data(hashp, bufp, len, set)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int len, set;
+{
+	register u_int16_t *bp;
+	register char *p;
+	BUFHEAD *xbp;
+	u_int16_t save_addr;
+	int mylen, totlen;
+
+	p = bufp->page;
+	bp = (u_int16_t *)p;
+	mylen = hashp->BSIZE - bp[1];
+	save_addr = bufp->addr;
+
+	if (bp[2] == FULL_KEY_DATA) {		/* End of Data */
+		totlen = len + mylen;
+		if (hashp->tmp_buf)
+			free(hashp->tmp_buf);
+		if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL)
+			return (-1);
+		if (set) {
+			hashp->cndx = 1;
+			if (bp[0] == 2) {	/* No more buckets in chain */
+				hashp->cpage = NULL;
+				hashp->cbucket++;
+			} else {
+				hashp->cpage =
+				    __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+				if (!hashp->cpage)
+					return (-1);
+				else if (!((u_int16_t *)hashp->cpage->page)[0]) {
+					hashp->cbucket++;
+					hashp->cpage = NULL;
+				}
+			}
+		}
+	} else {
+		xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!xbp || ((totlen =
+		    collect_data(hashp, xbp, len + mylen, set)) < 1))
+			return (-1);
+	}
+	if (bufp->addr != save_addr) {
+		errno = EINVAL;			/* Out of buffers. */
+		return (-1);
+	}
+	memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen);
+	return (totlen);
+}
+
+/*
+ * Fill in the key and data for this big pair.
+ */
+extern int
+__big_keydata(hashp, bufp, key, val, set)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	DBT *key, *val;
+	int set;
+{
+	key->size = collect_key(hashp, bufp, 0, val, set);
+	if (key->size == -1)
+		return (-1);
+	key->data = (u_char *)hashp->tmp_key;
+	return (0);
+}
+
+/*
+ * Count how big the total key size is by recursing through the pages.  Then
+ * collect the data, allocate a buffer and copy the key as you recurse up.
+ */
+static int
+collect_key(hashp, bufp, len, val, set)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	int len;
+	DBT *val;
+	int set;
+{
+	BUFHEAD *xbp;
+	char *p;
+	int mylen, totlen;
+	u_int16_t *bp, save_addr;
+
+	p = bufp->page;
+	bp = (u_int16_t *)p;
+	mylen = hashp->BSIZE - bp[1];
+
+	save_addr = bufp->addr;
+	totlen = len + mylen;
+	if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) {    /* End of Key. */
+		if (hashp->tmp_key != NULL)
+			free(hashp->tmp_key);
+		if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL)
+			return (-1);
+		if (__big_return(hashp, bufp, 1, val, set))
+			return (-1);
+	} else {
+		xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+		if (!xbp || ((totlen =
+		    collect_key(hashp, xbp, totlen, val, set)) < 1))
+			return (-1);
+	}
+	if (bufp->addr != save_addr) {
+		errno = EINVAL;		/* MIS -- OUT OF BUFFERS */
+		return (-1);
+	}
+	memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen);
+	return (totlen);
+}
+
+/*
+ * Returns:
+ *  0 => OK
+ * -1 => error
+ */
+extern int
+__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
+	HTAB *hashp;
+	BUFHEAD *op;	/* Pointer to where to put keys that go in old bucket */
+	BUFHEAD *np;	/* Pointer to new bucket page */
+			/* Pointer to first page containing the big key/data */
+	BUFHEAD *big_keyp;
+	int addr;	/* Address of big_keyp */
+	u_int32_t   obucket;/* Old Bucket */
+	SPLIT_RETURN *ret;
+{
+	register BUFHEAD *tmpp;
+	register u_int16_t *tp;
+	BUFHEAD *bp;
+	DBT key, val;
+	u_int32_t change;
+	u_int16_t free_space, n, off;
+
+	bp = big_keyp;
+
+	/* Now figure out where the big key/data goes */
+	if (__big_keydata(hashp, big_keyp, &key, &val, 0))
+		return (-1);
+	change = (__call_hash(hashp, key.data, key.size) != obucket);
+
+	if (ret->next_addr = __find_last_page(hashp, &big_keyp)) {
+		if (!(ret->nextp =
+		    __get_buf(hashp, ret->next_addr, big_keyp, 0)))
+			return (-1);;
+	} else
+		ret->nextp = NULL;
+
+	/* Now make one of np/op point to the big key/data pair */
+#ifdef DEBUG
+	assert(np->ovfl == NULL);
+#endif
+	if (change)
+		tmpp = np;
+	else
+		tmpp = op;
+
+	tmpp->flags |= BUF_MOD;
+#ifdef DEBUG1
+	(void)fprintf(stderr,
+	    "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
+	    (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
+#endif
+	tmpp->ovfl = bp;	/* one of op/np point to big_keyp */
+	tp = (u_int16_t *)tmpp->page;
+#ifdef DEBUG
+	assert(FREESPACE(tp) >= OVFLSIZE);
+#endif
+	n = tp[0];
+	off = OFFSET(tp);
+	free_space = FREESPACE(tp);
+	tp[++n] = (u_int16_t)addr;
+	tp[++n] = OVFLPAGE;
+	tp[0] = n;
+	OFFSET(tp) = off;
+	FREESPACE(tp) = free_space - OVFLSIZE;
+
+	/*
+	 * Finally, set the new and old return values. BIG_KEYP contains a
+	 * pointer to the last page of the big key_data pair. Make sure that
+	 * big_keyp has no following page (2 elements) or create an empty
+	 * following page.
+	 */
+
+	ret->newp = np;
+	ret->oldp = op;
+
+	tp = (u_int16_t *)big_keyp->page;
+	big_keyp->flags |= BUF_MOD;
+	if (tp[0] > 2) {
+		/*
+		 * There may be either one or two offsets on this page.  If
+		 * there is one, then the overflow page is linked on normally
+		 * and tp[4] is OVFLPAGE.  If there are two, tp[4] contains
+		 * the second offset and needs to get stuffed in after the
+		 * next overflow page is added.
+		 */
+		n = tp[4];
+		free_space = FREESPACE(tp);
+		off = OFFSET(tp);
+		tp[0] -= 2;
+		FREESPACE(tp) = free_space + OVFLSIZE;
+		OFFSET(tp) = off;
+		tmpp = __add_ovflpage(hashp, big_keyp);
+		if (!tmpp)
+			return (-1);
+		tp[4] = n;
+	} else
+		tmpp = big_keyp;
+
+	if (change)
+		ret->newp = tmpp;
+	else
+		ret->oldp = tmpp;
+	return (0);
+}
Index: /branches/EMX/src/emx/bsd/db/hash/hash_buf.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash_buf.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash_buf.c	(revision 273)
@@ -0,0 +1,355 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_buf.c	8.5 (Berkeley) 7/15/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE: hash
+ *
+ * DESCRIPTION:
+ *	Contains buffer management
+ *
+ * ROUTINES:
+ * External
+ *	__buf_init
+ *	__get_buf
+ *	__buf_free
+ *	__reclaim_buf
+ * Internal
+ *	newbuf
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *));
+
+/* Unlink B from its place in the lru */
+#define BUF_REMOVE(B) { \
+	(B)->prev->next = (B)->next; \
+	(B)->next->prev = (B)->prev; \
+}
+
+/* Insert B after P */
+#define BUF_INSERT(B, P) { \
+	(B)->next = (P)->next; \
+	(B)->prev = (P); \
+	(P)->next = (B); \
+	(B)->next->prev = (B); \
+}
+
+#define	MRU	hashp->bufhead.next
+#define	LRU	hashp->bufhead.prev
+
+#define MRU_INSERT(B)	BUF_INSERT((B), &hashp->bufhead)
+#define LRU_INSERT(B)	BUF_INSERT((B), LRU)
+
+/*
+ * We are looking for a buffer with address "addr".  If prev_bp is NULL, then
+ * address is a bucket index.  If prev_bp is not NULL, then it points to the
+ * page previous to an overflow page that we are trying to find.
+ *
+ * CAVEAT:  The buffer header accessed via prev_bp's ovfl field may no longer
+ * be valid.  Therefore, you must always verify that its address matches the
+ * address you are seeking.
+ */
+extern BUFHEAD *
+__get_buf(hashp, addr, prev_bp, newpage)
+	HTAB *hashp;
+	u_int32_t addr;
+	BUFHEAD *prev_bp;
+	int newpage;	/* If prev_bp set, indicates a new overflow page. */
+{
+	register BUFHEAD *bp;
+	register u_int32_t is_disk_mask;
+	register int is_disk, segment_ndx;
+	SEGMENT segp;
+
+	is_disk = 0;
+	is_disk_mask = 0;
+	if (prev_bp) {
+		bp = prev_bp->ovfl;
+		if (!bp || (bp->addr != addr))
+			bp = NULL;
+		if (!newpage)
+			is_disk = BUF_DISK;
+	} else {
+		/* Grab buffer out of directory */
+		segment_ndx = addr & (hashp->SGSIZE - 1);
+
+		/* valid segment ensured by __call_hash() */
+		segp = hashp->dir[addr >> hashp->SSHIFT];
+#ifdef DEBUG
+		assert(segp != NULL);
+#endif
+		bp = PTROF(segp[segment_ndx]);
+		is_disk_mask = ISDISK(segp[segment_ndx]);
+		is_disk = is_disk_mask || !hashp->new_file;
+	}
+
+	if (!bp) {
+		bp = newbuf(hashp, addr, prev_bp);
+		if (!bp ||
+		    __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
+			return (NULL);
+		if (!prev_bp)
+			segp[segment_ndx] =
+			    (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
+	} else {
+		BUF_REMOVE(bp);
+		MRU_INSERT(bp);
+	}
+	return (bp);
+}
+
+/*
+ * We need a buffer for this page. Either allocate one, or evict a resident
+ * one (if we have as many buffers as we're allowed) and put this one in.
+ *
+ * If newbuf finds an error (returning NULL), it also sets errno.
+ */
+static BUFHEAD *
+newbuf(hashp, addr, prev_bp)
+	HTAB *hashp;
+	u_int32_t addr;
+	BUFHEAD *prev_bp;
+{
+	register BUFHEAD *bp;		/* The buffer we're going to use */
+	register BUFHEAD *xbp;		/* Temp pointer */
+	register BUFHEAD *next_xbp;
+	SEGMENT segp;
+	int segment_ndx;
+	u_int16_t oaddr, *shortp;
+
+	oaddr = 0;
+	bp = LRU;
+	/*
+	 * If LRU buffer is pinned, the buffer pool is too small. We need to
+	 * allocate more buffers.
+	 */
+	if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+		/* Allocate a new one */
+		if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
+			return (NULL);
+#ifdef PURIFY
+		memset(bp, 0xff, sizeof(BUFHEAD));
+#endif
+		if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
+			free(bp);
+			return (NULL);
+		}
+#ifdef PURIFY
+		memset(bp->page, 0xff, hashp->BSIZE);
+#endif
+		if (hashp->nbufs)
+			hashp->nbufs--;
+	} else {
+		/* Kick someone out */
+		BUF_REMOVE(bp);
+		/*
+		 * If this is an overflow page with addr 0, it's already been
+		 * flushed back in an overflow chain and initialized.
+		 */
+		if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
+			/*
+			 * Set oaddr before __put_page so that you get it
+			 * before bytes are swapped.
+			 */
+			shortp = (u_int16_t *)bp->page;
+			if (shortp[0])
+				oaddr = shortp[shortp[0] - 1];
+			if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
+			    bp->addr, (int)IS_BUCKET(bp->flags), 0))
+				return (NULL);
+			/*
+			 * Update the pointer to this page (i.e. invalidate it).
+			 *
+			 * If this is a new file (i.e. we created it at open
+			 * time), make sure that we mark pages which have been
+			 * written to disk so we retrieve them from disk later,
+			 * rather than allocating new pages.
+			 */
+			if (IS_BUCKET(bp->flags)) {
+				segment_ndx = bp->addr & (hashp->SGSIZE - 1);
+				segp = hashp->dir[bp->addr >> hashp->SSHIFT];
+#ifdef DEBUG
+				assert(segp != NULL);
+#endif
+
+				if (hashp->new_file &&
+				    ((bp->flags & BUF_MOD) ||
+				    ISDISK(segp[segment_ndx])))
+					segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
+				else
+					segp[segment_ndx] = NULL;
+			}
+			/*
+			 * Since overflow pages can only be access by means of
+			 * their bucket, free overflow pages associated with
+			 * this bucket.
+			 */
+			for (xbp = bp; xbp->ovfl;) {
+				next_xbp = xbp->ovfl;
+				xbp->ovfl = 0;
+				xbp = next_xbp;
+
+				/* Check that ovfl pointer is up date. */
+				if (IS_BUCKET(xbp->flags) ||
+				    (oaddr != xbp->addr))
+					break;
+
+				shortp = (u_int16_t *)xbp->page;
+				if (shortp[0])
+					/* set before __put_page */
+					oaddr = shortp[shortp[0] - 1];
+				if ((xbp->flags & BUF_MOD) && __put_page(hashp,
+				    xbp->page, xbp->addr, 0, 0))
+					return (NULL);
+				xbp->addr = 0;
+				xbp->flags = 0;
+				BUF_REMOVE(xbp);
+				LRU_INSERT(xbp);
+			}
+		}
+	}
+
+	/* Now assign this buffer */
+	bp->addr = addr;
+#ifdef DEBUG1
+	(void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
+	    bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
+#endif
+	bp->ovfl = NULL;
+	if (prev_bp) {
+		/*
+		 * If prev_bp is set, this is an overflow page, hook it in to
+		 * the buffer overflow links.
+		 */
+#ifdef DEBUG1
+		(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
+		    prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
+		    (bp ? bp->addr : 0));
+#endif
+		prev_bp->ovfl = bp;
+		bp->flags = 0;
+	} else
+		bp->flags = BUF_BUCKET;
+	MRU_INSERT(bp);
+	return (bp);
+}
+
+extern void
+__buf_init(hashp, nbytes)
+	HTAB *hashp;
+	int nbytes;
+{
+	BUFHEAD *bfp;
+	int npages;
+
+	bfp = &(hashp->bufhead);
+	npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
+	npages = MAX(npages, MIN_BUFFERS);
+
+	hashp->nbufs = npages;
+	bfp->next = bfp;
+	bfp->prev = bfp;
+	/*
+	 * This space is calloc'd so these are already null.
+	 *
+	 * bfp->ovfl = NULL;
+	 * bfp->flags = 0;
+	 * bfp->page = NULL;
+	 * bfp->addr = 0;
+	 */
+}
+
+extern int
+__buf_free(hashp, do_free, to_disk)
+	HTAB *hashp;
+	int do_free, to_disk;
+{
+	BUFHEAD *bp;
+
+	/* Need to make sure that buffer manager has been initialized */
+	if (!LRU)
+		return (0);
+	for (bp = LRU; bp != &hashp->bufhead;) {
+		/* Check that the buffer is valid */
+		if (bp->addr || IS_BUCKET(bp->flags)) {
+			if (to_disk && (bp->flags & BUF_MOD) &&
+			    __put_page(hashp, bp->page,
+			    bp->addr, IS_BUCKET(bp->flags), 0))
+				return (-1);
+		}
+		/* Check if we are freeing stuff */
+		if (do_free) {
+			if (bp->page)
+				free(bp->page);
+			BUF_REMOVE(bp);
+			free(bp);
+			bp = LRU;
+		} else
+			bp = bp->prev;
+	}
+	return (0);
+}
+
+extern void
+__reclaim_buf(hashp, bp)
+	HTAB *hashp;
+	BUFHEAD *bp;
+{
+	bp->ovfl = 0;
+	bp->addr = 0;
+	bp->flags = 0;
+	BUF_REMOVE(bp);
+	LRU_INSERT(bp);
+}
Index: /branches/EMX/src/emx/bsd/db/hash/hash_func.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash_func.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash_func.c	(revision 273)
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_func.c	8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t hash1 __P((const void *, size_t));
+static u_int32_t hash2 __P((const void *, size_t));
+static u_int32_t hash3 __P((const void *, size_t));
+static u_int32_t hash4 __P((const void *, size_t));
+
+/* Global default hash function */
+u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4;
+
+/*
+ * HASH FUNCTIONS
+ *
+ * Assume that we've already split the bucket to which this key hashes,
+ * calculate that bucket, and check that in fact we did already split it.
+ *
+ * This came from ejb's hsearch.
+ */
+
+#define PRIME1		37
+#define PRIME2		1048583
+
+static u_int32_t
+hash1(keyarg, len)
+	const void *keyarg;
+	register size_t len;
+{
+	register const u_char *key;
+	register u_int32_t h;
+
+	/* Convert string to integer */
+	for (key = keyarg, h = 0; len--;)
+		h = h * PRIME1 ^ (*key++ - ' ');
+	h %= PRIME2;
+	return (h);
+}
+
+/*
+ * Phong's linear congruential hash
+ */
+#define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
+
+static u_int32_t
+hash2(keyarg, len)
+	const void *keyarg;
+	size_t len;
+{
+	register const u_char *e, *key;
+	register u_int32_t h;
+	register u_char c;
+
+	key = keyarg;
+	e = key + len;
+	for (h = 0; key != e;) {
+		c = *key++;
+		if (!c && key > e)
+			break;
+		dcharhash(h, c);
+	}
+	return (h);
+}
+
+/*
+ * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
+ * units.  On the first time through the loop we get the "leftover bytes"
+ * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
+ * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
+ * this routine is heavily used enough, it's worth the ugly coding.
+ *
+ * OZ's original sdbm hash
+ */
+static u_int32_t
+hash3(keyarg, len)
+	const void *keyarg;
+	register size_t len;
+{
+	register const u_char *key;
+	register size_t loop;
+	register u_int32_t h;
+
+#define HASHC   h = *key++ + 65599 * h
+
+	h = 0;
+	key = keyarg;
+	if (len > 0) {
+		loop = (len + 8 - 1) >> 3;
+
+		switch (len & (8 - 1)) {
+		case 0:
+			do {
+				HASHC;
+				/* FALLTHROUGH */
+		case 7:
+				HASHC;
+				/* FALLTHROUGH */
+		case 6:
+				HASHC;
+				/* FALLTHROUGH */
+		case 5:
+				HASHC;
+				/* FALLTHROUGH */
+		case 4:
+				HASHC;
+				/* FALLTHROUGH */
+		case 3:
+				HASHC;
+				/* FALLTHROUGH */
+		case 2:
+				HASHC;
+				/* FALLTHROUGH */
+		case 1:
+				HASHC;
+			} while (--loop);
+		}
+	}
+	return (h);
+}
+
+/* Hash function from Chris Torek. */
+static u_int32_t
+hash4(keyarg, len)
+	const void *keyarg;
+	register size_t len;
+{
+	register const u_char *key;
+	register size_t loop;
+	register u_int32_t h;
+
+#define HASH4a   h = (h << 5) - h + *key++;
+#define HASH4b   h = (h << 5) + h + *key++;
+#define HASH4 HASH4b
+
+	h = 0;
+	key = keyarg;
+	if (len > 0) {
+		loop = (len + 8 - 1) >> 3;
+
+		switch (len & (8 - 1)) {
+		case 0:
+			do {
+				HASH4;
+				/* FALLTHROUGH */
+		case 7:
+				HASH4;
+				/* FALLTHROUGH */
+		case 6:
+				HASH4;
+				/* FALLTHROUGH */
+		case 5:
+				HASH4;
+				/* FALLTHROUGH */
+		case 4:
+				HASH4;
+				/* FALLTHROUGH */
+		case 3:
+				HASH4;
+				/* FALLTHROUGH */
+		case 2:
+				HASH4;
+				/* FALLTHROUGH */
+		case 1:
+				HASH4;
+			} while (--loop);
+		}
+	}
+	return (h);
+}
Index: /branches/EMX/src/emx/bsd/db/hash/hash_log2.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash_log2.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash_log2.c	(revision 273)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_log2.c	8.2 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <db.h>
+
+u_int32_t
+__log2(num)
+	u_int32_t num;
+{
+	register u_int32_t i, limit;
+
+	limit = 1;
+	for (i = 0; limit < num; limit = limit << 1, i++);
+	return (i);
+}
Index: /branches/EMX/src/emx/bsd/db/hash/hash_page.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hash_page.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hash_page.c	(revision 273)
@@ -0,0 +1,958 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_page.c	8.7 (Berkeley) 8/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE:  hashing
+ *
+ * DESCRIPTION:
+ *	Page manipulation for hashing package.
+ *
+ * ROUTINES:
+ *
+ * External
+ *	__get_page
+ *	__add_ovflpage
+ * Internal
+ *	overflow_page
+ *	open_temp
+ */
+
+#include <sys/types.h>
+#ifdef __EMX__
+#include <sys/param.h>
+#endif /* __EMX__ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t	*fetch_bitmap __P((HTAB *, int));
+static u_int32_t	 first_free __P((u_int32_t));
+static int	 open_temp __P((HTAB *));
+static u_int16_t	 overflow_page __P((HTAB *));
+static void	 putpair __P((char *, const DBT *, const DBT *));
+static void	 squeeze_key __P((u_int16_t *, const DBT *, const DBT *));
+static int	 ugly_split
+		    __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int));
+
+#define	PAGE_INIT(P) { \
+	((u_int16_t *)(P))[0] = 0; \
+	((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \
+	((u_int16_t *)(P))[2] = hashp->BSIZE; \
+}
+
+/*
+ * This is called AFTER we have verified that there is room on the page for
+ * the pair (PAIRFITS has returned true) so we go right ahead and start moving
+ * stuff on.
+ */
+static void
+putpair(p, key, val)
+	char *p;
+	const DBT *key, *val;
+{
+	register u_int16_t *bp, n, off;
+
+	bp = (u_int16_t *)p;
+
+	/* Enter the key first. */
+	n = bp[0];
+
+	off = OFFSET(bp) - key->size;
+	memmove(p + off, key->data, key->size);
+	bp[++n] = off;
+
+	/* Now the data. */
+	off -= val->size;
+	memmove(p + off, val->data, val->size);
+	bp[++n] = off;
+
+	/* Adjust page info. */
+	bp[0] = n;
+	bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t));
+	bp[n + 2] = off;
+}
+
+/*
+ * Returns:
+ *	 0 OK
+ *	-1 error
+ */
+extern int
+__delpair(hashp, bufp, ndx)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	register int ndx;
+{
+	register u_int16_t *bp, newoff;
+	register int n;
+	u_int16_t pairlen;
+
+	bp = (u_int16_t *)bufp->page;
+	n = bp[0];
+
+	if (bp[ndx + 1] < REAL_KEY)
+		return (__big_delete(hashp, bufp));
+	if (ndx != 1)
+		newoff = bp[ndx - 1];
+	else
+		newoff = hashp->BSIZE;
+	pairlen = newoff - bp[ndx + 1];
+
+	if (ndx != (n - 1)) {
+		/* Hard Case -- need to shuffle keys */
+		register int i;
+		register char *src = bufp->page + (int)OFFSET(bp);
+		register char *dst = src + (int)pairlen;
+		memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
+
+		/* Now adjust the pointers */
+		for (i = ndx + 2; i <= n; i += 2) {
+			if (bp[i + 1] == OVFLPAGE) {
+				bp[i - 2] = bp[i];
+				bp[i - 1] = bp[i + 1];
+			} else {
+				bp[i - 2] = bp[i] + pairlen;
+				bp[i - 1] = bp[i + 1] + pairlen;
+			}
+		}
+	}
+	/* Finally adjust the page data */
+	bp[n] = OFFSET(bp) + pairlen;
+	bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t);
+	bp[0] = n - 2;
+	hashp->NKEYS--;
+
+	bufp->flags |= BUF_MOD;
+	return (0);
+}
+/*
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==> Error
+ */
+extern int
+__split_page(hashp, obucket, nbucket)
+	HTAB *hashp;
+	u_int32_t obucket, nbucket;
+{
+	register BUFHEAD *new_bufp, *old_bufp;
+	register u_int16_t *ino;
+	register char *np;
+	DBT key, val;
+	int n, ndx, retval;
+	u_int16_t copyto, diff, off, moved;
+	char *op;
+
+	copyto = (u_int16_t)hashp->BSIZE;
+	off = (u_int16_t)hashp->BSIZE;
+	old_bufp = __get_buf(hashp, obucket, NULL, 0);
+	if (old_bufp == NULL)
+		return (-1);
+	new_bufp = __get_buf(hashp, nbucket, NULL, 0);
+	if (new_bufp == NULL)
+		return (-1);
+
+	old_bufp->flags |= (BUF_MOD | BUF_PIN);
+	new_bufp->flags |= (BUF_MOD | BUF_PIN);
+
+	ino = (u_int16_t *)(op = old_bufp->page);
+	np = new_bufp->page;
+
+	moved = 0;
+
+	for (n = 1, ndx = 1; n < ino[0]; n += 2) {
+		if (ino[n + 1] < REAL_KEY) {
+			retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
+			    (int)copyto, (int)moved);
+			old_bufp->flags &= ~BUF_PIN;
+			new_bufp->flags &= ~BUF_PIN;
+			return (retval);
+
+		}
+		key.data = (u_char *)op + ino[n];
+		key.size = off - ino[n];
+
+		if (__call_hash(hashp, key.data, key.size) == obucket) {
+			/* Don't switch page */
+			diff = copyto - off;
+			if (diff) {
+				copyto = ino[n + 1] + diff;
+				memmove(op + copyto, op + ino[n + 1],
+				    off - ino[n + 1]);
+				ino[ndx] = copyto + ino[n] - ino[n + 1];
+				ino[ndx + 1] = copyto;
+			} else
+				copyto = ino[n + 1];
+			ndx += 2;
+		} else {
+			/* Switch page */
+			val.data = (u_char *)op + ino[n + 1];
+			val.size = ino[n] - ino[n + 1];
+			putpair(np, &key, &val);
+			moved += 2;
+		}
+
+		off = ino[n + 1];
+	}
+
+	/* Now clean up the page */
+	ino[0] -= moved;
+	FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3);
+	OFFSET(ino) = copyto;
+
+#ifdef DEBUG3
+	(void)fprintf(stderr, "split %d/%d\n",
+	    ((u_int16_t *)np)[0] / 2,
+	    ((u_int16_t *)op)[0] / 2);
+#endif
+	/* unpin both pages */
+	old_bufp->flags &= ~BUF_PIN;
+	new_bufp->flags &= ~BUF_PIN;
+	return (0);
+}
+
+/*
+ * Called when we encounter an overflow or big key/data page during split
+ * handling.  This is special cased since we have to begin checking whether
+ * the key/data pairs fit on their respective pages and because we may need
+ * overflow pages for both the old and new pages.
+ *
+ * The first page might be a page with regular key/data pairs in which case
+ * we have a regular overflow condition and just need to go on to the next
+ * page or it might be a big key/data pair in which case we need to fix the
+ * big key/data pair.
+ *
+ * Returns:
+ *	 0 ==> success
+ *	-1 ==> failure
+ */
+static int
+ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
+	HTAB *hashp;
+	u_int32_t obucket;	/* Same as __split_page. */
+	BUFHEAD *old_bufp, *new_bufp;
+	int copyto;	/* First byte on page which contains key/data values. */
+	int moved;	/* Number of pairs moved to new page. */
+{
+	register BUFHEAD *bufp;	/* Buffer header for ino */
+	register u_int16_t *ino;	/* Page keys come off of */
+	register u_int16_t *np;	/* New page */
+	register u_int16_t *op;	/* Page keys go on to if they aren't moving */
+
+	BUFHEAD *last_bfp;	/* Last buf header OVFL needing to be freed */
+	DBT key, val;
+	SPLIT_RETURN ret;
+	u_int16_t n, off, ov_addr, scopyto;
+	char *cino;		/* Character value of ino */
+
+	bufp = old_bufp;
+	ino = (u_int16_t *)old_bufp->page;
+	np = (u_int16_t *)new_bufp->page;
+	op = (u_int16_t *)old_bufp->page;
+	last_bfp = NULL;
+	scopyto = (u_int16_t)copyto;	/* ANSI */
+
+	n = ino[0] - 1;
+	while (n < ino[0]) {
+		if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
+			if (__big_split(hashp, old_bufp,
+			    new_bufp, bufp, bufp->addr, obucket, &ret))
+				return (-1);
+			old_bufp = ret.oldp;
+			if (!old_bufp)
+				return (-1);
+			op = (u_int16_t *)old_bufp->page;
+			new_bufp = ret.newp;
+			if (!new_bufp)
+				return (-1);
+			np = (u_int16_t *)new_bufp->page;
+			bufp = ret.nextp;
+			if (!bufp)
+				return (0);
+			cino = (char *)bufp->page;
+			ino = (u_int16_t *)cino;
+			last_bfp = ret.nextp;
+		} else if (ino[n + 1] == OVFLPAGE) {
+			ov_addr = ino[n];
+			/*
+			 * Fix up the old page -- the extra 2 are the fields
+			 * which contained the overflow information.
+			 */
+			ino[0] -= (moved + 2);
+			FREESPACE(ino) =
+			    scopyto - sizeof(u_int16_t) * (ino[0] + 3);
+			OFFSET(ino) = scopyto;
+
+			bufp = __get_buf(hashp, ov_addr, bufp, 0);
+			if (!bufp)
+				return (-1);
+
+			ino = (u_int16_t *)bufp->page;
+			n = 1;
+			scopyto = hashp->BSIZE;
+			moved = 0;
+
+			if (last_bfp)
+				__free_ovflpage(hashp, last_bfp);
+			last_bfp = bufp;
+		}
+		/* Move regular sized pairs of there are any */
+		off = hashp->BSIZE;
+		for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
+			cino = (char *)ino;
+			key.data = (u_char *)cino + ino[n];
+			key.size = off - ino[n];
+			val.data = (u_char *)cino + ino[n + 1];
+			val.size = ino[n] - ino[n + 1];
+			off = ino[n + 1];
+
+			if (__call_hash(hashp, key.data, key.size) == obucket) {
+				/* Keep on old page */
+				if (PAIRFITS(op, (&key), (&val)))
+					putpair((char *)op, &key, &val);
+				else {
+					old_bufp =
+					    __add_ovflpage(hashp, old_bufp);
+					if (!old_bufp)
+						return (-1);
+					op = (u_int16_t *)old_bufp->page;
+					putpair((char *)op, &key, &val);
+				}
+				old_bufp->flags |= BUF_MOD;
+			} else {
+				/* Move to new page */
+				if (PAIRFITS(np, (&key), (&val)))
+					putpair((char *)np, &key, &val);
+				else {
+					new_bufp =
+					    __add_ovflpage(hashp, new_bufp);
+					if (!new_bufp)
+						return (-1);
+					np = (u_int16_t *)new_bufp->page;
+					putpair((char *)np, &key, &val);
+				}
+				new_bufp->flags |= BUF_MOD;
+			}
+		}
+	}
+	if (last_bfp)
+		__free_ovflpage(hashp, last_bfp);
+	return (0);
+}
+
+/*
+ * Add the given pair to the page
+ *
+ * Returns:
+ *	0 ==> OK
+ *	1 ==> failure
+ */
+extern int
+__addel(hashp, bufp, key, val)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+	const DBT *key, *val;
+{
+	register u_int16_t *bp, *sop;
+	int do_expand;
+
+	bp = (u_int16_t *)bufp->page;
+	do_expand = 0;
+	while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
+		/* Exception case */
+		if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
+			/* This is the last page of a big key/data pair
+			   and we need to add another page */
+			break;
+		else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
+			bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+			if (!bufp)
+				return (-1);
+			bp = (u_int16_t *)bufp->page;
+		} else
+			/* Try to squeeze key on this page */
+			if (FREESPACE(bp) > PAIRSIZE(key, val)) {
+				squeeze_key(bp, key, val);
+				return (0);
+			} else {
+				bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+				if (!bufp)
+					return (-1);
+				bp = (u_int16_t *)bufp->page;
+			}
+
+	if (PAIRFITS(bp, key, val))
+		putpair(bufp->page, key, val);
+	else {
+		do_expand = 1;
+		bufp = __add_ovflpage(hashp, bufp);
+		if (!bufp)
+			return (-1);
+		sop = (u_int16_t *)bufp->page;
+
+		if (PAIRFITS(sop, key, val))
+			putpair((char *)sop, key, val);
+		else
+			if (__big_insert(hashp, bufp, key, val))
+				return (-1);
+	}
+	bufp->flags |= BUF_MOD;
+	/*
+	 * If the average number of keys per bucket exceeds the fill factor,
+	 * expand the table.
+	 */
+	hashp->NKEYS++;
+	if (do_expand ||
+	    (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
+		return (__expand_table(hashp));
+	return (0);
+}
+
+/*
+ *
+ * Returns:
+ *	pointer on success
+ *	NULL on error
+ */
+extern BUFHEAD *
+__add_ovflpage(hashp, bufp)
+	HTAB *hashp;
+	BUFHEAD *bufp;
+{
+	register u_int16_t *sp;
+	u_int16_t ndx, ovfl_num;
+#ifdef DEBUG1
+	int tmp1, tmp2;
+#endif
+	sp = (u_int16_t *)bufp->page;
+
+	/* Check if we are dynamically determining the fill factor */
+	if (hashp->FFACTOR == DEF_FFACTOR) {
+		hashp->FFACTOR = sp[0] >> 1;
+		if (hashp->FFACTOR < MIN_FFACTOR)
+			hashp->FFACTOR = MIN_FFACTOR;
+	}
+	bufp->flags |= BUF_MOD;
+	ovfl_num = overflow_page(hashp);
+#ifdef DEBUG1
+	tmp1 = bufp->addr;
+	tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
+#endif
+	if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
+		return (NULL);
+	bufp->ovfl->flags |= BUF_MOD;
+#ifdef DEBUG1
+	(void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
+	    tmp1, tmp2, bufp->ovfl->addr);
+#endif
+	ndx = sp[0];
+	/*
+	 * Since a pair is allocated on a page only if there's room to add
+	 * an overflow page, we know that the OVFL information will fit on
+	 * the page.
+	 */
+	sp[ndx + 4] = OFFSET(sp);
+	sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
+	sp[ndx + 1] = ovfl_num;
+	sp[ndx + 2] = OVFLPAGE;
+	sp[0] = ndx + 2;
+#ifdef HASH_STATISTICS
+	hash_overflows++;
+#endif
+	return (bufp->ovfl);
+}
+
+/*
+ * Returns:
+ *	 0 indicates SUCCESS
+ *	-1 indicates FAILURE
+ */
+extern int
+__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
+	HTAB *hashp;
+	char *p;
+	u_int32_t bucket;
+	int is_bucket, is_disk, is_bitmap;
+{
+	register int fd, page, size;
+	int rsize;
+	u_int16_t *bp;
+
+	fd = hashp->fp;
+	size = hashp->BSIZE;
+
+	if ((fd == -1) || !is_disk) {
+		PAGE_INIT(p);
+		return (0);
+	}
+	if (is_bucket)
+		page = BUCKET_TO_PAGE(bucket);
+	else
+		page = OADDR_TO_PAGE(bucket);
+	if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+	    ((rsize = read(fd, p, size)) == -1))
+		return (-1);
+	bp = (u_int16_t *)p;
+	if (!rsize)
+		bp[0] = 0;	/* We hit the EOF, so initialize a new page */
+	else
+		if (rsize != size) {
+			errno = EFTYPE;
+			return (-1);
+		}
+	if (!is_bitmap && !bp[0]) {
+		PAGE_INIT(p);
+	} else
+		if (hashp->LORDER != BYTE_ORDER) {
+			register int i, max;
+
+			if (is_bitmap) {
+				max = hashp->BSIZE >> 2; /* divide by 4 */
+				for (i = 0; i < max; i++)
+					M_32_SWAP(((int *)p)[i]);
+			} else {
+				M_16_SWAP(bp[0]);
+				max = bp[0] + 2;
+				for (i = 1; i <= max; i++)
+					M_16_SWAP(bp[i]);
+			}
+		}
+	return (0);
+}
+
+/*
+ * Write page p to disk
+ *
+ * Returns:
+ *	 0 ==> OK
+ *	-1 ==>failure
+ */
+extern int
+__put_page(hashp, p, bucket, is_bucket, is_bitmap)
+	HTAB *hashp;
+	char *p;
+	u_int32_t bucket;
+	int is_bucket, is_bitmap;
+{
+	register int fd, page, size;
+	int wsize;
+
+	size = hashp->BSIZE;
+	if ((hashp->fp == -1) && open_temp(hashp))
+		return (-1);
+	fd = hashp->fp;
+
+	if (hashp->LORDER != BYTE_ORDER) {
+		register int i;
+		register int max;
+
+		if (is_bitmap) {
+			max = hashp->BSIZE >> 2;	/* divide by 4 */
+			for (i = 0; i < max; i++)
+				M_32_SWAP(((int *)p)[i]);
+		} else {
+			max = ((u_int16_t *)p)[0] + 2;
+			for (i = 0; i <= max; i++)
+				M_16_SWAP(((u_int16_t *)p)[i]);
+		}
+	}
+	if (is_bucket)
+		page = BUCKET_TO_PAGE(bucket);
+	else
+		page = OADDR_TO_PAGE(bucket);
+	if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+	    ((wsize = write(fd, p, size)) == -1))
+		/* Errno is set */
+		return (-1);
+	if (wsize != size) {
+		errno = EFTYPE;
+		return (-1);
+	}
+	return (0);
+}
+
+#define BYTE_MASK	((1 << INT_BYTE_SHIFT) -1)
+/*
+ * Initialize a new bitmap page.  Bitmap pages are left in memory
+ * once they are read in.
+ */
+extern int
+__ibitmap(hashp, pnum, nbits, ndx)
+	HTAB *hashp;
+	int pnum, nbits, ndx;
+{
+	u_int32_t *ip;
+	int clearbytes, clearints;
+
+	if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+		return (1);
+	hashp->nmaps++;
+	clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
+	clearbytes = clearints << INT_TO_BYTE;
+	(void)memset((char *)ip, 0, clearbytes);
+	(void)memset(((char *)ip) + clearbytes, 0xFF,
+	    hashp->BSIZE - clearbytes);
+	ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
+	SETBIT(ip, 0);
+	hashp->BITMAPS[ndx] = (u_int16_t)pnum;
+	hashp->mapp[ndx] = ip;
+	return (0);
+}
+
+static u_int32_t
+first_free(map)
+	u_int32_t map;
+{
+	register u_int32_t i, mask;
+
+	mask = 0x1;
+	for (i = 0; i < BITS_PER_MAP; i++) {
+		if (!(mask & map))
+			return (i);
+		mask = mask << 1;
+	}
+	return (i);
+}
+
+static u_int16_t
+overflow_page(hashp)
+	HTAB *hashp;
+{
+	register u_int32_t *freep;
+	register int max_free, offset, splitnum;
+	u_int16_t addr;
+	int bit, first_page, free_bit, free_page, i, in_use_bits, j;
+#ifdef DEBUG2
+	int tmp1, tmp2;
+#endif
+	splitnum = hashp->OVFL_POINT;
+	max_free = hashp->SPARES[splitnum];
+
+	free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
+	free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+	/* Look through all the free maps to find the first free block */
+	first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
+	for ( i = first_page; i <= free_page; i++ ) {
+		if (!(freep = (u_int32_t *)hashp->mapp[i]) &&
+		    !(freep = fetch_bitmap(hashp, i)))
+			return (0);
+		if (i == free_page)
+			in_use_bits = free_bit;
+		else
+			in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
+		
+		if (i == first_page) {
+			bit = hashp->LAST_FREED &
+			    ((hashp->BSIZE << BYTE_SHIFT) - 1);
+			j = bit / BITS_PER_MAP;
+			bit = bit & ~(BITS_PER_MAP - 1);
+		} else {
+			bit = 0;
+			j = 0;
+		}
+		for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
+			if (freep[j] != ALL_SET)
+				goto found;
+	}
+
+	/* No Free Page Found */
+	hashp->LAST_FREED = hashp->SPARES[splitnum];
+	hashp->SPARES[splitnum]++;
+	offset = hashp->SPARES[splitnum] -
+	    (splitnum ? hashp->SPARES[splitnum - 1] : 0);
+
+#define	OVMSG	"HASH: Out of overflow pages.  Increase page size\n"
+	if (offset > SPLITMASK) {
+		if (++splitnum >= NCACHED) {
+			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+			return (0);
+		}
+		hashp->OVFL_POINT = splitnum;
+		hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+		hashp->SPARES[splitnum-1]--;
+		offset = 1;
+	}
+
+	/* Check if we need to allocate a new bitmap page */
+	if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
+		free_page++;
+		if (free_page >= NCACHED) {
+			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+			return (0);
+		}
+		/*
+		 * This is tricky.  The 1 indicates that you want the new page
+		 * allocated with 1 clear bit.  Actually, you are going to
+		 * allocate 2 pages from this map.  The first is going to be
+		 * the map page, the second is the overflow page we were
+		 * looking for.  The init_bitmap routine automatically, sets
+		 * the first bit of itself to indicate that the bitmap itself
+		 * is in use.  We would explicitly set the second bit, but
+		 * don't have to if we tell init_bitmap not to leave it clear
+		 * in the first place.
+		 */
+		if (__ibitmap(hashp,
+		    (int)OADDR_OF(splitnum, offset), 1, free_page))
+			return (0);
+		hashp->SPARES[splitnum]++;
+#ifdef DEBUG2
+		free_bit = 2;
+#endif
+		offset++;
+		if (offset > SPLITMASK) {
+			if (++splitnum >= NCACHED) {
+				(void)write(STDERR_FILENO, OVMSG,
+				    sizeof(OVMSG) - 1);
+				return (0);
+			}
+			hashp->OVFL_POINT = splitnum;
+			hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+			hashp->SPARES[splitnum-1]--;
+			offset = 0;
+		}
+	} else {
+		/*
+		 * Free_bit addresses the last used bit.  Bump it to address
+		 * the first available bit.
+		 */
+		free_bit++;
+		SETBIT(freep, free_bit);
+	}
+
+	/* Calculate address of the new overflow page */
+	addr = OADDR_OF(splitnum, offset);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    addr, free_bit, free_page);
+#endif
+	return (addr);
+
+found:
+	bit = bit + first_free(freep[j]);
+	SETBIT(freep, bit);
+#ifdef DEBUG2
+	tmp1 = bit;
+	tmp2 = i;
+#endif
+	/*
+	 * Bits are addressed starting with 0, but overflow pages are addressed
+	 * beginning at 1. Bit is a bit addressnumber, so we need to increment
+	 * it to convert it to a page number.
+	 */
+	bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
+	if (bit >= hashp->LAST_FREED)
+		hashp->LAST_FREED = bit - 1;
+
+	/* Calculate the split number for this page */
+	for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
+	offset = (i ? bit - hashp->SPARES[i - 1] : bit);
+	if (offset >= SPLITMASK)
+		return (0);	/* Out of overflow pages */
+	addr = OADDR_OF(i, offset);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    addr, tmp1, tmp2);
+#endif
+
+	/* Allocate and return the overflow page */
+	return (addr);
+}
+
+/*
+ * Mark this overflow page as free.
+ */
+extern void
+__free_ovflpage(hashp, obufp)
+	HTAB *hashp;
+	BUFHEAD *obufp;
+{
+	register u_int16_t addr;
+	u_int32_t *freep;
+	int bit_address, free_page, free_bit;
+	u_int16_t ndx;
+
+	addr = obufp->addr;
+#ifdef DEBUG1
+	(void)fprintf(stderr, "Freeing %d\n", addr);
+#endif
+	ndx = (((u_int16_t)addr) >> SPLITSHIFT);
+	bit_address =
+	    (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
+	 if (bit_address < hashp->LAST_FREED)
+		hashp->LAST_FREED = bit_address;
+	free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
+	free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+	if (!(freep = hashp->mapp[free_page]))
+		freep = fetch_bitmap(hashp, free_page);
+#ifdef DEBUG
+	/*
+	 * This had better never happen.  It means we tried to read a bitmap
+	 * that has already had overflow pages allocated off it, and we
+	 * failed to read it from the file.
+	 */
+	if (!freep)
+		assert(0);
+#endif
+	CLRBIT(freep, free_bit);
+#ifdef DEBUG2
+	(void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
+	    obufp->addr, free_bit, free_page);
+#endif
+	__reclaim_buf(hashp, obufp);
+}
+
+/*
+ * Returns:
+ *	 0 success
+ *	-1 failure
+ */
+static int
+open_temp(hashp)
+	HTAB *hashp;
+{
+	sigset_t set, oset;
+#ifdef __EMX__
+	char namestr[] = "hsXXXXXX";
+#else /* not __EMX__ */
+	static char namestr[] = "_hashXXXXXX";
+#endif /* not __EMX__ */
+
+	/* Block signals; make sure file goes away at process exit. */
+	(void)sigfillset(&set);
+	(void)sigprocmask(SIG_BLOCK, &set, &oset);
+	if ((hashp->fp = mkstemp(namestr)) != -1) {
+#ifdef __EMX__
+		char absname[MAXPATHLEN];
+		setmode (hashp->fp, O_BINARY);
+		if (_abspath (absname, namestr, sizeof (absname)) == 0)
+			hashp->tempname = strdup (absname);
+#else /* not __EMX__ */
+		(void)unlink(namestr);
+#endif /* not __EMX__ */
+		(void)fcntl(hashp->fp, F_SETFD, 1);
+	}
+	(void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
+	return (hashp->fp != -1 ? 0 : -1);
+}
+
+/*
+ * We have to know that the key will fit, but the last entry on the page is
+ * an overflow pair, so we need to shift things.
+ */
+static void
+squeeze_key(sp, key, val)
+	u_int16_t *sp;
+	const DBT *key, *val;
+{
+	register char *p;
+	u_int16_t free_space, n, off, pageno;
+
+	p = (char *)sp;
+	n = sp[0];
+	free_space = FREESPACE(sp);
+	off = OFFSET(sp);
+
+	pageno = sp[n - 1];
+	off -= key->size;
+	sp[n - 1] = off;
+	memmove(p + off, key->data, key->size);
+	off -= val->size;
+	sp[n] = off;
+	memmove(p + off, val->data, val->size);
+	sp[0] = n + 2;
+	sp[n + 1] = pageno;
+	sp[n + 2] = OVFLPAGE;
+	FREESPACE(sp) = free_space - PAIRSIZE(key, val);
+	OFFSET(sp) = off;
+}
+
+static u_int32_t *
+fetch_bitmap(hashp, ndx)
+	HTAB *hashp;
+	int ndx;
+{
+	if (ndx >= hashp->nmaps)
+		return (NULL);
+	if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+		return (NULL);
+	if (__get_page(hashp,
+	    (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
+		free(hashp->mapp[ndx]);
+		return (NULL);
+	}
+	return (hashp->mapp[ndx]);
+}
+
+#ifdef DEBUG4
+int
+print_chain(addr)
+	int addr;
+{
+	BUFHEAD *bufp;
+	short *bp, oaddr;
+
+	(void)fprintf(stderr, "%d ", addr);
+	bufp = __get_buf(hashp, addr, NULL, 0);
+	bp = (short *)bufp->page;
+	while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
+		((bp[0] > 2) && bp[2] < REAL_KEY))) {
+		oaddr = bp[bp[0] - 1];
+		(void)fprintf(stderr, "%d ", (int)oaddr);
+		bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
+		bp = (short *)bufp->page;
+	}
+	(void)fprintf(stderr, "\n");
+}
+#endif
Index: /branches/EMX/src/emx/bsd/db/hash/hsearch.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/hsearch.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/hsearch.c	(revision 273)
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hsearch.c	8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+#include <db.h>
+#include "search.h"
+
+static DB *dbp = NULL;
+static ENTRY retval;
+
+extern int
+hcreate(nel)
+	u_int nel;
+{
+	HASHINFO info;
+
+	info.nelem = nel;
+	info.bsize = 256;
+	info.ffactor = 8;
+	info.cachesize = 0;
+	info.hash = NULL;
+	info.lorder = 0;
+	dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0);
+	return ((int)dbp);
+}
+
+extern ENTRY *
+hsearch(item, action)
+	ENTRY item;
+	ACTION action;
+{
+	DBT key, val;
+	int status;
+
+	if (!dbp)
+		return (NULL);
+	key.data = (u_char *)item.key;
+	key.size = strlen(item.key) + 1;
+
+	if (action == ENTER) {
+		val.data = (u_char *)item.data;
+		val.size = strlen(item.data) + 1;
+		status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE);
+		if (status)
+			return (NULL);
+	} else {
+		/* FIND */
+		status = (dbp->get)(dbp, &key, &val, 0);
+		if (status)
+			return (NULL);
+		else
+			item.data = (char *)val.data;
+	}
+	retval.key = item.key;
+	retval.data = item.data;
+	return (&retval);
+}
+
+extern void
+hdestroy()
+{
+	if (dbp) {
+		(void)(dbp->close)(dbp);
+		dbp = NULL;
+	}
+}
Index: /branches/EMX/src/emx/bsd/db/hash/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/makefile	(revision 273)
@@ -0,0 +1,3 @@
+OBJS =	hash.o hash_bigkey.o hash_buf.o hash_func.o hash_log2.o \
+	hash_page.o hsearch.o ndbm.o
+.INCLUDE:../emx/makefile.sub
Index: /branches/EMX/src/emx/bsd/db/hash/ndbm.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/ndbm.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/ndbm.c	(revision 273)
@@ -0,0 +1,202 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ndbm.c	8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This package provides a dbm compatible interface to the new hashing
+ * package described in db(3).
+ */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ndbm.h>
+#include "hash.h"
+
+/*
+ * Returns:
+ * 	*DBM on success
+ *	 NULL on failure
+ */
+extern DBM *
+dbm_open(file, flags, mode)
+	const char *file;
+	int flags, mode;
+{
+	HASHINFO info;
+	char path[MAXPATHLEN];
+
+	info.bsize = 4096;
+	info.ffactor = 40;
+	info.nelem = 1;
+	info.cachesize = 0;
+	info.hash = NULL;
+	info.lorder = 0;
+	(void)strcpy(path, file);
+	(void)strcat(path, DBM_SUFFIX);
+	return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+}
+
+extern void
+dbm_close(db)
+	DBM *db;
+{
+	(void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+extern datum
+dbm_fetch(db, key)
+	DBM *db;
+	datum key;
+{
+	datum retval;
+	int status;
+
+	status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+	if (status) {
+		retval.dptr = NULL;
+		retval.dsize = 0;
+	}
+	return (retval);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+extern datum
+dbm_firstkey(db)
+	DBM *db;
+{
+	int status;
+	datum retdata, retkey;
+
+	status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+	if (status)
+		retkey.dptr = NULL;
+	return (retkey);
+}
+
+/*
+ * Returns:
+ *	DATUM on success
+ *	NULL on failure
+ */
+extern datum
+dbm_nextkey(db)
+	DBM *db;
+{
+	int status;
+	datum retdata, retkey;
+
+	status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+	if (status)
+		retkey.dptr = NULL;
+	return (retkey);
+}
+/*
+ * Returns:
+ *	 0 on success
+ *	<0 failure
+ */
+extern int
+dbm_delete(db, key)
+	DBM *db;
+	datum key;
+{
+	int status;
+
+	status = (db->del)(db, (DBT *)&key, 0);
+	if (status)
+		return (-1);
+	else
+		return (0);
+}
+
+/*
+ * Returns:
+ *	 0 on success
+ *	<0 failure
+ *	 1 if DBM_INSERT and entry exists
+ */
+extern int
+dbm_store(db, key, content, flags)
+	DBM *db;
+	datum key, content;
+	int flags;
+{
+	return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+	    (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+}
+
+extern int
+dbm_error(db)
+	DBM *db;
+{
+	HTAB *hp;
+
+	hp = (HTAB *)db->internal;
+	return (hp->errno);
+}
+
+extern int
+dbm_clearerr(db)
+	DBM *db;
+{
+	HTAB *hp;
+
+	hp = (HTAB *)db->internal;
+	hp->errno = 0;
+	return (0);
+}
+
+extern int
+dbm_dirfno(db)
+	DBM *db;
+{
+	return(((HTAB *)db->internal)->fp);
+}
Index: /branches/EMX/src/emx/bsd/db/hash/page.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/page.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/page.h	(revision 273)
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)page.h	8.2 (Berkeley) 5/31/94
+ */
+
+/*
+ * Definitions for hashing page file format.
+ */
+
+/*
+ * routines dealing with a data page
+ *
+ * page format:
+ *	+------------------------------+
+ * p	| n | keyoff | datoff | keyoff |
+ * 	+------------+--------+--------+
+ *	| datoff | free  |  ptr  | --> |
+ *	+--------+---------------------+
+ *	|	 F R E E A R E A       |
+ *	+--------------+---------------+
+ *	|  <---- - - - | data          |
+ *	+--------+-----+----+----------+
+ *	|  key   | data     | key      |
+ *	+--------+----------+----------+
+ *
+ * Pointer to the free space is always:  p[p[0] + 2]
+ * Amount of free space on the page is:  p[p[0] + 1]
+ */
+
+/*
+ * How many bytes required for this pair?
+ *	2 shorts in the table at the top of the page + room for the
+ *	key and room for the data
+ *
+ * We prohibit entering a pair on a page unless there is also room to append
+ * an overflow page. The reason for this it that you can get in a situation
+ * where a single key/data pair fits on a page, but you can't append an
+ * overflow page and later you'd have to split the key/data and handle like
+ * a big pair.
+ * You might as well do this up front.
+ */
+
+#define	PAIRSIZE(K,D)	(2*sizeof(u_int16_t) + (K)->size + (D)->size)
+#define BIGOVERHEAD	(4*sizeof(u_int16_t))
+#define KEYSIZE(K)	(4*sizeof(u_int16_t) + (K)->size);
+#define OVFLSIZE	(2*sizeof(u_int16_t))
+#define FREESPACE(P)	((P)[(P)[0]+1])
+#define	OFFSET(P)	((P)[(P)[0]+2])
+#define PAIRFITS(P,K,D) \
+	(((P)[2] >= REAL_KEY) && \
+	    (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
+#define PAGE_META(N)	(((N)+3) * sizeof(u_int16_t))
+
+typedef struct {
+	BUFHEAD *newp;
+	BUFHEAD *oldp;
+	BUFHEAD *nextp;
+	u_int16_t next_addr;
+}       SPLIT_RETURN;
Index: /branches/EMX/src/emx/bsd/db/hash/search.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/hash/search.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/hash/search.h	(revision 273)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)search.h	8.1 (Berkeley) 6/4/93
+ */
+
+/* Backward compatibility to hsearch interface. */
+typedef struct entry {
+	char *key;
+	char *data;
+} ENTRY;
+
+typedef enum {
+	FIND, ENTER
+} ACTION;
+
+int	 hcreate __P((unsigned int));
+void	 hdestroy __P((void));
+ENTRY	*hsearch __P((ENTRY, ACTION));
Index: /branches/EMX/src/emx/bsd/db/include/compat.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/compat.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/compat.h	(revision 273)
@@ -0,0 +1,10 @@
+#include <machine/endian.h>
+#define	O_EXLOCK	0
+#define	O_SHLOCK	0
+#define EFTYPE EINVAL
+#define	WCOREDUMP(a)	0
+#define	TCSASOFT	0
+#define	_POSIX2_RE_DUP_MAX	255
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define	_BSD_VA_LIST_	char *
Index: /branches/EMX/src/emx/bsd/db/include/db.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/db.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/db.h	(revision 273)
@@ -0,0 +1,236 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)db.h	8.7 (Berkeley) 6/16/94
+ */
+
+#ifndef _DB_H_
+#define	_DB_H_
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <limits.h>
+
+#ifdef __DBINTERFACE_PRIVATE
+#include <compat.h>
+#endif
+
+#define	RET_ERROR	-1		/* Return values. */
+#define	RET_SUCCESS	 0
+#define	RET_SPECIAL	 1
+
+#ifndef	__BIT_TYPES_DEFINED__
+#define	__BIT_TYPES_DEFINED__
+typedef	__signed char		   int8_t;
+typedef	unsigned char		 u_int8_t;
+typedef	short			  int16_t;
+typedef	unsigned short		u_int16_t;
+typedef	int			  int32_t;
+typedef	unsigned int		u_int32_t;
+#ifdef WE_DONT_NEED_QUADS
+typedef	long long		  int64_t;
+typedef	unsigned long long	u_int64_t;
+#endif
+#endif
+
+#define	MAX_PAGE_NUMBER	0xffffffff	/* >= # of pages in a file */
+typedef u_int32_t	pgno_t;
+#define	MAX_PAGE_OFFSET	65535		/* >= # of bytes in a page */
+typedef u_int16_t	indx_t;
+#define	MAX_REC_NUMBER	0xffffffff	/* >= # of records in a tree */
+typedef u_int32_t	recno_t;
+
+/* Key/data structure -- a Data-Base Thang. */
+typedef struct {
+	void	*data;			/* data */
+	size_t	 size;			/* data length */
+} DBT;
+
+/* Routine flags. */
+#define	R_CURSOR	1		/* del, put, seq */
+#define	__R_UNUSED	2		/* UNUSED */
+#define	R_FIRST		3		/* seq */
+#define	R_IAFTER	4		/* put (RECNO) */
+#define	R_IBEFORE	5		/* put (RECNO) */
+#define	R_LAST		6		/* seq (BTREE, RECNO) */
+#define	R_NEXT		7		/* seq */
+#define	R_NOOVERWRITE	8		/* put */
+#define	R_PREV		9		/* seq (BTREE, RECNO) */
+#define	R_SETCURSOR	10		/* put (RECNO) */
+#define	R_RECNOSYNC	11		/* sync (RECNO) */
+
+typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+
+/*
+ * !!!
+ * The following flags are included in the dbopen(3) call as part of the
+ * open(2) flags.  In order to avoid conflicts with the open flags, start
+ * at the top of the 16 or 32-bit number space and work our way down.  If
+ * the open flags were significantly expanded in the future, it could be
+ * a problem.  Wish I'd left another flags word in the dbopen call.
+ *
+ * !!!
+ * None of this stuff is implemented yet.  The only reason that it's here
+ * is so that the access methods can skip copying the key/data pair when
+ * the DB_LOCK flag isn't set.
+ */
+#if UINT_MAX > 65535
+#define	DB_LOCK		0x20000000	/* Do locking. */
+#define	DB_SHMEM	0x40000000	/* Use shared memory. */
+#define	DB_TXN		0x80000000	/* Do transactions. */
+#else
+#define	DB_LOCK		    0x2000	/* Do locking. */
+#define	DB_SHMEM	    0x4000	/* Use shared memory. */
+#define	DB_TXN		    0x8000	/* Do transactions. */
+#endif
+
+/* Access method description structure. */
+typedef struct __db {
+	DBTYPE type;			/* Underlying db type. */
+	int (*close)	__P((struct __db *));
+	int (*del)	__P((const struct __db *, const DBT *, u_int));
+	int (*get)	__P((const struct __db *, const DBT *, DBT *, u_int));
+	int (*put)	__P((const struct __db *, DBT *, const DBT *, u_int));
+	int (*seq)	__P((const struct __db *, DBT *, DBT *, u_int));
+	int (*sync)	__P((const struct __db *, u_int));
+	void *internal;			/* Access method private. */
+	int (*fd)	__P((const struct __db *));
+} DB;
+
+#define	BTREEMAGIC	0x053162
+#define	BTREEVERSION	3
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define	R_DUP		0x01	/* duplicate keys */
+	u_long	flags;
+	u_int	cachesize;	/* bytes to cache */
+	int	maxkeypage;	/* maximum keys per page */
+	int	minkeypage;	/* minimum keys per page */
+	u_int	psize;		/* page size */
+	int	(*compare)	/* comparison function */
+	    __P((const DBT *, const DBT *));
+	size_t	(*prefix)	/* prefix function */
+	    __P((const DBT *, const DBT *));
+	int	lorder;		/* byte order */
+} BTREEINFO;
+
+#define	HASHMAGIC	0x061561
+#define	HASHVERSION	2
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+	u_int	bsize;		/* bucket size */
+	u_int	ffactor;	/* fill factor */
+	u_int	nelem;		/* number of elements */
+	u_int	cachesize;	/* bytes to cache */
+	u_int32_t		/* hash function */
+		(*hash) __P((const void *, size_t));
+	int	lorder;		/* byte order */
+} HASHINFO;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define	R_FIXEDLEN	0x01	/* fixed-length records */
+#define	R_NOKEY		0x02	/* key not required */
+#define	R_SNAPSHOT	0x04	/* snapshot the input */
+	u_long	flags;
+	u_int	cachesize;	/* bytes to cache */
+	u_int	psize;		/* page size */
+	int	lorder;		/* byte order */
+	size_t	reclen;		/* record length (fixed-length records) */
+	u_char	bval;		/* delimiting byte (variable-length records */
+	char	*bfname;	/* btree file name */ 
+} RECNOINFO;
+
+#ifdef __DBINTERFACE_PRIVATE
+/*
+ * Little endian <==> big endian 32-bit swap macros.
+ *	M_32_SWAP	swap a memory location
+ *	P_32_SWAP	swap a referenced memory location
+ *	P_32_COPY	swap from one location to another
+ */
+#define	M_32_SWAP(a) {							\
+	u_int32_t _tmp = a;						\
+	((char *)&a)[0] = ((char *)&_tmp)[3];				\
+	((char *)&a)[1] = ((char *)&_tmp)[2];				\
+	((char *)&a)[2] = ((char *)&_tmp)[1];				\
+	((char *)&a)[3] = ((char *)&_tmp)[0];				\
+}
+#define	P_32_SWAP(a) {							\
+	u_int32_t _tmp = *(u_int32_t *)a;				\
+	((char *)a)[0] = ((char *)&_tmp)[3];				\
+	((char *)a)[1] = ((char *)&_tmp)[2];				\
+	((char *)a)[2] = ((char *)&_tmp)[1];				\
+	((char *)a)[3] = ((char *)&_tmp)[0];				\
+}
+#define	P_32_COPY(a, b) {						\
+	((char *)&(b))[0] = ((char *)&(a))[3];				\
+	((char *)&(b))[1] = ((char *)&(a))[2];				\
+	((char *)&(b))[2] = ((char *)&(a))[1];				\
+	((char *)&(b))[3] = ((char *)&(a))[0];				\
+}
+
+/*
+ * Little endian <==> big endian 16-bit swap macros.
+ *	M_16_SWAP	swap a memory location
+ *	P_16_SWAP	swap a referenced memory location
+ *	P_16_COPY	swap from one location to another
+ */
+#define	M_16_SWAP(a) {							\
+	u_int16_t _tmp = a;						\
+	((char *)&a)[0] = ((char *)&_tmp)[1];				\
+	((char *)&a)[1] = ((char *)&_tmp)[0];				\
+}
+#define	P_16_SWAP(a) {							\
+	u_int16_t _tmp = *(u_int16_t *)a;				\
+	((char *)a)[0] = ((char *)&_tmp)[1];				\
+	((char *)a)[1] = ((char *)&_tmp)[0];				\
+}
+#define	P_16_COPY(a, b) {						\
+	((char *)&(b))[0] = ((char *)&(a))[1];				\
+	((char *)&(b))[1] = ((char *)&(a))[0];				\
+}
+#endif
+
+__BEGIN_DECLS
+DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+
+#ifdef __DBINTERFACE_PRIVATE
+DB	*__bt_open __P((const char *, int, int, const BTREEINFO *, int));
+DB	*__hash_open __P((const char *, int, int, const HASHINFO *, int));
+DB	*__rec_open __P((const char *, int, int, const RECNOINFO *, int));
+void	 __dbpanic __P((DB *dbp));
+#endif
+__END_DECLS
+#endif /* !_DB_H_ */
Index: /branches/EMX/src/emx/bsd/db/include/mpool.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/mpool.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/mpool.h	(revision 273)
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)mpool.h	8.2 (Berkeley) 7/14/94
+ */
+
+#include <sys/queue.h>
+
+/*
+ * The memory pool scheme is a simple one.  Each in-memory page is referenced
+ * by a bucket which is threaded in up to two of three ways.  All active pages
+ * are threaded on a hash chain (hashed by page number) and an lru chain.
+ * Inactive pages are threaded on a free chain.  Each reference to a memory
+ * pool is handed an opaque MPOOL cookie which stores all of this information.
+ */
+#define	HASHSIZE	128
+#define	HASHKEY(pgno)	((pgno - 1) % HASHSIZE)
+
+/* The BKT structures are the elements of the queues. */
+typedef struct _bkt {
+	CIRCLEQ_ENTRY(_bkt) hq;		/* hash queue */
+	CIRCLEQ_ENTRY(_bkt) q;		/* lru queue */
+	void    *page;			/* page */
+	pgno_t   pgno;			/* page number */
+
+#define	MPOOL_DIRTY	0x01		/* page needs to be written */
+#define	MPOOL_PINNED	0x02		/* page is pinned into memory */
+	u_int8_t flags;			/* flags */
+} BKT;
+
+typedef struct MPOOL {
+	CIRCLEQ_HEAD(_lqh, _bkt) lqh;	/* lru queue head */
+					/* hash queue array */
+	CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
+	pgno_t	curcache;		/* current number of cached pages */
+	pgno_t	maxcache;		/* max number of cached pages */
+	pgno_t	npages;			/* number of pages in the file */
+	u_long	pagesize;		/* file page size */
+	int	fd;			/* file descriptor */
+					/* page in conversion routine */
+	void    (*pgin) __P((void *, pgno_t, void *));
+					/* page out conversion routine */
+	void    (*pgout) __P((void *, pgno_t, void *));
+	void	*pgcookie;		/* cookie for page in/out routines */
+#ifdef STATISTICS
+	u_long	cachehit;
+	u_long	cachemiss;
+	u_long	pagealloc;
+	u_long	pageflush;
+	u_long	pageget;
+	u_long	pagenew;
+	u_long	pageput;
+	u_long	pageread;
+	u_long	pagewrite;
+#endif
+} MPOOL;
+
+__BEGIN_DECLS
+MPOOL	*mpool_open __P((void *, int, pgno_t, pgno_t));
+void	 mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *),
+	    void (*)(void *, pgno_t, void *), void *));
+void	*mpool_new __P((MPOOL *, pgno_t *));
+void	*mpool_get __P((MPOOL *, pgno_t, u_int));
+int	 mpool_put __P((MPOOL *, void *, u_int));
+int	 mpool_sync __P((MPOOL *));
+int	 mpool_close __P((MPOOL *));
+#ifdef STATISTICS
+void	 mpool_stat __P((MPOOL *));
+#endif
+__END_DECLS
Index: /branches/EMX/src/emx/bsd/db/include/ndbm.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/ndbm.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/ndbm.h	(revision 273)
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)ndbm.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _NDBM_H_
+#define	_NDBM_H_
+
+#include <db.h>
+
+/* Map dbm interface onto db(3). */
+#define DBM_RDONLY	O_RDONLY
+
+/* Flags to dbm_store(). */
+#define DBM_INSERT      0
+#define DBM_REPLACE     1
+
+/*
+ * The db(3) support for ndbm(3) always appends this suffix to the
+ * file name to avoid overwriting the user's original database.
+ */
+#define	DBM_SUFFIX	".db"
+
+typedef struct {
+	char *dptr;
+	int dsize;
+} datum;
+
+typedef DB DBM;
+#define	dbm_pagfno(a)	DBM_PAGFNO_NOT_AVAILABLE
+
+__BEGIN_DECLS
+void	 dbm_close __P((DBM *));
+int	 dbm_delete __P((DBM *, datum));
+datum	 dbm_fetch __P((DBM *, datum));
+datum	 dbm_firstkey __P((DBM *));
+long	 dbm_forder __P((DBM *, datum));
+datum	 dbm_nextkey __P((DBM *));
+DBM	*dbm_open __P((const char *, int, int));
+int	 dbm_store __P((DBM *, datum, datum, int));
+int	 dbm_dirfno __P((DBM *));
+__END_DECLS
+
+#endif /* !_NDBM_H_ */
Index: /branches/EMX/src/emx/bsd/db/include/sys/cdefs.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/sys/cdefs.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/sys/cdefs.h	(revision 273)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)cdefs.h	8.7 (Berkeley) 1/21/94
+ */
+
+#ifndef	_CDEFS_H_
+#define	_CDEFS_H_
+
+#if defined(__cplusplus)
+#define	__BEGIN_DECLS	extern "C" {
+#define	__END_DECLS	};
+#else
+#define	__BEGIN_DECLS
+#define	__END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments.  __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define	__P(protos)	protos		/* full-blown ANSI C */
+#define	__CONCAT(x,y)	x ## y
+#define	__STRING(x)	#x
+
+#define	__const		const		/* define reserved names to standard */
+#define	__signed	signed
+#define	__volatile	volatile
+#if defined(__cplusplus)
+#define	__inline	inline		/* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define	__inline			/* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else	/* !(__STDC__ || __cplusplus) */
+#define	__P(protos)	()		/* traditional C preprocessor */
+#define	__CONCAT(x,y)	x/**/y
+#define	__STRING(x)	"x"
+
+#ifndef __GNUC__
+#define	__const				/* delete pseudo-ANSI C keywords */
+#define	__inline
+#define	__signed
+#define	__volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef	NO_ANSI_KEYWORDS
+#define	const				/* delete ANSI C keywords */
+#define	inline
+#define	signed
+#define	volatile
+#endif
+#endif	/* !__GNUC__ */
+#endif	/* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style.  All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define	__attribute__(x)	/* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define	__dead		__volatile
+#define	__pure		__const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define	__dead
+#define	__pure
+#endif
+
+#endif /* !_CDEFS_H_ */
Index: /branches/EMX/src/emx/bsd/db/include/sys/mman.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/sys/mman.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/sys/mman.h	(revision 273)
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	from: @(#)mman.h	7.5 (Berkeley) 6/27/91
+ *	mman.h,v 1.3 1993/05/20 16:22:41 cgd Exp
+ */
+
+#ifndef _SYS_MMAN_H_
+#define _SYS_MMAN_H_
+
+/*
+ * Protections are chosen from these bits, or-ed together
+ */
+#define	PROT_READ	0x04	/* pages can be read */
+#define	PROT_WRITE	0x02	/* pages can be written */
+#define	PROT_EXEC	0x01	/* pages can be executed */
+
+/*
+ * Flags contain mapping type, sharing type and options.
+ * Mapping type; choose one
+ */
+#define	MAP_FILE	0x0001	/* mapped from a file or device */
+#define	MAP_ANON	0x0002	/* allocated from memory, swap space */
+#define	MAP_TYPE	0x000f	/* mask for type field */
+
+/*
+ * Sharing types; choose one
+ */
+#define	MAP_COPY	0x0020	/* "copy" region at mmap time */
+#define	MAP_SHARED	0x0010	/* share changes */
+#define	MAP_PRIVATE	0x0000	/* changes are private */
+
+/*
+ * Other flags
+ */
+#define	MAP_FIXED	0x0100	/* map addr must be exactly as requested */
+#define	MAP_NOEXTEND	0x0200	/* for MAP_FILE, don't change file size */
+#define	MAP_HASSEMPHORE	0x0400	/* region may contain semaphores */
+#define	MAP_INHERIT	0x0800	/* region is retained after exec */
+
+/*
+ * Advice to madvise
+ */
+#define	MADV_NORMAL	0	/* no further special treatment */
+#define	MADV_RANDOM	1	/* expect random page references */
+#define	MADV_SEQUENTIAL	2	/* expect sequential page references */
+#define	MADV_WILLNEED	3	/* will need these pages */
+#define	MADV_DONTNEED	4	/* dont need these pages */
+
+#ifndef KERNEL
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+/* Some of these int's should probably be size_t's */
+caddr_t	mmap __P((caddr_t, size_t, int, int, int, off_t));
+int	mprotect __P((caddr_t, int, int));
+int	munmap __P((caddr_t, int));
+int	msync __P((caddr_t, int));
+__END_DECLS
+
+#endif /* !KERNEL */
+
+#endif /* !_SYS_MMAN_H_ */
Index: /branches/EMX/src/emx/bsd/db/include/sys/queue.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/include/sys/queue.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/include/sys/queue.h	(revision 273)
@@ -0,0 +1,245 @@
+/* 
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)queue.h	8.3 (Berkeley) 12/13/93
+ */
+
+#ifndef	_QUEUE_H_
+#define	_QUEUE_H_
+
+/*
+ * This file defines three types of data structures: lists, tail queues,
+ * and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list after
+ * an existing element or at the head of the list. A list may only be
+ * traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A tail queue may only be traversed in the forward direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) {						\
+	(head)->lh_first = NULL;					\
+}
+
+#define LIST_INSERT_AFTER(listelm, elm, field) {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+}
+
+#define LIST_INSERT_HEAD(head, elm, field) {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+}
+
+#define LIST_REMOVE(elm, field) {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev = 			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+}
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+}
+
+#define TAILQ_INSERT_HEAD(head, elm, field) {				\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+}
+
+#define TAILQ_INSERT_TAIL(head, elm, field) {				\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+}
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) {			\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+}
+
+#define TAILQ_REMOVE(head, elm, field) {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+}
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) {						\
+	(head)->cqh_first = (void *)(head);				\
+	(head)->cqh_last = (void *)(head);				\
+}
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == (void *)(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+}
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == (void *)(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+}
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) {				\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = (void *)(head);				\
+	if ((head)->cqh_last == (void *)(head))				\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+}
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) {				\
+	(elm)->field.cqe_next = (void *)(head);				\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == (void *)(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+}
+
+#define	CIRCLEQ_REMOVE(head, elm, field) {				\
+	if ((elm)->field.cqe_next == (void *)(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == (void *)(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+}
+#endif	/* !_QUEUE_H_ */
Index: /branches/EMX/src/emx/bsd/db/make.cmd
===================================================================
--- /branches/EMX/src/emx/bsd/db/make.cmd	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/make.cmd	(revision 273)
@@ -0,0 +1,4 @@
+/* make.cmd */
+
+parse arg target
+call sub dmake target
Index: /branches/EMX/src/emx/bsd/db/man/btree.3
===================================================================
--- /branches/EMX/src/emx/bsd/db/man/btree.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/man/btree.3	(revision 273)
@@ -0,0 +1,233 @@
+.\" Copyright (c) 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"	@(#)btree.3	8.4 (Berkeley) 8/18/94
+.\"
+.TH BTREE 3 "August 18, 1994"
+.\".UC 7
+.SH NAME
+btree \- btree database access method
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <db.h>
+.ft R
+.fi
+.SH DESCRIPTION
+The routine
+.IR dbopen
+is the library interface to database files.
+One of the supported file formats is btree files.
+The general description of the database access methods is in
+.IR dbopen (3),
+this manual page describes only the btree specific information.
+.PP
+The btree data structure is a sorted, balanced tree structure storing
+associated key/data pairs.
+.PP
+The btree access method specific data structure provided to
+.I dbopen
+is defined in the <db.h> include file as follows:
+.PP
+typedef struct {
+.RS
+u_long flags;
+.br
+u_int cachesize;
+.br
+int maxkeypage;
+.br
+int minkeypage;
+.br
+u_int psize;
+.br
+int (*compare)(const DBT *key1, const DBT *key2);
+.br
+size_t (*prefix)(const DBT *key1, const DBT *key2);
+.br
+int lorder;
+.RE
+} BTREEINFO;
+.PP
+The elements of this structure are as follows:
+.TP
+flags
+The flag value is specified by
+.IR or 'ing
+any of the following values:
+.RS
+.TP
+R_DUP
+Permit duplicate keys in the tree, i.e. permit insertion if the key to be
+inserted already exists in the tree.
+The default behavior, as described in
+.IR dbopen (3),
+is to overwrite a matching key when inserting a new key or to fail if
+the R_NOOVERWRITE flag is specified.
+The R_DUP flag is overridden by the R_NOOVERWRITE flag, and if the
+R_NOOVERWRITE flag is specified, attempts to insert duplicate keys into
+the tree will fail.
+.IP
+If the database contains duplicate keys, the order of retrieval of
+key/data pairs is undefined if the
+.I get
+routine is used, however,
+.I seq
+routine calls with the R_CURSOR flag set will always return the logical
+``first'' of any group of duplicate keys.
+.RE
+.TP
+cachesize
+A suggested maximum size (in bytes) of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather than fail.
+Since every search examines the root page of the tree, caching the most
+recently used pages substantially improves access time.
+In addition, physical writes are delayed as long as possible, so a moderate
+cache can reduce the number of I/O operations significantly.
+Obviously, using a cache increases (but only increases) the likelihood of
+corruption or lost data if the system crashes while a tree is being modified.
+If
+.I cachesize
+is 0 (no size is specified) a default cache is used.
+.TP
+maxkeypage
+The maximum number of keys which will be stored on any single page.
+Not currently implemented.
+.\" The maximum number of keys which will be stored on any single page.
+.\" Because of the way the btree data structure works,
+.\" .I maxkeypage
+.\" must always be greater than or equal to 2.
+.\" If
+.\" .I maxkeypage
+.\" is 0 (no maximum number of keys is specified) the page fill factor is
+.\" made as large as possible (which is almost invariably what is wanted).
+.TP
+minkeypage
+The minimum number of keys which will be stored on any single page.
+This value is used to determine which keys will be stored on overflow
+pages, i.e. if a key or data item is longer than the pagesize divided
+by the minkeypage value, it will be stored on overflow pages instead
+of in the page itself.
+If
+.I minkeypage
+is 0 (no minimum number of keys is specified) a value of 2 is used.
+.TP
+psize
+Page size is the size (in bytes) of the pages used for nodes in the tree.
+The minimum page size is 512 bytes and the maximum page size is 64K.
+If
+.I psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+.TP
+compare
+Compare is the key comparison function.
+It must return an integer less than, equal to, or greater than zero if the
+first key argument is considered to be respectively less than, equal to,
+or greater than the second key argument.
+The same comparison function must be used on a given tree every time it
+is opened.
+If
+.I compare
+is NULL (no comparison function is specified), the keys are compared
+lexically, with shorter keys considered less than longer keys.
+.TP
+prefix
+Prefix is the prefix comparison function.
+If specified, this routine must return the number of bytes of the second key
+argument which are necessary to determine that it is greater than the first
+key argument.
+If the keys are equal, the key length should be returned.
+Note, the usefulness of this routine is very data dependent, but, in some
+data sets can produce significantly reduced tree sizes and search times.
+If
+.I prefix
+is NULL (no prefix function is specified),
+.B and
+no comparison function is specified, a default lexical comparison routine
+is used.
+If
+.I prefix
+is NULL and a comparison routine is specified, no prefix comparison is
+done.
+.TP
+lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example, 
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+.PP
+If the file already exists (and the O_TRUNC flag is not specified), the
+values specified for the parameters flags, lorder and psize are ignored
+in favor of the values used when the tree was created.
+.PP
+Forward sequential scans of a tree are from the least key to the greatest.
+.PP
+Space freed up by deleting key/data pairs from the tree is never reclaimed,
+although it is normally made available for reuse.
+This means that the btree storage structure is grow-only.
+The only solutions are to avoid excessive deletions, or to create a fresh
+tree periodically from a scan of an existing one.
+.PP
+Searches, insertions, and deletions in a btree will all complete in
+O lg base N where base is the average fill factor.
+Often, inserting ordered data into btrees results in a low fill factor.
+This implementation has been modified to make ordered insertion the best
+case, resulting in a much better than normal page fill factor.
+.SH ERRORS
+The
+.I btree
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3).
+.SH "SEE ALSO"
+.IR dbopen (3),
+.IR hash (3),
+.IR mpool (3),
+.IR recno (3)
+.sp
+.IR "The Ubiquitous B-tree" ,
+Douglas Comer, ACM Comput. Surv. 11, 2 (June 1979), 121-138.
+.sp
+.IR "Prefix B-trees" ,
+Bayer and Unterauer, ACM Transactions on Database Systems, Vol. 2, 1
+(March 1977), 11-26.
+.sp
+.IR "The Art of Computer Programming Vol. 3: Sorting and Searching" , 
+D.E. Knuth, 1968, pp 471-480.
+.SH BUGS
+Only big and little endian byte order is supported.
Index: /branches/EMX/src/emx/bsd/db/man/dbopen.3
===================================================================
--- /branches/EMX/src/emx/bsd/db/man/dbopen.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/man/dbopen.3	(revision 273)
@@ -0,0 +1,476 @@
+.\" Copyright (c) 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"	@(#)dbopen.3	8.5 (Berkeley) 1/2/94
+.\"
+.TH DBOPEN 3 "January 2, 1994"
+.UC 7
+.SH NAME
+dbopen \- database access methods
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <limits.h>
+#include <db.h>
+
+DB *
+dbopen(const char *file, int flags, int mode, DBTYPE type,
+.ti +5
+const void *openinfo);
+.ft R
+.fi
+.SH DESCRIPTION
+.IR Dbopen
+is the library interface to database files.
+The supported file formats are btree, hashed and UNIX file oriented.
+The btree format is a representation of a sorted, balanced tree structure.
+The hashed format is an extensible, dynamic hashing scheme.
+The flat-file format is a byte stream file with fixed or variable length
+records.
+The formats and file format specific information are described in detail
+in their respective manual pages
+.IR btree (3),
+.IR hash (3)
+and
+.IR recno (3).
+.PP
+Dbopen opens
+.I file
+for reading and/or writing.
+Files never intended to be preserved on disk may be created by setting
+the file parameter to NULL.
+.PP
+The
+.I flags
+and
+.I mode arguments
+are as specified to the
+.IR open (2)
+routine, however, only the O_CREAT, O_EXCL, O_EXLOCK, O_NONBLOCK,
+O_RDONLY, O_RDWR, O_SHLOCK and O_TRUNC flags are meaningful.
+(Note, opening a database file O_WRONLY is not possible.)
+.\"Three additional options may be specified by
+.\".IR or 'ing
+.\"them into the
+.\".I flags
+.\"argument.
+.\".TP
+.\"DB_LOCK
+.\"Do the necessary locking in the database to support concurrent access.
+.\"If concurrent access isn't needed or the database is read-only this
+.\"flag should not be set, as it tends to have an associated performance
+.\"penalty.
+.\".TP
+.\"DB_SHMEM
+.\"Place the underlying memory pool used by the database in shared
+.\"memory.
+.\"Necessary for concurrent access.
+.\".TP
+.\"DB_TXN
+.\"Support transactions in the database.
+.\"The DB_LOCK and DB_SHMEM flags must be set as well.
+.PP
+The
+.I type
+argument is of type DBTYPE (as defined in the <db.h> include file) and
+may be set to DB_BTREE, DB_HASH or DB_RECNO.
+.PP
+The
+.I openinfo
+argument is a pointer to an access method specific structure described
+in the access method's manual page.
+If
+.I openinfo
+is NULL, each access method will use defaults appropriate for the system
+and the access method.
+.PP
+.I Dbopen
+returns a pointer to a DB structure on success and NULL on error.
+The DB structure is defined in the <db.h> include file, and contains at
+least the following fields:
+.sp
+.nf
+typedef struct {
+.RS
+DBTYPE type;
+int (*close)(const DB *db);
+int (*del)(const DB *db, const DBT *key, u_int flags);
+int (*fd)(const DB *db);
+int (*get)(const DB *db, DBT *key, DBT *data, u_int flags);
+int (*put)(const DB *db, DBT *key, const DBT *data,
+.ti +5
+u_int flags);
+int (*sync)(const DB *db, u_int flags);
+int (*seq)(const DB *db, DBT *key, DBT *data, u_int flags);
+.RE
+} DB;
+.fi
+.PP
+These elements describe a database type and a set of functions performing
+various actions.
+These functions take a pointer to a structure as returned by
+.IR dbopen ,
+and sometimes one or more pointers to key/data structures and a flag value.
+.TP
+type
+The type of the underlying access method (and file format).
+.TP
+close
+A pointer to a routine to flush any cached information to disk, free any
+allocated resources, and close the underlying file(s).
+Since key/data pairs may be cached in memory, failing to sync the file
+with a
+.I close
+or
+.I sync
+function may result in inconsistent or lost information.
+.I Close
+routines return -1 on error (setting
+.IR errno )
+and 0 on success.
+.TP
+del
+A pointer to a routine to remove key/data pairs from the database.
+.IP
+The parameter
+.I flag
+may be set to the following value:
+.RS
+.TP
+R_CURSOR
+Delete the record referenced by the cursor.
+The cursor must have previously been initialized.
+.RE
+.IP
+.I Delete
+routines return -1 on error (setting
+.IR errno ),
+0 on success, and 1 if the specified
+.I key
+was not in the file.
+.TP
+fd
+A pointer to a routine which returns a file descriptor representative
+of the underlying database.
+A file descriptor referencing the same file will be returned to all
+processes which call
+.I dbopen
+with the same
+.I file
+name.
+This file descriptor may be safely used as an argument to the
+.IR fcntl (2)
+and
+.IR flock (2)
+locking functions.
+The file descriptor is not necessarily associated with any of the
+underlying files used by the access method.
+No file descriptor is available for in memory databases.
+.I Fd
+routines return -1 on error (setting
+.IR errno ),
+and the file descriptor on success.
+.TP
+get
+A pointer to a routine which is the interface for keyed retrieval from
+the database.
+The address and length of the data associated with the specified
+.I key
+are returned in the structure referenced by
+.IR data .
+.I Get
+routines return -1 on error (setting
+.IR errno ),
+0 on success, and 1 if the
+.I key
+was not in the file.
+.TP
+put
+A pointer to a routine to store key/data pairs in the database.
+.IP
+The parameter
+.I flag
+may be set to one of the following values:
+.RS
+.TP
+R_CURSOR
+Replace the key/data pair referenced by the cursor.
+The cursor must have previously been initialized.
+.TP
+R_IAFTER
+Append the data immediately after the data referenced by
+.IR key ,
+creating a new key/data pair.
+The record number of the appended key/data pair is returned in the
+.I key
+structure.
+(Applicable only to the DB_RECNO access method.)
+.TP
+R_IBEFORE
+Insert the data immediately before the data referenced by
+.IR key ,
+creating a new key/data pair.
+The record number of the inserted key/data pair is returned in the
+.I key
+structure.
+(Applicable only to the DB_RECNO access method.)
+.TP
+R_NOOVERWRITE
+Enter the new key/data pair only if the key does not previously exist.
+.TP
+R_SETCURSOR
+Store the key/data pair, setting or initializing the position of the
+cursor to reference it.
+(Applicable only to the DB_BTREE and DB_RECNO access methods.)
+.RE
+.IP
+R_SETCURSOR is available only for the DB_BTREE and DB_RECNO access
+methods because it implies that the keys have an inherent order
+which does not change.
+.IP
+R_IAFTER and R_IBEFORE are available only for the DB_RECNO
+access method because they each imply that the access method is able to
+create new keys.
+This is only true if the keys are ordered and independent, record numbers
+for example.
+.IP
+The default behavior of the
+.I put
+routines is to enter the new key/data pair, replacing any previously
+existing key.
+.IP
+.I Put
+routines return -1 on error (setting
+.IR errno ),
+0 on success, and 1 if the R_NOOVERWRITE
+.I flag
+was set and the key already exists in the file.
+.TP
+seq
+A pointer to a routine which is the interface for sequential
+retrieval from the database.
+The address and length of the key are returned in the structure
+referenced by
+.IR key ,
+and the address and length of the data are returned in the
+structure referenced
+by
+.IR data .
+.IP
+Sequential key/data pair retrieval may begin at any time, and the
+position of the ``cursor'' is not affected by calls to the
+.IR del ,
+.IR get ,
+.IR put ,
+or
+.I sync
+routines.
+Modifications to the database during a sequential scan will be reflected
+in the scan, i.e. records inserted behind the cursor will not be returned
+while records inserted in front of the cursor will be returned.
+.IP
+The flag value
+.B must
+be set to one of the following values:
+.RS
+.TP
+R_CURSOR
+The data associated with the specified key is returned.
+This differs from the
+.I get
+routines in that it sets or initializes the cursor to the location of
+the key as well.
+(Note, for the DB_BTREE access method, the returned key is not necessarily an
+exact match for the specified key.
+The returned key is the smallest key greater than or equal to the specified
+key, permitting partial key matches and range searches.)
+.TP
+R_FIRST
+The first key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+.TP
+R_LAST
+The last key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+(Applicable only to the DB_BTREE and DB_RECNO access methods.)
+.TP
+R_NEXT
+Retrieve the key/data pair immediately after the cursor.
+If the cursor is not yet set, this is the same as the R_FIRST flag.
+.TP
+R_PREV
+Retrieve the key/data pair immediately before the cursor.
+If the cursor is not yet set, this is the same as the R_LAST flag.
+(Applicable only to the DB_BTREE and DB_RECNO access methods.)
+.RE
+.IP
+R_LAST and R_PREV are available only for the DB_BTREE and DB_RECNO
+access methods because they each imply that the keys have an inherent
+order which does not change.
+.IP
+.I Seq
+routines return -1 on error (setting
+.IR errno ),
+0 on success and 1 if there are no key/data pairs less than or greater
+than the specified or current key.
+If the DB_RECNO access method is being used, and if the database file
+is a character special file and no complete key/data pairs are currently
+available, the
+.I seq
+routines return 2.
+.TP
+sync
+A pointer to a routine to flush any cached information to disk.
+If the database is in memory only, the
+.I sync
+routine has no effect and will always succeed.
+.IP
+The flag value may be set to the following value:
+.RS
+.TP
+R_RECNOSYNC
+If the DB_RECNO access method is being used, this flag causes
+the sync routine to apply to the btree file which underlies the
+recno file, not the recno file itself.
+(See the
+.I bfname
+field of the
+.IR recno (3)
+manual page for more information.)
+.RE
+.IP
+.I Sync
+routines return -1 on error (setting
+.IR errno )
+and 0 on success.
+.SH "KEY/DATA PAIRS"
+Access to all file types is based on key/data pairs.
+Both keys and data are represented by the following data structure:
+.PP
+typedef struct {
+.RS
+void *data;
+.br
+size_t size;
+.RE
+} DBT;
+.PP
+The elements of the DBT structure are defined as follows:
+.TP
+data
+A pointer to a byte string.
+.TP
+size
+The length of the byte string.
+.PP
+Key and data byte strings may reference strings of essentially unlimited
+length although any two of them must fit into available memory at the same
+time.
+It should be noted that the access methods provide no guarantees about
+byte string alignment.
+.SH ERRORS
+The
+.I dbopen
+routine may fail and set
+.I errno
+for any of the errors specified for the library routines
+.IR open (2)
+and
+.IR malloc (3)
+or the following:
+.TP
+[EFTYPE]
+A file is incorrectly formatted.
+.TP
+[EINVAL]
+A parameter has been specified (hash function, pad byte etc.) that is
+incompatible with the current file specification or which is not
+meaningful for the function (for example, use of the cursor without
+prior initialization) or there is a mismatch between the version
+number of file and the software.
+.PP
+The
+.I close
+routines may fail and set
+.I errno
+for any of the errors specified for the library routines
+.IR close (2),
+.IR read (2),
+.IR write (2),
+.IR free (3),
+or
+.IR fsync (2).
+.PP
+The
+.IR del ,
+.IR get ,
+.I put
+and
+.I seq
+routines may fail and set
+.I errno
+for any of the errors specified for the library routines
+.IR read (2),
+.IR write (2),
+.IR free (3)
+or
+.IR malloc (3).
+.PP
+The
+.I fd
+routines will fail and set
+.I errno
+to ENOENT for in memory databases.
+.PP
+The
+.I sync
+routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR fsync (2).
+.SH "SEE ALSO"
+.IR btree (3),
+.IR hash (3),
+.IR mpool (3),
+.IR recno (3)
+.sp
+.IR "LIBTP: Portable, Modular Transactions for UNIX" ,
+Margo Seltzer, Michael Olson, USENIX proceedings, Winter 1992.
+.SH BUGS
+The typedef DBT is a mnemonic for ``data base thang'', and was used
+because noone could think of a reasonable name that wasn't already used.
+.PP
+The file descriptor interface is a kluge and will be deleted in a
+future version of the interface.
+.PP
+None of the access methods provide any form of concurrent access,
+locking, or transactions.
Index: /branches/EMX/src/emx/bsd/db/man/hash.3
===================================================================
--- /branches/EMX/src/emx/bsd/db/man/hash.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/man/hash.3	(revision 273)
@@ -0,0 +1,159 @@
+.\" Copyright (c) 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"	@(#)hash.3	8.6 (Berkeley) 8/18/94
+.\"
+.TH HASH 3 "August 18, 1994"
+.UC 7
+.SH NAME
+hash \- hash database access method
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <db.h>
+.ft R
+.fi
+.SH DESCRIPTION
+The routine
+.IR dbopen
+is the library interface to database files.
+One of the supported file formats is hash files.
+The general description of the database access methods is in
+.IR dbopen (3),
+this manual page describes only the hash specific information.
+.PP
+The hash data structure is an extensible, dynamic hashing scheme.
+.PP
+The access method specific data structure provided to
+.I dbopen
+is defined in the <db.h> include file as follows:
+.sp
+typedef struct {
+.RS
+u_int bsize;
+.br
+u_int ffactor;
+.br
+u_int nelem;
+.br
+u_int cachesize;
+.br
+u_int32_t (*hash)(const void *, size_t);
+.br
+int lorder;
+.RE
+} HASHINFO;
+.PP
+The elements of this structure are as follows:
+.TP
+bsize
+.I Bsize
+defines the hash table bucket size, and is, by default, 256 bytes.
+It may be preferable to increase the page size for disk-resident tables
+and tables with large data items.
+.TP
+ffactor
+.I Ffactor
+indicates a desired density within the hash table.
+It is an approximation of the number of keys allowed to accumulate in any
+one bucket, determining when the hash table grows or shrinks.
+The default value is 8.
+.TP
+nelem
+.I Nelem
+is an estimate of the final size of the hash table.
+If not set or set too low, hash tables will expand gracefully as keys
+are entered, although a slight performance degradation may be noticed.
+The default value is 1.
+.TP
+cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather
+than fail.
+.TP
+hash
+.I Hash
+is a user defined hash function.
+Since no hash function performs equally well on all possible data, the
+user may find that the built-in hash function does poorly on a particular
+data set.
+User specified hash functions must take two arguments (a pointer to a byte
+string and a length) and return a 32-bit quantity to be used as the hash
+value.
+.TP
+lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example, 
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+If the  file already exists, the specified value is ignored and the
+value specified when the tree was created is used.
+.PP
+If the file already exists (and the O_TRUNC flag is not specified), the
+values specified for the parameters bsize, ffactor, lorder and nelem are
+ignored and the values specified when the tree was created are used.
+.PP
+If a hash function is specified,
+.I hash_open
+will attempt to determine if the hash function specified is the same as
+the one with which the database was created, and will fail if it is not.
+.PP
+Backward compatible interfaces to the routines described in
+.IR dbm (3),
+and
+.IR ndbm (3)
+are provided, however these interfaces are not compatible with
+previous file formats.
+.SH ERRORS
+The
+.I hash
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3).
+.SH "SEE ALSO"
+.IR btree (3),
+.IR dbopen (3),
+.IR mpool (3),
+.IR recno (3)
+.sp
+.IR "Dynamic Hash Tables" ,
+Per-Ake Larson, Communications of the ACM, April 1988.
+.sp
+.IR "A New Hash Package for UNIX" ,
+Margo Seltzer, USENIX Proceedings, Winter 1991.
+.SH BUGS
+Only big and little endian byte order is supported.
Index: /branches/EMX/src/emx/bsd/db/man/mpool.3
===================================================================
--- /branches/EMX/src/emx/bsd/db/man/mpool.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/man/mpool.3	(revision 273)
@@ -0,0 +1,219 @@
+.\" Copyright (c) 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"	@(#)mpool.3	8.1 (Berkeley) 6/4/93
+.\"
+.TH MPOOL 3 "June 4, 1993"
+.UC 7
+.SH NAME
+mpool \- shared memory buffer pool
+.SH SYNOPSIS
+.nf
+.ft B
+#include <db.h>
+#include <mpool.h>
+
+MPOOL *
+mpool_open (DBT *key, int fd, pgno_t pagesize, pgno_t maxcache);
+
+void
+mpool_filter (MPOOL *mp, void (*pgin)(void *, pgno_t, void *),
+.ti +5
+void (*pgout)(void *, pgno_t, void *), void *pgcookie);
+
+void *
+mpool_new (MPOOL *mp, pgno_t *pgnoaddr);
+
+void *
+mpool_get (MPOOL *mp, pgno_t pgno, u_int flags);
+
+int
+mpool_put (MPOOL *mp, void *pgaddr, u_int flags);
+
+int
+mpool_sync (MPOOL *mp);
+
+int
+mpool_close (MPOOL *mp);
+.ft R
+.fi
+.SH DESCRIPTION
+.IR Mpool
+is the library interface intended to provide page oriented buffer management
+of files.
+The buffers may be shared between processes.
+.PP
+The function
+.I mpool_open
+initializes a memory pool.
+The
+.I key
+argument is the byte string used to negotiate between multiple
+processes wishing to share buffers.
+If the file buffers are mapped in shared memory, all processes using
+the same key will share the buffers.
+If
+.I key
+is NULL, the buffers are mapped into private memory.
+The
+.I fd
+argument is a file descriptor for the underlying file, which must be seekable.
+If
+.I key
+is non-NULL and matches a file already being mapped, the
+.I fd
+argument is ignored.
+.PP
+The
+.I pagesize
+argument is the size, in bytes, of the pages into which the file is broken up.
+The
+.I maxcache
+argument is the maximum number of pages from the underlying file to cache
+at any one time.
+This value is not relative to the number of processes which share a file's
+buffers, but will be the largest value specified by any of the processes
+sharing the file.
+.PP
+The
+.I mpool_filter
+function is intended to make transparent input and output processing of the
+pages possible.
+If the
+.I pgin
+function is specified, it is called each time a buffer is read into the memory
+pool from the backing file.
+If the
+.I pgout
+function is specified, it is called each time a buffer is written into the
+backing file.
+Both functions are are called with the
+.I pgcookie
+pointer, the page number and a pointer to the page to being read or written.
+.PP
+The function
+.I mpool_new
+takes an MPOOL pointer and an address as arguments.
+If a new page can be allocated, a pointer to the page is returned and
+the page number is stored into the
+.I pgnoaddr
+address.
+Otherwise, NULL is returned and errno is set.
+.PP
+The function
+.I mpool_get
+takes a MPOOL pointer and a page number as arguments.
+If the page exists, a pointer to the page is returned.
+Otherwise, NULL is returned and errno is set.
+The flags parameter is not currently used.
+.PP
+The function
+.I mpool_put
+unpins the page referenced by
+.IR pgaddr .
+.I Pgaddr
+must be an address previously returned by
+.I mpool_get
+or
+.IR mpool_new .
+The flag value is specified by
+.IR or 'ing
+any of the following values:
+.TP
+MPOOL_DIRTY
+The page has been modified and needs to be written to the backing file.
+.PP
+.I Mpool_put
+returns 0 on success and -1 if an error occurs.
+.PP
+The function
+.I mpool_sync
+writes all modified pages associated with the MPOOL pointer to the
+backing file.
+.I Mpool_sync
+returns 0 on success and -1 if an error occurs.
+.PP
+The
+.I mpool_close
+function free's up any allocated memory associated with the memory pool
+cookie.
+Modified pages are
+.B not
+written to the backing file.
+.I Mpool_close
+returns 0 on success and -1 if an error occurs.
+.SH ERRORS
+The
+.I mpool_open
+function may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR malloc (3).
+.PP
+The
+.I mpool_get
+function may fail and set
+.I errno
+for the following:
+.TP 15
+[EINVAL]
+The requested record doesn't exist.
+.PP
+The
+.I mpool_new
+and
+.I mpool_get
+functions may fail and set
+.I errno
+for any of the errors specified for the library routines
+.IR read (2) ,
+.IR write (2) ,
+and
+.IR malloc (3).
+.PP
+The
+.I mpool_sync
+function may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR write (2).
+.PP
+The
+.I mpool_close
+function may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR free (3).
+.SH "SEE ALSO"
+.IR dbopen (3),
+.IR btree (3),
+.IR hash (3),
+.IR recno (3)
Index: /branches/EMX/src/emx/bsd/db/man/recno.3
===================================================================
--- /branches/EMX/src/emx/bsd/db/man/recno.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/man/recno.3	(revision 273)
@@ -0,0 +1,216 @@
+.\" Copyright (c) 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"	@(#)recno.3	8.5 (Berkeley) 8/18/94
+.\"
+.TH RECNO 3 "August 18, 1994"
+.UC 7
+.SH NAME
+recno \- record number database access method
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <db.h>
+.ft R
+.fi
+.SH DESCRIPTION
+The routine
+.IR dbopen
+is the library interface to database files.
+One of the supported file formats is record number files.
+The general description of the database access methods is in
+.IR dbopen (3),
+this manual page describes only the recno specific information.
+.PP
+The record number data structure is either variable or fixed-length
+records stored in a flat-file format, accessed by the logical record
+number.
+The existence of record number five implies the existence of records
+one through four, and the deletion of record number one causes
+record number five to be renumbered to record number four, as well
+as the cursor, if positioned after record number one, to shift down
+one record.
+.PP
+The recno access method specific data structure provided to
+.I dbopen
+is defined in the <db.h> include file as follows:
+.PP
+typedef struct {
+.RS
+u_long flags;
+.br
+u_int cachesize;
+.br
+u_int psize;
+.br
+int lorder;
+.br
+size_t reclen;
+.br
+u_char bval;
+.br
+char *bfname;
+.RE
+} RECNOINFO;
+.PP
+The elements of this structure are defined as follows:
+.TP
+flags
+The flag value is specified by
+.IR or 'ing
+any of the following values:
+.RS
+.TP
+R_FIXEDLEN
+The records are fixed-length, not byte delimited.
+The structure element
+.I reclen
+specifies the length of the record, and the structure element
+.I bval
+is used as the pad character.
+Any records, inserted into the database, that are less than
+.I reclen
+bytes long are automatically padded.
+.TP
+R_NOKEY
+In the interface specified by
+.IR dbopen ,
+the sequential record retrieval fills in both the caller's key and
+data structures.
+If the R_NOKEY flag is specified, the
+.I cursor
+routines are not required to fill in the key structure.
+This permits applications to retrieve records at the end of files without
+reading all of the intervening records.
+.TP
+R_SNAPSHOT
+This flag requires that a snapshot of the file be taken when
+.I dbopen
+is called, instead of permitting any unmodified records to be read from
+the original file.
+.RE
+.TP
+cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather than fail.
+If
+.I cachesize
+is  0 (no size is specified) a default cache is used.
+.TP
+psize
+The recno access method stores the in-memory copies of its records
+in a btree.
+This value is the size (in bytes) of the pages used for nodes in that tree.
+If
+.I psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+See
+.IR btree (3)
+for more information.
+.TP
+lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+.TP
+reclen
+The length of a fixed-length record.
+.TP
+bval
+The delimiting byte to be used to mark the end of a record for
+variable-length records, and the pad character for fixed-length
+records.
+If no value is specified, newlines (``\en'') are used to mark the end
+of variable-length records and fixed-length records are padded with
+spaces.
+.TP
+bfname
+The recno access method stores the in-memory copies of its records
+in a btree.
+If bfname is non-NULL, it specifies the name of the btree file,
+as if specified as the file name for a dbopen of a btree file.
+.PP
+The data part of the key/data pair used by the recno access method
+is the same as other access methods.
+The key is different.
+The
+.I data
+field of the key should be a pointer to a memory location of type
+.IR recno_t ,
+as defined in the <db.h> include file.
+This type is normally the largest unsigned integral type available to
+the implementation.
+The
+.I size
+field of the key should be the size of that type.
+.PP
+Because there can be no meta-data associated with the underlying
+recno access method files, any changes made to the default values
+(e.g. fixed record length or byte separator value) must be explicitly
+specified each time the file is opened.
+.PP
+In the interface specified by
+.IR dbopen ,
+using the
+.I put
+interface to create a new record will cause the creation of multiple,
+empty records if the record number is more than one greater than the
+largest record currently in the database.
+.SH ERRORS
+The
+.I recno
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3)
+or the following:
+.TP
+[EINVAL]
+An attempt was made to add a record to a fixed-length database that
+was too large to fit.
+.SH "SEE ALSO"
+.IR btree (3)
+.IR dbopen (3),
+.IR hash (3),
+.IR mpool (3),
+.sp
+.IR "Document Processing in a Relational Database System" ,
+Michael Stonebraker, Heidi Stettner, Joseph Kalash, Antonin Guttman,
+Nadene Lynn, Memorandum No. UCB/ERL M82/32, May 1982.
+.SH BUGS
+Only big and little endian byte order is supported.
Index: /branches/EMX/src/emx/bsd/db/mpool/README
===================================================================
--- /branches/EMX/src/emx/bsd/db/mpool/README	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/mpool/README	(revision 273)
@@ -0,0 +1,7 @@
+#	@(#)README	8.1 (Berkeley) 6/4/93
+
+These are the current memory pool routines.
+They aren't ready for prime time, yet, and
+the interface is expected to change.
+
+--keith
Index: /branches/EMX/src/emx/bsd/db/mpool/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/mpool/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/mpool/makefile	(revision 273)
@@ -0,0 +1,2 @@
+OBJS =	mpool.o
+.INCLUDE:../emx/makefile.sub
Index: /branches/EMX/src/emx/bsd/db/mpool/mpool.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/mpool/mpool.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/mpool/mpool.c	(revision 273)
@@ -0,0 +1,466 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mpool.c	8.5 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#ifdef __EMX__
+#include <sys/types.h>
+#endif /* __EMX__ */
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+#define	__MPOOLINTERFACE_PRIVATE
+#include <mpool.h>
+
+static BKT *mpool_bkt __P((MPOOL *));
+static BKT *mpool_look __P((MPOOL *, pgno_t));
+static int  mpool_write __P((MPOOL *, BKT *));
+
+/*
+ * mpool_open --
+ *	Initialize a memory pool.
+ */
+MPOOL *
+mpool_open(key, fd, pagesize, maxcache)
+	void *key;
+	int fd;
+	pgno_t pagesize, maxcache;
+{
+	struct stat sb;
+	MPOOL *mp;
+	int entry;
+
+	/*
+	 * Get information about the file.
+	 *
+	 * XXX
+	 * We don't currently handle pipes, although we should.
+	 */
+	if (fstat(fd, &sb))
+		return (NULL);
+	if (!S_ISREG(sb.st_mode)) {
+		errno = ESPIPE;
+		return (NULL);
+	}
+
+	/* Allocate and initialize the MPOOL cookie. */
+	if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
+		return (NULL);
+	CIRCLEQ_INIT(&mp->lqh);
+	for (entry = 0; entry < HASHSIZE; ++entry)
+		CIRCLEQ_INIT(&mp->hqh[entry]);
+	mp->maxcache = maxcache;
+	mp->npages = sb.st_size / pagesize;
+	mp->pagesize = pagesize;
+	mp->fd = fd;
+	return (mp);
+}
+
+/*
+ * mpool_filter --
+ *	Initialize input/output filters.
+ */
+void
+mpool_filter(mp, pgin, pgout, pgcookie)
+	MPOOL *mp;
+	void (*pgin) __P((void *, pgno_t, void *));
+	void (*pgout) __P((void *, pgno_t, void *));
+	void *pgcookie;
+{
+	mp->pgin = pgin;
+	mp->pgout = pgout;
+	mp->pgcookie = pgcookie;
+}
+	
+/*
+ * mpool_new --
+ *	Get a new page of memory.
+ */
+void *
+mpool_new(mp, pgnoaddr)
+	MPOOL *mp;
+	pgno_t *pgnoaddr;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	if (mp->npages == MAX_PAGE_NUMBER) {
+		(void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
+		abort();
+	}
+#ifdef STATISTICS
+	++mp->pagenew;
+#endif
+	/*
+	 * Get a BKT from the cache.  Assign a new page number, attach
+	 * it to the head of the hash chain, the tail of the lru chain,
+	 * and return.
+	 */
+	if ((bp = mpool_bkt(mp)) == NULL)
+		return (NULL);
+	*pgnoaddr = bp->pgno = mp->npages++;
+	bp->flags = MPOOL_PINNED;
+
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	CIRCLEQ_INSERT_HEAD(head, bp, hq);
+	CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
+	return (bp->page);
+}
+
+/*
+ * mpool_get
+ *	Get a page.
+ */
+void *
+mpool_get(mp, pgno, flags)
+	MPOOL *mp;
+	pgno_t pgno;
+	u_int flags;				/* XXX not used? */
+{
+	struct _hqh *head;
+	BKT *bp;
+	off_t off;
+	int nr;
+
+	/* Check for attempt to retrieve a non-existent page. */
+	if (pgno >= mp->npages) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+#ifdef STATISTICS
+	++mp->pageget;
+#endif
+
+	/* Check for a page that is cached. */
+	if ((bp = mpool_look(mp, pgno)) != NULL) {
+#ifdef DEBUG
+		if (bp->flags & MPOOL_PINNED) {
+			(void)fprintf(stderr,
+			    "mpool_get: page %d already pinned\n", bp->pgno);
+			abort();
+		}
+#endif
+		/*
+		 * Move the page to the head of the hash chain and the tail
+		 * of the lru chain.
+		 */
+		head = &mp->hqh[HASHKEY(bp->pgno)];
+		CIRCLEQ_REMOVE(head, bp, hq);
+		CIRCLEQ_INSERT_HEAD(head, bp, hq);
+		CIRCLEQ_REMOVE(&mp->lqh, bp, q);
+		CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+		/* Return a pinned page. */
+		bp->flags |= MPOOL_PINNED;
+		return (bp->page);
+	}
+
+	/* Get a page from the cache. */
+	if ((bp = mpool_bkt(mp)) == NULL)
+		return (NULL);
+
+	/* Read in the contents. */
+#ifdef STATISTICS
+	++mp->pageread;
+#endif
+	off = mp->pagesize * pgno;
+	if (lseek(mp->fd, off, SEEK_SET) != off)
+		return (NULL);
+	if ((nr = read(mp->fd, bp->page, mp->pagesize)) != mp->pagesize) {
+		if (nr >= 0)
+			errno = EFTYPE;
+		return (NULL);
+	}
+
+	/* Set the page number, pin the page. */
+	bp->pgno = pgno;
+	bp->flags = MPOOL_PINNED;
+
+	/*
+	 * Add the page to the head of the hash chain and the tail
+	 * of the lru chain.
+	 */
+	head = &mp->hqh[HASHKEY(bp->pgno)];
+	CIRCLEQ_INSERT_HEAD(head, bp, hq);
+	CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+	/* Run through the user's filter. */
+	if (mp->pgin != NULL)
+		(mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
+	return (bp->page);
+}
+
+/*
+ * mpool_put
+ *	Return a page.
+ */
+int
+mpool_put(mp, page, flags)
+	MPOOL *mp;
+	void *page;
+	u_int flags;
+{
+	BKT *bp;
+
+#ifdef STATISTICS
+	++mp->pageput;
+#endif
+	bp = (BKT *)((char *)page - sizeof(BKT));
+#ifdef DEBUG
+	if (!(bp->flags & MPOOL_PINNED)) {
+		(void)fprintf(stderr,
+		    "mpool_put: page %d not pinned\n", bp->pgno);
+		abort();
+	}
+#endif
+	bp->flags &= ~MPOOL_PINNED;
+	bp->flags |= flags & MPOOL_DIRTY;
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_close
+ *	Close the buffer pool.
+ */
+int
+mpool_close(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+
+	/* Free up any space allocated to the lru pages. */
+	while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) {
+		CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q);
+		free(bp);
+	}
+
+	/* Free the MPOOL cookie. */
+	free(mp);
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_sync
+ *	Sync the pool to disk.
+ */
+int
+mpool_sync(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+
+	/* Walk the lru chain, flushing any dirty pages to disk. */
+	for (bp = mp->lqh.cqh_first;
+	    bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
+		if (bp->flags & MPOOL_DIRTY &&
+		    mpool_write(mp, bp) == RET_ERROR)
+			return (RET_ERROR);
+
+	/* Sync the file descriptor. */
+	return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * mpool_bkt
+ *	Get a page from the cache (or create one).
+ */
+static BKT *
+mpool_bkt(mp)
+	MPOOL *mp;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	/* If under the max cached, always create a new page. */
+	if (mp->curcache < mp->maxcache)
+		goto new;
+
+	/*
+	 * If the cache is max'd out, walk the lru list for a buffer we
+	 * can flush.  If we find one, write it (if necessary) and take it
+	 * off any lists.  If we don't find anything we grow the cache anyway.
+	 * The cache never shrinks.
+	 */
+	for (bp = mp->lqh.cqh_first;
+	    bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
+		if (!(bp->flags & MPOOL_PINNED)) {
+			/* Flush if dirty. */
+			if (bp->flags & MPOOL_DIRTY &&
+			    mpool_write(mp, bp) == RET_ERROR)
+				return (NULL);
+#ifdef STATISTICS
+			++mp->pageflush;
+#endif
+			/* Remove from the hash and lru queues. */
+			head = &mp->hqh[HASHKEY(bp->pgno)];
+			CIRCLEQ_REMOVE(head, bp, hq);
+			CIRCLEQ_REMOVE(&mp->lqh, bp, q);
+#ifdef DEBUG
+			{ void *spage;
+				spage = bp->page;
+				memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+				bp->page = spage;
+			}
+#endif
+			return (bp);
+		}
+
+new:	if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+		return (NULL);
+#ifdef STATISTICS
+	++mp->pagealloc;
+#endif
+#if defined(DEBUG) || defined(PURIFY)
+	memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+#endif
+	bp->page = (char *)bp + sizeof(BKT);
+	++mp->curcache;
+	return (bp);
+}
+
+/*
+ * mpool_write
+ *	Write a page to disk.
+ */
+static int
+mpool_write(mp, bp)
+	MPOOL *mp;
+	BKT *bp;
+{
+	off_t off;
+
+#ifdef STATISTICS
+	++mp->pagewrite;
+#endif
+
+	/* Run through the user's filter. */
+	if (mp->pgout)
+		(mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
+
+	off = mp->pagesize * bp->pgno;
+	if (lseek(mp->fd, off, SEEK_SET) != off)
+		return (RET_ERROR);
+	if (write(mp->fd, bp->page, mp->pagesize) != mp->pagesize)
+		return (RET_ERROR);
+
+	bp->flags &= ~MPOOL_DIRTY;
+	return (RET_SUCCESS);
+}
+
+/*
+ * mpool_look
+ *	Lookup a page in the cache.
+ */
+static BKT *
+mpool_look(mp, pgno)
+	MPOOL *mp;
+	pgno_t pgno;
+{
+	struct _hqh *head;
+	BKT *bp;
+
+	head = &mp->hqh[HASHKEY(pgno)];
+	for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next)
+		if (bp->pgno == pgno) {
+#ifdef STATISTICS
+			++mp->cachehit;
+#endif
+			return (bp);
+		}
+#ifdef STATISTICS
+	++mp->cachemiss;
+#endif
+	return (NULL);
+}
+
+#ifdef STATISTICS
+/*
+ * mpool_stat
+ *	Print out cache statistics.
+ */
+void
+mpool_stat(mp)
+	MPOOL *mp;
+{
+	BKT *bp;
+	int cnt;
+	char *sep;
+
+	(void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
+	(void)fprintf(stderr,
+	    "page size %lu, cacheing %lu pages of %lu page max cache\n",
+	    mp->pagesize, mp->curcache, mp->maxcache);
+	(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
+	    mp->pageput, mp->pageget, mp->pagenew);
+	(void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
+	    mp->pagealloc, mp->pageflush);
+	if (mp->cachehit + mp->cachemiss)
+		(void)fprintf(stderr,
+		    "%.0f%% cache hit rate (%lu hits, %lu misses)\n", 
+		    ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
+		    * 100, mp->cachehit, mp->cachemiss);
+	(void)fprintf(stderr, "%lu page reads, %lu page writes\n",
+	    mp->pageread, mp->pagewrite);
+
+	sep = "";
+	cnt = 0;
+	for (bp = mp->lqh.cqh_first;
+	    bp != (void *)&mp->lqh; bp = bp->q.cqe_next) {
+		(void)fprintf(stderr, "%s%d", sep, bp->pgno);
+		if (bp->flags & MPOOL_DIRTY)
+			(void)fprintf(stderr, "d");
+		if (bp->flags & MPOOL_PINNED)
+			(void)fprintf(stderr, "P");
+		if (++cnt == 10) {
+			sep = "\n";
+			cnt = 0;
+		} else
+			sep = ", ";
+			
+	}
+	(void)fprintf(stderr, "\n");
+}
+#endif
Index: /branches/EMX/src/emx/bsd/db/recno/extern.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/extern.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/extern.h	(revision 273)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)extern.h	8.3 (Berkeley) 6/4/94
+ */
+
+#include "../btree/extern.h"
+
+int	 __rec_close __P((DB *));
+int	 __rec_delete __P((const DB *, const DBT *, u_int));
+int	 __rec_dleaf __P((BTREE *, PAGE *, u_int32_t));
+int	 __rec_fd __P((const DB *));
+int	 __rec_fmap __P((BTREE *, recno_t));
+int	 __rec_fout __P((BTREE *));
+int	 __rec_fpipe __P((BTREE *, recno_t));
+int	 __rec_get __P((const DB *, const DBT *, DBT *, u_int));
+int	 __rec_iput __P((BTREE *, recno_t, const DBT *, u_int));
+int	 __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int));
+int	 __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *));
+EPG	*__rec_search __P((BTREE *, recno_t, enum SRCHOP));
+int	 __rec_seq __P((const DB *, DBT *, DBT *, u_int));
+int	 __rec_sync __P((const DB *, u_int));
+int	 __rec_vmap __P((BTREE *, recno_t));
+int	 __rec_vout __P((BTREE *));
+int	 __rec_vpipe __P((BTREE *, recno_t));
Index: /branches/EMX/src/emx/bsd/db/recno/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/makefile	(revision 273)
@@ -0,0 +1,3 @@
+OBJS =	rec_close.o rec_delete.o rec_get.o rec_open.o rec_put.o rec_search.o \
+	rec_seq.o rec_utils.o
+.INCLUDE:../emx/makefile.sub
Index: /branches/EMX/src/emx/bsd/db/recno/rec_close.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_close.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_close.c	(revision 273)
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_close.c	8.6 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_CLOSE -- Close a recno tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_close(dbp)
+	DB *dbp;
+{
+	BTREE *t;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (__rec_sync(dbp, 0) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Committed to closing. */
+	status = RET_SUCCESS;
+	if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
+		status = RET_ERROR;
+
+	if (!F_ISSET(t, R_INMEM))
+		if (F_ISSET(t, R_CLOSEFP)) {
+			if (fclose(t->bt_rfp))
+				status = RET_ERROR;
+		} else
+			if (close(t->bt_rfd))
+				status = RET_ERROR;
+
+	if (__bt_close(dbp) == RET_ERROR)
+		status = RET_ERROR;
+
+	return (status);
+}
+
+/*
+ * __REC_SYNC -- sync the recno tree to disk.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_sync(dbp, flags)
+	const DB *dbp;
+	u_int flags;
+{
+	struct iovec iov[2];
+	BTREE *t;
+	DBT data, key;
+	off_t off;
+	recno_t scursor, trec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	if (flags == R_RECNOSYNC)
+		return (__bt_sync(dbp, 0));
+
+	if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
+		return (RET_SUCCESS);
+
+	/* Read any remaining records into the tree. */
+	if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+		return (RET_ERROR);
+
+	/* Rewind the file descriptor. */
+	if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
+		return (RET_ERROR);
+
+	/* Save the cursor. */
+	scursor = t->bt_cursor.rcursor;
+
+	key.size = sizeof(recno_t);
+	key.data = &trec;
+
+	if (F_ISSET(t, R_FIXLEN)) {
+		/*
+		 * We assume that fixed length records are all fixed length.
+		 * Any that aren't are either EINVAL'd or corrected by the
+		 * record put code.
+		 */
+		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+		while (status == RET_SUCCESS) {
+			if (write(t->bt_rfd, data.data, data.size) != data.size)
+				return (RET_ERROR);
+			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+		}
+	} else {
+		iov[1].iov_base = &t->bt_bval;
+		iov[1].iov_len = 1;
+
+		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+		while (status == RET_SUCCESS) {
+			iov[0].iov_base = data.data;
+			iov[0].iov_len = data.size;
+			if (writev(t->bt_rfd, iov, 2) != data.size + 1)
+				return (RET_ERROR);
+			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+		}
+	}
+
+	/* Restore the cursor. */
+	t->bt_cursor.rcursor = scursor;
+
+	if (status == RET_ERROR)
+		return (RET_ERROR);
+	if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
+		return (RET_ERROR);
+	if (ftruncate(t->bt_rfd, off))
+		return (RET_ERROR);
+	F_CLR(t, R_MODIFIED);
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_delete.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_delete.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_delete.c	(revision 273)
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_delete.c	8.7 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+static int rec_rdelete __P((BTREE *, recno_t));
+
+/*
+ * __REC_DELETE -- Delete the item(s) referenced by a key.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to delete
+ *	flags:	R_CURSOR if deleting what the cursor references
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_delete(dbp, key, flags)
+	const DB *dbp;
+	const DBT *key;
+	u_int flags;
+{
+	BTREE *t;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	switch(flags) {
+	case 0:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		if (nrec > t->bt_nrecs)
+			return (RET_SPECIAL);
+		--nrec;
+		status = rec_rdelete(t, nrec);
+		break;
+	case R_CURSOR:
+		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+			goto einval;
+		if (t->bt_nrecs == 0)
+			return (RET_SPECIAL);
+		status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
+		if (status == RET_SUCCESS)
+			--t->bt_cursor.rcursor;
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	if (status == RET_SUCCESS)
+		F_SET(t, B_MODIFIED | R_MODIFIED);
+	return (status);
+}
+
+/*
+ * REC_RDELETE -- Delete the data matching the specified key.
+ *
+ * Parameters:
+ *	tree:	tree
+ *	nrec:	record to delete
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+rec_rdelete(t, nrec)
+	BTREE *t;
+	recno_t nrec;
+{
+	EPG *e;
+	PAGE *h;
+	int status;
+
+	/* Find the record; __rec_search pins the page. */
+	if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
+		return (RET_ERROR);
+
+	/* Delete the record. */
+	h = e->page;
+	status = __rec_dleaf(t, h, e->index);
+	if (status != RET_SUCCESS) {
+		mpool_put(t->bt_mp, h, 0);
+		return (status);
+	}
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_DLEAF -- Delete a single record from a recno leaf page.
+ *
+ * Parameters:
+ *	t:	tree
+ *	index:	index on current page to delete
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_dleaf(t, h, index)
+	BTREE *t;
+	PAGE *h;
+	u_int32_t index;
+{
+	RLEAF *rl;
+	indx_t *ip, cnt, offset;
+	u_int32_t nbytes;
+	char *from;
+	void *to;
+
+	/*
+	 * Delete a record from a recno leaf page.  Internal records are never
+	 * deleted from internal pages, regardless of the records that caused
+	 * them to be added being deleted.  Pages made empty by deletion are
+	 * not reclaimed.  They are, however, made available for reuse.
+	 *
+	 * Pack the remaining entries at the end of the page, shift the indices
+	 * down, overwriting the deleted record and its index.  If the record
+	 * uses overflow pages, make them available for reuse.
+	 */
+	to = rl = GETRLEAF(h, index);
+	if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
+		return (RET_ERROR);
+	nbytes = NRLEAF(rl);
+
+	/*
+	 * Compress the key/data pairs.  Compress and adjust the [BR]LEAF
+	 * offsets.  Reset the headers.
+	 */
+	from = (char *)h + h->upper;
+	memmove(from + nbytes, from, (char *)to - from);
+	h->upper += nbytes;
+
+	offset = h->linp[index];
+	for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip)
+		if (ip[0] < offset)
+			ip[0] += nbytes;
+	for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
+		ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+	h->lower -= sizeof(indx_t);
+	--t->bt_nrecs;
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_get.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_get.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_get.c	(revision 273)
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_get.c	8.9 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key to find
+ *	data:	data to return
+ *	flag:	currently unused
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_get(dbp, key, data, flags)
+	const DB *dbp;
+	const DBT *key;
+	DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* Get currently doesn't take any flags, and keys of 0 are illegal. */
+	if (flags || (nrec = *(recno_t *)key->data) == 0) {
+		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * If we haven't seen this record yet, try to find it in the
+	 * original file.
+	 */
+	if (nrec > t->bt_nrecs) {
+		if (F_ISSET(t, R_EOF | R_INMEM))
+			return (RET_SPECIAL);
+		if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+			return (status);
+	}
+
+	--nrec;
+	if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	status = __rec_ret(t, e, 0, NULL, data);
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
+
+/*
+ * __REC_FPIPE -- Get fixed length records from a pipe.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fpipe(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	size_t len;
+	int ch;
+	u_char *p;
+
+	if (t->bt_rdata.size < t->bt_reclen) {
+		t->bt_rdata.data = t->bt_rdata.data == NULL ?
+		    malloc(t->bt_reclen) :
+		    realloc(t->bt_rdata.data, t->bt_reclen);
+		if (t->bt_rdata.data == NULL)
+			return (RET_ERROR);
+		t->bt_rdata.size = t->bt_reclen;
+	}
+	data.data = t->bt_rdata.data;
+	data.size = t->bt_reclen;
+
+	for (nrec = t->bt_nrecs; nrec < top;) {
+		len = t->bt_reclen;
+		for (p = t->bt_rdata.data;; *p++ = ch)
+			if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
+				if (ch != EOF)
+					*p = ch;
+				if (len != 0)
+					memset(p, t->bt_bval, len);
+				if (__rec_iput(t,
+				    nrec, &data, 0) != RET_SUCCESS)
+					return (RET_ERROR);
+				++nrec;
+				break;
+			}
+		if (ch == EOF)
+			break;
+	}
+	if (nrec < top) {
+		F_SET(t, R_EOF);
+		return (RET_SPECIAL);
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VPIPE -- Get variable length records from a pipe.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vpipe(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	indx_t len;
+	size_t sz;
+	int bval, ch;
+	u_char *p;
+
+	bval = t->bt_bval;
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		for (p = t->bt_rdata.data,
+		    sz = t->bt_rdata.size;; *p++ = ch, --sz) {
+			if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
+				data.data = t->bt_rdata.data;
+				data.size = p - (u_char *)t->bt_rdata.data;
+				if (ch == EOF && data.size == 0)
+					break;
+				if (__rec_iput(t, nrec, &data, 0)
+				    != RET_SUCCESS)
+					return (RET_ERROR);
+				break;
+			}
+			if (sz == 0) {
+				len = p - (u_char *)t->bt_rdata.data;
+				t->bt_rdata.size += (sz = 256);
+				t->bt_rdata.data = t->bt_rdata.data == NULL ?
+				    malloc(t->bt_rdata.size) :
+				    realloc(t->bt_rdata.data, t->bt_rdata.size);
+				if (t->bt_rdata.data == NULL)
+					return (RET_ERROR);
+				p = (u_char *)t->bt_rdata.data + len;
+			}
+		}
+		if (ch == EOF)
+			break;
+	}
+	if (nrec < top) {
+		F_SET(t, R_EOF);
+		return (RET_SPECIAL);
+	}
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_FMAP -- Get fixed length records from a file.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fmap(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	recno_t nrec;
+	u_char *sp, *ep, *p;
+	size_t len;
+
+	if (t->bt_rdata.size < t->bt_reclen) {
+		t->bt_rdata.data = t->bt_rdata.data == NULL ?
+		    malloc(t->bt_reclen) :
+		    realloc(t->bt_rdata.data, t->bt_reclen);
+		if (t->bt_rdata.data == NULL)
+			return (RET_ERROR);
+		t->bt_rdata.size = t->bt_reclen;
+	}
+	data.data = t->bt_rdata.data;
+	data.size = t->bt_reclen;
+
+	sp = (u_char *)t->bt_cmap;
+	ep = (u_char *)t->bt_emap;
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		if (sp >= ep) {
+			F_SET(t, R_EOF);
+			return (RET_SPECIAL);
+		}
+		len = t->bt_reclen;
+		for (p = t->bt_rdata.data;
+		    sp < ep && len > 0; *p++ = *sp++, --len);
+		if (len != 0)
+			memset(p, t->bt_bval, len);
+		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+			return (RET_ERROR);
+	}
+	t->bt_cmap = (caddr_t)sp;
+	return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VMAP -- Get variable length records from a file.
+ *
+ * Parameters:
+ *	t:	tree
+ *	cnt:	records to read
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vmap(t, top)
+	BTREE *t;
+	recno_t top;
+{
+	DBT data;
+	u_char *sp, *ep;
+	recno_t nrec;
+	int bval;
+
+	sp = (u_char *)t->bt_cmap;
+	ep = (u_char *)t->bt_emap;
+	bval = t->bt_bval;
+
+	for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+		if (sp >= ep) {
+			F_SET(t, R_EOF);
+			return (RET_SPECIAL);
+		}
+		for (data.data = sp; sp < ep && *sp != bval; ++sp);
+		data.size = sp - (u_char *)data.data;
+		if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+			return (RET_ERROR);
+		++sp;
+	}
+	t->bt_cmap = (caddr_t)sp;
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_open.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_open.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_open.c	(revision 273)
@@ -0,0 +1,241 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_open.c	8.10 (Berkeley) 9/1/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "recno.h"
+
+DB *
+__rec_open(fname, flags, mode, openinfo, dflags)
+	const char *fname;
+	int flags, mode, dflags;
+	const RECNOINFO *openinfo;
+{
+	BTREE *t;
+	BTREEINFO btopeninfo;
+	DB *dbp;
+	PAGE *h;
+	struct stat sb;
+	int rfd, sverrno;
+
+	/* Open the user's file -- if this fails, we're done. */
+	if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
+		return (NULL);
+
+	/* Create a btree in memory (backed by disk). */
+	dbp = NULL;
+	if (openinfo) {
+		if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
+			goto einval;
+		btopeninfo.flags = 0;
+		btopeninfo.cachesize = openinfo->cachesize;
+		btopeninfo.maxkeypage = 0;
+		btopeninfo.minkeypage = 0;
+		btopeninfo.psize = openinfo->psize;
+		btopeninfo.compare = NULL;
+		btopeninfo.prefix = NULL;
+		btopeninfo.lorder = openinfo->lorder;
+		dbp = __bt_open(openinfo->bfname,
+		    O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
+	} else
+		dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
+	if (dbp == NULL)
+		goto err;
+
+	/*
+	 * Some fields in the tree structure are recno specific.  Fill them
+	 * in and make the btree structure look like a recno structure.  We
+	 * don't change the bt_ovflsize value, it's close enough and slightly
+	 * bigger.
+	 */
+	t = dbp->internal;
+	if (openinfo) {
+		if (openinfo->flags & R_FIXEDLEN) {
+			F_SET(t, R_FIXLEN);
+			t->bt_reclen = openinfo->reclen;
+			if (t->bt_reclen == 0)
+				goto einval;
+		}
+		t->bt_bval = openinfo->bval;
+	} else
+		t->bt_bval = '\n';
+
+	F_SET(t, R_RECNO);
+	if (fname == NULL)
+		F_SET(t, R_EOF | R_INMEM);
+	else
+		t->bt_rfd = rfd;
+
+	if (fname != NULL) {
+		/*
+		 * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
+		 * Unfortunately, that's not portable, so we use lseek
+		 * and check the errno values.
+		 */
+		errno = 0;
+		if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
+			switch (flags & O_ACCMODE) {
+			case O_RDONLY:
+				F_SET(t, R_RDONLY);
+				break;
+			default:
+				goto einval;
+			}
+slow:			if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
+				goto err;
+			F_SET(t, R_CLOSEFP);
+			t->bt_irec =
+			    F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
+		} else {
+			switch (flags & O_ACCMODE) {
+			case O_RDONLY:
+				F_SET(t, R_RDONLY);
+				break;
+			case O_RDWR:
+				break;
+			default:
+				goto einval;
+			}
+
+			if (fstat(rfd, &sb))
+				goto err;
+			/*
+			 * Kluge -- we'd like to test to see if the file is too
+			 * big to mmap.  Since, we don't know what size or type
+			 * off_t's or size_t's are, what the largest unsigned
+			 * integral type is, or what random insanity the local
+			 * C compiler will perpetrate, doing the comparison in
+			 * a portable way is flatly impossible.  Hope that mmap
+			 * fails if the file is too large.
+			 */
+			if (sb.st_size == 0)
+				F_SET(t, R_EOF);
+			else {
+#ifdef MMAP_NOT_AVAILABLE
+				/*
+				 * XXX
+				 * Mmap doesn't work correctly on many current
+				 * systems.  In particular, it can fail subtly,
+				 * with cache coherency problems.  Don't use it
+				 * for now.
+				 */
+				t->bt_msize = sb.st_size;
+				if ((t->bt_smap = mmap(NULL, t->bt_msize,
+				    PROT_READ, MAP_PRIVATE, rfd,
+				    (off_t)0)) == (caddr_t)-1)
+					goto slow;
+				t->bt_cmap = t->bt_smap;
+				t->bt_emap = t->bt_smap + sb.st_size;
+				t->bt_irec = F_ISSET(t, R_FIXLEN) ?
+				    __rec_fmap : __rec_vmap;
+				F_SET(t, R_MEMMAPPED);
+#else
+				goto slow;
+#endif
+			}
+		}
+	}
+
+	/* Use the recno routines. */
+	dbp->close = __rec_close;
+	dbp->del = __rec_delete;
+	dbp->fd = __rec_fd;
+	dbp->get = __rec_get;
+	dbp->put = __rec_put;
+	dbp->seq = __rec_seq;
+	dbp->sync = __rec_sync;
+
+	/* If the root page was created, reset the flags. */
+	if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
+		goto err;
+	if ((h->flags & P_TYPE) == P_BLEAF) {
+		F_CLR(h, P_TYPE);
+		F_SET(h, P_RLEAF);
+		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+	} else
+		mpool_put(t->bt_mp, h, 0);
+
+	if (openinfo && openinfo->flags & R_SNAPSHOT &&
+	    !F_ISSET(t, R_EOF | R_INMEM) &&
+	    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+                goto err;
+	return (dbp);
+
+einval:	errno = EINVAL;
+err:	sverrno = errno;
+	if (dbp != NULL)
+		(void)__bt_close(dbp);
+	if (fname != NULL)
+		(void)close(rfd);
+	errno = sverrno;
+	return (NULL);
+}
+
+int
+__rec_fd(dbp)
+	const DB *dbp;
+{
+	BTREE *t;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/* In-memory database can't have a file descriptor. */
+	if (F_ISSET(t, R_INMEM)) {
+		errno = ENOENT;
+		return (-1);
+	}
+	return (t->bt_rfd);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_put.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_put.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_put.c	(revision 273)
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_put.c	8.7 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_PUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key
+ *	data:	data
+ *	flag:	R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
+ *	already in the tree and R_NOOVERWRITE specified.
+ */
+int
+__rec_put(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key;
+	const DBT *data;
+	u_int flags;
+{
+	BTREE *t;
+	DBT fdata, tdata;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	/*
+	 * If using fixed-length records, and the record is long, return
+	 * EINVAL.  If it's short, pad it out.  Use the record data return
+	 * memory, it's only short-term.
+	 */
+	if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
+		if (data->size > t->bt_reclen)
+			goto einval;
+
+		if (t->bt_rdata.size < t->bt_reclen) {
+			t->bt_rdata.data = t->bt_rdata.data == NULL ?
+			    malloc(t->bt_reclen) :
+			    realloc(t->bt_rdata.data, t->bt_reclen);
+			if (t->bt_rdata.data == NULL)
+				return (RET_ERROR);
+			t->bt_rdata.size = t->bt_reclen;
+		}
+		memmove(t->bt_rdata.data, data->data, data->size);
+		memset((char *)t->bt_rdata.data + data->size,
+		    t->bt_bval, t->bt_reclen - data->size);
+		fdata.data = t->bt_rdata.data;
+		fdata.size = t->bt_reclen;
+	} else {
+		fdata.data = data->data;
+		fdata.size = data->size;
+	}
+
+	switch (flags) {
+	case R_CURSOR:
+		if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+			goto einval;
+		nrec = t->bt_cursor.rcursor;
+		break;
+	case R_SETCURSOR:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_IAFTER:
+		if ((nrec = *(recno_t *)key->data) == 0) {
+			nrec = 1;
+			flags = R_IBEFORE;
+		}
+		break;
+	case 0:
+	case R_IBEFORE:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_NOOVERWRITE:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		if (nrec <= t->bt_nrecs)
+			return (RET_SPECIAL);
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+
+	/*
+	 * Make sure that records up to and including the put record are
+	 * already in the database.  If skipping records, create empty ones.
+	 */
+	if (nrec > t->bt_nrecs) {
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    t->bt_irec(t, nrec) == RET_ERROR)
+			return (RET_ERROR);
+		if (nrec > t->bt_nrecs + 1) {
+			if (F_ISSET(t, R_FIXLEN)) {
+				if ((tdata.data =
+				    (void *)malloc(t->bt_reclen)) == NULL)
+					return (RET_ERROR);
+				tdata.size = t->bt_reclen;
+				memset(tdata.data, t->bt_bval, tdata.size);
+			} else {
+				tdata.data = NULL;
+				tdata.size = 0;
+			}
+			while (nrec > t->bt_nrecs + 1)
+				if (__rec_iput(t,
+				    t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
+					return (RET_ERROR);
+			if (F_ISSET(t, R_FIXLEN))
+				free(tdata.data);
+		}
+	}
+
+	if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
+		return (status);
+
+	if (flags == R_SETCURSOR)
+		t->bt_cursor.rcursor = nrec;
+	
+	F_SET(t, R_MODIFIED);
+	return (__rec_ret(t, NULL, nrec, key, NULL));
+}
+
+/*
+ * __REC_IPUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ *	t:	tree
+ *	nrec:	record number
+ *	data:	data
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_iput(t, nrec, data, flags)
+	BTREE *t;
+	recno_t nrec;
+	const DBT *data;
+	u_int flags;
+{
+	DBT tdata;
+	EPG *e;
+	PAGE *h;
+	indx_t index, nxtindex;
+	pgno_t pg;
+	u_int32_t nbytes;
+	int dflags, status;
+	char *dest, db[NOVFLSIZE];
+
+	/*
+	 * If the data won't fit on a page, store it on indirect pages.
+	 *
+	 * XXX
+	 * If the insert fails later on, these pages aren't recovered.
+	 */
+	if (data->size > t->bt_ovflsize) {
+		if (__ovfl_put(t, data, &pg) == RET_ERROR)
+			return (RET_ERROR);
+		tdata.data = db;
+		tdata.size = NOVFLSIZE;
+		*(pgno_t *)db = pg;
+		*(u_int32_t *)(db + sizeof(pgno_t)) = data->size;
+		dflags = P_BIGDATA;
+		data = &tdata;
+	} else
+		dflags = 0;
+
+	/* __rec_search pins the returned page. */
+	if ((e = __rec_search(t, nrec,
+	    nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
+	    SINSERT : SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	h = e->page;
+	index = e->index;
+
+	/*
+	 * Add the specified key/data pair to the tree.  The R_IAFTER and
+	 * R_IBEFORE flags insert the key after/before the specified key.
+	 *
+	 * Pages are split as required.
+	 */
+	switch (flags) {
+	case R_IAFTER:
+		++index;
+		break;
+	case R_IBEFORE:
+		break;
+	default:
+		if (nrec < t->bt_nrecs &&
+		    __rec_dleaf(t, h, index) == RET_ERROR) {
+			mpool_put(t->bt_mp, h, 0);
+			return (RET_ERROR);
+		}
+		break;
+	}
+
+	/*
+	 * If not enough room, split the page.  The split code will insert
+	 * the key and data and unpin the current page.  If inserting into
+	 * the offset array, shift the pointers up.
+	 */
+	nbytes = NRLEAFDBT(data->size);
+	if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+		status = __bt_split(t, h, NULL, data, dflags, nbytes, index);
+		if (status == RET_SUCCESS)
+			++t->bt_nrecs;
+		return (status);
+	}
+
+	if (index < (nxtindex = NEXTINDEX(h)))
+		memmove(h->linp + index + 1, h->linp + index,
+		    (nxtindex - index) * sizeof(indx_t));
+	h->lower += sizeof(indx_t);
+
+	h->linp[index] = h->upper -= nbytes;
+	dest = (char *)h + h->upper;
+	WR_RLEAF(dest, data, dflags);
+
+	++t->bt_nrecs;
+	F_SET(t, B_MODIFIED);
+	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_search.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_search.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_search.c	(revision 273)
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_search.c	8.4 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEARCH -- Search a btree for a key.
+ *
+ * Parameters:
+ *	t:	tree to search
+ *	recno:	key to find
+ *	op: 	search operation
+ *
+ * Returns:
+ *	EPG for matching record, if any, or the EPG for the location of the
+ *	key, if it were inserted into the tree.
+ *
+ * Returns:
+ *	The EPG for matching record, if any, or the EPG for the location
+ *	of the key, if it were inserted into the tree, is entered into
+ *	the bt_cur field of the tree.  A pointer to the field is returned.
+ */
+EPG *
+__rec_search(t, recno, op)
+	BTREE *t;
+	recno_t recno;
+	enum SRCHOP op;
+{
+	register indx_t index;
+	register PAGE *h;
+	EPGNO *parent;
+	RINTERNAL *r;
+	pgno_t pg;
+	indx_t top;
+	recno_t total;
+	int sverrno;
+
+	BT_CLR(t);
+	for (pg = P_ROOT, total = 0;;) {
+		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+			goto err;
+		if (h->flags & P_RLEAF) {
+			t->bt_cur.page = h;
+			t->bt_cur.index = recno - total;
+			return (&t->bt_cur);
+		}
+		for (index = 0, top = NEXTINDEX(h);;) {
+			r = GETRINTERNAL(h, index);
+			if (++index == top || total + r->nrecs > recno)
+				break;
+			total += r->nrecs;
+		}
+
+		BT_PUSH(t, pg, index - 1);
+		
+		pg = r->pgno;
+		switch (op) {
+		case SDELETE:
+			--GETRINTERNAL(h, (index - 1))->nrecs;
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		case SINSERT:
+			++GETRINTERNAL(h, (index - 1))->nrecs;
+			mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+			break;
+		case SEARCH:
+			mpool_put(t->bt_mp, h, 0);
+			break;
+		}
+
+	}
+	/* Try and recover the tree. */
+err:	sverrno = errno;
+	if (op != SEARCH)
+		while  ((parent = BT_POP(t)) != NULL) {
+			if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+				break;
+			if (op == SINSERT)
+				--GETRINTERNAL(h, parent->index)->nrecs;
+			else
+				++GETRINTERNAL(h, parent->index)->nrecs;
+                        mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+                }
+	errno = sverrno;
+	return (NULL);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_seq.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_seq.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_seq.c	(revision 273)
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)rec_seq.c	8.3 (Berkeley) 7/14/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEQ -- Recno sequential scan interface.
+ *
+ * Parameters:
+ *	dbp:	pointer to access method
+ *	key:	key for positioning and return value
+ *	data:	data return value
+ *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__rec_seq(dbp, key, data, flags)
+	const DB *dbp;
+	DBT *key, *data;
+	u_int flags;
+{
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	int status;
+
+	t = dbp->internal;
+
+	/* Toss any page pinned across calls. */
+	if (t->bt_pinned != NULL) {
+		mpool_put(t->bt_mp, t->bt_pinned, 0);
+		t->bt_pinned = NULL;
+	}
+
+	switch(flags) {
+	case R_CURSOR:
+		if ((nrec = *(recno_t *)key->data) == 0)
+			goto einval;
+		break;
+	case R_NEXT:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			nrec = t->bt_cursor.rcursor + 1;
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_FIRST:
+		nrec = 1;
+		break;
+	case R_PREV:
+		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+			if ((nrec = t->bt_cursor.rcursor - 1) == 0)
+				return (RET_SPECIAL);
+			break;
+		}
+		/* FALLTHROUGH */
+	case R_LAST:
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+			return (RET_ERROR);
+		nrec = t->bt_nrecs;
+		break;
+	default:
+einval:		errno = EINVAL;
+		return (RET_ERROR);
+	}
+	
+	if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
+		if (!F_ISSET(t, R_EOF | R_INMEM) &&
+		    (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+			return (status);
+		if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
+			return (RET_SPECIAL);
+	}
+
+	if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
+		return (RET_ERROR);
+
+	F_SET(&t->bt_cursor, CURS_INIT);
+	t->bt_cursor.rcursor = nrec;
+
+	status = __rec_ret(t, e, nrec, key, data);
+	if (F_ISSET(t, B_DB_LOCK))
+		mpool_put(t->bt_mp, e->page, 0);
+	else
+		t->bt_pinned = e->page;
+	return (status);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/rec_utils.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/rec_utils.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/rec_utils.c	(revision 273)
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_utils.c	8.6 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __rec_ret --
+ *	Build return data.
+ *
+ * Parameters:
+ *	t:	tree
+ *	e:	key/data pair to be returned
+ *   nrec:	record number
+ *    key:	user's key structure
+ *	data:	user's data structure
+ *
+ * Returns:
+ *	RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_ret(t, e, nrec, key, data)
+	BTREE *t;
+	EPG *e;
+	recno_t nrec;
+	DBT *key, *data;
+{
+	RLEAF *rl;
+	void *p;
+
+	if (key == NULL)
+		goto dataonly;
+
+	/* We have to copy the key, it's not on the page. */
+	if (sizeof(recno_t) > t->bt_rkey.size) {
+		p = (void *)(t->bt_rkey.data == NULL ?
+		    malloc(sizeof(recno_t)) :
+		    realloc(t->bt_rkey.data, sizeof(recno_t)));
+		if (p == NULL)
+			return (RET_ERROR);
+		t->bt_rkey.data = p;
+		t->bt_rkey.size = sizeof(recno_t);
+	}
+	memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
+	key->size = sizeof(recno_t);
+	key->data = t->bt_rkey.data;
+
+dataonly:
+	if (data == NULL)
+		return (RET_SUCCESS);
+
+	/*
+	 * We must copy big keys/data to make them contigous.  Otherwise,
+	 * leave the page pinned and don't copy unless the user specified
+	 * concurrent access.
+	 */
+	rl = GETRLEAF(e->page, e->index);
+	if (rl->flags & P_BIGDATA) {
+		if (__ovfl_get(t, rl->bytes,
+		    &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
+			return (RET_ERROR);
+		data->data = t->bt_rdata.data;
+	} else if (F_ISSET(t, B_DB_LOCK)) {
+		/* Use +1 in case the first record retrieved is 0 length. */
+		if (rl->dsize + 1 > t->bt_rdata.size) {
+			p = (void *)(t->bt_rdata.data == NULL ?
+			    malloc(rl->dsize + 1) :
+			    realloc(t->bt_rdata.data, rl->dsize + 1));
+			if (p == NULL)
+				return (RET_ERROR);
+			t->bt_rdata.data = p;
+			t->bt_rdata.size = rl->dsize + 1;
+		}
+		memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
+		data->size = rl->dsize;
+		data->data = t->bt_rdata.data;
+	} else {
+		data->size = rl->dsize;
+		data->data = rl->bytes;
+	}
+	return (RET_SUCCESS);
+}
Index: /branches/EMX/src/emx/bsd/db/recno/recno.h
===================================================================
--- /branches/EMX/src/emx/bsd/db/recno/recno.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/recno/recno.h	(revision 273)
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)recno.h	8.1 (Berkeley) 6/4/93
+ */
+
+enum SRCHOP { SDELETE, SINSERT, SEARCH};	/* Rec_search operation. */
+
+#include "../btree/btree.h"
+#include "extern.h"
Index: /branches/EMX/src/emx/bsd/db/sub.cmd
===================================================================
--- /branches/EMX/src/emx/bsd/db/sub.cmd	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/sub.cmd	(revision 273)
@@ -0,0 +1,19 @@
+/* sub.cmd */
+
+parse arg prog
+'@echo off'
+call sub1 'emx'
+call sub1 'btree'
+call sub1 'db'
+call sub1 'hash'
+call sub1 'mpool'
+call sub1 'recno'
+exit
+
+sub1:
+  parse arg dir
+  'cd '||dir
+  say dir
+  prog
+  'cd ..'
+  return
Index: /branches/EMX/src/emx/bsd/db/test/README
===================================================================
--- /branches/EMX/src/emx/bsd/db/test/README	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/test/README	(revision 273)
@@ -0,0 +1,74 @@
+#	@(#)README	8.8 (Berkeley) 7/31/94
+
+To build this portably, try something like:
+
+    make PORTDIR="../PORT/MACH"
+
+where MACH is the machine, i.e. "sunos.4.1.1".
+
+To run the tests, enter "sh run.test".  If your system dictionary isn't
+in /usr/share/dict/words, edit run.test to reflect the correct place.
+
+Fairly large files (the command files) are built in this directory during
+the test runs, and even larger files (the database files) are created in
+"/var/tmp".  If the latter directory doesn't exist, set the environmental
+variable TMPDIR to a directory where the files can be built.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+The script file consists of lines with an initial character which is
+the command for that line, or an initial character indicating a key
+or data entry for a previous command.
+
+Legal command characters are as follows:
+
+c: compare a record
+	+ must be followed by [kK][dD]; the data value in the database
+	  associated with the specified key is compared to the specified
+	  data value.
+e: echo a string
+	+ writes out the rest of the line into the output file; if the
+	  last character is not a carriage-return, a newline is appended.
+f: set the flags for the next command
+	+ no value zero's the flags
+g: do a get command
+	+ must be followed by [kK]
+	+ writes out the retrieved data DBT.
+o [r]: dump [reverse]
+	+ dump the database out, if 'r' is set, in reverse order.
+p: do a put command
+	+ must be followed by [kK][dD]
+r: do a del command
+	+ must be followed by [kK] unless R_CURSOR flag set.
+S: sync the database
+s: do a seq command
+	+ must be followed by [kK] if R_CURSOR flag set.
+	+ writes out the retrieved data DBT.
+
+Legal key/data characters are as follows:
+
+D [file]: data file
+	+ set the current data value to the contents of the file
+d [data]:
+	+ set the current key value to the contents of the line.
+K [file]: key file
+	+ set the current key value to the contents of the file
+k [data]:
+	+ set the current key value to the contents of the line.
+
+Blank lines, lines with leading white space, and lines with leading
+hash marks (#) are ignored.
+
+Options to dbtest are as follows:
+
+	-d: Set the DB_LOCK flag.
+	-f: Use the file argument as the database file.
+	-i: Use the rest of the argument to set elements in the info
+	    structure.  If the type is btree, then "-i cachesize=10240"
+	    will set BTREEINFO.cachesize to 10240.
+	-o: The rest of the argument is the output file instead of
+	    using stdout.
+	-s: Don't delete the database file before opening it, i.e.
+	    use the database file from a previous run.
+
+Dbtest requires two arguments, the type of access "hash", "recno"
+or "btree", and the script name or "-" to indicate stdin.
Index: /branches/EMX/src/emx/bsd/db/test/dbtest.c
===================================================================
--- /branches/EMX/src/emx/bsd/db/test/dbtest.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/test/dbtest.c	(revision 273)
@@ -0,0 +1,783 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)dbtest.c	8.17 (Berkeley) 9/1/94";
+#endif /* not lint */
+
+#ifdef __EMX__
+#include <sys/types.h>
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif /* __EMX__ */
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
+
+void	 compare __P((DBT *, DBT *));
+DBTYPE	 dbtype __P((char *));
+void	 dump __P((DB *, int));
+void	 err __P((const char *, ...));
+void	 get __P((DB *, DBT *));
+void	 getdata __P((DB *, DBT *, DBT *));
+void	 put __P((DB *, DBT *, DBT *));
+void	 rem __P((DB *, DBT *));
+char	*sflags __P((int));
+void	 synk __P((DB *));
+void	*rfile __P((char *, size_t *));
+void	 seq __P((DB *, DBT *));
+u_int	 setflags __P((char *));
+void	*setinfo __P((DBTYPE, char *));
+void	 usage __P((void));
+void	*xmalloc __P((char *, size_t));
+
+DBTYPE type;				/* Database type. */
+void *infop;				/* Iflags. */
+u_long lineno;				/* Current line in test script. */
+u_int flags;				/* Current DB flags. */
+int ofd = STDOUT_FILENO;		/* Standard output fd. */
+
+DB *XXdbp;				/* Global for gdb. */
+int XXlineno;				/* Fast breakpoint for gdb. */
+
+#ifdef __EMX__
+int binary = 0;
+#endif /* __EMX__ */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern int optind;
+	extern char *optarg;
+	enum S command, state;
+	DB *dbp;
+	DBT data, key, keydata;
+	size_t len;
+	int ch, oflags, sflag;
+	char *fname, *infoarg, *p, *t, buf[8 * 1024];
+
+	infoarg = NULL;
+	fname = NULL;
+	oflags = O_CREAT | O_RDWR;
+	sflag = 0;
+#ifdef __EMX__
+	while ((ch = getopt(argc, argv, "f:i:lo:sB")) != EOF)
+#else /* not __EMX__ */
+	while ((ch = getopt(argc, argv, "f:i:lo:s")) != EOF)
+#endif /* not __EMX__ */
+		switch (ch) {
+		case 'f':
+			fname = optarg;
+			break;
+		case 'i':
+			infoarg = optarg;
+			break;
+		case 'l':
+			oflags |= DB_LOCK;
+			break;
+		case 'o':
+			if ((ofd = open(optarg,
+			    O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+				err("%s: %s", optarg, strerror(errno));
+			break;
+		case 's':
+			sflag = 1;
+			break;
+#ifdef __EMX__
+		case 'B':
+			binary = 1;
+			break;
+#endif /* __EMX__ */
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 2)
+		usage();
+
+#ifdef __EMX__
+	if (binary)
+		setmode (ofd, O_BINARY);
+#endif /* __EMX__ */
+
+	/* Set the type. */
+	type = dbtype(*argv++);
+
+	/* Open the descriptor file. */
+        if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
+	    err("%s: %s", *argv, strerror(errno));
+
+	/* Set up the db structure as necessary. */
+	if (infoarg == NULL)
+		infop = NULL;
+	else
+		for (p = strtok(infoarg, ",\t "); p != NULL;
+		    p = strtok(0, ",\t "))
+			if (*p != '\0')
+				infop = setinfo(type, p);
+
+	/*
+	 * Open the DB.  Delete any preexisting copy, you almost never
+	 * want it around, and it often screws up tests.
+	 */
+	if (fname == NULL) {
+#ifdef __EMX__
+		strcpy (buf, "__dbtest");
+#else /* not __EMX__ */
+		p = getenv("TMPDIR");
+		if (p == NULL)
+			p = "/var/tmp";
+		(void)sprintf(buf, "%s/__dbtest", p);
+#endif /* not __EMX__ */
+		fname = buf;
+		(void)unlink(buf);
+	} else  if (!sflag)
+		(void)unlink(fname);
+
+	if ((dbp = dbopen(fname,
+	    oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
+		err("dbopen: %s", strerror(errno));
+	XXdbp = dbp;
+
+	state = COMMAND;
+	for (lineno = 1;
+	    (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
+		/* Delete the newline, displaying the key/data is easier. */
+		if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
+			*t = '\0';
+		if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#')
+			continue;
+
+		/* Convenient gdb break point. */
+		if (XXlineno == lineno)
+			XXlineno = 1;
+		switch (*p) {
+		case 'c':			/* compare */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = COMPARE;
+			break;
+		case 'e':			/* echo */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			/* Don't display the newline, if CR at EOL. */
+			if (p[len - 2] == '\r')
+				--len;
+			if (write(ofd, p + 1, len - 1) != len - 1 ||
+			    write(ofd, "\n", 1) != 1)
+				err("write: %s", strerror(errno));
+			break;
+		case 'g':			/* get */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = GET;
+			break;
+		case 'p':			/* put */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			state = KEY;
+			command = PUT;
+			break;
+		case 'r':			/* remove */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+                        if (flags == R_CURSOR) {
+				rem(dbp, &key);
+				state = COMMAND;
+                        } else {
+				state = KEY;
+				command = REMOVE;
+			}
+			break;
+		case 'S':			/* sync */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			synk(dbp);
+			state = COMMAND;
+			break;
+		case 's':			/* seq */
+			if (state != COMMAND)
+				err("line %lu: not expecting command", lineno);
+			if (flags == R_CURSOR) {
+				state = KEY;
+				command = SEQ;
+			} else
+				seq(dbp, &key);
+			break;
+		case 'f':
+			flags = setflags(p + 1);
+			break;
+		case 'D':			/* data file */
+			if (state != DATA)
+				err("line %lu: not expecting data", lineno);
+			data.data = rfile(p + 1, &data.size);
+			goto ldata;
+		case 'd':			/* data */
+			if (state != DATA)
+				err("line %lu: not expecting data", lineno);
+			data.data = xmalloc(p + 1, len - 1);
+			data.size = len - 1;
+ldata:			switch (command) {
+			case COMPARE:
+				compare(&keydata, &data);
+				break;
+			case PUT:
+				put(dbp, &key, &data);
+				break;
+			default:
+				err("line %lu: command doesn't take data",
+				    lineno);
+			}
+			if (type != DB_RECNO)
+				free(key.data);
+			free(data.data);
+			state = COMMAND;
+			break;
+		case 'K':			/* key file */
+			if (state != KEY)
+				err("line %lu: not expecting a key", lineno);
+			if (type == DB_RECNO)
+				err("line %lu: 'K' not available for recno",
+				    lineno);
+			key.data = rfile(p + 1, &key.size);
+			goto lkey;
+		case 'k':			/* key */
+			if (state != KEY)
+				err("line %lu: not expecting a key", lineno);
+			if (type == DB_RECNO) {
+				static recno_t recno;
+				recno = atoi(p + 1);
+				key.data = &recno;
+				key.size = sizeof(recno);
+			} else {
+				key.data = xmalloc(p + 1, len - 1);
+				key.size = len - 1;
+			}
+lkey:			switch (command) {
+			case COMPARE:
+				getdata(dbp, &key, &keydata);
+				state = DATA;
+				break;
+			case GET:
+				get(dbp, &key);
+				if (type != DB_RECNO)
+					free(key.data);
+				state = COMMAND;
+				break;
+			case PUT:
+				state = DATA;
+				break;
+			case REMOVE:
+				rem(dbp, &key);
+				if ((type != DB_RECNO) && (flags != R_CURSOR))
+					free(key.data);
+				state = COMMAND;
+				break;
+			case SEQ:
+				seq(dbp, &key);
+				if ((type != DB_RECNO) && (flags != R_CURSOR))
+					free(key.data);
+				state = COMMAND;
+				break;
+			default:
+				err("line %lu: command doesn't take a key",
+				    lineno);
+			}
+			break;
+		case 'o':
+			dump(dbp, p[1] == 'r');
+			break;
+		default:
+			err("line %lu: %s: unknown command character",
+			    lineno, p);
+		}
+	}
+#ifdef STATISTICS
+	/*
+	 * -l must be used (DB_LOCK must be set) for this to be
+	 * used, otherwise a page will be locked and it will fail.
+	 */
+	if (type == DB_BTREE && oflags & DB_LOCK)
+		__bt_stat(dbp);
+#endif
+	if (dbp->close(dbp))
+		err("db->close: %s", strerror(errno));
+	(void)close(ofd);
+	exit(0);
+}
+
+#define	NOOVERWRITE	"put failed, would overwrite key\n"
+
+void
+compare(db1, db2)
+	DBT *db1, *db2;
+{
+	register size_t len;
+	register u_char *p1, *p2;
+
+	if (db1->size != db2->size)
+		printf("compare failed: key->data len %lu != data len %lu\n",
+		    db1->size, db2->size);
+
+	len = MIN(db1->size, db2->size);
+	for (p1 = db1->data, p2 = db2->data; len--;)
+		if (*p1++ != *p2++) {
+			printf("compare failed at offset %d\n",
+			    p1 - (u_char *)db1->data);
+			break;
+		}
+}
+
+void
+get(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	DBT data;
+
+	switch (dbp->get(dbp, kp, &data, flags)) {
+	case 0:
+		(void)write(ofd, data.data, data.size);
+		if (ofd == STDOUT_FILENO)
+			(void)write(ofd, "\n", 1);
+		break;
+	case -1:
+		err("line %lu: get: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"get failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else
+			(void)fprintf(stderr, "%d: %.*s: %s",
+			    lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+getdata(dbp, kp, dp)
+	DB *dbp;
+	DBT *kp, *dp;
+{
+	switch (dbp->get(dbp, kp, dp, flags)) {
+	case 0:
+		return;
+	case -1:
+		err("line %lu: getdata: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+		err("line %lu: getdata failed, no such key", lineno);
+		/* NOTREACHED */
+	}
+}
+
+void
+put(dbp, kp, dp)
+	DB *dbp;
+	DBT *kp, *dp;
+{
+	switch (dbp->put(dbp, kp, dp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: put: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+		(void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
+		break;
+	}
+}
+
+void
+rem(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	switch (dbp->del(dbp, kp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: rem: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"rem failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else if (flags != R_CURSOR)
+			(void)fprintf(stderr, "%d: %.*s: %s", 
+			    lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+		else
+			(void)fprintf(stderr,
+			    "%d: rem of cursor failed\n", lineno);
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+synk(dbp)
+	DB *dbp;
+{
+	switch (dbp->sync(dbp, flags)) {
+	case 0:
+		break;
+	case -1:
+		err("line %lu: synk: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	}
+}
+
+void
+seq(dbp, kp)
+	DB *dbp;
+	DBT *kp;
+{
+	DBT data;
+
+	switch (dbp->seq(dbp, kp, &data, flags)) {
+	case 0:
+		(void)write(ofd, data.data, data.size);
+		if (ofd == STDOUT_FILENO)
+			(void)write(ofd, "\n", 1);
+		break;
+	case -1:
+		err("line %lu: seq: %s", lineno, strerror(errno));
+		/* NOTREACHED */
+	case 1:
+#define	NOSUCHKEY	"seq failed, no such key\n"
+		if (ofd != STDOUT_FILENO)
+			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+		else if (flags == R_CURSOR)
+			(void)fprintf(stderr, "%d: %.*s: %s", 
+			    lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+		else
+			(void)fprintf(stderr,
+			    "%d: seq (%s) failed\n", lineno, sflags(flags));
+#undef	NOSUCHKEY
+		break;
+	}
+}
+
+void
+dump(dbp, rev)
+	DB *dbp;
+	int rev;
+{
+	DBT key, data;
+	int flags, nflags;
+
+	if (rev) {
+		flags = R_LAST;
+		nflags = R_PREV;
+	} else {
+		flags = R_FIRST;
+		nflags = R_NEXT;
+	}
+	for (;; flags = nflags)
+		switch (dbp->seq(dbp, &key, &data, flags)) {
+		case 0:
+			(void)write(ofd, data.data, data.size);
+			if (ofd == STDOUT_FILENO)
+				(void)write(ofd, "\n", 1);
+			break;
+		case 1:
+			goto done;
+		case -1:
+			err("line %lu: (dump) seq: %s",
+			    lineno, strerror(errno));
+			/* NOTREACHED */
+		}
+done:	return;
+}
+	
+u_int
+setflags(s)
+	char *s;
+{
+	char *p, *index();
+
+	for (; isspace(*s); ++s);
+	if (*s == '\n' || *s == '\0')
+		return (0);
+	if ((p = index(s, '\n')) != NULL)
+		*p = '\0';
+	if (!strcmp(s, "R_CURSOR"))		return (R_CURSOR);
+	if (!strcmp(s, "R_FIRST"))		return (R_FIRST);
+	if (!strcmp(s, "R_IAFTER")) 		return (R_IAFTER);
+	if (!strcmp(s, "R_IBEFORE")) 		return (R_IBEFORE);
+	if (!strcmp(s, "R_LAST")) 		return (R_LAST);
+	if (!strcmp(s, "R_NEXT")) 		return (R_NEXT);
+	if (!strcmp(s, "R_NOOVERWRITE"))	return (R_NOOVERWRITE);
+	if (!strcmp(s, "R_PREV"))		return (R_PREV);
+	if (!strcmp(s, "R_SETCURSOR"))		return (R_SETCURSOR);
+
+	err("line %lu: %s: unknown flag", lineno, s);
+	/* NOTREACHED */
+}
+
+char *
+sflags(flags)
+	int flags;
+{
+	switch (flags) {
+	case R_CURSOR:		return ("R_CURSOR");
+	case R_FIRST:		return ("R_FIRST");
+	case R_IAFTER:		return ("R_IAFTER");
+	case R_IBEFORE:		return ("R_IBEFORE");
+	case R_LAST:		return ("R_LAST");
+	case R_NEXT:		return ("R_NEXT");
+	case R_NOOVERWRITE:	return ("R_NOOVERWRITE");
+	case R_PREV:		return ("R_PREV");
+	case R_SETCURSOR:	return ("R_SETCURSOR");
+	}
+
+	return ("UNKNOWN!");
+}
+	
+DBTYPE
+dbtype(s)
+	char *s;
+{
+	if (!strcmp(s, "btree"))
+		return (DB_BTREE);
+	if (!strcmp(s, "hash"))
+		return (DB_HASH);
+	if (!strcmp(s, "recno"))
+		return (DB_RECNO);
+	err("%s: unknown type (use btree, hash or recno)", s);
+	/* NOTREACHED */
+}
+
+void *
+setinfo(type, s)
+	DBTYPE type;
+	char *s;
+{
+	static BTREEINFO ib;
+	static HASHINFO ih;
+	static RECNOINFO rh;
+	char *eq, *index();
+
+	if ((eq = index(s, '=')) == NULL)
+		err("%s: illegal structure set statement", s);
+	*eq++ = '\0';
+	if (!isdigit(*eq))
+		err("%s: structure set statement must be a number", s);
+		
+	switch (type) {
+	case DB_BTREE:
+		if (!strcmp("flags", s)) {
+			ib.flags = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("cachesize", s)) {
+			ib.cachesize = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("maxkeypage", s)) {
+			ib.maxkeypage = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("minkeypage", s)) {
+			ib.minkeypage = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("lorder", s)) {
+			ib.lorder = atoi(eq);
+			return (&ib);
+		}
+		if (!strcmp("psize", s)) {
+			ib.psize = atoi(eq);
+			return (&ib);
+		}
+		break;
+	case DB_HASH:
+		if (!strcmp("bsize", s)) {
+			ih.bsize = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("ffactor", s)) {
+			ih.ffactor = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("nelem", s)) {
+			ih.nelem = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("cachesize", s)) {
+			ih.cachesize = atoi(eq);
+			return (&ih);
+		}
+		if (!strcmp("lorder", s)) {
+			ih.lorder = atoi(eq);
+			return (&ih);
+		}
+		break;
+	case DB_RECNO:
+		if (!strcmp("flags", s)) {
+			rh.flags = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("cachesize", s)) {
+			rh.cachesize = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("lorder", s)) {
+			rh.lorder = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("reclen", s)) {
+			rh.reclen = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("bval", s)) {
+			rh.bval = atoi(eq);
+			return (&rh);
+		}
+		if (!strcmp("psize", s)) {
+			rh.psize = atoi(eq);
+			return (&rh);
+		}
+		break;
+	}
+	err("%s: unknown structure value", s);
+	/* NOTREACHED */
+}
+
+void *
+rfile(name, lenp)
+	char *name;
+	size_t *lenp;
+{
+	struct stat sb;
+	void *p;
+	int fd;
+	char *np, *index();
+
+	for (; isspace(*name); ++name);
+	if ((np = index(name, '\n')) != NULL)
+		*np = '\0';
+	if ((fd = open(name, O_RDONLY, 0)) < 0 ||
+	    fstat(fd, &sb))
+		err("%s: %s\n", name, strerror(errno));
+#ifdef __EMX__
+	if (binary)
+		setmode (fd, O_BINARY);
+#endif /* __EMX__ */
+#ifdef NOT_PORTABLE
+	if (sb.st_size > (off_t)SIZE_T_MAX)
+		err("%s: %s\n", name, strerror(E2BIG));
+#endif
+	if ((p = (void *)malloc((u_int)sb.st_size)) == NULL)
+		err("%s", strerror(errno));
+	(void)read(fd, p, (int)sb.st_size);
+	*lenp = sb.st_size;
+	(void)close(fd);
+	return (p);
+}
+
+void *
+xmalloc(text, len)
+	char *text;
+	size_t len;
+{
+	void *p;
+
+	if ((p = (void *)malloc(len)) == NULL)
+		err("%s", strerror(errno));
+	memmove(p, text, len);
+	return (p);
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n");
+	exit(1);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+	char *fmt;
+        va_dcl
+#endif
+{
+	va_list ap;
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	(void)fprintf(stderr, "dbtest: ");
+	(void)vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	(void)fprintf(stderr, "\n");
+	exit(1);
+	/* NOTREACHED */
+}
Index: /branches/EMX/src/emx/bsd/db/test/run.test
===================================================================
--- /branches/EMX/src/emx/bsd/db/test/run.test	(revision 273)
+++ /branches/EMX/src/emx/bsd/db/test/run.test	(revision 273)
@@ -0,0 +1,705 @@
+#!/bin/sh -
+#
+#	@(#)run.test	8.10 (Berkeley) 7/26/94
+#
+
+# db regression tests
+main()
+{
+
+	PROG=./dbtest
+	TMP1=t1
+	TMP2=t2
+	TMP3=t3
+
+	if [ -f /usr/share/dict/words ]; then
+		DICT=/usr/share/dict/words
+	elif [ -f /usr/dict/words ]; then
+		DICT=/usr/dict/words
+	else
+		echo 'run.test: no dictionary'
+		exit 1
+	fi
+	
+	if [ $# -eq 0 ]; then
+		for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
+			test$t
+		done
+	else
+		while [ $# -gt 0 ]
+			do case "$1" in
+			test*)
+				$1;;
+			[0-9]*)
+				test$1;;
+			btree)
+				for t in 1 2 3 7 8 9 10 12 13; do
+					test$t
+				done;;
+			hash)
+				for t in 1 2 3 8 13 20; do
+					test$t
+				done;;
+			recno)
+				for t in 1 2 3 4 5 6 7 10 11; do
+					test$t
+				done;;
+			*)
+				echo "run.test: unknown test $1"
+				echo "usage: run.test test# | type"
+				exit 1
+			esac
+			shift
+		done
+	fi
+	rm -f $TMP1 $TMP2 $TMP3
+	exit 0
+}
+
+# Take the first hundred entries in the dictionary, and make them
+# be key/data pairs.
+test1()
+{
+	echo "Test 1: btree, hash: small key, small data pairs"
+	sed 200q $DICT > $TMP1
+	for type in btree hash; do
+		rm -f $TMP2 $TMP3
+		for i in `sed 200q $DICT`; do
+			echo p
+			echo k$i
+			echo d$i
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test1: type $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 1: recno: small key, small data pairs"
+	rm -f $TMP2 $TMP3
+	sed 200q $DICT |
+	awk '{ 
+		++i;
+		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test1: type recno: failed"
+		exit 1
+	fi
+}
+
+# Take the first 200 entries in the dictionary, and give them
+# each a medium size data entry.
+test2()
+{
+	echo "Test 2: btree, hash: small key, medium data pairs"
+	mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+	echo $mdata |
+	awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
+	for type in hash btree; do
+		rm -f $TMP2 $TMP3
+		for i in `sed 200q $DICT`; do
+			echo p
+			echo k$i
+			echo d$mdata
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test2: type $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 2: recno: small key, medium data pairs"
+	rm -f $TMP2 $TMP3
+	echo $mdata | 
+	awk '{  for (i = 1; i < 201; ++i)
+		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test2: type recno: failed"
+		exit 1
+	fi
+}
+
+# Insert the programs in /bin with their paths as their keys.
+test3()
+{
+	echo "Test 3: hash: small key, big data pairs"
+	rm -f $TMP1
+	(gfind /bin -type f -print | xargs cat) > $TMP1
+	for type in hash; do
+		rm -f $TMP2 $TMP3
+		for i in `gfind /bin -type f -print`; do
+			echo p
+			echo k$i
+			echo D$i
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -B -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test3: $type: failed"
+			exit 1
+		fi
+	done
+	echo "Test 3: btree: small key, big data pairs"
+	for psize in 512 16384 65536; do
+		echo "    page size $psize"
+		for type in btree; do
+			rm -f $TMP2 $TMP3
+			for i in `gfind /bin -type f -print`; do
+				echo p
+				echo k$i
+				echo D$i
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -B -i psize=$psize -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test3: $type: page size $psize: failed"
+				exit 1
+			fi
+		done
+	done
+	echo "Test 3: recno: big data pairs"
+	rm -f $TMP2 $TMP3
+	gfind /bin -type f -print | 
+	awk '{
+		++i;
+		printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
+	}' > $TMP2
+	for psize in 512 16384 65536; do
+		echo "    page size $psize"
+		$PROG -B -i psize=$psize -o $TMP3 recno $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test3: recno: page size $psize: failed"
+			exit 1
+		fi
+	done
+}
+
+# Do random recno entries.
+test4()
+{
+	echo "Test 4: recno: random entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 37; i <= 37 + 88 * 17; i += 17) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 1; i <= 15; ++i) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
+			if (i % 41)
+				s = substr($0, 1, i % 41);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 37;
+			incr = 17;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			if (i == 19234 + 61 * 27)
+				exit;
+			if (i == 37 + 88 * 17) {
+				i = 1;
+				incr = 1;
+			} else if (i == 15) {
+				i = 19234;
+				incr = 27;
+			} else
+				i += incr;
+		}
+		END {
+			for (i = 37; i <= 37 + 88 * 17; i += 17)
+				printf("g\nk%d\n", i);
+			for (i = 1; i <= 15; ++i)
+				printf("g\nk%d\n", i);
+			for (i = 19234; i <= 19234 + 61 * 27; i += 27)
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test4: type recno: failed"
+		exit 1
+	fi
+}
+
+# Do reverse order recno entries.
+test5()
+{
+	echo "Test 5: recno: reverse order entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk ' {
+		for (i = 1500; i; --i) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 1500;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			--i;
+		}
+		END {
+			for (i = 1500; i; --i) 
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test5: type recno: failed"
+		exit 1
+	fi
+}
+		
+# Do alternating order recno entries.
+test6()
+{
+	echo "Test 6: recno: alternating order entries"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk ' {
+		for (i = 1; i < 1200; i += 2) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		for (i = 2; i < 1200; i += 2) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("input key %d: %s\n", i, s);
+		}
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+	cat $TMP1 |
+	awk 'BEGIN {
+			i = 1;
+			even = 0;
+		}
+		{
+			printf("p\nk%d\nd%s\n", i, $0);
+			i += 2;
+			if (i >= 1200) {
+				if (even == 1)
+					exit;
+				even = 1;
+				i = 2;
+			}
+		}
+		END {
+			for (i = 1; i < 1200; ++i) 
+				printf("g\nk%d\n", i);
+		}' > $TMP2
+	$PROG -o $TMP3 recno $TMP2
+	gsort -o $TMP1 $TMP1
+	gsort -o $TMP3 $TMP3
+	if (cmp -s $TMP1 $TMP3) ; then :
+	else
+		echo "test6: type recno: failed"
+		exit 1
+	fi
+}
+
+# Delete cursor record
+test7()
+{
+	echo "Test 7: btree, recno: delete cursor record"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 120; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		printf("%05d: input key %d: %s\n", 120, 120, $0);
+		printf("seq failed, no such key\n");
+		printf("%05d: input key %d: %s\n", 1, 1, $0);
+		printf("%05d: input key %d: %s\n", 2, 2, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 120)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_NEXT\n");
+			for (i = 1; i <= 120; ++i)
+				printf("s\n");
+			printf("fR_CURSOR\ns\nk120\n");
+			printf("r\n");
+			printf("fR_NEXT\ns\n");
+			printf("fR_CURSOR\ns\nk1\n");
+			printf("r\n");
+			printf("fR_FIRST\ns\n");
+		}' > $TMP2
+		$PROG -o $TMP3 recno $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test7: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Make sure that overflow pages are reused.
+test8()
+{
+	echo "Test 8: btree, hash: repeated small key, big data pairs"
+	rm -f $TMP1
+	echo "" | 
+	awk 'BEGIN {
+		for (i = 1; i <= 10; ++i) {
+			printf("p\nkkey1\nD/bin/sh\n");
+			printf("p\nkkey2\nD/bin/csh\n");
+			if (i % 8 == 0) {
+				printf("c\nkkey2\nD/bin/csh\n");
+				printf("c\nkkey1\nD/bin/sh\n");
+				printf("e\t%d of 10 (comparison)\n", i);
+			} else
+				printf("e\t%d of 10             \n", i);
+			printf("r\nkkey1\nr\nkkey2\n");
+		}
+	}' > $TMP1
+	$PROG -B btree $TMP1
+#	$PROG -B hash $TMP1
+	# No explicit test for success.
+}
+
+# Test btree duplicate keys
+test9()
+{
+	echo "Test 9: btree: duplicate keys"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 543; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in btree; do
+		cat $TMP1 | 
+		awk '{
+			if (i++ % 2)
+				printf("p\nkduplicatekey\nd%s\n", $0);
+			else
+				printf("p\nkunique%dkey\nd%s\n", i, $0);
+		}
+		END {
+				printf("o\n");
+		}' > $TMP2
+		$PROG -iflags=1 -o $TMP3 $type $TMP2
+		gsort -o $TMP3 $TMP3
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test9: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Test use of cursor flags without initialization
+test10()
+{
+	echo "Test 10: btree, recno: test cursor flag use"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 20; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	# Test that R_CURSOR doesn't succeed before cursor initialized
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 10)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_CURSOR\nr\n");
+			printf("eR_CURSOR SHOULD HAVE FAILED\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+		if [ -s $TMP3 ] ; then
+			echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
+			exit 1
+		fi
+	done
+	for type in btree recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 10)
+				exit;
+			printf("p\nk%d\nd%s\n", ++i, $0);
+		}
+		END {
+			printf("fR_CURSOR\np\nk1\ndsome data\n");
+			printf("eR_CURSOR SHOULD HAVE FAILED\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+		if [ -s $TMP3 ] ; then
+			echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
+			exit 1
+		fi
+	done
+}
+
+# Test insert in reverse order.
+test11()
+{
+	echo "Test 11: recno: reverse order insert"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 779; ++i)
+			printf("%05d: input key %d: %s\n", i, i, $0);
+		exit;
+	}' > $TMP1
+	rm -f $TMP2 $TMP3
+
+	for type in recno; do
+		cat $TMP1 |
+		awk '{
+			if (i == 0) {
+				i = 1;
+				printf("p\nk1\nd%s\n", $0);
+				printf("%s\n", "fR_IBEFORE");
+			} else
+				printf("p\nk1\nd%s\n", $0);
+		}
+		END {
+				printf("or\n");
+		}' > $TMP2
+		$PROG -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test11: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Take the first 20000 entries in the dictionary, reverse them, and give
+# them each a small size data entry.  Use a small page size to make sure
+# the btree split code gets hammered.
+test12()
+{
+	echo "Test 12: btree: lots of keys, small page size"
+	mdata=abcdefghijklmnopqrstuvwxy
+	echo $mdata |
+	awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
+	for type in btree; do
+		rm -f $TMP2 $TMP3
+		for i in `sed 20000q $DICT | tac`; do
+			echo p
+			echo k$i
+			echo d$mdata
+			echo g
+			echo k$i
+		done > $TMP2
+		$PROG -i psize=512 -o $TMP3 $type $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test12: type $type: failed"
+			exit 1
+		fi
+	done
+}
+
+# Test different byte orders.
+test13()
+{
+	echo "Test 13: btree, hash: differing byte orders"
+	sed 50q $DICT > $TMP1
+	for order in 1234 4321; do
+		for type in btree hash; do
+			rm -f byte.file $TMP2 $TMP3
+			for i in `sed 50q $DICT`; do
+				echo p
+				echo k$i
+				echo d$i
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test13: $type/$order put failed"
+				exit 1
+			fi
+			for i in `sed 50q $DICT`; do
+				echo g
+				echo k$i
+			done > $TMP2
+			$PROG -s \
+			    -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+			if (cmp -s $TMP1 $TMP3) ; then :
+			else
+				echo "test13: $type/$order get failed"
+				exit 1
+			fi
+		done
+	done
+	rm -f byte.file
+}
+
+# Try a variety of bucketsizes and fill factors for hashing
+test20()
+{
+	echo\
+    "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
+	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+	awk '{
+		for (i = 1; i <= 10000; ++i) {
+			if (i % 34)
+				s = substr($0, 1, i % 34);
+			else
+				s = substr($0, 1);
+			printf("%s\n", s);
+		}
+		exit;
+	}' > $TMP1
+	sed 10000q $DICT |
+	awk 'BEGIN {
+		ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg"
+	}
+	{
+		if (++i % 34)
+			s = substr(ds, 1, i % 34);
+		else
+			s = substr(ds, 1);
+		printf("p\nk%s\nd%s\n", $0, s);
+	}' > $TMP2
+	sed 10000q $DICT |
+	awk '{
+		++i;
+		printf("g\nk%s\n", $0);
+	}' >> $TMP2
+	bsize=256
+	for ffactor in 11 14 21; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=512
+	for ffactor in 21 28 43; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=1024
+	for ffactor in 43 57 85; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=2048
+	for ffactor in 85 114 171; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=4096
+	for ffactor in 171 228 341; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+	bsize=8192
+	for ffactor in 341 455 683; do
+		echo "    bucketsize $bsize, fill factor $ffactor"
+		$PROG -o$TMP3 \
+		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+		    hash $TMP2
+		if (cmp -s $TMP1 $TMP3) ; then :
+		else
+			echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+			exit 1
+		fi
+	done
+}
+
+main $*
Index: /branches/EMX/src/emx/bsd/libc/emxbsd.h
===================================================================
--- /branches/EMX/src/emx/bsd/libc/emxbsd.h	(revision 273)
+++ /branches/EMX/src/emx/bsd/libc/emxbsd.h	(revision 273)
@@ -0,0 +1,3 @@
+/* emxbsd.h */
+
+typedef	unsigned int    u_int;
Index: /branches/EMX/src/emx/bsd/libc/heapsort.c
===================================================================
--- /branches/EMX/src/emx/bsd/libc/heapsort.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/libc/heapsort.c	(revision 273)
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)heapsort.c	5.1 (Berkeley) 6/4/91";
+#endif /* LIBC_SCCS and not lint */
+
+#if defined (__EMX__)
+#define __P(X) X
+#else
+#include <sys/cdefs.h>
+#endif
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Swap two areas of size number of bytes.  Although qsort(3) permits random
+ * blocks of memory to be sorted, sorting pointers is almost certainly the
+ * common case (and, were it not, could easily be made so).  Regardless, it
+ * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
+ * arithmetic gets lost in the time required for comparison function calls.
+ */
+#define	SWAP(a, b) { \
+	cnt = size; \
+	do { \
+		ch = *a; \
+		*a++ = *b; \
+		*b++ = ch; \
+	} while (--cnt); \
+}
+
+/*
+ * Build the list into a heap, where a heap is defined such that for
+ * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
+ *
+ * There two cases.  If j == nmemb, select largest of Ki and Kj.  If
+ * j < nmemb, select largest of Ki, Kj and Kj+1.
+ *
+ * The initial value depends on if we're building the initial heap or
+ * reconstructing it after saving a value.
+ */
+#define	HEAP(initval) { \
+	for (i = initval; (j = i * 2) <= nmemb; i = j) { \
+		p = (char *)bot + j * size; \
+		if (j < nmemb && compar(p, p + size) < 0) { \
+			p += size; \
+			++j; \
+		} \
+		t = (char *)bot + i * size; \
+		if (compar(p, t) <= 0) \
+			break; \
+		SWAP(t, p); \
+	} \
+}
+
+/*
+ * Heapsort -- Knuth, Vol. 3, page 145.  Runs in O (N lg N), both average
+ * and worst.  While heapsort is faster than the worst case of quicksort,
+ * the BSD quicksort does median selection so that the chance of finding
+ * a data set that will trigger the worst case is nonexistent.  Heapsort's
+ * only advantage over quicksort is that it requires no additional memory.
+ */
+heapsort(bot, nmemb, size, compar)
+	register void *bot;
+	register size_t nmemb, size;
+	int (*compar) __P((const void *, const void *));
+{
+	register char *p, *t, ch;
+	register int cnt, i, j, l;
+
+	if (nmemb <= 1)
+		return (0);
+	if (!size) {
+		errno = EINVAL;
+		return (-1);
+	}
+	/*
+	 * Items are numbered from 1 to nmemb, so offset from size bytes
+	 * below the starting address.
+	 */
+	bot -= size;
+
+	for (l = nmemb / 2 + 1; --l;)
+		HEAP(l);
+
+	/*
+	 * For each element of the heap, save the largest element into its
+	 * final slot, then recreate the heap.
+	 */
+	while (nmemb > 1) {
+		p = (char *)bot + size;
+		t = (char *)bot + nmemb * size;
+		SWAP(p, t);
+		--nmemb;
+		HEAP(1);
+	}
+	return (0);
+}
Index: /branches/EMX/src/emx/bsd/libc/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/libc/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/libc/makefile	(revision 273)
@@ -0,0 +1,13 @@
+# /emx/bsd/libc/makefile
+
+CC=	gcc -O
+CFLAGS= -I.
+
+.c.o:
+	$(CC) -c $(CFLAGS) $<
+default: bsd.a
+
+bsd.a: heapsort.o random.o strsep.o
+	-del $@
+	ar r $@ *.o
+	ar s $@
Index: /branches/EMX/src/emx/bsd/libc/random.c
===================================================================
--- /branches/EMX/src/emx/bsd/libc/random.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/libc/random.c	(revision 273)
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c	5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined (__EMX__)
+#include "emxbsd.h"
+#endif
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package.  In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface.  The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information.  Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes.  The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate().  By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator.  If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of longs; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
+ * state information, which will allow a degree seven polynomial.  (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ * 
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way).  In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive).  The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits.  The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator.  Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift register is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define	TYPE_0		0		/* linear congruential */
+#define	BREAK_0		8
+#define	DEG_0		0
+#define	SEP_0		0
+
+#define	TYPE_1		1		/* x**7 + x**3 + 1 */
+#define	BREAK_1		32
+#define	DEG_1		7
+#define	SEP_1		3
+
+#define	TYPE_2		2		/* x**15 + x + 1 */
+#define	BREAK_2		64
+#define	DEG_2		15
+#define	SEP_2		1
+
+#define	TYPE_3		3		/* x**31 + x**3 + 1 */
+#define	BREAK_3		128
+#define	DEG_3		31
+#define	SEP_3		3
+
+#define	TYPE_4		4		/* x**63 + x + 1 */
+#define	BREAK_4		256
+#define	DEG_4		63
+#define	SEP_4		1
+
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define	MAX_TYPES	5		/* max number of types above */
+
+static int degrees[MAX_TYPES] =	{ DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps [MAX_TYPES] =	{ SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ *	initstate(1, &randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ *	MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static long randtbl[DEG_3 + 1] = {
+	TYPE_3,
+	0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+	0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+	0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+	0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+	0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+	0x27fb47b9,
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer.  These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information.  (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way).  The pointers are left positioned as they would be
+ * from the call
+ *
+ *	initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static long *fptr = &randtbl[SEP_3 + 1];
+static long *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers.  Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth.  Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G.  Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static long *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static long *end_ptr = &randtbl[DEG_3 + 1];
+
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed.  If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator.  Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart.  Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G.  Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+void
+srandom(x)
+	u_int x;
+{
+	register int i, j;
+
+	if (rand_type == TYPE_0)
+		state[0] = x;
+	else {
+		j = 1;
+		state[0] = x;
+		for (i = 1; i < rand_deg; i++)
+			state[i] = 1103515245 * state[i - 1] + 12345;
+		fptr = &state[rand_sep];
+		rptr = &state[0];
+		for (i = 0; i < 10 * rand_deg; i++)
+			(void)random();
+	}
+}
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation.  Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it.  srandom() is then called to
+ * initialize the state information.
+ * 
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ * 
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ */
+char *
+initstate(seed, arg_state, n)
+	u_int seed;			/* seed for R.N.G. */
+	char *arg_state;		/* pointer to state array */
+	int n;				/* # bytes of state info */
+{
+	register char *ostate = (char *)(&state[-1]);
+
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+	if (n < BREAK_0) {
+		(void)fprintf(stderr,
+		    "random: not enough state (%d bytes); ignored.\n", n);
+		return(0);
+	}
+	if (n < BREAK_1) {
+		rand_type = TYPE_0;
+		rand_deg = DEG_0;
+		rand_sep = SEP_0;
+	} else if (n < BREAK_2) {
+		rand_type = TYPE_1;
+		rand_deg = DEG_1;
+		rand_sep = SEP_1;
+	} else if (n < BREAK_3) {
+		rand_type = TYPE_2;
+		rand_deg = DEG_2;
+		rand_sep = SEP_2;
+	} else if (n < BREAK_4) {
+		rand_type = TYPE_3;
+		rand_deg = DEG_3;
+		rand_sep = SEP_3;
+	} else {
+		rand_type = TYPE_4;
+		rand_deg = DEG_4;
+		rand_sep = SEP_4;
+	}
+	state = &(((long *)arg_state)[1]);	/* first location */
+	end_ptr = &state[rand_deg];	/* must set end_ptr before srandom */
+	srandom(seed);
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES*(rptr - state) + rand_type;
+	return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information.  This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ */
+char *
+setstate(arg_state)
+	char *arg_state;
+{
+	register long *new_state = (long *)arg_state;
+	register int type = new_state[0] % MAX_TYPES;
+	register int rear = new_state[0] / MAX_TYPES;
+	char *ostate = (char *)(&state[-1]);
+
+	if (rand_type == TYPE_0)
+		state[-1] = rand_type;
+	else
+		state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+	switch(type) {
+	case TYPE_0:
+	case TYPE_1:
+	case TYPE_2:
+	case TYPE_3:
+	case TYPE_4:
+		rand_type = type;
+		rand_deg = degrees[type];
+		rand_sep = seps[type];
+		break;
+	default:
+		(void)fprintf(stderr,
+		    "random: state info corrupted; not changed.\n");
+	}
+	state = &new_state[1];
+	if (rand_type != TYPE_0) {
+		rptr = &state[rear];
+		fptr = &state[(rear + rand_sep) % rand_deg];
+	}
+	end_ptr = &state[rand_deg];		/* set end_ptr too */
+	return(ostate);
+}
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up.  The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer.  Then both pointers are advanced to
+ * the next location cyclically in the table.  The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+long
+random()
+{
+	long i;
+
+	if (rand_type == TYPE_0)
+		i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
+	else {
+		*fptr += *rptr;
+		i = (*fptr >> 1) & 0x7fffffff;	/* chucking least random bit */
+		if (++fptr >= end_ptr) {
+			fptr = state;
+			++rptr;
+		} else if (++rptr >= end_ptr)
+			rptr = state;
+	}
+	return(i);
+}
Index: /branches/EMX/src/emx/bsd/libc/strsep.c
===================================================================
--- /branches/EMX/src/emx/bsd/libc/strsep.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/libc/strsep.c	(revision 273)
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#if !defined (__EMX__)
+#include <sys/cdefs.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strsep.c	5.4 (Berkeley) 1/26/91";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Get next token from string *stringp, where tokens are nonempty
+ * strings separated by characters from delim.  
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strtoken returns NULL.
+ */
+char *
+strsep(stringp, delim)
+	register char **stringp;
+	register const char *delim;
+{
+	register char *s;
+	register const char *spanp;
+	register int c, sc;
+	char *tok;
+
+	if ((s = *stringp) == NULL)
+		return (NULL);
+	for (tok = s;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = 0;
+				*stringp = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
Index: /branches/EMX/src/emx/bsd/libterm/makefile
===================================================================
--- /branches/EMX/src/emx/bsd/libterm/makefile	(revision 273)
+++ /branches/EMX/src/emx/bsd/libterm/makefile	(revision 273)
@@ -0,0 +1,14 @@
+#
+# termcap/Makefile
+#
+default: termcap.a
+
+CFLAGS = -O -DEMX
+
+.c.o:
+	gcc -c $(CFLAGS) $<
+
+termcap.a: termcap.o tgoto.o tputs.o
+	-del termcap.a
+	ar r termcap.a termcap.o tgoto.o tputs.o
+	ar s termcap.a
Index: /branches/EMX/src/emx/bsd/libterm/termcap.3
===================================================================
--- /branches/EMX/src/emx/bsd/libterm/termcap.3	(revision 273)
+++ /branches/EMX/src/emx/bsd/libterm/termcap.3	(revision 273)
@@ -0,0 +1,254 @@
+.\" Copyright (c) 1980, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"     @(#)termcap.3	6.6 (Berkeley) 4/19/91
+.\"
+.Dd April 19, 1991
+.Dt TERMCAP 3
+.Os BSD 4
+.Sh NAME
+.Nm tgetent ,
+.Nm tgetnum ,
+.Nm tgetflag ,
+.Nm tgetstr ,
+.Nm tgoto ,
+.Nm tputs
+.Nd terminal independent operation routines
+.Sh SYNOPSIS
+.Vt char PC;
+.Vt char *BC;
+.Vt char *UP;
+.Vt short ospeed;
+.Fn tgetent "char *bp" "char *name"
+.Fn tgetnum "char *id"
+.Fn tgetflag "char *id"
+.Ft char *
+.Fn tgetstr "char *id" "char *area"
+.Ft char *
+.Fn tgoto "char *cm" destcol destline
+.Fn tputs "register char *cp" "int affcnt" "int (*outc)()"
+.Sh DESCRIPTION
+These functions extract and use capabilities from a terminal capability data
+base, usually
+.Pa /usr/share/misc/termcap ,
+the format of which is described in
+.Xr termcap 5 .
+These are low level routines;
+see
+.Xr curses 3
+for a higher level package.
+.Pp
+The
+.Fn tgetent
+function
+extracts the entry for terminal
+.Fa name
+into the buffer at
+.Fa bp .
+The
+.Fa bp
+argument
+should be a character buffer of size
+1024 and must be retained through all subsequent calls to
+.Fn tgetnum ,
+.Fn tgetflag ,
+and
+.Fn tgetstr .
+The
+.Fn tgetent
+function
+returns \-1 if none of the
+.Nm termcap
+data base files could be opened,
+0 if the terminal name given does not have an entry,
+and 1 if all goes well.
+It will look in the environment for a
+.Ev TERMCAP
+variable.
+If found, and the value does not begin with a slash,
+and the terminal type
+.Fa name
+is the same as the environment string
+.Ev TERM ,
+the
+.Ev TERMCAP
+string is used instead of reading a
+.Nm termcap
+file.
+If it does begin with a slash, the string is used as a path name
+of the
+.Nm termcap
+file to search.
+If
+.Ev TERMCAP
+does not begin with a slash and
+.Fa name
+is different from
+.Ev TERM ,
+.Fn tgetent
+searches the files
+.Pa $HOME/.termcap
+and
+.Pa /usr/share/misc/termcap ,
+in that order, unless the environment variable
+.Ev TERMPATH
+exists,
+in which case it specifies a list of file pathnames
+(separated by spaces or colons) to be searched instead.
+Whenever multiple files are searched and a
+.Sy tc
+field occurs in the requested entry, the entry it names must be found
+in the same file or one of the succeeding files.
+This can speed up entry into programs that call
+.Fn tgetent ,
+as well as help debug new terminal descriptions
+or make one for your terminal if you can't write the file
+.Pa /usr/share/misc/termcap .
+.Pp
+The
+.Fn tgetnum
+function
+gets the numeric value of capability
+.Fa id ,
+returning \-1 if is not given for the terminal.
+The
+.Fn tgetflag
+function
+returns 1 if the specified capability is present in
+the terminal's entry, 0 if it is not.
+The
+.Fn tgetstr
+function
+returns the string value of the capability
+.Fa id ,
+places it in the buffer at
+.Fa area ,
+and advances the
+.Fa area
+pointer.
+It decodes the abbreviations for this field described in
+.Xr termcap 5 ,
+except for cursor addressing and padding information.
+The
+.Fn tgetstr
+function
+returns
+.Dv NULL
+if the capability was not found.
+.Pp
+The
+.Fn tgoto
+function
+returns a cursor addressing string decoded from
+.Fa cm
+to go to column
+.Fa destcol
+in line
+.Fa destline .
+It uses the external variables
+.Va UP
+(from the
+.Sy up
+capability)
+and
+.Va BC
+(if
+.Sy bc
+is given rather than
+.Sy bs )
+if necessary to avoid placing
+.Sy \en ,
+.Sy ^D
+or
+.Sy ^@
+in
+the returned string.
+(Programs which call
+.Fn tgoto
+should be sure to turn off the
+.Dv XTABS
+bit(s),
+since
+.Fn tgoto
+may now output a tab.
+Note that programs using termcap should in general turn off
+.Dv XTABS
+anyway since some terminals use control-I for other functions,
+such as nondestructive space.)
+If a
+.Sy %
+sequence is given which is not understood, then
+.Fn tgoto
+returns
+.Pq Dv OOPS .
+.Pp
+The
+.Fn tputs
+function
+decodes the leading padding information of the string
+.Fa cp ;
+.Fa affcnt
+gives the number of lines affected by the operation, or 1 if this is
+not applicable,
+.Fa outc
+is a routine which is called with each character in turn.
+The external variable
+.Va ospeed
+should contain the output speed of the terminal as encoded by
+.Xr stty 3 .
+The external variable
+.Va PC
+should contain a pad character to be used (from the
+.SY pc
+capability)
+if a null
+.Pq Sy ^@
+is inappropriate.
+.Sh FILES
+.Bl -tag -width /usr/share/misc/termcap -compact
+.It Pa /usr/lib/libtermcap.a
+.Fl l Ar ltermcap
+library (also known as
+.Fl l Ar ltermlib )
+.It Pa /usr/share/misc/termcap
+standard terminal capability data base
+.It Pa $HOME/.termcap
+user's terminal capability data base
+.El
+.Sh SEE ALSO
+.Xr ex 1 ,
+.Xr curses 3 ,
+.Xr termcap 5
+.Sh HISTORY
+The
+.Nm
+functions appeared in 
+.Bx 4.0 .
Index: /branches/EMX/src/emx/bsd/libterm/termcap.5
===================================================================
--- /branches/EMX/src/emx/bsd/libterm/termcap.5	(revision 273)
+++ /branches/EMX/src/emx/bsd/libterm/termcap.5	(revision 273)
@@ -0,0 +1,1845 @@
+.\" Copyright (c) 1985, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\"     @(#)termcap.5	6.11 (Berkeley) 3/6/93
+.\"
+.Dd March 6, 1993
+.Dt TERMCAP 5
+.Os BSD 3
+.Sh NAME
+.Nm termcap
+.Nd terminal capability data base
+.Sh SYNOPSIS
+.Nm termcap
+.Sh DESCRIPTION
+The
+.Nm Termcap
+file
+is a data base describing terminals,
+used,
+for example,
+by
+.Xr \&vi 1
+and
+.Xr curses 3 .
+Terminals are described in
+.Nm termcap
+by giving a set of capabilities that they have and by describing
+how operations are performed.
+Padding requirements and initialization sequences
+are included in
+.Nm termcap .
+.Pp
+Entries in
+.Nm termcap
+consist of a number of `:'-separated fields.
+The first entry for each terminal gives the names that are known for the
+terminal, separated by `|' characters.
+The first name given is the most common abbreviation for the terminal.
+The last name given should be a long name fully identifying the terminal,
+and all others are understood as synonyms for the terminal name.
+All names but the last should be in lower case and contain no blanks;
+the last name may well contain upper case characters and blanks for
+readability.
+.Pp
+Terminal names (except for the last, verbose entry)
+should be chosen using the following conventions.
+The particular piece of hardware making up the terminal
+should have a root name chosen, thus
+.Dq hp2621
+This name should not contain hyphens.
+Modes that the hardware can be in
+or user preferences
+should be indicated by appending a hyphen and an indicator of the mode.
+Therefore, a
+.Dq vt100
+in 132-column mode would be
+.Dq vt100-w .
+The following suffixes should be used where possible:
+.Pp
+.Bd -filled -offset indent
+.Bl -column indent "With automatic margins (usually default)xx"
+.Sy Suffix	Meaning	Example
+-w	Wide mode (more than 80 columns)	vt100-w
+-am	With automatic margins (usually default)	vt100-am
+-nam	Without automatic margins	vt100-nam
+.Pf \- Ar n Ta No "Number of lines on the screen	aaa-60"
+-na	No arrow keys (leave them in local)	concept100-na
+.Pf \- Ar \&np Ta No "Number of pages of memory	concept100-4p"
+-rv	Reverse video	concept100-rv
+.El
+.Ed
+.Sh CAPABILITIES
+The characters in the
+The
+.Em Notes
+function
+field in the table have the following meanings
+(more than one may apply to a capability):
+.Pp
+.Bd -unfilled -offset indent
+N	indicates numeric parameter(s)
+P	indicates that padding may be specified
+*	indicates that padding may be based on the number of lines affected
+o	indicates capability is obsolete
+.Ed
+.Pp
+.Dq Obsolete
+capabilities have no
+.Em terminfo
+equivalents,
+since they were considered useless,
+or are subsumed by other capabilities.
+New software should not rely on them at all.
+.Pp
+.Bl -column indent indent indent
+.Sy Name	Type	Notes	Description
+functions
+.It "ae	str	(P)	End alternate character set."
+.It AL	str	(NP*)	Add"
+.Em n
+new blank lines
+.It "al	str	(P*)	Add new blank line."
+.It "am	bool		Terminal has automatic margins."
+.It "as	str	(P)	Start alternate character set."
+.It "bc	str	(o)	Backspace if not."
+.Sy \&^H .
+.It "bl	str	(P)	Audible signal (bell)."
+.It "bs	bool	(o)	Terminal can backspace with"
+.Sy \&^H .
+.It "bt	str	(P)	Back tab."
+.It "bw	bool	" Ta Sy \&le
+(backspace) wraps from column 0 to last column.
+.It "CC	str		Terminal settable command character in prototype."
+.It "cd	str	(P*)	Clear to end of display."
+.It "ce	str	(P)	Clear to end of line."
+.It "ch	str	(NP)	Set cursor column (horizontal position)."
+.It "cl	str	(P*)	Clear screen and home cursor."
+.It "CM	str	(NP)	Memory-relative cursor addressing."
+.It "cm	str	(NP)	Screen-relative cursor motion."
+.It "co	num		Number of columns in a line (See"
+.Sx BUGS
+section below).
+.It "cr	str	(P)	Carriage return."
+.It "cs	str	(NP)	Change scrolling region (VT100)."
+.It "ct	str	(P)	Clear all tab stops."
+.It "cv	str	(NP)	Set cursor row (vertical position)."
+.It "da	bool		Display may be retained above the screen."
+.It "dB	num	(o)	Milliseconds of"
+.Sy \&bs
+delay needed (default 0).
+.It "db	bool		Display may be retained below the screen."
+.It "DC	str	(NP*)	Delete"
+.Em n
+characters.
+.It "dC	num	(o)	Milliseconds of"
+.Sy \&cr
+delay needed (default 0).
+.It "dc	str	(P*)	Delete character."
+.It "dF	num	(o)	Milliseconds of"
+.Sy \&ff
+delay needed (default 0).
+.It "DL	str	(NP*)	Delete"
+.Ar n
+lines.
+.It "dl	str	(P*)	Delete line."
+.It "dm	str		Enter delete mode."
+.It "dN	num	(o)	Milliseconds of
+.Sy \&nl
+delay needed (default 0).
+.It "DO	str	(NP*)	Move cursor down:
+.Ar n
+lines.
+.It "do	str		Down one line."
+.It "ds	str		Disable status line."
+.It "dT	num	(o)	Milliseconds of horizontal tab delay needed (default 0)."
+.It "dV	num	(o)	Milliseconds of vertical tab delay needed (default 0)."
+.It "ec	str	(NP)	Erase"
+.Ar n
+characters.
+.It "ed	str		End delete mode."
+.It "ei	str		End insert mode."
+.It "eo	bool		Can erase overstrikes with a blank."
+.It "EP	bool	(o)	Even parity."
+.It "es	bool		Escape can be used on the status line."
+.It "ff	str	(P*)	Hardcopy terminal page eject."
+.It "fs	str		Return from status line."
+.It "gn	bool		Generic line type, for example dialup, switch)."
+.It "hc	bool		Hardcopy terminal."
+.It "HD	bool	(o)	Half-duplex."
+.It "hd	str		Half-line down (forward 1/2 linefeed)."
+.It "ho	str	(P)	Home cursor."
+.It "hs	bool		Has extra"
+.Dq status line .
+.It "hu	str		Half-line up (reverse 1/2 linefeed)."
+.It "hz	bool		Cannot print ``~'' (Hazeltine)."
+.It "i1-i3	str		Terminal initialization strings"
+.Pf ( Xr terminfo
+only)
+.It "IC	str	(NP*)	Insert"
+.Ar n
+blank characters.
+.It "ic	str	(P*)	Insert character."
+.It "if	str		Name of file containing initialization string."
+.It "im	str		Enter insert mode."
+.It "in	bool		Insert mode distinguishes nulls."
+.It "iP	str		Pathname of program for initialization"
+.Pf ( Xr terminfo
+only).
+.It "ip	str	(P*)	Insert pad after character inserted."
+.It "is	str		Terminal initialization string"
+.Pf ( Nm termcap
+only).
+.It "it	num		Tabs initially every"
+.Ar n
+positions.
+.It "K1	str		Sent by keypad upper left."
+.It "K2	str		Sent by keypad upper right."
+.It "K3	str		Sent by keypad center."
+.It "K4	str		Sent by keypad lower left."
+.It "K5	str		Sent by keypad lower right."
+.It "k0-k9	str		Sent by function keys 0-9."
+.It "kA	str		Sent by insert-line key."
+.It "ka	str		Sent by clear-all-tabs key."
+.It "kb	str		Sent by backspace key."
+.It "kC	str		Sent by clear-screen or erase key."
+.It "kD	str		Sent by delete-character key."
+.It "kd	str		Sent by down-arrow key."
+.It "kE	str		Sent by clear-to-end-of-line key."
+.It "ke	str		Out of"
+.Dq keypad transmit
+mode.
+.It "kF	str		Sent by scroll-forward/down key."
+.It "kH	str		Sent by home-down key."
+.It "kh	str		Sent by home key."
+.It "kI	str		Sent by insert-character or enter-insert-mode key."
+.It "kL	str		Sent by delete-line key."
+.It "kl	str		Sent by left-arrow key."
+.It "kM	str		Sent by insert key while in insert mode."
+.It "km	bool		Has a"
+.Dq meta
+key (shift, sets parity bit).
+.It "kN	str		Sent by next-page key."
+.It "kn	num	(o)	Number of function"
+.Pq Sy \&k\&0 Ns \- Sy \&k\&9
+keys (default 0).
+.It "ko	str	(o)	Termcap entries for other non-function keys."
+.It "kP	str		Sent by previous-page key."
+.It "kR	str		Sent by scroll-backward/up key."
+.It "kr	str		Sent by right-arrow key."
+.It "kS	str		Sent by clear-to-end-of-screen key."
+.It "ks	str		Put terminal in"
+.Dq keypad transmit
+mode.
+.It "kT	str		Sent by set-tab key."
+.It "kt	str		Sent by clear-tab key."
+.It "ku	str		Sent by up-arrow key."
+.It "l0-l9	str		Labels on function keys if not"
+.Dq \&f Ns Em n .
+.It "LC	bool	(o)	Lower-case only."
+.It "LE	str	(NP)	Move cursor left"
+.Ar n
+positions.
+.It "le	str	(P)	Move cursor left one position."
+.It "li	num		Number of lines on screen or page (See"
+.Sx BUGS
+section below)
+.It "ll	str		Last line, first column
+.It "lm	num		Lines of memory if >" Sy \&li
+(0 means varies).
+.It "ma	str	(o)	Arrow key map (used by"
+.Xr \&vi
+version 2 only).
+.It "mb	str		Turn on blinking attribute."
+.It "md	str		Turn on bold (extra bright) attribute."
+.It "me	str		Turn off all attributes."
+.It "mh	str		Turn on half-bright attribute."
+.It "mi	bool		Safe to move while in insert mode."
+.It "mk	str		Turn on blank attribute (characters invisible)."
+.It "ml	str	(o)	Memory lock on above cursor."
+.It "mm	str		Turn on"
+.Dq meta mode
+(8th bit).
+.It "mo	str		Turn off"
+.Dq meta mode .
+.It "mp	str		Turn on protected attribute."
+.It "mr	str		Turn on reverse-video attibute."
+.It "ms	bool		Safe to move in standout modes."
+.It "mu	str	(o)	Memory unlock (turn off memory lock)."
+.It "nc	bool	(o)	No correctly-working"
+.Sy \&cr
+(Datamedia 2500, Hazeltine 2000).
+.It "nd	str		Non-destructive space (cursor right)."
+.It "NL	bool	(o)" Ta Sy \&\en No "is newline, not line feed."
+.It "nl	str	(o)	Newline character if not" Sy \en .
+.It "ns	bool	(o)	Terminal is a" Tn CRT No "but doesn't scroll."
+.It "nw	str	(P)	Newline (behaves like"
+.Sy \&cr
+followed by
+.Sy \&do ).
+.It "OP	bool	(o)	Odd parity."
+.It "os	bool		Terminal overstrikes."
+.It "pb	num		Lowest baud where delays are required."
+.It "pc	str		Pad character (default" Tn NUL ).
+.It "pf	str		Turn off the printer."
+.It "pk	str		Program function key"
+.Em n
+to type string
+.Em s
+.Pf ( Xr terminfo
+only).
+.It "pl	str		Program function key"
+.Em n
+to execute string
+.Em s
+.Pf ( Xr terminfo
+only).
+.It "pO	str	(N)	Turn on the printer for"
+.Em n
+bytes.
+.It "po	str		Turn on the printer."
+.It "ps	str		Print contents of the screen."
+.It "pt	bool	(o)	Has hardware tabs (may need to be set with"
+.Sy \&is ).
+.It "px	str		Program function key"
+.Em n
+to transmit string
+.Em s
+.Pf ( Xr terminfo
+only).
+.It "r1-r3	str		Reset terminal completely to sane modes"
+.Pf ( Xr terminfo
+only).
+.It "rc	str	(P)	Restore cursor to position of last"
+.Sy \&sc .
+.It "rf	str		Name of file containing reset codes."
+.It "RI	str	(NP)	Move cursor right"
+.Em n
+positions.
+.It "rp	str	(NP*)	Repeat character"
+.Em c n
+times.
+.It "rs	str		Reset terminal completely to sane modes"
+.Pf ( Nm termcap
+only).
+.It "sa	str	(NP)	Define the video attributes."
+.It "sc	str	(P)	Save cursor position."
+.It "se	str		End standout mode."
+.It "SF	str	(NP*)	Scroll forward"
+.Em n
+lines.
+.It "sf	str	(P)	Scroll text up."
+.It "sg	num		Number of garbage chars left by"
+.Sy \&so
+or
+.Sy \&se
+(default 0).
+.It "so	str		Begin standout mode."
+.It "SR	str	(NP*)	Scroll backward"
+.Em n
+lines.
+.It "sr	str	(P)	Scroll text down."
+.It "st	str		Set a tab in all rows, current column."
+.It "ta	str	(P)	Tab to next 8-position hardware tab stop."
+.It "tc	str		Entry of similar terminal \- must be last."
+.It "te	str		String to end programs that use"
+.Nm termcap .
+.It "ti	str		String to begin programs that use"
+.Nm termcap .
+.It "ts	str	(N)	Go to status line, column"
+.Em n .
+.It "UC	bool	(o)	Upper-case only."
+.It "uc	str		Underscore one character and move past it."
+.It "ue	str		End underscore mode."
+.It "ug	num		Number of garbage chars left by"
+.Sy \&us
+or
+.Sy \&ue
+(default 0).
+.It "ul	bool		Underline character overstrikes."
+.It "UP	str	(NP*)	Move cursor up"
+.Em n
+lines.
+.It "up	str		Upline (cursor up)."
+.It "us	str		Start underscore mode."
+.It "vb	str		Visible bell (must not move cursor)."
+.It "ve	str		Make cursor appear normal (undo"
+.Sy \&vs Ns / Sy \&vi ) .
+.It "vi	str		Make cursor invisible."
+.It "vs	str		Make cursor very visible."
+.It "vt	num		Virtual terminal number (not supported on all systems)."
+.It "wi	str	(N)	Set current window."
+.It "ws	num		Number of columns in status line."
+.It "xb	bool		Beehive"
+.Pf ( "f1=" Dv ESC ,
+.Pf "f2=" Sy \&^C ) .
+.It "xn	bool		Newline ignored after 80 cols (Concept)."
+.It "xo	bool		Terminal uses xoff/xon"
+.Pq Dv DC3 Ns / Ns Dv DC1
+handshaking.
+.It "xr	bool	(o)	Return acts like"
+.Sy "ce cr nl"
+(Delta Data).
+.It "xs	bool		Standout not erased by overwriting (Hewlett-Packard)."
+.It "xt	bool		Tabs ruin, magic"
+.SY \&so
+char (Teleray 1061).
+.It "xx	bool	(o)	Tektronix 4025 insert-line."
+.El
+.Ss A Sample Entry
+The following entry, which describes the Concept\-100, is among the more
+complex entries in the
+.Nm termcap
+file as of this writing.
+.Pp
+.Bd -literal
+ca\||\|concept100\||\|c100\||\|concept\||\|c104\||\|concept100-4p\||\|HDS Concept\-100:\e
+	:al=3*\eE^R:am:bl=^G:cd=16*\eE^C:ce=16\eE^U:cl=2*^L:cm=\eEa%+ %+ :\e
+	:co#80:.cr=9^M:db:dc=16\eE^A:dl=3*\eE^B:do=^J:ei=\eE\e200:eo:im=\eE^P:in:\e
+	:ip=16*:is=\eEU\eEf\eE7\eE5\eE8\eEl\eENH\eEK\eE\e200\eEo&\e200\eEo\e47\eE:k1=\eE5:\e
+	:k2=\eE6:k3=\eE7:kb=^h:kd=\eE<:ke=\eEx:kh=\eE?:kl=\eE>:kr=\eE=:ks=\eEX:\e
+	:ku=\eE;:le=^H:li#24:mb=\eEC:me=\eEN\e200:mh=\eEE:mi:mk=\eEH:mp=\eEI:\e
+	:mr=\eED:nd=\eE=:pb#9600:rp=0.2*\eEr%.%+ :se=\eEd\eEe:sf=^J:so=\eEE\eED:\e
+	:.ta=8\et:te=\eEv    \e200\e200\e200\e200\e200\e200\eEp\er\en:\e
+	:ti=\eEU\eEv  8p\eEp\er:ue=\eEg:ul:up=\eE;:us=\eEG:\e
+	:vb=\eEk\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\e200\eEK:\e
+	:ve=\eEw:vs=\eEW:vt#8:xn:\e
+	:bs:cr=^M:dC#9:dT#8:nl=^J:ta=^I:pt:
+.Ed
+.Pp
+Entries may continue onto multiple lines by giving a \e as the last
+character of a line, and empty fields
+may be included for readability (here between the last field on a line
+and the first field on the next).
+Comments may be included on lines beginning with
+.Dq # .
+.Ss Types of Capabilities
+Capabilities in
+.Nm termcap
+are of three types: Boolean capabilities,
+which indicate particular features that the terminal has;
+numeric capabilities,
+giving the size of the display or the size of other attributes;
+and string capabilities,
+which give character sequences that can be used to perform particular
+terminal operations.
+All capabilities have two-letter codes.
+For instance, the fact that
+the Concept has
+.Em automatic margins
+(an automatic return and linefeed
+when the end of a line is reached) is indicated by the Boolean capability
+.Sy \&am .
+Hence the description of the Concept includes
+.Sy \&am .
+.Pp
+Numeric capabilities are followed by the character `#' then the value.
+In the example above
+.Sy \&co ,
+which indicates the number of columns the display has,
+gives the value `80' for the Concept.
+.Pp
+Finally, string-valued capabilities, such as
+.Sy \&ce
+(clear-to-end-of-line
+sequence) are given by the two-letter code, an `=', then a string
+ending at the next following `:'.
+A delay in milliseconds may appear after
+the `=' in such a capability,
+which causes padding characters to be supplied by
+.Xr tputs
+after the remainder of the string is sent to provide this delay.
+The delay can be either a number,
+such as `20', or a number followed by
+an `*',
+such as `3*'.
+An `*' indicates that the padding required is proportional
+to the number of lines affected by the operation, and the amount given is
+the per-affected-line padding required.
+(In the case of insert-character,
+the factor is still the number of
+.Em lines
+affected;
+this is always 1 unless the terminal has
+.Sy \&in
+and the software uses it.)
+When an `*' is specified, it is sometimes useful to give a delay of the form
+`3.5' to specify a delay per line to tenths of milliseconds.
+(Only one decimal place is allowed.)
+.Pp
+A number of escape sequences are provided in the string-valued capabilities
+for easy encoding of control characters there.
+.Sy \&\eE
+maps to an
+.Dv ESC
+character,
+.Sy \&^X
+maps to a control-X for any appropriate X,
+and the sequences
+.Sy \&\en
+.Sy \&\er
+.Sy \&\et
+.Sy \&\eb
+.Sy \&\ef
+map to linefeed, return, tab, backspace, and formfeed, respectively.
+Finally, characters may be given as three octal digits after a
+.Sy \&\e ,
+and the characters
+.Sy \&^
+and
+.Sy \&\e
+may be given as
+.Sy \&\e^
+and
+.Sy \&\e\e .
+If it is necessary to place a
+.Sy \&:
+in a capability it must be escaped in
+octal as
+.Sy \&\e072 .
+If it is necessary to place a
+.Dv NUL
+character in a string capability it
+must be encoded as
+.Sy \&\e200 .
+(The routines that deal with
+.Nm termcap
+use C strings and strip the high bits of the output very late, so that
+a
+.Sy \&\e200
+comes out as a
+.Sy \&\e000
+would.)
+.Pp
+Sometimes individual capabilities must be commented out.
+To do this, put a period before the capability name.
+For example, see the first
+.Sy \&cr
+and
+.Sy \&ta
+in the example above.
+.Ss Preparing Descriptions
+The most effective way to prepare a terminal description is by imitating
+the description of a similar terminal in
+.Nm termcap
+and to build up a description gradually, using partial descriptions
+with
+.Xr \&vi
+to check that they are correct.
+Be aware that a very unusual terminal may expose deficiencies in
+the ability of the
+.Nm termcap
+file to describe it
+or bugs in
+.Xr \&vi .
+To easily test a new terminal description you are working on
+you can put it in your home directory in a file called
+.Pa .termcap
+and programs will look there before looking in
+.Pa /usr/share/misc/termcap .
+You can also set the environment variable
+.Ev TERMPATH
+to a list of absolute file pathnames (separated by spaces or colons),
+one of which contains the description you are working on,
+and programs will search them in the order listed, and nowhere else.
+See
+.Xr termcap 3 .
+The
+.Ev TERMCAP
+environment variable is usually set to the
+.Nm termcap
+entry itself
+to avoid reading files when starting up a program.
+.Pp
+To get the padding for insert-line right
+(if the terminal manufacturer did not document it),
+a severe test is to use
+.Xr \&vi
+to edit
+.Pa /etc/passwd
+at 9600 baud, delete roughly 16 lines from the middle of the screen,
+then hit the `u' key several times quickly.
+If the display messes up, more padding is usually needed.
+A similar test can be used for insert-character.
+.Ss Basic Capabilities
+The number of columns on each line of the display is given by the
+.Sy \&co
+numeric capability.
+If the display is a
+.Tn CRT ,
+then the
+number of lines on the screen is given by the
+.Sy \&li
+capability.
+If the display wraps around to the beginning of the next line when
+the cursor reaches the right margin, then it should have the
+.Sy \&am
+capability.
+If the terminal can clear its screen,
+the code to do this is given by the
+.Sy \&cl
+string capability.
+If the terminal overstrikes
+(rather than clearing the position when a character is overwritten),
+it should have the
+.Sy \&os
+capability.
+If the terminal is a printing terminal,
+with no soft copy unit,
+give it both
+.Sy \&hc
+and
+.Sy \&os .
+.Pf ( Sy \&os
+applies to storage scope terminals,
+such as the Tektronix 4010 series,
+as well as to hard copy and
+.Tn APL
+terminals.)
+If there is a code to move the cursor to the left edge of the current row,
+give this as
+.Sy \&cr .
+(Normally this will be carriage-return,
+.Sy \&^M . )
+If there is a code to produce an audible signal (bell, beep,
+etc. ) ,
+give this as
+.Sy \&bl .
+.Pp
+If there is a code (such as backspace)
+to move the cursor one position to the left,
+that capability should be given as
+.Sy \&le .
+Similarly,
+codes to move to the right, up, and down
+should be given as
+.Sy \&nd ,
+.Sy \&up ,
+and
+.Sy \&do ,
+respectively.
+These
+.Em local cursor motions
+should not alter the text they pass over;
+for example, you would not normally use
+.Dq nd=\ \&
+unless the terminal has the
+.Sy \&os
+capability,
+because the space would erase the character moved over.
+.Pp
+A very important point here is that the local cursor motions encoded
+in
+.Nm termcap
+have undefined behavior at the left and top edges of a
+.Tn CRT
+display.
+Programs should never attempt to backspace around the left edge,
+unless
+.Sy \&bw
+is given, and never attempt to go up off the top
+using local cursor motions.
+.Pp
+In order to scroll text up,
+a program goes to the bottom left corner of the screen and sends the
+.Sy \&sf
+(index) string.
+To scroll text down,
+a program goes to the top left corner of the screen and sends the
+.Sy \&sr
+(reverse index) string.
+The strings
+.Sy \&sf
+and
+.Sy \&sr
+have undefined behavior
+when not on their respective corners of the screen.
+Parameterized versions of the scrolling sequences are
+.Sy \&SF
+and
+.Sy \&SR ,
+which have the same semantics as
+.Sy \&sf
+and
+.Sy \&sr
+except that they take one parameter
+and scroll that many lines.
+They also have undefined behavior
+except at the appropriate corner of the screen.
+.Pp
+The
+.Sy \&am
+capability tells whether the cursor sticks at the right
+edge of the screen when text is output there,
+but this does not necessarily apply to
+.Sy \&nd
+from the last column.
+Leftward local motion is defined from the left edge only when
+.Sy \&bw
+is given; then an
+.Sy \&le
+from the left edge will move to the right edge of the previous row.
+This is useful for drawing a box around the edge of the screen,
+for example.
+If the terminal has switch-selectable automatic margins,
+the
+.Nm termcap
+description usually assumes that this feature is on,
+.Em i.e . ,
+.Sy \&am .
+If the terminal has a command
+that moves to the first column of the next line,
+that command can be given as
+.Sy \&nw
+(newline).
+It is permissible for this to clear the remainder of the current line,
+so if the terminal has no correctly-working
+.Tn \&CR
+and
+.Tn \&LF
+it may still be possible to craft a working
+.Sy \&nw
+out of one or both of them.
+.Pp
+These capabilities suffice to describe hardcopy and
+.Dq glass-tty
+terminals.
+Thus the Teletype model 33 is described as
+.Bd -literal -offset indent
+T3\||\|tty33\||\|33\||\|tty\||\|Teletype model 33:\e
+	:bl=^G:co#72:cr=^M:do=^J:hc:os:
+.Ed
+.Pp
+and the Lear Siegler
+.Tn ADM Ns \-3
+is described as
+.Bd -literal -offset indent
+l3\||\|adm3\||\|3\||\|LSI \s-1ADM\s0-3:\e
+:am:bl=^G:cl=^Z:co#80:cr=^M:do=^J:le=^H:li#24:sf=^J:
+.Ed
+.Ss Parameterized Strings
+Cursor addressing and other strings requiring parameters
+are described by a
+parameterized string capability, with
+.Xr printf 3 Ns \-like
+escapes
+.Sy \&%x
+in it,
+while other characters are passed through unchanged.
+For example, to address the cursor the
+.Sy \&cm
+capability is given, using two parameters: the row and column to move to.
+(Rows and columns are numbered from zero and refer to the physical screen
+visible to the user, not to any unseen memory.
+If the terminal has memory-relative cursor addressing,
+that can be indicated by an analogous
+.Sy \&CM
+capability.)
+.Pp
+The
+.Sy \&%
+encodings have the following meanings:
+.Bl -column xxxxx
+.It "%%	output `%'"
+.It "%d	output value as in"
+.Xr printf
+%d
+.It "%2	output value as in"
+.Xr printf
+%2d
+.It "%3	output value as in"
+.Xr printf
+%3d
+.It "%.	output value as in"
+.Xr printf
+%c
+.It "%+" Ns Em x Ta No add
+.Em x
+to value, then do %.
+.It "%>" Ns Em \&xy Ta No if
+value >
+.Em x
+then add
+.Em y ,
+no output
+.It "%r	reverse order of two parameters, no output"
+.It "%i	increment by one, no output"
+.It "%n	exclusive-or all parameters with 0140 (Datamedia 2500)"
+.It "%B" Ta Tn BCD No "(16*(value/10)) + (value%10), no output"
+.It "%D	Reverse coding (value \- 2*(value%16)), no output (Delta Data)."
+.El
+.Pp
+Consider the Hewlett-Packard 2645, which, to get to row 3 and column 12, needs
+to be sent
+.Dq \eE&a12c03Y
+padded for 6 milliseconds.
+Note that the order
+of the row and column coordinates is reversed here
+and that the row and column
+are sent as two-digit integers.
+Thus its
+.Sy \&cm
+capability is
+.Dq Li cm=6\eE&%r%2c%2Y .
+.Pp
+The Datamedia 2500 needs the current row and column sent
+encoded in binary using
+.Dq \&%. .
+Terminals that use
+.Dq \&%.
+need to be able to
+backspace the cursor
+.Po Sy \&le Pc
+and to move the cursor up one line on the screen
+.Po Sy \&up Pc .
+This is necessary because it is not always safe to transmit
+.Sy \&\en ,
+.Sy \&^D ,
+and
+.Sy \&\er ,
+as the system may change or discard them.
+(Programs using
+.Nm termcap
+must set terminal modes so that tabs are not expanded, so
+.Sy \&\et
+is safe to send.
+This turns out to be essential for the Ann Arbor 4080.)
+.Pp
+A final example is the Lear Siegler
+.Tn ADM Ns \-3a,
+which offsets row and column
+by a blank character, thus
+.Dq Li cm=\eE=%+ %+\ \& .
+.Pp
+Row or column absolute cursor addressing
+can be given as single parameter capabilities
+.Sy \&ch
+(horizontal position absolute) and
+.Sy \&cv
+(vertical position absolute).
+Sometimes these are shorter than the more general two-parameter sequence
+(as with the Hewlett-Packard 2645) and can be used in preference to
+.Sy \&cm .
+If there are parameterized local motions
+.Pf ( Em e.g . ,
+move
+.Ar n
+positions to the right)
+these can be given as
+.Sy \&DO ,
+.Sy \&LE ,
+.Sy \&RI ,
+and
+.Sy \&UP
+with a single parameter indicating how many positions to move.
+These are primarily useful if the terminal does not have
+.Sy \&cm ,
+such as the Tektronix 4025.
+.Ss Cursor Motions
+.Pp
+If the terminal has a fast way to home the cursor
+(to the very upper left corner of the screen), this can be given as
+.Sy \&ho .
+Similarly, a fast way of getting to the lower left-hand corner
+can be given as
+.Sy \&ll ;
+this may involve going up with
+.Sy \&up
+from the home position,
+but a program should never do this itself (unless
+.Sy \&ll
+does), because it can
+make no assumption about the effect of moving up from the home position.
+Note that the home position is the same as
+cursor address (0,0): to the top left corner of the screen, not of memory.
+(Therefore, the
+.Dq \eEH
+sequence on Hewlett-Packard terminals
+cannot be used for
+.Sy \&ho . )
+.Ss Area Clears
+If the terminal can clear from the current position to the end of the
+line, leaving the cursor where it is, this should be given as
+.Sy \&ce .
+If the terminal can clear from the current position to the end of the
+display, this should be given as
+.Sy \&cd .
+.Sy \&cd
+must only be invoked from the first column of a line.
+(Therefore,
+it can be simulated by a request to delete a large number of lines,
+if a true
+.Sy \&cd
+is not available.)
+.Ss Insert/Delete Line
+If the terminal can open a new blank line
+before the line containing the cursor,
+this should be given as
+.Sy \&al ;
+this must be invoked only from the first
+position of a line.
+The cursor must then appear at the left of the newly blank line.
+If the terminal can delete the line that the cursor is on, this
+should be given as
+.Sy \&dl ;
+this must only be used from the first position on
+the line to be deleted.
+Versions of
+.Sy \&al
+and
+.Sy \&dl
+which take a single parameter
+and insert or delete that many lines
+can be given as
+.Sy \&AL
+and
+.Sy \&DL .
+If the terminal has a settable scrolling region
+(like the VT100),
+the command to set this can be described with the
+.Sy \&cs
+capability,
+which takes two parameters: the top and bottom lines of the scrolling region.
+The cursor position is, alas, undefined after using this command.
+It is possible to get the effect of insert or delete line
+using this command \(em the
+.Sy \&sc
+and
+.Sy \&rc
+(save and restore cursor) commands are also useful.
+Inserting lines at the top or bottom of the screen can also be done using
+.Sy \&sr
+or
+.Sy \&sf
+on many terminals without a true insert/delete line,
+and is often faster even on terminals with those features.
+.Pp
+If the terminal has the ability to define a window as part of memory
+which all commands affect, it should be given as the parameterized string
+.Sy \&wi .
+The four parameters are the starting and ending lines in memory
+and the starting and ending columns in memory, in that order.
+(This
+.Xr terminfo
+capability is described for completeness.
+It is unlikely that any
+.Nm termcap Ns \- using
+program will support it.)
+.Pp
+If the terminal can retain display memory above the screen, then the
+.Sy \&da
+capability should be given;
+if display memory can be retained
+below, then
+.Sy \&db
+should be given.
+These indicate
+that deleting a line or scrolling may bring non-blank lines up from below
+or that scrolling back with
+.Sy \&sr
+may bring down non-blank lines.
+.Ss Insert/Delete Character
+There are two basic kinds of intelligent terminals with respect to
+insert/delete character that can be described using
+.Nm termcap .
+The most common insert/delete character operations affect only the characters
+on the current line and shift characters off the end of the line rigidly.
+Other terminals, such as the Concept\-100 and the Perkin Elmer Owl, make
+a distinction between typed and untyped blanks on the screen, shifting
+upon an insert or delete only to an untyped blank on the screen which is
+either eliminated or expanded to two untyped blanks.
+You can determine
+the kind of terminal you have by clearing the screen then typing
+text separated by cursor motions.
+Type
+.Dq Li abc\ \ \ \ def
+using local
+cursor motions (not spaces) between the
+.Dq abc
+and the
+.Dq def .
+Then position the cursor before the
+.Dq abc
+and put the terminal in insert
+mode.
+If typing characters causes the rest of the line to shift
+rigidly and characters to fall off the end, then your terminal does
+not distinguish between blanks and untyped positions.
+If the
+.Dq abc
+shifts over to the
+.Dq def
+which then move together around the end of the
+current line and onto the next as you insert, then you have the second type of
+terminal and should give the capability
+.Sy \&in ,
+which stands for
+.Dq insert null .
+While these are two logically separate attributes
+(one line
+.Em \&vs .
+multi-line insert mode,
+and special treatment of untyped spaces),
+we have seen no terminals whose insert
+mode cannot be described with the single attribute.
+.Pp
+.Nm Termcap
+can describe both terminals that have an insert mode and terminals
+that send a simple sequence to open a blank position on the current line.
+Give as
+.Sy \&im
+the sequence to get into insert mode.
+Give as
+.Sy \&ei
+the sequence to leave insert mode.
+Now give as
+.Sy \&ic
+any sequence that needs to be sent just before
+each character to be inserted.
+Most terminals with a true insert mode
+will not give
+.Sy \&ic ;
+terminals that use a sequence to open a screen
+position should give it here.
+(If your terminal has both,
+insert mode is usually preferable to
+.Sy \&ic .
+Do not give both unless the terminal actually requires both to be used
+in combination.)
+If post-insert padding is needed, give this as a number of milliseconds
+in
+.Sy \&ip
+(a string option).
+Any other sequence that may need to be
+sent after insertion of a single character can also be given in
+.Sy \&ip .
+If your terminal needs to be placed into an `insert mode'
+and needs a special code preceding each inserted character,
+then both
+.Sy \&im Ns / Sy \&ei
+and
+.Sy \&ic
+can be given, and both will be used.
+The
+.Sy \&IC
+capability, with one parameter
+.Em n ,
+will repeat the effects of
+.Sy \&ic
+.Em n
+times.
+.Pp
+It is occasionally necessary to move around while in insert mode
+to delete characters on the same line
+.Pf ( Em e.g . ,
+if there is a tab after
+the insertion position).
+If your terminal allows motion while in
+insert mode, you can give the capability
+.Sy \&mi
+to speed up inserting
+in this case.
+Omitting
+.Sy \&mi
+will affect only speed.
+Some terminals
+(notably Datamedia's) must not have
+.Sy \&mi
+because of the way their
+insert mode works.
+.Pp
+Finally, you can specify
+.Sy \&dc
+to delete a single character,
+.Sy \&DC
+with one parameter
+.Em n
+to delete
+.Em n
+characters,
+and delete mode by giving
+.Sy \&dm
+and
+.Sy \&ed
+to enter and exit delete mode
+(which is any mode the terminal needs to be placed in for
+.Sy \&dc
+to work).
+.Ss Highlighting, Underlining, and Visible  Bells
+If your terminal has one or more kinds of display attributes,
+these can be represented in a number of different ways.
+You should choose one display form as
+.Em standout mode ,
+representing a good high-contrast, easy-on-the-eyes format
+for highlighting error messages and other attention getters.
+(If you have a choice, reverse video plus half-bright is good,
+or reverse video alone.)
+The sequences to enter and exit standout mode
+are given as
+.Sy \&so
+and
+.Sy \&se ,
+respectively.
+If the code to change into or out of standout
+mode leaves one or even two blank spaces or garbage characters on the screen,
+as the
+.Tn TVI
+912 and Teleray 1061 do,
+then
+.Sy \&sg
+should be given to tell how many characters are left.
+.Pp
+Codes to begin underlining and end underlining can be given as
+.Sy \&us
+and
+.Sy \&ue ,
+respectively.
+Underline mode change garbage is specified by
+.Sy \&ug ,
+similar to
+.Sy \&sg .
+If the terminal has a code to underline the current character and move
+the cursor one position to the right,
+such as the Microterm Mime,
+this can be given as
+.Sy \&uc .
+.Pp
+Other capabilities to enter various highlighting modes include
+.Sy \&mb
+(blinking),
+.Sy \&md
+(bold or extra bright),
+.Sy \&mh
+(dim or half-bright),
+.Sy \&mk
+(blanking or invisible text),
+.Sy \&mp
+(protected),
+.Sy \&mr
+(reverse video),
+.Sy \&me
+(turn off
+.Em all
+attribute modes),
+.Sy \&as
+(enter alternate character set mode), and
+.Sy \&ae
+(exit alternate character set mode).
+Turning on any of these modes singly may or may not turn off other modes.
+.Pp
+If there is a sequence to set arbitrary combinations of mode,
+this should be given as
+.Sy \&sa
+(set attributes), taking 9 parameters.
+Each parameter is either 0 or 1,
+as the corresponding attributes is on or off.
+The 9 parameters are, in order: standout, underline, reverse, blink,
+dim, bold, blank, protect, and alternate character set.
+Not all modes need be supported by
+.Sy \&sa ,
+only those for which corresponding attribute commands exist.
+(It is unlikely that a
+.Nm termcap Ns \-using
+program will support this capability, which is defined for compatibility
+with
+.Xr terminfo . )
+.Pp
+Terminals with the
+.Dq magic cookie
+glitches
+.Pf ( Sy \&sg
+and
+.Sy \&ug ) ,
+rather than maintaining extra attribute bits for each character cell,
+instead deposit special
+.Dq cookies ,
+or
+.Dq garbage characters ,,
+when they receive mode-setting sequences,
+which affect the display algorithm.
+.Pp
+Some terminals,
+such as the Hewlett-Packard 2621,
+automatically leave standout
+mode when they move to a new line or when the cursor is addressed.
+Programs using standout mode
+should exit standout mode on such terminals
+before moving the cursor or sending a newline.
+On terminals where this is not a problem,
+the
+.Sy \&ms
+capability should be present
+to say that this overhead is unnecessary.
+.Pp
+If the terminal has
+a way of flashing the screen to indicate an error quietly
+(a bell replacement),
+this can be given as
+.Sy \&vb ;
+it must not move the cursor.
+.Pp
+If the cursor needs to be made more visible than normal
+when it is not on the bottom line
+(to change, for example, a non-blinking underline into an easier-to-find
+block or blinking underline),
+give this sequence as
+.Sy \&vs .
+If there is a way to make the cursor completely invisible, give that as
+.Sy \&vi .
+The capability
+.Sy \&ve ,
+which undoes the effects of both of these modes,
+should also be given.
+.Pp
+If your terminal correctly displays underlined characters
+(with no special codes needed)
+even though it does not overstrike,
+then you should give the capability
+.Sy \&ul .
+If overstrikes are erasable with a blank,
+this should be indicated by giving
+.Sy \&eo .
+.Ss Keypad
+If the terminal has a keypad that transmits codes when the keys are pressed,
+this information can be given.
+Note that it is not possible to handle
+terminals where the keypad only works in local mode
+(this applies, for example, to the unshifted Hewlett-Packard 2621 keys).
+If the keypad can be set to transmit or not transmit,
+give these codes as
+.Sy \&ks
+and
+.Sy \&ke .
+Otherwise the keypad is assumed to always transmit.
+The codes sent by the left-arrow, right-arrow, up-arrow, down-arrow,
+and home keys can be given as
+.Sy \&kl ,
+.Sy \&kr ,
+.Sy \&ku ,
+.Sy \&kd ,
+and
+.Sy \&kh ,
+respectively.
+If there are function keys such as f0, f1, ..., f9, the codes they send
+can be given as
+.Sy \&k0 ,
+.Sy \&k1 ,
+...,
+.Sy \&k9 .
+If these keys have labels other than the default f0 through f9, the labels
+can be given as
+.Sy \&l0 ,
+.Sy \&l1 ,
+...,
+.Sy \&l9 .
+The codes transmitted by certain other special keys can be given:
+.Sy \&kH
+(home down),
+.Sy \&kb
+(backspace),
+.Sy \&ka
+(clear all tabs),
+.Sy \&kt
+(clear the tab stop in this column),
+.Sy \&kC
+(clear screen or erase),
+.Sy \&kD
+(delete character),
+.Sy \&kL
+(delete line),
+.Sy \&kM
+(exit insert mode),
+.Sy \&kE
+(clear to end of line),
+.Sy \&kS
+(clear to end of screen),
+.Sy \&kI
+(insert character or enter insert mode),
+.Sy \&kA
+(insert line),
+.Sy \&kN
+(next page),
+.Sy \&kP
+(previous page),
+.Sy \&kF
+(scroll forward/down),
+.Sy \&kR
+(scroll backward/up), and
+.Sy \&kT
+(set a tab stop in this column).
+In addition, if the keypad has a 3 by 3 array of keys
+including the four arrow keys, then the other five keys can be given as
+.Sy \&K1 ,
+.Sy \&K2 ,
+.Sy \&K3 ,
+.Sy \&K4 ,
+and
+.Sy \&K5 .
+These keys are useful when the effects of a 3 by 3 directional pad are needed.
+The obsolete
+.Sy \&ko
+capability formerly used to describe
+.Dq other
+function keys has been
+completely supplanted by the above capabilities.
+.Pp
+The
+.Sy \&ma
+entry is also used to indicate arrow keys on terminals that have
+single-character arrow keys.
+It is obsolete but still in use in
+version 2 of
+.Sy \&vi
+which must be run on some minicomputers due to
+memory limitations.
+This field is redundant with
+.Sy \&kl ,
+.Sy \&kr ,
+.Sy \&ku ,
+.Sy \&kd ,
+and
+.Sy \&kh .
+It consists of groups of two characters.
+In each group, the first character is what an arrow key sends, and the
+second character is the corresponding
+.Sy \&vi
+command.
+These commands are
+.Ar h
+for
+.Sy \&kl ,
+.Ar j
+for
+.Sy \&kd ,
+.Ar k
+for
+.Sy \&ku ,
+.Ar l
+for
+.Sy \&kr ,
+and
+.Ar H
+for
+.Sy \&kh .
+For example, the Mime would have
+.Dq Li ma=^Hh^Kj^Zk^Xl
+indicating arrow keys left (^H), down (^K), up (^Z), and right (^X).
+(There is no home key on the Mime.)
+.Ss Tabs and Initialization
+If the terminal needs to be in a special mode when running
+a program that uses these capabilities,
+the codes to enter and exit this mode can be given as
+.Sy \&ti
+and
+.Sy \&te .
+This arises, for example, from terminals like the Concept with more than
+one page of memory.
+If the terminal has only memory-relative cursor addressing and not
+screen-relative cursor addressing,
+a screen-sized window must be fixed into
+the display for cursor addressing to work properly.
+This is also used for the Tektronix 4025, where
+.Sy \&ti
+sets the command character to be the one used by
+.Nm termcap .
+.Pp
+Other capabilities
+include
+.Sy \&is ,
+an initialization string for the terminal,
+and
+.Sy \&if ,
+the name of a file containing long initialization strings.
+These strings are expected to set the terminal into modes
+consistent with the rest of the
+.Nm termcap
+description.
+They are normally sent to the terminal by the
+.Xr tset
+program each time the user logs in.
+They will be printed in the following order:
+.Sy \&is ;
+setting tabs using
+.Sy \&ct
+and
+.Sy \&st ;
+and finally
+.Sy \&if .
+.Pf ( Xr Terminfo
+uses
+.Sy \&i\&1-i2
+instead of
+.Sy \&is
+and runs the program
+.Sy \&iP
+and prints
+.Sy "\&i\&3"
+after the other initializations.)
+A pair of sequences that does a harder reset from a totally unknown state
+can be analogously given as
+.Sy \&rs
+and
+.Sy \&if .
+These strings are output by the
+.Xr reset
+program, which is used when the terminal gets into a wedged state.
+.Pf ( Xr Terminfo
+uses
+.Sy "\&r1-r3"
+instead of
+.Sy \&rs . )
+Commands are normally placed in
+.Sy \&rs
+and
+.Sy \&rf
+only if they produce annoying effects on the screen and are not necessary
+when logging in.
+For example, the command to set the VT100 into 80-column mode
+would normally be part of
+.Sy \&is ,
+but it causes an annoying glitch of the screen and is not normally needed
+since the terminal is usually already in 80-column mode.
+.Pp
+If the terminal has hardware tabs,
+the command to advance to the next tab stop can be given as
+.Sy \&ta
+(usually
+.Sy \&^I ) .
+A
+.Dq backtab
+command which moves leftward to the previous tab stop
+can be given as
+.Sy \&bt .
+By convention,
+if the terminal driver modes indicate that tab stops are being expanded
+by the computer rather than being sent to the terminal,
+programs should not use
+.Sy \&ta
+or
+.Sy \&bt
+even if they are present,
+since the user may not have the tab stops properly set.
+If the terminal has hardware tabs that are initially set every
+.Ar n
+positions when the terminal is powered up, then the numeric parameter
+.Sy \&it
+is given, showing the number of positions between tab stops.
+This is normally used by the
+.Xr tset
+command to determine whether to set the driver mode for hardware tab
+expansion, and whether to set the tab stops.
+If the terminal has tab stops that can be saved in nonvolatile memory, the
+.Nm termcap
+description can assume that they are properly set.
+.Pp
+If there are commands to set and clear tab stops, they can be given as
+.Sy \&ct
+(clear all tab stops) and
+.Sy \&st
+(set a tab stop in the current column of every row).
+If a more complex sequence is needed to set the tabs than can be
+described by this, the sequence can be placed in
+.Sy \&is
+or
+.Sy \&if .
+.Ss Delays
+Certain capabilities control padding in the terminal driver.
+These are primarily needed by hardcopy terminals and are used by the
+.Xr tset
+program to set terminal driver modes appropriately.
+Delays embedded in the capabilities
+.Sy \&cr ,
+.Sy \&sf ,
+.Sy \&le ,
+.Sy \&ff ,
+and
+.Sy \&ta
+will cause the appropriate delay bits to be set in the terminal driver.
+If
+.Sy \&pb
+(padding baud rate) is given, these values can be ignored at baud rates
+below the value of
+.Sy \&pb .
+For
+.Bx 4.2
+.Xr tset ,
+the delays are given as numeric capabilities
+.Sy \&dC ,
+.Sy \&dN ,
+.Sy \&dB ,
+.Sy \&dF ,
+and
+.Sy \&dT
+instead.
+.Ss Miscellaneous
+If the terminal requires other than a
+.Dv NUL
+(zero) character as a pad,
+this can be given as
+.Sy \&pc .
+Only the first character of the
+.Sy \&pc
+string is used.
+.Pp
+If the terminal has commands to save and restore the position of the
+cursor, give them as
+.Sy \&sc
+and
+.Sy \&rc .
+.Pp
+If the terminal has an extra
+.Dq status line
+that is not normally used by
+software, this fact can be indicated.
+If the status line is viewed as an extra line below the bottom line,
+then the capability
+.Sy \&hs
+should be given.
+Special strings to go to a position in the status line and to return
+from the status line can be given as
+.Sy \&ts
+and
+.Sy \&fs .
+.Pf ( Xr \&fs
+must leave the cursor position in the same place that it was before
+.Sy \&ts .
+If necessary, the
+.Sy \&sc
+and
+.Sy \&rc
+strings can be included in
+.Sy \&ts
+and
+.Sy \&fs
+to get this effect.)
+The capability
+.Sy \&ts
+takes one parameter, which is the column number of the status line
+to which the cursor is to be moved.
+If escape sequences and other special commands such as tab work while in
+the status line, the flag
+.Sy \&es
+can be given.
+A string that turns off the status line (or otherwise erases its contents)
+should be given as
+.Sy \&ds .
+The status line is normally assumed to be the same width as the
+rest of the screen,
+.Em i.e . ,
+.Sy \&co .
+If the status line is a different width (possibly because the terminal
+does not allow an entire line to be loaded), then its width in columns
+can be indicated with the numeric parameter
+.Sy \&ws .
+.Pp
+If the terminal can move up or down half a line, this can be
+indicated with
+.Sy \&hu
+(half-line up) and
+.Sy \&hd
+(half-line down).
+This is primarily useful for superscripts and subscripts on hardcopy
+terminals.
+If a hardcopy terminal can eject to the next page (form feed),
+give this as
+.Sy \&ff
+(usually
+.Sy \&^L ) .
+.Pp
+If there is a command to repeat a given character a given number of times
+(to save time transmitting a large number of identical characters),
+this can be indicated with the parameterized string
+.Sy \&rp .
+The first parameter is the character to be repeated and the second is
+the number of times to repeat it.
+(This is a
+.Xr terminfo
+feature that is unlikely to be supported by a program that uses
+.Nm termcap . )
+.Pp
+If the terminal has a settable command character, such as the
+Tektronix 4025, this can be indicated with
+.Sy \&CC .
+A prototype command character is chosen which is used in all capabilities.
+This character is given in the
+.Sy \&CC
+capability to identify it.
+The following convention is supported on some
+.Ux
+systems:
+The environment is to be searched for a
+.Ev \&CC
+variable,
+and if found,
+all occurrences of the prototype character are replaced by the character
+in the environment variable.
+This use of the
+.Ev \&CC
+environment variable
+is a very bad idea, as it conflicts with
+.Xr make 1 .
+.Pp
+Terminal descriptions that do not represent a specific kind of known
+terminal, such as
+.Em switch ,
+.Em dialup ,
+.Em patch ,
+and
+.Xr network ,
+should include the
+.Sy \&gn
+(generic) capability so that programs can complain that they do not know
+how to talk to the terminal.
+(This capability does not apply to
+.Em virtual
+terminal descriptions for which the escape sequences are known.)
+.Pp
+If the terminal uses xoff/xon
+.Pq Tn DC3 Ns / Ns Tn DC1
+handshaking for flow control, give
+.Sy \&xo .
+Padding information should still be included so that routines can make
+better decisions about costs, but actual pad characters will not be
+transmitted.
+.Pp
+If the terminal has a
+.Dq meta key
+which acts as a shift key, setting the
+8th bit of any character transmitted, then this fact can be indicated with
+.Sy \&km .
+Otherwise, software will assume that the 8th bit is parity and it will
+usually be cleared.
+If strings exist to turn this
+.Dq meta mode
+on and off, they can be given as
+.Sy \&mm
+and
+.Sy \&mo .
+.Pp
+If the terminal has more lines of memory than will fit on the screen at once,
+the number of lines of memory can be indicated with
+.Sy \&lm .
+An explicit value of 0 indicates that the number of lines is not fixed,
+but that there is still more memory than fits on the screen.
+.Pp
+If the terminal is one of those supported by the
+.Ux
+system virtual
+terminal protocol, the terminal number can be given as
+.Sy \&vt .
+.Pp
+Media copy strings which control an auxiliary printer
+connected to the terminal can be given as
+.Sy \&ps :
+print the contents of the screen;
+.Sy \&pf :
+turn off the printer; and
+.Sy \&po :
+turn on the printer.
+When the printer is on, all text sent to the terminal will be sent to the
+printer.
+It is undefined whether the text is also displayed on the terminal screen
+when the printer is on.
+A variation
+.Sy \&pO
+takes one parameter and leaves the printer on for as many characters as the
+value of the parameter, then turns the printer off.
+The parameter should not exceed 255.
+All text, including
+.Sy \&pf ,
+is transparently passed to the printer while
+.Sy \&pO
+is in effect.
+.Pp
+Strings to program function keys can be given as
+.Sy \&pk ,
+.Sy \&pl ,
+and
+.Sy \&px .
+Each of these strings takes two parameters: the function key number
+to program (from 0 to 9) and the string to program it with.
+Function key numbers out of this range may program undefined keys
+in a terminal-dependent manner.
+The differences among the capabilities are that
+.Sy \&pk
+causes pressing the given key to be the same as the user typing the given
+string;
+.Sy \&pl
+causes the string to be executed by the terminal in local mode;
+and
+.Sy \&px
+causes the string to be transmitted to the computer.
+Unfortunately, due to lack of a definition for string parameters in
+.Nm termcap ,
+only
+.Xr terminfo
+supports these capabilities.
+.Ss Glitches and Braindamage
+Hazeltine terminals, which do not allow `~' characters to be displayed,
+should indicate
+.Sy \&hz .
+.Pp
+The
+.Sy \&nc
+capability, now obsolete, formerly indicated Datamedia terminals,
+which echo
+.Sy \&\er \en
+for
+carriage return then ignore a following linefeed.
+.Pp
+Terminals that ignore a linefeed immediately after an
+.Sy \&am
+wrap, such as the Concept, should indicate
+.Sy \&xn .
+.Pp
+If
+.Sy \&ce
+is required to get rid of standout
+(instead of merely writing normal text on top of it),
+.Sy \&xs
+should be given.
+.Pp
+Teleray terminals, where tabs turn all characters moved over to blanks,
+should indicate
+.Sy \&xt
+(destructive tabs).
+This glitch is also taken to mean that it is not possible
+to position the cursor on top of a \*(lqmagic cookie\*(rq, and that
+to erase standout mode it is necessary to use delete and insert line.
+.Pp
+The Beehive Superbee, which is unable to correctly transmit the
+.Dv ESC
+or
+.Sy \&^C
+characters, has
+.Sy \&xb ,
+indicating that the
+.Dq \&f\&1
+key is used for
+.Dv ESC
+and
+.Dq \&f\&2
+for ^C.
+(Only certain Superbees have this problem, depending on the
+.Tn ROM . )
+.Pp
+Other specific terminal problems may be corrected by adding more
+capabilities of the form
+.Sy x Em x .
+.Ss Similar Terminals
+If there are two very similar terminals,
+one can be defined as being just like the other with certain exceptions.
+The string capability
+.Sy \&tc
+can be given
+with the name of the similar terminal.
+This capability must be
+.Em last ,
+and the combined length of the entries
+must not exceed 1024.
+The capabilities given before
+.Sy \&tc
+override those in the terminal type invoked by
+.Sy \&tc .
+A capability can be canceled by placing
+.Sy \&xx@
+to the left of the
+.Sy \&tc
+invocation, where
+.Sy \&xx
+is the capability.
+For example, the entry
+.Bd -literal -offset indent
+hn\||\|2621\-nl:ks@:ke@:tc=2621:
+.Ed
+.Pp
+defines a
+.Dq 2621\-nl
+that does not have the
+.Sy \&ks
+or
+.Sy \&ke
+capabilities,
+hence does not turn on the function key labels when in visual mode.
+This is useful for different modes for a terminal, or for different
+user preferences.
+.Sh FILES
+.Bl -tag -width /usr/share/misc/termcap.db -compact
+.It Pa /usr/share/misc/termcap
+File containing terminal descriptions.
+.It Pa /usr/share/misc/termcap.db
+Hash database file containing terminal descriptions (see 
+.Xr cap_mkdb 1 ) .
+.El
+.Sh SEE ALSO
+.Xr \&ex 1 ,
+.Xr cap_mkdb 1 ,
+.Xr more 1 ,
+.Xr tset 1 ,
+.Xr \&ul 1 ,
+.Xr vi 1 ,
+.Xr curses 3 ,
+.Xr printf 3 ,
+.Xr termcap 3 ,
+.Xr term 7
+.Sh CAVEATS AND BUGS
+The
+.Em Note :
+.Nm termcap
+functions
+were replaced by
+.Xr terminfo
+in
+.At V
+Release 2.0.
+The transition will be relatively painless if capabilities flagged as
+.Dq obsolete
+are avoided.
+.Pp
+Lines and columns are now stored by the kernel as well as in the termcap
+entry.
+Most programs now use the kernel information primarily; the information
+in this file is used only if the kernel does not have any information.
+.Pp
+.Xr \&Vi
+allows only 256 characters for string capabilities, and the routines
+in
+.Xr termlib 3
+do not check for overflow of this buffer.
+The total length of a single entry (excluding only escaped newlines)
+may not exceed 1024.
+.Pp
+Not all programs support all entries.
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Bx 3 .
Index: /branches/EMX/src/emx/bsd/libterm/termcap.c
===================================================================
--- /branches/EMX/src/emx/bsd/libterm/termcap.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/libterm/termcap.c	(revision 273)
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 1980 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)termcap.c	5.5 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#define	BUFSIZ		1024
+#define MAXHOP		32	/* max number of tc= indirections */
+#define	PBUFSIZ		512	/* max length of filename path */
+#define	PVECSIZ		32	/* max number of names in path */
+
+#include <ctype.h>
+#ifdef EMX
+#include <string.h>
+#include <fcntl.h>
+#define	_PATH_DEF	".termcap /emx/etc/termcap.dat"
+#else /* not EMX */
+#include "pathnames.h"
+#endif /* not EMX */
+
+/*
+ * termcap - routines for dealing with the terminal capability data base
+ *
+ * BUG:		Should use a "last" pointer in tbuf, so that searching
+ *		for capabilities alphabetically would not be a n**2/2
+ *		process when large numbers of capabilities are given.
+ * Note:	If we add a last pointer now we will screw up the
+ *		tc capability. We really should compile termcap.
+ *
+ * Essentially all the work here is scanning and decoding escapes
+ * in string capabilities.  We don't use stdio because the editor
+ * doesn't, and because living w/o it is not hard.
+ */
+
+static	char *tbuf;
+static	int hopcount;	/* detect infinite loops in termcap, init 0 */
+static	char pathbuf[PBUFSIZ];		/* holds raw path of filenames */
+static	char *pathvec[PVECSIZ];		/* to point to names in pathbuf */
+static	char **pvec;			/* holds usable tail of path vector */
+char	*tskip();
+char	*tgetstr();
+char	*tdecode();
+char	*getenv();
+
+/*
+ * Get an entry for terminal name in buffer bp from the termcap file.
+ */
+tgetent(bp, name)
+	char *bp, *name;
+{
+	register char *p;
+	register char *cp;
+	register int c;
+	char *term, *home, *termpath;
+	char **fname = pathvec;
+
+	pvec = pathvec;
+	tbuf = bp;
+	p = pathbuf;
+	cp = getenv("TERMCAP");
+	/*
+	 * TERMCAP can have one of two things in it. It can be the
+	 * name of a file to use instead of /etc/termcap. In this
+	 * case it better start with a "/". Or it can be an entry to
+	 * use so we don't have to read the file. In this case it
+	 * has to already have the newlines crunched out.  If TERMCAP
+	 * does not hold a file name then a path of names is searched
+	 * instead.  The path is found in the TERMPATH variable, or
+	 * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists.
+	 */
+#ifdef EMX
+	if (!cp || (*cp != '/' && *cp != '\\' && !_fngetdrive (cp))) {
+#else /* not EMX */
+	if (!cp || *cp != '/') {	/* no TERMCAP or it holds an entry */
+#endif /* not EMX */
+		if (termpath = getenv("TERMPATH"))
+			strncpy(pathbuf, termpath, PBUFSIZ);
+		else {
+			if (home = getenv("HOME")) {	/* set up default */
+				p += strlen(home);	/* path, looking in */
+				strcpy(pathbuf, home);	/* $HOME first */
+#ifdef EMX
+				if (*home && strchr ("/\\:", p[-1]) == NULL)
+				  *p++ = '/';
+#else /* not EMX */
+				*p++ = '/';
+#endif /* not EMX */
+			}	/* if no $HOME look in current directory */
+			strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf));
+		}
+	}
+	else				/* user-defined name in TERMCAP */
+		strncpy(pathbuf, cp, PBUFSIZ);	/* still can be tokenized */
+
+	*fname++ = pathbuf;	/* tokenize path into vector of names */
+	while (*++p)
+#ifdef EMX
+		if (*p == ' ' || *p == ';') {
+#else /* not EMX */
+		if (*p == ' ' || *p == ':') {
+#endif /* not EMX */
+			*p = '\0';
+			while (*++p)
+#ifdef EMX
+				if (*p != ' ' && *p != ';')
+#else /* not EMX */
+				if (*p != ' ' && *p != ':')
+#endif /* not EMX */
+					break;
+			if (*p == '\0')
+				break;
+			*fname++ = p;
+			if (fname >= pathvec + PVECSIZ) {
+				fname--;
+				break;
+			}
+		}
+	*fname = (char *) 0;			/* mark end of vector */
+#ifdef EMX
+	if (cp && *cp && *cp != '/' && *cp != '\\' && !_fngetdrive (cp)) {
+#else /* not EMX */
+	if (cp && *cp && *cp != '/') {
+#endif /* not EMX */
+		tbuf = cp;
+		c = tnamatch(name);
+		tbuf = bp;
+		if (c) {
+			strcpy(bp,cp);
+			return (tnchktc());
+		}
+	}
+	return (tfindent(bp, name));	/* find terminal entry in path */
+}
+
+/*
+ * tfindent - reads through the list of files in pathvec as if they were one
+ * continuous file searching for terminal entries along the way.  It will
+ * participate in indirect recursion if the call to tnchktc() finds a tc=
+ * field, which is only searched for in the current file and files ocurring
+ * after it in pathvec.  The usable part of this vector is kept in the global
+ * variable pvec.  Terminal entries may not be broken across files.  Parse is
+ * very rudimentary; we just notice escaped newlines.
+ */
+tfindent(bp, name)
+	char *bp, *name;
+{
+	register char *cp;
+	register int c;
+	register int i, cnt;
+	char ibuf[BUFSIZ];
+	int opencnt = 0;
+	int tf;
+
+	tbuf = bp;
+nextfile:
+	i = cnt = 0;
+#ifdef EMX
+	while (*pvec && (tf = open(*pvec, O_RDONLY | O_TEXT)) < 0)
+#else /* not EMX */
+	while (*pvec && (tf = open(*pvec, 0)) < 0)
+#endif /* not EMX */
+		pvec++;
+	if (!*pvec)
+		return (opencnt ? 0 : -1);
+	opencnt++;
+	for (;;) {
+		cp = bp;
+		for (;;) {
+			if (i == cnt) {
+				cnt = read(tf, ibuf, BUFSIZ);
+				if (cnt <= 0) {
+					close(tf);
+					pvec++;
+					goto nextfile;
+				}
+				i = 0;
+			}
+			c = ibuf[i++];
+			if (c == '\n') {
+				if (cp > bp && cp[-1] == '\\'){
+					cp--;
+					continue;
+				}
+				break;
+			}
+			if (cp >= bp+BUFSIZ) {
+				write(2,"Termcap entry too long\n", 23);
+				break;
+			} else
+				*cp++ = c;
+		}
+		*cp = 0;
+
+		/*
+		 * The real work for the match.
+		 */
+		if (tnamatch(name)) {
+			close(tf);
+			return(tnchktc());
+		}
+	}
+}
+
+/*
+ * tnchktc: check the last entry, see if it's tc=xxx. If so,
+ * recursively find xxx and append that entry (minus the names)
+ * to take the place of the tc=xxx entry. This allows termcap
+ * entries to say "like an HP2621 but doesn't turn on the labels".
+ * Note that this works because of the left to right scan.
+ */
+tnchktc()
+{
+	register char *p, *q;
+	char tcname[16];	/* name of similar terminal */
+	char tcbuf[BUFSIZ];
+	char *holdtbuf = tbuf;
+	int l;
+
+	p = tbuf + strlen(tbuf) - 2;	/* before the last colon */
+	while (*--p != ':')
+		if (p<tbuf) {
+			write(2, "Bad termcap entry\n", 18);
+			return (0);
+		}
+	p++;
+	/* p now points to beginning of last field */
+	if (p[0] != 't' || p[1] != 'c')
+		return(1);
+	strcpy(tcname,p+3);
+	q = tcname;
+	while (*q && *q != ':')
+		q++;
+	*q = 0;
+	if (++hopcount > MAXHOP) {
+		write(2, "Infinite tc= loop\n", 18);
+		return (0);
+	}
+	if (tfindent(tcbuf, tcname) != 1) {
+		hopcount = 0;		/* unwind recursion */
+		return(0);
+	}
+	for (q=tcbuf; *q != ':'; q++)
+		;
+	l = p - holdtbuf + strlen(q);
+	if (l > BUFSIZ) {
+		write(2, "Termcap entry too long\n", 23);
+		q[BUFSIZ - (p-tbuf)] = 0;
+	}
+	strcpy(p, q+1);
+	tbuf = holdtbuf;
+	hopcount = 0;			/* unwind recursion */
+	return(1);
+}
+
+/*
+ * Tnamatch deals with name matching.  The first field of the termcap
+ * entry is a sequence of names separated by |'s, so we compare
+ * against each such name.  The normal : terminator after the last
+ * name (before the first field) stops us.
+ */
+tnamatch(np)
+	char *np;
+{
+	register char *Np, *Bp;
+
+	Bp = tbuf;
+	if (*Bp == '#')
+		return(0);
+	for (;;) {
+		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
+			continue;
+		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
+			return (1);
+		while (*Bp && *Bp != ':' && *Bp != '|')
+			Bp++;
+		if (*Bp == 0 || *Bp == ':')
+			return (0);
+		Bp++;
+	}
+}
+
+/*
+ * Skip to the next field.  Notice that this is very dumb, not
+ * knowing about \: escapes or any such.  If necessary, :'s can be put
+ * into the termcap file in octal.
+ */
+static char *
+tskip(bp)
+	register char *bp;
+{
+
+	while (*bp && *bp != ':')
+		bp++;
+	if (*bp == ':')
+		bp++;
+	return (bp);
+}
+
+/*
+ * Return the (numeric) option id.
+ * Numeric options look like
+ *	li#80
+ * i.e. the option string is separated from the numeric value by
+ * a # character.  If the option is not found we return -1.
+ * Note that we handle octal numbers beginning with 0.
+ */
+tgetnum(id)
+	char *id;
+{
+	register int i, base;
+	register char *bp = tbuf;
+
+	for (;;) {
+		bp = tskip(bp);
+		if (*bp == 0)
+			return (-1);
+		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+			continue;
+		if (*bp == '@')
+			return(-1);
+		if (*bp != '#')
+			continue;
+		bp++;
+		base = 10;
+		if (*bp == '0')
+			base = 8;
+		i = 0;
+		while (isdigit(*bp))
+			i *= base, i += *bp++ - '0';
+		return (i);
+	}
+}
+
+/*
+ * Handle a flag option.
+ * Flag options are given "naked", i.e. followed by a : or the end
+ * of the buffer.  Return 1 if we find the option, or 0 if it is
+ * not given.
+ */
+tgetflag(id)
+	char *id;
+{
+	register char *bp = tbuf;
+
+	for (;;) {
+		bp = tskip(bp);
+		if (!*bp)
+			return (0);
+		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+			if (!*bp || *bp == ':')
+				return (1);
+			else if (*bp == '@')
+				return(0);
+		}
+	}
+}
+
+/*
+ * Get a string valued option.
+ * These are given as
+ *	cl=^Z
+ * Much decoding is done on the strings, and the strings are
+ * placed in area, which is a ref parameter which is updated.
+ * No checking on area overflow.
+ */
+char *
+tgetstr(id, area)
+	char *id, **area;
+{
+	register char *bp = tbuf;
+
+	for (;;) {
+		bp = tskip(bp);
+		if (!*bp)
+			return (0);
+		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+			continue;
+		if (*bp == '@')
+			return(0);
+		if (*bp != '=')
+			continue;
+		bp++;
+		return (tdecode(bp, area));
+	}
+}
+
+/*
+ * Tdecode does the grung work to decode the
+ * string capability escapes.
+ */
+static char *
+tdecode(str, area)
+	register char *str;
+	char **area;
+{
+	register char *cp;
+	register int c;
+	register char *dp;
+	int i;
+
+	cp = *area;
+	while ((c = *str++) && c != ':') {
+		switch (c) {
+
+		case '^':
+			c = *str++ & 037;
+			break;
+
+		case '\\':
+			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
+			c = *str++;
+nextc:
+			if (*dp++ == c) {
+				c = *dp++;
+				break;
+			}
+			dp++;
+			if (*dp)
+				goto nextc;
+			if (isdigit(c)) {
+				c -= '0', i = 2;
+				do
+					c <<= 3, c |= *str++ - '0';
+				while (--i && isdigit(*str));
+			}
+			break;
+		}
+		*cp++ = c;
+	}
+	*cp++ = 0;
+	str = *area;
+	*area = cp;
+	return (str);
+}
Index: /branches/EMX/src/emx/bsd/libterm/tgoto.c
===================================================================
--- /branches/EMX/src/emx/bsd/libterm/tgoto.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/libterm/tgoto.c	(revision 273)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1980 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)tgoto.c	5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#define	CTRL(c)	((c) & 037)
+
+#define MAXRETURNSIZE 64
+
+char	*UP;
+char	*BC;
+
+/*
+ * Routine to perform cursor addressing.
+ * CM is a string containing printf type escapes to allow
+ * cursor addressing.  We start out ready to print the destination
+ * line, and switch each time we print row or column.
+ * The following escapes are defined for substituting row/column:
+ *
+ *	%d	as in printf
+ *	%2	like %2d
+ *	%3	like %3d
+ *	%.	gives %c hacking special case characters
+ *	%+x	like %c but adding x first
+ *
+ *	The codes below affect the state but don't use up a value.
+ *
+ *	%>xy	if value > x add y
+ *	%r	reverses row/column
+ *	%i	increments row/column (for one origin indexing)
+ *	%%	gives %
+ *	%B	BCD (2 decimal digits encoded in one byte)
+ *	%D	Delta Data (backwards bcd)
+ *
+ * all other characters are ``self-inserting''.
+ */
+char *
+tgoto(CM, destcol, destline)
+	char *CM;
+	int destcol, destline;
+{
+	static char result[MAXRETURNSIZE];
+	static char added[10];
+	char *cp = CM;
+	register char *dp = result;
+	register int c;
+	int oncol = 0;
+	register int which = destline;
+
+	if (cp == 0) {
+toohard:
+		/*
+		 * ``We don't do that under BOZO's big top''
+		 */
+		return ("OOPS");
+	}
+	added[0] = 0;
+	while (c = *cp++) {
+		if (c != '%') {
+			*dp++ = c;
+			continue;
+		}
+		switch (c = *cp++) {
+
+#ifdef CM_N
+		case 'n':
+			destcol ^= 0140;
+			destline ^= 0140;
+			goto setwhich;
+#endif
+
+		case 'd':
+			if (which < 10)
+				goto one;
+			if (which < 100)
+				goto two;
+			/* fall into... */
+
+		case '3':
+			*dp++ = (which / 100) | '0';
+			which %= 100;
+			/* fall into... */
+
+		case '2':
+two:	
+			*dp++ = which / 10 | '0';
+one:
+			*dp++ = which % 10 | '0';
+swap:
+			oncol = 1 - oncol;
+setwhich:
+			which = oncol ? destcol : destline;
+			continue;
+
+#ifdef CM_GT
+		case '>':
+			if (which > *cp++)
+				which += *cp++;
+			else
+				cp++;
+			continue;
+#endif
+
+		case '+':
+			which += *cp++;
+			/* fall into... */
+
+		case '.':
+casedot:
+			/*
+			 * This code is worth scratching your head at for a
+			 * while.  The idea is that various weird things can
+			 * happen to nulls, EOT's, tabs, and newlines by the
+			 * tty driver, arpanet, and so on, so we don't send
+			 * them if we can help it.
+			 *
+			 * Tab is taken out to get Ann Arbors to work, otherwise
+			 * when they go to column 9 we increment which is wrong
+			 * because bcd isn't continuous.  We should take out
+			 * the rest too, or run the thing through more than
+			 * once until it doesn't make any of these, but that
+			 * would make termlib (and hence pdp-11 ex) bigger,
+			 * and also somewhat slower.  This requires all
+			 * programs which use termlib to stty tabs so they
+			 * don't get expanded.  They should do this anyway
+			 * because some terminals use ^I for other things,
+			 * like nondestructive space.
+			 */
+			if (which == 0 || which == CTRL('d') || /* which == '\t' || */ which == '\n') {
+				if (oncol || UP) /* Assumption: backspace works */
+					/*
+					 * Loop needed because newline happens
+					 * to be the successor of tab.
+					 */
+					do {
+						strcat(added, oncol ? (BC ? BC : "\b") : UP);
+						which++;
+					} while (which == '\n');
+			}
+			*dp++ = which;
+			goto swap;
+
+		case 'r':
+			oncol = 1;
+			goto setwhich;
+
+		case 'i':
+			destcol++;
+			destline++;
+			which++;
+			continue;
+
+		case '%':
+			*dp++ = c;
+			continue;
+
+#ifdef CM_B
+		case 'B':
+			which = (which/10 << 4) + which%10;
+			continue;
+#endif
+
+#ifdef CM_D
+		case 'D':
+			which = which - 2 * (which%16);
+			continue;
+#endif
+
+		default:
+			goto toohard;
+		}
+	}
+	strcpy(dp, added);
+	return (result);
+}
Index: /branches/EMX/src/emx/bsd/libterm/tputs.c
===================================================================
--- /branches/EMX/src/emx/bsd/libterm/tputs.c	(revision 273)
+++ /branches/EMX/src/emx/bsd/libterm/tputs.c	(revision 273)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1980 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)tputs.c	5.3 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#include <sgtty.h>
+#include <ctype.h>
+
+/*
+ * The following array gives the number of tens of milliseconds per
+ * character for each speed as returned by gtty.  Thus since 300
+ * baud returns a 7, there are 33.3 milliseconds per char at 300 baud.
+ */
+static
+short	tmspc10[] = {
+	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
+};
+
+short	ospeed;
+char	PC;
+
+/*
+ * Put the character string cp out, with padding.
+ * The number of affected lines is affcnt, and the routine
+ * used to output one character is outc.
+ */
+tputs(cp, affcnt, outc)
+	register char *cp;
+	int affcnt;
+	int (*outc)();
+{
+	register int i = 0;
+	register int mspc10;
+
+	if (cp == 0)
+		return;
+
+	/*
+	 * Convert the number representing the delay.
+	 */
+	if (isdigit(*cp)) {
+		do
+			i = i * 10 + *cp++ - '0';
+		while (isdigit(*cp));
+	}
+	i *= 10;
+	if (*cp == '.') {
+		cp++;
+		if (isdigit(*cp))
+			i += *cp - '0';
+		/*
+		 * Only one digit to the right of the decimal point.
+		 */
+		while (isdigit(*cp))
+			cp++;
+	}
+
+	/*
+	 * If the delay is followed by a `*', then
+	 * multiply by the affected lines count.
+	 */
+	if (*cp == '*')
+		cp++, i *= affcnt;
+
+	/*
+	 * The guts of the string.
+	 */
+	while (*cp)
+		(*outc)(*cp++);
+
+	/*
+	 * If no delay needed, or output speed is
+	 * not comprehensible, then don't try to delay.
+	 */
+	if (i == 0)
+		return;
+	if (ospeed <= 0 || ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
+		return;
+
+	/*
+	 * Round up by a half a character frame,
+	 * and then do the delay.
+	 * Too bad there are no user program accessible programmed delays.
+	 * Transmitting pad characters slows many
+	 * terminals down and also loads the system.
+	 */
+	mspc10 = tmspc10[ospeed];
+	i += mspc10 / 2;
+	for (i /= mspc10; i > 0; i--)
+		(*outc)(PC);
+}
