summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2010-01-09 16:15:40 +0000
committerChris Wilson <chris+github@qwirx.com>2010-01-09 16:15:40 +0000
commit84ce49c7e644e2a7da022f55a703e30498eee388 (patch)
treeb2c2e4ed6560735261652e94ff6bb19532a8e76a
parent059daaf09d915509982cdf472d4f3aa8c78c4d25 (diff)
Add QDBM 1.8.77 dbm-compatible database library to sources, will
probably be used as a default for the reference tracking implementation as it's smaller than BDB and apparently faster.
-rw-r--r--qdbm/COPYING504
-rw-r--r--qdbm/ChangeLog990
-rw-r--r--qdbm/LTmakefile.in318
-rw-r--r--qdbm/Makefile.in646
-rw-r--r--qdbm/NEWS43
-rw-r--r--qdbm/README50
-rw-r--r--qdbm/RISCmakefile140
-rw-r--r--qdbm/THANKS45
-rw-r--r--qdbm/VCmakefile248
-rw-r--r--qdbm/cabin.c3529
-rw-r--r--qdbm/cabin.h1544
-rw-r--r--qdbm/cbcodec.c1079
-rw-r--r--qdbm/cbtest.c924
-rwxr-xr-xqdbm/configure3913
-rw-r--r--qdbm/configure.in312
-rw-r--r--qdbm/crmgr.c956
-rw-r--r--qdbm/crtest.c873
-rw-r--r--qdbm/crtsv.c266
-rw-r--r--qdbm/curia.c1192
-rw-r--r--qdbm/curia.h474
-rw-r--r--qdbm/depot.c2219
-rw-r--r--qdbm/depot.h492
-rw-r--r--qdbm/dpmgr.c916
-rw-r--r--qdbm/dptest.c836
-rw-r--r--qdbm/dptsv.c261
-rw-r--r--qdbm/hovel.c568
-rw-r--r--qdbm/hovel.h278
-rw-r--r--qdbm/hvmgr.c582
-rw-r--r--qdbm/hvtest.c272
-rw-r--r--qdbm/misc/COPYING.txt504
-rw-r--r--qdbm/misc/README-win32.txt101
-rw-r--r--qdbm/misc/VCmakefile-old169
-rw-r--r--qdbm/misc/benchmark.pdfbin0 -> 52196 bytes
-rw-r--r--qdbm/misc/icon16.pngbin0 -> 339 bytes
-rw-r--r--qdbm/misc/icon20.pngbin0 -> 275 bytes
-rw-r--r--qdbm/misc/index.html202
-rw-r--r--qdbm/misc/index.ja.html209
-rw-r--r--qdbm/misc/logo.pngbin0 -> 11430 bytes
-rwxr-xr-xqdbm/misc/makevcdef48
-rw-r--r--qdbm/misc/mymemo-ja.html34
-rw-r--r--qdbm/misc/tutorial-ja.html622
-rw-r--r--qdbm/misc/win32check.bat111
-rw-r--r--qdbm/myconf.c1113
-rw-r--r--qdbm/myconf.h593
-rw-r--r--qdbm/odeum.c2090
-rw-r--r--qdbm/odeum.h590
-rw-r--r--qdbm/odidx.c890
-rw-r--r--qdbm/odmgr.c1085
-rw-r--r--qdbm/odtest.c694
-rw-r--r--qdbm/qdbm.def424
-rw-r--r--qdbm/qdbm.pc.in14
-rw-r--r--qdbm/qdbm.spec.in218
-rw-r--r--qdbm/qmttest.c300
-rw-r--r--qdbm/relic.c266
-rw-r--r--qdbm/relic.h170
-rw-r--r--qdbm/rlmgr.c465
-rw-r--r--qdbm/rltest.c241
-rw-r--r--qdbm/spex-ja.html4348
-rw-r--r--qdbm/spex.html4343
-rw-r--r--qdbm/villa.c2666
-rw-r--r--qdbm/villa.h758
-rw-r--r--qdbm/vista.c171
-rw-r--r--qdbm/vista.h138
-rw-r--r--qdbm/vlmgr.c968
-rw-r--r--qdbm/vltest.c1507
-rw-r--r--qdbm/vltsv.c261
66 files changed, 50783 insertions, 0 deletions
diff --git a/qdbm/COPYING b/qdbm/COPYING
new file mode 100644
index 00000000..b1e3f5a2
--- /dev/null
+++ b/qdbm/COPYING
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/qdbm/ChangeLog b/qdbm/ChangeLog
new file mode 100644
index 00000000..3fae65dd
--- /dev/null
+++ b/qdbm/ChangeLog
@@ -0,0 +1,990 @@
+2007-10-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A potential defect related to leaf division of B+ tree was cleared.
+ - Release: 1.8.77
+
+2007-03-07 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The hash function of on-memory map was optimized.
+ - A bug related to large object was fixed.
+ - Release: 1.8.76
+
+2006-11-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - A bug related to B+ tree API for Ruby was fixed.
+ - Release: 1.8.75
+
+2006-11-02 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug related to optimization on Intel Mac series was escaped.
+ - Release: 1.8.74
+
+2006-10-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug related to BZIP2 encoding was fixed.
+ - Release: 1.8.73
+
+2006-10-06 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.8.72
+
+2006-08-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefile was modified to assure portability.
+ - Silent flag was added to the C++ API, the Java API, and the Ruby API.
+ - Release: 1.8.71
+
+2006-08-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of segmentation fault on BSD was fixed.
+ - A test command for checking multi thread safety was added.
+ - Release: 1.8.70
+
+2006-08-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Mutex controll in C++ API became refined.
+ - Release: 1.8.69
+
+2006-08-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug about memory alignment was fixed.
+ - A bug of handling meta data on big endian platforms was fixed.
+ - Release: 1.8.68
+
+2006-08-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug about memory alignment was fixed.
+ - A bug about parsing MIME was fixed.
+ - Release: 1.8.67
+
+2006-08-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.8.66
+
+2006-08-03 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The extended API was enhanced.
+ - The extended advanced API was enhanced.
+ - Release: 1.8.65
+
+2006-07-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of Makefile ralated to optimization was fixed.
+ - Release: 1.8.64
+
+2006-07-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A lot of functions were replaced by macros.
+ - The utility API was enhanced.
+ - Release: 1.8.63
+
+2006-07-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A lot of functions were replaced by macros.
+ - The URL resolver was to allow unescaped meta characters.
+ - The advanced API was enhanced.
+ - Release: 1.8.62
+
+2006-07-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of the size checking function of the extended API was fixed.
+ - The advanced API was enhanced.
+ - Release: 1.8.61
+
+2006-06-03 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The basic API was enhanced.
+ - The extended API was enhanced.
+ - The advanced API was enhanced.
+ - Multiple cursor class is now supported on the java API.
+ - Release: 1.8.60
+
+2006-05-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The basic API was enhanced.
+ - The extended API was enhanced.
+ - The advanced API was enhanced.
+ - A bug of Makefile for Mac OS X support was fixed.
+ - Release: 1.8.59
+
+2006-05-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The basic API was enhanced.
+ - The advanced API was enhanced.
+ - Release: 1.8.58
+
+2006-05-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The basic API was enhanced.
+ - The utility API was enhanced.
+ - Release: 1.8.57
+
+2006-05-17 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of URL decoder was fixed.
+ - Release: 1.8.56
+
+2006-05-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The extended API was enhanced.
+ - The utility API was enhanced.
+ - Release: 1.8.55
+
+2006-05-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The basic API was enhanced.
+ - Release: 1.8.54
+
+2006-05-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - AIX is now supported.
+ - The utility API was enhanced.
+ - Release: 1.8.53
+
+2006-05-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug about evaluating RFC822 date format was fixed.
+ - Release: 1.8.52
+
+2006-05-02 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug about evaluating RFC822 date format was fixed.
+ - Warings from GCC 4.1.x were dealt with.
+ - Missing functions in qdbm.def were supplied.
+ - Release: 1.8.51
+
+2006-04-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.8.50
+
+2006-04-19 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A parameter of dynamic linking library on Mac OS X was modified.
+ - The utility API was enhanced.
+ - Release: 1.8.49
+
+2006-03-27 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.8.48
+
+2006-03-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - LTmakefile was modified.
+ - The utility API was enhanced.
+ - Release: 1.8.47
+
+2006-02-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.8.46
+
+2006-01-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Alignment algorithm was improved.
+ - A bug of mmap emulation on Windows was fixed.
+ - Release: 1.8.45
+
+2006-01-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of handling meta data on big endian platforms was fixed.
+ - The advanced API was enhanced.
+ - Release: 1.8.44
+
+2006-01-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of mmap emulation on Windows was fixed.
+ - Release: 1.8.43
+
+2006-01-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - mmap emulation on Windows was enhanced.
+ - Release: 1.8.42
+
+2006-01-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Compression of pages of B+ tree with LZO and BZIP was added.
+ - Release: 1.8.41
+
+2006-01-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Configuration for VC++ was to build DLL.
+ - Release: 1.8.40
+
+2006-01-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The advanced API was enhanced.
+ - Release: 1.8.39
+
+2006-01-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The advanced API was enhanced.
+ - Release: 1.8.38
+
+2005-12-26 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Functions to set the size of the free block pool were added.
+ - Commands line tools were enhanced.
+ - Release: 1.8.37
+
+2005-12-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Free block pool was enhanced.
+ - Commands line tools were enhanced.
+ - Release: 1.8.36
+
+2005-11-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The extended advanced API was enhanced.
+ - All stat calls were replaced with lstat calls.
+ - Release: 1.8.35
+
+2005-11-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of i-node duplication on MinGW was fixed.
+ - Release: 1.8.34
+
+2005-09-09 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Compressing options of ZLIB was changed.
+ - The utility API was enhanced.
+ - Release: 1.8.33
+
+2005-08-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of backward string matching was fixed.
+ - The utility API was enhanced.
+ - Release: 1.8.32
+
+2005-06-19 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug of the MIME parser was fixed.
+ - A bug about database repair on Win32 was fixed.
+ - A bug of Makefile for Mac OS X support was fixed.
+ - The type of error codes of GDBM-compatibility API was changed.
+ - Release: 1.8.31
+
+2005-06-09 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A Bug of APIs for C++ related to namespace was fixed.
+ - The library of shared objects of C++ APIs was added.
+ - The utility API was enhanced.
+ - Release: 1.8.30
+
+2005-06-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug about file locking on Win32 was fixed.
+ - Manuals of command line tools were added.
+ - The utility API was enhanced.
+ - Release: 1.8.29
+
+2005-05-27 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A compilation problem on hppa-linux was fixed.
+ - A configuration file for pkg-config was added.
+ - Release: 1.8.28
+
+2005-05-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Non-blocking lock was featured.
+ - Release: 1.8.27
+
+2005-05-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - The utility API was enhanced.
+ - Release: 1.8.26
+
+2005-05-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - The utility API was enhanced.
+ - Release: 1.8.25
+
+2005-04-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - A bug about database repair on Win32 was fixed.
+ - Release: 1.8.24
+
+2005-04-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The extended advanced API was enhanced.
+ - Release: 1.8.23
+
+2005-03-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The extended advanced API was enhanced.
+ - The utility API was enhanced.
+ - The inverted API was enhanced.
+ - Test commands were enhanced.
+ - Release: 1.8.22
+
+2005-01-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Functions to dump endian independent data was added.
+ - Release: 1.8.21
+
+2005-01-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Sparse file support was added.
+ - Release: 1.8.20
+
+2005-01-02 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Building configurations were enhanced.
+ - Release: 1.8.19
+
+2004-11-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The extended advanced API was enhanced.
+ - The inverted API was enhanced.
+ - Release: 1.8.18
+
+2004-09-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The CGI script for file upload was enhanced.
+ - The spec file for RPM packages was enhanced.
+ - Release: 1.8.17
+
+2004-08-17 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug in the extended API was fixed.
+ - A bug about seek on Windows 9x was fixed.
+ - The CGI script for file upload was enhanced.
+ - Release: 1.8.16
+
+2004-08-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - A bug about mmap on Mac OS X was fixed.
+ - A CGI script for file upload was added.
+ - Building configurations were enhanced.
+ - Release: 1.8.15
+
+2004-07-19 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The basic API was enhanced.
+ - The extended API was enhanced.
+ - The advanced API was enhanced.
+ - The inverted API was enhanced.
+ - Building configurations were enhanced.
+ - Release: 1.8.14
+
+2004-07-07 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The inverted API was enhanced.
+ - Release: 1.8.13
+
+2004-05-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The inverted API was enhanced.
+ - Building configurations were enhanced.
+ - Release: 1.8.12
+
+2004-05-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Source codes were cleaned up for Visual C++.
+ - Test commands were enhanced.
+ - Building configurations were enhanced.
+ - Release: 1.8.11
+
+2004-04-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Utility for performance test was enhanced.
+ - It was escaped from a bug about mmap on FreeBSD and NetBSD.
+ - Release: 1.8.10
+
+2004-04-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Logger for debugging is now featured.
+ - It was escaped from a bug about mmap on OpenBSD.
+ - Release: 1.8.9
+
+2004-04-11 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Processing speed was improved.
+ - The basic API was enhanced.
+ - The extended API was enhanced.
+ - The configuration for VC++ was enhanced.
+ - Release: 1.8.8
+
+2004-03-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The configuration of C++ API escaped from a bug of pthread.
+ - Release: 1.8.7
+
+2004-03-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The extended API was enhanced.
+ - Bugs in the utility API about memory management were fixed.
+ - Release: 1.8.6
+
+2004-03-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug in the utility API for 64-bit platforms was fixed.
+ - The utility API was enhanced.
+ - Release: 1.8.5
+
+2004-03-09 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Runtime switching of whether to use ZLIB was featured.
+ - The binary package for Win32 now features ZLIB and ICONV.
+ - The utility API was enhanced.
+ - Release: 1.8.4
+
+2004-03-06 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - A utility class of Java API was enhanced.
+ - Test commands were enhanced.
+ - Release: 1.8.3
+
+2004-03-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.8.2
+
+2004-02-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Processing speed of multi-thread support was improved.
+ - Release: 1.8.1
+
+2004-02-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Switch to make API for C thread-safe was added.
+ - Release: 1.8.0
+
+2004-02-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Potential bugs in APIs for C++ were fixed.
+ - Release: 1.7.34
+
+2004-01-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The extended API was enhanced.
+ - The inverted API was enhanced.
+ - Release: 1.7.33
+
+2004-01-17 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - Release: 1.7.32
+
+2004-01-16 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - Release: 1.7.31
+
+2004-01-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - Release: 1.7.30
+
+2004-01-11 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.7.29
+
+2004-01-09 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug in the utility API was fixed.
+ - Release: 1.7.28
+
+2004-01-06 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug in the advanced API was fixed.
+ - The utility API was enhanced.
+ - Release: 1.7.27
+
+2004-01-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - Release: 1.7.26
+
+2004-01-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - The utility API was enhanced.
+ - Release: 1.7.25
+
+2003-12-26 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - C++ export was supported in header files.
+ - The utility API was enhanced.
+ - Release: 1.7.24
+
+2003-12-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Repairing utility was added to the advanced API.
+ - The basic API was enhanced.
+ - The utility API was enhanced.
+ - Release: 1.7.23
+
+2003-12-16 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Repairing utility was added to the extended API.
+ - The utility API was enhanced.
+ - Release: 1.7.22
+
+2003-12-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A utility to repair a broken database file was added.
+ - A ulitity command for full-text search was enhanced.
+ - Release: 1.7.21
+
+2003-12-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Character encoding converter was added.
+ - Release: 1.7.20
+
+2003-12-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Format converter for older versions than 1.7.13 was added.
+ - Tuning paramters of the inverted API were modified.
+ - A CGI script for full-text search was enhanced.
+ - Release: 1.7.19
+
+2003-12-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The GDBM-compatible API was enhanced.
+ - Release: 1.7.18
+
+2003-12-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - A CGI script for full-text search was enhanced.
+ - Release: 1.7.17
+
+2003-12-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A CGI script for full-text search was enhanced.
+ - A ulitity command for full-text search was enhanced.
+ - Building configuration files were modified.
+ - Release: 1.7.16
+
+2003-11-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A CGI script for full-text search was enhanced.
+ - A ulitity command for full-text search was enhanced.
+ - Release: 1.7.15
+
+2003-11-29 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - A ulitity command for full-text search was enhanced.
+ - A CGI script for full-text search was enhanced.
+ - Release: 1.7.14
+
+2003-11-27 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Format of headers of database was modified.
+ - Supporting endian conversion was abolished.
+ - Import/export features were added to utility commands.
+ - A ulitity command for full-text search was enhanced.
+ - A CGI script for full-text search was enhanced.
+ - Release: 1.7.13
+
+2003-11-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - The inverted API was enhanced.
+ - A ulitity command for full-text search was enhanced.
+ - A CGI script for full-text search was enhanced.
+ - Release: 1.7.12
+
+2003-11-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API was enhanced.
+ - A ulitity command for full-text search was enhanced.
+ - A CGI script for full-text search was enhanced.
+ - A utility class of Java API was enhanced.
+ - Release: 1.7.11
+
+2003-11-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A utility class of Java API was enhanced.
+ - Building configuration for CGI scripts was modified.
+ - Release: 1.7.10
+
+2003-11-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Tuning paramters of the inverted API were modified.
+ - A ulitity command for full-text search was enhanced.
+ - Release: 1.7.9
+
+2003-11-16 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Optional features of compressing with ZLIB were added.
+ - Release: 1.7.8
+
+2003-11-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The extended advanced API, Vista was added.
+ - Release: 1.7.7
+
+2003-11-03 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - C API compilation using Visual C++ was supported.
+ - Odeum and its commands were enhanced.
+ - Release: 1.7.6
+
+2003-10-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A ulitity command for full-text search was enhanced.
+ - A CGI script for full-text search was enhanced.
+ - Release: 1.7.5
+
+2003-10-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A CGI script for full-text search was added.
+ - A bug of BSD support in Makefile was fixed.
+ - Release: 1.7.4
+
+2003-10-19 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Processing speed of the inverted API was improved.
+ - A ulitity command for full-text search was enhanced.
+ - Release: 1.7.3
+
+2003-10-17 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The license was changed to LGPL.
+ - An indexing command for the inverted API was added.
+ - Release: 1.7.2
+
+2003-10-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A test command for the inverted API was added.
+ - A bug about optimization in the inverted API was fixed.
+ - Tuning paramters of the inverted API were modified.
+ - Release: 1.7.1
+
+2003-10-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The inverted API, Odeum was added.
+ - Comments in source codes increased.
+ - Release: 1.7.0
+
+2003-10-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Executable commands were modified for RISC OS.
+ - Release: 1.6.22
+
+2003-10-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Executable commands were modified for RISC OS.
+ - Release: 1.6.21
+
+2003-09-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Naming file in RISC OS style was supported.
+ - Hash functions were enhanced.
+ - Release: 1.6.20
+
+2003-09-26 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Test commands were added.
+ - Release: 1.6.19
+
+2003-09-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefile for RISC OS was added.
+ - C++ API was enhanced.
+ - Release: 1.6.18
+
+2003-09-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Test commands were enhanced.
+ - Source codes and Makefile were modified for RISC OS.
+ - The CGI script was enhanced.
+ - Release: 1.6.17
+
+2003-09-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The CGI script for administration was added.
+ - C++ API was enhanced.
+ - Release: 1.6.16
+
+2003-08-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.6.15
+
+2003-08-16 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.6.14
+
+2003-08-11 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.6.13
+
+2003-08-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - A bug in the utility API was fixed.
+ - Test commands were enhanced.
+ - Release: 1.6.12
+
+2003-07-31 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - C and Java APIs support compilation using MinGW.
+ - Release: 1.6.11
+
+2003-07-27 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Perl and Ruby APIs support transaction.
+ - Release: 1.6.10
+
+2003-07-26 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Speed of transaction was improved.
+ - Release: 1.6.9
+
+2003-07-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - C++ and Java APIs of B+ tree support transaction.
+ - Release: 1.6.8
+
+2003-07-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - C API of B+ tree supports transaction.
+ - Bugs about Mutex in C++ and Java APIs were fixed.
+ - Release: 1.6.7
+
+2003-07-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - C++ and Java APIs of database abstraction were simplified.
+ - Ruby API of B+ tree was simplified.
+ - Release: 1.6.6
+
+2003-07-16 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Ruby API of B+ tree was added.
+ - C, C++, Java and Perl APIs of B+ tree were enhanced.
+ - Release: 1.6.5
+
+2003-07-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Perl API of B+ tree was added.
+ - C, C++ and Java APIs of B+ tree were enhanced.
+ - Release: 1.6.4
+
+2003-07-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Java API of B++ tree was added.
+ - C API of B+ tree was enhanced.
+ - C++ API of B+ tree was enhanced.
+ - Release: 1.6.3
+
+2003-07-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Debug routines were removed and speed was improved.
+ - No locking mode was added.
+ - Endian converter of Villa was added.
+ - C++ API of B++ tree was added.
+ - Release: 1.6.2
+
+2003-07-03 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The advanced API was enhanced to improve its speed.
+ - Makefiles were enhanced for HP-UX.
+ - Release: 1.6.1
+
+2003-06-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The advanced API for B+ tree database is added.
+ - Release: 1.6.0
+
+2003-06-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefiles were enhanced for Mac OS X.
+ - Release: 1.5.13
+
+2003-06-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefile was enhanced for Solaris and Mac OS X.
+ - Release: 1.5.12
+
+2003-06-06 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.5.11
+
+2003-05-31 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was enhanced.
+ - Release: 1.5.10
+
+2003-05-29 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was changed.
+ - Release: 1.5.9
+
+2003-05-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Alignment mechanism was simplified.
+ - Release: 1.5.8
+
+2003-05-17 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefile was updated
+ - Release: 1.5.7
+
+2003-05-16 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Test tools were enhanced.
+ - Release: 1.5.6
+
+2003-05-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefile using libtool was added.
+ - Release: 1.5.5
+
+2003-05-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - API for Ruby was enhanced.
+ - Release: 1.5.4
+
+2003-05-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - API for Ruby was added.
+ - Release: 1.5.3
+
+2003-05-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - API for Perl was enhanced.
+ - Release: 1.5.2
+
+2003-04-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - API for Perl was enhanced.
+ - Release: 1.5.1
+
+2003-04-29 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - API for Perl was added.
+ - Release: 1.5.0
+
+2003-04-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The package was reorganized to be a GNU package.
+ - Release: 1.4.11
+
+2003-04-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The utility API was added.
+ - Release: 1.4.10
+
+2003-04-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Endian converters were added.
+ - Release: 1.4.9
+
+2003-04-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The GDBM-compatible API was enhanced.
+ - Release: 1.4.8
+
+2003-04-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Some bugs were fixed and C++ API was enhanced.
+ - Release: 1.4.7
+
+2003-04-09 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Coalescence of dead regions and reuse of them were featured.
+ - Release: 1.4.6
+
+2003-04-06 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The GDBM-compatible API and the C++ API were enhanced.
+ - Release: 1.4.5
+
+2003-04-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The API for C++ and the API for Java were enhanced.
+ - Release: 1.4.4
+
+2003-04-02 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Documents for C++ was enhanced.
+ - Release: 1.4.3
+
+2003-04-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The API for Java was enhanced.
+ - Release: 1.4.2
+
+2003-03-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Makefiles were modified.
+ - Release: 1.4.1
+
+2003-03-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - APIs for C++ and Java was enhanced.
+ - Release: 1.4.0
+
+2003-03-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The API for C++ was added.
+ - Release: 1.3.2
+
+2003-03-11 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The API for Java was supported on Solaris and Windows.
+ - Release: 1.3.1
+
+2003-03-04 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The API for Java was added.
+ - Release: 1.3.0
+
+2003-02-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The GDBM-compatible API was added.
+ - Release: 1.2.0
+
+2003-02-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Compatibility with NDBM was improved.
+ - Release: 1.1.3
+
+2003-02-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Optimizing suppoted on Windows. DLL is supported.
+ - Release: 1.1.2
+
+2003-02-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - Windows is now supported.
+ - The compatible API was enhanced.
+ - Release: 1.1.1
+
+2003-02-11 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The NDBM-compatible API was added.
+ - Release: 1.1.0
+
+2003-02-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ - The initial version.
+ - Release: 1.0.0
+
diff --git a/qdbm/LTmakefile.in b/qdbm/LTmakefile.in
new file mode 100644
index 00000000..547abccf
--- /dev/null
+++ b/qdbm/LTmakefile.in
@@ -0,0 +1,318 @@
+# Makefile to build QDBM using libtool
+
+
+
+#================================================================
+# Setting variables
+#================================================================
+
+
+# Generic settings
+SHELL = @SHELL@
+
+# Packaging
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+LIBVER = @LIBVER@
+LIBREV = @LIBREV@
+
+# Targets
+MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h
+MYLIBOBJS = depot.lo curia.lo relic.lo hovel.lo cabin.lo villa.lo vista.lo odeum.lo myconf.lo
+MYLIBS = libqdbm.la
+MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \
+ cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest
+MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \
+ cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1
+MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \
+ cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3
+MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS
+MYPCS = qdbm.pc
+
+# Install destinations
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+MYHEADDIR = @includedir@
+MYLIBDIR = @libdir@
+MYBINDIR = @bindir@
+MYMAN1DIR = @mandir@/man1
+MYMAN3DIR = @mandir@/man3
+MYSHAREDIR = $(prefix)/share/$(PACKAGE)
+MYPCDIR = @libdir@/pkgconfig
+
+# Building binaries
+LIBTOOL = libtool
+CC = gcc
+CFLAGS = -I. -I$(MYHEADDIR) -I$(HOME)/include -I/usr/local/include @MYDEFS@ \
+ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \
+ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \
+ -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG -O3
+LD = gcc
+LIBLDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) \
+ -version-info $$(($(LIBVER)+$(LIBREV))):0:$(LIBREV) @LIBS@
+LDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) -L. -lqdbm @LIBS@
+INSTALL = install
+MKDIR = mkdir -p
+CP = cp -rf
+RM = rm -rf
+
+
+
+#================================================================
+# Suffix rules
+#================================================================
+
+
+.SUFFIXES :
+.SUFFIXES : .c .lo
+
+.c.lo :
+ $(LIBTOOL) --mode=compile --tag=CC $(CC) -c $(CFLAGS) $<
+
+
+
+#================================================================
+# Actions
+#================================================================
+
+
+all : $(MYLIBS) $(MYBINS)
+ @printf '\n'
+ @printf '#================================================================\n'
+ @printf '# Ready to install.\n'
+ @printf '#================================================================\n'
+
+
+clean :
+ $(RM) $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \
+ *.exe *.dll.a *.dll TAGS srcdoc gmon.out leak.log casket casket.* *~
+
+
+install :
+ $(LIBTOOL) --mode=install $(INSTALL) $(MYHEADS) $(MYHEADDIR)
+ $(LIBTOOL) --mode=install $(INSTALL) $(MYLIBS) $(MYLIBDIR)
+ $(LIBTOOL) --mode=install $(INSTALL) $(MYBINS) $(MYBINDIR)
+ $(MKDIR) $(MYMAN1DIR)
+ cd man && $(CP) $(MYMAN1S) $(MYMAN1DIR)
+ $(MKDIR) $(MYMAN3DIR)
+ cd man && $(CP) $(MYMAN3S) $(MYMAN3DIR)
+ $(MKDIR) $(MYSHAREDIR)
+ $(CP) $(MYDOCS) $(MYSHAREDIR)
+ $(MKDIR) $(MYPCDIR)
+ $(CP) $(MYPCS) $(MYPCDIR)
+ @printf '\n'
+ @printf '#================================================================\n'
+ @printf '# Thanks for using QDBM.\n'
+ @printf '#================================================================\n'
+
+
+uninstall :
+ cd $(MYHEADDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYHEADS)
+ cd $(MYLIBDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYLIBS)
+ cd $(MYBINDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYBINS)
+ cd $(MYMAN1DIR) && $(RM) $(MYMAN1S)
+ cd $(MYMAN3DIR) && $(RM) $(MYMAN3S)
+ $(RM) $(MYSHAREDIR)
+ cd $(MYPCDIR) && $(RM) $(MYPCS)
+
+
+distclean : clean
+ $(RM) Makefile LTmakefile rpmspec config.cache config.log config.status autom4te.cache
+
+
+check :
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./dptest write -s casket 500 500000
+ $(LIBTOOL) --mode=execute ./dptest write casket 50000 5000
+ $(LIBTOOL) --mode=execute ./dptest read casket
+ $(LIBTOOL) --mode=execute ./dptest read -wb casket
+ $(LIBTOOL) --mode=execute ./dptest rcat -c casket 50000 50 500 32 8
+ $(LIBTOOL) --mode=execute ./dptest combo casket
+ $(LIBTOOL) --mode=execute ./dptest wicked -c casket 5000
+ $(LIBTOOL) --mode=execute ./dptest wicked casket 500
+ $(LIBTOOL) --mode=execute ./dpmgr repair casket
+ $(LIBTOOL) --mode=execute ./dpmgr optimize casket
+ $(LIBTOOL) --mode=execute ./dpmgr list casket
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./crtest write -s casket 500 100000 5
+ $(LIBTOOL) --mode=execute ./crtest write casket 50000 500 10
+ $(LIBTOOL) --mode=execute ./crtest read casket
+ $(LIBTOOL) --mode=execute ./crtest read -wb casket
+ $(LIBTOOL) --mode=execute ./crtest rcat -c casket 50000 5 10 500 32 8
+ $(LIBTOOL) --mode=execute ./crtest combo casket
+ $(LIBTOOL) --mode=execute ./crtest wicked -c casket 5000
+ $(LIBTOOL) --mode=execute ./crtest wicked casket 500
+ $(LIBTOOL) --mode=execute ./crmgr repair casket
+ $(LIBTOOL) --mode=execute ./crmgr optimize casket
+ $(LIBTOOL) --mode=execute ./crmgr list casket
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./crtest write -lob casket 1000 50 10
+ $(LIBTOOL) --mode=execute ./crtest read -lob casket
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./rltest write casket 5000
+ $(LIBTOOL) --mode=execute ./rltest read casket 5000
+ $(LIBTOOL) --mode=execute ./rlmgr list casket
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./hvtest write casket 5000
+ $(LIBTOOL) --mode=execute ./hvtest read casket 5000
+ $(LIBTOOL) --mode=execute ./hvmgr optimize casket
+ $(LIBTOOL) --mode=execute ./hvmgr list casket
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./hvtest write -qdbm -s casket 500
+ $(LIBTOOL) --mode=execute ./hvtest write -qdbm casket 5000
+ $(LIBTOOL) --mode=execute ./hvtest read -qdbm casket 5000
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./cbtest sort 5000
+ $(LIBTOOL) --mode=execute ./cbtest strstr 500
+ $(LIBTOOL) --mode=execute ./cbtest list 50000
+ $(LIBTOOL) --mode=execute ./cbtest list -d 500
+ $(LIBTOOL) --mode=execute ./cbtest map 50000 500
+ $(LIBTOOL) --mode=execute ./cbtest map -d 500 5
+ $(LIBTOOL) --mode=execute ./cbtest heap 50000 500
+ $(LIBTOOL) --mode=execute ./cbtest heap -d 500 50
+ $(LIBTOOL) --mode=execute ./cbtest wicked 5000
+ $(LIBTOOL) --mode=execute ./cbtest misc
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./vltest write -tune 32 31 32 32 casket 50000
+ $(LIBTOOL) --mode=execute ./vltest read casket
+ $(LIBTOOL) --mode=execute ./vltest rdup -tune 32 31 512 256 casket 50000 50000
+ $(LIBTOOL) --mode=execute ./vltest combo casket
+ $(LIBTOOL) --mode=execute ./vltest wicked -c casket 5000
+ $(LIBTOOL) --mode=execute ./vltest wicked casket 500
+ $(LIBTOOL) --mode=execute ./vlmgr repair casket
+ $(LIBTOOL) --mode=execute ./vlmgr optimize casket
+ $(LIBTOOL) --mode=execute ./vlmgr list casket
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./vltest write -int -cz -tune 32 31 32 32 casket 50000
+ $(LIBTOOL) --mode=execute ./vltest read -int -vc casket
+ $(LIBTOOL) --mode=execute ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000
+ $(LIBTOOL) --mode=execute ./vltest combo -cz casket
+ $(LIBTOOL) --mode=execute ./vltest wicked -cz -c casket 5000
+ $(LIBTOOL) --mode=execute ./vltest combo -cy casket
+ $(LIBTOOL) --mode=execute ./vltest wicked -cy -c casket 5000
+ $(LIBTOOL) --mode=execute ./vltest combo -cx casket
+ $(LIBTOOL) --mode=execute ./vltest wicked -cx -c casket 5000
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./odtest write casket 500 50 5000
+ $(LIBTOOL) --mode=execute ./odtest read casket
+ $(LIBTOOL) --mode=execute ./odtest combo casket
+ $(LIBTOOL) --mode=execute ./odtest wicked casket 500
+ $(RM) casket*
+ $(LIBTOOL) --mode=execute ./qmttest casket 50000 10
+ $(RM) casket*
+ @printf '\n'
+ @printf '#================================================================\n'
+ @printf '# Checking completed.\n'
+ @printf '#================================================================\n'
+
+
+.PHONY : all clean install check
+
+
+
+#================================================================
+# Building binaries
+#================================================================
+
+
+libqdbm.la : $(MYLIBOBJS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) $(MYLIBOBJS) -o $@ $(LIBLDFLAGS)
+
+
+dpmgr : dpmgr.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dpmgr.lo $(LDFLAGS)
+
+
+dptest : dptest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptest.lo $(LDFLAGS)
+
+
+dptsv : dptsv.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptsv.lo $(LDFLAGS)
+
+
+crmgr : crmgr.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crmgr.lo $(LDFLAGS)
+
+
+crtest : crtest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtest.lo $(LDFLAGS)
+
+
+crtsv : crtsv.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtsv.lo $(LDFLAGS)
+
+
+rlmgr : rlmgr.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rlmgr.lo $(LDFLAGS)
+
+
+rltest : rltest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rltest.lo $(LDFLAGS)
+
+
+hvmgr : hvmgr.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvmgr.lo $(LDFLAGS)
+
+
+hvtest : hvtest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvtest.lo $(LDFLAGS)
+
+
+cbtest : cbtest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbtest.lo $(LDFLAGS)
+
+
+cbcodec : cbcodec.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbcodec.lo $(LDFLAGS)
+
+
+vlmgr : vlmgr.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vlmgr.lo $(LDFLAGS)
+
+
+vltest : vltest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltest.lo $(LDFLAGS)
+
+
+vltsv : vltsv.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltsv.lo $(LDFLAGS)
+
+
+odmgr : odmgr.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odmgr.lo $(LDFLAGS)
+
+
+odtest : odtest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odtest.lo $(LDFLAGS)
+
+
+odidx : odidx.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odidx.lo $(LDFLAGS)
+
+
+qmttest : qmttest.lo $(MYLIBS)
+ $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ qmttest.lo $(LDFLAGS)
+
+
+depot.lo dpmgr.lo dptest.lo dptsv.lo : depot.h myconf.h
+
+curia.lo crmgr.lo crtest.lo crtsv.lo : curia.h depot.h myconf.h
+
+relic.lo rlmgr.lo rltest.lo : relic.h depot.h myconf.h
+
+hovel.lo hvmgr.lo hvtest.lo : hovel.h depot.h curia.h myconf.h
+
+cabin.lo cbtest.lo : cabin.h myconf.h
+
+villa.lo vlmgr.lo vltest.lo vltsv.lo : villa.h depot.h cabin.h myconf.h
+
+vista.lo : vista.h villa.h depot.h curia.h cabin.h myconf.h villa.c
+
+odeum.lo odmgr.lo odtest.lo odidx.lo : odeum.h depot.h curia.h cabin.h villa.h myconf.h
+
+myconf.lo : myconf.h
+
+
+
+# END OF FILE
diff --git a/qdbm/Makefile.in b/qdbm/Makefile.in
new file mode 100644
index 00000000..78faa9bf
--- /dev/null
+++ b/qdbm/Makefile.in
@@ -0,0 +1,646 @@
+# Makefile for QDBM
+
+
+
+#================================================================
+# Setting variables
+#================================================================
+
+
+# Generic settings
+SHELL = @SHELL@
+srcdir = @srcdir@
+VPATH = @srcdir@
+SUBDIRS =
+
+# Packaging
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+PACKAGEDIR = $(PACKAGE)-$(VERSION)
+PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz
+LIBVER = @LIBVER@
+LIBREV = @LIBREV@
+
+# Targets
+MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h
+MYLIBOBJS = depot.o curia.o relic.o hovel.o cabin.o villa.o vista.o odeum.o myconf.o
+MYLIBS = libqdbm.a libqdbm.so.$(LIBVER).$(LIBREV).0 libqdbm.so.$(LIBVER) libqdbm.so
+MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \
+ cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest
+MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \
+ cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1
+MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \
+ cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3
+MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS
+MYPCS = qdbm.pc
+MYWINLIBS = libqdbm.a libqdbm.dll.a
+MYMACLIBS = libqdbm.a libqdbm.$(LIBVER).$(LIBREV).0.dylib libqdbm.$(LIBVER).dylib libqdbm.dylib
+MYHPUXLIBS = libqdbm.a libqdbm.sl
+
+# Install destinations
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+MYHEADDIR = @includedir@
+MYLIBDIR = @libdir@
+MYBINDIR = @bindir@
+MYMAN1DIR = @mandir@/man1
+MYMAN3DIR = @mandir@/man3
+MYDATADIR = @datadir@/$(PACKAGE)
+MYPCDIR = @libdir@/pkgconfig
+DESTDIR =
+
+# Building binaries
+CC = @CC@
+CPPFLAGS = @CPPFLAGS@ -I$(srcdir) -I$(MYHEADDIR) \
+ -I$(HOME)/include -I/usr/local/include @MYDEFS@ \
+ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \
+ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \
+ -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG
+CFLAGS = -Wall -pedantic -fPIC -fsigned-char -O3 -fomit-frame-pointer -fforce-addr @MYOPTS@
+LD = @LD@
+LIBS = -lqdbm @LIBS@
+LIBLDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib @LIBS@
+LDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib $(LIBS)
+LDENV = LD_RUN_PATH=/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib
+AR = @AR@
+ARFLAGS = rcsv
+RUNENV = LD_LIBRARY_PATH=.:/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib
+
+
+
+#================================================================
+# Suffix rules
+#================================================================
+
+
+.SUFFIXES :
+.SUFFIXES : .c .o
+
+.c.o :
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $<
+
+
+
+#================================================================
+# Actions
+#================================================================
+
+
+targets : @TARGETS@
+
+
+all : $(MYLIBS) $(MYBINS)
+ @printf '\n'
+ @printf '#================================================================\n'
+ @printf '# Ready to install.\n'
+ @printf '#================================================================\n'
+
+
+static :
+ make MYLIBS="$(MYLIBS)" LDFLAGS="-static $(LDFLAGS)" all
+
+
+debug :
+ make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \
+ CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g" \
+ LDFLAGS="-static $(LDFLAGS)" all
+
+
+devel :
+ make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \
+ CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g -pipe" all
+ sync ; sync
+
+
+stable :
+ make MYLIBS="$(MYLIBS)" CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2" all
+
+
+profile :
+ make MYLIBS="$(MYLIBS)" \
+ CFLAGS="-Wall -pedantic -fPIC -fsigned-char -O3 -pg -g -Werror" \
+ LDFLAGS="-static $(LDFLAGS)" all
+
+
+unsigned :
+ make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \
+ CFLAGS="-Wall -ansi -pedantic -fPIC -funsigned-char -g -O2" all
+
+
+m64 :
+ make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \
+ CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -m64 -g" all
+
+
+pen4 :
+ stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \
+ exopt="-march=pentium4 -minline-all-stringops -fprefetch-loop-arrays" ; \
+ make MYLIBS="$(MYLIBS)" \
+ CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all
+
+
+k8 :
+ stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \
+ exopt="-march=k8 -minline-all-stringops -fprefetch-loop-arrays" ; \
+ make MYLIBS="$(MYLIBS)" \
+ CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all
+
+
+clean :
+ rm -rf $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \
+ *.exe *.dll.a *.dll *.dylib *.sl TAGS srcdoc gmon.out leak.log \
+ casket casket.* casket-* *~
+
+
+version :
+ vernum=`expr $(LIBVER)00 + $(LIBREV)` ; \
+ sed -e 's/_QDBM_VERSION.*/_QDBM_VERSION "$(VERSION)"/' \
+ -e "s/_QDBM_LIBVER.*/_QDBM_LIBVER $$vernum/" depot.h > depot.h~
+ [ -f depot.h~ ] && mv -f depot.h~ depot.h
+
+
+install :
+ mkdir -p $(DESTDIR)$(MYHEADDIR)
+ cd $(srcdir) && cp -Rf $(MYHEADS) $(DESTDIR)$(MYHEADDIR)
+ mkdir -p $(DESTDIR)$(MYLIBDIR)
+ cp -Rf $(MYLIBS) $(DESTDIR)$(MYLIBDIR)
+ mkdir -p $(DESTDIR)$(MYBINDIR)
+ cp -Rf $(MYBINS) $(DESTDIR)$(MYBINDIR)
+ mkdir -p $(DESTDIR)$(MYMAN1DIR)
+ cd $(srcdir)/man && cp -Rf $(MYMAN1S) $(DESTDIR)$(MYMAN1DIR)
+ mkdir -p $(DESTDIR)$(MYMAN3DIR)
+ cd $(srcdir)/man && cp -Rf $(MYMAN3S) $(DESTDIR)$(MYMAN3DIR)
+ mkdir -p $(DESTDIR)$(MYDATADIR)
+ cd $(srcdir) && cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR)
+ mkdir -p $(DESTDIR)$(MYPCDIR)
+ cd $(srcdir) && cp -Rf $(MYPCS) $(DESTDIR)$(MYPCDIR)
+ @printf '\n'
+ @printf '#================================================================\n'
+ @printf '# Thanks for using QDBM.\n'
+ @printf '#================================================================\n'
+
+
+install-strip :
+ make DESTDIR=$(DESTDIR) install
+ cd $(DESTDIR)$(MYBINDIR) && strip $(MYBINS)
+
+
+uninstall :
+ cd $(DESTDIR)$(MYHEADDIR) && rm -f $(MYHEADS)
+ cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYLIBS)
+ cd $(DESTDIR)$(MYBINDIR) && rm -f $(MYBINS)
+ cd $(DESTDIR)$(MYMAN1DIR) && rm -f $(MYMAN1S)
+ cd $(DESTDIR)$(MYMAN3DIR) && rm -f $(MYMAN3S)
+ rm -rf $(DESTDIR)$(MYDATADIR)
+ cd $(DESTDIR)$(MYPCDIR) && rm -f $(MYPCS)
+
+
+dist :
+ sync ; sync
+ for dir in $(SUBDIRS) ; \
+ do \
+ if [ -d $$dir ] ; \
+ then \
+ echo Making $@ in $$dir ; \
+ ( cd $$dir && if [ -f configure.in ] ; then autoconf ; ./configure ; \
+ make dist ; fi ) ; \
+ fi ; \
+ done
+ make version
+ make distclean
+ cd .. && tar cvf - $(PACKAGEDIR) | gzip -c > $(PACKAGETGZ)
+ sync ; sync
+
+
+distclean : clean
+ for dir in $(SUBDIRS) ; \
+ do \
+ if [ -d $$dir ] ; \
+ then \
+ echo Making $@ in $$dir ; \
+ ( cd $$dir && if [ -f Makefile ] ; then make distclean ; fi ) ; \
+ fi ; \
+ done
+ rm -rf Makefile LTmakefile qdbm.spec qdbm.pc config.cache config.log config.status \
+ autom4te.cache rpm-tmp *-win32
+
+
+TAGS :
+ etags -o $@ *.c *.h
+
+
+sdoc :
+ rm -rf srcdoc
+ ./lab/ccdoc -d srcdoc -t "Source Documents of QDBM" *.h *.c
+
+
+check :
+ sync ; sync
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./dptest write -s casket 500 500000
+ $(RUNENV) $(RUNCMD) ./dptest write casket 50000 5000
+ $(RUNENV) $(RUNCMD) ./dptest read casket
+ $(RUNENV) $(RUNCMD) ./dptest read -wb casket
+ $(RUNENV) $(RUNCMD) ./dptest rcat -c casket 50000 50 500 32 8
+ $(RUNENV) $(RUNCMD) ./dptest combo casket
+ $(RUNENV) $(RUNCMD) ./dptest wicked -c casket 5000
+ $(RUNENV) $(RUNCMD) ./dptest wicked casket 500
+ $(RUNENV) $(RUNCMD) ./dpmgr repair casket
+ $(RUNENV) $(RUNCMD) ./dpmgr optimize casket
+ $(RUNENV) $(RUNCMD) ./dpmgr list casket
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./crtest write -s casket 500 100000 5
+ $(RUNENV) $(RUNCMD) ./crtest write casket 50000 500 10
+ $(RUNENV) $(RUNCMD) ./crtest read casket
+ $(RUNENV) $(RUNCMD) ./crtest read -wb casket
+ $(RUNENV) $(RUNCMD) ./crtest rcat -c casket 50000 5 10 500 32 8
+ $(RUNENV) $(RUNCMD) ./crtest combo casket
+ $(RUNENV) $(RUNCMD) ./crtest wicked -c casket 5000
+ $(RUNENV) $(RUNCMD) ./crtest wicked casket 500
+ $(RUNENV) $(RUNCMD) ./crmgr repair casket
+ $(RUNENV) $(RUNCMD) ./crmgr optimize casket
+ $(RUNENV) $(RUNCMD) ./crmgr list casket
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./crtest write -lob casket 1000 50 10
+ $(RUNENV) $(RUNCMD) ./crtest read -lob casket
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./rltest write casket 5000
+ $(RUNENV) $(RUNCMD) ./rltest read casket 5000
+ $(RUNENV) $(RUNCMD) ./rlmgr list casket
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./hvtest write casket 5000
+ $(RUNENV) $(RUNCMD) ./hvtest read casket 5000
+ $(RUNENV) $(RUNCMD) ./hvmgr optimize casket
+ $(RUNENV) $(RUNCMD) ./hvmgr list casket
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./hvtest write -qdbm -s casket 500
+ $(RUNENV) $(RUNCMD) ./hvtest write -qdbm casket 5000
+ $(RUNENV) $(RUNCMD) ./hvtest read -qdbm casket 5000
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./cbtest sort 5000
+ $(RUNENV) $(RUNCMD) ./cbtest strstr 500
+ $(RUNENV) $(RUNCMD) ./cbtest list 50000
+ $(RUNENV) $(RUNCMD) ./cbtest list -d 500
+ $(RUNENV) $(RUNCMD) ./cbtest map 50000 500
+ $(RUNENV) $(RUNCMD) ./cbtest map -d 500 5
+ $(RUNENV) $(RUNCMD) ./cbtest heap 50000 500
+ $(RUNENV) $(RUNCMD) ./cbtest heap -d 500 50
+ $(RUNENV) $(RUNCMD) ./cbtest wicked 5000
+ $(RUNENV) $(RUNCMD) ./cbtest misc
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./vltest write -tune 32 31 32 32 casket 50000
+ $(RUNENV) $(RUNCMD) ./vltest read casket
+ $(RUNENV) $(RUNCMD) ./vltest rdup -tune 32 31 512 256 casket 50000 50000
+ $(RUNENV) $(RUNCMD) ./vltest combo casket
+ $(RUNENV) $(RUNCMD) ./vltest wicked -c casket 5000
+ $(RUNENV) $(RUNCMD) ./vltest wicked casket 500
+ $(RUNENV) $(RUNCMD) ./vlmgr repair casket
+ $(RUNENV) $(RUNCMD) ./vlmgr optimize casket
+ $(RUNENV) $(RUNCMD) ./vlmgr list casket
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./vltest write -int -cz -tune 32 31 32 32 casket 50000
+ $(RUNENV) $(RUNCMD) ./vltest read -int -vc casket
+ $(RUNENV) $(RUNCMD) ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000
+ $(RUNENV) $(RUNCMD) ./vltest combo -cz casket
+ $(RUNENV) $(RUNCMD) ./vltest wicked -cz -c casket 5000
+ $(RUNENV) $(RUNCMD) ./vltest combo -cy casket
+ $(RUNENV) $(RUNCMD) ./vltest wicked -cy -c casket 5000
+ $(RUNENV) $(RUNCMD) ./vltest combo -cx casket
+ $(RUNENV) $(RUNCMD) ./vltest wicked -cx -c casket 5000
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./odtest write casket 500 50 5000
+ $(RUNENV) $(RUNCMD) ./odtest read casket
+ $(RUNENV) $(RUNCMD) ./odtest combo casket
+ $(RUNENV) $(RUNCMD) ./odtest wicked casket 500
+ rm -rf casket*
+ $(RUNENV) $(RUNCMD) ./qmttest casket 50000 10
+ rm -rf casket*
+ @printf '\n'
+ @printf '#================================================================\n'
+ @printf '# Checking completed.\n'
+ @printf '#================================================================\n'
+
+
+check-valgrind :
+ make RUNCMD="valgrind --tool=memcheck --log-fd=1" check | tee leak.log
+ grep ERROR leak.log
+ grep 'at exit' leak.log
+
+
+world :
+ make clean ; make
+ cd plus ; [ -f Makefile ] || ./configure ; make clean ; make
+ cd java ; [ -f Makefile ] || ./configure ; make clean ; make
+ cd perl ; [ -f Makefile ] || ./configure ; make clean ; make
+ cd ruby ; [ -f Makefile ] || ./configure ; make clean ; make
+ cd cgi ; [ -f Makefile ] || ./configure ; make clean ; make
+
+
+install-world :
+ make install
+ cd plus ; [ -f Makefile ] || ./configure ; make install
+ cd java ; [ -f Makefile ] || ./configure ; make install
+ cd perl ; [ -f Makefile ] || ./configure ; make install
+ cd ruby ; [ -f Makefile ] || ./configure ; make install
+ cd cgi ; [ -f Makefile ] || ./configure ; make install
+
+
+uninstall-world :
+ make uninstall
+ cd plus ; [ -f Makefile ] || ./configure ; make uninstall
+ cd java ; [ -f Makefile ] || ./configure ; make uninstall
+ cd perl ; [ -f Makefile ] || ./configure ; make uninstall
+ cd ruby ; [ -f Makefile ] || ./configure ; make uninstall
+ cd cgi ; [ -f Makefile ] || ./configure ; make uninstall
+
+
+check-world :
+ make check
+ cd plus ; [ -f Makefile ] || ./configure ; make check
+ cd java ; [ -f Makefile ] || ./configure ; make check
+ cd perl ; [ -f Makefile ] || ./configure ; make check
+ cd ruby ; [ -f Makefile ] || ./configure ; make check
+
+
+rpm : ../$(PACKAGETGZ) qdbm.spec
+ mkdir -p rpm-tmp/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
+ mkdir -p rpm-tmp/RPMS/i386
+ cp ../$(PACKAGETGZ) rpm-tmp/SOURCES
+ rpmbuild -bb --target i386 --define "_topdir `pwd`/rpm-tmp" qdbm.spec
+ mv -f rpm-tmp/RPMS/i386/$(PACKAGE)-*$(VERSION)*.rpm ..
+ rm -rf rpm-tmp
+
+
+win32pkg :
+ test -f /bin/mgwz.dll
+ test -f /bin/libiconv-2.dll
+ make uninstall && make uninstall-win && make clean
+ make mingw && strip *.exe && make install-win
+ cd java && ./configure
+ cd java && make uninstall && make uninstall-win && make clean
+ cd java && make mingw
+ cd cgi && ./configure
+ cd cgi && make clean
+ cd cgi && make mingw && strip *.cgi
+ mkdir -p $(PACKAGE)-$(VERSION)-win32
+ cp -Rf $(MYHEADS) libqdbm.dll.a qdbm.dll *.exe *.html \
+ misc/README-win32.txt misc/COPYING.txt misc/win32check.bat \
+ /bin/mgwz.dll /bin/libiconv-2.dll \
+ $(PACKAGE)-$(VERSION)-win32
+ cp -Rf java/jqdbm.dll java/qdbm.jar java/*.html java/japidoc $(PACKAGE)-$(VERSION)-win32
+ mkdir -p $(PACKAGE)-$(VERSION)-win32/cgi
+ cp -Rf cgi/*.cgi cgi/*.conf cgi/*.html $(PACKAGE)-$(VERSION)-win32/cgi
+ zip -r $(PACKAGE)-$(VERSION)-win32.zip $(PACKAGE)-$(VERSION)-win32
+ mv -f $(PACKAGE)-$(VERSION)-win32.zip ..
+ rm -rf $(PACKAGE)-$(VERSION)-win32
+ make uninstall && make uninstall-win && make clean
+ cd java ; make uninstall && make uninstall-win && make clean
+
+
+win :
+ make MYLIBS="$(MYWINLIBS)" CFLAGS="-Wall -ansi -pedantic -fsigned-char -O2"
+
+
+mingw :
+ make CC="gcc -mno-cygwin" MYLIBS="$(MYWINLIBS)" \
+ CFLAGS="-Wall -fsigned-char -O2" LIBLDFLAGS="@MGWLIBS@" LDFLAGS="-L. -lqdbm @MGWLIBS@"
+
+
+check-win :
+ make check
+
+
+install-win :
+ make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \
+ MYLIBS="$(MYWINLIBS)" install
+ cp -Rf qdbm.dll $(DESTDIR)$(MYBINDIR)
+
+
+uninstall-win :
+ make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \
+ MYLIBS="$(MYWINLIBS)" uninstall
+ rm -f $(DESTDIR)$(MYBINDIR)/qdbm.dll
+
+
+def : libqdbm.a
+ ./misc/makevcdef libqdbm.a > qdbm.def
+
+
+mac :
+ make MYLIBS="$(MYMACLIBS)" CFLAGS="-Wall -fsigned-char -fno-common -O2"
+
+
+check-mac :
+ make RUNENV="DYLD_LIBRARY_PATH=." check
+
+
+install-mac :
+ make MYLIBS="$(MYMACLIBS)" install
+
+
+uninstall-mac :
+ make MYLIBS="$(MYMACLIBS)" uninstall
+
+
+hpux :
+ make MYLIBS="$(MYHPUXLIBS)"
+
+
+check-hpux :
+ make RUNENV="SHLIB_PATH=." check
+
+
+install-hpux :
+ make MYLIBS="$(MYHPUXLIBS)" install
+
+
+uninstall-hpux :
+ make MYLIBS="$(MYHPUXLIBS)" uninstall
+
+
+no-so :
+ make MYLIBS="libqdbm.a" all
+
+
+install-no-so :
+ make MYLIBS="libqdbm.a" install
+
+
+uninstall-no-so :
+ make MYLIBS="libqdbm.a" uninstall
+
+
+.PHONY : all clean install check
+
+
+
+#================================================================
+# Building binaries
+#================================================================
+
+
+libqdbm.a : $(MYLIBOBJS)
+ $(AR) $(ARFLAGS) $@ $(MYLIBOBJS)
+
+
+libqdbm.so.$(LIBVER).$(LIBREV).0 : $(MYLIBOBJS)
+ if uname -a | egrep -i 'SunOS' > /dev/null ; \
+ then \
+ $(CC) -shared -Wl,-G,-h,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \
+ else \
+ $(CC) -shared -Wl,-soname,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \
+ fi
+
+
+libqdbm.so.$(LIBVER) : libqdbm.so.$(LIBVER).$(LIBREV).0
+ ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@
+
+
+libqdbm.so : libqdbm.so.$(LIBVER).$(LIBREV).0
+ ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@
+
+
+libqdbm.dll.a : qdbm.dll
+
+
+qdbm.dll : $(MYLIBOBJS)
+ $(CC) -shared -o $@ \
+ -Wl,--out-implib=lib$@.a \
+ -Wl,--export-all-symbols \
+ -Wl,--enable-auto-import \
+ -Wl,--add-stdcall-alias \
+ -Wl,--whole-archive \
+ -Wl,--no-whole-archive $(MYLIBOBJS) $(LIBLDFLAGS)
+
+
+libqdbm.$(LIBVER).$(LIBREV).0.dylib : $(MYLIBOBJS)
+ $(CC) -dynamiclib -o $@ \
+ -install_name $(MYLIBDIR)/libqdbm.$(LIBVER).dylib \
+ -current_version $(LIBVER).$(LIBREV).0 \
+ -compatibility_version $(LIBVER) \
+ $(MYLIBOBJS) $(LIBLDFLAGS)
+
+
+libqdbm.$(LIBVER).dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib
+ ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@
+
+
+libqdbm.dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib
+ ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@
+
+
+libqdbm.sl : $(MYLIBOBJS)
+ $(CC) -shared -Wl,-b -o $@ $(MYLIBOBJS) $(LIBLDFLAGS)
+
+
+dpmgr : dpmgr.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ dpmgr.o $(LDFLAGS)
+
+
+dptest : dptest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ dptest.o $(LDFLAGS)
+
+
+dptsv : dptsv.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ dptsv.o $(LDFLAGS)
+
+
+crmgr : crmgr.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ crmgr.o $(LDFLAGS)
+
+
+crtest : crtest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ crtest.o $(LDFLAGS)
+
+
+crtsv : crtsv.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ crtsv.o $(LDFLAGS)
+
+
+rlmgr : rlmgr.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ rlmgr.o $(LDFLAGS)
+
+
+rltest : rltest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ rltest.o $(LDFLAGS)
+
+
+hvmgr : hvmgr.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ hvmgr.o $(LDFLAGS)
+
+
+hvtest : hvtest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ hvtest.o $(LDFLAGS)
+
+
+cbtest : cbtest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ cbtest.o $(LDFLAGS)
+
+
+cbcodec : cbcodec.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ cbcodec.o $(LDFLAGS)
+
+
+vlmgr : vlmgr.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ vlmgr.o $(LDFLAGS)
+
+
+vltest : vltest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ vltest.o $(LDFLAGS)
+
+
+vltsv : vltsv.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ vltsv.o $(LDFLAGS)
+
+
+odmgr : odmgr.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ odmgr.o $(LDFLAGS)
+
+
+odtest : odtest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ odtest.o $(LDFLAGS)
+
+
+odidx : odidx.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ odidx.o $(LDFLAGS)
+
+
+qmttest : qmttest.o $(MYLIBS)
+ $(LDENV) $(CC) $(CFLAGS) -o $@ qmttest.o $(LDFLAGS)
+
+
+depot.o : depot.h myconf.h
+
+curia.o : depot.h curia.h myconf.h
+
+relic.o : depot.h relic.h myconf.h
+
+hovel.o : depot.h curia.h hovel.h myconf.h
+
+cabin.o : cabin.h myconf.h
+
+villa.o : depot.h cabin.h villa.h myconf.h
+
+vista.o : depot.h curia.h cabin.h villa.h vista.h myconf.h villa.c
+
+odeum.o : depot.h curia.h cabin.h villa.h myconf.h
+
+myconf.o : myconf.h
+
+dpmgr.o dptest.o dptsv.o : depot.h cabin.h
+
+crmgr.o crtest.o crtsv.o : depot.h curia.h cabin.h
+
+rlmgr.o rltest.o : depot.h relic.h cabin.h
+
+hvmgr.o hvtest.o : depot.h curia.h hovel.h cabin.h
+
+cbtest.o cbcodec.o : cabin.h
+
+vlmgr.o vltest.o vltsv.o : depot.h cabin.h villa.h
+
+odmgr.o odtest.o odidx.o : depot.h curia.h cabin.h villa.h odeum.h
+
+
+
+# END OF FILE
diff --git a/qdbm/NEWS b/qdbm/NEWS
new file mode 100644
index 00000000..52a27359
--- /dev/null
+++ b/qdbm/NEWS
@@ -0,0 +1,43 @@
+== Thu, 08 Sep 2005 13:13:58 +0900 ==
+
+Compressing options of ZLIB was changed. If you use villa with the option
+`VL_OZCOMP', databases of the earlier versions are not compatible with the
+current version of QDBM. To convert the old database to new format,
+export endian independent data by "vlmgr exportdb" with the old version,
+and then import it by "vlmgr importdb" with the latest version.
+
+
+
+== Wed, 10 Mar 2004 23:24:24 +0900 ==
+
+API of B+ tree was changed a bit. Even if you build QDBM with ZLIB
+enabled, records are not compressed. Instead of it, the function `vlopen'
+has the option `VL_OZCOMP'. If it is specified, records are compressed.
+So, you can switch whether to compress records or not, on runtime.
+
+Users who have used ZLIB feature should modify their source codes to
+specify that option.
+
+
+
+== Wed, 10 Dec 2003 09:24:12 +0900 ==
+
+The database format was changed with QDBM 1.7.13. Newer versions do not
+have backward compatibility to old format. You can convert old databases
+with the command `fmtcnv031127' in the sub directory `lab'. To build it,
+perform the following steps.
+
+ cd lab
+ make fmtcnv031127
+
+About usage of it, see the file `README' in `lab'. Typically, to convert
+a Depot database named as `old' and create a database named as `new',
+perform the following step.
+
+ ./fmtcnv031127 < old > new
+
+I'm sorry for bothering you.
+
+
+
+== END OF FILE ==
diff --git a/qdbm/README b/qdbm/README
new file mode 100644
index 00000000..d7adad4b
--- /dev/null
+++ b/qdbm/README
@@ -0,0 +1,50 @@
+================================================================
+ QDBM: Quick Database Manager
+ Copyright (C) 2000-2007 Mikio Hirabayashi
+================================================================
+
+
+Please read the following documents with a WWW browser.
+How to install QDBM is explained in the specification.
+
+ README - this file
+ COPYING - license
+ ChangeLog - history of enhancement
+ NEWS - news for users
+ THANKS - list of contributors
+ spex.html - specification
+ spex-ja.html - specification in Japanese
+
+
+Contents of the directory tree is below.
+
+ ./ - sources of QDBM
+ ./plus/ - API for C++ (read `./plus/xspex.html')
+ ./java/ - API for Java (read `./java/jspex.html')
+ ./perl/ - API for Perl (read `./perl/plspex.html')
+ ./ruby/ - API for Ruby (read `./ruby/rbspex.html')
+ ./cgi/ - CGI scripts (read `./cgi/cgispex.html')
+ ./man1/ - manual pages for commands
+ ./man3/ - manual pages for C API
+ ./lab/ - for test and experiment
+ ./bros/ - for comparison with other database managers
+ ./misc/ - miscellaneous files
+
+
+QDBM is released under the terms of the GNU Lesser General Public
+License. See the file `COPYING' for details.
+
+QDBM was written by Mikio Hirabayashi. You can contact the author
+by e-mail to `mikio@users.sourceforge.net'. However, as for
+topics which can be shared among other users, pleae send it to
+the mailing list. To join the mailing list, refer to the following
+URL.
+
+ http://lists.sourceforge.net/lists/listinfo/qdbm-users
+
+
+Thanks.
+
+
+
+== END OF FILE ==
diff --git a/qdbm/RISCmakefile b/qdbm/RISCmakefile
new file mode 100644
index 00000000..2cebbb3f
--- /dev/null
+++ b/qdbm/RISCmakefile
@@ -0,0 +1,140 @@
+# Makefile for the RISC OS version of QDBM
+
+
+# Define which compiler to use:
+
+CC = cc
+#CC = gcc
+
+
+#########################################
+# DO NOT EDIT ANYTHING BELOW THIS LINE! #
+#########################################
+
+ifeq (${CC},cc)
+CC = cc
+LD = link
+AR = libfile
+DEPEND = -depend !Depend
+CC_FLAGS = -Wdp -throwback -Otime -I@,Unix: -JUnix
+UNIXLIB = Unix:o.UnixLib
+else
+ifeq (${CC},gcc)
+CC = gcc
+LD = gcc
+AR = ar
+CC_FLAGS = -mthrowback -O3 -I.
+else
+# No other compiler supported!
+endif
+endif
+
+QDBM_OBJS = o.depot o.curia o.relic o.hovel o.cabin o.villa o.vista o.odeum o.myconf
+
+.INIT :
+ @cdir o
+
+## Rule Patterns ##
+
+.SUFFIXES : .c .o
+
+.c.o :
+ $(CC) $(CC_FLAGS) $(DEPEND) -c -o $@ $<
+
+# Static dependencies:
+
+all : libqdbm testcases managers converters
+
+libqdbm : $(QDBM_OBJS)
+ $(AR) $(AR_FLAGS) -c -o libqdbm $(QDBM_OBJS)
+
+testcases : dptest crtest rltest hvtest cbtest vltest odtest
+ create testcases
+
+managers : dpmgr crmgr rlmgr hvmgr vlmgr odmgr
+ create managers
+
+converters : dptsv crtsv cbcodec vltsv odidx
+ create converters
+
+dptest : o.dptest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+crtest : o.crtest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+rltest : o.rltest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+hvtest : o.hvtest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+cbtest : o.cbtest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+vltest : o.vltest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+odtest : o.odtest libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+dpmgr : o.dpmgr libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+crmgr : o.crmgr libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+rlmgr : o.rlmgr libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+hvmgr : o.hvmgr libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+vlmgr : o.vlmgr libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+odmgr : o.odmgr libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+dptsv : o.dptsv libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+crtsv : o.crtsv libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+cbcodec : o.cbcodec libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+vltsv : o.vltsv libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+odidx : o.odidx libqdbm
+ $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB)
+
+clean:
+ -ifthere libqdbm then wipe libqdbm ~CFR~V
+ -ifthere dptest then wipe dptest ~CFR~V
+ -ifthere crtest then wipe crtest ~CFR~V
+ -ifthere rltest then wipe rltest ~CFR~V
+ -ifthere hvtest then wipe hvtest ~CFR~V
+ -ifthere cbtest then wipe cbtest ~CFR~V
+ -ifthere vltest then wipe vltest ~CFR~V
+ -ifthere odtest then wipe odtest ~CFR~V
+ -ifthere dpmgr then wipe dpmgr ~CFR~V
+ -ifthere crmgr then wipe crmgr ~CFR~V
+ -ifthere rlmgr then wipe rlmgr ~CFR~V
+ -ifthere hvmgr then wipe hvmgr ~CFR~V
+ -ifthere cbmgr then wipe cbmgr ~CFR~V
+ -ifthere vlmgr then wipe vlmgr ~CFR~V
+ -ifthere odmgr then wipe odmgr ~CFR~V
+ -ifthere dptsv then wipe dptsv ~CFR~V
+ -ifthere crtsv then wipe crtsv ~CFR~V
+ -ifthere cbcodec then wipe cbcodec ~CFR~V
+ -ifthere vltsv then wipe vltsv ~CFR~V
+ -ifthere odidx then wipe odidx ~CFR~V
+ -ifthere testcases then wipe testcases ~CFR~V
+ -ifthere managers then wipe managers ~CFR~V
+ -ifthere converters then wipe converters ~CFR~V
+ -ifthere o.* then wipe o.* ~CFR~V
+
+# Dynamic dependencies:
diff --git a/qdbm/THANKS b/qdbm/THANKS
new file mode 100644
index 00000000..dc7a0dc6
--- /dev/null
+++ b/qdbm/THANKS
@@ -0,0 +1,45 @@
+================================================================
+ Thanks to all of the following for their valuable suggestions
+ or contributions.
+================================================================
+
+
+Kang-Jin Lee
+ - suggestions about the GDBM-compatible API
+ - contributions about Makefile
+
+Pat Podenski
+ - suggestions about porting to Mac OS X, Solaris, and HP-UX
+
+BERO
+ - contributions about supporting MinGW
+
+Stefan Bellon
+ - contributions about porting to RISC OS
+
+Donald Gobin
+ - contributions about supporting Visual C++
+
+Emanuel Dejanu
+ - contributions about supporting Visual C++
+
+Keith Bostic
+ - suggestions about the performance test suite
+
+William Lachance
+ - contributions about RPM spec file
+
+Zed A. Shaw
+ - contributions about a text analyzer in Odeum
+ - contributions about a query language in Odeum
+
+Chris Bilderback
+ - contributions about cursor functions in Villa.
+
+Fumitoshi Ukai
+ - contributions of troff manuals
+ - making Debian packages
+
+
+
+== END OF FILE ==
diff --git a/qdbm/VCmakefile b/qdbm/VCmakefile
new file mode 100644
index 00000000..210a98ff
--- /dev/null
+++ b/qdbm/VCmakefile
@@ -0,0 +1,248 @@
+# Makefile to build QDBM using Microsoft Visual C++
+
+
+
+#================================================================
+# Setting variables
+#================================================================
+
+
+# VC++ directory
+VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7
+
+# User options
+YOUR_CLFLAGS =
+YOUR_LIBFLAGS =
+YOUR_LINKFLAGS=
+
+# Configurations
+!IF "$(CFG)" == "ld"
+!MESSAGE Build using static debug configuration
+BASE_FLAGS = /MLd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"
+BASE_DEFS = /D_DEBUG /D__DEBUG__
+OUTDIR = .\tmp_ld
+LIB_APPEND = _ld
+EXE_APPEND = _ld
+!ELSEIF "$(CFG)" == "l"
+!MESSAGE Build using static release configuration
+BASE_DEFS = /DNDEBUG
+BASE_FLAGS = /ML /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"
+OUTDIR = .\tmp_l
+LIB_APPEND = _l
+EXE_APPEND = _l
+!ELSEIF "$(CFG)" == "td"
+!MESSAGE Build using static threaded debug configuration
+BASE_FLAGS = /MTd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"
+BASE_DEFS = /D_DEBUG /D__DEBUG__
+OUTDIR = .\tmp_td
+LIB_APPEND = _td
+EXE_APPEND = _td
+!ELSEIF "$(CFG)" == "t"
+!MESSAGE Build using static threaded release configuration
+BASE_DEFS = /DNDEBUG
+BASE_FLAGS = /MT /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"
+OUTDIR = .\tmp_t
+LIB_APPEND = _t
+EXE_APPEND = _t
+!ELSEIF "$(CFG)" == "dd"
+!MESSAGE Build using dynamic threaded debug configuration
+BASE_FLAGS = /MDd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"
+BASE_DEFS = /D_DEBUG /D__DEBUG__
+OUTDIR = .\tmp_dd
+LIB_APPEND = _dd
+EXE_APPEND = _dd
+!ELSE
+!MESSAGE Build using dynamic threaded release configuration
+BASE_DEFS = /DNDEBUG
+BASE_FLAGS = /MD /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"
+OUTDIR = .\tmp
+LIB_APPEND =
+EXE_APPEND =
+!ENDIF
+
+# Building binaries
+CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." \
+ /nologo $(YOUR_CLFLAGS) $(BASE_FLAGS) $(BASE_DEFS) /D_CRT_SECURE_NO_DEPRECATE=1
+LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \
+ /nologo $(YOUR_LIBFLAGS)
+LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \
+ /nologo $(YOUR_LINKFLAGS)
+
+# Targets
+MYLIBS = qdbm$(LIB_APPEND).dll qdbm$(LIB_APPEND).lib qdbm$(LIB_APPEND)_static.lib
+LIBOBJS = $(OUTDIR)\depot.obj $(OUTDIR)\curia.obj $(OUTDIR)\relic.obj \
+ $(OUTDIR)\hovel.obj $(OUTDIR)\cabin.obj $(OUTDIR)\villa.obj \
+ $(OUTDIR)\vista.obj $(OUTDIR)\odeum.obj $(OUTDIR)\myconf.obj
+MYBINS = dpmgr$(EXE_APPEND).exe dptest$(EXE_APPEND).exe dptsv$(EXE_APPEND).exe \
+ crmgr$(EXE_APPEND).exe crtest$(EXE_APPEND).exe crtsv$(EXE_APPEND).exe \
+ rlmgr$(EXE_APPEND).exe rltest$(EXE_APPEND).exe hvmgr$(EXE_APPEND).exe \
+ hvtest$(EXE_APPEND).exe cbtest$(EXE_APPEND).exe cbcodec$(EXE_APPEND).exe \
+ vlmgr$(EXE_APPEND).exe vltest$(EXE_APPEND).exe vltsv$(EXE_APPEND).exe \
+ odmgr$(EXE_APPEND).exe odtest$(EXE_APPEND).exe odidx$(EXE_APPEND).exe
+
+
+
+#================================================================
+# Suffix rules
+#================================================================
+
+
+.SUFFIXES :
+.SUFFIXES : .c .obj
+
+.c{$(OUTDIR)}.obj :
+ cl /c $(CLFLAGS) $<
+
+.c.obj:
+ cl /c $(CLFLAGS) $<
+
+
+
+#================================================================
+# Actions
+#================================================================
+
+
+all : $(OUTDIR) $(MYLIBS) $(MYBINS)
+
+
+allcfg:
+ nmake /NOLOGO /f VCmakefile CFG=ld
+ nmake /NOLOGO /f VCmakefile CFG=l
+ nmake /NOLOGO /f VCmakefile CFG=td
+ nmake /NOLOGO /f VCmakefile CFG=t
+ nmake /NOLOGO /f VCmakefile CFG=dd
+ nmake /NOLOGO /f VCmakefile
+
+
+clean :
+ -rd tmp_ld /S /Q > NUL: 2>&1
+ -rd tmp_l /S /Q > NUL: 2>&1
+ -rd tmp_td /S /Q > NUL: 2>&1
+ -rd tmp_t /S /Q > NUL: 2>&1
+ -rd tmp_dd /S /Q > NUL: 2>&1
+ -rd tmp /S /Q > NUL: 2>&1
+ -del *.obj *.lib *.dll *.exp *.exe casket /F /Q > NUL: 2>&1
+
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/" mkdir "$(OUTDIR)"
+
+
+
+#================================================================
+# Building binaries
+#================================================================
+
+
+qdbm$(LIB_APPEND).dll : $(LIBOBJS) qdbm.def
+ link /DLL /DEF:qdbm.def $(LINKFLAGS) /OUT:$@ /IMPLIB:qdbm$(LIB_APPEND).lib $(LIBOBJS)
+
+
+qdbm$(LIB_APPEND).lib : qdbm$(LIB_APPEND).dll
+
+
+qdbm$(LIB_APPEND)_static.lib : $(LIBOBJS)
+ lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS)
+
+
+dpmgr$(EXE_APPEND).exe : $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib
+
+
+dptest$(EXE_APPEND).exe : $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib
+
+
+dptsv$(EXE_APPEND).exe : $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib
+
+
+crmgr$(EXE_APPEND).exe : $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib
+
+
+crtest$(EXE_APPEND).exe : $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib
+
+
+crtsv$(EXE_APPEND).exe : $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib
+
+
+rlmgr$(EXE_APPEND).exe : $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib
+
+
+rltest$(EXE_APPEND).exe : $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib
+
+
+hvmgr$(EXE_APPEND).exe : $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib
+
+
+hvtest$(EXE_APPEND).exe : $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib
+
+
+cbtest$(EXE_APPEND).exe : $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib
+
+
+cbcodec$(EXE_APPEND).exe : $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib
+
+
+vlmgr$(EXE_APPEND).exe : $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib
+
+
+vltest$(EXE_APPEND).exe : $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib
+
+
+vltsv$(EXE_APPEND).exe : $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib
+
+
+odmgr$(EXE_APPEND).exe : $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib
+
+
+odtest$(EXE_APPEND).exe : $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib
+
+
+odidx$(EXE_APPEND).exe : $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib
+ link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib
+
+
+$(OUTDIR)\depot.obj $(OUTDIR)\dpmgr.obj $(OUTDIR)\dptest.obj $(OUTDIR)\dptsv.obj : \
+ depot.h myconf.h
+
+$(OUTDIR)\curia.obj $(OUTDIR)\crmgr.obj $(OUTDIR)\crtest.obj $(OUTDIR)\crtsv.obj : \
+ curia.h depot.h myconf.h
+
+$(OUTDIR)\relic.obj $(OUTDIR)\rlmgr.obj $(OUTDIR)\rltest.obj : \
+ relic.h depot.h myconf.h
+
+$(OUTDIR)\hovel.obj $(OUTDIR)\hvmgr.obj $(OUTDIR)\hvtest.obj : \
+ hovel.h depot.h curia.h myconf.h
+
+$(OUTDIR)\cabin.obj $(OUTDIR)\cbtest.obj $(OUTDIR)\cbcodec.obj : \
+ cabin.h myconf.h
+
+$(OUTDIR)\villa.obj $(OUTDIR)\vlmgr.obj $(OUTDIR)\vltest.obj $(OUTDIR)\vltsv.obj : \
+ villa.h depot.h cabin.h myconf.h
+
+$(OUTDIR)\vista.obj : vista.h villa.h depot.h curia.h cabin.h myconf.h
+
+$(OUTDIR)\odeum.obj $(OUTDIR)\odmgr.obj $(OUTDIR)\odtest.obj $(OUTDIR)\odidx.obj : \
+ odeum.h depot.h curia.h cabin.h villa.h myconf.h
+
+$(OUTDIR)\myconf.obj : myconf.h
+
+
+
+# END OF FILE
diff --git a/qdbm/cabin.c b/qdbm/cabin.c
new file mode 100644
index 00000000..262cb3eb
--- /dev/null
+++ b/qdbm/cabin.c
@@ -0,0 +1,3529 @@
+/*************************************************************************************************
+ * Implementation of Cabin
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#define QDBM_INTERNAL 1
+
+#include "cabin.h"
+#include "myconf.h"
+
+#define CB_GCUNIT 64 /* allocation unit size of a buffer in gc */
+#define CB_SPBUFSIZ 32 /* size of a buffer for sprintf */
+#define CB_SPMAXWIDTH 128 /* max width of a column for sprintf */
+#define CB_MAPPBNUM 251 /* bucket size of a petit map handle */
+#define CB_MAPCSUNIT 52 /* small allocation unit size of map concatenation */
+#define CB_MAPCBUNIT 252 /* big allocation unit size of map concatenation */
+#define CB_MSGBUFSIZ 256 /* size of a buffer for log message */
+#define CB_IOBUFSIZ 8192 /* size of an I/O buffer */
+#define CB_FILEMODE 00644 /* permission of a creating file */
+#define CB_NUMBUFSIZ 32 /* size of a buffer for a number */
+#define CB_ENCBUFSIZ 32 /* size of a buffer for encoding name */
+#define CB_DATEBUFSIZ 64 /* size of a buffer for date expression */
+#define CB_VNUMBUFSIZ 8 /* size of a buffer for variable length number */
+
+/* set a buffer for a variable length number */
+#define CB_SETVNUMBUF(CB_len, CB_buf, CB_num) \
+ do { \
+ int _CB_num; \
+ _CB_num = (CB_num); \
+ if(_CB_num == 0){ \
+ ((signed char *)(CB_buf))[0] = 0; \
+ (CB_len) = 1; \
+ } else { \
+ (CB_len) = 0; \
+ while(_CB_num > 0){ \
+ int _CB_rem = _CB_num & 0x7f; \
+ _CB_num >>= 7; \
+ if(_CB_num > 0){ \
+ ((signed char *)(CB_buf))[(CB_len)] = -_CB_rem - 1; \
+ } else { \
+ ((signed char *)(CB_buf))[(CB_len)] = _CB_rem; \
+ } \
+ (CB_len)++; \
+ } \
+ } \
+ } while(FALSE)
+
+/* read a variable length buffer */
+#define CB_READVNUMBUF(CB_buf, CB_size, CB_num, CB_step) \
+ do { \
+ int _CB_i, _CB_base; \
+ CB_num = 0; \
+ _CB_base = 1; \
+ if((size) < 2){ \
+ CB_num = ((signed char *)(CB_buf))[0]; \
+ (CB_step) = 1; \
+ } else { \
+ for(_CB_i = 0; _CB_i < (size); _CB_i++){ \
+ if(((signed char *)(CB_buf))[_CB_i] >= 0){ \
+ CB_num += ((signed char *)(CB_buf))[_CB_i] * _CB_base; \
+ break; \
+ } \
+ CB_num += _CB_base * (((signed char *)(CB_buf))[_CB_i] + 1) * -1; \
+ _CB_base *= 128; \
+ } \
+ (CB_step) = _CB_i + 1; \
+ } \
+ } while(FALSE)
+
+/* get the first hash value */
+#define CB_FIRSTHASH(CB_res, CB_kbuf, CB_ksiz) \
+ do { \
+ const unsigned char *_CB_p; \
+ int _CB_ksiz; \
+ _CB_p = (const unsigned char *)(CB_kbuf); \
+ _CB_ksiz = CB_ksiz; \
+ for((CB_res) = 19780211; _CB_ksiz--;){ \
+ (CB_res) = (CB_res) * 37 + *(_CB_p)++; \
+ } \
+ (CB_res) &= INT_MAX; \
+ } while(FALSE)
+
+/* get the second hash value */
+#define CB_SECONDHASH(CB_res, CB_kbuf, CB_ksiz) \
+ do { \
+ const unsigned char *_CB_p; \
+ int _CB_ksiz; \
+ _CB_p = (const unsigned char *)(CB_kbuf) + CB_ksiz - 1; \
+ _CB_ksiz = CB_ksiz; \
+ for((CB_res) = 0x13579bdf; _CB_ksiz--;){ \
+ (CB_res) = (CB_res) * 31 + *(_CB_p)--; \
+ } \
+ (CB_res) &= INT_MAX; \
+ } while(FALSE)
+
+
+/* private function prototypes */
+static void cbggchandler(void);
+static void cbggckeeper(void *ptr, void (*func)(void *));
+static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap,
+ int(*compar)(const void *, const void *));
+static int cblistelemcmp(const void *a, const void *b);
+static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz);
+
+
+
+/*************************************************************************************************
+ * public objects
+ *************************************************************************************************/
+
+
+/* Call back function for handling a fatal error. */
+void (*cbfatalfunc)(const char *message) = NULL;
+
+
+/* Allocate a region on memory. */
+void *cbmalloc(size_t size){
+ char *p;
+ assert(size > 0 && size < INT_MAX);
+ if(!(p = malloc(size))) cbmyfatal("out of memory");
+ return p;
+}
+
+
+/* Re-allocate a region on memory. */
+void *cbrealloc(void *ptr, size_t size){
+ char *p;
+ assert(size > 0);
+ if(!(p = realloc(ptr, size))) cbmyfatal("out of memory");
+ return p;
+}
+
+
+/* Duplicate a region on memory. */
+char *cbmemdup(const char *ptr, int size){
+ char *p;
+ assert(ptr);
+ if(size < 0) size = strlen(ptr);
+ CB_MALLOC(p, size + 1);
+ memcpy(p, ptr, size);
+ p[size] = '\0';
+ return p;
+}
+
+
+/* Free a region on memory. */
+void cbfree(void *ptr){
+ free(ptr);
+}
+
+
+/* Register the pointer or handle of an object to the global garbage collector. */
+void cbglobalgc(void *ptr, void (*func)(void *)){
+ assert(ptr && func);
+ cbggckeeper(ptr, func);
+}
+
+
+/* Exercise the global garbage collector explicitly. */
+void cbggcsweep(void){
+ cbggckeeper(NULL, NULL);
+}
+
+
+/* Check availability of allocation of the virtual memory. */
+int cbvmemavail(size_t size){
+ assert(size >= 0);
+ return _qdbm_vmemavail(size);
+}
+
+
+/* Sort an array using insert sort. */
+void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){
+ char *bp, *swap;
+ int i, j;
+ assert(base && nmemb >= 0 && size > 0 && compar);
+ bp = (char *)base;
+ CB_MALLOC(swap, size);
+ for(i = 1; i < nmemb; i++){
+ if(compar(bp + (i - 1) * size, bp + i * size) > 0){
+ memcpy(swap, bp + i * size, size);
+ for(j = i; j > 0; j--){
+ if(compar(bp + (j - 1) * size, swap) < 0) break;
+ memcpy(bp + j * size, bp + (j - 1) * size, size);
+ }
+ memcpy(bp + j * size, swap, size);
+ }
+ }
+ free(swap);
+}
+
+
+/* Sort an array using shell sort. */
+void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){
+ char *bp, *swap;
+ int step, bottom, i, j;
+ assert(base && nmemb >= 0 && size > 0 && compar);
+ bp = (char *)base;
+ CB_MALLOC(swap, size);
+ for(step = (nmemb - 1) / 3; step >= 0; step = (step - 1) / 3){
+ if(step < 5) step = 1;
+ for(bottom = 0; bottom < step; bottom++){
+ for(i = bottom + step; i < nmemb; i += step){
+ if(compar(bp + (i - step) * size, bp + i * size) > 0){
+ memcpy(swap, bp + i * size, size);
+ for(j = i; j > step - 1; j -= step){
+ if(compar(bp + (j - step) * size, swap) < 0) break;
+ memcpy(bp + j * size, bp + (j - step) * size, size);
+ }
+ memcpy(bp + j * size, swap, size);
+ }
+ }
+ }
+ if(step < 2) break;
+ }
+ free(swap);
+}
+
+
+/* Sort an array using heap sort. */
+void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){
+ char *bp, *swap;
+ int top, bottom, mybot, i;
+ assert(base && nmemb >= 0 && size > 0 && compar);
+ bp = (char *)base;
+ nmemb--;
+ bottom = nmemb / 2 + 1;
+ top = nmemb;
+ CB_MALLOC(swap, size);
+ while(bottom > 0){
+ bottom--;
+ mybot = bottom;
+ i = 2 * mybot;
+ while(i <= top) {
+ if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++;
+ if(compar(bp + mybot * size, bp + i * size) >= 0) break;
+ memcpy(swap, bp + mybot * size, size);
+ memcpy(bp + mybot * size, bp + i * size, size);
+ memcpy(bp + i * size, swap, size);
+ mybot = i;
+ i = 2 * mybot;
+ }
+ }
+ while(top > 0){
+ memcpy(swap, bp, size);
+ memcpy(bp, bp + top * size, size);
+ memcpy(bp + top * size, swap, size);
+ top--;
+ mybot = bottom;
+ i = 2 * mybot;
+ while(i <= top){
+ if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++;
+ if(compar(bp + mybot * size, bp + i * size) >= 0) break;
+ memcpy(swap, bp + mybot * size, size);
+ memcpy(bp + mybot * size, bp + i * size, size);
+ memcpy(bp + i * size, swap, size);
+ mybot = i;
+ i = 2 * mybot;
+ }
+ }
+ free(swap);
+}
+
+
+/* Sort an array using quick sort. */
+void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){
+ char *pswap, *vswap;
+ assert(base && nmemb >= 0 && size > 0 && compar);
+ CB_MALLOC(pswap, size);
+ CB_MALLOC(vswap, size);
+ cbqsortsub(base, nmemb, size, pswap, vswap, compar);
+ free(vswap);
+ free(pswap);
+}
+
+
+/* Compare two strings with case insensitive evaluation. */
+int cbstricmp(const char *astr, const char *bstr){
+ int ac, bc;
+ assert(astr && bstr);
+ while(*astr != '\0'){
+ if(*bstr == '\0') return 1;
+ ac = (*astr >= 'A' && *astr <= 'Z') ? *astr + ('a' - 'A') : *(unsigned char *)astr;
+ bc = (*bstr >= 'A' && *bstr <= 'Z') ? *bstr + ('a' - 'A') : *(unsigned char *)bstr;
+ if(ac != bc) return ac - bc;
+ astr++;
+ bstr++;
+ }
+ return *bstr == '\0' ? 0 : -1;
+}
+
+
+/* Check whether a string begins with a key. */
+int cbstrfwmatch(const char *str, const char *key){
+ assert(str && key);
+ while(*key != '\0'){
+ if(*str != *key || *str == '\0') return FALSE;
+ key++;
+ str++;
+ }
+ return TRUE;
+}
+
+
+/* Check whether a string begins with a key, with case insensitive evaluation. */
+int cbstrfwimatch(const char *str, const char *key){
+ int sc, kc;
+ assert(str && key);
+ while(*key != '\0'){
+ if(*str == '\0') return FALSE;
+ sc = *str;
+ if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A';
+ kc = *key;
+ if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A';
+ if(sc != kc) return FALSE;
+ key++;
+ str++;
+ }
+ return TRUE;
+}
+
+
+/* Check whether a string ends with a key. */
+int cbstrbwmatch(const char *str, const char *key){
+ int slen, klen, i;
+ assert(str && key);
+ slen = strlen(str);
+ klen = strlen(key);
+ for(i = 1; i <= klen; i++){
+ if(i > slen || str[slen-i] != key[klen-i]) return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* Check whether a string ends with a key, with case insensitive evaluation. */
+int cbstrbwimatch(const char *str, const char *key){
+ int slen, klen, i, sc, kc;
+ assert(str && key);
+ slen = strlen(str);
+ klen = strlen(key);
+ for(i = 1; i <= klen; i++){
+ if(i > slen) return FALSE;
+ sc = str[slen-i];
+ if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A';
+ kc = key[klen-i];
+ if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A';
+ if(sc != kc) return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* Locate a substring in a string using KMP method. */
+char *cbstrstrkmp(const char *haystack, const char *needle){
+ int i, j, hlen, nlen;
+ signed char tbl[0x100];
+ assert(haystack && needle);
+ nlen = strlen(needle);
+ if(nlen >= 0x100) return strstr(haystack, needle);
+ tbl[0] = -1;
+ i = 0;
+ j = -1;
+ while(i < nlen){
+ while((j >= 0) && (needle[i] != needle[j])){
+ j = tbl[j];
+ }
+ i++;
+ j++;
+ tbl[i] = j;
+ }
+ hlen = strlen(haystack);
+ i = 0;
+ j = 0;
+ while(i < hlen && j < nlen){
+ while((j >= 0) && (haystack[i] != needle[j])){
+ j = tbl[j];
+ }
+ i++;
+ j++;
+ }
+ if(j == nlen) return (char *)(haystack + i - nlen);
+ return NULL;
+}
+
+
+/* Locate a substring in a string using BM method. */
+char *cbstrstrbm(const char *haystack, const char *needle){
+ const unsigned char *rp;
+ const char *ep;
+ unsigned char tbl[0x100];
+ int i, j, nlen, len, idx;
+ assert(haystack && needle);
+ nlen = strlen(needle);
+ if(nlen < 3 || nlen >= 0x100) return strstr(haystack, needle);
+ for(i = 0; i < 0x100; i++){
+ tbl[i] = nlen;
+ }
+ len = nlen;
+ rp = (const unsigned char *)needle;
+ while(len > 0){
+ tbl[*rp++] = --len;
+ }
+ nlen--;
+ ep = haystack + strlen(haystack) - nlen;
+ while(haystack < ep){
+ for(i = nlen; haystack[i] == needle[i]; i--){
+ if(i == 0) return (char *)haystack;
+ }
+ idx = ((unsigned char *)haystack)[i];
+ j = tbl[idx] - nlen + i;
+ haystack += j > 0 ? j : 2;
+ }
+ return NULL;
+}
+
+
+/* Convert the letters of a string to upper case. */
+char *cbstrtoupper(char *str){
+ int i;
+ assert(str);
+ for(i = 0; str[i] != '\0'; i++){
+ if(str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A';
+ }
+ return str;
+}
+
+
+/* Convert the letters of a string to lower case. */
+char *cbstrtolower(char *str){
+ int i;
+ assert(str);
+ for(i = 0; str[i] != '\0'; i++){
+ if(str[i] >= 'A' && str[i] <= 'Z') str[i] += 'a' - 'A';
+ }
+ return str;
+}
+
+
+/* Cut space characters at head or tail of a string. */
+char *cbstrtrim(char *str){
+ char *wp;
+ int i, head;
+ assert(str);
+ wp = str;
+ head = TRUE;
+ for(i = 0; str[i] != '\0'; i++){
+ if((str[i] >= 0x07 && str[i] <= 0x0d) || str[i] == 0x20){
+ if(!head) *(wp++) = str[i];
+ } else {
+ *(wp++) = str[i];
+ head = FALSE;
+ }
+ }
+ *wp = '\0';
+ while(wp > str && ((wp[-1] >= 0x07 && wp[-1] <= 0x0d) || wp[-1] == 0x20)){
+ *(--wp) = '\0';
+ }
+ return str;
+}
+
+
+/* Squeeze space characters in a string and trim it. */
+char *cbstrsqzspc(char *str){
+ char *wp;
+ int i, spc;
+ assert(str);
+ wp = str;
+ spc = TRUE;
+ for(i = 0; str[i] != '\0'; i++){
+ if(str[i] > 0 && str[i] <= ' '){
+ if(!spc) *(wp++) = str[i];
+ spc = TRUE;
+ } else {
+ *(wp++) = str[i];
+ spc = FALSE;
+ }
+ }
+ *wp = '\0';
+ for(wp--; wp >= str; wp--){
+ if(*wp > 0 && *wp <= ' '){
+ *wp = '\0';
+ } else {
+ break;
+ }
+ }
+ return str;
+}
+
+
+/* Count the number of characters in a string of UTF-8. */
+int cbstrcountutf(const char *str){
+ const unsigned char *rp;
+ int cnt;
+ assert(str);
+ rp = (unsigned char *)str;
+ cnt = 0;
+ while(*rp != '\0'){
+ if((*rp & 0x80) == 0x00 || (*rp & 0xe0) == 0xc0 ||
+ (*rp & 0xf0) == 0xe0 || (*rp & 0xf8) == 0xf0) cnt++;
+ rp++;
+ }
+ return cnt;
+}
+
+
+/* Cut a string of UTF-8 at the specified number of characters. */
+char *cbstrcututf(char *str, int num){
+ unsigned char *wp;
+ int cnt;
+ assert(str && num >= 0);
+ wp = (unsigned char *)str;
+ cnt = 0;
+ while(*wp != '\0'){
+ if((*wp & 0x80) == 0x00 || (*wp & 0xe0) == 0xc0 ||
+ (*wp & 0xf0) == 0xe0 || (*wp & 0xf8) == 0xf0){
+ cnt++;
+ if(cnt > num){
+ *wp = '\0';
+ break;
+ }
+ }
+ wp++;
+ }
+ return str;
+}
+
+
+/* Get a datum handle. */
+CBDATUM *cbdatumopen(const char *ptr, int size){
+ CBDATUM *datum;
+ CB_MALLOC(datum, sizeof(*datum));
+ CB_MALLOC(datum->dptr, CB_DATUMUNIT);
+ datum->dptr[0] = '\0';
+ datum->dsize = 0;
+ datum->asize = CB_DATUMUNIT;
+ if(ptr) CB_DATUMCAT(datum, ptr, (size >= 0 ? size : strlen(ptr)));
+ return datum;
+}
+
+
+/* Copy a datum. */
+CBDATUM *cbdatumdup(const CBDATUM *datum){
+ assert(datum);
+ return cbdatumopen(datum->dptr, datum->dsize);
+}
+
+
+/* Free a datum handle. */
+void cbdatumclose(CBDATUM *datum){
+ assert(datum);
+ free(datum->dptr);
+ free(datum);
+}
+
+
+/* Concatenate a datum and a region. */
+void cbdatumcat(CBDATUM *datum, const char *ptr, int size){
+ assert(datum && ptr);
+ if(size < 0) size = strlen(ptr);
+ if(datum->dsize + size >= datum->asize){
+ datum->asize = datum->asize * 2 + size + 1;
+ CB_REALLOC(datum->dptr, datum->asize);
+ }
+ memcpy(datum->dptr + datum->dsize, ptr, size);
+ datum->dsize += size;
+ datum->dptr[datum->dsize] = '\0';
+}
+
+
+/* Get the pointer of the region of a datum. */
+const char *cbdatumptr(const CBDATUM *datum){
+ assert(datum);
+ return datum->dptr;
+}
+
+
+/* Get the size of the region of a datum. */
+int cbdatumsize(const CBDATUM *datum){
+ assert(datum);
+ return datum->dsize;
+}
+
+
+/* Set the size of the region of a datum. */
+void cbdatumsetsize(CBDATUM *datum, int size){
+ assert(datum && size >= 0);
+ if(size <= datum->dsize){
+ datum->dsize = size;
+ datum->dptr[size] = '\0';
+ } else {
+ if(size >= datum->asize){
+ datum->asize = datum->asize * 2 + size + 1;
+ CB_REALLOC(datum->dptr, datum->asize);
+ }
+ memset(datum->dptr + datum->dsize, 0, (size - datum->dsize) + 1);
+ datum->dsize = size;
+ }
+}
+
+
+/* Perform formatted output into a datum. */
+void cbdatumprintf(CBDATUM *datum, const char *format, ...){
+ va_list ap;
+ char *tmp, cbuf[CB_NUMBUFSIZ], tbuf[CB_NUMBUFSIZ*2];
+ unsigned char c;
+ int cblen, tlen;
+ assert(datum && format);
+ va_start(ap, format);
+ while(*format != '\0'){
+ if(*format == '%'){
+ cbuf[0] = '%';
+ cblen = 1;
+ format++;
+ while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_NUMBUFSIZ - 1){
+ cbuf[cblen++] = *format;
+ format++;
+ }
+ cbuf[cblen++] = *format;
+ cbuf[cblen] = '\0';
+ switch(*format){
+ case 's':
+ tmp = va_arg(ap, char *);
+ if(!tmp) tmp = "(null)";
+ cbdatumcat(datum, tmp, -1);
+ break;
+ case 'd':
+ tlen = sprintf(tbuf, cbuf, va_arg(ap, int));
+ cbdatumcat(datum, tbuf, tlen);
+ break;
+ case 'o': case 'u': case 'x': case 'X': case 'c':
+ tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int));
+ cbdatumcat(datum, tbuf, tlen);
+ break;
+ case 'e': case 'E': case 'f': case 'g': case 'G':
+ tlen = sprintf(tbuf, cbuf, va_arg(ap, double));
+ cbdatumcat(datum, tbuf, tlen);
+ break;
+ case '@':
+ tmp = va_arg(ap, char *);
+ if(!tmp) tmp = "(null)";
+ while(*tmp){
+ switch(*tmp){
+ case '&': cbdatumcat(datum, "&amp;", 5); break;
+ case '<': cbdatumcat(datum, "&lt;", 4); break;
+ case '>': cbdatumcat(datum, "&gt;", 4); break;
+ case '"': cbdatumcat(datum, "&quot;", 6); break;
+ default:
+ if(!((*tmp >= 0 && *tmp <= 0x8) || (*tmp >= 0x0e && *tmp <= 0x1f)))
+ cbdatumcat(datum, tmp, 1);
+ break;
+ }
+ tmp++;
+ }
+ break;
+ case '?':
+ tmp = va_arg(ap, char *);
+ if(!tmp) tmp = "(null)";
+ while(*tmp){
+ c = *(unsigned char *)tmp;
+ if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){
+ cbdatumcat(datum, tmp, 1);
+ } else {
+ tlen = sprintf(tbuf, "%%%02X", c);
+ cbdatumcat(datum, tbuf, tlen);
+ }
+ tmp++;
+ }
+ break;
+ case ':':
+ tmp = va_arg(ap, char *);
+ if(!tmp) tmp = "";
+ tmp = cbmimeencode(tmp, "UTF-8", TRUE);
+ cbdatumcat(datum, tmp, -1);
+ free(tmp);
+ break;
+ case '%':
+ cbdatumcat(datum, "%", 1);
+ break;
+ }
+ } else {
+ cbdatumcat(datum, format, 1);
+ }
+ format++;
+ }
+ va_end(ap);
+}
+
+
+/* Convert a datum to an allocated region. */
+char *cbdatumtomalloc(CBDATUM *datum, int *sp){
+ char *ptr;
+ assert(datum);
+ ptr = datum->dptr;
+ if(sp) *sp = datum->dsize;
+ free(datum);
+ return ptr;
+}
+
+
+/* Get a list handle. */
+CBLIST *cblistopen(void){
+ CBLIST *list;
+ CB_MALLOC(list, sizeof(*list));
+ list->anum = CB_LISTUNIT;
+ CB_MALLOC(list->array, sizeof(list->array[0]) * list->anum);
+ list->start = 0;
+ list->num = 0;
+ return list;
+}
+
+
+/* Copy a list. */
+CBLIST *cblistdup(const CBLIST *list){
+ CBLIST *newlist;
+ int i, size;
+ const char *val;
+ assert(list);
+ CB_LISTOPEN2(newlist, CB_LISTNUM(list));
+ for(i = 0; i < CB_LISTNUM(list); i++){
+ val = CB_LISTVAL2(list, i, size);
+ CB_LISTPUSH(newlist, val, size);
+ }
+ return newlist;
+}
+
+
+/* Close a list handle. */
+void cblistclose(CBLIST *list){
+ int i, end;
+ assert(list);
+ end = list->start + list->num;
+ for(i = list->start; i < end; i++){
+ free(list->array[i].dptr);
+ }
+ free(list->array);
+ free(list);
+}
+
+
+/* Get the number of elements of a list. */
+int cblistnum(const CBLIST *list){
+ assert(list);
+ return list->num;
+}
+
+
+/* Get the pointer to the region of an element. */
+const char *cblistval(const CBLIST *list, int index, int *sp){
+ assert(list && index >= 0);
+ if(index >= list->num) return NULL;
+ index += list->start;
+ if(sp) *sp = list->array[index].dsize;
+ return list->array[index].dptr;
+}
+
+
+/* Add an element at the end of a list. */
+void cblistpush(CBLIST *list, const char *ptr, int size){
+ int index;
+ assert(list && ptr);
+ if(size < 0) size = strlen(ptr);
+ index = list->start + list->num;
+ if(index >= list->anum){
+ list->anum *= 2;
+ CB_REALLOC(list->array, list->anum * sizeof(list->array[0]));
+ }
+ CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1);
+ memcpy(list->array[index].dptr, ptr, size);
+ list->array[index].dptr[size] = '\0';
+ list->array[index].dsize = size;
+ list->num++;
+}
+
+
+/* Remove an element of the end of a list. */
+char *cblistpop(CBLIST *list, int *sp){
+ int index;
+ assert(list);
+ if(list->num < 1) return NULL;
+ index = list->start + list->num - 1;
+ list->num--;
+ if(sp) *sp = list->array[index].dsize;
+ return list->array[index].dptr;
+}
+
+
+/* Add an element at the top of a list. */
+void cblistunshift(CBLIST *list, const char *ptr, int size){
+ int index;
+ assert(list && ptr);
+ if(size < 0) size = strlen(ptr);
+ if(list->start < 1){
+ if(list->start + list->num >= list->anum){
+ list->anum *= 2;
+ CB_REALLOC(list->array, list->anum * sizeof(list->array[0]));
+ }
+ list->start = list->anum - list->num;
+ memmove(list->array + list->start, list->array, list->num * sizeof(list->array[0]));
+ }
+ index = list->start - 1;
+ CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1);
+ memcpy(list->array[index].dptr, ptr, size);
+ list->array[index].dptr[size] = '\0';
+ list->array[index].dsize = size;
+ list->start--;
+ list->num++;
+}
+
+
+/* Remove an element of the top of a list. */
+char *cblistshift(CBLIST *list, int *sp){
+ int index;
+ assert(list);
+ if(list->num < 1) return NULL;
+ index = list->start;
+ list->start++;
+ list->num--;
+ if(sp) *sp = list->array[index].dsize;
+ return list->array[index].dptr;
+}
+
+
+/* Add an element at the specified location of a list. */
+void cblistinsert(CBLIST *list, int index, const char *ptr, int size){
+ assert(list && index >= 0);
+ if(index > list->num) return;
+ if(size < 0) size = strlen(ptr);
+ index += list->start;
+ if(list->start + list->num >= list->anum){
+ list->anum *= 2;
+ CB_REALLOC(list->array, list->anum * sizeof(list->array[0]));
+ }
+ memmove(list->array + index + 1, list->array + index,
+ sizeof(list->array[0]) * (list->start + list->num - index));
+ CB_MEMDUP(list->array[index].dptr, ptr, size);
+ list->array[index].dsize = size;
+ list->num++;
+}
+
+
+/* Remove an element at the specified location of a list. */
+char *cblistremove(CBLIST *list, int index, int *sp){
+ char *dptr;
+ assert(list && index >= 0);
+ if(index >= list->num) return NULL;
+ index += list->start;
+ dptr = list->array[index].dptr;
+ if(sp) *sp = list->array[index].dsize;
+ list->num--;
+ memmove(list->array + index, list->array + index + 1,
+ sizeof(list->array[0]) * (list->start + list->num - index));
+ return dptr;
+}
+
+
+/* Overwrite an element at the specified location of a list. */
+void cblistover(CBLIST *list, int index, const char *ptr, int size){
+ assert(list && index >= 0);
+ if(index >= list->num) return;
+ if(size < 0) size = strlen(ptr);
+ index += list->start;
+ if(size > list->array[index].dsize)
+ CB_REALLOC(list->array[index].dptr, size + 1);
+ memcpy(list->array[index].dptr, ptr, size);
+ list->array[index].dsize = size;
+ list->array[index].dptr[size] = '\0';
+}
+
+
+/* Sort elements of a list in lexical order. */
+void cblistsort(CBLIST *list){
+ assert(list);
+ qsort(list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp);
+}
+
+
+/* Search a list for an element using liner search. */
+int cblistlsearch(const CBLIST *list, const char *ptr, int size){
+ int i, end;
+ assert(list && ptr);
+ if(size < 0) size = strlen(ptr);
+ end = list->start + list->num;
+ for(i = list->start; i < end; i++){
+ if(list->array[i].dsize == size && !memcmp(list->array[i].dptr, ptr, size))
+ return i - list->start;
+ }
+ return -1;
+}
+
+
+/* Search a list for an element using binary search. */
+int cblistbsearch(const CBLIST *list, const char *ptr, int size){
+ CBLISTDATUM key, *res;
+ assert(list && ptr);
+ if(size < 0) size = strlen(ptr);
+ CB_MEMDUP(key.dptr, ptr, size);
+ key.dsize = size;
+ res = bsearch(&key, list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp);
+ free(key.dptr);
+ return res ? (res - list->array - list->start) : -1;
+}
+
+
+/* Serialize a list into a byte array. */
+char *cblistdump(const CBLIST *list, int *sp){
+ char *buf, vnumbuf[CB_VNUMBUFSIZ];
+ const char *vbuf;
+ int i, bsiz, vnumsiz, ln, vsiz;
+ assert(list && sp);
+ ln = CB_LISTNUM(list);
+ CB_SETVNUMBUF(vnumsiz, vnumbuf, ln);
+ CB_MALLOC(buf, vnumsiz + 1);
+ memcpy(buf, vnumbuf, vnumsiz);
+ bsiz = vnumsiz;
+ for(i = 0; i < ln; i++){
+ vbuf = CB_LISTVAL2(list, i, vsiz);
+ CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz);
+ CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1);
+ memcpy(buf + bsiz, vnumbuf, vnumsiz);
+ bsiz += vnumsiz;
+ memcpy(buf + bsiz, vbuf, vsiz);
+ bsiz += vsiz;
+ }
+ *sp = bsiz;
+ return buf;
+}
+
+
+/* Redintegrate a serialized list. */
+CBLIST *cblistload(const char *ptr, int size){
+ CBLIST *list;
+ const char *rp;
+ int i, anum, step, ln, vsiz;
+ assert(ptr && size >= 0);
+ anum = size / (sizeof(CBLISTDATUM) + 1);
+ CB_LISTOPEN2(list, anum);
+ rp = ptr;
+ CB_READVNUMBUF(rp, size, ln, step);
+ rp += step;
+ size -= step;
+ if(ln > size) return list;
+ for(i = 0; i < ln; i++){
+ if(size < 1) break;
+ CB_READVNUMBUF(rp, size, vsiz, step);
+ rp += step;
+ size -= step;
+ if(vsiz > size) break;
+ CB_LISTPUSH(list, rp, vsiz);
+ rp += vsiz;
+ }
+ return list;
+}
+
+
+/* Get a map handle. */
+CBMAP *cbmapopen(void){
+ return cbmapopenex(CB_MAPBNUM);
+}
+
+
+/* Copy a map. */
+CBMAP *cbmapdup(CBMAP *map){
+ CBMAP *newmap;
+ const char *kbuf, *vbuf;
+ int ksiz, vsiz;
+ assert(map);
+ cbmapiterinit(map);
+ newmap = map->rnum > CB_MAPPBNUM ? cbmapopen() : cbmapopenex(CB_MAPPBNUM);
+ while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
+ CB_MAPITERVAL(vbuf, kbuf, vsiz);
+ cbmapput(newmap, kbuf, ksiz, vbuf, vsiz, FALSE);
+ }
+ cbmapiterinit(map);
+ return newmap;
+}
+
+
+/* Close a map handle. */
+void cbmapclose(CBMAP *map){
+ CBMAPDATUM *datum, *next;
+ datum = map->first;
+ while(datum){
+ next = datum->next;
+ free(datum);
+ datum = next;
+ }
+ free(map->buckets);
+ free(map);
+}
+
+
+/* Store a record. */
+int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over){
+ CBMAPDATUM *datum, **entp, *old;
+ char *dbuf;
+ int bidx, hash, kcmp, psiz;
+ assert(map && kbuf && vbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(vsiz < 0) vsiz = strlen(vbuf);
+ CB_FIRSTHASH(hash, kbuf, ksiz);
+ bidx = hash % map->bnum;
+ datum = map->buckets[bidx];
+ entp = map->buckets + bidx;
+ CB_SECONDHASH(hash, kbuf, ksiz);
+ while(datum){
+ if(hash > datum->hash){
+ entp = &(datum->left);
+ datum = datum->left;
+ } else if(hash < datum->hash){
+ entp = &(datum->right);
+ datum = datum->right;
+ } else {
+ dbuf = (char *)datum + sizeof(*datum);
+ kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz);
+ if(kcmp < 0){
+ entp = &(datum->left);
+ datum = datum->left;
+ } else if(kcmp > 0){
+ entp = &(datum->right);
+ datum = datum->right;
+ } else {
+ if(!over) return FALSE;
+ psiz = CB_ALIGNPAD(ksiz);
+ if(vsiz > datum->vsiz){
+ old = datum;
+ CB_REALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1);
+ if(datum != old){
+ if(map->first == old) map->first = datum;
+ if(map->last == old) map->last = datum;
+ if(*entp == old) *entp = datum;
+ if(datum->prev) datum->prev->next = datum;
+ if(datum->next) datum->next->prev = datum;
+ dbuf = (char *)datum + sizeof(*datum);
+ }
+ }
+ memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
+ dbuf[ksiz+psiz+vsiz] = '\0';
+ datum->vsiz = vsiz;
+ return TRUE;
+ }
+ }
+ }
+ psiz = CB_ALIGNPAD(ksiz);
+ CB_MALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1);
+ dbuf = (char *)datum + sizeof(*datum);
+ memcpy(dbuf, kbuf, ksiz);
+ dbuf[ksiz] = '\0';
+ datum->ksiz = ksiz;
+ memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
+ dbuf[ksiz+psiz+vsiz] = '\0';
+ datum->vsiz = vsiz;
+ datum->hash = hash;
+ datum->left = NULL;
+ datum->right = NULL;
+ datum->prev = map->last;
+ datum->next = NULL;
+ *entp = datum;
+ if(!map->first) map->first = datum;
+ if(map->last) map->last->next = datum;
+ map->last = datum;
+ map->rnum++;
+ return TRUE;
+}
+
+
+/* Concatenate a value at the end of the value of the existing record. */
+void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz){
+ CBMAPDATUM *datum, **entp, *old;
+ char *dbuf;
+ int bidx, hash, kcmp, psiz, asiz, unit;
+ assert(map && kbuf && vbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(vsiz < 0) vsiz = strlen(vbuf);
+ CB_FIRSTHASH(hash, kbuf, ksiz);
+ bidx = hash % map->bnum;
+ datum = map->buckets[bidx];
+ entp = map->buckets + bidx;
+ CB_SECONDHASH(hash, kbuf, ksiz);
+ while(datum){
+ if(hash > datum->hash){
+ entp = &(datum->left);
+ datum = datum->left;
+ } else if(hash < datum->hash){
+ entp = &(datum->right);
+ datum = datum->right;
+ } else {
+ dbuf = (char *)datum + sizeof(*datum);
+ kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz);
+ if(kcmp < 0){
+ entp = &(datum->left);
+ datum = datum->left;
+ } else if(kcmp > 0){
+ entp = &(datum->right);
+ datum = datum->right;
+ } else {
+ psiz = CB_ALIGNPAD(ksiz);
+ asiz = sizeof(*datum) + ksiz + psiz + datum->vsiz + vsiz + 1;
+ unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT;
+ asiz = (asiz - 1) + unit - (asiz - 1) % unit;
+ old = datum;
+ CB_REALLOC(datum, asiz);
+ if(datum != old){
+ if(map->first == old) map->first = datum;
+ if(map->last == old) map->last = datum;
+ if(*entp == old) *entp = datum;
+ if(datum->prev) datum->prev->next = datum;
+ if(datum->next) datum->next->prev = datum;
+ dbuf = (char *)datum + sizeof(*datum);
+ }
+ memcpy(dbuf + ksiz + psiz + datum->vsiz, vbuf, vsiz);
+ dbuf[ksiz+psiz+datum->vsiz+vsiz] = '\0';
+ datum->vsiz += vsiz;
+ return;
+ }
+ }
+ }
+ psiz = CB_ALIGNPAD(ksiz);
+ asiz = sizeof(*datum) + ksiz + psiz + vsiz + 1;
+ unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT;
+ asiz = (asiz - 1) + unit - (asiz - 1) % unit;
+ CB_MALLOC(datum, asiz);
+ dbuf = (char *)datum + sizeof(*datum);
+ memcpy(dbuf, kbuf, ksiz);
+ dbuf[ksiz] = '\0';
+ datum->ksiz = ksiz;
+ memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
+ dbuf[ksiz+psiz+vsiz] = '\0';
+ datum->vsiz = vsiz;
+ datum->hash = hash;
+ datum->left = NULL;
+ datum->right = NULL;
+ datum->prev = map->last;
+ datum->next = NULL;
+ *entp = datum;
+ if(!map->first) map->first = datum;
+ if(map->last) map->last->next = datum;
+ map->last = datum;
+ map->rnum++;
+}
+
+
+/* Delete a record. */
+int cbmapout(CBMAP *map, const char *kbuf, int ksiz){
+ CBMAPDATUM *datum, **entp, *tmp;
+ char *dbuf;
+ int bidx, hash, kcmp;
+ assert(map && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ CB_FIRSTHASH(hash, kbuf, ksiz);
+ bidx = hash % map->bnum;
+ datum = map->buckets[bidx];
+ entp = map->buckets + bidx;
+ CB_SECONDHASH(hash, kbuf, ksiz);
+ while(datum){
+ if(hash > datum->hash){
+ entp = &(datum->left);
+ datum = datum->left;
+ } else if(hash < datum->hash){
+ entp = &(datum->right);
+ datum = datum->right;
+ } else {
+ dbuf = (char *)datum + sizeof(*datum);
+ kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz);
+ if(kcmp < 0){
+ entp = &(datum->left);
+ datum = datum->left;
+ } else if(kcmp > 0){
+ entp = &(datum->right);
+ datum = datum->right;
+ } else {
+ if(datum->prev) datum->prev->next = datum->next;
+ if(datum->next) datum->next->prev = datum->prev;
+ if(datum == map->first) map->first = datum->next;
+ if(datum == map->last) map->last = datum->prev;
+ if(datum->left && !datum->right){
+ *entp = datum->left;
+ } else if(!datum->left && datum->right){
+ *entp = datum->right;
+ } else if(!datum->left && !datum->left){
+ *entp = NULL;
+ } else {
+ *entp = datum->left;
+ tmp = *entp;
+ while(TRUE){
+ if(hash > tmp->hash){
+ if(tmp->left){
+ tmp = tmp->left;
+ } else {
+ tmp->left = datum->right;
+ break;
+ }
+ } else if(hash < tmp->hash){
+ if(tmp->right){
+ tmp = tmp->right;
+ } else {
+ tmp->right = datum->right;
+ break;
+ }
+ } else {
+ kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz);
+ if(kcmp < 0){
+ if(tmp->left){
+ tmp = tmp->left;
+ } else {
+ tmp->left = datum->right;
+ break;
+ }
+ } else {
+ if(tmp->right){
+ tmp = tmp->right;
+ } else {
+ tmp->right = datum->right;
+ break;
+ }
+ }
+ }
+ }
+ }
+ free(datum);
+ map->rnum--;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/* Retrieve a record. */
+const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp){
+ CBMAPDATUM *datum;
+ char *dbuf;
+ int hash, kcmp;
+ assert(map && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ CB_FIRSTHASH(hash, kbuf, ksiz);
+ datum = map->buckets[hash%map->bnum];
+ CB_SECONDHASH(hash, kbuf, ksiz);
+ while(datum){
+ if(hash > datum->hash){
+ datum = datum->left;
+ } else if(hash < datum->hash){
+ datum = datum->right;
+ } else {
+ dbuf = (char *)datum + sizeof(*datum);
+ kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz);
+ if(kcmp < 0){
+ datum = datum->left;
+ } else if(kcmp > 0){
+ datum = datum->right;
+ } else {
+ if(sp) *sp = datum->vsiz;
+ return dbuf + datum->ksiz + CB_ALIGNPAD(datum->ksiz);
+ }
+ }
+ }
+ return NULL;
+}
+
+
+/* Move a record to the edge. */
+int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head){
+ CBMAPDATUM *datum;
+ char *dbuf;
+ int hash, kcmp;
+ assert(map && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ CB_FIRSTHASH(hash, kbuf, ksiz);
+ datum = map->buckets[hash%map->bnum];
+ CB_SECONDHASH(hash, kbuf, ksiz);
+ while(datum){
+ if(hash > datum->hash){
+ datum = datum->left;
+ } else if(hash < datum->hash){
+ datum = datum->right;
+ } else {
+ dbuf = (char *)datum + sizeof(*datum);
+ kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz);
+ if(kcmp < 0){
+ datum = datum->left;
+ } else if(kcmp > 0){
+ datum = datum->right;
+ } else {
+ if(head){
+ if(map->first == datum) return TRUE;
+ if(map->last == datum) map->last = datum->prev;
+ if(datum->prev) datum->prev->next = datum->next;
+ if(datum->next) datum->next->prev = datum->prev;
+ datum->prev = NULL;
+ datum->next = map->first;
+ map->first->prev = datum;
+ map->first = datum;
+ } else {
+ if(map->last == datum) return TRUE;
+ if(map->first == datum) map->first = datum->next;
+ if(datum->prev) datum->prev->next = datum->next;
+ if(datum->next) datum->next->prev = datum->prev;
+ datum->prev = map->last;
+ datum->next = NULL;
+ map->last->next = datum;
+ map->last = datum;
+ }
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/* Initialize the iterator of a map handle. */
+void cbmapiterinit(CBMAP *map){
+ assert(map);
+ map->cur = map->first;
+}
+
+
+/* Get the next key of the iterator. */
+const char *cbmapiternext(CBMAP *map, int *sp){
+ CBMAPDATUM *datum;
+ assert(map);
+ if(!map->cur) return NULL;
+ datum = map->cur;
+ map->cur = datum->next;
+ if(sp) *sp = datum->ksiz;
+ return (char *)datum + sizeof(*datum);
+}
+
+
+/* Get the value binded to the key fetched from the iterator. */
+const char *cbmapiterval(const char *kbuf, int *sp){
+ CBMAPDATUM *datum;
+ assert(kbuf);
+ datum = (CBMAPDATUM *)(kbuf - sizeof(*datum));
+ if(sp) *sp = datum->vsiz;
+ return (char *)datum + sizeof(*datum) + datum->ksiz + CB_ALIGNPAD(datum->ksiz);
+}
+
+
+/* Get the number of the records stored in a map. */
+int cbmaprnum(const CBMAP *map){
+ assert(map);
+ return map->rnum;
+}
+
+
+/* Get the list handle contains all keys in a map. */
+CBLIST *cbmapkeys(CBMAP *map){
+ CBLIST *list;
+ const char *kbuf;
+ int anum, ksiz;
+ assert(map);
+ anum = cbmaprnum(map);
+ CB_LISTOPEN2(list, anum);
+ cbmapiterinit(map);
+ while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
+ CB_LISTPUSH(list, kbuf, ksiz);
+ }
+ return list;
+}
+
+
+/* Get the list handle contains all values in a map. */
+CBLIST *cbmapvals(CBMAP *map){
+ CBLIST *list;
+ const char *kbuf, *vbuf;
+ int anum, ksiz, vsiz;
+ assert(map);
+ anum = cbmaprnum(map);
+ CB_LISTOPEN2(list, anum);
+ cbmapiterinit(map);
+ while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
+ CB_MAPITERVAL(vbuf, kbuf, vsiz);
+ CB_LISTPUSH(list, vbuf, vsiz);
+ }
+ return list;
+}
+
+
+/* Serialize a map into a byte array. */
+char *cbmapdump(CBMAP *map, int *sp){
+ char *buf, vnumbuf[CB_VNUMBUFSIZ];
+ const char *kbuf, *vbuf;
+ int bsiz, vnumsiz, rn, ksiz, vsiz;
+ assert(map && sp);
+ rn = cbmaprnum(map);
+ CB_SETVNUMBUF(vnumsiz, vnumbuf, rn);
+ CB_MALLOC(buf, vnumsiz + 1);
+ memcpy(buf, vnumbuf, vnumsiz);
+ bsiz = vnumsiz;
+ cbmapiterinit(map);
+ while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
+ CB_MAPITERVAL(vbuf, kbuf, vsiz);
+ CB_SETVNUMBUF(vnumsiz, vnumbuf, ksiz);
+ CB_REALLOC(buf, bsiz + vnumsiz + ksiz + 1);
+ memcpy(buf + bsiz, vnumbuf, vnumsiz);
+ bsiz += vnumsiz;
+ memcpy(buf + bsiz, kbuf, ksiz);
+ bsiz += ksiz;
+ CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz);
+ CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1);
+ memcpy(buf + bsiz, vnumbuf, vnumsiz);
+ bsiz += vnumsiz;
+ memcpy(buf + bsiz, vbuf, vsiz);
+ bsiz += vsiz;
+ }
+ *sp = bsiz;
+ return buf;
+}
+
+
+/* Redintegrate a serialized map. */
+CBMAP *cbmapload(const char *ptr, int size){
+ CBMAP *map;
+ const char *rp, *kbuf, *vbuf;
+ int i, step, rn, ksiz, vsiz;
+ assert(ptr && size >= 0);
+ map = cbmapopenex(CB_MAPPBNUM);
+ rp = ptr;
+ CB_READVNUMBUF(rp, size, rn, step);
+ rp += step;
+ size -= step;
+ if(rn > size) return map;
+ for(i = 0; i < rn; i++){
+ if(size < 1) break;
+ CB_READVNUMBUF(rp, size, ksiz, step);
+ rp += step;
+ size -= step;
+ if(ksiz > size) break;
+ kbuf = rp;
+ rp += ksiz;
+ if(size < 1) break;
+ CB_READVNUMBUF(rp, size, vsiz, step);
+ rp += step;
+ size -= step;
+ if(vsiz > size) break;
+ vbuf = rp;
+ rp += vsiz;
+ cbmapput(map, kbuf, ksiz, vbuf, vsiz, TRUE);
+ }
+ return map;
+}
+
+
+/* Redintegrate a serialized map and get one of the records. */
+char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp){
+ const char *rp, *tkbuf, *vbuf;
+ char *rv;
+ int i, step, rn, tksiz, vsiz;
+ assert(ptr && size >= 0 && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ rp = ptr;
+ CB_READVNUMBUF(rp, size, rn, step);
+ rp += step;
+ size -= step;
+ if(rn > size) return NULL;
+ for(i = 0; i < rn; i++){
+ if(size < 1) break;
+ CB_READVNUMBUF(rp, size, tksiz, step);
+ rp += step;
+ size -= step;
+ if(tksiz > size) break;
+ tkbuf = rp;
+ rp += tksiz;
+ if(size < 1) break;
+ CB_READVNUMBUF(rp, size, vsiz, step);
+ rp += step;
+ size -= step;
+ if(vsiz > size) break;
+ vbuf = rp;
+ rp += vsiz;
+ if(tksiz == ksiz && !memcmp(tkbuf, kbuf, ksiz)){
+ if(sp) *sp = vsiz;
+ CB_MEMDUP(rv, vbuf, vsiz);
+ return rv;
+ }
+ }
+ return NULL;
+}
+
+
+/* Get a heap handle. */
+CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)){
+ CBHEAP *heap;
+ assert(size > 0 && max >= 0 && compar);
+ CB_MALLOC(heap, sizeof(*heap));
+ CB_MALLOC(heap->base, size * max + 1);
+ CB_MALLOC(heap->swap, size);
+ heap->size = size;
+ heap->num = 0;
+ heap->max = max;
+ heap->compar = compar;
+ return heap;
+}
+
+
+/* Copy a heap. */
+CBHEAP *cbheapdup(CBHEAP *heap){
+ CBHEAP *newheap;
+ assert(heap);
+ CB_MALLOC(newheap, sizeof(*newheap));
+ CB_MEMDUP(newheap->base, heap->base, heap->size * heap->max);
+ CB_MALLOC(newheap->swap, heap->size);
+ newheap->size = heap->size;
+ newheap->num = heap->num;
+ newheap->max = heap->max;
+ newheap->compar = heap->compar;
+ return newheap;
+}
+
+
+/* Close a heap handle. */
+void cbheapclose(CBHEAP *heap){
+ assert(heap);
+ free(heap->swap);
+ free(heap->base);
+ free(heap);
+}
+
+
+/* Get the number of the records stored in a heap. */
+int cbheapnum(CBHEAP *heap){
+ assert(heap);
+ return heap->num;
+}
+
+
+/* Insert a record into a heap. */
+int cbheapinsert(CBHEAP *heap, const void *ptr){
+ char *base;
+ int size, pidx, cidx, bot;
+ assert(heap && ptr);
+ if(heap->max < 1) return FALSE;
+ base = heap->base;
+ size = heap->size;
+ if(heap->num >= heap->max){
+ if(heap->compar(ptr, base) > 0) return FALSE;
+ memcpy(base, ptr, size);
+ pidx = 0;
+ bot = heap->num / 2;
+ while(pidx < bot){
+ cidx = pidx * 2 + 1;
+ if(cidx < heap->num - 1 && heap->compar(base + cidx * size, base + (cidx + 1) * size) < 0)
+ cidx++;
+ if(heap->compar(base + pidx * size, base + cidx * size) > 0) break;
+ memcpy(heap->swap, base + pidx * size, size);
+ memcpy(base + pidx * size, base + cidx * size, size);
+ memcpy(base + cidx * size, heap->swap, size);
+ pidx = cidx;
+ }
+ } else {
+ memcpy(base + size * heap->num, ptr, size);
+ cidx = heap->num;
+ while(cidx > 0){
+ pidx = (cidx - 1) / 2;
+ if(heap->compar(base + cidx * size, base + pidx * size) <= 0) break;
+ memcpy(heap->swap, base + cidx * size, size);
+ memcpy(base + cidx * size, base + pidx * size, size);
+ memcpy(base + pidx * size, heap->swap, size);
+ cidx = pidx;
+ }
+ heap->num++;
+ }
+ return TRUE;
+}
+
+
+/* Get the pointer to the region of a record in a heap. */
+const void *cbheapval(CBHEAP *heap, int index){
+ assert(heap && index >= 0);
+ if(index >= heap->num) return NULL;
+ return heap->base + index * heap->size;
+}
+
+
+/* Convert a heap to an allocated region. */
+void *cbheaptomalloc(CBHEAP *heap, int *np){
+ char *ptr;
+ assert(heap);
+ qsort(heap->base, heap->num, heap->size, heap->compar);
+ ptr = heap->base;
+ if(np) *np = heap->num;
+ free(heap->swap);
+ free(heap);
+ return ptr;
+}
+
+
+/* Allocate a formatted string on memory. */
+char *cbsprintf(const char *format, ...){
+ va_list ap;
+ char *buf, cbuf[CB_SPBUFSIZ], *str;
+ int len, cblen, num, slen;
+ unsigned int unum;
+ double dnum;
+ va_start(ap, format);
+ assert(format);
+ CB_MALLOC(buf, 1);
+ len = 0;
+ while(*format != '\0'){
+ if(*format == '%'){
+ cbuf[0] = '%';
+ cblen = 1;
+ format++;
+ while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_SPBUFSIZ - 1){
+ cbuf[cblen++] = *format;
+ format++;
+ }
+ cbuf[cblen] = '\0';
+ if(atoi(cbuf + 1) > CB_SPMAXWIDTH - 16){
+ sprintf(cbuf, "(err)");
+ } else {
+ cbuf[cblen++] = *format;
+ cbuf[cblen] = '\0';
+ }
+ switch(*format){
+ case 'd':
+ num = va_arg(ap, int);
+ CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2);
+ len += sprintf(buf + len, cbuf, num);
+ break;
+ case 'o': case 'u': case 'x': case 'X': case 'c':
+ unum = va_arg(ap, unsigned int);
+ CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2);
+ len += sprintf(buf + len, cbuf, unum);
+ break;
+ case 'e': case 'E': case 'f': case 'g': case 'G':
+ dnum = va_arg(ap, double);
+ CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2);
+ len += sprintf(buf + len, cbuf, dnum);
+ break;
+ case 's':
+ str = va_arg(ap, char *);
+ slen = strlen(str);
+ CB_REALLOC(buf, len + slen + 2);
+ memcpy(buf + len, str, slen);
+ len += slen;
+ break;
+ case '%':
+ CB_REALLOC(buf, len + 2);
+ buf[len++] = '%';
+ break;
+ default:
+ break;
+ }
+ } else {
+ CB_REALLOC(buf, len + 2);
+ buf[len++] = *format;
+ }
+ format++;
+ }
+ buf[len] = '\0';
+ va_end(ap);
+ return buf;
+}
+
+
+/* Replace some patterns in a string. */
+char *cbreplace(const char *str, CBMAP *pairs){
+ int i, bsiz, wi, rep, ksiz, vsiz;
+ char *buf;
+ const char *key, *val;
+ assert(str && pairs);
+ bsiz = CB_DATUMUNIT;
+ CB_MALLOC(buf, bsiz);
+ wi = 0;
+ while(*str != '\0'){
+ rep = FALSE;
+ cbmapiterinit(pairs);
+ while((key = cbmapiternext(pairs, &ksiz)) != NULL){
+ for(i = 0; i < ksiz; i++){
+ if(str[i] == '\0' || str[i] != key[i]) break;
+ }
+ if(i == ksiz){
+ CB_MAPITERVAL(val, key, vsiz);
+ if(wi + vsiz >= bsiz){
+ bsiz = bsiz * 2 + vsiz;
+ CB_REALLOC(buf, bsiz);
+ }
+ memcpy(buf + wi, val, vsiz);
+ wi += vsiz;
+ str += ksiz;
+ rep = TRUE;
+ break;
+ }
+ }
+ if(!rep){
+ if(wi + 1 >= bsiz){
+ bsiz = bsiz * 2 + 1;
+ CB_REALLOC(buf, bsiz);
+ }
+ buf[wi++] = *str;
+ str++;
+ }
+ }
+ CB_REALLOC(buf, wi + 1);
+ buf[wi] = '\0';
+ return buf;
+}
+
+
+/* Make a list by split a serial datum. */
+CBLIST *cbsplit(const char *ptr, int size, const char *delim){
+ CBLIST *list;
+ int bi, step;
+ assert(ptr);
+ CB_LISTOPEN(list);
+ if(size < 0) size = strlen(ptr);
+ if(delim){
+ for(bi = 0; bi < size; bi += step){
+ step = 0;
+ while(bi + step < size && !strchr(delim, ptr[bi+step])){
+ step++;
+ }
+ cblistpush(list, ptr + bi, step);
+ step++;
+ }
+ if(size > 0 && strchr(delim, ptr[size-1])) cblistpush(list, "", 0);
+ } else {
+ for(bi = 0; bi < size; bi += step){
+ step = 0;
+ while(bi + step < size && ptr[bi+step]){
+ step++;
+ }
+ cblistpush(list, ptr + bi, step);
+ step++;
+ }
+ if(size > 0 && ptr[size-1] == 0) cblistpush(list, "", 0);
+ }
+ return list;
+}
+
+
+/* Read whole data of a file. */
+char *cbreadfile(const char *name, int *sp){
+ struct stat sbuf;
+ char iobuf[CB_IOBUFSIZ], *buf;
+ int fd, size, asiz, rv;
+ asiz = CB_IOBUFSIZ * 2;
+ if(name){
+ if((fd = open(name, O_RDONLY, 0)) == -1) return NULL;
+ if(fstat(fd, &sbuf) != -1) asiz = sbuf.st_size + 1;
+ } else {
+ fd = 0;
+ }
+ CB_MALLOC(buf, asiz + 1);
+ size = 0;
+ while((rv = read(fd, iobuf, CB_IOBUFSIZ)) > 0){
+ if(size + rv >= asiz){
+ asiz = asiz * 2 + size;
+ CB_REALLOC(buf, asiz + 1);
+ }
+ memcpy(buf + size, iobuf, rv);
+ size += rv;
+ }
+ buf[size] = '\0';
+ if(close(fd) == -1 || rv == -1){
+ free(buf);
+ return NULL;
+ }
+ if(sp) *sp = size;
+ return buf;
+}
+
+
+/* Write data of a region into a file. */
+int cbwritefile(const char *name, const char *ptr, int size){
+ int fd, err, wb;
+ assert(ptr);
+ if(size < 0) size = strlen(ptr);
+ if(name){
+ if((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, CB_FILEMODE)) == -1) return FALSE;
+ } else {
+ fd = 1;
+ }
+ err = FALSE;
+ wb = 0;
+ do {
+ wb = write(fd, ptr, size);
+ switch(wb){
+ case -1: err = errno != EINTR ? TRUE : FALSE; break;
+ case 0: break;
+ default:
+ ptr += wb;
+ size -= wb;
+ break;
+ }
+ } while(size > 0);
+ if(close(fd) == -1) err = TRUE;
+ return err ? FALSE : TRUE;
+}
+
+
+/* Read every line of a file. */
+CBLIST *cbreadlines(const char *name){
+ char *buf, *tmp;
+ int vsiz;
+ CBMAP *pairs;
+ CBLIST *list;
+ if(!(buf = cbreadfile(name, NULL))) return NULL;
+ pairs = cbmapopenex(3);
+ cbmapput(pairs, "\r\n", 2, "\n", 1, TRUE);
+ cbmapput(pairs, "\r", 1, "\n", 1, TRUE);
+ tmp = cbreplace(buf, pairs);
+ list = cbsplit(tmp, strlen(tmp), "\n");
+ free(tmp);
+ cbmapclose(pairs);
+ free(buf);
+ if(CB_LISTNUM(list) > 0){
+ cblistval(list, CB_LISTNUM(list) - 1, &vsiz);
+ if(vsiz < 1) CB_LISTDROP(list);
+ }
+ return list;
+}
+
+
+/* Read names of files in a directory. */
+CBLIST *cbdirlist(const char *name){
+ DIR *DD;
+ struct dirent *dp;
+ CBLIST *list;
+ assert(name);
+ if(!(DD = opendir(name))) return NULL;
+ CB_LISTOPEN(list);
+ while((dp = readdir(DD)) != NULL){
+ CB_LISTPUSH(list, dp->d_name, strlen(dp->d_name));
+ }
+ if(closedir(DD) == -1){
+ CB_LISTCLOSE(list);
+ return NULL;
+ }
+ return list;
+}
+
+
+/* Get the status of a file or a directory. */
+int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep){
+ struct stat sbuf;
+ assert(name);
+ if(lstat(name, &sbuf) == -1) return FALSE;
+ if(isdirp) *isdirp = S_ISDIR(sbuf.st_mode);
+ if(sizep) *sizep = (int)sbuf.st_size;
+ if(mtimep) *mtimep = sbuf.st_mtime;
+ return TRUE;
+}
+
+
+/* Remove a file or a directory and its sub ones recursively. */
+int cbremove(const char *name){
+ CBLIST *list;
+ const char *elem;
+ char *path;
+ int i, err, tail;
+ struct stat sbuf;
+ assert(name);
+ if(lstat(name, &sbuf) == -1) return FALSE;
+ if(unlink(name) == 0) return TRUE;
+ if(!S_ISDIR(sbuf.st_mode) || !(list = cbdirlist(name))) return FALSE;
+ err = FALSE;
+ tail = name[0] != '\0' && name[strlen(name)-1] == MYPATHCHR;
+ for(i = 0; i < CB_LISTNUM(list); i++){
+ elem = CB_LISTVAL(list, i);
+ if(!strcmp(MYCDIRSTR, elem) || !strcmp(MYPDIRSTR, elem)) continue;
+ if(tail){
+ path = cbsprintf("%s%s", name, elem);
+ } else {
+ path = cbsprintf("%s%c%s", name, MYPATHCHR, elem);
+ }
+ if(!cbremove(path)) err = TRUE;
+ free(path);
+ }
+ CB_LISTCLOSE(list);
+ return rmdir(name) == 0 ? TRUE : FALSE;
+}
+
+
+/* Break up a URL into elements. */
+CBMAP *cburlbreak(const char *str){
+ CBMAP *map;
+ char *tmp, *ep;
+ const char *rp;
+ int serv;
+ assert(str);
+ map = cbmapopenex(CB_MAPPBNUM);
+ CB_MEMDUP(tmp, str, strlen(str));
+ rp = cbstrtrim(tmp);
+ cbmapput(map, "self", -1, rp, -1, TRUE);
+ serv = FALSE;
+ if(cbstrfwimatch(rp, "http://")){
+ cbmapput(map, "scheme", -1, "http", -1, TRUE);
+ rp += 7;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "https://")){
+ cbmapput(map, "scheme", -1, "https", -1, TRUE);
+ rp += 8;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "ftp://")){
+ cbmapput(map, "scheme", -1, "ftp", -1, TRUE);
+ rp += 6;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "sftp://")){
+ cbmapput(map, "scheme", -1, "sftp", -1, TRUE);
+ rp += 7;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "ftps://")){
+ cbmapput(map, "scheme", -1, "ftps", -1, TRUE);
+ rp += 7;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "tftp://")){
+ cbmapput(map, "scheme", -1, "tftp", -1, TRUE);
+ rp += 7;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "ldap://")){
+ cbmapput(map, "scheme", -1, "ldap", -1, TRUE);
+ rp += 7;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "ldaps://")){
+ cbmapput(map, "scheme", -1, "ldaps", -1, TRUE);
+ rp += 8;
+ serv = TRUE;
+ } else if(cbstrfwimatch(rp, "file://")){
+ cbmapput(map, "scheme", -1, "file", -1, TRUE);
+ rp += 7;
+ serv = TRUE;
+ }
+ if((ep = strchr(rp, '#')) != NULL){
+ cbmapput(map, "fragment", -1, ep + 1, -1, TRUE);
+ *ep = '\0';
+ }
+ if((ep = strchr(rp, '?')) != NULL){
+ cbmapput(map, "query", -1, ep + 1, -1, TRUE);
+ *ep = '\0';
+ }
+ if(serv){
+ if((ep = strchr(rp, '/')) != NULL){
+ cbmapput(map, "path", -1, ep, -1, TRUE);
+ *ep = '\0';
+ } else {
+ cbmapput(map, "path", -1, "/", -1, TRUE);
+ }
+ if((ep = strchr(rp, '@')) != NULL){
+ *ep = '\0';
+ if(rp[0] != '\0') cbmapput(map, "authority", -1, rp, -1, TRUE);
+ rp = ep + 1;
+ }
+ if((ep = strchr(rp, ':')) != NULL){
+ if(ep[1] != '\0') cbmapput(map, "port", -1, ep + 1, -1, TRUE);
+ *ep = '\0';
+ }
+ if(rp[0] != '\0') cbmapput(map, "host", -1, rp, -1, TRUE);
+ } else {
+ cbmapput(map, "path", -1, rp, -1, TRUE);
+ }
+ free(tmp);
+ if((rp = cbmapget(map, "path", -1, NULL)) != NULL){
+ if((ep = strrchr(rp, '/')) != NULL){
+ if(ep[1] != '\0') cbmapput(map, "file", -1, ep + 1, -1, TRUE);
+ } else {
+ cbmapput(map, "file", -1, rp, -1, TRUE);
+ }
+ }
+ if((rp = cbmapget(map, "file", -1, NULL)) != NULL && (!strcmp(rp, ".") || !strcmp(rp, "..")))
+ cbmapout(map, "file", -1);
+ return map;
+}
+
+
+/* Resolve a relative URL with another absolute URL. */
+char *cburlresolve(const char *base, const char *target){
+ CBMAP *telems, *belems;
+ CBLIST *bpaths, *opaths, *qelems;
+ CBDATUM *rbuf;
+ const char *vbuf, *path;
+ char *tmp, *wp, *enc, numbuf[CB_NUMBUFSIZ];
+ int i, vsiz, port, num;
+ assert(base && target);
+ while(*base > '\0' && *base <= ' '){
+ base++;
+ }
+ while(*target > '\0' && *target <= ' '){
+ target++;
+ }
+ if(*target == '\0') target = base;
+ CB_DATUMOPEN(rbuf);
+ telems = cburlbreak(target);
+ port = 80;
+ belems = cburlbreak(cbmapget(telems, "scheme", -1, &vsiz) ? target : base);
+ if((vbuf = cbmapget(belems, "scheme", -1, &vsiz)) != NULL){
+ CB_DATUMCAT(rbuf, vbuf, vsiz);
+ CB_DATUMCAT(rbuf, "://", 3);
+ if(!cbstricmp(vbuf, "https")){
+ port = 443;
+ } else if(!cbstricmp(vbuf, "ftp")){
+ port = 21;
+ } else if(!cbstricmp(vbuf, "sftp")){
+ port = 115;
+ } else if(!cbstricmp(vbuf, "ftps")){
+ port = 22;
+ } else if(!cbstricmp(vbuf, "tftp")){
+ port = 69;
+ } else if(!cbstricmp(vbuf, "ldap")){
+ port = 389;
+ } else if(!cbstricmp(vbuf, "ldaps")){
+ port = 636;
+ }
+ } else {
+ CB_DATUMCAT(rbuf, "http://", 7);
+ }
+ if((vbuf = cbmapget(belems, "authority", -1, &vsiz)) != NULL){
+ if((wp = strchr(vbuf, ':')) != NULL){
+ *wp = '\0';
+ tmp = cburldecode(vbuf, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ CB_DATUMCAT(rbuf, ":", 1);
+ wp++;
+ tmp = cburldecode(wp, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ } else {
+ tmp = cburldecode(vbuf, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ }
+ CB_DATUMCAT(rbuf, "@", 1);
+ }
+ if((vbuf = cbmapget(belems, "host", -1, &vsiz)) != NULL){
+ tmp = cburldecode(vbuf, NULL);
+ cbstrtolower(tmp);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ } else {
+ CB_DATUMCAT(rbuf, "localhost", 9);
+ }
+ if((vbuf = cbmapget(belems, "port", -1, &vsiz)) != NULL &&
+ (num = atoi(vbuf)) != port && num > 1){
+ sprintf(numbuf, ":%d", num);
+ CB_DATUMCAT(rbuf, numbuf, strlen(numbuf));
+ }
+ if(!(path = cbmapget(telems, "path", -1, NULL))) path = "/";
+ if(path[0] == '\0' && (vbuf = cbmapget(belems, "path", -1, NULL)) != NULL) path = vbuf;
+ if(path[0] == '\0') path = "/";
+ CB_LISTOPEN(bpaths);
+ if(path[0] != '/' && (vbuf = cbmapget(belems, "path", -1, &vsiz)) != NULL){
+ opaths = cbsplit(vbuf, vsiz, "/");
+ } else {
+ opaths = cbsplit("/", 1, "/");
+ }
+ CB_LISTDROP(opaths);
+ for(i = 0; i < CB_LISTNUM(opaths); i++){
+ vbuf = CB_LISTVAL2(opaths, i, vsiz);
+ if(vsiz < 1 || !strcmp(vbuf, ".")) continue;
+ if(!strcmp(vbuf, "..")){
+ CB_LISTDROP(bpaths);
+ } else {
+ CB_LISTPUSH(bpaths, vbuf, vsiz);
+ }
+ }
+ CB_LISTCLOSE(opaths);
+ opaths = cbsplit(path, -1, "/");
+ for(i = 0; i < CB_LISTNUM(opaths); i++){
+ vbuf = CB_LISTVAL2(opaths, i, vsiz);
+ if(vsiz < 1 || !strcmp(vbuf, ".")) continue;
+ if(!strcmp(vbuf, "..")){
+ CB_LISTDROP(bpaths);
+ } else {
+ CB_LISTPUSH(bpaths, vbuf, vsiz);
+ }
+ }
+ CB_LISTCLOSE(opaths);
+ for(i = 0; i < CB_LISTNUM(bpaths); i++){
+ vbuf = CB_LISTVAL(bpaths, i);
+ if(strchr(vbuf, '%')){
+ tmp = cburldecode(vbuf, NULL);
+ } else {
+ CB_MEMDUP(tmp, vbuf, strlen(vbuf));
+ }
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, "/", 1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ }
+ if(cbstrbwmatch(path, "/")) CB_DATUMCAT(rbuf, "/", 1);
+ CB_LISTCLOSE(bpaths);
+ if((vbuf = cbmapget(telems, "query", -1, &vsiz)) != NULL){
+ CB_DATUMCAT(rbuf, "?", 1);
+ qelems = cbsplit(vbuf, vsiz, "&;");
+ for(i = 0; i < CB_LISTNUM(qelems); i++){
+ vbuf = CB_LISTVAL(qelems, i);
+ if(i > 0) CB_DATUMCAT(rbuf, "&", 1);
+ if((wp = strchr(vbuf, '=')) != NULL){
+ *wp = '\0';
+ tmp = cburldecode(vbuf, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ CB_DATUMCAT(rbuf, "=", 1);
+ wp++;
+ tmp = cburldecode(wp, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ } else {
+ tmp = cburldecode(vbuf, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ }
+ }
+ CB_LISTCLOSE(qelems);
+ }
+ if((vbuf = cbmapget(telems, "fragment", -1, &vsiz)) != NULL){
+ tmp = cburldecode(vbuf, NULL);
+ enc = cburlencode(tmp, -1);
+ CB_DATUMCAT(rbuf, "#", 1);
+ CB_DATUMCAT(rbuf, enc, strlen(enc));
+ free(enc);
+ free(tmp);
+ }
+ cbmapclose(belems);
+ cbmapclose(telems);
+ return cbdatumtomalloc(rbuf, NULL);
+}
+
+
+/* Encode a serial object with URL encoding. */
+char *cburlencode(const char *ptr, int size){
+ char *buf, *wp;
+ int i, c;
+ assert(ptr);
+ if(size < 0) size = strlen(ptr);
+ CB_MALLOC(buf, size * 3 + 1);
+ wp = buf;
+ for(i = 0; i < size; i++){
+ c = ((unsigned char *)ptr)[i];
+ if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.!~*'()", c))){
+ *(wp++) = c;
+ } else {
+ wp += sprintf(wp, "%%%02X", c);
+ }
+ }
+ *wp = '\0';
+ return buf;
+}
+
+
+/* Decode a string encoded with URL encoding. */
+char *cburldecode(const char *str, int *sp){
+ char *buf, *wp;
+ unsigned char c;
+ CB_MEMDUP(buf, str, strlen(str));
+ wp = buf;
+ while(*str != '\0'){
+ if(*str == '%'){
+ str++;
+ if(((str[0] >= '0' && str[0] <= '9') || (str[0] >= 'A' && str[0] <= 'F') ||
+ (str[0] >= 'a' && str[0] <= 'f')) &&
+ ((str[1] >= '0' && str[1] <= '9') || (str[1] >= 'A' && str[1] <= 'F') ||
+ (str[1] >= 'a' && str[1] <= 'f'))){
+ c = *str;
+ if(c >= 'A' && c <= 'Z') c += 'a' - 'A';
+ if(c >= 'a' && c <= 'z'){
+ *wp = c - 'a' + 10;
+ } else {
+ *wp = c - '0';
+ }
+ *wp *= 0x10;
+ str++;
+ c = *str;
+ if(c >= 'A' && c <= 'Z') c += 'a' - 'A';
+ if(c >= 'a' && c <= 'z'){
+ *wp += c - 'a' + 10;
+ } else {
+ *wp += c - '0';
+ }
+ str++;
+ wp++;
+ } else {
+ break;
+ }
+ } else if(*str == '+'){
+ *wp = ' ';
+ str++;
+ wp++;
+ } else {
+ *wp = *str;
+ str++;
+ wp++;
+ }
+ }
+ *wp = '\0';
+ if(sp) *sp = wp - buf;
+ return buf;
+}
+
+
+/* Encode a serial object with Base64 encoding. */
+char *cbbaseencode(const char *ptr, int size){
+ char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ char *buf, *wp;
+ const unsigned char *obj;
+ int i;
+ assert(ptr);
+ if(size < 0) size = strlen(ptr);
+ CB_MALLOC(buf, 4 * (size + 2) / 3 + 1);
+ obj = (const unsigned char *)ptr;
+ wp = buf;
+ for(i = 0; i < size; i += 3){
+ switch(size - i){
+ case 1:
+ *wp++ = tbl[obj[0] >> 2];
+ *wp++ = tbl[(obj[0] & 3) << 4];
+ *wp++ = '=';
+ *wp++ = '=';
+ break;
+ case 2:
+ *wp++ = tbl[obj[0] >> 2];
+ *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)];
+ *wp++ = tbl[(obj[1] & 0xf) << 2];
+ *wp++ = '=';
+ break;
+ default:
+ *wp++ = tbl[obj[0] >> 2];
+ *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)];
+ *wp++ = tbl[((obj[1] & 0xf) << 2) + (obj[2] >> 6)];
+ *wp++ = tbl[obj[2] & 0x3f];
+ break;
+ }
+ obj += 3;
+ }
+ *wp = '\0';
+ return buf;
+}
+
+
+/* Decode a string encoded with Base64 encoding. */
+char *cbbasedecode(const char *str, int *sp){
+ unsigned char *obj, *wp;
+ int len, cnt, bpos, i, bits, eqcnt;
+ assert(str);
+ cnt = 0;
+ bpos = 0;
+ eqcnt = 0;
+ len = strlen(str);
+ CB_MALLOC(obj, len + 4);
+ wp = obj;
+ while(bpos < len && eqcnt == 0){
+ bits = 0;
+ for(i = 0; bpos < len && i < 4; bpos++){
+ if(str[bpos] >= 'A' && str[bpos] <= 'Z'){
+ bits = (bits << 6) | (str[bpos] - 'A');
+ i++;
+ } else if(str[bpos] >= 'a' && str[bpos] <= 'z'){
+ bits = (bits << 6) | (str[bpos] - 'a' + 26);
+ i++;
+ } else if(str[bpos] >= '0' && str[bpos] <= '9'){
+ bits = (bits << 6) | (str[bpos] - '0' + 52);
+ i++;
+ } else if(str[bpos] == '+'){
+ bits = (bits << 6) | 62;
+ i++;
+ } else if(str[bpos] == '/'){
+ bits = (bits << 6) | 63;
+ i++;
+ } else if(str[bpos] == '='){
+ bits <<= 6;
+ i++;
+ eqcnt++;
+ }
+ }
+ if(i == 0 && bpos >= len) continue;
+ switch(eqcnt){
+ case 0:
+ *wp++ = (bits >> 16) & 0xff;
+ *wp++ = (bits >> 8) & 0xff;
+ *wp++ = bits & 0xff;
+ cnt += 3;
+ break;
+ case 1:
+ *wp++ = (bits >> 16) & 0xff;
+ *wp++ = (bits >> 8) & 0xff;
+ cnt += 2;
+ break;
+ case 2:
+ *wp++ = (bits >> 16) & 0xff;
+ cnt += 1;
+ break;
+ }
+ }
+ obj[cnt] = '\0';
+ if(sp) *sp = cnt;
+ return (char *)obj;
+}
+
+
+/* Encode a serial object with quoted-printable encoding. */
+char *cbquoteencode(const char *ptr, int size){
+ const unsigned char *rp;
+ char *buf, *wp;
+ int i, cols;
+ assert(ptr);
+ if(size < 0) size = strlen(ptr);
+ rp = (const unsigned char *)ptr;
+ CB_MALLOC(buf, size * 3 + 1);
+ wp = buf;
+ cols = 0;
+ for(i = 0; i < size; i++){
+ if(rp[i] == '=' || (rp[i] < 0x20 && rp[i] != '\r' && rp[i] != '\n' && rp[i] != '\t') ||
+ rp[i] > 0x7e){
+ wp += sprintf(wp, "=%02X", rp[i]);
+ cols += 3;
+ } else {
+ *(wp++) = rp[i];
+ cols++;
+ }
+ }
+ *wp = '\0';
+ return buf;
+}
+
+
+/* Decode a string encoded with quoted-printable encoding. */
+char *cbquotedecode(const char *str, int *sp){
+ char *buf, *wp;
+ assert(str);
+ CB_MALLOC(buf, strlen(str) + 1);
+ wp = buf;
+ for(; *str != '\0'; str++){
+ if(*str == '='){
+ str++;
+ if(*str == '\0'){
+ break;
+ } else if(str[0] == '\r' && str[1] == '\n'){
+ str++;
+ } else if(str[0] != '\n' && str[0] != '\r'){
+ if(*str >= 'A' && *str <= 'Z'){
+ *wp = (*str - 'A' + 10) * 16;
+ } else if(*str >= 'a' && *str <= 'z'){
+ *wp = (*str - 'a' + 10) * 16;
+ } else {
+ *wp = (*str - '0') * 16;
+ }
+ str++;
+ if(*str == '\0') break;
+ if(*str >= 'A' && *str <= 'Z'){
+ *wp += *str - 'A' + 10;
+ } else if(*str >= 'a' && *str <= 'z'){
+ *wp += *str - 'a' + 10;
+ } else {
+ *wp += *str - '0';
+ }
+ wp++;
+ }
+ } else {
+ *wp = *str;
+ wp++;
+ }
+ }
+ *wp = '\0';
+ if(sp) *sp = wp - buf;
+ return buf;
+}
+
+
+/* Split a string of MIME into headers and the body. */
+char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp){
+ CBLIST *list;
+ const char *head, *line, *pv, *ep;
+ char *hbuf, *name, *rv;
+ int i, j, wi, hlen;
+ assert(ptr);
+ if(size < 0) size = strlen(ptr);
+ head = NULL;
+ hlen = 0;
+ for(i = 0; i < size; i++){
+ if(i < size - 4 && ptr[i] == '\r' && ptr[i+1] == '\n' &&
+ ptr[i+2] == '\r' && ptr[i+3] == '\n'){
+ head = ptr;
+ hlen = i;
+ ptr += i + 4;
+ size -= i + 4;
+ break;
+ } else if(i < size - 2 && ptr[i] == '\n' && ptr[i+1] == '\n'){
+ head = ptr;
+ hlen = i;
+ ptr += i + 2;
+ size -= i + 2;
+ break;
+ }
+ }
+ if(head && attrs){
+ CB_MALLOC(hbuf, hlen + 1);
+ wi = 0;
+ for(i = 0; i < hlen; i++){
+ if(head[i] == '\r') continue;
+ if(i < hlen - 1 && head[i] == '\n' && (head[i+1] == ' ' || head[i+1] == '\t')){
+ hbuf[wi++] = ' ';
+ i++;
+ } else {
+ hbuf[wi++] = head[i];
+ }
+ }
+ list = cbsplit(hbuf, wi, "\n");
+ for(i = 0; i < CB_LISTNUM(list); i++){
+ line = CB_LISTVAL(list, i);
+ if((pv = strchr(line, ':')) != NULL){
+ CB_MEMDUP(name, line, pv - line);
+ for(j = 0; name[j] != '\0'; j++){
+ if(name[j] >= 'A' && name[j] <= 'Z') name[j] -= 'A' - 'a';
+ }
+ pv++;
+ while(*pv == ' ' || *pv == '\t'){
+ pv++;
+ }
+ cbmapput(attrs, name, -1, pv, -1, TRUE);
+ free(name);
+ }
+
+ }
+ CB_LISTCLOSE(list);
+ free(hbuf);
+ if((pv = cbmapget(attrs, "content-type", -1, NULL)) != NULL){
+ if((ep = strchr(pv, ';')) != NULL){
+ cbmapput(attrs, "TYPE", -1, pv, ep - pv, TRUE);
+ do {
+ ep++;
+ while(ep[0] == ' '){
+ ep++;
+ }
+ if(cbstrfwimatch(ep, "charset=")){
+ ep += 8;
+ while(*ep > '\0' && *ep <= ' '){
+ ep++;
+ }
+ if(ep[0] == '"') ep++;
+ pv = ep;
+ while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){
+ ep++;
+ }
+ cbmapput(attrs, "CHARSET", -1, pv, ep - pv, TRUE);
+ } else if(cbstrfwimatch(ep, "boundary=")){
+ ep += 9;
+ while(*ep > '\0' && *ep <= ' '){
+ ep++;
+ }
+ if(ep[0] == '"'){
+ ep++;
+ pv = ep;
+ while(ep[0] != '\0' && ep[0] != '"'){
+ ep++;
+ }
+ } else {
+ pv = ep;
+ while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){
+ ep++;
+ }
+ }
+ cbmapput(attrs, "BOUNDARY", -1, pv, ep - pv, TRUE);
+ }
+ } while((ep = strchr(ep, ';')) != NULL);
+ } else {
+ cbmapput(attrs, "TYPE", -1, pv, -1, TRUE);
+ }
+ }
+ if((pv = cbmapget(attrs, "content-disposition", -1, NULL)) != NULL){
+ if((ep = strchr(pv, ';')) != NULL){
+ cbmapput(attrs, "DISPOSITION", -1, pv, ep - pv, TRUE);
+ do {
+ ep++;
+ while(ep[0] == ' '){
+ ep++;
+ }
+ if(cbstrfwimatch(ep, "filename=")){
+ ep += 9;
+ if(ep[0] == '"') ep++;
+ pv = ep;
+ while(ep[0] != '\0' && ep[0] != '"'){
+ ep++;
+ }
+ cbmapput(attrs, "FILENAME", -1, pv, ep - pv, TRUE);
+ } else if(cbstrfwimatch(ep, "name=")){
+ ep += 5;
+ if(ep[0] == '"') ep++;
+ pv = ep;
+ while(ep[0] != '\0' && ep[0] != '"'){
+ ep++;
+ }
+ cbmapput(attrs, "NAME", -1, pv, ep - pv, TRUE);
+ }
+ } while((ep = strchr(ep, ';')) != NULL);
+ } else {
+ cbmapput(attrs, "DISPOSITION", -1, pv, -1, TRUE);
+ }
+ }
+ }
+ if(sp) *sp = size;
+ CB_MEMDUP(rv, ptr, size);
+ return rv;
+}
+
+
+/* Split multipart data in MIME into its parts. */
+CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary){
+ CBLIST *list;
+ const char *pv, *ep;
+ int i, blen;
+ assert(ptr && boundary);
+ if(size < 0) size = strlen(ptr);
+ CB_LISTOPEN(list);
+ if((blen = strlen(boundary)) < 1) return list;
+ pv = NULL;
+ for(i = 0; i < size; i++){
+ if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size &&
+ cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r ", ptr[i+2+blen])){
+ pv = ptr + i + 2 + blen;
+ if(*pv == '\r') pv++;
+ if(*pv == '\n') pv++;
+ size -= pv - ptr;
+ ptr = pv;
+ break;
+ }
+ }
+ if(!pv) return list;
+ for(i = 0; i < size; i++){
+ if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size &&
+ cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r -", ptr[i+2+blen])){
+ ep = ptr + i;
+ if(ep > ptr && ep[-1] == '\n') ep--;
+ if(ep > ptr && ep[-1] == '\r') ep--;
+ if(ep > pv) CB_LISTPUSH(list, pv, ep - pv);
+ pv = ptr + i + 2 + blen;
+ if(*pv == '\r') pv++;
+ if(*pv == '\n') pv++;
+ }
+ }
+ return list;
+}
+
+
+/* Encode a string with MIME encoding. */
+char *cbmimeencode(const char *str, const char *encname, int base){
+ char *buf, *wp, *enc;
+ int len;
+ assert(str && encname);
+ len = strlen(str);
+ CB_MALLOC(buf, len * 3 + strlen(encname) + 16);
+ wp = buf;
+ wp += sprintf(wp, "=?%s?%c?", encname, base ? 'B' : 'Q');
+ enc = base ? cbbaseencode(str, len) : cbquoteencode(str, len);
+ wp += sprintf(wp, "%s?=", enc);
+ free(enc);
+ return buf;
+}
+
+
+/* Decode a string encoded with MIME encoding. */
+char *cbmimedecode(const char *str, char *enp){
+ char *buf, *wp, *tmp, *dec;
+ const char *pv, *ep;
+ int quoted;
+ assert(str);
+ if(enp) sprintf(enp, "US-ASCII");
+ CB_MALLOC(buf, strlen(str) + 1);
+ wp = buf;
+ while(*str != '\0'){
+ if(cbstrfwmatch(str, "=?")){
+ str += 2;
+ pv = str;
+ if(!(ep = strchr(str, '?'))) continue;
+ if(enp && ep - pv < CB_ENCBUFSIZ){
+ memcpy(enp, pv, ep - pv);
+ enp[ep-pv] = '\0';
+ }
+ pv = ep + 1;
+ quoted = (*pv == 'Q' || *pv == 'q');
+ if(*pv != '\0') pv++;
+ if(*pv != '\0') pv++;
+ if(!(ep = strchr(pv, '?'))) continue;
+ CB_MEMDUP(tmp, pv, ep - pv);
+ dec = quoted ? cbquotedecode(tmp, NULL) : cbbasedecode(tmp, NULL);
+ wp += sprintf(wp, "%s", dec);
+ free(dec);
+ free(tmp);
+ str = ep + 1;
+ if(*str != '\0') str++;
+ } else {
+ *(wp++) = *str;
+ str++;
+ }
+ }
+ *wp = '\0';
+ return buf;
+}
+
+
+/* Split a string of CSV into rows. */
+CBLIST *cbcsvrows(const char *str){
+ CBLIST *list;
+ const char *pv;
+ int quoted;
+ assert(str);
+ CB_LISTOPEN(list);
+ pv = str;
+ quoted = FALSE;
+ while(TRUE){
+ if(*str == '"') quoted = !quoted;
+ if(!quoted && (*str == '\r' || *str == '\n')){
+ CB_LISTPUSH(list, pv, str - pv);
+ if(str[0] == '\r' && str[1] == '\n') str++;
+ str++;
+ pv = str;
+ } else if(*str == '\0'){
+ if(str > pv) CB_LISTPUSH(list, pv, str - pv);
+ break;
+ } else {
+ str++;
+ }
+ }
+ return list;
+}
+
+
+/* Split a string of a row of CSV into cells. */
+CBLIST *cbcsvcells(const char *str){
+ CBLIST *list, *uelist;
+ const char *pv;
+ char *tmp;
+ int i, quoted;
+ assert(str);
+ CB_LISTOPEN(list);
+ pv = str;
+ quoted = FALSE;
+ while(TRUE){
+ if(*str == '"') quoted = !quoted;
+ if(!quoted && *str == ','){
+ CB_LISTPUSH(list, pv, str - pv);
+ str++;
+ pv = str;
+ } else if(*str == '\0'){
+ CB_LISTPUSH(list, pv, str - pv);
+ break;
+ } else {
+ str++;
+ }
+ }
+ CB_LISTOPEN(uelist);
+ for(i = 0; i < CB_LISTNUM(list); i++){
+ tmp = cbcsvunescape(CB_LISTVAL(list, i));
+ CB_LISTPUSH(uelist, tmp, strlen(tmp));
+ free(tmp);
+ }
+ CB_LISTCLOSE(list);
+ return uelist;
+}
+
+
+/* Escape a string with the meta characters of CSV. */
+char *cbcsvescape(const char *str){
+ char *buf, *wp;
+ int i;
+ assert(str);
+ CB_MALLOC(buf, strlen(str) * 2 + 3);
+ wp = buf;
+ *(wp++) = '"';
+ for(i = 0; str[i] != '\0'; i++){
+ if(str[i] == '"') *(wp++) = '"';
+ *(wp++) = str[i];
+ }
+ *(wp++) = '"';
+ *wp = '\0';
+ return buf;
+}
+
+
+/* Unescape a string with the escaped meta characters of CSV. */
+char *cbcsvunescape(const char *str){
+ char *buf, *wp;
+ int i, len;
+ assert(str);
+ len = strlen(str);
+ if(str[0] == '"'){
+ str++;
+ len--;
+ if(str[len-1] == '"') len--;
+ }
+ CB_MALLOC(buf, len + 1);
+ wp = buf;
+ for(i = 0; i < len; i++){
+ if(str[i] == '"'){
+ if(str[i+1] == '"') *(wp++) = str[i++];
+ } else {
+ *(wp++) = str[i];
+ }
+ }
+ *wp = '\0';
+ return buf;
+}
+
+
+/* Split a string of XML into tags and text sections. */
+CBLIST *cbxmlbreak(const char *str, int cr){
+ CBLIST *list;
+ CBDATUM *datum;
+ int i, pv, tag;
+ char *ep;
+ assert(str);
+ CB_LISTOPEN(list);
+ i = 0;
+ pv = 0;
+ tag = FALSE;
+ while(TRUE){
+ if(str[i] == '\0'){
+ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv);
+ break;
+ } else if(!tag && str[i] == '<'){
+ if(str[i+1] == '!' && str[i+2] == '-' && str[i+3] == '-'){
+ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv);
+ if((ep = strstr(str + i, "-->")) != NULL){
+ if(!cr) CB_LISTPUSH(list, str + i, ep - str - i + 3);
+ i = ep - str + 2;
+ pv = i + 1;
+ }
+ } else if(str[i+1] == '!' && str[i+2] == '[' && cbstrfwimatch(str + i, "<![CDATA[")){
+ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv);
+ if((ep = strstr(str + i, "]]>")) != NULL){
+ i += 9;
+ CB_DATUMOPEN(datum);
+ while(str + i < ep){
+ if(str[i] == '&'){
+ CB_DATUMCAT(datum, "&amp;", 5);
+ } else if(str[i] == '<'){
+ CB_DATUMCAT(datum, "&lt;", 4);
+ } else if(str[i] == '>'){
+ CB_DATUMCAT(datum, "&gt;", 4);
+ } else {
+ CB_DATUMCAT(datum, str + i, 1);
+ }
+ i++;
+ }
+ if(CB_DATUMSIZE(datum) > 0) CB_LISTPUSH(list, CB_DATUMPTR(datum), CB_DATUMSIZE(datum));
+ CB_DATUMCLOSE(datum);
+ i = ep - str + 2;
+ pv = i + 1;
+ }
+ } else {
+ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv);
+ tag = TRUE;
+ pv = i;
+ }
+ } else if(tag && str[i] == '>'){
+ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv + 1);
+ tag = FALSE;
+ pv = i + 1;
+ }
+ i++;
+ }
+ return list;
+}
+
+
+/* Get the map of attributes of a XML tag. */
+CBMAP *cbxmlattrs(const char *str){
+ CBMAP *map;
+ const unsigned char *rp, *key, *val;
+ char *copy, *raw;
+ int ksiz, vsiz;
+ assert(str);
+ map = cbmapopenex(CB_MAPPBNUM);
+ rp = (unsigned char *)str;
+ while(*rp == '<' || *rp == '/' || *rp == '?' || *rp == '!' || *rp == ' '){
+ rp++;
+ }
+ key = rp;
+ while(*rp > 0x20 && *rp != '/' && *rp != '>'){
+ rp++;
+ }
+ cbmapput(map, "", -1, (char *)key, rp - key, FALSE);
+ while(*rp != '\0'){
+ while(*rp != '\0' && (*rp <= 0x20 || *rp == '/' || *rp == '?' || *rp == '>')){
+ rp++;
+ }
+ key = rp;
+ while(*rp > 0x20 && *rp != '/' && *rp != '>' && *rp != '='){
+ rp++;
+ }
+ ksiz = rp - key;
+ while(*rp != '\0' && (*rp == '=' || *rp <= 0x20)){
+ rp++;
+ }
+ if(*rp == '"'){
+ rp++;
+ val = rp;
+ while(*rp != '\0' && *rp != '"'){
+ rp++;
+ }
+ vsiz = rp - val;
+ } else if(*rp == '\''){
+ rp++;
+ val = rp;
+ while(*rp != '\0' && *rp != '\''){
+ rp++;
+ }
+ vsiz = rp - val;
+ } else {
+ val = rp;
+ while(*rp > 0x20 && *rp != '"' && *rp != '\'' && *rp != '>'){
+ rp++;
+ }
+ vsiz = rp - val;
+ }
+ if(*rp != '\0') rp++;
+ if(ksiz > 0){
+ CB_MEMDUP(copy, (char *)val, vsiz);
+ raw = cbxmlunescape(copy);
+ cbmapput(map, (char *)key, ksiz, raw, -1, FALSE);
+ free(raw);
+ free(copy);
+ }
+ }
+ return map;
+}
+
+
+/* Escape a string with the meta characters of XML. */
+char *cbxmlescape(const char *str){
+ CBDATUM *datum;
+ assert(str);
+ CB_DATUMOPEN(datum);
+ while(*str != '\0'){
+ switch(*str){
+ case '&':
+ CB_DATUMCAT(datum, "&amp;", 5);
+ break;
+ case '<':
+ CB_DATUMCAT(datum, "&lt;", 4);
+ break;
+ case '>':
+ CB_DATUMCAT(datum, "&gt;", 4);
+ break;
+ case '"':
+ CB_DATUMCAT(datum, "&quot;", 6);
+ break;
+ case '\'':
+ CB_DATUMCAT(datum, "&apos;", 6);
+ break;
+ default:
+ CB_DATUMCAT(datum, str, 1);
+ break;
+ }
+ str++;
+ }
+ return cbdatumtomalloc(datum, NULL);
+}
+
+
+/* Unescape a string with the entity references of XML. */
+char *cbxmlunescape(const char *str){
+ CBDATUM *datum;
+ assert(str);
+ CB_DATUMOPEN(datum);
+ while(*str != '\0'){
+ if(*str == '&'){
+ if(cbstrfwmatch(str, "&amp;")){
+ CB_DATUMCAT(datum, "&", 1);
+ str += 5;
+ } else if(cbstrfwmatch(str, "&lt;")){
+ CB_DATUMCAT(datum, "<", 1);
+ str += 4;
+ } else if(cbstrfwmatch(str, "&gt;")){
+ CB_DATUMCAT(datum, ">", 1);
+ str += 4;
+ } else if(cbstrfwmatch(str, "&quot;")){
+ CB_DATUMCAT(datum, "\"", 1);
+ str += 6;
+ } else if(cbstrfwmatch(str, "&apos;")){
+ CB_DATUMCAT(datum, "'", 1);
+ str += 6;
+ } else {
+ CB_DATUMCAT(datum, str, 1);
+ str++;
+ }
+ } else {
+ CB_DATUMCAT(datum, str, 1);
+ str++;
+ }
+ }
+ return cbdatumtomalloc(datum, NULL);
+}
+
+
+/* Compress a serial object with ZLIB. */
+char *cbdeflate(const char *ptr, int size, int *sp){
+ assert(ptr && sp);
+ if(!_qdbm_deflate) return NULL;
+ return _qdbm_deflate(ptr, size, sp, _QDBM_ZMZLIB);
+}
+
+
+/* Decompress a serial object compressed with ZLIB. */
+char *cbinflate(const char *ptr, int size, int *sp){
+ assert(ptr && size >= 0);
+ if(!_qdbm_inflate) return NULL;
+ return _qdbm_inflate(ptr, size, sp, _QDBM_ZMZLIB);
+}
+
+
+/* Compress a serial object with GZIP. */
+char *cbgzencode(const char *ptr, int size, int *sp){
+ assert(ptr && sp);
+ if(!_qdbm_deflate) return NULL;
+ return _qdbm_deflate(ptr, size, sp, _QDBM_ZMGZIP);
+}
+
+
+/* Decompress a serial object compressed with GZIP. */
+char *cbgzdecode(const char *ptr, int size, int *sp){
+ assert(ptr && size >= 0);
+ if(!_qdbm_inflate) return NULL;
+ return _qdbm_inflate(ptr, size, sp, _QDBM_ZMGZIP);
+}
+
+
+/* Get the CRC32 checksum of a serial object. */
+unsigned int cbgetcrc(const char *ptr, int size){
+ assert(ptr);
+ if(!_qdbm_inflate) return 0;
+ return _qdbm_getcrc(ptr, size);
+}
+
+
+/* Compress a serial object with LZO. */
+char *cblzoencode(const char *ptr, int size, int *sp){
+ assert(ptr && sp);
+ if(!_qdbm_lzoencode) return NULL;
+ return _qdbm_lzoencode(ptr, size, sp);
+}
+
+
+/* Decompress a serial object compressed with LZO. */
+char *cblzodecode(const char *ptr, int size, int *sp){
+ assert(ptr && size >= 0);
+ if(!_qdbm_lzodecode) return NULL;
+ return _qdbm_lzodecode(ptr, size, sp);
+}
+
+
+/* Compress a serial object with BZIP2. */
+char *cbbzencode(const char *ptr, int size, int *sp){
+ assert(ptr && sp);
+ if(!_qdbm_bzencode) return NULL;
+ return _qdbm_bzencode(ptr, size, sp);
+}
+
+
+/* Decompress a serial object compressed with BZIP2. */
+char *cbbzdecode(const char *ptr, int size, int *sp){
+ assert(ptr && size >= 0);
+ if(!_qdbm_bzdecode) return NULL;
+ return _qdbm_bzdecode(ptr, size, sp);
+}
+
+
+/* Convert the character encoding of a string. */
+char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp){
+ char *res;
+ assert(ptr && icode && ocode);
+ if(!_qdbm_iconv) return NULL;
+ if((res = _qdbm_iconv(ptr, size, icode, ocode, sp, mp)) != NULL) return res;
+ if(!cbstricmp(icode, ocode)){
+ if(sp) *sp = size;
+ if(mp) *mp = 0;
+ CB_MEMDUP(res, ptr, size < 0 ? strlen(ptr) : size);
+ return res;
+ }
+ return NULL;
+}
+
+
+/* Detect the encoding of a string automatically. */
+const char *cbencname(const char *ptr, int size){
+ assert(ptr);
+ if(!_qdbm_encname) return "ISO-8859-1";
+ return _qdbm_encname(ptr, size);
+}
+
+
+/* Get the jet lag of the local time in seconds. */
+int cbjetlag(void){
+ struct tm ts, *tp;
+ time_t t, gt, lt;
+ if((t = time(NULL)) < 0) return 0;
+ if(!(tp = _qdbm_gmtime(&t, &ts))) return 0;
+ if((gt = mktime(tp)) < 0) return 0;
+ if(!(tp = _qdbm_localtime(&t, &ts))) return 0;
+ if((lt = mktime(tp)) < 0) return 0;
+ return lt - gt;
+}
+
+
+/* Get the Gregorian calendar of a time. */
+void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp){
+ struct tm ts, *tp;
+ if(t < 0) t = time(NULL);
+ t += jl;
+ if(!(tp = _qdbm_gmtime(&t, &ts))) return;
+ if(yearp) *yearp = tp->tm_year + 1900;
+ if(monp) *monp = tp->tm_mon + 1;
+ if(dayp) *dayp = tp->tm_mday;
+ if(hourp) *hourp = tp->tm_hour;
+ if(minp) *minp = tp->tm_min;
+ if(secp) *secp = tp->tm_sec;
+}
+
+
+/* Get the day of week of a date. */
+int cbdayofweek(int year, int mon, int day){
+ if(mon < 3){
+ year--;
+ mon += 12;
+ }
+ return (day + ((8 + (13 * mon)) / 5) + (year + (year / 4) - (year / 100) + (year / 400))) % 7;
+}
+
+
+/* Get the string for a date in W3CDTF. */
+char *cbdatestrwww(time_t t, int jl){
+ char date[CB_DATEBUFSIZ], tzone[CB_DATEBUFSIZ], *rv;
+ int year, mon, day, hour, min, sec;
+ cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec);
+ jl /= 60;
+ if(jl == 0){
+ sprintf(tzone, "Z");
+ } else if(jl < 0){
+ jl *= -1;
+ sprintf(tzone, "-%02d:%02d", jl / 60, jl % 60);
+ } else {
+ sprintf(tzone, "+%02d:%02d", jl / 60, jl % 60);
+ }
+ sprintf(date, "%04d-%02d-%02dT%02d:%02d:%02d%s", year, mon, day, hour, min, sec, tzone);
+ CB_MEMDUP(rv, date, strlen(date));
+ return rv;
+}
+
+
+/* Get the string for a date in RFC 1123 format. */
+char *cbdatestrhttp(time_t t, int jl){
+ char date[CB_DATEBUFSIZ], *wp, *rv;
+ int year, mon, day, hour, min, sec;
+ cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec);
+ jl /= 60;
+ wp = date;
+ switch(cbdayofweek(year, mon, day)){
+ case 0: wp += sprintf(wp, "Sun, "); break;
+ case 1: wp += sprintf(wp, "Mon, "); break;
+ case 2: wp += sprintf(wp, "Tue, "); break;
+ case 3: wp += sprintf(wp, "Wed, "); break;
+ case 4: wp += sprintf(wp, "Thu, "); break;
+ case 5: wp += sprintf(wp, "Fri, "); break;
+ case 6: wp += sprintf(wp, "Sat, "); break;
+ }
+ wp += sprintf(wp, "%02d ", day);
+ switch(mon){
+ case 1: wp += sprintf(wp, "Jan "); break;
+ case 2: wp += sprintf(wp, "Feb "); break;
+ case 3: wp += sprintf(wp, "Mar "); break;
+ case 4: wp += sprintf(wp, "Apr "); break;
+ case 5: wp += sprintf(wp, "May "); break;
+ case 6: wp += sprintf(wp, "Jun "); break;
+ case 7: wp += sprintf(wp, "Jul "); break;
+ case 8: wp += sprintf(wp, "Aug "); break;
+ case 9: wp += sprintf(wp, "Sep "); break;
+ case 10: wp += sprintf(wp, "Oct "); break;
+ case 11: wp += sprintf(wp, "Nov "); break;
+ case 12: wp += sprintf(wp, "Dec "); break;
+ }
+ wp += sprintf(wp, "%04d %02d:%02d:%02d ", year, hour, min, sec);
+ if(jl == 0){
+ wp += sprintf(wp, "GMT");
+ } else if(jl < 0){
+ jl *= -1;
+ wp += sprintf(wp, "-%02d%02d", jl / 60, jl % 60);
+ } else {
+ wp += sprintf(wp, "+%02d%02d", jl / 60, jl % 60);
+ }
+ CB_MEMDUP(rv, date, strlen(date));
+ return rv;
+}
+
+
+/* Get the time value of a date string in decimal, W3CDTF, or RFC 1123. */
+time_t cbstrmktime(const char *str){
+ const char *crp;
+ char *pv, *rp;
+ int len, clen;
+ time_t t;
+ struct tm ts;
+ assert(str);
+ while(*str > '\0' && *str <= ' '){
+ str++;
+ }
+ if(*str == '\0') return -1;
+ if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) return (time_t)strtol(str + 2, NULL, 16);
+ memset(&ts, 0, sizeof(struct tm));
+ ts.tm_year = 70;
+ ts.tm_mon = 0;
+ ts.tm_mday = 1;
+ ts.tm_hour = 0;
+ ts.tm_min = 0;
+ ts.tm_sec = 0;
+ ts.tm_isdst = 0;
+ len = strlen(str);
+ t = (time_t)strtol(str, &pv, 10);
+ if(*(signed char *)pv >= '\0' && *pv <= ' '){
+ while(*pv > '\0' && *pv <= ' '){
+ pv++;
+ }
+ if(*pv == '\0') return t;
+ }
+ if((pv[0] == 's' || pv[0] == 'S') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
+ return t;
+ if((pv[0] == 'm' || pv[0] == 'M') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
+ return t * 60;
+ if((pv[0] == 'h' || pv[0] == 'H') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
+ return t * 60 * 60;
+ if((pv[0] == 'd' || pv[0] == 'D') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
+ return t * 60 * 60 * 24;
+ if(len > 4 && str[4] == '-'){
+ ts.tm_year = atoi(str) - 1900;
+ if((pv = strchr(str, '-')) != NULL && pv - str == 4){
+ rp = pv + 1;
+ ts.tm_mon = atoi(rp) - 1;
+ if((pv = strchr(rp, '-')) != NULL && pv - str == 7){
+ rp = pv + 1;
+ ts.tm_mday = atoi(rp);
+ if((pv = strchr(rp, 'T')) != NULL && pv - str == 10){
+ rp = pv + 1;
+ ts.tm_hour = atoi(rp);
+ if((pv = strchr(rp, ':')) != NULL && pv - str == 13){
+ rp = pv + 1;
+ ts.tm_min = atoi(rp);
+ }
+ if((pv = strchr(rp, ':')) != NULL && pv - str == 16){
+ rp = pv + 1;
+ ts.tm_sec = atoi(rp);
+ }
+ if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1;
+ strtol(rp, &pv, 10);
+ if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':')
+ ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1);
+ }
+ }
+ }
+ ts.tm_sec += cbjetlag();
+ return mktime(&ts);
+ }
+ if(len > 4 && str[4] == '/'){
+ ts.tm_year = atoi(str) - 1900;
+ if((pv = strchr(str, '/')) != NULL && pv - str == 4){
+ rp = pv + 1;
+ ts.tm_mon = atoi(rp) - 1;
+ if((pv = strchr(rp, '/')) != NULL && pv - str == 7){
+ rp = pv + 1;
+ ts.tm_mday = atoi(rp);
+ if((pv = strchr(rp, ' ')) != NULL && pv - str == 10){
+ rp = pv + 1;
+ ts.tm_hour = atoi(rp);
+ if((pv = strchr(rp, ':')) != NULL && pv - str == 13){
+ rp = pv + 1;
+ ts.tm_min = atoi(rp);
+ }
+ if((pv = strchr(rp, ':')) != NULL && pv - str == 16){
+ rp = pv + 1;
+ ts.tm_sec = atoi(rp);
+ }
+ if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1;
+ strtol(rp, &pv, 10);
+ if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':')
+ ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1);
+ }
+ }
+ }
+ ts.tm_sec += cbjetlag();
+ return mktime(&ts);
+ }
+ crp = str;
+ if(len >= 4 && str[3] == ',') crp = str + 4;
+ while(*crp == ' '){
+ crp++;
+ }
+ ts.tm_mday = atoi(crp);
+ while((*crp >= '0' && *crp <= '9') || *crp == ' '){
+ crp++;
+ }
+ if(cbstrfwimatch(crp, "Jan")){
+ ts.tm_mon = 0;
+ } else if(cbstrfwimatch(crp, "Feb")){
+ ts.tm_mon = 1;
+ } else if(cbstrfwimatch(crp, "Mar")){
+ ts.tm_mon = 2;
+ } else if(cbstrfwimatch(crp, "Apr")){
+ ts.tm_mon = 3;
+ } else if(cbstrfwimatch(crp, "May")){
+ ts.tm_mon = 4;
+ } else if(cbstrfwimatch(crp, "Jun")){
+ ts.tm_mon = 5;
+ } else if(cbstrfwimatch(crp, "Jul")){
+ ts.tm_mon = 6;
+ } else if(cbstrfwimatch(crp, "Aug")){
+ ts.tm_mon = 7;
+ } else if(cbstrfwimatch(crp, "Sep")){
+ ts.tm_mon = 8;
+ } else if(cbstrfwimatch(crp, "Oct")){
+ ts.tm_mon = 9;
+ } else if(cbstrfwimatch(crp, "Nov")){
+ ts.tm_mon = 10;
+ } else if(cbstrfwimatch(crp, "Dec")){
+ ts.tm_mon = 11;
+ } else {
+ ts.tm_mon = -1;
+ }
+ if(ts.tm_mon >= 0) crp += 3;
+ while(*crp == ' '){
+ crp++;
+ }
+ ts.tm_year = atoi(crp);
+ if(ts.tm_year >= 1969) ts.tm_year -= 1900;
+ while(*crp >= '0' && *crp <= '9'){
+ crp++;
+ }
+ while(*crp == ' '){
+ crp++;
+ }
+ if(ts.tm_mday > 0 && ts.tm_mon >= 0 && ts.tm_year >= 0){
+ clen = strlen(crp);
+ if(clen >= 8 && crp[2] == ':' && crp[5] == ':'){
+ ts.tm_hour = atoi(crp + 0);
+ ts.tm_min = atoi(crp + 3);
+ ts.tm_sec = atoi(crp + 6);
+ if(clen >= 14 && crp[8] == ' ' && (crp[9] == '+' || crp[9] == '-')){
+ ts.tm_sec -= ((crp[10] - '0') * 36000 + (crp[11] - '0') * 3600 +
+ (crp[12] - '0') * 600 + (crp[13] - '0') * 60) * (crp[9] == '+' ? 1 : -1);
+ } else if(clen > 9){
+ if(!strcmp(crp + 9, "JST")){
+ ts.tm_sec -= 9 * 3600;
+ } else if(!strcmp(crp + 9, "CCT")){
+ ts.tm_sec -= 8 * 3600;
+ } else if(!strcmp(crp + 9, "KST")){
+ ts.tm_sec -= 9 * 3600;
+ } else if(!strcmp(crp + 9, "EDT")){
+ ts.tm_sec -= -4 * 3600;
+ } else if(!strcmp(crp + 9, "EST")){
+ ts.tm_sec -= -5 * 3600;
+ } else if(!strcmp(crp + 9, "CDT")){
+ ts.tm_sec -= -5 * 3600;
+ } else if(!strcmp(crp + 9, "CST")){
+ ts.tm_sec -= -6 * 3600;
+ } else if(!strcmp(crp + 9, "MDT")){
+ ts.tm_sec -= -6 * 3600;
+ } else if(!strcmp(crp + 9, "MST")){
+ ts.tm_sec -= -7 * 3600;
+ } else if(!strcmp(crp + 9, "PDT")){
+ ts.tm_sec -= -7 * 3600;
+ } else if(!strcmp(crp + 9, "PST")){
+ ts.tm_sec -= -8 * 3600;
+ } else if(!strcmp(crp + 9, "HDT")){
+ ts.tm_sec -= -9 * 3600;
+ } else if(!strcmp(crp + 9, "HST")){
+ ts.tm_sec -= -10 * 3600;
+ }
+ }
+ }
+ ts.tm_sec += cbjetlag();
+ return mktime(&ts);
+ }
+ return -1;
+}
+
+
+/* Get user and system processing times. */
+void cbproctime(double *usrp, double *sysp){
+ struct tms buf;
+ times(&buf);
+ if(usrp) *usrp = (double)buf.tms_utime / sysconf(_SC_CLK_TCK);
+ if(sysp) *sysp = (double)buf.tms_stime / sysconf(_SC_CLK_TCK);
+}
+
+
+/* Ensure that the standard I/O is binary mode. */
+void cbstdiobin(void){
+ if(setmode(0, O_BINARY) == -1 || setmode(1, O_BINARY) == -1 || setmode(2, O_BINARY) == -1)
+ cbmyfatal("setmode failed");
+}
+
+
+
+/*************************************************************************************************
+ * features for experts
+ *************************************************************************************************/
+
+
+/* Show error message on the standard error output and exit. */
+void *cbmyfatal(const char *message){
+ char buf[CB_MSGBUFSIZ];
+ assert(message);
+ if(cbfatalfunc){
+ cbfatalfunc(message);
+ } else {
+ sprintf(buf, "fatal error: %s\n", message);
+ write(2, buf, strlen(buf));
+ }
+ exit(1);
+ return NULL;
+}
+
+
+/* Create a datum handle from an allocated region. */
+CBDATUM *cbdatumopenbuf(char *ptr, int size){
+ CBDATUM *datum;
+ assert(ptr && size >= 0);
+ CB_REALLOC(ptr, size + 1);
+ CB_MALLOC(datum, sizeof(*datum));
+ datum->dptr = ptr;
+ datum->dptr[size] = '\0';
+ datum->dsize = size;
+ datum->asize = size;
+ return datum;
+}
+
+
+/* Set a buffer to a datum handle. */
+void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size){
+ assert(datum && ptr && size >= 0);
+ free(datum->dptr);
+ CB_REALLOC(ptr, size + 1);
+ datum->dptr = ptr;
+ datum->dptr[size] = '\0';
+ datum->dsize = size;
+ datum->asize = size;
+}
+
+
+/* Add an allocated element at the end of a list. */
+void cblistpushbuf(CBLIST *list, char *ptr, int size){
+ int index;
+ assert(list && ptr && size >= 0);
+ index = list->start + list->num;
+ if(index >= list->anum){
+ list->anum *= 2;
+ CB_REALLOC(list->array, list->anum * sizeof(list->array[0]));
+ }
+ list->array[index].dptr = ptr;
+ list->array[index].dsize = size;
+ list->num++;
+}
+
+
+/* Get a map handle with specifying the number of buckets. */
+CBMAP *cbmapopenex(int bnum){
+ CBMAP *map;
+ int i;
+ assert(bnum > 0);
+ CB_MALLOC(map, sizeof(*map));
+ CB_MALLOC(map->buckets, sizeof(map->buckets[0]) * bnum);
+ for(i = 0; i < bnum; i++){
+ map->buckets[i] = NULL;
+ }
+ map->first = NULL;
+ map->last = NULL;
+ map->cur = NULL;
+ map->bnum = bnum;
+ map->rnum = 0;
+ return map;
+}
+
+
+
+/*************************************************************************************************
+ * private objects
+ *************************************************************************************************/
+
+
+/* Handler to invoke the global garbage collector. */
+static void cbggchandler(void){
+ cbggckeeper(NULL, NULL);
+}
+
+
+/* Manage resources of the global garbage collector.
+ `ptr' specifies the pointer to add to the collection. If it is `NULL', all resources are
+ released.
+ `func' specifies the pointer to the function to release the resources. */
+static void cbggckeeper(void *ptr, void (*func)(void *)){
+ static void **parray = NULL;
+ static void (**farray)(void *) = NULL;
+ static int onum = 0;
+ static int asiz = CB_GCUNIT;
+ int i;
+ if(!ptr){
+ if(!parray) return;
+ for(i = onum - 1; i >= 0; i--){
+ farray[i](parray[i]);
+ }
+ free(parray);
+ free(farray);
+ parray = NULL;
+ farray = NULL;
+ onum = 0;
+ asiz = CB_GCUNIT;
+ return;
+ }
+ if(!parray){
+ CB_MALLOC(parray, sizeof(void *) * asiz);
+ CB_MALLOC(farray, sizeof(void *) * asiz);
+ if(atexit(cbggchandler) != 0) cbmyfatal("gc failed");
+ }
+ if(onum >= asiz){
+ asiz *= 2;
+ CB_REALLOC(parray, sizeof(void *) * asiz);
+ CB_REALLOC(farray, sizeof(void *) * asiz);
+ }
+ parray[onum] = ptr;
+ farray[onum] = func;
+ onum++;
+}
+
+
+/* Utility function for quick sort.
+ `bp' specifies the pointer to the pointer to an array.
+ `nmemb' specifies the number of elements of the array.
+ `size' specifies the size of each element.
+ `pswap' specifies the pointer to the swap region for a pivot.
+ `vswap' specifies the pointer to the swap region for elements.
+ `compar' specifies the pointer to comparing function. */
+static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap,
+ int(*compar)(const void *, const void *)){
+ int top, bottom;
+ assert(bp && nmemb >= 0 && size > 0 && pswap && vswap && compar);
+ if(nmemb < 10){
+ if(nmemb > 1) cbisort(bp, nmemb, size, compar);
+ return;
+ }
+ top = 0;
+ bottom = nmemb - 1;
+ memcpy(pswap, bp + (nmemb / 2) * size, size);
+ while(top - 1 < bottom){
+ if(compar(bp + top * size, pswap) < 0){
+ top++;
+ } else if(compar(bp + bottom * size, pswap) > 0){
+ bottom--;
+ } else {
+ if(top != bottom){
+ memcpy(vswap, bp + top * size, size);
+ memcpy(bp + top * size, bp + bottom * size, size);
+ memcpy(bp + bottom * size, vswap, size);
+ }
+ top++;
+ bottom--;
+ }
+ }
+ cbqsortsub(bp, top, size, pswap, vswap, compar);
+ cbqsortsub(bp + (bottom + 1) * size, nmemb - bottom - 1, size, pswap, vswap, compar);
+}
+
+
+/* Compare two list elements.
+ `a' specifies the pointer to one element.
+ `b' specifies the pointer to the other element.
+ The return value is positive if a is big, negative if b is big, else, it is 0. */
+static int cblistelemcmp(const void *a, const void *b){
+ int i, size;
+ CBLISTDATUM *ap, *bp;
+ char *ao, *bo;
+ assert(a && b);
+ ap = (CBLISTDATUM *)a;
+ bp = (CBLISTDATUM *)b;
+ ao = ap->dptr;
+ bo = bp->dptr;
+ size = ap->dsize < bp->dsize ? ap->dsize : bp->dsize;
+ for(i = 0; i < size; i++){
+ if(ao[i] > bo[i]) return 1;
+ if(ao[i] < bo[i]) return -1;
+ }
+ return ap->dsize - bp->dsize;
+}
+
+
+/* Compare two keys.
+ `abuf' specifies the pointer to the region of the former.
+ `asiz' specifies the size of the region.
+ `bbuf' specifies the pointer to the region of the latter.
+ `bsiz' specifies the size of the region.
+ The return value is 0 if two equals, positive if the formar is big, else, negative. */
+static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){
+ assert(abuf && asiz >= 0 && bbuf && bsiz >= 0);
+ if(asiz > bsiz) return 1;
+ if(asiz < bsiz) return -1;
+ return memcmp(abuf, bbuf, asiz);
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/cabin.h b/qdbm/cabin.h
new file mode 100644
index 00000000..230ec150
--- /dev/null
+++ b/qdbm/cabin.h
@@ -0,0 +1,1544 @@
+/*************************************************************************************************
+ * The utitlity API of QDBM
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#ifndef _CABIN_H /* duplication check */
+#define _CABIN_H
+
+#if defined(__cplusplus) /* export for C++ */
+extern "C" {
+#endif
+
+
+#include <stdlib.h>
+#include <time.h>
+
+
+#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC)
+#define MYEXTERN extern __declspec(dllimport)
+#else
+#define MYEXTERN extern
+#endif
+
+
+
+/*************************************************************************************************
+ * API
+ *************************************************************************************************/
+
+
+#define CB_DATUMUNIT 12 /* allocation unit size of a datum handle */
+#define CB_LISTUNIT 64 /* allocation unit number of a list handle */
+#define CB_MAPBNUM 4093 /* bucket size of a map handle */
+
+typedef struct { /* type of structure for a basic datum */
+ char *dptr; /* pointer to the region */
+ int dsize; /* size of the region */
+ int asize; /* size of the allocated region */
+} CBDATUM;
+
+typedef struct { /* type of structure for an element of a list */
+ char *dptr; /* pointer to the region */
+ int dsize; /* size of the effective region */
+} CBLISTDATUM;
+
+typedef struct { /* type of structure for a list */
+ CBLISTDATUM *array; /* array of data */
+ int anum; /* number of the elements of the array */
+ int start; /* start index of using elements */
+ int num; /* number of using elements */
+} CBLIST;
+
+typedef struct _CBMAPDATUM { /* type of structure for an element of a map */
+ int ksiz; /* size of the region of the key */
+ int vsiz; /* size of the region of the value */
+ int hash; /* second hash value */
+ struct _CBMAPDATUM *left; /* pointer to the left child */
+ struct _CBMAPDATUM *right; /* pointer to the right child */
+ struct _CBMAPDATUM *prev; /* pointer to the previous element */
+ struct _CBMAPDATUM *next; /* pointer to the next element */
+} CBMAPDATUM;
+
+typedef struct { /* type of structure for a map */
+ CBMAPDATUM **buckets; /* bucket array */
+ CBMAPDATUM *first; /* pointer to the first element */
+ CBMAPDATUM *last; /* pointer to the last element */
+ CBMAPDATUM *cur; /* pointer to the current element */
+ int bnum; /* number of buckets */
+ int rnum; /* number of records */
+} CBMAP;
+
+typedef struct { /* type of structure for a heap */
+ char *base; /* base pointer */
+ char *swap; /* region for swapping */
+ int size; /* size of each record */
+ int num; /* currnet number of records */
+ int max; /* maximum number of records */
+ int(*compar)(const void *, const void *); /* comparing function */
+} CBHEAP;
+
+
+/* Call back function for handling a fatal error.
+ The argument specifies the error message. The initial value of this variable is `NULL'.
+ If the value is `NULL', the default function is called when a fatal error occurs. A fatal
+ error occurs when memory allocation is failed. */
+MYEXTERN void (*cbfatalfunc)(const char *);
+
+
+/* Allocate a region on memory.
+ `size' specifies the size of the region.
+ The return value is the pointer to the allocated region.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+void *cbmalloc(size_t size);
+
+
+/* Re-allocate a region on memory.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region.
+ The return value is the pointer to the re-allocated region.
+ Because the region of the return value is allocated with the `realloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+void *cbrealloc(void *ptr, size_t size);
+
+
+/* Duplicate a region on memory.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the pointer to the allocated region of the duplicate.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if
+ it is no longer in use. */
+char *cbmemdup(const char *ptr, int size);
+
+
+/* Free a region on memory.
+ `ptr' specifies the pointer to a region. If it is `NULL', this function has no effect.
+ Although this function is just a wrapper of `free' call, this is useful in applications using
+ another package of the `malloc' series. */
+void cbfree(void *ptr);
+
+
+/* Register the pointer or handle of an object to the global garbage collector.
+ `ptr' specifies the pointer or handle of an object.
+ `func' specifies the pointer to a function to release resources of the object. Its argument
+ is the pointer or handle of the object to release.
+ This function assures that resources of an object are released when the process exits
+ normally by returning from the `main' function or calling the `exit' function. */
+void cbglobalgc(void *ptr, void (*func)(void *));
+
+
+/* Exercise the global garbage collector explicitly.
+ Note that you should not use objects registered to the global garbage collector any longer
+ after calling this function. Because the global garbage collecter is initialized and you
+ can register new objects into it. */
+void cbggcsweep(void);
+
+
+/* Check availability of allocation of the virtual memory.
+ `size' specifies the size of region to be allocated newly.
+ The return value is true if allocation should be success, or false if not. */
+int cbvmemavail(size_t size);
+
+
+/* Sort an array using insert sort.
+ `base' spacifies the pointer to an array.
+ `nmemb' specifies the number of elements of the array.
+ `size' specifies the size of each element.
+ `compar' specifies the pointer to comparing function. The two arguments specify the pointers
+ of elements. The comparing function should returns positive if the former is big, negative
+ if the latter is big, 0 if both are equal.
+ Insert sort is useful only if most elements have been sorted already. */
+void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
+
+/* Sort an array using shell sort.
+ `base' spacifies the pointer to an array.
+ `nmemb' specifies the number of elements of the array.
+ `size' specifies the size of each element.
+ `compar' specifies the pointer to comparing function. The two arguments specify the pointers
+ of elements. The comparing function should returns positive if the former is big, negative
+ if the latter is big, 0 if both are equal.
+ If most elements have been sorted, shell sort may be faster than heap sort or quick sort. */
+void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
+
+/* Sort an array using heap sort.
+ `base' spacifies the pointer to an array.
+ `nmemb' specifies the number of elements of the array.
+ `size' specifies the size of each element.
+ `compar' specifies the pointer to comparing function. The two arguments specify the pointers
+ of elements. The comparing function should returns positive if the former is big, negative
+ if the latter is big, 0 if both are equal.
+ Although heap sort is robust against bias of input, quick sort is faster in most cases. */
+void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
+
+/* Sort an array using quick sort.
+ `base' spacifies the pointer to an array.
+ `nmemb' specifies the number of elements of the array.
+ `size' specifies the size of each element.
+ `compar' specifies the pointer to comparing function. The two arguments specify the pointers
+ of elements. The comparing function should returns positive if the former is big, negative
+ if the latter is big, 0 if both are equal.
+ Being sensitive to bias of input, quick sort is the fastest sorting algorithm. */
+void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
+
+/* Compare two strings with case insensitive evaluation.
+ `astr' specifies the pointer of one string.
+ `astr' specifies the pointer of the other string.
+ The return value is positive if the former is big, negative if the latter is big, 0 if both
+ are equivalent.
+ Upper cases and lower cases of alphabets in ASCII code are not distinguished. */
+int cbstricmp(const char *astr, const char *bstr);
+
+
+/* Check whether a string begins with a key.
+ `str' specifies the pointer of a target string.
+ `key' specifies the pointer of a forward matching key string.
+ The return value is true if the target string begins with the key, else, it is false. */
+int cbstrfwmatch(const char *str, const char *key);
+
+
+/* Check whether a string begins with a key, with case insensitive evaluation.
+ `str' specifies the pointer of a target string.
+ `key' specifies the pointer of a forward matching key string.
+ The return value is true if the target string begins with the key, else, it is false.
+ Upper cases and lower cases of alphabets in ASCII code are not distinguished. */
+int cbstrfwimatch(const char *str, const char *key);
+
+
+/* Check whether a string ends with a key.
+ `str' specifies the pointer of a target string.
+ `key' specifies the pointer of a backward matching key string.
+ The return value is true if the target string ends with the key, else, it is false. */
+int cbstrbwmatch(const char *str, const char *key);
+
+
+/* Check whether a string ends with a key, with case insensitive evaluation.
+ `str' specifies the pointer of a target string.
+ `key' specifies the pointer of a backward matching key string.
+ The return value is true if the target string ends with the key, else, it is false.
+ Upper cases and lower cases of alphabets in ASCII code are not distinguished. */
+int cbstrbwimatch(const char *str, const char *key);
+
+
+/* Locate a substring in a string using KMP method.
+ `haystack' specifies the pointer of a target string.
+ `needle' specifies the pointer of a substring to be found.
+ The return value is the pointer to the beginning of the substring or `NULL' if the substring
+ is not found.
+ In most cases, `strstr' as a built-in function of the compiler is faster than this function. */
+char *cbstrstrkmp(const char *haystack, const char *needle);
+
+
+/* Locate a substring in a string using BM method.
+ `haystack' specifies the pointer of a target string.
+ `needle' specifies the pointer of a substring to be found.
+ The return value is the pointer to the beginning of the substring or `NULL' if the substring
+ is not found.
+ In most cases, `strstr' as a built-in function of the compiler is faster than this function. */
+char *cbstrstrbm(const char *haystack, const char *needle);
+
+
+/* Convert the letters of a string to upper case.
+ `str' specifies the pointer of a string to convert.
+ The return value is the pointer to the string. */
+char *cbstrtoupper(char *str);
+
+
+/* Convert the letters of a string to lower case.
+ `str' specifies the pointer of a string to convert.
+ The return value is the pointer to the string. */
+char *cbstrtolower(char *str);
+
+
+/* Cut space characters at head or tail of a string.
+ `str' specifies the pointer of a string to convert.
+ The return value is the pointer to the string. */
+char *cbstrtrim(char *str);
+
+
+/* Squeeze space characters in a string and trim it.
+ `str' specifies the pointer of a string to convert.
+ The return value is the pointer to the string. */
+char *cbstrsqzspc(char *str);
+
+
+/* Count the number of characters in a string of UTF-8.
+ `str' specifies the pointer of a string of UTF-8.
+ The return value is the number of characters in the string. */
+int cbstrcountutf(const char *str);
+
+
+/* Cut a string of UTF-8 at the specified number of characters.
+ `str' specifies the pointer of a string of UTF-8.
+ `num' specifies the number of characters to be kept.
+ The return value is the pointer to the string. */
+char *cbstrcututf(char *str, int num);
+
+
+/* Get a datum handle.
+ `ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty
+ datum is created.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is a datum handle. */
+CBDATUM *cbdatumopen(const char *ptr, int size);
+
+
+/* Copy a datum.
+ `datum' specifies a datum handle.
+ The return value is a new datum handle. */
+CBDATUM *cbdatumdup(const CBDATUM *datum);
+
+
+/* Free a datum handle.
+ `datum' specifies a datum handle.
+ Because the region of a closed handle is released, it becomes impossible to use the handle. */
+void cbdatumclose(CBDATUM *datum);
+
+
+/* Concatenate a datum and a region.
+ `datum' specifies a datum handle.
+ `ptr' specifies the pointer to the region to be appended.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'. */
+void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
+
+
+/* Get the pointer of the region of a datum.
+ `datum' specifies a datum handle.
+ The return value is the pointer of the region of a datum.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. */
+const char *cbdatumptr(const CBDATUM *datum);
+
+
+/* Get the size of the region of a datum.
+ `datum' specifies a datum handle.
+ The return value is the size of the region of a datum. */
+int cbdatumsize(const CBDATUM *datum);
+
+
+/* Change the size of the region of a datum.
+ `datum' specifies a datum handle.
+ `size' specifies the new size of the region.
+ If the new size is bigger than the one of old, the surplus region is filled with zero codes. */
+void cbdatumsetsize(CBDATUM *datum, int size);
+
+
+/* Perform formatted output into a datum.
+ `format' specifies a printf-like format string.
+ The conversion character `%' can be used with such flag characters as `s', `d', `o', `u',
+ `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes
+ meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works
+ as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with
+ each original. */
+void cbdatumprintf(CBDATUM *datum, const char *format, ...);
+
+
+/* Convert a datum to an allocated region.
+ `datum' specifies a datum handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the datum.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. Because the region of the original datam is released, it should not be
+ released again. */
+char *cbdatumtomalloc(CBDATUM *datum, int *sp);
+
+
+/* Get a list handle.
+ The return value is a list handle. */
+CBLIST *cblistopen(void);
+
+
+/* Copy a list.
+ `list' specifies a list handle.
+ The return value is a new list handle. */
+CBLIST *cblistdup(const CBLIST *list);
+
+
+/* Close a list handle.
+ `list' specifies a list handle.
+ Because the region of a closed handle is released, it becomes impossible to use the handle. */
+void cblistclose(CBLIST *list);
+
+
+/* Get the number of elements of a list.
+ `list' specifies a list handle.
+ The return value is the number of elements of the list. */
+int cblistnum(const CBLIST *list);
+
+
+/* Get the pointer to the region of an element of a list.
+ `list' specifies a list handle.
+ `index' specifies the index of an element.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the value.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. If `index' is equal to or more than
+ the number of elements, the return value is `NULL'. */
+const char *cblistval(const CBLIST *list, int index, int *sp);
+
+
+/* Add an element at the end of a list.
+ `list' specifies a list handle.
+ `ptr' specifies the pointer to the region of an element.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'. */
+void cblistpush(CBLIST *list, const char *ptr, int size);
+
+
+/* Remove an element of the end of a list.
+ `list' specifies a list handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the value.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. If the list is empty, the return value is `NULL'. */
+char *cblistpop(CBLIST *list, int *sp);
+
+
+/* Add an element at the top of a list.
+ `list' specifies a list handle.
+ `ptr' specifies the pointer to the region of an element.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'. */
+void cblistunshift(CBLIST *list, const char *ptr, int size);
+
+
+/* Remove an element of the top of a list.
+ `list' specifies a list handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the value.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. If the list is empty, the return value is `NULL'. */
+char *cblistshift(CBLIST *list, int *sp);
+
+
+/* Add an element at the specified location of a list.
+ `list' specifies a list handle.
+ `index' specifies the index of an element.
+ `ptr' specifies the pointer to the region of the element.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'. */
+void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
+
+
+/* Remove an element at the specified location of a list.
+ `list' specifies a list handle.
+ `index' specifies the index of an element.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the value.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. If `index' is equal to or more than the number of elements, no element
+ is removed and the return value is `NULL'. */
+char *cblistremove(CBLIST *list, int index, int *sp);
+
+
+/* Overwrite an element at the specified location of a list.
+ `list' specifies a list handle.
+ `index' specifies the index of an element.
+ `ptr' specifies the pointer to the region of the new content.
+ `size' specifies the size of the new content. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ If `index' is equal to or more than the number of elements, this function has no effect. */
+void cblistover(CBLIST *list, int index, const char *ptr, int size);
+
+
+/* Sort elements of a list in lexical order.
+ `list' specifies a list handle.
+ Quick sort is used for sorting. */
+void cblistsort(CBLIST *list);
+
+
+/* Search a list for an element using liner search.
+ `list' specifies a list handle.
+ `ptr' specifies the pointer to the region of a key.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the index of a corresponding element or -1 if there is no corresponding
+ element. If two or more elements corresponds, the former returns. */
+int cblistlsearch(const CBLIST *list, const char *ptr, int size);
+
+
+/* Search a list for an element using binary search.
+ `list' specifies a list handle. It should be sorted in lexical order.
+ `ptr' specifies the pointer to the region of a key.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the index of a corresponding element or -1 if there is no corresponding
+ element. If two or more elements corresponds, which returns is not defined. */
+int cblistbsearch(const CBLIST *list, const char *ptr, int size);
+
+
+/* Serialize a list into a byte array.
+ `list' specifies a list handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned.
+ The return value is the pointer to the region of the result serial region.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cblistdump(const CBLIST *list, int *sp);
+
+
+/* Redintegrate a serialized list.
+ `ptr' specifies the pointer to a byte array.
+ `size' specifies the size of the region.
+ The return value is a new list handle. */
+CBLIST *cblistload(const char *ptr, int size);
+
+
+/* Get a map handle.
+ The return value is a map handle. */
+CBMAP *cbmapopen(void);
+
+
+/* Copy a map.
+ `map' specifies a map handle.
+ The return value is a new map handle.
+ The iterator of the source map is initialized. */
+CBMAP *cbmapdup(CBMAP *map);
+
+
+/* Close a map handle.
+ `map' specifies a map handle.
+ Because the region of a closed handle is released, it becomes impossible to use the handle. */
+void cbmapclose(CBMAP *map);
+
+
+/* Store a record into a map.
+ `map' specifies a map handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `vbuf' specifies the pointer to the region of a value.
+ `vsiz' specifies the size of the region of the value. If it is negative, the size is
+ assigned with `strlen(vbuf)'.
+ `over' specifies whether the value of the duplicated record is overwritten or not.
+ If `over' is false and the key is duplicated, the return value is false, else, it is true. */
+int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
+
+
+/* Concatenate a value at the end of the value of the existing record.
+ `map' specifies a map handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `vbuf' specifies the pointer to the region of a value.
+ `vsiz' specifies the size of the region of the value. If it is negative, the size is
+ assigned with `strlen(vbuf)'.
+ If there is no corresponding record, a new record is created. */
+void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
+
+
+/* Delete a record in a map.
+ `map' specifies a map handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ If successful, the return value is true. False is returned when no record corresponds to
+ the specified key. */
+int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
+
+
+/* Retrieve a record in a map.
+ `map' specifies a map handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the value of the
+ corresponding record. `NULL' is returned when no record corresponds.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. */
+const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
+
+
+/* Move a record to the edge of a map.
+ `map' specifies a map handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `head' specifies the destination which is head if it is true or tail if else.
+ If successful, the return value is true. False is returned when no record corresponds to
+ the specified key. */
+int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
+
+
+/* Initialize the iterator of a map.
+ `map' specifies a map handle.
+ The iterator is used in order to access the key of every record stored in a map. */
+void cbmapiterinit(CBMAP *map);
+
+
+/* Get the next key of the iterator of a map.
+ `map' specifies a map handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the next key, else, it is
+ `NULL'. `NULL' is returned when no record is to be get out of the iterator.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. The order of iteration is assured
+ to be the same of the one of storing. */
+const char *cbmapiternext(CBMAP *map, int *sp);
+
+
+/* Get the value binded to the key fetched from the iterator of a map.
+ `kbuf' specifies the pointer to the region of a iteration key.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the value of the corresponding record.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. */
+const char *cbmapiterval(const char *kbuf, int *sp);
+
+
+/* Get the number of the records stored in a map.
+ `map' specifies a map handle.
+ The return value is the number of the records stored in the map. */
+int cbmaprnum(const CBMAP *map);
+
+
+/* Get the list handle contains all keys in a map.
+ `map' specifies a map handle.
+ The return value is the list handle contains all keys in the map.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. */
+CBLIST *cbmapkeys(CBMAP *map);
+
+
+/* Get the list handle contains all values in a map.
+ `map' specifies a map handle.
+ The return value is the list handle contains all values in the map.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. */
+CBLIST *cbmapvals(CBMAP *map);
+
+
+/* Serialize a map into a byte array.
+ `map' specifies a map handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned.
+ The return value is the pointer to the region of the result serial region.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbmapdump(CBMAP *map, int *sp);
+
+
+/* Redintegrate a serialized map.
+ `ptr' specifies the pointer to a byte array.
+ `size' specifies the size of the region.
+ The return value is a new map handle. */
+CBMAP *cbmapload(const char *ptr, int size);
+
+
+/* Extract a record from a serialized map.
+ `ptr' specifies the pointer to a byte array.
+ `size' specifies the size of the region.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the value of the
+ corresponding record. `NULL' is returned when no record corresponds.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. */
+char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
+
+
+/* Get a heap handle.
+ `size' specifies the size of each record.
+ `max' specifies the maximum number of records in the heap.
+ `compar' specifies the pointer to comparing function. The two arguments specify the pointers
+ of records. The comparing function should returns positive if the former is big, negative
+ if the latter is big, 0 if both are equal.
+ The return value is a heap handle. */
+CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
+
+
+/* Copy a heap.
+ `heap' specifies a heap handle.
+ The return value is a new heap handle. */
+CBHEAP *cbheapdup(CBHEAP *heap);
+
+
+/* Close a heap handle.
+ `heap' specifies a heap handle.
+ Because the region of a closed handle is released, it becomes impossible to use the handle. */
+void cbheapclose(CBHEAP *heap);
+
+
+/* Get the number of the records stored in a heap.
+ `heap' specifies a heap handle.
+ The return value is the number of the records stored in the heap. */
+int cbheapnum(CBHEAP *heap);
+
+
+/* Insert a record into a heap.
+ `heap' specifies a heap handle.
+ `ptr' specifies the pointer to the region of a record.
+ The return value is true if the record is added, else false.
+ If the new record is bigger than the biggest existing regord, the new record is not added.
+ If the new record is added and the number of records exceeds the maximum number, the biggest
+ existing record is removed. */
+int cbheapinsert(CBHEAP *heap, const void *ptr);
+
+
+/* Get the pointer to the region of a record in a heap.
+ `heap' specifies a heap handle.
+ `index' specifies the index of a record.
+ The return value is the pointer to the region of the record.
+ If `index' is equal to or more than the number of records, the return value is `NULL'. Note
+ that records are organized by the nagative order the comparing function. */
+const void *cbheapval(CBHEAP *heap, int index);
+
+
+/* Convert a heap to an allocated region.
+ `heap' specifies a heap handle.
+ `np' specifies the pointer to a variable to which the number of records of the return value
+ is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the heap. Records are sorted.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. Because the region of the original
+ heap is released, it should not be released again. */
+void *cbheaptomalloc(CBHEAP *heap, int *np);
+
+
+/* Allocate a formatted string on memory.
+ `format' specifies a printf-like format string. The conversion character `%' can be used
+ with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and
+ `%'. Specifiers of the field length and the precision can be put between the conversion
+ characters and the flag characters. The specifiers consist of decimal characters, `.', `+',
+ `-', and the space character.
+ The other arguments are used according to the format string.
+ The return value is the pointer to the allocated region of the result string. Because the
+ region of the return value is allocated with the `malloc' call, it should be released with
+ the `free' call if it is no longer in use. */
+char *cbsprintf(const char *format, ...);
+
+
+/* Replace some patterns in a string.
+ `str' specifies the pointer to a source string.
+ `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair
+ specifies a pattern before replacement and its value specifies the pattern after replacement.
+ The return value is the pointer to the allocated region of the result string.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbreplace(const char *str, CBMAP *pairs);
+
+
+/* Make a list by splitting a serial datum.
+ `ptr' specifies the pointer to the region of the source content.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is
+ used as a delimiter.
+ The return value is a list handle.
+ If two delimiters are successive, it is assumed that an empty element is between the two.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose'. */
+CBLIST *cbsplit(const char *ptr, int size, const char *delim);
+
+
+/* Read whole data of a file.
+ `name' specifies the name of a file. If it is `NULL', the standard input is specified.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the allocated region of the read data. Because an
+ additional zero code is appended at the end of the region of the return value, the return
+ value can be treated as a character string. Because the region of the return value is
+ allocated with the `malloc' call, it should be released with the `free' call if it is no
+ longer in use. */
+char *cbreadfile(const char *name, int *sp);
+
+
+/* Write a serial datum into a file.
+ `name specifies the name of a file. If it is `NULL', the standard output is specified.
+ `ptr' specifies the pointer to the region of the source content.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ If successful, the return value is true, else, it is false.
+ If the file exists, it is overwritten. Else, a new file is created. */
+int cbwritefile(const char *name, const char *ptr, int size);
+
+
+/* Read every line of a file.
+ `name' specifies the name of a file. If it is `NULL', the standard input is specified.
+ The return value is a list handle of the lines if successful, else it is NULL. Line
+ separators are cut out. Because the handle of the return value is opened with the function
+ `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */
+CBLIST *cbreadlines(const char *name);
+
+
+/* Read names of files in a directory.
+ `name' specifies the name of a directory.
+ The return value is a list handle of names if successful, else it is NULL.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. */
+CBLIST *cbdirlist(const char *name);
+
+
+/* Get the status of a file or a directory.
+ `name' specifies the name of a file or a directory.
+ `dirp' specifies the pointer to a variable to which whether the file is a directory is
+ assigned. If it is `NULL', it is not used.
+ `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it
+ is `NULL', it is not used.
+ `mtimep' specifies the pointer to a variable to which the last modified time of the file is
+ assigned. If it is `NULL', it is not used.
+ If successful, the return value is true, else, false. False is returned when the file does
+ not exist or the permission is denied. */
+int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep);
+
+
+/* Remove a file or a directory and its sub ones recursively.
+ `name' specifies the name of a file or a directory.
+ If successful, the return value is true, else, false. False is returned when the file does
+ not exist or the permission is denied. */
+int cbremove(const char *name);
+
+
+/* Break up a URL into elements.
+ `str' specifies the pointer to a string of URL.
+ The return value is a map handle. Each key of the map is the name of an element. The key
+ "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host"
+ specifies the host of the server. The key "port" specifies the port number of the server.
+ The key "authority" specifies the authority information. The key "path" specifies the path
+ of the resource. The key "file" specifies the file name without the directory section. The
+ key "query" specifies the query string. The key "fragment" specifies the fragment string.
+ Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported.
+ Because the handle of the return value is opened with the function `cbmapopen', it should
+ be closed with the function `cbmapclose' if it is no longer in use. */
+CBMAP *cburlbreak(const char *str);
+
+
+/* Resolve a relative URL with another absolute URL.
+ `base' specifies an absolute URL of a base location.
+ `target' specifies a URL to be resolved.
+ The return value is a resolved URL. If the target URL is relative, a new URL of relative
+ location from the base location is returned. Else, a copy of the target URL is returned.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cburlresolve(const char *base, const char *target);
+
+
+/* Encode a serial object with URL encoding.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the pointer to the result string.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cburlencode(const char *ptr, int size);
+
+
+/* Decode a string encoded with URL encoding.
+ `str' specifies the pointer to an encoded string.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the result.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if
+ it is no longer in use. */
+char *cburldecode(const char *str, int *sp);
+
+
+/* Encode a serial object with Base64 encoding.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the pointer to the result string.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbbaseencode(const char *ptr, int size);
+
+
+/* Decode a string encoded with Base64 encoding.
+ `str' specifies the pointer to an encoded string.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the result.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if
+ it is no longer in use. */
+char *cbbasedecode(const char *str, int *sp);
+
+
+/* Encode a serial object with quoted-printable encoding.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the pointer to the result string.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbquoteencode(const char *ptr, int size);
+
+
+/* Decode a string encoded with quoted-printable encoding.
+ `str' specifies the pointer to an encoded string.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer to the region of the result.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if
+ it is no longer in use. */
+char *cbquotedecode(const char *str, int *sp);
+
+
+/* Split a string of MIME into headers and the body.
+ `ptr' specifies the pointer to the region of MIME data.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each
+ key of the map is an attribute name uncapitalized.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ The return value is the pointer of the body data.
+ If the content type is defined, the attribute map has the key "TYPE" specifying the type. If
+ the character encoding is defined, the key "CHARSET" specifies the encoding name. If the
+ boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the
+ content disposition is defined, the key "DISPOSITION" specifies the direction. If the file
+ name is defined, the key "FILENAME" specifies the name. If the attribute name is defined,
+ the key "NAME" specifies the name. Because the region of the return value is allocated with
+ the `malloc' call, it should be released with the `free' call if it is no longer in use. */
+char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
+
+
+/* Split multipart data of MIME into its parts.
+ `ptr' specifies the pointer to the region of multipart data of MIME.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `boundary' specifies the pointer to the region of the boundary string.
+ The return value is a list handle. Each element of the list is the string of a part.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. */
+CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
+
+
+/* Encode a string with MIME encoding.
+ `str' specifies the pointer to a string.
+ `encname' specifies a string of the name of the character encoding.
+ The return value is the pointer to the result string.
+ `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbmimeencode(const char *str, const char *encname, int base);
+
+
+/* Decode a string encoded with MIME encoding.
+ `str' specifies the pointer to an encoded string.
+ `enp' specifies the pointer to a region into which the name of encoding is written. If it is
+ `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes.
+ The return value is the pointer to the result string.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbmimedecode(const char *str, char *enp);
+
+
+/* Split a string of CSV into rows.
+ `str' specifies the pointer to the region of an CSV string.
+ The return value is a list handle. Each element of the list is a string of a row.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. The character encoding
+ of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being
+ compatible with MS-Excel, these functions for CSV can handle cells including such meta
+ characters as comma, between double quotation marks. */
+CBLIST *cbcsvrows(const char *str);
+
+
+/* Split the string of a row of CSV into cells.
+ `str' specifies the pointer to the region of a row of CSV.
+ The return value is a list handle. Each element of the list is the unescaped string of a
+ cell of the row.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. */
+CBLIST *cbcsvcells(const char *str);
+
+
+/* Escape a string with the meta characters of CSV.
+ `str' specifies the pointer to the region of a string.
+ The return value is the pointer to the escaped string sanitized of meta characters.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbcsvescape(const char *str);
+
+
+/* Unescape a string with the escaped meta characters of CSV.
+ `str' specifies the pointer to the region of a string with meta characters.
+ The return value is the pointer to the unescaped string.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbcsvunescape(const char *str);
+
+
+/* Split a string of XML into tags and text sections.
+ `str' specifies the pointer to the region of an XML string.
+ `cr' specifies whether to remove comments.
+ The return value is a list handle. Each element of the list is the string of a tag or a
+ text section.
+ Because the handle of the return value is opened with the function `cblistopen', it should
+ be closed with the function `cblistclose' if it is no longer in use. The character encoding
+ of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because
+ these functions for XML are not XML parser with validation check, it can handle also HTML
+ and SGML. */
+CBLIST *cbxmlbreak(const char *str, int cr);
+
+
+/* Get the map of attributes of an XML tag.
+ `str' specifies the pointer to the region of a tag string.
+ The return value is a map handle. Each key of the map is the name of an attribute. Each
+ value is unescaped. You can get the name of the tag with the key of an empty string.
+ Because the handle of the return value is opened with the function `cbmapopen', it should
+ be closed with the function `cbmapclose' if it is no longer in use. */
+CBMAP *cbxmlattrs(const char *str);
+
+
+/* Escape a string with the meta characters of XML.
+ `str' specifies the pointer to the region of a string.
+ The return value is the pointer to the escaped string sanitized of meta characters.
+ This function converts only `&', `<', `>', and `"'. Because the region of the return value
+ is allocated with the `malloc' call, it should be released with the `free' call if it is no
+ longer in use. */
+char *cbxmlescape(const char *str);
+
+
+/* Unescape a string with the entity references of XML.
+ `str' specifies the pointer to the region of a string with meta characters.
+ The return value is the pointer to the unescaped string.
+ This function restores only `&amp;', `&lt;', `&gt;', and `&quot;'. Because the region of the
+ return value is allocated with the `malloc' call, it should be released with the `free' call
+ if it is no longer in use. */
+char *cbxmlunescape(const char *str);
+
+
+/* Compress a serial object with ZLIB.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. This function is available only if
+ QDBM was built with ZLIB enabled. */
+char *cbdeflate(const char *ptr, int size, int *sp);
+
+
+/* Decompress a serial object compressed with ZLIB.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */
+char *cbinflate(const char *ptr, int size, int *sp);
+
+
+/* Compress a serial object with GZIP.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. This function is available only if
+ QDBM was built with ZLIB enabled. */
+char *cbgzencode(const char *ptr, int size, int *sp);
+
+
+/* Decompress a serial object compressed with GZIP.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */
+char *cbgzdecode(const char *ptr, int size, int *sp);
+
+
+/* Get the CRC32 checksum of a serial object.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the CRC32 checksum of the object.
+ This function is available only if QDBM was built with ZLIB enabled. */
+unsigned int cbgetcrc(const char *ptr, int size);
+
+
+/* Compress a serial object with LZO.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. This function is available only if
+ QDBM was built with LZO enabled. */
+char *cblzoencode(const char *ptr, int size, int *sp);
+
+
+/* Decompress a serial object compressed with LZO.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. This function is available only if QDBM was built with LZO enabled. */
+char *cblzodecode(const char *ptr, int size, int *sp);
+
+
+/* Compress a serial object with BZIP2.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. This function is available only if
+ QDBM was built with LZO enabled. */
+char *cbbzencode(const char *ptr, int size, int *sp);
+
+
+/* Decompress a serial object compressed with BZIP2.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. This function is available only if QDBM was built with LZO enabled. */
+char *cbbzdecode(const char *ptr, int size, int *sp);
+
+
+/* Convert the character encoding of a string.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ `icode' specifies the name of encoding of the input string.
+ `ocode' specifies the name of encoding of the output string.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ `mp' specifies the pointer to a variable to which the number of missing characters by failure
+ of conversion is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the result object, else, it is `NULL'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. This function is available only if QDBM was built with ICONV enabled. */
+char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
+
+
+/* Detect the encoding of a string automatically.
+ `ptr' specifies the pointer to a region.
+ `size' specifies the size of the region. If it is negative, the size is assigned with
+ `strlen(ptr)'.
+ The return value is the string of the encoding name of the string.
+ As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE,
+ and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function
+ is available only if QDBM was built with ICONV enabled. */
+const char *cbencname(const char *ptr, int size);
+
+
+/* Get the jet lag of the local time in seconds.
+ The return value is the jet lag of the local time in seconds. */
+int cbjetlag(void);
+
+
+/* Get the Gregorian calendar of a time.
+ `t' specifies a source time. If it is negative, the current time is specified.
+ `jl' specifies the jet lag of a location in seconds.
+ `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL',
+ it is not used.
+ `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL',
+ it is not used. 1 means January and 12 means December.
+ `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it
+ is `NULL', it is not used.
+ `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL',
+ it is not used.
+ `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL',
+ it is not used.
+ `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL',
+ it is not used. */
+void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp);
+
+
+/* Get the day of week of a date.
+ `year' specifies the year of a date.
+ `mon' specifies the month of the date.
+ `day' specifies the day of the date.
+ The return value is the day of week of the date. 0 means Sunday and 6 means Saturday. */
+int cbdayofweek(int year, int mon, int day);
+
+
+/* Get the string for a date in W3CDTF.
+ `t' specifies a source time. If it is negative, the current time is specified.
+ `jl' specifies the jet lag of a location in seconds.
+ The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD).
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbdatestrwww(time_t t, int jl);
+
+
+/* Get the string for a date in RFC 1123 format.
+ `t' specifies a source time. If it is negative, the current time is specified.
+ `jl' specifies the jet lag of a location in seconds.
+ The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD).
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *cbdatestrhttp(time_t t, int jl);
+
+
+/* Get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123).
+ `str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123).
+ The return value is the time value of the date or -1 if the format is invalid.
+ Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours,
+ and "d" for in days. */
+time_t cbstrmktime(const char *str);
+
+
+/* Get user and system processing times.
+ `usrp' specifies the pointer to a variable to which the user processing time is assigned.
+ If it is `NULL', it is not used. The unit of time is seconds.
+ `sysp' specifies the pointer to a variable to which the system processing time is assigned.
+ If it is `NULL', it is not used. The unit of time is seconds. */
+void cbproctime(double *usrp, double *sysp);
+
+
+/* Ensure that the standard I/O is binary mode.
+ This function is useful for applications on dosish file systems. */
+void cbstdiobin(void);
+
+
+
+/*************************************************************************************************
+ * features for experts
+ *************************************************************************************************/
+
+
+/* Show error message on the standard error output and exit.
+ `message' specifies an error message.
+ This function does not return. */
+void *cbmyfatal(const char *message);
+
+
+/* Create a datum handle from an allocated region.
+ `ptr' specifies the pointer to the region of an element. The region should be allocated with
+ malloc and it is released by the function.
+ `size' specifies the size of the region. */
+CBDATUM *cbdatumopenbuf(char *ptr, int size);
+
+
+/* Set a buffer to a datum handle.
+ `ptr' specifies the pointer to the region of an element. The region should be allocated with
+ malloc and it is released by the function.
+ `size' specifies the size of the region. */
+void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size);
+
+
+/* Add an allocated element at the end of a list.
+ `list' specifies a list handle.
+ `ptr' specifies the pointer to the region of an element. The region should be allocated with
+ malloc and it is released by the function.
+ `size' specifies the size of the region. */
+void cblistpushbuf(CBLIST *list, char *ptr, int size);
+
+
+/* Get a map handle with specifying the number of buckets.
+ `bnum' specifies the number of buckets.
+ The return value is a map handle. */
+CBMAP *cbmapopenex(int bnum);
+
+
+/* Alias of `cbmalloc'. */
+#define CB_MALLOC(CB_ptr, CB_size) \
+ (((CB_ptr) = malloc(CB_size)) ? (CB_ptr) : cbmyfatal("out of memory"))
+
+
+/* Alias of `cbrealloc'. */
+#define CB_REALLOC(CB_ptr, CB_size) \
+ (((CB_ptr) = realloc((CB_ptr), (CB_size))) ? (CB_ptr) : cbmyfatal("out of memory"))
+
+
+/* Alias of `cbmemdup'.
+ However, `size' should not be negative. */
+#define CB_MEMDUP(CB_res, CB_ptr, CB_size) \
+ do { \
+ CB_MALLOC((CB_res), (CB_size) + 1); \
+ memcpy((CB_res), (CB_ptr), (CB_size)); \
+ (CB_res)[(CB_size)] = '\0'; \
+ } while(FALSE)
+
+
+/* Get the size of padding bytes for pointer alignment.
+ `hsiz' specifies the header size of the object.
+ The return value is the size of padding bytes. */
+#define CB_ALIGNPAD(CB_hsiz) \
+ (((CB_hsiz | ~-(int)sizeof(void *)) + 1) - CB_hsiz)
+
+
+/* Alias of `cbdatumopen'.
+ However, no dafault data is specified. */
+#define CB_DATUMOPEN(CB_datum) \
+ do { \
+ CB_MALLOC((CB_datum), sizeof(*(CB_datum))); \
+ CB_MALLOC((CB_datum)->dptr, CB_DATUMUNIT); \
+ (CB_datum)->dptr[0] = '\0'; \
+ (CB_datum)->dsize = 0; \
+ (CB_datum)->asize = CB_DATUMUNIT; \
+ } while(FALSE)
+
+
+/* Alias of `cbdatumopen'.
+ However, `size' should not be negative. */
+#define CB_DATUMOPEN2(CB_datum, CB_ptr, CB_size) \
+ do { \
+ CB_DATUMOPEN((CB_datum)); \
+ CB_DATUMCAT((CB_datum), (CB_ptr), (CB_size)); \
+ } while(FALSE)
+
+
+/* Alias of `cbdatumclose'. */
+#define CB_DATUMCLOSE(CB_datum) \
+ do { \
+ free((CB_datum)->dptr); \
+ free((CB_datum)); \
+ } while(FALSE)
+
+
+/* Alias of `cbdatumcat'.
+ However, `size' should not be negative. */
+#define CB_DATUMCAT(CB_datum, CB_ptr, CB_size) \
+ do { \
+ if((CB_datum)->dsize + (CB_size) >= (CB_datum)->asize){ \
+ (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \
+ CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \
+ } \
+ memcpy((CB_datum)->dptr + (CB_datum)->dsize, (CB_ptr), (CB_size)); \
+ (CB_datum)->dsize += (CB_size); \
+ (CB_datum)->dptr[(CB_datum)->dsize] = '\0'; \
+ } while(FALSE)
+
+
+/* Alias of `cbdatumptr'. */
+#define CB_DATUMPTR(CB_datum) ((const char *)((CB_datum)->dptr))
+
+
+/* Alias of `cbdatumsize'. */
+#define CB_DATUMSIZE(CB_datum) ((int)((CB_datum)->dsize))
+
+
+/* Alias of `cbdatumsetsize'. */
+#define CB_DATUMSETSIZE(CB_datum, CB_size) \
+ do { \
+ if((CB_size) <= (CB_datum)->dsize){ \
+ (CB_datum)->dsize = (CB_size); \
+ (CB_datum)->dptr[(CB_size)] = '\0'; \
+ } else { \
+ if((CB_size) >= (CB_datum)->asize){ \
+ (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \
+ CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \
+ } \
+ memset((CB_datum)->dptr + (CB_datum)->dsize, 0, ((CB_size) - (CB_datum)->dsize) + 1); \
+ (CB_datum)->dsize = (CB_size); \
+ } \
+ } while(FALSE)
+
+
+/* Alias of `cbdatumtomalloc'. */
+#define CB_DATUMTOMALLOC(CB_datum, CB_ptr, CB_size) \
+ do { \
+ (CB_ptr) = (CB_datum)->dptr; \
+ (CB_size) = (CB_datum)->dsize; \
+ free((CB_datum)); \
+ } while(FALSE)
+
+
+/* Alias of `cblistopen'. */
+#define CB_LISTOPEN(CB_list) \
+ do { \
+ CB_MALLOC((CB_list), sizeof(*(CB_list))); \
+ (CB_list)->anum = CB_LISTUNIT; \
+ CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \
+ (CB_list)->start = 0; \
+ (CB_list)->num = 0; \
+ } while(FALSE)
+
+
+/* Alias of `cblistopen'.
+ However, `anum' is specified for the number of initial allocated elements. */
+#define CB_LISTOPEN2(CB_list, CB_anum) \
+ do { \
+ CB_MALLOC((CB_list), sizeof(*(CB_list))); \
+ (CB_list)->anum = (CB_anum) > 4 ? (CB_anum) : 4; \
+ CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \
+ (CB_list)->start = 0; \
+ (CB_list)->num = 0; \
+ } while(FALSE)
+
+
+/* Alias of `cblistclose'. */
+#define CB_LISTCLOSE(CB_list) \
+ do { \
+ int _CB_i, _CB_end; \
+ _CB_end = (CB_list)->start + (CB_list)->num; \
+ for(_CB_i = (CB_list)->start; _CB_i < _CB_end; _CB_i++){ \
+ free((CB_list)->array[_CB_i].dptr); \
+ } \
+ free((CB_list)->array); \
+ free((CB_list)); \
+ } while(FALSE)
+
+
+/* Alias of `cblistnum'. */
+#define CB_LISTNUM(CB_list) \
+ ((int)((CB_list)->num))
+
+
+/* Alias of `cblistval'.
+ However, `sp' is ignored. */
+#define CB_LISTVAL(CB_list, CB_index) \
+ ((const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr))
+
+
+/* Alias of `cblistval'.
+ However, `size' is used instead of `sp'. */
+#define CB_LISTVAL2(CB_list, CB_index, CB_size) \
+ ((CB_size) = (CB_list)->array[(CB_list)->start+(CB_index)].dsize, \
+ (const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr))
+
+
+/* Alias of `cblistpush'.
+ However, `size' should not be negative. */
+#define CB_LISTPUSH(CB_list, CB_ptr, CB_size) \
+ do { \
+ int _CB_index; \
+ _CB_index = (CB_list)->start + (CB_list)->num; \
+ if(_CB_index >= (CB_list)->anum){ \
+ (CB_list)->anum *= 2; \
+ CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \
+ } \
+ CB_MALLOC((CB_list)->array[_CB_index].dptr, \
+ ((CB_size) < CB_DATUMUNIT ? CB_DATUMUNIT : (CB_size)) + 1); \
+ memcpy((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \
+ (CB_list)->array[_CB_index].dptr[(CB_size)] = '\0'; \
+ (CB_list)->array[_CB_index].dsize = (CB_size); \
+ (CB_list)->num++; \
+ } while(FALSE)
+
+
+/* Remove and free an element of the end of a list.
+ `list' specifies a list handle. */
+#define CB_LISTDROP(CB_list) \
+ do { \
+ if((CB_list)->num > 0){ \
+ free((CB_list)->array[(CB_list)->start+(CB_list)->num-1].dptr); \
+ (CB_list)->num--; \
+ } \
+ } while(FALSE)
+
+
+/* Alias of `cblistinsert'.
+ However, `index' is not checked and `size' should not be negative. */
+#define CB_LISTINSERT(CB_list, CB_index, CB_ptr, CB_size) \
+ do { \
+ int _CB_index = (CB_index); \
+ _CB_index += (CB_list)->start; \
+ if((CB_list)->start + (CB_list)->num >= (CB_list)->anum){ \
+ (CB_list)->anum *= 2; \
+ CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \
+ } \
+ memmove((CB_list)->array + _CB_index + 1, (CB_list)->array + _CB_index, \
+ sizeof((CB_list)->array[0]) * ((CB_list)->start + (CB_list)->num - _CB_index)); \
+ CB_MEMDUP((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \
+ (CB_list)->array[_CB_index].dsize = (CB_size); \
+ (CB_list)->num++; \
+ } while(FALSE)
+
+
+/* Alias of `cblistpushbuf'. */
+#define CB_LISTPUSHBUF(CB_list, CB_ptr, CB_size) \
+ do{ \
+ int _CB_index; \
+ _CB_index = (CB_list)->start + (CB_list)->num; \
+ if(_CB_index >= (CB_list)->anum){ \
+ (CB_list)->anum *= 2; \
+ CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \
+ } \
+ (CB_list)->array[_CB_index].dptr = (CB_ptr); \
+ (CB_list)->array[_CB_index].dsize = (CB_size); \
+ (CB_list)->num++; \
+ } while(FALSE) \
+
+
+/* Alias of `cbmapiterval'.
+ However, `size' is used instead of `sp'. */
+#define CB_MAPITERVAL(CB_vbuf, CB_kbuf, CB_vsiz) \
+ do { \
+ CBMAPDATUM *_CB_datum; \
+ _CB_datum = (CBMAPDATUM *)((CB_kbuf) - sizeof(*_CB_datum)); \
+ (CB_vsiz) = _CB_datum->vsiz; \
+ (CB_vbuf) = (char *)_CB_datum + sizeof(*_CB_datum) + \
+ _CB_datum->ksiz + CB_ALIGNPAD(_CB_datum->ksiz); \
+ } while(FALSE)
+
+
+
+#undef MYEXTERN
+
+#if defined(__cplusplus) /* export for C++ */
+}
+#endif
+
+#endif /* duplication check */
+
+
+/* END OF FILE */
diff --git a/qdbm/cbcodec.c b/qdbm/cbcodec.c
new file mode 100644
index 00000000..1ab45153
--- /dev/null
+++ b/qdbm/cbcodec.c
@@ -0,0 +1,1079 @@
+/*************************************************************************************************
+ * Popular encoders and decoders
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#include <cabin.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#undef TRUE
+#define TRUE 1 /* boolean true */
+#undef FALSE
+#define FALSE 0 /* boolean false */
+
+#define DEFCODE "UTF-8" /* default encoding */
+
+
+/* for RISC OS */
+#if defined(__riscos__) || defined(__riscos)
+#include <unixlib/local.h>
+int __riscosify_control = __RISCOSIFY_NO_PROCESS;
+#endif
+
+
+/* global variables */
+const char *progname; /* program name */
+
+
+/* function prototypes */
+int main(int argc, char **argv);
+void usage(void);
+char *readstdin(int *sp);
+int runurl(int argc, char **argv);
+int runbase(int argc, char **argv);
+int runquote(int argc, char **argv);
+int runmime(int argc, char **argv);
+int runcsv(int argc, char **argv);
+int runxml(int argc, char **argv);
+int runzlib(int argc, char **argv);
+int runlzo(int argc, char **argv);
+int runbzip(int argc, char **argv);
+int runiconv(int argc, char **argv);
+int rundate(int argc, char **argv);
+void shouucsmap(void);
+
+
+/* main routine */
+int main(int argc, char **argv){
+ int rv;
+ cbstdiobin();
+ progname = argv[0];
+ if(argc < 2) usage();
+ rv = 0;
+ if(!strcmp(argv[1], "url")){
+ rv = runurl(argc, argv);
+ } else if(!strcmp(argv[1], "base")){
+ rv = runbase(argc, argv);
+ } else if(!strcmp(argv[1], "quote")){
+ rv = runquote(argc, argv);
+ } else if(!strcmp(argv[1], "mime")){
+ rv = runmime(argc, argv);
+ } else if(!strcmp(argv[1], "csv")){
+ rv = runcsv(argc, argv);
+ } else if(!strcmp(argv[1], "xml")){
+ rv = runxml(argc, argv);
+ } else if(!strcmp(argv[1], "zlib")){
+ rv = runzlib(argc, argv);
+ } else if(!strcmp(argv[1], "lzo")){
+ rv = runlzo(argc, argv);
+ } else if(!strcmp(argv[1], "bzip")){
+ rv = runbzip(argc, argv);
+ } else if(!strcmp(argv[1], "iconv")){
+ rv = runiconv(argc, argv);
+ } else if(!strcmp(argv[1], "date")){
+ rv = rundate(argc, argv);
+ } else {
+ usage();
+ }
+ return rv;
+}
+
+
+/* print the usage and exit */
+void usage(void){
+ char *tmp;
+ int tsiz;
+ fprintf(stderr, "%s: popular encoders and decoders\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " %s url [-d] [-br] [-rs base target] [-l] [-e expr] [file]\n", progname);
+ fprintf(stderr, " %s base [-d] [-l] [-c num] [-e expr] [file]\n", progname);
+ fprintf(stderr, " %s quote [-d] [-l] [-c num] [-e expr] [file]\n", progname);
+ fprintf(stderr, " %s mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr]"
+ " [file]\n", progname);
+ fprintf(stderr, " %s csv [-d] [-t] [-l] [-e expr] [-html] [file]\n", progname);
+ fprintf(stderr, " %s xml [-d] [-p] [-l] [-e expr] [-tsv] [file]\n", progname);
+ if((tmp = cbdeflate("", 0, &tsiz)) != NULL){
+ fprintf(stderr, " %s zlib [-d] [-gz] [-crc] [file]\n", progname);
+ free(tmp);
+ }
+ if((tmp = cblzoencode("", 0, &tsiz)) != NULL){
+ fprintf(stderr, " %s lzo [-d] [file]\n", progname);
+ free(tmp);
+ }
+ if((tmp = cbbzencode("", 0, &tsiz)) != NULL){
+ fprintf(stderr, " %s bzip [-d] [file]\n", progname);
+ free(tmp);
+ }
+ if((tmp = cbiconv("", 0, "US-ASCII", "US-ASCII", NULL, NULL)) != NULL){
+ fprintf(stderr, " %s iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-wc] [-um] [file]\n",
+ progname);
+ free(tmp);
+ }
+ fprintf(stderr, " %s date [-wf] [-rf] [-utc] [str]\n", progname);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+
+/* read the standard input */
+char *readstdin(int *sp){
+ char *buf;
+ int i, blen, c;
+ blen = 256;
+ buf = cbmalloc(blen);
+ for(i = 0; (c = getchar()) != EOF; i++){
+ if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2);
+ buf[i] = c;
+ }
+ buf[i] = '\0';
+ if(sp) *sp = i;
+ return buf;
+}
+
+
+/* parse arguments of url command */
+int runurl(int argc, char **argv){
+ CBMAP *map;
+ int i, size, dec, br, line;
+ const char *val;
+ char *base, *target, *expr, *file, *buf, *res;
+ dec = FALSE;
+ br = FALSE;
+ line = FALSE;
+ base = NULL;
+ target = NULL;
+ expr = NULL;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-br")){
+ br = TRUE;
+ } else if(!strcmp(argv[i], "-rs")){
+ if(++i >= argc) usage();
+ base = argv[i];
+ if(++i >= argc) usage();
+ target = argv[i];
+ } else if(!strcmp(argv[i], "-l")){
+ line = TRUE;
+ } else if(!strcmp(argv[i], "-e")){
+ if(++i >= argc) usage();
+ expr = argv[i];
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(base){
+ size = strlen(base);
+ buf = cbmemdup(base, size);
+ } else if(expr){
+ size = strlen(expr);
+ buf = cbmemdup(expr, size);
+ } else if(file){
+ if(!(buf = cbreadfile(file, &size))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&size);
+ }
+ if(target){
+ res = cburlresolve(base, target);
+ printf("%s", res);
+ free(res);
+ } else if(br){
+ map = cburlbreak(buf);
+ if((val = cbmapget(map, "self", -1, NULL))) printf("self\t%s\n", val);
+ if((val = cbmapget(map, "scheme", -1, NULL))) printf("scheme\t%s\n", val);
+ if((val = cbmapget(map, "host", -1, NULL))) printf("host\t%s\n", val);
+ if((val = cbmapget(map, "port", -1, NULL))) printf("port\t%s\n", val);
+ if((val = cbmapget(map, "authority", -1, NULL))) printf("authority\t%s\n", val);
+ if((val = cbmapget(map, "path", -1, NULL))) printf("path\t%s\n", val);
+ if((val = cbmapget(map, "file", -1, NULL))) printf("file\t%s\n", val);
+ if((val = cbmapget(map, "query", -1, NULL))) printf("query\t%s\n", val);
+ if((val = cbmapget(map, "fragment", -1, NULL))) printf("fragment\t%s\n", val);
+ cbmapclose(map);
+ } else if(dec){
+ res = cburldecode(buf, &size);
+ for(i = 0; i < size; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ res = cburlencode(buf, size);
+ for(i = 0; res[i] != '\0'; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ }
+ if(line) putchar('\n');
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of base command */
+int runbase(int argc, char **argv){
+ int i, ci, size, dec, line, cols;
+ char *expr, *file, *buf, *res;
+ dec = FALSE;
+ line = FALSE;
+ cols = -1;
+ expr = NULL;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-l")){
+ line = TRUE;
+ } else if(!strcmp(argv[i], "-c")){
+ if(++i >= argc) usage();
+ cols = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-e")){
+ if(++i >= argc) usage();
+ expr = argv[i];
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(expr){
+ size = strlen(expr);
+ buf = cbmemdup(expr, size);
+ } else if(file){
+ if(!(buf = cbreadfile(file, &size))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&size);
+ }
+ if(dec){
+ res = cbbasedecode(buf, &size);
+ for(i = 0; i < size; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ res = cbbaseencode(buf, size);
+ ci = 0;
+ for(i = 0; res[i] != '\0'; i++){
+ if(cols > 0 && ci >= cols){
+ putchar('\n');
+ ci = 0;
+ }
+ putchar(res[i]);
+ ci++;
+ }
+ free(res);
+ }
+ if(line) putchar('\n');
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of quote command */
+int runquote(int argc, char **argv){
+ int i, ci, size, dec, line, cols;
+ char *expr, *file, *buf, *res;
+ dec = FALSE;
+ line = FALSE;
+ cols = -1;
+ expr = NULL;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-l")){
+ line = TRUE;
+ } else if(!strcmp(argv[i], "-c")){
+ if(++i >= argc) usage();
+ cols = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-e")){
+ if(++i >= argc) usage();
+ expr = argv[i];
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(expr){
+ size = strlen(expr);
+ buf = cbmemdup(expr, size);
+ } else if(file){
+ if(!(buf = cbreadfile(file, &size))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&size);
+ }
+ if(dec){
+ res = cbquotedecode(buf, &size);
+ for(i = 0; i < size; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ res = cbquoteencode(buf, size);
+ ci = 0;
+ for(i = 0; res[i] != '\0'; i++){
+ if(cols > 0 && (ci >= cols || (ci >= cols - 2 && res[i] == '='))){
+ printf("=\n");
+ ci = 0;
+ }
+ if(res[i] == '\r' || res[i] == '\n') ci = 0;
+ putchar(res[i]);
+ ci++;
+ }
+ free(res);
+ }
+ if(line) putchar('\n');
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of mime command */
+int runmime(int argc, char **argv){
+ CBMAP *attrs;
+ CBLIST *parts;
+ int i, size, dec, line, qp, dc, hd, bd, pnum, rsiz, bsiz;
+ const char *key, *body;
+ char *code, *expr, *file, *buf, *res, renc[64];
+ dec = FALSE;
+ hd = FALSE;
+ bd = FALSE;
+ pnum = 0;
+ line = FALSE;
+ dc = FALSE;
+ qp = FALSE;
+ code = NULL;
+ expr = NULL;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-hd")){
+ hd = TRUE;
+ } else if(!strcmp(argv[i], "-bd")){
+ bd = TRUE;
+ } else if(!strcmp(argv[i], "-part")){
+ if(++i >= argc) usage();
+ pnum = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-l")){
+ line = TRUE;
+ } else if(!strcmp(argv[i], "-ec")){
+ if(++i >= argc) usage();
+ code = argv[i];
+ } else if(!strcmp(argv[i], "-qp")){
+ qp = TRUE;
+ } else if(!strcmp(argv[i], "-dc")){
+ dc = TRUE;
+ } else if(!strcmp(argv[i], "-e")){
+ if(++i >= argc) usage();
+ expr = argv[i];
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(expr){
+ size = strlen(expr);
+ buf = cbmemdup(expr, size);
+ } else if(file){
+ if(!(buf = cbreadfile(file, &size))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&size);
+ }
+ if(hd || bd || pnum > 0){
+ attrs = cbmapopen();
+ res = cbmimebreak(buf, size, attrs, &rsiz);
+ if(pnum > 0){
+ parts = NULL;
+ if(!(key = cbmapget(attrs, "TYPE", -1, NULL)) || !cbstrfwimatch(key, "multipart/") ||
+ !(key = cbmapget(attrs, "BOUNDARY", -1, NULL)) ||
+ !(parts = cbmimeparts(res, rsiz, key)) || cblistnum(parts) < pnum){
+ fprintf(stderr, "%s: not multipart or no such part\n", progname);
+ if(parts) cblistclose(parts);
+ free(res);
+ cbmapclose(attrs);
+ free(buf);
+ return 1;
+ }
+ body = cblistval(parts, pnum - 1, &bsiz);
+ for(i = 0; i < bsiz; i++){
+ putchar(body[i]);
+ }
+ cblistclose(parts);
+ } else if(hd){
+ cbmapiterinit(attrs);
+ while((key = cbmapiternext(attrs, NULL)) != NULL){
+ printf("%s\t%s\n", key, cbmapget(attrs, key, -1, NULL));
+ }
+ } else {
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ }
+ free(res);
+ cbmapclose(attrs);
+ } else if(dec){
+ res = cbmimedecode(buf, renc);
+ printf("%s", dc ? renc : res);
+ free(res);
+ } else {
+ res = cbmimeencode(buf, code ? code : DEFCODE, !qp);
+ printf("%s", res);
+ free(res);
+ }
+ if(line) putchar('\n');
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of csv command */
+int runcsv(int argc, char **argv){
+ CBLIST *rows, *cells;
+ int i, j, k, dec, tb, line, html;
+ const char *row, *cell;
+ char *expr, *file, *buf, *res;
+ dec = FALSE;
+ tb = FALSE;
+ line = FALSE;
+ html = FALSE;
+ expr = NULL;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-t")){
+ tb = TRUE;
+ } else if(!strcmp(argv[i], "-l")){
+ line = TRUE;
+ } else if(!strcmp(argv[i], "-e")){
+ if(++i >= argc) usage();
+ expr = argv[i];
+ } else if(!strcmp(argv[i], "-html")){
+ html = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(expr){
+ buf = cbmemdup(expr, -1);
+ } else if(file){
+ if(!(buf = cbreadfile(file, NULL))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(NULL);
+ }
+ if(tb || html){
+ if(html) printf("<table border=\"1\">\n");
+ rows = cbcsvrows(buf);
+ for(i = 0; i < cblistnum(rows); i++){
+ if(html) printf("<tr>");
+ row = cblistval(rows, i, NULL);
+ cells = cbcsvcells(row);
+ for(j = 0; j < cblistnum(cells); j++){
+ cell = cblistval(cells, j, NULL);
+ if(html){
+ printf("<td>");
+ for(k = 0; cell[k] != '\0'; k++){
+ if(cell[k] == '\r' || cell[k] == '\n'){
+ printf("<br>");
+ if(cell[k] == '\r' && cell[k] == '\n') k++;
+ } else {
+ switch(cell[k]){
+ case '&': printf("&amp;"); break;
+ case '<': printf("&lt;"); break;
+ case '>': printf("&gt;"); break;
+ default: putchar(cell[k]); break;
+ }
+ }
+ }
+ printf("</td>");
+ } else {
+ if(j > 0) putchar('\t');
+ for(k = 0; cell[k] != '\0'; k++){
+ if(((unsigned char *)cell)[k] >= 0x20) putchar(cell[k]);
+ }
+ }
+ }
+ cblistclose(cells);
+ if(html) printf("</tr>");
+ putchar('\n');
+ }
+ cblistclose(rows);
+ if(html) printf("</table>\n");
+ } else if(dec){
+ res = cbcsvunescape(buf);
+ for(i = 0; res[i] != '\0'; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ res = cbcsvescape(buf);
+ for(i = 0; res[i] != '\0'; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ }
+ if(line) putchar('\n');
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of xml command */
+int runxml(int argc, char **argv){
+ CBLIST *elems;
+ CBMAP *attrs;
+ int i, j, dec, pb, line, tsv, div;
+ const char *elem, *attr;
+ char *expr, *file, *buf, *res;
+ dec = FALSE;
+ pb = FALSE;
+ line = FALSE;
+ tsv = FALSE;
+ expr = NULL;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-p")){
+ pb = TRUE;
+ } else if(!strcmp(argv[i], "-l")){
+ line = TRUE;
+ } else if(!strcmp(argv[i], "-e")){
+ if(++i >= argc) usage();
+ expr = argv[i];
+ } else if(!strcmp(argv[i], "-tsv")){
+ tsv = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(expr){
+ buf = cbmemdup(expr, -1);
+ } else if(file){
+ if(!(buf = cbreadfile(file, NULL))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(NULL);
+ }
+ if(pb || tsv){
+ elems = cbxmlbreak(buf, FALSE);
+ for(i = 0; i < cblistnum(elems); i++){
+ elem = cblistval(elems, i, NULL);
+ div = FALSE;
+ if(elem[0] == '<'){
+ if(cbstrfwimatch(elem, "<?xml")){
+ printf("XMLDECL");
+ div = TRUE;
+ } else if(cbstrfwimatch(elem, "<!DOCTYPE")){
+ printf("DOCTYPE");
+ } else if(cbstrfwimatch(elem, "<!--")){
+ printf("COMMENT");
+ } else if(cbstrfwimatch(elem, "</")){
+ printf("ENDTAG");
+ div = TRUE;
+ } else if(cbstrbwimatch(elem, "/>")){
+ printf("EMPTAG");
+ div = TRUE;
+ } else {
+ printf("BEGTAG");
+ div = TRUE;
+ }
+ } else {
+ printf("TEXT");
+ }
+ putchar('\t');
+ if(tsv){
+ if(div){
+ attrs = cbxmlattrs(elem);
+ cbmapiterinit(attrs);
+ for(j = 0; (attr = cbmapiternext(attrs, NULL)) != NULL; j++){
+ if(j < 1){
+ printf("%s", cbmapget(attrs, attr, -1, NULL));
+ } else {
+ printf("\t%s\t%s", attr, cbmapget(attrs, attr, -1, NULL));
+ }
+ }
+ cbmapclose(attrs);
+ } else {
+ res = cbxmlunescape(elem);
+ for(j = 0; elem[j] != '\0'; j++){
+ if(((unsigned char *)elem)[j] < 0x20 || elem[j] == '%'){
+ printf("%%%02X", elem[j]);
+ } else {
+ putchar(elem[j]);
+ }
+ }
+ free(res);
+ }
+ } else {
+ printf("%s", elem);
+ }
+ putchar('\n');
+ }
+ cblistclose(elems);
+ } else if(dec){
+ res = cbxmlunescape(buf);
+ for(i = 0; res[i] != '\0'; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ res = cbxmlescape(buf);
+ for(i = 0; res[i] != '\0'; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ }
+ if(line) putchar('\n');
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of zlib command */
+int runzlib(int argc, char **argv){
+ unsigned int sum;
+ int i, bsiz, rsiz, dec, gz, crc;
+ char *file, *buf, *res;
+ dec = FALSE;
+ gz = FALSE;
+ crc = FALSE;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else if(!strcmp(argv[i], "-gz")){
+ gz = TRUE;
+ } else if(!strcmp(argv[i], "-crc")){
+ crc = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(file){
+ if(!(buf = cbreadfile(file, &bsiz))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&bsiz);
+ }
+ if(crc){
+ sum = cbgetcrc(buf, bsiz);
+ for(i = 0; i < sizeof(int); i++){
+ printf("%02x", sum / 0x1000000);
+ sum <<= 8;
+ }
+ putchar('\n');
+ } else if(dec){
+ if(!(res = gz ? cbgzdecode(buf, bsiz, &rsiz) : cbinflate(buf, bsiz, &rsiz))){
+ fprintf(stderr, "%s: inflate failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ if(!(res = gz ? cbgzencode(buf, bsiz, &rsiz) : cbdeflate(buf, bsiz, &rsiz))){
+ fprintf(stderr, "%s: deflate failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ }
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of lzo command */
+int runlzo(int argc, char **argv){
+ int i, bsiz, rsiz, dec;
+ char *file, *buf, *res;
+ dec = FALSE;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(file){
+ if(!(buf = cbreadfile(file, &bsiz))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&bsiz);
+ }
+ if(dec){
+ if(!(res = cblzodecode(buf, bsiz, &rsiz))){
+ fprintf(stderr, "%s: decode failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ if(!(res = cblzoencode(buf, bsiz, &rsiz))){
+ fprintf(stderr, "%s: encode failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ }
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of bzip command */
+int runbzip(int argc, char **argv){
+ int i, bsiz, rsiz, dec;
+ char *file, *buf, *res;
+ dec = FALSE;
+ file = NULL;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ dec = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(file){
+ if(!(buf = cbreadfile(file, &bsiz))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&bsiz);
+ }
+ if(dec){
+ if(!(res = cbbzdecode(buf, bsiz, &rsiz))){
+ fprintf(stderr, "%s: decode failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ } else {
+ if(!(res = cbbzencode(buf, bsiz, &rsiz))){
+ fprintf(stderr, "%s: encode failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ free(res);
+ }
+ free(buf);
+ return 0;
+}
+
+
+/* parse arguments of iconv command */
+int runiconv(int argc, char **argv){
+ CBDATUM *datum;
+ const char *rcode;
+ char *icode, *ocode, *ltype, *file, *buf, *res, *norm, *orig;
+ int i, cn, wc, bsiz, rsiz, nsiz, osiz, miss;
+ icode = NULL;
+ ocode = NULL;
+ ltype = NULL;
+ file = NULL;
+ cn = FALSE;
+ wc = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!file && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-ic")){
+ if(++i >= argc) usage();
+ icode = argv[i];
+ } else if(!strcmp(argv[i], "-oc")){
+ if(++i >= argc) usage();
+ ocode = argv[i];
+ } else if(!strcmp(argv[i], "-ol")){
+ if(++i >= argc) usage();
+ ltype = argv[i];
+ } else if(!strcmp(argv[i], "-cn")){
+ cn = TRUE;
+ } else if(!strcmp(argv[i], "-wc")){
+ wc = TRUE;
+ } else if(!strcmp(argv[i], "-um")){
+ shouucsmap();
+ } else {
+ usage();
+ }
+ } else if(!file){
+ file = argv[i];
+ } else {
+ usage();
+ }
+ }
+ buf = NULL;
+ if(file){
+ if(!(buf = cbreadfile(file, &bsiz))){
+ fprintf(stderr, "%s: %s: cannot open\n", progname, file);
+ return 1;
+ }
+ } else {
+ buf = readstdin(&bsiz);
+ }
+ miss = 0;
+ if(cn){
+ printf("%s\n", cbencname(buf, bsiz));
+ } else if(wc){
+ printf("%d\n", cbstrcountutf(buf));
+ } else {
+ rcode = icode ? icode : cbencname(buf, bsiz);
+ if(!(res = cbiconv(buf, bsiz, rcode, ocode ? ocode : DEFCODE,
+ &rsiz, &miss))){
+ fprintf(stderr, "%s: iconv failed\n", progname);
+ free(buf);
+ return 1;
+ }
+ if(miss > 0) fprintf(stderr, "%s: missing %d characters\n", progname, miss);
+ if(ltype && (!cbstricmp(ltype, "u") || !cbstricmp(ltype, "unix") ||
+ !cbstricmp(ltype, "lf"))){
+ ltype = "\n";
+ } else if(ltype && (!cbstricmp(ltype, "d") || !cbstricmp(ltype, "dos") ||
+ !cbstricmp(ltype, "crlf"))){
+ ltype = "\r\n";
+ } else if(ltype && (!cbstricmp(ltype, "m") || !cbstricmp(ltype, "mac") ||
+ !cbstricmp(ltype, "cr"))){
+ ltype = "\r";
+ } else {
+ ltype = NULL;
+ }
+ if(ltype){
+ if(!(norm = cbiconv(res, rsiz, ocode, "UTF-8", &nsiz, NULL))){
+ fprintf(stderr, "%s: iconv failed\n", progname);
+ free(res);
+ free(buf);
+ return 1;
+ }
+ datum = cbdatumopen(NULL, -1);
+ for(i = 0; i < nsiz; i++){
+ if(norm[i] == '\r'){
+ if(norm[i+1] == '\n') i++;
+ cbdatumcat(datum, ltype, -1);
+ } else if(norm[i] == '\n'){
+ cbdatumcat(datum, ltype, -1);
+ } else {
+ cbdatumcat(datum, norm + i, 1);
+ }
+ }
+ if(!(orig = cbiconv(cbdatumptr(datum), cbdatumsize(datum), "UTF-8", ocode, &osiz, NULL))){
+ fprintf(stderr, "%s: iconv failed\n", progname);
+ cbdatumclose(datum);
+ free(norm);
+ free(res);
+ free(buf);
+ return 1;
+ }
+ for(i = 0; i < osiz; i++){
+ putchar(orig[i]);
+ }
+ free(orig);
+ cbdatumclose(datum);
+ free(norm);
+ } else {
+ for(i = 0; i < rsiz; i++){
+ putchar(res[i]);
+ }
+ }
+ free(res);
+ }
+ free(buf);
+ return miss > 0 ? 1 : 0;
+}
+
+
+/* parse arguments of date command */
+int rundate(int argc, char **argv){
+ int i, wb, rb, utc, jl;
+ char *date, *res;
+ time_t t;
+ wb = FALSE;
+ rb = FALSE;
+ utc = FALSE;
+ date = NULL;
+ for(i = 2; i < argc; i++){
+ if(!date && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-wf")){
+ wb = TRUE;
+ } else if(!strcmp(argv[i], "-rf")){
+ rb = TRUE;
+ } else if(!strcmp(argv[i], "-utc")){
+ utc = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!date){
+ date = argv[i];
+ } else {
+ usage();
+ }
+ }
+ jl = utc ? 0 : cbjetlag();
+ if(date){
+ t = cbstrmktime(date);
+ } else {
+ t = time(NULL);
+ }
+ if(wb){
+ res = cbdatestrwww(t, jl);
+ } else if(rb){
+ res = cbdatestrhttp(t, jl);
+ } else {
+ res = cbsprintf("%d", (int)t);
+ }
+ if(t >= 0){
+ printf("%s\n", res);
+ } else {
+ if(date){
+ fprintf(stderr, "%s: %s: invalid date format\n", progname, date);
+ } else {
+ fprintf(stderr, "%s: invalid time setting\n", progname);
+ }
+ }
+ free(res);
+ return 0;
+}
+
+
+/* show mapping of UCS-2 and exit. */
+void shouucsmap(void){
+ unsigned char buf[2], *tmp;
+ int i, j, tsiz;
+ for(i = 0; i < 65536; i++){
+ buf[0] = i / 256;
+ buf[1] = i % 256;
+ printf("%d\t", i);
+ printf("U+%02X%02X\t", buf[0], buf[1]);
+ printf("\"\\x%x\\x%x\"\t", buf[0], buf[1]);
+ if((tmp = (unsigned char *)cbiconv((char *)buf, 2, "UTF-16BE", "UTF-8",
+ &tsiz, NULL)) != NULL){
+ if(tsiz > 0){
+ printf("\"");
+ for(j = 0; j < tsiz; j++){
+ printf("\\x%x", tmp[j]);
+ }
+ printf("\"");
+ } else {
+ printf("NULL");
+ }
+ free(tmp);
+ }
+ printf("\n");
+ }
+ exit(0);
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/cbtest.c b/qdbm/cbtest.c
new file mode 100644
index 00000000..d1c84e0d
--- /dev/null
+++ b/qdbm/cbtest.c
@@ -0,0 +1,924 @@
+/*************************************************************************************************
+ * Test cases of Cabin
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#include <cabin.h>
+#include <stdio.h>
+#include <cabin.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <time.h>
+
+#undef TRUE
+#define TRUE 1 /* boolean true */
+#undef FALSE
+#define FALSE 0 /* boolean false */
+
+#define RECBUFSIZ 32 /* buffer for records */
+#define TEXTBUFSIZ 262144 /* buffer for text */
+
+
+/* for RISC OS */
+#if defined(__riscos__) || defined(__riscos)
+#include <unixlib/local.h>
+int __riscosify_control = __RISCOSIFY_NO_PROCESS;
+#endif
+
+
+/* global variables */
+const char *progname; /* program name */
+
+
+/* function prototypes */
+int main(int argc, char **argv);
+void usage(void);
+int runsort(int argc, char **argv);
+int runstrstr(int argc, char **argv);
+int runlist(int argc, char **argv);
+int runmap(int argc, char **argv);
+int runheap(int argc, char **argv);
+int runwicked(int argc, char **argv);
+int runmisc(int argc, char **argv);
+int printfflush(const char *format, ...);
+int strpcmp(const void *ap, const void *bp);
+int intpcmp(const void *ap, const void *bp);
+int myrand(void);
+int dosort(int rnum, int disp);
+int dostrstr(int rnum, int disp);
+int dolist(int rnum, int disp);
+int domap(int rnum, int bnum, int disp);
+int doheap(int rnum, int max, int disp);
+int dowicked(int rnum);
+int domisc(void);
+
+
+/* main routine */
+int main(int argc, char **argv){
+ int rv;
+ cbstdiobin();
+ progname = argv[0];
+ if(argc < 2) usage();
+ rv = 0;
+ if(!strcmp(argv[1], "sort")){
+ rv = runsort(argc, argv);
+ } else if(!strcmp(argv[1], "strstr")){
+ rv = runstrstr(argc, argv);
+ } else if(!strcmp(argv[1], "list")){
+ rv = runlist(argc, argv);
+ } else if(!strcmp(argv[1], "map")){
+ rv = runmap(argc, argv);
+ } else if(!strcmp(argv[1], "heap")){
+ rv = runheap(argc, argv);
+ } else if(!strcmp(argv[1], "wicked")){
+ rv = runwicked(argc, argv);
+ } else if(!strcmp(argv[1], "misc")){
+ rv = runmisc(argc, argv);
+ } else {
+ usage();
+ }
+ return rv;
+}
+
+
+/* print the usage and exit */
+void usage(void){
+ fprintf(stderr, "%s: test cases for Cabin\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " %s sort [-d] rnum\n", progname);
+ fprintf(stderr, " %s strstr [-d] rnum\n", progname);
+ fprintf(stderr, " %s list [-d] rnum\n", progname);
+ fprintf(stderr, " %s map [-d] rnum [bnum]\n", progname);
+ fprintf(stderr, " %s heap [-d] rnum [top]\n", progname);
+ fprintf(stderr, " %s wicked rnum\n", progname);
+ fprintf(stderr, " %s misc\n", progname);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+
+/* parse arguments of sort command */
+int runsort(int argc, char **argv){
+ int i, rnum, disp, rv;
+ char *rstr;
+ rstr = NULL;
+ rnum = 0;
+ disp = FALSE;
+ for(i = 2; i < argc; i++){
+ if(argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ disp = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!rstr){
+ rstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ rv = dosort(rnum, disp);
+ return rv;
+}
+
+
+/* parse arguments of strstr command */
+int runstrstr(int argc, char **argv){
+ int i, rnum, disp, rv;
+ char *rstr;
+ rstr = NULL;
+ rnum = 0;
+ disp = FALSE;
+ for(i = 2; i < argc; i++){
+ if(argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ disp = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!rstr){
+ rstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ rv = dostrstr(rnum, disp);
+ return rv;
+}
+
+
+/* parse arguments of list command */
+int runlist(int argc, char **argv){
+ int i, rnum, disp, rv;
+ char *rstr;
+ rstr = NULL;
+ rnum = 0;
+ disp = FALSE;
+ for(i = 2; i < argc; i++){
+ if(argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ disp = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!rstr){
+ rstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ rv = dolist(rnum, disp);
+ return rv;
+}
+
+
+/* parse arguments of map command */
+int runmap(int argc, char **argv){
+ int i, rnum, bnum, disp, rv;
+ char *rstr, *bstr;
+ rstr = NULL;
+ bstr = NULL;
+ rnum = 0;
+ bnum = -1;
+ disp = FALSE;
+ for(i = 2; i < argc; i++){
+ if(argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ disp = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!rstr){
+ rstr = argv[i];
+ } else if(!bstr){
+ bstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ if(bstr) bnum = atoi(bstr);
+ rv = domap(rnum, bnum, disp);
+ return rv;
+}
+
+
+/* parse arguments of heap command */
+int runheap(int argc, char **argv){
+ int i, rnum, max, disp, rv;
+ char *rstr, *mstr;
+ rstr = NULL;
+ mstr = NULL;
+ rnum = 0;
+ max = -1;
+ disp = FALSE;
+ for(i = 2; i < argc; i++){
+ if(argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-d")){
+ disp = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!rstr){
+ rstr = argv[i];
+ } else if(!mstr){
+ mstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ if(mstr) max = atoi(mstr);
+ if(max < 0) max = rnum;
+ rv = doheap(rnum, max, disp);
+ rv = 0;
+ return rv;
+}
+
+
+/* parse arguments of wicked command */
+int runwicked(int argc, char **argv){
+ int i, rnum, rv;
+ char *rstr;
+ rstr = NULL;
+ rnum = 0;
+ for(i = 2; i < argc; i++){
+ if(argv[i][0] == '-'){
+ usage();
+ } else if(!rstr){
+ rstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ rv = dowicked(rnum);
+ return rv;
+}
+
+
+/* parse arguments of misc command */
+int runmisc(int argc, char **argv){
+ int rv;
+ rv = domisc();
+ return rv;
+}
+
+
+/* print formatted string and flush the buffer */
+int printfflush(const char *format, ...){
+ va_list ap;
+ int rv;
+ va_start(ap, format);
+ rv = vprintf(format, ap);
+ if(fflush(stdout) == EOF) rv = -1;
+ va_end(ap);
+ return rv;
+}
+
+
+/* comparing function for strings */
+int strpcmp(const void *ap, const void *bp){
+ return strcmp(*(char **)ap, *(char **)bp);
+}
+
+
+/* comparing function for integers */
+int intpcmp(const void *ap, const void *bp){
+ return *(int *)ap - *(int *)bp;
+}
+
+
+/* pseudo random number generator */
+int myrand(void){
+ static int cnt = 0;
+ if(cnt == 0) srand(time(NULL));
+ return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX;
+}
+
+
+/* perform sort command */
+int dosort(int rnum, int disp){
+ char **ivector1, **ivector2, **ivector3, **ivector4, **ivector5;
+ char buf[RECBUFSIZ];
+ int i, len, err;
+ if(!disp) printfflush("<Sorting Test>\n rnum=%d\n\n", rnum);
+ ivector1 = cbmalloc(rnum * sizeof(ivector1[0]));
+ ivector2 = cbmalloc(rnum * sizeof(ivector2[0]));
+ ivector3 = cbmalloc(rnum * sizeof(ivector3[0]));
+ ivector4 = cbmalloc(rnum * sizeof(ivector4[0]));
+ ivector5 = cbmalloc(rnum * sizeof(ivector5[0]));
+ err = FALSE;
+ for(i = 0; i < rnum; i++){
+ len = sprintf(buf, "%08d", myrand() % rnum + 1);
+ ivector1[i] = cbmemdup(buf, len);
+ ivector2[i] = cbmemdup(buf, len);
+ ivector3[i] = cbmemdup(buf, len);
+ ivector4[i] = cbmemdup(buf, len);
+ ivector5[i] = cbmemdup(buf, len);
+ }
+ if(!disp) printfflush("Sorting with insert sort ... ");
+ cbisort(ivector1, rnum, sizeof(ivector1[0]), strpcmp);
+ if(!disp) printfflush("ok\n");
+ if(!disp) printfflush("Sorting with shell sort ... ");
+ cbssort(ivector2, rnum, sizeof(ivector2[0]), strpcmp);
+ if(!disp) printfflush("ok\n");
+ if(!disp) printfflush("Sorting with heap sort ... ");
+ cbhsort(ivector3, rnum, sizeof(ivector3[0]), strpcmp);
+ if(!disp) printfflush("ok\n");
+ if(!disp) printfflush("Sorting with quick sort ... ");
+ cbqsort(ivector4, rnum, sizeof(ivector4[0]), strpcmp);
+ if(!disp) printfflush("ok\n");
+ for(i = 0; i < rnum; i++){
+ if(disp) printfflush("%s\t%s\t%s\t%s\t[%s]\n",
+ ivector1[i], ivector2[i], ivector3[i], ivector4[i], ivector5[i]);
+ if(strcmp(ivector1[i], ivector2[i])) err = TRUE;
+ if(strcmp(ivector1[i], ivector3[i])) err = TRUE;
+ if(strcmp(ivector1[i], ivector4[i])) err = TRUE;
+ free(ivector1[i]);
+ free(ivector2[i]);
+ free(ivector3[i]);
+ free(ivector4[i]);
+ free(ivector5[i]);
+ }
+ free(ivector1);
+ free(ivector2);
+ free(ivector3);
+ free(ivector4);
+ free(ivector5);
+ if(err) fprintf(stderr, "%s: sorting failed\n", progname);
+ if(!disp && !err) printfflush("all ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform strstr command */
+int dostrstr(int rnum, int disp){
+ char *text, buf[RECBUFSIZ], *std, *kmp, *bm;
+ int i, j, len, err;
+ text = cbmalloc(TEXTBUFSIZ);
+ for(i = 0; i < TEXTBUFSIZ - 1; i++){
+ text[i] = 'a' + myrand() % ('z' - 'a');
+ }
+ text[i] = '\0';
+ err = FALSE;
+ if(!disp) printfflush("Locating substrings ... ");
+ for(i = 0; i < rnum; i++){
+ len = myrand() % (RECBUFSIZ - 1);
+ for(j = 0; j < len; j++){
+ buf[j] = 'a' + myrand() % ('z' - 'a');
+ }
+ buf[j] = 0;
+ std = strstr(text, buf);
+ kmp = cbstrstrkmp(text, buf);
+ bm = cbstrstrbm(text, buf);
+ if(kmp != std || bm != std){
+ err = TRUE;
+ break;
+ }
+ if(disp && std) printf("%s\n", buf);
+ }
+ if(err) fprintf(stderr, "%s: string scanning failed\n", progname);
+ if(!disp && !err){
+ printfflush("ok\n");
+ printfflush("all ok\n\n");
+ }
+ free(text);
+ return err ? 1 : 0;
+}
+
+
+/* perform list command */
+int dolist(int rnum, int disp){
+ CBLIST *list;
+ const char *vbuf;
+ char buf[RECBUFSIZ], *tmp;
+ int i, err, len, vsiz;
+ if(!disp) printfflush("<List Writing Test>\n rnum=%d\n\n", rnum);
+ list = cblistopen();
+ err = FALSE;
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", i);
+ cblistpush(list, buf, len);
+ if(!disp && rnum > 250 && i % (rnum / 250) == 0){
+ putchar('.');
+ fflush(stdout);
+ if(i == rnum || i % (rnum / 10) == 0){
+ printfflush(" (%08d)\n", i);
+ }
+ }
+ }
+ if(disp){
+ for(i = 0; i < cblistnum(list); i++){
+ if((vbuf = cblistval(list, i, &vsiz)) != NULL){
+ printfflush("%s:%d\n", vbuf, vsiz);
+ } else {
+ fprintf(stderr, "%s: val error\n", progname);
+ err = TRUE;
+ break;
+ }
+ }
+ printfflush("\n");
+ while((tmp = cblistpop(list, &vsiz)) != NULL){
+ printfflush("%s:%d\n", tmp, vsiz);
+ free(tmp);
+ }
+ }
+ cblistclose(list);
+ if(!disp && !err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform list command */
+int domap(int rnum, int bnum, int disp){
+ CBMAP *map;
+ const char *kbuf, *vbuf;
+ char buf[RECBUFSIZ];
+ int i, err, len, ksiz, vsiz;
+ if(!disp) printfflush("<Map Writing Test>\n rnum=%d bnum=%d\n\n", rnum, bnum);
+ map = bnum > 0 ? cbmapopenex(bnum) : cbmapopen();
+ err = FALSE;
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!cbmapput(map, buf, len, buf, len, FALSE)){
+ fprintf(stderr, "%s: put error\n", progname);
+ err = TRUE;
+ break;
+ }
+ if(!disp && rnum > 250 && i % (rnum / 250) == 0){
+ putchar('.');
+ fflush(stdout);
+ if(i == rnum || i % (rnum / 10) == 0){
+ printfflush(" (%08d)\n", i);
+ }
+ }
+ }
+ if(disp){
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", i);
+ if((vbuf = cbmapget(map, buf, len, &vsiz)) != NULL){
+ printfflush("%s:%d\t%s:%d\n", buf, len, vbuf, vsiz);
+ } else {
+ fprintf(stderr, "%s: get error\n", progname);
+ }
+ }
+ printfflush("\n");
+ cbmapiterinit(map);
+ while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
+ vbuf = cbmapiterval(kbuf, &vsiz);
+ printfflush("%s:%d\t%s:%d\n", kbuf, ksiz, vbuf, vsiz);
+ }
+ }
+ cbmapclose(map);
+ if(!disp && !err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform heap command */
+int doheap(int rnum, int max, int disp){
+ CBHEAP *heap;
+ int *orig, *ary;
+ int i, err, num, anum;
+ if(!disp) printfflush("<Heap Writing Test>\n rnum=%d max=%d\n\n", rnum, max);
+ orig = disp ? cbmalloc(rnum * sizeof(int) + 1) : NULL;
+ heap = cbheapopen(sizeof(int), max, intpcmp);
+ err = FALSE;
+ for(i = 1; i <= rnum; i++){
+ num = myrand() % rnum + 1;
+ if(orig) orig[i-1] = num;
+ cbheapinsert(heap, &num);
+ if(!disp && rnum > 250 && i % (rnum / 250) == 0){
+ putchar('.');
+ fflush(stdout);
+ if(i == rnum || i % (rnum / 10) == 0){
+ printfflush(" (%08d)\n", i);
+ }
+ }
+ }
+ if(disp){
+ for(i = 0; i < cbheapnum(heap); i++){
+ printf("%d\n", *(int *)cbheapval(heap, i));
+ }
+ printf("\n");
+ qsort(orig, rnum, sizeof(int), intpcmp);
+ ary = (int *)cbheaptomalloc(heap, &anum);
+ if(anum != rnum && anum != max) err = TRUE;
+ for(i = 0; i < anum; i++){
+ printf("%d\t%d\n", ary[i], orig[i]);
+ if(ary[i] != orig[i]) err = TRUE;
+ }
+ free(ary);
+ } else {
+ cbheapclose(heap);
+ }
+ free(orig);
+ if(!disp && !err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform wicked command */
+int dowicked(int rnum){
+ CBLIST *list;
+ CBMAP *map;
+ int i, len;
+ char buf[RECBUFSIZ], *tmp;
+ printfflush("<Wicked Writing Test>\n rnum=%d\n\n", rnum);
+ list = cblistopen();
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%d", myrand() % rnum + 1);
+ switch(myrand() % 16){
+ case 0:
+ free(cblistpop(list, NULL));
+ putchar('O');
+ break;
+ case 1:
+ cblistunshift(list, buf, len);
+ putchar('U');
+ break;
+ case 2:
+ free(cblistshift(list, NULL));
+ putchar('S');
+ break;
+ case 3:
+ cblistinsert(list, myrand() % (cblistnum(list) + 1), buf, len);
+ putchar('I');
+ break;
+ case 4:
+ free(cblistremove(list, myrand() % (cblistnum(list) + 1), NULL));
+ putchar('R');
+ break;
+ case 5:
+ cblistover(list, myrand() % (cblistnum(list) + 1), buf, len);
+ putchar('V');
+ break;
+ case 6:
+ tmp = cbmemdup(buf, len);
+ cblistpushbuf(list, tmp, len);
+ putchar('B');
+ break;
+ default:
+ cblistpush(list, buf, len);
+ putchar('P');
+ break;
+ }
+ if(i % 50 == 0) printfflush(" (%08d)\n", i);
+ }
+ cblistclose(list);
+ map = cbmapopen();
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%d", myrand() % rnum + 1);
+ switch(myrand() % 16){
+ case 0:
+ cbmapput(map, buf, len, buf, len, FALSE);
+ putchar('I');
+ break;
+ case 1:
+ cbmapputcat(map, buf, len, buf, len);
+ putchar('C');
+ break;
+ case 2:
+ cbmapget(map, buf, len, NULL);
+ putchar('V');
+ break;
+ case 3:
+ cbmapout(map, buf, len);
+ putchar('D');
+ break;
+ case 4:
+ cbmapmove(map, buf, len, myrand() % 2);
+ putchar('M');
+ break;
+ default:
+ cbmapput(map, buf, len, buf, len, TRUE);
+ putchar('O');
+ break;
+ }
+ if(i % 50 == 0) printfflush(" (%08d)\n", i);
+ }
+ cbmapclose(map);
+ printfflush("ok\n\n");
+ return 0;
+}
+
+
+/* perform misc command */
+int domisc(void){
+ CBDATUM *odatum, *ndatum;
+ CBLIST *olist, *nlist, *elems, *glist;
+ CBMAP *omap, *nmap, *pairs, *gmap;
+ int i, j, ssiz, osiz, tsiz, jl;
+ char kbuf[RECBUFSIZ], vbuf[RECBUFSIZ], *sbuf, spbuf[1024], *tmp, *orig, renc[64];
+ const char *op, *np;
+ time_t t;
+ printfflush("<Miscellaneous Test>\n\n");
+ printfflush("Checking memory allocation ... ");
+ tmp = cbmalloc(1024);
+ for(i = 1; i <= 65536; i *= 2){
+ tmp = cbrealloc(tmp, i);
+ }
+ cbfree(tmp);
+ printfflush("ok\n");
+ printfflush("Checking basic datum ... ");
+ odatum = cbdatumopen("x", -1);
+ for(i = 0; i < 1000; i++){
+ cbdatumcat(odatum, "x", 1);
+ }
+ cbdatumclose(odatum);
+ tmp = cbmalloc(3);
+ memcpy(tmp, "abc", 3);
+ odatum = cbdatumopenbuf(tmp, 3);
+ for(i = 0; i < 1000; i++){
+ cbdatumcat(odatum, ".", 1);
+ }
+ ndatum = cbdatumdup(odatum);
+ for(i = 0; i < 1000; i++){
+ cbdatumcat(ndatum, "*", 1);
+ }
+ for(i = 0; i < 1000; i++){
+ tmp = cbmalloc(3);
+ memcpy(tmp, "123", 3);
+ cbdatumsetbuf(ndatum, tmp, 3);
+ }
+ cbdatumprintf(ndatum, "[%s\t%08d\t%08o\t%08x\t%08.1f\t%@\t%?\t%:]",
+ "mikio", 1978, 1978, 1978, 1978.0211, "<>&#!+-*/%", "<>&#!+-*/%", "<>&#!+-*/%");
+ cbdatumclose(ndatum);
+ cbdatumclose(odatum);
+ printfflush("ok\n");
+ printfflush("Checking serialization of list ... ");
+ olist = cblistopen();
+ for(i = 1; i <= 1000; i++){
+ sprintf(vbuf, "%d", i);
+ cblistpush(olist, vbuf, -1);
+ }
+ sbuf = cblistdump(olist, &ssiz);
+ nlist = cblistload(sbuf, ssiz);
+ free(sbuf);
+ for(i = 0; i < cblistnum(olist); i++){
+ op = cblistval(olist, i, NULL);
+ np = cblistval(nlist, i, NULL);
+ if(!op || !np || strcmp(op, np)){
+ cblistclose(nlist);
+ cblistclose(olist);
+ fprintf(stderr, "%s: validation failed\n", progname);
+ return 1;
+ }
+ }
+ cblistclose(nlist);
+ cblistclose(olist);
+ printfflush("ok\n");
+ printfflush("Checking serialization of map ... ");
+ omap = cbmapopen();
+ for(i = 1; i <= 1000; i++){
+ sprintf(kbuf, "%X", i);
+ sprintf(vbuf, "[%d]", i);
+ cbmapput(omap, kbuf, -1, vbuf, -1, TRUE);
+ }
+ sbuf = cbmapdump(omap, &ssiz);
+ nmap = cbmapload(sbuf, ssiz);
+ free(cbmaploadone(sbuf, ssiz, "1", 2, &tsiz));
+ free(cbmaploadone(sbuf, ssiz, "33", 2, &tsiz));
+ free(sbuf);
+ cbmapiterinit(omap);
+ while((op = cbmapiternext(omap, NULL)) != NULL){
+ if(!(np = cbmapget(nmap, op, -1, NULL))){
+ cbmapclose(nmap);
+ cbmapclose(omap);
+ fprintf(stderr, "%s: validation failed\n", progname);
+ return 1;
+ }
+ }
+ cbmapclose(nmap);
+ cbmapclose(omap);
+ printfflush("ok\n");
+ printfflush("Checking string utilities ... ");
+ sprintf(spbuf, "[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]",
+ 123456, 123456, 123456, 123456, 123456,
+ 123456.789, 123456.789, 123456.789, 123456.789, 123456.789,
+ 'A', "hoge");
+ tmp = cbsprintf("[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]",
+ 123456, 123456, 123456, 123456, 123456,
+ 123456.789, 123456.789, 123456.789, 123456.789, 123456.789,
+ 'A', "hoge");
+ while(strcmp(spbuf, tmp)){
+ free(tmp);
+ fprintf(stderr, "%s: cbsprintf is invalid\n", progname);
+ return 1;
+ }
+ free(tmp);
+ pairs = cbmapopen();
+ cbmapput(pairs, "aa", -1, "AAA", -1, TRUE);
+ cbmapput(pairs, "bb", -1, "BBB", -1, TRUE);
+ cbmapput(pairs, "cc", -1, "CCC", -1, TRUE);
+ cbmapput(pairs, "ZZZ", -1, "z", -1, TRUE);
+ tmp = cbreplace("[aaaaabbbbbcccccdddddZZZZ]", pairs);
+ if(strcmp(tmp, "[AAAAAAaBBBBBBbCCCCCCcdddddzZ]")){
+ free(tmp);
+ cbmapclose(pairs);
+ fprintf(stderr, "%s: cbreplace is invalid\n", progname);
+ return 1;
+ }
+ free(tmp);
+ cbmapclose(pairs);
+ elems = cbsplit("aa bb,ccc-dd,", -1, " ,-");
+ if(cblistnum(elems) != 5 || strcmp(cblistval(elems, 0, NULL), "aa") ||
+ strcmp(cblistval(elems, 1, NULL), "bb") || strcmp(cblistval(elems, 2, NULL), "ccc") ||
+ strcmp(cblistval(elems, 3, NULL), "dd") || strcmp(cblistval(elems, 4, NULL), "")){
+ cblistclose(elems);
+ fprintf(stderr, "%s: cbsplit is invalid\n", progname);
+ return 1;
+ }
+ cblistclose(elems);
+ if(cbstricmp("abc", "ABC") || !cbstricmp("abc", "abcd")){
+ fprintf(stderr, "%s: cbstricmp is invalid\n", progname);
+ return 1;
+ }
+ if(!cbstrfwmatch("abcd", "abc") || cbstrfwmatch("abc", "abcd")){
+ fprintf(stderr, "%s: cbstrfwmatch is invalid\n", progname);
+ return 1;
+ }
+ if(!cbstrfwimatch("abcd", "ABC") || cbstrfwmatch("abc", "ABCD")){
+ fprintf(stderr, "%s: cbstrfwimatch is invalid\n", progname);
+ return 1;
+ }
+ if(!cbstrbwmatch("dcba", "cba") || cbstrbwmatch("cba", "dcba")){
+ fprintf(stderr, "%s: cbstrbwmatch is invalid\n", progname);
+ return 1;
+ }
+ if(!cbstrbwimatch("dcba", "CBA") || cbstrbwimatch("cba", "DCBA")){
+ fprintf(stderr, "%s: cbstrbwimatch is invalid\n", progname);
+ return 1;
+ }
+ tmp = cbmemdup(" \r\n[Quick Database Manager]\r\n ", -1);
+ if(cbstrtoupper(tmp) != tmp || strcmp(tmp, " \r\n[QUICK DATABASE MANAGER]\r\n ")){
+ free(tmp);
+ fprintf(stderr, "%s: cbstrtoupper is invalid\n", progname);
+ return 1;
+ }
+ if(cbstrtolower(tmp) != tmp || strcmp(tmp, " \r\n[quick database manager]\r\n ")){
+ free(tmp);
+ fprintf(stderr, "%s: cbstrtolower is invalid\n", progname);
+ return 1;
+ }
+ if(cbstrtrim(tmp) != tmp || strcmp(tmp, "[quick database manager]")){
+ free(tmp);
+ fprintf(stderr, "%s: cbstrtrim is invalid\n", progname);
+ return 1;
+ }
+ if(cbstrsqzspc(tmp) != tmp || strcmp(tmp, "[quick database manager]")){
+ free(tmp);
+ fprintf(stderr, "%s: cbstrsqzspc is invalid\n", progname);
+ return 1;
+ }
+ cbstrcututf(tmp, 5);
+ if(cbstrcountutf(tmp) != 5){
+ free(tmp);
+ fprintf(stderr, "%s: cbstrcututf or cbstrcountutf is invalid\n", progname);
+ return 1;
+ }
+ free(tmp);
+ printfflush("ok\n");
+ printfflush("Checking encoding utilities ... ");
+ strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n<Love & Peace!>\n");
+ tmp = cbbaseencode(spbuf, -1);
+ orig = cbbasedecode(tmp, &osiz);
+ if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: Base64 encoding is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n<Love & Peace!>\n");
+ tmp = cbquoteencode(spbuf, -1);
+ orig = cbquotedecode(tmp, &osiz);
+ if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: quoted-printable encoding is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n<Love & Peace!>\n");
+ tmp = cbmimeencode(spbuf, "ISO-8859-1", TRUE);
+ orig = cbmimedecode(tmp, renc);
+ if(osiz != strlen(spbuf) || strcmp(orig, spbuf) || strcmp(renc, "ISO-8859-1")){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: MIME encoding is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ strcpy(spbuf, "\"He says...\r\n\"\"What PROGRAM are they watching?\"\"\"");
+ tmp = cbcsvunescape(spbuf);
+ orig = cbcsvescape(tmp);
+ if(strcmp(orig, spbuf)){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: CSV escaping is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ strcpy(spbuf, "&lt;Nuts&amp;Milk&gt; is &quot;very&quot; surfin&apos;!");
+ tmp = cbxmlunescape(spbuf);
+ orig = cbxmlescape(tmp);
+ if(strcmp(orig, spbuf)){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: XML escaping is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ printfflush("ok\n");
+ printfflush("Checking date utilities ... ");
+ for(i = 0; i < 200; i++){
+ jl = (myrand() % 23) * 1800;
+ if(myrand() % 2 == 0) jl *= -1;
+ t = myrand() % (INT_MAX - 3600 * 24 * 365 * 6) + 3600 * 24 * 365 * 5;
+ tmp = cbdatestrwww(t, jl);
+ t = cbstrmktime(tmp);
+ orig = cbdatestrwww(t, jl);
+ if(strcmp(orig, tmp)){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: W3CDTF formatter is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ tmp = cbdatestrhttp(t, jl);
+ t = cbstrmktime(tmp);
+ orig = cbdatestrhttp(t, jl);
+ if(strcmp(orig, tmp)){
+ free(orig);
+ free(tmp);
+ fprintf(stderr, "%s: RFC 822 date formatter is invalid\n", progname);
+ return 1;
+ }
+ free(orig);
+ free(tmp);
+ }
+ printfflush("ok\n");
+ printfflush("Checking the global garbage collector ... ");
+ for(i = 0; i < 512; i++){
+ glist = cblistopen();
+ cbglobalgc(glist, (void (*)(void *))cblistclose);
+ for(j = 0; j < 10; j++){
+ sprintf(kbuf, "%08d", j);
+ cblistpush(glist, kbuf, -1);
+ }
+ gmap = cbmapopen();
+ cbglobalgc(gmap, (void (*)(void *))cbmapclose);
+ for(j = 0; j < 10; j++){
+ sprintf(kbuf, "%08d", j);
+ cbmapput(gmap, kbuf, -1, kbuf, -1, TRUE);
+ }
+ if(myrand() % 64 == 0){
+ cbvmemavail(100);
+ cbggcsweep();
+ }
+ }
+ printfflush("ok\n");
+ printfflush("all ok\n\n");
+ return 0;
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/configure b/qdbm/configure
new file mode 100755
index 00000000..60e3d2fa
--- /dev/null
+++ b/qdbm/configure
@@ -0,0 +1,3913 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59 for qdbm 1.8.77.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='qdbm'
+PACKAGE_TARNAME='qdbm'
+PACKAGE_VERSION='1.8.77'
+PACKAGE_STRING='qdbm 1.8.77'
+PACKAGE_BUGREPORT=''
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LIBVER LIBREV TARGETS MYDEFS MYOPTS MGWLIBS LD AR LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures qdbm 1.8.77 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of qdbm 1.8.77:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-debug build for debugging
+ --enable-devel build for development
+ --enable-stable build for stable release
+ --enable-pthread use POSIX thread and make APIs thread-safe
+ --disable-lock build for environments without file locking
+ --disable-mmap build for environments without memory mapping
+ --enable-zlib feature ZLIB for B+ tree and inverted index
+ --enable-lzo feature LZO for B+ tree and inverted index
+ --enable-bzip feature BZIP2 for B+ tree and inverted index
+ --enable-iconv feature ICONV utilities
+ --disable-warn hide warnings in the configuration
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+qdbm configure 1.8.77
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by qdbm $as_me 1.8.77, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Export variables
+LIBVER=14
+LIBREV=13
+TARGETS="all"
+MYDEFS=""
+MYOPTS=""
+MGWLIBS=""
+LD="ld"
+AR="ar"
+
+# Building paths
+pathtmp="$PATH"
+PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
+PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp"
+LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH"
+LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH"
+CPATH="$HOME/include:/usr/local/include:$CPATH"
+export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH
+
+
+
+#================================================================
+# Options
+#================================================================
+
+
+# Internal variables
+enables=""
+ispthread=""
+iszlib=""
+isiconv=""
+isnowarn=""
+
+# Debug mode
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+
+fi;
+if test "$enable_debug" = "yes"
+then
+ TARGETS="debug"
+ enables="$enables (debug)"
+fi
+
+# Developping mode
+# Check whether --enable-devel or --disable-devel was given.
+if test "${enable_devel+set}" = set; then
+ enableval="$enable_devel"
+
+fi;
+if test "$enable_devel" = "yes"
+then
+ TARGETS="devel"
+ enables="$enables (devel)"
+fi
+
+# Stable mode
+# Check whether --enable-stable or --disable-stable was given.
+if test "${enable_stable+set}" = set; then
+ enableval="$enable_stable"
+
+fi;
+if test "$enable_stable" = "yes"
+then
+ TARGETS="stable"
+ enables="$enables (stable)"
+fi
+
+# Enable POSIX thread
+# Check whether --enable-pthread or --disable-pthread was given.
+if test "${enable_pthread+set}" = set; then
+ enableval="$enable_pthread"
+
+fi;
+if test "$enable_pthread" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYPTHREAD"
+ enables="$enables (pthread)"
+ ispthread="yes"
+fi
+
+# Disable file locking
+# Check whether --enable-lock or --disable-lock was given.
+if test "${enable_lock+set}" = set; then
+ enableval="$enable_lock"
+
+fi;
+if test "$enable_lock" = "no"
+then
+ MYDEFS="$MYDEFS -DMYNOLOCK"
+ enables="$enables (no-lock)"
+fi
+
+# Disable memory mapping
+# Check whether --enable-mmap or --disable-mmap was given.
+if test "${enable_mmap+set}" = set; then
+ enableval="$enable_mmap"
+
+fi;
+if test "$enable_mmap" = "no"
+then
+ MYDEFS="$MYDEFS -DMYNOMMAP"
+ enables="$enables (no-mmap)"
+fi
+
+# Enable ZLIB compression
+# Check whether --enable-zlib or --disable-zlib was given.
+if test "${enable_zlib+set}" = set; then
+ enableval="$enable_zlib"
+
+fi;
+if test "$enable_zlib" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYZLIB"
+ MGWLIBS="-lz $MGWLIBS"
+ enables="$enables (zlib)"
+ iszlib="yes"
+fi
+
+# Enable LZO compression
+# Check whether --enable-lzo or --disable-lzo was given.
+if test "${enable_lzo+set}" = set; then
+ enableval="$enable_lzo"
+
+fi;
+if test "$enable_lzo" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYLZO"
+ MGWLIBS="-llzo2 $MGWLIBS"
+ enables="$enables (lzo)"
+ islzo="yes"
+fi
+
+# Enable BZIP2 compression
+# Check whether --enable-bzip or --disable-bzip was given.
+if test "${enable_bzip+set}" = set; then
+ enableval="$enable_bzip"
+
+fi;
+if test "$enable_bzip" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYBZIP"
+ MGWLIBS="-lbz2 $MGWLIBS"
+ enables="$enables (bzip)"
+ isbzip="yes"
+fi
+
+# Enable ICONV utilities
+# Check whether --enable-iconv or --disable-iconv was given.
+if test "${enable_iconv+set}" = set; then
+ enableval="$enable_iconv"
+
+fi;
+if test "$enable_iconv" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYICONV"
+ MGWLIBS="-liconv $MGWLIBS"
+ enables="$enables (iconv)"
+ isiconv="yes"
+fi
+
+# No warning configuration
+# Check whether --enable-warn or --disable-warn was given.
+if test "${enable_warn+set}" = set; then
+ enableval="$enable_warn"
+
+fi;
+if test "$enable_warn" = "no"
+then
+ isnowarn="yes"
+fi
+
+# Messages
+printf '#================================================================\n'
+printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables"
+printf '#================================================================\n'
+
+
+
+#================================================================
+# Checking Commands to Build with
+#================================================================
+
+
+# C compiler
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test "$GCC" != "yes"
+then
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: GCC is required to build this package.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+fi
+if uname | egrep -i 'Linux' > /dev/null 2>&1 &&
+ uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1
+then
+ MYOPTS="-minline-all-stringops"
+fi
+if uname | egrep -i 'SunOS' > /dev/null 2>&1
+then
+ MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr"
+fi
+if uname | egrep -i 'BSD' > /dev/null 2>&1
+then
+ MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr"
+fi
+if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1
+then
+ MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr"
+fi
+
+# Linker
+printf 'checking for ld... '
+if which ld | grep '/ld$' > /dev/null 2>&1
+then
+ LD=`which ld`
+ printf '%s\n' "$LD"
+else
+ printf 'no\n'
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: ld is not found in PATH.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+fi
+
+# Archiver
+printf 'checking for ar... '
+if which ar | grep '/ar$' > /dev/null 2>&1
+then
+ AR=`which ar`
+ printf '%s\n' "$AR"
+else
+ printf 'no\n'
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: ar is not found in PATH.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+fi
+
+
+
+#================================================================
+# Checking Libraries
+#================================================================
+
+
+# Underlying libraries
+
+
+echo "$as_me:$LINENO: checking for main in -lc" >&5
+echo $ECHO_N "checking for main in -lc... $ECHO_C" >&6
+if test "${ac_cv_lib_c_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_c_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_main" >&5
+echo "${ECHO_T}$ac_cv_lib_c_main" >&6
+if test $ac_cv_lib_c_main = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBC 1
+_ACEOF
+
+ LIBS="-lc $LIBS"
+
+fi
+
+
+# for pthread
+if test "$ispthread" = "yes"
+then
+
+echo "$as_me:$LINENO: checking for main in -lpthread" >&5
+echo $ECHO_N "checking for main in -lpthread... $ECHO_C" >&6
+if test "${ac_cv_lib_pthread_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_pthread_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_pthread_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_main" >&6
+if test $ac_cv_lib_pthread_main = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+ LIBS="-lpthread $LIBS"
+
+fi
+
+fi
+
+# for zlib
+if test "$iszlib" = "yes"
+then
+
+echo "$as_me:$LINENO: checking for main in -lz" >&5
+echo $ECHO_N "checking for main in -lz... $ECHO_C" >&6
+if test "${ac_cv_lib_z_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_z_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_z_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_z_main" >&5
+echo "${ECHO_T}$ac_cv_lib_z_main" >&6
+if test $ac_cv_lib_z_main = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
+
+ LIBS="-lz $LIBS"
+
+fi
+
+fi
+
+# for lzo
+if test "$islzo" = "yes"
+then
+
+echo "$as_me:$LINENO: checking for main in -llzo2" >&5
+echo $ECHO_N "checking for main in -llzo2... $ECHO_C" >&6
+if test "${ac_cv_lib_lzo2_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-llzo2 $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_lzo2_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_lzo2_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_lzo2_main" >&5
+echo "${ECHO_T}$ac_cv_lib_lzo2_main" >&6
+if test $ac_cv_lib_lzo2_main = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBLZO2 1
+_ACEOF
+
+ LIBS="-llzo2 $LIBS"
+
+fi
+
+fi
+
+# for bzip
+if test "$isbzip" = "yes"
+then
+
+echo "$as_me:$LINENO: checking for main in -lbz2" >&5
+echo $ECHO_N "checking for main in -lbz2... $ECHO_C" >&6
+if test "${ac_cv_lib_bz2_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbz2 $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_bz2_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_bz2_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_bz2_main" >&5
+echo "${ECHO_T}$ac_cv_lib_bz2_main" >&6
+if test $ac_cv_lib_bz2_main = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBBZ2 1
+_ACEOF
+
+ LIBS="-lbz2 $LIBS"
+
+fi
+
+fi
+
+# for iconv
+if test "$isiconv" = "yes"
+then
+
+echo "$as_me:$LINENO: checking for main in -liconv" >&5
+echo $ECHO_N "checking for main in -liconv... $ECHO_C" >&6
+if test "${ac_cv_lib_iconv_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-liconv $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_iconv_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_iconv_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_main" >&5
+echo "${ECHO_T}$ac_cv_lib_iconv_main" >&6
+if test $ac_cv_lib_iconv_main = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBICONV 1
+_ACEOF
+
+ LIBS="-liconv $LIBS"
+
+fi
+
+fi
+
+# For old BSDs
+if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null &&
+ test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a
+then
+ LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'`
+fi
+
+# Duplication of QDBM for C
+echo "$as_me:$LINENO: checking for main in -lqdbm" >&5
+echo $ECHO_N "checking for main in -lqdbm... $ECHO_C" >&6
+if test "${ac_cv_lib_qdbm_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lqdbm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_qdbm_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_qdbm_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_qdbm_main" >&5
+echo "${ECHO_T}$ac_cv_lib_qdbm_main" >&6
+if test $ac_cv_lib_qdbm_main = yes; then
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: The existing library was detected.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+
+fi
+
+
+
+
+#================================================================
+# Generic Settings
+#================================================================
+
+
+# Export variables
+
+
+
+
+
+
+
+
+
+
+
+# Targets
+ ac_config_files="$ac_config_files Makefile LTmakefile qdbm.spec qdbm.pc"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
+t quote
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output. A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by qdbm $as_me 1.8.77, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+qdbm config.status 1.8.77
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "LTmakefile" ) CONFIG_FILES="$CONFIG_FILES LTmakefile" ;;
+ "qdbm.spec" ) CONFIG_FILES="$CONFIG_FILES qdbm.spec" ;;
+ "qdbm.pc" ) CONFIG_FILES="$CONFIG_FILES qdbm.pc" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@LIBVER@,$LIBVER,;t t
+s,@LIBREV@,$LIBREV,;t t
+s,@TARGETS@,$TARGETS,;t t
+s,@MYDEFS@,$MYDEFS,;t t
+s,@MYOPTS@,$MYOPTS,;t t
+s,@MGWLIBS@,$MGWLIBS,;t t
+s,@LD@,$LD,;t t
+s,@AR@,$AR,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+# Messages
+printf '#================================================================\n'
+printf '# Ready to make.\n'
+printf '#================================================================\n'
+
+
+
+# END OF FILE
diff --git a/qdbm/configure.in b/qdbm/configure.in
new file mode 100644
index 00000000..9a6f4c40
--- /dev/null
+++ b/qdbm/configure.in
@@ -0,0 +1,312 @@
+# Source of configuration for QDBM
+
+
+
+#================================================================
+# Generic Settings
+#================================================================
+
+
+# Targets
+AC_INIT(qdbm, 1.8.77)
+
+# Export variables
+LIBVER=14
+LIBREV=13
+TARGETS="all"
+MYDEFS=""
+MYOPTS=""
+MGWLIBS=""
+LD="ld"
+AR="ar"
+
+# Building paths
+pathtmp="$PATH"
+PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
+PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp"
+LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH"
+LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH"
+CPATH="$HOME/include:/usr/local/include:$CPATH"
+export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH
+
+
+
+#================================================================
+# Options
+#================================================================
+
+
+# Internal variables
+enables=""
+ispthread=""
+iszlib=""
+isiconv=""
+isnowarn=""
+
+# Debug mode
+AC_ARG_ENABLE(debug,
+ AC_HELP_STRING([--enable-debug], [build for debugging]))
+if test "$enable_debug" = "yes"
+then
+ TARGETS="debug"
+ enables="$enables (debug)"
+fi
+
+# Developping mode
+AC_ARG_ENABLE(devel,
+ AC_HELP_STRING([--enable-devel], [build for development]))
+if test "$enable_devel" = "yes"
+then
+ TARGETS="devel"
+ enables="$enables (devel)"
+fi
+
+# Stable mode
+AC_ARG_ENABLE(stable,
+ AC_HELP_STRING([--enable-stable], [build for stable release]))
+if test "$enable_stable" = "yes"
+then
+ TARGETS="stable"
+ enables="$enables (stable)"
+fi
+
+# Enable POSIX thread
+AC_ARG_ENABLE(pthread,
+ AC_HELP_STRING([--enable-pthread], [use POSIX thread and make APIs thread-safe]))
+if test "$enable_pthread" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYPTHREAD"
+ enables="$enables (pthread)"
+ ispthread="yes"
+fi
+
+# Disable file locking
+AC_ARG_ENABLE(lock,
+ AC_HELP_STRING([--disable-lock], [build for environments without file locking]))
+if test "$enable_lock" = "no"
+then
+ MYDEFS="$MYDEFS -DMYNOLOCK"
+ enables="$enables (no-lock)"
+fi
+
+# Disable memory mapping
+AC_ARG_ENABLE(mmap,
+ AC_HELP_STRING([--disable-mmap], [build for environments without memory mapping]))
+if test "$enable_mmap" = "no"
+then
+ MYDEFS="$MYDEFS -DMYNOMMAP"
+ enables="$enables (no-mmap)"
+fi
+
+# Enable ZLIB compression
+AC_ARG_ENABLE(zlib,
+ AC_HELP_STRING([--enable-zlib], [feature ZLIB for B+ tree and inverted index]))
+if test "$enable_zlib" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYZLIB"
+ MGWLIBS="-lz $MGWLIBS"
+ enables="$enables (zlib)"
+ iszlib="yes"
+fi
+
+# Enable LZO compression
+AC_ARG_ENABLE(lzo,
+ AC_HELP_STRING([--enable-lzo], [feature LZO for B+ tree and inverted index]))
+if test "$enable_lzo" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYLZO"
+ MGWLIBS="-llzo2 $MGWLIBS"
+ enables="$enables (lzo)"
+ islzo="yes"
+fi
+
+# Enable BZIP2 compression
+AC_ARG_ENABLE(bzip,
+ AC_HELP_STRING([--enable-bzip], [feature BZIP2 for B+ tree and inverted index]))
+if test "$enable_bzip" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYBZIP"
+ MGWLIBS="-lbz2 $MGWLIBS"
+ enables="$enables (bzip)"
+ isbzip="yes"
+fi
+
+# Enable ICONV utilities
+AC_ARG_ENABLE(iconv,
+ AC_HELP_STRING([--enable-iconv], [feature ICONV utilities]))
+if test "$enable_iconv" = "yes"
+then
+ MYDEFS="$MYDEFS -DMYICONV"
+ MGWLIBS="-liconv $MGWLIBS"
+ enables="$enables (iconv)"
+ isiconv="yes"
+fi
+
+# No warning configuration
+AC_ARG_ENABLE(warn,
+ AC_HELP_STRING([--disable-warn], [hide warnings in the configuration]))
+if test "$enable_warn" = "no"
+then
+ isnowarn="yes"
+fi
+
+# Messages
+printf '#================================================================\n'
+printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables"
+printf '#================================================================\n'
+
+
+
+#================================================================
+# Checking Commands to Build with
+#================================================================
+
+
+# C compiler
+AC_PROG_CC
+if test "$GCC" != "yes"
+then
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: GCC is required to build this package.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+fi
+if uname | egrep -i 'Linux' > /dev/null 2>&1 &&
+ uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1
+then
+ MYOPTS="-minline-all-stringops"
+fi
+if uname | egrep -i 'SunOS' > /dev/null 2>&1
+then
+ MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr"
+fi
+if uname | egrep -i 'BSD' > /dev/null 2>&1
+then
+ MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr"
+fi
+if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1
+then
+ MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr"
+fi
+
+# Linker
+printf 'checking for ld... '
+if which ld | grep '/ld$' > /dev/null 2>&1
+then
+ LD=`which ld`
+ printf '%s\n' "$LD"
+else
+ printf 'no\n'
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: ld is not found in PATH.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+fi
+
+# Archiver
+printf 'checking for ar... '
+if which ar | grep '/ar$' > /dev/null 2>&1
+then
+ AR=`which ar`
+ printf '%s\n' "$AR"
+else
+ printf 'no\n'
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: ar is not found in PATH.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+fi
+
+
+
+#================================================================
+# Checking Libraries
+#================================================================
+
+
+# Underlying libraries
+AC_CHECK_LIB(c, main)
+
+# for pthread
+if test "$ispthread" = "yes"
+then
+ AC_CHECK_LIB(pthread, main)
+fi
+
+# for zlib
+if test "$iszlib" = "yes"
+then
+ AC_CHECK_LIB(z, main)
+fi
+
+# for lzo
+if test "$islzo" = "yes"
+then
+ AC_CHECK_LIB(lzo2, main)
+fi
+
+# for bzip
+if test "$isbzip" = "yes"
+then
+ AC_CHECK_LIB(bz2, main)
+fi
+
+# for iconv
+if test "$isiconv" = "yes"
+then
+ AC_CHECK_LIB(iconv, main)
+fi
+
+# For old BSDs
+if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null &&
+ test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a
+then
+ LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'`
+fi
+
+# Duplication of QDBM for C
+AC_CHECK_LIB(qdbm, main,
+ if test "$isnowarn" != "yes"
+ then
+ printf '#================================================================\n' 1>&2
+ printf '# WARNING: The existing library was detected.\n' 1>&2
+ printf '#================================================================\n' 1>&2
+ fi
+)
+
+
+
+#================================================================
+# Generic Settings
+#================================================================
+
+
+# Export variables
+AC_SUBST(LIBVER)
+AC_SUBST(LIBREV)
+AC_SUBST(TARGETS)
+AC_SUBST(MYDEFS)
+AC_SUBST(MYOPTS)
+AC_SUBST(MGWLIBS)
+AC_SUBST(LD)
+AC_SUBST(AR)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+
+# Targets
+AC_OUTPUT(Makefile LTmakefile qdbm.spec qdbm.pc)
+
+# Messages
+printf '#================================================================\n'
+printf '# Ready to make.\n'
+printf '#================================================================\n'
+
+
+
+# END OF FILE
diff --git a/qdbm/crmgr.c b/qdbm/crmgr.c
new file mode 100644
index 00000000..8d9baf34
--- /dev/null
+++ b/qdbm/crmgr.c
@@ -0,0 +1,956 @@
+/*************************************************************************************************
+ * Utility for debugging Curia and its applications
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#include <depot.h>
+#include <curia.h>
+#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef TRUE
+#define TRUE 1 /* boolean true */
+#undef FALSE
+#define FALSE 0 /* boolean false */
+
+#define ALIGNSIZ 32 /* basic size of alignment */
+
+
+/* for RISC OS */
+#if defined(__riscos__) || defined(__riscos)
+#include <unixlib/local.h>
+int __riscosify_control = __RISCOSIFY_NO_PROCESS;
+#endif
+
+
+/* global variables */
+const char *progname; /* program name */
+
+
+/* function prototypes */
+int main(int argc, char **argv);
+void usage(void);
+char *hextoobj(const char *str, int *sp);
+char *dectoiobj(const char *str, int *sp);
+int runcreate(int argc, char **argv);
+int runput(int argc, char **argv);
+int runout(int argc, char **argv);
+int runget(int argc, char **argv);
+int runlist(int argc, char **argv);
+int runoptimize(int argc, char **argv);
+int runinform(int argc, char **argv);
+int runremove(int argc, char **argv);
+int runrepair(int argc, char **argv);
+int runexportdb(int argc, char **argv);
+int runimportdb(int argc, char **argv);
+int runsnaffle(int argc, char **argv);
+void pdperror(const char *name);
+void printobj(const char *obj, int size);
+void printobjhex(const char *obj, int size);
+int docreate(const char *name, int bnum, int dnum, int sparse);
+int doput(const char *name, const char *kbuf, int ksiz,
+ const char *vbuf, int vsiz, int dmode, int lob, int align);
+int doout(const char *name, const char *kbuf, int ksiz, int lob);
+int doget(const char *name, int opts, const char *kbuf, int ksiz,
+ int start, int max, int ox, int lob, int nb);
+int dolist(const char *name, int opts, int kb, int vb, int ox);
+int dooptimize(const char *name, int bnum, int align);
+int doinform(const char *name, int opts);
+int doremove(const char *name);
+int dorepair(const char *name);
+int doexportdb(const char *name, const char *dir);
+int doimportdb(const char *name, const char *dir, int bnum, int dnum);
+int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb);
+
+
+/* main routine */
+int main(int argc, char **argv){
+ char *env;
+ int rv;
+ cbstdiobin();
+ progname = argv[0];
+ if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env);
+ if(argc < 2) usage();
+ rv = 0;
+ if(!strcmp(argv[1], "create")){
+ rv = runcreate(argc, argv);
+ } else if(!strcmp(argv[1], "put")){
+ rv = runput(argc, argv);
+ } else if(!strcmp(argv[1], "out")){
+ rv = runout(argc, argv);
+ } else if(!strcmp(argv[1], "get")){
+ rv = runget(argc, argv);
+ } else if(!strcmp(argv[1], "list")){
+ rv = runlist(argc, argv);
+ } else if(!strcmp(argv[1], "optimize")){
+ rv = runoptimize(argc, argv);
+ } else if(!strcmp(argv[1], "inform")){
+ rv = runinform(argc, argv);
+ } else if(!strcmp(argv[1], "remove")){
+ rv = runremove(argc, argv);
+ } else if(!strcmp(argv[1], "repair")){
+ rv = runrepair(argc, argv);
+ } else if(!strcmp(argv[1], "exportdb")){
+ rv = runexportdb(argc, argv);
+ } else if(!strcmp(argv[1], "importdb")){
+ rv = runimportdb(argc, argv);
+ } else if(!strcmp(argv[1], "snaffle")){
+ rv = runsnaffle(argc, argv);
+ } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){
+ printf("Powered by QDBM version %s on %s%s\n",
+ dpversion, dpsysname, dpisreentrant ? " (reentrant)" : "");
+ printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n");
+ rv = 0;
+ } else {
+ usage();
+ }
+ return rv;
+}
+
+
+/* print the usage and exit */
+void usage(void){
+ fprintf(stderr, "%s: administration utility for Curia\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " %s create [-s] [-bnum num] [-dnum num] name\n", progname);
+ fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] "
+ "name key val\n", progname);
+ fprintf(stderr, " %s out [-kx|-ki] [-lob] name key\n", progname);
+ fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key\n",
+ progname);
+ fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname);
+ fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname);
+ fprintf(stderr, " %s inform [-nl] name\n", progname);
+ fprintf(stderr, " %s remove name\n", progname);
+ fprintf(stderr, " %s repair name\n", progname);
+ fprintf(stderr, " %s exportdb name dir\n", progname);
+ fprintf(stderr, " %s importdb [-bnum num] [-dnum num] name dir\n", progname);
+ fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname);
+ fprintf(stderr, " %s version\n", progname);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+
+/* create a binary object from a hexadecimal string */
+char *hextoobj(const char *str, int *sp){
+ char *buf, mbuf[3];
+ int len, i, j;
+ len = strlen(str);
+ if(!(buf = malloc(len + 1))) return NULL;
+ j = 0;
+ for(i = 0; i < len; i += 2){
+ while(strchr(" \n\r\t\f\v", str[i])){
+ i++;
+ }
+ if((mbuf[0] = str[i]) == '\0') break;
+ if((mbuf[1] = str[i+1]) == '\0') break;
+ mbuf[2] = '\0';
+ buf[j++] = (char)strtol(mbuf, NULL, 16);
+ }
+ buf[j] = '\0';
+ *sp = j;
+ return buf;
+}
+
+
+/* create a integer object from a decimal string */
+char *dectoiobj(const char *str, int *sp){
+ char *buf;
+ int num;
+ num = atoi(str);
+ if(!(buf = malloc(sizeof(int)))) return NULL;
+ *(int *)buf = num;
+ *sp = sizeof(int);
+ return buf;
+}
+
+
+/* parse arguments of create command */
+int runcreate(int argc, char **argv){
+ char *name;
+ int i, sb, bnum, dnum, rv;
+ name = NULL;
+ sb = FALSE;
+ bnum = -1;
+ dnum = -1;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-s")){
+ sb = TRUE;
+ } else if(!strcmp(argv[i], "-bnum")){
+ if(++i >= argc) usage();
+ bnum = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-dnum")){
+ if(++i >= argc) usage();
+ dnum = atoi(argv[i]);
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = docreate(name, bnum, dnum, sb);
+ return rv;
+}
+
+
+/* parse arguments of put command */
+int runput(int argc, char **argv){
+ char *name, *key, *val, *kbuf, *vbuf;
+ int i, kx, ki, vx, vi, vf, lob, ksiz, vsiz, align, rv;
+ int dmode;
+ name = NULL;
+ kx = FALSE;
+ ki = FALSE;
+ vx = FALSE;
+ vi = FALSE;
+ vf = FALSE;
+ lob = FALSE;
+ align = ALIGNSIZ;
+ key = NULL;
+ val = NULL;
+ dmode = CR_DOVER;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-kx")){
+ kx = TRUE;
+ } else if(!strcmp(argv[i], "-ki")){
+ ki = TRUE;
+ } else if(!strcmp(argv[i], "-vx")){
+ vx = TRUE;
+ } else if(!strcmp(argv[i], "-vi")){
+ vi = TRUE;
+ } else if(!strcmp(argv[i], "-vf")){
+ vf = TRUE;
+ } else if(!strcmp(argv[i], "-keep")){
+ dmode = CR_DKEEP;
+ } else if(!strcmp(argv[i], "-cat")){
+ dmode = CR_DCAT;
+ } else if(!strcmp(argv[i], "-lob")){
+ lob = TRUE;
+ } else if(!strcmp(argv[i], "-na")){
+ align = 0;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!key){
+ key = argv[i];
+ } else if(!val){
+ val = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !key || !val) usage();
+ if(kx){
+ kbuf = hextoobj(key, &ksiz);
+ } else if(ki){
+ kbuf = dectoiobj(key, &ksiz);
+ } else {
+ kbuf = cbmemdup(key, -1);
+ ksiz = -1;
+ }
+ if(vx){
+ vbuf = hextoobj(val, &vsiz);
+ } else if(vi){
+ vbuf = dectoiobj(val, &vsiz);
+ } else if(vf){
+ vbuf = cbreadfile(val, &vsiz);
+ } else {
+ vbuf = cbmemdup(val, -1);
+ vsiz = -1;
+ }
+ if(kbuf && vbuf){
+ rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, lob, align);
+ } else {
+ if(vf){
+ fprintf(stderr, "%s: %s: cannot read\n", progname, val);
+ } else {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ }
+ rv = 1;
+ }
+ free(kbuf);
+ free(vbuf);
+ return rv;
+}
+
+
+/* parse arguments of out command */
+int runout(int argc, char **argv){
+ char *name, *key, *kbuf;
+ int i, kx, ki, lob, ksiz, rv;
+ name = NULL;
+ kx = FALSE;
+ ki = FALSE;
+ lob = FALSE;
+ key = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-kx")){
+ kx = TRUE;
+ } else if(!strcmp(argv[i], "-ki")){
+ ki = TRUE;
+ } else if(!strcmp(argv[i], "-lob")){
+ lob = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!key){
+ key = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !key) usage();
+ if(kx){
+ kbuf = hextoobj(key, &ksiz);
+ } else if(ki){
+ kbuf = dectoiobj(key, &ksiz);
+ } else {
+ kbuf = cbmemdup(key, -1);
+ ksiz = -1;
+ }
+ if(kbuf){
+ rv = doout(name, kbuf, ksiz, lob);
+ } else {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ rv = 1;
+ }
+ free(kbuf);
+ return rv;
+}
+
+
+/* parse arguments of get command */
+int runget(int argc, char **argv){
+ char *name, *key, *kbuf;
+ int i, opts, kx, ki, ox, lob, nb, start, max, ksiz, rv;
+ name = NULL;
+ opts = 0;
+ kx = FALSE;
+ ki = FALSE;
+ ox = FALSE;
+ lob = FALSE;
+ nb = FALSE;
+ start = 0;
+ max = -1;
+ key = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-nl")){
+ opts |= CR_ONOLCK;
+ } else if(!strcmp(argv[i], "-kx")){
+ kx = TRUE;
+ } else if(!strcmp(argv[i], "-ki")){
+ ki = TRUE;
+ } else if(!strcmp(argv[i], "-ox")){
+ ox = TRUE;
+ } else if(!strcmp(argv[i], "-lob")){
+ lob = TRUE;
+ } else if(!strcmp(argv[i], "-n")){
+ nb = TRUE;
+ } else if(!strcmp(argv[i], "-start")){
+ if(++i >= argc) usage();
+ start = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-max")){
+ if(++i >= argc) usage();
+ max = atoi(argv[i]);
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!key){
+ key = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !key || start < 0) usage();
+ if(kx){
+ kbuf = hextoobj(key, &ksiz);
+ } else if(ki){
+ kbuf = dectoiobj(key, &ksiz);
+ } else {
+ kbuf = cbmemdup(key, -1);
+ ksiz = -1;
+ }
+ if(kbuf){
+ rv = doget(name, opts, kbuf, ksiz, start, max, ox, lob, nb);
+ } else {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ rv = 1;
+ }
+ free(kbuf);
+ return rv;
+}
+
+
+/* parse arguments of list command */
+int runlist(int argc, char **argv){
+ char *name;
+ int i, opts, kb, vb, ox, rv;
+ name = NULL;
+ opts = 0;
+ kb = FALSE;
+ vb = FALSE;
+ ox = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-nl")){
+ opts |= CR_ONOLCK;
+ } else if(!strcmp(argv[i], "-k")){
+ kb = TRUE;
+ } else if(!strcmp(argv[i], "-v")){
+ vb = TRUE;
+ } else if(!strcmp(argv[i], "-ox")){
+ ox = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = dolist(name, opts, kb, vb, ox);
+ return rv;
+}
+
+
+/* parse arguments of optimize command */
+int runoptimize(int argc, char **argv){
+ char *name;
+ int i, bnum, align, rv;
+ name = NULL;
+ bnum = -1;
+ align = ALIGNSIZ;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-bnum")){
+ if(++i >= argc) usage();
+ bnum = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-na")){
+ align = 0;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = dooptimize(name, bnum, align);
+ return rv;
+}
+
+
+/* parse arguments of inform command */
+int runinform(int argc, char **argv){
+ char *name;
+ int i, opts, rv;
+ name = NULL;
+ opts = 0;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-nl")){
+ opts |= CR_ONOLCK;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = doinform(name, opts);
+ return rv;
+}
+
+
+/* parse arguments of remove command */
+int runremove(int argc, char **argv){
+ char *name;
+ int i, rv;
+ name = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ usage();
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = doremove(name);
+ return rv;
+}
+
+
+/* parse arguments of repair command */
+int runrepair(int argc, char **argv){
+ char *name;
+ int i, rv;
+ name = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ usage();
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = dorepair(name);
+ return rv;
+}
+
+
+/* parse arguments of exportdb command */
+int runexportdb(int argc, char **argv){
+ char *name, *dir;
+ int i, rv;
+ name = NULL;
+ dir = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ usage();
+ } else if(!name){
+ name = argv[i];
+ } else if(!dir){
+ dir = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !dir) usage();
+ rv = doexportdb(name, dir);
+ return rv;
+}
+
+
+/* parse arguments of importdb command */
+int runimportdb(int argc, char **argv){
+ char *name, *dir;
+ int i, bnum, dnum, rv;
+ name = NULL;
+ dir = NULL;
+ bnum = -1;
+ dnum = -1;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-bnum")){
+ if(++i >= argc) usage();
+ bnum = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-dnum")){
+ if(++i >= argc) usage();
+ dnum = atoi(argv[i]);
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!dir){
+ dir = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !dir) usage();
+ rv = doimportdb(name, dir, bnum, dnum);
+ return rv;
+}
+
+
+/* parse arguments of snaffle command */
+int runsnaffle(int argc, char **argv){
+ char *name, *key, *kbuf;
+ int i, kx, ki, ox, nb, start, max, ksiz, rv;
+ name = NULL;
+ kx = FALSE;
+ ki = FALSE;
+ ox = FALSE;
+ nb = FALSE;
+ start = 0;
+ max = -1;
+ key = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-kx")){
+ kx = TRUE;
+ } else if(!strcmp(argv[i], "-ki")){
+ ki = TRUE;
+ } else if(!strcmp(argv[i], "-ox")){
+ ox = TRUE;
+ } else if(!strcmp(argv[i], "-n")){
+ nb = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!key){
+ key = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !key || start < 0) usage();
+ if(kx){
+ kbuf = hextoobj(key, &ksiz);
+ } else if(ki){
+ kbuf = dectoiobj(key, &ksiz);
+ } else {
+ kbuf = cbmemdup(key, -1);
+ ksiz = -1;
+ }
+ if(kbuf){
+ rv = dosnaffle(name, kbuf, ksiz, ox, nb);
+ } else {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ rv = 1;
+ }
+ free(kbuf);
+ return rv;
+}
+
+
+/* print an error message */
+void pdperror(const char *name){
+ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode));
+}
+
+
+/* print an object */
+void printobj(const char *obj, int size){
+ int i;
+ for(i = 0; i < size; i++){
+ putchar(obj[i]);
+ }
+}
+
+
+/* print an object as a hexadecimal string */
+void printobjhex(const char *obj, int size){
+ int i;
+ for(i = 0; i < size; i++){
+ printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]);
+ }
+}
+
+
+/* perform create command */
+int docreate(const char *name, int bnum, int dnum, int sparse){
+ CURIA *curia;
+ int omode;
+ omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0);
+ if(!(curia = cropen(name, omode, bnum, dnum))){
+ pdperror(name);
+ return 1;
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform put command */
+int doput(const char *name, const char *kbuf, int ksiz,
+ const char *vbuf, int vsiz, int dmode, int lob, int align){
+ CURIA *curia;
+ if(!(curia = cropen(name, CR_OWRITER, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ if(align > 0 && !crsetalign(curia, ALIGNSIZ)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ if(lob){
+ if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, dmode)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ } else {
+ if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform out command */
+int doout(const char *name, const char *kbuf, int ksiz, int lob){
+ CURIA *curia;
+ if(!(curia = cropen(name, CR_OWRITER, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ if(lob){
+ if(!croutlob(curia, kbuf, ksiz)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ } else {
+ if(!crout(curia, kbuf, ksiz)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform get command */
+int doget(const char *name, int opts, const char *kbuf, int ksiz,
+ int start, int max, int ox, int lob, int nb){
+ CURIA *curia;
+ char *vbuf;
+ int vsiz;
+ if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ if(lob){
+ if(!(vbuf = crgetlob(curia, kbuf, ksiz, start, max, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ } else {
+ if(!(vbuf = crget(curia, kbuf, ksiz, start, max, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ if(ox){
+ printobjhex(vbuf, vsiz);
+ } else {
+ printobj(vbuf, vsiz);
+ }
+ free(vbuf);
+ if(!nb) putchar('\n');
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform list command */
+int dolist(const char *name, int opts, int kb, int vb, int ox){
+ CURIA *curia;
+ char *kbuf, *vbuf;
+ int ksiz, vsiz;
+ if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ criterinit(curia);
+ while((kbuf = criternext(curia, &ksiz)) != NULL){
+ if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){
+ pdperror(name);
+ free(kbuf);
+ break;
+ }
+ if(ox){
+ if(!vb) printobjhex(kbuf, ksiz);
+ if(!kb && !vb) putchar('\t');
+ if(!kb) printobjhex(vbuf, vsiz);
+ } else {
+ if(!vb) printobj(kbuf, ksiz);
+ if(!kb && !vb) putchar('\t');
+ if(!kb) printobj(vbuf, vsiz);
+ }
+ putchar('\n');
+ free(vbuf);
+ free(kbuf);
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform optimize command */
+int dooptimize(const char *name, int bnum, int align){
+ CURIA *curia;
+ if(!(curia = cropen(name, CR_OWRITER, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ if(align > 0 && !crsetalign(curia, ALIGNSIZ)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ if(!croptimize(curia, bnum)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform inform command */
+int doinform(const char *name, int opts){
+ CURIA *curia;
+ if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ printf("name: %s\n", crname(curia));
+ printf("file size: %.0f\n", crfsizd(curia));
+ printf("all buckets: %d\n", crbnum(curia));
+ printf("used buckets: %d\n", crbusenum(curia));
+ printf("records: %d\n", crrnum(curia));
+ printf("inode number: %d\n", crinode(curia));
+ printf("modified time: %.0f\n", (double)crmtime(curia));
+ printf("LOB records: %d\n", crrnumlob(curia));
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform remove command */
+int doremove(const char *name){
+ if(!crremove(name)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform repair command */
+int dorepair(const char *name){
+ if(!crrepair(name)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform exportdb command */
+int doexportdb(const char *name, const char *dir){
+ CURIA *curia;
+ if(!(curia = cropen(name, CR_OREADER, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ if(!crexportdb(curia, dir)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform importdb command */
+int doimportdb(const char *name, const char *dir, int bnum, int dnum){
+ CURIA *curia;
+ if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){
+ pdperror(name);
+ return 1;
+ }
+ if(!crimportdb(curia, dir)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* perform snaffle command */
+int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){
+ char *vbuf;
+ int vsiz;
+ if(!(vbuf = crsnaffle(name, kbuf, ksiz, &vsiz))){
+ pdperror(name);
+ return 1;
+ }
+ if(ox){
+ printobjhex(vbuf, vsiz);
+ } else {
+ printobj(vbuf, vsiz);
+ }
+ free(vbuf);
+ if(!nb) putchar('\n');
+ return 0;
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/crtest.c b/qdbm/crtest.c
new file mode 100644
index 00000000..6239841b
--- /dev/null
+++ b/qdbm/crtest.c
@@ -0,0 +1,873 @@
+/*************************************************************************************************
+ * Test cases of Curia
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#include <depot.h>
+#include <curia.h>
+#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <time.h>
+
+#undef TRUE
+#define TRUE 1 /* boolean true */
+#undef FALSE
+#define FALSE 0 /* boolean false */
+
+#define RECBUFSIZ 32 /* buffer for records */
+
+
+/* for RISC OS */
+#if defined(__riscos__) || defined(__riscos)
+#include <unixlib/local.h>
+int __riscosify_control = __RISCOSIFY_NO_PROCESS;
+#endif
+
+
+/* global variables */
+const char *progname; /* program name */
+
+
+/* function prototypes */
+int main(int argc, char **argv);
+void usage(void);
+int runwrite(int argc, char **argv);
+int runread(int argc, char **argv);
+int runrcat(int argc, char **argv);
+int runcombo(int argc, char **argv);
+int runwicked(int argc, char **argv);
+int printfflush(const char *format, ...);
+void pdperror(const char *name);
+int myrand(void);
+int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob);
+int doread(const char *name, int wb, int lob);
+int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum,
+ int align, int fbpsiz, int cb);
+int docombo(const char *name);
+int dowicked(const char *name, int rnum, int cb);
+
+
+/* main routine */
+int main(int argc, char **argv){
+ char *env;
+ int rv;
+ cbstdiobin();
+ if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env);
+ progname = argv[0];
+ if(argc < 2) usage();
+ rv = 0;
+ if(!strcmp(argv[1], "write")){
+ rv = runwrite(argc, argv);
+ } else if(!strcmp(argv[1], "read")){
+ rv = runread(argc, argv);
+ } else if(!strcmp(argv[1], "rcat")){
+ rv = runrcat(argc, argv);
+ } else if(!strcmp(argv[1], "combo")){
+ rv = runcombo(argc, argv);
+ } else if(!strcmp(argv[1], "wicked")){
+ rv = runwicked(argc, argv);
+ } else {
+ usage();
+ }
+ return rv;
+}
+
+
+/* print the usage and exit */
+void usage(void){
+ fprintf(stderr, "%s: test cases for Curia\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " %s write [-s] [-lob] name rnum bnum dnum\n", progname);
+ fprintf(stderr, " %s read [-wb] [-lob] name\n", progname);
+ fprintf(stderr, " %s rcat [-c] name rnum bnum dnum pnum align fbpsiz\n", progname);
+ fprintf(stderr, " %s combo name\n", progname);
+ fprintf(stderr, " %s wicked [-c] name rnum\n", progname);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+
+/* parse arguments of write command */
+int runwrite(int argc, char **argv){
+ char *name, *rstr, *bstr, *dstr;
+ int i, rnum, bnum, dnum, sb, lob, rv;
+ name = NULL;
+ rstr = NULL;
+ bstr = NULL;
+ dstr = NULL;
+ rnum = 0;
+ bnum = 0;
+ dnum = 0;
+ sb = FALSE;
+ lob = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-s")){
+ sb = TRUE;
+ } else if(!strcmp(argv[i], "-lob")){
+ lob = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!rstr){
+ rstr = argv[i];
+ } else if(!bstr){
+ bstr = argv[i];
+ } else if(!dstr){
+ dstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !rstr || !bstr || !dstr) usage();
+ rnum = atoi(rstr);
+ bnum = atoi(bstr);
+ dnum = atoi(dstr);
+ if(rnum < 1 || bnum < 1 || dnum < 1) usage();
+ rv = dowrite(name, rnum, bnum, dnum, sb, lob);
+ return rv;
+}
+
+
+/* parse arguments of read command */
+int runread(int argc, char **argv){
+ char *name;
+ int i, wb, lob, rv;
+ name = NULL;
+ wb = FALSE;
+ lob = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-wb")){
+ wb = TRUE;
+ } else if(!strcmp(argv[i], "-lob")){
+ lob = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = doread(name, wb, lob);
+ return rv;
+}
+
+
+/* parse arguments of rcat command */
+int runrcat(int argc, char **argv){
+ char *name, *rstr, *bstr, *dstr, *pstr, *astr, *fstr;
+ int i, rnum, bnum, dnum, pnum, align, fbpsiz, cb, rv;
+ name = NULL;
+ rstr = NULL;
+ bstr = NULL;
+ dstr = NULL;
+ pstr = NULL;
+ astr = NULL;
+ fstr = NULL;
+ rnum = 0;
+ bnum = 0;
+ pnum = 0;
+ align = 0;
+ fbpsiz = 0;
+ cb = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-c")){
+ cb = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!rstr){
+ rstr = argv[i];
+ } else if(!bstr){
+ bstr = argv[i];
+ } else if(!dstr){
+ dstr = argv[i];
+ } else if(!pstr){
+ pstr = argv[i];
+ } else if(!astr){
+ astr = argv[i];
+ } else if(!fstr){
+ fstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !rstr || !bstr || !dstr || !pstr || !astr || !fstr) usage();
+ rnum = atoi(rstr);
+ bnum = atoi(bstr);
+ dnum = atoi(dstr);
+ pnum = atoi(pstr);
+ align = atoi(astr);
+ fbpsiz = atoi(fstr);
+ if(rnum < 1 || bnum < 1 || dnum < 1 || pnum < 1 || fbpsiz < 0) usage();
+ rv = dorcat(name, rnum, bnum, dnum, pnum, align, fbpsiz, cb);
+ return rv;
+}
+
+
+/* parse arguments of combo command */
+int runcombo(int argc, char **argv){
+ char *name;
+ int i, rv;
+ name = NULL;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ usage();
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = docombo(name);
+ return rv;
+}
+
+
+/* parse arguments of wicked command */
+int runwicked(int argc, char **argv){
+ char *name, *rstr;
+ int i, rnum, cb, rv;
+ name = NULL;
+ rstr = NULL;
+ rnum = 0;
+ cb = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-c")){
+ cb = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else if(!rstr){
+ rstr = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name || !rstr) usage();
+ rnum = atoi(rstr);
+ if(rnum < 1) usage();
+ rv = dowicked(name, rnum, cb);
+ return rv;
+}
+
+
+/* print formatted string and flush the buffer */
+int printfflush(const char *format, ...){
+ va_list ap;
+ int rv;
+ va_start(ap, format);
+ rv = vprintf(format, ap);
+ if(fflush(stdout) == EOF) rv = -1;
+ va_end(ap);
+ return rv;
+}
+
+
+/* print an error message */
+void pdperror(const char *name){
+ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode));
+}
+
+
+/* pseudo random number generator */
+int myrand(void){
+ static int cnt = 0;
+ if(cnt == 0) srand(time(NULL));
+ return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX;
+}
+
+
+/* perform write command */
+int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob){
+ CURIA *curia;
+ int i, omode, err, len;
+ char buf[RECBUFSIZ];
+ printfflush("<Writing Test>\n name=%s rnum=%d bnum=%d dnum=%d s=%d lob=%d\n\n",
+ name, rnum, bnum, dnum, sparse, lob);
+ /* open a database */
+ omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0);
+ if(!(curia = cropen(name, omode, bnum, dnum))){
+ pdperror(name);
+ return 1;
+ }
+ err = FALSE;
+ /* loop for each record */
+ for(i = 1; i <= rnum; i++){
+ /* store a record */
+ len = sprintf(buf, "%08d", i);
+ if(lob){
+ if(!crputlob(curia, buf, len, buf, len, CR_DOVER)){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ } else {
+ if(!crput(curia, buf, len, buf, len, CR_DOVER)){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ }
+ /* print progression */
+ if(rnum > 250 && i % (rnum / 250) == 0){
+ putchar('.');
+ fflush(stdout);
+ if(i == rnum || i % (rnum / 10) == 0){
+ printfflush(" (%08d)\n", i);
+ }
+ }
+ }
+ /* close the database */
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ if(!err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform read command */
+int doread(const char *name, int wb, int lob){
+ CURIA *curia;
+ int i, rnum, err, len;
+ char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val;
+ printfflush("<Reading Test>\n name=%s wb=%d lob=%d\n\n", name, wb, lob);
+ /* open a database */
+ if(!(curia = cropen(name, CR_OREADER, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ /* get the number of records */
+ if(lob){
+ rnum = crrnumlob(curia);
+ } else {
+ rnum = crrnum(curia);
+ }
+ err = FALSE;
+ /* loop for each record */
+ for(i = 1; i <= rnum; i++){
+ /* retrieve a record */
+ len = sprintf(buf, "%08d", i);
+ if(lob){
+ if(!(val = crgetlob(curia, buf, len, 0, -1, NULL))){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ free(val);
+ } else if(wb){
+ if(crgetwb(curia, buf, len, 0, RECBUFSIZ, vbuf) == -1){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ } else {
+ if(!(val = crget(curia, buf, len, 0, -1, NULL))){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ free(val);
+ }
+ /* print progression */
+ if(rnum > 250 && i % (rnum / 250) == 0){
+ putchar('.');
+ fflush(stdout);
+ if(i == rnum || i % (rnum / 10) == 0){
+ printfflush(" (%08d)\n", i);
+ }
+ }
+ }
+ /* close the database */
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ if(!err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform rcat command */
+int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum,
+ int align, int fbpsiz, int cb){
+ CURIA *curia;
+ CBMAP *map;
+ int i, err, len, ksiz, vsiz, rsiz;
+ const char *kbuf, *vbuf;
+ char buf[RECBUFSIZ], *rbuf;
+ printfflush("<Random Writing Test>\n name=%s rnum=%d bnum=%d dnum=%d pnum=%d"
+ " align=%d fbpsiz=%d c=%d\n\n", name, rnum, bnum, dnum, pnum, align, fbpsiz, cb);
+ if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){
+ pdperror(name);
+ return 1;
+ }
+ if(!crsetalign(curia, align) || !crsetfbpsiz(curia, fbpsiz)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ map = NULL;
+ if(cb) map = cbmapopen();
+ err = FALSE;
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", myrand() % pnum + 1);
+ if(!crput(curia, buf, len, buf, len, CR_DCAT)){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ if(rnum > 250 && i % (rnum / 250) == 0){
+ putchar('.');
+ fflush(stdout);
+ if(i == rnum || i % (rnum / 10) == 0){
+ printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, crfsiz(curia), crrnum(curia));
+ }
+ }
+ }
+ if(map){
+ printfflush("Matching records ... ");
+ cbmapiterinit(map);
+ while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
+ vbuf = cbmapget(map, kbuf, ksiz, &vsiz);
+ if(!(rbuf = crget(curia, kbuf, ksiz, 0, -1, &rsiz))){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
+ fprintf(stderr, "%s: %s: unmatched record\n", progname, name);
+ free(rbuf);
+ err = TRUE;
+ break;
+ }
+ free(rbuf);
+ }
+ cbmapclose(map);
+ if(!err) printfflush("ok\n");
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ if(!err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+/* perform combo command */
+int docombo(const char *name){
+ CURIA *curia;
+ char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf;
+ int i, len, wlen, vsiz;
+ printfflush("<Combination Test>\n name=%s\n\n", name);
+ printfflush("Creating a database with bnum 3 ... ");
+ if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, 3, 3))){
+ pdperror(name);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Setting alignment as 16 ... ");
+ if(!crsetalign(curia, 16)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Adding 20 records ... ");
+ for(i = 1; i <= 20; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!crput(curia, buf, len, buf, len, CR_DOVER)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Checking records ... ");
+ for(i = 1; i <= 20; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ free(vbuf);
+ if(vsiz != crvsiz(curia, buf, len)){
+ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Overwriting top 10 records without moving rooms ... ");
+ for(i = 1; i <= 10; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!crput(curia, buf, len, buf, len, CR_DOVER)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Overwriting top 5 records with moving rooms ... ");
+ for(i = 1; i <= 5; i++){
+ len = sprintf(buf, "%08d", i);
+ wlen = sprintf(wbuf, "%024d", i);
+ if(!crput(curia, buf, len, wbuf, wlen, CR_DOVER)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Overwriting top 15 records in concatenation with moving rooms ... ");
+ for(i = 1; i <= 15; i++){
+ len = sprintf(buf, "%08d", i);
+ wlen = sprintf(wbuf, "========================");
+ if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Checking records ... ");
+ for(i = 1; i <= 20; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ free(vbuf);
+ if(vsiz != crvsiz(curia, buf, len)){
+ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Deleting top 10 records ... ");
+ for(i = 1; i <= 10; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!crout(curia, buf, len)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Checking deleted records ... ");
+ for(i = 1; i <= 10; i++){
+ len = sprintf(buf, "%08d", i);
+ vbuf = crget(curia, buf, len, 0, -1, &vsiz);
+ free(vbuf);
+ if(vbuf || dpecode != DP_ENOITEM){
+ fprintf(stderr, "%s: %s: deleting failed\n", progname, name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Overwriting top 15 records in concatenation with moving rooms ... ");
+ for(i = 1; i <= 15; i++){
+ len = sprintf(buf, "%08d", i);
+ wlen = sprintf(wbuf, "========================");
+ if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Checking records ... ");
+ for(i = 1; i <= 20; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ free(vbuf);
+ if(vsiz != crvsiz(curia, buf, len)){
+ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Optimizing the database ... ");
+ if(!croptimize(curia, -1)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Checking records ... ");
+ for(i = 1; i <= 20; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ free(vbuf);
+ if(vsiz != crvsiz(curia, buf, len)){
+ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Closing database ... ");
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Creating a database with bnum 1000000 ... ");
+ if(!(curia = cropen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000, -1))){
+ pdperror(name);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Adding 1000 records ... ");
+ for(i = 1; i <= 1000; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!crput(curia, buf, len, buf, len, DP_DOVER)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Adding 64 records ... ");
+ for(i = 1; i <= 64; i++){
+ len = sprintf(buf, "%o", i);
+ if(!crput(curia, buf, len, buf, len, DP_DOVER)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Syncing the database ... ");
+ if(!crsync(curia)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Retrieving records directly ... ");
+ for(i = 1; i <= 64; i++){
+ len = sprintf(buf, "%o", i);
+ if(!(vbuf = crsnaffle(name, buf, len, &vsiz))){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ if(strcmp(vbuf, buf)){
+ fprintf(stderr, "%s: %s: invalid content\n", progname, name);
+ free(vbuf);
+ crclose(curia);
+ return 1;
+ }
+ free(vbuf);
+ if(vsiz != crvsiz(curia, buf, len)){
+ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name);
+ crclose(curia);
+ return 1;
+ }
+ }
+ printfflush("ok\n");
+ printfflush("Optimizing the database ... ");
+ if(!croptimize(curia, -1)){
+ pdperror(name);
+ crclose(curia);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("Closing the database ... ");
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ printfflush("ok\n");
+ printfflush("all ok\n\n");
+ return 0;
+}
+
+
+/* perform wicked command */
+int dowicked(const char *name, int rnum, int cb){
+ CURIA *curia;
+ CBMAP *map;
+ int i, len, err, align, mksiz, mvsiz, rsiz;
+ const char *mkbuf, *mvbuf;
+ char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val;
+ printfflush("<Wicked Writing Test>\n name=%s rnum=%d\n\n", name, rnum);
+ err = FALSE;
+ if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, rnum / 10, 5))){
+ pdperror(name);
+ return 1;
+ }
+ if(!crsetalign(curia, 16) || !crsetfbpsiz(curia, 256)){
+ pdperror(name);
+ err = TRUE;
+ }
+ map = NULL;
+ if(cb) map = cbmapopen();
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", myrand() % rnum + 1);
+ switch(myrand() % 16){
+ case 0:
+ putchar('O');
+ if(!crput(curia, buf, len, buf, len, CR_DOVER)) err = TRUE;
+ if(map) cbmapput(map, buf, len, buf, len, TRUE);
+ break;
+ case 1:
+ putchar('K');
+ if(!crput(curia, buf, len, buf, len, CR_DKEEP) && dpecode != DP_EKEEP) err = TRUE;
+ if(map) cbmapput(map, buf, len, buf, len, FALSE);
+ break;
+ case 2:
+ putchar('D');
+ if(!crout(curia, buf, len) && dpecode != DP_ENOITEM) err = TRUE;
+ if(map) cbmapout(map, buf, len);
+ break;
+ case 3:
+ putchar('G');
+ if(crgetwb(curia, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE;
+ break;
+ case 4:
+ putchar('V');
+ if(crvsiz(curia, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE;
+ break;
+ default:
+ putchar('C');
+ if(!crput(curia, buf, len, buf, len, CR_DCAT)) err = TRUE;
+ if(map) cbmapputcat(map, buf, len, buf, len);
+ break;
+ }
+ if(i % 50 == 0) printfflush(" (%08d)\n", i);
+ if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){
+ if(myrand() % 10 == 0){
+ align = (myrand() % 4 + 1) * -1;
+ } else {
+ align = myrand() % 32;
+ }
+ if(!crsetalign(curia, align)) err = TRUE;
+ }
+ if(err){
+ pdperror(name);
+ break;
+ }
+ }
+ if(!croptimize(curia, -1)){
+ pdperror(name);
+ err = TRUE;
+ }
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!crput(curia, buf, len, ":", -1, CR_DCAT)){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ if(map) cbmapputcat(map, buf, len, ":", -1);
+ putchar(':');
+ if(i % 50 == 0) printfflush(" (%08d)\n", i);
+ }
+ if(!croptimize(curia, -1)){
+ pdperror(name);
+ err = TRUE;
+ }
+ for(i = 1; i <= rnum; i++){
+ len = sprintf(buf, "%08d", i);
+ if(!(val = crget(curia, buf, len, 0, -1, NULL))){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ free(val);
+ putchar('=');
+ if(i % 50 == 0) printfflush(" (%08d)\n", i);
+ }
+ if(!criterinit(curia)){
+ pdperror(name);
+ err = TRUE;
+ }
+ for(i = 1; i <= rnum; i++){
+ if(!(val = criternext(curia, NULL))){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ free(val);
+ putchar('@');
+ if(i % 50 == 0) printfflush(" (%08d)\n", i);
+ }
+ if(map){
+ printfflush("Matching records ... ");
+ cbmapiterinit(map);
+ while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){
+ mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz);
+ if(!(val = crget(curia, mkbuf, mksiz, 0, -1, &rsiz))){
+ pdperror(name);
+ err = TRUE;
+ break;
+ }
+ if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){
+ fprintf(stderr, "%s: %s: unmatched record\n", progname, name);
+ free(val);
+ err = TRUE;
+ break;
+ }
+ free(val);
+ }
+ cbmapclose(map);
+ if(!err) printfflush("ok\n");
+ }
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ if(!err) printfflush("ok\n\n");
+ return err ? 1 : 0;
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/crtsv.c b/qdbm/crtsv.c
new file mode 100644
index 00000000..5b52488d
--- /dev/null
+++ b/qdbm/crtsv.c
@@ -0,0 +1,266 @@
+/*************************************************************************************************
+ * Mutual converter between a database of Curia and a TSV text
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#include <depot.h>
+#include <curia.h>
+#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef TRUE
+#define TRUE 1 /* boolean true */
+#undef FALSE
+#define FALSE 0 /* boolean false */
+
+
+/* for RISC OS */
+#if defined(__riscos__) || defined(__riscos)
+#include <unixlib/local.h>
+int __riscosify_control = __RISCOSIFY_NO_PROCESS;
+#endif
+
+
+/* global variables */
+const char *progname; /* program name */
+
+
+/* function prototypes */
+int main(int argc, char **argv);
+void usage(void);
+int runimport(int argc, char **argv);
+int runexport(int argc, char **argv);
+void pdperror(const char *name);
+char *getl(void);
+int doimport(const char *name, int bnum, int dnum, int bin);
+int doexport(const char *name, int bin);
+
+
+/* main routine */
+int main(int argc, char **argv){
+ int rv;
+ cbstdiobin();
+ progname = argv[0];
+ if(argc < 2) usage();
+ rv = 0;
+ if(!strcmp(argv[1], "import")){
+ rv = runimport(argc, argv);
+ } else if(!strcmp(argv[1], "export")){
+ rv = runexport(argc, argv);
+ } else {
+ usage();
+ }
+ return rv;
+}
+
+
+/* print the usage and exit */
+void usage(void){
+ fprintf(stderr, "%s: mutual converter between TSV and Curia database\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " %s import [-bnum num] [-dnum num] [-bin] name\n", progname);
+ fprintf(stderr, " %s export [-bin] name\n", progname);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+
+/* parse arguments of import command */
+int runimport(int argc, char **argv){
+ char *name;
+ int i, bnum, dnum, bin, rv;
+ name = NULL;
+ bnum = -1;
+ dnum = -1;
+ bin = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-bnum")){
+ if(++i >= argc) usage();
+ bnum = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-dnum")){
+ if(++i >= argc) usage();
+ dnum = atoi(argv[i]);
+ } else if(!strcmp(argv[i], "-bin")){
+ bin = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = doimport(name, bnum, dnum, bin);
+ return rv;
+}
+
+
+/* parse arguments of export command */
+int runexport(int argc, char **argv){
+ char *name;
+ int i, bin, rv;
+ name = NULL;
+ bin = FALSE;
+ for(i = 2; i < argc; i++){
+ if(!name && argv[i][0] == '-'){
+ if(!strcmp(argv[i], "-bin")){
+ bin = TRUE;
+ } else {
+ usage();
+ }
+ } else if(!name){
+ name = argv[i];
+ } else {
+ usage();
+ }
+ }
+ if(!name) usage();
+ rv = doexport(name, bin);
+ return rv;
+}
+
+
+/* print an error message */
+void pdperror(const char *name){
+ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode));
+}
+
+
+/* read a line */
+char *getl(void){
+ char *buf;
+ int c, len, blen;
+ buf = NULL;
+ len = 0;
+ blen = 256;
+ while((c = getchar()) != EOF){
+ if(blen <= len) blen *= 2;
+ buf = cbrealloc(buf, blen + 1);
+ if(c == '\n') c = '\0';
+ buf[len++] = c;
+ if(c == '\0') break;
+ }
+ if(!buf) return NULL;
+ buf[len] = '\0';
+ return buf;
+}
+
+
+/* perform import command */
+int doimport(const char *name, int bnum, int dnum, int bin){
+ CURIA *curia;
+ char *buf, *kbuf, *vbuf, *ktmp, *vtmp;
+ int i, err, ktsiz, vtsiz;
+ /* open a database */
+ if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT, bnum, dnum))){
+ pdperror(name);
+ return 1;
+ }
+ /* loop for each line */
+ err = FALSE;
+ for(i = 1; (buf = getl()) != NULL; i++){
+ kbuf = buf;
+ if((vbuf = strchr(buf, '\t')) != NULL){
+ *vbuf = '\0';
+ vbuf++;
+ /* store a record */
+ if(bin){
+ ktmp = cbbasedecode(kbuf, &ktsiz);
+ vtmp = cbbasedecode(vbuf, &vtsiz);
+ if(!crput(curia, ktmp, ktsiz, vtmp, vtsiz, CR_DOVER)){
+ pdperror(name);
+ err = TRUE;
+ }
+ free(vtmp);
+ free(ktmp);
+ } else {
+ if(!crput(curia, kbuf, -1, vbuf, -1, CR_DOVER)){
+ pdperror(name);
+ err = TRUE;
+ }
+ }
+ } else {
+ fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i);
+ }
+ free(buf);
+ if(err) break;
+ }
+ /* close the database */
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return err ? 1 : 0;
+}
+
+
+/* perform export command */
+int doexport(const char *name, int bin){
+ CURIA *curia;
+ char *kbuf, *vbuf, *tmp;
+ int err, ksiz, vsiz;
+ /* open a database */
+ if(!(curia = cropen(name, CR_OREADER, -1, -1))){
+ pdperror(name);
+ return 1;
+ }
+ /* initialize the iterator */
+ criterinit(curia);
+ /* loop for each key */
+ err = FALSE;
+ while((kbuf = criternext(curia, &ksiz)) != NULL){
+ /* retrieve a value with a key */
+ if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){
+ pdperror(name);
+ free(kbuf);
+ err = TRUE;
+ break;
+ }
+ /* output data */
+ if(bin){
+ tmp = cbbaseencode(kbuf, ksiz);
+ printf("%s\t", tmp);
+ free(tmp);
+ tmp = cbbaseencode(vbuf, vsiz);
+ printf("%s\n", tmp);
+ free(tmp);
+ } else {
+ printf("%s\t%s\n", kbuf, vbuf);
+ }
+ /* free resources */
+ free(vbuf);
+ free(kbuf);
+ }
+ /* check whether all records were retrieved */
+ if(dpecode != DP_ENOITEM){
+ pdperror(name);
+ err = TRUE;
+ }
+ /* close the database */
+ if(!crclose(curia)){
+ pdperror(name);
+ return 1;
+ }
+ return err ? 1 : 0;
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/curia.c b/qdbm/curia.c
new file mode 100644
index 00000000..100529d0
--- /dev/null
+++ b/qdbm/curia.c
@@ -0,0 +1,1192 @@
+/*************************************************************************************************
+ * Implementation of Curia
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#define QDBM_INTERNAL 1
+
+#include "curia.h"
+#include "myconf.h"
+
+#define CR_NAMEMAX 512 /* max size of a database name */
+#define CR_DPMAX 512 /* max number of division of a database */
+#define CR_DIRMODE 00755 /* permission of a creating directory */
+#define CR_FILEMODE 00644 /* permission of a creating file */
+#define CR_PATHBUFSIZ 1024 /* size of a path buffer */
+#define CR_DEFDNUM 5 /* default number of division of a database */
+#define CR_ATTRBNUM 16 /* bucket number of attrubute database */
+#define CR_DPNAME "depot" /* name of each sub database */
+#define CR_KEYDNUM "dnum" /* key of division number */
+#define CR_KEYLRNUM "lrnum" /* key of the number of large objects */
+#define CR_TMPFSUF MYEXTSTR "crtmp" /* suffix of a temporary directory */
+#define CR_LOBDIR "lob" /* name of the directory of large objects */
+#define CR_LOBDDEPTH 2 /* depth of the directories of large objects */
+#define CR_NUMBUFSIZ 32 /* size of a buffer for a number */
+#define CR_IOBUFSIZ 8192 /* size of an I/O buffer */
+
+
+/* private function prototypes */
+static char *crstrdup(const char *str);
+static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz);
+static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz);
+static int crmklobdir(const char *path);
+static int crrmlobdir(const char *path);
+static int crcplobdir(CURIA *curia, const char *path);
+static int crwrite(int fd, const void *buf, int size);
+static int crread(int fd, void *buf, int size);
+
+
+
+/*************************************************************************************************
+ * public objects
+ *************************************************************************************************/
+
+
+/* Get a database handle. */
+CURIA *cropen(const char *name, int omode, int bnum, int dnum){
+ DEPOT *attr, **depots;
+ char path[CR_PATHBUFSIZ], *tname;
+ int i, j, dpomode, inode, lrnum;
+ struct stat sbuf;
+ CURIA *curia;
+ assert(name);
+ if(dnum < 1) dnum = CR_DEFDNUM;
+ if(dnum > CR_DPMAX) dnum = CR_DPMAX;
+ if(strlen(name) > CR_NAMEMAX){
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ return NULL;
+ }
+ dpomode = DP_OREADER;
+ if(omode & CR_OWRITER){
+ dpomode = DP_OWRITER;
+ if(omode & CR_OCREAT) dpomode |= DP_OCREAT;
+ if(omode & CR_OTRUNC) dpomode |= DP_OTRUNC;
+ if(omode & CR_OSPARSE) dpomode |= DP_OSPARSE;
+ }
+ if(omode & CR_ONOLCK) dpomode |= DP_ONOLCK;
+ if(omode & CR_OLCKNB) dpomode |= DP_OLCKNB;
+ attr = NULL;
+ lrnum = 0;
+ if((omode & CR_OWRITER) && (omode & CR_OCREAT)){
+ if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){
+ dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
+ return NULL;
+ }
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
+ if(!(attr = dpopen(path, dpomode, CR_ATTRBNUM))) return NULL;
+ if(dprnum(attr) > 0){
+ if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 ||
+ (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){
+ dpclose(attr);
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ } else {
+ if(!dpput(attr, CR_KEYDNUM, -1, (char *)&dnum, sizeof(int), DP_DOVER) ||
+ !dpput(attr, CR_KEYLRNUM, -1, (char *)&lrnum, sizeof(int), DP_DOVER)){
+ dpclose(attr);
+ return NULL;
+ }
+ for(i = 0; i < dnum; i++){
+ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1);
+ if(mkdir(path, CR_DIRMODE) == -1 && errno != EEXIST){
+ dpclose(attr);
+ dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
+ return NULL;
+ }
+ }
+ }
+ }
+ if(!attr){
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
+ if(!(attr = dpopen(path, dpomode, 1))) return NULL;
+ if(!(omode & CR_OTRUNC)){
+ if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 ||
+ (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){
+ dpclose(attr);
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ }
+ }
+ if(omode & CR_OTRUNC){
+ for(i = 0; i < CR_DPMAX; i++){
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME);
+ if(unlink(path) == -1 && errno != ENOENT){
+ dpclose(attr);
+ dpecodeset(DP_EUNLINK, __FILE__, __LINE__);
+ return NULL;
+ }
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_LOBDIR);
+ if(!crrmlobdir(path)){
+ dpclose(attr);
+ return NULL;
+ }
+ if(i >= dnum){
+ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1);
+ if(rmdir(path) == -1 && errno != ENOENT){
+ dpclose(attr);
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
+ return NULL;
+ }
+ }
+ }
+ errno = 0;
+ }
+ if(lstat(name, &sbuf) == -1){
+ dpclose(attr);
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
+ return NULL;
+ }
+ inode = sbuf.st_ino;
+ if(!(depots = malloc(dnum * sizeof(DEPOT *)))){
+ dpclose(attr);
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ for(i = 0; i < dnum; i++){
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME);
+ if(!(depots[i] = dpopen(path, dpomode, bnum))){
+ for(j = 0; j < i; j++){
+ dpclose(depots[j]);
+ }
+ free(depots);
+ dpclose(attr);
+ return NULL;
+ }
+ }
+ curia = malloc(sizeof(CURIA));
+ tname = crstrdup(name);
+ if(!curia || !tname){
+ free(curia);
+ free(tname);
+ for(i = 0; i < dnum; i++){
+ dpclose(depots[i]);
+ }
+ free(depots);
+ dpclose(attr);
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ curia->name = tname;
+ curia->wmode = (omode & CR_OWRITER);
+ curia->inode = inode;
+ curia->attr = attr;
+ curia->depots = depots;
+ curia->dnum = dnum;
+ curia->inum = 0;
+ curia->lrnum = lrnum;
+ return curia;
+}
+
+
+/* Close a database handle. */
+int crclose(CURIA *curia){
+ int i, err;
+ assert(curia);
+ err = FALSE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpclose(curia->depots[i])) err = TRUE;
+ }
+ free(curia->depots);
+ if(curia->wmode){
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER))
+ err = TRUE;
+ }
+ if(!dpclose(curia->attr)) err = TRUE;
+ free(curia->name);
+ free(curia);
+ return err ? FALSE : TRUE;
+}
+
+
+/* Store a record. */
+int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){
+ int dpdmode;
+ int tnum;
+ assert(curia && kbuf && vbuf);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ switch(dmode){
+ case CR_DKEEP: dpdmode = DP_DKEEP; break;
+ case CR_DCAT: dpdmode = DP_DCAT; break;
+ default: dpdmode = DP_DOVER; break;
+ }
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
+ return dpput(curia->depots[tnum], kbuf, ksiz, vbuf, vsiz, dpdmode);
+}
+
+
+/* Delete a record. */
+int crout(CURIA *curia, const char *kbuf, int ksiz){
+ int tnum;
+ assert(curia && kbuf);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
+ return dpout(curia->depots[tnum], kbuf, ksiz);
+}
+
+
+/* Retrieve a record. */
+char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){
+ int tnum;
+ assert(curia && kbuf && start >= 0);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
+ return dpget(curia->depots[tnum], kbuf, ksiz, start, max, sp);
+}
+
+
+/* Retrieve a record and write the value into a buffer. */
+int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf){
+ int tnum;
+ assert(curia && kbuf && start >= 0 && max >= 0 && vbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
+ return dpgetwb(curia->depots[tnum], kbuf, ksiz, start, max, vbuf);
+}
+
+
+/* Get the size of the value of a record. */
+int crvsiz(CURIA *curia, const char *kbuf, int ksiz){
+ int tnum;
+ assert(curia && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
+ return dpvsiz(curia->depots[tnum], kbuf, ksiz);
+}
+
+
+/* Initialize the iterator of a database handle. */
+int criterinit(CURIA *curia){
+ int i, err;
+ assert(curia);
+ err = FALSE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpiterinit(curia->depots[i])){
+ err = TRUE;
+ break;
+ }
+ }
+ curia->inum = 0;
+ return err ? FALSE : TRUE;
+}
+
+
+/* Get the next key of the iterator. */
+char *criternext(CURIA *curia, int *sp){
+ char *kbuf;
+ assert(curia);
+ kbuf = NULL;
+ while(curia->inum < curia->dnum && !(kbuf = dpiternext(curia->depots[curia->inum], sp))){
+ if(dpecode != DP_ENOITEM) return NULL;
+ (curia->inum)++;
+ }
+ return kbuf;
+}
+
+
+/* Set alignment of a database handle. */
+int crsetalign(CURIA *curia, int align){
+ int i, err;
+ assert(curia);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpsetalign(curia->depots[i], align)){
+ err = TRUE;
+ break;
+ }
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Set the size of the free block pool of a database handle. */
+int crsetfbpsiz(CURIA *curia, int size){
+ int i, err;
+ assert(curia && size >= 0);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpsetfbpsiz(curia->depots[i], size)){
+ err = TRUE;
+ break;
+ }
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Synchronize contents of updating a database with the files and the devices. */
+int crsync(CURIA *curia){
+ int i, err;
+ assert(curia);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) ||
+ !dpsync(curia->attr)) err = TRUE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpsync(curia->depots[i])){
+ err = TRUE;
+ break;
+ }
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Optimize a database. */
+int croptimize(CURIA *curia, int bnum){
+ int i, err;
+ assert(curia);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpoptimize(curia->depots[i], bnum)){
+ err = TRUE;
+ break;
+ }
+ }
+ curia->inum = 0;
+ return err ? FALSE : TRUE;
+}
+
+
+/* Get the name of a database. */
+char *crname(CURIA *curia){
+ char *name;
+ assert(curia);
+ if(!(name = crstrdup(curia->name))){
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ return name;
+}
+
+
+/* Get the total size of database files. */
+int crfsiz(CURIA *curia){
+ int i, sum, rv;
+ assert(curia);
+ if((sum = dpfsiz(curia->attr)) == -1) return -1;
+ for(i = 0; i < curia->dnum; i++){
+ if((rv = dpfsiz(curia->depots[i])) == -1) return -1;
+ sum += rv;
+ }
+ return sum;
+}
+
+
+/* Get the total size of database files as double-precision value. */
+double crfsizd(CURIA *curia){
+ double sum;
+ int i, rv;
+ assert(curia);
+ sum = 0.0;
+ if((sum = dpfsiz(curia->attr)) < 0) return -1.0;
+ for(i = 0; i < curia->dnum; i++){
+ if((rv = dpfsiz(curia->depots[i])) == -1) return -1.0;
+ sum += rv;
+ }
+ return sum;
+}
+
+
+/* Get the total number of the elements of each bucket array. */
+int crbnum(CURIA *curia){
+ int i, sum, rv;
+ assert(curia);
+ sum = 0;
+ for(i = 0; i < curia->dnum; i++){
+ rv = dpbnum(curia->depots[i]);
+ if(rv == -1) return -1;
+ sum += rv;
+ }
+ return sum;
+}
+
+
+/* Get the total number of the used elements of each bucket array. */
+int crbusenum(CURIA *curia){
+ int i, sum, rv;
+ assert(curia);
+ sum = 0;
+ for(i = 0; i < curia->dnum; i++){
+ rv = dpbusenum(curia->depots[i]);
+ if(rv == -1) return -1;
+ sum += rv;
+ }
+ return sum;
+}
+
+
+/* Get the number of the records stored in a database. */
+int crrnum(CURIA *curia){
+ int i, sum, rv;
+ assert(curia);
+ sum = 0;
+ for(i = 0; i < curia->dnum; i++){
+ rv = dprnum(curia->depots[i]);
+ if(rv == -1) return -1;
+ sum += rv;
+ }
+ return sum;
+}
+
+
+/* Check whether a database handle is a writer or not. */
+int crwritable(CURIA *curia){
+ assert(curia);
+ return curia->wmode;
+}
+
+
+/* Check whether a database has a fatal error or not. */
+int crfatalerror(CURIA *curia){
+ int i;
+ assert(curia);
+ if(dpfatalerror(curia->attr)) return TRUE;
+ for(i = 0; i < curia->dnum; i++){
+ if(dpfatalerror(curia->depots[i])) return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* Get the inode number of a database directory. */
+int crinode(CURIA *curia){
+ assert(curia);
+ return curia->inode;
+}
+
+
+/* Get the last modified time of a database. */
+time_t crmtime(CURIA *curia){
+ assert(curia);
+ return dpmtime(curia->attr);
+}
+
+
+/* Remove a database directory. */
+int crremove(const char *name){
+ struct stat sbuf;
+ CURIA *curia;
+ char path[CR_PATHBUFSIZ];
+ assert(name);
+ if(lstat(name, &sbuf) == -1){
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if((curia = cropen(name, CR_OWRITER | CR_OTRUNC, 1, 1)) != NULL) crclose(curia);
+ sprintf(path, "%s%c0001%c%s", name, MYPATHCHR, MYPATHCHR, CR_DPNAME);
+ dpremove(path);
+ sprintf(path, "%s%c0001", name, MYPATHCHR);
+ if(rmdir(path) == -1){
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
+ return FALSE;
+ }
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
+ if(!dpremove(path)) return FALSE;
+ if(rmdir(name) == -1){
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* Repair a broken database directory. */
+int crrepair(const char *name){
+ CURIA *tcuria;
+ DEPOT *tdepot;
+ char path[CR_PATHBUFSIZ], *kbuf, *vbuf;
+ struct stat sbuf;
+ int i, j, err, flags, bnum, dnum, ksiz, vsiz;
+ assert(name);
+ err = FALSE;
+ flags = 0;
+ bnum = 0;
+ dnum = 0;
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
+ if(lstat(path, &sbuf) != -1){
+ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){
+ flags = dpgetflags(tdepot);
+ dpclose(tdepot);
+ }
+ }
+ for(i = 1; i <= CR_DPMAX; i++){
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME);
+ if(lstat(path, &sbuf) != -1){
+ dnum++;
+ if(!dprepair(path)) err = TRUE;
+ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){
+ bnum += dpbnum(tdepot);
+ dpclose(tdepot);
+ }
+ }
+ }
+ if(dnum < CR_DEFDNUM) dnum = CR_DEFDNUM;
+ bnum /= dnum;
+ sprintf(path, "%s%s", name, CR_TMPFSUF);
+ if((tcuria = cropen(path, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum)) != NULL){
+ if(!crsetflags(tcuria, flags)) err = TRUE;
+ for(i = 1; i <= CR_DPMAX; i++){
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME);
+ if(lstat(path, &sbuf) != -1){
+ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){
+ if(!dpiterinit(tdepot)) err = TRUE;
+ while((kbuf = dpiternext(tdepot, &ksiz)) != NULL){
+ if((vbuf = dpget(tdepot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
+ if(!crput(tcuria, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE;
+ free(vbuf);
+ }
+ free(kbuf);
+ }
+ dpclose(tdepot);
+ } else {
+ err = TRUE;
+ }
+ }
+ for(j = 0; j <= CR_DPMAX; j++){
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, j, MYPATHCHR, CR_LOBDIR);
+ if(lstat(path, &sbuf) != -1){
+ if(!crcplobdir(tcuria, path)) err = TRUE;
+ }
+ }
+ }
+ if(!crclose(tcuria)) err = TRUE;
+ if(!crremove(name)) err = TRUE;
+ sprintf(path, "%s%s", name, CR_TMPFSUF);
+ if(rename(path, name) == -1){
+ if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ err = TRUE;
+ }
+ } else {
+ err = TRUE;
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Dump all records as endian independent data. */
+int crexportdb(CURIA *curia, const char *name){
+ char path[CR_PATHBUFSIZ], *kbuf, *vbuf, *pbuf;
+ int i, err, *fds, ksiz, vsiz, psiz;
+ assert(curia && name);
+ if(!(criterinit(curia))) return FALSE;
+ if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){
+ dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ fds = malloc(sizeof(int) * curia->dnum);
+ for(i = 0; i < curia->dnum; i++){
+ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1);
+ if((fds[i] = open(path, O_RDWR | O_CREAT | O_TRUNC, CR_FILEMODE)) == -1){
+ if(!err) dpecodeset(DP_EOPEN, __FILE__, __LINE__);
+ err = TRUE;
+ break;
+ }
+ }
+ while(!err && (kbuf = criternext(curia, &ksiz)) != NULL){
+ if((vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
+ if((pbuf = malloc(ksiz + vsiz + CR_NUMBUFSIZ * 2)) != NULL){
+ psiz = 0;
+ psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz);
+ memcpy(pbuf + psiz, kbuf, ksiz);
+ psiz += ksiz;
+ pbuf[psiz++] = '\n';
+ memcpy(pbuf + psiz, vbuf, vsiz);
+ psiz += vsiz;
+ pbuf[psiz++] = '\n';
+ if(!crwrite(fds[curia->inum], pbuf, psiz)){
+ dpecodeset(DP_EWRITE, __FILE__, __LINE__);
+ err = TRUE;
+ }
+ free(pbuf);
+ } else {
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ err = TRUE;
+ }
+ free(vbuf);
+ } else {
+ err = TRUE;
+ }
+ free(kbuf);
+ }
+ for(i = 0; i < curia->dnum; i++){
+ if(fds[i] != -1 && close(fds[i]) == -1){
+ if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__);
+ err = TRUE;
+ }
+ }
+ free(fds);
+ return !err && !crfatalerror(curia);
+}
+
+
+/* Load all records from endian independent data. */
+int crimportdb(CURIA *curia, const char *name){
+ DEPOT *depot;
+ char ipath[CR_PATHBUFSIZ], opath[CR_PATHBUFSIZ], *kbuf, *vbuf;
+ int i, err, ksiz, vsiz;
+ struct stat sbuf;
+ assert(curia && name);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(crrnum(curia) > 0){
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ for(i = 0; !err && i < CR_DPMAX; i++){
+ sprintf(ipath, "%s%c%04d", name, MYPATHCHR, i + 1);
+ if(lstat(ipath, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)) break;
+ sprintf(opath, "%s%c%04d%s", curia->name, MYPATHCHR, i + 1, CR_TMPFSUF);
+ if((depot = dpopen(opath, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1)) != NULL){
+ if(dpimportdb(depot, ipath)){
+ dpiterinit(depot);
+ while((kbuf = dpiternext(depot, &ksiz)) != NULL){
+ if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
+ if(!crput(curia, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE;
+ free(vbuf);
+ } else {
+ err = TRUE;
+ }
+ free(kbuf);
+ }
+ } else {
+ err = TRUE;
+ }
+ if(!dpclose(depot)) err = TRUE;
+ if(!dpremove(opath)) err = TRUE;
+ } else {
+ err = TRUE;
+ }
+ }
+ return !err && !crfatalerror(curia);
+}
+
+
+/* Retrieve a record directly from a database directory. */
+char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp){
+ char path[CR_PATHBUFSIZ], *vbuf;
+ int dnum, vsiz, tnum;
+ assert(name && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
+ if(!(vbuf = dpsnaffle(path, CR_KEYDNUM, -1, &vsiz)) || vsiz != sizeof(int) ||
+ (dnum = *(int *)vbuf) < 1){
+ free(vbuf);
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ free(vbuf);
+ tnum = dpouterhash(kbuf, ksiz) % dnum;
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, tnum + 1, MYPATHCHR, CR_DPNAME);
+ return dpsnaffle(path, kbuf, ksiz, sp);
+}
+
+
+/* Store a large object. */
+int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){
+ char *path;
+ int mode, fd, err, be;
+ struct stat sbuf;
+ assert(curia && kbuf && vbuf);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(vsiz < 0) vsiz = strlen(vbuf);
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE;
+ if(!crmklobdir(path)){
+ free(path);
+ return FALSE;
+ }
+ be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode);
+ mode = O_RDWR | O_CREAT;
+ if(dmode & CR_DKEEP) mode |= O_EXCL;
+ if(dmode & CR_DCAT){
+ mode |= O_APPEND;
+ } else {
+ mode |= O_TRUNC;
+ }
+ if((fd = open(path, mode, CR_FILEMODE)) == -1){
+ free(path);
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
+ if(dmode == CR_DKEEP) dpecodeset(DP_EKEEP, __FILE__, __LINE__);
+ return FALSE;
+ }
+ free(path);
+ err = FALSE;
+ if(crwrite(fd, vbuf, vsiz) == -1){
+ err = TRUE;
+ dpecodeset(DP_EWRITE, __FILE__, __LINE__);
+ }
+ if(close(fd) == -1){
+ err = TRUE;
+ dpecodeset(DP_ECLOSE, __FILE__, __LINE__);
+ }
+ if(!err && !be) (curia->lrnum)++;
+ return err ? FALSE : TRUE;
+}
+
+
+/* Delete a large object. */
+int croutlob(CURIA *curia, const char *kbuf, int ksiz){
+ char *path;
+ int err, be;
+ struct stat sbuf;
+ assert(curia && kbuf);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE;
+ be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode);
+ err = FALSE;
+ if(unlink(path) == -1){
+ err = TRUE;
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ }
+ free(path);
+ if(!err && be) (curia->lrnum)--;
+ return err ? FALSE : TRUE;
+}
+
+
+/* Retrieve a large object. */
+char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){
+ char *path, *buf;
+ struct stat sbuf;
+ int fd, size;
+ assert(curia && kbuf && start >= 0);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return NULL;
+ if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){
+ free(path);
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return NULL;
+ }
+ free(path);
+ if(fstat(fd, &sbuf) == -1){
+ close(fd);
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(start > sbuf.st_size){
+ close(fd);
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(lseek(fd, start, SEEK_SET) == -1){
+ close(fd);
+ dpecodeset(DP_ESEEK, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(max < 0) max = sbuf.st_size;
+ if(!(buf = malloc(max + 1))){
+ close(fd);
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ size = crread(fd, buf, max);
+ close(fd);
+ if(size == -1){
+ free(buf);
+ dpecodeset(DP_EREAD, __FILE__, __LINE__);
+ return NULL;
+ }
+ buf[size] = '\0';
+ if(sp) *sp = size;
+ return buf;
+}
+
+
+/* Get the file descriptor of a large object. */
+int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz){
+ char *path;
+ int fd;
+ assert(curia && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1;
+ if((fd = open(path, curia->wmode ? O_RDWR: O_RDONLY, CR_FILEMODE)) == -1){
+ free(path);
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return -1;
+ }
+ free(path);
+ return fd;
+}
+
+
+/* Get the size of the value of a large object. */
+int crvsizlob(CURIA *curia, const char *kbuf, int ksiz){
+ char *path;
+ struct stat sbuf;
+ assert(curia && kbuf);
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1;
+ if(lstat(path, &sbuf) == -1){
+ free(path);
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return -1;
+ }
+ free(path);
+ return sbuf.st_size;
+}
+
+
+/* Get the number of the large objects stored in a database. */
+int crrnumlob(CURIA *curia){
+ assert(curia);
+ return curia->lrnum;
+}
+
+
+
+/*************************************************************************************************
+ * features for experts
+ *************************************************************************************************/
+
+
+/* Synchronize updating contents on memory. */
+int crmemsync(CURIA *curia){
+ int i, err;
+ assert(curia);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) ||
+ !dpmemsync(curia->attr)) err = TRUE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpmemsync(curia->depots[i])){
+ err = TRUE;
+ break;
+ }
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Synchronize updating contents on memory, not physically. */
+int crmemflush(CURIA *curia){
+ int i, err;
+ assert(curia);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ err = FALSE;
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) ||
+ !dpmemsync(curia->attr)) err = TRUE;
+ for(i = 0; i < curia->dnum; i++){
+ if(!dpmemflush(curia->depots[i])){
+ err = TRUE;
+ break;
+ }
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Get flags of a database. */
+int crgetflags(CURIA *curia){
+ assert(curia);
+ return dpgetflags(curia->attr);
+}
+
+
+/* Set flags of a database. */
+int crsetflags(CURIA *curia, int flags){
+ assert(curia);
+ if(!curia->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ return dpsetflags(curia->attr, flags);
+}
+
+
+
+/*************************************************************************************************
+ * private objects
+ *************************************************************************************************/
+
+
+/* Get a copied string.
+ `str' specifies an original string.
+ The return value is a copied string whose region is allocated by `malloc'. */
+static char *crstrdup(const char *str){
+ int len;
+ char *buf;
+ assert(str);
+ len = strlen(str);
+ if(!(buf = malloc(len + 1))) return NULL;
+ memcpy(buf, str, len + 1);
+ return buf;
+}
+
+
+/* Get an integer from a database.
+ `depot' specifies an inner database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the key.
+ The return value is the integer of the corresponding record. */
+static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz){
+ char *vbuf;
+ int vsiz, rv;
+ if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) || vsiz != sizeof(int)){
+ free(vbuf);
+ return INT_MIN;
+ }
+ rv = *(int *)vbuf;
+ free(vbuf);
+ return rv;
+}
+
+
+/* Get the path of a large object.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the key.
+ The return value is a path string whose region is allocated by `malloc'. */
+static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz){
+ char prefix[CR_PATHBUFSIZ], *wp, *path;
+ int i, hash;
+ assert(curia && kbuf && ksiz >= 0);
+ wp = prefix;
+ wp += sprintf(wp, "%s%c%04d%c%s%c",
+ curia->name, MYPATHCHR, dpouterhash(kbuf, ksiz) % curia->dnum + 1,
+ MYPATHCHR, CR_LOBDIR, MYPATHCHR);
+ hash = dpinnerhash(kbuf, ksiz);
+ for(i = 0; i < CR_LOBDDEPTH; i++){
+ wp += sprintf(wp, "%02X%c", hash % 0x100, MYPATHCHR);
+ hash /= 0x100;
+ }
+ if(!(path = malloc(strlen(prefix) + ksiz * 2 + 1))){
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ wp = path;
+ wp += sprintf(path, "%s", prefix);
+ for(i = 0; i < ksiz; i++){
+ wp += sprintf(wp, "%02X", ((unsigned char *)kbuf)[i]);
+ }
+ return path;
+}
+
+
+/* Create directories included in a path.
+ `path' specifies a path.
+ The return value is true if successful, else, it is false. */
+static int crmklobdir(const char *path){
+ char elem[CR_PATHBUFSIZ], *wp;
+ const char *dp;
+ int err, len;
+ wp = elem;
+ err = FALSE;
+ while(*path != '\0' && (dp = strchr(path, MYPATHCHR)) != NULL){
+ len = dp - path;
+ if((wp != elem || dp == path)) wp += sprintf(wp, "%c", MYPATHCHR);
+ memcpy(wp, path, len);
+ wp[len] = '\0';
+ wp += len;
+ if(mkdir(elem, CR_DIRMODE) == -1 && errno != EEXIST) err = TRUE;
+ path = dp + 1;
+ }
+ if(err) dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
+ return err ? FALSE : TRUE;
+}
+
+
+/* Remove file and directories under a directory.
+ `path' specifies a path.
+ The return value is true if successful, else, it is false. */
+static int crrmlobdir(const char *path){
+ char elem[CR_PATHBUFSIZ];
+ DIR *DD;
+ struct dirent *dp;
+ assert(path);
+ if(unlink(path) != -1){
+ return TRUE;
+ } else {
+ if(errno == ENOENT) return TRUE;
+ if(!(DD = opendir(path))){
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ return FALSE;
+ }
+ while((dp = readdir(DD)) != NULL){
+ if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue;
+ sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name);
+ if(!crrmlobdir(elem)){
+ closedir(DD);
+ return FALSE;
+ }
+ }
+ }
+ if(closedir(DD) == -1){
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(rmdir(path) == -1){
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* Copy file and directories under a directory for repairing.
+ `path' specifies a path.
+ The return value is true if successful, else, it is false. */
+static int crcplobdir(CURIA *curia, const char *path){
+ char elem[CR_PATHBUFSIZ], numbuf[3], *rp, *kbuf, *vbuf;
+ DIR *DD;
+ struct dirent *dp;
+ struct stat sbuf;
+ int i, ksiz, vsiz, fd;
+ assert(curia && path);
+ if(lstat(path, &sbuf) == -1){
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(S_ISREG(sbuf.st_mode)){
+ rp = strrchr(path, MYPATHCHR) + 1;
+ for(i = 0; rp[i] != '\0'; i += 2){
+ numbuf[0] = rp[i];
+ numbuf[1] = rp[i+1];
+ numbuf[2] = '\0';
+ elem[i/2] = (int)strtol(numbuf, NULL, 16);
+ }
+ kbuf = elem;
+ ksiz = i / 2;
+ vsiz = sbuf.st_size;
+ if(!(vbuf = malloc(vsiz + 1))){
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){
+ free(vbuf);
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(crread(fd, vbuf, vsiz) == -1){
+ close(fd);
+ free(vbuf);
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, DP_DOVER)){
+ close(fd);
+ free(vbuf);
+ return FALSE;
+ }
+ close(fd);
+ free(vbuf);
+ return TRUE;
+ }
+ if(!(DD = opendir(path))){
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ return FALSE;
+ }
+ while((dp = readdir(DD)) != NULL){
+ if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue;
+ sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name);
+ if(!crcplobdir(curia, elem)){
+ closedir(DD);
+ return FALSE;
+ }
+ }
+ if(closedir(DD) == -1){
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* Write into a file.
+ `fd' specifies a file descriptor.
+ `buf' specifies a buffer to write.
+ `size' specifies the size of the buffer.
+ The return value is the size of the written buffer, or, -1 on failure. */
+static int crwrite(int fd, const void *buf, int size){
+ char *lbuf;
+ int rv, wb;
+ assert(fd >= 0 && buf && size >= 0);
+ lbuf = (char *)buf;
+ rv = 0;
+ do {
+ wb = write(fd, lbuf, size);
+ switch(wb){
+ case -1: if(errno != EINTR) return -1;
+ case 0: break;
+ default:
+ lbuf += wb;
+ size -= wb;
+ rv += wb;
+ break;
+ }
+ } while(size > 0);
+ return rv;
+}
+
+
+/* Read from a file and store the data into a buffer.
+ `fd' specifies a file descriptor.
+ `buffer' specifies a buffer to store into.
+ `size' specifies the size to read with.
+ The return value is the size read with, or, -1 on failure. */
+static int crread(int fd, void *buf, int size){
+ char *lbuf;
+ int i, bs;
+ assert(fd >= 0 && buf && size >= 0);
+ lbuf = buf;
+ for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){
+ if(bs == -1 && errno != EINTR) return -1;
+ }
+ return i;
+}
+
+
+
+/* END OF FILE */
diff --git a/qdbm/curia.h b/qdbm/curia.h
new file mode 100644
index 00000000..24ce23f3
--- /dev/null
+++ b/qdbm/curia.h
@@ -0,0 +1,474 @@
+/*************************************************************************************************
+ * The extended API of QDBM
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#ifndef _CURIA_H /* duplication check */
+#define _CURIA_H
+
+#if defined(__cplusplus) /* export for C++ */
+extern "C" {
+#endif
+
+
+#include <depot.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC)
+#define MYEXTERN extern __declspec(dllimport)
+#else
+#define MYEXTERN extern
+#endif
+
+
+
+/*************************************************************************************************
+ * API
+ *************************************************************************************************/
+
+
+typedef struct { /* type of structure for the database handle */
+ char *name; /* name of the database directory */
+ int wmode; /* whether to be writable */
+ int inode; /* inode of the database directory */
+ DEPOT *attr; /* database handle for attributes */
+ DEPOT **depots; /* handles of the record database */
+ int dnum; /* number of record database handles */
+ int inum; /* number of the database of the using iterator */
+ int lrnum; /* number of large objects */
+} CURIA;
+
+enum { /* enumeration for open modes */
+ CR_OREADER = 1 << 0, /* open as a reader */
+ CR_OWRITER = 1 << 1, /* open as a writer */
+ CR_OCREAT = 1 << 2, /* a writer creating */
+ CR_OTRUNC = 1 << 3, /* a writer truncating */
+ CR_ONOLCK = 1 << 4, /* open without locking */
+ CR_OLCKNB = 1 << 5, /* lock without blocking */
+ CR_OSPARSE = 1 << 6 /* create as sparse files */
+};
+
+enum { /* enumeration for write modes */
+ CR_DOVER, /* overwrite an existing value */
+ CR_DKEEP, /* keep an existing value */
+ CR_DCAT /* concatenate values */
+};
+
+
+/* Get a database handle.
+ `name' specifies the name of a database directory.
+ `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader.
+ If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which
+ means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new
+ database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by
+ bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or
+ `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to
+ by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files.
+ `bnum' specifies the number of elements of each bucket array. If it is not more than 0,
+ the default value is specified. The size of each bucket array is determined on creating,
+ and can not be changed except for by optimization of the database. Suggested size of each
+ bucket array is about from 0.5 to 4 times of the number of all records to store.
+ `dnum' specifies the number of division of the database. If it is not more than 0, the
+ default value is specified. The number of division can not be changed from the initial value.
+ The max number of division is 512.
+ The return value is the database handle or `NULL' if it is not successful.
+ While connecting as a writer, an exclusive lock is invoked to the database directory.
+ While connecting as a reader, a shared lock is invoked to the database directory.
+ The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is
+ responsible for exclusion control. */
+CURIA *cropen(const char *name, int omode, int bnum, int dnum);
+
+
+/* Close a database handle.
+ `curia' specifies a database handle.
+ If successful, the return value is true, else, it is false.
+ Because the region of a closed handle is released, it becomes impossible to use the handle.
+ Updating a database is assured to be written when the handle is closed. If a writer opens
+ a database but does not close it appropriately, the database will be broken. */
+int crclose(CURIA *curia);
+
+
+/* Store a record.
+ `curia' specifies a database handle connected as a writer.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `vbuf' specifies the pointer to the region of a value.
+ `vsiz' specifies the size of the region of the value. If it is negative, the size is
+ assigned with `strlen(vbuf)'.
+ `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER',
+ which means the specified value overwrites the existing one, `CR_DKEEP', which means the
+ existing value is kept, `CR_DCAT', which means the specified value is concatenated at the
+ end of the existing value.
+ If successful, the return value is true, else, it is false. */
+int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
+
+/* Delete a record.
+ `curia' specifies a database handle connected as a writer.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ If successful, the return value is true, else, it is false. False is returned when no
+ record corresponds to the specified key. */
+int crout(CURIA *curia, const char *kbuf, int ksiz);
+
+
+/* Retrieve a record.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `start' specifies the offset address of the beginning of the region of the value to be read.
+ `max' specifies the max size to be read. If it is negative, the size to read is unlimited.
+ `sp' specifies the pointer to a variable to which the size of the region of the return value
+ is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the value of the
+ corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to
+ the specified key or the size of the value of the corresponding record is less than `start'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. */
+char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
+
+
+/* Retrieve a record and write the value into a buffer.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `start' specifies the offset address of the beginning of the region of the value to be read.
+ `max' specifies the max size to be read. It shuld be equal to or less than the size of the
+ writing buffer.
+ `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is
+ written.
+ If successful, the return value is the size of the written data, else, it is -1. -1 is
+ returned when no record corresponds to the specified key or the size of the value of the
+ corresponding record is less than `start'.
+ Note that no additional zero code is appended at the end of the region of the writing buffer. */
+int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
+
+
+/* Get the size of the value of a record.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ If successful, the return value is the size of the value of the corresponding record, else,
+ it is -1.
+ Because this function does not read the entity of a record, it is faster than `crget'. */
+int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
+
+
+/* Initialize the iterator of a database handle.
+ `curia' specifies a database handle.
+ If successful, the return value is true, else, it is false.
+ The iterator is used in order to access the key of every record stored in a database. */
+int criterinit(CURIA *curia);
+
+
+/* Get the next key of the iterator.
+ `curia' specifies a database handle.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the next key, else, it is
+ `NULL'. `NULL' is returned when no record is to be get out of the iterator.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. It is possible to access every record by iteration of calling this
+ function. However, it is not assured if updating the database is occurred while the
+ iteration. Besides, the order of this traversal access method is arbitrary, so it is not
+ assured that the order of storing matches the one of the traversal access. */
+char *criternext(CURIA *curia, int *sp);
+
+
+/* Set alignment of a database handle.
+ `curia' specifies a database handle connected as a writer.
+ `align' specifies the size of alignment.
+ If successful, the return value is true, else, it is false.
+ If alignment is set to a database, the efficiency of overwriting values is improved.
+ The size of alignment is suggested to be average size of the values of the records to be
+ stored. If alignment is positive, padding whose size is multiple number of the alignment
+ is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding
+ is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not
+ saved in a database, you should specify alignment every opening a database. */
+int crsetalign(CURIA *curia, int align);
+
+
+/* Set the size of the free block pool of a database handle.
+ `curia' specifies a database handle connected as a writer.
+ `size' specifies the size of the free block pool of a database.
+ If successful, the return value is true, else, it is false.
+ The default size of the free block pool is 16. If the size is greater, the space efficiency
+ of overwriting values is improved with the time efficiency sacrificed. */
+int crsetfbpsiz(CURIA *curia, int size);
+
+
+/* Synchronize updating contents with the files and the devices.
+ `curia' specifies a database handle connected as a writer.
+ If successful, the return value is true, else, it is false.
+ This function is useful when another process uses the connected database directory. */
+int crsync(CURIA *curia);
+
+
+/* Optimize a database.
+ `curia' specifies a database handle connected as a writer.
+ `bnum' specifies the number of the elements of each bucket array. If it is not more than 0,
+ the default value is specified.
+ If successful, the return value is true, else, it is false.
+ In an alternating succession of deleting and storing with overwrite or concatenate,
+ dispensable regions accumulate. This function is useful to do away with them. */
+int croptimize(CURIA *curia, int bnum);
+
+/* Get the name of a database.
+ `curia' specifies a database handle.
+ If successful, the return value is the pointer to the region of the name of the database,
+ else, it is `NULL'.
+ Because the region of the return value is allocated with the `malloc' call, it should be
+ released with the `free' call if it is no longer in use. */
+char *crname(CURIA *curia);
+
+
+/* Get the total size of database files.
+ `curia' specifies a database handle.
+ If successful, the return value is the total size of the database files, else, it is -1.
+ If the total size is more than 2GB, the return value overflows. */
+int crfsiz(CURIA *curia);
+
+
+/* Get the total size of database files as double-precision floating-point number.
+ `curia' specifies a database handle.
+ If successful, the return value is the total size of the database files, else, it is -1.0. */
+double crfsizd(CURIA *curia);
+
+
+/* Get the total number of the elements of each bucket array.
+ `curia' specifies a database handle.
+ If successful, the return value is the total number of the elements of each bucket array,
+ else, it is -1. */
+int crbnum(CURIA *curia);
+
+
+/* Get the total number of the used elements of each bucket array.
+ `curia' specifies a database handle.
+ If successful, the return value is the total number of the used elements of each bucket
+ array, else, it is -1.
+ This function is inefficient because it accesses all elements of each bucket array. */
+int crbusenum(CURIA *curia);
+
+
+/* Get the number of the records stored in a database.
+ `curia' specifies a database handle.
+ If successful, the return value is the number of the records stored in the database, else,
+ it is -1. */
+int crrnum(CURIA *curia);
+
+
+/* Check whether a database handle is a writer or not.
+ `curia' specifies a database handle.
+ The return value is true if the handle is a writer, false if not. */
+int crwritable(CURIA *curia);
+
+
+/* Check whether a database has a fatal error or not.
+ `curia' specifies a database handle.
+ The return value is true if the database has a fatal error, false if not. */
+int crfatalerror(CURIA *curia);
+
+
+/* Get the inode number of a database directory.
+ `curia' specifies a database handle.
+ The return value is the inode number of the database directory. */
+int crinode(CURIA *curia);
+
+
+/* Get the last modified time of a database.
+ `curia' specifies a database handle.
+ The return value is the last modified time of the database. */
+time_t crmtime(CURIA *curia);
+
+
+/* Remove a database directory.
+ `name' specifies the name of a database directory.
+ If successful, the return value is true, else, it is false. */
+int crremove(const char *name);
+
+
+/* Repair a broken database directory.
+ `name' specifies the name of a database directory.
+ If successful, the return value is true, else, it is false.
+ There is no guarantee that all records in a repaired database directory correspond to the
+ original or expected state. */
+int crrepair(const char *name);
+
+
+/* Dump all records as endian independent data.
+ `curia' specifies a database handle.
+ `name' specifies the name of an output directory.
+ If successful, the return value is true, else, it is false.
+ Note that large objects are ignored. */
+int crexportdb(CURIA *curia, const char *name);
+
+
+/* Load all records from endian independent data.
+ `curia' specifies a database handle connected as a writer. The database of the handle must
+ be empty.
+ `name' specifies the name of an input directory.
+ If successful, the return value is true, else, it is false.
+ Note that large objects are ignored. */
+int crimportdb(CURIA *curia, const char *name);
+
+
+/* Retrieve a record directly from a database directory.
+ `name' specifies the name of a database directory.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `sp' specifies the pointer to a variable to which the size of the region of the return
+ value is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the value of the
+ corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to
+ the specified key.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. Although this function can be used even while the database directory is
+ locked by another process, it is not assured that recent updated is reflected. */
+char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
+
+
+/* Store a large object.
+ `curia' specifies a database handle connected as a writer.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `vbuf' specifies the pointer to the region of a value.
+ `vsiz' specifies the size of the region of the value. If it is negative, the size is
+ assigned with `strlen(vbuf)'.
+ `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER',
+ which means the specified value overwrites the existing one, `CR_DKEEP', which means the
+ existing value is kept, `CR_DCAT', which means the specified value is concatenated at the
+ end of the existing value.
+ If successful, the return value is true, else, it is false. */
+int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
+
+/* Delete a large object.
+ `curia' specifies a database handle connected as a writer.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ If successful, the return value is true, else, it is false. false is returned when no large
+ object corresponds to the specified key. */
+int croutlob(CURIA *curia, const char *kbuf, int ksiz);
+
+
+/* Retrieve a large object.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ `start' specifies the offset address of the beginning of the region of the value to be read.
+ `max' specifies the max size to be read. If it is negative, the size to read is unlimited.
+ `sp' specifies the pointer to a variable to which the size of the region of the return value
+ is assigned. If it is `NULL', it is not used.
+ If successful, the return value is the pointer to the region of the value of the
+ corresponding large object, else, it is `NULL'. `NULL' is returned when no large object
+ corresponds to the specified key or the size of the value of the corresponding large object
+ is less than `start'.
+ Because an additional zero code is appended at the end of the region of the return value,
+ the return value can be treated as a character string. Because the region of the return
+ value is allocated with the `malloc' call, it should be released with the `free' call if it
+ is no longer in use. */
+char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
+
+
+/* Get the file descriptor of a large object.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ If successful, the return value is the file descriptor of the corresponding large object,
+ else, it is -1. -1 is returned when no large object corresponds to the specified key. The
+ returned file descriptor is opened with the `open' call. If the database handle was opened
+ as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The
+ descriptor should be closed with the `close' call if it is no longer in use. */
+int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
+
+
+/* Get the size of the value of a large object.
+ `curia' specifies a database handle.
+ `kbuf' specifies the pointer to the region of a key.
+ `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned
+ with `strlen(kbuf)'.
+ If successful, the return value is the size of the value of the corresponding large object,
+ else, it is -1.
+ Because this function does not read the entity of a large object, it is faster than
+ `crgetlob'. */
+int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
+
+
+/* Get the number of the large objects stored in a database.
+ `curia' specifies a database handle.
+ If successful, the return value is the number of the large objects stored in the database,
+ else, it is -1. */
+int crrnumlob(CURIA *curia);
+
+
+
+/*************************************************************************************************
+ * features for experts
+ *************************************************************************************************/
+
+
+/* Synchronize updating contents on memory.
+ `curia' specifies a database handle connected as a writer.
+ If successful, the return value is true, else, it is false. */
+int crmemsync(CURIA *curia);
+
+
+/* Synchronize updating contents on memory, not physically.
+ `curia' specifies a database handle connected as a writer.
+ If successful, the return value is true, else, it is false. */
+int crmemflush(CURIA *curia);
+
+
+/* Get flags of a database.
+ `curia' specifies a database handle.
+ The return value is the flags of a database. */
+int crgetflags(CURIA *curia);
+
+
+/* Set flags of a database.
+ `curia' specifies a database handle connected as a writer.
+ `flags' specifies flags to set. Least ten bits are reserved for internal use.
+ If successful, the return value is true, else, it is false. */
+int crsetflags(CURIA *curia, int flags);
+
+
+
+#undef MYEXTERN
+
+#if defined(__cplusplus) /* export for C++ */
+}
+#endif
+
+#endif /* duplication check */
+
+
+/* END OF FILE */
diff --git a/qdbm/depot.c b/qdbm/depot.c
new file mode 100644
index 00000000..717335b8
--- /dev/null
+++ b/qdbm/depot.c
@@ -0,0 +1,2219 @@
+/*************************************************************************************************
+ * Implementation of Depot
+ * Copyright (C) 2000-2007 Mikio Hirabayashi
+ * This file is part of QDBM, Quick Database Manager.
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ *************************************************************************************************/
+
+
+#define QDBM_INTERNAL 1
+
+#include "depot.h"
+#include "myconf.h"
+
+#define DP_FILEMODE 00644 /* permission of a creating file */
+#define DP_MAGICNUMB "[DEPOT]\n\f" /* magic number on environments of big endian */
+#define DP_MAGICNUML "[depot]\n\f" /* magic number on environments of little endian */
+#define DP_HEADSIZ 48 /* size of the reagion of the header */
+#define DP_LIBVEROFF 12 /* offset of the region for the library version */
+#define DP_FLAGSOFF 16 /* offset of the region for flags */
+#define DP_FSIZOFF 24 /* offset of the region for the file size */
+#define DP_BNUMOFF 32 /* offset of the region for the bucket number */
+#define DP_RNUMOFF 40 /* offset of the region for the record number */
+#define DP_DEFBNUM 8191 /* default bucket number */
+#define DP_FBPOOLSIZ 16 /* size of free block pool */
+#define DP_ENTBUFSIZ 128 /* size of the entity buffer */
+#define DP_STKBUFSIZ 256 /* size of the stack key buffer */
+#define DP_WRTBUFSIZ 8192 /* size of the writing buffer */
+#define DP_FSBLKSIZ 4096 /* size of a block of the file system */
+#define DP_TMPFSUF MYEXTSTR "dptmp" /* suffix of a temporary file */
+#define DP_OPTBLOAD 0.25 /* ratio of bucket loading at optimization */
+#define DP_OPTRUNIT 256 /* number of records in a process of optimization */
+#define DP_NUMBUFSIZ 32 /* size of a buffer for a number */
+#define DP_IOBUFSIZ 8192 /* size of an I/O buffer */
+
+/* get the first hash value */
+#define DP_FIRSTHASH(DP_res, DP_kbuf, DP_ksiz) \
+ do { \
+ const unsigned char *_DP_p; \
+ int _DP_ksiz; \
+ _DP_p = (const unsigned char *)(DP_kbuf); \
+ _DP_ksiz = DP_ksiz; \
+ if((_DP_ksiz) == sizeof(int)){ \
+ memcpy(&(DP_res), (DP_kbuf), sizeof(int)); \
+ } else { \
+ (DP_res) = 751; \
+ } \
+ while(_DP_ksiz--){ \
+ (DP_res) = (DP_res) * 31 + *(_DP_p)++; \
+ } \
+ (DP_res) = ((DP_res) * 87767623) & INT_MAX; \
+ } while(FALSE)
+
+/* get the second hash value */
+#define DP_SECONDHASH(DP_res, DP_kbuf, DP_ksiz) \
+ do { \
+ const unsigned char *_DP_p; \
+ int _DP_ksiz; \
+ _DP_p = (const unsigned char *)(DP_kbuf) + DP_ksiz - 1; \
+ _DP_ksiz = DP_ksiz; \
+ for((DP_res) = 19780211; _DP_ksiz--;){ \
+ (DP_res) = (DP_res) * 37 + *(_DP_p)--; \
+ } \
+ (DP_res) = ((DP_res) * 43321879) & INT_MAX; \
+ } while(FALSE)
+
+/* get the third hash value */
+#define DP_THIRDHASH(DP_res, DP_kbuf, DP_ksiz) \
+ do { \
+ int _DP_i; \
+ (DP_res) = 774831917; \
+ for(_DP_i = (DP_ksiz) - 1; _DP_i >= 0; _DP_i--){ \
+ (DP_res) = (DP_res) * 29 + ((const unsigned char *)(DP_kbuf))[_DP_i]; \
+ } \
+ (DP_res) = ((DP_res) * 5157883) & INT_MAX; \
+ } while(FALSE)
+
+enum { /* enumeration for a record header */
+ DP_RHIFLAGS, /* offset of flags */
+ DP_RHIHASH, /* offset of value of the second hash function */
+ DP_RHIKSIZ, /* offset of the size of the key */
+ DP_RHIVSIZ, /* offset of the size of the value */
+ DP_RHIPSIZ, /* offset of the size of the padding bytes */
+ DP_RHILEFT, /* offset of the offset of the left child */
+ DP_RHIRIGHT, /* offset of the offset of the right child */
+ DP_RHNUM /* number of elements of a header */
+};
+
+enum { /* enumeration for the flag of a record */
+ DP_RECFDEL = 1 << 0, /* deleted */
+ DP_RECFREUSE = 1 << 1 /* reusable */
+};
+
+
+/* private function prototypes */
+static int dpbigendian(void);
+static char *dpstrdup(const char *str);
+static int dplock(int fd, int ex, int nb);
+static int dpwrite(int fd, const void *buf, int size);
+static int dpseekwrite(int fd, int off, const void *buf, int size);
+static int dpseekwritenum(int fd, int off, int num);
+static int dpread(int fd, void *buf, int size);
+static int dpseekread(int fd, int off, void *buf, int size);
+static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff);
+static int dpgetprime(int num);
+static int dppadsize(DEPOT *depot, int ksiz, int vsiz);
+static int dprecsize(int *head);
+static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep);
+static char *dpreckey(DEPOT *depot, int off, int *head);
+static char *dprecval(DEPOT *depot, int off, int *head, int start, int max);
+static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf);
+static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz);
+static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp,
+ int *entp, int *head, char *ebuf, int *eep, int delhit);
+static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz,
+ const char *vbuf, int vsiz, int hash, int left, int right);
+static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
+ int hash, int left, int right);
+static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat);
+static int dprecdelete(DEPOT *depot, int off, int *head, int reusable);
+static void dpfbpoolcoal(DEPOT *depot);
+static int dpfbpoolcmp(const void *a, const void *b);
+
+
+
+/*************************************************************************************************
+ * public objects
+ *************************************************************************************************/
+
+
+/* String containing the version information. */
+const char *dpversion = _QDBM_VERSION;
+
+
+/* Get a message string corresponding to an error code. */
+const char *dperrmsg(int ecode){
+ switch(ecode){
+ case DP_ENOERR: return "no error";
+ case DP_EFATAL: return "with fatal error";
+ case DP_EMODE: return "invalid mode";
+ case DP_EBROKEN: return "broken database file";
+ case DP_EKEEP: return "existing record";
+ case DP_ENOITEM: return "no item found";
+ case DP_EALLOC: return "memory allocation error";
+ case DP_EMAP: return "memory mapping error";
+ case DP_EOPEN: return "open error";
+ case DP_ECLOSE: return "close error";
+ case DP_ETRUNC: return "trunc error";
+ case DP_ESYNC: return "sync error";
+ case DP_ESTAT: return "stat error";
+ case DP_ESEEK: return "seek error";
+ case DP_EREAD: return "read error";
+ case DP_EWRITE: return "write error";
+ case DP_ELOCK: return "lock error";
+ case DP_EUNLINK: return "unlink error";
+ case DP_EMKDIR: return "mkdir error";
+ case DP_ERMDIR: return "rmdir error";
+ case DP_EMISC: return "miscellaneous error";
+ }
+ return "(invalid ecode)";
+}
+
+
+/* Get a database handle. */
+DEPOT *dpopen(const char *name, int omode, int bnum){
+ char hbuf[DP_HEADSIZ], *map, c, *tname;
+ int i, mode, fd, inode, fsiz, rnum, msiz, *fbpool;
+ struct stat sbuf;
+ time_t mtime;
+ DEPOT *depot;
+ assert(name);
+ mode = O_RDONLY;
+ if(omode & DP_OWRITER){
+ mode = O_RDWR;
+ if(omode & DP_OCREAT) mode |= O_CREAT;
+ }
+ if((fd = open(name, mode, DP_FILEMODE)) == -1){
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(!(omode & DP_ONOLCK)){
+ if(!dplock(fd, omode & DP_OWRITER, omode & DP_OLCKNB)){
+ close(fd);
+ return NULL;
+ }
+ }
+ if((omode & DP_OWRITER) && (omode & DP_OTRUNC)){
+ if(ftruncate(fd, 0) == -1){
+ close(fd);
+ dpecodeset(DP_ETRUNC, __FILE__, __LINE__);
+ return NULL;
+ }
+ }
+ if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode) ||
+ (sbuf.st_ino == 0 && lstat(name, &sbuf) == -1)){
+ close(fd);
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
+ return NULL;
+ }
+ inode = sbuf.st_ino;
+ mtime = sbuf.st_mtime;
+ fsiz = sbuf.st_size;
+ if((omode & DP_OWRITER) && fsiz == 0){
+ memset(hbuf, 0, DP_HEADSIZ);
+ if(dpbigendian()){
+ memcpy(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB));
+ } else {
+ memcpy(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML));
+ }
+ sprintf(hbuf + DP_LIBVEROFF, "%d", _QDBM_LIBVER / 100);
+ bnum = bnum < 1 ? DP_DEFBNUM : bnum;
+ bnum = dpgetprime(bnum);
+ memcpy(hbuf + DP_BNUMOFF, &bnum, sizeof(int));
+ rnum = 0;
+ memcpy(hbuf + DP_RNUMOFF, &rnum, sizeof(int));
+ fsiz = DP_HEADSIZ + bnum * sizeof(int);
+ memcpy(hbuf + DP_FSIZOFF, &fsiz, sizeof(int));
+ if(!dpseekwrite(fd, 0, hbuf, DP_HEADSIZ)){
+ close(fd);
+ return NULL;
+ }
+ if(omode & DP_OSPARSE){
+ c = 0;
+ if(!dpseekwrite(fd, fsiz - 1, &c, 1)){
+ close(fd);
+ return NULL;
+ }
+ } else {
+ if(!(map = malloc(bnum * sizeof(int)))){
+ close(fd);
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ memset(map, 0, bnum * sizeof(int));
+ if(!dpseekwrite(fd, DP_HEADSIZ, map, bnum * sizeof(int))){
+ free(map);
+ close(fd);
+ return NULL;
+ }
+ free(map);
+ }
+ }
+ if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){
+ close(fd);
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(!(omode & DP_ONOLCK) &&
+ ((dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 :
+ memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0) ||
+ *((int *)(hbuf + DP_FSIZOFF)) != fsiz)){
+ close(fd);
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ bnum = *((int *)(hbuf + DP_BNUMOFF));
+ rnum = *((int *)(hbuf + DP_RNUMOFF));
+ if(bnum < 1 || rnum < 0 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){
+ close(fd);
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
+ return NULL;
+ }
+ msiz = DP_HEADSIZ + bnum * sizeof(int);
+ map = mmap(0, msiz, PROT_READ | ((mode & DP_OWRITER) ? PROT_WRITE : 0), MAP_SHARED, fd, 0);
+ if(map == MAP_FAILED){
+ close(fd);
+ dpecodeset(DP_EMAP, __FILE__, __LINE__);
+ return NULL;
+ }
+ tname = NULL;
+ fbpool = NULL;
+ if(!(depot = malloc(sizeof(DEPOT))) || !(tname = dpstrdup(name)) ||
+ !(fbpool = malloc(DP_FBPOOLSIZ * 2 * sizeof(int)))){
+ free(fbpool);
+ free(tname);
+ free(depot);
+ munmap(map, msiz);
+ close(fd);
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ return NULL;
+ }
+ depot->name = tname;
+ depot->wmode = (mode & DP_OWRITER);
+ depot->inode = inode;
+ depot->mtime = mtime;
+ depot->fd = fd;
+ depot->fsiz = fsiz;
+ depot->map = map;
+ depot->msiz = msiz;
+ depot->buckets = (int *)(map + DP_HEADSIZ);
+ depot->bnum = bnum;
+ depot->rnum = rnum;
+ depot->fatal = FALSE;
+ depot->ioff = 0;
+ depot->fbpool = fbpool;
+ for(i = 0; i < DP_FBPOOLSIZ * 2; i += 2){
+ depot->fbpool[i] = -1;
+ depot->fbpool[i+1] = -1;
+ }
+ depot->fbpsiz = DP_FBPOOLSIZ * 2;
+ depot->fbpinc = 0;
+ depot->align = 0;
+ return depot;
+}
+
+
+/* Close a database handle. */
+int dpclose(DEPOT *depot){
+ int fatal, err;
+ assert(depot);
+ fatal = depot->fatal;
+ err = FALSE;
+ if(depot->wmode){
+ *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz;
+ *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum;
+ }
+ if(depot->map != MAP_FAILED){
+ if(munmap(depot->map, depot->msiz) == -1){
+ err = TRUE;
+ dpecodeset(DP_EMAP, __FILE__, __LINE__);
+ }
+ }
+ if(close(depot->fd) == -1){
+ err = TRUE;
+ dpecodeset(DP_ECLOSE, __FILE__, __LINE__);
+ }
+ free(depot->fbpool);
+ free(depot->name);
+ free(depot);
+ if(fatal){
+ dpecodeset(DP_EFATAL, __FILE__, __LINE__);
+ return FALSE;
+ }
+ return err ? FALSE : TRUE;
+}
+
+
+/* Store a record. */
+int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){
+ int head[DP_RHNUM], next[DP_RHNUM];
+ int i, hash, bi, off, entoff, ee, newoff, rsiz, nsiz, fdel, mroff, mrsiz, mi, min;
+ char ebuf[DP_ENTBUFSIZ], *tval, *swap;
+ assert(depot && kbuf && vbuf);
+ if(depot->fatal){
+ dpecodeset(DP_EFATAL, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(!depot->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ if(vsiz < 0) vsiz = strlen(vbuf);
+ newoff = -1;
+ DP_SECONDHASH(hash, kbuf, ksiz);
+ switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, TRUE)){
+ case -1:
+ depot->fatal = TRUE;
+ return FALSE;
+ case 0:
+ fdel = head[DP_RHIFLAGS] & DP_RECFDEL;
+ if(dmode == DP_DKEEP && !fdel){
+ dpecodeset(DP_EKEEP, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(fdel){
+ head[DP_RHIPSIZ] += head[DP_RHIVSIZ];
+ head[DP_RHIVSIZ] = 0;
+ }
+ rsiz = dprecsize(head);
+ nsiz = DP_RHNUM * sizeof(int) + ksiz + vsiz;
+ if(dmode == DP_DCAT) nsiz += head[DP_RHIVSIZ];
+ if(off + rsiz >= depot->fsiz){
+ if(rsiz < nsiz){
+ head[DP_RHIPSIZ] += nsiz - rsiz;
+ rsiz = nsiz;
+ depot->fsiz = off + rsiz;
+ }
+ } else {
+ while(nsiz > rsiz && off + rsiz < depot->fsiz){
+ if(!dprechead(depot, off + rsiz, next, NULL, NULL)) return FALSE;
+ if(!(next[DP_RHIFLAGS] & DP_RECFREUSE)) break;
+ head[DP_RHIPSIZ] += dprecsize(next);
+ rsiz += dprecsize(next);
+ }
+ for(i = 0; i < depot->fbpsiz; i += 2){
+ if(depot->fbpool[i] >= off && depot->fbpool[i] < off + rsiz){
+ depot->fbpool[i] = -1;
+ depot->fbpool[i+1] = -1;
+ }
+ }
+ }
+ if(nsiz <= rsiz){
+ if(!dprecover(depot, off, head, vbuf, vsiz, dmode == DP_DCAT)){
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ } else {
+ tval = NULL;
+ if(dmode == DP_DCAT){
+ if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){
+ if(!(tval = malloc(head[DP_RHIVSIZ] + vsiz + 1))){
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ memcpy(tval, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), head[DP_RHIVSIZ]);
+ } else {
+ if(!(tval = dprecval(depot, off, head, 0, -1))){
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ if(!(swap = realloc(tval, head[DP_RHIVSIZ] + vsiz + 1))){
+ free(tval);
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ tval = swap;
+ }
+ memcpy(tval + head[DP_RHIVSIZ], vbuf, vsiz);
+ vsiz += head[DP_RHIVSIZ];
+ vbuf = tval;
+ }
+ mi = -1;
+ min = -1;
+ for(i = 0; i < depot->fbpsiz; i += 2){
+ if(depot->fbpool[i+1] < nsiz) continue;
+ if(mi == -1 || depot->fbpool[i+1] < min){
+ mi = i;
+ min = depot->fbpool[i+1];
+ }
+ }
+ if(mi >= 0){
+ mroff = depot->fbpool[mi];
+ mrsiz = depot->fbpool[mi+1];
+ depot->fbpool[mi] = -1;
+ depot->fbpool[mi+1] = -1;
+ } else {
+ mroff = -1;
+ mrsiz = -1;
+ }
+ if(!dprecdelete(depot, off, head, TRUE)){
+ free(tval);
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ if(mroff > 0 && nsiz <= mrsiz){
+ if(!dprecrewrite(depot, mroff, mrsiz, kbuf, ksiz, vbuf, vsiz,
+ hash, head[DP_RHILEFT], head[DP_RHIRIGHT])){
+ free(tval);
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ newoff = mroff;
+ } else {
+ if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz,
+ hash, head[DP_RHILEFT], head[DP_RHIRIGHT])) == -1){
+ free(tval);
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ }
+ free(tval);
+ }
+ if(fdel) depot->rnum++;
+ break;
+ default:
+ if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, hash, 0, 0)) == -1){
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ depot->rnum++;
+ break;
+ }
+ if(newoff > 0){
+ if(entoff > 0){
+ if(!dpseekwritenum(depot->fd, entoff, newoff)){
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ } else {
+ depot->buckets[bi] = newoff;
+ }
+ }
+ return TRUE;
+}
+
+
+/* Delete a record. */
+int dpout(DEPOT *depot, const char *kbuf, int ksiz){
+ int head[DP_RHNUM], hash, bi, off, entoff, ee;
+ char ebuf[DP_ENTBUFSIZ];
+ assert(depot && kbuf);
+ if(depot->fatal){
+ dpecodeset(DP_EFATAL, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(!depot->wmode){
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ DP_SECONDHASH(hash, kbuf, ksiz);
+ switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){
+ case -1:
+ depot->fatal = TRUE;
+ return FALSE;
+ case 0:
+ break;
+ default:
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return FALSE;
+ }
+ if(!dprecdelete(depot, off, head, FALSE)){
+ depot->fatal = TRUE;
+ return FALSE;
+ }
+ depot->rnum--;
+ return TRUE;
+}
+
+
+/* Retrieve a record. */
+char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp){
+ int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz;
+ char ebuf[DP_ENTBUFSIZ], *vbuf;
+ assert(depot && kbuf && start >= 0);
+ if(depot->fatal){
+ dpecodeset(DP_EFATAL, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ DP_SECONDHASH(hash, kbuf, ksiz);
+ switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){
+ case -1:
+ depot->fatal = TRUE;
+ return NULL;
+ case 0:
+ break;
+ default:
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(start > head[DP_RHIVSIZ]){
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
+ return NULL;
+ }
+ if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){
+ head[DP_RHIVSIZ] -= start;
+ if(max < 0){
+ vsiz = head[DP_RHIVSIZ];
+ } else {
+ vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ];
+ }
+ if(!(vbuf = malloc(vsiz + 1))){
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
+ depot->fatal = TRUE;
+ return NULL;
+ }
+ memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz);
+ vbuf[vsiz] = '\0';
+ } else {
+ if(!(vbuf = dprecval(depot, off, head, start, max))){
+ depot->fatal = TRUE;
+ return NULL;
+ }
+ }
+ if(sp){
+ if(max < 0){
+ *sp = head[DP_RHIVSIZ];
+ } else {
+ *sp = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ];
+ }
+ }
+ return vbuf;
+}
+
+
+/* Retrieve a record and write the value into a buffer. */
+int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf){
+ int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz;
+ char ebuf[DP_ENTBUFSIZ];
+ assert(depot && kbuf && start >= 0 && max >= 0 && vbuf);
+ if(depot->fatal){
+ dpecodeset(DP_EFATAL, __FILE__, __LINE__);
+ return -1;
+ }
+ if(ksiz < 0) ksiz = strlen(kbuf);
+ DP_SECONDHASH(hash, kbuf, ksiz);
+ switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &