summaryrefslogtreecommitdiff
path: root/ext/SDBM_File
diff options
context:
space:
mode:
authorLarry Wall <lwall@netlabs.com>1994-10-17 23:00:00 +0000
committerLarry Wall <lwall@netlabs.com>1994-10-17 23:00:00 +0000
commita0d0e21ea6ea90a22318550944fe6cb09ae10cda (patch)
treefaca1018149b736b1142f487e44d1ff2de5cc1fa /ext/SDBM_File
parent85e6fe838fb25b257a1b363debf8691c0992ef71 (diff)
downloadperl-a0d0e21ea6ea90a22318550944fe6cb09ae10cda.tar.gz
perl 5.000perl-5.000
[editor's note: this commit combines approximate 4 months of furious releases of Andy Dougherty and Larry Wall - see pod/perlhist.pod for details. Andy notes that; Alas neither my "Irwin AccuTrack" nor my DC 600A quarter-inch cartridge backup tapes from that era seem to be readable anymore. I guess 13 years exceeds the shelf life for that backup technology :-(. ]
Diffstat (limited to 'ext/SDBM_File')
-rw-r--r--ext/SDBM_File/Makefile.SH216
-rw-r--r--ext/SDBM_File/SDBM_File.pm11
-rw-r--r--ext/SDBM_File/SDBM_File.xs71
-rw-r--r--ext/SDBM_File/sdbm/CHANGES18
-rw-r--r--ext/SDBM_File/sdbm/COMPARE88
-rw-r--r--ext/SDBM_File/sdbm/Makefile.SH99
-rw-r--r--ext/SDBM_File/sdbm/README396
-rw-r--r--ext/SDBM_File/sdbm/README.too9
-rw-r--r--ext/SDBM_File/sdbm/biblio64
-rw-r--r--ext/SDBM_File/sdbm/dba.c84
-rw-r--r--ext/SDBM_File/sdbm/dbd.c110
-rw-r--r--ext/SDBM_File/sdbm/dbe.146
-rw-r--r--ext/SDBM_File/sdbm/dbe.c435
-rw-r--r--ext/SDBM_File/sdbm/dbm.c120
-rw-r--r--ext/SDBM_File/sdbm/dbm.h35
-rw-r--r--ext/SDBM_File/sdbm/dbu.c250
-rwxr-xr-xext/SDBM_File/sdbm/grind9
-rw-r--r--ext/SDBM_File/sdbm/hash.c48
-rw-r--r--ext/SDBM_File/sdbm/linux.patches67
-rw-r--r--ext/SDBM_File/sdbm/makefile.sdbm55
-rw-r--r--ext/SDBM_File/sdbm/pair.c307
-rw-r--r--ext/SDBM_File/sdbm/pair.h10
-rw-r--r--ext/SDBM_File/sdbm/readme.ms353
-rw-r--r--ext/SDBM_File/sdbm/readme.ps2225
-rw-r--r--ext/SDBM_File/sdbm/sdbm.3290
-rw-r--r--ext/SDBM_File/sdbm/sdbm.c520
-rw-r--r--ext/SDBM_File/sdbm/sdbm.h234
-rw-r--r--ext/SDBM_File/sdbm/tune.h23
-rw-r--r--ext/SDBM_File/sdbm/util.c50
-rw-r--r--ext/SDBM_File/typemap25
30 files changed, 6268 insertions, 0 deletions
diff --git a/ext/SDBM_File/Makefile.SH b/ext/SDBM_File/Makefile.SH
new file mode 100644
index 0000000000..1f181e3b09
--- /dev/null
+++ b/ext/SDBM_File/Makefile.SH
@@ -0,0 +1,216 @@
+: This forces SH files to create target in same directory as SH file.
+: This is so that make depend always knows where to find SH derivatives.
+
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+
+if test -f config.sh; then TOP=.;
+elif test -f ../config.sh; then TOP=..;
+elif test -f ../../config.sh; then TOP=../..;
+elif test -f ../../../config.sh; then TOP=../../..;
+elif test -f ../../../../config.sh; then TOP=../../../..;
+else
+ echo "Can't find config.sh."; exit 1
+fi
+
+: Find absolute path name for TOP. This is needed when we cd to TOP
+: to run perl on autosplit.
+oldpwd=`pwd`; cd $TOP; ABSTOP=`pwd`; cd $oldpwd
+
+case $CONFIG in
+'')
+ . $TOP/config.sh
+ ;;
+esac
+
+: Find out directory name. This is also the extension name.
+ext=`pwd | $sed -e 's@.*/@@'`
+
+: This extension might have its own typemap
+if test -f typemap; then
+ exttypemap='typemap'
+else
+ exttypemap=''
+fi
+
+: This extension might need additional libraries.
+potential_libs=" "
+. $TOP/ext/util/extliblist
+
+: This extension might need bootstrap support
+if test -f ${ext}_BS; then
+ bootdep=${ext}_BS
+else
+ bootdep=''
+fi
+
+case "$dlsrc" in
+dl_aix*)
+ echo "#!" > $ext.exp
+ echo "boot_$ext" >> $ext.exp
+ ;;
+esac
+
+echo "Extracting ext/$ext/Makefile (with variable substitutions)"
+: This section of the file will have variable substitutions done on it.
+: Move anything that needs config subs from !NO!SUBS! section to !GROK!THIS!.
+: Protect any dollar signs and backticks that you do not want interpreted
+: by putting a backslash in front. You may delete these comments.
+$spitshell >Makefile << !GROK!THIS!
+#
+# This Makefile is for the $ext extension to perl.
+#
+CC = $cc
+RANLIB = $ranlib
+TOP = $TOP
+ABSTOP = $ABSTOP
+LDFLAGS = $ldflags
+CLDFLAGS = $ldflags
+SMALL = $small
+LARGE = $large $split
+
+# To use an alternate make, set \$altmake in config.sh.
+MAKE = ${altmake-make}
+
+EXT = $ext
+
+# $ext might have its own typemap
+EXTTYPEMAP = $exttypemap
+
+# $ext might have its own bootstrap support
+BOOTDEP = $bootdep
+BOOTSTRAP = $ext.bs
+
+# The following are used to build and install shared libraries for
+# dynamic loading.
+LDDLFLAGS = $lddlflags
+CCDLFLAGS = $ccdlflags
+CCCDLFLAGS = $cccdlflags
+SO = $so
+DLEXT = $dlext
+
+# $ext might need to be linked with some extra libraries.
+# EXTRALIBS = full list of libraries needed for static linking.
+# Only those libraries that actually exist are included.
+# DYNLOADLIBS = list of those libraries that are needed but can be
+# linked in dynamically on this platform. On SunOS, for
+# example, this would be .so* libraries, but not archive
+# libraries. The bootstrap file is installed only if
+# this list is not empty.
+# STATLOADLIBS = list of those libraries which must be statically
+# linked into the shared library. On SunOS 4.1.3,
+# for example, I have only an archive version of
+# -lm, and it must be linked in statically.
+EXTRALIBS = $extralibs
+DYNALOADLIBS = $dynaloadlibs
+STATLOADLIBS = $statloadlibs
+
+!GROK!THIS!
+
+$spitshell >>Makefile <<'!NO!SUBS!'
+
+# Where to put things:
+AUTO = $(TOP)/lib/auto
+INSTALLBOOT = $(AUTO)/$(EXT)/$(EXT).bs
+INSTALLDYNAMIC = $(AUTO)/$(EXT)/$(EXT).$(DLEXT)
+INSTALLSTATIC = $(EXT).a
+INSTALLPM = $(TOP)/lib/$(EXT).pm
+
+PERL = $(ABSTOP)/miniperl
+XSUBPP = $(TOP)/ext/xsubpp
+SHELL = /bin/sh
+CCCMD = `sh $(shellflags) $(TOP)/cflags $@`
+
+.c.o:
+ $(CCCMD) $(CCCDLFLAGS) -I$(TOP) $*.c
+
+all: dynamic
+# Phony target to force checking subdirectories.
+FORCE:
+
+config:
+
+# Target for Dynamic Loading:
+dynamic: $(INSTALLDYNAMIC) $(INSTALLPM) $(INSTALLBOOT)
+
+$(INSTALLDYNAMIC): $(EXT).o sdbm/libsdbm.a
+ @test -d $(AUTO) || mkdir $(AUTO)
+ @test -d $(AUTO)/$(EXT) || mkdir $(AUTO)/$(EXT)
+ ld $(LDDLFLAGS) -o $@ $(EXT).o sdbm/libsdbm.a $(STATLOADLIBS)
+
+$(BOOTSTRAP): Makefile $(BOOTDEP)
+ $(PERL) -I$(TOP)/lib $(TOP)/ext/util/mkbootstrap $(DYNALOADLIBS)
+ touch $(BOOTSTRAP)
+
+$(INSTALLBOOT): $(BOOTSTRAP)
+ @test ! -s $(BOOTSTRAP) || cp $(BOOTSTRAP) $@
+
+# Target for Static Loading:
+static: $(INSTALLSTATIC) $(INSTALLPM)
+
+$(INSTALLSTATIC): $(EXT).o sdbm/libsdbm.a
+ cp sdbm/libsdbm.a $@
+ ar r $@ $(EXT).o
+ $(RANLIB) $@
+ echo $(EXTRALIBS) >> $(TOP)/ext.libs
+
+$(EXT).c: $(EXT).xs $(XSUBPP) $(TOP)/ext/typemap $(EXTTYPEMAP) $(TOP)/cflags Makefile
+ $(PERL) $(XSUBPP) $(EXT).xs >tmp
+ mv tmp $@
+
+sdbm/libsdbm.a: FORCE
+ @cd sdbm; \
+ if test ! -f Makefile ; then \
+ test -f Makefile.SH && sh Makefile.SH ; \
+ fi ; $(MAKE)
+
+$(INSTALLPM): $(EXT).pm
+ rm -f $@
+ cp $(EXT).pm $@
+ cd $(TOP); $(PERL) autosplit $(EXT)
+
+clean:
+ -cd sdbm; $(MAKE) clean
+ rm -f *.o *.a mon.out core $(EXT).c so_locations $(BOOTSTRAP) $(EXT).exp
+
+realclean: clean
+ -cd sdbm; $(MAKE) realclean
+ rm -f makefile Makefile
+ rm -f $(INSTALLPM) $(INSTALLDYNAMIC) $(INSTALLSTATIC) $(INSTALLBOOT)
+ rm -rf $(AUTO)/$(EXT)
+
+purge: realclean
+
+$(EXT).o : $(TOP)/EXTERN.h
+$(EXT).o : $(TOP)/perl.h
+$(EXT).o : $(TOP)/embed.h
+$(EXT).o : $(TOP)/config.h
+$(EXT).o : $(TOP)/unixish.h
+$(EXT).o : $(TOP)/handy.h
+$(EXT).o : $(TOP)/regexp.h
+$(EXT).o : $(TOP)/sv.h
+$(EXT).o : $(TOP)/util.h
+$(EXT).o : $(TOP)/form.h
+$(EXT).o : $(TOP)/gv.h
+$(EXT).o : $(TOP)/cv.h
+$(EXT).o : $(TOP)/opcode.h
+$(EXT).o : $(TOP)/op.h
+$(EXT).o : $(TOP)/cop.h
+$(EXT).o : $(TOP)/av.h
+$(EXT).o : $(TOP)/hv.h
+$(EXT).o : $(TOP)/mg.h
+$(EXT).o : $(TOP)/scope.h
+$(EXT).o : $(TOP)/pp.h
+$(EXT).o : $(TOP)/proto.h
+$(EXT).o : $(TOP)/XSUB.h
+
+Makefile: Makefile.SH $(TOP)/config.sh ; /bin/sh Makefile.SH
+$(TOP)/config.h: $(TOP)/config.sh; cd $(TOP); /bin/sh config_h.SH
+$(TOP)/embed.h: $(TOP)/config.sh; cd $(TOP); /bin/sh embed_h.SH
+$(TOP)/cflags: $(TOP)/config.sh; cd $(TOP); /bin/sh cflags.SH
+
+!NO!SUBS!
+chmod 644 Makefile
+$eunicefix Makefile
+
diff --git a/ext/SDBM_File/SDBM_File.pm b/ext/SDBM_File/SDBM_File.pm
new file mode 100644
index 0000000000..1f93e52893
--- /dev/null
+++ b/ext/SDBM_File/SDBM_File.pm
@@ -0,0 +1,11 @@
+package SDBM_File;
+
+require TieHash;
+require DynaLoader;
+@ISA = qw(TieHash DynaLoader);
+
+bootstrap SDBM_File;
+
+1;
+
+__END__
diff --git a/ext/SDBM_File/SDBM_File.xs b/ext/SDBM_File/SDBM_File.xs
new file mode 100644
index 0000000000..97f9c1f9f4
--- /dev/null
+++ b/ext/SDBM_File/SDBM_File.xs
@@ -0,0 +1,71 @@
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "sdbm/sdbm.h"
+
+typedef DBM* SDBM_File;
+#define sdbm_TIEHASH(dbtype,filename,flags,mode) sdbm_open(filename,flags,mode)
+#define sdbm_FETCH(db,key) sdbm_fetch(db,key)
+#define sdbm_STORE(db,key,value,flags) sdbm_store(db,key,value,flags)
+#define sdbm_DELETE(db,key) sdbm_delete(db,key)
+#define sdbm_FIRSTKEY(db) sdbm_firstkey(db)
+#define sdbm_NEXTKEY(db,key) sdbm_nextkey(db)
+
+
+MODULE = SDBM_File PACKAGE = SDBM_File PREFIX = sdbm_
+
+SDBM_File
+sdbm_TIEHASH(dbtype, filename, flags, mode)
+ char * dbtype
+ char * filename
+ int flags
+ int mode
+
+void
+sdbm_DESTROY(db)
+ SDBM_File db
+ CODE:
+ sdbm_close(db);
+
+datum
+sdbm_FETCH(db, key)
+ SDBM_File db
+ datum key
+
+int
+sdbm_STORE(db, key, value, flags = DBM_REPLACE)
+ SDBM_File db
+ datum key
+ datum value
+ int flags
+ CLEANUP:
+ if (RETVAL) {
+ if (RETVAL < 0 && errno == EPERM)
+ croak("No write permission to sdbm file");
+ warn("sdbm store returned %d, errno %d, key \"%s\"",
+ RETVAL,errno,key.dptr);
+ sdbm_clearerr(db);
+ }
+
+int
+sdbm_DELETE(db, key)
+ SDBM_File db
+ datum key
+
+datum
+sdbm_FIRSTKEY(db)
+ SDBM_File db
+
+datum
+sdbm_NEXTKEY(db, key)
+ SDBM_File db
+ datum key
+
+int
+sdbm_error(db)
+ SDBM_File db
+
+int
+sdbm_clearerr(db)
+ SDBM_File db
+
diff --git a/ext/SDBM_File/sdbm/CHANGES b/ext/SDBM_File/sdbm/CHANGES
new file mode 100644
index 0000000000..f7296d1b3a
--- /dev/null
+++ b/ext/SDBM_File/sdbm/CHANGES
@@ -0,0 +1,18 @@
+Changes from the earlier BETA releases.
+
+o dbm_prep does everything now, so dbm_open is just a simple
+ wrapper that builds the default filenames. dbm_prep no longer
+ requires a (DBM *) db parameter: it allocates one itself. It
+ returns (DBM *) db or (DBM *) NULL.
+
+o makroom is now reliable. In the common-case optimization of the page
+ split, the page into which the incoming key/value pair is to be inserted
+ is write-deferred (if the split is successful), thereby saving a cosly
+ write. BUT, if the split does not make enough room (unsuccessful), the
+ deferred page is written out, as the failure-window is now dependent on
+ the number of split attempts.
+
+o if -DDUFF is defined, hash function will also use the DUFF construct.
+ This may look like a micro-performance tweak (maybe it is), but in fact,
+ the hash function is the third most-heavily used function, after read
+ and write.
diff --git a/ext/SDBM_File/sdbm/COMPARE b/ext/SDBM_File/sdbm/COMPARE
new file mode 100644
index 0000000000..a595e831d2
--- /dev/null
+++ b/ext/SDBM_File/sdbm/COMPARE
@@ -0,0 +1,88 @@
+
+Script started on Thu Sep 28 15:41:06 1989
+% uname -a
+titan titan 4_0 UMIPS mips
+% make all x-dbm
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dbm.c
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c sdbm.c
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c pair.c
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c hash.c
+ ar cr libsdbm.a sdbm.o pair.o hash.o
+ ranlib libsdbm.a
+ cc -o dbm dbm.o libsdbm.a
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dba.c
+ cc -o dba dba.o
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dbd.c
+ cc -o dbd dbd.o
+ cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -o x-dbm dbm.o
+%
+%
+% wc history
+ 65110 218344 3204883 history
+%
+% /bin/time dbm build foo <history
+
+real 5:56.9
+user 13.3
+sys 26.3
+% ls -s
+total 14251
+ 5 README 2 dbd.c 1 hash.c 1 pair.h
+ 0 SCRIPT 5 dbd.o 1 hash.o 5 pair.o
+ 1 WISHLIST 62 dbm 3130 history 1 port.h
+ 46 dba 5 dbm.c 11 howtodbm.txt 11 sdbm.c
+ 3 dba.c 8 dbm.o 14 libsdbm.a 2 sdbm.h
+ 6 dba.o 4 foo.dir 1 makefile 8 sdbm.o
+ 46 dbd 10810 foo.pag 6 pair.c 60 x-dbm
+% ls -l foo.*
+-rw-r--r-- 1 oz 4096 Sep 28 15:48 foo.dir
+-rw-r--r-- 1 oz 11069440 Sep 28 15:48 foo.pag
+%
+% /bin/time x-dbm build bar <history
+
+real 5:59.4
+user 24.7
+sys 29.1
+%
+% ls -s
+total 27612
+ 5 README 46 dbd 1 hash.c 5 pair.o
+ 1 SCRIPT 2 dbd.c 1 hash.o 1 port.h
+ 1 WISHLIST 5 dbd.o 3130 history 11 sdbm.c
+ 4 bar.dir 62 dbm 11 howtodbm.txt 2 sdbm.h
+13356 bar.pag 5 dbm.c 14 libsdbm.a 8 sdbm.o
+ 46 dba 8 dbm.o 1 makefile 60 x-dbm
+ 3 dba.c 4 foo.dir 6 pair.c
+ 6 dba.o 10810 foo.pag 1 pair.h
+%
+% ls -l bar.*
+-rw-r--r-- 1 oz 4096 Sep 28 15:54 bar.dir
+-rw-r--r-- 1 oz 13676544 Sep 28 15:54 bar.pag
+%
+% dba foo | tail
+#10801: ok. no entries.
+#10802: ok. no entries.
+#10803: ok. no entries.
+#10804: ok. no entries.
+#10805: ok. no entries.
+#10806: ok. no entries.
+#10807: ok. no entries.
+#10808: ok. no entries.
+#10809: ok. 11 entries 67% used free 337.
+10810 pages (6036 holes): 65073 entries
+%
+% dba bar | tail
+#13347: ok. no entries.
+#13348: ok. no entries.
+#13349: ok. no entries.
+#13350: ok. no entries.
+#13351: ok. no entries.
+#13352: ok. no entries.
+#13353: ok. no entries.
+#13354: ok. no entries.
+#13355: ok. 7 entries 33% used free 676.
+13356 pages (8643 holes): 65073 entries
+%
+% exit
+script done on Thu Sep 28 16:08:45 1989
+
diff --git a/ext/SDBM_File/sdbm/Makefile.SH b/ext/SDBM_File/sdbm/Makefile.SH
new file mode 100644
index 0000000000..521c97270a
--- /dev/null
+++ b/ext/SDBM_File/sdbm/Makefile.SH
@@ -0,0 +1,99 @@
+: This forces SH files to create target in same directory as SH file.
+: This is so that make depend always knows where to find SH derivatives.
+
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+
+if test -f config.sh; then TOP=.;
+elif test -f ../config.sh; then TOP=..;
+elif test -f ../../config.sh; then TOP=../..;
+elif test -f ../../../config.sh; then TOP=../../..;
+elif test -f ../../../../config.sh; then TOP=../../../..;
+else
+ echo "Can't find config.sh."; exit 1
+fi
+
+: Find absolute path name for TOP. This is needed when we cd to TOP
+: to run perl on autosplit.
+oldpwd=`pwd`; cd $TOP; ABSTOP=`pwd`; cd $oldpwd
+
+case $CONFIG in
+'')
+ . $TOP/config.sh
+ ;;
+esac
+
+echo "Extracting ext/SDBM_File/sdbm/Makefile (with variable substitutions)"
+: This section of the file will have variable substitutions done on it.
+: Move anything that needs config subs from !NO!SUBS! section to !GROK!THIS!.
+: Protect any dollar signs and backticks that you do not want interpreted
+: by putting a backslash in front. You may delete these comments.
+$spitshell >Makefile <<!GROK!THIS!
+#
+# This Makefile is for the library part of sdbm. For the
+# Full package, see makefile.sdbm.
+#
+# Makefile for public domain ndbm-clone: sdbm
+# DUFF: use duff's device (loop unroll) in parts of the code
+#
+#
+CC = $cc
+RANLIB = $ranlib
+TOP = $TOP
+ABSTOP = $ABSTOP
+LDFLAGS = $ldflags
+CLDFLAGS = $ldflags
+SMALL = $small
+LARGE = $large $split
+
+# To use an alternate make, set \$altmake in config.sh.
+MAKE = ${altmake-make}
+
+# The following are used to build and install shared libraries for
+# dynamic loading.
+LDDLFLAGS = $lddlflags
+CCDLFLAGS = $ccdlflags
+CCCDLFLAGS = $cccdlflags
+
+!GROK!THIS!
+
+: In the following dollars and backticks do not need the extra backslash.
+$spitshell >>Makefile <<'!NO!SUBS!'
+SHELL = /bin/sh
+CCCMD = `sh $(shellflags) $(TOP)/cflags $@`
+
+.c.o:
+ $(CCCMD) $(CCCDLFLAGS) -I$(TOP) -DSDBM -DDUFF $*.c
+
+LIBOBJS = sdbm.o pair.o hash.o
+LIBSRCS = sdbm.c pair.c hash.c
+HDRS = tune.h sdbm.h pair.h $(TOP)/config.h
+
+all: libsdbm.a
+
+libsdbm.a: $(LIBOBJS)
+ ar cr libsdbm.a $(LIBOBJS)
+ $(RANLIB) libsdbm.a
+
+$(LIBOBJS): $(HDRS)
+
+lint:
+ lint -abchx $(LIBSRCS)
+
+clean:
+ rm -f *.o *.a mon.out core
+
+realclean: clean
+ rm -f dbu libsdbm.a dbd dba dbe x-dbu *.dir *.pag
+ rm -f makefile Makefile
+
+purge: realclean
+
+sdbm.o : sdbm.c $(TOP)/config.h sdbm.h tune.h pair.h
+hash.o : hash.c $(TOP)/config.h sdbm.h
+pair.o : pair.c $(TOP)/config.h sdbm.h tune.h pair.h
+
+!NO!SUBS!
+chmod 755 Makefile
+$eunicefix Makefile
diff --git a/ext/SDBM_File/sdbm/README b/ext/SDBM_File/sdbm/README
new file mode 100644
index 0000000000..cd7312cc57
--- /dev/null
+++ b/ext/SDBM_File/sdbm/README
@@ -0,0 +1,396 @@
+
+
+
+
+
+
+ sdbm - Substitute DBM
+ or
+ Berkeley ndbm for Every UN*X[1] Made Simple
+
+ Ozan (oz) Yigit
+
+ The Guild of PD Software Toolmakers
+ Toronto - Canada
+
+ oz@nexus.yorku.ca
+
+
+
+Implementation is the sincerest form of flattery. - L. Peter
+Deutsch
+
+A The Clone of the ndbm library
+
+ The sources accompanying this notice - sdbm - consti-
+tute the first public release (Dec. 1990) of a complete
+clone of the Berkeley UN*X ndbm library. The sdbm library is
+meant to clone the proven functionality of ndbm as closely
+as possible, including a few improvements. It is practical,
+easy to understand, and compatible. The sdbm library is not
+derived from any licensed, proprietary or copyrighted
+software.
+
+ The sdbm implementation is based on a 1978 algorithm
+[Lar78] by P.-A. (Paul) Larson known as ``Dynamic Hashing''.
+In the course of searching for a substitute for ndbm, I pro-
+totyped three different external-hashing algorithms [Lar78,
+Fag79, Lit80] and ultimately chose Larson's algorithm as a
+basis of the sdbm implementation. The Bell Labs dbm (and
+therefore ndbm) is based on an algorithm invented by Ken
+Thompson, [Tho90, Tor87] and predates Larson's work.
+
+ The sdbm programming interface is totally compatible
+with ndbm and includes a slight improvement in database ini-
+tialization. It is also expected to be binary-compatible
+under most UN*X versions that support the ndbm library.
+
+ The sdbm implementation shares the shortcomings of the
+ndbm library, as a side effect of various simplifications to
+the original Larson algorithm. It does produce holes in the
+page file as it writes pages past the end of file. (Larson's
+paper include a clever solution to this problem that is a
+result of using the hash value directly as a block address.)
+On the other hand, extensive tests seem to indicate that
+sdbm creates fewer holes in general, and the resulting page-
+files are smaller. The sdbm implementation is also faster
+than ndbm in database creation. Unlike the ndbm, the sdbm
+_________________________
+
+ [1] UN*X is not a trademark of any (dis)organization.
+
+
+
+
+
+
+
+
+
+ - 2 -
+
+
+store operation will not ``wander away'' trying to split its
+data pages to insert a datum that cannot (due to elaborate
+worst-case situations) be inserted. (It will fail after a
+pre-defined number of attempts.)
+
+Important Compatibility Warning
+
+ The sdbm and ndbm libraries cannot share databases: one
+cannot read the (dir/pag) database created by the other.
+This is due to the differences between the ndbm and sdbm
+algorithms[2], and the hash functions used. It is easy to
+convert between the dbm/ndbm databases and sdbm by ignoring
+the index completely: see dbd, dbu etc.
+
+
+Notice of Intellectual Property
+
+The entire sdbm library package, as authored by me, Ozan S.
+Yigit, is hereby placed in the public domain. As such, the
+author is not responsible for the consequences of use of
+this software, no matter how awful, even if they arise from
+defects in it. There is no expressed or implied warranty for
+the sdbm library.
+
+ Since the sdbm library package is in the public domain,
+this original release or any additional public-domain
+releases of the modified original cannot possibly (by defin-
+ition) be withheld from you. Also by definition, You (singu-
+lar) have all the rights to this code (including the right
+to sell without permission, the right to hoard[3] and the
+right to do other icky things as you see fit) but those
+rights are also granted to everyone else.
+
+ Please note that all previous distributions of this
+software contained a copyright (which is now dropped) to
+protect its origins and its current public domain status
+against any possible claims and/or challenges.
+
+Acknowledgments
+
+ Many people have been very helpful and supportive. A
+partial list would necessarily include Rayan Zacherissen
+(who contributed the man page, and also hacked a MMAP
+_________________________
+
+ [2] Torek's discussion [Tor87] indicates that
+dbm/ndbm implementations use the hash value to traverse
+the radix trie differently than sdbm and as a result,
+the page indexes are generated in different order. For
+more information, send e-mail to the author.
+ [3] You cannot really hoard something that is avail-
+able to the public at large, but try if it makes you
+feel any better.
+
+
+
+
+
+
+
+
+
+
+ - 3 -
+
+
+version of sdbm), Arnold Robbins, Chris Lewis, Bill David-
+sen, Henry Spencer, Geoff Collyer, Rich Salz (who got me
+started in the first place), Johannes Ruschein (who did the
+minix port) and David Tilbrook. I thank you all.
+
+Distribution Manifest and Notes
+
+This distribution of sdbm includes (at least) the following:
+
+ CHANGES change log
+ README this file.
+ biblio a small bibliography on external hashing
+ dba.c a crude (n/s)dbm page file analyzer
+ dbd.c a crude (n/s)dbm page file dumper (for conversion)
+ dbe.1 man page for dbe.c
+ dbe.c Janick's database editor
+ dbm.c a dbm library emulation wrapper for ndbm/sdbm
+ dbm.h header file for the above
+ dbu.c a crude db management utility
+ hash.c hashing function
+ makefile guess.
+ pair.c page-level routines (posted earlier)
+ pair.h header file for the above
+ readme.ms troff source for the README file
+ sdbm.3 man page
+ sdbm.c the real thing
+ sdbm.h header file for the above
+ tune.h place for tuning & portability thingies
+ util.c miscellaneous
+
+ dbu is a simple database manipulation program[4] that
+tries to look like Bell Labs' cbt utility. It is currently
+incomplete in functionality. I use dbu to test out the rou-
+tines: it takes (from stdin) tab separated key/value pairs
+for commands like build or insert or takes keys for commands
+like delete or look.
+
+ dbu <build|creat|look|insert|cat|delete> dbmfile
+
+ dba is a crude analyzer of dbm/sdbm/ndbm page files. It
+scans the entire page file, reporting page level statistics,
+and totals at the end.
+
+ dbd is a crude dump program for dbm/ndbm/sdbm data-
+bases. It ignores the bitmap, and dumps the data pages in
+sequence. It can be used to create input for the dbu util-
+ity. Note that dbd will skip any NULLs in the key and data
+fields, thus is unsuitable to convert some peculiar
+_________________________
+
+ [4] The dbd, dba, dbu utilities are quick hacks and
+are not fit for production use. They were developed
+late one night, just to test out sdbm, and convert some
+databases.
+
+
+
+
+
+
+
+
+
+ - 4 -
+
+
+databases that insist in including the terminating null.
+
+ I have also included a copy of the dbe (ndbm DataBase
+Editor) by Janick Bergeron [janick@bnr.ca] for your pleas-
+ure. You may find it more useful than the little dbu util-
+ity.
+
+ dbm.[ch] is a dbm library emulation on top of ndbm (and
+hence suitable for sdbm). Written by Robert Elz.
+
+ The sdbm library has been around in beta test for quite
+a long time, and from whatever little feedback I received
+(maybe no news is good news), I believe it has been func-
+tioning without any significant problems. I would, of
+course, appreciate all fixes and/or improvements. Portabil-
+ity enhancements would especially be useful.
+
+Implementation Issues
+
+ Hash functions: The algorithm behind sdbm implementa-
+tion needs a good bit-scrambling hash function to be effec-
+tive. I ran into a set of constants for a simple hash func-
+tion that seem to help sdbm perform better than ndbm for
+various inputs:
+
+ /*
+ * polynomial conversion ignoring overflows
+ * 65599 nice. 65587 even better.
+ */
+ long
+ dbm_hash(char *str, int len) {
+ register unsigned long n = 0;
+
+ while (len--)
+ n = n * 65599 + *str++;
+ return n;
+ }
+
+ There may be better hash functions for the purposes of
+dynamic hashing. Try your favorite, and check the pagefile.
+If it contains too many pages with too many holes, (in rela-
+tion to this one for example) or if sdbm simply stops work-
+ing (fails after SPLTMAX attempts to split) when you feed
+your NEWS history file to it, you probably do not have a
+good hashing function. If you do better (for different
+types of input), I would like to know about the function you
+use.
+
+ Block sizes: It seems (from various tests on a few
+machines) that a page file block size PBLKSIZ of 1024 is by
+far the best for performance, but this also happens to limit
+the size of a key/value pair. Depending on your needs, you
+may wish to increase the page size, and also adjust PAIRMAX
+(the maximum size of a key/value pair allowed: should always
+
+
+
+
+
+
+
+
+
+ - 5 -
+
+
+be at least three words smaller than PBLKSIZ.) accordingly.
+The system-wide version of the library should probably be
+configured with 1024 (distribution default), as this appears
+to be sufficient for most common uses of sdbm.
+
+Portability
+
+ This package has been tested in many different UN*Xes
+even including minix, and appears to be reasonably portable.
+This does not mean it will port easily to non-UN*X systems.
+
+Notes and Miscellaneous
+
+ The sdbm is not a very complicated package, at least
+not after you familiarize yourself with the literature on
+external hashing. There are other interesting algorithms in
+existence that ensure (approximately) single-read access to
+a data value associated with any key. These are directory-
+less schemes such as linear hashing [Lit80] (+ Larson varia-
+tions), spiral storage [Mar79] or directory schemes such as
+extensible hashing [Fag79] by Fagin et al. I do hope these
+sources provide a reasonable playground for experimentation
+with other algorithms. See the June 1988 issue of ACM Com-
+puting Surveys [Enb88] for an excellent overview of the
+field.
+
+References
+
+
+[Lar78]
+ P.-A. Larson, ``Dynamic Hashing'', BIT, vol. 18, pp.
+ 184-201, 1978.
+
+[Tho90]
+ Ken Thompson, private communication, Nov. 1990
+
+[Lit80]
+ W. Litwin, `` Linear Hashing: A new tool for file and
+ table addressing'', Proceedings of the 6th Conference on
+ Very Large Dabatases (Montreal), pp. 212-223, Very
+ Large Database Foundation, Saratoga, Calif., 1980.
+
+[Fag79]
+ R. Fagin, J. Nievergelt, N. Pippinger, and H. R.
+ Strong, ``Extendible Hashing - A Fast Access Method for
+ Dynamic Files'', ACM Trans. Database Syst., vol. 4,
+ no.3, pp. 315-344, Sept. 1979.
+
+[Wal84]
+ Rich Wales, ``Discussion of "dbm" data base system'',
+ USENET newsgroup unix.wizards, Jan. 1984.
+
+[Tor87]
+ Chris Torek, ``Re: dbm.a and ndbm.a archives'',
+
+
+
+
+
+
+
+
+
+ - 6 -
+
+
+ USENET newsgroup comp.unix, 1987.
+
+[Mar79]
+ G. N. Martin, ``Spiral Storage: Incrementally Augment-
+ able Hash Addressed Storage'', Technical Report #27,
+ University of Varwick, Coventry, U.K., 1979.
+
+[Enb88]
+ R. J. Enbody and H. C. Du, ``Dynamic Hashing
+ Schemes'',ACM Computing Surveys, vol. 20, no. 2, pp.
+ 85-113, June 1988.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/SDBM_File/sdbm/README.too b/ext/SDBM_File/sdbm/README.too
new file mode 100644
index 0000000000..c2d095944d
--- /dev/null
+++ b/ext/SDBM_File/sdbm/README.too
@@ -0,0 +1,9 @@
+This version of sdbm merely has all the dbm_* names translated to sdbm_*
+so that we can link ndbm and sdbm into the same executable. (It also has
+the bad() macro redefined to allow a zero-length key.)
+
+
+Fri Apr 15 10:15:30 EDT 1994.
+
+Additional portability/configuration changes for libsdbm by Andy Dougherty
+doughera@lafcol.lafayette.edu.
diff --git a/ext/SDBM_File/sdbm/biblio b/ext/SDBM_File/sdbm/biblio
new file mode 100644
index 0000000000..0be09fa005
--- /dev/null
+++ b/ext/SDBM_File/sdbm/biblio
@@ -0,0 +1,64 @@
+%A R. J. Enbody
+%A H. C. Du
+%T Dynamic Hashing Schemes
+%J ACM Computing Surveys
+%V 20
+%N 2
+%D June 1988
+%P 85-113
+%K surveys
+
+%A P.-A. Larson
+%T Dynamic Hashing
+%J BIT
+%V 18
+%P 184-201
+%D 1978
+%K dynamic
+
+%A W. Litwin
+%T Linear Hashing: A new tool for file and table addressing
+%J Proceedings of the 6th Conference on Very Large Dabatases (Montreal)
+%I Very Large Database Foundation
+%C Saratoga, Calif.
+%P 212-223
+%D 1980
+%K linear
+
+%A R. Fagin
+%A J. Nievergelt
+%A N. Pippinger
+%A H. R. Strong
+%T Extendible Hashing - A Fast Access Method for Dynamic Files
+%J ACM Trans. Database Syst.
+%V 4
+%N 3
+%D Sept. 1979
+%P 315-344
+%K extend
+
+%A G. N. Martin
+%T Spiral Storage: Incrementally Augmentable Hash Addressed Storage
+%J Technical Report #27
+%I University of Varwick
+%C Coventry, U.K.
+%D 1979
+%K spiral
+
+%A Chris Torek
+%T Re: dbm.a and ndbm.a archives
+%B USENET newsgroup comp.unix
+%D 1987
+%K torek
+
+%A Rich Wales
+%T Discusson of "dbm" data base system
+%B USENET newsgroup unix.wizards
+%D Jan. 1984
+%K rich
+
+
+
+
+
+
diff --git a/ext/SDBM_File/sdbm/dba.c b/ext/SDBM_File/sdbm/dba.c
new file mode 100644
index 0000000000..4f227e5245
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dba.c
@@ -0,0 +1,84 @@
+/*
+ * dba dbm analysis/recovery
+ */
+
+#include <stdio.h>
+#include <sys/file.h>
+#include "sdbm.h"
+
+char *progname;
+extern void oops();
+
+int
+main(argc, argv)
+char **argv;
+{
+ int n;
+ char *p;
+ char *name;
+ int pagf;
+
+ progname = argv[0];
+
+ if (p = argv[1]) {
+ name = (char *) malloc((n = strlen(p)) + 5);
+ strcpy(name, p);
+ strcpy(name + n, ".pag");
+
+ if ((pagf = open(name, O_RDONLY)) < 0)
+ oops("cannot open %s.", name);
+
+ sdump(pagf);
+ }
+ else
+ oops("usage: %s dbname", progname);
+
+ return 0;
+}
+
+sdump(pagf)
+int pagf;
+{
+ register b;
+ register n = 0;
+ register t = 0;
+ register o = 0;
+ register e;
+ char pag[PBLKSIZ];
+
+ while ((b = read(pagf, pag, PBLKSIZ)) > 0) {
+ printf("#%d: ", n);
+ if (!okpage(pag))
+ printf("bad\n");
+ else {
+ printf("ok. ");
+ if (!(e = pagestat(pag)))
+ o++;
+ else
+ t += e;
+ }
+ n++;
+ }
+
+ if (b == 0)
+ printf("%d pages (%d holes): %d entries\n", n, o, t);
+ else
+ oops("read failed: block %d", n);
+}
+
+pagestat(pag)
+char *pag;
+{
+ register n;
+ register free;
+ register short *ino = (short *) pag;
+
+ if (!(n = ino[0]))
+ printf("no entries.\n");
+ else {
+ free = ino[n] - (n + 1) * sizeof(short);
+ printf("%3d entries %2d%% used free %d.\n",
+ n / 2, ((PBLKSIZ - free) * 100) / PBLKSIZ, free);
+ }
+ return n / 2;
+}
diff --git a/ext/SDBM_File/sdbm/dbd.c b/ext/SDBM_File/sdbm/dbd.c
new file mode 100644
index 0000000000..697a547597
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dbd.c
@@ -0,0 +1,110 @@
+/*
+ * dbd - dump a dbm data file
+ */
+
+#include <stdio.h>
+#include <sys/file.h>
+#include "sdbm.h"
+
+char *progname;
+extern void oops();
+
+
+#define empty(page) (((short *) page)[0] == 0)
+
+int
+main(argc, argv)
+char **argv;
+{
+ int n;
+ char *p;
+ char *name;
+ int pagf;
+
+ progname = argv[0];
+
+ if (p = argv[1]) {
+ name = (char *) malloc((n = strlen(p)) + 5);
+ strcpy(name, p);
+ strcpy(name + n, ".pag");
+
+ if ((pagf = open(name, O_RDONLY)) < 0)
+ oops("cannot open %s.", name);
+
+ sdump(pagf);
+ }
+ else
+ oops("usage: %s dbname", progname);
+ return 0;
+}
+
+sdump(pagf)
+int pagf;
+{
+ register r;
+ register n = 0;
+ register o = 0;
+ char pag[PBLKSIZ];
+
+ while ((r = read(pagf, pag, PBLKSIZ)) > 0) {
+ if (!okpage(pag))
+ fprintf(stderr, "%d: bad page.\n", n);
+ else if (empty(pag))
+ o++;
+ else
+ dispage(pag);
+ n++;
+ }
+
+ if (r == 0)
+ fprintf(stderr, "%d pages (%d holes).\n", n, o);
+ else
+ oops("read failed: block %d", n);
+}
+
+
+#ifdef OLD
+dispage(pag)
+char *pag;
+{
+ register i, n;
+ register off;
+ register short *ino = (short *) pag;
+
+ off = PBLKSIZ;
+ for (i = 1; i < ino[0]; i += 2) {
+ printf("\t[%d]: ", ino[i]);
+ for (n = ino[i]; n < off; n++)
+ putchar(pag[n]);
+ putchar(' ');
+ off = ino[i];
+ printf("[%d]: ", ino[i + 1]);
+ for (n = ino[i + 1]; n < off; n++)
+ putchar(pag[n]);
+ off = ino[i + 1];
+ putchar('\n');
+ }
+}
+#else
+dispage(pag)
+char *pag;
+{
+ register i, n;
+ register off;
+ register short *ino = (short *) pag;
+
+ off = PBLKSIZ;
+ for (i = 1; i < ino[0]; i += 2) {
+ for (n = ino[i]; n < off; n++)
+ if (pag[n] != 0)
+ putchar(pag[n]);
+ putchar('\t');
+ off = ino[i];
+ for (n = ino[i + 1]; n < off; n++)
+ if (pag[n] != 0)
+ putchar(pag[n]);
+ putchar('\n');
+ off = ino[i + 1];
+ }
+}
+#endif
diff --git a/ext/SDBM_File/sdbm/dbe.1 b/ext/SDBM_File/sdbm/dbe.1
new file mode 100644
index 0000000000..3b32272684
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dbe.1
@@ -0,0 +1,46 @@
+.TH dbe 1 "ndbm(3) EDITOR"
+.SH NAME
+dbe \- Edit a ndbm(3) database
+.SH USAGE
+dbe <database> [-m r|w|rw] [-crtvx] -a|-d|-f|-F|-s [<key> [<content>]]
+.SH DESCRIPTION
+\fIdbme\fP operates on ndbm(3) databases.
+It can be used to create them, look at them or change them.
+When specifying the value of a key or the content of its associated entry,
+\\nnn, \\0, \\n, \\t, \\f and \\r are interpreted as usual.
+When displaying key/content pairs, non-printable characters are displayed
+using the \\nnn notation.
+.SH OPTIONS
+.IP -a
+List all entries in the database.
+.IP -c
+Create the database if it does not exist.
+.IP -d
+Delete the entry associated with the specified key.
+.IP -f
+Fetch and display the entry associated with the specified key.
+.IP -F
+Fetch and display all the entries whose key match the specified
+regular-expression
+.IP "-m r|w|rw"
+Open the database in read-only, write-only or read-write mode
+.IP -r
+Replace the entry associated with the specified key if it already exists.
+See option -s.
+.IP -s
+Store an entry under a specific key.
+An error occurs if the key already exists and the option -r was not specified.
+.IP -t
+Re-initialize the database before executing the command.
+.IP -v
+Verbose mode.
+Confirm stores and deletions.
+.IP -x
+If option -x is used with option -c, then if the database already exists,
+an error occurs.
+This can be used to implement a simple exclusive access locking mechanism.
+.SH SEE ALSO
+ndbm(3)
+.SH AUTHOR
+janick@bnr.ca
+
diff --git a/ext/SDBM_File/sdbm/dbe.c b/ext/SDBM_File/sdbm/dbe.c
new file mode 100644
index 0000000000..2a306f276e
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dbe.c
@@ -0,0 +1,435 @@
+#include <stdio.h>
+#ifndef VMS
+#include <sys/file.h>
+#include <ndbm.h>
+#else
+#include "file.h"
+#include "ndbm.h"
+#endif
+#include <ctype.h>
+
+/***************************************************************************\
+** **
+** Function name: getopt() **
+** Author: Henry Spencer, UofT **
+** Coding date: 84/04/28 **
+** **
+** Description: **
+** **
+** Parses argv[] for arguments. **
+** Works with Whitesmith's C compiler. **
+** **
+** Inputs - The number of arguments **
+** - The base address of the array of arguments **
+** - A string listing the valid options (':' indicates an **
+** argument to the preceding option is required, a ';' **
+** indicates an argument to the preceding option is optional) **
+** **
+** Outputs - Returns the next option character, **
+** '?' for non '-' arguments **
+** or ':' when there is no more arguments. **
+** **
+** Side Effects + The argument to an option is pointed to by 'optarg' **
+** **
+*****************************************************************************
+** **
+** REVISION HISTORY: **
+** **
+** DATE NAME DESCRIPTION **
+** YY/MM/DD ------------------ ------------------------------------ **
+** 88/10/20 Janick Bergeron Returns '?' on unamed arguments **
+** returns '!' on unknown options **
+** and 'EOF' only when exhausted. **
+** 88/11/18 Janick Bergeron Return ':' when no more arguments **
+** 89/08/11 Janick Bergeron Optional optarg when ';' in optstring **
+** **
+\***************************************************************************/
+
+char *optarg; /* Global argument pointer. */
+
+#ifdef VMS
+#define index strchr
+#endif
+
+char
+getopt(argc, argv, optstring)
+int argc;
+char **argv;
+char *optstring;
+{
+ register int c;
+ register char *place;
+ extern char *index();
+ static int optind = 0;
+ static char *scan = NULL;
+
+ optarg = NULL;
+
+ if (scan == NULL || *scan == '\0') {
+
+ if (optind == 0)
+ optind++;
+ if (optind >= argc)
+ return ':';
+
+ optarg = place = argv[optind++];
+ if (place[0] != '-' || place[1] == '\0')
+ return '?';
+ if (place[1] == '-' && place[2] == '\0')
+ return '?';
+ scan = place + 1;
+ }
+
+ c = *scan++;
+ place = index(optstring, c);
+ if (place == NULL || c == ':' || c == ';') {
+
+ (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+ scan = NULL;
+ return '!';
+ }
+ if (*++place == ':') {
+
+ if (*scan != '\0') {
+
+ optarg = scan;
+ scan = NULL;
+
+ }
+ else {
+
+ if (optind >= argc) {
+
+ (void) fprintf(stderr, "%s: %c requires an argument\n",
+ argv[0], c);
+ return '!';
+ }
+ optarg = argv[optind];
+ optind++;
+ }
+ }
+ else if (*place == ';') {
+
+ if (*scan != '\0') {
+
+ optarg = scan;
+ scan = NULL;
+
+ }
+ else {
+
+ if (optind >= argc || *argv[optind] == '-')
+ optarg = NULL;
+ else {
+ optarg = argv[optind];
+ optind++;
+ }
+ }
+ }
+ return c;
+}
+
+
+void
+print_datum(db)
+datum db;
+{
+ int i;
+
+ putchar('"');
+ for (i = 0; i < db.dsize; i++) {
+ if (isprint(db.dptr[i]))
+ putchar(db.dptr[i]);
+ else {
+ putchar('\\');
+ putchar('0' + ((db.dptr[i] >> 6) & 0x07));
+ putchar('0' + ((db.dptr[i] >> 3) & 0x07));
+ putchar('0' + (db.dptr[i] & 0x07));
+ }
+ }
+ putchar('"');
+}
+
+
+datum
+read_datum(s)
+char *s;
+{
+ datum db;
+ char *p;
+ int i;
+
+ db.dsize = 0;
+ db.dptr = (char *) malloc(strlen(s) * sizeof(char));
+ for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) {
+ if (*s == '\\') {
+ if (*++s == 'n')
+ *p = '\n';
+ else if (*s == 'r')
+ *p = '\r';
+ else if (*s == 'f')
+ *p = '\f';
+ else if (*s == 't')
+ *p = '\t';
+ else if (isdigit(*s) && isdigit(*(s + 1)) && isdigit(*(s + 2))) {
+ i = (*s++ - '0') << 6;
+ i |= (*s++ - '0') << 3;
+ i |= *s - '0';
+ *p = i;
+ }
+ else if (*s == '0')
+ *p = '\0';
+ else
+ *p = *s;
+ }
+ else
+ *p = *s;
+ }
+
+ return db;
+}
+
+
+char *
+key2s(db)
+datum db;
+{
+ char *buf;
+ char *p1, *p2;
+
+ buf = (char *) malloc((db.dsize + 1) * sizeof(char));
+ for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++);
+ *p1 = '\0';
+ return buf;
+}
+
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ typedef enum {
+ YOW, FETCH, STORE, DELETE, SCAN, REGEXP
+ } commands;
+ char opt;
+ int flags;
+ int giveusage = 0;
+ int verbose = 0;
+ commands what = YOW;
+ char *comarg[3];
+ int st_flag = DBM_INSERT;
+ int argn;
+ DBM *db;
+ datum key;
+ datum content;
+
+ flags = O_RDWR;
+ argn = 0;
+
+ while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') {
+ switch (opt) {
+ case 'a':
+ what = SCAN;
+ break;
+ case 'c':
+ flags |= O_CREAT;
+ break;
+ case 'd':
+ what = DELETE;
+ break;
+ case 'f':
+ what = FETCH;
+ break;
+ case 'F':
+ what = REGEXP;
+ break;
+ case 'm':
+ flags &= ~(000007);
+ if (strcmp(optarg, "r") == 0)
+ flags |= O_RDONLY;
+ else if (strcmp(optarg, "w") == 0)
+ flags |= O_WRONLY;
+ else if (strcmp(optarg, "rw") == 0)
+ flags |= O_RDWR;
+ else {
+ fprintf(stderr, "Invalid mode: \"%s\"\n", optarg);
+ giveusage = 1;
+ }
+ break;
+ case 'r':
+ st_flag = DBM_REPLACE;
+ break;
+ case 's':
+ what = STORE;
+ break;
+ case 't':
+ flags |= O_TRUNC;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'x':
+ flags |= O_EXCL;
+ break;
+ case '!':
+ giveusage = 1;
+ break;
+ case '?':
+ if (argn < 3)
+ comarg[argn++] = optarg;
+ else {
+ fprintf(stderr, "Too many arguments.\n");
+ giveusage = 1;
+ }
+ break;
+ }
+ }
+
+ if (giveusage | what == YOW | argn < 1) {
+ fprintf(stderr, "Usage: %s databse [-m r|w|rw] [-crtx] -a|-d|-f|-F|-s [key [content]]\n", argv[0]);
+ exit(-1);
+ }
+
+ if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) {
+ fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]);
+ exit(-1);
+ }
+
+ if (argn > 1)
+ key = read_datum(comarg[1]);
+ if (argn > 2)
+ content = read_datum(comarg[2]);
+
+ switch (what) {
+
+ case SCAN:
+ key = dbm_firstkey(db);
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching first key\n");
+ goto db_exit;
+ }
+ while (key.dptr != NULL) {
+ content = dbm_fetch(db, key);
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching ");
+ print_datum(key);
+ printf("\n");
+ goto db_exit;
+ }
+ print_datum(key);
+ printf(": ");
+ print_datum(content);
+ printf("\n");
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching next key\n");
+ goto db_exit;
+ }
+ key = dbm_nextkey(db);
+ }
+ break;
+
+ case REGEXP:
+ if (argn < 2) {
+ fprintf(stderr, "Missing regular expression.\n");
+ goto db_exit;
+ }
+ if (re_comp(comarg[1])) {
+ fprintf(stderr, "Invalid regular expression\n");
+ goto db_exit;
+ }
+ key = dbm_firstkey(db);
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching first key\n");
+ goto db_exit;
+ }
+ while (key.dptr != NULL) {
+ if (re_exec(key2s(key))) {
+ content = dbm_fetch(db, key);
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching ");
+ print_datum(key);
+ printf("\n");
+ goto db_exit;
+ }
+ print_datum(key);
+ printf(": ");
+ print_datum(content);
+ printf("\n");
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching next key\n");
+ goto db_exit;
+ }
+ }
+ key = dbm_nextkey(db);
+ }
+ break;
+
+ case FETCH:
+ if (argn < 2) {
+ fprintf(stderr, "Missing fetch key.\n");
+ goto db_exit;
+ }
+ content = dbm_fetch(db, key);
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error when fetching ");
+ print_datum(key);
+ printf("\n");
+ goto db_exit;
+ }
+ if (content.dptr == NULL) {
+ fprintf(stderr, "Cannot find ");
+ print_datum(key);
+ printf("\n");
+ goto db_exit;
+ }
+ print_datum(key);
+ printf(": ");
+ print_datum(content);
+ printf("\n");
+ break;
+
+ case DELETE:
+ if (argn < 2) {
+ fprintf(stderr, "Missing delete key.\n");
+ goto db_exit;
+ }
+ if (dbm_delete(db, key) || dbm_error(db)) {
+ fprintf(stderr, "Error when deleting ");
+ print_datum(key);
+ printf("\n");
+ goto db_exit;
+ }
+ if (verbose) {
+ print_datum(key);
+ printf(": DELETED\n");
+ }
+ break;
+
+ case STORE:
+ if (argn < 3) {
+ fprintf(stderr, "Missing key and/or content.\n");
+ goto db_exit;
+ }
+ if (dbm_store(db, key, content, st_flag) || dbm_error(db)) {
+ fprintf(stderr, "Error when storing ");
+ print_datum(key);
+ printf("\n");
+ goto db_exit;
+ }
+ if (verbose) {
+ print_datum(key);
+ printf(": ");
+ print_datum(content);
+ printf(" STORED\n");
+ }
+ break;
+ }
+
+db_exit:
+ dbm_clearerr(db);
+ dbm_close(db);
+ if (dbm_error(db)) {
+ fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]);
+ exit(-1);
+ }
+}
diff --git a/ext/SDBM_File/sdbm/dbm.c b/ext/SDBM_File/sdbm/dbm.c
new file mode 100644
index 0000000000..1388230e2d
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dbm.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1985 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)dbm.c 5.4 (Berkeley) 5/24/89";
+#endif /* not lint */
+
+#include "dbm.h"
+
+#define NODB ((DBM *)0)
+
+static DBM *cur_db = NODB;
+
+static char no_db[] = "dbm: no open database\n";
+
+dbminit(file)
+ char *file;
+{
+ if (cur_db != NODB)
+ dbm_close(cur_db);
+
+ cur_db = dbm_open(file, 2, 0);
+ if (cur_db == NODB) {
+ cur_db = dbm_open(file, 0, 0);
+ if (cur_db == NODB)
+ return (-1);
+ }
+ return (0);
+}
+
+long
+forder(key)
+datum key;
+{
+ if (cur_db == NODB) {
+ printf(no_db);
+ return (0L);
+ }
+ return (dbm_forder(cur_db, key));
+}
+
+datum
+fetch(key)
+datum key;
+{
+ datum item;
+
+ if (cur_db == NODB) {
+ printf(no_db);
+ item.dptr = 0;
+ return (item);
+ }
+ return (dbm_fetch(cur_db, key));
+}
+
+delete(key)
+datum key;
+{
+ if (cur_db == NODB) {
+ printf(no_db);
+ return (-1);
+ }
+ if (dbm_rdonly(cur_db))
+ return (-1);
+ return (dbm_delete(cur_db, key));
+}
+
+store(key, dat)
+datum key, dat;
+{
+ if (cur_db == NODB) {
+ printf(no_db);
+ return (-1);
+ }
+ if (dbm_rdonly(cur_db))
+ return (-1);
+
+ return (dbm_store(cur_db, key, dat, DBM_REPLACE));
+}
+
+datum
+firstkey()
+{
+ datum item;
+
+ if (cur_db == NODB) {
+ printf(no_db);
+ item.dptr = 0;
+ return (item);
+ }
+ return (dbm_firstkey(cur_db));
+}
+
+datum
+nextkey(key)
+datum key;
+{
+ datum item;
+
+ if (cur_db == NODB) {
+ printf(no_db);
+ item.dptr = 0;
+ return (item);
+ }
+ return (dbm_nextkey(cur_db, key));
+}
diff --git a/ext/SDBM_File/sdbm/dbm.h b/ext/SDBM_File/sdbm/dbm.h
new file mode 100644
index 0000000000..1196953d96
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dbm.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)dbm.h 5.2 (Berkeley) 5/24/89
+ */
+
+#ifndef NULL
+/*
+ * this is lunacy, we no longer use it (and never should have
+ * unconditionally defined it), but, this whole file is for
+ * backwards compatability - someone may rely on this.
+ */
+#define NULL ((char *) 0)
+#endif
+
+#ifdef I_NDBM
+# include <ndbm.h>
+#endif
+
+datum fetch();
+datum firstkey();
+datum nextkey();
diff --git a/ext/SDBM_File/sdbm/dbu.c b/ext/SDBM_File/sdbm/dbu.c
new file mode 100644
index 0000000000..106262872e
--- /dev/null
+++ b/ext/SDBM_File/sdbm/dbu.c
@@ -0,0 +1,250 @@
+#include <stdio.h>
+#include <sys/file.h>
+#ifdef SDBM
+#include "sdbm.h"
+#else
+#include <ndbm.h>
+#endif
+#include <string.h>
+
+#ifdef BSD42
+#define strchr index
+#endif
+
+extern int getopt();
+extern char *strchr();
+extern void oops();
+
+char *progname;
+
+static int rflag;
+static char *usage = "%s [-R] cat | look |... dbmname";
+
+#define DERROR 0
+#define DLOOK 1
+#define DINSERT 2
+#define DDELETE 3
+#define DCAT 4
+#define DBUILD 5
+#define DPRESS 6
+#define DCREAT 7
+
+#define LINEMAX 8192
+
+typedef struct {
+ char *sname;
+ int scode;
+ int flags;
+} cmd;
+
+static cmd cmds[] = {
+
+ "fetch", DLOOK, O_RDONLY,
+ "get", DLOOK, O_RDONLY,
+ "look", DLOOK, O_RDONLY,
+ "add", DINSERT, O_RDWR,
+ "insert", DINSERT, O_RDWR,
+ "store", DINSERT, O_RDWR,
+ "delete", DDELETE, O_RDWR,
+ "remove", DDELETE, O_RDWR,
+ "dump", DCAT, O_RDONLY,
+ "list", DCAT, O_RDONLY,
+ "cat", DCAT, O_RDONLY,
+ "creat", DCREAT, O_RDWR | O_CREAT | O_TRUNC,
+ "new", DCREAT, O_RDWR | O_CREAT | O_TRUNC,
+ "build", DBUILD, O_RDWR | O_CREAT,
+ "squash", DPRESS, O_RDWR,
+ "compact", DPRESS, O_RDWR,
+ "compress", DPRESS, O_RDWR
+};
+
+#define CTABSIZ (sizeof (cmds)/sizeof (cmd))
+
+static cmd *parse();
+static void badk(), doit(), prdatum();
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int c;
+ register cmd *act;
+ extern int optind;
+ extern char *optarg;
+
+ progname = argv[0];
+
+ while ((c = getopt(argc, argv, "R")) != EOF)
+ switch (c) {
+ case 'R': /* raw processing */
+ rflag++;
+ break;
+
+ default:
+ oops("usage: %s", usage);
+ break;
+ }
+
+ if ((argc -= optind) < 2)
+ oops("usage: %s", usage);
+
+ if ((act = parse(argv[optind])) == NULL)
+ badk(argv[optind]);
+ optind++;
+ doit(act, argv[optind]);
+ return 0;
+}
+
+static void
+doit(act, file)
+register cmd *act;
+char *file;
+{
+ datum key;
+ datum val;
+ register DBM *db;
+ register char *op;
+ register int n;
+ char *line;
+#ifdef TIME
+ long start;
+ extern long time();
+#endif
+
+ if ((db = dbm_open(file, act->flags, 0644)) == NULL)
+ oops("cannot open: %s", file);
+
+ if ((line = (char *) malloc(LINEMAX)) == NULL)
+ oops("%s: cannot get memory", "line alloc");
+
+ switch (act->scode) {
+
+ case DLOOK:
+ while (fgets(line, LINEMAX, stdin) != NULL) {
+ n = strlen(line) - 1;
+ line[n] = 0;
+ key.dptr = line;
+ key.dsize = n;
+ val = dbm_fetch(db, key);
+ if (val.dptr != NULL) {
+ prdatum(stdout, val);
+ putchar('\n');
+ continue;
+ }
+ prdatum(stderr, key);
+ fprintf(stderr, ": not found.\n");
+ }
+ break;
+ case DINSERT:
+ break;
+ case DDELETE:
+ while (fgets(line, LINEMAX, stdin) != NULL) {
+ n = strlen(line) - 1;
+ line[n] = 0;
+ key.dptr = line;
+ key.dsize = n;
+ if (dbm_delete(db, key) == -1) {
+ prdatum(stderr, key);
+ fprintf(stderr, ": not found.\n");
+ }
+ }
+ break;
+ case DCAT:
+ for (key = dbm_firstkey(db); key.dptr != 0;
+ key = dbm_nextkey(db)) {
+ prdatum(stdout, key);
+ putchar('\t');
+ prdatum(stdout, dbm_fetch(db, key));
+ putchar('\n');
+ }
+ break;
+ case DBUILD:
+#ifdef TIME
+ start = time(0);
+#endif
+ while (fgets(line, LINEMAX, stdin) != NULL) {
+ n = strlen(line) - 1;
+ line[n] = 0;
+ key.dptr = line;
+ if ((op = strchr(line, '\t')) != 0) {
+ key.dsize = op - line;
+ *op++ = 0;
+ val.dptr = op;
+ val.dsize = line + n - op;
+ }
+ else
+ oops("bad input; %s", line);
+
+ if (dbm_store(db, key, val, DBM_REPLACE) < 0) {
+ prdatum(stderr, key);
+ fprintf(stderr, ": ");
+ oops("store: %s", "failed");
+ }
+ }
+#ifdef TIME
+ printf("done: %d seconds.\n", time(0) - start);
+#endif
+ break;
+ case DPRESS:
+ break;
+ case DCREAT:
+ break;
+ }
+
+ dbm_close(db);
+}
+
+static void
+badk(word)
+char *word;
+{
+ register int i;
+
+ if (progname)
+ fprintf(stderr, "%s: ", progname);
+ fprintf(stderr, "bad keywd %s. use one of\n", word);
+ for (i = 0; i < (int)CTABSIZ; i++)
+ fprintf(stderr, "%-8s%c", cmds[i].sname,
+ ((i + 1) % 6 == 0) ? '\n' : ' ');
+ fprintf(stderr, "\n");
+ exit(1);
+ /*NOTREACHED*/
+}
+
+static cmd *
+parse(str)
+register char *str;
+{
+ register int i = CTABSIZ;
+ register cmd *p;
+
+ for (p = cmds; i--; p++)
+ if (strcmp(p->sname, str) == 0)
+ return p;
+ return NULL;
+}
+
+static void
+prdatum(stream, d)
+FILE *stream;
+datum d;
+{
+ register int c;
+ register char *p = d.dptr;
+ register int n = d.dsize;
+
+ while (n--) {
+ c = *p++ & 0377;
+ if (c & 0200) {
+ fprintf(stream, "M-");
+ c &= 0177;
+ }
+ if (c == 0177 || c < ' ')
+ fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
+ else
+ putc(c, stream);
+ }
+}
+
+
diff --git a/ext/SDBM_File/sdbm/grind b/ext/SDBM_File/sdbm/grind
new file mode 100755
index 0000000000..23728b7d49
--- /dev/null
+++ b/ext/SDBM_File/sdbm/grind
@@ -0,0 +1,9 @@
+#!/bin/sh
+rm -f /tmp/*.dir /tmp/*.pag
+awk -e '{
+ printf "%s\t", $0
+ for (i = 0; i < 40; i++)
+ printf "%s.", $0
+ printf "\n"
+}' < /usr/dict/words | $1 build /tmp/$2
+
diff --git a/ext/SDBM_File/sdbm/hash.c b/ext/SDBM_File/sdbm/hash.c
new file mode 100644
index 0000000000..eb585ac102
--- /dev/null
+++ b/ext/SDBM_File/sdbm/hash.c
@@ -0,0 +1,48 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain. keep it that way.
+ *
+ * hashing routine
+ */
+
+#include "config.h"
+#include "sdbm.h"
+/*
+ * polynomial conversion ignoring overflows
+ * [this seems to work remarkably well, in fact better
+ * then the ndbm hash function. Replace at your own risk]
+ * use: 65599 nice.
+ * 65587 even better.
+ */
+long
+sdbm_hash(str, len)
+register char *str;
+register int len;
+{
+ register unsigned long n = 0;
+
+#ifdef DUFF
+
+#define HASHC n = *str++ + 65599 * n
+
+ if (len > 0) {
+ register int loop = (len + 8 - 1) >> 3;
+
+ switch(len & (8 - 1)) {
+ case 0: do {
+ HASHC; case 7: HASHC;
+ case 6: HASHC; case 5: HASHC;
+ case 4: HASHC; case 3: HASHC;
+ case 2: HASHC; case 1: HASHC;
+ } while (--loop);
+ }
+
+ }
+#else
+ while (len--)
+ n = *str++ + 65599 * n;
+#endif
+ return n;
+}
diff --git a/ext/SDBM_File/sdbm/linux.patches b/ext/SDBM_File/sdbm/linux.patches
new file mode 100644
index 0000000000..cb7b1b7d8e
--- /dev/null
+++ b/ext/SDBM_File/sdbm/linux.patches
@@ -0,0 +1,67 @@
+*** sdbm.dist/./dbu.c Mon Feb 17 21:18:52 1992
+--- sdbm/./dbu.c Mon Feb 17 21:11:20 1992
+***************
+*** 12,18 ****
+ #endif
+
+ extern int getopt();
+! extern char *strchr();
+ extern void oops();
+
+ char *progname;
+--- 12,18 ----
+ #endif
+
+ extern int getopt();
+! /* extern char *strchr(); */
+ extern void oops();
+
+ char *progname;
+*** sdbm.dist/./makefile Mon Feb 17 21:18:56 1992
+--- sdbm/./makefile Mon Feb 17 21:10:46 1992
+***************
+*** 2,8 ****
+ # makefile for public domain ndbm-clone: sdbm
+ # DUFF: use duff's device (loop unroll) in parts of the code
+ #
+! CFLAGS = -O -DSDBM -DDUFF -DBSD42
+ #LDFLAGS = -p
+
+ OBJS = sdbm.o pair.o hash.o
+--- 2,8 ----
+ # makefile for public domain ndbm-clone: sdbm
+ # DUFF: use duff's device (loop unroll) in parts of the code
+ #
+! CFLAGS = -O -DSDBM -DDUFF
+ #LDFLAGS = -p
+
+ OBJS = sdbm.o pair.o hash.o
+*** sdbm.dist/./sdbm.c Mon Feb 17 21:19:17 1992
+--- sdbm/./sdbm.c Mon Feb 17 21:12:59 1992
+***************
+*** 25,30 ****
+--- 25,31 ----
+ #endif
+ #include <errno.h>
+ #include <string.h>
++ #include <unistd.h>
+
+ #ifdef __STDC__
+ #include <stddef.h>
+***************
+*** 43,49 ****
+
+ extern char *malloc proto((unsigned int));
+ extern void free proto((void *));
+! extern long lseek();
+
+ /*
+ * forward
+--- 44,50 ----
+
+ extern char *malloc proto((unsigned int));
+ extern void free proto((void *));
+! /* extern long lseek(); */
+
+ /*
+ * forward
diff --git a/ext/SDBM_File/sdbm/makefile.sdbm b/ext/SDBM_File/sdbm/makefile.sdbm
new file mode 100644
index 0000000000..c959c1fab5
--- /dev/null
+++ b/ext/SDBM_File/sdbm/makefile.sdbm
@@ -0,0 +1,55 @@
+#
+# makefile for public domain ndbm-clone: sdbm
+# DUFF: use duff's device (loop unroll) in parts of the code
+#
+CFLAGS = -O -DSDBM -DDUFF -DBSD42 -pic
+#LDFLAGS = -p
+
+OBJS = sdbm.o pair.o hash.o
+SRCS = sdbm.c pair.c hash.c dbu.c dba.c dbd.c util.c
+HDRS = tune.h sdbm.h pair.h
+MISC = README CHANGES COMPARE sdbm.3 dbe.c dbe.1 dbm.c dbm.h biblio \
+ readme.ms readme.ps
+
+all: dbu dba dbd dbe
+
+dbu: dbu.o sdbm util.o
+ cc $(LDFLAGS) -o dbu dbu.o util.o libsdbm.a
+
+dba: dba.o util.o
+ cc $(LDFLAGS) -o dba dba.o util.o
+dbd: dbd.o util.o
+ cc $(LDFLAGS) -o dbd dbd.o util.o
+dbe: dbe.o sdbm
+ cc $(LDFLAGS) -o dbe dbe.o libsdbm.a
+
+sdbm: $(OBJS)
+ ar cr libsdbm.a $(OBJS)
+ ranlib libsdbm.a
+### cp libsdbm.a /usr/lib/libsdbm.a
+
+dba.o: sdbm.h
+dbu.o: sdbm.h
+util.o:sdbm.h
+
+$(OBJS): sdbm.h tune.h pair.h
+
+#
+# dbu using berkelezoid ndbm routines [if you have them] for testing
+#
+#x-dbu: dbu.o util.o
+# cc $(CFLAGS) -o x-dbu dbu.o util.o
+lint:
+ lint -abchx $(SRCS)
+
+clean:
+ rm -f *.o mon.out core
+
+purge: clean
+ rm -f dbu libsdbm.a dbd dba dbe x-dbu *.dir *.pag
+
+shar:
+ shar $(MISC) makefile $(SRCS) $(HDRS) >SDBM.SHAR
+
+readme:
+ nroff -ms readme.ms | col -b >README
diff --git a/ext/SDBM_File/sdbm/pair.c b/ext/SDBM_File/sdbm/pair.c
new file mode 100644
index 0000000000..a02c73f28f
--- /dev/null
+++ b/ext/SDBM_File/sdbm/pair.c
@@ -0,0 +1,307 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ *
+ * page-level routines
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";
+#endif
+
+#include "config.h"
+#include "sdbm.h"
+#include "tune.h"
+#include "pair.h"
+
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+/*
+ * forward
+ */
+static int seepair proto((char *, int, char *, int));
+
+/*
+ * page format:
+ * +------------------------------+
+ * ino | n | keyoff | datoff | keyoff |
+ * +------------+--------+--------+
+ * | datoff | - - - ----> |
+ * +--------+---------------------+
+ * | F R E E A R E A |
+ * +--------------+---------------+
+ * | <---- - - - | data |
+ * +--------+-----+----+----------+
+ * | key | data | key |
+ * +--------+----------+----------+
+ *
+ * calculating the offsets for free area: if the number
+ * of entries (ino[0]) is zero, the offset to the END of
+ * the free area is the block size. Otherwise, it is the
+ * nth (ino[ino[0]]) entry's offset.
+ */
+
+int
+fitpair(pag, need)
+char *pag;
+int need;
+{
+ register int n;
+ register int off;
+ register int free;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+ free = off - (n + 1) * sizeof(short);
+ need += 2 * sizeof(short);
+
+ debug(("free %d need %d\n", free, need));
+
+ return need <= free;
+}
+
+void
+putpair(pag, key, val)
+char *pag;
+datum key;
+datum val;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+/*
+ * enter the key first
+ */
+ off -= key.dsize;
+ (void) memcpy(pag + off, key.dptr, key.dsize);
+ ino[n + 1] = off;
+/*
+ * now the data
+ */
+ off -= val.dsize;
+ (void) memcpy(pag + off, val.dptr, val.dsize);
+ ino[n + 2] = off;
+/*
+ * adjust item count
+ */
+ ino[0] += 2;
+}
+
+datum
+getpair(pag, key)
+char *pag;
+datum key;
+{
+ register int i;
+ register int n;
+ datum val;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return nullitem;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return nullitem;
+
+ val.dptr = pag + ino[i + 1];
+ val.dsize = ino[i] - ino[i + 1];
+ return val;
+}
+
+#ifdef SEEDUPS
+int
+duppair(pag, key)
+char *pag;
+datum key;
+{
+ register short *ino = (short *) pag;
+ return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
+}
+#endif
+
+datum
+getnkey(pag, num)
+char *pag;
+int num;
+{
+ datum key;
+ register int off;
+ register short *ino = (short *) pag;
+
+ num = num * 2 - 1;
+ if (ino[0] == 0 || num > ino[0])
+ return nullitem;
+
+ off = (num > 1) ? ino[num - 1] : PBLKSIZ;
+
+ key.dptr = pag + ino[num];
+ key.dsize = off - ino[num];
+
+ return key;
+}
+
+int
+delpair(pag, key)
+char *pag;
+datum key;
+{
+ register int n;
+ register int i;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return 0;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return 0;
+/*
+ * found the key. if it is the last entry
+ * [i.e. i == n - 1] we just adjust the entry count.
+ * hard case: move all data down onto the deleted pair,
+ * shift offsets onto deleted offsets, and adjust them.
+ * [note: 0 < i < n]
+ */
+ if (i < n - 1) {
+ register int m;
+ register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
+ register char *src = pag + ino[i + 1];
+ register int zoo = dst - src;
+
+ debug(("free-up %d ", zoo));
+/*
+ * shift data/keys down
+ */
+ m = ino[i + 1] - ino[n];
+#ifdef DUFF
+#define MOVB *--dst = *--src
+
+ if (m > 0) {
+ register int loop = (m + 8 - 1) >> 3;
+
+ switch (m & (8 - 1)) {
+ case 0: do {
+ MOVB; case 7: MOVB;
+ case 6: MOVB; case 5: MOVB;
+ case 4: MOVB; case 3: MOVB;
+ case 2: MOVB; case 1: MOVB;
+ } while (--loop);
+ }
+ }
+#else
+#ifdef HAS_MEMMOVE
+ dst -= m;
+ src -= m;
+ memmove(dst, src, m);
+#else
+ while (m--)
+ *--dst = *--src;
+#endif
+#endif
+/*
+ * adjust offset index up
+ */
+ while (i < n - 1) {
+ ino[i] = ino[i + 2] + zoo;
+ i++;
+ }
+ }
+ ino[0] -= 2;
+ return 1;
+}
+
+/*
+ * search for the key in the page.
+ * return offset index in the range 0 < i < n.
+ * return 0 if not found.
+ */
+static int
+seepair(pag, n, key, siz)
+char *pag;
+register int n;
+register char *key;
+register int siz;
+{
+ register int i;
+ register int off = PBLKSIZ;
+ register short *ino = (short *) pag;
+
+ for (i = 1; i < n; i += 2) {
+ if (siz == off - ino[i] &&
+ memcmp(key, pag + ino[i], siz) == 0)
+ return i;
+ off = ino[i + 1];
+ }
+ return 0;
+}
+
+void
+splpage(pag, new, sbit)
+char *pag;
+char *new;
+long sbit;
+{
+ datum key;
+ datum val;
+
+ register int n;
+ register int off = PBLKSIZ;
+ char cur[PBLKSIZ];
+ register short *ino = (short *) cur;
+
+ (void) memcpy(cur, pag, PBLKSIZ);
+ (void) memset(pag, 0, PBLKSIZ);
+ (void) memset(new, 0, PBLKSIZ);
+
+ n = ino[0];
+ for (ino++; n > 0; ino += 2) {
+ key.dptr = cur + ino[0];
+ key.dsize = off - ino[0];
+ val.dptr = cur + ino[1];
+ val.dsize = ino[0] - ino[1];
+/*
+ * select the page pointer (by looking at sbit) and insert
+ */
+ (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+
+ off = ino[1];
+ n -= 2;
+ }
+
+ debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
+ ((short *) new)[0] / 2,
+ ((short *) pag)[0] / 2));
+}
+
+/*
+ * check page sanity:
+ * number of entries should be something
+ * reasonable, and all offsets in the index should be in order.
+ * this could be made more rigorous.
+ */
+int
+chkpage(pag)
+char *pag;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
+ return 0;
+
+ if (n > 0) {
+ off = PBLKSIZ;
+ for (ino++; n > 0; ino += 2) {
+ if (ino[0] > off || ino[1] > off ||
+ ino[1] > ino[0])
+ return 0;
+ off = ino[1];
+ n -= 2;
+ }
+ }
+ return 1;
+}
diff --git a/ext/SDBM_File/sdbm/pair.h b/ext/SDBM_File/sdbm/pair.h
new file mode 100644
index 0000000000..bd66d02fd2
--- /dev/null
+++ b/ext/SDBM_File/sdbm/pair.h
@@ -0,0 +1,10 @@
+extern int fitpair proto((char *, int));
+extern void putpair proto((char *, datum, datum));
+extern datum getpair proto((char *, datum));
+extern int delpair proto((char *, datum));
+extern int chkpage proto((char *));
+extern datum getnkey proto((char *, int));
+extern void splpage proto((char *, char *, long));
+#ifdef SEEDUPS
+extern int duppair proto((char *, datum));
+#endif
diff --git a/ext/SDBM_File/sdbm/readme.ms b/ext/SDBM_File/sdbm/readme.ms
new file mode 100644
index 0000000000..01ca17ccdf
--- /dev/null
+++ b/ext/SDBM_File/sdbm/readme.ms
@@ -0,0 +1,353 @@
+.\" tbl | readme.ms | [tn]roff -ms | ...
+.\" note the "C" (courier) and "CB" fonts: you will probably have to
+.\" change these.
+.\" $Id: readme.ms,v 1.1 90/12/13 13:09:15 oz Exp Locker: oz $
+
+.de P1
+.br
+.nr dT 4
+.nf
+.ft C
+.sp .5
+.nr t \\n(dT*\\w'x'u
+.ta 1u*\\ntu 2u*\\ntu 3u*\\ntu 4u*\\ntu 5u*\\ntu 6u*\\ntu 7u*\\ntu 8u*\\ntu 9u*\\ntu 10u*\\ntu 11u*\\ntu 12u*\\ntu 13u*\\ntu 14u*\\ntu
+..
+.de P2
+.br
+.ft 1
+.br
+.sp .5
+.br
+.fi
+..
+.\" CW uses the typewriter/courier font.
+.de CW
+\fC\\$1\\fP\\$2
+..
+
+.\" Footnote numbering [by Henry Spencer]
+.\" <text>\*f for a footnote number..
+.\" .FS
+.\" \*F <footnote text>
+.\" .FE
+.\"
+.ds f \\u\\s-2\\n+f\\s+2\\d
+.nr f 0 1
+.ds F \\n+F.
+.nr F 0 1
+
+.ND
+.LP
+.TL
+\fIsdbm\fP \(em Substitute DBM
+.br
+or
+.br
+Berkeley \fIndbm\fP for Every UN*X\** Made Simple
+.AU
+Ozan (oz) Yigit
+.AI
+The Guild of PD Software Toolmakers
+Toronto - Canada
+.sp
+oz@nexus.yorku.ca
+.LP
+.FS
+UN*X is not a trademark of any (dis)organization.
+.FE
+.sp 2
+\fIImplementation is the sincerest form of flattery. \(em L. Peter Deutsch\fP
+.SH
+A The Clone of the \fIndbm\fP library
+.PP
+The sources accompanying this notice \(em \fIsdbm\fP \(em constitute
+the first public release (Dec. 1990) of a complete clone of
+the Berkeley UN*X \fIndbm\fP library. The \fIsdbm\fP library is meant to
+clone the proven functionality of \fIndbm\fP as closely as possible,
+including a few improvements. It is practical, easy to understand, and
+compatible.
+The \fIsdbm\fP library is not derived from any licensed, proprietary or
+copyrighted software.
+.PP
+The \fIsdbm\fP implementation is based on a 1978 algorithm
+[Lar78] by P.-A. (Paul) Larson known as ``Dynamic Hashing''.
+In the course of searching for a substitute for \fIndbm\fP, I
+prototyped three different external-hashing algorithms [Lar78, Fag79, Lit80]
+and ultimately chose Larson's algorithm as a basis of the \fIsdbm\fP
+implementation. The Bell Labs
+\fIdbm\fP (and therefore \fIndbm\fP) is based on an algorithm invented by
+Ken Thompson, [Tho90, Tor87] and predates Larson's work.
+.PP
+The \fIsdbm\fR programming interface is totally compatible
+with \fIndbm\fP and includes a slight improvement in database initialization.
+It is also expected to be binary-compatible under most UN*X versions that
+support the \fIndbm\fP library.
+.PP
+The \fIsdbm\fP implementation shares the shortcomings of the \fIndbm\fP
+library, as a side effect of various simplifications to the original Larson
+algorithm. It does produce \fIholes\fP in the page file as it writes
+pages past the end of file. (Larson's paper include a clever solution to
+this problem that is a result of using the hash value directly as a block
+address.) On the other hand, extensive tests seem to indicate that \fIsdbm\fP
+creates fewer holes in general, and the resulting pagefiles are
+smaller. The \fIsdbm\fP implementation is also faster than \fIndbm\fP
+in database creation.
+Unlike the \fIndbm\fP, the \fIsdbm\fP
+.CW store
+operation will not ``wander away'' trying to split its
+data pages to insert a datum that \fIcannot\fP (due to elaborate worst-case
+situations) be inserted. (It will fail after a pre-defined number of attempts.)
+.SH
+Important Compatibility Warning
+.PP
+The \fIsdbm\fP and \fIndbm\fP
+libraries \fIcannot\fP share databases: one cannot read the (dir/pag)
+database created by the other. This is due to the differences
+between the \fIndbm\fP and \fIsdbm\fP algorithms\**,
+.FS
+Torek's discussion [Tor87]
+indicates that \fIdbm/ndbm\fP implementations use the hash
+value to traverse the radix trie differently than \fIsdbm\fP
+and as a result, the page indexes are generated in \fIdifferent\fP order.
+For more information, send e-mail to the author.
+.FE
+and the hash functions
+used.
+It is easy to convert between the \fIdbm/ndbm\fP databases and \fIsdbm\fP
+by ignoring the index completely: see
+.CW dbd ,
+.CW dbu
+etc.
+.R
+.LP
+.SH
+Notice of Intellectual Property
+.LP
+\fIThe entire\fP sdbm \fIlibrary package, as authored by me,\fP Ozan S. Yigit,
+\fIis hereby placed in the public domain.\fP As such, the author is not
+responsible for the consequences of use of this software, no matter how
+awful, even if they arise from defects in it. There is no expressed or
+implied warranty for the \fIsdbm\fP library.
+.PP
+Since the \fIsdbm\fP
+library package is in the public domain, this \fIoriginal\fP
+release or any additional public-domain releases of the modified original
+cannot possibly (by definition) be withheld from you. Also by definition,
+You (singular) have all the rights to this code (including the right to
+sell without permission, the right to hoard\**
+.FS
+You cannot really hoard something that is available to the public at
+large, but try if it makes you feel any better.
+.FE
+and the right to do other icky things as
+you see fit) but those rights are also granted to everyone else.
+.PP
+Please note that all previous distributions of this software contained
+a copyright (which is now dropped) to protect its
+origins and its current public domain status against any possible claims
+and/or challenges.
+.SH
+Acknowledgments
+.PP
+Many people have been very helpful and supportive. A partial list would
+necessarily include Rayan Zacherissen (who contributed the man page,
+and also hacked a MMAP version of \fIsdbm\fP),
+Arnold Robbins, Chris Lewis,
+Bill Davidsen, Henry Spencer, Geoff Collyer, Rich Salz (who got me started
+in the first place), Johannes Ruschein
+(who did the minix port) and David Tilbrook. I thank you all.
+.SH
+Distribution Manifest and Notes
+.LP
+This distribution of \fIsdbm\fP includes (at least) the following:
+.P1
+ CHANGES change log
+ README this file.
+ biblio a small bibliography on external hashing
+ dba.c a crude (n/s)dbm page file analyzer
+ dbd.c a crude (n/s)dbm page file dumper (for conversion)
+ dbe.1 man page for dbe.c
+ dbe.c Janick's database editor
+ dbm.c a dbm library emulation wrapper for ndbm/sdbm
+ dbm.h header file for the above
+ dbu.c a crude db management utility
+ hash.c hashing function
+ makefile guess.
+ pair.c page-level routines (posted earlier)
+ pair.h header file for the above
+ readme.ms troff source for the README file
+ sdbm.3 man page
+ sdbm.c the real thing
+ sdbm.h header file for the above
+ tune.h place for tuning & portability thingies
+ util.c miscellaneous
+.P2
+.PP
+.CW dbu
+is a simple database manipulation program\** that tries to look
+.FS
+The
+.CW dbd ,
+.CW dba ,
+.CW dbu
+utilities are quick hacks and are not fit for production use. They were
+developed late one night, just to test out \fIsdbm\fP, and convert some
+databases.
+.FE
+like Bell Labs'
+.CW cbt
+utility. It is currently incomplete in functionality.
+I use
+.CW dbu
+to test out the routines: it takes (from stdin) tab separated
+key/value pairs for commands like
+.CW build
+or
+.CW insert
+or takes keys for
+commands like
+.CW delete
+or
+.CW look .
+.P1
+ dbu <build|creat|look|insert|cat|delete> dbmfile
+.P2
+.PP
+.CW dba
+is a crude analyzer of \fIdbm/sdbm/ndbm\fP
+page files. It scans the entire
+page file, reporting page level statistics, and totals at the end.
+.PP
+.CW dbd
+is a crude dump program for \fIdbm/ndbm/sdbm\fP
+databases. It ignores the
+bitmap, and dumps the data pages in sequence. It can be used to create
+input for the
+.CW dbu
+utility.
+Note that
+.CW dbd
+will skip any NULLs in the key and data
+fields, thus is unsuitable to convert some peculiar databases that
+insist in including the terminating null.
+.PP
+I have also included a copy of the
+.CW dbe
+(\fIndbm\fP DataBase Editor) by Janick Bergeron [janick@bnr.ca] for
+your pleasure. You may find it more useful than the little
+.CW dbu
+utility.
+.PP
+.CW dbm.[ch]
+is a \fIdbm\fP library emulation on top of \fIndbm\fP
+(and hence suitable for \fIsdbm\fP). Written by Robert Elz.
+.PP
+The \fIsdbm\fP
+library has been around in beta test for quite a long time, and from whatever
+little feedback I received (maybe no news is good news), I believe it has been
+functioning without any significant problems. I would, of course, appreciate
+all fixes and/or improvements. Portability enhancements would especially be
+useful.
+.SH
+Implementation Issues
+.PP
+Hash functions:
+The algorithm behind \fIsdbm\fP implementation needs a good bit-scrambling
+hash function to be effective. I ran into a set of constants for a simple
+hash function that seem to help \fIsdbm\fP perform better than \fIndbm\fP
+for various inputs:
+.P1
+ /*
+ * polynomial conversion ignoring overflows
+ * 65599 nice. 65587 even better.
+ */
+ long
+ dbm_hash(char *str, int len) {
+ register unsigned long n = 0;
+
+ while (len--)
+ n = n * 65599 + *str++;
+ return n;
+ }
+.P2
+.PP
+There may be better hash functions for the purposes of dynamic hashing.
+Try your favorite, and check the pagefile. If it contains too many pages
+with too many holes, (in relation to this one for example) or if
+\fIsdbm\fP
+simply stops working (fails after
+.CW SPLTMAX
+attempts to split) when you feed your
+NEWS
+.CW history
+file to it, you probably do not have a good hashing function.
+If you do better (for different types of input), I would like to know
+about the function you use.
+.PP
+Block sizes: It seems (from various tests on a few machines) that a page
+file block size
+.CW PBLKSIZ
+of 1024 is by far the best for performance, but
+this also happens to limit the size of a key/value pair. Depending on your
+needs, you may wish to increase the page size, and also adjust
+.CW PAIRMAX
+(the maximum size of a key/value pair allowed: should always be at least
+three words smaller than
+.CW PBLKSIZ .)
+accordingly. The system-wide version of the library
+should probably be
+configured with 1024 (distribution default), as this appears to be sufficient
+for most common uses of \fIsdbm\fP.
+.SH
+Portability
+.PP
+This package has been tested in many different UN*Xes even including minix,
+and appears to be reasonably portable. This does not mean it will port
+easily to non-UN*X systems.
+.SH
+Notes and Miscellaneous
+.PP
+The \fIsdbm\fP is not a very complicated package, at least not after you
+familiarize yourself with the literature on external hashing. There are
+other interesting algorithms in existence that ensure (approximately)
+single-read access to a data value associated with any key. These are
+directory-less schemes such as \fIlinear hashing\fP [Lit80] (+ Larson
+variations), \fIspiral storage\fP [Mar79] or directory schemes such as
+\fIextensible hashing\fP [Fag79] by Fagin et al. I do hope these sources
+provide a reasonable playground for experimentation with other algorithms.
+See the June 1988 issue of ACM Computing Surveys [Enb88] for an
+excellent overview of the field.
+.PG
+.SH
+References
+.LP
+.IP [Lar78] 4m
+P.-A. Larson,
+``Dynamic Hashing'', \fIBIT\fP, vol. 18, pp. 184-201, 1978.
+.IP [Tho90] 4m
+Ken Thompson, \fIprivate communication\fP, Nov. 1990
+.IP [Lit80] 4m
+W. Litwin,
+`` Linear Hashing: A new tool for file and table addressing'',
+\fIProceedings of the 6th Conference on Very Large Dabatases (Montreal)\fP,
+pp. 212-223, Very Large Database Foundation, Saratoga, Calif., 1980.
+.IP [Fag79] 4m
+R. Fagin, J. Nievergelt, N. Pippinger, and H. R. Strong,
+``Extendible Hashing - A Fast Access Method for Dynamic Files'',
+\fIACM Trans. Database Syst.\fP, vol. 4, no.3, pp. 315-344, Sept. 1979.
+.IP [Wal84] 4m
+Rich Wales,
+``Discussion of "dbm" data base system'', \fIUSENET newsgroup unix.wizards\fP,
+Jan. 1984.
+.IP [Tor87] 4m
+Chris Torek,
+``Re: dbm.a and ndbm.a archives'', \fIUSENET newsgroup comp.unix\fP,
+1987.
+.IP [Mar79] 4m
+G. N. Martin,
+``Spiral Storage: Incrementally Augmentable Hash Addressed Storage'',
+\fITechnical Report #27\fP, University of Varwick, Coventry, U.K., 1979.
+.IP [Enb88] 4m
+R. J. Enbody and H. C. Du,
+``Dynamic Hashing Schemes'',\fIACM Computing Surveys\fP,
+vol. 20, no. 2, pp. 85-113, June 1988.
diff --git a/ext/SDBM_File/sdbm/readme.ps b/ext/SDBM_File/sdbm/readme.ps
new file mode 100644
index 0000000000..2b0c675595
--- /dev/null
+++ b/ext/SDBM_File/sdbm/readme.ps
@@ -0,0 +1,2225 @@
+%!PS-Adobe-1.0
+%%Creator: yetti:oz (Ozan Yigit)
+%%Title: stdin (ditroff)
+%%CreationDate: Thu Dec 13 15:56:08 1990
+%%EndComments
+% lib/psdit.pro -- prolog for psdit (ditroff) files
+% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
+% last edit: shore Sat Nov 23 20:28:03 1985
+% RCSID: $Header: psdit.pro,v 2.1 85/11/24 12:19:43 shore Rel $
+
+/$DITroff 140 dict def $DITroff begin
+/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
+/xi {0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
+ /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F
+ /pagesave save def}def
+/PB{save /psv exch def currentpoint translate
+ resolution 72 div dup neg scale 0 0 moveto}def
+/PE{psv restore}def
+/arctoobig 90 def /arctoosmall .05 def
+/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
+/tan{dup sin exch cos div}def
+/point{resolution 72 div mul}def
+/dround {transform round exch round exch itransform}def
+/xT{/devname exch def}def
+/xr{/mh exch def /my exch def /resolution exch def}def
+/xp{}def
+/xs{docsave restore end}def
+/xt{}def
+/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
+ {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
+/xH{/fontheight exch def F}def
+/xS{/fontslant exch def F}def
+/s{/fontsize exch def /fontheight fontsize def F}def
+/f{/fontnum exch def F}def
+/F{fontheight 0 le {/fontheight fontsize def}if
+ fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
+ fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
+ makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
+/X{exch currentpoint exch pop moveto show}def
+/N{3 1 roll moveto show}def
+/Y{exch currentpoint pop exch moveto show}def
+/S{show}def
+/ditpush{}def/ditpop{}def
+/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
+/AN{4 2 roll moveto 0 exch ashow}def
+/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
+/AS{0 exch ashow}def
+/MX{currentpoint exch pop moveto}def
+/MY{currentpoint pop exch moveto}def
+/MXY{moveto}def
+/cb{pop}def % action on unknown char -- nothing for now
+/n{}def/w{}def
+/p{pop showpage pagesave restore /pagesave save def}def
+/abspoint{currentpoint exch pop add exch currentpoint pop add exch}def
+/distance{dup mul exch dup mul add sqrt}def
+/dstroke{currentpoint stroke moveto}def
+/Dl{2 copy gsave rlineto stroke grestore rmoveto}def
+/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
+ currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
+ currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
+/Dc{dup arcellipse dstroke}def
+/De{arcellipse dstroke}def
+/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
+ /cradius centerv centerv mul centerh centerh mul add sqrt def
+ /eradius endv endv mul endh endh mul add sqrt def
+ /endang endv endh atan def
+ /startang centerv neg centerh neg atan def
+ /sweep startang endang sub dup 0 lt{360 add}if def
+ sweep arctoobig gt
+ {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
+ /midh midang cos midrad mul def /midv midang sin midrad mul def
+ midh neg midv neg endh endv centerh centerv midh midv Da
+ currentpoint moveto Da}
+ {sweep arctoosmall ge
+ {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
+ centerv neg controldelt mul centerh controldelt mul
+ endv neg controldelt mul centerh add endh add
+ endh controldelt mul centerv add endv add
+ centerh endh add centerv endv add rcurveto dstroke}
+ {centerh endh add centerv endv add rlineto dstroke}ifelse}ifelse}def
+
+/Barray 200 array def % 200 values in a wiggle
+/D~{mark}def
+/D~~{counttomark Barray exch 0 exch getinterval astore /Bcontrol exch def pop
+ /Blen Bcontrol length def Blen 4 ge Blen 2 mod 0 eq and
+ {Bcontrol 0 get Bcontrol 1 get abspoint /Ycont exch def /Xcont exch def
+ Bcontrol 0 2 copy get 2 mul put Bcontrol 1 2 copy get 2 mul put
+ Bcontrol Blen 2 sub 2 copy get 2 mul put
+ Bcontrol Blen 1 sub 2 copy get 2 mul put
+ /Ybi /Xbi currentpoint 3 1 roll def def 0 2 Blen 4 sub
+ {/i exch def
+ Bcontrol i get 3 div Bcontrol i 1 add get 3 div
+ Bcontrol i get 3 mul Bcontrol i 2 add get add 6 div
+ Bcontrol i 1 add get 3 mul Bcontrol i 3 add get add 6 div
+ /Xbi Xcont Bcontrol i 2 add get 2 div add def
+ /Ybi Ycont Bcontrol i 3 add get 2 div add def
+ /Xcont Xcont Bcontrol i 2 add get add def
+ /Ycont Ycont Bcontrol i 3 add get add def
+ Xbi currentpoint pop sub Ybi currentpoint exch pop sub rcurveto
+ }for dstroke}if}def
+end
+/ditstart{$DITroff begin
+ /nfonts 60 def % NFONTS makedev/ditroff dependent!
+ /fonts[nfonts{0}repeat]def
+ /fontnames[nfonts{()}repeat]def
+/docsave save def
+}def
+
+% character outcalls
+/oc {/pswid exch def /cc exch def /name exch def
+ /ditwid pswid fontsize mul resolution mul 72000 div def
+ /ditsiz fontsize resolution mul 72 div def
+ ocprocs name known{ocprocs name get exec}{name cb}
+ ifelse}def
+/fractm [.65 0 0 .6 0 0] def
+/fraction
+ {/fden exch def /fnum exch def gsave /cf currentfont def
+ cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
+ fnum show rmoveto currentfont cf setfont(\244)show setfont fden show
+ grestore ditwid 0 rmoveto} def
+/oce {grestore ditwid 0 rmoveto}def
+/dm {ditsiz mul}def
+/ocprocs 50 dict def ocprocs begin
+(14){(1)(4)fraction}def
+(12){(1)(2)fraction}def
+(34){(3)(4)fraction}def
+(13){(1)(3)fraction}def
+(23){(2)(3)fraction}def
+(18){(1)(8)fraction}def
+(38){(3)(8)fraction}def
+(58){(5)(8)fraction}def
+(78){(7)(8)fraction}def
+(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
+(is){gsave 0 .15 dm rmoveto(\362)show oce}def
+(->){gsave 0 .02 dm rmoveto(\256)show oce}def
+(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
+(==){gsave 0 .05 dm rmoveto(\272)show oce}def
+end
+
+% an attempt at a PostScript FONT to implement ditroff special chars
+% this will enable us to
+% cache the little buggers
+% generate faster, more compact PS out of psdit
+% confuse everyone (including myself)!
+50 dict dup begin
+/FontType 3 def
+/FontName /DIThacks def
+/FontMatrix [.001 0 0 .001 0 0] def
+/FontBBox [-260 -260 900 900] def% a lie but ...
+/Encoding 256 array def
+0 1 255{Encoding exch /.notdef put}for
+Encoding
+ dup 8#040/space put %space
+ dup 8#110/rc put %right ceil
+ dup 8#111/lt put %left top curl
+ dup 8#112/bv put %bold vert
+ dup 8#113/lk put %left mid curl
+ dup 8#114/lb put %left bot curl
+ dup 8#115/rt put %right top curl
+ dup 8#116/rk put %right mid curl
+ dup 8#117/rb put %right bot curl
+ dup 8#120/rf put %right floor
+ dup 8#121/lf put %left floor
+ dup 8#122/lc put %left ceil
+ dup 8#140/sq put %square
+ dup 8#141/bx put %box
+ dup 8#142/ci put %circle
+ dup 8#143/br put %box rule
+ dup 8#144/rn put %root extender
+ dup 8#145/vr put %vertical rule
+ dup 8#146/ob put %outline bullet
+ dup 8#147/bu put %bullet
+ dup 8#150/ru put %rule
+ dup 8#151/ul put %underline
+ pop
+/DITfd 100 dict def
+/BuildChar{0 begin
+ /cc exch def /fd exch def
+ /charname fd /Encoding get cc get def
+ /charwid fd /Metrics get charname get def
+ /charproc fd /CharProcs get charname get def
+ charwid 0 fd /FontBBox get aload pop setcachedevice
+ 2 setlinejoin 40 setlinewidth
+ newpath 0 0 moveto gsave charproc grestore
+ end}def
+/BuildChar load 0 DITfd put
+%/UniqueID 5 def
+/CharProcs 50 dict def
+CharProcs begin
+/space{}def
+/.notdef{}def
+/ru{500 0 rls}def
+/rn{0 840 moveto 500 0 rls}def
+/vr{0 800 moveto 0 -770 rls}def
+/bv{0 800 moveto 0 -1000 rls}def
+/br{0 750 moveto 0 -1000 rls}def
+/ul{0 -140 moveto 500 0 rls}def
+/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
+/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
+/sq{80 0 rmoveto currentpoint dround newpath moveto
+ 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
+/bx{80 0 rmoveto currentpoint dround newpath moveto
+ 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
+/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
+ 50 setlinewidth stroke}def
+
+/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
+/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
+/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
+/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
+/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
+ 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
+ 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
+/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
+/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
+/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
+end
+
+/Metrics 50 dict def Metrics begin
+/.notdef 0 def
+/space 500 def
+/ru 500 def
+/br 0 def
+/lt 416 def
+/lb 416 def
+/rt 416 def
+/rb 416 def
+/lk 416 def
+/rk 416 def
+/rc 416 def
+/lc 416 def
+/rf 416 def
+/lf 416 def
+/bv 416 def
+/ob 350 def
+/bu 350 def
+/ci 750 def
+/bx 750 def
+/sq 750 def
+/rn 500 def
+/ul 500 def
+/vr 0 def
+end
+
+DITfd begin
+/s2 500 def /s4 250 def /s3 333 def
+/a4p{arcto pop pop pop pop}def
+/2cx{2 copy exch}def
+/rls{rlineto stroke}def
+/currx{currentpoint pop}def
+/dround{transform round exch round exch itransform} def
+end
+end
+/DIThacks exch definefont pop
+ditstart
+(psc)xT
+576 1 1 xr
+1(Times-Roman)xf 1 f
+2(Times-Italic)xf 2 f
+3(Times-Bold)xf 3 f
+4(Times-BoldItalic)xf 4 f
+5(Helvetica)xf 5 f
+6(Helvetica-Bold)xf 6 f
+7(Courier)xf 7 f
+8(Courier-Bold)xf 8 f
+9(Symbol)xf 9 f
+10(DIThacks)xf 10 f
+10 s
+1 f
+xi
+%%EndProlog
+
+%%Page: 1 1
+10 s 0 xH 0 xS 1 f
+8 s
+2 f
+12 s
+1778 672(sdbm)N
+3 f
+2004(\320)X
+2124(Substitute)X
+2563(DBM)X
+2237 768(or)N
+1331 864(Berkeley)N
+2 f
+1719(ndbm)X
+3 f
+1956(for)X
+2103(Every)X
+2373(UN*X)X
+1 f
+10 s
+2628 832(1)N
+3 f
+12 s
+2692 864(Made)N
+2951(Simple)X
+2 f
+10 s
+2041 1056(Ozan)N
+2230(\(oz\))X
+2375(Yigit)X
+1 f
+1658 1200(The)N
+1803(Guild)X
+2005(of)X
+2092(PD)X
+2214(Software)X
+2524(Toolmakers)X
+2000 1296(Toronto)N
+2278(-)X
+2325(Canada)X
+1965 1488(oz@nexus.yorku.ca)N
+2 f
+555 1804(Implementation)N
+1078(is)X
+1151(the)X
+1269(sincerest)X
+1574(form)X
+1745(of)X
+1827(\257attery.)X
+2094(\320)X
+2185(L.)X
+2269(Peter)X
+2463(Deutsch)X
+3 f
+555 1996(A)N
+633(The)X
+786(Clone)X
+1006(of)X
+1093(the)X
+2 f
+1220(ndbm)X
+3 f
+1418(library)X
+1 f
+755 2120(The)N
+903(sources)X
+1167(accompanying)X
+1658(this)X
+1796(notice)X
+2015(\320)X
+2 f
+2118(sdbm)X
+1 f
+2309(\320)X
+2411(constitute)X
+2744(the)X
+2864(\256rst)X
+3010(public)X
+3232(release)X
+3478(\(Dec.)X
+3677(1990\))X
+3886(of)X
+3975(a)X
+555 2216(complete)N
+874(clone)X
+1073(of)X
+1165(the)X
+1288(Berkeley)X
+1603(UN*X)X
+2 f
+1842(ndbm)X
+1 f
+2045(library.)X
+2304(The)X
+2 f
+2454(sdbm)X
+1 f
+2648(library)X
+2887(is)X
+2965(meant)X
+3186(to)X
+3273(clone)X
+3472(the)X
+3594(proven)X
+3841(func-)X
+555 2312(tionality)N
+846(of)X
+2 f
+938(ndbm)X
+1 f
+1141(as)X
+1233(closely)X
+1485(as)X
+1576(possible,)X
+1882(including)X
+2208(a)X
+2268(few)X
+2413(improvements.)X
+2915(It)X
+2988(is)X
+3065(practical,)X
+3386(easy)X
+3553(to)X
+3639(understand,)X
+555 2408(and)N
+691(compatible.)X
+1107(The)X
+2 f
+1252(sdbm)X
+1 f
+1441(library)X
+1675(is)X
+1748(not)X
+1870(derived)X
+2131(from)X
+2307(any)X
+2443(licensed,)X
+2746(proprietary)X
+3123(or)X
+3210(copyrighted)X
+3613(software.)X
+755 2532(The)N
+2 f
+910(sdbm)X
+1 f
+1109(implementation)X
+1641(is)X
+1723(based)X
+1935(on)X
+2044(a)X
+2109(1978)X
+2298(algorithm)X
+2638([Lar78])X
+2913(by)X
+3022(P.-A.)X
+3220(\(Paul\))X
+3445(Larson)X
+3697(known)X
+3944(as)X
+555 2628(``Dynamic)N
+934(Hashing''.)X
+1326(In)X
+1424(the)X
+1553(course)X
+1794(of)X
+1892(searching)X
+2231(for)X
+2355(a)X
+2421(substitute)X
+2757(for)X
+2 f
+2881(ndbm)X
+1 f
+3059(,)X
+3109(I)X
+3166(prototyped)X
+3543(three)X
+3734(different)X
+555 2724(external-hashing)N
+1119(algorithms)X
+1490([Lar78,)X
+1758(Fag79,)X
+2007(Lit80])X
+2236(and)X
+2381(ultimately)X
+2734(chose)X
+2946(Larson's)X
+3256(algorithm)X
+3596(as)X
+3692(a)X
+3756(basis)X
+3944(of)X
+555 2820(the)N
+2 f
+680(sdbm)X
+1 f
+875(implementation.)X
+1423(The)X
+1574(Bell)X
+1733(Labs)X
+2 f
+1915(dbm)X
+1 f
+2079(\(and)X
+2248(therefore)X
+2 f
+2565(ndbm)X
+1 f
+2743(\))X
+2796(is)X
+2875(based)X
+3084(on)X
+3190(an)X
+3292(algorithm)X
+3629(invented)X
+3931(by)X
+555 2916(Ken)N
+709(Thompson,)X
+1091([Tho90,)X
+1367(Tor87])X
+1610(and)X
+1746(predates)X
+2034(Larson's)X
+2335(work.)X
+755 3040(The)N
+2 f
+903(sdbm)X
+1 f
+1095(programming)X
+1553(interface)X
+1857(is)X
+1932(totally)X
+2158(compatible)X
+2536(with)X
+2 f
+2700(ndbm)X
+1 f
+2900(and)X
+3038(includes)X
+3327(a)X
+3385(slight)X
+3584(improvement)X
+555 3136(in)N
+641(database)X
+942(initialization.)X
+1410(It)X
+1483(is)X
+1560(also)X
+1713(expected)X
+2023(to)X
+2109(be)X
+2208(binary-compatible)X
+2819(under)X
+3025(most)X
+3203(UN*X)X
+3440(versions)X
+3730(that)X
+3873(sup-)X
+555 3232(port)N
+704(the)X
+2 f
+822(ndbm)X
+1 f
+1020(library.)X
+755 3356(The)N
+2 f
+909(sdbm)X
+1 f
+1107(implementation)X
+1638(shares)X
+1868(the)X
+1995(shortcomings)X
+2455(of)X
+2551(the)X
+2 f
+2678(ndbm)X
+1 f
+2885(library,)X
+3148(as)X
+3244(a)X
+3309(side)X
+3467(effect)X
+3680(of)X
+3775(various)X
+555 3452(simpli\256cations)N
+1046(to)X
+1129(the)X
+1248(original)X
+1518(Larson)X
+1762(algorithm.)X
+2114(It)X
+2183(does)X
+2350(produce)X
+2 f
+2629(holes)X
+1 f
+2818(in)X
+2900(the)X
+3018(page)X
+3190(\256le)X
+3312(as)X
+3399(it)X
+3463(writes)X
+3679(pages)X
+3882(past)X
+555 3548(the)N
+680(end)X
+823(of)X
+917(\256le.)X
+1066(\(Larson's)X
+1400(paper)X
+1605(include)X
+1867(a)X
+1929(clever)X
+2152(solution)X
+2435(to)X
+2523(this)X
+2664(problem)X
+2957(that)X
+3103(is)X
+3182(a)X
+3244(result)X
+3448(of)X
+3541(using)X
+3740(the)X
+3864(hash)X
+555 3644(value)N
+758(directly)X
+1032(as)X
+1128(a)X
+1193(block)X
+1400(address.\))X
+1717(On)X
+1844(the)X
+1971(other)X
+2165(hand,)X
+2370(extensive)X
+2702(tests)X
+2873(seem)X
+3067(to)X
+3158(indicate)X
+3441(that)X
+2 f
+3590(sdbm)X
+1 f
+3787(creates)X
+555 3740(fewer)N
+762(holes)X
+954(in)X
+1039(general,)X
+1318(and)X
+1456(the)X
+1576(resulting)X
+1878(page\256les)X
+2185(are)X
+2306(smaller.)X
+2584(The)X
+2 f
+2731(sdbm)X
+1 f
+2922(implementation)X
+3446(is)X
+3521(also)X
+3672(faster)X
+3873(than)X
+2 f
+555 3836(ndbm)N
+1 f
+757(in)X
+843(database)X
+1144(creation.)X
+1467(Unlike)X
+1709(the)X
+2 f
+1831(ndbm)X
+1 f
+2009(,)X
+2053(the)X
+2 f
+2175(sdbm)X
+7 f
+2396(store)X
+1 f
+2660(operation)X
+2987(will)X
+3134(not)X
+3259(``wander)X
+3573(away'')X
+3820(trying)X
+555 3932(to)N
+642(split)X
+804(its)X
+904(data)X
+1063(pages)X
+1271(to)X
+1358(insert)X
+1561(a)X
+1622(datum)X
+1847(that)X
+2 f
+1992(cannot)X
+1 f
+2235(\(due)X
+2403(to)X
+2490(elaborate)X
+2810(worst-case)X
+3179(situations\))X
+3537(be)X
+3637(inserted.)X
+3935(\(It)X
+555 4028(will)N
+699(fail)X
+826(after)X
+994(a)X
+1050(pre-de\256ned)X
+1436(number)X
+1701(of)X
+1788(attempts.\))X
+3 f
+555 4220(Important)N
+931(Compatibility)X
+1426(Warning)X
+1 f
+755 4344(The)N
+2 f
+904(sdbm)X
+1 f
+1097(and)X
+2 f
+1237(ndbm)X
+1 f
+1439(libraries)X
+2 f
+1726(cannot)X
+1 f
+1968(share)X
+2162(databases:)X
+2515(one)X
+2654(cannot)X
+2891(read)X
+3053(the)X
+3174(\(dir/pag\))X
+3478(database)X
+3778(created)X
+555 4440(by)N
+657(the)X
+777(other.)X
+984(This)X
+1148(is)X
+1222(due)X
+1359(to)X
+1442(the)X
+1561(differences)X
+1940(between)X
+2229(the)X
+2 f
+2348(ndbm)X
+1 f
+2547(and)X
+2 f
+2684(sdbm)X
+1 f
+2874(algorithms)X
+8 s
+3216 4415(2)N
+10 s
+4440(,)Y
+3289(and)X
+3426(the)X
+3545(hash)X
+3713(functions)X
+555 4536(used.)N
+769(It)X
+845(is)X
+925(easy)X
+1094(to)X
+1182(convert)X
+1449(between)X
+1743(the)X
+2 f
+1867(dbm/ndbm)X
+1 f
+2231(databases)X
+2565(and)X
+2 f
+2707(sdbm)X
+1 f
+2902(by)X
+3008(ignoring)X
+3305(the)X
+3429(index)X
+3633(completely:)X
+555 4632(see)N
+7 f
+706(dbd)X
+1 f
+(,)S
+7 f
+918(dbu)X
+1 f
+1082(etc.)X
+3 f
+555 4852(Notice)N
+794(of)X
+881(Intellectual)X
+1288(Property)X
+2 f
+555 4976(The)N
+696(entire)X
+1 f
+904(sdbm)X
+2 f
+1118(library)X
+1361(package,)X
+1670(as)X
+1762(authored)X
+2072(by)X
+2169(me,)X
+1 f
+2304(Ozan)X
+2495(S.)X
+2580(Yigit,)X
+2 f
+2785(is)X
+2858(hereby)X
+3097(placed)X
+3331(in)X
+3413(the)X
+3531(public)X
+3751(domain.)X
+1 f
+555 5072(As)N
+670(such,)X
+863(the)X
+987(author)X
+1218(is)X
+1297(not)X
+1425(responsible)X
+1816(for)X
+1936(the)X
+2060(consequences)X
+2528(of)X
+2621(use)X
+2754(of)X
+2847(this)X
+2988(software,)X
+3310(no)X
+3415(matter)X
+3645(how)X
+3808(awful,)X
+555 5168(even)N
+727(if)X
+796(they)X
+954(arise)X
+1126(from)X
+1302(defects)X
+1550(in)X
+1632(it.)X
+1716(There)X
+1924(is)X
+1997(no)X
+2097(expressed)X
+2434(or)X
+2521(implied)X
+2785(warranty)X
+3091(for)X
+3205(the)X
+2 f
+3323(sdbm)X
+1 f
+3512(library.)X
+8 s
+10 f
+555 5316(hhhhhhhhhhhhhhhhhh)N
+6 s
+1 f
+635 5391(1)N
+8 s
+691 5410(UN*X)N
+877(is)X
+936(not)X
+1034(a)X
+1078(trademark)X
+1352(of)X
+1421(any)X
+1529(\(dis\)organization.)X
+6 s
+635 5485(2)N
+8 s
+691 5504(Torek's)N
+908(discussion)X
+1194([Tor87])X
+1411(indicates)X
+1657(that)X
+2 f
+1772(dbm/ndbm)X
+1 f
+2061(implementations)X
+2506(use)X
+2609(the)X
+2705(hash)X
+2840(value)X
+2996(to)X
+3064(traverse)X
+3283(the)X
+3379(radix)X
+3528(trie)X
+3631(dif-)X
+555 5584(ferently)N
+772(than)X
+2 f
+901(sdbm)X
+1 f
+1055(and)X
+1166(as)X
+1238(a)X
+1285(result,)X
+1462(the)X
+1559(page)X
+1698(indexes)X
+1912(are)X
+2008(generated)X
+2274(in)X
+2 f
+2343(different)X
+1 f
+2579(order.)X
+2764(For)X
+2872(more)X
+3021(information,)X
+3357(send)X
+3492(e-mail)X
+3673(to)X
+555 5664(the)N
+649(author.)X
+
+2 p
+%%Page: 2 2
+8 s 0 xH 0 xS 1 f
+10 s
+2216 384(-)N
+2263(2)X
+2323(-)X
+755 672(Since)N
+971(the)X
+2 f
+1107(sdbm)X
+1 f
+1314(library)X
+1566(package)X
+1868(is)X
+1959(in)X
+2058(the)X
+2193(public)X
+2430(domain,)X
+2727(this)X
+2 f
+2879(original)X
+1 f
+3173(release)X
+3434(or)X
+3538(any)X
+3691(additional)X
+555 768(public-domain)N
+1045(releases)X
+1323(of)X
+1413(the)X
+1534(modi\256ed)X
+1841(original)X
+2112(cannot)X
+2348(possibly)X
+2636(\(by)X
+2765(de\256nition\))X
+3120(be)X
+3218(withheld)X
+3520(from)X
+3698(you.)X
+3860(Also)X
+555 864(by)N
+659(de\256nition,)X
+1009(You)X
+1170(\(singular\))X
+1505(have)X
+1680(all)X
+1783(the)X
+1904(rights)X
+2109(to)X
+2194(this)X
+2332(code)X
+2507(\(including)X
+2859(the)X
+2980(right)X
+3154(to)X
+3239(sell)X
+3373(without)X
+3640(permission,)X
+555 960(the)N
+679(right)X
+856(to)X
+944(hoard)X
+8 s
+1127 935(3)N
+10 s
+1185 960(and)N
+1327(the)X
+1451(right)X
+1628(to)X
+1716(do)X
+1821(other)X
+2011(icky)X
+2174(things)X
+2394(as)X
+2486(you)X
+2631(see)X
+2759(\256t\))X
+2877(but)X
+3004(those)X
+3198(rights)X
+3405(are)X
+3529(also)X
+3683(granted)X
+3949(to)X
+555 1056(everyone)N
+870(else.)X
+755 1180(Please)N
+997(note)X
+1172(that)X
+1329(all)X
+1446(previous)X
+1759(distributions)X
+2195(of)X
+2298(this)X
+2449(software)X
+2762(contained)X
+3110(a)X
+3182(copyright)X
+3525(\(which)X
+3784(is)X
+3873(now)X
+555 1276(dropped\))N
+868(to)X
+953(protect)X
+1199(its)X
+1297(origins)X
+1542(and)X
+1681(its)X
+1779(current)X
+2030(public)X
+2253(domain)X
+2516(status)X
+2721(against)X
+2970(any)X
+3108(possible)X
+3392(claims)X
+3623(and/or)X
+3850(chal-)X
+555 1372(lenges.)N
+3 f
+555 1564(Acknowledgments)N
+1 f
+755 1688(Many)N
+966(people)X
+1204(have)X
+1380(been)X
+1556(very)X
+1723(helpful)X
+1974(and)X
+2114(supportive.)X
+2515(A)X
+2596(partial)X
+2824(list)X
+2944(would)X
+3167(necessarily)X
+3547(include)X
+3806(Rayan)X
+555 1784(Zacherissen)N
+963(\(who)X
+1152(contributed)X
+1541(the)X
+1663(man)X
+1824(page,)X
+2019(and)X
+2158(also)X
+2310(hacked)X
+2561(a)X
+2620(MMAP)X
+2887(version)X
+3146(of)X
+2 f
+3236(sdbm)X
+1 f
+3405(\),)X
+3475(Arnold)X
+3725(Robbins,)X
+555 1880(Chris)N
+763(Lewis,)X
+1013(Bill)X
+1166(Davidsen,)X
+1523(Henry)X
+1758(Spencer,)X
+2071(Geoff)X
+2293(Collyer,)X
+2587(Rich)X
+2772(Salz)X
+2944(\(who)X
+3143(got)X
+3279(me)X
+3411(started)X
+3659(in)X
+3755(the)X
+3887(\256rst)X
+555 1976(place\),)N
+792(Johannes)X
+1106(Ruschein)X
+1424(\(who)X
+1609(did)X
+1731(the)X
+1849(minix)X
+2055(port\))X
+2231(and)X
+2367(David)X
+2583(Tilbrook.)X
+2903(I)X
+2950(thank)X
+3148(you)X
+3288(all.)X
+3 f
+555 2168(Distribution)N
+992(Manifest)X
+1315(and)X
+1463(Notes)X
+1 f
+555 2292(This)N
+717(distribution)X
+1105(of)X
+2 f
+1192(sdbm)X
+1 f
+1381(includes)X
+1668(\(at)X
+1773(least\))X
+1967(the)X
+2085(following:)X
+7 f
+747 2436(CHANGES)N
+1323(change)X
+1659(log)X
+747 2532(README)N
+1323(this)X
+1563(file.)X
+747 2628(biblio)N
+1323(a)X
+1419(small)X
+1707(bibliography)X
+2331(on)X
+2475(external)X
+2907(hashing)X
+747 2724(dba.c)N
+1323(a)X
+1419(crude)X
+1707(\(n/s\)dbm)X
+2139(page)X
+2379(file)X
+2619(analyzer)X
+747 2820(dbd.c)N
+1323(a)X
+1419(crude)X
+1707(\(n/s\)dbm)X
+2139(page)X
+2379(file)X
+2619(dumper)X
+2955(\(for)X
+3195(conversion\))X
+747 2916(dbe.1)N
+1323(man)X
+1515(page)X
+1755(for)X
+1947(dbe.c)X
+747 3012(dbe.c)N
+1323(Janick's)X
+1755(database)X
+2187(editor)X
+747 3108(dbm.c)N
+1323(a)X
+1419(dbm)X
+1611(library)X
+1995(emulation)X
+2475(wrapper)X
+2859(for)X
+3051(ndbm/sdbm)X
+747 3204(dbm.h)N
+1323(header)X
+1659(file)X
+1899(for)X
+2091(the)X
+2283(above)X
+747 3300(dbu.c)N
+1323(a)X
+1419(crude)X
+1707(db)X
+1851(management)X
+2379(utility)X
+747 3396(hash.c)N
+1323(hashing)X
+1707(function)X
+747 3492(makefile)N
+1323(guess.)X
+747 3588(pair.c)N
+1323(page-level)X
+1851(routines)X
+2283(\(posted)X
+2667(earlier\))X
+747 3684(pair.h)N
+1323(header)X
+1659(file)X
+1899(for)X
+2091(the)X
+2283(above)X
+747 3780(readme.ms)N
+1323(troff)X
+1611(source)X
+1947(for)X
+2139(the)X
+2331(README)X
+2667(file)X
+747 3876(sdbm.3)N
+1323(man)X
+1515(page)X
+747 3972(sdbm.c)N
+1323(the)X
+1515(real)X
+1755(thing)X
+747 4068(sdbm.h)N
+1323(header)X
+1659(file)X
+1899(for)X
+2091(the)X
+2283(above)X
+747 4164(tune.h)N
+1323(place)X
+1611(for)X
+1803(tuning)X
+2139(&)X
+2235(portability)X
+2811(thingies)X
+747 4260(util.c)N
+1323(miscellaneous)X
+755 4432(dbu)N
+1 f
+924(is)X
+1002(a)X
+1063(simple)X
+1301(database)X
+1603(manipulation)X
+2050(program)X
+8 s
+2322 4407(4)N
+10 s
+2379 4432(that)N
+2524(tries)X
+2687(to)X
+2774(look)X
+2941(like)X
+3086(Bell)X
+3244(Labs')X
+7 f
+3480(cbt)X
+1 f
+3649(utility.)X
+3884(It)X
+3958(is)X
+555 4528(currently)N
+867(incomplete)X
+1245(in)X
+1329(functionality.)X
+1800(I)X
+1849(use)X
+7 f
+2006(dbu)X
+1 f
+2172(to)X
+2255(test)X
+2387(out)X
+2510(the)X
+2629(routines:)X
+2930(it)X
+2995(takes)X
+3181(\(from)X
+3385(stdin\))X
+3588(tab)X
+3707(separated)X
+555 4624(key/value)N
+898(pairs)X
+1085(for)X
+1210(commands)X
+1587(like)X
+7 f
+1765(build)X
+1 f
+2035(or)X
+7 f
+2160(insert)X
+1 f
+2478(or)X
+2575(takes)X
+2770(keys)X
+2947(for)X
+3071(commands)X
+3448(like)X
+7 f
+3626(delete)X
+1 f
+3944(or)X
+7 f
+555 4720(look)N
+1 f
+(.)S
+7 f
+747 4864(dbu)N
+939(<build|creat|look|insert|cat|delete>)X
+2715(dbmfile)X
+755 5036(dba)N
+1 f
+927(is)X
+1008(a)X
+1072(crude)X
+1279(analyzer)X
+1580(of)X
+2 f
+1675(dbm/sdbm/ndbm)X
+1 f
+2232(page)X
+2412(\256les.)X
+2593(It)X
+2670(scans)X
+2872(the)X
+2998(entire)X
+3209(page)X
+3389(\256le,)X
+3538(reporting)X
+3859(page)X
+555 5132(level)N
+731(statistics,)X
+1046(and)X
+1182(totals)X
+1375(at)X
+1453(the)X
+1571(end.)X
+7 f
+755 5256(dbd)N
+1 f
+925(is)X
+1004(a)X
+1066(crude)X
+1271(dump)X
+1479(program)X
+1777(for)X
+2 f
+1897(dbm/ndbm/sdbm)X
+1 f
+2452(databases.)X
+2806(It)X
+2881(ignores)X
+3143(the)X
+3267(bitmap,)X
+3534(and)X
+3675(dumps)X
+3913(the)X
+555 5352(data)N
+717(pages)X
+928(in)X
+1018(sequence.)X
+1361(It)X
+1437(can)X
+1576(be)X
+1679(used)X
+1853(to)X
+1942(create)X
+2162(input)X
+2353(for)X
+2474(the)X
+7 f
+2627(dbu)X
+1 f
+2798(utility.)X
+3055(Note)X
+3238(that)X
+7 f
+3413(dbd)X
+1 f
+3584(will)X
+3735(skip)X
+3895(any)X
+8 s
+10 f
+555 5432(hhhhhhhhhhhhhhhhhh)N
+6 s
+1 f
+635 5507(3)N
+8 s
+691 5526(You)N
+817(cannot)X
+1003(really)X
+1164(hoard)X
+1325(something)X
+1608(that)X
+1720(is)X
+1779(available)X
+2025(to)X
+2091(the)X
+2185(public)X
+2361(at)X
+2423(large,)X
+2582(but)X
+2680(try)X
+2767(if)X
+2822(it)X
+2874(makes)X
+3053(you)X
+3165(feel)X
+3276(any)X
+3384(better.)X
+6 s
+635 5601(4)N
+8 s
+691 5620(The)N
+7 f
+829(dbd)X
+1 f
+943(,)X
+7 f
+998(dba)X
+1 f
+1112(,)X
+7 f
+1167(dbu)X
+1 f
+1298(utilities)X
+1508(are)X
+1602(quick)X
+1761(hacks)X
+1923(and)X
+2032(are)X
+2126(not)X
+2225(\256t)X
+2295(for)X
+2385(production)X
+2678(use.)X
+2795(They)X
+2942(were)X
+3081(developed)X
+3359(late)X
+3467(one)X
+3575(night,)X
+555 5700(just)N
+664(to)X
+730(test)X
+835(out)X
+2 f
+933(sdbm)X
+1 f
+1068(,)X
+1100(and)X
+1208(convert)X
+1415(some)X
+1566(databases.)X
+
+3 p
+%%Page: 3 3
+8 s 0 xH 0 xS 1 f
+10 s
+2216 384(-)N
+2263(3)X
+2323(-)X
+555 672(NULLs)N
+821(in)X
+903(the)X
+1021(key)X
+1157(and)X
+1293(data)X
+1447(\256elds,)X
+1660(thus)X
+1813(is)X
+1886(unsuitable)X
+2235(to)X
+2317(convert)X
+2578(some)X
+2767(peculiar)X
+3046(databases)X
+3374(that)X
+3514(insist)X
+3702(in)X
+3784(includ-)X
+555 768(ing)N
+677(the)X
+795(terminating)X
+1184(null.)X
+755 892(I)N
+841(have)X
+1052(also)X
+1240(included)X
+1575(a)X
+1670(copy)X
+1885(of)X
+2011(the)X
+7 f
+2195(dbe)X
+1 f
+2397(\()X
+2 f
+2424(ndbm)X
+1 f
+2660(DataBase)X
+3026(Editor\))X
+3311(by)X
+3449(Janick)X
+3712(Bergeron)X
+555 988([janick@bnr.ca])N
+1098(for)X
+1212(your)X
+1379(pleasure.)X
+1687(You)X
+1845(may)X
+2003(\256nd)X
+2147(it)X
+2211(more)X
+2396(useful)X
+2612(than)X
+2770(the)X
+2888(little)X
+7 f
+3082(dbu)X
+1 f
+3246(utility.)X
+7 f
+755 1112(dbm.[ch])N
+1 f
+1169(is)X
+1252(a)X
+2 f
+1318(dbm)X
+1 f
+1486(library)X
+1730(emulation)X
+2079(on)X
+2188(top)X
+2319(of)X
+2 f
+2415(ndbm)X
+1 f
+2622(\(and)X
+2794(hence)X
+3011(suitable)X
+3289(for)X
+2 f
+3412(sdbm)X
+1 f
+3581(\).)X
+3657(Written)X
+3931(by)X
+555 1208(Robert)N
+793(Elz.)X
+755 1332(The)N
+2 f
+901(sdbm)X
+1 f
+1090(library)X
+1324(has)X
+1451(been)X
+1623(around)X
+1866(in)X
+1948(beta)X
+2102(test)X
+2233(for)X
+2347(quite)X
+2527(a)X
+2583(long)X
+2745(time,)X
+2927(and)X
+3063(from)X
+3239(whatever)X
+3554(little)X
+3720(feedback)X
+555 1428(I)N
+609(received)X
+909(\(maybe)X
+1177(no)X
+1284(news)X
+1476(is)X
+1555(good)X
+1741(news\),)X
+1979(I)X
+2032(believe)X
+2290(it)X
+2360(has)X
+2493(been)X
+2671(functioning)X
+3066(without)X
+3336(any)X
+3478(signi\256cant)X
+3837(prob-)X
+555 1524(lems.)N
+752(I)X
+805(would,)X
+1051(of)X
+1144(course,)X
+1400(appreciate)X
+1757(all)X
+1863(\256xes)X
+2040(and/or)X
+2271(improvements.)X
+2774(Portability)X
+3136(enhancements)X
+3616(would)X
+3841(espe-)X
+555 1620(cially)N
+753(be)X
+849(useful.)X
+3 f
+555 1812(Implementation)N
+1122(Issues)X
+1 f
+755 1936(Hash)N
+944(functions:)X
+1288(The)X
+1437(algorithm)X
+1772(behind)X
+2 f
+2014(sdbm)X
+1 f
+2207(implementation)X
+2733(needs)X
+2939(a)X
+2998(good)X
+3181(bit-scrambling)X
+3671(hash)X
+3841(func-)X
+555 2032(tion)N
+702(to)X
+787(be)X
+886(effective.)X
+1211(I)X
+1261(ran)X
+1387(into)X
+1534(a)X
+1593(set)X
+1705(of)X
+1795(constants)X
+2116(for)X
+2233(a)X
+2292(simple)X
+2528(hash)X
+2698(function)X
+2988(that)X
+3130(seem)X
+3317(to)X
+3401(help)X
+2 f
+3561(sdbm)X
+1 f
+3752(perform)X
+555 2128(better)N
+758(than)X
+2 f
+916(ndbm)X
+1 f
+1114(for)X
+1228(various)X
+1484(inputs:)X
+7 f
+747 2272(/*)N
+795 2368(*)N
+891(polynomial)X
+1419(conversion)X
+1947(ignoring)X
+2379(overflows)X
+795 2464(*)N
+891(65599)X
+1179(nice.)X
+1467(65587)X
+1755(even)X
+1995(better.)X
+795 2560(*/)N
+747 2656(long)N
+747 2752(dbm_hash\(char)N
+1419(*str,)X
+1707(int)X
+1899(len\))X
+2139({)X
+939 2848(register)N
+1371(unsigned)X
+1803(long)X
+2043(n)X
+2139(=)X
+2235(0;)X
+939 3040(while)N
+1227(\(len--\))X
+1131 3136(n)N
+1227(=)X
+1323(n)X
+1419(*)X
+1515(65599)X
+1803(+)X
+1899(*str++;)X
+939 3232(return)N
+1275(n;)X
+747 3328(})N
+1 f
+755 3500(There)N
+975(may)X
+1145(be)X
+1253(better)X
+1467(hash)X
+1645(functions)X
+1974(for)X
+2099(the)X
+2228(purposes)X
+2544(of)X
+2642(dynamic)X
+2949(hashing.)X
+3269(Try)X
+3416(your)X
+3594(favorite,)X
+3895(and)X
+555 3596(check)N
+766(the)X
+887(page\256le.)X
+1184(If)X
+1261(it)X
+1328(contains)X
+1618(too)X
+1743(many)X
+1944(pages)X
+2150(with)X
+2315(too)X
+2440(many)X
+2641(holes,)X
+2853(\(in)X
+2965(relation)X
+3233(to)X
+3318(this)X
+3456(one)X
+3595(for)X
+3712(example\))X
+555 3692(or)N
+656(if)X
+2 f
+739(sdbm)X
+1 f
+942(simply)X
+1193(stops)X
+1391(working)X
+1692(\(fails)X
+1891(after)X
+7 f
+2101(SPLTMAX)X
+1 f
+2471(attempts)X
+2776(to)X
+2872(split\))X
+3070(when)X
+3278(you)X
+3432(feed)X
+3604(your)X
+3784(NEWS)X
+7 f
+555 3788(history)N
+1 f
+912(\256le)X
+1035(to)X
+1118(it,)X
+1203(you)X
+1344(probably)X
+1650(do)X
+1751(not)X
+1874(have)X
+2047(a)X
+2104(good)X
+2285(hashing)X
+2555(function.)X
+2883(If)X
+2958(you)X
+3099(do)X
+3200(better)X
+3404(\(for)X
+3545(different)X
+3842(types)X
+555 3884(of)N
+642(input\),)X
+873(I)X
+920(would)X
+1140(like)X
+1280(to)X
+1362(know)X
+1560(about)X
+1758(the)X
+1876(function)X
+2163(you)X
+2303(use.)X
+755 4008(Block)N
+967(sizes:)X
+1166(It)X
+1236(seems)X
+1453(\(from)X
+1657(various)X
+1914(tests)X
+2077(on)X
+2178(a)X
+2235(few)X
+2377(machines\))X
+2727(that)X
+2867(a)X
+2923(page)X
+3095(\256le)X
+3217(block)X
+3415(size)X
+7 f
+3588(PBLKSIZ)X
+1 f
+3944(of)X
+555 4104(1024)N
+738(is)X
+814(by)X
+917(far)X
+1030(the)X
+1150(best)X
+1301(for)X
+1417(performance,)X
+1866(but)X
+1990(this)X
+2127(also)X
+2278(happens)X
+2563(to)X
+2647(limit)X
+2819(the)X
+2939(size)X
+3086(of)X
+3175(a)X
+3233(key/value)X
+3567(pair.)X
+3734(Depend-)X
+555 4200(ing)N
+681(on)X
+785(your)X
+956(needs,)X
+1183(you)X
+1327(may)X
+1489(wish)X
+1663(to)X
+1748(increase)X
+2035(the)X
+2156(page)X
+2331(size,)X
+2499(and)X
+2638(also)X
+2790(adjust)X
+7 f
+3032(PAIRMAX)X
+1 f
+3391(\(the)X
+3539(maximum)X
+3886(size)X
+555 4296(of)N
+648(a)X
+710(key/value)X
+1048(pair)X
+1199(allowed:)X
+1501(should)X
+1740(always)X
+1989(be)X
+2090(at)X
+2173(least)X
+2345(three)X
+2531(words)X
+2752(smaller)X
+3013(than)X
+7 f
+3204(PBLKSIZ)X
+1 f
+(.\))S
+3612(accordingly.)X
+555 4392(The)N
+706(system-wide)X
+1137(version)X
+1399(of)X
+1492(the)X
+1616(library)X
+1856(should)X
+2095(probably)X
+2406(be)X
+2508(con\256gured)X
+2877(with)X
+3044(1024)X
+3229(\(distribution)X
+3649(default\),)X
+3944(as)X
+555 4488(this)N
+690(appears)X
+956(to)X
+1038(be)X
+1134(suf\256cient)X
+1452(for)X
+1566(most)X
+1741(common)X
+2041(uses)X
+2199(of)X
+2 f
+2286(sdbm)X
+1 f
+2455(.)X
+3 f
+555 4680(Portability)N
+1 f
+755 4804(This)N
+917(package)X
+1201(has)X
+1328(been)X
+1500(tested)X
+1707(in)X
+1789(many)X
+1987(different)X
+2284(UN*Xes)X
+2585(even)X
+2757(including)X
+3079(minix,)X
+3305(and)X
+3441(appears)X
+3707(to)X
+3789(be)X
+3885(rea-)X
+555 4900(sonably)N
+824(portable.)X
+1127(This)X
+1289(does)X
+1456(not)X
+1578(mean)X
+1772(it)X
+1836(will)X
+1980(port)X
+2129(easily)X
+2336(to)X
+2418(non-UN*X)X
+2799(systems.)X
+3 f
+555 5092(Notes)N
+767(and)X
+915(Miscellaneous)X
+1 f
+755 5216(The)N
+2 f
+913(sdbm)X
+1 f
+1115(is)X
+1201(not)X
+1336(a)X
+1405(very)X
+1581(complicated)X
+2006(package,)X
+2323(at)X
+2414(least)X
+2594(not)X
+2729(after)X
+2910(you)X
+3063(familiarize)X
+3444(yourself)X
+3739(with)X
+3913(the)X
+555 5312(literature)N
+879(on)X
+993(external)X
+1286(hashing.)X
+1589(There)X
+1811(are)X
+1944(other)X
+2143(interesting)X
+2514(algorithms)X
+2889(in)X
+2984(existence)X
+3316(that)X
+3469(ensure)X
+3712(\(approxi-)X
+555 5408(mately\))N
+825(single-read)X
+1207(access)X
+1438(to)X
+1525(a)X
+1586(data)X
+1745(value)X
+1944(associated)X
+2299(with)X
+2466(any)X
+2607(key.)X
+2768(These)X
+2984(are)X
+3107(directory-less)X
+3568(schemes)X
+3864(such)X
+555 5504(as)N
+2 f
+644(linear)X
+857(hashing)X
+1 f
+1132([Lit80])X
+1381(\(+)X
+1475(Larson)X
+1720(variations\),)X
+2 f
+2105(spiral)X
+2313(storage)X
+1 f
+2575([Mar79])X
+2865(or)X
+2954(directory)X
+3265(schemes)X
+3558(such)X
+3726(as)X
+2 f
+3814(exten-)X
+555 5600(sible)N
+731(hashing)X
+1 f
+1009([Fag79])X
+1288(by)X
+1393(Fagin)X
+1600(et)X
+1683(al.)X
+1786(I)X
+1838(do)X
+1943(hope)X
+2124(these)X
+2314(sources)X
+2579(provide)X
+2848(a)X
+2908(reasonable)X
+3276(playground)X
+3665(for)X
+3783(experi-)X
+555 5696(mentation)N
+907(with)X
+1081(other)X
+1277(algorithms.)X
+1690(See)X
+1837(the)X
+1966(June)X
+2144(1988)X
+2335(issue)X
+2526(of)X
+2624(ACM)X
+2837(Computing)X
+3227(Surveys)X
+3516([Enb88])X
+3810(for)X
+3935(an)X
+555 5792(excellent)N
+865(overview)X
+1184(of)X
+1271(the)X
+1389(\256eld.)X
+
+4 p
+%%Page: 4 4
+10 s 0 xH 0 xS 1 f
+2216 384(-)N
+2263(4)X
+2323(-)X
+3 f
+555 672(References)N
+1 f
+555 824([Lar78])N
+875(P.-A.)X
+1064(Larson,)X
+1327(``Dynamic)X
+1695(Hashing'',)X
+2 f
+2056(BIT)X
+1 f
+(,)S
+2216(vol.)X
+2378(18,)X
+2518(pp.)X
+2638(184-201,)X
+2945(1978.)X
+555 948([Tho90])N
+875(Ken)X
+1029(Thompson,)X
+2 f
+1411(private)X
+1658(communication)X
+1 f
+2152(,)X
+2192(Nov.)X
+2370(1990)X
+555 1072([Lit80])N
+875(W.)X
+992(Litwin,)X
+1246(``)X
+1321(Linear)X
+1552(Hashing:)X
+1862(A)X
+1941(new)X
+2096(tool)X
+2261(for)X
+2396(\256le)X
+2539(and)X
+2675(table)X
+2851(addressing'',)X
+2 f
+3288(Proceedings)X
+3709(of)X
+3791(the)X
+3909(6th)X
+875 1168(Conference)N
+1269(on)X
+1373(Very)X
+1548(Large)X
+1782(Dabatases)X
+2163(\(Montreal\))X
+1 f
+2515(,)X
+2558(pp.)X
+2701(212-223,)X
+3031(Very)X
+3215(Large)X
+3426(Database)X
+3744(Founda-)X
+875 1264(tion,)N
+1039(Saratoga,)X
+1360(Calif.,)X
+1580(1980.)X
+555 1388([Fag79])N
+875(R.)X
+969(Fagin,)X
+1192(J.)X
+1284(Nievergelt,)X
+1684(N.)X
+1803(Pippinger,)X
+2175(and)X
+2332(H.)X
+2451(R.)X
+2544(Strong,)X
+2797(``Extendible)X
+3218(Hashing)X
+3505(-)X
+3552(A)X
+3630(Fast)X
+3783(Access)X
+875 1484(Method)N
+1144(for)X
+1258(Dynamic)X
+1572(Files'',)X
+2 f
+1821(ACM)X
+2010(Trans.)X
+2236(Database)X
+2563(Syst.)X
+1 f
+2712(,)X
+2752(vol.)X
+2894(4,)X
+2994(no.3,)X
+3174(pp.)X
+3294(315-344,)X
+3601(Sept.)X
+3783(1979.)X
+555 1608([Wal84])N
+875(Rich)X
+1055(Wales,)X
+1305(``Discussion)X
+1739(of)X
+1835("dbm")X
+2072(data)X
+2235(base)X
+2406(system'',)X
+2 f
+2730(USENET)X
+3051(newsgroup)X
+3430(unix.wizards)X
+1 f
+3836(,)X
+3884(Jan.)X
+875 1704(1984.)N
+555 1828([Tor87])N
+875(Chris)X
+1068(Torek,)X
+1300(``Re:)X
+1505(dbm.a)X
+1743(and)X
+1899(ndbm.a)X
+2177(archives'',)X
+2 f
+2539(USENET)X
+2852(newsgroup)X
+3223(comp.unix)X
+1 f
+3555(,)X
+3595(1987.)X
+555 1952([Mar79])N
+875(G.)X
+974(N.)X
+1073(Martin,)X
+1332(``Spiral)X
+1598(Storage:)X
+1885(Incrementally)X
+2371(Augmentable)X
+2843(Hash)X
+3048(Addressed)X
+3427(Storage'',)X
+2 f
+3766(Techni-)X
+875 2048(cal)N
+993(Report)X
+1231(#27)X
+1 f
+(,)S
+1391(University)X
+1749(of)X
+1836(Varwick,)X
+2153(Coventry,)X
+2491(U.K.,)X
+2687(1979.)X
+555 2172([Enb88])N
+875(R.)X
+977(J.)X
+1057(Enbody)X
+1335(and)X
+1480(H.)X
+1586(C.)X
+1687(Du,)X
+1833(``Dynamic)X
+2209(Hashing)X
+2524(Schemes'',)X
+2 f
+2883(ACM)X
+3080(Computing)X
+3463(Surveys)X
+1 f
+3713(,)X
+3761(vol.)X
+3911(20,)X
+875 2268(no.)N
+995(2,)X
+1075(pp.)X
+1195(85-113,)X
+1462(June)X
+1629(1988.)X
+
+4 p
+%%Trailer
+xt
+
+xs
diff --git a/ext/SDBM_File/sdbm/sdbm.3 b/ext/SDBM_File/sdbm/sdbm.3
new file mode 100644
index 0000000000..f0f2d07c84
--- /dev/null
+++ b/ext/SDBM_File/sdbm/sdbm.3
@@ -0,0 +1,290 @@
+.\" $Id: sdbm.3,v 1.2 90/12/13 13:00:57 oz Exp $
+.TH SDBM 3 "1 March 1990"
+.SH NAME
+sdbm, dbm_open, dbm_prep, dbm_close, dbm_fetch, dbm_store, dbm_delete, dbm_firstkey, dbm_nextkey, dbm_hash, dbm_rdonly, dbm_error, dbm_clearerr, dbm_dirfno, dbm_pagfno \- data base subroutines
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sdbm.h>
+.sp
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+.sp
+datum nullitem = { NULL, 0 };
+.sp
+\s-1DBM\s0 *dbm_open(char *file, int flags, int mode)
+.sp
+\s-1DBM\s0 *dbm_prep(char *dirname, char *pagname, int flags, int mode)
+.sp
+void dbm_close(\s-1DBM\s0 *db)
+.sp
+datum dbm_fetch(\s-1DBM\s0 *db, key)
+.sp
+int dbm_store(\s-1DBM\s0 *db, datum key, datum val, int flags)
+.sp
+int dbm_delete(\s-1DBM\s0 *db, datum key)
+.sp
+datum dbm_firstkey(\s-1DBM\s0 *db)
+.sp
+datum dbm_nextkey(\s-1DBM\s0 *db)
+.sp
+long dbm_hash(char *string, int len)
+.sp
+int dbm_rdonly(\s-1DBM\s0 *db)
+int dbm_error(\s-1DBM\s0 *db)
+dbm_clearerr(\s-1DBM\s0 *db)
+int dbm_dirfno(\s-1DBM\s0 *db)
+int dbm_pagfno(\s-1DBM\s0 *db)
+.ft R
+.fi
+.SH DESCRIPTION
+.IX "database library" sdbm "" "\fLsdbm\fR"
+.IX dbm_open "" "\fLdbm_open\fR \(em open \fLsdbm\fR database"
+.IX dbm_prep "" "\fLdbm_prep\fR \(em prepare \fLsdbm\fR database"
+.IX dbm_close "" "\fLdbm_close\fR \(em close \fLsdbm\fR routine"
+.IX dbm_fetch "" "\fLdbm_fetch\fR \(em fetch \fLsdbm\fR database data"
+.IX dbm_store "" "\fLdbm_store\fR \(em add data to \fLsdbm\fR database"
+.IX dbm_delete "" "\fLdbm_delete\fR \(em remove data from \fLsdbm\fR database"
+.IX dbm_firstkey "" "\fLdbm_firstkey\fR \(em access \fLsdbm\fR database"
+.IX dbm_nextkey "" "\fLdbm_nextkey\fR \(em access \fLsdbm\fR database"
+.IX dbm_hash "" "\fLdbm_hash\fR \(em string hash for \fLsdbm\fR database"
+.IX dbm_rdonly "" "\fLdbm_rdonly\fR \(em return \fLsdbm\fR database read-only mode"
+.IX dbm_error "" "\fLdbm_error\fR \(em return \fLsdbm\fR database error condition"
+.IX dbm_clearerr "" "\fLdbm_clearerr\fR \(em clear \fLsdbm\fR database error condition"
+.IX dbm_dirfno "" "\fLdbm_dirfno\fR \(em return \fLsdbm\fR database bitmap file descriptor"
+.IX dbm_pagfno "" "\fLdbm_pagfno\fR \(em return \fLsdbm\fR database data file descriptor"
+.IX "database functions \(em \fLsdbm\fR" dbm_open "" \fLdbm_open\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_prep "" \fLdbm_prep\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_close "" \fLdbm_close\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_fetch "" \fLdbm_fetch\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_store "" \fLdbm_store\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_delete "" \fLdbm_delete\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_firstkey "" \fLdbm_firstkey\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_nextkey "" \fLdbm_nextkey\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_rdonly "" \fLdbm_rdonly\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_error "" \fLdbm_error\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_clearerr "" \fLdbm_clearerr\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_dirfno "" \fLdbm_dirfno\fP
+.IX "database functions \(em \fLsdbm\fR" dbm_pagfno "" \fLdbm_pagfno\fP
+.LP
+This package allows an application to maintain a mapping of <key,value> pairs
+in disk files. This is not to be considered a real database system, but is
+still useful in many simple applications built around fast retrieval of a data
+value from a key. This implementation uses an external hashing scheme,
+called Dynamic Hashing, as described by Per-Aake Larson in BIT 18 (1978) pp.
+184-201. Retrieval of any item usually requires a single disk access.
+The application interface is compatible with the
+.IR ndbm (3)
+library.
+.LP
+An
+.B sdbm
+database is kept in two files usually given the extensions
+.B \.dir
+and
+.BR \.pag .
+The
+.B \.dir
+file contains a bitmap representing a forest of binary hash trees, the leaves
+of which indicate data pages in the
+.B \.pag
+file.
+.LP
+The application interface uses the
+.B datum
+structure to describe both
+.I keys
+and
+.IR value s.
+A
+.B datum
+specifies a byte sequence of
+.I dsize
+size pointed to by
+.IR dptr .
+If you use
+.SM ASCII
+strings as
+.IR key s
+or
+.IR value s,
+then you must decide whether or not to include the terminating
+.SM NUL
+byte which sometimes defines strings. Including it will require larger
+database files, but it will be possible to get sensible output from a
+.IR strings (1)
+command applied to the data file.
+.LP
+In order to allow a process using this package to manipulate multiple
+databases, the applications interface always requires a
+.IR handle ,
+a
+.BR "DBM *" ,
+to identify the database to be manipulated. Such a handle can be obtained
+from the only routines that do not require it, namely
+.BR dbm_open (\|)
+or
+.BR dbm_prep (\|).
+Either of these will open or create the two necessary files. The
+difference is that the latter allows explicitly naming the bitmap and data
+files whereas
+.BR dbm_open (\|)
+will take a base file name and call
+.BR dbm_prep (\|)
+with the default extensions.
+The
+.I flags
+and
+.I mode
+parameters are the same as for
+.BR open (2).
+.LP
+To free the resources occupied while a database handle is active, call
+.BR dbm_close (\|).
+.LP
+Given a handle, one can retrieve data associated with a key by using the
+.BR dbm_fetch (\|)
+routine, and associate data with a key by using the
+.BR dbm_store (\|)
+routine.
+.LP
+The values of the
+.I flags
+parameter for
+.BR dbm_store (\|)
+can be either
+.BR \s-1DBM_INSERT\s0 ,
+which will not change an existing entry with the same key, or
+.BR \s-1DBM_REPLACE\s0 ,
+which will replace an existing entry with the same key.
+Keys are unique within the database.
+.LP
+To delete a key and its associated value use the
+.BR dbm_delete (\|)
+routine.
+.LP
+To retrieve every key in the database, use a loop like:
+.sp
+.nf
+.ft B
+for (key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db))
+ ;
+.ft R
+.fi
+.LP
+The order of retrieval is unspecified.
+.LP
+If you determine that the performance of the database is inadequate or
+you notice clustering or other effects that may be due to the hashing
+algorithm used by this package, you can override it by supplying your
+own
+.BR dbm_hash (\|)
+routine. Doing so will make the database unintelligable to any other
+applications that do not use your specialized hash function.
+.sp
+.LP
+The following macros are defined in the header file:
+.IP
+.BR dbm_rdonly (\|)
+returns true if the database has been opened read\-only.
+.IP
+.BR dbm_error (\|)
+returns true if an I/O error has occurred.
+.IP
+.BR dbm_clearerr (\|)
+allows you to clear the error flag if you think you know what the error
+was and insist on ignoring it.
+.IP
+.BR dbm_dirfno (\|)
+returns the file descriptor associated with the bitmap file.
+.IP
+.BR dbm_pagfno (\|)
+returns the file descriptor associated with the data file.
+.SH SEE ALSO
+.IR open (2).
+.SH DIAGNOSTICS
+Functions that return a
+.B "DBM *"
+handle will use
+.SM NULL
+to indicate an error.
+Functions that return an
+.B int
+will use \-1 to indicate an error. The normal return value in that case is 0.
+Functions that return a
+.B datum
+will return
+.B nullitem
+to indicate an error.
+.LP
+As a special case of
+.BR dbm_store (\|),
+if it is called with the
+.B \s-1DBM_INSERT\s0
+flag and the key already exists in the database, the return value will be 1.
+.LP
+In general, if a function parameter is invalid,
+.B errno
+will be set to
+.BR \s-1EINVAL\s0 .
+If a write operation is requested on a read-only database,
+.B errno
+will be set to
+.BR \s-1ENOPERM\s0 .
+If a memory allocation (using
+.IR malloc (3))
+failed,
+.B errno
+will be set to
+.BR \s-1ENOMEM\s0 .
+For I/O operation failures
+.B errno
+will contain the value set by the relevant failed system call, either
+.IR read (2),
+.IR write (2),
+or
+.IR lseek (2).
+.SH AUTHOR
+.IP "Ozan S. Yigit" (oz@nexus.yorku.ca)
+.SH BUGS
+The sum of key and value data sizes must not exceed
+.B \s-1PAIRMAX\s0
+(1008 bytes).
+.LP
+The sum of the key and value data sizes where several keys hash to the
+same value must fit within one bitmap page.
+.LP
+The
+.B \.pag
+file will contain holes, so its apparent size is larger than its contents.
+When copied through the filesystem the holes will be filled.
+.LP
+The contents of
+.B datum
+values returned are in volatile storage. If you want to retain the values
+pointed to, you must copy them immediately before another call to this package.
+.LP
+The only safe way for multiple processes to (read and) update a database at
+the same time, is to implement a private locking scheme outside this package
+and open and close the database between lock acquisitions. It is safe for
+multiple processes to concurrently access a database read-only.
+.SH APPLICATIONS PORTABILITY
+For complete source code compatibility with the Berkeley Unix
+.IR ndbm (3)
+library, the
+.B sdbm.h
+header file should be installed in
+.BR /usr/include/ndbm.h .
+.LP
+The
+.B nullitem
+data item, and the
+.BR dbm_prep (\|),
+.BR dbm_hash (\|),
+.BR dbm_rdonly (\|),
+.BR dbm_dirfno (\|),
+and
+.BR dbm_pagfno (\|)
+functions are unique to this package.
diff --git a/ext/SDBM_File/sdbm/sdbm.c b/ext/SDBM_File/sdbm/sdbm.c
new file mode 100644
index 0000000000..d09adccdd3
--- /dev/null
+++ b/ext/SDBM_File/sdbm/sdbm.c
@@ -0,0 +1,520 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ *
+ * core routines
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: sdbm.c,v 1.16 90/12/13 13:01:31 oz Exp $";
+#endif
+
+#include "config.h"
+#include "sdbm.h"
+#include "tune.h"
+#include "pair.h"
+
+#ifdef I_FCNTL
+# include <fcntl.h>
+#endif
+#ifdef I_SYS_FILE
+# include <sys/file.h>
+#endif
+
+#ifdef I_STRING
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+/*
+ * externals
+ */
+#ifndef sun
+extern int errno;
+#endif
+
+extern Malloc_t malloc proto((MEM_SIZE));
+extern void free proto((void *));
+extern Off_t lseek();
+
+/*
+ * forward
+ */
+static int getdbit proto((DBM *, long));
+static int setdbit proto((DBM *, long));
+static int getpage proto((DBM *, long));
+static datum getnext proto((DBM *));
+static int makroom proto((DBM *, long, int));
+
+/*
+ * useful macros
+ */
+#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+#define ioerr(db) ((db)->flags |= DBM_IOERR)
+
+#define OFF_PAG(off) (long) (off) * PBLKSIZ
+#define OFF_DIR(off) (long) (off) * DBLKSIZ
+
+static long masks[] = {
+ 000000000000, 000000000001, 000000000003, 000000000007,
+ 000000000017, 000000000037, 000000000077, 000000000177,
+ 000000000377, 000000000777, 000000001777, 000000003777,
+ 000000007777, 000000017777, 000000037777, 000000077777,
+ 000000177777, 000000377777, 000000777777, 000001777777,
+ 000003777777, 000007777777, 000017777777, 000037777777,
+ 000077777777, 000177777777, 000377777777, 000777777777,
+ 001777777777, 003777777777, 007777777777, 017777777777
+};
+
+datum nullitem = {NULL, 0};
+
+DBM *
+sdbm_open(file, flags, mode)
+register char *file;
+register int flags;
+register int mode;
+{
+ register DBM *db;
+ register char *dirname;
+ register char *pagname;
+ register int n;
+
+ if (file == NULL || !*file)
+ return errno = EINVAL, (DBM *) NULL;
+/*
+ * need space for two seperate filenames
+ */
+ n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
+
+ if ((dirname = malloc((unsigned) n)) == NULL)
+ return errno = ENOMEM, (DBM *) NULL;
+/*
+ * build the file names
+ */
+ dirname = strcat(strcpy(dirname, file), DIRFEXT);
+ pagname = strcpy(dirname + strlen(dirname) + 1, file);
+ pagname = strcat(pagname, PAGFEXT);
+
+ db = sdbm_prep(dirname, pagname, flags, mode);
+ free((char *) dirname);
+ return db;
+}
+
+DBM *
+sdbm_prep(dirname, pagname, flags, mode)
+char *dirname;
+char *pagname;
+int flags;
+int mode;
+{
+ register DBM *db;
+ struct stat dstat;
+
+ if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
+ return errno = ENOMEM, (DBM *) NULL;
+
+ db->flags = 0;
+ db->hmask = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+/*
+ * adjust user flags so that WRONLY becomes RDWR,
+ * as required by this package. Also set our internal
+ * flag for RDONLY if needed.
+ */
+ if (flags & O_WRONLY)
+ flags = (flags & ~O_WRONLY) | O_RDWR;
+
+ else if ((flags & 03) == O_RDONLY)
+ db->flags = DBM_RDONLY;
+/*
+ * open the files in sequence, and stat the dirfile.
+ * If we fail anywhere, undo everything, return NULL.
+ */
+ if ((db->pagf = open(pagname, flags, mode)) > -1) {
+ if ((db->dirf = open(dirname, flags, mode)) > -1) {
+/*
+ * need the dirfile size to establish max bit number.
+ */
+ if (fstat(db->dirf, &dstat) == 0) {
+/*
+ * zero size: either a fresh database, or one with a single,
+ * unsplit data page: dirpage is all zeros.
+ */
+ db->dirbno = (!dstat.st_size) ? 0 : -1;
+ db->pagbno = -1;
+ db->maxbno = dstat.st_size * BYTESIZ;
+
+ (void) memset(db->pagbuf, 0, PBLKSIZ);
+ (void) memset(db->dirbuf, 0, DBLKSIZ);
+ /*
+ * success
+ */
+ return db;
+ }
+ (void) close(db->dirf);
+ }
+ (void) close(db->pagf);
+ }
+ free((char *) db);
+ return (DBM *) NULL;
+}
+
+void
+sdbm_close(db)
+register DBM *db;
+{
+ if (db == NULL)
+ errno = EINVAL;
+ else {
+ (void) close(db->dirf);
+ (void) close(db->pagf);
+ free((char *) db);
+ }
+}
+
+datum
+sdbm_fetch(db, key)
+register DBM *db;
+datum key;
+{
+ if (db == NULL || bad(key))
+ return errno = EINVAL, nullitem;
+
+ if (getpage(db, exhash(key)))
+ return getpair(db->pagbuf, key);
+
+ return ioerr(db), nullitem;
+}
+
+int
+sdbm_delete(db, key)
+register DBM *db;
+datum key;
+{
+ if (db == NULL || bad(key))
+ return errno = EINVAL, -1;
+ if (sdbm_rdonly(db))
+ return errno = EPERM, -1;
+
+ if (getpage(db, exhash(key))) {
+ if (!delpair(db->pagbuf, key))
+ return -1;
+/*
+ * update the page file
+ */
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), -1;
+
+ return 0;
+ }
+
+ return ioerr(db), -1;
+}
+
+int
+sdbm_store(db, key, val, flags)
+register DBM *db;
+datum key;
+datum val;
+int flags;
+{
+ int need;
+ register long hash;
+
+ if (db == NULL || bad(key))
+ return errno = EINVAL, -1;
+ if (sdbm_rdonly(db))
+ return errno = EPERM, -1;
+
+ need = key.dsize + val.dsize;
+/*
+ * is the pair too big (or too small) for this database ??
+ */
+ if (need < 0 || need > PAIRMAX)
+ return errno = EINVAL, -1;
+
+ if (getpage(db, (hash = exhash(key)))) {
+/*
+ * if we need to replace, delete the key/data pair
+ * first. If it is not there, ignore.
+ */
+ if (flags == DBM_REPLACE)
+ (void) delpair(db->pagbuf, key);
+#ifdef SEEDUPS
+ else if (duppair(db->pagbuf, key))
+ return 1;
+#endif
+/*
+ * if we do not have enough room, we have to split.
+ */
+ if (!fitpair(db->pagbuf, need))
+ if (!makroom(db, hash, need))
+ return ioerr(db), -1;
+/*
+ * we have enough room or split is successful. insert the key,
+ * and update the page file.
+ */
+ (void) putpair(db->pagbuf, key, val);
+
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), -1;
+ /*
+ * success
+ */
+ return 0;
+ }
+
+ return ioerr(db), -1;
+}
+
+/*
+ * makroom - make room by splitting the overfull page
+ * this routine will attempt to make room for SPLTMAX times before
+ * giving up.
+ */
+static int
+makroom(db, hash, need)
+register DBM *db;
+long hash;
+int need;
+{
+ long newp;
+ char twin[PBLKSIZ];
+ char *pag = db->pagbuf;
+ char *new = twin;
+ register int smax = SPLTMAX;
+
+ do {
+/*
+ * split the current page
+ */
+ (void) splpage(pag, new, db->hmask + 1);
+/*
+ * address of the new page
+ */
+ newp = (hash & db->hmask) | (db->hmask + 1);
+
+/*
+ * write delay, read avoidence/cache shuffle:
+ * select the page for incoming pair: if key is to go to the new page,
+ * write out the previous one, and copy the new one over, thus making
+ * it the current page. If not, simply write the new page, and we are
+ * still looking at the page of interest. current page is not updated
+ * here, as sdbm_store will do so, after it inserts the incoming pair.
+ */
+ if (hash & (db->hmask + 1)) {
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+ db->pagbno = newp;
+ (void) memcpy(pag, new, PBLKSIZ);
+ }
+ else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
+ || write(db->pagf, new, PBLKSIZ) < 0)
+ return 0;
+
+ if (!setdbit(db, db->curbit))
+ return 0;
+/*
+ * see if we have enough room now
+ */
+ if (fitpair(pag, need))
+ return 1;
+/*
+ * try again... update curbit and hmask as getpage would have
+ * done. because of our update of the current page, we do not
+ * need to read in anything. BUT we have to write the current
+ * [deferred] page out, as the window of failure is too great.
+ */
+ db->curbit = 2 * db->curbit +
+ ((hash & (db->hmask + 1)) ? 2 : 1);
+ db->hmask |= db->hmask + 1;
+
+ if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
+ || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+
+ } while (--smax);
+/*
+ * if we are here, this is real bad news. After SPLTMAX splits,
+ * we still cannot fit the key. say goodnight.
+ */
+#ifdef BADMESS
+ (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
+#endif
+ return 0;
+
+}
+
+/*
+ * the following two routines will break if
+ * deletions aren't taken into account. (ndbm bug)
+ */
+datum
+sdbm_firstkey(db)
+register DBM *db;
+{
+ if (db == NULL)
+ return errno = EINVAL, nullitem;
+/*
+ * start at page 0
+ */
+ if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
+ || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return ioerr(db), nullitem;
+ db->pagbno = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+
+ return getnext(db);
+}
+
+datum
+sdbm_nextkey(db)
+register DBM *db;
+{
+ if (db == NULL)
+ return errno = EINVAL, nullitem;
+ return getnext(db);
+}
+
+/*
+ * all important binary trie traversal
+ */
+static int
+getpage(db, hash)
+register DBM *db;
+register long hash;
+{
+ register int hbit;
+ register long dbit;
+ register long pagb;
+
+ dbit = 0;
+ hbit = 0;
+ while (dbit < db->maxbno && getdbit(db, dbit))
+ dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+
+ debug(("dbit: %d...", dbit));
+
+ db->curbit = dbit;
+ db->hmask = masks[hbit];
+
+ pagb = hash & db->hmask;
+/*
+ * see if the block we need is already in memory.
+ * note: this lookaside cache has about 10% hit rate.
+ */
+ if (pagb != db->pagbno) {
+/*
+ * note: here, we assume a "hole" is read as 0s.
+ * if not, must zero pagbuf first.
+ */
+ if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
+ || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
+ return 0;
+ if (!chkpage(db->pagbuf))
+ return 0;
+ db->pagbno = pagb;
+
+ debug(("pag read: %d\n", pagb));
+ }
+ return 1;
+}
+
+static int
+getdbit(db, dbit)
+register DBM *db;
+register long dbit;
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
+}
+
+static int
+setdbit(db, dbit)
+register DBM *db;
+register long dbit;
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
+
+ if (dbit >= db->maxbno)
+ db->maxbno += DBLKSIZ * BYTESIZ;
+
+ if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
+ || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * getnext - get the next key in the page, and if done with
+ * the page, try the next page in sequence
+ */
+static datum
+getnext(db)
+register DBM *db;
+{
+ datum key;
+
+ for (;;) {
+ db->keyptr++;
+ key = getnkey(db->pagbuf, db->keyptr);
+ if (key.dptr != NULL)
+ return key;
+/*
+ * we either run out, or there is nothing on this page..
+ * try the next one... If we lost our position on the
+ * file, we will have to seek.
+ */
+ db->keyptr = 0;
+ if (db->pagbno != db->blkptr++)
+ if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
+ break;
+ db->pagbno = db->blkptr;
+ if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
+ break;
+ if (!chkpage(db->pagbuf))
+ break;
+ }
+
+ return ioerr(db), nullitem;
+}
+
diff --git a/ext/SDBM_File/sdbm/sdbm.h b/ext/SDBM_File/sdbm/sdbm.h
new file mode 100644
index 0000000000..927e2c2e30
--- /dev/null
+++ b/ext/SDBM_File/sdbm/sdbm.h
@@ -0,0 +1,234 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: public domain.
+ */
+#define DBLKSIZ 4096
+#define PBLKSIZ 1024
+#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
+#define SPLTMAX 10 /* maximum allowed splits */
+ /* for a single insertion */
+#define DIRFEXT ".dir"
+#define PAGFEXT ".pag"
+
+typedef struct {
+ int dirf; /* directory file descriptor */
+ int pagf; /* page file descriptor */
+ int flags; /* status/error flags, see below */
+ long maxbno; /* size of dirfile in bits */
+ long curbit; /* current bit number */
+ long hmask; /* current hash mask */
+ long blkptr; /* current block for nextkey */
+ int keyptr; /* current key for nextkey */
+ long blkno; /* current page to read/write */
+ long pagbno; /* current page in pagbuf */
+ char pagbuf[PBLKSIZ]; /* page file block buffer */
+ long dirbno; /* current block in dirbuf */
+ char dirbuf[DBLKSIZ]; /* directory file block buffer */
+} DBM;
+
+#define DBM_RDONLY 0x1 /* data base open read-only */
+#define DBM_IOERR 0x2 /* data base I/O error */
+
+/*
+ * utility macros
+ */
+#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
+#define sdbm_error(db) ((db)->flags & DBM_IOERR)
+
+#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
+
+#define sdbm_dirfno(db) ((db)->dirf)
+#define sdbm_pagfno(db) ((db)->pagf)
+
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+extern datum nullitem;
+
+#ifdef __STDC__
+#define proto(p) p
+#else
+#define proto(p) ()
+#endif
+
+/*
+ * flags to sdbm_store
+ */
+#define DBM_INSERT 0
+#define DBM_REPLACE 1
+
+/*
+ * ndbm interface
+ */
+extern DBM *sdbm_open proto((char *, int, int));
+extern void sdbm_close proto((DBM *));
+extern datum sdbm_fetch proto((DBM *, datum));
+extern int sdbm_delete proto((DBM *, datum));
+extern int sdbm_store proto((DBM *, datum, datum, int));
+extern datum sdbm_firstkey proto((DBM *));
+extern datum sdbm_nextkey proto((DBM *));
+
+/*
+ * other
+ */
+extern DBM *sdbm_prep proto((char *, char *, int, int));
+extern long sdbm_hash proto((char *, int));
+
+#ifndef SDBM_ONLY
+#define dbm_open sdbm_open;
+#define dbm_close sdbm_close;
+#define dbm_fetch sdbm_fetch;
+#define dbm_store sdbm_store;
+#define dbm_delete sdbm_delete;
+#define dbm_firstkey sdbm_firstkey;
+#define dbm_nextkey sdbm_nextkey;
+#define dbm_error sdbm_error;
+#define dbm_clearerr sdbm_clearerr;
+#endif
+
+/* Most of the following is stolen from perl.h. */
+#ifndef H_PERL /* Include guard */
+
+/*
+ * The following contortions are brought to you on behalf of all the
+ * standards, semi-standards, de facto standards, not-so-de-facto standards
+ * of the world, as well as all the other botches anyone ever thought of.
+ * The basic theory is that if we work hard enough here, the rest of the
+ * code can be a lot prettier. Well, so much for theory. Sorry, Henry...
+ */
+
+#include <errno.h>
+#ifdef HAS_SOCKET
+# ifdef I_NET_ERRNO
+# include <net/errno.h>
+# endif
+#endif
+
+#ifdef MYMALLOC
+# ifdef HIDEMYMALLOC
+# define malloc Mymalloc
+# define realloc Myremalloc
+# define free Myfree
+# endif
+# define safemalloc malloc
+# define saferealloc realloc
+# define safefree free
+#endif
+
+#if defined(__STDC__) || defined(_AIX) || defined(__stdc__) || defined(__cplusplus)
+# define STANDARD_C 1
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <setjmp.h>
+
+#ifdef I_UNISTD
+#include <unistd.h>
+#endif
+
+#ifndef MSDOS
+# ifdef PARAM_NEEDS_TYPES
+# include <sys/types.h>
+# endif
+# include <sys/param.h>
+#endif
+
+#ifndef _TYPES_ /* If types.h defines this it's easy. */
+# ifndef major /* Does everyone's types.h define this? */
+# include <sys/types.h>
+# endif
+#endif
+
+#include <sys/stat.h>
+
+#ifndef SEEK_SET
+# ifdef L_SET
+# define SEEK_SET L_SET
+# else
+# define SEEK_SET 0 /* Wild guess. */
+# endif
+#endif
+
+/* Use all the "standard" definitions? */
+#ifdef STANDARD_C
+# include <stdlib.h>
+#endif /* STANDARD_C */
+
+#define MEM_SIZE Size_t
+
+#ifdef I_STRING
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifdef I_MEMORY
+#include <memory.h>
+#endif
+
+#if defined(mips) && defined(ultrix) && !defined(__STDC__)
+# undef HAS_MEMCMP
+#endif
+
+#ifdef HAS_MEMCPY
+# if !defined(STANDARD_C) && !defined(I_STRING) && !defined(I_MEMORY)
+# ifndef memcpy
+ extern char * memcpy _((char*, char*, int));
+# endif
+# endif
+#else
+# ifndef memcpy
+# ifdef HAS_BCOPY
+# define memcpy(d,s,l) bcopy(s,d,l)
+# else
+# define memcpy(d,s,l) my_bcopy(s,d,l)
+# endif
+# endif
+#endif /* HAS_MEMCPY */
+
+#ifdef HAS_MEMSET
+# if !defined(STANDARD_C) && !defined(I_STRING) && !defined(I_MEMORY)
+# ifndef memset
+ extern char *memset _((char*, int, int));
+# endif
+# endif
+# define memzero(d,l) memset(d,0,l)
+#else
+# ifndef memzero
+# ifdef HAS_BZERO
+# define memzero(d,l) bzero(d,l)
+# else
+# define memzero(d,l) my_bzero(d,l)
+# endif
+# endif
+#endif /* HAS_MEMSET */
+
+#ifdef HAS_MEMCMP
+# if !defined(STANDARD_C) && !defined(I_STRING) && !defined(I_MEMORY)
+# ifndef memcmp
+ extern int memcmp _((char*, char*, int));
+# endif
+# endif
+#else
+# ifndef memcmp
+# define memcmp(s1,s2,l) my_memcmp(s1,s2,l)
+# endif
+#endif /* HAS_MEMCMP */
+
+/* we prefer bcmp slightly for comparisons that don't care about ordering */
+#ifndef HAS_BCMP
+# ifndef bcmp
+# define bcmp(s1,s2,l) memcmp(s1,s2,l)
+# endif
+#endif /* HAS_BCMP */
+
+#ifdef I_NETINET_IN
+# include <netinet/in.h>
+#endif
+
+#endif /* Include guard */
diff --git a/ext/SDBM_File/sdbm/tune.h b/ext/SDBM_File/sdbm/tune.h
new file mode 100644
index 0000000000..b95c8c8634
--- /dev/null
+++ b/ext/SDBM_File/sdbm/tune.h
@@ -0,0 +1,23 @@
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * tuning and portability constructs [not nearly enough]
+ * author: oz@nexus.yorku.ca
+ */
+
+#define BYTESIZ 8
+
+/*
+ * important tuning parms (hah)
+ */
+
+#define SEEDUPS /* always detect duplicates */
+#define BADMESS /* generate a message for worst case:
+ cannot make room after SPLTMAX splits */
+/*
+ * misc
+ */
+#ifdef DEBUG
+#define debug(x) printf x
+#else
+#define debug(x)
+#endif
diff --git a/ext/SDBM_File/sdbm/util.c b/ext/SDBM_File/sdbm/util.c
new file mode 100644
index 0000000000..4b03d89f09
--- /dev/null
+++ b/ext/SDBM_File/sdbm/util.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#ifdef SDBM
+#include "sdbm.h"
+#else
+#include "ndbm.h"
+#endif
+
+void
+oops(s1, s2)
+register char *s1;
+register char *s2;
+{
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+ extern char *progname;
+
+ if (progname)
+ fprintf(stderr, "%s: ", progname);
+ fprintf(stderr, s1, s2);
+ if (errno > 0 && errno < sys_nerr)
+ fprintf(stderr, " (%s)", sys_errlist[errno]);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+int
+okpage(pag)
+char *pag;
+{
+ register unsigned n;
+ register off;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) > PBLKSIZ / sizeof(short))
+ return 0;
+
+ if (!n)
+ return 1;
+
+ off = PBLKSIZ;
+ for (ino++; n; ino += 2) {
+ if (ino[0] > off || ino[1] > off ||
+ ino[1] > ino[0])
+ return 0;
+ off = ino[1];
+ n -= 2;
+ }
+
+ return 1;
+}
diff --git a/ext/SDBM_File/typemap b/ext/SDBM_File/typemap
new file mode 100644
index 0000000000..a6b0e5faa8
--- /dev/null
+++ b/ext/SDBM_File/typemap
@@ -0,0 +1,25 @@
+#
+#################################### DBM SECTION
+#
+
+datum T_DATUM
+gdatum T_GDATUM
+NDBM_File T_PTROBJ
+GDBM_File T_PTROBJ
+SDBM_File T_PTROBJ
+ODBM_File T_PTROBJ
+DB_File T_PTROBJ
+DBZ_File T_PTROBJ
+FATALFUNC T_OPAQUEPTR
+
+INPUT
+T_DATUM
+ $var.dptr = SvPV($arg, na);
+ $var.dsize = (int)na;
+T_GDATUM
+ UNIMPLEMENTED
+OUTPUT
+T_DATUM
+ sv_setpvn($arg, $var.dptr, $var.dsize);
+T_GDATUM
+ sv_usepvn($arg, $var.dptr, $var.dsize);