1 if test -f 'CHANGES' -a "${1}" != "-c" ; then
2 echo shar: Will not clobber existing file \"'CHANGES'\"
4 echo shar: Extracting \"'CHANGES'\" \(900 characters\)
5 sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
6 XChanges from the earlier BETA releases.
8 Xo dbm_prep does everything now, so dbm_open is just a simple
9 X wrapper that builds the default filenames. dbm_prep no longer
10 X requires a (DBM *) db parameter: it allocates one itself. It
11 X returns (DBM *) db or (DBM *) NULL.
13 Xo makroom is now reliable. In the common-case optimization of the page
14 X split, the page into which the incoming key/value pair is to be inserted
15 X is write-deferred (if the split is successful), thereby saving a cosly
16 X write. BUT, if the split does not make enough room (unsuccessful), the
17 X deferred page is written out, as the failure-window is now dependent on
18 X the number of split attempts.
20 Xo if -DDUFF is defined, hash function will also use the DUFF construct.
21 X This may look like a micro-performance tweak (maybe it is), but in fact,
22 X the hash function is the third most-heavily used function, after read
25 if test 900 -ne `wc -c <'CHANGES'`; then
26 echo shar: \"'CHANGES'\" unpacked with wrong size!
30 if test -f 'COMPARE' -a "${1}" != "-c" ; then
31 echo shar: Will not clobber existing file \"'COMPARE'\"
33 echo shar: Extracting \"'COMPARE'\" \(2832 characters\)
34 sed "s/^X//" >'COMPARE' <<'END_OF_FILE'
36 XScript started on Thu Sep 28 15:41:06 1989
38 Xtitan titan 4_0 UMIPS mips
40 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dbm.c
41 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c sdbm.c
42 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c pair.c
43 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c hash.c
44 X ar cr libsdbm.a sdbm.o pair.o hash.o
46 X cc -o dbm dbm.o libsdbm.a
47 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dba.c
49 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dbd.c
51 X cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -o x-dbm dbm.o
55 X 65110 218344 3204883 history
57 X% /bin/time dbm build foo <history
64 X 5 README 2 dbd.c 1 hash.c 1 pair.h
65 X 0 SCRIPT 5 dbd.o 1 hash.o 5 pair.o
66 X 1 WISHLIST 62 dbm 3130 history 1 port.h
67 X 46 dba 5 dbm.c 11 howtodbm.txt 11 sdbm.c
68 X 3 dba.c 8 dbm.o 14 libsdbm.a 2 sdbm.h
69 X 6 dba.o 4 foo.dir 1 makefile 8 sdbm.o
70 X 46 dbd 10810 foo.pag 6 pair.c 60 x-dbm
72 X-rw-r--r-- 1 oz 4096 Sep 28 15:48 foo.dir
73 X-rw-r--r-- 1 oz 11069440 Sep 28 15:48 foo.pag
75 X% /bin/time x-dbm build bar <history
83 X 5 README 46 dbd 1 hash.c 5 pair.o
84 X 1 SCRIPT 2 dbd.c 1 hash.o 1 port.h
85 X 1 WISHLIST 5 dbd.o 3130 history 11 sdbm.c
86 X 4 bar.dir 62 dbm 11 howtodbm.txt 2 sdbm.h
87 X13356 bar.pag 5 dbm.c 14 libsdbm.a 8 sdbm.o
88 X 46 dba 8 dbm.o 1 makefile 60 x-dbm
89 X 3 dba.c 4 foo.dir 6 pair.c
90 X 6 dba.o 10810 foo.pag 1 pair.h
93 X-rw-r--r-- 1 oz 4096 Sep 28 15:54 bar.dir
94 X-rw-r--r-- 1 oz 13676544 Sep 28 15:54 bar.pag
97 X#10801: ok. no entries.
98 X#10802: ok. no entries.
99 X#10803: ok. no entries.
100 X#10804: ok. no entries.
101 X#10805: ok. no entries.
102 X#10806: ok. no entries.
103 X#10807: ok. no entries.
104 X#10808: ok. no entries.
105 X#10809: ok. 11 entries 67% used free 337.
106 X10810 pages (6036 holes): 65073 entries
109 X#13347: ok. no entries.
110 X#13348: ok. no entries.
111 X#13349: ok. no entries.
112 X#13350: ok. no entries.
113 X#13351: ok. no entries.
114 X#13352: ok. no entries.
115 X#13353: ok. no entries.
116 X#13354: ok. no entries.
117 X#13355: ok. 7 entries 33% used free 676.
118 X13356 pages (8643 holes): 65073 entries
121 Xscript done on Thu Sep 28 16:08:45 1989
124 if test 2832 -ne `wc -c <'COMPARE'`; then
125 echo shar: \"'COMPARE'\" unpacked with wrong size!
129 if test -f 'README' -a "${1}" != "-c" ; then
130 echo shar: Will not clobber existing file \"'README'\"
132 echo shar: Extracting \"'README'\" \(11457 characters\)
133 sed "s/^X//" >'README' <<'END_OF_FILE'
140 X sdbm - Substitute DBM
142 X Berkeley ndbm for Every UN*X[1] Made Simple
146 X The Guild of PD Software Toolmakers
153 XImplementation is the sincerest form of flattery. - L. Peter
156 XA The Clone of the ndbm library
158 X The sources accompanying this notice - sdbm - consti-
159 Xtute the first public release (Dec. 1990) of a complete
160 Xclone of the Berkeley UN*X ndbm library. The sdbm library is
161 Xmeant to clone the proven functionality of ndbm as closely
162 Xas possible, including a few improvements. It is practical,
163 Xeasy to understand, and compatible. The sdbm library is not
164 Xderived from any licensed, proprietary or copyrighted
167 X The sdbm implementation is based on a 1978 algorithm
168 X[Lar78] by P.-A. (Paul) Larson known as ``Dynamic Hashing''.
169 XIn the course of searching for a substitute for ndbm, I pro-
170 Xtotyped three different external-hashing algorithms [Lar78,
171 XFag79, Lit80] and ultimately chose Larson's algorithm as a
172 Xbasis of the sdbm implementation. The Bell Labs dbm (and
173 Xtherefore ndbm) is based on an algorithm invented by Ken
174 XThompson, [Tho90, Tor87] and predates Larson's work.
176 X The sdbm programming interface is totally compatible
177 Xwith ndbm and includes a slight improvement in database ini-
178 Xtialization. It is also expected to be binary-compatible
179 Xunder most UN*X versions that support the ndbm library.
181 X The sdbm implementation shares the shortcomings of the
182 Xndbm library, as a side effect of various simplifications to
183 Xthe original Larson algorithm. It does produce holes in the
184 Xpage file as it writes pages past the end of file. (Larson's
185 Xpaper include a clever solution to this problem that is a
186 Xresult of using the hash value directly as a block address.)
187 XOn the other hand, extensive tests seem to indicate that
188 Xsdbm creates fewer holes in general, and the resulting page-
189 Xfiles are smaller. The sdbm implementation is also faster
190 Xthan ndbm in database creation. Unlike the ndbm, the sdbm
191 X_________________________
193 X [1] UN*X is not a trademark of any (dis)organization.
206 Xstore operation will not ``wander away'' trying to split its
207 Xdata pages to insert a datum that cannot (due to elaborate
208 Xworst-case situations) be inserted. (It will fail after a
209 Xpre-defined number of attempts.)
211 XImportant Compatibility Warning
213 X The sdbm and ndbm libraries cannot share databases: one
214 Xcannot read the (dir/pag) database created by the other.
215 XThis is due to the differences between the ndbm and sdbm
216 Xalgorithms[2], and the hash functions used. It is easy to
217 Xconvert between the dbm/ndbm databases and sdbm by ignoring
218 Xthe index completely: see dbd, dbu etc.
221 XNotice of Intellectual Property
223 XThe entire sdbm library package, as authored by me, Ozan S.
224 XYigit, is hereby placed in the public domain. As such, the
225 Xauthor is not responsible for the consequences of use of
226 Xthis software, no matter how awful, even if they arise from
227 Xdefects in it. There is no expressed or implied warranty for
230 X Since the sdbm library package is in the public domain,
231 Xthis original release or any additional public-domain
232 Xreleases of the modified original cannot possibly (by defin-
233 Xition) be withheld from you. Also by definition, You (singu-
234 Xlar) have all the rights to this code (including the right
235 Xto sell without permission, the right to hoard[3] and the
236 Xright to do other icky things as you see fit) but those
237 Xrights are also granted to everyone else.
239 X Please note that all previous distributions of this
240 Xsoftware contained a copyright (which is now dropped) to
241 Xprotect its origins and its current public domain status
242 Xagainst any possible claims and/or challenges.
246 X Many people have been very helpful and supportive. A
247 Xpartial list would necessarily include Rayan Zacherissen
248 X(who contributed the man page, and also hacked a MMAP
249 X_________________________
251 X [2] Torek's discussion [Tor87] indicates that
252 Xdbm/ndbm implementations use the hash value to traverse
253 Xthe radix trie differently than sdbm and as a result,
254 Xthe page indexes are generated in different order. For
255 Xmore information, send e-mail to the author.
256 X [3] You cannot really hoard something that is avail-
257 Xable to the public at large, but try if it makes you
272 Xversion of sdbm), Arnold Robbins, Chris Lewis, Bill David-
273 Xsen, Henry Spencer, Geoff Collyer, Rich Salz (who got me
274 Xstarted in the first place), Johannes Ruschein (who did the
275 Xminix port) and David Tilbrook. I thank you all.
277 XDistribution Manifest and Notes
279 XThis distribution of sdbm includes (at least) the following:
283 X biblio a small bibliography on external hashing
284 X dba.c a crude (n/s)dbm page file analyzer
285 X dbd.c a crude (n/s)dbm page file dumper (for conversion)
286 X dbe.1 man page for dbe.c
287 X dbe.c Janick's database editor
288 X dbm.c a dbm library emulation wrapper for ndbm/sdbm
289 X dbm.h header file for the above
290 X dbu.c a crude db management utility
291 X hash.c hashing function
293 X pair.c page-level routines (posted earlier)
294 X pair.h header file for the above
295 X readme.ms troff source for the README file
297 X sdbm.c the real thing
298 X sdbm.h header file for the above
299 X tune.h place for tuning & portability thingies
300 X util.c miscellaneous
302 X dbu is a simple database manipulation program[4] that
303 Xtries to look like Bell Labs' cbt utility. It is currently
304 Xincomplete in functionality. I use dbu to test out the rou-
305 Xtines: it takes (from stdin) tab separated key/value pairs
306 Xfor commands like build or insert or takes keys for commands
307 Xlike delete or look.
309 X dbu <build|creat|look|insert|cat|delete> dbmfile
311 X dba is a crude analyzer of dbm/sdbm/ndbm page files. It
312 Xscans the entire page file, reporting page level statistics,
313 Xand totals at the end.
315 X dbd is a crude dump program for dbm/ndbm/sdbm data-
316 Xbases. It ignores the bitmap, and dumps the data pages in
317 Xsequence. It can be used to create input for the dbu util-
318 Xity. Note that dbd will skip any NULLs in the key and data
319 Xfields, thus is unsuitable to convert some peculiar
320 X_________________________
322 X [4] The dbd, dba, dbu utilities are quick hacks and
323 Xare not fit for production use. They were developed
324 Xlate one night, just to test out sdbm, and convert some
338 Xdatabases that insist in including the terminating null.
340 X I have also included a copy of the dbe (ndbm DataBase
341 XEditor) by Janick Bergeron [janick@bnr.ca] for your pleas-
342 Xure. You may find it more useful than the little dbu util-
345 X dbm.[ch] is a dbm library emulation on top of ndbm (and
346 Xhence suitable for sdbm). Written by Robert Elz.
348 X The sdbm library has been around in beta test for quite
349 Xa long time, and from whatever little feedback I received
350 X(maybe no news is good news), I believe it has been func-
351 Xtioning without any significant problems. I would, of
352 Xcourse, appreciate all fixes and/or improvements. Portabil-
353 Xity enhancements would especially be useful.
355 XImplementation Issues
357 X Hash functions: The algorithm behind sdbm implementa-
358 Xtion needs a good bit-scrambling hash function to be effec-
359 Xtive. I ran into a set of constants for a simple hash func-
360 Xtion that seem to help sdbm perform better than ndbm for
364 X * polynomial conversion ignoring overflows
365 X * 65599 nice. 65587 even better.
368 X dbm_hash(char *str, int len) {
369 X register unsigned long n = 0;
372 X n = n * 65599 + *str++;
376 X There may be better hash functions for the purposes of
377 Xdynamic hashing. Try your favorite, and check the pagefile.
378 XIf it contains too many pages with too many holes, (in rela-
379 Xtion to this one for example) or if sdbm simply stops work-
380 Xing (fails after SPLTMAX attempts to split) when you feed
381 Xyour NEWS history file to it, you probably do not have a
382 Xgood hashing function. If you do better (for different
383 Xtypes of input), I would like to know about the function you
386 X Block sizes: It seems (from various tests on a few
387 Xmachines) that a page file block size PBLKSIZ of 1024 is by
388 Xfar the best for performance, but this also happens to limit
389 Xthe size of a key/value pair. Depending on your needs, you
390 Xmay wish to increase the page size, and also adjust PAIRMAX
391 X(the maximum size of a key/value pair allowed: should always
404 Xbe at least three words smaller than PBLKSIZ.) accordingly.
405 XThe system-wide version of the library should probably be
406 Xconfigured with 1024 (distribution default), as this appears
407 Xto be sufficient for most common uses of sdbm.
411 X This package has been tested in many different UN*Xes
412 Xeven including minix, and appears to be reasonably portable.
413 XThis does not mean it will port easily to non-UN*X systems.
415 XNotes and Miscellaneous
417 X The sdbm is not a very complicated package, at least
418 Xnot after you familiarize yourself with the literature on
419 Xexternal hashing. There are other interesting algorithms in
420 Xexistence that ensure (approximately) single-read access to
421 Xa data value associated with any key. These are directory-
422 Xless schemes such as linear hashing [Lit80] (+ Larson varia-
423 Xtions), spiral storage [Mar79] or directory schemes such as
424 Xextensible hashing [Fag79] by Fagin et al. I do hope these
425 Xsources provide a reasonable playground for experimentation
426 Xwith other algorithms. See the June 1988 issue of ACM Com-
427 Xputing Surveys [Enb88] for an excellent overview of the
434 X P.-A. Larson, ``Dynamic Hashing'', BIT, vol. 18, pp.
438 X Ken Thompson, private communication, Nov. 1990
441 X W. Litwin, `` Linear Hashing: A new tool for file and
442 X table addressing'', Proceedings of the 6th Conference on
443 X Very Large Dabatases (Montreal), pp. 212-223, Very
444 X Large Database Foundation, Saratoga, Calif., 1980.
447 X R. Fagin, J. Nievergelt, N. Pippinger, and H. R.
448 X Strong, ``Extendible Hashing - A Fast Access Method for
449 X Dynamic Files'', ACM Trans. Database Syst., vol. 4,
450 X no.3, pp. 315-344, Sept. 1979.
453 X Rich Wales, ``Discussion of "dbm" data base system'',
454 X USENET newsgroup unix.wizards, Jan. 1984.
457 X Chris Torek, ``Re: dbm.a and ndbm.a archives'',
470 X USENET newsgroup comp.unix, 1987.
473 X G. N. Martin, ``Spiral Storage: Incrementally Augment-
474 X able Hash Addressed Storage'', Technical Report #27,
475 X University of Varwick, Coventry, U.K., 1979.
478 X R. J. Enbody and H. C. Du, ``Dynamic Hashing
479 X Schemes'',ACM Computing Surveys, vol. 20, no. 2, pp.
531 if test 11457 -ne `wc -c <'README'`; then
532 echo shar: \"'README'\" unpacked with wrong size!
536 if test -f 'biblio' -a "${1}" != "-c" ; then
537 echo shar: Will not clobber existing file \"'biblio'\"
539 echo shar: Extracting \"'biblio'\" \(1012 characters\)
540 sed "s/^X//" >'biblio' <<'END_OF_FILE'
543 X%T Dynamic Hashing Schemes
544 X%J ACM Computing Surveys
560 X%T Linear Hashing: A new tool for file and table addressing
561 X%J Proceedings of the 6th Conference on Very Large Dabatases (Montreal)
562 X%I Very Large Database Foundation
572 X%T Extendible Hashing - A Fast Access Method for Dynamic Files
573 X%J ACM Trans. Database Syst.
581 X%T Spiral Storage: Incrementally Augmentable Hash Addressed Storage
582 X%J Technical Report #27
583 X%I University of Varwick
589 X%T Re: dbm.a and ndbm.a archives
590 X%B USENET newsgroup comp.unix
595 X%T Discusson of "dbm" data base system
596 X%B USENET newsgroup unix.wizards
606 if test 1012 -ne `wc -c <'biblio'`; then
607 echo shar: \"'biblio'\" unpacked with wrong size!
611 if test -f 'dba.c' -a "${1}" != "-c" ; then
612 echo shar: Will not clobber existing file \"'dba.c'\"
614 echo shar: Extracting \"'dba.c'\" \(1273 characters\)
615 sed "s/^X//" >'dba.c' <<'END_OF_FILE'
617 X * dba dbm analysis/recovery
621 X#include <sys/file.h>
636 X progname = argv[0];
639 X name = (char *) malloc((n = strlen(p)) + 5);
641 X strcpy(name + n, ".pag");
643 X if ((pagf = open(name, O_RDONLY)) < 0)
644 X oops("cannot open %s.", name);
649 X oops("usage: %s dbname", progname);
664 X while ((b = read(pagf, pag, PBLKSIZ)) > 0) {
665 X printf("#%d: ", n);
670 X if (!(e = pagestat(pag)))
679 X printf("%d pages (%d holes): %d entries\n", n, o, t);
681 X oops("read failed: block %d", n);
689 X register short *ino = (short *) pag;
692 X printf("no entries.\n");
694 X free = ino[n] - (n + 1) * sizeof(short);
695 X printf("%3d entries %2d%% used free %d.\n",
696 X n / 2, ((PBLKSIZ - free) * 100) / PBLKSIZ, free);
701 if test 1273 -ne `wc -c <'dba.c'`; then
702 echo shar: \"'dba.c'\" unpacked with wrong size!
706 if test -f 'dbd.c' -a "${1}" != "-c" ; then
707 echo shar: Will not clobber existing file \"'dbd.c'\"
709 echo shar: Extracting \"'dbd.c'\" \(1719 characters\)
710 sed "s/^X//" >'dbd.c' <<'END_OF_FILE'
712 X * dbd - dump a dbm data file
716 X#include <sys/file.h>
723 X#define empty(page) (((short *) page)[0] == 0)
734 X progname = argv[0];
737 X name = (char *) malloc((n = strlen(p)) + 5);
739 X strcpy(name + n, ".pag");
741 X if ((pagf = open(name, O_RDONLY)) < 0)
742 X oops("cannot open %s.", name);
747 X oops("usage: %s dbname", progname);
759 X while ((r = read(pagf, pag, PBLKSIZ)) > 0) {
761 X fprintf(stderr, "%d: bad page.\n", n);
762 X else if (empty(pag))
770 X fprintf(stderr, "%d pages (%d holes).\n", n, o);
772 X oops("read failed: block %d", n);
782 X register short *ino = (short *) pag;
785 X for (i = 1; i < ino[0]; i += 2) {
786 X printf("\t[%d]: ", ino[i]);
787 X for (n = ino[i]; n < off; n++)
791 X printf("[%d]: ", ino[i + 1]);
792 X for (n = ino[i + 1]; n < off; n++)
804 X register short *ino = (short *) pag;
807 X for (i = 1; i < ino[0]; i += 2) {
808 X for (n = ino[i]; n < off; n++)
813 X for (n = ino[i + 1]; n < off; n++)
822 if test 1719 -ne `wc -c <'dbd.c'`; then
823 echo shar: \"'dbd.c'\" unpacked with wrong size!
827 if test -f 'dbe.1' -a "${1}" != "-c" ; then
828 echo shar: Will not clobber existing file \"'dbe.1'\"
830 echo shar: Extracting \"'dbe.1'\" \(1454 characters\)
831 sed "s/^X//" >'dbe.1' <<'END_OF_FILE'
832 X.TH dbe 1 "ndbm(3) EDITOR"
834 Xdbe \- Edit a ndbm(3) database
836 Xdbe <database> [-m r|w|rw] [-crtvx] -a|-d|-f|-F|-s [<key> [<content>]]
838 X\fIdbme\fP operates on ndbm(3) databases.
839 XIt can be used to create them, look at them or change them.
840 XWhen specifying the value of a key or the content of its associated entry,
841 X\\nnn, \\0, \\n, \\t, \\f and \\r are interpreted as usual.
842 XWhen displaying key/content pairs, non-printable characters are displayed
843 Xusing the \\nnn notation.
846 XList all entries in the database.
848 XCreate the database if it does not exist.
850 XDelete the entry associated with the specified key.
852 XFetch and display the entry associated with the specified key.
854 XFetch and display all the entries whose key match the specified
857 XOpen the database in read-only, write-only or read-write mode
859 XReplace the entry associated with the specified key if it already exists.
862 XStore an entry under a specific key.
863 XAn error occurs if the key already exists and the option -r was not specified.
865 XRe-initialize the database before executing the command.
868 XConfirm stores and deletions.
870 XIf option -x is used with option -c, then if the database already exists,
872 XThis can be used to implement a simple exclusive access locking mechanism.
879 if test 1454 -ne `wc -c <'dbe.1'`; then
880 echo shar: \"'dbe.1'\" unpacked with wrong size!
884 if test -f 'dbe.c' -a "${1}" != "-c" ; then
885 echo shar: Will not clobber existing file \"'dbe.c'\"
887 echo shar: Extracting \"'dbe.c'\" \(9799 characters\)
888 sed "s/^X//" >'dbe.c' <<'END_OF_FILE'
891 X#include <sys/file.h>
899 X/***************************************************************************\
901 X** Function name: getopt() **
902 X** Author: Henry Spencer, UofT **
903 X** Coding date: 84/04/28 **
907 X** Parses argv[] for arguments. **
908 X** Works with Whitesmith's C compiler. **
910 X** Inputs - The number of arguments **
911 X** - The base address of the array of arguments **
912 X** - A string listing the valid options (':' indicates an **
913 X** argument to the preceding option is required, a ';' **
914 X** indicates an argument to the preceding option is optional) **
916 X** Outputs - Returns the next option character, **
917 X** '?' for non '-' arguments **
918 X** or ':' when there is no more arguments. **
920 X** Side Effects + The argument to an option is pointed to by 'optarg' **
922 X*****************************************************************************
924 X** REVISION HISTORY: **
926 X** DATE NAME DESCRIPTION **
927 X** YY/MM/DD ------------------ ------------------------------------ **
928 X** 88/10/20 Janick Bergeron Returns '?' on unamed arguments **
929 X** returns '!' on unknown options **
930 X** and 'EOF' only when exhausted. **
931 X** 88/11/18 Janick Bergeron Return ':' when no more arguments **
932 X** 89/08/11 Janick Bergeron Optional optarg when ';' in optstring **
934 X\***************************************************************************/
936 Xchar *optarg; /* Global argument pointer. */
939 X#define index strchr
943 Xgetopt(argc, argv, optstring)
949 X register char *place;
950 X extern char *index();
951 X static int optind = 0;
952 X static char *scan = NULL;
956 X if (scan == NULL || *scan == '\0') {
960 X if (optind >= argc)
963 X optarg = place = argv[optind++];
964 X if (place[0] != '-' || place[1] == '\0')
966 X if (place[1] == '-' && place[2] == '\0')
972 X place = index(optstring, c);
973 X if (place == NULL || c == ':' || c == ';') {
975 X (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
979 X if (*++place == ':') {
981 X if (*scan != '\0') {
989 X if (optind >= argc) {
991 X (void) fprintf(stderr, "%s: %c requires an argument\n",
995 X optarg = argv[optind];
999 X else if (*place == ';') {
1001 X if (*scan != '\0') {
1009 X if (optind >= argc || *argv[optind] == '-')
1012 X optarg = argv[optind];
1028 X for (i = 0; i < db.dsize; i++) {
1029 X if (isprint(db.dptr[i]))
1030 X putchar(db.dptr[i]);
1033 X putchar('0' + ((db.dptr[i] >> 6) & 0x07));
1034 X putchar('0' + ((db.dptr[i] >> 3) & 0x07));
1035 X putchar('0' + (db.dptr[i] & 0x07));
1051 X db.dptr = (char *) malloc(strlen(s) * sizeof(char));
1052 X for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) {
1056 X else if (*s == 'r')
1058 X else if (*s == 'f')
1060 X else if (*s == 't')
1062 X else if (isdigit(*s) && isdigit(*(s + 1)) && isdigit(*(s + 2))) {
1063 X i = (*s++ - '0') << 6;
1064 X i |= (*s++ - '0') << 3;
1068 X else if (*s == '0')
1088 X buf = (char *) malloc((db.dsize + 1) * sizeof(char));
1089 X for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++);
1100 X YOW, FETCH, STORE, DELETE, SCAN, REGEXP
1104 X int giveusage = 0;
1106 X commands what = YOW;
1108 X int st_flag = DBM_INSERT;
1117 X while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') {
1135 X flags &= ~(000007);
1136 X if (strcmp(optarg, "r") == 0)
1137 X flags |= O_RDONLY;
1138 X else if (strcmp(optarg, "w") == 0)
1139 X flags |= O_WRONLY;
1140 X else if (strcmp(optarg, "rw") == 0)
1143 X fprintf(stderr, "Invalid mode: \"%s\"\n", optarg);
1148 X st_flag = DBM_REPLACE;
1167 X comarg[argn++] = optarg;
1169 X fprintf(stderr, "Too many arguments.\n");
1176 X if (giveusage | what == YOW | argn < 1) {
1177 X fprintf(stderr, "Usage: %s databse [-m r|w|rw] [-crtx] -a|-d|-f|-F|-s [key [content]]\n", argv[0]);
1181 X if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) {
1182 X fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]);
1187 X key = read_datum(comarg[1]);
1189 X content = read_datum(comarg[2]);
1194 X key = dbm_firstkey(db);
1195 X if (dbm_error(db)) {
1196 X fprintf(stderr, "Error when fetching first key\n");
1199 X while (key.dptr != NULL) {
1200 X content = dbm_fetch(db, key);
1201 X if (dbm_error(db)) {
1202 X fprintf(stderr, "Error when fetching ");
1209 X print_datum(content);
1211 X if (dbm_error(db)) {
1212 X fprintf(stderr, "Error when fetching next key\n");
1215 X key = dbm_nextkey(db);
1221 X fprintf(stderr, "Missing regular expression.\n");
1224 X if (re_comp(comarg[1])) {
1225 X fprintf(stderr, "Invalid regular expression\n");
1228 X key = dbm_firstkey(db);
1229 X if (dbm_error(db)) {
1230 X fprintf(stderr, "Error when fetching first key\n");
1233 X while (key.dptr != NULL) {
1234 X if (re_exec(key2s(key))) {
1235 X content = dbm_fetch(db, key);
1236 X if (dbm_error(db)) {
1237 X fprintf(stderr, "Error when fetching ");
1244 X print_datum(content);
1246 X if (dbm_error(db)) {
1247 X fprintf(stderr, "Error when fetching next key\n");
1251 X key = dbm_nextkey(db);
1257 X fprintf(stderr, "Missing fetch key.\n");
1260 X content = dbm_fetch(db, key);
1261 X if (dbm_error(db)) {
1262 X fprintf(stderr, "Error when fetching ");
1267 X if (content.dptr == NULL) {
1268 X fprintf(stderr, "Cannot find ");
1275 X print_datum(content);
1281 X fprintf(stderr, "Missing delete key.\n");
1284 X if (dbm_delete(db, key) || dbm_error(db)) {
1285 X fprintf(stderr, "Error when deleting ");
1292 X printf(": DELETED\n");
1298 X fprintf(stderr, "Missing key and/or content.\n");
1301 X if (dbm_store(db, key, content, st_flag) || dbm_error(db)) {
1302 X fprintf(stderr, "Error when storing ");
1310 X print_datum(content);
1311 X printf(" STORED\n");
1319 X if (dbm_error(db)) {
1320 X fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]);
1325 if test 9799 -ne `wc -c <'dbe.c'`; then
1326 echo shar: \"'dbe.c'\" unpacked with wrong size!
1330 if test -f 'dbm.c' -a "${1}" != "-c" ; then
1331 echo shar: Will not clobber existing file \"'dbm.c'\"
1333 echo shar: Extracting \"'dbm.c'\" \(2426 characters\)
1334 sed "s/^X//" >'dbm.c' <<'END_OF_FILE'
1336 X * Copyright (c) 1985 The Regents of the University of California.
1337 X * All rights reserved.
1339 X * Redistribution and use in source and binary forms are permitted
1340 X * provided that the above copyright notice and this paragraph are
1341 X * duplicated in all such forms and that any documentation,
1342 X * advertising materials, and other materials related to such
1343 X * distribution and use acknowledge that the software was developed
1344 X * by the University of California, Berkeley. The name of the
1345 X * University may not be used to endorse or promote products derived
1346 X * from this software without specific prior written permission.
1347 X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1348 X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1349 X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1353 Xstatic char sccsid[] = "@(#)dbm.c 5.4 (Berkeley) 5/24/89";
1354 X#endif /* not lint */
1358 X#define NODB ((DBM *)0)
1360 Xstatic DBM *cur_db = NODB;
1362 Xstatic char no_db[] = "dbm: no open database\n";
1367 X if (cur_db != NODB)
1368 X dbm_close(cur_db);
1370 X cur_db = dbm_open(file, 2, 0);
1371 X if (cur_db == NODB) {
1372 X cur_db = dbm_open(file, 0, 0);
1373 X if (cur_db == NODB)
1383 X if (cur_db == NODB) {
1387 X return (dbm_forder(cur_db, key));
1396 X if (cur_db == NODB) {
1401 X return (dbm_fetch(cur_db, key));
1407 X if (cur_db == NODB) {
1411 X if (dbm_rdonly(cur_db))
1413 X return (dbm_delete(cur_db, key));
1419 X if (cur_db == NODB) {
1423 X if (dbm_rdonly(cur_db))
1426 X return (dbm_store(cur_db, key, dat, DBM_REPLACE));
1434 X if (cur_db == NODB) {
1439 X return (dbm_firstkey(cur_db));
1448 X if (cur_db == NODB) {
1453 X return (dbm_nextkey(cur_db, key));
1456 if test 2426 -ne `wc -c <'dbm.c'`; then
1457 echo shar: \"'dbm.c'\" unpacked with wrong size!
1461 if test -f 'dbm.h' -a "${1}" != "-c" ; then
1462 echo shar: Will not clobber existing file \"'dbm.h'\"
1464 echo shar: Extracting \"'dbm.h'\" \(1186 characters\)
1465 sed "s/^X//" >'dbm.h' <<'END_OF_FILE'
1467 X * Copyright (c) 1983 The Regents of the University of California.
1468 X * All rights reserved.
1470 X * Redistribution and use in source and binary forms are permitted
1471 X * provided that the above copyright notice and this paragraph are
1472 X * duplicated in all such forms and that any documentation,
1473 X * advertising materials, and other materials related to such
1474 X * distribution and use acknowledge that the software was developed
1475 X * by the University of California, Berkeley. The name of the
1476 X * University may not be used to endorse or promote products derived
1477 X * from this software without specific prior written permission.
1478 X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1479 X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1480 X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1482 X * @(#)dbm.h 5.2 (Berkeley) 5/24/89
1487 X * this is lunacy, we no longer use it (and never should have
1488 X * unconditionally defined it), but, this whole file is for
1489 X * backwards compatability - someone may rely on this.
1491 X#define NULL ((char *) 0)
1500 if test 1186 -ne `wc -c <'dbm.h'`; then
1501 echo shar: \"'dbm.h'\" unpacked with wrong size!
1505 if test -f 'dbu.c' -a "${1}" != "-c" ; then
1506 echo shar: Will not clobber existing file \"'dbu.c'\"
1508 echo shar: Extracting \"'dbu.c'\" \(4408 characters\)
1509 sed "s/^X//" >'dbu.c' <<'END_OF_FILE'
1511 X#include <sys/file.h>
1517 X#include <string.h>
1520 X#define strchr index
1523 Xextern int getopt();
1524 Xextern char *strchr();
1525 Xextern void oops();
1530 Xstatic char *usage = "%s [-R] cat | look |... dbmname";
1541 X#define LINEMAX 8192
1549 Xstatic cmd cmds[] = {
1551 X "fetch", DLOOK, O_RDONLY,
1552 X "get", DLOOK, O_RDONLY,
1553 X "look", DLOOK, O_RDONLY,
1554 X "add", DINSERT, O_RDWR,
1555 X "insert", DINSERT, O_RDWR,
1556 X "store", DINSERT, O_RDWR,
1557 X "delete", DDELETE, O_RDWR,
1558 X "remove", DDELETE, O_RDWR,
1559 X "dump", DCAT, O_RDONLY,
1560 X "list", DCAT, O_RDONLY,
1561 X "cat", DCAT, O_RDONLY,
1562 X "creat", DCREAT, O_RDWR | O_CREAT | O_TRUNC,
1563 X "new", DCREAT, O_RDWR | O_CREAT | O_TRUNC,
1564 X "build", DBUILD, O_RDWR | O_CREAT,
1565 X "squash", DPRESS, O_RDWR,
1566 X "compact", DPRESS, O_RDWR,
1567 X "compress", DPRESS, O_RDWR
1570 X#define CTABSIZ (sizeof (cmds)/sizeof (cmd))
1572 Xstatic cmd *parse();
1573 Xstatic void badk(), doit(), prdatum();
1581 X register cmd *act;
1582 X extern int optind;
1583 X extern char *optarg;
1585 X progname = argv[0];
1587 X while ((c = getopt(argc, argv, "R")) != EOF)
1589 X case 'R': /* raw processing */
1594 X oops("usage: %s", usage);
1598 X if ((argc -= optind) < 2)
1599 X oops("usage: %s", usage);
1601 X if ((act = parse(argv[optind])) == NULL)
1602 X badk(argv[optind]);
1604 X doit(act, argv[optind]);
1616 X register char *op;
1621 X extern long time();
1624 X if ((db = dbm_open(file, act->flags, 0644)) == NULL)
1625 X oops("cannot open: %s", file);
1627 X if ((line = (char *) malloc(LINEMAX)) == NULL)
1628 X oops("%s: cannot get memory", "line alloc");
1630 X switch (act->scode) {
1633 X while (fgets(line, LINEMAX, stdin) != NULL) {
1634 X n = strlen(line) - 1;
1638 X val = dbm_fetch(db, key);
1639 X if (val.dptr != NULL) {
1640 X prdatum(stdout, val);
1644 X prdatum(stderr, key);
1645 X fprintf(stderr, ": not found.\n");
1651 X while (fgets(line, LINEMAX, stdin) != NULL) {
1652 X n = strlen(line) - 1;
1656 X if (dbm_delete(db, key) == -1) {
1657 X prdatum(stderr, key);
1658 X fprintf(stderr, ": not found.\n");
1663 X for (key = dbm_firstkey(db); key.dptr != 0;
1664 X key = dbm_nextkey(db)) {
1665 X prdatum(stdout, key);
1667 X prdatum(stdout, dbm_fetch(db, key));
1675 X while (fgets(line, LINEMAX, stdin) != NULL) {
1676 X n = strlen(line) - 1;
1679 X if ((op = strchr(line, '\t')) != 0) {
1680 X key.dsize = op - line;
1683 X val.dsize = line + n - op;
1686 X oops("bad input; %s", line);
1688 X if (dbm_store(db, key, val, DBM_REPLACE) < 0) {
1689 X prdatum(stderr, key);
1690 X fprintf(stderr, ": ");
1691 X oops("store: %s", "failed");
1695 X printf("done: %d seconds.\n", time(0) - start);
1714 X fprintf(stderr, "%s: ", progname);
1715 X fprintf(stderr, "bad keywd %s. use one of\n", word);
1716 X for (i = 0; i < (int)CTABSIZ; i++)
1717 X fprintf(stderr, "%-8s%c", cmds[i].sname,
1718 X ((i + 1) % 6 == 0) ? '\n' : ' ');
1719 X fprintf(stderr, "\n");
1726 Xregister char *str;
1728 X register int i = CTABSIZ;
1731 X for (p = cmds; i--; p++)
1732 X if (strcmp(p->sname, str) == 0)
1743 X register char *p = d.dptr;
1744 X register int n = d.dsize;
1749 X fprintf(stream, "M-");
1752 X if (c == 0177 || c < ' ')
1753 X fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
1761 if test 4408 -ne `wc -c <'dbu.c'`; then
1762 echo shar: \"'dbu.c'\" unpacked with wrong size!
1766 if test -f 'grind' -a "${1}" != "-c" ; then
1767 echo shar: Will not clobber existing file \"'grind'\"
1769 echo shar: Extracting \"'grind'\" \(201 characters\)
1770 sed "s/^X//" >'grind' <<'END_OF_FILE'
1772 Xrm -f /tmp/*.dir /tmp/*.pag
1775 X for (i = 0; i < 40; i++)
1778 X}' < /usr/dict/words | $1 build /tmp/$2
1781 if test 201 -ne `wc -c <'grind'`; then
1782 echo shar: \"'grind'\" unpacked with wrong size!
1787 if test -f 'hash.c' -a "${1}" != "-c" ; then
1788 echo shar: Will not clobber existing file \"'hash.c'\"
1790 echo shar: Extracting \"'hash.c'\" \(922 characters\)
1791 sed "s/^X//" >'hash.c' <<'END_OF_FILE'
1793 X * sdbm - ndbm work-alike hashed database library
1794 X * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
1795 X * author: oz@nexus.yorku.ca
1796 X * status: public domain. keep it that way.
1803 X * polynomial conversion ignoring overflows
1804 X * [this seems to work remarkably well, in fact better
1805 X * then the ndbm hash function. Replace at your own risk]
1806 X * use: 65599 nice.
1807 X * 65587 even better.
1811 Xregister char *str;
1814 X register unsigned long n = 0;
1818 X#define HASHC n = *str++ + 65599 * n
1821 X register int loop = (len + 8 - 1) >> 3;
1823 X switch(len & (8 - 1)) {
1825 X HASHC; case 7: HASHC;
1826 X case 6: HASHC; case 5: HASHC;
1827 X case 4: HASHC; case 3: HASHC;
1828 X case 2: HASHC; case 1: HASHC;
1835 X n = *str++ + 65599 * n;
1840 if test 922 -ne `wc -c <'hash.c'`; then
1841 echo shar: \"'hash.c'\" unpacked with wrong size!
1845 if test -f 'makefile' -a "${1}" != "-c" ; then
1846 echo shar: Will not clobber existing file \"'makefile'\"
1848 echo shar: Extracting \"'makefile'\" \(1147 characters\)
1849 sed "s/^X//" >'makefile' <<'END_OF_FILE'
1851 X# makefile for public domain ndbm-clone: sdbm
1852 X# DUFF: use duff's device (loop unroll) in parts of the code
1854 XCFLAGS = -O -DSDBM -DDUFF -DBSD42
1857 XOBJS = sdbm.o pair.o hash.o
1858 XSRCS = sdbm.c pair.c hash.c dbu.c dba.c dbd.c util.c
1859 XHDRS = tune.h sdbm.h pair.h
1860 XMISC = README CHANGES COMPARE sdbm.3 dbe.c dbe.1 dbm.c dbm.h biblio \
1861 X readme.ms readme.ps
1863 Xall: dbu dba dbd dbe
1865 Xdbu: dbu.o sdbm util.o
1866 X cc $(LDFLAGS) -o dbu dbu.o util.o libsdbm.a
1869 X cc $(LDFLAGS) -o dba dba.o util.o
1871 X cc $(LDFLAGS) -o dbd dbd.o util.o
1873 X cc $(LDFLAGS) -o dbe dbe.o libsdbm.a
1876 X ar cr libsdbm.a $(OBJS)
1878 X### cp libsdbm.a /usr/lib/libsdbm.a
1884 X$(OBJS): sdbm.h tune.h pair.h
1887 X# dbu using berkelezoid ndbm routines [if you have them] for testing
1889 X#x-dbu: dbu.o util.o
1890 X# cc $(CFLAGS) -o x-dbu dbu.o util.o
1892 X lint -abchx $(SRCS)
1895 X rm -f *.o mon.out core
1898 X rm -f dbu libsdbm.a dbd dba dbe x-dbu *.dir *.pag
1901 X shar $(MISC) makefile $(SRCS) $(HDRS) >SDBM.SHAR
1904 X nroff -ms readme.ms | col -b >README
1906 if test 1147 -ne `wc -c <'makefile'`; then
1907 echo shar: \"'makefile'\" unpacked with wrong size!
1911 if test -f 'pair.c' -a "${1}" != "-c" ; then
1912 echo shar: Will not clobber existing file \"'pair.c'\"
1914 echo shar: Extracting \"'pair.c'\" \(5720 characters\)
1915 sed "s/^X//" >'pair.c' <<'END_OF_FILE'
1917 X * sdbm - ndbm work-alike hashed database library
1918 X * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
1919 X * author: oz@nexus.yorku.ca
1920 X * status: public domain.
1922 X * page-level routines
1926 Xstatic char rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";
1934 X#include <memory.h>
1937 X#define exhash(item) dbm_hash((item).dptr, (item).dsize)
1942 Xstatic int seepair proto((char *, int, char *, int));
1946 X * +------------------------------+
1947 X * ino | n | keyoff | datoff | keyoff |
1948 X * +------------+--------+--------+
1949 X * | datoff | - - - ----> |
1950 X * +--------+---------------------+
1951 X * | F R E E A R E A |
1952 X * +--------------+---------------+
1953 X * | <---- - - - | data |
1954 X * +--------+-----+----+----------+
1955 X * | key | data | key |
1956 X * +--------+----------+----------+
1958 X * calculating the offsets for free area: if the number
1959 X * of entries (ino[0]) is zero, the offset to the END of
1960 X * the free area is the block size. Otherwise, it is the
1961 X * nth (ino[ino[0]]) entry's offset.
1971 X register int free;
1972 X register short *ino = (short *) pag;
1974 X off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
1975 X free = off - (n + 1) * sizeof(short);
1976 X need += 2 * sizeof(short);
1978 X debug(("free %d need %d\n", free, need));
1980 X return need <= free;
1984 Xputpair(pag, key, val)
1991 X register short *ino = (short *) pag;
1993 X off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
1995 X * enter the key first
1998 X (void) memcpy(pag + off, key.dptr, key.dsize);
2004 X (void) memcpy(pag + off, val.dptr, val.dsize);
2007 X * adjust item count
2020 X register short *ino = (short *) pag;
2022 X if ((n = ino[0]) == 0)
2025 X if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
2028 X val.dptr = pag + ino[i + 1];
2029 X val.dsize = ino[i] - ino[i + 1];
2039 X register short *ino = (short *) pag;
2040 X return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
2051 X register short *ino = (short *) pag;
2053 X num = num * 2 - 1;
2054 X if (ino[0] == 0 || num > ino[0])
2057 X off = (num > 1) ? ino[num - 1] : PBLKSIZ;
2059 X key.dptr = pag + ino[num];
2060 X key.dsize = off - ino[num];
2072 X register short *ino = (short *) pag;
2074 X if ((n = ino[0]) == 0)
2077 X if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
2080 X * found the key. if it is the last entry
2081 X * [i.e. i == n - 1] we just adjust the entry count.
2082 X * hard case: move all data down onto the deleted pair,
2083 X * shift offsets onto deleted offsets, and adjust them.
2084 X * [note: 0 < i < n]
2088 X register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
2089 X register char *src = pag + ino[i + 1];
2090 X register int zoo = dst - src;
2092 X debug(("free-up %d ", zoo));
2094 X * shift data/keys down
2096 X m = ino[i + 1] - ino[n];
2098 X#define MOVB *--dst = *--src
2101 X register int loop = (m + 8 - 1) >> 3;
2103 X switch (m & (8 - 1)) {
2105 X MOVB; case 7: MOVB;
2106 X case 6: MOVB; case 5: MOVB;
2107 X case 4: MOVB; case 3: MOVB;
2108 X case 2: MOVB; case 1: MOVB;
2114 X memmove(dst, src, m);
2121 X * adjust offset index up
2123 X while (i < n - 1) {
2124 X ino[i] = ino[i + 2] + zoo;
2133 X * search for the key in the page.
2134 X * return offset index in the range 0 < i < n.
2135 X * return 0 if not found.
2138 Xseepair(pag, n, key, siz)
2141 Xregister char *key;
2145 X register int off = PBLKSIZ;
2146 X register short *ino = (short *) pag;
2148 X for (i = 1; i < n; i += 2) {
2149 X if (siz == off - ino[i] &&
2150 X memcmp(key, pag + ino[i], siz) == 0)
2158 Xsplpage(pag, new, sbit)
2167 X register int off = PBLKSIZ;
2168 X char cur[PBLKSIZ];
2169 X register short *ino = (short *) cur;
2171 X (void) memcpy(cur, pag, PBLKSIZ);
2172 X (void) memset(pag, 0, PBLKSIZ);
2173 X (void) memset(new, 0, PBLKSIZ);
2176 X for (ino++; n > 0; ino += 2) {
2177 X key.dptr = cur + ino[0];
2178 X key.dsize = off - ino[0];
2179 X val.dptr = cur + ino[1];
2180 X val.dsize = ino[0] - ino[1];
2182 X * select the page pointer (by looking at sbit) and insert
2184 X (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
2190 X debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
2191 X ((short *) new)[0] / 2,
2192 X ((short *) pag)[0] / 2));
2196 X * check page sanity:
2197 X * number of entries should be something
2198 X * reasonable, and all offsets in the index should be in order.
2199 X * this could be made more rigorous.
2207 X register short *ino = (short *) pag;
2209 X if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
2214 X for (ino++; n > 0; ino += 2) {
2215 X if (ino[0] > off || ino[1] > off ||
2225 if test 5720 -ne `wc -c <'pair.c'`; then
2226 echo shar: \"'pair.c'\" unpacked with wrong size!
2230 if test -f 'pair.h' -a "${1}" != "-c" ; then
2231 echo shar: Will not clobber existing file \"'pair.h'\"
2233 echo shar: Extracting \"'pair.h'\" \(378 characters\)
2234 sed "s/^X//" >'pair.h' <<'END_OF_FILE'
2235 Xextern int fitpair proto((char *, int));
2236 Xextern void putpair proto((char *, datum, datum));
2237 Xextern datum getpair proto((char *, datum));
2238 Xextern int delpair proto((char *, datum));
2239 Xextern int chkpage proto((char *));
2240 Xextern datum getnkey proto((char *, int));
2241 Xextern void splpage proto((char *, char *, long));
2243 Xextern int duppair proto((char *, datum));
2246 if test 378 -ne `wc -c <'pair.h'`; then
2247 echo shar: \"'pair.h'\" unpacked with wrong size!
2251 if test -f 'readme.ms' -a "${1}" != "-c" ; then
2252 echo shar: Will not clobber existing file \"'readme.ms'\"
2254 echo shar: Extracting \"'readme.ms'\" \(11691 characters\)
2255 sed "s/^X//" >'readme.ms' <<'END_OF_FILE'
2256 X.\" tbl | readme.ms | [tn]roff -ms | ...
2257 X.\" note the "C" (courier) and "CB" fonts: you will probably have to
2259 X.\" $Id: readme.ms,v 1.1 90/12/13 13:09:15 oz Exp Locker: oz $
2267 X.nr t \\n(dT*\\w'x'u
2268 X.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
2278 X.\" CW uses the typewriter/courier font.
2283 X.\" Footnote numbering [by Henry Spencer]
2284 X.\" <text>\*f for a footnote number..
2286 X.\" \*F <footnote text>
2289 X.ds f \\u\\s-2\\n+f\\s+2\\d
2297 X\fIsdbm\fP \(em Substitute DBM
2301 XBerkeley \fIndbm\fP for Every UN*X\** Made Simple
2305 XThe Guild of PD Software Toolmakers
2311 XUN*X is not a trademark of any (dis)organization.
2314 X\fIImplementation is the sincerest form of flattery. \(em L. Peter Deutsch\fP
2316 XA The Clone of the \fIndbm\fP library
2318 XThe sources accompanying this notice \(em \fIsdbm\fP \(em constitute
2319 Xthe first public release (Dec. 1990) of a complete clone of
2320 Xthe Berkeley UN*X \fIndbm\fP library. The \fIsdbm\fP library is meant to
2321 Xclone the proven functionality of \fIndbm\fP as closely as possible,
2322 Xincluding a few improvements. It is practical, easy to understand, and
2324 XThe \fIsdbm\fP library is not derived from any licensed, proprietary or
2325 Xcopyrighted software.
2327 XThe \fIsdbm\fP implementation is based on a 1978 algorithm
2328 X[Lar78] by P.-A. (Paul) Larson known as ``Dynamic Hashing''.
2329 XIn the course of searching for a substitute for \fIndbm\fP, I
2330 Xprototyped three different external-hashing algorithms [Lar78, Fag79, Lit80]
2331 Xand ultimately chose Larson's algorithm as a basis of the \fIsdbm\fP
2332 Ximplementation. The Bell Labs
2333 X\fIdbm\fP (and therefore \fIndbm\fP) is based on an algorithm invented by
2334 XKen Thompson, [Tho90, Tor87] and predates Larson's work.
2336 XThe \fIsdbm\fR programming interface is totally compatible
2337 Xwith \fIndbm\fP and includes a slight improvement in database initialization.
2338 XIt is also expected to be binary-compatible under most UN*X versions that
2339 Xsupport the \fIndbm\fP library.
2341 XThe \fIsdbm\fP implementation shares the shortcomings of the \fIndbm\fP
2342 Xlibrary, as a side effect of various simplifications to the original Larson
2343 Xalgorithm. It does produce \fIholes\fP in the page file as it writes
2344 Xpages past the end of file. (Larson's paper include a clever solution to
2345 Xthis problem that is a result of using the hash value directly as a block
2346 Xaddress.) On the other hand, extensive tests seem to indicate that \fIsdbm\fP
2347 Xcreates fewer holes in general, and the resulting pagefiles are
2348 Xsmaller. The \fIsdbm\fP implementation is also faster than \fIndbm\fP
2349 Xin database creation.
2350 XUnlike the \fIndbm\fP, the \fIsdbm\fP
2352 Xoperation will not ``wander away'' trying to split its
2353 Xdata pages to insert a datum that \fIcannot\fP (due to elaborate worst-case
2354 Xsituations) be inserted. (It will fail after a pre-defined number of attempts.)
2356 XImportant Compatibility Warning
2358 XThe \fIsdbm\fP and \fIndbm\fP
2359 Xlibraries \fIcannot\fP share databases: one cannot read the (dir/pag)
2360 Xdatabase created by the other. This is due to the differences
2361 Xbetween the \fIndbm\fP and \fIsdbm\fP algorithms\**,
2363 XTorek's discussion [Tor87]
2364 Xindicates that \fIdbm/ndbm\fP implementations use the hash
2365 Xvalue to traverse the radix trie differently than \fIsdbm\fP
2366 Xand as a result, the page indexes are generated in \fIdifferent\fP order.
2367 XFor more information, send e-mail to the author.
2369 Xand the hash functions
2371 XIt is easy to convert between the \fIdbm/ndbm\fP databases and \fIsdbm\fP
2372 Xby ignoring the index completely: see
2379 XNotice of Intellectual Property
2381 X\fIThe entire\fP sdbm \fIlibrary package, as authored by me,\fP Ozan S. Yigit,
2382 X\fIis hereby placed in the public domain.\fP As such, the author is not
2383 Xresponsible for the consequences of use of this software, no matter how
2384 Xawful, even if they arise from defects in it. There is no expressed or
2385 Ximplied warranty for the \fIsdbm\fP library.
2387 XSince the \fIsdbm\fP
2388 Xlibrary package is in the public domain, this \fIoriginal\fP
2389 Xrelease or any additional public-domain releases of the modified original
2390 Xcannot possibly (by definition) be withheld from you. Also by definition,
2391 XYou (singular) have all the rights to this code (including the right to
2392 Xsell without permission, the right to hoard\**
2394 XYou cannot really hoard something that is available to the public at
2395 Xlarge, but try if it makes you feel any better.
2397 Xand the right to do other icky things as
2398 Xyou see fit) but those rights are also granted to everyone else.
2400 XPlease note that all previous distributions of this software contained
2401 Xa copyright (which is now dropped) to protect its
2402 Xorigins and its current public domain status against any possible claims
2407 XMany people have been very helpful and supportive. A partial list would
2408 Xnecessarily include Rayan Zacherissen (who contributed the man page,
2409 Xand also hacked a MMAP version of \fIsdbm\fP),
2410 XArnold Robbins, Chris Lewis,
2411 XBill Davidsen, Henry Spencer, Geoff Collyer, Rich Salz (who got me started
2412 Xin the first place), Johannes Ruschein
2413 X(who did the minix port) and David Tilbrook. I thank you all.
2415 XDistribution Manifest and Notes
2417 XThis distribution of \fIsdbm\fP includes (at least) the following:
2419 X CHANGES change log
2421 X biblio a small bibliography on external hashing
2422 X dba.c a crude (n/s)dbm page file analyzer
2423 X dbd.c a crude (n/s)dbm page file dumper (for conversion)
2424 X dbe.1 man page for dbe.c
2425 X dbe.c Janick's database editor
2426 X dbm.c a dbm library emulation wrapper for ndbm/sdbm
2427 X dbm.h header file for the above
2428 X dbu.c a crude db management utility
2429 X hash.c hashing function
2431 X pair.c page-level routines (posted earlier)
2432 X pair.h header file for the above
2433 X readme.ms troff source for the README file
2435 X sdbm.c the real thing
2436 X sdbm.h header file for the above
2437 X tune.h place for tuning & portability thingies
2438 X util.c miscellaneous
2442 Xis a simple database manipulation program\** that tries to look
2448 Xutilities are quick hacks and are not fit for production use. They were
2449 Xdeveloped late one night, just to test out \fIsdbm\fP, and convert some
2454 Xutility. It is currently incomplete in functionality.
2457 Xto test out the routines: it takes (from stdin) tab separated
2458 Xkey/value pairs for commands like
2468 X dbu <build|creat|look|insert|cat|delete> dbmfile
2472 Xis a crude analyzer of \fIdbm/sdbm/ndbm\fP
2473 Xpage files. It scans the entire
2474 Xpage file, reporting page level statistics, and totals at the end.
2477 Xis a crude dump program for \fIdbm/ndbm/sdbm\fP
2478 Xdatabases. It ignores the
2479 Xbitmap, and dumps the data pages in sequence. It can be used to create
2485 Xwill skip any NULLs in the key and data
2486 Xfields, thus is unsuitable to convert some peculiar databases that
2487 Xinsist in including the terminating null.
2489 XI have also included a copy of the
2491 X(\fIndbm\fP DataBase Editor) by Janick Bergeron [janick@bnr.ca] for
2492 Xyour pleasure. You may find it more useful than the little
2497 Xis a \fIdbm\fP library emulation on top of \fIndbm\fP
2498 X(and hence suitable for \fIsdbm\fP). Written by Robert Elz.
2501 Xlibrary has been around in beta test for quite a long time, and from whatever
2502 Xlittle feedback I received (maybe no news is good news), I believe it has been
2503 Xfunctioning without any significant problems. I would, of course, appreciate
2504 Xall fixes and/or improvements. Portability enhancements would especially be
2507 XImplementation Issues
2510 XThe algorithm behind \fIsdbm\fP implementation needs a good bit-scrambling
2511 Xhash function to be effective. I ran into a set of constants for a simple
2512 Xhash function that seem to help \fIsdbm\fP perform better than \fIndbm\fP
2513 Xfor various inputs:
2516 X * polynomial conversion ignoring overflows
2517 X * 65599 nice. 65587 even better.
2520 X dbm_hash(char *str, int len) {
2521 X register unsigned long n = 0;
2524 X n = n * 65599 + *str++;
2529 XThere may be better hash functions for the purposes of dynamic hashing.
2530 XTry your favorite, and check the pagefile. If it contains too many pages
2531 Xwith too many holes, (in relation to this one for example) or if
2533 Xsimply stops working (fails after
2535 Xattempts to split) when you feed your
2538 Xfile to it, you probably do not have a good hashing function.
2539 XIf you do better (for different types of input), I would like to know
2540 Xabout the function you use.
2542 XBlock sizes: It seems (from various tests on a few machines) that a page
2545 Xof 1024 is by far the best for performance, but
2546 Xthis also happens to limit the size of a key/value pair. Depending on your
2547 Xneeds, you may wish to increase the page size, and also adjust
2549 X(the maximum size of a key/value pair allowed: should always be at least
2550 Xthree words smaller than
2552 Xaccordingly. The system-wide version of the library
2554 Xconfigured with 1024 (distribution default), as this appears to be sufficient
2555 Xfor most common uses of \fIsdbm\fP.
2559 XThis package has been tested in many different UN*Xes even including minix,
2560 Xand appears to be reasonably portable. This does not mean it will port
2561 Xeasily to non-UN*X systems.
2563 XNotes and Miscellaneous
2565 XThe \fIsdbm\fP is not a very complicated package, at least not after you
2566 Xfamiliarize yourself with the literature on external hashing. There are
2567 Xother interesting algorithms in existence that ensure (approximately)
2568 Xsingle-read access to a data value associated with any key. These are
2569 Xdirectory-less schemes such as \fIlinear hashing\fP [Lit80] (+ Larson
2570 Xvariations), \fIspiral storage\fP [Mar79] or directory schemes such as
2571 X\fIextensible hashing\fP [Fag79] by Fagin et al. I do hope these sources
2572 Xprovide a reasonable playground for experimentation with other algorithms.
2573 XSee the June 1988 issue of ACM Computing Surveys [Enb88] for an
2574 Xexcellent overview of the field.
2581 X``Dynamic Hashing'', \fIBIT\fP, vol. 18, pp. 184-201, 1978.
2583 XKen Thompson, \fIprivate communication\fP, Nov. 1990
2586 X`` Linear Hashing: A new tool for file and table addressing'',
2587 X\fIProceedings of the 6th Conference on Very Large Dabatases (Montreal)\fP,
2588 Xpp. 212-223, Very Large Database Foundation, Saratoga, Calif., 1980.
2590 XR. Fagin, J. Nievergelt, N. Pippinger, and H. R. Strong,
2591 X``Extendible Hashing - A Fast Access Method for Dynamic Files'',
2592 X\fIACM Trans. Database Syst.\fP, vol. 4, no.3, pp. 315-344, Sept. 1979.
2595 X``Discussion of "dbm" data base system'', \fIUSENET newsgroup unix.wizards\fP,
2599 X``Re: dbm.a and ndbm.a archives'', \fIUSENET newsgroup comp.unix\fP,
2603 X``Spiral Storage: Incrementally Augmentable Hash Addressed Storage'',
2604 X\fITechnical Report #27\fP, University of Varwick, Coventry, U.K., 1979.
2606 XR. J. Enbody and H. C. Du,
2607 X``Dynamic Hashing Schemes'',\fIACM Computing Surveys\fP,
2608 Xvol. 20, no. 2, pp. 85-113, June 1988.
2610 if test 11691 -ne `wc -c <'readme.ms'`; then
2611 echo shar: \"'readme.ms'\" unpacked with wrong size!
2613 # end of 'readme.ms'
2615 if test -f 'readme.ps' -a "${1}" != "-c" ; then
2616 echo shar: Will not clobber existing file \"'readme.ps'\"
2618 echo shar: Extracting \"'readme.ps'\" \(33302 characters\)
2619 sed "s/^X//" >'readme.ps' <<'END_OF_FILE'
2621 X%%Creator: yetti:oz (Ozan Yigit)
2622 X%%Title: stdin (ditroff)
2623 X%%CreationDate: Thu Dec 13 15:56:08 1990
2625 X% lib/psdit.pro -- prolog for psdit (ditroff) files
2626 X% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
2627 X% last edit: shore Sat Nov 23 20:28:03 1985
2628 X% RCSID: $Header: psdit.pro,v 2.1 85/11/24 12:19:43 shore Rel $
2630 X/$DITroff 140 dict def $DITroff begin
2631 X/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
2632 X/xi {0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
2633 X /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F
2634 X /pagesave save def}def
2635 X/PB{save /psv exch def currentpoint translate
2636 X resolution 72 div dup neg scale 0 0 moveto}def
2637 X/PE{psv restore}def
2638 X/arctoobig 90 def /arctoosmall .05 def
2639 X/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
2640 X/tan{dup sin exch cos div}def
2641 X/point{resolution 72 div mul}def
2642 X/dround {transform round exch round exch itransform}def
2643 X/xT{/devname exch def}def
2644 X/xr{/mh exch def /my exch def /resolution exch def}def
2646 X/xs{docsave restore end}def
2648 X/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
2649 X {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
2650 X/xH{/fontheight exch def F}def
2651 X/xS{/fontslant exch def F}def
2652 X/s{/fontsize exch def /fontheight fontsize def F}def
2653 X/f{/fontnum exch def F}def
2654 X/F{fontheight 0 le {/fontheight fontsize def}if
2655 X fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
2656 X fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
2657 X makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
2658 X/X{exch currentpoint exch pop moveto show}def
2659 X/N{3 1 roll moveto show}def
2660 X/Y{exch currentpoint pop exch moveto show}def
2662 X/ditpush{}def/ditpop{}def
2663 X/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
2664 X/AN{4 2 roll moveto 0 exch ashow}def
2665 X/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
2666 X/AS{0 exch ashow}def
2667 X/MX{currentpoint exch pop moveto}def
2668 X/MY{currentpoint pop exch moveto}def
2670 X/cb{pop}def % action on unknown char -- nothing for now
2672 X/p{pop showpage pagesave restore /pagesave save def}def
2673 X/abspoint{currentpoint exch pop add exch currentpoint pop add exch}def
2674 X/distance{dup mul exch dup mul add sqrt}def
2675 X/dstroke{currentpoint stroke moveto}def
2676 X/Dl{2 copy gsave rlineto stroke grestore rmoveto}def
2677 X/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
2678 X currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
2679 X currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
2680 X/Dc{dup arcellipse dstroke}def
2681 X/De{arcellipse dstroke}def
2682 X/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
2683 X /cradius centerv centerv mul centerh centerh mul add sqrt def
2684 X /eradius endv endv mul endh endh mul add sqrt def
2685 X /endang endv endh atan def
2686 X /startang centerv neg centerh neg atan def
2687 X /sweep startang endang sub dup 0 lt{360 add}if def
2688 X sweep arctoobig gt
2689 X {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
2690 X /midh midang cos midrad mul def /midv midang sin midrad mul def
2691 X midh neg midv neg endh endv centerh centerv midh midv Da
2692 X currentpoint moveto Da}
2693 X {sweep arctoosmall ge
2694 X {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
2695 X centerv neg controldelt mul centerh controldelt mul
2696 X endv neg controldelt mul centerh add endh add
2697 X endh controldelt mul centerv add endv add
2698 X centerh endh add centerv endv add rcurveto dstroke}
2699 X {centerh endh add centerv endv add rlineto dstroke}ifelse}ifelse}def
2701 X/Barray 200 array def % 200 values in a wiggle
2703 X/D~~{counttomark Barray exch 0 exch getinterval astore /Bcontrol exch def pop
2704 X /Blen Bcontrol length def Blen 4 ge Blen 2 mod 0 eq and
2705 X {Bcontrol 0 get Bcontrol 1 get abspoint /Ycont exch def /Xcont exch def
2706 X Bcontrol 0 2 copy get 2 mul put Bcontrol 1 2 copy get 2 mul put
2707 X Bcontrol Blen 2 sub 2 copy get 2 mul put
2708 X Bcontrol Blen 1 sub 2 copy get 2 mul put
2709 X /Ybi /Xbi currentpoint 3 1 roll def def 0 2 Blen 4 sub
2711 X Bcontrol i get 3 div Bcontrol i 1 add get 3 div
2712 X Bcontrol i get 3 mul Bcontrol i 2 add get add 6 div
2713 X Bcontrol i 1 add get 3 mul Bcontrol i 3 add get add 6 div
2714 X /Xbi Xcont Bcontrol i 2 add get 2 div add def
2715 X /Ybi Ycont Bcontrol i 3 add get 2 div add def
2716 X /Xcont Xcont Bcontrol i 2 add get add def
2717 X /Ycont Ycont Bcontrol i 3 add get add def
2718 X Xbi currentpoint pop sub Ybi currentpoint exch pop sub rcurveto
2719 X }for dstroke}if}def
2721 X/ditstart{$DITroff begin
2722 X /nfonts 60 def % NFONTS makedev/ditroff dependent!
2723 X /fonts[nfonts{0}repeat]def
2724 X /fontnames[nfonts{()}repeat]def
2728 X% character outcalls
2729 X/oc {/pswid exch def /cc exch def /name exch def
2730 X /ditwid pswid fontsize mul resolution mul 72000 div def
2731 X /ditsiz fontsize resolution mul 72 div def
2732 X ocprocs name known{ocprocs name get exec}{name cb}
2734 X/fractm [.65 0 0 .6 0 0] def
2736 X {/fden exch def /fnum exch def gsave /cf currentfont def
2737 X cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
2738 X fnum show rmoveto currentfont cf setfont(\244)show setfont fden show
2739 X grestore ditwid 0 rmoveto} def
2740 X/oce {grestore ditwid 0 rmoveto}def
2741 X/dm {ditsiz mul}def
2742 X/ocprocs 50 dict def ocprocs begin
2743 X(14){(1)(4)fraction}def
2744 X(12){(1)(2)fraction}def
2745 X(34){(3)(4)fraction}def
2746 X(13){(1)(3)fraction}def
2747 X(23){(2)(3)fraction}def
2748 X(18){(1)(8)fraction}def
2749 X(38){(3)(8)fraction}def
2750 X(58){(5)(8)fraction}def
2751 X(78){(7)(8)fraction}def
2752 X(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
2753 X(is){gsave 0 .15 dm rmoveto(\362)show oce}def
2754 X(->){gsave 0 .02 dm rmoveto(\256)show oce}def
2755 X(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
2756 X(==){gsave 0 .05 dm rmoveto(\272)show oce}def
2759 X% an attempt at a PostScript FONT to implement ditroff special chars
2760 X% this will enable us to
2761 X% cache the little buggers
2762 X% generate faster, more compact PS out of psdit
2763 X% confuse everyone (including myself)!
2766 X/FontName /DIThacks def
2767 X/FontMatrix [.001 0 0 .001 0 0] def
2768 X/FontBBox [-260 -260 900 900] def% a lie but ...
2769 X/Encoding 256 array def
2770 X0 1 255{Encoding exch /.notdef put}for
2772 X dup 8#040/space put %space
2773 X dup 8#110/rc put %right ceil
2774 X dup 8#111/lt put %left top curl
2775 X dup 8#112/bv put %bold vert
2776 X dup 8#113/lk put %left mid curl
2777 X dup 8#114/lb put %left bot curl
2778 X dup 8#115/rt put %right top curl
2779 X dup 8#116/rk put %right mid curl
2780 X dup 8#117/rb put %right bot curl
2781 X dup 8#120/rf put %right floor
2782 X dup 8#121/lf put %left floor
2783 X dup 8#122/lc put %left ceil
2784 X dup 8#140/sq put %square
2785 X dup 8#141/bx put %box
2786 X dup 8#142/ci put %circle
2787 X dup 8#143/br put %box rule
2788 X dup 8#144/rn put %root extender
2789 X dup 8#145/vr put %vertical rule
2790 X dup 8#146/ob put %outline bullet
2791 X dup 8#147/bu put %bullet
2792 X dup 8#150/ru put %rule
2793 X dup 8#151/ul put %underline
2795 X/DITfd 100 dict def
2797 X /cc exch def /fd exch def
2798 X /charname fd /Encoding get cc get def
2799 X /charwid fd /Metrics get charname get def
2800 X /charproc fd /CharProcs get charname get def
2801 X charwid 0 fd /FontBBox get aload pop setcachedevice
2802 X 2 setlinejoin 40 setlinewidth
2803 X newpath 0 0 moveto gsave charproc grestore
2805 X/BuildChar load 0 DITfd put
2807 X/CharProcs 50 dict def
2812 X/rn{0 840 moveto 500 0 rls}def
2813 X/vr{0 800 moveto 0 -770 rls}def
2814 X/bv{0 800 moveto 0 -1000 rls}def
2815 X/br{0 750 moveto 0 -1000 rls}def
2816 X/ul{0 -140 moveto 500 0 rls}def
2817 X/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
2818 X/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
2819 X/sq{80 0 rmoveto currentpoint dround newpath moveto
2820 X 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
2821 X/bx{80 0 rmoveto currentpoint dround newpath moveto
2822 X 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
2823 X/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
2824 X 50 setlinewidth stroke}def
2826 X/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
2827 X/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
2828 X/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
2829 X/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
2830 X/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
2831 X 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
2832 X/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
2833 X 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
2834 X/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
2835 X/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
2836 X/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
2837 X/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
2840 X/Metrics 50 dict def Metrics begin
2867 X/s2 500 def /s4 250 def /s3 333 def
2868 X/a4p{arcto pop pop pop pop}def
2869 X/2cx{2 copy exch}def
2870 X/rls{rlineto stroke}def
2871 X/currx{currentpoint pop}def
2872 X/dround{transform round exch round exch itransform} def
2875 X/DIThacks exch definefont pop
2879 X1(Times-Roman)xf 1 f
2880 X2(Times-Italic)xf 2 f
2881 X3(Times-Bold)xf 3 f
2882 X4(Times-BoldItalic)xf 4 f
2884 X6(Helvetica-Bold)xf 6 f
2886 X8(Courier-Bold)xf 8 f
2888 X10(DIThacks)xf 10 f
2905 X1331 864(Berkeley)N
2931 X2000 1296(Toronto)N
2934 X1965 1488(oz@nexus.yorku.ca)N
2936 X555 1804(Implementation)N
2960 X1167(accompanying)X
2977 X555 2216(complete)N
2999 X555 2312(tionality)N
3011 X2413(improvements.)X
3039 X1109(implementation)X
3053 X555 2628(``Dynamic)N
3072 X555 2724(external-hashing)N
3090 X875(implementation.)X
3138 X942(initialization.)X
3145 X2208(binary-compatible)X
3162 X1107(implementation)X
3165 X1995(shortcomings)X
3178 X555 3452(simpli\256cations)N
3254 X2922(implementation)X
3300 X3179(situations\))X
3308 X1050(pre-de\256ned)X
3313 X555 4220(Important)N
3314 X931(Compatibility)X
3434 X2060(consequences)X
3467 X555 5316(hhhhhhhhhhhhhhhhhh)N
3479 X1529(\(dis\)organization.)X
3491 X2061(implementations)X
3502 X555 5584(ferently)N
3523 X3021(information,)X
3557 X555 768(public-domain)N
3566 X2765(de\256nition\))X
3573 X659(de\256nition,)X
3575 X1170(\(singular\))X
3616 X555 1056(everyone)N
3623 X1759(distributions)X
3633 X555 1276(dropped\))N
3652 X555 1564(Acknowledgments)N
3669 X555 1784(Zacherissen)N
3705 X555 1976(place\),)N
3721 X555 2168(Distribution)N
3747 X1707(bibliography)X
3766 X3195(conversion\))X
3799 X747 3492(makefile)N
3812 X747 3780(readme.ms)N
3840 X1323(miscellaneous)X
3847 X1603(manipulation)X
3865 X555 4528(currently)N
3868 X1329(functionality.)X
3885 X555 4624(key/value)N
3913 X939(<build|creat|look|insert|cat|delete>)X
3923 X1675(dbm/sdbm/ndbm)X
3952 X1897(dbm/ndbm/sdbm)X
3989 X555 5432(hhhhhhhhhhhhhhhhhh)N
4111 X555 988([janick@bnr.ca])N
4129 X755 1112(dbm.[ch])N
4193 X3478(signi\256cant)X
4204 X2271(improvements.)X
4206 X3136(enhancements)X
4213 X555 1812(Implementation)N
4224 X2207(implementation)X
4228 X3181(bit-scrambling)X
4278 X747 2752(dbm_hash\(char)N
4283 X939 2848(register)N
4421 X1417(performance,)X
4474 X3612(accordingly.)X
4484 X2508(con\256gured)X
4487 X3229(\(distribution)X
4494 X1134(suf\256cient)X
4505 X555 4680(Portability)N
4540 X915(Miscellaneous)X
4561 X555 5312(literature)N
4575 X555 5408(mately\))N
4588 X3107(directory-less)X
4599 X1720(variations\),)X
4631 X555 5696(mentation)N
4647 X555 5792(excellent)N
4660 X555 672(References)N
4681 X1658(communication)X
4699 X2851(addressing'',)X
4705 X875 1168(Conference)N
4710 X2163(\(Montreal\))X
4734 X2797(``Extendible)X
4761 X1305(``Discussion)X
4770 X3430(unix.wizards)X
4796 X1885(Incrementally)X
4846 if test 33302 -ne `wc -c <'readme.ps'`; then
4847 echo shar: \"'readme.ps'\" unpacked with wrong size!
4849 # end of 'readme.ps'
4851 if test -f 'sdbm.3' -a "${1}" != "-c" ; then
4852 echo shar: Will not clobber existing file \"'sdbm.3'\"
4854 echo shar: Extracting \"'sdbm.3'\" \(8952 characters\)
4855 sed "s/^X//" >'sdbm.3' <<'END_OF_FILE'
4856 X.\" $Id: sdbm.3,v 1.2 90/12/13 13:00:57 oz Exp $
4857 X.TH SDBM 3 "1 March 1990"
4859 Xsdbm, 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
4870 Xdatum nullitem = { NULL, 0 };
4872 X\s-1DBM\s0 *dbm_open(char *file, int flags, int mode)
4874 X\s-1DBM\s0 *dbm_prep(char *dirname, char *pagname, int flags, int mode)
4876 Xvoid dbm_close(\s-1DBM\s0 *db)
4878 Xdatum dbm_fetch(\s-1DBM\s0 *db, key)
4880 Xint dbm_store(\s-1DBM\s0 *db, datum key, datum val, int flags)
4882 Xint dbm_delete(\s-1DBM\s0 *db, datum key)
4884 Xdatum dbm_firstkey(\s-1DBM\s0 *db)
4886 Xdatum dbm_nextkey(\s-1DBM\s0 *db)
4888 Xlong dbm_hash(char *string, int len)
4890 Xint dbm_rdonly(\s-1DBM\s0 *db)
4891 Xint dbm_error(\s-1DBM\s0 *db)
4892 Xdbm_clearerr(\s-1DBM\s0 *db)
4893 Xint dbm_dirfno(\s-1DBM\s0 *db)
4894 Xint dbm_pagfno(\s-1DBM\s0 *db)
4898 X.IX "database library" sdbm "" "\fLsdbm\fR"
4899 X.IX dbm_open "" "\fLdbm_open\fR \(em open \fLsdbm\fR database"
4900 X.IX dbm_prep "" "\fLdbm_prep\fR \(em prepare \fLsdbm\fR database"
4901 X.IX dbm_close "" "\fLdbm_close\fR \(em close \fLsdbm\fR routine"
4902 X.IX dbm_fetch "" "\fLdbm_fetch\fR \(em fetch \fLsdbm\fR database data"
4903 X.IX dbm_store "" "\fLdbm_store\fR \(em add data to \fLsdbm\fR database"
4904 X.IX dbm_delete "" "\fLdbm_delete\fR \(em remove data from \fLsdbm\fR database"
4905 X.IX dbm_firstkey "" "\fLdbm_firstkey\fR \(em access \fLsdbm\fR database"
4906 X.IX dbm_nextkey "" "\fLdbm_nextkey\fR \(em access \fLsdbm\fR database"
4907 X.IX dbm_hash "" "\fLdbm_hash\fR \(em string hash for \fLsdbm\fR database"
4908 X.IX dbm_rdonly "" "\fLdbm_rdonly\fR \(em return \fLsdbm\fR database read-only mode"
4909 X.IX dbm_error "" "\fLdbm_error\fR \(em return \fLsdbm\fR database error condition"
4910 X.IX dbm_clearerr "" "\fLdbm_clearerr\fR \(em clear \fLsdbm\fR database error condition"
4911 X.IX dbm_dirfno "" "\fLdbm_dirfno\fR \(em return \fLsdbm\fR database bitmap file descriptor"
4912 X.IX dbm_pagfno "" "\fLdbm_pagfno\fR \(em return \fLsdbm\fR database data file descriptor"
4913 X.IX "database functions \(em \fLsdbm\fR" dbm_open "" \fLdbm_open\fP
4914 X.IX "database functions \(em \fLsdbm\fR" dbm_prep "" \fLdbm_prep\fP
4915 X.IX "database functions \(em \fLsdbm\fR" dbm_close "" \fLdbm_close\fP
4916 X.IX "database functions \(em \fLsdbm\fR" dbm_fetch "" \fLdbm_fetch\fP
4917 X.IX "database functions \(em \fLsdbm\fR" dbm_store "" \fLdbm_store\fP
4918 X.IX "database functions \(em \fLsdbm\fR" dbm_delete "" \fLdbm_delete\fP
4919 X.IX "database functions \(em \fLsdbm\fR" dbm_firstkey "" \fLdbm_firstkey\fP
4920 X.IX "database functions \(em \fLsdbm\fR" dbm_nextkey "" \fLdbm_nextkey\fP
4921 X.IX "database functions \(em \fLsdbm\fR" dbm_rdonly "" \fLdbm_rdonly\fP
4922 X.IX "database functions \(em \fLsdbm\fR" dbm_error "" \fLdbm_error\fP
4923 X.IX "database functions \(em \fLsdbm\fR" dbm_clearerr "" \fLdbm_clearerr\fP
4924 X.IX "database functions \(em \fLsdbm\fR" dbm_dirfno "" \fLdbm_dirfno\fP
4925 X.IX "database functions \(em \fLsdbm\fR" dbm_pagfno "" \fLdbm_pagfno\fP
4927 XThis package allows an application to maintain a mapping of <key,value> pairs
4928 Xin disk files. This is not to be considered a real database system, but is
4929 Xstill useful in many simple applications built around fast retrieval of a data
4930 Xvalue from a key. This implementation uses an external hashing scheme,
4931 Xcalled Dynamic Hashing, as described by Per-Aake Larson in BIT 18 (1978) pp.
4932 X184-201. Retrieval of any item usually requires a single disk access.
4933 XThe application interface is compatible with the
4939 Xdatabase is kept in two files usually given the extensions
4945 Xfile contains a bitmap representing a forest of binary hash trees, the leaves
4946 Xof which indicate data pages in the
4950 XThe application interface uses the
4952 Xstructure to describe both
4958 Xspecifies a byte sequence of
4968 Xthen you must decide whether or not to include the terminating
4970 Xbyte which sometimes defines strings. Including it will require larger
4971 Xdatabase files, but it will be possible to get sensible output from a
4973 Xcommand applied to the data file.
4975 XIn order to allow a process using this package to manipulate multiple
4976 Xdatabases, the applications interface always requires a
4980 Xto identify the database to be manipulated. Such a handle can be obtained
4981 Xfrom the only routines that do not require it, namely
4985 XEither of these will open or create the two necessary files. The
4986 Xdifference is that the latter allows explicitly naming the bitmap and data
4989 Xwill take a base file name and call
4991 Xwith the default extensions.
4996 Xparameters are the same as for
4999 XTo free the resources occupied while a database handle is active, call
5000 X.BR dbm_close (\|).
5002 XGiven a handle, one can retrieve data associated with a key by using the
5004 Xroutine, and associate data with a key by using the
5013 X.BR \s-1DBM_INSERT\s0 ,
5014 Xwhich will not change an existing entry with the same key, or
5015 X.BR \s-1DBM_REPLACE\s0 ,
5016 Xwhich will replace an existing entry with the same key.
5017 XKeys are unique within the database.
5019 XTo delete a key and its associated value use the
5020 X.BR dbm_delete (\|)
5023 XTo retrieve every key in the database, use a loop like:
5027 Xfor (key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db))
5032 XThe order of retrieval is unspecified.
5034 XIf you determine that the performance of the database is inadequate or
5035 Xyou notice clustering or other effects that may be due to the hashing
5036 Xalgorithm used by this package, you can override it by supplying your
5039 Xroutine. Doing so will make the database unintelligable to any other
5040 Xapplications that do not use your specialized hash function.
5043 XThe following macros are defined in the header file:
5045 X.BR dbm_rdonly (\|)
5046 Xreturns true if the database has been opened read\-only.
5049 Xreturns true if an I/O error has occurred.
5051 X.BR dbm_clearerr (\|)
5052 Xallows you to clear the error flag if you think you know what the error
5053 Xwas and insist on ignoring it.
5055 X.BR dbm_dirfno (\|)
5056 Xreturns the file descriptor associated with the bitmap file.
5058 X.BR dbm_pagfno (\|)
5059 Xreturns the file descriptor associated with the data file.
5063 XFunctions that return a
5067 Xto indicate an error.
5068 XFunctions that return an
5070 Xwill use \-1 to indicate an error. The normal return value in that case is 0.
5071 XFunctions that return a
5075 Xto indicate an error.
5077 XAs a special case of
5078 X.BR dbm_store (\|),
5079 Xif it is called with the
5080 X.B \s-1DBM_INSERT\s0
5081 Xflag and the key already exists in the database, the return value will be 1.
5083 XIn general, if a function parameter is invalid,
5086 X.BR \s-1EINVAL\s0 .
5087 XIf a write operation is requested on a read-only database,
5090 X.BR \s-1ENOPERM\s0 .
5091 XIf a memory allocation (using
5096 X.BR \s-1ENOMEM\s0 .
5097 XFor I/O operation failures
5099 Xwill contain the value set by the relevant failed system call, either
5105 X.IP "Ozan S. Yigit" (oz@nexus.yorku.ca)
5107 XThe sum of key and value data sizes must not exceed
5111 XThe sum of the key and value data sizes where several keys hash to the
5112 Xsame value must fit within one bitmap page.
5116 Xfile will contain holes, so its apparent size is larger than its contents.
5117 XWhen copied through the filesystem the holes will be filled.
5121 Xvalues returned are in volatile storage. If you want to retain the values
5122 Xpointed to, you must copy them immediately before another call to this package.
5124 XThe only safe way for multiple processes to (read and) update a database at
5125 Xthe same time, is to implement a private locking scheme outside this package
5126 Xand open and close the database between lock acquisitions. It is safe for
5127 Xmultiple processes to concurrently access a database read-only.
5128 X.SH APPLICATIONS PORTABILITY
5129 XFor complete source code compatibility with the Berkeley Unix
5133 Xheader file should be installed in
5134 X.BR /usr/include/ndbm.h .
5141 X.BR dbm_rdonly (\|),
5142 X.BR dbm_dirfno (\|),
5144 X.BR dbm_pagfno (\|)
5145 Xfunctions are unique to this package.
5147 if test 8952 -ne `wc -c <'sdbm.3'`; then
5148 echo shar: \"'sdbm.3'\" unpacked with wrong size!
5152 if test -f 'sdbm.c' -a "${1}" != "-c" ; then
5153 echo shar: Will not clobber existing file \"'sdbm.c'\"
5155 echo shar: Extracting \"'sdbm.c'\" \(11029 characters\)
5156 sed "s/^X//" >'sdbm.c' <<'END_OF_FILE'
5158 X * sdbm - ndbm work-alike hashed database library
5159 X * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
5160 X * author: oz@nexus.yorku.ca
5161 X * status: public domain.
5167 Xstatic char rcsid[] = "$Id: sdbm.c,v 1.16 90/12/13 13:01:31 oz Exp $";
5174 X#include <sys/types.h>
5175 X#include <sys/stat.h>
5177 X#include <sys/file.h>
5180 X#include <memory.h>
5183 X#include <string.h>
5186 X#include <stddef.h>
5200 Xextern char *malloc proto((unsigned int));
5201 Xextern void free proto((void *));
5202 Xextern long lseek();
5207 Xstatic int getdbit proto((DBM *, long));
5208 Xstatic int setdbit proto((DBM *, long));
5209 Xstatic int getpage proto((DBM *, long));
5210 Xstatic datum getnext proto((DBM *));
5211 Xstatic int makroom proto((DBM *, long, int));
5216 X#define bad(x) ((x).dptr == NULL || (x).dsize <= 0)
5217 X#define exhash(item) dbm_hash((item).dptr, (item).dsize)
5218 X#define ioerr(db) ((db)->flags |= DBM_IOERR)
5220 X#define OFF_PAG(off) (long) (off) * PBLKSIZ
5221 X#define OFF_DIR(off) (long) (off) * DBLKSIZ
5223 Xstatic long masks[] = {
5224 X 000000000000, 000000000001, 000000000003, 000000000007,
5225 X 000000000017, 000000000037, 000000000077, 000000000177,
5226 X 000000000377, 000000000777, 000000001777, 000000003777,
5227 X 000000007777, 000000017777, 000000037777, 000000077777,
5228 X 000000177777, 000000377777, 000000777777, 000001777777,
5229 X 000003777777, 000007777777, 000017777777, 000037777777,
5230 X 000077777777, 000177777777, 000377777777, 000777777777,
5231 X 001777777777, 003777777777, 007777777777, 017777777777
5234 Xdatum nullitem = {NULL, 0};
5237 Xdbm_open(file, flags, mode)
5238 Xregister char *file;
5239 Xregister int flags;
5243 X register char *dirname;
5244 X register char *pagname;
5247 X if (file == NULL || !*file)
5248 X return errno = EINVAL, (DBM *) NULL;
5250 X * need space for two seperate filenames
5252 X n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
5254 X if ((dirname = malloc((unsigned) n)) == NULL)
5255 X return errno = ENOMEM, (DBM *) NULL;
5257 X * build the file names
5259 X dirname = strcat(strcpy(dirname, file), DIRFEXT);
5260 X pagname = strcpy(dirname + strlen(dirname) + 1, file);
5261 X pagname = strcat(pagname, PAGFEXT);
5263 X db = dbm_prep(dirname, pagname, flags, mode);
5264 X free((char *) dirname);
5269 Xdbm_prep(dirname, pagname, flags, mode)
5276 X struct stat dstat;
5278 X if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
5279 X return errno = ENOMEM, (DBM *) NULL;
5286 X * adjust user flags so that WRONLY becomes RDWR,
5287 X * as required by this package. Also set our internal
5288 X * flag for RDONLY if needed.
5290 X if (flags & O_WRONLY)
5291 X flags = (flags & ~O_WRONLY) | O_RDWR;
5293 X else if ((flags & 03) == O_RDONLY)
5294 X db->flags = DBM_RDONLY;
5296 X * open the files in sequence, and stat the dirfile.
5297 X * If we fail anywhere, undo everything, return NULL.
5299 X if ((db->pagf = open(pagname, flags, mode)) > -1) {
5300 X if ((db->dirf = open(dirname, flags, mode)) > -1) {
5302 X * need the dirfile size to establish max bit number.
5304 X if (fstat(db->dirf, &dstat) == 0) {
5306 X * zero size: either a fresh database, or one with a single,
5307 X * unsplit data page: dirpage is all zeros.
5309 X db->dirbno = (!dstat.st_size) ? 0 : -1;
5311 X db->maxbno = dstat.st_size * BYTESIZ;
5313 X (void) memset(db->pagbuf, 0, PBLKSIZ);
5314 X (void) memset(db->dirbuf, 0, DBLKSIZ);
5320 X (void) close(db->dirf);
5322 X (void) close(db->pagf);
5324 X free((char *) db);
5325 X return (DBM *) NULL;
5335 X (void) close(db->dirf);
5336 X (void) close(db->pagf);
5337 X free((char *) db);
5346 X if (db == NULL || bad(key))
5347 X return errno = EINVAL, nullitem;
5349 X if (getpage(db, exhash(key)))
5350 X return getpair(db->pagbuf, key);
5352 X return ioerr(db), nullitem;
5356 Xdbm_delete(db, key)
5360 X if (db == NULL || bad(key))
5361 X return errno = EINVAL, -1;
5362 X if (dbm_rdonly(db))
5363 X return errno = EPERM, -1;
5365 X if (getpage(db, exhash(key))) {
5366 X if (!delpair(db->pagbuf, key))
5369 X * update the page file
5371 X if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
5372 X || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5373 X return ioerr(db), -1;
5378 X return ioerr(db), -1;
5382 Xdbm_store(db, key, val, flags)
5389 X register long hash;
5391 X if (db == NULL || bad(key))
5392 X return errno = EINVAL, -1;
5393 X if (dbm_rdonly(db))
5394 X return errno = EPERM, -1;
5396 X need = key.dsize + val.dsize;
5398 X * is the pair too big (or too small) for this database ??
5400 X if (need < 0 || need > PAIRMAX)
5401 X return errno = EINVAL, -1;
5403 X if (getpage(db, (hash = exhash(key)))) {
5405 X * if we need to replace, delete the key/data pair
5406 X * first. If it is not there, ignore.
5408 X if (flags == DBM_REPLACE)
5409 X (void) delpair(db->pagbuf, key);
5411 X else if (duppair(db->pagbuf, key))
5415 X * if we do not have enough room, we have to split.
5417 X if (!fitpair(db->pagbuf, need))
5418 X if (!makroom(db, hash, need))
5419 X return ioerr(db), -1;
5421 X * we have enough room or split is successful. insert the key,
5422 X * and update the page file.
5424 X (void) putpair(db->pagbuf, key, val);
5426 X if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
5427 X || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5428 X return ioerr(db), -1;
5435 X return ioerr(db), -1;
5439 X * makroom - make room by splitting the overfull page
5440 X * this routine will attempt to make room for SPLTMAX times before
5444 Xmakroom(db, hash, need)
5450 X char twin[PBLKSIZ];
5451 X char *pag = db->pagbuf;
5453 X register int smax = SPLTMAX;
5457 X * split the current page
5459 X (void) splpage(pag, new, db->hmask + 1);
5461 X * address of the new page
5463 X newp = (hash & db->hmask) | (db->hmask + 1);
5466 X * write delay, read avoidence/cache shuffle:
5467 X * select the page for incoming pair: if key is to go to the new page,
5468 X * write out the previous one, and copy the new one over, thus making
5469 X * it the current page. If not, simply write the new page, and we are
5470 X * still looking at the page of interest. current page is not updated
5471 X * here, as dbm_store will do so, after it inserts the incoming pair.
5473 X if (hash & (db->hmask + 1)) {
5474 X if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
5475 X || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5477 X db->pagbno = newp;
5478 X (void) memcpy(pag, new, PBLKSIZ);
5480 X else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
5481 X || write(db->pagf, new, PBLKSIZ) < 0)
5484 X if (!setdbit(db, db->curbit))
5487 X * see if we have enough room now
5489 X if (fitpair(pag, need))
5492 X * try again... update curbit and hmask as getpage would have
5493 X * done. because of our update of the current page, we do not
5494 X * need to read in anything. BUT we have to write the current
5495 X * [deferred] page out, as the window of failure is too great.
5497 X db->curbit = 2 * db->curbit +
5498 X ((hash & (db->hmask + 1)) ? 2 : 1);
5499 X db->hmask |= db->hmask + 1;
5501 X if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
5502 X || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5507 X * if we are here, this is real bad news. After SPLTMAX splits,
5508 X * we still cannot fit the key. say goodnight.
5511 X (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
5518 X * the following two routines will break if
5519 X * deletions aren't taken into account. (ndbm bug)
5526 X return errno = EINVAL, nullitem;
5530 X if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
5531 X || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5532 X return ioerr(db), nullitem;
5537 X return getnext(db);
5545 X return errno = EINVAL, nullitem;
5546 X return getnext(db);
5550 X * all important binary trie traversal
5555 Xregister long hash;
5557 X register int hbit;
5558 X register long dbit;
5559 X register long pagb;
5563 X while (dbit < db->maxbno && getdbit(db, dbit))
5564 X dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
5566 X debug(("dbit: %d...", dbit));
5568 X db->curbit = dbit;
5569 X db->hmask = masks[hbit];
5571 X pagb = hash & db->hmask;
5573 X * see if the block we need is already in memory.
5574 X * note: this lookaside cache has about 10% hit rate.
5576 X if (pagb != db->pagbno) {
5578 X * note: here, we assume a "hole" is read as 0s.
5579 X * if not, must zero pagbuf first.
5581 X if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
5582 X || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5584 X if (!chkpage(db->pagbuf))
5586 X db->pagbno = pagb;
5588 X debug(("pag read: %d\n", pagb));
5596 Xregister long dbit;
5599 X register long dirb;
5601 X c = dbit / BYTESIZ;
5602 X dirb = c / DBLKSIZ;
5604 X if (dirb != db->dirbno) {
5605 X if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
5606 X || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
5608 X db->dirbno = dirb;
5610 X debug(("dir read: %d\n", dirb));
5613 X return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
5619 Xregister long dbit;
5622 X register long dirb;
5624 X c = dbit / BYTESIZ;
5625 X dirb = c / DBLKSIZ;
5627 X if (dirb != db->dirbno) {
5628 X if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
5629 X || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
5631 X db->dirbno = dirb;
5633 X debug(("dir read: %d\n", dirb));
5636 X db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
5638 X if (dbit >= db->maxbno)
5639 X db->maxbno += DBLKSIZ * BYTESIZ;
5641 X if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
5642 X || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
5649 X * getnext - get the next key in the page, and if done with
5650 X * the page, try the next page in sequence
5660 X key = getnkey(db->pagbuf, db->keyptr);
5661 X if (key.dptr != NULL)
5664 X * we either run out, or there is nothing on this page..
5665 X * try the next one... If we lost our position on the
5666 X * file, we will have to seek.
5669 X if (db->pagbno != db->blkptr++)
5670 X if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
5672 X db->pagbno = db->blkptr;
5673 X if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
5675 X if (!chkpage(db->pagbuf))
5679 X return ioerr(db), nullitem;
5682 if test 11029 -ne `wc -c <'sdbm.c'`; then
5683 echo shar: \"'sdbm.c'\" unpacked with wrong size!
5687 if test -f 'sdbm.h' -a "${1}" != "-c" ; then
5688 echo shar: Will not clobber existing file \"'sdbm.h'\"
5690 echo shar: Extracting \"'sdbm.h'\" \(2174 characters\)
5691 sed "s/^X//" >'sdbm.h' <<'END_OF_FILE'
5693 X * sdbm - ndbm work-alike hashed database library
5694 X * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
5695 X * author: oz@nexus.yorku.ca
5696 X * status: public domain.
5698 X#define DBLKSIZ 4096
5699 X#define PBLKSIZ 1024
5700 X#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
5701 X#define SPLTMAX 10 /* maximum allowed splits */
5702 X /* for a single insertion */
5703 X#define DIRFEXT ".dir"
5704 X#define PAGFEXT ".pag"
5707 X int dirf; /* directory file descriptor */
5708 X int pagf; /* page file descriptor */
5709 X int flags; /* status/error flags, see below */
5710 X long maxbno; /* size of dirfile in bits */
5711 X long curbit; /* current bit number */
5712 X long hmask; /* current hash mask */
5713 X long blkptr; /* current block for nextkey */
5714 X int keyptr; /* current key for nextkey */
5715 X long blkno; /* current page to read/write */
5716 X long pagbno; /* current page in pagbuf */
5717 X char pagbuf[PBLKSIZ]; /* page file block buffer */
5718 X long dirbno; /* current block in dirbuf */
5719 X char dirbuf[DBLKSIZ]; /* directory file block buffer */
5722 X#define DBM_RDONLY 0x1 /* data base open read-only */
5723 X#define DBM_IOERR 0x2 /* data base I/O error */
5728 X#define dbm_rdonly(db) ((db)->flags & DBM_RDONLY)
5729 X#define dbm_error(db) ((db)->flags & DBM_IOERR)
5731 X#define dbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
5733 X#define dbm_dirfno(db) ((db)->dirf)
5734 X#define dbm_pagfno(db) ((db)->pagf)
5741 Xextern datum nullitem;
5746 X#define proto(p) ()
5750 X * flags to dbm_store
5752 X#define DBM_INSERT 0
5753 X#define DBM_REPLACE 1
5758 Xextern DBM *dbm_open proto((char *, int, int));
5759 Xextern void dbm_close proto((DBM *));
5760 Xextern datum dbm_fetch proto((DBM *, datum));
5761 Xextern int dbm_delete proto((DBM *, datum));
5762 Xextern int dbm_store proto((DBM *, datum, datum, int));
5763 Xextern datum dbm_firstkey proto((DBM *));
5764 Xextern datum dbm_nextkey proto((DBM *));
5769 Xextern DBM *dbm_prep proto((char *, char *, int, int));
5770 Xextern long dbm_hash proto((char *, int));
5772 if test 2174 -ne `wc -c <'sdbm.h'`; then
5773 echo shar: \"'sdbm.h'\" unpacked with wrong size!
5777 if test -f 'tune.h' -a "${1}" != "-c" ; then
5778 echo shar: Will not clobber existing file \"'tune.h'\"
5780 echo shar: Extracting \"'tune.h'\" \(665 characters\)
5781 sed "s/^X//" >'tune.h' <<'END_OF_FILE'
5783 X * sdbm - ndbm work-alike hashed database library
5784 X * tuning and portability constructs [not nearly enough]
5785 X * author: oz@nexus.yorku.ca
5791 X#include <unistd.h>
5795 X#define SEEK_SET L_SET
5796 X#define memset(s,c,n) bzero(s, n) /* only when c is zero */
5797 X#define memcpy(s1,s2,n) bcopy(s2, s1, n)
5798 X#define memcmp(s1,s2,n) bcmp(s1,s2,n)
5802 X * important tuning parms (hah)
5805 X#define SEEDUPS /* always detect duplicates */
5806 X#define BADMESS /* generate a message for worst case:
5807 X cannot make room after SPLTMAX splits */
5812 X#define debug(x) printf x
5817 if test 665 -ne `wc -c <'tune.h'`; then
5818 echo shar: \"'tune.h'\" unpacked with wrong size!
5822 if test -f 'util.c' -a "${1}" != "-c" ; then
5823 echo shar: Will not clobber existing file \"'util.c'\"
5825 echo shar: Extracting \"'util.c'\" \(767 characters\)
5826 sed "s/^X//" >'util.c' <<'END_OF_FILE'
5839 X extern int errno, sys_nerr;
5840 X extern char *sys_errlist[];
5841 X extern char *progname;
5844 X fprintf(stderr, "%s: ", progname);
5845 X fprintf(stderr, s1, s2);
5846 X if (errno > 0 && errno < sys_nerr)
5847 X fprintf(stderr, " (%s)", sys_errlist[errno]);
5848 X fprintf(stderr, "\n");
5856 X register unsigned n;
5858 X register short *ino = (short *) pag;
5860 X if ((n = ino[0]) > PBLKSIZ / sizeof(short))
5867 X for (ino++; n; ino += 2) {
5868 X if (ino[0] > off || ino[1] > off ||
5878 if test 767 -ne `wc -c <'util.c'`; then
5879 echo shar: \"'util.c'\" unpacked with wrong size!
5883 echo shar: End of shell archive.