├── .depend ├── .gitignore ├── Changelog ├── LICENSE ├── META ├── Makefile ├── README.md ├── cldbm.c ├── configure ├── dbm.ml ├── dbm.mli └── testdbm.ml /.depend: -------------------------------------------------------------------------------- 1 | dbm.cmo: dbm.cmi 2 | dbm.cmx: dbm.cmi 3 | dbm.cmi: 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile.config 2 | *.cm[aiox] 3 | *.cmx[as] 4 | *.o 5 | *.obj 6 | *.so 7 | *.dll 8 | *.a 9 | *.lib 10 | testdbm.byte 11 | testdbm.opt 12 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | Release 1.4 (2024-07-11) 2 | - Autoconfiguration revised to find GDBM in more places (#16) 3 | - Add missing `free` in `Dbm.fetch` (#18) 4 | 5 | Release 1.3 (2021-10-09) 6 | - Clean up the C stubs; use CAML_NAME_SPACE 7 | - Install dbm.cmx (#13, #14) 8 | 9 | Release 1.2 (2018-05-02) 10 | - Use the GDBM interface when the NDBM interface is not available 11 | - Look for include files in /usr/local/include as well 12 | 13 | Release 1.1 (2016-12-10) 14 | - Apply patches from OPAM package for 1.0 15 | 16 | Release 1.0 (2011-11-22) 17 | - First public release, based on the sources taken from OCaml 3.12.1 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This Library is distributed under the terms of the GNU Library General 2 | Public License version 2 (included below). 3 | 4 | As a special exception to the GNU Library General Public License, you 5 | may link, statically or dynamically, a "work that uses the Library" 6 | with a publicly distributed version of the Library to produce an 7 | executable file containing portions of the Library, and distribute 8 | that executable file under terms of your choice, without any of the 9 | additional requirements listed in clause 6 of the GNU Library General 10 | Public License. By "a publicly distributed version of the Library", 11 | we mean either the unmodified Library as distributed by INRIA, or a 12 | modified version of the Library that is distributed under the 13 | conditions defined in clause 3 of the GNU Library General Public 14 | License. This exception does not however invalidate any other reasons 15 | why the executable file might be covered by the GNU Library General 16 | Public License. 17 | 18 | ---------------------------------------------------------------------- 19 | 20 | GNU LIBRARY GENERAL PUBLIC LICENSE 21 | Version 2, June 1991 22 | 23 | Copyright (C) 1991 Free Software Foundation, Inc. 24 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 25 | Everyone is permitted to copy and distribute verbatim copies 26 | of this license document, but changing it is not allowed. 27 | 28 | [This is the first released version of the library GPL. It is 29 | numbered 2 because it goes with version 2 of the ordinary GPL.] 30 | 31 | Preamble 32 | 33 | The licenses for most software are designed to take away your 34 | freedom to share and change it. By contrast, the GNU General Public 35 | Licenses are intended to guarantee your freedom to share and change 36 | free software--to make sure the software is free for all its users. 37 | 38 | This license, the Library General Public License, applies to some 39 | specially designated Free Software Foundation software, and to any 40 | other libraries whose authors decide to use it. You can use it for 41 | your libraries, too. 42 | 43 | When we speak of free software, we are referring to freedom, not 44 | price. Our General Public Licenses are designed to make sure that you 45 | have the freedom to distribute copies of free software (and charge for 46 | this service if you wish), that you receive source code or can get it 47 | if you want it, that you can change the software or use pieces of it 48 | in new free programs; and that you know you can do these things. 49 | 50 | To protect your rights, we need to make restrictions that forbid 51 | anyone to deny you these rights or to ask you to surrender the rights. 52 | These restrictions translate to certain responsibilities for you if 53 | you distribute copies of the library, or if you modify it. 54 | 55 | For example, if you distribute copies of the library, whether gratis 56 | or for a fee, you must give the recipients all the rights that we gave 57 | you. You must make sure that they, too, receive or can get the source 58 | code. If you link a program with the library, you must provide 59 | complete object files to the recipients so that they can relink them 60 | with the library, after making changes to the library and recompiling 61 | it. And you must show them these terms so they know their rights. 62 | 63 | Our method of protecting your rights has two steps: (1) copyright 64 | the library, and (2) offer you this license which gives you legal 65 | permission to copy, distribute and/or modify the library. 66 | 67 | Also, for each distributor's protection, we want to make certain 68 | that everyone understands that there is no warranty for this free 69 | library. If the library is modified by someone else and passed on, we 70 | want its recipients to know that what they have is not the original 71 | version, so that any problems introduced by others will not reflect on 72 | the original authors' reputations. 73 | 74 | Finally, any free program is threatened constantly by software 75 | patents. We wish to avoid the danger that companies distributing free 76 | software will individually obtain patent licenses, thus in effect 77 | transforming the program into proprietary software. To prevent this, 78 | we have made it clear that any patent must be licensed for everyone's 79 | free use or not licensed at all. 80 | 81 | Most GNU software, including some libraries, is covered by the ordinary 82 | GNU General Public License, which was designed for utility programs. This 83 | license, the GNU Library General Public License, applies to certain 84 | designated libraries. This license is quite different from the ordinary 85 | one; be sure to read it in full, and don't assume that anything in it is 86 | the same as in the ordinary license. 87 | 88 | The reason we have a separate public license for some libraries is that 89 | they blur the distinction we usually make between modifying or adding to a 90 | program and simply using it. Linking a program with a library, without 91 | changing the library, is in some sense simply using the library, and is 92 | analogous to running a utility program or application program. However, in 93 | a textual and legal sense, the linked executable is a combined work, a 94 | derivative of the original library, and the ordinary General Public License 95 | treats it as such. 96 | 97 | Because of this blurred distinction, using the ordinary General 98 | Public License for libraries did not effectively promote software 99 | sharing, because most developers did not use the libraries. We 100 | concluded that weaker conditions might promote sharing better. 101 | 102 | However, unrestricted linking of non-free programs would deprive the 103 | users of those programs of all benefit from the free status of the 104 | libraries themselves. This Library General Public License is intended to 105 | permit developers of non-free programs to use free libraries, while 106 | preserving your freedom as a user of such programs to change the free 107 | libraries that are incorporated in them. (We have not seen how to achieve 108 | this as regards changes in header files, but we have achieved it as regards 109 | changes in the actual functions of the Library.) The hope is that this 110 | will lead to faster development of free libraries. 111 | 112 | The precise terms and conditions for copying, distribution and 113 | modification follow. Pay close attention to the difference between a 114 | "work based on the library" and a "work that uses the library". The 115 | former contains code derived from the library, while the latter only 116 | works together with the library. 117 | 118 | Note that it is possible for a library to be covered by the ordinary 119 | General Public License rather than by this special one. 120 | 121 | GNU LIBRARY GENERAL PUBLIC LICENSE 122 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 123 | 124 | 0. This License Agreement applies to any software library which 125 | contains a notice placed by the copyright holder or other authorized 126 | party saying it may be distributed under the terms of this Library 127 | General Public License (also called "this License"). Each licensee is 128 | addressed as "you". 129 | 130 | A "library" means a collection of software functions and/or data 131 | prepared so as to be conveniently linked with application programs 132 | (which use some of those functions and data) to form executables. 133 | 134 | The "Library", below, refers to any such software library or work 135 | which has been distributed under these terms. A "work based on the 136 | Library" means either the Library or any derivative work under 137 | copyright law: that is to say, a work containing the Library or a 138 | portion of it, either verbatim or with modifications and/or translated 139 | straightforwardly into another language. (Hereinafter, translation is 140 | included without limitation in the term "modification".) 141 | 142 | "Source code" for a work means the preferred form of the work for 143 | making modifications to it. For a library, complete source code means 144 | all the source code for all modules it contains, plus any associated 145 | interface definition files, plus the scripts used to control compilation 146 | and installation of the library. 147 | 148 | Activities other than copying, distribution and modification are not 149 | covered by this License; they are outside its scope. The act of 150 | running a program using the Library is not restricted, and output from 151 | such a program is covered only if its contents constitute a work based 152 | on the Library (independent of the use of the Library in a tool for 153 | writing it). Whether that is true depends on what the Library does 154 | and what the program that uses the Library does. 155 | 156 | 1. You may copy and distribute verbatim copies of the Library's 157 | complete source code as you receive it, in any medium, provided that 158 | you conspicuously and appropriately publish on each copy an 159 | appropriate copyright notice and disclaimer of warranty; keep intact 160 | all the notices that refer to this License and to the absence of any 161 | warranty; and distribute a copy of this License along with the 162 | Library. 163 | 164 | You may charge a fee for the physical act of transferring a copy, 165 | and you may at your option offer warranty protection in exchange for a 166 | fee. 167 | 168 | 2. You may modify your copy or copies of the Library or any portion 169 | of it, thus forming a work based on the Library, and copy and 170 | distribute such modifications or work under the terms of Section 1 171 | above, provided that you also meet all of these conditions: 172 | 173 | a) The modified work must itself be a software library. 174 | 175 | b) You must cause the files modified to carry prominent notices 176 | stating that you changed the files and the date of any change. 177 | 178 | c) You must cause the whole of the work to be licensed at no 179 | charge to all third parties under the terms of this License. 180 | 181 | d) If a facility in the modified Library refers to a function or a 182 | table of data to be supplied by an application program that uses 183 | the facility, other than as an argument passed when the facility 184 | is invoked, then you must make a good faith effort to ensure that, 185 | in the event an application does not supply such function or 186 | table, the facility still operates, and performs whatever part of 187 | its purpose remains meaningful. 188 | 189 | (For example, a function in a library to compute square roots has 190 | a purpose that is entirely well-defined independent of the 191 | application. Therefore, Subsection 2d requires that any 192 | application-supplied function or table used by this function must 193 | be optional: if the application does not supply it, the square 194 | root function must still compute square roots.) 195 | 196 | These requirements apply to the modified work as a whole. If 197 | identifiable sections of that work are not derived from the Library, 198 | and can be reasonably considered independent and separate works in 199 | themselves, then this License, and its terms, do not apply to those 200 | sections when you distribute them as separate works. But when you 201 | distribute the same sections as part of a whole which is a work based 202 | on the Library, the distribution of the whole must be on the terms of 203 | this License, whose permissions for other licensees extend to the 204 | entire whole, and thus to each and every part regardless of who wrote 205 | it. 206 | 207 | Thus, it is not the intent of this section to claim rights or contest 208 | your rights to work written entirely by you; rather, the intent is to 209 | exercise the right to control the distribution of derivative or 210 | collective works based on the Library. 211 | 212 | In addition, mere aggregation of another work not based on the Library 213 | with the Library (or with a work based on the Library) on a volume of 214 | a storage or distribution medium does not bring the other work under 215 | the scope of this License. 216 | 217 | 3. You may opt to apply the terms of the ordinary GNU General Public 218 | License instead of this License to a given copy of the Library. To do 219 | this, you must alter all the notices that refer to this License, so 220 | that they refer to the ordinary GNU General Public License, version 2, 221 | instead of to this License. (If a newer version than version 2 of the 222 | ordinary GNU General Public License has appeared, then you can specify 223 | that version instead if you wish.) Do not make any other change in 224 | these notices. 225 | 226 | Once this change is made in a given copy, it is irreversible for 227 | that copy, so the ordinary GNU General Public License applies to all 228 | subsequent copies and derivative works made from that copy. 229 | 230 | This option is useful when you wish to copy part of the code of 231 | the Library into a program that is not a library. 232 | 233 | 4. You may copy and distribute the Library (or a portion or 234 | derivative of it, under Section 2) in object code or executable form 235 | under the terms of Sections 1 and 2 above provided that you accompany 236 | it with the complete corresponding machine-readable source code, which 237 | must be distributed under the terms of Sections 1 and 2 above on a 238 | medium customarily used for software interchange. 239 | 240 | If distribution of object code is made by offering access to copy 241 | from a designated place, then offering equivalent access to copy the 242 | source code from the same place satisfies the requirement to 243 | distribute the source code, even though third parties are not 244 | compelled to copy the source along with the object code. 245 | 246 | 5. A program that contains no derivative of any portion of the 247 | Library, but is designed to work with the Library by being compiled or 248 | linked with it, is called a "work that uses the Library". Such a 249 | work, in isolation, is not a derivative work of the Library, and 250 | therefore falls outside the scope of this License. 251 | 252 | However, linking a "work that uses the Library" with the Library 253 | creates an executable that is a derivative of the Library (because it 254 | contains portions of the Library), rather than a "work that uses the 255 | library". The executable is therefore covered by this License. 256 | Section 6 states terms for distribution of such executables. 257 | 258 | When a "work that uses the Library" uses material from a header file 259 | that is part of the Library, the object code for the work may be a 260 | derivative work of the Library even though the source code is not. 261 | Whether this is true is especially significant if the work can be 262 | linked without the Library, or if the work is itself a library. The 263 | threshold for this to be true is not precisely defined by law. 264 | 265 | If such an object file uses only numerical parameters, data 266 | structure layouts and accessors, and small macros and small inline 267 | functions (ten lines or less in length), then the use of the object 268 | file is unrestricted, regardless of whether it is legally a derivative 269 | work. (Executables containing this object code plus portions of the 270 | Library will still fall under Section 6.) 271 | 272 | Otherwise, if the work is a derivative of the Library, you may 273 | distribute the object code for the work under the terms of Section 6. 274 | Any executables containing that work also fall under Section 6, 275 | whether or not they are linked directly with the Library itself. 276 | 277 | 6. As an exception to the Sections above, you may also compile or 278 | link a "work that uses the Library" with the Library to produce a 279 | work containing portions of the Library, and distribute that work 280 | under terms of your choice, provided that the terms permit 281 | modification of the work for the customer's own use and reverse 282 | engineering for debugging such modifications. 283 | 284 | You must give prominent notice with each copy of the work that the 285 | Library is used in it and that the Library and its use are covered by 286 | this License. You must supply a copy of this License. If the work 287 | during execution displays copyright notices, you must include the 288 | copyright notice for the Library among them, as well as a reference 289 | directing the user to the copy of this License. Also, you must do one 290 | of these things: 291 | 292 | a) Accompany the work with the complete corresponding 293 | machine-readable source code for the Library including whatever 294 | changes were used in the work (which must be distributed under 295 | Sections 1 and 2 above); and, if the work is an executable linked 296 | with the Library, with the complete machine-readable "work that 297 | uses the Library", as object code and/or source code, so that the 298 | user can modify the Library and then relink to produce a modified 299 | executable containing the modified Library. (It is understood 300 | that the user who changes the contents of definitions files in the 301 | Library will not necessarily be able to recompile the application 302 | to use the modified definitions.) 303 | 304 | b) Accompany the work with a written offer, valid for at 305 | least three years, to give the same user the materials 306 | specified in Subsection 6a, above, for a charge no more 307 | than the cost of performing this distribution. 308 | 309 | c) If distribution of the work is made by offering access to copy 310 | from a designated place, offer equivalent access to copy the above 311 | specified materials from the same place. 312 | 313 | d) Verify that the user has already received a copy of these 314 | materials or that you have already sent this user a copy. 315 | 316 | For an executable, the required form of the "work that uses the 317 | Library" must include any data and utility programs needed for 318 | reproducing the executable from it. However, as a special exception, 319 | the source code distributed need not include anything that is normally 320 | distributed (in either source or binary form) with the major 321 | components (compiler, kernel, and so on) of the operating system on 322 | which the executable runs, unless that component itself accompanies 323 | the executable. 324 | 325 | It may happen that this requirement contradicts the license 326 | restrictions of other proprietary libraries that do not normally 327 | accompany the operating system. Such a contradiction means you cannot 328 | use both them and the Library together in an executable that you 329 | distribute. 330 | 331 | 7. You may place library facilities that are a work based on the 332 | Library side-by-side in a single library together with other library 333 | facilities not covered by this License, and distribute such a combined 334 | library, provided that the separate distribution of the work based on 335 | the Library and of the other library facilities is otherwise 336 | permitted, and provided that you do these two things: 337 | 338 | a) Accompany the combined library with a copy of the same work 339 | based on the Library, uncombined with any other library 340 | facilities. This must be distributed under the terms of the 341 | Sections above. 342 | 343 | b) Give prominent notice with the combined library of the fact 344 | that part of it is a work based on the Library, and explaining 345 | where to find the accompanying uncombined form of the same work. 346 | 347 | 8. You may not copy, modify, sublicense, link with, or distribute 348 | the Library except as expressly provided under this License. Any 349 | attempt otherwise to copy, modify, sublicense, link with, or 350 | distribute the Library is void, and will automatically terminate your 351 | rights under this License. However, parties who have received copies, 352 | or rights, from you under this License will not have their licenses 353 | terminated so long as such parties remain in full compliance. 354 | 355 | 9. You are not required to accept this License, since you have not 356 | signed it. However, nothing else grants you permission to modify or 357 | distribute the Library or its derivative works. These actions are 358 | prohibited by law if you do not accept this License. Therefore, by 359 | modifying or distributing the Library (or any work based on the 360 | Library), you indicate your acceptance of this License to do so, and 361 | all its terms and conditions for copying, distributing or modifying 362 | the Library or works based on it. 363 | 364 | 10. Each time you redistribute the Library (or any work based on the 365 | Library), the recipient automatically receives a license from the 366 | original licensor to copy, distribute, link with or modify the Library 367 | subject to these terms and conditions. You may not impose any further 368 | restrictions on the recipients' exercise of the rights granted herein. 369 | You are not responsible for enforcing compliance by third parties to 370 | this License. 371 | 372 | 11. If, as a consequence of a court judgment or allegation of patent 373 | infringement or for any other reason (not limited to patent issues), 374 | conditions are imposed on you (whether by court order, agreement or 375 | otherwise) that contradict the conditions of this License, they do not 376 | excuse you from the conditions of this License. If you cannot 377 | distribute so as to satisfy simultaneously your obligations under this 378 | License and any other pertinent obligations, then as a consequence you 379 | may not distribute the Library at all. For example, if a patent 380 | license would not permit royalty-free redistribution of the Library by 381 | all those who receive copies directly or indirectly through you, then 382 | the only way you could satisfy both it and this License would be to 383 | refrain entirely from distribution of the Library. 384 | 385 | If any portion of this section is held invalid or unenforceable under any 386 | particular circumstance, the balance of the section is intended to apply, 387 | and the section as a whole is intended to apply in other circumstances. 388 | 389 | It is not the purpose of this section to induce you to infringe any 390 | patents or other property right claims or to contest validity of any 391 | such claims; this section has the sole purpose of protecting the 392 | integrity of the free software distribution system which is 393 | implemented by public license practices. Many people have made 394 | generous contributions to the wide range of software distributed 395 | through that system in reliance on consistent application of that 396 | system; it is up to the author/donor to decide if he or she is willing 397 | to distribute software through any other system and a licensee cannot 398 | impose that choice. 399 | 400 | This section is intended to make thoroughly clear what is believed to 401 | be a consequence of the rest of this License. 402 | 403 | 12. If the distribution and/or use of the Library is restricted in 404 | certain countries either by patents or by copyrighted interfaces, the 405 | original copyright holder who places the Library under this License may add 406 | an explicit geographical distribution limitation excluding those countries, 407 | so that distribution is permitted only in or among countries not thus 408 | excluded. In such case, this License incorporates the limitation as if 409 | written in the body of this License. 410 | 411 | 13. The Free Software Foundation may publish revised and/or new 412 | versions of the Library General Public License from time to time. 413 | Such new versions will be similar in spirit to the present version, 414 | but may differ in detail to address new problems or concerns. 415 | 416 | Each version is given a distinguishing version number. If the Library 417 | specifies a version number of this License which applies to it and 418 | "any later version", you have the option of following the terms and 419 | conditions either of that version or of any later version published by 420 | the Free Software Foundation. If the Library does not specify a 421 | license version number, you may choose any version ever published by 422 | the Free Software Foundation. 423 | 424 | 14. If you wish to incorporate parts of the Library into other free 425 | programs whose distribution conditions are incompatible with these, 426 | write to the author to ask for permission. For software which is 427 | copyrighted by the Free Software Foundation, write to the Free 428 | Software Foundation; we sometimes make exceptions for this. Our 429 | decision will be guided by the two goals of preserving the free status 430 | of all derivatives of our free software and of promoting the sharing 431 | and reuse of software generally. 432 | 433 | NO WARRANTY 434 | 435 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 436 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 437 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 438 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 439 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 440 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 441 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 442 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 443 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 444 | 445 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 446 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 447 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 448 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 449 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 450 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 451 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 452 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 453 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 454 | DAMAGES. 455 | 456 | END OF TERMS AND CONDITIONS 457 | 458 | Appendix: How to Apply These Terms to Your New Libraries 459 | 460 | If you develop a new library, and you want it to be of the greatest 461 | possible use to the public, we recommend making it free software that 462 | everyone can redistribute and change. You can do so by permitting 463 | redistribution under these terms (or, alternatively, under the terms of the 464 | ordinary General Public License). 465 | 466 | To apply these terms, attach the following notices to the library. It is 467 | safest to attach them to the start of each source file to most effectively 468 | convey the exclusion of warranty; and each file should have at least the 469 | "copyright" line and a pointer to where the full notice is found. 470 | 471 | 472 | Copyright (C) 473 | 474 | This library is free software; you can redistribute it and/or 475 | modify it under the terms of the GNU Library General Public 476 | License as published by the Free Software Foundation; either 477 | version 2 of the License, or (at your option) any later version. 478 | 479 | This library is distributed in the hope that it will be useful, 480 | but WITHOUT ANY WARRANTY; without even the implied warranty of 481 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 482 | Library General Public License for more details. 483 | 484 | You should have received a copy of the GNU Library General Public 485 | License along with this library; if not, write to the Free 486 | Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 487 | MA 02111-1307, USA 488 | 489 | Also add information on how to contact you by electronic and paper mail. 490 | 491 | You should also get your employer (if you work as a programmer) or your 492 | school, if any, to sign a "copyright disclaimer" for the library, if 493 | necessary. Here is a sample; alter the names: 494 | 495 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 496 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 497 | 498 | , 1 April 1990 499 | Ty Coon, President of Vice 500 | 501 | That's all there is to it! 502 | -------------------------------------------------------------------------------- /META: -------------------------------------------------------------------------------- 1 | description = "Access to GDBM/NDBM databases" 2 | requires = "" 3 | version = "1.0" 4 | archive(byte) = "dbm.cma" 5 | archive(native) = "dbm.cmxa" 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # # 3 | # CamlDBM # 4 | # # 5 | # Xavier Leroy, projet Gallium, INRIA Rocquencourt # 6 | # # 7 | # Copyright 2011 Institut National de Recherche en Informatique et # 8 | # en Automatique. All rights reserved. This file is distributed # 9 | # under the terms of the GNU Library General Public License, with # 10 | # the special exception on linking described in file ../../LICENSE. # 11 | # # 12 | ######################################################################### 13 | 14 | include Makefile.config 15 | 16 | OCAMLC=ocamlc 17 | OCAMLOPT=ocamlopt 18 | OCAMLMKLIB=ocamlmklib 19 | OCAMLDEP=ocamldep 20 | OCAMLRUN=ocamlrun 21 | O=o 22 | A=a 23 | SO=so 24 | LIBDIR=`ocamlc -where` 25 | STUBLIBDIR=$(LIBDIR)/stublibs 26 | 27 | 28 | all: libcamldbm.$(A) dbm.cma dbm.cmxa dbm.cmxs 29 | 30 | dbm.cma: dbm.cmo 31 | $(OCAMLMKLIB) -o dbm -oc camldbm -linkall dbm.cmo $(DBM_LINK) 32 | 33 | dbm.cmxa: dbm.cmx 34 | $(OCAMLMKLIB) -o dbm -oc camldbm -linkall dbm.cmx $(DBM_LINK) 35 | 36 | dbm.cmxs: dbm.cmxa libcamldbm.$(A) 37 | $(OCAMLOPT) -shared -o dbm.cmxs -I . dbm.cmxa 38 | 39 | libcamldbm.$(A): cldbm.$(O) 40 | $(OCAMLMKLIB) -oc camldbm cldbm.$(O) $(DBM_LINK) 41 | 42 | .SUFFIXES: .ml .mli .cmi .cmo .cmx .$(O) 43 | 44 | .mli.cmi: 45 | $(OCAMLC) -c $(COMPFLAGS) $< 46 | 47 | .ml.cmo: 48 | $(OCAMLC) -c $(COMPFLAGS) $< 49 | 50 | .ml.cmx: 51 | $(OCAMLOPT) -c $(COMPFLAGS) $< 52 | 53 | .c.$(O): 54 | $(OCAMLC) -c -ccopt "$(DBM_INCLUDES)" -ccopt "$(DBM_DEFINES)" -ccopt -DCAML_NAME_SPACE $< 55 | 56 | depend: 57 | $(OCAMLDEP) *.ml *.mli > .depend 58 | 59 | install:: 60 | if test -f dllcamldbm.$(SO); then mkdir $(STUBLIBDIR) || echo Ok; cp dllcamldbm.$(SO) $(STUBLIBDIR)/; fi 61 | cp libcamldbm.$(A) $(LIBDIR)/ 62 | cd $(LIBDIR) && ranlib libcamldbm.$(A) 63 | cp dbm.cmx dbm.cma dbm.cmxa dbm.cmi dbm.mli $(LIBDIR)/ 64 | cp dbm.$(A) $(LIBDIR)/ 65 | cd $(LIBDIR) && ranlib dbm.$(A) 66 | if test -f dbm.cmxs; then cp dbm.cmxs $(LIBDIR)/; fi 67 | 68 | clean:: 69 | rm -f *.cm* *.$(O) *.$(A) *.$(SO) 70 | 71 | testdbm.byte: dbm.cma testdbm.ml 72 | $(OCAMLC) -o $@ dbm.cma testdbm.ml 73 | 74 | testdbm.opt: dbm.cmxa testdbm.ml 75 | $(OCAMLOPT) -ccopt -L. -o $@ dbm.cmxa testdbm.ml 76 | 77 | clean:: 78 | rm -f testdbm.byte testdbm.opt testdatabase.* 79 | 80 | test: testdbm.byte testdbm.opt 81 | rm -f testdatabase.* 82 | ocamlrun -I . ./testdbm.byte 83 | rm -f testdatabase.* 84 | ./testdbm.opt 85 | rm -f testdatabase.* 86 | 87 | 88 | include .depend 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The CamlDBM library 2 | 3 | ## OVERVIEW 4 | 5 | This OCaml library is a binding to the NDBM/GDBM Unix "databases" -- more exactly, persistent key-value stores. 6 | 7 | See the file `dbm.mli` for documentation of the programming inteface. 8 | 9 | This library used to be included in the standard OCaml distribution. This is the standalone distribution of this library, with the same functionalities. 10 | 11 | 12 | ## REQUIREMENTS 13 | 14 | * OCaml 15 | * Either the GDBM library or any NDBM-compatible library. Make sure to install the development files as well. For Debian or Ubuntu, install the package `libgdbm-dev`. 16 | 17 | 18 | ## INSTALLATION 19 | 20 | * Run the "configure" script by typing 21 | ./configure 22 | 23 | * Build the library: 24 | make all 25 | 26 | * Test the library: 27 | make test 28 | 29 | * Install the library: 30 | sudo make install 31 | 32 | 33 | ## USAGE 34 | 35 | In bytecode: 36 | ocamlc dbm.cma 37 | 38 | In native code: 39 | ocamlopt dbm.cmxa 40 | 41 | 42 | ## LICENSE 43 | 44 | This Library is distributed under the terms of the GNU Library General Public License version 2, with a special exception allowing unconstrained static linking. See file LICENSE for details. 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /cldbm.c: -------------------------------------------------------------------------------- 1 | /***********************************************************************/ 2 | /* */ 3 | /* OCaml */ 4 | /* */ 5 | /* Francois Rouaix, projet Cristal, INRIA Rocquencourt */ 6 | /* */ 7 | /* Copyright 1996 Institut National de Recherche en Informatique et */ 8 | /* en Automatique. All rights reserved. This file is distributed */ 9 | /* under the terms of the GNU Library General Public License, with */ 10 | /* the special exception on linking described in file ../../LICENSE. */ 11 | /* */ 12 | /***********************************************************************/ 13 | 14 | /* $Id: cldbm.c 11156 2011-07-27 14:17:02Z doligez $ */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #ifdef DBM_COMPAT 25 | #include 26 | #else 27 | #include 28 | #endif 29 | 30 | #ifndef DBM_COMPAT 31 | typedef struct gdbm_file_info DBM; 32 | #endif 33 | 34 | /* Quite close to sys_open_flags, but we need RDWR */ 35 | static int dbm_open_flags[] = { 36 | O_RDONLY, O_WRONLY, O_RDWR, O_CREAT 37 | }; 38 | 39 | static void raise_dbm (char *errmsg) Noreturn; 40 | 41 | static void raise_dbm(char *errmsg) 42 | { 43 | static const value * dbm_exn = NULL; 44 | if (dbm_exn == NULL) 45 | dbm_exn = caml_named_value("dbmerror"); 46 | caml_raise_with_string(*dbm_exn, errmsg); 47 | } 48 | 49 | #define DBM_val(v) *((DBM **) &Field(v, 0)) 50 | #define DBM_db_memory_val(v) *((datum **) &Field(v, 1)) 51 | 52 | static value alloc_dbm(DBM * db) 53 | { 54 | value res = caml_alloc_small(2, Abstract_tag); 55 | datum *db_mem = malloc(sizeof(datum)); 56 | if (db_mem == NULL) 57 | caml_raise_out_of_memory(); 58 | DBM_val(res) = db; 59 | DBM_db_memory_val(res) = db_mem; 60 | db_mem->dptr = NULL; 61 | db_mem->dsize = 0; 62 | return res; 63 | } 64 | 65 | static DBM * extract_dbm(value vdb) 66 | { 67 | if (DBM_val(vdb) == NULL) raise_dbm("DBM has been closed"); 68 | return DBM_val(vdb); 69 | } 70 | 71 | static value alloc_datum(const datum * d) 72 | { 73 | value res = caml_alloc_string(d->dsize); 74 | memcpy ((char *) String_val (res), d->dptr, d->dsize); 75 | return res; 76 | } 77 | 78 | static void extract_datum(value v, datum * d) 79 | { 80 | d->dptr = (char *) String_val(v); 81 | d->dsize = caml_string_length(v); 82 | } 83 | 84 | /* Dbm.open : string -> Sys.open_flag list -> int -> t */ 85 | value caml_dbm_open(value vfile, value vflags, value vmode) /* ML */ 86 | { 87 | const char *file = String_val(vfile); 88 | int flags = caml_convert_flag_list(vflags, dbm_open_flags); 89 | int mode = Int_val(vmode); 90 | #ifdef DBM_COMPAT 91 | DBM *db = dbm_open(file,flags,mode); 92 | #else 93 | const char *ext = ".pag"; 94 | char *filename = malloc(sizeof(char) * (strlen(file) + strlen(ext) + 1)); 95 | if (filename == NULL) 96 | caml_raise_out_of_memory(); 97 | strcpy(filename, file); 98 | strcat(filename, ext); 99 | DBM *db = gdbm_open(filename,0,flags,mode,NULL); 100 | #endif 101 | 102 | if (db == NULL) 103 | raise_dbm("Can't open file"); 104 | else 105 | return (alloc_dbm(db)); 106 | } 107 | 108 | /* Dbm.close: t -> unit */ 109 | value caml_dbm_close(value vdb) /* ML */ 110 | { 111 | #ifdef DBM_COMPAT 112 | dbm_close(extract_dbm(vdb)); 113 | #else 114 | gdbm_close(extract_dbm(vdb)); 115 | #endif 116 | DBM_val(vdb) = NULL; 117 | return Val_unit; 118 | } 119 | 120 | /* Dbm.fetch: t -> string -> string */ 121 | value caml_dbm_fetch(value vdb, value vkey) /* ML */ 122 | { 123 | datum key, answer; 124 | extract_datum(vkey, &key); 125 | #ifdef DBM_COMPAT 126 | answer = dbm_fetch(extract_dbm(vdb), key); 127 | #else 128 | answer = gdbm_fetch(extract_dbm(vdb), key); 129 | #endif 130 | if (answer.dptr) { 131 | value res = alloc_datum(&answer); 132 | #ifndef DBM_COMPAT 133 | free(answer.dptr); 134 | #endif 135 | return res; 136 | } 137 | else caml_raise_not_found(); 138 | } 139 | 140 | value caml_dbm_insert(value vdb, value vkey, value vcontent) /* ML */ 141 | { 142 | datum key, content; 143 | extract_datum(vkey, &key); 144 | extract_datum(vcontent, &content); 145 | #ifdef DBM_COMPAT 146 | switch(dbm_store(extract_dbm(vdb), key, content, DBM_INSERT)) { 147 | #else 148 | switch(gdbm_store(extract_dbm(vdb), key, content, GDBM_INSERT)) { 149 | #endif 150 | case 0: 151 | return Val_unit; 152 | case 1: /* DBM_INSERT and already existing */ 153 | raise_dbm("Entry already exists"); 154 | default: 155 | raise_dbm("dbm_store failed"); 156 | } 157 | } 158 | 159 | value caml_dbm_replace(value vdb, value vkey, value vcontent) /* ML */ 160 | { 161 | datum key, content; 162 | extract_datum(vkey, &key); 163 | extract_datum(vcontent, &content); 164 | #ifdef DBM_COMPAT 165 | switch(dbm_store(extract_dbm(vdb), key, content, DBM_REPLACE)) { 166 | #else 167 | switch(gdbm_store(extract_dbm(vdb), key, content, GDBM_REPLACE)) { 168 | #endif 169 | case 0: 170 | return Val_unit; 171 | default: 172 | raise_dbm("dbm_store failed"); 173 | } 174 | } 175 | 176 | value caml_dbm_delete(value vdb, value vkey) /* ML */ 177 | { 178 | datum key; 179 | extract_datum(vkey, &key); 180 | #ifdef DBM_COMPAT 181 | if (dbm_delete(extract_dbm(vdb), key) < 0) 182 | #else 183 | if (gdbm_delete(extract_dbm(vdb), key) < 0) 184 | #endif 185 | raise_dbm("dbm_delete"); 186 | else return Val_unit; 187 | } 188 | 189 | value caml_dbm_firstkey(value vdb) /* ML */ 190 | { 191 | #ifdef DBM_COMPAT 192 | datum key = dbm_firstkey(extract_dbm(vdb)); 193 | #else 194 | datum key = gdbm_firstkey(extract_dbm(vdb)); 195 | datum *db_mem = DBM_db_memory_val(vdb); 196 | if (db_mem->dptr != NULL) 197 | free(db_mem->dptr); 198 | (DBM_db_memory_val(vdb))->dptr = key.dptr; 199 | (DBM_db_memory_val(vdb))->dsize = key.dsize; 200 | #endif 201 | 202 | if (key.dptr) return alloc_datum(&key); else caml_raise_not_found(); 203 | } 204 | 205 | value caml_dbm_nextkey(value vdb) /* ML */ 206 | { 207 | #ifdef DBM_COMPAT 208 | datum key = dbm_nextkey(extract_dbm(vdb)); 209 | #else 210 | datum key = {NULL, 0}; 211 | datum *db_mem = DBM_db_memory_val(vdb); 212 | if (db_mem->dptr != NULL) { 213 | key = gdbm_nextkey(extract_dbm(vdb), *db_mem); 214 | free(db_mem->dptr); 215 | (DBM_db_memory_val(vdb))->dptr = key.dptr; 216 | (DBM_db_memory_val(vdb))->dsize = key.dsize; 217 | } 218 | #endif 219 | 220 | if (key.dptr) return alloc_datum(&key); else caml_raise_not_found(); 221 | } 222 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ######################################################################### 4 | # # 5 | # CamlDBM # 6 | # # 7 | # Xavier Leroy, projet Gallium, INRIA Rocquencourt # 8 | # # 9 | # Copyright 2011 Institut National de Recherche en Informatique et # 10 | # en Automatique. All rights reserved. This file is distributed # 11 | # under the terms of the GNU Library General Public License, with # 12 | # the special exception on linking described in file LICENSE. # 13 | # # 14 | ######################################################################### 15 | 16 | version=`ocamlc -version` 17 | 18 | if test $? -ne 0; then 19 | echo "ocamlc not found, aborting." 20 | exit 2 21 | fi 22 | 23 | echo "Configuring for OCaml version $version" 24 | echo 25 | 26 | stdlib=`ocamlc -where` 27 | 28 | hasgot() { 29 | rm -f hasgot.c 30 | (echo "#include <$2>" 31 | echo 'int main() {' 32 | if test $2 = gdbm.h; then 33 | echo ' (void) gdbm_open("foo", 0, 0, 0, NULL);' 34 | else 35 | echo ' (void) dbm_open("foo", 0, 0);' 36 | fi 37 | echo ' return 0;' 38 | echo '}') > hasgot.c 39 | ${CC:-cc} $1 -o hasgot.exe hasgot.c $3 2>/dev/null 40 | res=$? 41 | rm -f hasgot.c hasgot.exe 42 | return $res 43 | } 44 | 45 | dbm_include="not found" 46 | dbm_link="not found" 47 | dbm_defines="" 48 | 49 | for include in \ 50 | "" \ 51 | "-I/usr/include/db1" \ 52 | "-I/usr/include/gdbm" \ 53 | "-I/usr/local/include" \ 54 | "-I/opt/homebrew/include" ; do 55 | if hasgot "$include" ndbm.h ""; then 56 | dbm_include="$include" 57 | dbm_defines="-DDBM_COMPAT" 58 | dbm_link="" 59 | break 60 | elif hasgot "$include" gdbm.h -lgdbm; then 61 | dbm_include="$include" 62 | dbm_link="-lgdbm" 63 | break 64 | elif hasgot "$include" ndbm.h -lndbm; then 65 | dbm_include="$include" 66 | dbm_defines="-DDBM_COMPAT" 67 | dbm_link="-lndbm" 68 | break 69 | elif hasgot "$include" ndbm.h -ldb1; then 70 | dbm_include="$include" 71 | dbm_defines="-DDBM_COMPAT" 72 | dbm_link="-ldb1" 73 | break 74 | fi 75 | done 76 | if test "$dbm_include" = "not found" || test "$dbm_link" = "not found"; then 77 | echo "NDBM and GDBM not found, the \"camldbm\" library cannot be built." 78 | exit 2 79 | fi 80 | 81 | echo "Configuration for the \"camldbm\" library:" 82 | echo " options for compiling .... $dbm_include $dbm_defines" 83 | echo " options for linking ...... $dbm_link" 84 | echo 85 | echo "Configuration successful" 86 | echo 87 | 88 | echo "OCAML_STDLIB=$stdlib" > Makefile.config 89 | echo "DBM_INCLUDES=$dbm_include" >> Makefile.config 90 | echo "DBM_LINK=$dbm_link" >> Makefile.config 91 | echo "DBM_DEFINES=$dbm_defines" >> Makefile.config 92 | 93 | -------------------------------------------------------------------------------- /dbm.ml: -------------------------------------------------------------------------------- 1 | (***********************************************************************) 2 | (* *) 3 | (* OCaml *) 4 | (* *) 5 | (* Francois Rouaix, projet Cristal, INRIA Rocquencourt *) 6 | (* *) 7 | (* Copyright 1996 Institut National de Recherche en Informatique et *) 8 | (* en Automatique. All rights reserved. This file is distributed *) 9 | (* under the terms of the GNU Library General Public License, with *) 10 | (* the special exception on linking described in file ../../LICENSE. *) 11 | (* *) 12 | (***********************************************************************) 13 | 14 | (* $Id: dbm.ml 11156 2011-07-27 14:17:02Z doligez $ *) 15 | 16 | type t 17 | 18 | type open_flag = 19 | Dbm_rdonly | Dbm_wronly | Dbm_rdwr | Dbm_create 20 | 21 | type dbm_flag = 22 | DBM_INSERT 23 | | DBM_REPLACE 24 | 25 | exception Dbm_error of string 26 | 27 | external raw_opendbm : string -> open_flag list -> int -> t 28 | = "caml_dbm_open" 29 | 30 | let opendbm file flags mode = 31 | try 32 | raw_opendbm file flags mode 33 | with Dbm_error msg -> 34 | raise(Dbm_error("Can't open file " ^ file)) 35 | 36 | (* By exporting opendbm as val, we are sure to link in this 37 | file (we must register the exception). Since t is abstract, programs 38 | have to call it in order to do anything *) 39 | 40 | external close : t -> unit = "caml_dbm_close" 41 | external find : t -> string -> string = "caml_dbm_fetch" 42 | external add : t -> string -> string -> unit = "caml_dbm_insert" 43 | external replace : t -> string -> string -> unit = "caml_dbm_replace" 44 | external remove : t -> string -> unit = "caml_dbm_delete" 45 | external firstkey : t -> string = "caml_dbm_firstkey" 46 | external nextkey : t -> string = "caml_dbm_nextkey" 47 | 48 | let _ = Callback.register_exception "dbmerror" (Dbm_error "") 49 | 50 | (* Usual iterator *) 51 | let iter f t = 52 | let rec walk = function 53 | None -> () 54 | | Some k -> 55 | f k (find t k); 56 | walk (try Some(nextkey t) with Not_found -> None) 57 | in 58 | walk (try Some(firstkey t) with Not_found -> None) 59 | -------------------------------------------------------------------------------- /dbm.mli: -------------------------------------------------------------------------------- 1 | (***********************************************************************) 2 | (* *) 3 | (* CamlDBM *) 4 | (* *) 5 | (* Francois Rouaix, projet Cristal, INRIA Rocquencourt *) 6 | (* *) 7 | (* Copyright 1996 Institut National de Recherche en Informatique et *) 8 | (* en Automatique. All rights reserved. This file is distributed *) 9 | (* under the terms of the GNU Library General Public License, with *) 10 | (* the special exception on linking described in file ../../LICENSE. *) 11 | (* *) 12 | (***********************************************************************) 13 | 14 | (* $Id: dbm.mli 11156 2011-07-27 14:17:02Z doligez $ *) 15 | 16 | (** Interface to the NDBM database. *) 17 | 18 | type t 19 | (** The type of file descriptors opened on NDBM databases. *) 20 | 21 | 22 | type open_flag = 23 | Dbm_rdonly 24 | | Dbm_wronly 25 | | Dbm_rdwr 26 | | Dbm_create 27 | (** Flags for opening a database (see {!Dbm.opendbm}). *) 28 | 29 | 30 | exception Dbm_error of string 31 | (** Raised by the following functions when an error is encountered. *) 32 | 33 | val opendbm : string -> open_flag list -> int -> t 34 | (** Open a descriptor on an NDBM database. The first argument is 35 | the name of the database (without the [.dir] and [.pag] suffixes). 36 | The second argument is a list of flags: [Dbm_rdonly] opens 37 | the database for reading only, [Dbm_wronly] for writing only, 38 | [Dbm_rdwr] for reading and writing; [Dbm_create] causes the 39 | database to be created if it does not already exist. 40 | The third argument is the permissions to give to the database 41 | files, if the database is created. *) 42 | 43 | external close : t -> unit = "caml_dbm_close" 44 | (** Close the given descriptor. *) 45 | 46 | external find : t -> string -> string = "caml_dbm_fetch" 47 | (** [find db key] returns the data associated with the given 48 | [key] in the database opened for the descriptor [db]. 49 | Raise [Not_found] if the [key] has no associated data. *) 50 | 51 | external add : t -> string -> string -> unit = "caml_dbm_insert" 52 | (** [add db key data] inserts the pair ([key], [data]) in 53 | the database [db]. If the database already contains data 54 | associated with [key], raise [Dbm_error "Entry already exists"]. *) 55 | 56 | external replace : t -> string -> string -> unit = "caml_dbm_replace" 57 | (** [replace db key data] inserts the pair ([key], [data]) in 58 | the database [db]. If the database already contains data 59 | associated with [key], that data is discarded and silently 60 | replaced by the new [data]. *) 61 | 62 | external remove : t -> string -> unit = "caml_dbm_delete" 63 | (** [remove db key data] removes the data associated with [key] 64 | in [db]. If [key] has no associated data, raise 65 | [Dbm_error "dbm_delete"]. *) 66 | 67 | external firstkey : t -> string = "caml_dbm_firstkey" 68 | (** See {!Dbm.nextkey}.*) 69 | 70 | external nextkey : t -> string = "caml_dbm_nextkey" 71 | (** Enumerate all keys in the given database, in an unspecified order. 72 | [firstkey db] returns the first key, and repeated calls 73 | to [nextkey db] return the remaining keys. [Not_found] is raised 74 | when all keys have been enumerated. *) 75 | 76 | val iter : (string -> string -> 'a) -> t -> unit 77 | (** [iter f db] applies [f] to each ([key], [data]) pair in 78 | the database [db]. [f] receives [key] as first argument 79 | and [data] as second argument. *) 80 | -------------------------------------------------------------------------------- /testdbm.ml: -------------------------------------------------------------------------------- 1 | (***********************************************************************) 2 | (* *) 3 | (* CamlDBM *) 4 | (* *) 5 | (* Francois Rouaix, projet Cristal, INRIA Rocquencourt *) 6 | (* *) 7 | (* Copyright 1996 Institut National de Recherche en Informatique et *) 8 | (* en Automatique. All rights reserved. This file is distributed *) 9 | (* under the terms of the GNU Library General Public License, with *) 10 | (* the special exception on linking described in file ../../LICENSE. *) 11 | (* *) 12 | (***********************************************************************) 13 | 14 | let optfind d k = try Some(Dbm.find d k) with Not_found -> None 15 | 16 | let _ = 17 | let db = Dbm.opendbm "testdatabase" [Dbm.Dbm_rdwr;Dbm.Dbm_create] 0o666 in 18 | Dbm.add db "one" "un"; 19 | Dbm.add db "two" "dos"; 20 | Dbm.replace db "two" "deux"; 21 | Dbm.add db "three" "trois"; 22 | assert (optfind db "one" = Some "un"); 23 | assert (optfind db "two" = Some "deux"); 24 | assert (optfind db "three" = Some "trois"); 25 | assert (optfind db "four" = None); 26 | Dbm.close db; 27 | let db = Dbm.opendbm "testdatabase" [Dbm.Dbm_rdonly] 0 in 28 | Dbm.iter (fun k d -> Printf.printf "key '%s' -> data '%s'\n" k d) db; 29 | Dbm.close db 30 | 31 | 32 | 33 | 34 | --------------------------------------------------------------------------------