perl 5.0 alpha 4
[p5sagit/p5-mst-13.2.git] / ext / dbm / sdbm / .r
1 if test -f 'CHANGES' -a "${1}" != "-c" ; then 
2   echo shar: Will not clobber existing file \"'CHANGES'\"
3 else
4 echo shar: Extracting \"'CHANGES'\" \(900 characters\)
5 sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
6 XChanges from the earlier BETA releases.
7 X
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.
12 X
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.
19 X
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
23 X  and write.
24 END_OF_FILE
25 if test 900 -ne `wc -c <'CHANGES'`; then
26     echo shar: \"'CHANGES'\" unpacked with wrong size!
27 fi
28 # end of 'CHANGES'
29 fi
30 if test -f 'COMPARE' -a "${1}" != "-c" ; then 
31   echo shar: Will not clobber existing file \"'COMPARE'\"
32 else
33 echo shar: Extracting \"'COMPARE'\" \(2832 characters\)
34 sed "s/^X//" >'COMPARE' <<'END_OF_FILE'
35 X
36 XScript started on Thu Sep 28 15:41:06 1989
37 X% uname -a
38 Xtitan titan 4_0 UMIPS mips
39 X% make all x-dbm
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
45 X        ranlib libsdbm.a
46 X        cc  -o dbm dbm.o libsdbm.a
47 X        cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dba.c
48 X        cc  -o dba dba.o
49 X        cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -c dbd.c
50 X        cc  -o dbd dbd.o
51 X        cc -O -DSDBM -DDUFF -DDUPERROR -DSPLITFAIL -o x-dbm dbm.o
52 X% 
53 X% 
54 X% wc history
55 X  65110 218344 3204883 history
56 X% 
57 X% /bin/time dbm build foo <history
58 X
59 Xreal     5:56.9
60 Xuser       13.3
61 Xsys        26.3
62 X% ls -s
63 Xtotal 14251
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
71 X% ls -l foo.*
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
74 X% 
75 X% /bin/time x-dbm build bar <history
76 X
77 Xreal     5:59.4
78 Xuser       24.7
79 Xsys        29.1
80 X% 
81 X% ls -s
82 Xtotal 27612
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
91 X% 
92 X% ls -l bar.*
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
95 X% 
96 X% dba foo | tail
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
107 X% 
108 X% dba bar | tail
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
119 X%
120 X% exit
121 Xscript done on Thu Sep 28 16:08:45 1989
122 X
123 END_OF_FILE
124 if test 2832 -ne `wc -c <'COMPARE'`; then
125     echo shar: \"'COMPARE'\" unpacked with wrong size!
126 fi
127 # end of 'COMPARE'
128 fi
129 if test -f 'README' -a "${1}" != "-c" ; then 
130   echo shar: Will not clobber existing file \"'README'\"
131 else
132 echo shar: Extracting \"'README'\" \(11457 characters\)
133 sed "s/^X//" >'README' <<'END_OF_FILE'
134 X
135 X
136 X
137 X
138 X
139 X
140 X                   sdbm - Substitute DBM
141 X                             or
142 X        Berkeley ndbm for Every UN*X[1] Made Simple
143 X
144 X                      Ozan (oz) Yigit
145 X
146 X            The Guild of PD Software Toolmakers
147 X                      Toronto - Canada
148 X
149 X                     oz@nexus.yorku.ca
150 X
151 X
152 X
153 XImplementation is the sincerest form of flattery. - L. Peter
154 XDeutsch
155 X
156 XA The Clone of the ndbm library
157 X
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
165 Xsoftware.
166 X
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.
175 X
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.
180 X
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_________________________
192 X
193 X  [1] UN*X is not a trademark of any (dis)organization.
194 X
195 X
196 X
197 X
198 X
199 X
200 X
201 X
202 X
203 X                           - 2 -
204 X
205 X
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.)
210 X
211 XImportant Compatibility Warning
212 X
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.
219 X
220 X
221 XNotice of Intellectual Property
222 X
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
228 Xthe sdbm library.
229 X
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.
238 X
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.
243 X
244 XAcknowledgments
245 X
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_________________________
250 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
258 Xfeel any better.
259 X
260 X
261 X
262 X
263 X
264 X
265 X
266 X
267 X
268 X
269 X                           - 3 -
270 X
271 X
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.
276 X
277 XDistribution Manifest and Notes
278 X
279 XThis distribution of sdbm includes (at least) the following:
280 X
281 X    CHANGES     change log
282 X    README      this file.
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
292 X    makefile    guess.
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
296 X    sdbm.3      man page
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
301 X
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.
308 X
309 X    dbu <build|creat|look|insert|cat|delete> dbmfile
310 X
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.
314 X
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_________________________
321 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
325 Xdatabases.
326 X
327 X
328 X
329 X
330 X
331 X
332 X
333 X
334 X
335 X                           - 4 -
336 X
337 X
338 Xdatabases that insist in including the terminating null.
339 X
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-
343 Xity.
344 X
345 X     dbm.[ch] is a dbm library emulation on top of ndbm (and
346 Xhence suitable for sdbm). Written by Robert Elz.
347 X
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.
354 X
355 XImplementation Issues
356 X
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
361 Xvarious inputs:
362 X
363 X    /*
364 X     * polynomial conversion ignoring overflows
365 X     * 65599 nice. 65587 even better.
366 X     */
367 X    long
368 X    dbm_hash(char *str, int len) {
369 X        register unsigned long n = 0;
370 X
371 X        while (len--)
372 X            n = n * 65599 + *str++;
373 X        return n;
374 X    }
375 X
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
384 Xuse.
385 X
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
392 X
393 X
394 X
395 X
396 X
397 X
398 X
399 X
400 X
401 X                           - 5 -
402 X
403 X
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.
408 X
409 XPortability
410 X
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.
414 X
415 XNotes and Miscellaneous
416 X
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
428 Xfield.
429 X
430 XReferences
431 X
432 X
433 X[Lar78]
434 X    P.-A. Larson, ``Dynamic Hashing'', BIT, vol.   18,   pp.
435 X    184-201, 1978.
436 X
437 X[Tho90]
438 X    Ken Thompson, private communication, Nov. 1990
439 X
440 X[Lit80]
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.
445 X
446 X[Fag79]
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.
451 X
452 X[Wal84]
453 X    Rich Wales, ``Discussion of "dbm"  data  base  system'',
454 X    USENET newsgroup unix.wizards, Jan. 1984.
455 X
456 X[Tor87]
457 X    Chris Torek,  ``Re:   dbm.a   and   ndbm.a   archives'',
458 X
459 X
460 X
461 X
462 X
463 X
464 X
465 X
466 X
467 X                           - 6 -
468 X
469 X
470 X    USENET newsgroup comp.unix, 1987.
471 X
472 X[Mar79]
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.
476 X
477 X[Enb88]
478 X    R.  J.  Enbody  and  H.   C.   Du,   ``Dynamic   Hashing
479 X    Schemes'',ACM  Computing  Surveys,  vol.  20, no. 2, pp.
480 X    85-113, June 1988.
481 X
482 X
483 X
484 X
485 X
486 X
487 X
488 X
489 X
490 X
491 X
492 X
493 X
494 X
495 X
496 X
497 X
498 X
499 X
500 X
501 X
502 X
503 X
504 X
505 X
506 X
507 X
508 X
509 X
510 X
511 X
512 X
513 X
514 X
515 X
516 X
517 X
518 X
519 X
520 X
521 X
522 X
523 X
524 X
525 X
526 X
527 X
528 X
529 X
530 END_OF_FILE
531 if test 11457 -ne `wc -c <'README'`; then
532     echo shar: \"'README'\" unpacked with wrong size!
533 fi
534 # end of 'README'
535 fi
536 if test -f 'biblio' -a "${1}" != "-c" ; then 
537   echo shar: Will not clobber existing file \"'biblio'\"
538 else
539 echo shar: Extracting \"'biblio'\" \(1012 characters\)
540 sed "s/^X//" >'biblio' <<'END_OF_FILE'
541 X%A R. J. Enbody
542 X%A H. C. Du
543 X%T Dynamic Hashing Schemes
544 X%J ACM Computing Surveys
545 X%V 20
546 X%N 2
547 X%D June 1988
548 X%P 85-113
549 X%K surveys
550 X
551 X%A P.-A. Larson
552 X%T Dynamic Hashing
553 X%J BIT
554 X%V 18
555 X%P 184-201
556 X%D 1978
557 X%K dynamic
558 X
559 X%A W. Litwin
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
563 X%C Saratoga, Calif.
564 X%P 212-223
565 X%D 1980
566 X%K linear
567 X
568 X%A R. Fagin
569 X%A J. Nievergelt
570 X%A N. Pippinger
571 X%A H. R. Strong
572 X%T Extendible Hashing - A Fast Access Method for Dynamic Files
573 X%J ACM Trans. Database Syst.
574 X%V 4
575 X%N 3
576 X%D Sept. 1979
577 X%P 315-344
578 X%K extend
579 X
580 X%A G. N. Martin
581 X%T Spiral Storage: Incrementally Augmentable Hash Addressed Storage
582 X%J Technical Report #27
583 X%I University of Varwick
584 X%C Coventry, U.K.
585 X%D 1979
586 X%K spiral
587 X
588 X%A Chris Torek
589 X%T Re: dbm.a and ndbm.a archives
590 X%B USENET newsgroup comp.unix
591 X%D 1987
592 X%K torek
593 X
594 X%A Rich Wales
595 X%T Discusson of "dbm" data base system
596 X%B USENET newsgroup unix.wizards
597 X%D Jan. 1984
598 X%K rich
599 X
600 X
601 X
602 X
603 X
604 X
605 END_OF_FILE
606 if test 1012 -ne `wc -c <'biblio'`; then
607     echo shar: \"'biblio'\" unpacked with wrong size!
608 fi
609 # end of 'biblio'
610 fi
611 if test -f 'dba.c' -a "${1}" != "-c" ; then 
612   echo shar: Will not clobber existing file \"'dba.c'\"
613 else
614 echo shar: Extracting \"'dba.c'\" \(1273 characters\)
615 sed "s/^X//" >'dba.c' <<'END_OF_FILE'
616 X/*
617 X * dba dbm analysis/recovery
618 X */
619 X
620 X#include <stdio.h>
621 X#include <sys/file.h>
622 X#include "sdbm.h"
623 X
624 Xchar *progname;
625 Xextern void oops();
626 X
627 Xint
628 Xmain(argc, argv)
629 Xchar **argv;
630 X{
631 X       int n;
632 X       char *p;
633 X       char *name;
634 X       int pagf;
635 X
636 X       progname = argv[0];
637 X
638 X       if (p = argv[1]) {
639 X               name = (char *) malloc((n = strlen(p)) + 5);
640 X               strcpy(name, p);
641 X               strcpy(name + n, ".pag");
642 X
643 X               if ((pagf = open(name, O_RDONLY)) < 0)
644 X                       oops("cannot open %s.", name);
645 X
646 X               sdump(pagf);
647 X       }
648 X       else
649 X               oops("usage: %s dbname", progname);
650 X
651 X       return 0;
652 X}
653 X
654 Xsdump(pagf)
655 Xint pagf;
656 X{
657 X       register b;
658 X       register n = 0;
659 X       register t = 0;
660 X       register o = 0;
661 X       register e;
662 X       char pag[PBLKSIZ];
663 X
664 X       while ((b = read(pagf, pag, PBLKSIZ)) > 0) {
665 X               printf("#%d: ", n);
666 X               if (!okpage(pag))
667 X                       printf("bad\n");
668 X               else {
669 X                       printf("ok. ");
670 X                       if (!(e = pagestat(pag)))
671 X                           o++;
672 X                       else
673 X                           t += e;
674 X               }
675 X               n++;
676 X       }
677 X
678 X       if (b == 0)
679 X               printf("%d pages (%d holes):  %d entries\n", n, o, t);
680 X       else
681 X               oops("read failed: block %d", n);
682 X}
683 X
684 Xpagestat(pag)
685 Xchar *pag;
686 X{
687 X       register n;
688 X       register free;
689 X       register short *ino = (short *) pag;
690 X
691 X       if (!(n = ino[0]))
692 X               printf("no entries.\n");
693 X       else {
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);
697 X       }
698 X       return n / 2;
699 X}
700 END_OF_FILE
701 if test 1273 -ne `wc -c <'dba.c'`; then
702     echo shar: \"'dba.c'\" unpacked with wrong size!
703 fi
704 # end of 'dba.c'
705 fi
706 if test -f 'dbd.c' -a "${1}" != "-c" ; then 
707   echo shar: Will not clobber existing file \"'dbd.c'\"
708 else
709 echo shar: Extracting \"'dbd.c'\" \(1719 characters\)
710 sed "s/^X//" >'dbd.c' <<'END_OF_FILE'
711 X/*
712 X * dbd - dump a dbm data file
713 X */
714 X
715 X#include <stdio.h>
716 X#include <sys/file.h>
717 X#include "sdbm.h"
718 X
719 Xchar *progname;
720 Xextern void oops();
721 X
722 X
723 X#define empty(page)    (((short *) page)[0] == 0)
724 X
725 Xint
726 Xmain(argc, argv)
727 Xchar **argv;
728 X{
729 X       int n;
730 X       char *p;
731 X       char *name;
732 X       int pagf;
733 X
734 X       progname = argv[0];
735 X
736 X       if (p = argv[1]) {
737 X               name = (char *) malloc((n = strlen(p)) + 5);
738 X               strcpy(name, p);
739 X               strcpy(name + n, ".pag");
740 X
741 X               if ((pagf = open(name, O_RDONLY)) < 0)
742 X                       oops("cannot open %s.", name);
743 X
744 X               sdump(pagf);
745 X       }
746 X       else
747 X               oops("usage: %s dbname", progname);
748 X       return 0;
749 X}
750 X
751 Xsdump(pagf)
752 Xint pagf;
753 X{
754 X       register r;
755 X       register n = 0;
756 X       register o = 0;
757 X       char pag[PBLKSIZ];
758 X
759 X       while ((r = read(pagf, pag, PBLKSIZ)) > 0) {
760 X               if (!okpage(pag))
761 X                       fprintf(stderr, "%d: bad page.\n", n);
762 X               else if (empty(pag))
763 X                       o++;
764 X               else
765 X                       dispage(pag);
766 X               n++;
767 X       }
768 X
769 X       if (r == 0)
770 X               fprintf(stderr, "%d pages (%d holes).\n", n, o);
771 X       else
772 X               oops("read failed: block %d", n);
773 X}
774 X
775 X
776 X#ifdef OLD
777 Xdispage(pag)
778 Xchar *pag;
779 X{
780 X       register i, n;
781 X       register off;
782 X       register short *ino = (short *) pag;
783 X
784 X       off = PBLKSIZ;
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++)
788 X                       putchar(pag[n]);
789 X               putchar(' ');
790 X               off = ino[i];
791 X               printf("[%d]: ", ino[i + 1]);
792 X               for (n = ino[i + 1]; n < off; n++)
793 X                       putchar(pag[n]);
794 X               off = ino[i + 1];
795 X               putchar('\n');
796 X       }
797 X}
798 X#else
799 Xdispage(pag)
800 Xchar *pag;
801 X{
802 X       register i, n;
803 X       register off;
804 X       register short *ino = (short *) pag;
805 X
806 X       off = PBLKSIZ;
807 X       for (i = 1; i < ino[0]; i += 2) {
808 X               for (n = ino[i]; n < off; n++)
809 X                       if (pag[n] != 0)
810 X                               putchar(pag[n]);
811 X               putchar('\t');
812 X               off = ino[i];
813 X               for (n = ino[i + 1]; n < off; n++)
814 X                       if (pag[n] != 0)
815 X                               putchar(pag[n]);
816 X               putchar('\n');
817 X               off = ino[i + 1];
818 X       }
819 X}
820 X#endif
821 END_OF_FILE
822 if test 1719 -ne `wc -c <'dbd.c'`; then
823     echo shar: \"'dbd.c'\" unpacked with wrong size!
824 fi
825 # end of 'dbd.c'
826 fi
827 if test -f 'dbe.1' -a "${1}" != "-c" ; then 
828   echo shar: Will not clobber existing file \"'dbe.1'\"
829 else
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"
833 X.SH NAME
834 Xdbe \- Edit a ndbm(3) database
835 X.SH USAGE
836 Xdbe <database> [-m r|w|rw] [-crtvx] -a|-d|-f|-F|-s [<key> [<content>]]
837 X.SH DESCRIPTION
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.
844 X.SH OPTIONS
845 X.IP -a
846 XList all entries in the database.
847 X.IP -c
848 XCreate the database if it does not exist.
849 X.IP -d
850 XDelete the entry associated with the specified key.
851 X.IP -f
852 XFetch and display the entry associated with the specified key.
853 X.IP -F
854 XFetch and display all the entries whose key match the specified
855 Xregular-expression
856 X.IP "-m r|w|rw"
857 XOpen the database in read-only, write-only or read-write mode
858 X.IP -r
859 XReplace the entry associated with the specified key if it already exists.
860 XSee option -s.
861 X.IP -s
862 XStore an entry under a specific key.
863 XAn error occurs if the key already exists and the option -r was not specified.
864 X.IP -t
865 XRe-initialize the database before executing the command.
866 X.IP -v
867 XVerbose mode.
868 XConfirm stores and deletions.
869 X.IP -x
870 XIf option -x is used with option -c, then if the database already exists,
871 Xan error occurs.
872 XThis can be used to implement a simple exclusive access locking mechanism.
873 X.SH SEE ALSO
874 Xndbm(3)
875 X.SH AUTHOR
876 Xjanick@bnr.ca
877 X
878 END_OF_FILE
879 if test 1454 -ne `wc -c <'dbe.1'`; then
880     echo shar: \"'dbe.1'\" unpacked with wrong size!
881 fi
882 # end of 'dbe.1'
883 fi
884 if test -f 'dbe.c' -a "${1}" != "-c" ; then 
885   echo shar: Will not clobber existing file \"'dbe.c'\"
886 else
887 echo shar: Extracting \"'dbe.c'\" \(9799 characters\)
888 sed "s/^X//" >'dbe.c' <<'END_OF_FILE'
889 X#include <stdio.h>
890 X#ifndef VMS
891 X#include <sys/file.h>
892 X#include <ndbm.h>
893 X#else
894 X#include "file.h"
895 X#include "ndbm.h"
896 X#endif
897 X#include <ctype.h>
898 X
899 X/***************************************************************************\
900 X**                                                                         **
901 X**   Function name: getopt()                                               **
902 X**   Author:        Henry Spencer, UofT                                    **
903 X**   Coding date:   84/04/28                                               **
904 X**                                                                         **
905 X**   Description:                                                          **
906 X**                                                                         **
907 X**   Parses argv[] for arguments.                                          **
908 X**   Works with Whitesmith's C compiler.                                   **
909 X**                                                                         **
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) **
915 X**                                                                         **
916 X**   Outputs  - Returns the next option character,                         **
917 X**              '?' for non '-' arguments                                  **
918 X**              or ':' when there is no more arguments.                    **
919 X**                                                                         **
920 X**   Side Effects + The argument to an option is pointed to by 'optarg'    **
921 X**                                                                         **
922 X*****************************************************************************
923 X**                                                                         **
924 X**   REVISION HISTORY:                                                     **
925 X**                                                                         **
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  **
933 X**                                                                         **
934 X\***************************************************************************/
935 X
936 Xchar *optarg;                         /* Global argument pointer. */
937 X
938 X#ifdef VMS
939 X#define index  strchr
940 X#endif
941 X
942 Xchar
943 Xgetopt(argc, argv, optstring)
944 Xint argc;
945 Xchar **argv;
946 Xchar *optstring;
947 X{
948 X       register int c;
949 X       register char *place;
950 X       extern char *index();
951 X       static int optind = 0;
952 X       static char *scan = NULL;
953 X
954 X       optarg = NULL;
955 X
956 X       if (scan == NULL || *scan == '\0') {
957 X
958 X               if (optind == 0)
959 X                       optind++;
960 X               if (optind >= argc)
961 X                       return ':';
962 X
963 X               optarg = place = argv[optind++];
964 X               if (place[0] != '-' || place[1] == '\0')
965 X                       return '?';
966 X               if (place[1] == '-' && place[2] == '\0')
967 X                       return '?';
968 X               scan = place + 1;
969 X       }
970 X
971 X       c = *scan++;
972 X       place = index(optstring, c);
973 X       if (place == NULL || c == ':' || c == ';') {
974 X
975 X               (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
976 X               scan = NULL;
977 X               return '!';
978 X       }
979 X       if (*++place == ':') {
980 X
981 X               if (*scan != '\0') {
982 X
983 X                       optarg = scan;
984 X                       scan = NULL;
985 X
986 X               }
987 X               else {
988 X
989 X                       if (optind >= argc) {
990 X
991 X                               (void) fprintf(stderr, "%s: %c requires an argument\n",
992 X                                              argv[0], c);
993 X                               return '!';
994 X                       }
995 X                       optarg = argv[optind];
996 X                       optind++;
997 X               }
998 X       }
999 X       else if (*place == ';') {
1000 X
1001 X               if (*scan != '\0') {
1002 X
1003 X                       optarg = scan;
1004 X                       scan = NULL;
1005 X
1006 X               }
1007 X               else {
1008 X
1009 X                       if (optind >= argc || *argv[optind] == '-')
1010 X                               optarg = NULL;
1011 X                       else {
1012 X                               optarg = argv[optind];
1013 X                               optind++;
1014 X                       }
1015 X               }
1016 X       }
1017 X       return c;
1018 X}
1019 X
1020 X
1021 Xvoid
1022 Xprint_datum(db)
1023 Xdatum db;
1024 X{
1025 X       int i;
1026 X
1027 X       putchar('"');
1028 X       for (i = 0; i < db.dsize; i++) {
1029 X               if (isprint(db.dptr[i]))
1030 X                       putchar(db.dptr[i]);
1031 X               else {
1032 X                       putchar('\\');
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));
1036 X               }
1037 X       }
1038 X       putchar('"');
1039 X}
1040 X
1041 X
1042 Xdatum
1043 Xread_datum(s)
1044 Xchar *s;
1045 X{
1046 X       datum db;
1047 X       char *p;
1048 X       int i;
1049 X
1050 X       db.dsize = 0;
1051 X       db.dptr = (char *) malloc(strlen(s) * sizeof(char));
1052 X       for (p = db.dptr; *s != '\0'; p++, db.dsize++, s++) {
1053 X               if (*s == '\\') {
1054 X                       if (*++s == 'n')
1055 X                               *p = '\n';
1056 X                       else if (*s == 'r')
1057 X                               *p = '\r';
1058 X                       else if (*s == 'f')
1059 X                               *p = '\f';
1060 X                       else if (*s == 't')
1061 X                               *p = '\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;
1065 X                               i |= *s - '0';
1066 X                               *p = i;
1067 X                       }
1068 X                       else if (*s == '0')
1069 X                               *p = '\0';
1070 X                       else
1071 X                               *p = *s;
1072 X               }
1073 X               else
1074 X                       *p = *s;
1075 X       }
1076 X
1077 X       return db;
1078 X}
1079 X
1080 X
1081 Xchar *
1082 Xkey2s(db)
1083 Xdatum db;
1084 X{
1085 X       char *buf;
1086 X       char *p1, *p2;
1087 X
1088 X       buf = (char *) malloc((db.dsize + 1) * sizeof(char));
1089 X       for (p1 = buf, p2 = db.dptr; *p2 != '\0'; *p1++ = *p2++);
1090 X       *p1 = '\0';
1091 X       return buf;
1092 X}
1093 X
1094 X
1095 Xmain(argc, argv)
1096 Xint argc;
1097 Xchar **argv;
1098 X{
1099 X       typedef enum {
1100 X               YOW, FETCH, STORE, DELETE, SCAN, REGEXP
1101 X       } commands;
1102 X       char opt;
1103 X       int flags;
1104 X       int giveusage = 0;
1105 X       int verbose = 0;
1106 X       commands what = YOW;
1107 X       char *comarg[3];
1108 X       int st_flag = DBM_INSERT;
1109 X       int argn;
1110 X       DBM *db;
1111 X       datum key;
1112 X       datum content;
1113 X
1114 X       flags = O_RDWR;
1115 X       argn = 0;
1116 X
1117 X       while ((opt = getopt(argc, argv, "acdfFm:rstvx")) != ':') {
1118 X               switch (opt) {
1119 X               case 'a':
1120 X                       what = SCAN;
1121 X                       break;
1122 X               case 'c':
1123 X                       flags |= O_CREAT;
1124 X                       break;
1125 X               case 'd':
1126 X                       what = DELETE;
1127 X                       break;
1128 X               case 'f':
1129 X                       what = FETCH;
1130 X                       break;
1131 X               case 'F':
1132 X                       what = REGEXP;
1133 X                       break;
1134 X               case 'm':
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)
1141 X                               flags |= O_RDWR;
1142 X                       else {
1143 X                               fprintf(stderr, "Invalid mode: \"%s\"\n", optarg);
1144 X                               giveusage = 1;
1145 X                       }
1146 X                       break;
1147 X               case 'r':
1148 X                       st_flag = DBM_REPLACE;
1149 X                       break;
1150 X               case 's':
1151 X                       what = STORE;
1152 X                       break;
1153 X               case 't':
1154 X                       flags |= O_TRUNC;
1155 X                       break;
1156 X               case 'v':
1157 X                       verbose = 1;
1158 X                       break;
1159 X               case 'x':
1160 X                       flags |= O_EXCL;
1161 X                       break;
1162 X               case '!':
1163 X                       giveusage = 1;
1164 X                       break;
1165 X               case '?':
1166 X                       if (argn < 3)
1167 X                               comarg[argn++] = optarg;
1168 X                       else {
1169 X                               fprintf(stderr, "Too many arguments.\n");
1170 X                               giveusage = 1;
1171 X                       }
1172 X                       break;
1173 X               }
1174 X       }
1175 X
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]);
1178 X               exit(-1);
1179 X       }
1180 X
1181 X       if ((db = dbm_open(comarg[0], flags, 0777)) == NULL) {
1182 X               fprintf(stderr, "Error opening database \"%s\"\n", comarg[0]);
1183 X               exit(-1);
1184 X       }
1185 X
1186 X       if (argn > 1)
1187 X               key = read_datum(comarg[1]);
1188 X       if (argn > 2)
1189 X               content = read_datum(comarg[2]);
1190 X
1191 X       switch (what) {
1192 X
1193 X       case SCAN:
1194 X               key = dbm_firstkey(db);
1195 X               if (dbm_error(db)) {
1196 X                       fprintf(stderr, "Error when fetching first key\n");
1197 X                       goto db_exit;
1198 X               }
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 ");
1203 X                               print_datum(key);
1204 X                               printf("\n");
1205 X                               goto db_exit;
1206 X                       }
1207 X                       print_datum(key);
1208 X                       printf(": ");
1209 X                       print_datum(content);
1210 X                       printf("\n");
1211 X                       if (dbm_error(db)) {
1212 X                               fprintf(stderr, "Error when fetching next key\n");
1213 X                               goto db_exit;
1214 X                       }
1215 X                       key = dbm_nextkey(db);
1216 X               }
1217 X               break;
1218 X
1219 X       case REGEXP:
1220 X               if (argn < 2) {
1221 X                       fprintf(stderr, "Missing regular expression.\n");
1222 X                       goto db_exit;
1223 X               }
1224 X               if (re_comp(comarg[1])) {
1225 X                       fprintf(stderr, "Invalid regular expression\n");
1226 X                       goto db_exit;
1227 X               }
1228 X               key = dbm_firstkey(db);
1229 X               if (dbm_error(db)) {
1230 X                       fprintf(stderr, "Error when fetching first key\n");
1231 X                       goto db_exit;
1232 X               }
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 ");
1238 X                                       print_datum(key);
1239 X                                       printf("\n");
1240 X                                       goto db_exit;
1241 X                               }
1242 X                               print_datum(key);
1243 X                               printf(": ");
1244 X                               print_datum(content);
1245 X                               printf("\n");
1246 X                               if (dbm_error(db)) {
1247 X                                       fprintf(stderr, "Error when fetching next key\n");
1248 X                                       goto db_exit;
1249 X                               }
1250 X                       }
1251 X                       key = dbm_nextkey(db);
1252 X               }
1253 X               break;
1254 X
1255 X       case FETCH:
1256 X               if (argn < 2) {
1257 X                       fprintf(stderr, "Missing fetch key.\n");
1258 X                       goto db_exit;
1259 X               }
1260 X               content = dbm_fetch(db, key);
1261 X               if (dbm_error(db)) {
1262 X                       fprintf(stderr, "Error when fetching ");
1263 X                       print_datum(key);
1264 X                       printf("\n");
1265 X                       goto db_exit;
1266 X               }
1267 X               if (content.dptr == NULL) {
1268 X                       fprintf(stderr, "Cannot find ");
1269 X                       print_datum(key);
1270 X                       printf("\n");
1271 X                       goto db_exit;
1272 X               }
1273 X               print_datum(key);
1274 X               printf(": ");
1275 X               print_datum(content);
1276 X               printf("\n");
1277 X               break;
1278 X
1279 X       case DELETE:
1280 X               if (argn < 2) {
1281 X                       fprintf(stderr, "Missing delete key.\n");
1282 X                       goto db_exit;
1283 X               }
1284 X               if (dbm_delete(db, key) || dbm_error(db)) {
1285 X                       fprintf(stderr, "Error when deleting ");
1286 X                       print_datum(key);
1287 X                       printf("\n");
1288 X                       goto db_exit;
1289 X               }
1290 X               if (verbose) {
1291 X                       print_datum(key);
1292 X                       printf(": DELETED\n");
1293 X               }
1294 X               break;
1295 X
1296 X       case STORE:
1297 X               if (argn < 3) {
1298 X                       fprintf(stderr, "Missing key and/or content.\n");
1299 X                       goto db_exit;
1300 X               }
1301 X               if (dbm_store(db, key, content, st_flag) || dbm_error(db)) {
1302 X                       fprintf(stderr, "Error when storing ");
1303 X                       print_datum(key);
1304 X                       printf("\n");
1305 X                       goto db_exit;
1306 X               }
1307 X               if (verbose) {
1308 X                       print_datum(key);
1309 X                       printf(": ");
1310 X                       print_datum(content);
1311 X                       printf(" STORED\n");
1312 X               }
1313 X               break;
1314 X       }
1315 X
1316 Xdb_exit:
1317 X       dbm_clearerr(db);
1318 X       dbm_close(db);
1319 X       if (dbm_error(db)) {
1320 X               fprintf(stderr, "Error closing database \"%s\"\n", comarg[0]);
1321 X               exit(-1);
1322 X       }
1323 X}
1324 END_OF_FILE
1325 if test 9799 -ne `wc -c <'dbe.c'`; then
1326     echo shar: \"'dbe.c'\" unpacked with wrong size!
1327 fi
1328 # end of 'dbe.c'
1329 fi
1330 if test -f 'dbm.c' -a "${1}" != "-c" ; then 
1331   echo shar: Will not clobber existing file \"'dbm.c'\"
1332 else
1333 echo shar: Extracting \"'dbm.c'\" \(2426 characters\)
1334 sed "s/^X//" >'dbm.c' <<'END_OF_FILE'
1335 X/*
1336 X * Copyright (c) 1985 The Regents of the University of California.
1337 X * All rights reserved.
1338 X *
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.
1350 X */
1351 X
1352 X#ifndef lint
1353 Xstatic char sccsid[] = "@(#)dbm.c    5.4 (Berkeley) 5/24/89";
1354 X#endif /* not lint */
1355 X
1356 X#include    "dbm.h"
1357 X
1358 X#define    NODB    ((DBM *)0)
1359 X
1360 Xstatic DBM *cur_db = NODB;
1361 X
1362 Xstatic char no_db[] = "dbm: no open database\n";
1363 X
1364 Xdbminit(file)
1365 X    char *file;
1366 X{
1367 X    if (cur_db != NODB)
1368 X        dbm_close(cur_db);
1369 X
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)
1374 X            return (-1);
1375 X    }
1376 X    return (0);
1377 X}
1378 X
1379 Xlong
1380 Xforder(key)
1381 Xdatum key;
1382 X{
1383 X    if (cur_db == NODB) {
1384 X        printf(no_db);
1385 X        return (0L);
1386 X    }
1387 X    return (dbm_forder(cur_db, key));
1388 X}
1389 X
1390 Xdatum
1391 Xfetch(key)
1392 Xdatum key;
1393 X{
1394 X    datum item;
1395 X
1396 X    if (cur_db == NODB) {
1397 X        printf(no_db);
1398 X        item.dptr = 0;
1399 X        return (item);
1400 X    }
1401 X    return (dbm_fetch(cur_db, key));
1402 X}
1403 X
1404 Xdelete(key)
1405 Xdatum key;
1406 X{
1407 X    if (cur_db == NODB) {
1408 X        printf(no_db);
1409 X        return (-1);
1410 X    }
1411 X    if (dbm_rdonly(cur_db))
1412 X        return (-1);
1413 X    return (dbm_delete(cur_db, key));
1414 X}
1415 X
1416 Xstore(key, dat)
1417 Xdatum key, dat;
1418 X{
1419 X    if (cur_db == NODB) {
1420 X        printf(no_db);
1421 X        return (-1);
1422 X    }
1423 X    if (dbm_rdonly(cur_db))
1424 X        return (-1);
1425 X
1426 X    return (dbm_store(cur_db, key, dat, DBM_REPLACE));
1427 X}
1428 X
1429 Xdatum
1430 Xfirstkey()
1431 X{
1432 X    datum item;
1433 X
1434 X    if (cur_db == NODB) {
1435 X        printf(no_db);
1436 X        item.dptr = 0;
1437 X        return (item);
1438 X    }
1439 X    return (dbm_firstkey(cur_db));
1440 X}
1441 X
1442 Xdatum
1443 Xnextkey(key)
1444 Xdatum key;
1445 X{
1446 X    datum item;
1447 X
1448 X    if (cur_db == NODB) {
1449 X        printf(no_db);
1450 X        item.dptr = 0;
1451 X        return (item);
1452 X    }
1453 X    return (dbm_nextkey(cur_db, key));
1454 X}
1455 END_OF_FILE
1456 if test 2426 -ne `wc -c <'dbm.c'`; then
1457     echo shar: \"'dbm.c'\" unpacked with wrong size!
1458 fi
1459 # end of 'dbm.c'
1460 fi
1461 if test -f 'dbm.h' -a "${1}" != "-c" ; then 
1462   echo shar: Will not clobber existing file \"'dbm.h'\"
1463 else
1464 echo shar: Extracting \"'dbm.h'\" \(1186 characters\)
1465 sed "s/^X//" >'dbm.h' <<'END_OF_FILE'
1466 X/*
1467 X * Copyright (c) 1983 The Regents of the University of California.
1468 X * All rights reserved.
1469 X *
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.
1481 X *
1482 X *    @(#)dbm.h    5.2 (Berkeley) 5/24/89
1483 X */
1484 X
1485 X#ifndef NULL
1486 X/*
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.
1490 X */
1491 X#define    NULL    ((char *) 0)
1492 X#endif
1493 X
1494 X#include <ndbm.h>
1495 X
1496 Xdatum    fetch();
1497 Xdatum    firstkey();
1498 Xdatum    nextkey();
1499 END_OF_FILE
1500 if test 1186 -ne `wc -c <'dbm.h'`; then
1501     echo shar: \"'dbm.h'\" unpacked with wrong size!
1502 fi
1503 # end of 'dbm.h'
1504 fi
1505 if test -f 'dbu.c' -a "${1}" != "-c" ; then 
1506   echo shar: Will not clobber existing file \"'dbu.c'\"
1507 else
1508 echo shar: Extracting \"'dbu.c'\" \(4408 characters\)
1509 sed "s/^X//" >'dbu.c' <<'END_OF_FILE'
1510 X#include <stdio.h>
1511 X#include <sys/file.h>
1512 X#ifdef SDBM
1513 X#include "sdbm.h"
1514 X#else
1515 X#include <ndbm.h>
1516 X#endif
1517 X#include <string.h>
1518 X
1519 X#ifdef BSD42
1520 X#define strchr index
1521 X#endif
1522 X
1523 Xextern int     getopt();
1524 Xextern char    *strchr();
1525 Xextern void    oops();
1526 X
1527 Xchar *progname;
1528 X
1529 Xstatic int rflag;
1530 Xstatic char *usage = "%s [-R] cat | look |... dbmname";
1531 X
1532 X#define DERROR 0
1533 X#define DLOOK  1
1534 X#define DINSERT        2
1535 X#define DDELETE 3
1536 X#define        DCAT    4
1537 X#define DBUILD 5
1538 X#define DPRESS 6
1539 X#define DCREAT 7
1540 X
1541 X#define LINEMAX        8192
1542 X
1543 Xtypedef struct {
1544 X       char *sname;
1545 X       int scode;
1546 X       int flags;
1547 X} cmd;
1548 X
1549 Xstatic cmd cmds[] = {
1550 X
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
1568 X};
1569 X
1570 X#define CTABSIZ (sizeof (cmds)/sizeof (cmd))
1571 X
1572 Xstatic cmd *parse();
1573 Xstatic void badk(), doit(), prdatum();
1574 X
1575 Xint
1576 Xmain(argc, argv)
1577 Xint    argc;
1578 Xchar *argv[];
1579 X{
1580 X       int c;
1581 X       register cmd *act;
1582 X       extern int optind;
1583 X       extern char *optarg;
1584 X
1585 X       progname = argv[0];
1586 X
1587 X       while ((c = getopt(argc, argv, "R")) != EOF)
1588 X               switch (c) {
1589 X               case 'R':              /* raw processing  */
1590 X                       rflag++;
1591 X                       break;
1592 X
1593 X               default:
1594 X                       oops("usage: %s", usage);
1595 X                       break;
1596 X               }
1597 X
1598 X       if ((argc -= optind) < 2)
1599 X               oops("usage: %s", usage);
1600 X
1601 X       if ((act = parse(argv[optind])) == NULL)
1602 X               badk(argv[optind]);
1603 X       optind++;
1604 X       doit(act, argv[optind]);
1605 X       return 0;
1606 X}
1607 X
1608 Xstatic void
1609 Xdoit(act, file)
1610 Xregister cmd *act;
1611 Xchar *file;
1612 X{
1613 X       datum key;
1614 X       datum val;
1615 X       register DBM *db;
1616 X       register char *op;
1617 X       register int n;
1618 X       char *line;
1619 X#ifdef TIME
1620 X       long start;
1621 X       extern long time();
1622 X#endif
1623 X
1624 X       if ((db = dbm_open(file, act->flags, 0644)) == NULL)
1625 X               oops("cannot open: %s", file);
1626 X
1627 X       if ((line = (char *) malloc(LINEMAX)) == NULL)
1628 X               oops("%s: cannot get memory", "line alloc");
1629 X
1630 X       switch (act->scode) {
1631 X
1632 X       case DLOOK:
1633 X               while (fgets(line, LINEMAX, stdin) != NULL) {
1634 X                       n = strlen(line) - 1;
1635 X                       line[n] = 0;
1636 X                       key.dptr = line;
1637 X                       key.dsize = n;
1638 X                       val = dbm_fetch(db, key);
1639 X                       if (val.dptr != NULL) {
1640 X                               prdatum(stdout, val);
1641 X                               putchar('\n');
1642 X                               continue;
1643 X                       }
1644 X                       prdatum(stderr, key);
1645 X                       fprintf(stderr, ": not found.\n");
1646 X               }
1647 X               break;
1648 X       case DINSERT:
1649 X               break;
1650 X       case DDELETE:
1651 X               while (fgets(line, LINEMAX, stdin) != NULL) {
1652 X                       n = strlen(line) - 1;
1653 X                       line[n] = 0;
1654 X                       key.dptr = line;
1655 X                       key.dsize = n;
1656 X                       if (dbm_delete(db, key) == -1) {
1657 X                               prdatum(stderr, key);
1658 X                               fprintf(stderr, ": not found.\n");
1659 X                       }
1660 X               }
1661 X               break;
1662 X       case DCAT:
1663 X               for (key = dbm_firstkey(db); key.dptr != 0; 
1664 X                    key = dbm_nextkey(db)) {
1665 X                       prdatum(stdout, key);
1666 X                       putchar('\t');
1667 X                       prdatum(stdout, dbm_fetch(db, key));
1668 X                       putchar('\n');
1669 X               }
1670 X               break;
1671 X       case DBUILD:
1672 X#ifdef TIME
1673 X               start = time(0);
1674 X#endif
1675 X               while (fgets(line, LINEMAX, stdin) != NULL) {
1676 X                       n = strlen(line) - 1;
1677 X                       line[n] = 0;
1678 X                       key.dptr = line;
1679 X                       if ((op = strchr(line, '\t')) != 0) {
1680 X                               key.dsize = op - line;
1681 X                               *op++ = 0;
1682 X                               val.dptr = op;
1683 X                               val.dsize = line + n - op;
1684 X                       }
1685 X                       else
1686 X                               oops("bad input; %s", line);
1687 X       
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");
1692 X                       }
1693 X               }
1694 X#ifdef TIME
1695 X               printf("done: %d seconds.\n", time(0) - start);
1696 X#endif
1697 X               break;
1698 X       case DPRESS:
1699 X               break;
1700 X       case DCREAT:
1701 X               break;
1702 X       }
1703 X
1704 X       dbm_close(db);
1705 X}
1706 X
1707 Xstatic void
1708 Xbadk(word)
1709 Xchar *word;
1710 X{
1711 X       register int i;
1712 X
1713 X       if (progname)
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");
1720 X       exit(1);
1721 X       /*NOTREACHED*/
1722 X}
1723 X
1724 Xstatic cmd *
1725 Xparse(str)
1726 Xregister char *str;
1727 X{
1728 X       register int i = CTABSIZ;
1729 X       register cmd *p;
1730 X       
1731 X       for (p = cmds; i--; p++)
1732 X               if (strcmp(p->sname, str) == 0)
1733 X                       return p;
1734 X       return NULL;
1735 X}
1736 X
1737 Xstatic void
1738 Xprdatum(stream, d)
1739 XFILE *stream;
1740 Xdatum d;
1741 X{
1742 X       register int c;
1743 X       register char *p = d.dptr;
1744 X       register int n = d.dsize;
1745 X
1746 X       while (n--) {
1747 X               c = *p++ & 0377;
1748 X               if (c & 0200) {
1749 X                       fprintf(stream, "M-");
1750 X                       c &= 0177;
1751 X               }
1752 X               if (c == 0177 || c < ' ') 
1753 X                       fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
1754 X               else
1755 X                       putc(c, stream);
1756 X       }
1757 X}
1758 X
1759 X
1760 END_OF_FILE
1761 if test 4408 -ne `wc -c <'dbu.c'`; then
1762     echo shar: \"'dbu.c'\" unpacked with wrong size!
1763 fi
1764 # end of 'dbu.c'
1765 fi
1766 if test -f 'grind' -a "${1}" != "-c" ; then 
1767   echo shar: Will not clobber existing file \"'grind'\"
1768 else
1769 echo shar: Extracting \"'grind'\" \(201 characters\)
1770 sed "s/^X//" >'grind' <<'END_OF_FILE'
1771 X#!/bin/sh
1772 Xrm -f /tmp/*.dir /tmp/*.pag
1773 Xawk -e '{
1774 X        printf "%s\t", $0
1775 X        for (i = 0; i < 40; i++)
1776 X                printf "%s.", $0
1777 X        printf "\n"
1778 X}' < /usr/dict/words | $1 build /tmp/$2
1779 X
1780 END_OF_FILE
1781 if test 201 -ne `wc -c <'grind'`; then
1782     echo shar: \"'grind'\" unpacked with wrong size!
1783 fi
1784 chmod +x 'grind'
1785 # end of 'grind'
1786 fi
1787 if test -f 'hash.c' -a "${1}" != "-c" ; then 
1788   echo shar: Will not clobber existing file \"'hash.c'\"
1789 else
1790 echo shar: Extracting \"'hash.c'\" \(922 characters\)
1791 sed "s/^X//" >'hash.c' <<'END_OF_FILE'
1792 X/*
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.
1797 X *
1798 X * hashing routine
1799 X */
1800 X
1801 X#include "sdbm.h"
1802 X/*
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. 
1808 X */
1809 Xlong
1810 Xdbm_hash(str, len)
1811 Xregister char *str;
1812 Xregister int len;
1813 X{
1814 X       register unsigned long n = 0;
1815 X
1816 X#ifdef DUFF
1817 X
1818 X#define HASHC  n = *str++ + 65599 * n
1819 X
1820 X       if (len > 0) {
1821 X               register int loop = (len + 8 - 1) >> 3;
1822 X
1823 X               switch(len & (8 - 1)) {
1824 X               case 0: do {
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;
1829 X                       } while (--loop);
1830 X               }
1831 X
1832 X       }
1833 X#else
1834 X       while (len--)
1835 X               n = *str++ + 65599 * n;
1836 X#endif
1837 X       return n;
1838 X}
1839 END_OF_FILE
1840 if test 922 -ne `wc -c <'hash.c'`; then
1841     echo shar: \"'hash.c'\" unpacked with wrong size!
1842 fi
1843 # end of 'hash.c'
1844 fi
1845 if test -f 'makefile' -a "${1}" != "-c" ; then 
1846   echo shar: Will not clobber existing file \"'makefile'\"
1847 else
1848 echo shar: Extracting \"'makefile'\" \(1147 characters\)
1849 sed "s/^X//" >'makefile' <<'END_OF_FILE'
1850 X#
1851 X# makefile for public domain ndbm-clone: sdbm
1852 X# DUFF: use duff's device (loop unroll) in parts of the code
1853 X#
1854 XCFLAGS = -O -DSDBM -DDUFF -DBSD42
1855 X#LDFLAGS = -p
1856 X
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
1862 X
1863 Xall: dbu dba dbd dbe
1864 X
1865 Xdbu: dbu.o sdbm util.o
1866 X       cc $(LDFLAGS) -o dbu dbu.o util.o libsdbm.a
1867 X
1868 Xdba: dba.o util.o
1869 X       cc $(LDFLAGS) -o dba dba.o util.o
1870 Xdbd: dbd.o util.o
1871 X       cc $(LDFLAGS) -o dbd dbd.o util.o
1872 Xdbe: dbe.o sdbm
1873 X       cc $(LDFLAGS) -o dbe dbe.o libsdbm.a
1874 X
1875 Xsdbm: $(OBJS)
1876 X       ar cr libsdbm.a $(OBJS)
1877 X       ranlib libsdbm.a
1878 X###    cp libsdbm.a /usr/lib/libsdbm.a
1879 X
1880 Xdba.o: sdbm.h
1881 Xdbu.o: sdbm.h
1882 Xutil.o:sdbm.h
1883 X
1884 X$(OBJS): sdbm.h tune.h pair.h
1885 X
1886 X#
1887 X# dbu using berkelezoid ndbm routines [if you have them] for testing
1888 X#
1889 X#x-dbu: dbu.o util.o
1890 X#      cc $(CFLAGS) -o x-dbu dbu.o util.o
1891 Xlint:
1892 X       lint -abchx $(SRCS)
1893 X
1894 Xclean:
1895 X       rm -f *.o mon.out core
1896 X
1897 Xpurge:         clean
1898 X       rm -f dbu libsdbm.a dbd dba dbe x-dbu *.dir *.pag
1899 X
1900 Xshar:
1901 X       shar $(MISC) makefile $(SRCS) $(HDRS) >SDBM.SHAR
1902 X
1903 Xreadme:
1904 X       nroff -ms readme.ms | col -b >README
1905 END_OF_FILE
1906 if test 1147 -ne `wc -c <'makefile'`; then
1907     echo shar: \"'makefile'\" unpacked with wrong size!
1908 fi
1909 # end of 'makefile'
1910 fi
1911 if test -f 'pair.c' -a "${1}" != "-c" ; then 
1912   echo shar: Will not clobber existing file \"'pair.c'\"
1913 else
1914 echo shar: Extracting \"'pair.c'\" \(5720 characters\)
1915 sed "s/^X//" >'pair.c' <<'END_OF_FILE'
1916 X/*
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.
1921 X *
1922 X * page-level routines
1923 X */
1924 X
1925 X#ifndef lint
1926 Xstatic char rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";
1927 X#endif
1928 X
1929 X#include "sdbm.h"
1930 X#include "tune.h"
1931 X#include "pair.h"
1932 X
1933 X#ifndef BSD42
1934 X#include <memory.h>
1935 X#endif
1936 X
1937 X#define exhash(item)   dbm_hash((item).dptr, (item).dsize)
1938 X
1939 X/* 
1940 X * forward 
1941 X */
1942 Xstatic int seepair proto((char *, int, char *, int));
1943 X
1944 X/*
1945 X * page format:
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 *     +--------+----------+----------+
1957 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.
1962 X */
1963 X
1964 Xint
1965 Xfitpair(pag, need)
1966 Xchar *pag;
1967 Xint need;
1968 X{
1969 X       register int n;
1970 X       register int off;
1971 X       register int free;
1972 X       register short *ino = (short *) pag;
1973 X
1974 X       off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
1975 X       free = off - (n + 1) * sizeof(short);
1976 X       need += 2 * sizeof(short);
1977 X
1978 X       debug(("free %d need %d\n", free, need));
1979 X
1980 X       return need <= free;
1981 X}
1982 X
1983 Xvoid
1984 Xputpair(pag, key, val)
1985 Xchar *pag;
1986 Xdatum key;
1987 Xdatum val;
1988 X{
1989 X       register int n;
1990 X       register int off;
1991 X       register short *ino = (short *) pag;
1992 X
1993 X       off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
1994 X/*
1995 X * enter the key first
1996 X */
1997 X       off -= key.dsize;
1998 X       (void) memcpy(pag + off, key.dptr, key.dsize);
1999 X       ino[n + 1] = off;
2000 X/*
2001 X * now the data
2002 X */
2003 X       off -= val.dsize;
2004 X       (void) memcpy(pag + off, val.dptr, val.dsize);
2005 X       ino[n + 2] = off;
2006 X/*
2007 X * adjust item count
2008 X */
2009 X       ino[0] += 2;
2010 X}
2011 X
2012 Xdatum
2013 Xgetpair(pag, key)
2014 Xchar *pag;
2015 Xdatum key;
2016 X{
2017 X       register int i;
2018 X       register int n;
2019 X       datum val;
2020 X       register short *ino = (short *) pag;
2021 X
2022 X       if ((n = ino[0]) == 0)
2023 X               return nullitem;
2024 X
2025 X       if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
2026 X               return nullitem;
2027 X
2028 X       val.dptr = pag + ino[i + 1];
2029 X       val.dsize = ino[i] - ino[i + 1];
2030 X       return val;
2031 X}
2032 X
2033 X#ifdef SEEDUPS
2034 Xint
2035 Xduppair(pag, key)
2036 Xchar *pag;
2037 Xdatum key;
2038 X{
2039 X       register short *ino = (short *) pag;
2040 X       return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
2041 X}
2042 X#endif
2043 X
2044 Xdatum
2045 Xgetnkey(pag, num)
2046 Xchar *pag;
2047 Xint num;
2048 X{
2049 X       datum key;
2050 X       register int off;
2051 X       register short *ino = (short *) pag;
2052 X
2053 X       num = num * 2 - 1;
2054 X       if (ino[0] == 0 || num > ino[0])
2055 X               return nullitem;
2056 X
2057 X       off = (num > 1) ? ino[num - 1] : PBLKSIZ;
2058 X
2059 X       key.dptr = pag + ino[num];
2060 X       key.dsize = off - ino[num];
2061 X
2062 X       return key;
2063 X}
2064 X
2065 Xint
2066 Xdelpair(pag, key)
2067 Xchar *pag;
2068 Xdatum key;
2069 X{
2070 X       register int n;
2071 X       register int i;
2072 X       register short *ino = (short *) pag;
2073 X
2074 X       if ((n = ino[0]) == 0)
2075 X               return 0;
2076 X
2077 X       if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
2078 X               return 0;
2079 X/*
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]
2085 X */
2086 X       if (i < n - 1) {
2087 X               register int m;
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;
2091 X
2092 X               debug(("free-up %d ", zoo));
2093 X/*
2094 X * shift data/keys down
2095 X */
2096 X               m = ino[i + 1] - ino[n];
2097 X#ifdef DUFF
2098 X#define MOVB   *--dst = *--src
2099 X
2100 X               if (m > 0) {
2101 X                       register int loop = (m + 8 - 1) >> 3;
2102 X
2103 X                       switch (m & (8 - 1)) {
2104 X                       case 0: do {
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;
2109 X                               } while (--loop);
2110 X                       }
2111 X               }
2112 X#else
2113 X#ifdef MEMMOVE
2114 X               memmove(dst, src, m);
2115 X#else
2116 X               while (m--)
2117 X                       *--dst = *--src;
2118 X#endif
2119 X#endif
2120 X/*
2121 X * adjust offset index up
2122 X */
2123 X               while (i < n - 1) {
2124 X                       ino[i] = ino[i + 2] + zoo;
2125 X                       i++;
2126 X               }
2127 X       }
2128 X       ino[0] -= 2;
2129 X       return 1;
2130 X}
2131 X
2132 X/*
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.
2136 X */
2137 Xstatic int
2138 Xseepair(pag, n, key, siz)
2139 Xchar *pag;
2140 Xregister int n;
2141 Xregister char *key;
2142 Xregister int siz;
2143 X{
2144 X       register int i;
2145 X       register int off = PBLKSIZ;
2146 X       register short *ino = (short *) pag;
2147 X
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)
2151 X                       return i;
2152 X               off = ino[i + 1];
2153 X       }
2154 X       return 0;
2155 X}
2156 X
2157 Xvoid
2158 Xsplpage(pag, new, sbit)
2159 Xchar *pag;
2160 Xchar *new;
2161 Xlong sbit;
2162 X{
2163 X       datum key;
2164 X       datum val;
2165 X
2166 X       register int n;
2167 X       register int off = PBLKSIZ;
2168 X       char cur[PBLKSIZ];
2169 X       register short *ino = (short *) cur;
2170 X
2171 X       (void) memcpy(cur, pag, PBLKSIZ);
2172 X       (void) memset(pag, 0, PBLKSIZ);
2173 X       (void) memset(new, 0, PBLKSIZ);
2174 X
2175 X       n = ino[0];
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];
2181 X/*
2182 X * select the page pointer (by looking at sbit) and insert
2183 X */
2184 X               (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
2185 X
2186 X               off = ino[1];
2187 X               n -= 2;
2188 X       }
2189 X
2190 X       debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, 
2191 X              ((short *) new)[0] / 2,
2192 X              ((short *) pag)[0] / 2));
2193 X}
2194 X
2195 X/*
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.
2200 X */
2201 Xint
2202 Xchkpage(pag)
2203 Xchar *pag;
2204 X{
2205 X       register int n;
2206 X       register int off;
2207 X       register short *ino = (short *) pag;
2208 X
2209 X       if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
2210 X               return 0;
2211 X
2212 X       if (n > 0) {
2213 X               off = PBLKSIZ;
2214 X               for (ino++; n > 0; ino += 2) {
2215 X                       if (ino[0] > off || ino[1] > off ||
2216 X                           ino[1] > ino[0])
2217 X                               return 0;
2218 X                       off = ino[1];
2219 X                       n -= 2;
2220 X               }
2221 X       }
2222 X       return 1;
2223 X}
2224 END_OF_FILE
2225 if test 5720 -ne `wc -c <'pair.c'`; then
2226     echo shar: \"'pair.c'\" unpacked with wrong size!
2227 fi
2228 # end of 'pair.c'
2229 fi
2230 if test -f 'pair.h' -a "${1}" != "-c" ; then 
2231   echo shar: Will not clobber existing file \"'pair.h'\"
2232 else
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));
2242 X#ifdef SEEDUPS
2243 Xextern int duppair proto((char *, datum));
2244 X#endif
2245 END_OF_FILE
2246 if test 378 -ne `wc -c <'pair.h'`; then
2247     echo shar: \"'pair.h'\" unpacked with wrong size!
2248 fi
2249 # end of 'pair.h'
2250 fi
2251 if test -f 'readme.ms' -a "${1}" != "-c" ; then 
2252   echo shar: Will not clobber existing file \"'readme.ms'\"
2253 else
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
2258 X.\" change these.
2259 X.\" $Id: readme.ms,v 1.1 90/12/13 13:09:15 oz Exp Locker: oz $
2260 X
2261 X.de P1
2262 X.br
2263 X.nr dT 4
2264 X.nf
2265 X.ft C
2266 X.sp .5
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
2269 X..
2270 X.de P2
2271 X.br
2272 X.ft 1
2273 X.br
2274 X.sp .5
2275 X.br
2276 X.fi
2277 X..
2278 X.\" CW uses the typewriter/courier font.
2279 X.de CW
2280 X\fC\\$1\\fP\\$2
2281 X..
2282 X
2283 X.\" Footnote numbering [by Henry Spencer]
2284 X.\" <text>\*f for a footnote number..
2285 X.\" .FS
2286 X.\" \*F <footnote text>
2287 X.\" .FE
2288 X.\"
2289 X.ds f \\u\\s-2\\n+f\\s+2\\d
2290 X.nr f 0 1
2291 X.ds F \\n+F.
2292 X.nr F 0 1
2293 X
2294 X.ND
2295 X.LP
2296 X.TL
2297 X\fIsdbm\fP \(em Substitute DBM
2298 X.br
2299 Xor
2300 X.br
2301 XBerkeley \fIndbm\fP for Every UN*X\** Made Simple
2302 X.AU
2303 XOzan (oz) Yigit
2304 X.AI
2305 XThe Guild of PD Software Toolmakers
2306 XToronto - Canada
2307 X.sp
2308 Xoz@nexus.yorku.ca
2309 X.LP
2310 X.FS
2311 XUN*X is not a trademark of any (dis)organization.
2312 X.FE
2313 X.sp 2
2314 X\fIImplementation is the sincerest form of flattery. \(em L. Peter Deutsch\fP
2315 X.SH
2316 XA The Clone of the \fIndbm\fP library
2317 X.PP
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
2323 Xcompatible.
2324 XThe \fIsdbm\fP library is not derived from any licensed, proprietary or
2325 Xcopyrighted software.
2326 X.PP
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.
2335 X.PP
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.
2340 X.PP
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
2351 X.CW store
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.)
2355 X.SH
2356 XImportant Compatibility Warning
2357 X.PP
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\**, 
2362 X.FS
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.
2368 X.FE
2369 Xand the hash functions
2370 Xused.
2371 XIt is easy to convert between the \fIdbm/ndbm\fP databases and \fIsdbm\fP
2372 Xby ignoring the index completely: see
2373 X.CW dbd ,
2374 X.CW dbu
2375 Xetc.
2376 X.R
2377 X.LP
2378 X.SH
2379 XNotice of Intellectual Property
2380 X.LP
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.
2386 X.PP
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\**
2393 X.FS
2394 XYou cannot really hoard something that is available to the public at
2395 Xlarge, but try if it makes you feel any better.
2396 X.FE
2397 Xand the right to do other icky things as
2398 Xyou see fit) but those rights are also granted to everyone else.
2399 X.PP
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
2403 Xand/or challenges.
2404 X.SH
2405 XAcknowledgments
2406 X.PP
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.
2414 X.SH
2415 XDistribution Manifest and Notes
2416 X.LP
2417 XThis distribution of \fIsdbm\fP includes (at least) the following:
2418 X.P1
2419 X       CHANGES         change log
2420 X       README          this file.
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
2430 X       makefile        guess.
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
2434 X       sdbm.3          man page
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
2439 X.P2
2440 X.PP
2441 X.CW dbu
2442 Xis a simple database manipulation program\** that tries to look
2443 X.FS
2444 XThe 
2445 X.CW dbd ,
2446 X.CW dba ,
2447 X.CW dbu
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
2450 Xdatabases.
2451 X.FE
2452 Xlike Bell Labs'
2453 X.CW cbt
2454 Xutility. It is currently incomplete in functionality.
2455 XI use
2456 X.CW dbu
2457 Xto test out the routines: it takes (from stdin) tab separated
2458 Xkey/value pairs for commands like
2459 X.CW build
2460 Xor
2461 X.CW insert
2462 Xor takes keys for
2463 Xcommands like
2464 X.CW delete
2465 Xor
2466 X.CW look .
2467 X.P1
2468 X       dbu <build|creat|look|insert|cat|delete> dbmfile
2469 X.P2
2470 X.PP
2471 X.CW dba
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.
2475 X.PP
2476 X.CW dbd
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
2480 Xinput for the
2481 X.CW dbu 
2482 Xutility.
2483 XNote that
2484 X.CW dbd
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.
2488 X.PP
2489 XI have also included a copy of the
2490 X.CW dbe
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
2493 X.CW dbu
2494 Xutility.
2495 X.PP
2496 X.CW dbm.[ch]
2497 Xis a \fIdbm\fP library emulation on top of \fIndbm\fP
2498 X(and hence suitable for \fIsdbm\fP). Written by Robert Elz.
2499 X.PP
2500 XThe \fIsdbm\fP
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
2505 Xuseful.
2506 X.SH
2507 XImplementation Issues
2508 X.PP
2509 XHash functions:
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:
2514 X.P1
2515 X       /*
2516 X        * polynomial conversion ignoring overflows
2517 X        * 65599 nice. 65587 even better.
2518 X        */
2519 X       long
2520 X       dbm_hash(char *str, int len) {
2521 X               register unsigned long n = 0;
2522 X       
2523 X               while (len--)
2524 X                       n = n * 65599 + *str++;
2525 X               return n;
2526 X       }
2527 X.P2
2528 X.PP
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
2532 X\fIsdbm\fP
2533 Xsimply stops working (fails after 
2534 X.CW SPLTMAX
2535 Xattempts to split) when you feed your
2536 XNEWS 
2537 X.CW history
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.
2541 X.PP
2542 XBlock sizes: It seems (from various tests on a few machines) that a page
2543 Xfile block size
2544 X.CW PBLKSIZ
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
2548 X.CW PAIRMAX
2549 X(the maximum size of a key/value pair allowed: should always be at least
2550 Xthree words smaller than
2551 X.CW PBLKSIZ .)
2552 Xaccordingly. The system-wide version of the library
2553 Xshould probably be
2554 Xconfigured with 1024 (distribution default), as this appears to be sufficient
2555 Xfor most common uses of \fIsdbm\fP.
2556 X.SH
2557 XPortability
2558 X.PP
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.
2562 X.SH
2563 XNotes and Miscellaneous
2564 X.PP
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. 
2575 X.PG
2576 X.SH
2577 XReferences
2578 X.LP
2579 X.IP [Lar78] 4m
2580 XP.-A. Larson,
2581 X``Dynamic Hashing'', \fIBIT\fP, vol.  18,  pp. 184-201, 1978.
2582 X.IP [Tho90] 4m
2583 XKen Thompson, \fIprivate communication\fP, Nov. 1990
2584 X.IP [Lit80] 4m
2585 XW. Litwin,
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.
2589 X.IP [Fag79] 4m
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.
2593 X.IP [Wal84] 4m
2594 XRich Wales,
2595 X``Discussion of "dbm" data base system'', \fIUSENET newsgroup unix.wizards\fP,
2596 XJan. 1984.
2597 X.IP [Tor87] 4m
2598 XChris Torek,
2599 X``Re:  dbm.a  and  ndbm.a  archives'', \fIUSENET newsgroup comp.unix\fP,
2600 X1987.
2601 X.IP [Mar79] 4m
2602 XG. N. Martin,
2603 X``Spiral Storage: Incrementally  Augmentable  Hash  Addressed  Storage'',
2604 X\fITechnical Report #27\fP, University of Varwick, Coventry, U.K., 1979.
2605 X.IP [Enb88] 4m
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.
2609 END_OF_FILE
2610 if test 11691 -ne `wc -c <'readme.ms'`; then
2611     echo shar: \"'readme.ms'\" unpacked with wrong size!
2612 fi
2613 # end of 'readme.ms'
2614 fi
2615 if test -f 'readme.ps' -a "${1}" != "-c" ; then 
2616   echo shar: Will not clobber existing file \"'readme.ps'\"
2617 else
2618 echo shar: Extracting \"'readme.ps'\" \(33302 characters\)
2619 sed "s/^X//" >'readme.ps' <<'END_OF_FILE'
2620 X%!PS-Adobe-1.0
2621 X%%Creator: yetti:oz (Ozan Yigit)
2622 X%%Title: stdin (ditroff)
2623 X%%CreationDate: Thu Dec 13 15:56:08 1990
2624 X%%EndComments
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 $
2629 X
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
2645 X/xp{}def
2646 X/xs{docsave restore end}def
2647 X/xt{}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
2661 X/S{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
2669 X/MXY{moveto}def
2670 X/cb{pop}def    % action on unknown char -- nothing for now
2671 X/n{}def/w{}def
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
2700 X
2701 X/Barray 200 array def % 200 values in a wiggle
2702 X/D~{mark}def
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
2710 X  {/i exch def
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
2720 Xend
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
2725 X/docsave save def
2726 X}def
2727 X
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}
2733 X   ifelse}def
2734 X/fractm [.65 0 0 .6 0 0] def
2735 X/fraction
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
2757 Xend
2758 X
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)!
2764 X50 dict dup begin
2765 X/FontType 3 def
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
2771 XEncoding
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
2794 X pop
2795 X/DITfd 100 dict def
2796 X/BuildChar{0 begin
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
2804 X end}def
2805 X/BuildChar load 0 DITfd put
2806 X%/UniqueID 5 def
2807 X/CharProcs 50 dict def
2808 XCharProcs begin
2809 X/space{}def
2810 X/.notdef{}def
2811 X/ru{500 0 rls}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
2825 X
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
2838 Xend
2839 X
2840 X/Metrics 50 dict def Metrics begin
2841 X/.notdef 0 def
2842 X/space 500 def
2843 X/ru 500 def
2844 X/br 0 def
2845 X/lt 416 def
2846 X/lb 416 def
2847 X/rt 416 def
2848 X/rb 416 def
2849 X/lk 416 def
2850 X/rk 416 def
2851 X/rc 416 def
2852 X/lc 416 def
2853 X/rf 416 def
2854 X/lf 416 def
2855 X/bv 416 def
2856 X/ob 350 def
2857 X/bu 350 def
2858 X/ci 750 def
2859 X/bx 750 def
2860 X/sq 750 def
2861 X/rn 500 def
2862 X/ul 500 def
2863 X/vr 0 def
2864 Xend
2865 X
2866 XDITfd 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
2873 Xend
2874 Xend
2875 X/DIThacks exch definefont pop
2876 Xditstart
2877 X(psc)xT
2878 X576 1 1 xr
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
2883 X5(Helvetica)xf 5 f
2884 X6(Helvetica-Bold)xf 6 f
2885 X7(Courier)xf 7 f
2886 X8(Courier-Bold)xf 8 f
2887 X9(Symbol)xf 9 f
2888 X10(DIThacks)xf 10 f
2889 X10 s
2890 X1 f
2891 Xxi
2892 X%%EndProlog
2893 X
2894 X%%Page: 1 1
2895 X10 s 0 xH 0 xS 1 f
2896 X8 s
2897 X2 f
2898 X12 s
2899 X1778 672(sdbm)N
2900 X3 f
2901 X2004(\320)X
2902 X2124(Substitute)X
2903 X2563(DBM)X
2904 X2237 768(or)N
2905 X1331 864(Berkeley)N
2906 X2 f
2907 X1719(ndbm)X
2908 X3 f
2909 X1956(for)X
2910 X2103(Every)X
2911 X2373(UN*X)X
2912 X1 f
2913 X10 s
2914 X2628 832(1)N
2915 X3 f
2916 X12 s
2917 X2692 864(Made)N
2918 X2951(Simple)X
2919 X2 f
2920 X10 s
2921 X2041 1056(Ozan)N
2922 X2230(\(oz\))X
2923 X2375(Yigit)X
2924 X1 f
2925 X1658 1200(The)N
2926 X1803(Guild)X
2927 X2005(of)X
2928 X2092(PD)X
2929 X2214(Software)X
2930 X2524(Toolmakers)X
2931 X2000 1296(Toronto)N
2932 X2278(-)X
2933 X2325(Canada)X
2934 X1965 1488(oz@nexus.yorku.ca)N
2935 X2 f
2936 X555 1804(Implementation)N
2937 X1078(is)X
2938 X1151(the)X
2939 X1269(sincerest)X
2940 X1574(form)X
2941 X1745(of)X
2942 X1827(\257attery.)X
2943 X2094(\320)X
2944 X2185(L.)X
2945 X2269(Peter)X
2946 X2463(Deutsch)X
2947 X3 f
2948 X555 1996(A)N
2949 X633(The)X
2950 X786(Clone)X
2951 X1006(of)X
2952 X1093(the)X
2953 X2 f
2954 X1220(ndbm)X
2955 X3 f
2956 X1418(library)X
2957 X1 f
2958 X755 2120(The)N
2959 X903(sources)X
2960 X1167(accompanying)X
2961 X1658(this)X
2962 X1796(notice)X
2963 X2015(\320)X
2964 X2 f
2965 X2118(sdbm)X
2966 X1 f
2967 X2309(\320)X
2968 X2411(constitute)X
2969 X2744(the)X
2970 X2864(\256rst)X
2971 X3010(public)X
2972 X3232(release)X
2973 X3478(\(Dec.)X
2974 X3677(1990\))X
2975 X3886(of)X
2976 X3975(a)X
2977 X555 2216(complete)N
2978 X874(clone)X
2979 X1073(of)X
2980 X1165(the)X
2981 X1288(Berkeley)X
2982 X1603(UN*X)X
2983 X2 f
2984 X1842(ndbm)X
2985 X1 f
2986 X2045(library.)X
2987 X2304(The)X
2988 X2 f
2989 X2454(sdbm)X
2990 X1 f
2991 X2648(library)X
2992 X2887(is)X
2993 X2965(meant)X
2994 X3186(to)X
2995 X3273(clone)X
2996 X3472(the)X
2997 X3594(proven)X
2998 X3841(func-)X
2999 X555 2312(tionality)N
3000 X846(of)X
3001 X2 f
3002 X938(ndbm)X
3003 X1 f
3004 X1141(as)X
3005 X1233(closely)X
3006 X1485(as)X
3007 X1576(possible,)X
3008 X1882(including)X
3009 X2208(a)X
3010 X2268(few)X
3011 X2413(improvements.)X
3012 X2915(It)X
3013 X2988(is)X
3014 X3065(practical,)X
3015 X3386(easy)X
3016 X3553(to)X
3017 X3639(understand,)X
3018 X555 2408(and)N
3019 X691(compatible.)X
3020 X1107(The)X
3021 X2 f
3022 X1252(sdbm)X
3023 X1 f
3024 X1441(library)X
3025 X1675(is)X
3026 X1748(not)X
3027 X1870(derived)X
3028 X2131(from)X
3029 X2307(any)X
3030 X2443(licensed,)X
3031 X2746(proprietary)X
3032 X3123(or)X
3033 X3210(copyrighted)X
3034 X3613(software.)X
3035 X755 2532(The)N
3036 X2 f
3037 X910(sdbm)X
3038 X1 f
3039 X1109(implementation)X
3040 X1641(is)X
3041 X1723(based)X
3042 X1935(on)X
3043 X2044(a)X
3044 X2109(1978)X
3045 X2298(algorithm)X
3046 X2638([Lar78])X
3047 X2913(by)X
3048 X3022(P.-A.)X
3049 X3220(\(Paul\))X
3050 X3445(Larson)X
3051 X3697(known)X
3052 X3944(as)X
3053 X555 2628(``Dynamic)N
3054 X934(Hashing''.)X
3055 X1326(In)X
3056 X1424(the)X
3057 X1553(course)X
3058 X1794(of)X
3059 X1892(searching)X
3060 X2231(for)X
3061 X2355(a)X
3062 X2421(substitute)X
3063 X2757(for)X
3064 X2 f
3065 X2881(ndbm)X
3066 X1 f
3067 X3059(,)X
3068 X3109(I)X
3069 X3166(prototyped)X
3070 X3543(three)X
3071 X3734(different)X
3072 X555 2724(external-hashing)N
3073 X1119(algorithms)X
3074 X1490([Lar78,)X
3075 X1758(Fag79,)X
3076 X2007(Lit80])X
3077 X2236(and)X
3078 X2381(ultimately)X
3079 X2734(chose)X
3080 X2946(Larson's)X
3081 X3256(algorithm)X
3082 X3596(as)X
3083 X3692(a)X
3084 X3756(basis)X
3085 X3944(of)X
3086 X555 2820(the)N
3087 X2 f
3088 X680(sdbm)X
3089 X1 f
3090 X875(implementation.)X
3091 X1423(The)X
3092 X1574(Bell)X
3093 X1733(Labs)X
3094 X2 f
3095 X1915(dbm)X
3096 X1 f
3097 X2079(\(and)X
3098 X2248(therefore)X
3099 X2 f
3100 X2565(ndbm)X
3101 X1 f
3102 X2743(\))X
3103 X2796(is)X
3104 X2875(based)X
3105 X3084(on)X
3106 X3190(an)X
3107 X3292(algorithm)X
3108 X3629(invented)X
3109 X3931(by)X
3110 X555 2916(Ken)N
3111 X709(Thompson,)X
3112 X1091([Tho90,)X
3113 X1367(Tor87])X
3114 X1610(and)X
3115 X1746(predates)X
3116 X2034(Larson's)X
3117 X2335(work.)X
3118 X755 3040(The)N
3119 X2 f
3120 X903(sdbm)X
3121 X1 f
3122 X1095(programming)X
3123 X1553(interface)X
3124 X1857(is)X
3125 X1932(totally)X
3126 X2158(compatible)X
3127 X2536(with)X
3128 X2 f
3129 X2700(ndbm)X
3130 X1 f
3131 X2900(and)X
3132 X3038(includes)X
3133 X3327(a)X
3134 X3385(slight)X
3135 X3584(improvement)X
3136 X555 3136(in)N
3137 X641(database)X
3138 X942(initialization.)X
3139 X1410(It)X
3140 X1483(is)X
3141 X1560(also)X
3142 X1713(expected)X
3143 X2023(to)X
3144 X2109(be)X
3145 X2208(binary-compatible)X
3146 X2819(under)X
3147 X3025(most)X
3148 X3203(UN*X)X
3149 X3440(versions)X
3150 X3730(that)X
3151 X3873(sup-)X
3152 X555 3232(port)N
3153 X704(the)X
3154 X2 f
3155 X822(ndbm)X
3156 X1 f
3157 X1020(library.)X
3158 X755 3356(The)N
3159 X2 f
3160 X909(sdbm)X
3161 X1 f
3162 X1107(implementation)X
3163 X1638(shares)X
3164 X1868(the)X
3165 X1995(shortcomings)X
3166 X2455(of)X
3167 X2551(the)X
3168 X2 f
3169 X2678(ndbm)X
3170 X1 f
3171 X2885(library,)X
3172 X3148(as)X
3173 X3244(a)X
3174 X3309(side)X
3175 X3467(effect)X
3176 X3680(of)X
3177 X3775(various)X
3178 X555 3452(simpli\256cations)N
3179 X1046(to)X
3180 X1129(the)X
3181 X1248(original)X
3182 X1518(Larson)X
3183 X1762(algorithm.)X
3184 X2114(It)X
3185 X2183(does)X
3186 X2350(produce)X
3187 X2 f
3188 X2629(holes)X
3189 X1 f
3190 X2818(in)X
3191 X2900(the)X
3192 X3018(page)X
3193 X3190(\256le)X
3194 X3312(as)X
3195 X3399(it)X
3196 X3463(writes)X
3197 X3679(pages)X
3198 X3882(past)X
3199 X555 3548(the)N
3200 X680(end)X
3201 X823(of)X
3202 X917(\256le.)X
3203 X1066(\(Larson's)X
3204 X1400(paper)X
3205 X1605(include)X
3206 X1867(a)X
3207 X1929(clever)X
3208 X2152(solution)X
3209 X2435(to)X
3210 X2523(this)X
3211 X2664(problem)X
3212 X2957(that)X
3213 X3103(is)X
3214 X3182(a)X
3215 X3244(result)X
3216 X3448(of)X
3217 X3541(using)X
3218 X3740(the)X
3219 X3864(hash)X
3220 X555 3644(value)N
3221 X758(directly)X
3222 X1032(as)X
3223 X1128(a)X
3224 X1193(block)X
3225 X1400(address.\))X
3226 X1717(On)X
3227 X1844(the)X
3228 X1971(other)X
3229 X2165(hand,)X
3230 X2370(extensive)X
3231 X2702(tests)X
3232 X2873(seem)X
3233 X3067(to)X
3234 X3158(indicate)X
3235 X3441(that)X
3236 X2 f
3237 X3590(sdbm)X
3238 X1 f
3239 X3787(creates)X
3240 X555 3740(fewer)N
3241 X762(holes)X
3242 X954(in)X
3243 X1039(general,)X
3244 X1318(and)X
3245 X1456(the)X
3246 X1576(resulting)X
3247 X1878(page\256les)X
3248 X2185(are)X
3249 X2306(smaller.)X
3250 X2584(The)X
3251 X2 f
3252 X2731(sdbm)X
3253 X1 f
3254 X2922(implementation)X
3255 X3446(is)X
3256 X3521(also)X
3257 X3672(faster)X
3258 X3873(than)X
3259 X2 f
3260 X555 3836(ndbm)N
3261 X1 f
3262 X757(in)X
3263 X843(database)X
3264 X1144(creation.)X
3265 X1467(Unlike)X
3266 X1709(the)X
3267 X2 f
3268 X1831(ndbm)X
3269 X1 f
3270 X2009(,)X
3271 X2053(the)X
3272 X2 f
3273 X2175(sdbm)X
3274 X7 f
3275 X2396(store)X
3276 X1 f
3277 X2660(operation)X
3278 X2987(will)X
3279 X3134(not)X
3280 X3259(``wander)X
3281 X3573(away'')X
3282 X3820(trying)X
3283 X555 3932(to)N
3284 X642(split)X
3285 X804(its)X
3286 X904(data)X
3287 X1063(pages)X
3288 X1271(to)X
3289 X1358(insert)X
3290 X1561(a)X
3291 X1622(datum)X
3292 X1847(that)X
3293 X2 f
3294 X1992(cannot)X
3295 X1 f
3296 X2235(\(due)X
3297 X2403(to)X
3298 X2490(elaborate)X
3299 X2810(worst-case)X
3300 X3179(situations\))X
3301 X3537(be)X
3302 X3637(inserted.)X
3303 X3935(\(It)X
3304 X555 4028(will)N
3305 X699(fail)X
3306 X826(after)X
3307 X994(a)X
3308 X1050(pre-de\256ned)X
3309 X1436(number)X
3310 X1701(of)X
3311 X1788(attempts.\))X
3312 X3 f
3313 X555 4220(Important)N
3314 X931(Compatibility)X
3315 X1426(Warning)X
3316 X1 f
3317 X755 4344(The)N
3318 X2 f
3319 X904(sdbm)X
3320 X1 f
3321 X1097(and)X
3322 X2 f
3323 X1237(ndbm)X
3324 X1 f
3325 X1439(libraries)X
3326 X2 f
3327 X1726(cannot)X
3328 X1 f
3329 X1968(share)X
3330 X2162(databases:)X
3331 X2515(one)X
3332 X2654(cannot)X
3333 X2891(read)X
3334 X3053(the)X
3335 X3174(\(dir/pag\))X
3336 X3478(database)X
3337 X3778(created)X
3338 X555 4440(by)N
3339 X657(the)X
3340 X777(other.)X
3341 X984(This)X
3342 X1148(is)X
3343 X1222(due)X
3344 X1359(to)X
3345 X1442(the)X
3346 X1561(differences)X
3347 X1940(between)X
3348 X2229(the)X
3349 X2 f
3350 X2348(ndbm)X
3351 X1 f
3352 X2547(and)X
3353 X2 f
3354 X2684(sdbm)X
3355 X1 f
3356 X2874(algorithms)X
3357 X8 s
3358 X3216 4415(2)N
3359 X10 s
3360 X4440(,)Y
3361 X3289(and)X
3362 X3426(the)X
3363 X3545(hash)X
3364 X3713(functions)X
3365 X555 4536(used.)N
3366 X769(It)X
3367 X845(is)X
3368 X925(easy)X
3369 X1094(to)X
3370 X1182(convert)X
3371 X1449(between)X
3372 X1743(the)X
3373 X2 f
3374 X1867(dbm/ndbm)X
3375 X1 f
3376 X2231(databases)X
3377 X2565(and)X
3378 X2 f
3379 X2707(sdbm)X
3380 X1 f
3381 X2902(by)X
3382 X3008(ignoring)X
3383 X3305(the)X
3384 X3429(index)X
3385 X3633(completely:)X
3386 X555 4632(see)N
3387 X7 f
3388 X706(dbd)X
3389 X1 f
3390 X(,)S
3391 X7 f
3392 X918(dbu)X
3393 X1 f
3394 X1082(etc.)X
3395 X3 f
3396 X555 4852(Notice)N
3397 X794(of)X
3398 X881(Intellectual)X
3399 X1288(Property)X
3400 X2 f
3401 X555 4976(The)N
3402 X696(entire)X
3403 X1 f
3404 X904(sdbm)X
3405 X2 f
3406 X1118(library)X
3407 X1361(package,)X
3408 X1670(as)X
3409 X1762(authored)X
3410 X2072(by)X
3411 X2169(me,)X
3412 X1 f
3413 X2304(Ozan)X
3414 X2495(S.)X
3415 X2580(Yigit,)X
3416 X2 f
3417 X2785(is)X
3418 X2858(hereby)X
3419 X3097(placed)X
3420 X3331(in)X
3421 X3413(the)X
3422 X3531(public)X
3423 X3751(domain.)X
3424 X1 f
3425 X555 5072(As)N
3426 X670(such,)X
3427 X863(the)X
3428 X987(author)X
3429 X1218(is)X
3430 X1297(not)X
3431 X1425(responsible)X
3432 X1816(for)X
3433 X1936(the)X
3434 X2060(consequences)X
3435 X2528(of)X
3436 X2621(use)X
3437 X2754(of)X
3438 X2847(this)X
3439 X2988(software,)X
3440 X3310(no)X
3441 X3415(matter)X
3442 X3645(how)X
3443 X3808(awful,)X
3444 X555 5168(even)N
3445 X727(if)X
3446 X796(they)X
3447 X954(arise)X
3448 X1126(from)X
3449 X1302(defects)X
3450 X1550(in)X
3451 X1632(it.)X
3452 X1716(There)X
3453 X1924(is)X
3454 X1997(no)X
3455 X2097(expressed)X
3456 X2434(or)X
3457 X2521(implied)X
3458 X2785(warranty)X
3459 X3091(for)X
3460 X3205(the)X
3461 X2 f
3462 X3323(sdbm)X
3463 X1 f
3464 X3512(library.)X
3465 X8 s
3466 X10 f
3467 X555 5316(hhhhhhhhhhhhhhhhhh)N
3468 X6 s
3469 X1 f
3470 X635 5391(1)N
3471 X8 s
3472 X691 5410(UN*X)N
3473 X877(is)X
3474 X936(not)X
3475 X1034(a)X
3476 X1078(trademark)X
3477 X1352(of)X
3478 X1421(any)X
3479 X1529(\(dis\)organization.)X
3480 X6 s
3481 X635 5485(2)N
3482 X8 s
3483 X691 5504(Torek's)N
3484 X908(discussion)X
3485 X1194([Tor87])X
3486 X1411(indicates)X
3487 X1657(that)X
3488 X2 f
3489 X1772(dbm/ndbm)X
3490 X1 f
3491 X2061(implementations)X
3492 X2506(use)X
3493 X2609(the)X
3494 X2705(hash)X
3495 X2840(value)X
3496 X2996(to)X
3497 X3064(traverse)X
3498 X3283(the)X
3499 X3379(radix)X
3500 X3528(trie)X
3501 X3631(dif-)X
3502 X555 5584(ferently)N
3503 X772(than)X
3504 X2 f
3505 X901(sdbm)X
3506 X1 f
3507 X1055(and)X
3508 X1166(as)X
3509 X1238(a)X
3510 X1285(result,)X
3511 X1462(the)X
3512 X1559(page)X
3513 X1698(indexes)X
3514 X1912(are)X
3515 X2008(generated)X
3516 X2274(in)X
3517 X2 f
3518 X2343(different)X
3519 X1 f
3520 X2579(order.)X
3521 X2764(For)X
3522 X2872(more)X
3523 X3021(information,)X
3524 X3357(send)X
3525 X3492(e-mail)X
3526 X3673(to)X
3527 X555 5664(the)N
3528 X649(author.)X
3529 X
3530 X2 p
3531 X%%Page: 2 2
3532 X8 s 0 xH 0 xS 1 f
3533 X10 s
3534 X2216 384(-)N
3535 X2263(2)X
3536 X2323(-)X
3537 X755 672(Since)N
3538 X971(the)X
3539 X2 f
3540 X1107(sdbm)X
3541 X1 f
3542 X1314(library)X
3543 X1566(package)X
3544 X1868(is)X
3545 X1959(in)X
3546 X2058(the)X
3547 X2193(public)X
3548 X2430(domain,)X
3549 X2727(this)X
3550 X2 f
3551 X2879(original)X
3552 X1 f
3553 X3173(release)X
3554 X3434(or)X
3555 X3538(any)X
3556 X3691(additional)X
3557 X555 768(public-domain)N
3558 X1045(releases)X
3559 X1323(of)X
3560 X1413(the)X
3561 X1534(modi\256ed)X
3562 X1841(original)X
3563 X2112(cannot)X
3564 X2348(possibly)X
3565 X2636(\(by)X
3566 X2765(de\256nition\))X
3567 X3120(be)X
3568 X3218(withheld)X
3569 X3520(from)X
3570 X3698(you.)X
3571 X3860(Also)X
3572 X555 864(by)N
3573 X659(de\256nition,)X
3574 X1009(You)X
3575 X1170(\(singular\))X
3576 X1505(have)X
3577 X1680(all)X
3578 X1783(the)X
3579 X1904(rights)X
3580 X2109(to)X
3581 X2194(this)X
3582 X2332(code)X
3583 X2507(\(including)X
3584 X2859(the)X
3585 X2980(right)X
3586 X3154(to)X
3587 X3239(sell)X
3588 X3373(without)X
3589 X3640(permission,)X
3590 X555 960(the)N
3591 X679(right)X
3592 X856(to)X
3593 X944(hoard)X
3594 X8 s
3595 X1127 935(3)N
3596 X10 s
3597 X1185 960(and)N
3598 X1327(the)X
3599 X1451(right)X
3600 X1628(to)X
3601 X1716(do)X
3602 X1821(other)X
3603 X2011(icky)X
3604 X2174(things)X
3605 X2394(as)X
3606 X2486(you)X
3607 X2631(see)X
3608 X2759(\256t\))X
3609 X2877(but)X
3610 X3004(those)X
3611 X3198(rights)X
3612 X3405(are)X
3613 X3529(also)X
3614 X3683(granted)X
3615 X3949(to)X
3616 X555 1056(everyone)N
3617 X870(else.)X
3618 X755 1180(Please)N
3619 X997(note)X
3620 X1172(that)X
3621 X1329(all)X
3622 X1446(previous)X
3623 X1759(distributions)X
3624 X2195(of)X
3625 X2298(this)X
3626 X2449(software)X
3627 X2762(contained)X
3628 X3110(a)X
3629 X3182(copyright)X
3630 X3525(\(which)X
3631 X3784(is)X
3632 X3873(now)X
3633 X555 1276(dropped\))N
3634 X868(to)X
3635 X953(protect)X
3636 X1199(its)X
3637 X1297(origins)X
3638 X1542(and)X
3639 X1681(its)X
3640 X1779(current)X
3641 X2030(public)X
3642 X2253(domain)X
3643 X2516(status)X
3644 X2721(against)X
3645 X2970(any)X
3646 X3108(possible)X
3647 X3392(claims)X
3648 X3623(and/or)X
3649 X3850(chal-)X
3650 X555 1372(lenges.)N
3651 X3 f
3652 X555 1564(Acknowledgments)N
3653 X1 f
3654 X755 1688(Many)N
3655 X966(people)X
3656 X1204(have)X
3657 X1380(been)X
3658 X1556(very)X
3659 X1723(helpful)X
3660 X1974(and)X
3661 X2114(supportive.)X
3662 X2515(A)X
3663 X2596(partial)X
3664 X2824(list)X
3665 X2944(would)X
3666 X3167(necessarily)X
3667 X3547(include)X
3668 X3806(Rayan)X
3669 X555 1784(Zacherissen)N
3670 X963(\(who)X
3671 X1152(contributed)X
3672 X1541(the)X
3673 X1663(man)X
3674 X1824(page,)X
3675 X2019(and)X
3676 X2158(also)X
3677 X2310(hacked)X
3678 X2561(a)X
3679 X2620(MMAP)X
3680 X2887(version)X
3681 X3146(of)X
3682 X2 f
3683 X3236(sdbm)X
3684 X1 f
3685 X3405(\),)X
3686 X3475(Arnold)X
3687 X3725(Robbins,)X
3688 X555 1880(Chris)N
3689 X763(Lewis,)X
3690 X1013(Bill)X
3691 X1166(Davidsen,)X
3692 X1523(Henry)X
3693 X1758(Spencer,)X
3694 X2071(Geoff)X
3695 X2293(Collyer,)X
3696 X2587(Rich)X
3697 X2772(Salz)X
3698 X2944(\(who)X
3699 X3143(got)X
3700 X3279(me)X
3701 X3411(started)X
3702 X3659(in)X
3703 X3755(the)X
3704 X3887(\256rst)X
3705 X555 1976(place\),)N
3706 X792(Johannes)X
3707 X1106(Ruschein)X
3708 X1424(\(who)X
3709 X1609(did)X
3710 X1731(the)X
3711 X1849(minix)X
3712 X2055(port\))X
3713 X2231(and)X
3714 X2367(David)X
3715 X2583(Tilbrook.)X
3716 X2903(I)X
3717 X2950(thank)X
3718 X3148(you)X
3719 X3288(all.)X
3720 X3 f
3721 X555 2168(Distribution)N
3722 X992(Manifest)X
3723 X1315(and)X
3724 X1463(Notes)X
3725 X1 f
3726 X555 2292(This)N
3727 X717(distribution)X
3728 X1105(of)X
3729 X2 f
3730 X1192(sdbm)X
3731 X1 f
3732 X1381(includes)X
3733 X1668(\(at)X
3734 X1773(least\))X
3735 X1967(the)X
3736 X2085(following:)X
3737 X7 f
3738 X747 2436(CHANGES)N
3739 X1323(change)X
3740 X1659(log)X
3741 X747 2532(README)N
3742 X1323(this)X
3743 X1563(file.)X
3744 X747 2628(biblio)N
3745 X1323(a)X
3746 X1419(small)X
3747 X1707(bibliography)X
3748 X2331(on)X
3749 X2475(external)X
3750 X2907(hashing)X
3751 X747 2724(dba.c)N
3752 X1323(a)X
3753 X1419(crude)X
3754 X1707(\(n/s\)dbm)X
3755 X2139(page)X
3756 X2379(file)X
3757 X2619(analyzer)X
3758 X747 2820(dbd.c)N
3759 X1323(a)X
3760 X1419(crude)X
3761 X1707(\(n/s\)dbm)X
3762 X2139(page)X
3763 X2379(file)X
3764 X2619(dumper)X
3765 X2955(\(for)X
3766 X3195(conversion\))X
3767 X747 2916(dbe.1)N
3768 X1323(man)X
3769 X1515(page)X
3770 X1755(for)X
3771 X1947(dbe.c)X
3772 X747 3012(dbe.c)N
3773 X1323(Janick's)X
3774 X1755(database)X
3775 X2187(editor)X
3776 X747 3108(dbm.c)N
3777 X1323(a)X
3778 X1419(dbm)X
3779 X1611(library)X
3780 X1995(emulation)X
3781 X2475(wrapper)X
3782 X2859(for)X
3783 X3051(ndbm/sdbm)X
3784 X747 3204(dbm.h)N
3785 X1323(header)X
3786 X1659(file)X
3787 X1899(for)X
3788 X2091(the)X
3789 X2283(above)X
3790 X747 3300(dbu.c)N
3791 X1323(a)X
3792 X1419(crude)X
3793 X1707(db)X
3794 X1851(management)X
3795 X2379(utility)X
3796 X747 3396(hash.c)N
3797 X1323(hashing)X
3798 X1707(function)X
3799 X747 3492(makefile)N
3800 X1323(guess.)X
3801 X747 3588(pair.c)N
3802 X1323(page-level)X
3803 X1851(routines)X
3804 X2283(\(posted)X
3805 X2667(earlier\))X
3806 X747 3684(pair.h)N
3807 X1323(header)X
3808 X1659(file)X
3809 X1899(for)X
3810 X2091(the)X
3811 X2283(above)X
3812 X747 3780(readme.ms)N
3813 X1323(troff)X
3814 X1611(source)X
3815 X1947(for)X
3816 X2139(the)X
3817 X2331(README)X
3818 X2667(file)X
3819 X747 3876(sdbm.3)N
3820 X1323(man)X
3821 X1515(page)X
3822 X747 3972(sdbm.c)N
3823 X1323(the)X
3824 X1515(real)X
3825 X1755(thing)X
3826 X747 4068(sdbm.h)N
3827 X1323(header)X
3828 X1659(file)X
3829 X1899(for)X
3830 X2091(the)X
3831 X2283(above)X
3832 X747 4164(tune.h)N
3833 X1323(place)X
3834 X1611(for)X
3835 X1803(tuning)X
3836 X2139(&)X
3837 X2235(portability)X
3838 X2811(thingies)X
3839 X747 4260(util.c)N
3840 X1323(miscellaneous)X
3841 X755 4432(dbu)N
3842 X1 f
3843 X924(is)X
3844 X1002(a)X
3845 X1063(simple)X
3846 X1301(database)X
3847 X1603(manipulation)X
3848 X2050(program)X
3849 X8 s
3850 X2322 4407(4)N
3851 X10 s
3852 X2379 4432(that)N
3853 X2524(tries)X
3854 X2687(to)X
3855 X2774(look)X
3856 X2941(like)X
3857 X3086(Bell)X
3858 X3244(Labs')X
3859 X7 f
3860 X3480(cbt)X
3861 X1 f
3862 X3649(utility.)X
3863 X3884(It)X
3864 X3958(is)X
3865 X555 4528(currently)N
3866 X867(incomplete)X
3867 X1245(in)X
3868 X1329(functionality.)X
3869 X1800(I)X
3870 X1849(use)X
3871 X7 f
3872 X2006(dbu)X
3873 X1 f
3874 X2172(to)X
3875 X2255(test)X
3876 X2387(out)X
3877 X2510(the)X
3878 X2629(routines:)X
3879 X2930(it)X
3880 X2995(takes)X
3881 X3181(\(from)X
3882 X3385(stdin\))X
3883 X3588(tab)X
3884 X3707(separated)X
3885 X555 4624(key/value)N
3886 X898(pairs)X
3887 X1085(for)X
3888 X1210(commands)X
3889 X1587(like)X
3890 X7 f
3891 X1765(build)X
3892 X1 f
3893 X2035(or)X
3894 X7 f
3895 X2160(insert)X
3896 X1 f
3897 X2478(or)X
3898 X2575(takes)X
3899 X2770(keys)X
3900 X2947(for)X
3901 X3071(commands)X
3902 X3448(like)X
3903 X7 f
3904 X3626(delete)X
3905 X1 f
3906 X3944(or)X
3907 X7 f
3908 X555 4720(look)N
3909 X1 f
3910 X(.)S
3911 X7 f
3912 X747 4864(dbu)N
3913 X939(<build|creat|look|insert|cat|delete>)X
3914 X2715(dbmfile)X
3915 X755 5036(dba)N
3916 X1 f
3917 X927(is)X
3918 X1008(a)X
3919 X1072(crude)X
3920 X1279(analyzer)X
3921 X1580(of)X
3922 X2 f
3923 X1675(dbm/sdbm/ndbm)X
3924 X1 f
3925 X2232(page)X
3926 X2412(\256les.)X
3927 X2593(It)X
3928 X2670(scans)X
3929 X2872(the)X
3930 X2998(entire)X
3931 X3209(page)X
3932 X3389(\256le,)X
3933 X3538(reporting)X
3934 X3859(page)X
3935 X555 5132(level)N
3936 X731(statistics,)X
3937 X1046(and)X
3938 X1182(totals)X
3939 X1375(at)X
3940 X1453(the)X
3941 X1571(end.)X
3942 X7 f
3943 X755 5256(dbd)N
3944 X1 f
3945 X925(is)X
3946 X1004(a)X
3947 X1066(crude)X
3948 X1271(dump)X
3949 X1479(program)X
3950 X1777(for)X
3951 X2 f
3952 X1897(dbm/ndbm/sdbm)X
3953 X1 f
3954 X2452(databases.)X
3955 X2806(It)X
3956 X2881(ignores)X
3957 X3143(the)X
3958 X3267(bitmap,)X
3959 X3534(and)X
3960 X3675(dumps)X
3961 X3913(the)X
3962 X555 5352(data)N
3963 X717(pages)X
3964 X928(in)X
3965 X1018(sequence.)X
3966 X1361(It)X
3967 X1437(can)X
3968 X1576(be)X
3969 X1679(used)X
3970 X1853(to)X
3971 X1942(create)X
3972 X2162(input)X
3973 X2353(for)X
3974 X2474(the)X
3975 X7 f
3976 X2627(dbu)X
3977 X1 f
3978 X2798(utility.)X
3979 X3055(Note)X
3980 X3238(that)X
3981 X7 f
3982 X3413(dbd)X
3983 X1 f
3984 X3584(will)X
3985 X3735(skip)X
3986 X3895(any)X
3987 X8 s
3988 X10 f
3989 X555 5432(hhhhhhhhhhhhhhhhhh)N
3990 X6 s
3991 X1 f
3992 X635 5507(3)N
3993 X8 s
3994 X691 5526(You)N
3995 X817(cannot)X
3996 X1003(really)X
3997 X1164(hoard)X
3998 X1325(something)X
3999 X1608(that)X
4000 X1720(is)X
4001 X1779(available)X
4002 X2025(to)X
4003 X2091(the)X
4004 X2185(public)X
4005 X2361(at)X
4006 X2423(large,)X
4007 X2582(but)X
4008 X2680(try)X
4009 X2767(if)X
4010 X2822(it)X
4011 X2874(makes)X
4012 X3053(you)X
4013 X3165(feel)X
4014 X3276(any)X
4015 X3384(better.)X
4016 X6 s
4017 X635 5601(4)N
4018 X8 s
4019 X691 5620(The)N
4020 X7 f
4021 X829(dbd)X
4022 X1 f
4023 X943(,)X
4024 X7 f
4025 X998(dba)X
4026 X1 f
4027 X1112(,)X
4028 X7 f
4029 X1167(dbu)X
4030 X1 f
4031 X1298(utilities)X
4032 X1508(are)X
4033 X1602(quick)X
4034 X1761(hacks)X
4035 X1923(and)X
4036 X2032(are)X
4037 X2126(not)X
4038 X2225(\256t)X
4039 X2295(for)X
4040 X2385(production)X
4041 X2678(use.)X
4042 X2795(They)X
4043 X2942(were)X
4044 X3081(developed)X
4045 X3359(late)X
4046 X3467(one)X
4047 X3575(night,)X
4048 X555 5700(just)N
4049 X664(to)X
4050 X730(test)X
4051 X835(out)X
4052 X2 f
4053 X933(sdbm)X
4054 X1 f
4055 X1068(,)X
4056 X1100(and)X
4057 X1208(convert)X
4058 X1415(some)X
4059 X1566(databases.)X
4060 X
4061 X3 p
4062 X%%Page: 3 3
4063 X8 s 0 xH 0 xS 1 f
4064 X10 s
4065 X2216 384(-)N
4066 X2263(3)X
4067 X2323(-)X
4068 X555 672(NULLs)N
4069 X821(in)X
4070 X903(the)X
4071 X1021(key)X
4072 X1157(and)X
4073 X1293(data)X
4074 X1447(\256elds,)X
4075 X1660(thus)X
4076 X1813(is)X
4077 X1886(unsuitable)X
4078 X2235(to)X
4079 X2317(convert)X
4080 X2578(some)X
4081 X2767(peculiar)X
4082 X3046(databases)X
4083 X3374(that)X
4084 X3514(insist)X
4085 X3702(in)X
4086 X3784(includ-)X
4087 X555 768(ing)N
4088 X677(the)X
4089 X795(terminating)X
4090 X1184(null.)X
4091 X755 892(I)N
4092 X841(have)X
4093 X1052(also)X
4094 X1240(included)X
4095 X1575(a)X
4096 X1670(copy)X
4097 X1885(of)X
4098 X2011(the)X
4099 X7 f
4100 X2195(dbe)X
4101 X1 f
4102 X2397(\()X
4103 X2 f
4104 X2424(ndbm)X
4105 X1 f
4106 X2660(DataBase)X
4107 X3026(Editor\))X
4108 X3311(by)X
4109 X3449(Janick)X
4110 X3712(Bergeron)X
4111 X555 988([janick@bnr.ca])N
4112 X1098(for)X
4113 X1212(your)X
4114 X1379(pleasure.)X
4115 X1687(You)X
4116 X1845(may)X
4117 X2003(\256nd)X
4118 X2147(it)X
4119 X2211(more)X
4120 X2396(useful)X
4121 X2612(than)X
4122 X2770(the)X
4123 X2888(little)X
4124 X7 f
4125 X3082(dbu)X
4126 X1 f
4127 X3246(utility.)X
4128 X7 f
4129 X755 1112(dbm.[ch])N
4130 X1 f
4131 X1169(is)X
4132 X1252(a)X
4133 X2 f
4134 X1318(dbm)X
4135 X1 f
4136 X1486(library)X
4137 X1730(emulation)X
4138 X2079(on)X
4139 X2188(top)X
4140 X2319(of)X
4141 X2 f
4142 X2415(ndbm)X
4143 X1 f
4144 X2622(\(and)X
4145 X2794(hence)X
4146 X3011(suitable)X
4147 X3289(for)X
4148 X2 f
4149 X3412(sdbm)X
4150 X1 f
4151 X3581(\).)X
4152 X3657(Written)X
4153 X3931(by)X
4154 X555 1208(Robert)N
4155 X793(Elz.)X
4156 X755 1332(The)N
4157 X2 f
4158 X901(sdbm)X
4159 X1 f
4160 X1090(library)X
4161 X1324(has)X
4162 X1451(been)X
4163 X1623(around)X
4164 X1866(in)X
4165 X1948(beta)X
4166 X2102(test)X
4167 X2233(for)X
4168 X2347(quite)X
4169 X2527(a)X
4170 X2583(long)X
4171 X2745(time,)X
4172 X2927(and)X
4173 X3063(from)X
4174 X3239(whatever)X
4175 X3554(little)X
4176 X3720(feedback)X
4177 X555 1428(I)N
4178 X609(received)X
4179 X909(\(maybe)X
4180 X1177(no)X
4181 X1284(news)X
4182 X1476(is)X
4183 X1555(good)X
4184 X1741(news\),)X
4185 X1979(I)X
4186 X2032(believe)X
4187 X2290(it)X
4188 X2360(has)X
4189 X2493(been)X
4190 X2671(functioning)X
4191 X3066(without)X
4192 X3336(any)X
4193 X3478(signi\256cant)X
4194 X3837(prob-)X
4195 X555 1524(lems.)N
4196 X752(I)X
4197 X805(would,)X
4198 X1051(of)X
4199 X1144(course,)X
4200 X1400(appreciate)X
4201 X1757(all)X
4202 X1863(\256xes)X
4203 X2040(and/or)X
4204 X2271(improvements.)X
4205 X2774(Portability)X
4206 X3136(enhancements)X
4207 X3616(would)X
4208 X3841(espe-)X
4209 X555 1620(cially)N
4210 X753(be)X
4211 X849(useful.)X
4212 X3 f
4213 X555 1812(Implementation)N
4214 X1122(Issues)X
4215 X1 f
4216 X755 1936(Hash)N
4217 X944(functions:)X
4218 X1288(The)X
4219 X1437(algorithm)X
4220 X1772(behind)X
4221 X2 f
4222 X2014(sdbm)X
4223 X1 f
4224 X2207(implementation)X
4225 X2733(needs)X
4226 X2939(a)X
4227 X2998(good)X
4228 X3181(bit-scrambling)X
4229 X3671(hash)X
4230 X3841(func-)X
4231 X555 2032(tion)N
4232 X702(to)X
4233 X787(be)X
4234 X886(effective.)X
4235 X1211(I)X
4236 X1261(ran)X
4237 X1387(into)X
4238 X1534(a)X
4239 X1593(set)X
4240 X1705(of)X
4241 X1795(constants)X
4242 X2116(for)X
4243 X2233(a)X
4244 X2292(simple)X
4245 X2528(hash)X
4246 X2698(function)X
4247 X2988(that)X
4248 X3130(seem)X
4249 X3317(to)X
4250 X3401(help)X
4251 X2 f
4252 X3561(sdbm)X
4253 X1 f
4254 X3752(perform)X
4255 X555 2128(better)N
4256 X758(than)X
4257 X2 f
4258 X916(ndbm)X
4259 X1 f
4260 X1114(for)X
4261 X1228(various)X
4262 X1484(inputs:)X
4263 X7 f
4264 X747 2272(/*)N
4265 X795 2368(*)N
4266 X891(polynomial)X
4267 X1419(conversion)X
4268 X1947(ignoring)X
4269 X2379(overflows)X
4270 X795 2464(*)N
4271 X891(65599)X
4272 X1179(nice.)X
4273 X1467(65587)X
4274 X1755(even)X
4275 X1995(better.)X
4276 X795 2560(*/)N
4277 X747 2656(long)N
4278 X747 2752(dbm_hash\(char)N
4279 X1419(*str,)X
4280 X1707(int)X
4281 X1899(len\))X
4282 X2139({)X
4283 X939 2848(register)N
4284 X1371(unsigned)X
4285 X1803(long)X
4286 X2043(n)X
4287 X2139(=)X
4288 X2235(0;)X
4289 X939 3040(while)N
4290 X1227(\(len--\))X
4291 X1131 3136(n)N
4292 X1227(=)X
4293 X1323(n)X
4294 X1419(*)X
4295 X1515(65599)X
4296 X1803(+)X
4297 X1899(*str++;)X
4298 X939 3232(return)N
4299 X1275(n;)X
4300 X747 3328(})N
4301 X1 f
4302 X755 3500(There)N
4303 X975(may)X
4304 X1145(be)X
4305 X1253(better)X
4306 X1467(hash)X
4307 X1645(functions)X
4308 X1974(for)X
4309 X2099(the)X
4310 X2228(purposes)X
4311 X2544(of)X
4312 X2642(dynamic)X
4313 X2949(hashing.)X
4314 X3269(Try)X
4315 X3416(your)X
4316 X3594(favorite,)X
4317 X3895(and)X
4318 X555 3596(check)N
4319 X766(the)X
4320 X887(page\256le.)X
4321 X1184(If)X
4322 X1261(it)X
4323 X1328(contains)X
4324 X1618(too)X
4325 X1743(many)X
4326 X1944(pages)X
4327 X2150(with)X
4328 X2315(too)X
4329 X2440(many)X
4330 X2641(holes,)X
4331 X2853(\(in)X
4332 X2965(relation)X
4333 X3233(to)X
4334 X3318(this)X
4335 X3456(one)X
4336 X3595(for)X
4337 X3712(example\))X
4338 X555 3692(or)N
4339 X656(if)X
4340 X2 f
4341 X739(sdbm)X
4342 X1 f
4343 X942(simply)X
4344 X1193(stops)X
4345 X1391(working)X
4346 X1692(\(fails)X
4347 X1891(after)X
4348 X7 f
4349 X2101(SPLTMAX)X
4350 X1 f
4351 X2471(attempts)X
4352 X2776(to)X
4353 X2872(split\))X
4354 X3070(when)X
4355 X3278(you)X
4356 X3432(feed)X
4357 X3604(your)X
4358 X3784(NEWS)X
4359 X7 f
4360 X555 3788(history)N
4361 X1 f
4362 X912(\256le)X
4363 X1035(to)X
4364 X1118(it,)X
4365 X1203(you)X
4366 X1344(probably)X
4367 X1650(do)X
4368 X1751(not)X
4369 X1874(have)X
4370 X2047(a)X
4371 X2104(good)X
4372 X2285(hashing)X
4373 X2555(function.)X
4374 X2883(If)X
4375 X2958(you)X
4376 X3099(do)X
4377 X3200(better)X
4378 X3404(\(for)X
4379 X3545(different)X
4380 X3842(types)X
4381 X555 3884(of)N
4382 X642(input\),)X
4383 X873(I)X
4384 X920(would)X
4385 X1140(like)X
4386 X1280(to)X
4387 X1362(know)X
4388 X1560(about)X
4389 X1758(the)X
4390 X1876(function)X
4391 X2163(you)X
4392 X2303(use.)X
4393 X755 4008(Block)N
4394 X967(sizes:)X
4395 X1166(It)X
4396 X1236(seems)X
4397 X1453(\(from)X
4398 X1657(various)X
4399 X1914(tests)X
4400 X2077(on)X
4401 X2178(a)X
4402 X2235(few)X
4403 X2377(machines\))X
4404 X2727(that)X
4405 X2867(a)X
4406 X2923(page)X
4407 X3095(\256le)X
4408 X3217(block)X
4409 X3415(size)X
4410 X7 f
4411 X3588(PBLKSIZ)X
4412 X1 f
4413 X3944(of)X
4414 X555 4104(1024)N
4415 X738(is)X
4416 X814(by)X
4417 X917(far)X
4418 X1030(the)X
4419 X1150(best)X
4420 X1301(for)X
4421 X1417(performance,)X
4422 X1866(but)X
4423 X1990(this)X
4424 X2127(also)X
4425 X2278(happens)X
4426 X2563(to)X
4427 X2647(limit)X
4428 X2819(the)X
4429 X2939(size)X
4430 X3086(of)X
4431 X3175(a)X
4432 X3233(key/value)X
4433 X3567(pair.)X
4434 X3734(Depend-)X
4435 X555 4200(ing)N
4436 X681(on)X
4437 X785(your)X
4438 X956(needs,)X
4439 X1183(you)X
4440 X1327(may)X
4441 X1489(wish)X
4442 X1663(to)X
4443 X1748(increase)X
4444 X2035(the)X
4445 X2156(page)X
4446 X2331(size,)X
4447 X2499(and)X
4448 X2638(also)X
4449 X2790(adjust)X
4450 X7 f
4451 X3032(PAIRMAX)X
4452 X1 f
4453 X3391(\(the)X
4454 X3539(maximum)X
4455 X3886(size)X
4456 X555 4296(of)N
4457 X648(a)X
4458 X710(key/value)X
4459 X1048(pair)X
4460 X1199(allowed:)X
4461 X1501(should)X
4462 X1740(always)X
4463 X1989(be)X
4464 X2090(at)X
4465 X2173(least)X
4466 X2345(three)X
4467 X2531(words)X
4468 X2752(smaller)X
4469 X3013(than)X
4470 X7 f
4471 X3204(PBLKSIZ)X
4472 X1 f
4473 X(.\))S
4474 X3612(accordingly.)X
4475 X555 4392(The)N
4476 X706(system-wide)X
4477 X1137(version)X
4478 X1399(of)X
4479 X1492(the)X
4480 X1616(library)X
4481 X1856(should)X
4482 X2095(probably)X
4483 X2406(be)X
4484 X2508(con\256gured)X
4485 X2877(with)X
4486 X3044(1024)X
4487 X3229(\(distribution)X
4488 X3649(default\),)X
4489 X3944(as)X
4490 X555 4488(this)N
4491 X690(appears)X
4492 X956(to)X
4493 X1038(be)X
4494 X1134(suf\256cient)X
4495 X1452(for)X
4496 X1566(most)X
4497 X1741(common)X
4498 X2041(uses)X
4499 X2199(of)X
4500 X2 f
4501 X2286(sdbm)X
4502 X1 f
4503 X2455(.)X
4504 X3 f
4505 X555 4680(Portability)N
4506 X1 f
4507 X755 4804(This)N
4508 X917(package)X
4509 X1201(has)X
4510 X1328(been)X
4511 X1500(tested)X
4512 X1707(in)X
4513 X1789(many)X
4514 X1987(different)X
4515 X2284(UN*Xes)X
4516 X2585(even)X
4517 X2757(including)X
4518 X3079(minix,)X
4519 X3305(and)X
4520 X3441(appears)X
4521 X3707(to)X
4522 X3789(be)X
4523 X3885(rea-)X
4524 X555 4900(sonably)N
4525 X824(portable.)X
4526 X1127(This)X
4527 X1289(does)X
4528 X1456(not)X
4529 X1578(mean)X
4530 X1772(it)X
4531 X1836(will)X
4532 X1980(port)X
4533 X2129(easily)X
4534 X2336(to)X
4535 X2418(non-UN*X)X
4536 X2799(systems.)X
4537 X3 f
4538 X555 5092(Notes)N
4539 X767(and)X
4540 X915(Miscellaneous)X
4541 X1 f
4542 X755 5216(The)N
4543 X2 f
4544 X913(sdbm)X
4545 X1 f
4546 X1115(is)X
4547 X1201(not)X
4548 X1336(a)X
4549 X1405(very)X
4550 X1581(complicated)X
4551 X2006(package,)X
4552 X2323(at)X
4553 X2414(least)X
4554 X2594(not)X
4555 X2729(after)X
4556 X2910(you)X
4557 X3063(familiarize)X
4558 X3444(yourself)X
4559 X3739(with)X
4560 X3913(the)X
4561 X555 5312(literature)N
4562 X879(on)X
4563 X993(external)X
4564 X1286(hashing.)X
4565 X1589(There)X
4566 X1811(are)X
4567 X1944(other)X
4568 X2143(interesting)X
4569 X2514(algorithms)X
4570 X2889(in)X
4571 X2984(existence)X
4572 X3316(that)X
4573 X3469(ensure)X
4574 X3712(\(approxi-)X
4575 X555 5408(mately\))N
4576 X825(single-read)X
4577 X1207(access)X
4578 X1438(to)X
4579 X1525(a)X
4580 X1586(data)X
4581 X1745(value)X
4582 X1944(associated)X
4583 X2299(with)X
4584 X2466(any)X
4585 X2607(key.)X
4586 X2768(These)X
4587 X2984(are)X
4588 X3107(directory-less)X
4589 X3568(schemes)X
4590 X3864(such)X
4591 X555 5504(as)N
4592 X2 f
4593 X644(linear)X
4594 X857(hashing)X
4595 X1 f
4596 X1132([Lit80])X
4597 X1381(\(+)X
4598 X1475(Larson)X
4599 X1720(variations\),)X
4600 X2 f
4601 X2105(spiral)X
4602 X2313(storage)X
4603 X1 f
4604 X2575([Mar79])X
4605 X2865(or)X
4606 X2954(directory)X
4607 X3265(schemes)X
4608 X3558(such)X
4609 X3726(as)X
4610 X2 f
4611 X3814(exten-)X
4612 X555 5600(sible)N
4613 X731(hashing)X
4614 X1 f
4615 X1009([Fag79])X
4616 X1288(by)X
4617 X1393(Fagin)X
4618 X1600(et)X
4619 X1683(al.)X
4620 X1786(I)X
4621 X1838(do)X
4622 X1943(hope)X
4623 X2124(these)X
4624 X2314(sources)X
4625 X2579(provide)X
4626 X2848(a)X
4627 X2908(reasonable)X
4628 X3276(playground)X
4629 X3665(for)X
4630 X3783(experi-)X
4631 X555 5696(mentation)N
4632 X907(with)X
4633 X1081(other)X
4634 X1277(algorithms.)X
4635 X1690(See)X
4636 X1837(the)X
4637 X1966(June)X
4638 X2144(1988)X
4639 X2335(issue)X
4640 X2526(of)X
4641 X2624(ACM)X
4642 X2837(Computing)X
4643 X3227(Surveys)X
4644 X3516([Enb88])X
4645 X3810(for)X
4646 X3935(an)X
4647 X555 5792(excellent)N
4648 X865(overview)X
4649 X1184(of)X
4650 X1271(the)X
4651 X1389(\256eld.)X
4652 X
4653 X4 p
4654 X%%Page: 4 4
4655 X10 s 0 xH 0 xS 1 f
4656 X2216 384(-)N
4657 X2263(4)X
4658 X2323(-)X
4659 X3 f
4660 X555 672(References)N
4661 X1 f
4662 X555 824([Lar78])N
4663 X875(P.-A.)X
4664 X1064(Larson,)X
4665 X1327(``Dynamic)X
4666 X1695(Hashing'',)X
4667 X2 f
4668 X2056(BIT)X
4669 X1 f
4670 X(,)S
4671 X2216(vol.)X
4672 X2378(18,)X
4673 X2518(pp.)X
4674 X2638(184-201,)X
4675 X2945(1978.)X
4676 X555 948([Tho90])N
4677 X875(Ken)X
4678 X1029(Thompson,)X
4679 X2 f
4680 X1411(private)X
4681 X1658(communication)X
4682 X1 f
4683 X2152(,)X
4684 X2192(Nov.)X
4685 X2370(1990)X
4686 X555 1072([Lit80])N
4687 X875(W.)X
4688 X992(Litwin,)X
4689 X1246(``)X
4690 X1321(Linear)X
4691 X1552(Hashing:)X
4692 X1862(A)X
4693 X1941(new)X
4694 X2096(tool)X
4695 X2261(for)X
4696 X2396(\256le)X
4697 X2539(and)X
4698 X2675(table)X
4699 X2851(addressing'',)X
4700 X2 f
4701 X3288(Proceedings)X
4702 X3709(of)X
4703 X3791(the)X
4704 X3909(6th)X
4705 X875 1168(Conference)N
4706 X1269(on)X
4707 X1373(Very)X
4708 X1548(Large)X
4709 X1782(Dabatases)X
4710 X2163(\(Montreal\))X
4711 X1 f
4712 X2515(,)X
4713 X2558(pp.)X
4714 X2701(212-223,)X
4715 X3031(Very)X
4716 X3215(Large)X
4717 X3426(Database)X
4718 X3744(Founda-)X
4719 X875 1264(tion,)N
4720 X1039(Saratoga,)X
4721 X1360(Calif.,)X
4722 X1580(1980.)X
4723 X555 1388([Fag79])N
4724 X875(R.)X
4725 X969(Fagin,)X
4726 X1192(J.)X
4727 X1284(Nievergelt,)X
4728 X1684(N.)X
4729 X1803(Pippinger,)X
4730 X2175(and)X
4731 X2332(H.)X
4732 X2451(R.)X
4733 X2544(Strong,)X
4734 X2797(``Extendible)X
4735 X3218(Hashing)X
4736 X3505(-)X
4737 X3552(A)X
4738 X3630(Fast)X
4739 X3783(Access)X
4740 X875 1484(Method)N
4741 X1144(for)X
4742 X1258(Dynamic)X
4743 X1572(Files'',)X
4744 X2 f
4745 X1821(ACM)X
4746 X2010(Trans.)X
4747 X2236(Database)X
4748 X2563(Syst.)X
4749 X1 f
4750 X2712(,)X
4751 X2752(vol.)X
4752 X2894(4,)X
4753 X2994(no.3,)X
4754 X3174(pp.)X
4755 X3294(315-344,)X
4756 X3601(Sept.)X
4757 X3783(1979.)X
4758 X555 1608([Wal84])N
4759 X875(Rich)X
4760 X1055(Wales,)X
4761 X1305(``Discussion)X
4762 X1739(of)X
4763 X1835("dbm")X
4764 X2072(data)X
4765 X2235(base)X
4766 X2406(system'',)X
4767 X2 f
4768 X2730(USENET)X
4769 X3051(newsgroup)X
4770 X3430(unix.wizards)X
4771 X1 f
4772 X3836(,)X
4773 X3884(Jan.)X
4774 X875 1704(1984.)N
4775 X555 1828([Tor87])N
4776 X875(Chris)X
4777 X1068(Torek,)X
4778 X1300(``Re:)X
4779 X1505(dbm.a)X
4780 X1743(and)X
4781 X1899(ndbm.a)X
4782 X2177(archives'',)X
4783 X2 f
4784 X2539(USENET)X
4785 X2852(newsgroup)X
4786 X3223(comp.unix)X
4787 X1 f
4788 X3555(,)X
4789 X3595(1987.)X
4790 X555 1952([Mar79])N
4791 X875(G.)X
4792 X974(N.)X
4793 X1073(Martin,)X
4794 X1332(``Spiral)X
4795 X1598(Storage:)X
4796 X1885(Incrementally)X
4797 X2371(Augmentable)X
4798 X2843(Hash)X
4799 X3048(Addressed)X
4800 X3427(Storage'',)X
4801 X2 f
4802 X3766(Techni-)X
4803 X875 2048(cal)N
4804 X993(Report)X
4805 X1231(#27)X
4806 X1 f
4807 X(,)S
4808 X1391(University)X
4809 X1749(of)X
4810 X1836(Varwick,)X
4811 X2153(Coventry,)X
4812 X2491(U.K.,)X
4813 X2687(1979.)X
4814 X555 2172([Enb88])N
4815 X875(R.)X
4816 X977(J.)X
4817 X1057(Enbody)X
4818 X1335(and)X
4819 X1480(H.)X
4820 X1586(C.)X
4821 X1687(Du,)X
4822 X1833(``Dynamic)X
4823 X2209(Hashing)X
4824 X2524(Schemes'',)X
4825 X2 f
4826 X2883(ACM)X
4827 X3080(Computing)X
4828 X3463(Surveys)X
4829 X1 f
4830 X3713(,)X
4831 X3761(vol.)X
4832 X3911(20,)X
4833 X875 2268(no.)N
4834 X995(2,)X
4835 X1075(pp.)X
4836 X1195(85-113,)X
4837 X1462(June)X
4838 X1629(1988.)X
4839 X
4840 X4 p
4841 X%%Trailer
4842 Xxt
4843 X
4844 Xxs
4845 END_OF_FILE
4846 if test 33302 -ne `wc -c <'readme.ps'`; then
4847     echo shar: \"'readme.ps'\" unpacked with wrong size!
4848 fi
4849 # end of 'readme.ps'
4850 fi
4851 if test -f 'sdbm.3' -a "${1}" != "-c" ; then 
4852   echo shar: Will not clobber existing file \"'sdbm.3'\"
4853 else
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"
4858 X.SH NAME
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
4860 X.SH SYNOPSIS
4861 X.nf
4862 X.ft B
4863 X#include <sdbm.h>
4864 X.sp
4865 Xtypedef struct {
4866 X       char *dptr;
4867 X       int dsize;
4868 X} datum;
4869 X.sp
4870 Xdatum nullitem = { NULL, 0 };
4871 X.sp
4872 X\s-1DBM\s0 *dbm_open(char *file, int flags, int mode)
4873 X.sp
4874 X\s-1DBM\s0 *dbm_prep(char *dirname, char *pagname, int flags, int mode)
4875 X.sp
4876 Xvoid dbm_close(\s-1DBM\s0 *db)
4877 X.sp
4878 Xdatum dbm_fetch(\s-1DBM\s0 *db, key)
4879 X.sp
4880 Xint dbm_store(\s-1DBM\s0 *db, datum key, datum val, int flags)
4881 X.sp
4882 Xint dbm_delete(\s-1DBM\s0 *db, datum key)
4883 X.sp
4884 Xdatum dbm_firstkey(\s-1DBM\s0 *db)
4885 X.sp
4886 Xdatum dbm_nextkey(\s-1DBM\s0 *db)
4887 X.sp
4888 Xlong dbm_hash(char *string, int len)
4889 X.sp
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)
4895 X.ft R
4896 X.fi
4897 X.SH DESCRIPTION
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
4926 X.LP
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
4934 X.IR ndbm (3)
4935 Xlibrary.
4936 X.LP
4937 XAn
4938 X.B sdbm
4939 Xdatabase is kept in two files usually given the extensions
4940 X.B \.dir
4941 Xand
4942 X.BR \.pag .
4943 XThe
4944 X.B \.dir
4945 Xfile contains a bitmap representing a forest of binary hash trees, the leaves
4946 Xof which indicate data pages in the
4947 X.B \.pag
4948 Xfile.
4949 X.LP
4950 XThe application interface uses the
4951 X.B datum
4952 Xstructure to describe both
4953 X.I keys
4954 Xand
4955 X.IR value s.
4956 XA
4957 X.B datum
4958 Xspecifies a byte sequence of
4959 X.I dsize
4960 Xsize pointed to by
4961 X.IR dptr .
4962 XIf you use
4963 X.SM ASCII
4964 Xstrings as
4965 X.IR key s
4966 Xor
4967 X.IR value s,
4968 Xthen you must decide whether or not to include the terminating
4969 X.SM NUL
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
4972 X.IR strings (1)
4973 Xcommand applied to the data file.
4974 X.LP
4975 XIn order to allow a process using this package to manipulate multiple
4976 Xdatabases, the applications interface always requires a
4977 X.IR handle ,
4978 Xa
4979 X.BR "DBM *" ,
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
4982 X.BR dbm_open (\|)
4983 Xor
4984 X.BR dbm_prep (\|).
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
4987 Xfiles whereas
4988 X.BR dbm_open (\|)
4989 Xwill take a base file name and call
4990 X.BR dbm_prep (\|)
4991 Xwith the default extensions.
4992 XThe
4993 X.I flags
4994 Xand
4995 X.I mode
4996 Xparameters are the same as for
4997 X.BR open (2).
4998 X.LP
4999 XTo free the resources occupied while a database handle is active, call
5000 X.BR dbm_close (\|).
5001 X.LP
5002 XGiven a handle, one can retrieve data associated with a key by using the
5003 X.BR dbm_fetch (\|)
5004 Xroutine, and associate data with a key by using the
5005 X.BR dbm_store (\|)
5006 Xroutine.
5007 X.LP
5008 XThe values of the
5009 X.I flags
5010 Xparameter for
5011 X.BR dbm_store (\|)
5012 Xcan be either
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.
5018 X.LP
5019 XTo delete a key and its associated value use the
5020 X.BR dbm_delete (\|)
5021 Xroutine.
5022 X.LP
5023 XTo retrieve every key in the database, use a loop like:
5024 X.sp
5025 X.nf
5026 X.ft B
5027 Xfor (key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db))
5028 X        ;
5029 X.ft R
5030 X.fi
5031 X.LP
5032 XThe order of retrieval is unspecified.
5033 X.LP
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
5037 Xown
5038 X.BR dbm_hash (\|)
5039 Xroutine.  Doing so will make the database unintelligable to any other
5040 Xapplications that do not use your specialized hash function.
5041 X.sp
5042 X.LP
5043 XThe following macros are defined in the header file:
5044 X.IP
5045 X.BR dbm_rdonly (\|)
5046 Xreturns true if the database has been opened read\-only.
5047 X.IP
5048 X.BR dbm_error (\|)
5049 Xreturns true if an I/O error has occurred.
5050 X.IP
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.
5054 X.IP
5055 X.BR dbm_dirfno (\|)
5056 Xreturns the file descriptor associated with the bitmap file.
5057 X.IP
5058 X.BR dbm_pagfno (\|)
5059 Xreturns the file descriptor associated with the data file.
5060 X.SH SEE ALSO
5061 X.IR open (2).
5062 X.SH DIAGNOSTICS
5063 XFunctions that return a
5064 X.B "DBM *"
5065 Xhandle will use
5066 X.SM NULL
5067 Xto indicate an error.
5068 XFunctions that return an
5069 X.B int
5070 Xwill use \-1 to indicate an error.  The normal return value in that case is 0.
5071 XFunctions that return a
5072 X.B datum
5073 Xwill return
5074 X.B nullitem
5075 Xto indicate an error.
5076 X.LP
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.
5082 X.LP
5083 XIn general, if a function parameter is invalid,
5084 X.B errno
5085 Xwill be set to
5086 X.BR \s-1EINVAL\s0 .
5087 XIf a write operation is requested on a read-only database,
5088 X.B errno
5089 Xwill be set to
5090 X.BR \s-1ENOPERM\s0 .
5091 XIf a memory allocation (using
5092 X.IR malloc (3))
5093 Xfailed,
5094 X.B errno
5095 Xwill be set to
5096 X.BR \s-1ENOMEM\s0 .
5097 XFor I/O operation failures
5098 X.B errno
5099 Xwill contain the value set by the relevant failed system call, either
5100 X.IR read (2),
5101 X.IR write (2),
5102 Xor
5103 X.IR lseek (2).
5104 X.SH AUTHOR
5105 X.IP "Ozan S. Yigit" (oz@nexus.yorku.ca)
5106 X.SH BUGS
5107 XThe sum of key and value data sizes must not exceed
5108 X.B \s-1PAIRMAX\s0
5109 X(1008 bytes).
5110 X.LP
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.
5113 X.LP
5114 XThe
5115 X.B \.pag
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.
5118 X.LP
5119 XThe contents of
5120 X.B datum
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.
5123 X.LP
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
5130 X.IR ndbm (3)
5131 Xlibrary, the 
5132 X.B sdbm.h
5133 Xheader file should be installed in
5134 X.BR /usr/include/ndbm.h .
5135 X.LP
5136 XThe
5137 X.B nullitem
5138 Xdata item, and the
5139 X.BR dbm_prep (\|),
5140 X.BR dbm_hash (\|),
5141 X.BR dbm_rdonly (\|),
5142 X.BR dbm_dirfno (\|),
5143 Xand
5144 X.BR dbm_pagfno (\|)
5145 Xfunctions are unique to this package.
5146 END_OF_FILE
5147 if test 8952 -ne `wc -c <'sdbm.3'`; then
5148     echo shar: \"'sdbm.3'\" unpacked with wrong size!
5149 fi
5150 # end of 'sdbm.3'
5151 fi
5152 if test -f 'sdbm.c' -a "${1}" != "-c" ; then 
5153   echo shar: Will not clobber existing file \"'sdbm.c'\"
5154 else
5155 echo shar: Extracting \"'sdbm.c'\" \(11029 characters\)
5156 sed "s/^X//" >'sdbm.c' <<'END_OF_FILE'
5157 X/*
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.
5162 X *
5163 X * core routines
5164 X */
5165 X
5166 X#ifndef lint
5167 Xstatic char rcsid[] = "$Id: sdbm.c,v 1.16 90/12/13 13:01:31 oz Exp $";
5168 X#endif
5169 X
5170 X#include "sdbm.h"
5171 X#include "tune.h"
5172 X#include "pair.h"
5173 X
5174 X#include <sys/types.h>
5175 X#include <sys/stat.h>
5176 X#ifdef BSD42
5177 X#include <sys/file.h>
5178 X#else
5179 X#include <fcntl.h>
5180 X#include <memory.h>
5181 X#endif
5182 X#include <errno.h>
5183 X#include <string.h>
5184 X
5185 X#ifdef __STDC__
5186 X#include <stddef.h>
5187 X#endif
5188 X
5189 X#ifndef NULL
5190 X#define NULL   0
5191 X#endif
5192 X
5193 X/*
5194 X * externals
5195 X */
5196 X#ifndef sun
5197 Xextern int errno;
5198 X#endif
5199 X
5200 Xextern char *malloc proto((unsigned int));
5201 Xextern void free proto((void *));
5202 Xextern long lseek();
5203 X
5204 X/*
5205 X * forward
5206 X */
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));
5212 X
5213 X/*
5214 X * useful macros
5215 X */
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)
5219 X
5220 X#define OFF_PAG(off)   (long) (off) * PBLKSIZ
5221 X#define OFF_DIR(off)   (long) (off) * DBLKSIZ
5222 X
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
5232 X};
5233 X
5234 Xdatum nullitem = {NULL, 0};
5235 X
5236 XDBM *
5237 Xdbm_open(file, flags, mode)
5238 Xregister char *file;
5239 Xregister int flags;
5240 Xregister int mode;
5241 X{
5242 X       register DBM *db;
5243 X       register char *dirname;
5244 X       register char *pagname;
5245 X       register int n;
5246 X
5247 X       if (file == NULL || !*file)
5248 X               return errno = EINVAL, (DBM *) NULL;
5249 X/*
5250 X * need space for two seperate filenames
5251 X */
5252 X       n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
5253 X
5254 X       if ((dirname = malloc((unsigned) n)) == NULL)
5255 X               return errno = ENOMEM, (DBM *) NULL;
5256 X/*
5257 X * build the file names
5258 X */
5259 X       dirname = strcat(strcpy(dirname, file), DIRFEXT);
5260 X       pagname = strcpy(dirname + strlen(dirname) + 1, file);
5261 X       pagname = strcat(pagname, PAGFEXT);
5262 X
5263 X       db = dbm_prep(dirname, pagname, flags, mode);
5264 X       free((char *) dirname);
5265 X       return db;
5266 X}
5267 X
5268 XDBM *
5269 Xdbm_prep(dirname, pagname, flags, mode)
5270 Xchar *dirname;
5271 Xchar *pagname;
5272 Xint flags;
5273 Xint mode;
5274 X{
5275 X       register DBM *db;
5276 X       struct stat dstat;
5277 X
5278 X       if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
5279 X               return errno = ENOMEM, (DBM *) NULL;
5280 X
5281 X        db->flags = 0;
5282 X        db->hmask = 0;
5283 X        db->blkptr = 0;
5284 X        db->keyptr = 0;
5285 X/*
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.
5289 X */
5290 X       if (flags & O_WRONLY)
5291 X               flags = (flags & ~O_WRONLY) | O_RDWR;
5292 X
5293 X       else if ((flags & 03) == O_RDONLY)
5294 X               db->flags = DBM_RDONLY;
5295 X/*
5296 X * open the files in sequence, and stat the dirfile.
5297 X * If we fail anywhere, undo everything, return NULL.
5298 X */
5299 X       if ((db->pagf = open(pagname, flags, mode)) > -1) {
5300 X               if ((db->dirf = open(dirname, flags, mode)) > -1) {
5301 X/*
5302 X * need the dirfile size to establish max bit number.
5303 X */
5304 X                       if (fstat(db->dirf, &dstat) == 0) {
5305 X/*
5306 X * zero size: either a fresh database, or one with a single,
5307 X * unsplit data page: dirpage is all zeros.
5308 X */
5309 X                               db->dirbno = (!dstat.st_size) ? 0 : -1;
5310 X                               db->pagbno = -1;
5311 X                               db->maxbno = dstat.st_size * BYTESIZ;
5312 X
5313 X                               (void) memset(db->pagbuf, 0, PBLKSIZ);
5314 X                               (void) memset(db->dirbuf, 0, DBLKSIZ);
5315 X                       /*
5316 X                        * success
5317 X                        */
5318 X                               return db;
5319 X                       }
5320 X                       (void) close(db->dirf);
5321 X               }
5322 X               (void) close(db->pagf);
5323 X       }
5324 X       free((char *) db);
5325 X       return (DBM *) NULL;
5326 X}
5327 X
5328 Xvoid
5329 Xdbm_close(db)
5330 Xregister DBM *db;
5331 X{
5332 X       if (db == NULL)
5333 X               errno = EINVAL;
5334 X       else {
5335 X               (void) close(db->dirf);
5336 X               (void) close(db->pagf);
5337 X               free((char *) db);
5338 X       }
5339 X}
5340 X
5341 Xdatum
5342 Xdbm_fetch(db, key)
5343 Xregister DBM *db;
5344 Xdatum key;
5345 X{
5346 X       if (db == NULL || bad(key))
5347 X               return errno = EINVAL, nullitem;
5348 X
5349 X       if (getpage(db, exhash(key)))
5350 X               return getpair(db->pagbuf, key);
5351 X
5352 X       return ioerr(db), nullitem;
5353 X}
5354 X
5355 Xint
5356 Xdbm_delete(db, key)
5357 Xregister DBM *db;
5358 Xdatum key;
5359 X{
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;
5364 X
5365 X       if (getpage(db, exhash(key))) {
5366 X               if (!delpair(db->pagbuf, key))
5367 X                       return -1;
5368 X/*
5369 X * update the page file
5370 X */
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;
5374 X
5375 X               return 0;
5376 X       }
5377 X
5378 X       return ioerr(db), -1;
5379 X}
5380 X
5381 Xint
5382 Xdbm_store(db, key, val, flags)
5383 Xregister DBM *db;
5384 Xdatum key;
5385 Xdatum val;
5386 Xint flags;
5387 X{
5388 X       int need;
5389 X       register long hash;
5390 X
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;
5395 X
5396 X       need = key.dsize + val.dsize;
5397 X/*
5398 X * is the pair too big (or too small) for this database ??
5399 X */
5400 X       if (need < 0 || need > PAIRMAX)
5401 X               return errno = EINVAL, -1;
5402 X
5403 X       if (getpage(db, (hash = exhash(key)))) {
5404 X/*
5405 X * if we need to replace, delete the key/data pair
5406 X * first. If it is not there, ignore.
5407 X */
5408 X               if (flags == DBM_REPLACE)
5409 X                       (void) delpair(db->pagbuf, key);
5410 X#ifdef SEEDUPS
5411 X               else if (duppair(db->pagbuf, key))
5412 X                       return 1;
5413 X#endif
5414 X/*
5415 X * if we do not have enough room, we have to split.
5416 X */
5417 X               if (!fitpair(db->pagbuf, need))
5418 X                       if (!makroom(db, hash, need))
5419 X                               return ioerr(db), -1;
5420 X/*
5421 X * we have enough room or split is successful. insert the key,
5422 X * and update the page file.
5423 X */
5424 X               (void) putpair(db->pagbuf, key, val);
5425 X
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;
5429 X       /*
5430 X        * success
5431 X        */
5432 X               return 0;
5433 X       }
5434 X
5435 X       return ioerr(db), -1;
5436 X}
5437 X
5438 X/*
5439 X * makroom - make room by splitting the overfull page
5440 X * this routine will attempt to make room for SPLTMAX times before
5441 X * giving up.
5442 X */
5443 Xstatic int
5444 Xmakroom(db, hash, need)
5445 Xregister DBM *db;
5446 Xlong hash;
5447 Xint need;
5448 X{
5449 X       long newp;
5450 X       char twin[PBLKSIZ];
5451 X       char *pag = db->pagbuf;
5452 X       char *new = twin;
5453 X       register int smax = SPLTMAX;
5454 X
5455 X       do {
5456 X/*
5457 X * split the current page
5458 X */
5459 X               (void) splpage(pag, new, db->hmask + 1);
5460 X/*
5461 X * address of the new page
5462 X */
5463 X               newp = (hash & db->hmask) | (db->hmask + 1);
5464 X
5465 X/*
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.
5472 X */
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)
5476 X                               return 0;
5477 X                       db->pagbno = newp;
5478 X                       (void) memcpy(pag, new, PBLKSIZ);
5479 X               }
5480 X               else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
5481 X                        || write(db->pagf, new, PBLKSIZ) < 0)
5482 X                       return 0;
5483 X
5484 X               if (!setdbit(db, db->curbit))
5485 X                       return 0;
5486 X/*
5487 X * see if we have enough room now
5488 X */
5489 X               if (fitpair(pag, need))
5490 X                       return 1;
5491 X/*
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.
5496 X */
5497 X               db->curbit = 2 * db->curbit +
5498 X                       ((hash & (db->hmask + 1)) ? 2 : 1);
5499 X               db->hmask |= db->hmask + 1;
5500 X
5501 X               if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
5502 X                   || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5503 X                       return 0;
5504 X
5505 X       } while (--smax);
5506 X/*
5507 X * if we are here, this is real bad news. After SPLTMAX splits,
5508 X * we still cannot fit the key. say goodnight.
5509 X */
5510 X#ifdef BADMESS
5511 X       (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
5512 X#endif
5513 X       return 0;
5514 X
5515 X}
5516 X
5517 X/*
5518 X * the following two routines will break if
5519 X * deletions aren't taken into account. (ndbm bug)
5520 X */
5521 Xdatum
5522 Xdbm_firstkey(db)
5523 Xregister DBM *db;
5524 X{
5525 X       if (db == NULL)
5526 X               return errno = EINVAL, nullitem;
5527 X/*
5528 X * start at page 0
5529 X */
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;
5533 X       db->pagbno = 0;
5534 X       db->blkptr = 0;
5535 X       db->keyptr = 0;
5536 X
5537 X       return getnext(db);
5538 X}
5539 X
5540 Xdatum
5541 Xdbm_nextkey(db)
5542 Xregister DBM *db;
5543 X{
5544 X       if (db == NULL)
5545 X               return errno = EINVAL, nullitem;
5546 X       return getnext(db);
5547 X}
5548 X
5549 X/*
5550 X * all important binary trie traversal
5551 X */
5552 Xstatic int
5553 Xgetpage(db, hash)
5554 Xregister DBM *db;
5555 Xregister long hash;
5556 X{
5557 X       register int hbit;
5558 X       register long dbit;
5559 X       register long pagb;
5560 X
5561 X       dbit = 0;
5562 X       hbit = 0;
5563 X       while (dbit < db->maxbno && getdbit(db, dbit))
5564 X               dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
5565 X
5566 X       debug(("dbit: %d...", dbit));
5567 X
5568 X       db->curbit = dbit;
5569 X       db->hmask = masks[hbit];
5570 X
5571 X       pagb = hash & db->hmask;
5572 X/*
5573 X * see if the block we need is already in memory.
5574 X * note: this lookaside cache has about 10% hit rate.
5575 X */
5576 X       if (pagb != db->pagbno) { 
5577 X/*
5578 X * note: here, we assume a "hole" is read as 0s.
5579 X * if not, must zero pagbuf first.
5580 X */
5581 X               if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
5582 X                   || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
5583 X                       return 0;
5584 X               if (!chkpage(db->pagbuf))
5585 X                       return 0;
5586 X               db->pagbno = pagb;
5587 X
5588 X               debug(("pag read: %d\n", pagb));
5589 X       }
5590 X       return 1;
5591 X}
5592 X
5593 Xstatic int
5594 Xgetdbit(db, dbit)
5595 Xregister DBM *db;
5596 Xregister long dbit;
5597 X{
5598 X       register long c;
5599 X       register long dirb;
5600 X
5601 X       c = dbit / BYTESIZ;
5602 X       dirb = c / DBLKSIZ;
5603 X
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)
5607 X                       return 0;
5608 X               db->dirbno = dirb;
5609 X
5610 X               debug(("dir read: %d\n", dirb));
5611 X       }
5612 X
5613 X       return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
5614 X}
5615 X
5616 Xstatic int
5617 Xsetdbit(db, dbit)
5618 Xregister DBM *db;
5619 Xregister long dbit;
5620 X{
5621 X       register long c;
5622 X       register long dirb;
5623 X
5624 X       c = dbit / BYTESIZ;
5625 X       dirb = c / DBLKSIZ;
5626 X
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)
5630 X                       return 0;
5631 X               db->dirbno = dirb;
5632 X
5633 X               debug(("dir read: %d\n", dirb));
5634 X       }
5635 X
5636 X       db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
5637 X
5638 X       if (dbit >= db->maxbno)
5639 X               db->maxbno += DBLKSIZ * BYTESIZ;
5640 X
5641 X       if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
5642 X           || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
5643 X               return 0;
5644 X
5645 X       return 1;
5646 X}
5647 X
5648 X/*
5649 X * getnext - get the next key in the page, and if done with
5650 X * the page, try the next page in sequence
5651 X */
5652 Xstatic datum
5653 Xgetnext(db)
5654 Xregister DBM *db;
5655 X{
5656 X       datum key;
5657 X
5658 X       for (;;) {
5659 X               db->keyptr++;
5660 X               key = getnkey(db->pagbuf, db->keyptr);
5661 X               if (key.dptr != NULL)
5662 X                       return key;
5663 X/*
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.
5667 X */
5668 X               db->keyptr = 0;
5669 X               if (db->pagbno != db->blkptr++)
5670 X                       if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
5671 X                               break;
5672 X               db->pagbno = db->blkptr;
5673 X               if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
5674 X                       break;
5675 X               if (!chkpage(db->pagbuf))
5676 X                       break;
5677 X       }
5678 X
5679 X       return ioerr(db), nullitem;
5680 X}
5681 END_OF_FILE
5682 if test 11029 -ne `wc -c <'sdbm.c'`; then
5683     echo shar: \"'sdbm.c'\" unpacked with wrong size!
5684 fi
5685 # end of 'sdbm.c'
5686 fi
5687 if test -f 'sdbm.h' -a "${1}" != "-c" ; then 
5688   echo shar: Will not clobber existing file \"'sdbm.h'\"
5689 else
5690 echo shar: Extracting \"'sdbm.h'\" \(2174 characters\)
5691 sed "s/^X//" >'sdbm.h' <<'END_OF_FILE'
5692 X/*
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. 
5697 X */
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"
5705 X
5706 Xtypedef struct {
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 */
5720 X} DBM;
5721 X
5722 X#define DBM_RDONLY     0x1            /* data base open read-only */
5723 X#define DBM_IOERR      0x2            /* data base I/O error */
5724 X
5725 X/*
5726 X * utility macros
5727 X */
5728 X#define dbm_rdonly(db)         ((db)->flags & DBM_RDONLY)
5729 X#define dbm_error(db)          ((db)->flags & DBM_IOERR)
5730 X
5731 X#define dbm_clearerr(db)       ((db)->flags &= ~DBM_IOERR)  /* ouch */
5732 X
5733 X#define dbm_dirfno(db) ((db)->dirf)
5734 X#define dbm_pagfno(db) ((db)->pagf)
5735 X
5736 Xtypedef struct {
5737 X       char *dptr;
5738 X       int dsize;
5739 X} datum;
5740 X
5741 Xextern datum nullitem;
5742 X
5743 X#ifdef __STDC__
5744 X#define proto(p) p
5745 X#else
5746 X#define proto(p) ()
5747 X#endif
5748 X
5749 X/*
5750 X * flags to dbm_store
5751 X */
5752 X#define DBM_INSERT     0
5753 X#define DBM_REPLACE    1
5754 X
5755 X/*
5756 X * ndbm interface
5757 X */
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 *));
5765 X
5766 X/*
5767 X * other
5768 X */
5769 Xextern DBM *dbm_prep proto((char *, char *, int, int));
5770 Xextern long dbm_hash proto((char *, int));
5771 END_OF_FILE
5772 if test 2174 -ne `wc -c <'sdbm.h'`; then
5773     echo shar: \"'sdbm.h'\" unpacked with wrong size!
5774 fi
5775 # end of 'sdbm.h'
5776 fi
5777 if test -f 'tune.h' -a "${1}" != "-c" ; then 
5778   echo shar: Will not clobber existing file \"'tune.h'\"
5779 else
5780 echo shar: Extracting \"'tune.h'\" \(665 characters\)
5781 sed "s/^X//" >'tune.h' <<'END_OF_FILE'
5782 X/*
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
5786 X */
5787 X
5788 X#define BYTESIZ                8
5789 X
5790 X#ifdef SVID
5791 X#include <unistd.h>
5792 X#endif
5793 X
5794 X#ifdef BSD42
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)
5799 X#endif
5800 X
5801 X/*
5802 X * important tuning parms (hah)
5803 X */
5804 X
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 */
5808 X/*
5809 X * misc
5810 X */
5811 X#ifdef DEBUG
5812 X#define debug(x)       printf x
5813 X#else
5814 X#define debug(x)
5815 X#endif
5816 END_OF_FILE
5817 if test 665 -ne `wc -c <'tune.h'`; then
5818     echo shar: \"'tune.h'\" unpacked with wrong size!
5819 fi
5820 # end of 'tune.h'
5821 fi
5822 if test -f 'util.c' -a "${1}" != "-c" ; then 
5823   echo shar: Will not clobber existing file \"'util.c'\"
5824 else
5825 echo shar: Extracting \"'util.c'\" \(767 characters\)
5826 sed "s/^X//" >'util.c' <<'END_OF_FILE'
5827 X#include <stdio.h>
5828 X#ifdef SDBM
5829 X#include "sdbm.h"
5830 X#else
5831 X#include "ndbm.h"
5832 X#endif
5833 X
5834 Xvoid
5835 Xoops(s1, s2)
5836 Xregister char *s1;
5837 Xregister char *s2;
5838 X{
5839 X       extern int errno, sys_nerr;
5840 X       extern char *sys_errlist[];
5841 X       extern char *progname;
5842 X
5843 X       if (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");
5849 X       exit(1);
5850 X}
5851 X
5852 Xint
5853 Xokpage(pag)
5854 Xchar *pag;
5855 X{
5856 X       register unsigned n;
5857 X       register off;
5858 X       register short *ino = (short *) pag;
5859 X
5860 X       if ((n = ino[0]) > PBLKSIZ / sizeof(short))
5861 X               return 0;
5862 X
5863 X       if (!n)
5864 X               return 1;
5865 X
5866 X       off = PBLKSIZ;
5867 X       for (ino++; n; ino += 2) {
5868 X               if (ino[0] > off || ino[1] > off ||
5869 X                   ino[1] > ino[0])
5870 X                       return 0;
5871 X               off = ino[1];
5872 X               n -= 2;
5873 X       }
5874 X
5875 X       return 1;
5876 X}
5877 END_OF_FILE
5878 if test 767 -ne `wc -c <'util.c'`; then
5879     echo shar: \"'util.c'\" unpacked with wrong size!
5880 fi
5881 # end of 'util.c'
5882 fi
5883 echo shar: End of shell archive.
5884 exit 0